Fossil SCM

Merge in trunk (version-2.11)

george 2020-05-26 18:27 wiki-history merge
Commit 6819e2ffab2e2f50b13035b795e05a839b9c255ecba9c6c632c31996800bca01
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,17 +17,18 @@
1717
html "<a href='$home$url' class='active $cls'>$name</a>\n"
1818
} else {
1919
html "<a href='$home$url' class='$cls'>$name</a>\n"
2020
}
2121
}
22
-html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
22
+html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>&#9776;</a>"
2323
menulink $index_page Home {}
2424
if {[anycap jor]} {
2525
menulink /timeline Timeline {}
2626
}
2727
if {[hascap oh]} {
28
- menulink /dir?ci=tip Files desktoponly
28
+ if {![info exists current_checkin]} {set current_checkin tip}
29
+ menulink /dir?ci=$current_checkin Files desktoponly
2930
}
3031
if {[hascap o]} {
3132
menulink /brlist Branches desktoponly
3233
menulink /taglist Tags wideonly
3334
}
3435
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,17 +17,18 @@
17 html "<a href='$home$url' class='active $cls'>$name</a>\n"
18 } else {
19 html "<a href='$home$url' class='$cls'>$name</a>\n"
20 }
21 }
22 html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
23 menulink $index_page Home {}
24 if {[anycap jor]} {
25 menulink /timeline Timeline {}
26 }
27 if {[hascap oh]} {
28 menulink /dir?ci=tip Files desktoponly
 
29 }
30 if {[hascap o]} {
31 menulink /brlist Branches desktoponly
32 menulink /taglist Tags wideonly
33 }
34
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,17 +17,18 @@
17 html "<a href='$home$url' class='active $cls'>$name</a>\n"
18 } else {
19 html "<a href='$home$url' class='$cls'>$name</a>\n"
20 }
21 }
22 html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>&#9776;</a>"
23 menulink $index_page Home {}
24 if {[anycap jor]} {
25 menulink /timeline Timeline {}
26 }
27 if {[hascap oh]} {
28 if {![info exists current_checkin]} {set current_checkin tip}
29 menulink /dir?ci=$current_checkin Files desktoponly
30 }
31 if {[hascap o]} {
32 menulink /brlist Branches desktoponly
33 menulink /taglist Tags wideonly
34 }
35
+3 -1
--- src/allrepo.c
+++ src/allrepo.c
@@ -128,11 +128,11 @@
128128
** supported by the rebuild command itself, if any are
129129
** present, are passed along verbatim. The --force and
130130
** --randomize options are not supported.
131131
**
132132
** sync Run a "sync" on all repositories. Only the --verbose
133
-** option is supported.
133
+** and --unversioned options are supported.
134134
**
135135
** setting Run the "setting", "set", or "unset" commands on all
136136
** set repositories. These command are particularly useful in
137137
** unset conjunction with the "max-loadavg" setting which cannot
138138
** otherwise be set globally.
@@ -283,11 +283,13 @@
283283
}else if( strncmp(zCmd, "sync", n)==0 ){
284284
zCmd = "sync -autourl -R";
285285
collect_argument(&extra, "verbose","v");
286286
collect_argument(&extra, "unversioned","u");
287287
}else if( strncmp(zCmd, "test-integrity", n)==0 ){
288
+ collect_argument(&extra, "db-only", "d");
288289
collect_argument(&extra, "parse", 0);
290
+ collect_argument(&extra, "quick", "q");
289291
zCmd = "test-integrity";
290292
}else if( strncmp(zCmd, "test-orphans", n)==0 ){
291293
zCmd = "test-orphans -R";
292294
}else if( strncmp(zCmd, "test-missing", n)==0 ){
293295
zCmd = "test-missing -q -R";
294296
--- src/allrepo.c
+++ src/allrepo.c
@@ -128,11 +128,11 @@
128 ** supported by the rebuild command itself, if any are
129 ** present, are passed along verbatim. The --force and
130 ** --randomize options are not supported.
131 **
132 ** sync Run a "sync" on all repositories. Only the --verbose
133 ** option is supported.
134 **
135 ** setting Run the "setting", "set", or "unset" commands on all
136 ** set repositories. These command are particularly useful in
137 ** unset conjunction with the "max-loadavg" setting which cannot
138 ** otherwise be set globally.
@@ -283,11 +283,13 @@
283 }else if( strncmp(zCmd, "sync", n)==0 ){
284 zCmd = "sync -autourl -R";
285 collect_argument(&extra, "verbose","v");
286 collect_argument(&extra, "unversioned","u");
287 }else if( strncmp(zCmd, "test-integrity", n)==0 ){
 
288 collect_argument(&extra, "parse", 0);
 
289 zCmd = "test-integrity";
290 }else if( strncmp(zCmd, "test-orphans", n)==0 ){
291 zCmd = "test-orphans -R";
292 }else if( strncmp(zCmd, "test-missing", n)==0 ){
293 zCmd = "test-missing -q -R";
294
--- src/allrepo.c
+++ src/allrepo.c
@@ -128,11 +128,11 @@
128 ** supported by the rebuild command itself, if any are
129 ** present, are passed along verbatim. The --force and
130 ** --randomize options are not supported.
131 **
132 ** sync Run a "sync" on all repositories. Only the --verbose
133 ** and --unversioned options are supported.
134 **
135 ** setting Run the "setting", "set", or "unset" commands on all
136 ** set repositories. These command are particularly useful in
137 ** unset conjunction with the "max-loadavg" setting which cannot
138 ** otherwise be set globally.
@@ -283,11 +283,13 @@
283 }else if( strncmp(zCmd, "sync", n)==0 ){
284 zCmd = "sync -autourl -R";
285 collect_argument(&extra, "verbose","v");
286 collect_argument(&extra, "unversioned","u");
287 }else if( strncmp(zCmd, "test-integrity", n)==0 ){
288 collect_argument(&extra, "db-only", "d");
289 collect_argument(&extra, "parse", 0);
290 collect_argument(&extra, "quick", "q");
291 zCmd = "test-integrity";
292 }else if( strncmp(zCmd, "test-orphans", n)==0 ){
293 zCmd = "test-orphans -R";
294 }else if( strncmp(zCmd, "test-missing", n)==0 ){
295 zCmd = "test-missing -q -R";
296
+14
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
1818
** This file contains code used to create new branches within a repository.
1919
*/
2020
#include "config.h"
2121
#include "branch.h"
2222
#include <assert.h>
23
+
24
+/*
25
+** Return true if zBr is the branch name associated with check-in with
26
+** blob.uuid value of zUuid
27
+*/
28
+int branch_includes_uuid(const char *zBr, const char *zUuid){
29
+ return db_exists(
30
+ "SELECT 1 FROM tagxref, blob"
31
+ " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
32
+ " AND tagxref.value=%Q AND tagxref.tagtype>0"
33
+ " AND tagxref.tagid=%d",
34
+ zUuid, zBr, TAG_BRANCH
35
+ );
36
+}
2337
2438
/*
2539
** If RID refers to a check-in, return the name of the branch for that
2640
** check-in.
2741
**
2842
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24 /*
25 ** If RID refers to a check-in, return the name of the branch for that
26 ** check-in.
27 **
28
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
23
24 /*
25 ** Return true if zBr is the branch name associated with check-in with
26 ** blob.uuid value of zUuid
27 */
28 int branch_includes_uuid(const char *zBr, const char *zUuid){
29 return db_exists(
30 "SELECT 1 FROM tagxref, blob"
31 " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
32 " AND tagxref.value=%Q AND tagxref.tagtype>0"
33 " AND tagxref.tagid=%d",
34 zUuid, zBr, TAG_BRANCH
35 );
36 }
37
38 /*
39 ** If RID refers to a check-in, return the name of the branch for that
40 ** check-in.
41 **
42
+146 -75
--- src/browse.c
+++ src/browse.c
@@ -59,10 +59,18 @@
5959
zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
6060
sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
6161
}
6262
}
6363
64
+/*
65
+** Flag arguments for hyperlinked_path()
66
+*/
67
+#if INTERFACE
68
+# define LINKPATH_FINFO 0x0001 /* Link final term to /finfo */
69
+# define LINKPATH_FILE 0x0002 /* Link final term to /file */
70
+#endif
71
+
6472
/*
6573
** Given a pathname which is a relative path from the root of
6674
** the repository to a file or directory, compute a string which
6775
** is an HTML rendering of that path with hyperlinks on each
6876
** directory component of the path where the hyperlink redirects
@@ -76,29 +84,36 @@
7684
void hyperlinked_path(
7785
const char *zPath, /* Path to render */
7886
Blob *pOut, /* Write into this blob */
7987
const char *zCI, /* check-in name, or NULL */
8088
const char *zURI, /* "dir" or "tree" */
81
- const char *zREx /* Extra query parameters */
89
+ const char *zREx, /* Extra query parameters */
90
+ unsigned int mFlags /* Extra flags */
8291
){
8392
int i, j;
8493
char *zSep = "";
8594
8695
for(i=0; zPath[i]; i=j){
8796
for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88
- if( zPath[j] && g.perm.Hyperlink ){
89
- if( zCI ){
90
- char *zLink = href("%R/%s?name=%#T%s&ci=%!S", zURI, j, zPath, zREx,zCI);
91
- blob_appendf(pOut, "%s%z%#h</a>",
92
- zSep, zLink, j-i, &zPath[i]);
93
- }else{
94
- char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
95
- blob_appendf(pOut, "%s%z%#h</a>",
96
- zSep, zLink, j-i, &zPath[i]);
97
- }
98
- }else{
99
- blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
97
+ if( zPath[j]==0 ){
98
+ if( mFlags & LINKPATH_FILE ){
99
+ zURI = "file";
100
+ }else if( mFlags & LINKPATH_FINFO ){
101
+ zURI = "finfo";
102
+ }else{
103
+ blob_appendf(pOut, "/%h", zPath+i);
104
+ break;
105
+ }
106
+ }
107
+ if( zCI ){
108
+ char *zLink = href("%R/%s?name=%#T%s&ci=%T", zURI, j, zPath, zREx,zCI);
109
+ blob_appendf(pOut, "%s%z%#h</a>",
110
+ zSep, zLink, j-i, &zPath[i]);
111
+ }else{
112
+ char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113
+ blob_appendf(pOut, "%s%z%#h</a>",
114
+ zSep, zLink, j-i, &zPath[i]);
100115
}
101116
zSep = "/";
102117
while( zPath[j]=='/' ){ j++; }
103118
}
104119
}
@@ -127,27 +142,24 @@
127142
char *zPrefix;
128143
Stmt q;
129144
const char *zCI = P("ci");
130145
int rid = 0;
131146
char *zUuid = 0;
132
- Blob dirname;
133147
Manifest *pM = 0;
134148
const char *zSubdirLink;
135149
int linkTrunk = 1;
136150
int linkTip = 1;
137151
HQuery sURI;
152
+ int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
153
+ int isBranchCI = 0; /* True if ci= refers to a branch name */
154
+ char *zHeader = 0;
138155
156
+ if( zCI && strlen(zCI)==0 ){ zCI = 0; }
139157
if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
140158
login_check_credentials();
141159
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
142160
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
143
- style_header("File List");
144
- style_adunit_config(ADUNIT_RIGHT_OK);
145
- sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
146
- pathelementFunc, 0, 0);
147
- url_initialize(&sURI, "dir");
148
- cgi_query_parameters_to_url(&sURI);
149161
150162
/* If the name= parameter is an empty string, make it a NULL pointer */
151163
if( zD && strlen(zD)==0 ){ zD = 0; }
152164
153165
/* If a specific check-in is requested, fetch and parse it. If the
@@ -159,53 +171,80 @@
159171
if( pM ){
160172
int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
161173
linkTrunk = trunkRid && rid != trunkRid;
162174
linkTip = rid != symbolic_name_to_rid("tip", "ci");
163175
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
176
+ isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177
+ isBranchCI = branch_includes_uuid(zCI, zUuid);
178
+ Th_Store("current_checkin", zCI);
164179
}else{
165180
zCI = 0;
166181
}
167182
}
168183
184
+ assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
185
+ if( zD==0 ){
186
+ if( zCI ){
187
+ zHeader = mprintf("Top-level Files of %s", zCI);
188
+ }else{
189
+ zHeader = mprintf("All Top-level Files");
190
+ }
191
+ }else{
192
+ if( zCI ){
193
+ zHeader = mprintf("Files in %s/ of %s", zD, zCI);
194
+ }else{
195
+ zHeader = mprintf("All File in %s/", zD);
196
+ }
197
+ }
198
+ style_header("%s", zHeader);
199
+ fossil_free(zHeader);
200
+ style_adunit_config(ADUNIT_RIGHT_OK);
201
+ sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
202
+ pathelementFunc, 0, 0);
203
+ url_initialize(&sURI, "dir");
204
+ cgi_query_parameters_to_url(&sURI);
205
+
169206
/* Compute the title of the page */
170
- blob_zero(&dirname);
171207
if( zD ){
172
- blob_append(&dirname, "in directory ", -1);
173
- hyperlinked_path(zD, &dirname, zCI, "dir", "");
208
+ Blob dirname;
209
+ blob_init(&dirname, 0, 0);
210
+ hyperlinked_path(zD, &dirname, zCI, "dir", "", 0);
211
+ @ <h2>Files in directory %s(blob_str(&dirname)) \
212
+ blob_reset(&dirname);
174213
zPrefix = mprintf("%s/", zD);
175214
style_submenu_element("Top-Level", "%s",
176215
url_render(&sURI, "name", 0, 0, 0));
177216
}else{
178
- blob_append(&dirname, "in the top-level directory", -1);
217
+ @ <h2>Files in the top-level directory \
179218
zPrefix = "";
180219
}
220
+ if( zCI ){
221
+ if( fossil_strcmp(zCI,"tip")==0 ){
222
+ @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a></h2>
223
+ }else if( isBranchCI ){
224
+ @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a> \
225
+ @ of branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
226
+ }else {
227
+ @ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
228
+ }
229
+ zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
230
+ if( nD==0 ){
231
+ style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
232
+ }
233
+ }else{
234
+ @ in any check-in</h2>
235
+ zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
236
+ }
181237
if( linkTrunk ){
182238
style_submenu_element("Trunk", "%s",
183239
url_render(&sURI, "ci", "trunk", 0, 0));
184240
}
185241
if( linkTip ){
186242
style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
187243
}
188
- if( zCI ){
189
- @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
190
- @ %s(blob_str(&dirname))
191
- if( zD ){
192
- @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
193
- }
194
- @ </h2>
195
- zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix);
196
- if( nD==0 ){
197
- style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid);
198
- }
199
- }else{
200
- @ <h2>The union of all files from all check-ins
201
- @ %s(blob_str(&dirname))
202
- if( zD ){
203
- @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
204
- }
205
- @ </h2>
206
- zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
244
+ if( zD ){
245
+ style_submenu_element("History","%R/timeline?chng=%T/*", zD);
207246
}
208247
style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
209248
style_submenu_element("Tree-View", "%s",
210249
url_render(&sURI, "type", "tree", 0, 0));
211250
@@ -282,12 +321,11 @@
282321
zFN++;
283322
@ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
284323
}else{
285324
const char *zLink;
286325
if( zCI ){
287
- const char *zUuid = db_column_text(&q, 1);
288
- zLink = href("%R/artifact/%!S",zUuid);
326
+ zLink = href("%R/file?name=%T%T&ci=%T",zPrefix,zFN,zCI);
289327
}else{
290328
zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
291329
}
292330
@ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
293331
}
@@ -612,11 +650,15 @@
612650
HQuery sURI; /* Hyperlink */
613651
int startExpanded; /* True to start out with the tree expanded */
614652
int showDirOnly; /* Show directories only. Omit files */
615653
int nDir = 0; /* Number of directories. Used for ID attributes */
616654
char *zProjectName = db_get("project-name", 0);
655
+ int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
656
+ int isBranchCI = 0; /* ci= refers to a branch name */
657
+ char *zHeader = 0;
617658
659
+ if( zCI && strlen(zCI)==0 ){ zCI = 0; }
618660
if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
619661
memset(&sTree, 0, sizeof(sTree));
620662
login_check_credentials();
621663
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
622664
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
@@ -624,14 +666,12 @@
624666
pathelementFunc, 0, 0);
625667
url_initialize(&sURI, "tree");
626668
cgi_query_parameters_to_url(&sURI);
627669
if( PB("nofiles") ){
628670
showDirOnly = 1;
629
- style_header("Folder Hierarchy");
630671
}else{
631672
showDirOnly = 0;
632
- style_header("File Tree");
633673
}
634674
style_adunit_config(ADUNIT_RIGHT_OK);
635675
if( PB("expand") ){
636676
startExpanded = 1;
637677
}else{
@@ -660,37 +700,55 @@
660700
linkTip = rid != symbolic_name_to_rid("tip", "ci");
661701
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
662702
rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
663703
zNow = db_text("", "SELECT datetime(mtime,toLocal())"
664704
" FROM event WHERE objid=%d", rid);
705
+ isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
706
+ isBranchCI = branch_includes_uuid(zCI, zUuid);
707
+ Th_Store("current_checkin", zCI);
665708
}else{
666709
zCI = 0;
667710
}
668711
}
669712
if( zCI==0 ){
670713
rNow = db_double(0.0, "SELECT max(mtime) FROM event");
671714
zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
672715
}
716
+
717
+ assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
718
+ if( zD==0 ){
719
+ if( zCI ){
720
+ zHeader = mprintf("Top-level Files of %s", zCI);
721
+ }else{
722
+ zHeader = mprintf("All Top-level Files");
723
+ }
724
+ }else{
725
+ if( zCI ){
726
+ zHeader = mprintf("Files in %s/ of %s", zD, zCI);
727
+ }else{
728
+ zHeader = mprintf("All File in %s/", zD);
729
+ }
730
+ }
731
+ style_header("%s", zHeader);
732
+ fossil_free(zHeader);
673733
674734
/* Compute the title of the page */
675735
blob_zero(&dirname);
676736
if( zD ){
677737
blob_append(&dirname, "within directory ", -1);
678
- hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
738
+ hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
679739
if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
680740
style_submenu_element("Top-Level", "%s",
681741
url_render(&sURI, "name", 0, 0, 0));
682
- }else{
683
- if( zRE ){
684
- blob_appendf(&dirname, "matching \"%s\"", zRE);
685
- }
742
+ }else if( zRE ){
743
+ blob_appendf(&dirname, "matching \"%s\"", zRE);
686744
}
687745
style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
688746
if( zCI ){
689747
style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
690748
if( nD==0 && !showDirOnly ){
691
- style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid);
749
+ style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
692750
}
693751
}
694752
if( linkTrunk ){
695753
style_submenu_element("Trunk", "%s",
696754
url_render(&sURI, "ci", "trunk", 0, 0));
@@ -745,10 +803,11 @@
745803
tree_add_node(&sTree, zName, zUuid, mtime);
746804
nFile++;
747805
}
748806
db_finalize(&q);
749807
}
808
+ style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
750809
751810
if( showDirOnly ){
752811
for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
753812
if( p->pChild!=0 && p->nFullName>nD ) nFile++;
754813
}
@@ -755,18 +814,24 @@
755814
zObjType = "Folders";
756815
}else{
757816
zObjType = "Files";
758817
}
759818
760
- style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
761
-
762
- if( zCI ){
763
- @ <h2>%s(zObjType) from
764
- if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
765
- @ "%h(zCI)"
766
- }
767
- @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
819
+ if( zCI && strcmp(zCI,"tip")==0 ){
820
+ @ <h2>%s(zObjType) in the %z(href("%R/info?name=tip"))latest check-in</a>
821
+ }else if( isBranchCI ){
822
+ @ <h2>%s(zObjType) in the %z(href("%R/info?name=%T",zCI))latest check-in\
823
+ @ </a> for branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a>
824
+ if( blob_size(&dirname) ){
825
+ @ and %s(blob_str(&dirname))</h2>
826
+ }
827
+ }else if( zCI ){
828
+ @ <h2>%s(zObjType) for check-in \
829
+ @ %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
830
+ if( blob_size(&dirname) ){
831
+ @ and %s(blob_str(&dirname))</h2>
832
+ }
768833
}else{
769834
int n = db_int(0, "SELECT count(*) FROM plink");
770835
@ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
771836
}
772837
if( useMtime ){
@@ -824,11 +889,11 @@
824889
nDir++;
825890
}else if( !showDirOnly ){
826891
const char *zFileClass = fileext_class(p->zName);
827892
char *zLink;
828893
if( zCI ){
829
- zLink = href("%R/artifact/%!S",p->zUuid);
894
+ zLink = href("%R/file?name=%T&ci=%T",p->zFullName,zCI);
830895
}else{
831896
zLink = href("%R/finfo?name=%T",p->zFullName);
832897
}
833898
@ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
834899
@ %z(zLink)%h(p->zName)</a>
@@ -1001,10 +1066,11 @@
10011066
int rid;
10021067
const char *zName;
10031068
const char *zGlob;
10041069
const char *zUuid;
10051070
const char *zNow; /* Time of check-in */
1071
+ int isBranchCI; /* name= is a branch name */
10061072
int showId = PB("showid");
10071073
Stmt q1, q2;
10081074
double baseTime;
10091075
login_check_credentials();
10101076
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1014,28 +1080,34 @@
10141080
rid = symbolic_name_to_rid(zName, "ci");
10151081
if( rid==0 ){
10161082
fossil_fatal("not a valid check-in: %s", zName);
10171083
}
10181084
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1085
+ isBranchCI = branch_includes_uuid(zName,zUuid);
10191086
baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
10201087
zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
10211088
" WHERE objid=%d", rid);
10221089
style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
10231090
style_header("File Ages");
10241091
zGlob = P("glob");
10251092
compute_fileage(rid,zGlob);
10261093
db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
10271094
1028
- @ <h1>Files in
1029
- @ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
1095
+ if( fossil_strcmp(zName,"tip")==0 ){
1096
+ @ <h1>Files in the %z(href("%R/info?name=tip"))latest check-in</a>
1097
+ }else if( isBranchCI ){
1098
+ @ <h1>Files in the %z(href("%R/info?name=%T",zName))latest check-in</a>
1099
+ @ of branch %z(href("%R/timeline?r=%T",zName))%h(zName)</a>
1100
+ }else{
1101
+ @ <h1>Files in check-in %z(href("%R/info?name=%T",zName))%h(zName)</a>
1102
+ }
10301103
if( zGlob && zGlob[0] ){
10311104
@ that match "%h(zGlob)"
10321105
}
10331106
@ ordered by age</h1>
10341107
@
1035
- @ <p>File ages are expressed relative to the
1036
- @ %z(href("%R/ci/%!S",zUuid))[%S(zUuid)]</a> check-in time of
1108
+ @ <p>File ages are expressed relative to the check-in time of
10371109
@ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
10381110
@
10391111
@ <div class='fileage'><table>
10401112
@ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
10411113
db_prepare(&q1,
@@ -1050,14 +1122,13 @@
10501122
" AND blob.rid=event.objid\n"
10511123
" ORDER BY event.mtime DESC;",
10521124
TAG_BRANCH
10531125
);
10541126
db_prepare(&q2,
1055
- "SELECT blob.uuid, filename.name, fileage.fid\n"
1056
- " FROM fileage, blob, filename\n"
1127
+ "SELECT filename.name, fileage.fid\n"
1128
+ " FROM fileage, filename\n"
10571129
" WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1058
- " AND blob.rid=fileage.fid;"
10591130
);
10601131
while( db_step(&q1)==SQLITE_ROW ){
10611132
double age = baseTime - db_column_double(&q1, 0);
10621133
int mid = db_column_int(&q1, 1);
10631134
const char *zUuid = db_column_text(&q1, 2);
@@ -1067,24 +1138,24 @@
10671138
char *zAge = human_readable_age(age);
10681139
@ <tr><td>%s(zAge)</td>
10691140
@ <td>
10701141
db_bind_int(&q2, ":mid", mid);
10711142
while( db_step(&q2)==SQLITE_ROW ){
1072
- const char *zFUuid = db_column_text(&q2,0);
1073
- const char *zFile = db_column_text(&q2,1);
1074
- int fid = db_column_int(&q2,2);
1143
+ const char *zFile = db_column_text(&q2,0);
1144
+ @ %z(href("%R/file?name=%T&ci=%!S",zFile,zUuid))%h(zFile)</a> \
10751145
if( showId ){
1076
- @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
1146
+ int fid = db_column_int(&q2,1);
1147
+ @ (%d(fid))<br />
10771148
}else{
1078
- @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
1149
+ @ </a><br />
10791150
}
10801151
}
10811152
db_reset(&q2);
10821153
@ </td>
10831154
@ <td>
10841155
@ %W(zComment)
1085
- @ (check-in:&nbsp;%z(href("%R/ci/%!S",zUuid))%S(zUuid)</a>,
1156
+ @ (check-in:&nbsp;%z(href("%R/info/%!S",zUuid))%S(zUuid)</a>,
10861157
if( showId ){
10871158
@ id: %d(mid)
10881159
}
10891160
@ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
10901161
@ branch:&nbsp;\
10911162
--- src/browse.c
+++ src/browse.c
@@ -59,10 +59,18 @@
59 zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
60 sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
61 }
62 }
63
 
 
 
 
 
 
 
 
64 /*
65 ** Given a pathname which is a relative path from the root of
66 ** the repository to a file or directory, compute a string which
67 ** is an HTML rendering of that path with hyperlinks on each
68 ** directory component of the path where the hyperlink redirects
@@ -76,29 +84,36 @@
76 void hyperlinked_path(
77 const char *zPath, /* Path to render */
78 Blob *pOut, /* Write into this blob */
79 const char *zCI, /* check-in name, or NULL */
80 const char *zURI, /* "dir" or "tree" */
81 const char *zREx /* Extra query parameters */
 
82 ){
83 int i, j;
84 char *zSep = "";
85
86 for(i=0; zPath[i]; i=j){
87 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88 if( zPath[j] && g.perm.Hyperlink ){
89 if( zCI ){
90 char *zLink = href("%R/%s?name=%#T%s&ci=%!S", zURI, j, zPath, zREx,zCI);
91 blob_appendf(pOut, "%s%z%#h</a>",
92 zSep, zLink, j-i, &zPath[i]);
93 }else{
94 char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
95 blob_appendf(pOut, "%s%z%#h</a>",
96 zSep, zLink, j-i, &zPath[i]);
97 }
98 }else{
99 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
 
 
 
 
 
 
100 }
101 zSep = "/";
102 while( zPath[j]=='/' ){ j++; }
103 }
104 }
@@ -127,27 +142,24 @@
127 char *zPrefix;
128 Stmt q;
129 const char *zCI = P("ci");
130 int rid = 0;
131 char *zUuid = 0;
132 Blob dirname;
133 Manifest *pM = 0;
134 const char *zSubdirLink;
135 int linkTrunk = 1;
136 int linkTip = 1;
137 HQuery sURI;
 
 
 
138
 
139 if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
140 login_check_credentials();
141 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
142 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
143 style_header("File List");
144 style_adunit_config(ADUNIT_RIGHT_OK);
145 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
146 pathelementFunc, 0, 0);
147 url_initialize(&sURI, "dir");
148 cgi_query_parameters_to_url(&sURI);
149
150 /* If the name= parameter is an empty string, make it a NULL pointer */
151 if( zD && strlen(zD)==0 ){ zD = 0; }
152
153 /* If a specific check-in is requested, fetch and parse it. If the
@@ -159,53 +171,80 @@
159 if( pM ){
160 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
161 linkTrunk = trunkRid && rid != trunkRid;
162 linkTip = rid != symbolic_name_to_rid("tip", "ci");
163 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
 
 
 
164 }else{
165 zCI = 0;
166 }
167 }
168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169 /* Compute the title of the page */
170 blob_zero(&dirname);
171 if( zD ){
172 blob_append(&dirname, "in directory ", -1);
173 hyperlinked_path(zD, &dirname, zCI, "dir", "");
 
 
 
174 zPrefix = mprintf("%s/", zD);
175 style_submenu_element("Top-Level", "%s",
176 url_render(&sURI, "name", 0, 0, 0));
177 }else{
178 blob_append(&dirname, "in the top-level directory", -1);
179 zPrefix = "";
180 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181 if( linkTrunk ){
182 style_submenu_element("Trunk", "%s",
183 url_render(&sURI, "ci", "trunk", 0, 0));
184 }
185 if( linkTip ){
186 style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
187 }
188 if( zCI ){
189 @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
190 @ %s(blob_str(&dirname))
191 if( zD ){
192 @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
193 }
194 @ </h2>
195 zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix);
196 if( nD==0 ){
197 style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid);
198 }
199 }else{
200 @ <h2>The union of all files from all check-ins
201 @ %s(blob_str(&dirname))
202 if( zD ){
203 @ &nbsp;&nbsp;%z(href("%R/timeline?chng=%T/*", zD))[history]</a>
204 }
205 @ </h2>
206 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
207 }
208 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
209 style_submenu_element("Tree-View", "%s",
210 url_render(&sURI, "type", "tree", 0, 0));
211
@@ -282,12 +321,11 @@
282 zFN++;
283 @ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
284 }else{
285 const char *zLink;
286 if( zCI ){
287 const char *zUuid = db_column_text(&q, 1);
288 zLink = href("%R/artifact/%!S",zUuid);
289 }else{
290 zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
291 }
292 @ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
293 }
@@ -612,11 +650,15 @@
612 HQuery sURI; /* Hyperlink */
613 int startExpanded; /* True to start out with the tree expanded */
614 int showDirOnly; /* Show directories only. Omit files */
615 int nDir = 0; /* Number of directories. Used for ID attributes */
616 char *zProjectName = db_get("project-name", 0);
 
 
 
617
 
618 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
619 memset(&sTree, 0, sizeof(sTree));
620 login_check_credentials();
621 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
622 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
@@ -624,14 +666,12 @@
624 pathelementFunc, 0, 0);
625 url_initialize(&sURI, "tree");
626 cgi_query_parameters_to_url(&sURI);
627 if( PB("nofiles") ){
628 showDirOnly = 1;
629 style_header("Folder Hierarchy");
630 }else{
631 showDirOnly = 0;
632 style_header("File Tree");
633 }
634 style_adunit_config(ADUNIT_RIGHT_OK);
635 if( PB("expand") ){
636 startExpanded = 1;
637 }else{
@@ -660,37 +700,55 @@
660 linkTip = rid != symbolic_name_to_rid("tip", "ci");
661 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
662 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
663 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
664 " FROM event WHERE objid=%d", rid);
 
 
 
665 }else{
666 zCI = 0;
667 }
668 }
669 if( zCI==0 ){
670 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
671 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
672 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
674 /* Compute the title of the page */
675 blob_zero(&dirname);
676 if( zD ){
677 blob_append(&dirname, "within directory ", -1);
678 hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
679 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
680 style_submenu_element("Top-Level", "%s",
681 url_render(&sURI, "name", 0, 0, 0));
682 }else{
683 if( zRE ){
684 blob_appendf(&dirname, "matching \"%s\"", zRE);
685 }
686 }
687 style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
688 if( zCI ){
689 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
690 if( nD==0 && !showDirOnly ){
691 style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid);
692 }
693 }
694 if( linkTrunk ){
695 style_submenu_element("Trunk", "%s",
696 url_render(&sURI, "ci", "trunk", 0, 0));
@@ -745,10 +803,11 @@
745 tree_add_node(&sTree, zName, zUuid, mtime);
746 nFile++;
747 }
748 db_finalize(&q);
749 }
 
750
751 if( showDirOnly ){
752 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
753 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
754 }
@@ -755,18 +814,24 @@
755 zObjType = "Folders";
756 }else{
757 zObjType = "Files";
758 }
759
760 style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
761
762 if( zCI ){
763 @ <h2>%s(zObjType) from
764 if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
765 @ "%h(zCI)"
766 }
767 @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
 
 
 
 
 
 
768 }else{
769 int n = db_int(0, "SELECT count(*) FROM plink");
770 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
771 }
772 if( useMtime ){
@@ -824,11 +889,11 @@
824 nDir++;
825 }else if( !showDirOnly ){
826 const char *zFileClass = fileext_class(p->zName);
827 char *zLink;
828 if( zCI ){
829 zLink = href("%R/artifact/%!S",p->zUuid);
830 }else{
831 zLink = href("%R/finfo?name=%T",p->zFullName);
832 }
833 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
834 @ %z(zLink)%h(p->zName)</a>
@@ -1001,10 +1066,11 @@
1001 int rid;
1002 const char *zName;
1003 const char *zGlob;
1004 const char *zUuid;
1005 const char *zNow; /* Time of check-in */
 
1006 int showId = PB("showid");
1007 Stmt q1, q2;
1008 double baseTime;
1009 login_check_credentials();
1010 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1014,28 +1080,34 @@
1014 rid = symbolic_name_to_rid(zName, "ci");
1015 if( rid==0 ){
1016 fossil_fatal("not a valid check-in: %s", zName);
1017 }
1018 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
 
1019 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1020 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1021 " WHERE objid=%d", rid);
1022 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1023 style_header("File Ages");
1024 zGlob = P("glob");
1025 compute_fileage(rid,zGlob);
1026 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1027
1028 @ <h1>Files in
1029 @ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
 
 
 
 
 
 
1030 if( zGlob && zGlob[0] ){
1031 @ that match "%h(zGlob)"
1032 }
1033 @ ordered by age</h1>
1034 @
1035 @ <p>File ages are expressed relative to the
1036 @ %z(href("%R/ci/%!S",zUuid))[%S(zUuid)]</a> check-in time of
1037 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1038 @
1039 @ <div class='fileage'><table>
1040 @ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
1041 db_prepare(&q1,
@@ -1050,14 +1122,13 @@
1050 " AND blob.rid=event.objid\n"
1051 " ORDER BY event.mtime DESC;",
1052 TAG_BRANCH
1053 );
1054 db_prepare(&q2,
1055 "SELECT blob.uuid, filename.name, fileage.fid\n"
1056 " FROM fileage, blob, filename\n"
1057 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1058 " AND blob.rid=fileage.fid;"
1059 );
1060 while( db_step(&q1)==SQLITE_ROW ){
1061 double age = baseTime - db_column_double(&q1, 0);
1062 int mid = db_column_int(&q1, 1);
1063 const char *zUuid = db_column_text(&q1, 2);
@@ -1067,24 +1138,24 @@
1067 char *zAge = human_readable_age(age);
1068 @ <tr><td>%s(zAge)</td>
1069 @ <td>
1070 db_bind_int(&q2, ":mid", mid);
1071 while( db_step(&q2)==SQLITE_ROW ){
1072 const char *zFUuid = db_column_text(&q2,0);
1073 const char *zFile = db_column_text(&q2,1);
1074 int fid = db_column_int(&q2,2);
1075 if( showId ){
1076 @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
 
1077 }else{
1078 @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
1079 }
1080 }
1081 db_reset(&q2);
1082 @ </td>
1083 @ <td>
1084 @ %W(zComment)
1085 @ (check-in:&nbsp;%z(href("%R/ci/%!S",zUuid))%S(zUuid)</a>,
1086 if( showId ){
1087 @ id: %d(mid)
1088 }
1089 @ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
1090 @ branch:&nbsp;\
1091
--- src/browse.c
+++ src/browse.c
@@ -59,10 +59,18 @@
59 zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
60 sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
61 }
62 }
63
64 /*
65 ** Flag arguments for hyperlinked_path()
66 */
67 #if INTERFACE
68 # define LINKPATH_FINFO 0x0001 /* Link final term to /finfo */
69 # define LINKPATH_FILE 0x0002 /* Link final term to /file */
70 #endif
71
72 /*
73 ** Given a pathname which is a relative path from the root of
74 ** the repository to a file or directory, compute a string which
75 ** is an HTML rendering of that path with hyperlinks on each
76 ** directory component of the path where the hyperlink redirects
@@ -76,29 +84,36 @@
84 void hyperlinked_path(
85 const char *zPath, /* Path to render */
86 Blob *pOut, /* Write into this blob */
87 const char *zCI, /* check-in name, or NULL */
88 const char *zURI, /* "dir" or "tree" */
89 const char *zREx, /* Extra query parameters */
90 unsigned int mFlags /* Extra flags */
91 ){
92 int i, j;
93 char *zSep = "";
94
95 for(i=0; zPath[i]; i=j){
96 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
97 if( zPath[j]==0 ){
98 if( mFlags & LINKPATH_FILE ){
99 zURI = "file";
100 }else if( mFlags & LINKPATH_FINFO ){
101 zURI = "finfo";
102 }else{
103 blob_appendf(pOut, "/%h", zPath+i);
104 break;
105 }
106 }
107 if( zCI ){
108 char *zLink = href("%R/%s?name=%#T%s&ci=%T", zURI, j, zPath, zREx,zCI);
109 blob_appendf(pOut, "%s%z%#h</a>",
110 zSep, zLink, j-i, &zPath[i]);
111 }else{
112 char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113 blob_appendf(pOut, "%s%z%#h</a>",
114 zSep, zLink, j-i, &zPath[i]);
115 }
116 zSep = "/";
117 while( zPath[j]=='/' ){ j++; }
118 }
119 }
@@ -127,27 +142,24 @@
142 char *zPrefix;
143 Stmt q;
144 const char *zCI = P("ci");
145 int rid = 0;
146 char *zUuid = 0;
 
147 Manifest *pM = 0;
148 const char *zSubdirLink;
149 int linkTrunk = 1;
150 int linkTip = 1;
151 HQuery sURI;
152 int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
153 int isBranchCI = 0; /* True if ci= refers to a branch name */
154 char *zHeader = 0;
155
156 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
157 if( strcmp(PD("type","flat"),"tree")==0 ){ page_tree(); return; }
158 login_check_credentials();
159 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
160 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
 
 
 
 
 
 
161
162 /* If the name= parameter is an empty string, make it a NULL pointer */
163 if( zD && strlen(zD)==0 ){ zD = 0; }
164
165 /* If a specific check-in is requested, fetch and parse it. If the
@@ -159,53 +171,80 @@
171 if( pM ){
172 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
173 linkTrunk = trunkRid && rid != trunkRid;
174 linkTip = rid != symbolic_name_to_rid("tip", "ci");
175 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
176 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177 isBranchCI = branch_includes_uuid(zCI, zUuid);
178 Th_Store("current_checkin", zCI);
179 }else{
180 zCI = 0;
181 }
182 }
183
184 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
185 if( zD==0 ){
186 if( zCI ){
187 zHeader = mprintf("Top-level Files of %s", zCI);
188 }else{
189 zHeader = mprintf("All Top-level Files");
190 }
191 }else{
192 if( zCI ){
193 zHeader = mprintf("Files in %s/ of %s", zD, zCI);
194 }else{
195 zHeader = mprintf("All File in %s/", zD);
196 }
197 }
198 style_header("%s", zHeader);
199 fossil_free(zHeader);
200 style_adunit_config(ADUNIT_RIGHT_OK);
201 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
202 pathelementFunc, 0, 0);
203 url_initialize(&sURI, "dir");
204 cgi_query_parameters_to_url(&sURI);
205
206 /* Compute the title of the page */
 
207 if( zD ){
208 Blob dirname;
209 blob_init(&dirname, 0, 0);
210 hyperlinked_path(zD, &dirname, zCI, "dir", "", 0);
211 @ <h2>Files in directory %s(blob_str(&dirname)) \
212 blob_reset(&dirname);
213 zPrefix = mprintf("%s/", zD);
214 style_submenu_element("Top-Level", "%s",
215 url_render(&sURI, "name", 0, 0, 0));
216 }else{
217 @ <h2>Files in the top-level directory \
218 zPrefix = "";
219 }
220 if( zCI ){
221 if( fossil_strcmp(zCI,"tip")==0 ){
222 @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a></h2>
223 }else if( isBranchCI ){
224 @ from the %z(href("%R/info?name=%T",zCI))latest check-in</a> \
225 @ of branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
226 }else {
227 @ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
228 }
229 zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
230 if( nD==0 ){
231 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
232 }
233 }else{
234 @ in any check-in</h2>
235 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
236 }
237 if( linkTrunk ){
238 style_submenu_element("Trunk", "%s",
239 url_render(&sURI, "ci", "trunk", 0, 0));
240 }
241 if( linkTip ){
242 style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
243 }
244 if( zD ){
245 style_submenu_element("History","%R/timeline?chng=%T/*", zD);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246 }
247 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
248 style_submenu_element("Tree-View", "%s",
249 url_render(&sURI, "type", "tree", 0, 0));
250
@@ -282,12 +321,11 @@
321 zFN++;
322 @ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
323 }else{
324 const char *zLink;
325 if( zCI ){
326 zLink = href("%R/file?name=%T%T&ci=%T",zPrefix,zFN,zCI);
 
327 }else{
328 zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
329 }
330 @ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
331 }
@@ -612,11 +650,15 @@
650 HQuery sURI; /* Hyperlink */
651 int startExpanded; /* True to start out with the tree expanded */
652 int showDirOnly; /* Show directories only. Omit files */
653 int nDir = 0; /* Number of directories. Used for ID attributes */
654 char *zProjectName = db_get("project-name", 0);
655 int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
656 int isBranchCI = 0; /* ci= refers to a branch name */
657 char *zHeader = 0;
658
659 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
660 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
661 memset(&sTree, 0, sizeof(sTree));
662 login_check_credentials();
663 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
664 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
@@ -624,14 +666,12 @@
666 pathelementFunc, 0, 0);
667 url_initialize(&sURI, "tree");
668 cgi_query_parameters_to_url(&sURI);
669 if( PB("nofiles") ){
670 showDirOnly = 1;
 
671 }else{
672 showDirOnly = 0;
 
673 }
674 style_adunit_config(ADUNIT_RIGHT_OK);
675 if( PB("expand") ){
676 startExpanded = 1;
677 }else{
@@ -660,37 +700,55 @@
700 linkTip = rid != symbolic_name_to_rid("tip", "ci");
701 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
702 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
703 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
704 " FROM event WHERE objid=%d", rid);
705 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
706 isBranchCI = branch_includes_uuid(zCI, zUuid);
707 Th_Store("current_checkin", zCI);
708 }else{
709 zCI = 0;
710 }
711 }
712 if( zCI==0 ){
713 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
714 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
715 }
716
717 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
718 if( zD==0 ){
719 if( zCI ){
720 zHeader = mprintf("Top-level Files of %s", zCI);
721 }else{
722 zHeader = mprintf("All Top-level Files");
723 }
724 }else{
725 if( zCI ){
726 zHeader = mprintf("Files in %s/ of %s", zD, zCI);
727 }else{
728 zHeader = mprintf("All File in %s/", zD);
729 }
730 }
731 style_header("%s", zHeader);
732 fossil_free(zHeader);
733
734 /* Compute the title of the page */
735 blob_zero(&dirname);
736 if( zD ){
737 blob_append(&dirname, "within directory ", -1);
738 hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
739 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
740 style_submenu_element("Top-Level", "%s",
741 url_render(&sURI, "name", 0, 0, 0));
742 }else if( zRE ){
743 blob_appendf(&dirname, "matching \"%s\"", zRE);
 
 
744 }
745 style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
746 if( zCI ){
747 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
748 if( nD==0 && !showDirOnly ){
749 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
750 }
751 }
752 if( linkTrunk ){
753 style_submenu_element("Trunk", "%s",
754 url_render(&sURI, "ci", "trunk", 0, 0));
@@ -745,10 +803,11 @@
803 tree_add_node(&sTree, zName, zUuid, mtime);
804 nFile++;
805 }
806 db_finalize(&q);
807 }
808 style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
809
810 if( showDirOnly ){
811 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
812 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
813 }
@@ -755,18 +814,24 @@
814 zObjType = "Folders";
815 }else{
816 zObjType = "Files";
817 }
818
819 if( zCI && strcmp(zCI,"tip")==0 ){
820 @ <h2>%s(zObjType) in the %z(href("%R/info?name=tip"))latest check-in</a>
821 }else if( isBranchCI ){
822 @ <h2>%s(zObjType) in the %z(href("%R/info?name=%T",zCI))latest check-in\
823 @ </a> for branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a>
824 if( blob_size(&dirname) ){
825 @ and %s(blob_str(&dirname))</h2>
826 }
827 }else if( zCI ){
828 @ <h2>%s(zObjType) for check-in \
829 @ %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
830 if( blob_size(&dirname) ){
831 @ and %s(blob_str(&dirname))</h2>
832 }
833 }else{
834 int n = db_int(0, "SELECT count(*) FROM plink");
835 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
836 }
837 if( useMtime ){
@@ -824,11 +889,11 @@
889 nDir++;
890 }else if( !showDirOnly ){
891 const char *zFileClass = fileext_class(p->zName);
892 char *zLink;
893 if( zCI ){
894 zLink = href("%R/file?name=%T&ci=%T",p->zFullName,zCI);
895 }else{
896 zLink = href("%R/finfo?name=%T",p->zFullName);
897 }
898 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
899 @ %z(zLink)%h(p->zName)</a>
@@ -1001,10 +1066,11 @@
1066 int rid;
1067 const char *zName;
1068 const char *zGlob;
1069 const char *zUuid;
1070 const char *zNow; /* Time of check-in */
1071 int isBranchCI; /* name= is a branch name */
1072 int showId = PB("showid");
1073 Stmt q1, q2;
1074 double baseTime;
1075 login_check_credentials();
1076 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1014,28 +1080,34 @@
1080 rid = symbolic_name_to_rid(zName, "ci");
1081 if( rid==0 ){
1082 fossil_fatal("not a valid check-in: %s", zName);
1083 }
1084 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1085 isBranchCI = branch_includes_uuid(zName,zUuid);
1086 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1087 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1088 " WHERE objid=%d", rid);
1089 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1090 style_header("File Ages");
1091 zGlob = P("glob");
1092 compute_fileage(rid,zGlob);
1093 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1094
1095 if( fossil_strcmp(zName,"tip")==0 ){
1096 @ <h1>Files in the %z(href("%R/info?name=tip"))latest check-in</a>
1097 }else if( isBranchCI ){
1098 @ <h1>Files in the %z(href("%R/info?name=%T",zName))latest check-in</a>
1099 @ of branch %z(href("%R/timeline?r=%T",zName))%h(zName)</a>
1100 }else{
1101 @ <h1>Files in check-in %z(href("%R/info?name=%T",zName))%h(zName)</a>
1102 }
1103 if( zGlob && zGlob[0] ){
1104 @ that match "%h(zGlob)"
1105 }
1106 @ ordered by age</h1>
1107 @
1108 @ <p>File ages are expressed relative to the check-in time of
 
1109 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1110 @
1111 @ <div class='fileage'><table>
1112 @ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
1113 db_prepare(&q1,
@@ -1050,14 +1122,13 @@
1122 " AND blob.rid=event.objid\n"
1123 " ORDER BY event.mtime DESC;",
1124 TAG_BRANCH
1125 );
1126 db_prepare(&q2,
1127 "SELECT filename.name, fileage.fid\n"
1128 " FROM fileage, filename\n"
1129 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
 
1130 );
1131 while( db_step(&q1)==SQLITE_ROW ){
1132 double age = baseTime - db_column_double(&q1, 0);
1133 int mid = db_column_int(&q1, 1);
1134 const char *zUuid = db_column_text(&q1, 2);
@@ -1067,24 +1138,24 @@
1138 char *zAge = human_readable_age(age);
1139 @ <tr><td>%s(zAge)</td>
1140 @ <td>
1141 db_bind_int(&q2, ":mid", mid);
1142 while( db_step(&q2)==SQLITE_ROW ){
1143 const char *zFile = db_column_text(&q2,0);
1144 @ %z(href("%R/file?name=%T&ci=%!S",zFile,zUuid))%h(zFile)</a> \
 
1145 if( showId ){
1146 int fid = db_column_int(&q2,1);
1147 @ (%d(fid))<br />
1148 }else{
1149 @ </a><br />
1150 }
1151 }
1152 db_reset(&q2);
1153 @ </td>
1154 @ <td>
1155 @ %W(zComment)
1156 @ (check-in:&nbsp;%z(href("%R/info/%!S",zUuid))%S(zUuid)</a>,
1157 if( showId ){
1158 @ id: %d(mid)
1159 }
1160 @ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
1161 @ branch:&nbsp;\
1162
+10 -2
--- src/builtin.c
+++ src/builtin.c
@@ -55,17 +55,25 @@
5555
return (char*)builtin_file(zFilename, 0);
5656
}
5757
5858
/*
5959
** COMMAND: test-builtin-list
60
+**
61
+** If -verbose is used, it outputs a line at the end
62
+** with the total item count and size.
6063
**
6164
** List the names and sizes of all built-in resources.
6265
*/
6366
void test_builtin_list(void){
64
- int i;
67
+ int i, size = 0;;
6568
for(i=0; i<count(aBuiltinFiles); i++){
66
- fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte);
69
+ const int n = aBuiltinFiles[i].nByte;
70
+ fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,n);
71
+ size += n;
72
+ }
73
+ if(find_option("verbose","v",0)!=0){
74
+ fossil_print("%d entries totaling %d bytes\n", i, size);
6775
}
6876
}
6977
7078
/*
7179
** WEBPAGE: test-builtin-files
7280
--- src/builtin.c
+++ src/builtin.c
@@ -55,17 +55,25 @@
55 return (char*)builtin_file(zFilename, 0);
56 }
57
58 /*
59 ** COMMAND: test-builtin-list
 
 
 
60 **
61 ** List the names and sizes of all built-in resources.
62 */
63 void test_builtin_list(void){
64 int i;
65 for(i=0; i<count(aBuiltinFiles); i++){
66 fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte);
 
 
 
 
 
67 }
68 }
69
70 /*
71 ** WEBPAGE: test-builtin-files
72
--- src/builtin.c
+++ src/builtin.c
@@ -55,17 +55,25 @@
55 return (char*)builtin_file(zFilename, 0);
56 }
57
58 /*
59 ** COMMAND: test-builtin-list
60 **
61 ** If -verbose is used, it outputs a line at the end
62 ** with the total item count and size.
63 **
64 ** List the names and sizes of all built-in resources.
65 */
66 void test_builtin_list(void){
67 int i, size = 0;;
68 for(i=0; i<count(aBuiltinFiles); i++){
69 const int n = aBuiltinFiles[i].nByte;
70 fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,n);
71 size += n;
72 }
73 if(find_option("verbose","v",0)!=0){
74 fossil_print("%d entries totaling %d bytes\n", i, size);
75 }
76 }
77
78 /*
79 ** WEBPAGE: test-builtin-files
80
--- src/capabilities.c
+++ src/capabilities.c
@@ -239,11 +239,11 @@
239239
char *zOneLiner; /* One-line summary */
240240
} aCap[] = {
241241
{ 'a', CAPCLASS_SUPER, 0,
242242
"Admin", "Create and delete users" },
243243
{ 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
244
- "Attach", "Add attchments to wiki or tickets" },
244
+ "Attach", "Add attachments to wiki or tickets" },
245245
{ 'c', CAPCLASS_TKT, 0,
246246
"Append-Tkt", "Append to existing tickets" },
247247
/*
248248
** d unused since fork from CVSTrac;
249249
** see https://fossil-scm.org/forum/forumpost/43c78f4bef
250250
--- src/capabilities.c
+++ src/capabilities.c
@@ -239,11 +239,11 @@
239 char *zOneLiner; /* One-line summary */
240 } aCap[] = {
241 { 'a', CAPCLASS_SUPER, 0,
242 "Admin", "Create and delete users" },
243 { 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
244 "Attach", "Add attchments to wiki or tickets" },
245 { 'c', CAPCLASS_TKT, 0,
246 "Append-Tkt", "Append to existing tickets" },
247 /*
248 ** d unused since fork from CVSTrac;
249 ** see https://fossil-scm.org/forum/forumpost/43c78f4bef
250
--- src/capabilities.c
+++ src/capabilities.c
@@ -239,11 +239,11 @@
239 char *zOneLiner; /* One-line summary */
240 } aCap[] = {
241 { 'a', CAPCLASS_SUPER, 0,
242 "Admin", "Create and delete users" },
243 { 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
244 "Attach", "Add attachments to wiki or tickets" },
245 { 'c', CAPCLASS_TKT, 0,
246 "Append-Tkt", "Append to existing tickets" },
247 /*
248 ** d unused since fork from CVSTrac;
249 ** see https://fossil-scm.org/forum/forumpost/43c78f4bef
250
+2 -1
--- src/captcha.c
+++ src/captcha.c
@@ -558,11 +558,12 @@
558558
/*
559559
** Add a "Speak the captcha" button.
560560
*/
561561
void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
562562
if( zMsg==0 ) zMsg = "Speak the text";
563
- @ <input type="button" value="%h(zMsg)" id="speakthetext">
563
+ @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \
564
+ @ id="speakthetext">
564565
@ <script nonce="%h(style_nonce())">
565566
@ document.getElementById("speakthetext").onclick = function(){
566567
@ var audio = window.fossilAudioCaptcha \
567568
@ || new Audio("%R/captcha-audio/%u(uSeed)");
568569
@ window.fossilAudioCaptcha = audio;
569570
--- src/captcha.c
+++ src/captcha.c
@@ -558,11 +558,12 @@
558 /*
559 ** Add a "Speak the captcha" button.
560 */
561 void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
562 if( zMsg==0 ) zMsg = "Speak the text";
563 @ <input type="button" value="%h(zMsg)" id="speakthetext">
 
564 @ <script nonce="%h(style_nonce())">
565 @ document.getElementById("speakthetext").onclick = function(){
566 @ var audio = window.fossilAudioCaptcha \
567 @ || new Audio("%R/captcha-audio/%u(uSeed)");
568 @ window.fossilAudioCaptcha = audio;
569
--- src/captcha.c
+++ src/captcha.c
@@ -558,11 +558,12 @@
558 /*
559 ** Add a "Speak the captcha" button.
560 */
561 void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
562 if( zMsg==0 ) zMsg = "Speak the text";
563 @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \
564 @ id="speakthetext">
565 @ <script nonce="%h(style_nonce())">
566 @ document.getElementById("speakthetext").onclick = function(){
567 @ var audio = window.fossilAudioCaptcha \
568 @ || new Audio("%R/captcha-audio/%u(uSeed)");
569 @ window.fossilAudioCaptcha = audio;
570
+32 -10
--- src/cgi.c
+++ src/cgi.c
@@ -174,12 +174,12 @@
174174
}
175175
176176
/*
177177
** Additional information used to form the HTTP reply
178178
*/
179
-static const char *zContentType = "text/html"; /* Content type of the reply */
180
-static const char *zReplyStatus = "OK"; /* Reply status description */
179
+static const char *zContentType = "text/html"; /* Content type of the reply */
180
+static const char *zReplyStatus = "OK"; /* Reply status description */
181181
static int iReplyStatus = 200; /* Reply status code */
182182
static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
183183
static int rangeStart = 0; /* Start of Range: */
184184
static int rangeEnd = 0; /* End of Range: plus 1 */
185185
@@ -293,11 +293,11 @@
293293
}
294294
if( g.isConst ){
295295
/* isConst means that the reply is guaranteed to be invariant, even
296296
** after configuration changes and/or Fossil binary recompiles. */
297297
fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
298
- }else if( etag_tag()!=0 ){
298
+ }else if( etag_tag()[0]!=0 ){
299299
fprintf(g.httpOut, "ETag: %s\r\n", etag_tag());
300300
fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
301301
}else{
302302
fprintf(g.httpOut, "Cache-control: no-cache\r\n");
303303
}
@@ -329,17 +329,17 @@
329329
*/
330330
331331
/* Content intended for logged in users should only be cached in
332332
** the browser, not some shared location.
333333
*/
334
- fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
335
- if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
336
- cgi_combine_header_and_body();
337
- blob_compress(&cgiContent[0], &cgiContent[0]);
338
- }
339
-
340334
if( iReplyStatus!=304 ) {
335
+ fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
336
+ if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
337
+ cgi_combine_header_and_body();
338
+ blob_compress(&cgiContent[0], &cgiContent[0]);
339
+ }
340
+
341341
if( is_gzippable() && iReplyStatus!=206 ){
342342
int i;
343343
gzip_begin(0);
344344
for( i=0; i<2; i++ ){
345345
int size = blob_size(&cgiContent[i]);
@@ -359,11 +359,12 @@
359359
fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
360360
}else{
361361
total_size = 0;
362362
}
363363
fprintf(g.httpOut, "\r\n");
364
- if( total_size>0 && iReplyStatus != 304
364
+ if( total_size>0
365
+ && iReplyStatus!=304
365366
&& fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
366367
){
367368
int i, size;
368369
for(i=0; i<2; i++){
369370
size = blob_size(&cgiContent[i]);
@@ -432,10 +433,31 @@
432433
va_list ap;
433434
va_start(ap, zFormat);
434435
cgi_redirect(vmprintf(zFormat, ap));
435436
va_end(ap);
436437
}
438
+
439
+/*
440
+** Add a "Content-disposition: attachment; filename=%s" header to the reply.
441
+*/
442
+void cgi_content_disposition_filename(const char *zFilename){
443
+ char *z;
444
+ int i, n;
445
+
446
+ /* 0123456789 123456789 123456789 123456789 123456*/
447
+ z = mprintf("Content-Disposition: attachment; filename=\"%s\";\r\n",
448
+ file_tail(zFilename));
449
+ n = (int)strlen(z);
450
+ for(i=43; i<n-4; i++){
451
+ char c = z[i];
452
+ if( fossil_isalnum(c) ) continue;
453
+ if( c=='.' || c=='-' || c=='/' ) continue;
454
+ z[i] = '_';
455
+ }
456
+ cgi_append_header(z);
457
+ fossil_free(z);
458
+}
437459
438460
/*
439461
** Return the URL for the caller. This is obtained from either the
440462
** referer CGI parameter, if it exists, or the HTTP_REFERER HTTP parameter.
441463
** If neither exist, return zDefault.
442464
--- src/cgi.c
+++ src/cgi.c
@@ -174,12 +174,12 @@
174 }
175
176 /*
177 ** Additional information used to form the HTTP reply
178 */
179 static const char *zContentType = "text/html"; /* Content type of the reply */
180 static const char *zReplyStatus = "OK"; /* Reply status description */
181 static int iReplyStatus = 200; /* Reply status code */
182 static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
183 static int rangeStart = 0; /* Start of Range: */
184 static int rangeEnd = 0; /* End of Range: plus 1 */
185
@@ -293,11 +293,11 @@
293 }
294 if( g.isConst ){
295 /* isConst means that the reply is guaranteed to be invariant, even
296 ** after configuration changes and/or Fossil binary recompiles. */
297 fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
298 }else if( etag_tag()!=0 ){
299 fprintf(g.httpOut, "ETag: %s\r\n", etag_tag());
300 fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
301 }else{
302 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
303 }
@@ -329,17 +329,17 @@
329 */
330
331 /* Content intended for logged in users should only be cached in
332 ** the browser, not some shared location.
333 */
334 fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
335 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
336 cgi_combine_header_and_body();
337 blob_compress(&cgiContent[0], &cgiContent[0]);
338 }
339
340 if( iReplyStatus!=304 ) {
 
 
 
 
 
 
341 if( is_gzippable() && iReplyStatus!=206 ){
342 int i;
343 gzip_begin(0);
344 for( i=0; i<2; i++ ){
345 int size = blob_size(&cgiContent[i]);
@@ -359,11 +359,12 @@
359 fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
360 }else{
361 total_size = 0;
362 }
363 fprintf(g.httpOut, "\r\n");
364 if( total_size>0 && iReplyStatus != 304
 
365 && fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
366 ){
367 int i, size;
368 for(i=0; i<2; i++){
369 size = blob_size(&cgiContent[i]);
@@ -432,10 +433,31 @@
432 va_list ap;
433 va_start(ap, zFormat);
434 cgi_redirect(vmprintf(zFormat, ap));
435 va_end(ap);
436 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
438 /*
439 ** Return the URL for the caller. This is obtained from either the
440 ** referer CGI parameter, if it exists, or the HTTP_REFERER HTTP parameter.
441 ** If neither exist, return zDefault.
442
--- src/cgi.c
+++ src/cgi.c
@@ -174,12 +174,12 @@
174 }
175
176 /*
177 ** Additional information used to form the HTTP reply
178 */
179 static const char *zContentType = "text/html"; /* Content type of the reply */
180 static const char *zReplyStatus = "OK"; /* Reply status description */
181 static int iReplyStatus = 200; /* Reply status code */
182 static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
183 static int rangeStart = 0; /* Start of Range: */
184 static int rangeEnd = 0; /* End of Range: plus 1 */
185
@@ -293,11 +293,11 @@
293 }
294 if( g.isConst ){
295 /* isConst means that the reply is guaranteed to be invariant, even
296 ** after configuration changes and/or Fossil binary recompiles. */
297 fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
298 }else if( etag_tag()[0]!=0 ){
299 fprintf(g.httpOut, "ETag: %s\r\n", etag_tag());
300 fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
301 }else{
302 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
303 }
@@ -329,17 +329,17 @@
329 */
330
331 /* Content intended for logged in users should only be cached in
332 ** the browser, not some shared location.
333 */
 
 
 
 
 
 
334 if( iReplyStatus!=304 ) {
335 fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
336 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
337 cgi_combine_header_and_body();
338 blob_compress(&cgiContent[0], &cgiContent[0]);
339 }
340
341 if( is_gzippable() && iReplyStatus!=206 ){
342 int i;
343 gzip_begin(0);
344 for( i=0; i<2; i++ ){
345 int size = blob_size(&cgiContent[i]);
@@ -359,11 +359,12 @@
359 fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
360 }else{
361 total_size = 0;
362 }
363 fprintf(g.httpOut, "\r\n");
364 if( total_size>0
365 && iReplyStatus!=304
366 && fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
367 ){
368 int i, size;
369 for(i=0; i<2; i++){
370 size = blob_size(&cgiContent[i]);
@@ -432,10 +433,31 @@
433 va_list ap;
434 va_start(ap, zFormat);
435 cgi_redirect(vmprintf(zFormat, ap));
436 va_end(ap);
437 }
438
439 /*
440 ** Add a "Content-disposition: attachment; filename=%s" header to the reply.
441 */
442 void cgi_content_disposition_filename(const char *zFilename){
443 char *z;
444 int i, n;
445
446 /* 0123456789 123456789 123456789 123456789 123456*/
447 z = mprintf("Content-Disposition: attachment; filename=\"%s\";\r\n",
448 file_tail(zFilename));
449 n = (int)strlen(z);
450 for(i=43; i<n-4; i++){
451 char c = z[i];
452 if( fossil_isalnum(c) ) continue;
453 if( c=='.' || c=='-' || c=='/' ) continue;
454 z[i] = '_';
455 }
456 cgi_append_header(z);
457 fossil_free(z);
458 }
459
460 /*
461 ** Return the URL for the caller. This is obtained from either the
462 ** referer CGI parameter, if it exists, or the HTTP_REFERER HTTP parameter.
463 ** If neither exist, return zDefault.
464
+14 -3
--- src/checkin.c
+++ src/checkin.c
@@ -2090,12 +2090,17 @@
20902090
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
20912091
noSign = find_option("nosign",0,0)!=0;
20922092
privateFlag = find_option("private",0,0)!=0;
20932093
forceDelta = find_option("delta",0,0)!=0;
20942094
forceBaseline = find_option("baseline",0,0)!=0;
2095
- if( forceDelta && forceBaseline ){
2096
- fossil_fatal("cannot use --delta and --baseline together");
2095
+ if( forceDelta ){
2096
+ if( forceBaseline ){
2097
+ fossil_fatal("cannot use --delta and --baseline together");
2098
+ }
2099
+ if( db_get_boolean("forbid-delta-manifests",0) ){
2100
+ fossil_fatal("delta manifests are prohibited in this repository");
2101
+ }
20972102
}
20982103
dryRunFlag = find_option("dry-run","n",0)!=0;
20992104
if( !dryRunFlag ){
21002105
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
21012106
}
@@ -2174,11 +2179,14 @@
21742179
** manifest) can continue to use this repository, do not create a new
21752180
** delta-manifest unless this repository already contains one or more
21762181
** delta-manifests, or unless the delta-manifest is explicitly requested
21772182
** by the --delta option.
21782183
*/
2179
- if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
2184
+ if( !forceDelta
2185
+ && !db_get_boolean("seen-delta-manifest",0)
2186
+ && !db_get_boolean("forbid-delta-manifests",0)
2187
+ ){
21802188
forceBaseline = 1;
21812189
}
21822190
21832191
/*
21842192
** Autosync if autosync is enabled and this is not a private check-in.
@@ -2648,10 +2656,11 @@
26482656
/* Commit */
26492657
db_multi_exec("DELETE FROM vvar WHERE name='ci-comment'");
26502658
db_multi_exec("PRAGMA repository.application_id=252006673;");
26512659
db_multi_exec("PRAGMA localdb.application_id=252006674;");
26522660
if( dryRunFlag ){
2661
+ leaf_ambiguity_warning(nvid,nvid);
26532662
db_end_transaction(1);
26542663
exit(1);
26552664
}
26562665
db_end_transaction(0);
26572666
@@ -2670,7 +2679,9 @@
26702679
int nTries = db_get_int("autosync-tries",1);
26712680
autosync_loop(syncFlags, nTries, 0);
26722681
}
26732682
if( count_nonbranch_children(vid)>1 ){
26742683
fossil_print("**** warning: a fork has occurred *****\n");
2684
+ }else{
2685
+ leaf_ambiguity_warning(nvid,nvid);
26752686
}
26762687
}
26772688
--- src/checkin.c
+++ src/checkin.c
@@ -2090,12 +2090,17 @@
2090 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
2091 noSign = find_option("nosign",0,0)!=0;
2092 privateFlag = find_option("private",0,0)!=0;
2093 forceDelta = find_option("delta",0,0)!=0;
2094 forceBaseline = find_option("baseline",0,0)!=0;
2095 if( forceDelta && forceBaseline ){
2096 fossil_fatal("cannot use --delta and --baseline together");
 
 
 
 
 
2097 }
2098 dryRunFlag = find_option("dry-run","n",0)!=0;
2099 if( !dryRunFlag ){
2100 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
2101 }
@@ -2174,11 +2179,14 @@
2174 ** manifest) can continue to use this repository, do not create a new
2175 ** delta-manifest unless this repository already contains one or more
2176 ** delta-manifests, or unless the delta-manifest is explicitly requested
2177 ** by the --delta option.
2178 */
2179 if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
 
 
 
2180 forceBaseline = 1;
2181 }
2182
2183 /*
2184 ** Autosync if autosync is enabled and this is not a private check-in.
@@ -2648,10 +2656,11 @@
2648 /* Commit */
2649 db_multi_exec("DELETE FROM vvar WHERE name='ci-comment'");
2650 db_multi_exec("PRAGMA repository.application_id=252006673;");
2651 db_multi_exec("PRAGMA localdb.application_id=252006674;");
2652 if( dryRunFlag ){
 
2653 db_end_transaction(1);
2654 exit(1);
2655 }
2656 db_end_transaction(0);
2657
@@ -2670,7 +2679,9 @@
2670 int nTries = db_get_int("autosync-tries",1);
2671 autosync_loop(syncFlags, nTries, 0);
2672 }
2673 if( count_nonbranch_children(vid)>1 ){
2674 fossil_print("**** warning: a fork has occurred *****\n");
 
 
2675 }
2676 }
2677
--- src/checkin.c
+++ src/checkin.c
@@ -2090,12 +2090,17 @@
2090 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
2091 noSign = find_option("nosign",0,0)!=0;
2092 privateFlag = find_option("private",0,0)!=0;
2093 forceDelta = find_option("delta",0,0)!=0;
2094 forceBaseline = find_option("baseline",0,0)!=0;
2095 if( forceDelta ){
2096 if( forceBaseline ){
2097 fossil_fatal("cannot use --delta and --baseline together");
2098 }
2099 if( db_get_boolean("forbid-delta-manifests",0) ){
2100 fossil_fatal("delta manifests are prohibited in this repository");
2101 }
2102 }
2103 dryRunFlag = find_option("dry-run","n",0)!=0;
2104 if( !dryRunFlag ){
2105 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
2106 }
@@ -2174,11 +2179,14 @@
2179 ** manifest) can continue to use this repository, do not create a new
2180 ** delta-manifest unless this repository already contains one or more
2181 ** delta-manifests, or unless the delta-manifest is explicitly requested
2182 ** by the --delta option.
2183 */
2184 if( !forceDelta
2185 && !db_get_boolean("seen-delta-manifest",0)
2186 && !db_get_boolean("forbid-delta-manifests",0)
2187 ){
2188 forceBaseline = 1;
2189 }
2190
2191 /*
2192 ** Autosync if autosync is enabled and this is not a private check-in.
@@ -2648,10 +2656,11 @@
2656 /* Commit */
2657 db_multi_exec("DELETE FROM vvar WHERE name='ci-comment'");
2658 db_multi_exec("PRAGMA repository.application_id=252006673;");
2659 db_multi_exec("PRAGMA localdb.application_id=252006674;");
2660 if( dryRunFlag ){
2661 leaf_ambiguity_warning(nvid,nvid);
2662 db_end_transaction(1);
2663 exit(1);
2664 }
2665 db_end_transaction(0);
2666
@@ -2670,7 +2679,9 @@
2679 int nTries = db_get_int("autosync-tries",1);
2680 autosync_loop(syncFlags, nTries, 0);
2681 }
2682 if( count_nonbranch_children(vid)>1 ){
2683 fossil_print("**** warning: a fork has occurred *****\n");
2684 }else{
2685 leaf_ambiguity_warning(nvid,nvid);
2686 }
2687 }
2688
+17 -31
--- src/comformat.c
+++ src/comformat.c
@@ -19,16 +19,10 @@
1919
** text on a TTY.
2020
*/
2121
#include "config.h"
2222
#include "comformat.h"
2323
#include <assert.h>
24
-#ifdef _WIN32
25
-# include <windows.h>
26
-#else
27
-# include <termios.h>
28
-# include <sys/ioctl.h>
29
-#endif
3024
3125
#if INTERFACE
3226
#define COMMENT_PRINT_NONE ((u32)0x00000000) /* No flags = non-legacy. */
3327
#define COMMENT_PRINT_LEGACY ((u32)0x00000001) /* Use legacy algorithm. */
3428
#define COMMENT_PRINT_TRIM_CRLF ((u32)0x00000002) /* Trim leading CR/LF. */
@@ -67,35 +61,27 @@
6761
*/
6862
static int comment_set_maxchars(
6963
int indent,
7064
int *pMaxChars
7165
){
72
-#if defined(_WIN32)
73
- CONSOLE_SCREEN_BUFFER_INFO csbi;
74
- memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
75
- if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
76
- *pMaxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
77
- return 1;
78
- }
79
- return 0;
80
-#elif defined(TIOCGWINSZ)
81
- struct winsize w;
82
- memset(&w, 0, sizeof(struct winsize));
83
- if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
84
- *pMaxChars = w.ws_col - indent;
85
- return 1;
86
- }
87
- return 0;
88
-#else
89
- /*
90
- ** Fallback to using more-or-less the "legacy semantics" of hard-coding
91
- ** the maximum line length to a value reasonable for the vast majority
92
- ** of supported systems.
93
- */
94
- *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
95
- return -1;
96
-#endif
66
+ struct TerminalSize ts;
67
+ if ( !terminal_get_size(&ts) ){
68
+ return 0;
69
+ }
70
+
71
+ if( ts.nColumns ){
72
+ *pMaxChars = ts.nColumns - indent;
73
+ return 1;
74
+ }else{
75
+ /*
76
+ ** Fallback to using more-or-less the "legacy semantics" of hard-coding
77
+ ** the maximum line length to a value reasonable for the vast majority
78
+ ** of supported systems.
79
+ */
80
+ *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
81
+ return -1;
82
+ }
9783
}
9884
9985
/*
10086
** This function checks the current line being printed against the original
10187
** comment text. Upon matching, it updates the provided character and line
10288
--- src/comformat.c
+++ src/comformat.c
@@ -19,16 +19,10 @@
19 ** text on a TTY.
20 */
21 #include "config.h"
22 #include "comformat.h"
23 #include <assert.h>
24 #ifdef _WIN32
25 # include <windows.h>
26 #else
27 # include <termios.h>
28 # include <sys/ioctl.h>
29 #endif
30
31 #if INTERFACE
32 #define COMMENT_PRINT_NONE ((u32)0x00000000) /* No flags = non-legacy. */
33 #define COMMENT_PRINT_LEGACY ((u32)0x00000001) /* Use legacy algorithm. */
34 #define COMMENT_PRINT_TRIM_CRLF ((u32)0x00000002) /* Trim leading CR/LF. */
@@ -67,35 +61,27 @@
67 */
68 static int comment_set_maxchars(
69 int indent,
70 int *pMaxChars
71 ){
72 #if defined(_WIN32)
73 CONSOLE_SCREEN_BUFFER_INFO csbi;
74 memset(&csbi, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));
75 if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) ){
76 *pMaxChars = csbi.srWindow.Right - csbi.srWindow.Left - indent;
77 return 1;
78 }
79 return 0;
80 #elif defined(TIOCGWINSZ)
81 struct winsize w;
82 memset(&w, 0, sizeof(struct winsize));
83 if( ioctl(0, TIOCGWINSZ, &w)!=-1 ){
84 *pMaxChars = w.ws_col - indent;
85 return 1;
86 }
87 return 0;
88 #else
89 /*
90 ** Fallback to using more-or-less the "legacy semantics" of hard-coding
91 ** the maximum line length to a value reasonable for the vast majority
92 ** of supported systems.
93 */
94 *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
95 return -1;
96 #endif
97 }
98
99 /*
100 ** This function checks the current line being printed against the original
101 ** comment text. Upon matching, it updates the provided character and line
102
--- src/comformat.c
+++ src/comformat.c
@@ -19,16 +19,10 @@
19 ** text on a TTY.
20 */
21 #include "config.h"
22 #include "comformat.h"
23 #include <assert.h>
 
 
 
 
 
 
24
25 #if INTERFACE
26 #define COMMENT_PRINT_NONE ((u32)0x00000000) /* No flags = non-legacy. */
27 #define COMMENT_PRINT_LEGACY ((u32)0x00000001) /* Use legacy algorithm. */
28 #define COMMENT_PRINT_TRIM_CRLF ((u32)0x00000002) /* Trim leading CR/LF. */
@@ -67,35 +61,27 @@
61 */
62 static int comment_set_maxchars(
63 int indent,
64 int *pMaxChars
65 ){
66 struct TerminalSize ts;
67 if ( !terminal_get_size(&ts) ){
68 return 0;
69 }
70
71 if( ts.nColumns ){
72 *pMaxChars = ts.nColumns - indent;
73 return 1;
74 }else{
75 /*
76 ** Fallback to using more-or-less the "legacy semantics" of hard-coding
77 ** the maximum line length to a value reasonable for the vast majority
78 ** of supported systems.
79 */
80 *pMaxChars = COMMENT_LEGACY_LINE_LENGTH - indent;
81 return -1;
82 }
 
 
 
 
 
 
 
 
83 }
84
85 /*
86 ** This function checks the current line being printed against the original
87 ** comment text. Upon matching, it updates the provided character and line
88
--- src/configure.c
+++ src/configure.c
@@ -147,10 +147,11 @@
147147
{ "parent-project-code", CONFIGSET_PROJ },
148148
{ "parent-project-name", CONFIGSET_PROJ },
149149
{ "hash-policy", CONFIGSET_PROJ },
150150
{ "comment-format", CONFIGSET_PROJ },
151151
{ "mimetypes", CONFIGSET_PROJ },
152
+ { "forbid-delta-manifests", CONFIGSET_PROJ },
152153
153154
#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
154155
{ "mv-rm-files", CONFIGSET_PROJ },
155156
#endif
156157
157158
--- src/configure.c
+++ src/configure.c
@@ -147,10 +147,11 @@
147 { "parent-project-code", CONFIGSET_PROJ },
148 { "parent-project-name", CONFIGSET_PROJ },
149 { "hash-policy", CONFIGSET_PROJ },
150 { "comment-format", CONFIGSET_PROJ },
151 { "mimetypes", CONFIGSET_PROJ },
 
152
153 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
154 { "mv-rm-files", CONFIGSET_PROJ },
155 #endif
156
157
--- src/configure.c
+++ src/configure.c
@@ -147,10 +147,11 @@
147 { "parent-project-code", CONFIGSET_PROJ },
148 { "parent-project-name", CONFIGSET_PROJ },
149 { "hash-policy", CONFIGSET_PROJ },
150 { "comment-format", CONFIGSET_PROJ },
151 { "mimetypes", CONFIGSET_PROJ },
152 { "forbid-delta-manifests", CONFIGSET_PROJ },
153
154 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
155 { "mv-rm-files", CONFIGSET_PROJ },
156 #endif
157
158
--- src/content.c
+++ src/content.c
@@ -944,13 +944,19 @@
944944
** Verify that all content can be extracted from the BLOB table correctly.
945945
** If the BLOB table is correct, then the repository can always be
946946
** successfully reconstructed using "fossil rebuild".
947947
**
948948
** Options:
949
+**
950
+** -d|--db-only Run "PRAGMA integrity_check" on the database only.
951
+** No other validation is performed.
949952
**
950953
** --parse Parse all manifests, wikis, tickets, events, and
951954
** so forth, reporting any errors found.
955
+**
956
+** -q|--quick Run "PRAGMA quick_check" on the database only.
957
+** No other validation is performed.
952958
*/
953959
void test_integrity(void){
954960
Stmt q;
955961
Blob content;
956962
int n1 = 0;
@@ -958,11 +964,25 @@
958964
int nErr = 0;
959965
int total;
960966
int nCA = 0;
961967
int anCA[10];
962968
int bParse = find_option("parse",0,0)!=0;
969
+ int bDbOnly = find_option("db-only","d",0)!=0;
970
+ int bQuick = find_option("quick","q",0)!=0;
963971
db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
972
+ if( bDbOnly || bQuick ){
973
+ const char *zType = bQuick ? "quick" : "integrity";
974
+ char *zRes;
975
+ zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
976
+ if( fossil_strcmp(zRes,"ok")!=0 ){
977
+ fossil_print("%s_check failed!\n", zType);
978
+ exit(1);
979
+ }else{
980
+ fossil_print("ok\n");
981
+ }
982
+ return;
983
+ }
964984
memset(anCA, 0, sizeof(anCA));
965985
966986
/* Make sure no public artifact is a delta from a private artifact */
967987
db_prepare(&q,
968988
"SELECT "
969989
--- src/content.c
+++ src/content.c
@@ -944,13 +944,19 @@
944 ** Verify that all content can be extracted from the BLOB table correctly.
945 ** If the BLOB table is correct, then the repository can always be
946 ** successfully reconstructed using "fossil rebuild".
947 **
948 ** Options:
 
 
 
949 **
950 ** --parse Parse all manifests, wikis, tickets, events, and
951 ** so forth, reporting any errors found.
 
 
 
952 */
953 void test_integrity(void){
954 Stmt q;
955 Blob content;
956 int n1 = 0;
@@ -958,11 +964,25 @@
958 int nErr = 0;
959 int total;
960 int nCA = 0;
961 int anCA[10];
962 int bParse = find_option("parse",0,0)!=0;
 
 
963 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
 
 
 
 
 
 
 
 
 
 
 
 
964 memset(anCA, 0, sizeof(anCA));
965
966 /* Make sure no public artifact is a delta from a private artifact */
967 db_prepare(&q,
968 "SELECT "
969
--- src/content.c
+++ src/content.c
@@ -944,13 +944,19 @@
944 ** Verify that all content can be extracted from the BLOB table correctly.
945 ** If the BLOB table is correct, then the repository can always be
946 ** successfully reconstructed using "fossil rebuild".
947 **
948 ** Options:
949 **
950 ** -d|--db-only Run "PRAGMA integrity_check" on the database only.
951 ** No other validation is performed.
952 **
953 ** --parse Parse all manifests, wikis, tickets, events, and
954 ** so forth, reporting any errors found.
955 **
956 ** -q|--quick Run "PRAGMA quick_check" on the database only.
957 ** No other validation is performed.
958 */
959 void test_integrity(void){
960 Stmt q;
961 Blob content;
962 int n1 = 0;
@@ -958,11 +964,25 @@
964 int nErr = 0;
965 int total;
966 int nCA = 0;
967 int anCA[10];
968 int bParse = find_option("parse",0,0)!=0;
969 int bDbOnly = find_option("db-only","d",0)!=0;
970 int bQuick = find_option("quick","q",0)!=0;
971 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
972 if( bDbOnly || bQuick ){
973 const char *zType = bQuick ? "quick" : "integrity";
974 char *zRes;
975 zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
976 if( fossil_strcmp(zRes,"ok")!=0 ){
977 fossil_print("%s_check failed!\n", zType);
978 exit(1);
979 }else{
980 fossil_print("ok\n");
981 }
982 return;
983 }
984 memset(anCA, 0, sizeof(anCA));
985
986 /* Make sure no public artifact is a delta from a private artifact */
987 db_prepare(&q,
988 "SELECT "
989
+17 -1
--- src/db.c
+++ src/db.c
@@ -2381,16 +2381,28 @@
23812381
char c = i==argc-1 ? '\n' : ' ';
23822382
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
23832383
}
23842384
}
23852385
}
2386
-LOCAL int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
2386
+
2387
+/*
2388
+** Callback for sqlite3_trace_v2();
2389
+*/
2390
+int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
23872391
sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
23882392
char *zSql;
23892393
int n;
23902394
const char *zArg = (const char*)pX;
23912395
char zEnd[40];
2396
+ if( m & SQLITE_TRACE_CLOSE ){
2397
+ /* If we are tracking closes, that means we want to clean up static
2398
+ ** prepared statements. */
2399
+ while( db.pAllStmt ){
2400
+ db_finalize(db.pAllStmt);
2401
+ }
2402
+ return 0;
2403
+ }
23922404
if( zArg[0]=='-' ) return 0;
23932405
if( m & SQLITE_TRACE_PROFILE ){
23942406
sqlite3_int64 nNano = *(sqlite3_int64*)pX;
23952407
double rMillisec = 0.000001 * nNano;
23962408
sqlite3_snprintf(sizeof(zEnd),zEnd," /* %.3fms */\n", rMillisec);
@@ -3556,10 +3568,14 @@
35563568
/*
35573569
** SETTING: pgp-command width=40
35583570
** Command used to clear-sign manifests at check-in.
35593571
** Default value is "gpg --clearsign -o"
35603572
*/
3573
+/*
3574
+** SETTING: forbid-delta-manifests boolean default=off
3575
+** If enabled, new delta manifests are prohibited.
3576
+*/
35613577
/*
35623578
** SETTING: proxy width=32 default=off
35633579
** URL of the HTTP proxy. If undefined or "off" then
35643580
** the "http_proxy" environment variable is consulted.
35653581
** If the http_proxy environment variable is undefined
35663582
--- src/db.c
+++ src/db.c
@@ -2381,16 +2381,28 @@
2381 char c = i==argc-1 ? '\n' : ' ';
2382 fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
2383 }
2384 }
2385 }
2386 LOCAL int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
 
 
 
 
2387 sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
2388 char *zSql;
2389 int n;
2390 const char *zArg = (const char*)pX;
2391 char zEnd[40];
 
 
 
 
 
 
 
 
2392 if( zArg[0]=='-' ) return 0;
2393 if( m & SQLITE_TRACE_PROFILE ){
2394 sqlite3_int64 nNano = *(sqlite3_int64*)pX;
2395 double rMillisec = 0.000001 * nNano;
2396 sqlite3_snprintf(sizeof(zEnd),zEnd," /* %.3fms */\n", rMillisec);
@@ -3556,10 +3568,14 @@
3556 /*
3557 ** SETTING: pgp-command width=40
3558 ** Command used to clear-sign manifests at check-in.
3559 ** Default value is "gpg --clearsign -o"
3560 */
 
 
 
 
3561 /*
3562 ** SETTING: proxy width=32 default=off
3563 ** URL of the HTTP proxy. If undefined or "off" then
3564 ** the "http_proxy" environment variable is consulted.
3565 ** If the http_proxy environment variable is undefined
3566
--- src/db.c
+++ src/db.c
@@ -2381,16 +2381,28 @@
2381 char c = i==argc-1 ? '\n' : ' ';
2382 fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
2383 }
2384 }
2385 }
2386
2387 /*
2388 ** Callback for sqlite3_trace_v2();
2389 */
2390 int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
2391 sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
2392 char *zSql;
2393 int n;
2394 const char *zArg = (const char*)pX;
2395 char zEnd[40];
2396 if( m & SQLITE_TRACE_CLOSE ){
2397 /* If we are tracking closes, that means we want to clean up static
2398 ** prepared statements. */
2399 while( db.pAllStmt ){
2400 db_finalize(db.pAllStmt);
2401 }
2402 return 0;
2403 }
2404 if( zArg[0]=='-' ) return 0;
2405 if( m & SQLITE_TRACE_PROFILE ){
2406 sqlite3_int64 nNano = *(sqlite3_int64*)pX;
2407 double rMillisec = 0.000001 * nNano;
2408 sqlite3_snprintf(sizeof(zEnd),zEnd," /* %.3fms */\n", rMillisec);
@@ -3556,10 +3568,14 @@
3568 /*
3569 ** SETTING: pgp-command width=40
3570 ** Command used to clear-sign manifests at check-in.
3571 ** Default value is "gpg --clearsign -o"
3572 */
3573 /*
3574 ** SETTING: forbid-delta-manifests boolean default=off
3575 ** If enabled, new delta manifests are prohibited.
3576 */
3577 /*
3578 ** SETTING: proxy width=32 default=off
3579 ** URL of the HTTP proxy. If undefined or "off" then
3580 ** the "http_proxy" environment variable is consulted.
3581 ** If the http_proxy environment variable is undefined
3582
--- src/default_css.txt
+++ src/default_css.txt
@@ -840,6 +840,31 @@
840840
display: inline-block;
841841
}
842842
.accordion_panel {
843843
overflow: hidden;
844844
transition: max-height 0.25s ease-out;
845
+}
846
+#setup_skinedit_css_defaults {
847
+ max-width: 98%;
848
+ font-family: monospace;
849
+// These are for the UL-based implementation:
850
+ column-width: auto;
851
+ column-count: 2;
852
+ padding-top: 1em;
853
+}
854
+// These are for the alternate table-based skinedit CSS list:
855
+// #setup_skinedit_css_defaults > tbody > tr > td {
856
+// font-family: monospace;
857
+// white-space: pre-wrap;
858
+// border: 1px solid black;
859
+// vertical-align: top;
860
+// }
861
+// #setup_skinedit_css_defaults > tbody > tr > td:nth-of-type(2) > div {
862
+// max-width: 30em;
863
+// overflow: auto;
864
+// }
865
+input {
866
+ max-width: 95%;
867
+}
868
+textarea {
869
+ max-width: 95%;
845870
}
846871
--- src/default_css.txt
+++ src/default_css.txt
@@ -840,6 +840,31 @@
840 display: inline-block;
841 }
842 .accordion_panel {
843 overflow: hidden;
844 transition: max-height 0.25s ease-out;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
845 }
846
--- src/default_css.txt
+++ src/default_css.txt
@@ -840,6 +840,31 @@
840 display: inline-block;
841 }
842 .accordion_panel {
843 overflow: hidden;
844 transition: max-height 0.25s ease-out;
845 }
846 #setup_skinedit_css_defaults {
847 max-width: 98%;
848 font-family: monospace;
849 // These are for the UL-based implementation:
850 column-width: auto;
851 column-count: 2;
852 padding-top: 1em;
853 }
854 // These are for the alternate table-based skinedit CSS list:
855 // #setup_skinedit_css_defaults > tbody > tr > td {
856 // font-family: monospace;
857 // white-space: pre-wrap;
858 // border: 1px solid black;
859 // vertical-align: top;
860 // }
861 // #setup_skinedit_css_defaults > tbody > tr > td:nth-of-type(2) > div {
862 // max-width: 30em;
863 // overflow: auto;
864 // }
865 input {
866 max-width: 95%;
867 }
868 textarea {
869 max-width: 95%;
870 }
871
+27 -2
--- src/diff.c
+++ src/diff.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2007 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -1826,14 +1826,39 @@
18261826
}
18271827
18281828
/*
18291829
** Extract the width of columns for side-by-side diff. Supply an
18301830
** appropriate default if no width is given.
1831
+**
1832
+** Calculate the default automatically, based on terminal's current width:
1833
+** term-width = 2*diff-col + diff-marker + 1
1834
+** diff-col = lineno + lmargin + text-width + rmargin
1835
+**
1836
+** text-width = (term-width - diff-marker - 1)/2 - lineno - lmargin - rmargin
18311837
*/
18321838
int diff_width(u64 diffFlags){
18331839
int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1);
1834
- if( w==0 ) w = 80;
1840
+ if( w==0 ){
1841
+ static struct {
1842
+ unsigned int lineno, lmargin, text, rmargin, marker;
1843
+ } sbsW = { 5, 2, 0, 0, 3 };
1844
+ const unsigned int wMin = 24, wMax = 132;
1845
+ unsigned int tw = terminal_get_width(80);
1846
+ unsigned int twMin =
1847
+ (wMin + sbsW.lineno + sbsW.lmargin + sbsW.rmargin)*2 + sbsW.marker + 1;
1848
+ unsigned int twMax =
1849
+ (wMax + sbsW.lineno + sbsW.lmargin + sbsW.rmargin)*2 + sbsW.marker + 1;
1850
+
1851
+ if( tw<twMin ){
1852
+ tw = twMin;
1853
+ }else if( tw>twMax ){
1854
+ tw = twMax;
1855
+ }
1856
+ sbsW.text =
1857
+ (tw - sbsW.marker - 1)/2 - sbsW.lineno - sbsW.lmargin - sbsW.rmargin;
1858
+ w = sbsW.text;
1859
+ }
18351860
return w;
18361861
}
18371862
18381863
/*
18391864
** Append the error message to pOut.
18401865
--- src/diff.c
+++ src/diff.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2007 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:
@@ -1826,14 +1826,39 @@
1826 }
1827
1828 /*
1829 ** Extract the width of columns for side-by-side diff. Supply an
1830 ** appropriate default if no width is given.
 
 
 
 
 
 
1831 */
1832 int diff_width(u64 diffFlags){
1833 int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1);
1834 if( w==0 ) w = 80;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1835 return w;
1836 }
1837
1838 /*
1839 ** Append the error message to pOut.
1840
--- src/diff.c
+++ src/diff.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2007 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:
@@ -1826,14 +1826,39 @@
1826 }
1827
1828 /*
1829 ** Extract the width of columns for side-by-side diff. Supply an
1830 ** appropriate default if no width is given.
1831 **
1832 ** Calculate the default automatically, based on terminal's current width:
1833 ** term-width = 2*diff-col + diff-marker + 1
1834 ** diff-col = lineno + lmargin + text-width + rmargin
1835 **
1836 ** text-width = (term-width - diff-marker - 1)/2 - lineno - lmargin - rmargin
1837 */
1838 int diff_width(u64 diffFlags){
1839 int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1);
1840 if( w==0 ){
1841 static struct {
1842 unsigned int lineno, lmargin, text, rmargin, marker;
1843 } sbsW = { 5, 2, 0, 0, 3 };
1844 const unsigned int wMin = 24, wMax = 132;
1845 unsigned int tw = terminal_get_width(80);
1846 unsigned int twMin =
1847 (wMin + sbsW.lineno + sbsW.lmargin + sbsW.rmargin)*2 + sbsW.marker + 1;
1848 unsigned int twMax =
1849 (wMax + sbsW.lineno + sbsW.lmargin + sbsW.rmargin)*2 + sbsW.marker + 1;
1850
1851 if( tw<twMin ){
1852 tw = twMin;
1853 }else if( tw>twMax ){
1854 tw = twMax;
1855 }
1856 sbsW.text =
1857 (tw - sbsW.marker - 1)/2 - sbsW.lineno - sbsW.lmargin - sbsW.rmargin;
1858 w = sbsW.text;
1859 }
1860 return w;
1861 }
1862
1863 /*
1864 ** Append the error message to pOut.
1865
+19 -14
--- src/doc.c
+++ src/doc.c
@@ -810,11 +810,11 @@
810810
** WEBPAGE: doc
811811
** URL: /uv/FILE
812812
** URL: /doc/CHECKIN/FILE
813813
**
814814
** CHECKIN can be either tag or hash prefix or timestamp identifying a
815
-** particular check, or the name of a branch (meaning the most recent
815
+** particular check-in, or the name of a branch (meaning the most recent
816816
** check-in on that branch) or one of various magic words:
817817
**
818818
** "tip" means the most recent check-in
819819
**
820820
** "ckout" means the current check-out, if the server is run from
@@ -824,11 +824,12 @@
824824
** regardless of what branch it occurs on.
825825
**
826826
** FILE is the name of a file to delivered up as a webpage. FILE is relative
827827
** to the root of the source tree of the repository. The FILE must
828828
** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
829
-** directly from disk and need not be a managed file.
829
+** directly from disk and need not be a managed file. For /uv, FILE
830
+** can also be the hash of the unversioned file.
830831
**
831832
** The "ckout" CHECKIN is intended for development - to provide a mechanism
832833
** for looking at what a file will look like using the /doc webpage after
833834
** it gets checked in.
834835
**
@@ -931,22 +932,26 @@
931932
goto doc_not_found;
932933
}
933934
}
934935
if( isUV ){
935936
if( db_table_exists("repository","unversioned") ){
936
- Stmt q;
937
- db_prepare(&q, "SELECT hash, mtime FROM unversioned"
938
- " WHERE name=%Q", zName);
939
- if( db_step(&q)==SQLITE_ROW ){
940
- etag_check(ETAG_HASH, db_column_text(&q,0));
941
- etag_last_modified(db_column_int64(&q,1));
942
- }
943
- db_finalize(&q);
944
- if( unversioned_content(zName, &filebody)==0 ){
945
- rid = 1;
946
- zDfltTitle = zName;
947
- }
937
+ rid = unversioned_content(zName, &filebody);
938
+ if( rid==1 ){
939
+ Stmt q;
940
+ db_prepare(&q, "SELECT hash, mtime FROM unversioned"
941
+ " WHERE name=%Q", zName);
942
+ if( db_step(&q)==SQLITE_ROW ){
943
+ etag_check(ETAG_HASH, db_column_text(&q,0));
944
+ etag_last_modified(db_column_int64(&q,1));
945
+ }
946
+ db_finalize(&q);
947
+ }else if( rid==2 ){
948
+ zName = db_text(zName,
949
+ "SELECT name FROM unversioned WHERE hash=%Q", zName);
950
+ g.isConst = 1;
951
+ }
952
+ zDfltTitle = zName;
948953
}
949954
}else if( fossil_strcmp(zCheckin,"ckout")==0 ){
950955
/* Read from the local checkout */
951956
char *zFullpath;
952957
db_must_be_within_tree();
953958
--- src/doc.c
+++ src/doc.c
@@ -810,11 +810,11 @@
810 ** WEBPAGE: doc
811 ** URL: /uv/FILE
812 ** URL: /doc/CHECKIN/FILE
813 **
814 ** CHECKIN can be either tag or hash prefix or timestamp identifying a
815 ** particular check, or the name of a branch (meaning the most recent
816 ** check-in on that branch) or one of various magic words:
817 **
818 ** "tip" means the most recent check-in
819 **
820 ** "ckout" means the current check-out, if the server is run from
@@ -824,11 +824,12 @@
824 ** regardless of what branch it occurs on.
825 **
826 ** FILE is the name of a file to delivered up as a webpage. FILE is relative
827 ** to the root of the source tree of the repository. The FILE must
828 ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
829 ** directly from disk and need not be a managed file.
 
830 **
831 ** The "ckout" CHECKIN is intended for development - to provide a mechanism
832 ** for looking at what a file will look like using the /doc webpage after
833 ** it gets checked in.
834 **
@@ -931,22 +932,26 @@
931 goto doc_not_found;
932 }
933 }
934 if( isUV ){
935 if( db_table_exists("repository","unversioned") ){
936 Stmt q;
937 db_prepare(&q, "SELECT hash, mtime FROM unversioned"
938 " WHERE name=%Q", zName);
939 if( db_step(&q)==SQLITE_ROW ){
940 etag_check(ETAG_HASH, db_column_text(&q,0));
941 etag_last_modified(db_column_int64(&q,1));
942 }
943 db_finalize(&q);
944 if( unversioned_content(zName, &filebody)==0 ){
945 rid = 1;
946 zDfltTitle = zName;
947 }
 
 
 
 
948 }
949 }else if( fossil_strcmp(zCheckin,"ckout")==0 ){
950 /* Read from the local checkout */
951 char *zFullpath;
952 db_must_be_within_tree();
953
--- src/doc.c
+++ src/doc.c
@@ -810,11 +810,11 @@
810 ** WEBPAGE: doc
811 ** URL: /uv/FILE
812 ** URL: /doc/CHECKIN/FILE
813 **
814 ** CHECKIN can be either tag or hash prefix or timestamp identifying a
815 ** particular check-in, or the name of a branch (meaning the most recent
816 ** check-in on that branch) or one of various magic words:
817 **
818 ** "tip" means the most recent check-in
819 **
820 ** "ckout" means the current check-out, if the server is run from
@@ -824,11 +824,12 @@
824 ** regardless of what branch it occurs on.
825 **
826 ** FILE is the name of a file to delivered up as a webpage. FILE is relative
827 ** to the root of the source tree of the repository. The FILE must
828 ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
829 ** directly from disk and need not be a managed file. For /uv, FILE
830 ** can also be the hash of the unversioned file.
831 **
832 ** The "ckout" CHECKIN is intended for development - to provide a mechanism
833 ** for looking at what a file will look like using the /doc webpage after
834 ** it gets checked in.
835 **
@@ -931,22 +932,26 @@
932 goto doc_not_found;
933 }
934 }
935 if( isUV ){
936 if( db_table_exists("repository","unversioned") ){
937 rid = unversioned_content(zName, &filebody);
938 if( rid==1 ){
939 Stmt q;
940 db_prepare(&q, "SELECT hash, mtime FROM unversioned"
941 " WHERE name=%Q", zName);
942 if( db_step(&q)==SQLITE_ROW ){
943 etag_check(ETAG_HASH, db_column_text(&q,0));
944 etag_last_modified(db_column_int64(&q,1));
945 }
946 db_finalize(&q);
947 }else if( rid==2 ){
948 zName = db_text(zName,
949 "SELECT name FROM unversioned WHERE hash=%Q", zName);
950 g.isConst = 1;
951 }
952 zDfltTitle = zName;
953 }
954 }else if( fossil_strcmp(zCheckin,"ckout")==0 ){
955 /* Read from the local checkout */
956 char *zFullpath;
957 db_must_be_within_tree();
958
+43 -6
--- src/etag.c
+++ src/etag.c
@@ -24,10 +24,12 @@
2424
** (1) The mtime on the Fossil executable
2525
** (2) The last change to the CONFIG table
2626
** (3) The last change to the EVENT table
2727
** (4) The value of the display cookie
2828
** (5) A hash value supplied by the page generator
29
+** (6) The details of the request URI
30
+** (7) The name user as determined by the login cookie
2931
**
3032
** Item (1) is always included in the ETag. The other elements are
3133
** optional. Because (1) is always included as part of the ETag, all
3234
** outstanding ETags can be invalidated by touching the fossil executable.
3335
**
@@ -60,32 +62,50 @@
6062
*/
6163
#define ETAG_CONFIG 0x01 /* Output depends on the CONFIG table */
6264
#define ETAG_DATA 0x02 /* Output depends on the EVENT table */
6365
#define ETAG_COOKIE 0x04 /* Output depends on a display cookie value */
6466
#define ETAG_HASH 0x08 /* Output depends on a hash */
67
+#define ETAG_QUERY 0x10 /* Output depends on PATH_INFO and QUERY_STRING */
68
+ /* and the g.zLogin value */
6569
#endif
6670
6771
static char zETag[33]; /* The generated ETag */
6872
static int iMaxAge = 0; /* The max-age parameter in the reply */
6973
static sqlite3_int64 iEtagMtime = 0; /* Last-Modified time */
74
+
75
+/*
76
+** Return a hash that changes every time the Fossil source code is
77
+** rebuilt.
78
+**
79
+** The FOSSIL_BUILD_HASH string that is returned here gets computed by
80
+** the mkversion utility program. The result is a hash of MANIFEST_UUID
81
+** and the unix timestamp for when the mkversion utility program is run.
82
+**
83
+** During development rebuilds, if you need the source code id to change
84
+** in order to invalidate caches, simply "touch" the "manifest" file in
85
+** the top of the source directory prior to running "make" and a new
86
+** FOSSIL_BUILD_HASH will be generated automatically.
87
+*/
88
+const char *fossil_exe_id(void){
89
+ return FOSSIL_BUILD_HASH;
90
+}
7091
7192
/*
7293
** Generate an ETag
7394
*/
7495
void etag_check(unsigned eFlags, const char *zHash){
75
- sqlite3_int64 mtime;
7696
const char *zIfNoneMatch;
7797
char zBuf[50];
7898
assert( zETag[0]==0 ); /* Only call this routine once! */
7999
80100
iMaxAge = 86400;
81101
md5sum_init();
82102
83
- /* Always include the mtime of the executable as part of the hash */
84
- mtime = file_mtime(g.nameOfExe, ExtFILE);
85
- sqlite3_snprintf(sizeof(zBuf),zBuf,"mtime: %lld\n", mtime);
86
- md5sum_step_text(zBuf, -1);
103
+ /* Always include the executable ID as part of the hash */
104
+ md5sum_step_text("exe-id: ", -1);
105
+ md5sum_step_text(fossil_exe_id(), -1);
106
+ md5sum_step_text("\n", 1);
87107
88108
if( (eFlags & ETAG_HASH)!=0 && zHash ){
89109
md5sum_step_text("hash: ", -1);
90110
md5sum_step_text(zHash, -1);
91111
md5sum_step_text("\n", 1);
@@ -98,11 +118,11 @@
98118
md5sum_step_text("\n", 1);
99119
iMaxAge = 60;
100120
}else if( eFlags & ETAG_CONFIG ){
101121
int iKey = db_int(0, "SELECT value FROM config WHERE name='cfgcnt'");
102122
sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",iKey);
103
- md5sum_step_text("data: ", -1);
123
+ md5sum_step_text("config: ", -1);
104124
md5sum_step_text(zBuf, -1);
105125
md5sum_step_text("\n", 1);
106126
iMaxAge = 3600;
107127
}
108128
@@ -111,10 +131,27 @@
111131
md5sum_step_text("display-cookie: ", -1);
112132
md5sum_step_text(PD(DISPLAY_SETTINGS_COOKIE,""), -1);
113133
md5sum_step_text("\n", 1);
114134
iMaxAge = 0;
115135
}
136
+
137
+ /* Output depends on PATH_INFO and QUERY_STRING */
138
+ if( eFlags & ETAG_QUERY ){
139
+ const char *zQS = P("QUERY_STRING");
140
+ md5sum_step_text("query: ", -1);
141
+ md5sum_step_text(PD("PATH_INFO",""), -1);
142
+ if( zQS ){
143
+ md5sum_step_text("?", 1);
144
+ md5sum_step_text(zQS, -1);
145
+ }
146
+ md5sum_step_text("\n",1);
147
+ if( g.zLogin ){
148
+ md5sum_step_text("login: ", -1);
149
+ md5sum_step_text(g.zLogin, -1);
150
+ md5sum_step_text("\n", 1);
151
+ }
152
+ }
116153
117154
/* Generate the ETag */
118155
memcpy(zETag, md5sum_finish(0), 33);
119156
120157
/* Check to see if the generated ETag matches If-None-Match and
121158
--- src/etag.c
+++ src/etag.c
@@ -24,10 +24,12 @@
24 ** (1) The mtime on the Fossil executable
25 ** (2) The last change to the CONFIG table
26 ** (3) The last change to the EVENT table
27 ** (4) The value of the display cookie
28 ** (5) A hash value supplied by the page generator
 
 
29 **
30 ** Item (1) is always included in the ETag. The other elements are
31 ** optional. Because (1) is always included as part of the ETag, all
32 ** outstanding ETags can be invalidated by touching the fossil executable.
33 **
@@ -60,32 +62,50 @@
60 */
61 #define ETAG_CONFIG 0x01 /* Output depends on the CONFIG table */
62 #define ETAG_DATA 0x02 /* Output depends on the EVENT table */
63 #define ETAG_COOKIE 0x04 /* Output depends on a display cookie value */
64 #define ETAG_HASH 0x08 /* Output depends on a hash */
 
 
65 #endif
66
67 static char zETag[33]; /* The generated ETag */
68 static int iMaxAge = 0; /* The max-age parameter in the reply */
69 static sqlite3_int64 iEtagMtime = 0; /* Last-Modified time */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
71 /*
72 ** Generate an ETag
73 */
74 void etag_check(unsigned eFlags, const char *zHash){
75 sqlite3_int64 mtime;
76 const char *zIfNoneMatch;
77 char zBuf[50];
78 assert( zETag[0]==0 ); /* Only call this routine once! */
79
80 iMaxAge = 86400;
81 md5sum_init();
82
83 /* Always include the mtime of the executable as part of the hash */
84 mtime = file_mtime(g.nameOfExe, ExtFILE);
85 sqlite3_snprintf(sizeof(zBuf),zBuf,"mtime: %lld\n", mtime);
86 md5sum_step_text(zBuf, -1);
87
88 if( (eFlags & ETAG_HASH)!=0 && zHash ){
89 md5sum_step_text("hash: ", -1);
90 md5sum_step_text(zHash, -1);
91 md5sum_step_text("\n", 1);
@@ -98,11 +118,11 @@
98 md5sum_step_text("\n", 1);
99 iMaxAge = 60;
100 }else if( eFlags & ETAG_CONFIG ){
101 int iKey = db_int(0, "SELECT value FROM config WHERE name='cfgcnt'");
102 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",iKey);
103 md5sum_step_text("data: ", -1);
104 md5sum_step_text(zBuf, -1);
105 md5sum_step_text("\n", 1);
106 iMaxAge = 3600;
107 }
108
@@ -111,10 +131,27 @@
111 md5sum_step_text("display-cookie: ", -1);
112 md5sum_step_text(PD(DISPLAY_SETTINGS_COOKIE,""), -1);
113 md5sum_step_text("\n", 1);
114 iMaxAge = 0;
115 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
117 /* Generate the ETag */
118 memcpy(zETag, md5sum_finish(0), 33);
119
120 /* Check to see if the generated ETag matches If-None-Match and
121
--- src/etag.c
+++ src/etag.c
@@ -24,10 +24,12 @@
24 ** (1) The mtime on the Fossil executable
25 ** (2) The last change to the CONFIG table
26 ** (3) The last change to the EVENT table
27 ** (4) The value of the display cookie
28 ** (5) A hash value supplied by the page generator
29 ** (6) The details of the request URI
30 ** (7) The name user as determined by the login cookie
31 **
32 ** Item (1) is always included in the ETag. The other elements are
33 ** optional. Because (1) is always included as part of the ETag, all
34 ** outstanding ETags can be invalidated by touching the fossil executable.
35 **
@@ -60,32 +62,50 @@
62 */
63 #define ETAG_CONFIG 0x01 /* Output depends on the CONFIG table */
64 #define ETAG_DATA 0x02 /* Output depends on the EVENT table */
65 #define ETAG_COOKIE 0x04 /* Output depends on a display cookie value */
66 #define ETAG_HASH 0x08 /* Output depends on a hash */
67 #define ETAG_QUERY 0x10 /* Output depends on PATH_INFO and QUERY_STRING */
68 /* and the g.zLogin value */
69 #endif
70
71 static char zETag[33]; /* The generated ETag */
72 static int iMaxAge = 0; /* The max-age parameter in the reply */
73 static sqlite3_int64 iEtagMtime = 0; /* Last-Modified time */
74
75 /*
76 ** Return a hash that changes every time the Fossil source code is
77 ** rebuilt.
78 **
79 ** The FOSSIL_BUILD_HASH string that is returned here gets computed by
80 ** the mkversion utility program. The result is a hash of MANIFEST_UUID
81 ** and the unix timestamp for when the mkversion utility program is run.
82 **
83 ** During development rebuilds, if you need the source code id to change
84 ** in order to invalidate caches, simply "touch" the "manifest" file in
85 ** the top of the source directory prior to running "make" and a new
86 ** FOSSIL_BUILD_HASH will be generated automatically.
87 */
88 const char *fossil_exe_id(void){
89 return FOSSIL_BUILD_HASH;
90 }
91
92 /*
93 ** Generate an ETag
94 */
95 void etag_check(unsigned eFlags, const char *zHash){
 
96 const char *zIfNoneMatch;
97 char zBuf[50];
98 assert( zETag[0]==0 ); /* Only call this routine once! */
99
100 iMaxAge = 86400;
101 md5sum_init();
102
103 /* Always include the executable ID as part of the hash */
104 md5sum_step_text("exe-id: ", -1);
105 md5sum_step_text(fossil_exe_id(), -1);
106 md5sum_step_text("\n", 1);
107
108 if( (eFlags & ETAG_HASH)!=0 && zHash ){
109 md5sum_step_text("hash: ", -1);
110 md5sum_step_text(zHash, -1);
111 md5sum_step_text("\n", 1);
@@ -98,11 +118,11 @@
118 md5sum_step_text("\n", 1);
119 iMaxAge = 60;
120 }else if( eFlags & ETAG_CONFIG ){
121 int iKey = db_int(0, "SELECT value FROM config WHERE name='cfgcnt'");
122 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",iKey);
123 md5sum_step_text("config: ", -1);
124 md5sum_step_text(zBuf, -1);
125 md5sum_step_text("\n", 1);
126 iMaxAge = 3600;
127 }
128
@@ -111,10 +131,27 @@
131 md5sum_step_text("display-cookie: ", -1);
132 md5sum_step_text(PD(DISPLAY_SETTINGS_COOKIE,""), -1);
133 md5sum_step_text("\n", 1);
134 iMaxAge = 0;
135 }
136
137 /* Output depends on PATH_INFO and QUERY_STRING */
138 if( eFlags & ETAG_QUERY ){
139 const char *zQS = P("QUERY_STRING");
140 md5sum_step_text("query: ", -1);
141 md5sum_step_text(PD("PATH_INFO",""), -1);
142 if( zQS ){
143 md5sum_step_text("?", 1);
144 md5sum_step_text(zQS, -1);
145 }
146 md5sum_step_text("\n",1);
147 if( g.zLogin ){
148 md5sum_step_text("login: ", -1);
149 md5sum_step_text(g.zLogin, -1);
150 md5sum_step_text("\n", 1);
151 }
152 }
153
154 /* Generate the ETag */
155 memcpy(zETag, md5sum_finish(0), 33);
156
157 /* Check to see if the generated ETag matches If-None-Match and
158
+1 -1
--- src/file.c
+++ src/file.c
@@ -294,11 +294,11 @@
294294
**
295295
** On windows, this routine returns only PERM_REG.
296296
*/
297297
int file_perm(const char *zFilename, int eFType){
298298
#if !defined(_WIN32)
299
- if( !getStat(zFilename, RepoFILE) ){
299
+ if( !getStat(zFilename, eFType) ){
300300
if( S_ISREG(fx.fileStat.st_mode) && ((S_IXUSR)&fx.fileStat.st_mode)!=0 )
301301
return PERM_EXE;
302302
else if( db_allow_symlinks() && S_ISLNK(fx.fileStat.st_mode) )
303303
return PERM_LNK;
304304
}
305305
--- src/file.c
+++ src/file.c
@@ -294,11 +294,11 @@
294 **
295 ** On windows, this routine returns only PERM_REG.
296 */
297 int file_perm(const char *zFilename, int eFType){
298 #if !defined(_WIN32)
299 if( !getStat(zFilename, RepoFILE) ){
300 if( S_ISREG(fx.fileStat.st_mode) && ((S_IXUSR)&fx.fileStat.st_mode)!=0 )
301 return PERM_EXE;
302 else if( db_allow_symlinks() && S_ISLNK(fx.fileStat.st_mode) )
303 return PERM_LNK;
304 }
305
--- src/file.c
+++ src/file.c
@@ -294,11 +294,11 @@
294 **
295 ** On windows, this routine returns only PERM_REG.
296 */
297 int file_perm(const char *zFilename, int eFType){
298 #if !defined(_WIN32)
299 if( !getStat(zFilename, eFType) ){
300 if( S_ISREG(fx.fileStat.st_mode) && ((S_IXUSR)&fx.fileStat.st_mode)!=0 )
301 return PERM_EXE;
302 else if( db_allow_symlinks() && S_ISLNK(fx.fileStat.st_mode) )
303 return PERM_LNK;
304 }
305
+15 -11
--- src/finfo.c
+++ src/finfo.c
@@ -199,11 +199,11 @@
199199
TAG_BRANCH, zFilename, filename_collation(),
200200
iLimit, iOffset
201201
);
202202
blob_zero(&line);
203203
if( iBrief ){
204
- fossil_print("History of %s\n", blob_str(&fname));
204
+ fossil_print("History for %s\n", blob_str(&fname));
205205
}
206206
while( db_step(&q)==SQLITE_ROW ){
207207
const char *zFileUuid = db_column_text(&q, 0);
208208
const char *zCiUuid = db_column_text(&q,1);
209209
const char *zDate = db_column_text(&q, 2);
@@ -296,11 +296,11 @@
296296
** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
297297
** (eastward). Either no timezone suffix or "Z" means UTC.
298298
*/
299299
void finfo_page(void){
300300
Stmt q;
301
- const char *zFilename;
301
+ const char *zFilename = PD("name","");
302302
char zPrevDate[20];
303303
const char *zA;
304304
const char *zB;
305305
int n;
306306
int baseCheckin;
@@ -321,11 +321,16 @@
321321
const char *zMark; /* Mark this version of the file */
322322
int selRid = 0; /* RID of the marked file version */
323323
324324
login_check_credentials();
325325
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
326
- style_header("File History");
326
+ fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
327
+ if( fnid==0 ){
328
+ style_header("No such file");
329
+ }else{
330
+ style_header("History for %s", zFilename);
331
+ }
327332
login_anonymous_available();
328333
tmFlags = timeline_ss_submenu();
329334
if( tmFlags & TIMELINE_COLUMNAR ){
330335
zStyle = "Columnar";
331336
}else if( tmFlags & TIMELINE_COMPACT ){
@@ -340,13 +345,11 @@
340345
url_initialize(&url, "finfo");
341346
if( brBg ) url_add_parameter(&url, "brbg", 0);
342347
if( uBg ) url_add_parameter(&url, "ubg", 0);
343348
baseCheckin = name_to_rid_www("ci");
344349
zPrevDate[0] = 0;
345
- zFilename = PD("name","");
346350
cookie_render();
347
- fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
348351
if( fnid==0 ){
349352
@ No such file: %h(zFilename)
350353
style_footer();
351354
return;
352355
}
@@ -435,12 +438,13 @@
435438
}else if( n>0 ){
436439
blob_appendf(&title, "First %d ancestors of file ", n);
437440
}else{
438441
blob_appendf(&title, "Ancestors of file ");
439442
}
440
- blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
441
- zFilename, zFilename);
443
+ blob_appendf(&title,"%z%h</a>",
444
+ href("%R/file?name=%T&ci=%!S", zFilename, zUuid),
445
+ zFilename);
442446
if( fShowId ) blob_appendf(&title, " (%d)", fnid);
443447
blob_append(&title, origCheckin ? " between " : " from ", -1);
444448
blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
445449
if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
446450
fossil_free(zUuid);
@@ -449,12 +453,12 @@
449453
zLink = href("%R/info/%!S", zUuid);
450454
blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
451455
fossil_free(zUuid);
452456
}
453457
}else{
454
- blob_appendf(&title, "History of ");
455
- hyperlinked_path(zFilename, &title, 0, "tree", "");
458
+ blob_appendf(&title, "History for ");
459
+ hyperlinked_path(zFilename, &title, 0, "tree", "", LINKPATH_FILE);
456460
if( fShowId ) blob_appendf(&title, " (%d)", fnid);
457461
}
458462
if( uBg ){
459463
blob_append(&title, " (color-coded by user)", -1);
460464
}
@@ -524,11 +528,11 @@
524528
@ <tr class='timelineSelected'>
525529
}else{
526530
@ <tr>
527531
}
528532
@ <td class="timelineTime">\
529
- @ %z(href("%R/artifact/%!S",zUuid))%s(zTime)</a></td>
533
+ @ %z(href("%R/file?name=%T&ci=%!S",zFilename,zCkin))%s(zTime)</a></td>
530534
@ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
531535
@ </td>
532536
if( zBgClr && zBgClr[0] ){
533537
@ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
534538
}else{
@@ -561,11 +565,11 @@
561565
cgi_printf("<span class='clutter' id='detail-%d'>",frid);
562566
}
563567
cgi_printf("<span class='timeline%sDetail'>", zStyle);
564568
if( tmFlags & (TIMELINE_COMPACT|TIMELINE_VERBOSE) ) cgi_printf("(");
565569
if( zUuid && (tmFlags & TIMELINE_VERBOSE)==0 ){
566
- @ file:&nbsp;%z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
570
+ @ file:&nbsp;%z(href("%R/file?name=%T&ci=%!S",zFilename,zCkin))[%S(zUuid)]</a>
567571
if( fShowId ){
568572
int srcId = delta_source_rid(frid);
569573
if( srcId>0 ){
570574
@ id:&nbsp;%d(frid)&larr;%d(srcId)
571575
}else{
572576
--- src/finfo.c
+++ src/finfo.c
@@ -199,11 +199,11 @@
199 TAG_BRANCH, zFilename, filename_collation(),
200 iLimit, iOffset
201 );
202 blob_zero(&line);
203 if( iBrief ){
204 fossil_print("History of %s\n", blob_str(&fname));
205 }
206 while( db_step(&q)==SQLITE_ROW ){
207 const char *zFileUuid = db_column_text(&q, 0);
208 const char *zCiUuid = db_column_text(&q,1);
209 const char *zDate = db_column_text(&q, 2);
@@ -296,11 +296,11 @@
296 ** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
297 ** (eastward). Either no timezone suffix or "Z" means UTC.
298 */
299 void finfo_page(void){
300 Stmt q;
301 const char *zFilename;
302 char zPrevDate[20];
303 const char *zA;
304 const char *zB;
305 int n;
306 int baseCheckin;
@@ -321,11 +321,16 @@
321 const char *zMark; /* Mark this version of the file */
322 int selRid = 0; /* RID of the marked file version */
323
324 login_check_credentials();
325 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
326 style_header("File History");
 
 
 
 
 
327 login_anonymous_available();
328 tmFlags = timeline_ss_submenu();
329 if( tmFlags & TIMELINE_COLUMNAR ){
330 zStyle = "Columnar";
331 }else if( tmFlags & TIMELINE_COMPACT ){
@@ -340,13 +345,11 @@
340 url_initialize(&url, "finfo");
341 if( brBg ) url_add_parameter(&url, "brbg", 0);
342 if( uBg ) url_add_parameter(&url, "ubg", 0);
343 baseCheckin = name_to_rid_www("ci");
344 zPrevDate[0] = 0;
345 zFilename = PD("name","");
346 cookie_render();
347 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
348 if( fnid==0 ){
349 @ No such file: %h(zFilename)
350 style_footer();
351 return;
352 }
@@ -435,12 +438,13 @@
435 }else if( n>0 ){
436 blob_appendf(&title, "First %d ancestors of file ", n);
437 }else{
438 blob_appendf(&title, "Ancestors of file ");
439 }
440 blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
441 zFilename, zFilename);
 
442 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
443 blob_append(&title, origCheckin ? " between " : " from ", -1);
444 blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
445 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
446 fossil_free(zUuid);
@@ -449,12 +453,12 @@
449 zLink = href("%R/info/%!S", zUuid);
450 blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
451 fossil_free(zUuid);
452 }
453 }else{
454 blob_appendf(&title, "History of ");
455 hyperlinked_path(zFilename, &title, 0, "tree", "");
456 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
457 }
458 if( uBg ){
459 blob_append(&title, " (color-coded by user)", -1);
460 }
@@ -524,11 +528,11 @@
524 @ <tr class='timelineSelected'>
525 }else{
526 @ <tr>
527 }
528 @ <td class="timelineTime">\
529 @ %z(href("%R/artifact/%!S",zUuid))%s(zTime)</a></td>
530 @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
531 @ </td>
532 if( zBgClr && zBgClr[0] ){
533 @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
534 }else{
@@ -561,11 +565,11 @@
561 cgi_printf("<span class='clutter' id='detail-%d'>",frid);
562 }
563 cgi_printf("<span class='timeline%sDetail'>", zStyle);
564 if( tmFlags & (TIMELINE_COMPACT|TIMELINE_VERBOSE) ) cgi_printf("(");
565 if( zUuid && (tmFlags & TIMELINE_VERBOSE)==0 ){
566 @ file:&nbsp;%z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
567 if( fShowId ){
568 int srcId = delta_source_rid(frid);
569 if( srcId>0 ){
570 @ id:&nbsp;%d(frid)&larr;%d(srcId)
571 }else{
572
--- src/finfo.c
+++ src/finfo.c
@@ -199,11 +199,11 @@
199 TAG_BRANCH, zFilename, filename_collation(),
200 iLimit, iOffset
201 );
202 blob_zero(&line);
203 if( iBrief ){
204 fossil_print("History for %s\n", blob_str(&fname));
205 }
206 while( db_step(&q)==SQLITE_ROW ){
207 const char *zFileUuid = db_column_text(&q, 0);
208 const char *zCiUuid = db_column_text(&q,1);
209 const char *zDate = db_column_text(&q, 2);
@@ -296,11 +296,11 @@
296 ** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
297 ** (eastward). Either no timezone suffix or "Z" means UTC.
298 */
299 void finfo_page(void){
300 Stmt q;
301 const char *zFilename = PD("name","");
302 char zPrevDate[20];
303 const char *zA;
304 const char *zB;
305 int n;
306 int baseCheckin;
@@ -321,11 +321,16 @@
321 const char *zMark; /* Mark this version of the file */
322 int selRid = 0; /* RID of the marked file version */
323
324 login_check_credentials();
325 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
326 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
327 if( fnid==0 ){
328 style_header("No such file");
329 }else{
330 style_header("History for %s", zFilename);
331 }
332 login_anonymous_available();
333 tmFlags = timeline_ss_submenu();
334 if( tmFlags & TIMELINE_COLUMNAR ){
335 zStyle = "Columnar";
336 }else if( tmFlags & TIMELINE_COMPACT ){
@@ -340,13 +345,11 @@
345 url_initialize(&url, "finfo");
346 if( brBg ) url_add_parameter(&url, "brbg", 0);
347 if( uBg ) url_add_parameter(&url, "ubg", 0);
348 baseCheckin = name_to_rid_www("ci");
349 zPrevDate[0] = 0;
 
350 cookie_render();
 
351 if( fnid==0 ){
352 @ No such file: %h(zFilename)
353 style_footer();
354 return;
355 }
@@ -435,12 +438,13 @@
438 }else if( n>0 ){
439 blob_appendf(&title, "First %d ancestors of file ", n);
440 }else{
441 blob_appendf(&title, "Ancestors of file ");
442 }
443 blob_appendf(&title,"%z%h</a>",
444 href("%R/file?name=%T&ci=%!S", zFilename, zUuid),
445 zFilename);
446 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
447 blob_append(&title, origCheckin ? " between " : " from ", -1);
448 blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
449 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
450 fossil_free(zUuid);
@@ -449,12 +453,12 @@
453 zLink = href("%R/info/%!S", zUuid);
454 blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
455 fossil_free(zUuid);
456 }
457 }else{
458 blob_appendf(&title, "History for ");
459 hyperlinked_path(zFilename, &title, 0, "tree", "", LINKPATH_FILE);
460 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
461 }
462 if( uBg ){
463 blob_append(&title, " (color-coded by user)", -1);
464 }
@@ -524,11 +528,11 @@
528 @ <tr class='timelineSelected'>
529 }else{
530 @ <tr>
531 }
532 @ <td class="timelineTime">\
533 @ %z(href("%R/file?name=%T&ci=%!S",zFilename,zCkin))%s(zTime)</a></td>
534 @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
535 @ </td>
536 if( zBgClr && zBgClr[0] ){
537 @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
538 }else{
@@ -561,11 +565,11 @@
565 cgi_printf("<span class='clutter' id='detail-%d'>",frid);
566 }
567 cgi_printf("<span class='timeline%sDetail'>", zStyle);
568 if( tmFlags & (TIMELINE_COMPACT|TIMELINE_VERBOSE) ) cgi_printf("(");
569 if( zUuid && (tmFlags & TIMELINE_VERBOSE)==0 ){
570 @ file:&nbsp;%z(href("%R/file?name=%T&ci=%!S",zFilename,zCkin))[%S(zUuid)]</a>
571 if( fShowId ){
572 int srcId = delta_source_rid(frid);
573 if( srcId>0 ){
574 @ id:&nbsp;%d(frid)&larr;%d(srcId)
575 }else{
576
+5 -4
--- src/forum.c
+++ src/forum.c
@@ -1013,12 +1013,12 @@
10131013
@ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
10141014
@ maxlength="125"><br>
10151015
}
10161016
@ %z(href("%R/markup_help"))Markup style</a>:
10171017
mimetype_option_menu(zMimetype);
1018
- @ <br><textarea name="content" class="wikiedit" cols="80" \
1019
- @ rows="25" wrap="virtual">%h(zContent)</textarea><br>
1018
+ @ <br><textarea aria-label="Content:" name="content" class="wikiedit" \
1019
+ @ cols="80" rows="25" wrap="virtual">%h(zContent)</textarea><br>
10201020
}
10211021
10221022
/*
10231023
** WEBPAGE: forumnew
10241024
** WEBPAGE: forumedit
@@ -1119,11 +1119,12 @@
11191119
@ <input type="submit" name="submit" value="Submit">
11201120
}else{
11211121
@ <input type="submit" name="submit" value="Submit" disabled>
11221122
}
11231123
if( g.perm.Debug ){
1124
- /* For the test-forumnew page add these extra debugging controls */
1124
+ /* Give extra control over the post to users with the special
1125
+ * Debug capability, which includes Admin and Setup users */
11251126
@ <div class="debug">
11261127
@ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
11271128
@ Dry run</label>
11281129
@ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
11291130
@ Require moderator approval</label>
@@ -1235,11 +1236,11 @@
12351236
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
12361237
@ <input type="hidden" name="nullout" value="1">
12371238
@ <input type="hidden" name="mimetype" value="%h(zMimetype)">
12381239
@ <input type="hidden" name="content" value="%h(zContent)">
12391240
if( zTitle ){
1240
- @ <input type="hidden" name="title" value="%h(zTitle)">
1241
+ @ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
12411242
}
12421243
}else if( P("edit") ){
12431244
/* Provide an edit to the fpid post */
12441245
zMimetype = P("mimetype");
12451246
zContent = PT("content");
12461247
--- src/forum.c
+++ src/forum.c
@@ -1013,12 +1013,12 @@
1013 @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
1014 @ maxlength="125"><br>
1015 }
1016 @ %z(href("%R/markup_help"))Markup style</a>:
1017 mimetype_option_menu(zMimetype);
1018 @ <br><textarea name="content" class="wikiedit" cols="80" \
1019 @ rows="25" wrap="virtual">%h(zContent)</textarea><br>
1020 }
1021
1022 /*
1023 ** WEBPAGE: forumnew
1024 ** WEBPAGE: forumedit
@@ -1119,11 +1119,12 @@
1119 @ <input type="submit" name="submit" value="Submit">
1120 }else{
1121 @ <input type="submit" name="submit" value="Submit" disabled>
1122 }
1123 if( g.perm.Debug ){
1124 /* For the test-forumnew page add these extra debugging controls */
 
1125 @ <div class="debug">
1126 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1127 @ Dry run</label>
1128 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1129 @ Require moderator approval</label>
@@ -1235,11 +1236,11 @@
1235 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1236 @ <input type="hidden" name="nullout" value="1">
1237 @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
1238 @ <input type="hidden" name="content" value="%h(zContent)">
1239 if( zTitle ){
1240 @ <input type="hidden" name="title" value="%h(zTitle)">
1241 }
1242 }else if( P("edit") ){
1243 /* Provide an edit to the fpid post */
1244 zMimetype = P("mimetype");
1245 zContent = PT("content");
1246
--- src/forum.c
+++ src/forum.c
@@ -1013,12 +1013,12 @@
1013 @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
1014 @ maxlength="125"><br>
1015 }
1016 @ %z(href("%R/markup_help"))Markup style</a>:
1017 mimetype_option_menu(zMimetype);
1018 @ <br><textarea aria-label="Content:" name="content" class="wikiedit" \
1019 @ cols="80" rows="25" wrap="virtual">%h(zContent)</textarea><br>
1020 }
1021
1022 /*
1023 ** WEBPAGE: forumnew
1024 ** WEBPAGE: forumedit
@@ -1119,11 +1119,12 @@
1119 @ <input type="submit" name="submit" value="Submit">
1120 }else{
1121 @ <input type="submit" name="submit" value="Submit" disabled>
1122 }
1123 if( g.perm.Debug ){
1124 /* Give extra control over the post to users with the special
1125 * Debug capability, which includes Admin and Setup users */
1126 @ <div class="debug">
1127 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1128 @ Dry run</label>
1129 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1130 @ Require moderator approval</label>
@@ -1235,11 +1236,11 @@
1236 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1237 @ <input type="hidden" name="nullout" value="1">
1238 @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
1239 @ <input type="hidden" name="content" value="%h(zContent)">
1240 if( zTitle ){
1241 @ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
1242 }
1243 }else if( P("edit") ){
1244 /* Provide an edit to the fpid post */
1245 zMimetype = P("mimetype");
1246 zContent = PT("content");
1247
+5 -1
--- src/fshell.c
+++ src/fshell.c
@@ -60,11 +60,15 @@
6060
pid_t childPid;
6161
char *zLine = 0;
6262
char *zPrompt = 0;
6363
fDebug = find_option("debug", 0, 0)!=0;
6464
db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
65
- zPrompt = mprintf("fossil (%z)> ", db_get("project-name","no repo"));
65
+ if(g.zRepositoryName!=0){
66
+ zPrompt = mprintf("fossil (%z)> ", db_get("project-name","unnamed"));
67
+ }else{
68
+ zPrompt = mprintf("fossil (no repo)> ");
69
+ }
6670
db_close(0);
6771
sqlite3_shutdown();
6872
linenoiseSetMultiLine(1);
6973
while( (free(zLine), zLine = linenoise(zPrompt)) ){
7074
/* Remember shell history within the current session */
7175
--- src/fshell.c
+++ src/fshell.c
@@ -60,11 +60,15 @@
60 pid_t childPid;
61 char *zLine = 0;
62 char *zPrompt = 0;
63 fDebug = find_option("debug", 0, 0)!=0;
64 db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
65 zPrompt = mprintf("fossil (%z)> ", db_get("project-name","no repo"));
 
 
 
 
66 db_close(0);
67 sqlite3_shutdown();
68 linenoiseSetMultiLine(1);
69 while( (free(zLine), zLine = linenoise(zPrompt)) ){
70 /* Remember shell history within the current session */
71
--- src/fshell.c
+++ src/fshell.c
@@ -60,11 +60,15 @@
60 pid_t childPid;
61 char *zLine = 0;
62 char *zPrompt = 0;
63 fDebug = find_option("debug", 0, 0)!=0;
64 db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
65 if(g.zRepositoryName!=0){
66 zPrompt = mprintf("fossil (%z)> ", db_get("project-name","unnamed"));
67 }else{
68 zPrompt = mprintf("fossil (no repo)> ");
69 }
70 db_close(0);
71 sqlite3_shutdown();
72 linenoiseSetMultiLine(1);
73 while( (free(zLine), zLine = linenoise(zPrompt)) ){
74 /* Remember shell history within the current session */
75
+3 -1
--- src/graph.c
+++ src/graph.c
@@ -534,17 +534,19 @@
534534
pParent->idxTop = pRow->idxTop;
535535
}
536536
}
537537
538538
if( tmFlags & TIMELINE_FILLGAPS ){
539
- /* If a node has no pChild and there is a node higher up in the graph
539
+ /* If a node has no pChild in the graph
540
+ ** and there is a node higher up in the graph
540541
** that is in the same branch and has no in-graph parent, then
541542
** make the lower node a step-child of the upper node. This will
542543
** be represented on the graph by a thick dotted line without an arrowhead.
543544
*/
544545
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
545546
if( pRow->pChild ) continue;
547
+ if( pRow->isLeaf ) continue;
546548
for(pLoop=pRow->pPrev; pLoop; pLoop=pLoop->pPrev){
547549
if( pLoop->nParent>0
548550
&& pLoop->zBranch==pRow->zBranch
549551
&& hashFind(p,pLoop->aParent[0])==0
550552
){
551553
--- src/graph.c
+++ src/graph.c
@@ -534,17 +534,19 @@
534 pParent->idxTop = pRow->idxTop;
535 }
536 }
537
538 if( tmFlags & TIMELINE_FILLGAPS ){
539 /* If a node has no pChild and there is a node higher up in the graph
 
540 ** that is in the same branch and has no in-graph parent, then
541 ** make the lower node a step-child of the upper node. This will
542 ** be represented on the graph by a thick dotted line without an arrowhead.
543 */
544 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
545 if( pRow->pChild ) continue;
 
546 for(pLoop=pRow->pPrev; pLoop; pLoop=pLoop->pPrev){
547 if( pLoop->nParent>0
548 && pLoop->zBranch==pRow->zBranch
549 && hashFind(p,pLoop->aParent[0])==0
550 ){
551
--- src/graph.c
+++ src/graph.c
@@ -534,17 +534,19 @@
534 pParent->idxTop = pRow->idxTop;
535 }
536 }
537
538 if( tmFlags & TIMELINE_FILLGAPS ){
539 /* If a node has no pChild in the graph
540 ** and there is a node higher up in the graph
541 ** that is in the same branch and has no in-graph parent, then
542 ** make the lower node a step-child of the upper node. This will
543 ** be represented on the graph by a thick dotted line without an arrowhead.
544 */
545 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
546 if( pRow->pChild ) continue;
547 if( pRow->isLeaf ) continue;
548 for(pLoop=pRow->pPrev; pLoop; pLoop=pLoop->pPrev){
549 if( pLoop->nParent>0
550 && pLoop->zBranch==pRow->zBranch
551 && hashFind(p,pLoop->aParent[0])==0
552 ){
553
+214 -128
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -24,19 +24,19 @@
2424
** SSL support is abstracted out into this module because Fossil can
2525
** be compiled without SSL support (which requires OpenSSL library)
2626
*/
2727
2828
#include "config.h"
29
+#include "http_ssl.h"
2930
3031
#ifdef FOSSIL_ENABLE_SSL
3132
3233
#include <openssl/bio.h>
3334
#include <openssl/ssl.h>
3435
#include <openssl/err.h>
3536
#include <openssl/x509.h>
3637
37
-#include "http_ssl.h"
3838
#include <assert.h>
3939
#include <sys/types.h>
4040
4141
/*
4242
** There can only be a single OpenSSL IO connection open at a time.
@@ -46,11 +46,15 @@
4646
static int sslIsInit = 0; /* True after global initialization */
4747
static BIO *iBio = 0; /* OpenSSL I/O abstraction */
4848
static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
4949
static SSL_CTX *sslCtx; /* SSL context */
5050
static SSL *ssl;
51
-
51
+static struct { /* Accept this SSL cert for this session only */
52
+ char *zHost; /* Subject or host name */
53
+ char *zHash; /* SHA2-256 hash of the cert */
54
+} sException;
55
+static int sslNoCertVerify = 0; /* Do not verify SSL certs */
5256
5357
/*
5458
** Clear the SSL error message
5559
*/
5660
static void ssl_clear_errmsg(void){
@@ -224,38 +228,36 @@
224228
}while(!done);
225229
sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
226230
blob_reset(&reply);
227231
return rc;
228232
}
233
+
234
+/*
235
+** Invoke this routine to disable SSL cert verification. After
236
+** this call is made, any SSL cert that the server provides will
237
+** be accepted. Communication will still be encrypted, but the
238
+** client has no way of knowing whether it is talking to the
239
+** real server or a man-in-the-middle imposter.
240
+*/
241
+void ssl_disable_cert_verification(void){
242
+ sslNoCertVerify = 1;
243
+}
229244
230245
/*
231246
** Open an SSL connection. The identify of the server is determined
232247
** as follows:
233248
**
234
-** g.url.name Name of the server. Ex: www.fossil-scm.org
249
+** pUrlData->name Name of the server. Ex: www.fossil-scm.org
250
+** g.url.name Name of the proxy server, if proxying.
235251
** pUrlData->port TCP/IP port to use. Ex: 80
236252
**
237253
** Return the number of errors.
238254
*/
239255
int ssl_open(UrlData *pUrlData){
240256
X509 *cert;
241
- int hasSavedCertificate = 0;
242
- int trusted = 0;
243
- unsigned long e;
244257
245258
ssl_global_init();
246
-
247
- /* Get certificate for current server from global config and
248
- * (if we have it in config) add it to certificate store.
249
- */
250
- cert = ssl_get_certificate(pUrlData, &trusted);
251
- if ( cert!=NULL ){
252
- X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
253
- X509_free(cert);
254
- hasSavedCertificate = 1;
255
- }
256
-
257259
if( pUrlData->useProxy ){
258260
int rc;
259261
char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
260262
BIO *sBio = BIO_new_connect(connStr);
261263
free(connStr);
@@ -325,70 +327,72 @@
325327
ssl_set_errmsg("No SSL certificate was presented by the peer");
326328
ssl_close();
327329
return 1;
328330
}
329331
330
- if( trusted<=0 && (e = SSL_get_verify_result(ssl)) != X509_V_OK ){
332
+ if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
333
+ int x;
331334
char *desc, *prompt;
332
- const char *warning = "";
333335
Blob ans;
334336
char cReply;
335337
BIO *mem;
336338
unsigned char md[32];
337
- unsigned int mdLength = 31;
338
-
339
- mem = BIO_new(BIO_s_mem());
340
- X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
341
- BIO_puts(mem, "\n\nIssued By:\n\n");
342
- X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
343
- BIO_puts(mem, "\n\nSHA1 Fingerprint:\n\n ");
344
- if(X509_digest(cert, EVP_sha1(), md, &mdLength)){
339
+ char zHash[32*2+1];
340
+ unsigned int mdLength = (int)sizeof(md);
341
+
342
+ memset(md, 0, sizeof(md));
343
+ zHash[0] = 0;
344
+ /* MMNNFFPPS */
345
+#if OPENSSL_VERSION_NUMBER >= 0x010000000
346
+ x = X509_digest(cert, EVP_sha256(), md, &mdLength);
347
+#else
348
+ x = X509_digest(cert, EVP_sha1(), md, &mdLength);
349
+#endif
350
+ if( x ){
345351
int j;
346
- for( j = 0; j < mdLength; ++j ) {
347
- BIO_printf(mem, " %02x", md[j]);
348
- }
349
- }
350
- BIO_write(mem, "", 1); /* nul-terminate mem buffer */
351
- BIO_get_mem_data(mem, &desc);
352
-
353
- if( hasSavedCertificate ){
354
- warning = "WARNING: Certificate doesn't match the "
355
- "saved certificate for this host!";
356
- }
357
- prompt = mprintf("\nSSL verification failed: %s\n"
358
- "Certificate received: \n\n%s\n\n%s\n"
359
- "Either:\n"
360
- " * verify the certificate is correct using the "
361
- "SHA1 fingerprint above\n"
362
- " * use the global ssl-ca-location setting to specify your CA root\n"
363
- " certificates list\n\n"
364
- "If you are not expecting this message, answer no and "
365
- "contact your server\nadministrator.\n\n"
366
- "Accept certificate for host %s (a=always/y/N)? ",
367
- X509_verify_cert_error_string(e), desc, warning,
368
- pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
369
- BIO_free(mem);
370
-
371
- prompt_user(prompt, &ans);
372
- free(prompt);
373
- cReply = blob_str(&ans)[0];
374
- blob_reset(&ans);
375
- if( cReply!='y' && cReply!='Y' && cReply!='a' && cReply!='A') {
376
- X509_free(cert);
377
- ssl_set_errmsg("SSL certificate declined");
378
- ssl_close();
379
- return 1;
380
- }
381
- if( cReply=='a' || cReply=='A') {
382
- if ( trusted==0 ){
383
- prompt_user("\nSave this certificate as fully trusted (a=always/N)? ",
384
- &ans);
385
- cReply = blob_str(&ans)[0];
386
- trusted = ( cReply=='a' || cReply=='A' );
387
- blob_reset(&ans);
388
- }
389
- ssl_save_certificate(pUrlData, cert, trusted);
352
+ for(j=0; j<mdLength && j*2+1<sizeof(zHash); ++j){
353
+ zHash[j*2] = "0123456789abcdef"[md[j]>>4];
354
+ zHash[j*2+1] = "0123456789abcdef"[md[j]&0xf];
355
+ }
356
+ zHash[j*2] = 0;
357
+ }
358
+
359
+ if( ssl_certificate_exception_exists(pUrlData, zHash) ){
360
+ /* Ignore the failure because an exception exists */
361
+ ssl_one_time_exception(pUrlData, zHash);
362
+ }else{
363
+ /* Tell the user about the failure and ask what to do */
364
+ mem = BIO_new(BIO_s_mem());
365
+ BIO_puts(mem, " subject: ");
366
+ X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE);
367
+ BIO_puts(mem, "\n issuer: ");
368
+ X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE);
369
+ BIO_printf(mem, "\n sha256: %s", zHash);
370
+ BIO_get_mem_data(mem, &desc);
371
+
372
+ prompt = mprintf("Unable to verify SSL cert from %s\n%s\n"
373
+ "accept this cert and continue (y/N)? ",
374
+ pUrlData->name, desc);
375
+ BIO_free(mem);
376
+
377
+ prompt_user(prompt, &ans);
378
+ free(prompt);
379
+ cReply = blob_str(&ans)[0];
380
+ blob_reset(&ans);
381
+ if( cReply!='y' && cReply!='Y' ){
382
+ X509_free(cert);
383
+ ssl_set_errmsg("SSL cert declined");
384
+ ssl_close();
385
+ return 1;
386
+ }
387
+ ssl_one_time_exception(pUrlData, zHash);
388
+ prompt_user("remember this exception (y/N)? ", &ans);
389
+ cReply = blob_str(&ans)[0];
390
+ if( cReply=='y' || cReply=='Y') {
391
+ ssl_remember_certificate_exception(pUrlData, zHash);
392
+ }
393
+ blob_reset(&ans);
390394
}
391395
}
392396
393397
/* Set the Global.zIpAddr variable to the server we are talking to.
394398
** This is used to populate the ipaddr column of the rcvfrom table,
@@ -415,60 +419,53 @@
415419
X509_free(cert);
416420
return 0;
417421
}
418422
419423
/*
420
-** Save certificate to global config.
421
-*/
422
-void ssl_save_certificate(UrlData *pUrlData, X509 *cert, int trusted){
423
- BIO *mem;
424
- char *zCert, *zHost;
425
-
426
- mem = BIO_new(BIO_s_mem());
427
- PEM_write_bio_X509(mem, cert);
428
- BIO_write(mem, "", 1); /* nul-terminate mem buffer */
429
- BIO_get_mem_data(mem, &zCert);
430
- zHost = mprintf("cert:%s",
431
- pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
432
- db_set(zHost, zCert, 1);
433
- free(zHost);
434
- zHost = mprintf("trusted:%s",
435
- pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
436
- db_set_int(zHost, trusted, 1);
437
- free(zHost);
438
- BIO_free(mem);
424
+** Remember that the cert with the given hash is a acceptable for
425
+** use with pUrlData->name.
426
+*/
427
+LOCAL void ssl_remember_certificate_exception(
428
+ UrlData *pUrlData,
429
+ const char *zHash
430
+){
431
+ char *zName = mprintf("cert:%s", pUrlData->name);
432
+ db_set(zName, zHash, 1);
433
+ fossil_free(zName);
434
+}
435
+
436
+/*
437
+** Return true if the there exists a certificate exception for
438
+** pUrlData->name that matches the hash.
439
+*/
440
+LOCAL int ssl_certificate_exception_exists(
441
+ UrlData *pUrlData,
442
+ const char *zHash
443
+){
444
+ char *zName, *zValue;
445
+ if( fossil_strcmp(sException.zHost,pUrlData->name)==0
446
+ && fossil_strcmp(sException.zHash,zHash)==0
447
+ ){
448
+ return 1;
449
+ }
450
+ zName = mprintf("cert:%s", pUrlData->name);
451
+ zValue = db_get(zName,0);
452
+ fossil_free(zName);
453
+ return zValue!=0 && strcmp(zHash,zValue)==0;
439454
}
440455
441456
/*
442
-** Get certificate for pUrlData->urlName from global config.
443
-** Return NULL if no certificate found.
457
+** Remember zHash as an acceptable certificate for this session only.
444458
*/
445
-X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
446
- char *zHost, *zCert;
447
- BIO *mem;
448
- X509 *cert;
449
-
450
- zHost = mprintf("cert:%s",
451
- pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
452
- zCert = db_get(zHost, NULL);
453
- free(zHost);
454
- if ( zCert==NULL )
455
- return NULL;
456
-
457
- if ( pTrusted!=0 ){
458
- zHost = mprintf("trusted:%s",
459
- pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
460
- *pTrusted = db_get_int(zHost, 0);
461
- free(zHost);
462
- }
463
-
464
- mem = BIO_new(BIO_s_mem());
465
- BIO_puts(mem, zCert);
466
- cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
467
- free(zCert);
468
- BIO_free(mem);
469
- return cert;
459
+LOCAL void ssl_one_time_exception(
460
+ UrlData *pUrlData,
461
+ const char *zHash
462
+){
463
+ fossil_free(sException.zHost);
464
+ sException.zHost = fossil_strdup(pUrlData->name);
465
+ fossil_free(sException.zHash);
466
+ sException.zHash = fossil_strdup(zHash);
470467
}
471468
472469
/*
473470
** Send content out over the SSL connection.
474471
*/
@@ -510,22 +507,111 @@
510507
}
511508
512509
#endif /* FOSSIL_ENABLE_SSL */
513510
514511
/*
515
-** COMMAND: test-ssl-trust-store
512
+** COMMAND: tls-config*
513
+**
514
+** Usage: %fossil tls-config [SUBCOMMAND] [OPTIONS...] [ARGS...]
515
+**
516
+** This command is used to view or modify the TLS (Transport Layer
517
+** Security) configuration for Fossil. TLS (formerly SSL) is the
518
+** encryption technology used for secure HTTPS transport.
519
+**
520
+** Sub-commands:
521
+**
522
+** show Show the TLS configuration
516523
**
517
-** Show the file and directory where OpenSSL looks for certificates
518
-** of trusted CAs.
524
+** remove-exception DOMAIN... Remove TLS cert exceptions
525
+** for the domains listed. Or if
526
+** the --all option is specified,
527
+** remove all TLS cert exceptions.
519528
*/
520
-void test_ssl_info(void){
529
+void test_tlsconfig_info(void){
521530
#if !defined(FOSSIL_ENABLE_SSL)
522
- fossil_print("SSL disabled in this build\n");
531
+ fossil_print("TLS disabled in this build\n");
523532
#else
524
- fossil_print("file: %-14s %s\n",
525
- X509_get_default_cert_file_env(),
526
- X509_get_default_cert_file());
527
- fossil_print("dir: %-14s %s\n",
528
- X509_get_default_cert_dir_env(),
529
- X509_get_default_cert_dir());
533
+ const char *zCmd;
534
+ size_t nCmd;
535
+ int nHit = 0;
536
+ db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
537
+ db_open_config(1,0);
538
+ zCmd = g.argc>=3 ? g.argv[2] : "show";
539
+ nCmd = strlen(zCmd);
540
+ if( strncmp("show",zCmd,nCmd)==0 ){
541
+ const char *zName, *zValue;
542
+ size_t nName;
543
+ Stmt q;
544
+ fossil_print("OpenSSL-version: %s (0x%09x)\n",
545
+ SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
546
+ fossil_print("OpenSSL-cert-file: %s\n", X509_get_default_cert_file());
547
+ fossil_print("OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
548
+ zName = X509_get_default_cert_file_env();
549
+ zValue = fossil_getenv(zName);
550
+ if( zValue==0 ) zValue = "";
551
+ nName = strlen(zName);
552
+ fossil_print("%s:%.*s%s\n", zName, 19-nName, "", zValue);
553
+ zName = X509_get_default_cert_dir_env();
554
+ zValue = fossil_getenv(zName);
555
+ if( zValue==0 ) zValue = "";
556
+ nName = strlen(zName);
557
+ fossil_print("%s:%.*s%s\n", zName, 19-nName, "", zValue);
558
+ nHit++;
559
+ fossil_print("ssl-ca-location: %s\n", db_get("ssl-ca-location",""));
560
+ fossil_print("ssl-identity: %s\n", db_get("ssl-identity",""));
561
+ db_prepare(&q,
562
+ "SELECT name FROM global_config"
563
+ " WHERE name GLOB 'cert:*'"
564
+ "UNION ALL "
565
+ "SELECT name FROM config"
566
+ " WHERE name GLOB 'cert:*'"
567
+ " ORDER BY name"
568
+ );
569
+ while( db_step(&q)==SQLITE_ROW ){
570
+ fossil_print("exception: %s\n", db_column_text(&q,0)+5);
571
+ }
572
+ db_finalize(&q);
573
+ }else
574
+ if( strncmp("remove-exception",zCmd,nCmd)==0 ){
575
+ int i;
576
+ Blob sql;
577
+ char *zSep = "(";
578
+ db_begin_transaction();
579
+ blob_init(&sql, 0, 0);
580
+ if( g.argc==4 && find_option("all",0,0)!=0 ){
581
+ blob_append_sql(&sql,
582
+ "DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
583
+ "DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
584
+ "DELETE FROM config WHERE name GLOB 'cert:*';\n"
585
+ "DELETE FROM config WHERE name GLOB 'trusted:*';\n"
586
+ );
587
+ }else{
588
+ if( g.argc<4 ){
589
+ usage("remove-exception DOMAIN-NAME ...");
590
+ }
591
+ blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
592
+ for(i=3; i<g.argc; i++){
593
+ blob_append_sql(&sql,"%s'cert:%q','trust:%q'",
594
+ zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
595
+ zSep = ",";
596
+ }
597
+ blob_append_sql(&sql,");\n");
598
+ zSep = "(";
599
+ blob_append_sql(&sql,"DELETE FROM config WHERE name IN ");
600
+ for(i=3; i<g.argc; i++){
601
+ blob_append_sql(&sql,"%s'cert:%q','trusted:%q'",
602
+ zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
603
+ zSep = ",";
604
+ }
605
+ blob_append_sql(&sql,");");
606
+ }
607
+ db_exec_sql(blob_str(&sql));
608
+ db_commit_transaction();
609
+ blob_reset(&sql);
610
+ }else
611
+ /*default*/{
612
+ fossil_fatal("unknown sub-command \"%s\".\nshould be one of:"
613
+ " remove-exception show",
614
+ zCmd);
615
+ }
530616
#endif
531617
}
532618
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -24,19 +24,19 @@
24 ** SSL support is abstracted out into this module because Fossil can
25 ** be compiled without SSL support (which requires OpenSSL library)
26 */
27
28 #include "config.h"
 
29
30 #ifdef FOSSIL_ENABLE_SSL
31
32 #include <openssl/bio.h>
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 #include <openssl/x509.h>
36
37 #include "http_ssl.h"
38 #include <assert.h>
39 #include <sys/types.h>
40
41 /*
42 ** There can only be a single OpenSSL IO connection open at a time.
@@ -46,11 +46,15 @@
46 static int sslIsInit = 0; /* True after global initialization */
47 static BIO *iBio = 0; /* OpenSSL I/O abstraction */
48 static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
49 static SSL_CTX *sslCtx; /* SSL context */
50 static SSL *ssl;
51
 
 
 
 
52
53 /*
54 ** Clear the SSL error message
55 */
56 static void ssl_clear_errmsg(void){
@@ -224,38 +228,36 @@
224 }while(!done);
225 sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
226 blob_reset(&reply);
227 return rc;
228 }
 
 
 
 
 
 
 
 
 
 
 
229
230 /*
231 ** Open an SSL connection. The identify of the server is determined
232 ** as follows:
233 **
234 ** g.url.name Name of the server. Ex: www.fossil-scm.org
 
235 ** pUrlData->port TCP/IP port to use. Ex: 80
236 **
237 ** Return the number of errors.
238 */
239 int ssl_open(UrlData *pUrlData){
240 X509 *cert;
241 int hasSavedCertificate = 0;
242 int trusted = 0;
243 unsigned long e;
244
245 ssl_global_init();
246
247 /* Get certificate for current server from global config and
248 * (if we have it in config) add it to certificate store.
249 */
250 cert = ssl_get_certificate(pUrlData, &trusted);
251 if ( cert!=NULL ){
252 X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
253 X509_free(cert);
254 hasSavedCertificate = 1;
255 }
256
257 if( pUrlData->useProxy ){
258 int rc;
259 char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
260 BIO *sBio = BIO_new_connect(connStr);
261 free(connStr);
@@ -325,70 +327,72 @@
325 ssl_set_errmsg("No SSL certificate was presented by the peer");
326 ssl_close();
327 return 1;
328 }
329
330 if( trusted<=0 && (e = SSL_get_verify_result(ssl)) != X509_V_OK ){
 
331 char *desc, *prompt;
332 const char *warning = "";
333 Blob ans;
334 char cReply;
335 BIO *mem;
336 unsigned char md[32];
337 unsigned int mdLength = 31;
338
339 mem = BIO_new(BIO_s_mem());
340 X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
341 BIO_puts(mem, "\n\nIssued By:\n\n");
342 X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
343 BIO_puts(mem, "\n\nSHA1 Fingerprint:\n\n ");
344 if(X509_digest(cert, EVP_sha1(), md, &mdLength)){
 
 
 
 
345 int j;
346 for( j = 0; j < mdLength; ++j ) {
347 BIO_printf(mem, " %02x", md[j]);
348 }
349 }
350 BIO_write(mem, "", 1); /* nul-terminate mem buffer */
351 BIO_get_mem_data(mem, &desc);
352
353 if( hasSavedCertificate ){
354 warning = "WARNING: Certificate doesn't match the "
355 "saved certificate for this host!";
356 }
357 prompt = mprintf("\nSSL verification failed: %s\n"
358 "Certificate received: \n\n%s\n\n%s\n"
359 "Either:\n"
360 " * verify the certificate is correct using the "
361 "SHA1 fingerprint above\n"
362 " * use the global ssl-ca-location setting to specify your CA root\n"
363 " certificates list\n\n"
364 "If you are not expecting this message, answer no and "
365 "contact your server\nadministrator.\n\n"
366 "Accept certificate for host %s (a=always/y/N)? ",
367 X509_verify_cert_error_string(e), desc, warning,
368 pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
369 BIO_free(mem);
370
371 prompt_user(prompt, &ans);
372 free(prompt);
373 cReply = blob_str(&ans)[0];
374 blob_reset(&ans);
375 if( cReply!='y' && cReply!='Y' && cReply!='a' && cReply!='A') {
376 X509_free(cert);
377 ssl_set_errmsg("SSL certificate declined");
378 ssl_close();
379 return 1;
380 }
381 if( cReply=='a' || cReply=='A') {
382 if ( trusted==0 ){
383 prompt_user("\nSave this certificate as fully trusted (a=always/N)? ",
384 &ans);
385 cReply = blob_str(&ans)[0];
386 trusted = ( cReply=='a' || cReply=='A' );
387 blob_reset(&ans);
388 }
389 ssl_save_certificate(pUrlData, cert, trusted);
390 }
391 }
392
393 /* Set the Global.zIpAddr variable to the server we are talking to.
394 ** This is used to populate the ipaddr column of the rcvfrom table,
@@ -415,60 +419,53 @@
415 X509_free(cert);
416 return 0;
417 }
418
419 /*
420 ** Save certificate to global config.
421 */
422 void ssl_save_certificate(UrlData *pUrlData, X509 *cert, int trusted){
423 BIO *mem;
424 char *zCert, *zHost;
425
426 mem = BIO_new(BIO_s_mem());
427 PEM_write_bio_X509(mem, cert);
428 BIO_write(mem, "", 1); /* nul-terminate mem buffer */
429 BIO_get_mem_data(mem, &zCert);
430 zHost = mprintf("cert:%s",
431 pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
432 db_set(zHost, zCert, 1);
433 free(zHost);
434 zHost = mprintf("trusted:%s",
435 pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
436 db_set_int(zHost, trusted, 1);
437 free(zHost);
438 BIO_free(mem);
 
 
 
 
 
 
 
 
 
 
 
439 }
440
441 /*
442 ** Get certificate for pUrlData->urlName from global config.
443 ** Return NULL if no certificate found.
444 */
445 X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
446 char *zHost, *zCert;
447 BIO *mem;
448 X509 *cert;
449
450 zHost = mprintf("cert:%s",
451 pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
452 zCert = db_get(zHost, NULL);
453 free(zHost);
454 if ( zCert==NULL )
455 return NULL;
456
457 if ( pTrusted!=0 ){
458 zHost = mprintf("trusted:%s",
459 pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
460 *pTrusted = db_get_int(zHost, 0);
461 free(zHost);
462 }
463
464 mem = BIO_new(BIO_s_mem());
465 BIO_puts(mem, zCert);
466 cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
467 free(zCert);
468 BIO_free(mem);
469 return cert;
470 }
471
472 /*
473 ** Send content out over the SSL connection.
474 */
@@ -510,22 +507,111 @@
510 }
511
512 #endif /* FOSSIL_ENABLE_SSL */
513
514 /*
515 ** COMMAND: test-ssl-trust-store
 
 
 
 
 
 
 
 
 
 
516 **
517 ** Show the file and directory where OpenSSL looks for certificates
518 ** of trusted CAs.
 
 
519 */
520 void test_ssl_info(void){
521 #if !defined(FOSSIL_ENABLE_SSL)
522 fossil_print("SSL disabled in this build\n");
523 #else
524 fossil_print("file: %-14s %s\n",
525 X509_get_default_cert_file_env(),
526 X509_get_default_cert_file());
527 fossil_print("dir: %-14s %s\n",
528 X509_get_default_cert_dir_env(),
529 X509_get_default_cert_dir());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530 #endif
531 }
532
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -24,19 +24,19 @@
24 ** SSL support is abstracted out into this module because Fossil can
25 ** be compiled without SSL support (which requires OpenSSL library)
26 */
27
28 #include "config.h"
29 #include "http_ssl.h"
30
31 #ifdef FOSSIL_ENABLE_SSL
32
33 #include <openssl/bio.h>
34 #include <openssl/ssl.h>
35 #include <openssl/err.h>
36 #include <openssl/x509.h>
37
 
38 #include <assert.h>
39 #include <sys/types.h>
40
41 /*
42 ** There can only be a single OpenSSL IO connection open at a time.
@@ -46,11 +46,15 @@
46 static int sslIsInit = 0; /* True after global initialization */
47 static BIO *iBio = 0; /* OpenSSL I/O abstraction */
48 static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
49 static SSL_CTX *sslCtx; /* SSL context */
50 static SSL *ssl;
51 static struct { /* Accept this SSL cert for this session only */
52 char *zHost; /* Subject or host name */
53 char *zHash; /* SHA2-256 hash of the cert */
54 } sException;
55 static int sslNoCertVerify = 0; /* Do not verify SSL certs */
56
57 /*
58 ** Clear the SSL error message
59 */
60 static void ssl_clear_errmsg(void){
@@ -224,38 +228,36 @@
228 }while(!done);
229 sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
230 blob_reset(&reply);
231 return rc;
232 }
233
234 /*
235 ** Invoke this routine to disable SSL cert verification. After
236 ** this call is made, any SSL cert that the server provides will
237 ** be accepted. Communication will still be encrypted, but the
238 ** client has no way of knowing whether it is talking to the
239 ** real server or a man-in-the-middle imposter.
240 */
241 void ssl_disable_cert_verification(void){
242 sslNoCertVerify = 1;
243 }
244
245 /*
246 ** Open an SSL connection. The identify of the server is determined
247 ** as follows:
248 **
249 ** pUrlData->name Name of the server. Ex: www.fossil-scm.org
250 ** g.url.name Name of the proxy server, if proxying.
251 ** pUrlData->port TCP/IP port to use. Ex: 80
252 **
253 ** Return the number of errors.
254 */
255 int ssl_open(UrlData *pUrlData){
256 X509 *cert;
 
 
 
257
258 ssl_global_init();
 
 
 
 
 
 
 
 
 
 
 
259 if( pUrlData->useProxy ){
260 int rc;
261 char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
262 BIO *sBio = BIO_new_connect(connStr);
263 free(connStr);
@@ -325,70 +327,72 @@
327 ssl_set_errmsg("No SSL certificate was presented by the peer");
328 ssl_close();
329 return 1;
330 }
331
332 if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
333 int x;
334 char *desc, *prompt;
 
335 Blob ans;
336 char cReply;
337 BIO *mem;
338 unsigned char md[32];
339 char zHash[32*2+1];
340 unsigned int mdLength = (int)sizeof(md);
341
342 memset(md, 0, sizeof(md));
343 zHash[0] = 0;
344 /* MMNNFFPPS */
345 #if OPENSSL_VERSION_NUMBER >= 0x010000000
346 x = X509_digest(cert, EVP_sha256(), md, &mdLength);
347 #else
348 x = X509_digest(cert, EVP_sha1(), md, &mdLength);
349 #endif
350 if( x ){
351 int j;
352 for(j=0; j<mdLength && j*2+1<sizeof(zHash); ++j){
353 zHash[j*2] = "0123456789abcdef"[md[j]>>4];
354 zHash[j*2+1] = "0123456789abcdef"[md[j]&0xf];
355 }
356 zHash[j*2] = 0;
357 }
358
359 if( ssl_certificate_exception_exists(pUrlData, zHash) ){
360 /* Ignore the failure because an exception exists */
361 ssl_one_time_exception(pUrlData, zHash);
362 }else{
363 /* Tell the user about the failure and ask what to do */
364 mem = BIO_new(BIO_s_mem());
365 BIO_puts(mem, " subject: ");
366 X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE);
367 BIO_puts(mem, "\n issuer: ");
368 X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE);
369 BIO_printf(mem, "\n sha256: %s", zHash);
370 BIO_get_mem_data(mem, &desc);
371
372 prompt = mprintf("Unable to verify SSL cert from %s\n%s\n"
373 "accept this cert and continue (y/N)? ",
374 pUrlData->name, desc);
375 BIO_free(mem);
376
377 prompt_user(prompt, &ans);
378 free(prompt);
379 cReply = blob_str(&ans)[0];
380 blob_reset(&ans);
381 if( cReply!='y' && cReply!='Y' ){
382 X509_free(cert);
383 ssl_set_errmsg("SSL cert declined");
384 ssl_close();
385 return 1;
386 }
387 ssl_one_time_exception(pUrlData, zHash);
388 prompt_user("remember this exception (y/N)? ", &ans);
389 cReply = blob_str(&ans)[0];
390 if( cReply=='y' || cReply=='Y') {
391 ssl_remember_certificate_exception(pUrlData, zHash);
392 }
393 blob_reset(&ans);
 
 
394 }
395 }
396
397 /* Set the Global.zIpAddr variable to the server we are talking to.
398 ** This is used to populate the ipaddr column of the rcvfrom table,
@@ -415,60 +419,53 @@
419 X509_free(cert);
420 return 0;
421 }
422
423 /*
424 ** Remember that the cert with the given hash is a acceptable for
425 ** use with pUrlData->name.
426 */
427 LOCAL void ssl_remember_certificate_exception(
428 UrlData *pUrlData,
429 const char *zHash
430 ){
431 char *zName = mprintf("cert:%s", pUrlData->name);
432 db_set(zName, zHash, 1);
433 fossil_free(zName);
434 }
435
436 /*
437 ** Return true if the there exists a certificate exception for
438 ** pUrlData->name that matches the hash.
439 */
440 LOCAL int ssl_certificate_exception_exists(
441 UrlData *pUrlData,
442 const char *zHash
443 ){
444 char *zName, *zValue;
445 if( fossil_strcmp(sException.zHost,pUrlData->name)==0
446 && fossil_strcmp(sException.zHash,zHash)==0
447 ){
448 return 1;
449 }
450 zName = mprintf("cert:%s", pUrlData->name);
451 zValue = db_get(zName,0);
452 fossil_free(zName);
453 return zValue!=0 && strcmp(zHash,zValue)==0;
454 }
455
456 /*
457 ** Remember zHash as an acceptable certificate for this session only.
 
458 */
459 LOCAL void ssl_one_time_exception(
460 UrlData *pUrlData,
461 const char *zHash
462 ){
463 fossil_free(sException.zHost);
464 sException.zHost = fossil_strdup(pUrlData->name);
465 fossil_free(sException.zHash);
466 sException.zHash = fossil_strdup(zHash);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
467 }
468
469 /*
470 ** Send content out over the SSL connection.
471 */
@@ -510,22 +507,111 @@
507 }
508
509 #endif /* FOSSIL_ENABLE_SSL */
510
511 /*
512 ** COMMAND: tls-config*
513 **
514 ** Usage: %fossil tls-config [SUBCOMMAND] [OPTIONS...] [ARGS...]
515 **
516 ** This command is used to view or modify the TLS (Transport Layer
517 ** Security) configuration for Fossil. TLS (formerly SSL) is the
518 ** encryption technology used for secure HTTPS transport.
519 **
520 ** Sub-commands:
521 **
522 ** show Show the TLS configuration
523 **
524 ** remove-exception DOMAIN... Remove TLS cert exceptions
525 ** for the domains listed. Or if
526 ** the --all option is specified,
527 ** remove all TLS cert exceptions.
528 */
529 void test_tlsconfig_info(void){
530 #if !defined(FOSSIL_ENABLE_SSL)
531 fossil_print("TLS disabled in this build\n");
532 #else
533 const char *zCmd;
534 size_t nCmd;
535 int nHit = 0;
536 db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
537 db_open_config(1,0);
538 zCmd = g.argc>=3 ? g.argv[2] : "show";
539 nCmd = strlen(zCmd);
540 if( strncmp("show",zCmd,nCmd)==0 ){
541 const char *zName, *zValue;
542 size_t nName;
543 Stmt q;
544 fossil_print("OpenSSL-version: %s (0x%09x)\n",
545 SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
546 fossil_print("OpenSSL-cert-file: %s\n", X509_get_default_cert_file());
547 fossil_print("OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
548 zName = X509_get_default_cert_file_env();
549 zValue = fossil_getenv(zName);
550 if( zValue==0 ) zValue = "";
551 nName = strlen(zName);
552 fossil_print("%s:%.*s%s\n", zName, 19-nName, "", zValue);
553 zName = X509_get_default_cert_dir_env();
554 zValue = fossil_getenv(zName);
555 if( zValue==0 ) zValue = "";
556 nName = strlen(zName);
557 fossil_print("%s:%.*s%s\n", zName, 19-nName, "", zValue);
558 nHit++;
559 fossil_print("ssl-ca-location: %s\n", db_get("ssl-ca-location",""));
560 fossil_print("ssl-identity: %s\n", db_get("ssl-identity",""));
561 db_prepare(&q,
562 "SELECT name FROM global_config"
563 " WHERE name GLOB 'cert:*'"
564 "UNION ALL "
565 "SELECT name FROM config"
566 " WHERE name GLOB 'cert:*'"
567 " ORDER BY name"
568 );
569 while( db_step(&q)==SQLITE_ROW ){
570 fossil_print("exception: %s\n", db_column_text(&q,0)+5);
571 }
572 db_finalize(&q);
573 }else
574 if( strncmp("remove-exception",zCmd,nCmd)==0 ){
575 int i;
576 Blob sql;
577 char *zSep = "(";
578 db_begin_transaction();
579 blob_init(&sql, 0, 0);
580 if( g.argc==4 && find_option("all",0,0)!=0 ){
581 blob_append_sql(&sql,
582 "DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
583 "DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
584 "DELETE FROM config WHERE name GLOB 'cert:*';\n"
585 "DELETE FROM config WHERE name GLOB 'trusted:*';\n"
586 );
587 }else{
588 if( g.argc<4 ){
589 usage("remove-exception DOMAIN-NAME ...");
590 }
591 blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
592 for(i=3; i<g.argc; i++){
593 blob_append_sql(&sql,"%s'cert:%q','trust:%q'",
594 zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
595 zSep = ",";
596 }
597 blob_append_sql(&sql,");\n");
598 zSep = "(";
599 blob_append_sql(&sql,"DELETE FROM config WHERE name IN ");
600 for(i=3; i<g.argc; i++){
601 blob_append_sql(&sql,"%s'cert:%q','trusted:%q'",
602 zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
603 zSep = ",";
604 }
605 blob_append_sql(&sql,");");
606 }
607 db_exec_sql(blob_str(&sql));
608 db_commit_transaction();
609 blob_reset(&sql);
610 }else
611 /*default*/{
612 fossil_fatal("unknown sub-command \"%s\".\nshould be one of:"
613 " remove-exception show",
614 zCmd);
615 }
616 #endif
617 }
618
+217 -140
--- src/info.c
+++ src/info.c
@@ -666,10 +666,11 @@
666666
const char *zOrigDate;
667667
int okWiki = 0;
668668
Blob wiki_read_links = BLOB_INITIALIZER;
669669
Blob wiki_add_links = BLOB_INITIALIZER;
670670
671
+ Th_Store("current_checkin", zName);
671672
style_header("Check-in [%S]", zUuid);
672673
login_anonymous_available();
673674
zEUser = db_text(0,
674675
"SELECT value FROM tagxref"
675676
" WHERE tagid=%d AND rid=%d AND tagtype>0",
@@ -1340,33 +1341,22 @@
13401341
13411342
/*
13421343
** Possible flags for the second parameter to
13431344
** object_description()
13441345
*/
1345
-#define OBJDESC_DETAIL 0x0001 /* more detail */
1346
+#define OBJDESC_DETAIL 0x0001 /* Show more detail */
13461347
#define OBJDESC_BASE 0x0002 /* Set <base> using this object */
13471348
#endif
13481349
13491350
/*
13501351
** Write a description of an object to the www reply.
1351
-**
1352
-** If the object is a file then mention:
1353
-**
1354
-** * It's artifact ID
1355
-** * All its filenames
1356
-** * The check-in it was part of, with times and users
1357
-**
1358
-** If the object is a manifest, then mention:
1359
-**
1360
-** * It's artifact ID
1361
-** * date of check-in
1362
-** * Comment & user
13631352
*/
13641353
int object_description(
1365
- int rid, /* The artifact ID */
1354
+ int rid, /* The artifact ID for the object to describe */
13661355
u32 objdescFlags, /* Flags to control display */
1367
- Blob *pDownloadName /* Fill with an appropriate download name */
1356
+ const char *zFileName, /* For file objects, use this name. Can be NULL */
1357
+ Blob *pDownloadName /* Fill with a good download name. Can be NULL */
13681358
){
13691359
Stmt q;
13701360
int cnt = 0;
13711361
int nWiki = 0;
13721362
int objType = 0;
@@ -1401,10 +1391,11 @@
14011391
const char *zVers = db_column_text(&q, 4);
14021392
int mPerm = db_column_int(&q, 5);
14031393
const char *zBr = db_column_text(&q, 6);
14041394
int szFile = db_column_int(&q,7);
14051395
int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0;
1396
+ if( zFileName && fossil_strcmp(zName,zFileName)!=0 ) continue;
14061397
if( sameFilename && !showDetail ){
14071398
if( cnt==1 ){
14081399
@ %z(href("%R/whatis/%!S",zUuid))[more...]</a>
14091400
}
14101401
cnt++;
@@ -1671,12 +1662,12 @@
16711662
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
16721663
cookie_link_parameter("diff","diff","2");
16731664
diffType = atoi(PD("diff","2"));
16741665
cookie_render();
16751666
if( P("from") && P("to") ){
1676
- v1 = artifact_from_ci_and_filename(0, "from");
1677
- v2 = artifact_from_ci_and_filename(0, "to");
1667
+ v1 = artifact_from_ci_and_filename("from");
1668
+ v2 = artifact_from_ci_and_filename("to");
16781669
}else{
16791670
Stmt q;
16801671
v1 = name_to_rid_www("v1");
16811672
v2 = name_to_rid_www("v2");
16821673
@@ -1747,13 +1738,13 @@
17471738
@ %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a> To
17481739
@ %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>.</h2>
17491740
}else{
17501741
@ <h2>Differences From
17511742
@ Artifact %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a>:</h2>
1752
- object_description(v1, objdescFlags, 0);
1743
+ object_description(v1, objdescFlags,0, 0);
17531744
@ <h2>To Artifact %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>:</h2>
1754
- object_description(v2, objdescFlags, 0);
1745
+ object_description(v2, objdescFlags,0, 0);
17551746
}
17561747
if( pRe ){
17571748
@ <b>Only differences that match regular expression "%h(zRe)"
17581749
@ are shown.</b>
17591750
}
@@ -1763,22 +1754,27 @@
17631754
style_footer();
17641755
}
17651756
17661757
/*
17671758
** WEBPAGE: raw
1768
-** URL: /raw?name=ARTIFACTID&m=TYPE
1759
+** URL: /raw/ARTIFACTID
17691760
** URL: /raw?ci=BRANCH&filename=NAME
17701761
**
1762
+** Additional query parameters:
1763
+**
1764
+** m=MIMETYPE The mimetype is MIMETYPE
1765
+** at=FILENAME Content-disposition; attachment; filename=FILENAME;
1766
+**
17711767
** Return the uninterpreted content of an artifact. Used primarily
17721768
** to view artifacts that are images.
17731769
*/
17741770
void rawartifact_page(void){
17751771
int rid = 0;
17761772
char *zUuid;
17771773
1778
- if( P("ci") && P("filename") ){
1779
- rid = artifact_from_ci_and_filename(0, 0);
1774
+ if( P("ci") ){
1775
+ rid = artifact_from_ci_and_filename(0);
17801776
}
17811777
if( rid==0 ){
17821778
rid = name_to_rid_www("name");
17831779
}
17841780
login_check_credentials();
@@ -1825,26 +1821,37 @@
18251821
** NULL, guess at the MIME-type based on the filename
18261822
** associated with the artifact.
18271823
*/
18281824
void deliver_artifact(int rid, const char *zMime){
18291825
Blob content;
1826
+ const char *zAttachName = P("at");
18301827
if( zMime==0 ){
1831
- char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
1832
- " WHERE mlink.fid=%d"
1833
- " AND filename.fnid=mlink.fnid", rid);
1834
- if( !zFName ){
1828
+ char *zFN = (char*)zAttachName;
1829
+ if( zFN==0 ){
1830
+ zFN = db_text(0, "SELECT filename.name FROM mlink, filename"
1831
+ " WHERE mlink.fid=%d"
1832
+ " AND filename.fnid=mlink.fnid", rid);
1833
+ }
1834
+ if( zFN==0 ){
18351835
/* Look also at the attachment table */
1836
- zFName = db_text(0, "SELECT attachment.filename FROM attachment, blob"
1837
- " WHERE blob.rid=%d"
1838
- " AND attachment.src=blob.uuid", rid);
1836
+ zFN = db_text(0, "SELECT attachment.filename FROM attachment, blob"
1837
+ " WHERE blob.rid=%d"
1838
+ " AND attachment.src=blob.uuid", rid);
1839
+ }
1840
+ if( zFN ){
1841
+ zMime = mimetype_from_name(zFN);
18391842
}
1840
- if( zFName ) zMime = mimetype_from_name(zFName);
1841
- if( zMime==0 ) zMime = "application/x-fossil-artifact";
1843
+ if( zMime==0 ){
1844
+ zMime = "application/x-fossil-artifact";
1845
+ }
18421846
}
18431847
content_get(rid, &content);
18441848
fossil_free(style_csp(1));
18451849
cgi_set_content_type(zMime);
1850
+ if( zAttachName ){
1851
+ cgi_content_disposition_filename(zAttachName);
1852
+ }
18461853
cgi_set_content(&content);
18471854
}
18481855
18491856
/*
18501857
** Render a hex dump of a file.
@@ -1937,13 +1944,13 @@
19371944
}else{
19381945
@ :</h2>
19391946
}
19401947
blob_zero(&downloadName);
19411948
if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
1942
- object_description(rid, objdescFlags, &downloadName);
1943
- style_submenu_element("Download", "%s/raw/%T?name=%s",
1944
- g.zTop, blob_str(&downloadName), zUuid);
1949
+ object_description(rid, objdescFlags, 0, &downloadName);
1950
+ style_submenu_element("Download", "%R/raw/%s?at=%T",
1951
+ zUuid, file_tail(blob_str(&downloadName)));
19451952
@ <hr />
19461953
content_get(rid, &content);
19471954
@ <blockquote><pre>
19481955
hexdump(&content);
19491956
@ </pre></blockquote>
@@ -1952,59 +1959,53 @@
19521959
19531960
/*
19541961
** Look for "ci" and "filename" query parameters. If found, try to
19551962
** use them to extract the record ID of an artifact for the file.
19561963
**
1957
-** Also look for "fn" as an alias for "filename". If either "filename"
1958
-** or "fn" is present but "ci" is missing, use "tip" as a default value
1959
-** for "ci".
1960
-**
1961
-** If zNameParam is not NULL, this use that parameter as the filename
1962
-** rather than "fn" or "filename".
1963
-**
1964
-** If pUrl is not NULL, then record the "ci" and "filename" values in
1965
-** pUrl.
1966
-**
1967
-** At least one of pUrl or zNameParam must be NULL.
1964
+** Also look for "fn" and "name" as an aliases for "filename". If any
1965
+** "filename" or "fn" or "name" are present but "ci" is missing, then
1966
+** use "tip" as the default value for "ci".
1967
+**
1968
+** If zNameParam is not NULL, then use that parameter as the filename
1969
+** rather than "fn" or "filename" or "name". the zNameParam is used
1970
+** for the from= and to= query parameters of /fdiff.
19681971
*/
1969
-int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){
1972
+int artifact_from_ci_and_filename(const char *zNameParam){
19701973
const char *zFilename;
19711974
const char *zCI;
19721975
int cirid;
19731976
Manifest *pManifest;
19741977
ManifestFile *pFile;
1978
+ int rid = 0;
19751979
19761980
if( zNameParam ){
19771981
zFilename = P(zNameParam);
19781982
}else{
19791983
zFilename = P("filename");
19801984
if( zFilename==0 ){
19811985
zFilename = P("fn");
19821986
}
1987
+ if( zFilename==0 ){
1988
+ zFilename = P("name");
1989
+ }
19831990
}
19841991
if( zFilename==0 ) return 0;
19851992
1986
- zCI = P("ci");
1987
- cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci");
1993
+ zCI = PD("ci", "tip");
1994
+ cirid = name_to_typed_rid(zCI, "ci");
19881995
if( cirid<=0 ) return 0;
19891996
pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
19901997
if( pManifest==0 ) return 0;
19911998
manifest_file_rewind(pManifest);
19921999
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
19932000
if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1994
- int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
1995
- manifest_destroy(pManifest);
1996
- if( pUrl ){
1997
- assert( zNameParam==0 );
1998
- url_add_parameter(pUrl, "fn", zFilename);
1999
- if( zCI ) url_add_parameter(pUrl, "ci", zCI);
2000
- }
2001
- return rid;
2001
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
2002
+ break;
20022003
}
20032004
}
20042005
manifest_destroy(pManifest);
2005
- return 0;
2006
+ return rid;
20062007
}
20072008
20082009
/*
20092010
** The "z" argument is a string that contains the text of a source code
20102011
** file. This routine appends that text to the HTTP reply with line numbering.
@@ -2106,21 +2107,31 @@
21062107
** ln=N - highlight line number N
21072108
** ln=M-N - highlight lines M through N inclusive
21082109
** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
21092110
** verbose - show more detail in the description
21102111
** download - redirect to the download (artifact page only)
2111
-** name=SHA1HASH - Provide the SHA1HASH as a query parameter
2112
-** filename=NAME - Show information for content file NAME
2113
-** fn=NAME - "fn" is shorthand for "filename"
2114
-** ci=VERSION - The specific check-in to use for "filename=".
2112
+** name=NAME - filename or hash as a query parameter
2113
+** filename=NAME - alternative spelling for "name="
2114
+** fn=NAME - alternative spelling for "name="
2115
+** ci=VERSION - The specific check-in to use with "name=" to
2116
+** identify the file.
21152117
**
21162118
** The /artifact page show the complete content of a file
2117
-** identified by HASH as preformatted text. The
2118
-** /whatis page shows only a description of the file. The /file
2119
-** page shows the most recent version of the file or directory
2120
-** called NAME, or a list of the top-level directory if NAME is
2121
-** omitted.
2119
+** identified by HASH. The /whatis page shows only a description
2120
+** of how the artifact is used. The /file page shows the most recent
2121
+** version of the file or directory called NAME, or a list of the
2122
+** top-level directory if NAME is omitted.
2123
+**
2124
+** For /artifact and /whatis, the name= query parameter can refer to
2125
+** either the name of a file, or an artifact hash. If the ci= query
2126
+** parameter is also present, then name= must refer to a file name.
2127
+** If ci= is omitted, then the hash interpretation is preferred but
2128
+** if name= cannot be understood as a hash, a default "tip" value is
2129
+** used for ci=.
2130
+**
2131
+** For /file, name= can only be interpreted as a filename. As before,
2132
+** a default value of "tip" is used for ci= if ci= is omitted.
21222133
*/
21232134
void artifact_page(void){
21242135
int rid = 0;
21252136
Blob content;
21262137
const char *zMime;
@@ -2127,98 +2138,150 @@
21272138
Blob downloadName;
21282139
int renderAsWiki = 0;
21292140
int renderAsHtml = 0;
21302141
int objType;
21312142
int asText;
2132
- const char *zUuid;
2143
+ const char *zUuid = 0;
21332144
u32 objdescFlags = OBJDESC_BASE;
21342145
int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
21352146
int isFile = fossil_strcmp(g.zPath,"file")==0;
21362147
const char *zLn = P("ln");
21372148
const char *zName = P("name");
2138
- HQuery url;
2139
-
2140
- url_initialize(&url, g.zPath);
2141
- rid = artifact_from_ci_and_filename(&url, 0);
2142
- if( rid==0 ){
2143
- url_add_parameter(&url, "name", zName);
2144
- if( isFile ){
2145
- /* Do a top-level directory listing in /file mode if no argument
2146
- ** specified */
2147
- if( zName==0 || zName[0]==0 ){
2148
- if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2149
- page_tree();
2150
- return;
2151
- }
2152
- /* Look for a single file with the given name */
2153
- rid = db_int(0,
2154
- "SELECT fid FROM filename, mlink, event"
2155
- " WHERE name=%Q"
2156
- " AND mlink.fnid=filename.fnid"
2157
- " AND event.objid=mlink.mid"
2158
- " ORDER BY event.mtime DESC LIMIT 1",
2159
- zName
2160
- );
2161
- /* If no file called NAME exists, instead look for a directory
2162
- ** with that name, and do a directory listing */
2163
- if( rid==0 ){
2164
- int nName = (int)strlen(zName);
2165
- if( nName && zName[nName-1]=='/' ) nName--;
2166
- if( db_exists(
2167
- "SELECT 1 FROM filename"
2168
- " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2169
- nName, zName, nName+1, nName, zName
2170
- ) ){
2171
- if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2172
- page_tree();
2173
- return;
2174
- }
2175
- }
2176
- /* If no file or directory called NAME: issue an error */
2177
- if( rid==0 ){
2178
- style_header("No such file");
2179
- @ File '%h(zName)' does not exist in this repository.
2180
- style_footer();
2181
- return;
2182
- }
2183
- }else{
2184
- rid = name_to_rid_www("name");
2185
- }
2186
- }
2187
-
2188
- login_check_credentials();
2189
- if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2190
- if( rid==0 ){
2191
- style_header("No such artifact");
2192
- @ Artifact '%h(zName)' does not exist in this repository.
2193
- style_footer();
2194
- return;
2195
- }
2149
+ const char *zCI = P("ci");
2150
+ HQuery url;
2151
+ char *zCIUuid = 0;
2152
+ int isSymbolicCI = 0; /* ci= exists and is a symbolic name, not a hash */
2153
+ int isBranchCI = 0; /* ci= refers to a branch name */
2154
+ char *zHeader = 0;
2155
+
2156
+ login_check_credentials();
2157
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2158
+
2159
+ /* Capture and normalize the name= and ci= query parameters */
2160
+ if( zName==0 ){
2161
+ zName = P("filename");
2162
+ if( zName==0 ){
2163
+ zName = P("fn");
2164
+ }
2165
+ }
2166
+ if( zCI && strlen(zCI)==0 ){ zCI = 0; }
2167
+ if( zCI
2168
+ && name_to_uuid2(zCI, "ci", &zCIUuid)
2169
+ && sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
2170
+ ){
2171
+ isSymbolicCI = 1;
2172
+ isBranchCI = branch_includes_uuid(zCI, zCIUuid);
2173
+ }
2174
+
2175
+ /* The name= query parameter (or at least one of its alternative
2176
+ ** spellings) is required. Except for /file, show a top-level
2177
+ ** directory listing if name= is omitted.
2178
+ */
2179
+ if( zName==0 ){
2180
+ if( isFile ){
2181
+ if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2182
+ page_tree();
2183
+ return;
2184
+ }
2185
+ style_header("Missing name= query parameter");
2186
+ @ The name= query parameter is missing
2187
+ style_footer();
2188
+ return;
2189
+ }
2190
+
2191
+ url_initialize(&url, g.zPath);
2192
+ url_add_parameter(&url, "name", zName);
2193
+ url_add_parameter(&url, "ci", zCI);
2194
+
2195
+ if( zCI==0 && !isFile ){
2196
+ /* If there is no ci= query parameter, then prefer to interpret
2197
+ ** name= as a hash for /artifact and /whatis. But for not for /file.
2198
+ ** For /file, a name= without a ci= while prefer to use the default
2199
+ ** "tip" value for ci=. */
2200
+ rid = name_to_rid(zName);
2201
+ }
2202
+ if( rid==0 ){
2203
+ rid = artifact_from_ci_and_filename(0);
2204
+ }
2205
+
2206
+ if( rid==0 ){ /* Artifact not found */
2207
+ if( isFile ){
2208
+ /* For /file, also check to see if name= refers to a directory,
2209
+ ** and if so, do a listing for that directory */
2210
+ int nName = (int)strlen(zName);
2211
+ if( nName && zName[nName-1]=='/' ) nName--;
2212
+ if( db_exists(
2213
+ "SELECT 1 FROM filename"
2214
+ " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2215
+ nName, zName, nName+1, nName, zName
2216
+ ) ){
2217
+ if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2218
+ page_tree();
2219
+ return;
2220
+ }
2221
+ style_header("No such file");
2222
+ @ File '%h(zName)' does not exist in this repository.
2223
+ }else{
2224
+ style_header("No such artifact");
2225
+ @ Artifact '%h(zName)' does not exist in this repository.
2226
+ }
2227
+ style_footer();
2228
+ return;
2229
+ }
2230
+
21962231
if( descOnly || P("verbose")!=0 ){
21972232
url_add_parameter(&url, "verbose", "1");
21982233
objdescFlags |= OBJDESC_DETAIL;
21992234
}
22002235
zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
2236
+
2237
+ asText = P("txt")!=0;
22012238
if( isFile ){
2202
- @ <h2>Latest version of file '%h(zName)':</h2>
2239
+ if( zCI==0 || fossil_strcmp(zCI,"tip")==0 ){
2240
+ zCI = "tip";
2241
+ @ <h2>File %z(href("%R/finfo?name=%T&m=tip",zName))%h(zName)</a>
2242
+ @ from the %z(href("%R/info/tip"))latest check-in</a></h2>
2243
+ }else{
2244
+ const char *zPath;
2245
+ Blob path;
2246
+ blob_zero(&path);
2247
+ hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
2248
+ zPath = blob_str(&path);
2249
+ @ <h2>File %s(zPath) \
2250
+ if( isBranchCI ){
2251
+ @ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
2252
+ }else if( isSymbolicCI ){
2253
+ @ as of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
2254
+ }else{
2255
+ @ as of check-in [%z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a>]</h2>
2256
+ }
2257
+ blob_reset(&path);
2258
+ }
22032259
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2260
+ style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2261
+ zName, zCI);
2262
+ style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2263
+ zName, zCI);
2264
+ blob_init(&downloadName, zName, -1);
2265
+ objType = OBJTYPE_CONTENT;
22042266
}else{
22052267
@ <h2>Artifact
22062268
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
22072269
if( g.perm.Setup ){
22082270
@ (%d(rid)):</h2>
22092271
}else{
22102272
@ :</h2>
22112273
}
2274
+ blob_zero(&downloadName);
2275
+ if( asText ) objdescFlags &= ~OBJDESC_BASE;
2276
+ objType = object_description(rid, objdescFlags,
2277
+ (isFile?zName:0), &downloadName);
22122278
}
2213
- blob_zero(&downloadName);
2214
- asText = P("txt")!=0;
2215
- if( asText ) objdescFlags &= ~OBJDESC_BASE;
2216
- objType = object_description(rid, objdescFlags, &downloadName);
22172279
if( !descOnly && P("download")!=0 ){
2218
- cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
2219
- db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
2280
+ cgi_redirectf("%R/raw/%s?at=%T",
2281
+ db_text("x", "SELECT uuid FROM blob WHERE rid=%d", rid),
2282
+ file_tail(blob_str(&downloadName)));
22202283
/*NOTREACHED*/
22212284
}
22222285
if( g.perm.Admin ){
22232286
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
22242287
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
@@ -2226,13 +2289,28 @@
22262289
g.zTop, zUuid);
22272290
}else{
22282291
style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
22292292
}
22302293
}
2231
- style_header("%s", isFile ? "File Content" :
2232
- descOnly ? "Artifact Description" : "Artifact Content");
2233
- if( g.perm.Admin ){
2294
+
2295
+ if( isFile ){
2296
+ if( isSymbolicCI ){
2297
+ zHeader = mprintf("%s at %s", file_tail(zName), zCI);
2298
+ }else if( zCI ){
2299
+ zHeader = mprintf("%s at [%S]", file_tail(zName), zCIUuid);
2300
+ }else{
2301
+ zHeader = mprintf("%s", file_tail(zName));
2302
+ }
2303
+ }else if( descOnly ){
2304
+ zHeader = mprintf("Artifact Description [%S]", zUuid);
2305
+ }else{
2306
+ zHeader = mprintf("Artifact [%S]", zUuid);
2307
+ }
2308
+ style_header("%s", zHeader);
2309
+ fossil_free(zCIUuid);
2310
+ fossil_free(zHeader);
2311
+ if( !isFile && g.perm.Admin ){
22342312
Stmt q;
22352313
db_prepare(&q,
22362314
"SELECT coalesce(user.login,rcvfrom.uid),"
22372315
" datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
22382316
" FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
@@ -2244,12 +2322,11 @@
22442322
const char *zIp = db_column_text(&q,2);
22452323
@ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
22462324
}
22472325
db_finalize(&q);
22482326
}
2249
- style_submenu_element("Download", "%R/raw/%T?name=%s",
2250
- blob_str(&downloadName), zUuid);
2327
+ style_submenu_element("Download", "%R/raw/%s?at=%T", zUuid, file_tail(zName));
22512328
if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
22522329
style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
22532330
}
22542331
zMime = mimetype_from_name(blob_str(&downloadName));
22552332
if( zMime ){
@@ -2279,11 +2356,11 @@
22792356
@ <hr />
22802357
content_get(rid, &content);
22812358
if( renderAsWiki ){
22822359
wiki_render_by_mimetype(&content, zMime);
22832360
}else if( renderAsHtml ){
2284
- @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
2361
+ @ <iframe src="%R/raw/%s(zUuid)"
22852362
@ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
22862363
@ sandbox="allow-same-origin" id="ifm1">
22872364
@ </iframe>
22882365
@ <script nonce="%h(style_nonce())">
22892366
@ document.getElementById("ifm1").addEventListener("load",
@@ -2708,15 +2785,15 @@
27082785
**
27092786
** Edit a check-in. (Check-ins are immutable and do not really change.
27102787
** This page really creates supplemental tags that affect the display
27112788
** of the check-in.)
27122789
**
2713
-** Query parmeters:
2790
+** Query parameters:
27142791
**
27152792
** rid=INTEGER Record ID of the check-in to edit (REQUIRED)
27162793
**
2717
-** POST parameters after pressing "Perview", "Cancel", or "Apply":
2794
+** POST parameters after pressing "Preview", "Cancel", or "Apply":
27182795
**
27192796
** c=TEXT New check-in comment
27202797
** u=TEXT New user name
27212798
** newclr Apply a background color
27222799
** clr=TEXT New background color (only if newclr)
27232800
--- src/info.c
+++ src/info.c
@@ -666,10 +666,11 @@
666 const char *zOrigDate;
667 int okWiki = 0;
668 Blob wiki_read_links = BLOB_INITIALIZER;
669 Blob wiki_add_links = BLOB_INITIALIZER;
670
 
671 style_header("Check-in [%S]", zUuid);
672 login_anonymous_available();
673 zEUser = db_text(0,
674 "SELECT value FROM tagxref"
675 " WHERE tagid=%d AND rid=%d AND tagtype>0",
@@ -1340,33 +1341,22 @@
1340
1341 /*
1342 ** Possible flags for the second parameter to
1343 ** object_description()
1344 */
1345 #define OBJDESC_DETAIL 0x0001 /* more detail */
1346 #define OBJDESC_BASE 0x0002 /* Set <base> using this object */
1347 #endif
1348
1349 /*
1350 ** Write a description of an object to the www reply.
1351 **
1352 ** If the object is a file then mention:
1353 **
1354 ** * It's artifact ID
1355 ** * All its filenames
1356 ** * The check-in it was part of, with times and users
1357 **
1358 ** If the object is a manifest, then mention:
1359 **
1360 ** * It's artifact ID
1361 ** * date of check-in
1362 ** * Comment & user
1363 */
1364 int object_description(
1365 int rid, /* The artifact ID */
1366 u32 objdescFlags, /* Flags to control display */
1367 Blob *pDownloadName /* Fill with an appropriate download name */
 
1368 ){
1369 Stmt q;
1370 int cnt = 0;
1371 int nWiki = 0;
1372 int objType = 0;
@@ -1401,10 +1391,11 @@
1401 const char *zVers = db_column_text(&q, 4);
1402 int mPerm = db_column_int(&q, 5);
1403 const char *zBr = db_column_text(&q, 6);
1404 int szFile = db_column_int(&q,7);
1405 int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0;
 
1406 if( sameFilename && !showDetail ){
1407 if( cnt==1 ){
1408 @ %z(href("%R/whatis/%!S",zUuid))[more...]</a>
1409 }
1410 cnt++;
@@ -1671,12 +1662,12 @@
1671 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1672 cookie_link_parameter("diff","diff","2");
1673 diffType = atoi(PD("diff","2"));
1674 cookie_render();
1675 if( P("from") && P("to") ){
1676 v1 = artifact_from_ci_and_filename(0, "from");
1677 v2 = artifact_from_ci_and_filename(0, "to");
1678 }else{
1679 Stmt q;
1680 v1 = name_to_rid_www("v1");
1681 v2 = name_to_rid_www("v2");
1682
@@ -1747,13 +1738,13 @@
1747 @ %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a> To
1748 @ %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>.</h2>
1749 }else{
1750 @ <h2>Differences From
1751 @ Artifact %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a>:</h2>
1752 object_description(v1, objdescFlags, 0);
1753 @ <h2>To Artifact %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>:</h2>
1754 object_description(v2, objdescFlags, 0);
1755 }
1756 if( pRe ){
1757 @ <b>Only differences that match regular expression "%h(zRe)"
1758 @ are shown.</b>
1759 }
@@ -1763,22 +1754,27 @@
1763 style_footer();
1764 }
1765
1766 /*
1767 ** WEBPAGE: raw
1768 ** URL: /raw?name=ARTIFACTID&m=TYPE
1769 ** URL: /raw?ci=BRANCH&filename=NAME
1770 **
 
 
 
 
 
1771 ** Return the uninterpreted content of an artifact. Used primarily
1772 ** to view artifacts that are images.
1773 */
1774 void rawartifact_page(void){
1775 int rid = 0;
1776 char *zUuid;
1777
1778 if( P("ci") && P("filename") ){
1779 rid = artifact_from_ci_and_filename(0, 0);
1780 }
1781 if( rid==0 ){
1782 rid = name_to_rid_www("name");
1783 }
1784 login_check_credentials();
@@ -1825,26 +1821,37 @@
1825 ** NULL, guess at the MIME-type based on the filename
1826 ** associated with the artifact.
1827 */
1828 void deliver_artifact(int rid, const char *zMime){
1829 Blob content;
 
1830 if( zMime==0 ){
1831 char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
1832 " WHERE mlink.fid=%d"
1833 " AND filename.fnid=mlink.fnid", rid);
1834 if( !zFName ){
 
 
 
1835 /* Look also at the attachment table */
1836 zFName = db_text(0, "SELECT attachment.filename FROM attachment, blob"
1837 " WHERE blob.rid=%d"
1838 " AND attachment.src=blob.uuid", rid);
 
 
 
1839 }
1840 if( zFName ) zMime = mimetype_from_name(zFName);
1841 if( zMime==0 ) zMime = "application/x-fossil-artifact";
 
1842 }
1843 content_get(rid, &content);
1844 fossil_free(style_csp(1));
1845 cgi_set_content_type(zMime);
 
 
 
1846 cgi_set_content(&content);
1847 }
1848
1849 /*
1850 ** Render a hex dump of a file.
@@ -1937,13 +1944,13 @@
1937 }else{
1938 @ :</h2>
1939 }
1940 blob_zero(&downloadName);
1941 if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
1942 object_description(rid, objdescFlags, &downloadName);
1943 style_submenu_element("Download", "%s/raw/%T?name=%s",
1944 g.zTop, blob_str(&downloadName), zUuid);
1945 @ <hr />
1946 content_get(rid, &content);
1947 @ <blockquote><pre>
1948 hexdump(&content);
1949 @ </pre></blockquote>
@@ -1952,59 +1959,53 @@
1952
1953 /*
1954 ** Look for "ci" and "filename" query parameters. If found, try to
1955 ** use them to extract the record ID of an artifact for the file.
1956 **
1957 ** Also look for "fn" as an alias for "filename". If either "filename"
1958 ** or "fn" is present but "ci" is missing, use "tip" as a default value
1959 ** for "ci".
1960 **
1961 ** If zNameParam is not NULL, this use that parameter as the filename
1962 ** rather than "fn" or "filename".
1963 **
1964 ** If pUrl is not NULL, then record the "ci" and "filename" values in
1965 ** pUrl.
1966 **
1967 ** At least one of pUrl or zNameParam must be NULL.
1968 */
1969 int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){
1970 const char *zFilename;
1971 const char *zCI;
1972 int cirid;
1973 Manifest *pManifest;
1974 ManifestFile *pFile;
 
1975
1976 if( zNameParam ){
1977 zFilename = P(zNameParam);
1978 }else{
1979 zFilename = P("filename");
1980 if( zFilename==0 ){
1981 zFilename = P("fn");
1982 }
 
 
 
1983 }
1984 if( zFilename==0 ) return 0;
1985
1986 zCI = P("ci");
1987 cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci");
1988 if( cirid<=0 ) return 0;
1989 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1990 if( pManifest==0 ) return 0;
1991 manifest_file_rewind(pManifest);
1992 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1993 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1994 int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
1995 manifest_destroy(pManifest);
1996 if( pUrl ){
1997 assert( zNameParam==0 );
1998 url_add_parameter(pUrl, "fn", zFilename);
1999 if( zCI ) url_add_parameter(pUrl, "ci", zCI);
2000 }
2001 return rid;
2002 }
2003 }
2004 manifest_destroy(pManifest);
2005 return 0;
2006 }
2007
2008 /*
2009 ** The "z" argument is a string that contains the text of a source code
2010 ** file. This routine appends that text to the HTTP reply with line numbering.
@@ -2106,21 +2107,31 @@
2106 ** ln=N - highlight line number N
2107 ** ln=M-N - highlight lines M through N inclusive
2108 ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
2109 ** verbose - show more detail in the description
2110 ** download - redirect to the download (artifact page only)
2111 ** name=SHA1HASH - Provide the SHA1HASH as a query parameter
2112 ** filename=NAME - Show information for content file NAME
2113 ** fn=NAME - "fn" is shorthand for "filename"
2114 ** ci=VERSION - The specific check-in to use for "filename=".
 
2115 **
2116 ** The /artifact page show the complete content of a file
2117 ** identified by HASH as preformatted text. The
2118 ** /whatis page shows only a description of the file. The /file
2119 ** page shows the most recent version of the file or directory
2120 ** called NAME, or a list of the top-level directory if NAME is
2121 ** omitted.
 
 
 
 
 
 
 
 
 
2122 */
2123 void artifact_page(void){
2124 int rid = 0;
2125 Blob content;
2126 const char *zMime;
@@ -2127,98 +2138,150 @@
2127 Blob downloadName;
2128 int renderAsWiki = 0;
2129 int renderAsHtml = 0;
2130 int objType;
2131 int asText;
2132 const char *zUuid;
2133 u32 objdescFlags = OBJDESC_BASE;
2134 int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
2135 int isFile = fossil_strcmp(g.zPath,"file")==0;
2136 const char *zLn = P("ln");
2137 const char *zName = P("name");
2138 HQuery url;
2139
2140 url_initialize(&url, g.zPath);
2141 rid = artifact_from_ci_and_filename(&url, 0);
2142 if( rid==0 ){
2143 url_add_parameter(&url, "name", zName);
2144 if( isFile ){
2145 /* Do a top-level directory listing in /file mode if no argument
2146 ** specified */
2147 if( zName==0 || zName[0]==0 ){
2148 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2149 page_tree();
2150 return;
2151 }
2152 /* Look for a single file with the given name */
2153 rid = db_int(0,
2154 "SELECT fid FROM filename, mlink, event"
2155 " WHERE name=%Q"
2156 " AND mlink.fnid=filename.fnid"
2157 " AND event.objid=mlink.mid"
2158 " ORDER BY event.mtime DESC LIMIT 1",
2159 zName
2160 );
2161 /* If no file called NAME exists, instead look for a directory
2162 ** with that name, and do a directory listing */
2163 if( rid==0 ){
2164 int nName = (int)strlen(zName);
2165 if( nName && zName[nName-1]=='/' ) nName--;
2166 if( db_exists(
2167 "SELECT 1 FROM filename"
2168 " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2169 nName, zName, nName+1, nName, zName
2170 ) ){
2171 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2172 page_tree();
2173 return;
2174 }
2175 }
2176 /* If no file or directory called NAME: issue an error */
2177 if( rid==0 ){
2178 style_header("No such file");
2179 @ File '%h(zName)' does not exist in this repository.
2180 style_footer();
2181 return;
2182 }
2183 }else{
2184 rid = name_to_rid_www("name");
2185 }
2186 }
2187
2188 login_check_credentials();
2189 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2190 if( rid==0 ){
2191 style_header("No such artifact");
2192 @ Artifact '%h(zName)' does not exist in this repository.
2193 style_footer();
2194 return;
2195 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2196 if( descOnly || P("verbose")!=0 ){
2197 url_add_parameter(&url, "verbose", "1");
2198 objdescFlags |= OBJDESC_DETAIL;
2199 }
2200 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
 
 
2201 if( isFile ){
2202 @ <h2>Latest version of file '%h(zName)':</h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2203 style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
 
 
 
 
 
 
2204 }else{
2205 @ <h2>Artifact
2206 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2207 if( g.perm.Setup ){
2208 @ (%d(rid)):</h2>
2209 }else{
2210 @ :</h2>
2211 }
 
 
 
 
2212 }
2213 blob_zero(&downloadName);
2214 asText = P("txt")!=0;
2215 if( asText ) objdescFlags &= ~OBJDESC_BASE;
2216 objType = object_description(rid, objdescFlags, &downloadName);
2217 if( !descOnly && P("download")!=0 ){
2218 cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
2219 db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
 
2220 /*NOTREACHED*/
2221 }
2222 if( g.perm.Admin ){
2223 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
2224 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
@@ -2226,13 +2289,28 @@
2226 g.zTop, zUuid);
2227 }else{
2228 style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
2229 }
2230 }
2231 style_header("%s", isFile ? "File Content" :
2232 descOnly ? "Artifact Description" : "Artifact Content");
2233 if( g.perm.Admin ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2234 Stmt q;
2235 db_prepare(&q,
2236 "SELECT coalesce(user.login,rcvfrom.uid),"
2237 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
2238 " FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
@@ -2244,12 +2322,11 @@
2244 const char *zIp = db_column_text(&q,2);
2245 @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
2246 }
2247 db_finalize(&q);
2248 }
2249 style_submenu_element("Download", "%R/raw/%T?name=%s",
2250 blob_str(&downloadName), zUuid);
2251 if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
2252 style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
2253 }
2254 zMime = mimetype_from_name(blob_str(&downloadName));
2255 if( zMime ){
@@ -2279,11 +2356,11 @@
2279 @ <hr />
2280 content_get(rid, &content);
2281 if( renderAsWiki ){
2282 wiki_render_by_mimetype(&content, zMime);
2283 }else if( renderAsHtml ){
2284 @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"
2285 @ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
2286 @ sandbox="allow-same-origin" id="ifm1">
2287 @ </iframe>
2288 @ <script nonce="%h(style_nonce())">
2289 @ document.getElementById("ifm1").addEventListener("load",
@@ -2708,15 +2785,15 @@
2708 **
2709 ** Edit a check-in. (Check-ins are immutable and do not really change.
2710 ** This page really creates supplemental tags that affect the display
2711 ** of the check-in.)
2712 **
2713 ** Query parmeters:
2714 **
2715 ** rid=INTEGER Record ID of the check-in to edit (REQUIRED)
2716 **
2717 ** POST parameters after pressing "Perview", "Cancel", or "Apply":
2718 **
2719 ** c=TEXT New check-in comment
2720 ** u=TEXT New user name
2721 ** newclr Apply a background color
2722 ** clr=TEXT New background color (only if newclr)
2723
--- src/info.c
+++ src/info.c
@@ -666,10 +666,11 @@
666 const char *zOrigDate;
667 int okWiki = 0;
668 Blob wiki_read_links = BLOB_INITIALIZER;
669 Blob wiki_add_links = BLOB_INITIALIZER;
670
671 Th_Store("current_checkin", zName);
672 style_header("Check-in [%S]", zUuid);
673 login_anonymous_available();
674 zEUser = db_text(0,
675 "SELECT value FROM tagxref"
676 " WHERE tagid=%d AND rid=%d AND tagtype>0",
@@ -1340,33 +1341,22 @@
1341
1342 /*
1343 ** Possible flags for the second parameter to
1344 ** object_description()
1345 */
1346 #define OBJDESC_DETAIL 0x0001 /* Show more detail */
1347 #define OBJDESC_BASE 0x0002 /* Set <base> using this object */
1348 #endif
1349
1350 /*
1351 ** Write a description of an object to the www reply.
 
 
 
 
 
 
 
 
 
 
 
 
1352 */
1353 int object_description(
1354 int rid, /* The artifact ID for the object to describe */
1355 u32 objdescFlags, /* Flags to control display */
1356 const char *zFileName, /* For file objects, use this name. Can be NULL */
1357 Blob *pDownloadName /* Fill with a good download name. Can be NULL */
1358 ){
1359 Stmt q;
1360 int cnt = 0;
1361 int nWiki = 0;
1362 int objType = 0;
@@ -1401,10 +1391,11 @@
1391 const char *zVers = db_column_text(&q, 4);
1392 int mPerm = db_column_int(&q, 5);
1393 const char *zBr = db_column_text(&q, 6);
1394 int szFile = db_column_int(&q,7);
1395 int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0;
1396 if( zFileName && fossil_strcmp(zName,zFileName)!=0 ) continue;
1397 if( sameFilename && !showDetail ){
1398 if( cnt==1 ){
1399 @ %z(href("%R/whatis/%!S",zUuid))[more...]</a>
1400 }
1401 cnt++;
@@ -1671,12 +1662,12 @@
1662 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1663 cookie_link_parameter("diff","diff","2");
1664 diffType = atoi(PD("diff","2"));
1665 cookie_render();
1666 if( P("from") && P("to") ){
1667 v1 = artifact_from_ci_and_filename("from");
1668 v2 = artifact_from_ci_and_filename("to");
1669 }else{
1670 Stmt q;
1671 v1 = name_to_rid_www("v1");
1672 v2 = name_to_rid_www("v2");
1673
@@ -1747,13 +1738,13 @@
1738 @ %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a> To
1739 @ %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>.</h2>
1740 }else{
1741 @ <h2>Differences From
1742 @ Artifact %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a>:</h2>
1743 object_description(v1, objdescFlags,0, 0);
1744 @ <h2>To Artifact %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>:</h2>
1745 object_description(v2, objdescFlags,0, 0);
1746 }
1747 if( pRe ){
1748 @ <b>Only differences that match regular expression "%h(zRe)"
1749 @ are shown.</b>
1750 }
@@ -1763,22 +1754,27 @@
1754 style_footer();
1755 }
1756
1757 /*
1758 ** WEBPAGE: raw
1759 ** URL: /raw/ARTIFACTID
1760 ** URL: /raw?ci=BRANCH&filename=NAME
1761 **
1762 ** Additional query parameters:
1763 **
1764 ** m=MIMETYPE The mimetype is MIMETYPE
1765 ** at=FILENAME Content-disposition; attachment; filename=FILENAME;
1766 **
1767 ** Return the uninterpreted content of an artifact. Used primarily
1768 ** to view artifacts that are images.
1769 */
1770 void rawartifact_page(void){
1771 int rid = 0;
1772 char *zUuid;
1773
1774 if( P("ci") ){
1775 rid = artifact_from_ci_and_filename(0);
1776 }
1777 if( rid==0 ){
1778 rid = name_to_rid_www("name");
1779 }
1780 login_check_credentials();
@@ -1825,26 +1821,37 @@
1821 ** NULL, guess at the MIME-type based on the filename
1822 ** associated with the artifact.
1823 */
1824 void deliver_artifact(int rid, const char *zMime){
1825 Blob content;
1826 const char *zAttachName = P("at");
1827 if( zMime==0 ){
1828 char *zFN = (char*)zAttachName;
1829 if( zFN==0 ){
1830 zFN = db_text(0, "SELECT filename.name FROM mlink, filename"
1831 " WHERE mlink.fid=%d"
1832 " AND filename.fnid=mlink.fnid", rid);
1833 }
1834 if( zFN==0 ){
1835 /* Look also at the attachment table */
1836 zFN = db_text(0, "SELECT attachment.filename FROM attachment, blob"
1837 " WHERE blob.rid=%d"
1838 " AND attachment.src=blob.uuid", rid);
1839 }
1840 if( zFN ){
1841 zMime = mimetype_from_name(zFN);
1842 }
1843 if( zMime==0 ){
1844 zMime = "application/x-fossil-artifact";
1845 }
1846 }
1847 content_get(rid, &content);
1848 fossil_free(style_csp(1));
1849 cgi_set_content_type(zMime);
1850 if( zAttachName ){
1851 cgi_content_disposition_filename(zAttachName);
1852 }
1853 cgi_set_content(&content);
1854 }
1855
1856 /*
1857 ** Render a hex dump of a file.
@@ -1937,13 +1944,13 @@
1944 }else{
1945 @ :</h2>
1946 }
1947 blob_zero(&downloadName);
1948 if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
1949 object_description(rid, objdescFlags, 0, &downloadName);
1950 style_submenu_element("Download", "%R/raw/%s?at=%T",
1951 zUuid, file_tail(blob_str(&downloadName)));
1952 @ <hr />
1953 content_get(rid, &content);
1954 @ <blockquote><pre>
1955 hexdump(&content);
1956 @ </pre></blockquote>
@@ -1952,59 +1959,53 @@
1959
1960 /*
1961 ** Look for "ci" and "filename" query parameters. If found, try to
1962 ** use them to extract the record ID of an artifact for the file.
1963 **
1964 ** Also look for "fn" and "name" as an aliases for "filename". If any
1965 ** "filename" or "fn" or "name" are present but "ci" is missing, then
1966 ** use "tip" as the default value for "ci".
1967 **
1968 ** If zNameParam is not NULL, then use that parameter as the filename
1969 ** rather than "fn" or "filename" or "name". the zNameParam is used
1970 ** for the from= and to= query parameters of /fdiff.
 
 
 
 
1971 */
1972 int artifact_from_ci_and_filename(const char *zNameParam){
1973 const char *zFilename;
1974 const char *zCI;
1975 int cirid;
1976 Manifest *pManifest;
1977 ManifestFile *pFile;
1978 int rid = 0;
1979
1980 if( zNameParam ){
1981 zFilename = P(zNameParam);
1982 }else{
1983 zFilename = P("filename");
1984 if( zFilename==0 ){
1985 zFilename = P("fn");
1986 }
1987 if( zFilename==0 ){
1988 zFilename = P("name");
1989 }
1990 }
1991 if( zFilename==0 ) return 0;
1992
1993 zCI = PD("ci", "tip");
1994 cirid = name_to_typed_rid(zCI, "ci");
1995 if( cirid<=0 ) return 0;
1996 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1997 if( pManifest==0 ) return 0;
1998 manifest_file_rewind(pManifest);
1999 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
2000 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
2001 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
2002 break;
 
 
 
 
 
 
2003 }
2004 }
2005 manifest_destroy(pManifest);
2006 return rid;
2007 }
2008
2009 /*
2010 ** The "z" argument is a string that contains the text of a source code
2011 ** file. This routine appends that text to the HTTP reply with line numbering.
@@ -2106,21 +2107,31 @@
2107 ** ln=N - highlight line number N
2108 ** ln=M-N - highlight lines M through N inclusive
2109 ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
2110 ** verbose - show more detail in the description
2111 ** download - redirect to the download (artifact page only)
2112 ** name=NAME - filename or hash as a query parameter
2113 ** filename=NAME - alternative spelling for "name="
2114 ** fn=NAME - alternative spelling for "name="
2115 ** ci=VERSION - The specific check-in to use with "name=" to
2116 ** identify the file.
2117 **
2118 ** The /artifact page show the complete content of a file
2119 ** identified by HASH. The /whatis page shows only a description
2120 ** of how the artifact is used. The /file page shows the most recent
2121 ** version of the file or directory called NAME, or a list of the
2122 ** top-level directory if NAME is omitted.
2123 **
2124 ** For /artifact and /whatis, the name= query parameter can refer to
2125 ** either the name of a file, or an artifact hash. If the ci= query
2126 ** parameter is also present, then name= must refer to a file name.
2127 ** If ci= is omitted, then the hash interpretation is preferred but
2128 ** if name= cannot be understood as a hash, a default "tip" value is
2129 ** used for ci=.
2130 **
2131 ** For /file, name= can only be interpreted as a filename. As before,
2132 ** a default value of "tip" is used for ci= if ci= is omitted.
2133 */
2134 void artifact_page(void){
2135 int rid = 0;
2136 Blob content;
2137 const char *zMime;
@@ -2127,98 +2138,150 @@
2138 Blob downloadName;
2139 int renderAsWiki = 0;
2140 int renderAsHtml = 0;
2141 int objType;
2142 int asText;
2143 const char *zUuid = 0;
2144 u32 objdescFlags = OBJDESC_BASE;
2145 int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
2146 int isFile = fossil_strcmp(g.zPath,"file")==0;
2147 const char *zLn = P("ln");
2148 const char *zName = P("name");
2149 const char *zCI = P("ci");
2150 HQuery url;
2151 char *zCIUuid = 0;
2152 int isSymbolicCI = 0; /* ci= exists and is a symbolic name, not a hash */
2153 int isBranchCI = 0; /* ci= refers to a branch name */
2154 char *zHeader = 0;
2155
2156 login_check_credentials();
2157 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2158
2159 /* Capture and normalize the name= and ci= query parameters */
2160 if( zName==0 ){
2161 zName = P("filename");
2162 if( zName==0 ){
2163 zName = P("fn");
2164 }
2165 }
2166 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
2167 if( zCI
2168 && name_to_uuid2(zCI, "ci", &zCIUuid)
2169 && sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
2170 ){
2171 isSymbolicCI = 1;
2172 isBranchCI = branch_includes_uuid(zCI, zCIUuid);
2173 }
2174
2175 /* The name= query parameter (or at least one of its alternative
2176 ** spellings) is required. Except for /file, show a top-level
2177 ** directory listing if name= is omitted.
2178 */
2179 if( zName==0 ){
2180 if( isFile ){
2181 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2182 page_tree();
2183 return;
2184 }
2185 style_header("Missing name= query parameter");
2186 @ The name= query parameter is missing
2187 style_footer();
2188 return;
2189 }
2190
2191 url_initialize(&url, g.zPath);
2192 url_add_parameter(&url, "name", zName);
2193 url_add_parameter(&url, "ci", zCI);
2194
2195 if( zCI==0 && !isFile ){
2196 /* If there is no ci= query parameter, then prefer to interpret
2197 ** name= as a hash for /artifact and /whatis. But for not for /file.
2198 ** For /file, a name= without a ci= while prefer to use the default
2199 ** "tip" value for ci=. */
2200 rid = name_to_rid(zName);
2201 }
2202 if( rid==0 ){
2203 rid = artifact_from_ci_and_filename(0);
2204 }
2205
2206 if( rid==0 ){ /* Artifact not found */
2207 if( isFile ){
2208 /* For /file, also check to see if name= refers to a directory,
2209 ** and if so, do a listing for that directory */
2210 int nName = (int)strlen(zName);
2211 if( nName && zName[nName-1]=='/' ) nName--;
2212 if( db_exists(
2213 "SELECT 1 FROM filename"
2214 " WHERE name GLOB '%.*q/*' AND substr(name,1,%d)=='%.*q/';",
2215 nName, zName, nName+1, nName, zName
2216 ) ){
2217 if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
2218 page_tree();
2219 return;
2220 }
2221 style_header("No such file");
2222 @ File '%h(zName)' does not exist in this repository.
2223 }else{
2224 style_header("No such artifact");
2225 @ Artifact '%h(zName)' does not exist in this repository.
2226 }
2227 style_footer();
2228 return;
2229 }
2230
2231 if( descOnly || P("verbose")!=0 ){
2232 url_add_parameter(&url, "verbose", "1");
2233 objdescFlags |= OBJDESC_DETAIL;
2234 }
2235 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
2236
2237 asText = P("txt")!=0;
2238 if( isFile ){
2239 if( zCI==0 || fossil_strcmp(zCI,"tip")==0 ){
2240 zCI = "tip";
2241 @ <h2>File %z(href("%R/finfo?name=%T&m=tip",zName))%h(zName)</a>
2242 @ from the %z(href("%R/info/tip"))latest check-in</a></h2>
2243 }else{
2244 const char *zPath;
2245 Blob path;
2246 blob_zero(&path);
2247 hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
2248 zPath = blob_str(&path);
2249 @ <h2>File %s(zPath) \
2250 if( isBranchCI ){
2251 @ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
2252 }else if( isSymbolicCI ){
2253 @ as of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
2254 }else{
2255 @ as of check-in [%z(href("%R/info/%!S",zCIUuid))%S(zCIUuid)</a>]</h2>
2256 }
2257 blob_reset(&path);
2258 }
2259 style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
2260 style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
2261 zName, zCI);
2262 style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
2263 zName, zCI);
2264 blob_init(&downloadName, zName, -1);
2265 objType = OBJTYPE_CONTENT;
2266 }else{
2267 @ <h2>Artifact
2268 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2269 if( g.perm.Setup ){
2270 @ (%d(rid)):</h2>
2271 }else{
2272 @ :</h2>
2273 }
2274 blob_zero(&downloadName);
2275 if( asText ) objdescFlags &= ~OBJDESC_BASE;
2276 objType = object_description(rid, objdescFlags,
2277 (isFile?zName:0), &downloadName);
2278 }
 
 
 
 
2279 if( !descOnly && P("download")!=0 ){
2280 cgi_redirectf("%R/raw/%s?at=%T",
2281 db_text("x", "SELECT uuid FROM blob WHERE rid=%d", rid),
2282 file_tail(blob_str(&downloadName)));
2283 /*NOTREACHED*/
2284 }
2285 if( g.perm.Admin ){
2286 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
2287 if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
@@ -2226,13 +2289,28 @@
2289 g.zTop, zUuid);
2290 }else{
2291 style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
2292 }
2293 }
2294
2295 if( isFile ){
2296 if( isSymbolicCI ){
2297 zHeader = mprintf("%s at %s", file_tail(zName), zCI);
2298 }else if( zCI ){
2299 zHeader = mprintf("%s at [%S]", file_tail(zName), zCIUuid);
2300 }else{
2301 zHeader = mprintf("%s", file_tail(zName));
2302 }
2303 }else if( descOnly ){
2304 zHeader = mprintf("Artifact Description [%S]", zUuid);
2305 }else{
2306 zHeader = mprintf("Artifact [%S]", zUuid);
2307 }
2308 style_header("%s", zHeader);
2309 fossil_free(zCIUuid);
2310 fossil_free(zHeader);
2311 if( !isFile && g.perm.Admin ){
2312 Stmt q;
2313 db_prepare(&q,
2314 "SELECT coalesce(user.login,rcvfrom.uid),"
2315 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
2316 " FROM blob, rcvfrom LEFT JOIN user ON user.uid=rcvfrom.uid"
@@ -2244,12 +2322,11 @@
2322 const char *zIp = db_column_text(&q,2);
2323 @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
2324 }
2325 db_finalize(&q);
2326 }
2327 style_submenu_element("Download", "%R/raw/%s?at=%T", zUuid, file_tail(zName));
 
2328 if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
2329 style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
2330 }
2331 zMime = mimetype_from_name(blob_str(&downloadName));
2332 if( zMime ){
@@ -2279,11 +2356,11 @@
2356 @ <hr />
2357 content_get(rid, &content);
2358 if( renderAsWiki ){
2359 wiki_render_by_mimetype(&content, zMime);
2360 }else if( renderAsHtml ){
2361 @ <iframe src="%R/raw/%s(zUuid)"
2362 @ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
2363 @ sandbox="allow-same-origin" id="ifm1">
2364 @ </iframe>
2365 @ <script nonce="%h(style_nonce())">
2366 @ document.getElementById("ifm1").addEventListener("load",
@@ -2708,15 +2785,15 @@
2785 **
2786 ** Edit a check-in. (Check-ins are immutable and do not really change.
2787 ** This page really creates supplemental tags that affect the display
2788 ** of the check-in.)
2789 **
2790 ** Query parameters:
2791 **
2792 ** rid=INTEGER Record ID of the check-in to edit (REQUIRED)
2793 **
2794 ** POST parameters after pressing "Preview", "Cancel", or "Apply":
2795 **
2796 ** c=TEXT New check-in comment
2797 ** u=TEXT New user name
2798 ** newclr Apply a background color
2799 ** clr=TEXT New background color (only if newclr)
2800
+34 -28
--- src/login.c
+++ src/login.c
@@ -678,20 +678,18 @@
678678
}else{
679679
zAnonPw = 0;
680680
}
681681
@ <table class="login_out">
682682
@ <tr>
683
- @ <td class="form_label">User ID:</td>
684
- if( anonFlag ){
685
- @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
686
- }else{
687
- @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
688
- }
683
+ @ <td class="form_label" id="userlabel1">User ID:</td>
684
+ @ <td><input type="text" id="u" aria-labelledby="userlabel1" name="u" \
685
+ @ size="30" value="%s(anonFlag?"anonymous":"")"></td>
689686
@ </tr>
690687
@ <tr>
691
- @ <td class="form_label">Password:</td>
692
- @ <td><input type="password" id="p" name="p" value="" size="30" />\
688
+ @ <td class="form_label" id="pswdlabel">Password:</td>
689
+ @ <td><input aria-labelledby="pswdlabel" type="password" id="p" \
690
+ @ name="p" value="" size="30" />\
693691
if( zAnonPw && !noAnon ){
694692
captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
695693
}
696694
@ </td>
697695
@ </tr>
@@ -750,16 +748,19 @@
750748
if( g.perm.Password ){
751749
@ <hr>
752750
@ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
753751
form_begin(0, "%R/login");
754752
@ <table>
755
- @ <tr><td class="form_label">Old Password:</td>
756
- @ <td><input type="password" name="p" size="30" /></td></tr>
757
- @ <tr><td class="form_label">New Password:</td>
758
- @ <td><input type="password" name="n1" size="30" /></td></tr>
759
- @ <tr><td class="form_label">Repeat New Password:</td>
760
- @ <td><input type="password" name="n2" size="30" /></td></tr>
753
+ @ <tr><td class="form_label" id="oldpw">Old Password:</td>
754
+ @ <td><input aria-labelledby="oldpw" type="password" name="p" \
755
+ @ size="30"/></td></tr>
756
+ @ <tr><td class="form_label" id="newpw">New Password:</td>
757
+ @ <td><input aria-labelledby="newpw" type="password" name="n1" \
758
+ @ size="30" /></td></tr>
759
+ @ <tr><td class="form_label" id="reppw">Repeat New Password:</td>
760
+ @ <td><input aria-labledby="reppw" type="password" name="n2" \
761
+ @ size="30" /></td></tr>
761762
@ <tr><td></td>
762763
@ <td><input type="submit" value="Change Password" /></td></tr>
763764
@ </table>
764765
@ </form>
765766
}
@@ -1690,57 +1691,62 @@
16901691
@ <input type="hidden" name="g" value="%h(P("g"))" />
16911692
}
16921693
@ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
16931694
@ <table class="login_out">
16941695
@ <tr>
1695
- @ <td class="form_label" align="right">User ID:</td>
1696
- @ <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
1696
+ @ <td class="form_label" align="right" id="uid">User ID:</td>
1697
+ @ <td><input aria-labelledby="uid" type="text" name="u" \
1698
+ @ value="%h(zUserID)" size="30"></td>
16971699
@
16981700
if( iErrLine==1 ){
16991701
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17001702
}
17011703
@ <tr>
1702
- @ <td class="form_label" align="right">Display Name:</td>
1703
- @ <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
1704
+ @ <td class="form_label" align="right" id="dpyname">Display Name:</td>
1705
+ @ <td><input aria-labelledby="dpyname" type="text" name="dn" \
1706
+ @ value="%h(zDName)" size="30"></td>
17041707
@ </tr>
17051708
if( iErrLine==2 ){
17061709
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17071710
}
17081711
@ </tr>
17091712
@ <tr>
1710
- @ <td class="form_label" align="right">Email Address:</td>
1711
- @ <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
1713
+ @ <td class="form_label" align="right" id="emaddr">Email Address:</td>
1714
+ @ <td><input aria-labelledby="emaddr" type="text" name="ea" \
1715
+ @ value="%h(zEAddr)" size="30"></td>
17121716
@ </tr>
17131717
if( iErrLine==3 ){
17141718
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17151719
}
17161720
if( canDoAlerts ){
17171721
int a = atoi(PD("alerts","1"));
17181722
@ <tr>
1719
- @ <td class="form_label" align="right">Email&nbsp;Alerts?</td>
1720
- @ <td><select size='1' name='alerts'>
1723
+ @ <td class="form_label" align="right" id="emalrt">Email&nbsp;Alerts?</td>
1724
+ @ <td><select aria-labelledby="emalrt" size='1' name='alerts'>
17211725
@ <option value="1" %s(a?"selected":"")>Yes</option>
17221726
@ <option value="0" %s(!a?"selected":"")>No</option>
17231727
@ </select></td></tr>
17241728
}
17251729
@ <tr>
1726
- @ <td class="form_label" align="right">Password:</td>
1727
- @ <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
1730
+ @ <td class="form_label" align="right" id="pswd">Password:</td>
1731
+ @ <td><input aria-labelledby="pswd" type="password" name="p" \
1732
+ @ value="%h(zPasswd)" size="30"></td>
17281733
@ <tr>
17291734
if( iErrLine==4 ){
17301735
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17311736
}
17321737
@ <tr>
1733
- @ <td class="form_label" align="right">Confirm:</td>
1734
- @ <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
1738
+ @ <td class="form_label" align="right" id="pwcfrm">Confirm:</td>
1739
+ @ <td><input aria-labelledby="pwcfrm" type="password" name="cp" \
1740
+ @ value="%h(zConfirm)" size="30"></td>
17351741
@ </tr>
17361742
if( iErrLine==5 ){
17371743
@ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
17381744
}
17391745
@ <tr>
1740
- @ <td class="form_label" align="right">Captcha:</td>
1741
- @ <td><input type="text" name="captcha" size="30"\
1746
+ @ <td class="form_label" align="right" id="cptcha">Captcha:</td>
1747
+ @ <td><input type="text" name="captcha" aria-labelledby="cptcha" \
17421748
@ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
17431749
captcha_speakit_button(uSeed, "Speak the captcha text");
17441750
@ </td>
17451751
@ </tr>
17461752
if( iErrLine==6 ){
17471753
--- src/login.c
+++ src/login.c
@@ -678,20 +678,18 @@
678 }else{
679 zAnonPw = 0;
680 }
681 @ <table class="login_out">
682 @ <tr>
683 @ <td class="form_label">User ID:</td>
684 if( anonFlag ){
685 @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
686 }else{
687 @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
688 }
689 @ </tr>
690 @ <tr>
691 @ <td class="form_label">Password:</td>
692 @ <td><input type="password" id="p" name="p" value="" size="30" />\
 
693 if( zAnonPw && !noAnon ){
694 captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
695 }
696 @ </td>
697 @ </tr>
@@ -750,16 +748,19 @@
750 if( g.perm.Password ){
751 @ <hr>
752 @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
753 form_begin(0, "%R/login");
754 @ <table>
755 @ <tr><td class="form_label">Old Password:</td>
756 @ <td><input type="password" name="p" size="30" /></td></tr>
757 @ <tr><td class="form_label">New Password:</td>
758 @ <td><input type="password" name="n1" size="30" /></td></tr>
759 @ <tr><td class="form_label">Repeat New Password:</td>
760 @ <td><input type="password" name="n2" size="30" /></td></tr>
 
 
 
761 @ <tr><td></td>
762 @ <td><input type="submit" value="Change Password" /></td></tr>
763 @ </table>
764 @ </form>
765 }
@@ -1690,57 +1691,62 @@
1690 @ <input type="hidden" name="g" value="%h(P("g"))" />
1691 }
1692 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1693 @ <table class="login_out">
1694 @ <tr>
1695 @ <td class="form_label" align="right">User ID:</td>
1696 @ <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
 
1697 @
1698 if( iErrLine==1 ){
1699 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1700 }
1701 @ <tr>
1702 @ <td class="form_label" align="right">Display Name:</td>
1703 @ <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
 
1704 @ </tr>
1705 if( iErrLine==2 ){
1706 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1707 }
1708 @ </tr>
1709 @ <tr>
1710 @ <td class="form_label" align="right">Email Address:</td>
1711 @ <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
 
1712 @ </tr>
1713 if( iErrLine==3 ){
1714 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1715 }
1716 if( canDoAlerts ){
1717 int a = atoi(PD("alerts","1"));
1718 @ <tr>
1719 @ <td class="form_label" align="right">Email&nbsp;Alerts?</td>
1720 @ <td><select size='1' name='alerts'>
1721 @ <option value="1" %s(a?"selected":"")>Yes</option>
1722 @ <option value="0" %s(!a?"selected":"")>No</option>
1723 @ </select></td></tr>
1724 }
1725 @ <tr>
1726 @ <td class="form_label" align="right">Password:</td>
1727 @ <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
 
1728 @ <tr>
1729 if( iErrLine==4 ){
1730 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1731 }
1732 @ <tr>
1733 @ <td class="form_label" align="right">Confirm:</td>
1734 @ <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
 
1735 @ </tr>
1736 if( iErrLine==5 ){
1737 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1738 }
1739 @ <tr>
1740 @ <td class="form_label" align="right">Captcha:</td>
1741 @ <td><input type="text" name="captcha" size="30"\
1742 @ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
1743 captcha_speakit_button(uSeed, "Speak the captcha text");
1744 @ </td>
1745 @ </tr>
1746 if( iErrLine==6 ){
1747
--- src/login.c
+++ src/login.c
@@ -678,20 +678,18 @@
678 }else{
679 zAnonPw = 0;
680 }
681 @ <table class="login_out">
682 @ <tr>
683 @ <td class="form_label" id="userlabel1">User ID:</td>
684 @ <td><input type="text" id="u" aria-labelledby="userlabel1" name="u" \
685 @ size="30" value="%s(anonFlag?"anonymous":"")"></td>
 
 
 
686 @ </tr>
687 @ <tr>
688 @ <td class="form_label" id="pswdlabel">Password:</td>
689 @ <td><input aria-labelledby="pswdlabel" type="password" id="p" \
690 @ name="p" value="" size="30" />\
691 if( zAnonPw && !noAnon ){
692 captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
693 }
694 @ </td>
695 @ </tr>
@@ -750,16 +748,19 @@
748 if( g.perm.Password ){
749 @ <hr>
750 @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
751 form_begin(0, "%R/login");
752 @ <table>
753 @ <tr><td class="form_label" id="oldpw">Old Password:</td>
754 @ <td><input aria-labelledby="oldpw" type="password" name="p" \
755 @ size="30"/></td></tr>
756 @ <tr><td class="form_label" id="newpw">New Password:</td>
757 @ <td><input aria-labelledby="newpw" type="password" name="n1" \
758 @ size="30" /></td></tr>
759 @ <tr><td class="form_label" id="reppw">Repeat New Password:</td>
760 @ <td><input aria-labledby="reppw" type="password" name="n2" \
761 @ size="30" /></td></tr>
762 @ <tr><td></td>
763 @ <td><input type="submit" value="Change Password" /></td></tr>
764 @ </table>
765 @ </form>
766 }
@@ -1690,57 +1691,62 @@
1691 @ <input type="hidden" name="g" value="%h(P("g"))" />
1692 }
1693 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1694 @ <table class="login_out">
1695 @ <tr>
1696 @ <td class="form_label" align="right" id="uid">User ID:</td>
1697 @ <td><input aria-labelledby="uid" type="text" name="u" \
1698 @ value="%h(zUserID)" size="30"></td>
1699 @
1700 if( iErrLine==1 ){
1701 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1702 }
1703 @ <tr>
1704 @ <td class="form_label" align="right" id="dpyname">Display Name:</td>
1705 @ <td><input aria-labelledby="dpyname" type="text" name="dn" \
1706 @ value="%h(zDName)" size="30"></td>
1707 @ </tr>
1708 if( iErrLine==2 ){
1709 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1710 }
1711 @ </tr>
1712 @ <tr>
1713 @ <td class="form_label" align="right" id="emaddr">Email Address:</td>
1714 @ <td><input aria-labelledby="emaddr" type="text" name="ea" \
1715 @ value="%h(zEAddr)" size="30"></td>
1716 @ </tr>
1717 if( iErrLine==3 ){
1718 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1719 }
1720 if( canDoAlerts ){
1721 int a = atoi(PD("alerts","1"));
1722 @ <tr>
1723 @ <td class="form_label" align="right" id="emalrt">Email&nbsp;Alerts?</td>
1724 @ <td><select aria-labelledby="emalrt" size='1' name='alerts'>
1725 @ <option value="1" %s(a?"selected":"")>Yes</option>
1726 @ <option value="0" %s(!a?"selected":"")>No</option>
1727 @ </select></td></tr>
1728 }
1729 @ <tr>
1730 @ <td class="form_label" align="right" id="pswd">Password:</td>
1731 @ <td><input aria-labelledby="pswd" type="password" name="p" \
1732 @ value="%h(zPasswd)" size="30"></td>
1733 @ <tr>
1734 if( iErrLine==4 ){
1735 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1736 }
1737 @ <tr>
1738 @ <td class="form_label" align="right" id="pwcfrm">Confirm:</td>
1739 @ <td><input aria-labelledby="pwcfrm" type="password" name="cp" \
1740 @ value="%h(zConfirm)" size="30"></td>
1741 @ </tr>
1742 if( iErrLine==5 ){
1743 @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
1744 }
1745 @ <tr>
1746 @ <td class="form_label" align="right" id="cptcha">Captcha:</td>
1747 @ <td><input type="text" name="captcha" aria-labelledby="cptcha" \
1748 @ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
1749 captcha_speakit_button(uSeed, "Speak the captcha text");
1750 @ </td>
1751 @ </tr>
1752 if( iErrLine==6 ){
1753
+12
--- src/main.mk
+++ src/main.mk
@@ -131,10 +131,11 @@
131131
$(SRCDIR)/statrep.c \
132132
$(SRCDIR)/style.c \
133133
$(SRCDIR)/sync.c \
134134
$(SRCDIR)/tag.c \
135135
$(SRCDIR)/tar.c \
136
+ $(SRCDIR)/terminal.c \
136137
$(SRCDIR)/th_main.c \
137138
$(SRCDIR)/timeline.c \
138139
$(SRCDIR)/tkt.c \
139140
$(SRCDIR)/tktsetup.c \
140141
$(SRCDIR)/undo.c \
@@ -365,10 +366,11 @@
365366
$(OBJDIR)/statrep_.c \
366367
$(OBJDIR)/style_.c \
367368
$(OBJDIR)/sync_.c \
368369
$(OBJDIR)/tag_.c \
369370
$(OBJDIR)/tar_.c \
371
+ $(OBJDIR)/terminal_.c \
370372
$(OBJDIR)/th_main_.c \
371373
$(OBJDIR)/timeline_.c \
372374
$(OBJDIR)/tkt_.c \
373375
$(OBJDIR)/tktsetup_.c \
374376
$(OBJDIR)/undo_.c \
@@ -507,10 +509,11 @@
507509
$(OBJDIR)/statrep.o \
508510
$(OBJDIR)/style.o \
509511
$(OBJDIR)/sync.o \
510512
$(OBJDIR)/tag.o \
511513
$(OBJDIR)/tar.o \
514
+ $(OBJDIR)/terminal.o \
512515
$(OBJDIR)/th_main.o \
513516
$(OBJDIR)/timeline.o \
514517
$(OBJDIR)/tkt.o \
515518
$(OBJDIR)/tktsetup.o \
516519
$(OBJDIR)/undo.o \
@@ -844,10 +847,11 @@
844847
$(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
845848
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
846849
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
847850
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
848851
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
852
+ $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
849853
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
850854
$(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
851855
$(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
852856
$(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
853857
$(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -1809,10 +1813,18 @@
18091813
18101814
$(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
18111815
$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
18121816
18131817
$(OBJDIR)/tar.h: $(OBJDIR)/headers
1818
+
1819
+$(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(OBJDIR)/translate
1820
+ $(OBJDIR)/translate $(SRCDIR)/terminal.c >$@
1821
+
1822
+$(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
1823
+ $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
1824
+
1825
+$(OBJDIR)/terminal.h: $(OBJDIR)/headers
18141826
18151827
$(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(OBJDIR)/translate
18161828
$(OBJDIR)/translate $(SRCDIR)/th_main.c >$@
18171829
18181830
$(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
18191831
--- src/main.mk
+++ src/main.mk
@@ -131,10 +131,11 @@
131 $(SRCDIR)/statrep.c \
132 $(SRCDIR)/style.c \
133 $(SRCDIR)/sync.c \
134 $(SRCDIR)/tag.c \
135 $(SRCDIR)/tar.c \
 
136 $(SRCDIR)/th_main.c \
137 $(SRCDIR)/timeline.c \
138 $(SRCDIR)/tkt.c \
139 $(SRCDIR)/tktsetup.c \
140 $(SRCDIR)/undo.c \
@@ -365,10 +366,11 @@
365 $(OBJDIR)/statrep_.c \
366 $(OBJDIR)/style_.c \
367 $(OBJDIR)/sync_.c \
368 $(OBJDIR)/tag_.c \
369 $(OBJDIR)/tar_.c \
 
370 $(OBJDIR)/th_main_.c \
371 $(OBJDIR)/timeline_.c \
372 $(OBJDIR)/tkt_.c \
373 $(OBJDIR)/tktsetup_.c \
374 $(OBJDIR)/undo_.c \
@@ -507,10 +509,11 @@
507 $(OBJDIR)/statrep.o \
508 $(OBJDIR)/style.o \
509 $(OBJDIR)/sync.o \
510 $(OBJDIR)/tag.o \
511 $(OBJDIR)/tar.o \
 
512 $(OBJDIR)/th_main.o \
513 $(OBJDIR)/timeline.o \
514 $(OBJDIR)/tkt.o \
515 $(OBJDIR)/tktsetup.o \
516 $(OBJDIR)/undo.o \
@@ -844,10 +847,11 @@
844 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
845 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
846 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
847 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
848 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
 
849 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
850 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
851 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
852 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
853 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -1809,10 +1813,18 @@
1809
1810 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
1811 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
1812
1813 $(OBJDIR)/tar.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1814
1815 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(OBJDIR)/translate
1816 $(OBJDIR)/translate $(SRCDIR)/th_main.c >$@
1817
1818 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
1819
--- src/main.mk
+++ src/main.mk
@@ -131,10 +131,11 @@
131 $(SRCDIR)/statrep.c \
132 $(SRCDIR)/style.c \
133 $(SRCDIR)/sync.c \
134 $(SRCDIR)/tag.c \
135 $(SRCDIR)/tar.c \
136 $(SRCDIR)/terminal.c \
137 $(SRCDIR)/th_main.c \
138 $(SRCDIR)/timeline.c \
139 $(SRCDIR)/tkt.c \
140 $(SRCDIR)/tktsetup.c \
141 $(SRCDIR)/undo.c \
@@ -365,10 +366,11 @@
366 $(OBJDIR)/statrep_.c \
367 $(OBJDIR)/style_.c \
368 $(OBJDIR)/sync_.c \
369 $(OBJDIR)/tag_.c \
370 $(OBJDIR)/tar_.c \
371 $(OBJDIR)/terminal_.c \
372 $(OBJDIR)/th_main_.c \
373 $(OBJDIR)/timeline_.c \
374 $(OBJDIR)/tkt_.c \
375 $(OBJDIR)/tktsetup_.c \
376 $(OBJDIR)/undo_.c \
@@ -507,10 +509,11 @@
509 $(OBJDIR)/statrep.o \
510 $(OBJDIR)/style.o \
511 $(OBJDIR)/sync.o \
512 $(OBJDIR)/tag.o \
513 $(OBJDIR)/tar.o \
514 $(OBJDIR)/terminal.o \
515 $(OBJDIR)/th_main.o \
516 $(OBJDIR)/timeline.o \
517 $(OBJDIR)/tkt.o \
518 $(OBJDIR)/tktsetup.o \
519 $(OBJDIR)/undo.o \
@@ -844,10 +847,11 @@
847 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
848 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
849 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
850 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
851 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
852 $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
853 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
854 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
855 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
856 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
857 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -1809,10 +1813,18 @@
1813
1814 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
1815 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
1816
1817 $(OBJDIR)/tar.h: $(OBJDIR)/headers
1818
1819 $(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(OBJDIR)/translate
1820 $(OBJDIR)/translate $(SRCDIR)/terminal.c >$@
1821
1822 $(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
1823 $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
1824
1825 $(OBJDIR)/terminal.h: $(OBJDIR)/headers
1826
1827 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(OBJDIR)/translate
1828 $(OBJDIR)/translate $(SRCDIR)/th_main.c >$@
1829
1830 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
1831
+12
--- src/main.mk
+++ src/main.mk
@@ -131,10 +131,11 @@
131131
$(SRCDIR)/statrep.c \
132132
$(SRCDIR)/style.c \
133133
$(SRCDIR)/sync.c \
134134
$(SRCDIR)/tag.c \
135135
$(SRCDIR)/tar.c \
136
+ $(SRCDIR)/terminal.c \
136137
$(SRCDIR)/th_main.c \
137138
$(SRCDIR)/timeline.c \
138139
$(SRCDIR)/tkt.c \
139140
$(SRCDIR)/tktsetup.c \
140141
$(SRCDIR)/undo.c \
@@ -365,10 +366,11 @@
365366
$(OBJDIR)/statrep_.c \
366367
$(OBJDIR)/style_.c \
367368
$(OBJDIR)/sync_.c \
368369
$(OBJDIR)/tag_.c \
369370
$(OBJDIR)/tar_.c \
371
+ $(OBJDIR)/terminal_.c \
370372
$(OBJDIR)/th_main_.c \
371373
$(OBJDIR)/timeline_.c \
372374
$(OBJDIR)/tkt_.c \
373375
$(OBJDIR)/tktsetup_.c \
374376
$(OBJDIR)/undo_.c \
@@ -507,10 +509,11 @@
507509
$(OBJDIR)/statrep.o \
508510
$(OBJDIR)/style.o \
509511
$(OBJDIR)/sync.o \
510512
$(OBJDIR)/tag.o \
511513
$(OBJDIR)/tar.o \
514
+ $(OBJDIR)/terminal.o \
512515
$(OBJDIR)/th_main.o \
513516
$(OBJDIR)/timeline.o \
514517
$(OBJDIR)/tkt.o \
515518
$(OBJDIR)/tktsetup.o \
516519
$(OBJDIR)/undo.o \
@@ -844,10 +847,11 @@
844847
$(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
845848
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
846849
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
847850
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
848851
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
852
+ $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
849853
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
850854
$(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
851855
$(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
852856
$(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
853857
$(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -1809,10 +1813,18 @@
18091813
18101814
$(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
18111815
$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
18121816
18131817
$(OBJDIR)/tar.h: $(OBJDIR)/headers
1818
+
1819
+$(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(OBJDIR)/translate
1820
+ $(OBJDIR)/translate $(SRCDIR)/terminal.c >$@
1821
+
1822
+$(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
1823
+ $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
1824
+
1825
+$(OBJDIR)/terminal.h: $(OBJDIR)/headers
18141826
18151827
$(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(OBJDIR)/translate
18161828
$(OBJDIR)/translate $(SRCDIR)/th_main.c >$@
18171829
18181830
$(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
18191831
--- src/main.mk
+++ src/main.mk
@@ -131,10 +131,11 @@
131 $(SRCDIR)/statrep.c \
132 $(SRCDIR)/style.c \
133 $(SRCDIR)/sync.c \
134 $(SRCDIR)/tag.c \
135 $(SRCDIR)/tar.c \
 
136 $(SRCDIR)/th_main.c \
137 $(SRCDIR)/timeline.c \
138 $(SRCDIR)/tkt.c \
139 $(SRCDIR)/tktsetup.c \
140 $(SRCDIR)/undo.c \
@@ -365,10 +366,11 @@
365 $(OBJDIR)/statrep_.c \
366 $(OBJDIR)/style_.c \
367 $(OBJDIR)/sync_.c \
368 $(OBJDIR)/tag_.c \
369 $(OBJDIR)/tar_.c \
 
370 $(OBJDIR)/th_main_.c \
371 $(OBJDIR)/timeline_.c \
372 $(OBJDIR)/tkt_.c \
373 $(OBJDIR)/tktsetup_.c \
374 $(OBJDIR)/undo_.c \
@@ -507,10 +509,11 @@
507 $(OBJDIR)/statrep.o \
508 $(OBJDIR)/style.o \
509 $(OBJDIR)/sync.o \
510 $(OBJDIR)/tag.o \
511 $(OBJDIR)/tar.o \
 
512 $(OBJDIR)/th_main.o \
513 $(OBJDIR)/timeline.o \
514 $(OBJDIR)/tkt.o \
515 $(OBJDIR)/tktsetup.o \
516 $(OBJDIR)/undo.o \
@@ -844,10 +847,11 @@
844 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
845 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
846 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
847 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
848 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
 
849 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
850 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
851 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
852 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
853 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -1809,10 +1813,18 @@
1809
1810 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
1811 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
1812
1813 $(OBJDIR)/tar.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1814
1815 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(OBJDIR)/translate
1816 $(OBJDIR)/translate $(SRCDIR)/th_main.c >$@
1817
1818 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
1819
--- src/main.mk
+++ src/main.mk
@@ -131,10 +131,11 @@
131 $(SRCDIR)/statrep.c \
132 $(SRCDIR)/style.c \
133 $(SRCDIR)/sync.c \
134 $(SRCDIR)/tag.c \
135 $(SRCDIR)/tar.c \
136 $(SRCDIR)/terminal.c \
137 $(SRCDIR)/th_main.c \
138 $(SRCDIR)/timeline.c \
139 $(SRCDIR)/tkt.c \
140 $(SRCDIR)/tktsetup.c \
141 $(SRCDIR)/undo.c \
@@ -365,10 +366,11 @@
366 $(OBJDIR)/statrep_.c \
367 $(OBJDIR)/style_.c \
368 $(OBJDIR)/sync_.c \
369 $(OBJDIR)/tag_.c \
370 $(OBJDIR)/tar_.c \
371 $(OBJDIR)/terminal_.c \
372 $(OBJDIR)/th_main_.c \
373 $(OBJDIR)/timeline_.c \
374 $(OBJDIR)/tkt_.c \
375 $(OBJDIR)/tktsetup_.c \
376 $(OBJDIR)/undo_.c \
@@ -507,10 +509,11 @@
509 $(OBJDIR)/statrep.o \
510 $(OBJDIR)/style.o \
511 $(OBJDIR)/sync.o \
512 $(OBJDIR)/tag.o \
513 $(OBJDIR)/tar.o \
514 $(OBJDIR)/terminal.o \
515 $(OBJDIR)/th_main.o \
516 $(OBJDIR)/timeline.o \
517 $(OBJDIR)/tkt.o \
518 $(OBJDIR)/tktsetup.o \
519 $(OBJDIR)/undo.o \
@@ -844,10 +847,11 @@
847 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
848 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
849 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
850 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
851 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
852 $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
853 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
854 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
855 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
856 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
857 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -1809,10 +1813,18 @@
1813
1814 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
1815 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
1816
1817 $(OBJDIR)/tar.h: $(OBJDIR)/headers
1818
1819 $(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(OBJDIR)/translate
1820 $(OBJDIR)/translate $(SRCDIR)/terminal.c >$@
1821
1822 $(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
1823 $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
1824
1825 $(OBJDIR)/terminal.h: $(OBJDIR)/headers
1826
1827 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(OBJDIR)/translate
1828 $(OBJDIR)/translate $(SRCDIR)/th_main.c >$@
1829
1830 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
1831
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -141,10 +141,11 @@
141141
statrep
142142
style
143143
sync
144144
tag
145145
tar
146
+ terminal
146147
th_main
147148
timeline
148149
tkt
149150
tktsetup
150151
undo
151152
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -141,10 +141,11 @@
141 statrep
142 style
143 sync
144 tag
145 tar
 
146 th_main
147 timeline
148 tkt
149 tktsetup
150 undo
151
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -141,10 +141,11 @@
141 statrep
142 style
143 sync
144 tag
145 tar
146 terminal
147 th_main
148 timeline
149 tkt
150 tktsetup
151 undo
152
+1 -1
--- src/merge3.c
+++ src/merge3.c
@@ -139,11 +139,11 @@
139139
** Text of boundary markers for merge conflicts.
140140
*/
141141
static const char *const mergeMarker[] = {
142142
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143143
"<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144
- "======= COMMON ANCESTOR content follows ============================\n",
144
+ "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||\n",
145145
"======= MERGED IN content follows ==================================\n",
146146
">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147147
};
148148
149149
150150
--- src/merge3.c
+++ src/merge3.c
@@ -139,11 +139,11 @@
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "======= COMMON ANCESTOR content follows ============================\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147 };
148
149
150
--- src/merge3.c
+++ src/merge3.c
@@ -139,11 +139,11 @@
139 ** Text of boundary markers for merge conflicts.
140 */
141 static const char *const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "||||||| COMMON ANCESTOR content follows ||||||||||||||||||||||||||||\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147 };
148
149
150
--- src/mkversion.c
+++ src/mkversion.c
@@ -9,27 +9,59 @@
99
*/
1010
#include <stdio.h>
1111
#include <string.h>
1212
#include <stdlib.h>
1313
#include <ctype.h>
14
+#include <time.h>
1415
1516
static FILE *open_for_reading(const char *zFilename){
1617
FILE *f = fopen(zFilename, "r");
1718
if( f==0 ){
1819
fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
1920
exit(1);
2021
}
2122
return f;
2223
}
24
+
25
+/*
26
+** Given an arbitrary-length input string key zIn, generate
27
+** an N-byte hexadecimal hash of that string into zOut.
28
+*/
29
+static void hash(const char *zIn, int N, char *zOut){
30
+ unsigned char i, j, t;
31
+ int m, n;
32
+ unsigned char s[256];
33
+ for(m=0; m<256; m++){ s[m] = m; }
34
+ for(j=0, m=n=0; m<256; m++, n++){
35
+ j += s[m] + zIn[n];
36
+ if( zIn[n]==0 ){ n = -1; }
37
+ t = s[j];
38
+ s[j] = s[m];
39
+ s[m] = t;
40
+ }
41
+ i = j = 0;
42
+ for(n=0; n<N-2; n+=2){
43
+ i++;
44
+ t = s[i];
45
+ j += t;
46
+ s[i] = s[j];
47
+ s[j] = t;
48
+ t += s[i];
49
+ zOut[n] = "0123456789abcdef"[(t>>4)&0xf];
50
+ zOut[n+1] = "0123456789abcdef"[t&0xf];
51
+ }
52
+ zOut[n] = 0;
53
+}
2354
2455
int main(int argc, char *argv[]){
2556
FILE *m,*u,*v;
2657
char *z;
2758
#if defined(__DMC__) /* e.g. 0x857 */
2859
int i = 0;
2960
#endif
3061
int j = 0, x = 0, d = 0;
62
+ size_t n;
3163
int vn[3];
3264
char b[1000];
3365
char vx[1000];
3466
if( argc!=4 ){
3567
fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]);
@@ -45,10 +77,16 @@
4577
fclose(u);
4678
for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
4779
*z = 0;
4880
printf("#define MANIFEST_UUID \"%s\"\n",b);
4981
printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b);
82
+ n = strlen(b);
83
+ if( n + 50 < sizeof(b) ){
84
+ sprintf(b+n, "%d", (int)time(0));
85
+ hash(b,33,vx);
86
+ printf("#define FOSSIL_BUILD_HASH \"%s\"\n", vx);
87
+ }
5088
m = open_for_reading(argv[2]);
5189
while(b == fgets(b, sizeof(b)-1,m)){
5290
if(0 == strncmp("D ",b,2)){
5391
int k, n;
5492
char zDateNum[30];
5593
--- src/mkversion.c
+++ src/mkversion.c
@@ -9,27 +9,59 @@
9 */
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <ctype.h>
 
14
15 static FILE *open_for_reading(const char *zFilename){
16 FILE *f = fopen(zFilename, "r");
17 if( f==0 ){
18 fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
19 exit(1);
20 }
21 return f;
22 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24 int main(int argc, char *argv[]){
25 FILE *m,*u,*v;
26 char *z;
27 #if defined(__DMC__) /* e.g. 0x857 */
28 int i = 0;
29 #endif
30 int j = 0, x = 0, d = 0;
 
31 int vn[3];
32 char b[1000];
33 char vx[1000];
34 if( argc!=4 ){
35 fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]);
@@ -45,10 +77,16 @@
45 fclose(u);
46 for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
47 *z = 0;
48 printf("#define MANIFEST_UUID \"%s\"\n",b);
49 printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b);
 
 
 
 
 
 
50 m = open_for_reading(argv[2]);
51 while(b == fgets(b, sizeof(b)-1,m)){
52 if(0 == strncmp("D ",b,2)){
53 int k, n;
54 char zDateNum[30];
55
--- src/mkversion.c
+++ src/mkversion.c
@@ -9,27 +9,59 @@
9 */
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14 #include <time.h>
15
16 static FILE *open_for_reading(const char *zFilename){
17 FILE *f = fopen(zFilename, "r");
18 if( f==0 ){
19 fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
20 exit(1);
21 }
22 return f;
23 }
24
25 /*
26 ** Given an arbitrary-length input string key zIn, generate
27 ** an N-byte hexadecimal hash of that string into zOut.
28 */
29 static void hash(const char *zIn, int N, char *zOut){
30 unsigned char i, j, t;
31 int m, n;
32 unsigned char s[256];
33 for(m=0; m<256; m++){ s[m] = m; }
34 for(j=0, m=n=0; m<256; m++, n++){
35 j += s[m] + zIn[n];
36 if( zIn[n]==0 ){ n = -1; }
37 t = s[j];
38 s[j] = s[m];
39 s[m] = t;
40 }
41 i = j = 0;
42 for(n=0; n<N-2; n+=2){
43 i++;
44 t = s[i];
45 j += t;
46 s[i] = s[j];
47 s[j] = t;
48 t += s[i];
49 zOut[n] = "0123456789abcdef"[(t>>4)&0xf];
50 zOut[n+1] = "0123456789abcdef"[t&0xf];
51 }
52 zOut[n] = 0;
53 }
54
55 int main(int argc, char *argv[]){
56 FILE *m,*u,*v;
57 char *z;
58 #if defined(__DMC__) /* e.g. 0x857 */
59 int i = 0;
60 #endif
61 int j = 0, x = 0, d = 0;
62 size_t n;
63 int vn[3];
64 char b[1000];
65 char vx[1000];
66 if( argc!=4 ){
67 fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]);
@@ -45,10 +77,16 @@
77 fclose(u);
78 for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
79 *z = 0;
80 printf("#define MANIFEST_UUID \"%s\"\n",b);
81 printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b);
82 n = strlen(b);
83 if( n + 50 < sizeof(b) ){
84 sprintf(b+n, "%d", (int)time(0));
85 hash(b,33,vx);
86 printf("#define FOSSIL_BUILD_HASH \"%s\"\n", vx);
87 }
88 m = open_for_reading(argv[2]);
89 while(b == fgets(b, sizeof(b)-1,m)){
90 if(0 == strncmp("D ",b,2)){
91 int k, n;
92 char zDateNum[30];
93
+3 -3
--- src/name.c
+++ src/name.c
@@ -614,11 +614,11 @@
614614
while( db_step(&q)==SQLITE_ROW ){
615615
const char *zUuid = db_column_text(&q, 0);
616616
int rid = db_column_int(&q, 1);
617617
@ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
618618
@ %s(zUuid)</a> -
619
- object_description(rid, 0, 0);
619
+ object_description(rid, 0, 0, 0);
620620
@ </p></li>
621621
}
622622
db_finalize(&q);
623623
db_prepare(&q,
624624
" SELECT tkt_rid, tkt_uuid, title"
@@ -636,11 +636,11 @@
636636
@ <ul></ul>
637637
@ Ticket
638638
hyperlink_to_uuid(zUuid);
639639
@ - %h(zTitle).
640640
@ <ul><li>
641
- object_description(rid, 0, 0);
641
+ object_description(rid, 0, 0, 0);
642642
@ </li></ul>
643643
@ </p></li>
644644
}
645645
db_finalize(&q);
646646
db_prepare(&q,
@@ -652,11 +652,11 @@
652652
int rid = db_column_int(&q, 0);
653653
const char* zUuid = db_column_text(&q, 1);
654654
@ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
655655
@ %s(zUuid)</a> -
656656
@ <ul><li>
657
- object_description(rid, 0, 0);
657
+ object_description(rid, 0, 0, 0);
658658
@ </li></ul>
659659
@ </p></li>
660660
}
661661
@ </ol>
662662
db_finalize(&q);
663663
--- src/name.c
+++ src/name.c
@@ -614,11 +614,11 @@
614 while( db_step(&q)==SQLITE_ROW ){
615 const char *zUuid = db_column_text(&q, 0);
616 int rid = db_column_int(&q, 1);
617 @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
618 @ %s(zUuid)</a> -
619 object_description(rid, 0, 0);
620 @ </p></li>
621 }
622 db_finalize(&q);
623 db_prepare(&q,
624 " SELECT tkt_rid, tkt_uuid, title"
@@ -636,11 +636,11 @@
636 @ <ul></ul>
637 @ Ticket
638 hyperlink_to_uuid(zUuid);
639 @ - %h(zTitle).
640 @ <ul><li>
641 object_description(rid, 0, 0);
642 @ </li></ul>
643 @ </p></li>
644 }
645 db_finalize(&q);
646 db_prepare(&q,
@@ -652,11 +652,11 @@
652 int rid = db_column_int(&q, 0);
653 const char* zUuid = db_column_text(&q, 1);
654 @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
655 @ %s(zUuid)</a> -
656 @ <ul><li>
657 object_description(rid, 0, 0);
658 @ </li></ul>
659 @ </p></li>
660 }
661 @ </ol>
662 db_finalize(&q);
663
--- src/name.c
+++ src/name.c
@@ -614,11 +614,11 @@
614 while( db_step(&q)==SQLITE_ROW ){
615 const char *zUuid = db_column_text(&q, 0);
616 int rid = db_column_int(&q, 1);
617 @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
618 @ %s(zUuid)</a> -
619 object_description(rid, 0, 0, 0);
620 @ </p></li>
621 }
622 db_finalize(&q);
623 db_prepare(&q,
624 " SELECT tkt_rid, tkt_uuid, title"
@@ -636,11 +636,11 @@
636 @ <ul></ul>
637 @ Ticket
638 hyperlink_to_uuid(zUuid);
639 @ - %h(zTitle).
640 @ <ul><li>
641 object_description(rid, 0, 0, 0);
642 @ </li></ul>
643 @ </p></li>
644 }
645 db_finalize(&q);
646 db_prepare(&q,
@@ -652,11 +652,11 @@
652 int rid = db_column_int(&q, 0);
653 const char* zUuid = db_column_text(&q, 1);
654 @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
655 @ %s(zUuid)</a> -
656 @ <ul><li>
657 object_description(rid, 0, 0, 0);
658 @ </li></ul>
659 @ </p></li>
660 }
661 @ </ol>
662 db_finalize(&q);
663
+3 -3
--- src/printf.c
+++ src/printf.c
@@ -34,11 +34,11 @@
3434
** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
3535
** is the default number of digits to display to humans. This value can
3636
** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
3737
** is the minimum number of digits to be used in URLs. The number used
3838
** will always be at least 6 more than the number used for human output,
39
-** or 40 if the number of digits in human output is 34 or more.
39
+** or HNAME_MAX, whichever is least.
4040
*/
4141
#ifndef FOSSIL_HASH_DIGITS
4242
# define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
4343
#endif
4444
#ifndef FOSSIL_HASH_DIGITS_URL
@@ -54,14 +54,14 @@
5454
static int nDigitHuman = 0;
5555
static int nDigitUrl = 0;
5656
if( nDigitHuman==0 ){
5757
nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
5858
if( nDigitHuman < 6 ) nDigitHuman = 6;
59
- if( nDigitHuman > 40 ) nDigitHuman = 40;
59
+ if( nDigitHuman > HNAME_MAX ) nDigitHuman = HNAME_MAX;
6060
nDigitUrl = nDigitHuman + 6;
6161
if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62
- if( nDigitUrl > 40 ) nDigitUrl = 40;
62
+ if( nDigitUrl > HNAME_MAX ) nDigitUrl = HNAME_MAX;
6363
}
6464
return bForUrl ? nDigitUrl : nDigitHuman;
6565
}
6666
6767
/*
6868
--- src/printf.c
+++ src/printf.c
@@ -34,11 +34,11 @@
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
35 ** is the default number of digits to display to humans. This value can
36 ** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
37 ** is the minimum number of digits to be used in URLs. The number used
38 ** will always be at least 6 more than the number used for human output,
39 ** or 40 if the number of digits in human output is 34 or more.
40 */
41 #ifndef FOSSIL_HASH_DIGITS
42 # define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
43 #endif
44 #ifndef FOSSIL_HASH_DIGITS_URL
@@ -54,14 +54,14 @@
54 static int nDigitHuman = 0;
55 static int nDigitUrl = 0;
56 if( nDigitHuman==0 ){
57 nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
58 if( nDigitHuman < 6 ) nDigitHuman = 6;
59 if( nDigitHuman > 40 ) nDigitHuman = 40;
60 nDigitUrl = nDigitHuman + 6;
61 if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62 if( nDigitUrl > 40 ) nDigitUrl = 40;
63 }
64 return bForUrl ? nDigitUrl : nDigitHuman;
65 }
66
67 /*
68
--- src/printf.c
+++ src/printf.c
@@ -34,11 +34,11 @@
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
35 ** is the default number of digits to display to humans. This value can
36 ** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
37 ** is the minimum number of digits to be used in URLs. The number used
38 ** will always be at least 6 more than the number used for human output,
39 ** or HNAME_MAX, whichever is least.
40 */
41 #ifndef FOSSIL_HASH_DIGITS
42 # define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
43 #endif
44 #ifndef FOSSIL_HASH_DIGITS_URL
@@ -54,14 +54,14 @@
54 static int nDigitHuman = 0;
55 static int nDigitUrl = 0;
56 if( nDigitHuman==0 ){
57 nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
58 if( nDigitHuman < 6 ) nDigitHuman = 6;
59 if( nDigitHuman > HNAME_MAX ) nDigitHuman = HNAME_MAX;
60 nDigitUrl = nDigitHuman + 6;
61 if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62 if( nDigitUrl > HNAME_MAX ) nDigitUrl = HNAME_MAX;
63 }
64 return bForUrl ? nDigitUrl : nDigitHuman;
65 }
66
67 /*
68
+43 -31
--- src/setup.c
+++ src/setup.c
@@ -201,16 +201,17 @@
201201
admin_log("Set option [%q] to [%q].",
202202
zVar, iQ ? "on" : "off");
203203
iVal = iQ;
204204
}
205205
}
206
- @ <label><input type="checkbox" name="%s(zQParm)"
206
+ @ <label><input type="checkbox" name="%s(zQParm)" \
207
+ @ aria-label="%s(zLabel[0]?zLabel:zQParm)" \
207208
if( iVal ){
208
- @ checked="checked"
209
+ @ checked="checked" \
209210
}
210211
if( disabled ){
211
- @ disabled="disabled"
212
+ @ disabled="disabled" \
212213
}
213214
@ /> <b>%s(zLabel)</b></label>
214215
}
215216
216217
/*
@@ -232,12 +233,12 @@
232233
db_set(zVar, zQ, 0);
233234
admin_log("Set entry_attribute %Q to: %.*s%s",
234235
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
235236
zVal = zQ;
236237
}
237
- @ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" \
238
- @ size="%d(width)" \
238
+ @ <input aria-label="%h(zLabel[0]?zLabel:zQParm)" type="text" \
239
+ @ id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" \
239240
if( disabled ){
240241
@ disabled="disabled" \
241242
}
242243
@ /> <b>%s(zLabel)</b>
243244
}
@@ -263,16 +264,17 @@
263264
admin_log("Set textarea_attribute %Q to: %.*s%s",
264265
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
265266
z = zQ;
266267
}
267268
if( rows>0 && cols>0 ){
268
- @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"
269
+ @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)" \
270
+ @ aria-label="%h(zLabel[0]?zLabel:zQP)" \
269271
if( disabled ){
270
- @ disabled="disabled"
272
+ @ disabled="disabled" \
271273
}
272274
@ cols="%d(cols)">%h(z)</textarea>
273
- if( zLabel && *zLabel ){
275
+ if( *zLabel ){
274276
@ <span class="textareaLabel">%s(zLabel)</span>
275277
}
276278
}
277279
return z;
278280
}
@@ -297,11 +299,11 @@
297299
db_set(zVar, zQ, 0);
298300
admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
299301
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
300302
z = zQ;
301303
}
302
- @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
304
+ @ <select aria-label="%h(zLabel)" size="1" name="%s(zQP)" id="id%s(zQP)">
303305
for(i=0; i<nChoice*2; i+=2){
304306
const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
305307
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
306308
}
307309
@ </select> <b>%h(zLabel)</b>
@@ -398,11 +400,11 @@
398400
@ <hr />
399401
onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
400402
"http_authentication_ok", "http_authentication_ok", 0, 0);
401403
@ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
402404
@ variable or the "Authentication:" HTTP header to find the username and
403
- @ password. This is another way of supporting Basic Authenitication.
405
+ @ password. This is another way of supporting Basic Authentication.
404406
@ (Property: "http_authentication_ok")
405407
@ </p>
406408
@
407409
@ <hr />
408410
entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
@@ -606,25 +608,30 @@
606608
@
607609
@ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
608610
login_insert_csrf_secret();
609611
@ <blockquote><table border="0">
610612
@
611
- @ <tr><th align="right">Repository filename in group to join:</th>
612
- @ <td width="5"></td><td>
613
- @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr>
614
- @
615
- @ <tr><th align="right">Login on the above repo:</th>
616
- @ <td width="5"></td><td>
617
- @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr>
618
- @
619
- @ <tr><th align="right">Password:</th>
620
- @ <td width="5"></td><td>
621
- @ <input type="password" size="20" name="pw"></td></tr>
622
- @
623
- @ <tr><th align="right">Name of login-group:</th>
624
- @ <td width="5"></td><td>
625
- @ <input type="text" size="30" value="%h(zNewName)" name="newname">
613
+ @ <tr><th align="right" id="rfigtj">Repository filename \
614
+ @ in group to join:</th>
615
+ @ <td width="5"></td><td>
616
+ @ <input aria-labelledby="rfigtj" type="text" size="50" \
617
+ @ value="%h(zRepo)" name="repo"></td></tr>
618
+ @
619
+ @ <tr><th align="right" id="lotar">Login on the above repo:</th>
620
+ @ <td width="5"></td><td>
621
+ @ <input aria-labelledby="lotar" type="text" size="20" \
622
+ @ value="%h(zLogin)" name="login"></td></tr>
623
+ @
624
+ @ <tr><th align="right" id="lgpw">Password:</th>
625
+ @ <td width="5"></td><td>
626
+ @ <input aria-labelledby="lgpw" type="password" size="20" name="pw">\
627
+ @ </td></tr>
628
+ @
629
+ @ <tr><th align="right" id="nolg">Name of login-group:</th>
630
+ @ <td width="5"></td><td>
631
+ @ <input aria-labelledby="nolg" type="text" size="30" \
632
+ @ value="%h(zNewName)" name="newname">
626633
@ (only used if creating a new login-group).</td></tr>
627634
@
628635
@ <tr><td colspan="3" align="center">
629636
@ <input type="submit" value="Join" name="join"></td></tr>
630637
@ </table></blockquote></div></form>
@@ -876,25 +883,30 @@
876883
}
877884
}
878885
}
879886
@ <br /><input type="submit" name="submit" value="Apply Changes" />
880887
@ </td><td style="width:50px;"></td><td valign="top">
888
+ @ <table>
881889
for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
882890
if( pSet->width>0 && !pSet->forceTextArea ){
883891
int hasVersionableValue = pSet->versionable &&
884892
(db_get_versioned(pSet->name, NULL)!=0);
893
+ @ <tr><td>
894
+ @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
895
+ if( pSet->versionable ){
896
+ @ (v)
897
+ } else {
898
+ @
899
+ }
900
+ @</td><td>
885901
entry_attribute("", /*pSet->width*/ 25, pSet->name,
886902
pSet->var!=0 ? pSet->var : pSet->name,
887903
(char*)pSet->def, hasVersionableValue);
888
- @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
889
- if( pSet->versionable ){
890
- @ (v)<br />
891
- } else {
892
- @ <br />
893
- }
904
+ @</td></tr>
894905
}
895906
}
907
+ @</table>
896908
@ </td><td style="width:50px;"></td><td valign="top">
897909
for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
898910
if( pSet->width>0 && pSet->forceTextArea ){
899911
int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0;
900912
@ <a href='%R/help?cmd=%s(pSet->name)'>%s(pSet->name)</a>
901913
--- src/setup.c
+++ src/setup.c
@@ -201,16 +201,17 @@
201 admin_log("Set option [%q] to [%q].",
202 zVar, iQ ? "on" : "off");
203 iVal = iQ;
204 }
205 }
206 @ <label><input type="checkbox" name="%s(zQParm)"
 
207 if( iVal ){
208 @ checked="checked"
209 }
210 if( disabled ){
211 @ disabled="disabled"
212 }
213 @ /> <b>%s(zLabel)</b></label>
214 }
215
216 /*
@@ -232,12 +233,12 @@
232 db_set(zVar, zQ, 0);
233 admin_log("Set entry_attribute %Q to: %.*s%s",
234 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
235 zVal = zQ;
236 }
237 @ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" \
238 @ size="%d(width)" \
239 if( disabled ){
240 @ disabled="disabled" \
241 }
242 @ /> <b>%s(zLabel)</b>
243 }
@@ -263,16 +264,17 @@
263 admin_log("Set textarea_attribute %Q to: %.*s%s",
264 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
265 z = zQ;
266 }
267 if( rows>0 && cols>0 ){
268 @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"
 
269 if( disabled ){
270 @ disabled="disabled"
271 }
272 @ cols="%d(cols)">%h(z)</textarea>
273 if( zLabel && *zLabel ){
274 @ <span class="textareaLabel">%s(zLabel)</span>
275 }
276 }
277 return z;
278 }
@@ -297,11 +299,11 @@
297 db_set(zVar, zQ, 0);
298 admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
299 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
300 z = zQ;
301 }
302 @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
303 for(i=0; i<nChoice*2; i+=2){
304 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
305 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
306 }
307 @ </select> <b>%h(zLabel)</b>
@@ -398,11 +400,11 @@
398 @ <hr />
399 onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
400 "http_authentication_ok", "http_authentication_ok", 0, 0);
401 @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
402 @ variable or the "Authentication:" HTTP header to find the username and
403 @ password. This is another way of supporting Basic Authenitication.
404 @ (Property: "http_authentication_ok")
405 @ </p>
406 @
407 @ <hr />
408 entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
@@ -606,25 +608,30 @@
606 @
607 @ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
608 login_insert_csrf_secret();
609 @ <blockquote><table border="0">
610 @
611 @ <tr><th align="right">Repository filename in group to join:</th>
612 @ <td width="5"></td><td>
613 @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr>
614 @
615 @ <tr><th align="right">Login on the above repo:</th>
616 @ <td width="5"></td><td>
617 @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr>
618 @
619 @ <tr><th align="right">Password:</th>
620 @ <td width="5"></td><td>
621 @ <input type="password" size="20" name="pw"></td></tr>
622 @
623 @ <tr><th align="right">Name of login-group:</th>
624 @ <td width="5"></td><td>
625 @ <input type="text" size="30" value="%h(zNewName)" name="newname">
 
 
 
 
 
626 @ (only used if creating a new login-group).</td></tr>
627 @
628 @ <tr><td colspan="3" align="center">
629 @ <input type="submit" value="Join" name="join"></td></tr>
630 @ </table></blockquote></div></form>
@@ -876,25 +883,30 @@
876 }
877 }
878 }
879 @ <br /><input type="submit" name="submit" value="Apply Changes" />
880 @ </td><td style="width:50px;"></td><td valign="top">
 
881 for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
882 if( pSet->width>0 && !pSet->forceTextArea ){
883 int hasVersionableValue = pSet->versionable &&
884 (db_get_versioned(pSet->name, NULL)!=0);
 
 
 
 
 
 
 
 
885 entry_attribute("", /*pSet->width*/ 25, pSet->name,
886 pSet->var!=0 ? pSet->var : pSet->name,
887 (char*)pSet->def, hasVersionableValue);
888 @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
889 if( pSet->versionable ){
890 @ (v)<br />
891 } else {
892 @ <br />
893 }
894 }
895 }
 
896 @ </td><td style="width:50px;"></td><td valign="top">
897 for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
898 if( pSet->width>0 && pSet->forceTextArea ){
899 int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0;
900 @ <a href='%R/help?cmd=%s(pSet->name)'>%s(pSet->name)</a>
901
--- src/setup.c
+++ src/setup.c
@@ -201,16 +201,17 @@
201 admin_log("Set option [%q] to [%q].",
202 zVar, iQ ? "on" : "off");
203 iVal = iQ;
204 }
205 }
206 @ <label><input type="checkbox" name="%s(zQParm)" \
207 @ aria-label="%s(zLabel[0]?zLabel:zQParm)" \
208 if( iVal ){
209 @ checked="checked" \
210 }
211 if( disabled ){
212 @ disabled="disabled" \
213 }
214 @ /> <b>%s(zLabel)</b></label>
215 }
216
217 /*
@@ -232,12 +233,12 @@
233 db_set(zVar, zQ, 0);
234 admin_log("Set entry_attribute %Q to: %.*s%s",
235 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
236 zVal = zQ;
237 }
238 @ <input aria-label="%h(zLabel[0]?zLabel:zQParm)" type="text" \
239 @ id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" \
240 if( disabled ){
241 @ disabled="disabled" \
242 }
243 @ /> <b>%s(zLabel)</b>
244 }
@@ -263,16 +264,17 @@
264 admin_log("Set textarea_attribute %Q to: %.*s%s",
265 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
266 z = zQ;
267 }
268 if( rows>0 && cols>0 ){
269 @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)" \
270 @ aria-label="%h(zLabel[0]?zLabel:zQP)" \
271 if( disabled ){
272 @ disabled="disabled" \
273 }
274 @ cols="%d(cols)">%h(z)</textarea>
275 if( *zLabel ){
276 @ <span class="textareaLabel">%s(zLabel)</span>
277 }
278 }
279 return z;
280 }
@@ -297,11 +299,11 @@
299 db_set(zVar, zQ, 0);
300 admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
301 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
302 z = zQ;
303 }
304 @ <select aria-label="%h(zLabel)" size="1" name="%s(zQP)" id="id%s(zQP)">
305 for(i=0; i<nChoice*2; i+=2){
306 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
307 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
308 }
309 @ </select> <b>%h(zLabel)</b>
@@ -398,11 +400,11 @@
400 @ <hr />
401 onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
402 "http_authentication_ok", "http_authentication_ok", 0, 0);
403 @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
404 @ variable or the "Authentication:" HTTP header to find the username and
405 @ password. This is another way of supporting Basic Authentication.
406 @ (Property: "http_authentication_ok")
407 @ </p>
408 @
409 @ <hr />
410 entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
@@ -606,25 +608,30 @@
608 @
609 @ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
610 login_insert_csrf_secret();
611 @ <blockquote><table border="0">
612 @
613 @ <tr><th align="right" id="rfigtj">Repository filename \
614 @ in group to join:</th>
615 @ <td width="5"></td><td>
616 @ <input aria-labelledby="rfigtj" type="text" size="50" \
617 @ value="%h(zRepo)" name="repo"></td></tr>
618 @
619 @ <tr><th align="right" id="lotar">Login on the above repo:</th>
620 @ <td width="5"></td><td>
621 @ <input aria-labelledby="lotar" type="text" size="20" \
622 @ value="%h(zLogin)" name="login"></td></tr>
623 @
624 @ <tr><th align="right" id="lgpw">Password:</th>
625 @ <td width="5"></td><td>
626 @ <input aria-labelledby="lgpw" type="password" size="20" name="pw">\
627 @ </td></tr>
628 @
629 @ <tr><th align="right" id="nolg">Name of login-group:</th>
630 @ <td width="5"></td><td>
631 @ <input aria-labelledby="nolg" type="text" size="30" \
632 @ value="%h(zNewName)" name="newname">
633 @ (only used if creating a new login-group).</td></tr>
634 @
635 @ <tr><td colspan="3" align="center">
636 @ <input type="submit" value="Join" name="join"></td></tr>
637 @ </table></blockquote></div></form>
@@ -876,25 +883,30 @@
883 }
884 }
885 }
886 @ <br /><input type="submit" name="submit" value="Apply Changes" />
887 @ </td><td style="width:50px;"></td><td valign="top">
888 @ <table>
889 for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
890 if( pSet->width>0 && !pSet->forceTextArea ){
891 int hasVersionableValue = pSet->versionable &&
892 (db_get_versioned(pSet->name, NULL)!=0);
893 @ <tr><td>
894 @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
895 if( pSet->versionable ){
896 @ (v)
897 } else {
898 @
899 }
900 @</td><td>
901 entry_attribute("", /*pSet->width*/ 25, pSet->name,
902 pSet->var!=0 ? pSet->var : pSet->name,
903 (char*)pSet->def, hasVersionableValue);
904 @</td></tr>
 
 
 
 
 
905 }
906 }
907 @</table>
908 @ </td><td style="width:50px;"></td><td valign="top">
909 for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
910 if( pSet->width>0 && pSet->forceTextArea ){
911 int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0;
912 @ <a href='%R/help?cmd=%s(pSet->name)'>%s(pSet->name)</a>
913
+16 -12
--- src/setupuser.c
+++ src/setupuser.c
@@ -534,24 +534,27 @@
534534
@ <input type="hidden" name="pw" value="*">
535535
}
536536
@ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
537537
@ <table width="100%%">
538538
@ <tr>
539
- @ <td class="usetupEditLabel">User ID:</td>
539
+ @ <td class="usetupEditLabel" id="suuid">User ID:</td>
540540
if( uid ){
541
- @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" />\
541
+ @ <td>%d(uid) <input aria-labelledby="suuid" type="hidden" \
542
+ @ name="id" value="%d(uid)"/>\
542543
@ </td>
543544
}else{
544
- @ <td>(new user)<input type="hidden" name="id" value="0" /></td>
545
+ @ <td>(new user)<input aria-labelledby="suuid" type="hidden" name="id" \
546
+ @ value="0" /></td>
545547
}
546548
@ </tr>
547549
@ <tr>
548
- @ <td class="usetupEditLabel">Login:</td>
550
+ @ <td class="usetupEditLabel" id="sulgn">Login:</td>
549551
if( login_is_special(zLogin) ){
550552
@ <td><b>%h(zLogin)</b></td>
551553
}else{
552
- @ <td><input type="text" name="login" value="%h(zLogin)" />\
554
+ @ <td><input aria-labelledby="sulgn" type="text" name="login" \
555
+ @ value="%h(zLogin)" />
553556
if( alert_tables_exist() ){
554557
int sid;
555558
sid = db_int(0, "SELECT subscriberId FROM subscriber"
556559
" WHERE suname=%Q", zLogin);
557560
if( sid>0 ){
@@ -559,12 +562,13 @@
559562
@ (subscription info for %h(zLogin))</a>\
560563
}
561564
}
562565
@ </td></tr>
563566
@ <tr>
564
- @ <td class="usetupEditLabel">Contact&nbsp;Info:</td>
565
- @ <td><textarea name="info" cols="40" rows="2">%h(zInfo)</textarea></td>
567
+ @ <td class="usetupEditLabel" id="sucnfo">Contact&nbsp;Info:</td>
568
+ @ <td><textarea aria-labelledby="sucnfo" name="info" cols="40" \
569
+ @ rows="2">%h(zInfo)</textarea></td>
566570
}
567571
@ </tr>
568572
@ <tr>
569573
@ <td class="usetupEditLabel">Capabilities:</td>
570574
@ <td width="100%%">
@@ -653,19 +657,19 @@
653657
@ <a href="%R/setup_ucap_list">(key)</a>
654658
@ </td>
655659
@ </tr>
656660
if( !login_is_special(zLogin) ){
657661
@ <tr>
658
- @ <td align="right">Password:</td>
662
+ @ <td align="right" id="supw">Password:</td>
659663
if( zPw[0] ){
660664
/* Obscure the password for all users */
661
- @ <td><input type="password" autocomplete="off" name="pw"\
662
- @ value="**********" /></td>
665
+ @ <td><input aria-labelledby="supw" type="password" autocomplete="off" \
666
+ @ name="pw" value="**********" /></td>
663667
}else{
664668
/* Show an empty password as an empty input field */
665
- @ <td><input type="password" autocomplete="off" name="pw"\
666
- @ value="" /></td>
669
+ @ <td><input aria-labelledby="supw" type="password" name="pw" \
670
+ @ autocomplete="off" value="" /></td>
667671
}
668672
@ </tr>
669673
}
670674
zGroup = login_group_name();
671675
if( zGroup ){
672676
--- src/setupuser.c
+++ src/setupuser.c
@@ -534,24 +534,27 @@
534 @ <input type="hidden" name="pw" value="*">
535 }
536 @ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
537 @ <table width="100%%">
538 @ <tr>
539 @ <td class="usetupEditLabel">User ID:</td>
540 if( uid ){
541 @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" />\
 
542 @ </td>
543 }else{
544 @ <td>(new user)<input type="hidden" name="id" value="0" /></td>
 
545 }
546 @ </tr>
547 @ <tr>
548 @ <td class="usetupEditLabel">Login:</td>
549 if( login_is_special(zLogin) ){
550 @ <td><b>%h(zLogin)</b></td>
551 }else{
552 @ <td><input type="text" name="login" value="%h(zLogin)" />\
 
553 if( alert_tables_exist() ){
554 int sid;
555 sid = db_int(0, "SELECT subscriberId FROM subscriber"
556 " WHERE suname=%Q", zLogin);
557 if( sid>0 ){
@@ -559,12 +562,13 @@
559 @ (subscription info for %h(zLogin))</a>\
560 }
561 }
562 @ </td></tr>
563 @ <tr>
564 @ <td class="usetupEditLabel">Contact&nbsp;Info:</td>
565 @ <td><textarea name="info" cols="40" rows="2">%h(zInfo)</textarea></td>
 
566 }
567 @ </tr>
568 @ <tr>
569 @ <td class="usetupEditLabel">Capabilities:</td>
570 @ <td width="100%%">
@@ -653,19 +657,19 @@
653 @ <a href="%R/setup_ucap_list">(key)</a>
654 @ </td>
655 @ </tr>
656 if( !login_is_special(zLogin) ){
657 @ <tr>
658 @ <td align="right">Password:</td>
659 if( zPw[0] ){
660 /* Obscure the password for all users */
661 @ <td><input type="password" autocomplete="off" name="pw"\
662 @ value="**********" /></td>
663 }else{
664 /* Show an empty password as an empty input field */
665 @ <td><input type="password" autocomplete="off" name="pw"\
666 @ value="" /></td>
667 }
668 @ </tr>
669 }
670 zGroup = login_group_name();
671 if( zGroup ){
672
--- src/setupuser.c
+++ src/setupuser.c
@@ -534,24 +534,27 @@
534 @ <input type="hidden" name="pw" value="*">
535 }
536 @ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
537 @ <table width="100%%">
538 @ <tr>
539 @ <td class="usetupEditLabel" id="suuid">User ID:</td>
540 if( uid ){
541 @ <td>%d(uid) <input aria-labelledby="suuid" type="hidden" \
542 @ name="id" value="%d(uid)"/>\
543 @ </td>
544 }else{
545 @ <td>(new user)<input aria-labelledby="suuid" type="hidden" name="id" \
546 @ value="0" /></td>
547 }
548 @ </tr>
549 @ <tr>
550 @ <td class="usetupEditLabel" id="sulgn">Login:</td>
551 if( login_is_special(zLogin) ){
552 @ <td><b>%h(zLogin)</b></td>
553 }else{
554 @ <td><input aria-labelledby="sulgn" type="text" name="login" \
555 @ value="%h(zLogin)" />
556 if( alert_tables_exist() ){
557 int sid;
558 sid = db_int(0, "SELECT subscriberId FROM subscriber"
559 " WHERE suname=%Q", zLogin);
560 if( sid>0 ){
@@ -559,12 +562,13 @@
562 @ (subscription info for %h(zLogin))</a>\
563 }
564 }
565 @ </td></tr>
566 @ <tr>
567 @ <td class="usetupEditLabel" id="sucnfo">Contact&nbsp;Info:</td>
568 @ <td><textarea aria-labelledby="sucnfo" name="info" cols="40" \
569 @ rows="2">%h(zInfo)</textarea></td>
570 }
571 @ </tr>
572 @ <tr>
573 @ <td class="usetupEditLabel">Capabilities:</td>
574 @ <td width="100%%">
@@ -653,19 +657,19 @@
657 @ <a href="%R/setup_ucap_list">(key)</a>
658 @ </td>
659 @ </tr>
660 if( !login_is_special(zLogin) ){
661 @ <tr>
662 @ <td align="right" id="supw">Password:</td>
663 if( zPw[0] ){
664 /* Obscure the password for all users */
665 @ <td><input aria-labelledby="supw" type="password" autocomplete="off" \
666 @ name="pw" value="**********" /></td>
667 }else{
668 /* Show an empty password as an empty input field */
669 @ <td><input aria-labelledby="supw" type="password" name="pw" \
670 @ autocomplete="off" value="" /></td>
671 }
672 @ </tr>
673 }
674 zGroup = login_group_name();
675 if( zGroup ){
676
+14 -11
--- src/shell.c
+++ src/shell.c
@@ -4330,10 +4330,11 @@
43304330
int nKey2, const void *pKey2
43314331
){
43324332
const unsigned char *zA = (const unsigned char*)pKey1;
43334333
const unsigned char *zB = (const unsigned char*)pKey2;
43344334
int i=0, j=0, x;
4335
+ (void)notUsed;
43354336
while( i<nKey1 && j<nKey2 ){
43364337
x = zA[i] - zB[j];
43374338
if( isdigit(zA[i]) ){
43384339
int k;
43394340
if( !isdigit(zB[j]) ) return x;
@@ -6588,10 +6589,11 @@
65886589
** sqlar support.
65896590
*/
65906591
/* #include "sqlite3ext.h" */
65916592
SQLITE_EXTENSION_INIT1
65926593
#include <zlib.h>
6594
+#include <assert.h>
65936595
65946596
/*
65956597
** Implementation of the "sqlar_compress(X)" SQL function.
65966598
**
65976599
** If the type of X is SQLITE_BLOB, and compressing that blob using
@@ -7997,18 +7999,23 @@
79977999
while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
79988000
/* int iId = sqlite3_column_int(pExplain, 0); */
79998001
/* int iParent = sqlite3_column_int(pExplain, 1); */
80008002
/* int iNotUsed = sqlite3_column_int(pExplain, 2); */
80018003
const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
8002
- int nDetail = STRLEN(zDetail);
8004
+ int nDetail;
80038005
int i;
80048006
8007
+ if( !zDetail ) continue;
8008
+ nDetail = STRLEN(zDetail);
8009
+
80058010
for(i=0; i<nDetail; i++){
80068011
const char *zIdx = 0;
8007
- if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
8012
+ if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
80088013
zIdx = &zDetail[i+13];
8009
- }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
8014
+ }else if( i+22<nDetail
8015
+ && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
8016
+ ){
80108017
zIdx = &zDetail[i+22];
80118018
}
80128019
if( zIdx ){
80138020
const char *zSql;
80148021
int nIdx = 0;
@@ -8819,11 +8826,11 @@
88198826
sqlite3_free(p->zCandidates);
88208827
sqlite3_free(p);
88218828
}
88228829
}
88238830
8824
-#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8831
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
88258832
88268833
/************************* End ../ext/expert/sqlite3expert.c ********************/
88278834
88288835
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
88298836
/************************* Begin ../ext/misc/dbdata.c ******************/
@@ -11816,10 +11823,11 @@
1181611823
if( rc==SQLITE_OK ){
1181711824
while( sqlite3_step(pExplain)==SQLITE_ROW ){
1181811825
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
1181911826
int iEqpId = sqlite3_column_int(pExplain, 0);
1182011827
int iParentId = sqlite3_column_int(pExplain, 1);
11828
+ if( zEQPLine==0 ) zEQPLine = "";
1182111829
if( zEQPLine[0]=='-' ) eqp_render(pArg);
1182211830
eqp_append(pArg, iEqpId, iParentId, zEQPLine);
1182311831
}
1182411832
eqp_render(pArg);
1182511833
}
@@ -13725,16 +13733,11 @@
1372513733
if( p->db==0 ) return 1;
1372613734
rc = sqlite3_prepare_v2(p->db,
1372713735
"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
1372813736
-1, &pStmt, 0);
1372913737
if( rc ){
13730
- if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
13731
- utf8_printf(stderr, "the \".dbinfo\" command requires the "
13732
- "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
13733
- }else{
13734
- utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
13735
- }
13738
+ utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
1373613739
sqlite3_finalize(pStmt);
1373713740
return 1;
1373813741
}
1373913742
sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
1374013743
if( sqlite3_step(pStmt)==SQLITE_ROW
@@ -17004,11 +17007,11 @@
1700417007
const char *zFile = 0;
1700517008
int bTxtMode = 0;
1700617009
int i;
1700717010
int eMode = 0;
1700817011
int bBOM = 0;
17009
- int bOnce;
17012
+ int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
1701017013
1701117014
if( c=='e' ){
1701217015
eMode = 'x';
1701317016
bOnce = 2;
1701417017
}else if( strncmp(azArg[0],"once",n)==0 ){
1701517018
--- src/shell.c
+++ src/shell.c
@@ -4330,10 +4330,11 @@
4330 int nKey2, const void *pKey2
4331 ){
4332 const unsigned char *zA = (const unsigned char*)pKey1;
4333 const unsigned char *zB = (const unsigned char*)pKey2;
4334 int i=0, j=0, x;
 
4335 while( i<nKey1 && j<nKey2 ){
4336 x = zA[i] - zB[j];
4337 if( isdigit(zA[i]) ){
4338 int k;
4339 if( !isdigit(zB[j]) ) return x;
@@ -6588,10 +6589,11 @@
6588 ** sqlar support.
6589 */
6590 /* #include "sqlite3ext.h" */
6591 SQLITE_EXTENSION_INIT1
6592 #include <zlib.h>
 
6593
6594 /*
6595 ** Implementation of the "sqlar_compress(X)" SQL function.
6596 **
6597 ** If the type of X is SQLITE_BLOB, and compressing that blob using
@@ -7997,18 +7999,23 @@
7997 while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
7998 /* int iId = sqlite3_column_int(pExplain, 0); */
7999 /* int iParent = sqlite3_column_int(pExplain, 1); */
8000 /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
8001 const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
8002 int nDetail = STRLEN(zDetail);
8003 int i;
8004
 
 
 
8005 for(i=0; i<nDetail; i++){
8006 const char *zIdx = 0;
8007 if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
8008 zIdx = &zDetail[i+13];
8009 }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
 
 
8010 zIdx = &zDetail[i+22];
8011 }
8012 if( zIdx ){
8013 const char *zSql;
8014 int nIdx = 0;
@@ -8819,11 +8826,11 @@
8819 sqlite3_free(p->zCandidates);
8820 sqlite3_free(p);
8821 }
8822 }
8823
8824 #endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8825
8826 /************************* End ../ext/expert/sqlite3expert.c ********************/
8827
8828 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8829 /************************* Begin ../ext/misc/dbdata.c ******************/
@@ -11816,10 +11823,11 @@
11816 if( rc==SQLITE_OK ){
11817 while( sqlite3_step(pExplain)==SQLITE_ROW ){
11818 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
11819 int iEqpId = sqlite3_column_int(pExplain, 0);
11820 int iParentId = sqlite3_column_int(pExplain, 1);
 
11821 if( zEQPLine[0]=='-' ) eqp_render(pArg);
11822 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
11823 }
11824 eqp_render(pArg);
11825 }
@@ -13725,16 +13733,11 @@
13725 if( p->db==0 ) return 1;
13726 rc = sqlite3_prepare_v2(p->db,
13727 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
13728 -1, &pStmt, 0);
13729 if( rc ){
13730 if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
13731 utf8_printf(stderr, "the \".dbinfo\" command requires the "
13732 "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
13733 }else{
13734 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
13735 }
13736 sqlite3_finalize(pStmt);
13737 return 1;
13738 }
13739 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
13740 if( sqlite3_step(pStmt)==SQLITE_ROW
@@ -17004,11 +17007,11 @@
17004 const char *zFile = 0;
17005 int bTxtMode = 0;
17006 int i;
17007 int eMode = 0;
17008 int bBOM = 0;
17009 int bOnce;
17010
17011 if( c=='e' ){
17012 eMode = 'x';
17013 bOnce = 2;
17014 }else if( strncmp(azArg[0],"once",n)==0 ){
17015
--- src/shell.c
+++ src/shell.c
@@ -4330,10 +4330,11 @@
4330 int nKey2, const void *pKey2
4331 ){
4332 const unsigned char *zA = (const unsigned char*)pKey1;
4333 const unsigned char *zB = (const unsigned char*)pKey2;
4334 int i=0, j=0, x;
4335 (void)notUsed;
4336 while( i<nKey1 && j<nKey2 ){
4337 x = zA[i] - zB[j];
4338 if( isdigit(zA[i]) ){
4339 int k;
4340 if( !isdigit(zB[j]) ) return x;
@@ -6588,10 +6589,11 @@
6589 ** sqlar support.
6590 */
6591 /* #include "sqlite3ext.h" */
6592 SQLITE_EXTENSION_INIT1
6593 #include <zlib.h>
6594 #include <assert.h>
6595
6596 /*
6597 ** Implementation of the "sqlar_compress(X)" SQL function.
6598 **
6599 ** If the type of X is SQLITE_BLOB, and compressing that blob using
@@ -7997,18 +7999,23 @@
7999 while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
8000 /* int iId = sqlite3_column_int(pExplain, 0); */
8001 /* int iParent = sqlite3_column_int(pExplain, 1); */
8002 /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
8003 const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
8004 int nDetail;
8005 int i;
8006
8007 if( !zDetail ) continue;
8008 nDetail = STRLEN(zDetail);
8009
8010 for(i=0; i<nDetail; i++){
8011 const char *zIdx = 0;
8012 if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
8013 zIdx = &zDetail[i+13];
8014 }else if( i+22<nDetail
8015 && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
8016 ){
8017 zIdx = &zDetail[i+22];
8018 }
8019 if( zIdx ){
8020 const char *zSql;
8021 int nIdx = 0;
@@ -8819,11 +8826,11 @@
8826 sqlite3_free(p->zCandidates);
8827 sqlite3_free(p);
8828 }
8829 }
8830
8831 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
8832
8833 /************************* End ../ext/expert/sqlite3expert.c ********************/
8834
8835 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8836 /************************* Begin ../ext/misc/dbdata.c ******************/
@@ -11816,10 +11823,11 @@
11823 if( rc==SQLITE_OK ){
11824 while( sqlite3_step(pExplain)==SQLITE_ROW ){
11825 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
11826 int iEqpId = sqlite3_column_int(pExplain, 0);
11827 int iParentId = sqlite3_column_int(pExplain, 1);
11828 if( zEQPLine==0 ) zEQPLine = "";
11829 if( zEQPLine[0]=='-' ) eqp_render(pArg);
11830 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
11831 }
11832 eqp_render(pArg);
11833 }
@@ -13725,16 +13733,11 @@
13733 if( p->db==0 ) return 1;
13734 rc = sqlite3_prepare_v2(p->db,
13735 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
13736 -1, &pStmt, 0);
13737 if( rc ){
13738 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
 
 
 
 
 
13739 sqlite3_finalize(pStmt);
13740 return 1;
13741 }
13742 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
13743 if( sqlite3_step(pStmt)==SQLITE_ROW
@@ -17004,11 +17007,11 @@
17007 const char *zFile = 0;
17008 int bTxtMode = 0;
17009 int i;
17010 int eMode = 0;
17011 int bBOM = 0;
17012 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
17013
17014 if( c=='e' ){
17015 eMode = 'x';
17016 bOnce = 2;
17017 }else if( strncmp(azArg[0],"once",n)==0 ){
17018
+2 -2
--- src/shun.c
+++ src/shun.c
@@ -187,11 +187,11 @@
187187
@ sight - set the "hidden" tag on such artifacts instead.</p>
188188
@
189189
@ <blockquote>
190190
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
191191
login_insert_csrf_secret();
192
- @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
192
+ @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
193193
if( zShun ){
194194
if( strlen(zShun) ){
195195
@ %h(zShun)
196196
}else if( nRcvid ){
197197
db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
@@ -214,11 +214,11 @@
214214
@ operations.</p>
215215
@
216216
@ <blockquote>
217217
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
218218
login_insert_csrf_secret();
219
- @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
219
+ @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
220220
if( zAccept ){
221221
if( strlen(zAccept) ){
222222
@ %h(zAccept)
223223
}else if( nRcvid ){
224224
db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
225225
--- src/shun.c
+++ src/shun.c
@@ -187,11 +187,11 @@
187 @ sight - set the "hidden" tag on such artifacts instead.</p>
188 @
189 @ <blockquote>
190 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
191 login_insert_csrf_secret();
192 @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
193 if( zShun ){
194 if( strlen(zShun) ){
195 @ %h(zShun)
196 }else if( nRcvid ){
197 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
@@ -214,11 +214,11 @@
214 @ operations.</p>
215 @
216 @ <blockquote>
217 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
218 login_insert_csrf_secret();
219 @ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
220 if( zAccept ){
221 if( strlen(zAccept) ){
222 @ %h(zAccept)
223 }else if( nRcvid ){
224 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
225
--- src/shun.c
+++ src/shun.c
@@ -187,11 +187,11 @@
187 @ sight - set the "hidden" tag on such artifacts instead.</p>
188 @
189 @ <blockquote>
190 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
191 login_insert_csrf_secret();
192 @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
193 if( zShun ){
194 if( strlen(zShun) ){
195 @ %h(zShun)
196 }else if( nRcvid ){
197 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
@@ -214,11 +214,11 @@
214 @ operations.</p>
215 @
216 @ <blockquote>
217 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
218 login_insert_csrf_secret();
219 @ <textarea class="fullsize-text" cols="70" rows="%d(numRows)" name="uuid">
220 if( zAccept ){
221 if( strlen(zAccept) ){
222 @ %h(zAccept)
223 }else if( nRcvid ){
224 db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
225
+62 -2
--- src/skins.c
+++ src/skins.c
@@ -281,10 +281,13 @@
281281
** Return an identifier that is (probably) different for every skin
282282
** but that is (probably) the same if the skin is unchanged. This
283283
** identifier can be attached to resource URLs to force reloading when
284284
** the resources change but allow the resources to be read from cache
285285
** as long as they are unchanged.
286
+**
287
+** The zResource argument is the name of a CONFIG setting that
288
+** defines the resource. Examples: "css", "logo-image".
286289
*/
287290
unsigned int skin_id(const char *zResource){
288291
unsigned int h = 0;
289292
if( zAltSkinDir ){
290293
h = skin_hash(0, zAltSkinDir);
@@ -293,11 +296,13 @@
293296
}else{
294297
char *zMTime = db_get_mtime(zResource, 0, 0);
295298
h = skin_hash(0, zMTime);
296299
fossil_free(zMTime);
297300
}
298
- h = skin_hash(h, MANIFEST_UUID);
301
+
302
+ /* Change the ID every time Fossil is recompiled */
303
+ h = skin_hash(h, fossil_exe_id());
299304
return h;
300305
}
301306
302307
/*
303308
** For a skin named zSkinName, compute the name of the CONFIG table
@@ -688,10 +693,62 @@
688693
}
689694
}
690695
return zResult;
691696
}
692697
698
+extern const struct strctCssDefaults {
699
+/* From the generated default_css.h, which we cannot #include here
700
+** without causing an ODR violation.
701
+*/
702
+ const char *elementClass; /* Name of element needed */
703
+ const char *value; /* CSS text */
704
+} cssDefaultList[];
705
+
706
+/*
707
+** Emits the list of built-in default CSS selectors. Intended
708
+** for use only from the /setup_skinedit page.
709
+*/
710
+static void skin_emit_css_defaults(){
711
+ struct strctCssDefaults const * pCss;
712
+ fossil_print("<h1>CSS Defaults</h1>");
713
+ fossil_print("If a skin defines any of the following CSS selectors, "
714
+ "that definition replaces the default, as opposed to "
715
+ "cascading from it. ");
716
+ fossil_print("See <a href=\"https://fossil-scm.org/fossil/"
717
+ "doc/trunk/www/css-tricks.md\">this "
718
+ "document</a> for more details.");
719
+ /* To discuss: do we want to list only the default selectors or
720
+ ** also their default values? The latter increases the size of the
721
+ ** page considerably, but is arguably more useful. We could, of
722
+ ** course, offer a URL param to toggle the view, but that currently
723
+ ** seems like overkill.
724
+ **
725
+ ** Be sure to adjust the default_css.txt #setup_skinedit_css entry
726
+ ** for whichever impl ends up being selected.
727
+ */
728
+#if 1
729
+ /* List impl which elides style values */
730
+ fossil_print("<div class=\"columns\" "
731
+ "id=\"setup_skinedit_css_defaults\"><ul>");
732
+ for(pCss = &cssDefaultList[0]; pCss->value!=0; ++pCss){
733
+ fossil_print("<li>%s</li>", pCss->elementClass);
734
+ }
735
+ fossil_print("</ul>");
736
+#else
737
+ /* Table impl which also includes style values. */
738
+ fossil_print("<table id=\"setup_skinedit_css_defaults\"><tbody>");
739
+ for(pCss = &cssDefaultList[0]; pCss->value!=0; ++pCss){
740
+ fossil_print("<tr><td>%s</td>", pCss->elementClass);
741
+ /* A TD element apparently cannot be told to scroll its contents,
742
+ ** so we require a DIV inside the value TD to scroll the long
743
+ ** url(data:...) entries. */
744
+ fossil_print("<td><div>%s</div></td>", pCss->value);
745
+ fossil_print("</td></tr>");
746
+ }
747
+ fossil_print("</tbody></table>");
748
+#endif
749
+}
693750
694751
/*
695752
** WEBPAGE: setup_skinedit
696753
**
697754
** Edit aspects of a skin determined by the w= query parameter.
@@ -814,10 +871,13 @@
814871
blob_reset(&from);
815872
blob_reset(&to);
816873
blob_reset(&out);
817874
}
818875
@ </div></form>
876
+ if(ii==0/*CSS*/){
877
+ skin_emit_css_defaults();
878
+ }
819879
style_footer();
820880
db_end_transaction(0);
821881
}
822882
823883
/*
@@ -1062,11 +1122,11 @@
10621122
if( !g.perm.Admin ){
10631123
@ <p>Only administrators are allowed to publish draft skins. Contact
10641124
@ an administrator to get this "draft%d(iSkin)" skin published.</p>
10651125
}else{
10661126
@ <p>When the draft%d(iSkin) skin is ready for production use,
1067
- @ make it the default scan by clicking the acknowledgements and
1127
+ @ make it the default skin by clicking the acknowledgements and
10681128
@ pressing the button below:</p>
10691129
@
10701130
@ <form method='POST' action='%R/setup_skin#step7'>
10711131
@ <p class='skinInput'>
10721132
@ <input type='hidden' name='sk' value='%d(iSkin)'>
10731133
--- src/skins.c
+++ src/skins.c
@@ -281,10 +281,13 @@
281 ** Return an identifier that is (probably) different for every skin
282 ** but that is (probably) the same if the skin is unchanged. This
283 ** identifier can be attached to resource URLs to force reloading when
284 ** the resources change but allow the resources to be read from cache
285 ** as long as they are unchanged.
 
 
 
286 */
287 unsigned int skin_id(const char *zResource){
288 unsigned int h = 0;
289 if( zAltSkinDir ){
290 h = skin_hash(0, zAltSkinDir);
@@ -293,11 +296,13 @@
293 }else{
294 char *zMTime = db_get_mtime(zResource, 0, 0);
295 h = skin_hash(0, zMTime);
296 fossil_free(zMTime);
297 }
298 h = skin_hash(h, MANIFEST_UUID);
 
 
299 return h;
300 }
301
302 /*
303 ** For a skin named zSkinName, compute the name of the CONFIG table
@@ -688,10 +693,62 @@
688 }
689 }
690 return zResult;
691 }
692
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
693
694 /*
695 ** WEBPAGE: setup_skinedit
696 **
697 ** Edit aspects of a skin determined by the w= query parameter.
@@ -814,10 +871,13 @@
814 blob_reset(&from);
815 blob_reset(&to);
816 blob_reset(&out);
817 }
818 @ </div></form>
 
 
 
819 style_footer();
820 db_end_transaction(0);
821 }
822
823 /*
@@ -1062,11 +1122,11 @@
1062 if( !g.perm.Admin ){
1063 @ <p>Only administrators are allowed to publish draft skins. Contact
1064 @ an administrator to get this "draft%d(iSkin)" skin published.</p>
1065 }else{
1066 @ <p>When the draft%d(iSkin) skin is ready for production use,
1067 @ make it the default scan by clicking the acknowledgements and
1068 @ pressing the button below:</p>
1069 @
1070 @ <form method='POST' action='%R/setup_skin#step7'>
1071 @ <p class='skinInput'>
1072 @ <input type='hidden' name='sk' value='%d(iSkin)'>
1073
--- src/skins.c
+++ src/skins.c
@@ -281,10 +281,13 @@
281 ** Return an identifier that is (probably) different for every skin
282 ** but that is (probably) the same if the skin is unchanged. This
283 ** identifier can be attached to resource URLs to force reloading when
284 ** the resources change but allow the resources to be read from cache
285 ** as long as they are unchanged.
286 **
287 ** The zResource argument is the name of a CONFIG setting that
288 ** defines the resource. Examples: "css", "logo-image".
289 */
290 unsigned int skin_id(const char *zResource){
291 unsigned int h = 0;
292 if( zAltSkinDir ){
293 h = skin_hash(0, zAltSkinDir);
@@ -293,11 +296,13 @@
296 }else{
297 char *zMTime = db_get_mtime(zResource, 0, 0);
298 h = skin_hash(0, zMTime);
299 fossil_free(zMTime);
300 }
301
302 /* Change the ID every time Fossil is recompiled */
303 h = skin_hash(h, fossil_exe_id());
304 return h;
305 }
306
307 /*
308 ** For a skin named zSkinName, compute the name of the CONFIG table
@@ -688,10 +693,62 @@
693 }
694 }
695 return zResult;
696 }
697
698 extern const struct strctCssDefaults {
699 /* From the generated default_css.h, which we cannot #include here
700 ** without causing an ODR violation.
701 */
702 const char *elementClass; /* Name of element needed */
703 const char *value; /* CSS text */
704 } cssDefaultList[];
705
706 /*
707 ** Emits the list of built-in default CSS selectors. Intended
708 ** for use only from the /setup_skinedit page.
709 */
710 static void skin_emit_css_defaults(){
711 struct strctCssDefaults const * pCss;
712 fossil_print("<h1>CSS Defaults</h1>");
713 fossil_print("If a skin defines any of the following CSS selectors, "
714 "that definition replaces the default, as opposed to "
715 "cascading from it. ");
716 fossil_print("See <a href=\"https://fossil-scm.org/fossil/"
717 "doc/trunk/www/css-tricks.md\">this "
718 "document</a> for more details.");
719 /* To discuss: do we want to list only the default selectors or
720 ** also their default values? The latter increases the size of the
721 ** page considerably, but is arguably more useful. We could, of
722 ** course, offer a URL param to toggle the view, but that currently
723 ** seems like overkill.
724 **
725 ** Be sure to adjust the default_css.txt #setup_skinedit_css entry
726 ** for whichever impl ends up being selected.
727 */
728 #if 1
729 /* List impl which elides style values */
730 fossil_print("<div class=\"columns\" "
731 "id=\"setup_skinedit_css_defaults\"><ul>");
732 for(pCss = &cssDefaultList[0]; pCss->value!=0; ++pCss){
733 fossil_print("<li>%s</li>", pCss->elementClass);
734 }
735 fossil_print("</ul>");
736 #else
737 /* Table impl which also includes style values. */
738 fossil_print("<table id=\"setup_skinedit_css_defaults\"><tbody>");
739 for(pCss = &cssDefaultList[0]; pCss->value!=0; ++pCss){
740 fossil_print("<tr><td>%s</td>", pCss->elementClass);
741 /* A TD element apparently cannot be told to scroll its contents,
742 ** so we require a DIV inside the value TD to scroll the long
743 ** url(data:...) entries. */
744 fossil_print("<td><div>%s</div></td>", pCss->value);
745 fossil_print("</td></tr>");
746 }
747 fossil_print("</tbody></table>");
748 #endif
749 }
750
751 /*
752 ** WEBPAGE: setup_skinedit
753 **
754 ** Edit aspects of a skin determined by the w= query parameter.
@@ -814,10 +871,13 @@
871 blob_reset(&from);
872 blob_reset(&to);
873 blob_reset(&out);
874 }
875 @ </div></form>
876 if(ii==0/*CSS*/){
877 skin_emit_css_defaults();
878 }
879 style_footer();
880 db_end_transaction(0);
881 }
882
883 /*
@@ -1062,11 +1122,11 @@
1122 if( !g.perm.Admin ){
1123 @ <p>Only administrators are allowed to publish draft skins. Contact
1124 @ an administrator to get this "draft%d(iSkin)" skin published.</p>
1125 }else{
1126 @ <p>When the draft%d(iSkin) skin is ready for production use,
1127 @ make it the default skin by clicking the acknowledgements and
1128 @ pressing the button below:</p>
1129 @
1130 @ <form method='POST' action='%R/setup_skin#step7'>
1131 @ <p class='skinInput'>
1132 @ <input type='hidden' name='sk' value='%d(iSkin)'>
1133
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -164,10 +164,11 @@
164164
static int sqlcmd_autoinit(
165165
sqlite3 *db,
166166
const char **pzErrMsg,
167167
const void *notUsed
168168
){
169
+ int mTrace = SQLITE_TRACE_CLOSE;
169170
add_content_sql_commands(db);
170171
db_add_aux_functions(db);
171172
re_add_sql_func(db);
172173
search_sql_setup(db);
173174
foci_register(db);
@@ -186,10 +187,14 @@
186187
char *zSql = sqlite3_mprintf("ATTACH %Q AS 'configdb' KEY ''",
187188
g.zConfigDbName);
188189
sqlite3_exec(db, zSql, 0, 0, 0);
189190
sqlite3_free(zSql);
190191
}
192
+ /* Arrange to trace close operations so that static prepared statements
193
+ ** will get cleaned up when the shell closes the database connection */
194
+ if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
195
+ sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
191196
return SQLITE_OK;
192197
}
193198
194199
/*
195200
** atexit() handler that cleans up global state modified by this module.
196201
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -164,10 +164,11 @@
164 static int sqlcmd_autoinit(
165 sqlite3 *db,
166 const char **pzErrMsg,
167 const void *notUsed
168 ){
 
169 add_content_sql_commands(db);
170 db_add_aux_functions(db);
171 re_add_sql_func(db);
172 search_sql_setup(db);
173 foci_register(db);
@@ -186,10 +187,14 @@
186 char *zSql = sqlite3_mprintf("ATTACH %Q AS 'configdb' KEY ''",
187 g.zConfigDbName);
188 sqlite3_exec(db, zSql, 0, 0, 0);
189 sqlite3_free(zSql);
190 }
 
 
 
 
191 return SQLITE_OK;
192 }
193
194 /*
195 ** atexit() handler that cleans up global state modified by this module.
196
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -164,10 +164,11 @@
164 static int sqlcmd_autoinit(
165 sqlite3 *db,
166 const char **pzErrMsg,
167 const void *notUsed
168 ){
169 int mTrace = SQLITE_TRACE_CLOSE;
170 add_content_sql_commands(db);
171 db_add_aux_functions(db);
172 re_add_sql_func(db);
173 search_sql_setup(db);
174 foci_register(db);
@@ -186,10 +187,14 @@
187 char *zSql = sqlite3_mprintf("ATTACH %Q AS 'configdb' KEY ''",
188 g.zConfigDbName);
189 sqlite3_exec(db, zSql, 0, 0, 0);
190 sqlite3_free(zSql);
191 }
192 /* Arrange to trace close operations so that static prepared statements
193 ** will get cleaned up when the shell closes the database connection */
194 if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
195 sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
196 return SQLITE_OK;
197 }
198
199 /*
200 ** atexit() handler that cleans up global state modified by this module.
201
+1753 -833
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.32.0. By combining all the individual C code files into this
3
+** version 3.32.1. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -215,10 +215,13 @@
215215
#if SQLITE_ENABLE_ATOMIC_WRITE
216216
"ENABLE_ATOMIC_WRITE",
217217
#endif
218218
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
219219
"ENABLE_BATCH_ATOMIC_WRITE",
220
+#endif
221
+#if SQLITE_ENABLE_BYTECODE_VTAB
222
+ "ENABLE_BYTECODE_VTAB",
220223
#endif
221224
#if SQLITE_ENABLE_CEROD
222225
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
223226
#endif
224227
#if SQLITE_ENABLE_COLUMN_METADATA
@@ -534,13 +537,10 @@
534537
"OMIT_BETWEEN_OPTIMIZATION",
535538
#endif
536539
#if SQLITE_OMIT_BLOB_LITERAL
537540
"OMIT_BLOB_LITERAL",
538541
#endif
539
-#if SQLITE_OMIT_BTREECOUNT
540
- "OMIT_BTREECOUNT",
541
-#endif
542542
#if SQLITE_OMIT_CAST
543543
"OMIT_CAST",
544544
#endif
545545
#if SQLITE_OMIT_CHECK
546546
"OMIT_CHECK",
@@ -1160,13 +1160,13 @@
11601160
**
11611161
** See also: [sqlite3_libversion()],
11621162
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
11631163
** [sqlite_version()] and [sqlite_source_id()].
11641164
*/
1165
-#define SQLITE_VERSION "3.32.0"
1166
-#define SQLITE_VERSION_NUMBER 3032000
1167
-#define SQLITE_SOURCE_ID "2020-04-20 17:35:32 2fc80ef16ce5878311ab88a0c64631813572ffbb71f75363b4619c9667e0926b"
1165
+#define SQLITE_VERSION "3.32.1"
1166
+#define SQLITE_VERSION_NUMBER 3032001
1167
+#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
11681168
11691169
/*
11701170
** CAPI3REF: Run-Time Library Version Numbers
11711171
** KEYWORDS: sqlite3_version sqlite3_sourceid
11721172
**
@@ -1336,30 +1336,26 @@
13361336
** for the [sqlite3] object.
13371337
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
13381338
** the [sqlite3] object is successfully destroyed and all associated
13391339
** resources are deallocated.
13401340
**
1341
+** Ideally, applications should [sqlite3_finalize | finalize] all
1342
+** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
1343
+** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
1344
+** with the [sqlite3] object prior to attempting to close the object.
13411345
** ^If the database connection is associated with unfinalized prepared
1342
-** statements or unfinished sqlite3_backup objects then sqlite3_close()
1343
-** will leave the database connection open and return [SQLITE_BUSY].
1344
-** ^If sqlite3_close_v2() is called with unfinalized prepared statements
1345
-** and/or unfinished sqlite3_backups, then the database connection becomes
1346
-** an unusable "zombie" which will automatically be deallocated when the
1347
-** last prepared statement is finalized or the last sqlite3_backup is
1348
-** finished. The sqlite3_close_v2() interface is intended for use with
1349
-** host languages that are garbage collected, and where the order in which
1350
-** destructors are called is arbitrary.
1351
-**
1352
-** Applications should [sqlite3_finalize | finalize] all [prepared statements],
1353
-** [sqlite3_blob_close | close] all [BLOB handles], and
1354
-** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
1355
-** with the [sqlite3] object prior to attempting to close the object. ^If
1356
-** sqlite3_close_v2() is called on a [database connection] that still has
1357
-** outstanding [prepared statements], [BLOB handles], and/or
1358
-** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
1359
-** of resources is deferred until all [prepared statements], [BLOB handles],
1360
-** and [sqlite3_backup] objects are also destroyed.
1346
+** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
1347
+** sqlite3_close() will leave the database connection open and return
1348
+** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
1349
+** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
1350
+** it returns [SQLITE_OK] regardless, but instead of deallocating the database
1351
+** connection immediately, it marks the database connection as an unusable
1352
+** "zombie" and makes arrangements to automatically deallocate the database
1353
+** connection after all prepared statements are finalized, all BLOB handles
1354
+** are closed, and all backups have finished. The sqlite3_close_v2() interface
1355
+** is intended for use with host languages that are garbage collected, and
1356
+** where the order in which destructors are called is arbitrary.
13611357
**
13621358
** ^If an [sqlite3] object is destroyed while a transaction is open,
13631359
** the transaction is automatically rolled back.
13641360
**
13651361
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
@@ -1544,22 +1540,25 @@
15441540
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
15451541
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
15461542
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
15471543
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
15481544
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
1545
+#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
15491546
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
15501547
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
15511548
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
15521549
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
1550
+#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
15531551
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
15541552
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
15551553
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
15561554
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
15571555
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
15581556
#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
15591557
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
15601558
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
1559
+#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
15611560
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
15621561
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
15631562
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
15641563
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
15651564
#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
@@ -2150,10 +2149,15 @@
21502149
** a single attached database that occur due to other database connections,
21512150
** but omits changes implemented by the database connection on which it is
21522151
** called. This file control is the only mechanism to detect changes that
21532152
** happen either internally or externally and that are associated with
21542153
** a particular attached database.
2154
+**
2155
+** <li>[[SQLITE_FCNTL_CKPT_START]]
2156
+** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
2157
+** in wal mode before the client starts to copy pages from the wal
2158
+** file to the database file.
21552159
**
21562160
** <li>[[SQLITE_FCNTL_CKPT_DONE]]
21572161
** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
21582162
** in wal mode after the client has finished copying pages from the wal
21592163
** file to the database file, but before the *-shm file is updated to
@@ -2195,10 +2199,11 @@
21952199
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
21962200
#define SQLITE_FCNTL_DATA_VERSION 35
21972201
#define SQLITE_FCNTL_SIZE_LIMIT 36
21982202
#define SQLITE_FCNTL_CKPT_DONE 37
21992203
#define SQLITE_FCNTL_RESERVE_BYTES 38
2204
+#define SQLITE_FCNTL_CKPT_START 39
22002205
22012206
/* deprecated names */
22022207
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
22032208
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
22042209
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -4573,12 +4578,23 @@
45734578
**
45744579
** These are utility routines, useful to [VFS|custom VFS implementations],
45754580
** that check if a database file was a URI that contained a specific query
45764581
** parameter, and if so obtains the value of that query parameter.
45774582
**
4578
-** If F is the database filename pointer passed into the xOpen() method of
4579
-** a VFS implementation or it is the return value of [sqlite3_db_filename()]
4583
+** The first parameter to these interfaces (hereafter referred to
4584
+** as F) must be one of:
4585
+** <ul>
4586
+** <li> A database filename pointer created by the SQLite core and
4587
+** passed into the xOpen() method of a VFS implemention, or
4588
+** <li> A filename obtained from [sqlite3_db_filename()], or
4589
+** <li> A new filename constructed using [sqlite3_create_filename()].
4590
+** </ul>
4591
+** If the F parameter is not one of the above, then the behavior is
4592
+** undefined and probably undesirable. Older versions of SQLite were
4593
+** more tolerant of invalid F parameters than newer versions.
4594
+**
4595
+** If F is a suitable filename (as described in the previous paragraph)
45804596
** and if P is the name of the query parameter, then
45814597
** sqlite3_uri_parameter(F,P) returns the value of the P
45824598
** parameter if it exists or a NULL pointer if P does not appear as a
45834599
** query parameter on F. If P is a query parameter of F and it
45844600
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
@@ -4657,10 +4673,29 @@
46574673
*/
46584674
SQLITE_API const char *sqlite3_filename_database(const char*);
46594675
SQLITE_API const char *sqlite3_filename_journal(const char*);
46604676
SQLITE_API const char *sqlite3_filename_wal(const char*);
46614677
4678
+/*
4679
+** CAPI3REF: Database File Corresponding To A Journal
4680
+**
4681
+** ^If X is the name of a rollback or WAL-mode journal file that is
4682
+** passed into the xOpen method of [sqlite3_vfs], then
4683
+** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
4684
+** object that represents the main database file.
4685
+**
4686
+** This routine is intended for use in custom [VFS] implementations
4687
+** only. It is not a general-purpose interface.
4688
+** The argument sqlite3_file_object(X) must be a filename pointer that
4689
+** has been passed into [sqlite3_vfs].xOpen method where the
4690
+** flags parameter to xOpen contains one of the bits
4691
+** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
4692
+** of this routine results in undefined and probably undesirable
4693
+** behavior.
4694
+*/
4695
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
4696
+
46624697
/*
46634698
** CAPI3REF: Create and Destroy VFS Filenames
46644699
**
46654700
** These interfces are provided for use by [VFS shim] implementations and
46664701
** are not useful outside of that context.
@@ -4691,11 +4726,11 @@
46914726
** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
46924727
** be NULL pointers, though they can be empty strings.
46934728
**
46944729
** The sqlite3_free_filename(Y) routine releases a memory allocation
46954730
** previously obtained from sqlite3_create_filename(). Invoking
4696
-** sqlite3_free_filename(Y) is a NULL pointer is a harmless no-op.
4731
+** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
46974732
**
46984733
** If the Y parameter to sqlite3_free_filename(Y) is anything other
46994734
** than a NULL pointer or a pointer previously acquired from
47004735
** sqlite3_create_filename(), then bad things such as heap
47014736
** corruption or segfaults may occur. The value Y should be
@@ -6497,11 +6532,11 @@
64976532
** when first called if N is less than or equal to zero or if a memory
64986533
** allocate error occurs.
64996534
**
65006535
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
65016536
** determined by the N parameter on first successful call. Changing the
6502
-** value of N in any subsequents call to sqlite3_aggregate_context() within
6537
+** value of N in any subsequent call to sqlite3_aggregate_context() within
65036538
** the same aggregate function instance will not resize the memory
65046539
** allocation.)^ Within the xFinal callback, it is customary to set
65056540
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
65066541
** pointless memory allocations occur.
65076542
**
@@ -14502,11 +14537,10 @@
1450214537
typedef struct BusyHandler BusyHandler;
1450314538
struct BusyHandler {
1450414539
int (*xBusyHandler)(void *,int); /* The busy callback */
1450514540
void *pBusyArg; /* First arg to busy callback */
1450614541
int nBusy; /* Incremented with each busy call */
14507
- u8 bExtraFileArg; /* Include sqlite3_file as callback arg */
1450814542
};
1450914543
1451014544
/*
1451114545
** Name of the master database table. The master database table
1451214546
** is a special table that holds the names and attributes of all
@@ -15022,13 +15056,11 @@
1502215056
#ifndef NDEBUG
1502315057
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
1502415058
#endif
1502515059
SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
1502615060
15027
-#ifndef SQLITE_OMIT_BTREECOUNT
1502815061
SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
15029
-#endif
1503015062
1503115063
#ifdef SQLITE_TEST
1503215064
SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
1503315065
SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
1503415066
#endif
@@ -15599,10 +15631,13 @@
1559915631
1560015632
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
1560115633
SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
1560215634
1560315635
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
15636
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
15637
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
15638
+#endif
1560415639
1560515640
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
1560615641
** each VDBE opcode.
1560715642
**
1560815643
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
@@ -15884,17 +15919,25 @@
1588415919
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
1588515920
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
1588615921
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
1588715922
SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
1588815923
# ifdef SQLITE_ENABLE_SNAPSHOT
15889
-SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
15890
-SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
15924
+SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
15925
+SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot);
1589115926
SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
1589215927
SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
1589315928
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
1589415929
# endif
1589515930
#endif
15931
+
15932
+#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT)
15933
+SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int);
15934
+SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*);
15935
+#else
15936
+# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK
15937
+# define sqlite3PagerWalDb(x,y)
15938
+#endif
1589615939
1589715940
#ifdef SQLITE_DIRECT_OVERFLOW_READ
1589815941
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
1589915942
#endif
1590015943
@@ -15917,15 +15960,10 @@
1591715960
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
1591815961
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
1591915962
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
1592015963
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
1592115964
SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
15922
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
15923
-SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager);
15924
-#else
15925
-# define sqlite3PagerResetLockTimeout(X)
15926
-#endif
1592715965
1592815966
/* Functions used to truncate the database file. */
1592915967
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
1593015968
1593115969
SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
@@ -16855,10 +16893,11 @@
1685516893
Hash aFunc; /* Hash table of connection functions */
1685616894
Hash aCollSeq; /* All collating sequences */
1685716895
BusyHandler busyHandler; /* Busy callback */
1685816896
Db aDbStatic[2]; /* Static space for the 2 default backends */
1685916897
Savepoint *pSavepoint; /* List of active savepoints */
16898
+ int nAnalysisLimit; /* Number of index rows to ANALYZE */
1686016899
int busyTimeout; /* Busy handler timeout, in msec */
1686116900
int nSavepoint; /* Number of non-transaction savepoints */
1686216901
int nStatement; /* Number of nested statement-transactions */
1686316902
i64 nDeferredCons; /* Net deferred constraints this transaction. */
1686416903
i64 nDeferredImmCons; /* Net deferred immediate constraints */
@@ -17080,11 +17119,11 @@
1708017119
#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
1708117120
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
1708217121
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
1708317122
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
1708417123
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
17085
-#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
17124
+/* 0x0200 -- available for reuse */
1708617125
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
1708717126
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
1708817127
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
1708917128
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
1709017129
** single query - might change over time */
@@ -17101,10 +17140,11 @@
1710117140
#define INLINEFUNC_coalesce 0
1710217141
#define INLINEFUNC_implies_nonnull_row 1
1710317142
#define INLINEFUNC_expr_implies_expr 2
1710417143
#define INLINEFUNC_expr_compare 3
1710517144
#define INLINEFUNC_affinity 4
17145
+#define INLINEFUNC_iif 5
1710617146
#define INLINEFUNC_unlikely 99 /* Default case */
1710717147
1710817148
/*
1710917149
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
1711017150
** used to create the initializers for the FuncDef structures.
@@ -17801,11 +17841,11 @@
1780117841
/*
1780217842
** An instance of this structure contains information needed to generate
1780317843
** code for a SELECT that contains aggregate functions.
1780417844
**
1780517845
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
17806
-** pointer to this structure. The Expr.iColumn field is the index in
17846
+** pointer to this structure. The Expr.iAgg field is the index in
1780717847
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
1780817848
** code for that node.
1780917849
**
1781017850
** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
1781117851
** original Select structure that describes the SELECT statement. These
@@ -19040,10 +19080,13 @@
1904019080
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
1904119081
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
1904219082
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
1904319083
SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
1904419084
SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
19085
+SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*);
19086
+SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*);
19087
+
1904519088
#ifdef SQLITE_DEBUG
1904619089
SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
1904719090
#endif
1904819091
1904919092
/*
@@ -19900,11 +19943,11 @@
1990019943
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
1990119944
SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
1990219945
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
1990319946
SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
1990419947
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
19905
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
19948
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
1990619949
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
1990719950
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
1990819951
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
1990919952
SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*);
1991019953
SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
@@ -20025,12 +20068,14 @@
2002520068
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
2002620069
#endif
2002720070
SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
2002820071
#ifndef SQLITE_OMIT_VIRTUALTABLE
2002920072
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
20073
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
2003020074
#else
2003120075
# define sqlite3ShadowTableName(A,B) 0
20076
+# define sqlite3IsShadowTableOf(A,B,C) 0
2003220077
#endif
2003320078
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
2003420079
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
2003520080
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
2003620081
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
@@ -20636,11 +20681,12 @@
2063620681
/*
2063720682
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
2063820683
** "explain" P4 display logic is enabled.
2063920684
*/
2064020685
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
20641
- || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
20686
+ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
20687
+ || defined(SQLITE_ENABLE_BYTECODE_VTAB)
2064220688
# define VDBE_DISPLAY_P4 1
2064320689
#else
2064420690
# define VDBE_DISPLAY_P4 0
2064520691
#endif
2064620692
@@ -21101,11 +21147,18 @@
2110121147
2110221148
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
2110321149
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
2110421150
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
2110521151
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
21106
-#ifndef SQLITE_OMIT_EXPLAIN
21152
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
21153
+SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
21154
+SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
21155
+#endif
21156
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
21157
+SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
21158
+#endif
21159
+#if !defined(SQLITE_OMIT_EXPLAIN)
2110721160
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
2110821161
#endif
2110921162
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
2111021163
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
2111121164
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
@@ -21143,11 +21196,11 @@
2114321196
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
2114421197
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
2114521198
#ifndef SQLITE_OMIT_WINDOWFUNC
2114621199
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
2114721200
#endif
21148
-#ifndef SQLITE_OMIT_EXPLAIN
21201
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
2114921202
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
2115021203
#endif
2115121204
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
2115221205
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
2115321206
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
@@ -27316,11 +27369,11 @@
2731627369
if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
2731727370
n = mem0.hardLimit;
2731827371
}
2731927372
mem0.alarmThreshold = n;
2732027373
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27321
- mem0.nearlyFull = (n>0 && n<=nUsed);
27374
+ AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
2732227375
sqlite3_mutex_leave(mem0.mutex);
2732327376
excess = sqlite3_memory_used() - n;
2732427377
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
2732527378
return priorLimit;
2732627379
}
@@ -27384,11 +27437,11 @@
2738427437
** Return true if the heap is currently under memory pressure - in other
2738527438
** words if the amount of heap used is close to the limit set by
2738627439
** sqlite3_soft_heap_limit().
2738727440
*/
2738827441
SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
27389
- return mem0.nearlyFull;
27442
+ return AtomicLoad(&mem0.nearlyFull);
2739027443
}
2739127444
2739227445
/*
2739327446
** Deinitialize the memory allocation subsystem.
2739427447
*/
@@ -27448,21 +27501,21 @@
2744827501
2744927502
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
2745027503
if( mem0.alarmThreshold>0 ){
2745127504
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
2745227505
if( nUsed >= mem0.alarmThreshold - nFull ){
27453
- mem0.nearlyFull = 1;
27506
+ AtomicStore(&mem0.nearlyFull, 1);
2745427507
sqlite3MallocAlarm(nFull);
2745527508
if( mem0.hardLimit ){
2745627509
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
2745727510
if( nUsed >= mem0.hardLimit - nFull ){
2745827511
*pp = 0;
2745927512
return;
2746027513
}
2746127514
}
2746227515
}else{
27463
- mem0.nearlyFull = 0;
27516
+ AtomicStore(&mem0.nearlyFull, 0);
2746427517
}
2746527518
}
2746627519
p = sqlite3GlobalConfig.m.xMalloc(nFull);
2746727520
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
2746827521
if( p==0 && mem0.alarmThreshold>0 ){
@@ -27687,14 +27740,16 @@
2768727740
if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
2768827741
mem0.alarmThreshold-nDiff ){
2768927742
sqlite3MallocAlarm(nDiff);
2769027743
}
2769127744
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
27745
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
2769227746
if( pNew==0 && mem0.alarmThreshold>0 ){
2769327747
sqlite3MallocAlarm((int)nBytes);
2769427748
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
2769527749
}
27750
+#endif
2769627751
if( pNew ){
2769727752
nNew = sqlite3MallocSize(pNew);
2769827753
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
2769927754
}
2770027755
sqlite3_mutex_leave(mem0.mutex);
@@ -27875,11 +27930,11 @@
2787527930
}
2787627931
}else{
2787727932
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
2787827933
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
2787927934
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
27880
- pNew = sqlite3_realloc64(p, n);
27935
+ pNew = sqlite3Realloc(p, n);
2788127936
if( !pNew ){
2788227937
sqlite3OomFault(db);
2788327938
}
2788427939
sqlite3MemdebugSetType(pNew,
2788527940
(db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
@@ -28222,10 +28277,17 @@
2822228277
#ifndef SQLITE_PRINT_BUF_SIZE
2822328278
# define SQLITE_PRINT_BUF_SIZE 70
2822428279
#endif
2822528280
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
2822628281
28282
+/*
28283
+** Hard limit on the precision of floating-point conversions.
28284
+*/
28285
+#ifndef SQLITE_PRINTF_PRECISION_LIMIT
28286
+# define SQLITE_FP_PRECISION_LIMIT 100000000
28287
+#endif
28288
+
2822728289
/*
2822828290
** Render a string given by "fmt" into the StrAccum object.
2822928291
*/
2823028292
SQLITE_API void sqlite3_str_vappendf(
2823128293
sqlite3_str *pAccum, /* Accumulate results here */
@@ -28422,10 +28484,12 @@
2842228484
** precision The specified precision. The default
2842328485
** is -1.
2842428486
** xtype The class of the conversion.
2842528487
** infop Pointer to the appropriate info struct.
2842628488
*/
28489
+ assert( width>=0 );
28490
+ assert( precision>=(-1) );
2842728491
switch( xtype ){
2842828492
case etPOINTER:
2842928493
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
2843028494
sizeof(char*)==sizeof(long int) ? 1 : 0;
2843128495
/* Fall through into the next case */
@@ -28543,10 +28607,15 @@
2854328607
}
2854428608
#ifdef SQLITE_OMIT_FLOATING_POINT
2854528609
length = 0;
2854628610
#else
2854728611
if( precision<0 ) precision = 6; /* Set default precision */
28612
+#ifdef SQLITE_FP_PRECISION_LIMIT
28613
+ if( precision>SQLITE_FP_PRECISION_LIMIT ){
28614
+ precision = SQLITE_FP_PRECISION_LIMIT;
28615
+ }
28616
+#endif
2854828617
if( realvalue<0.0 ){
2854928618
realvalue = -realvalue;
2855028619
prefix = '-';
2855128620
}else{
2855228621
prefix = flag_prefix;
@@ -28825,11 +28894,11 @@
2882528894
}else{
2882628895
escarg = va_arg(ap,char*);
2882728896
}
2882828897
isnull = escarg==0;
2882928898
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
28830
- /* For %q, %Q, and %w, the precision is the number of byte (or
28899
+ /* For %q, %Q, and %w, the precision is the number of bytes (or
2883128900
** characters if the ! flags is present) to use from the input.
2883228901
** Because of the extra quoting characters inserted, the number
2883328902
** of output characters may be larger than the precision.
2883428903
*/
2883528904
k = precision;
@@ -28952,11 +29021,11 @@
2895229021
p->nAlloc = (int)szNew;
2895329022
}
2895429023
if( p->db ){
2895529024
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
2895629025
}else{
28957
- zNew = sqlite3_realloc64(zOld, p->nAlloc);
29026
+ zNew = sqlite3Realloc(zOld, p->nAlloc);
2895829027
}
2895929028
if( zNew ){
2896029029
assert( p->zText!=0 || p->nChar==0 );
2896129030
if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
2896229031
p->zText = zNew;
@@ -29294,11 +29363,11 @@
2929429363
** and segfaults if you give it a long long int.
2929529364
*/
2929629365
SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
2929729366
va_list ap;
2929829367
StrAccum acc;
29299
- char zBuf[500];
29368
+ char zBuf[SQLITE_PRINT_BUF_SIZE*10];
2930029369
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
2930129370
va_start(ap,zFormat);
2930229371
sqlite3_str_vappendf(&acc, zFormat, ap);
2930329372
va_end(ap);
2930429373
sqlite3StrAccumFinish(&acc);
@@ -29910,12 +29979,13 @@
2991029979
#else
2991129980
pWin = 0;
2991229981
#endif
2991329982
}
2991429983
if( pExpr->op==TK_AGG_FUNCTION ){
29915
- sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s",
29916
- pExpr->op2, pExpr->u.zToken, zFlgs);
29984
+ sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s iAgg=%d agg=%p",
29985
+ pExpr->op2, pExpr->u.zToken, zFlgs,
29986
+ pExpr->iAgg, pExpr->pAggInfo);
2991729987
}else if( pExpr->op2!=0 ){
2991829988
const char *zOp2;
2991929989
char zBuf[8];
2992029990
sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
2992129991
zOp2 = zBuf;
@@ -30804,10 +30874,11 @@
3080430874
/* UTF-16 Little-endian -> UTF-8 */
3080530875
while( zIn<zTerm ){
3080630876
c = *(zIn++);
3080730877
c += (*(zIn++))<<8;
3080830878
if( c>=0xd800 && c<0xe000 ){
30879
+#ifdef SQLITE_REPLACE_INVALID_UTF
3080930880
if( c>=0xdc00 || zIn>=zTerm ){
3081030881
c = 0xfffd;
3081130882
}else{
3081230883
int c2 = *(zIn++);
3081330884
c2 += (*(zIn++))<<8;
@@ -30816,19 +30887,27 @@
3081630887
c = 0xfffd;
3081730888
}else{
3081830889
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
3081930890
}
3082030891
}
30892
+#else
30893
+ if( zIn<zTerm ){
30894
+ int c2 = (*zIn++);
30895
+ c2 += ((*zIn++)<<8);
30896
+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
30897
+ }
30898
+#endif
3082130899
}
3082230900
WRITE_UTF8(z, c);
3082330901
}
3082430902
}else{
3082530903
/* UTF-16 Big-endian -> UTF-8 */
3082630904
while( zIn<zTerm ){
3082730905
c = (*(zIn++))<<8;
3082830906
c += *(zIn++);
3082930907
if( c>=0xd800 && c<0xe000 ){
30908
+#ifdef SQLITE_REPLACE_INVALID_UTF
3083030909
if( c>=0xdc00 || zIn>=zTerm ){
3083130910
c = 0xfffd;
3083230911
}else{
3083330912
int c2 = (*(zIn++))<<8;
3083430913
c2 += *(zIn++);
@@ -30837,10 +30916,17 @@
3083730916
c = 0xfffd;
3083830917
}else{
3083930918
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
3084030919
}
3084130920
}
30921
+#else
30922
+ if( zIn<zTerm ){
30923
+ int c2 = ((*zIn++)<<8);
30924
+ c2 += (*zIn++);
30925
+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
30926
+ }
30927
+#endif
3084230928
}
3084330929
WRITE_UTF8(z, c);
3084430930
}
3084530931
}
3084630932
pMem->n = (int)(z - zOut);
@@ -34928,20 +35014,21 @@
3492835014
static int osSetPosixAdvisoryLock(
3492935015
int h, /* The file descriptor on which to take the lock */
3493035016
struct flock *pLock, /* The description of the lock */
3493135017
unixFile *pFile /* Structure holding timeout value */
3493235018
){
35019
+ int tm = pFile->iBusyTimeout;
3493335020
int rc = osFcntl(h,F_SETLK,pLock);
34934
- while( rc<0 && pFile->iBusyTimeout>0 ){
35021
+ while( rc<0 && tm>0 ){
3493535022
/* On systems that support some kind of blocking file lock with a timeout,
3493635023
** make appropriate changes here to invoke that blocking file lock. On
3493735024
** generic posix, however, there is no such API. So we simply try the
3493835025
** lock once every millisecond until either the timeout expires, or until
3493935026
** the lock is obtained. */
3494035027
usleep(1000);
3494135028
rc = osFcntl(h,F_SETLK,pLock);
34942
- pFile->iBusyTimeout--;
35029
+ tm--;
3494335030
}
3494435031
return rc;
3494535032
}
3494635033
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
3494735034
@@ -37679,17 +37766,24 @@
3767937766
3768037767
/* Locks are within range */
3768137768
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
3768237769
3768337770
if( pShmNode->hShm>=0 ){
37771
+ int res;
3768437772
/* Initialize the locking parameters */
3768537773
f.l_type = lockType;
3768637774
f.l_whence = SEEK_SET;
3768737775
f.l_start = ofst;
3768837776
f.l_len = n;
37689
- rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
37690
- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
37777
+ res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
37778
+ if( res==-1 ){
37779
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
37780
+ rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
37781
+#else
37782
+ rc = SQLITE_BUSY;
37783
+#endif
37784
+ }
3769137785
}
3769237786
3769337787
/* Update the global lock state and do debug tracing */
3769437788
#ifdef SQLITE_DEBUG
3769537789
{ u16 mask;
@@ -38182,26 +38276,27 @@
3818238276
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
3818338277
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
3818438278
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
3818538279
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
3818638280
38187
- /* Check that, if this to be a blocking lock, that locks have been
38188
- ** obtained in the following order.
38281
+ /* Check that, if this to be a blocking lock, no locks that occur later
38282
+ ** in the following list than the lock being obtained are already held:
3818938283
**
3819038284
** 1. Checkpointer lock (ofst==1).
38191
- ** 2. Recover lock (ofst==2).
38285
+ ** 2. Write lock (ofst==0).
3819238286
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
38193
- ** 4. Write lock (ofst==0).
3819438287
**
3819538288
** In other words, if this is a blocking lock, none of the locks that
3819638289
** occur later in the above list than the lock being obtained may be
3819738290
** held. */
3819838291
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
38199
- assert( pDbFd->iBusyTimeout==0
38200
- || (flags & SQLITE_SHM_UNLOCK) || ofst==0
38201
- || ((p->exclMask|p->sharedMask)&~((1<<ofst)-2))==0
38202
- );
38292
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
38293
+ (ofst!=2) /* not RECOVER */
38294
+ && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
38295
+ && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
38296
+ && (ofst<3 || (p->exclMask|p->sharedMask)<(1<<ofst))
38297
+ ));
3820338298
#endif
3820438299
3820538300
mask = (1<<(ofst+n)) - (1<<ofst);
3820638301
assert( n>1 || mask==(1<<ofst) );
3820738302
sqlite3_mutex_enter(pShmNode->pShmMutex);
@@ -44990,10 +45085,11 @@
4499045085
}
4499145086
4499245087
/* Forward references to VFS helper methods used for temporary files */
4499345088
static int winGetTempname(sqlite3_vfs *, char **);
4499445089
static int winIsDir(const void *);
45090
+static BOOL winIsLongPathPrefix(const char *);
4499545091
static BOOL winIsDriveLetterAndColon(const char *);
4499645092
4499745093
/*
4499845094
** Control and query of the open file handle.
4499945095
*/
@@ -46759,11 +46855,13 @@
4675946855
pFile->pVfs = pVfs;
4676046856
pFile->h = h;
4676146857
if( isReadonly ){
4676246858
pFile->ctrlFlags |= WINFILE_RDONLY;
4676346859
}
46764
- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
46860
+ if( (flags & SQLITE_OPEN_MAIN_DB)
46861
+ && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
46862
+ ){
4676546863
pFile->ctrlFlags |= WINFILE_PSOW;
4676646864
}
4676746865
pFile->lastErrno = NO_ERROR;
4676846866
pFile->zPath = zName;
4676946867
#if SQLITE_MAX_MMAP_SIZE>0
@@ -46968,10 +47066,21 @@
4696847066
*pResOut = rc;
4696947067
OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
4697047068
zFilename, pResOut, *pResOut));
4697147069
return SQLITE_OK;
4697247070
}
47071
+
47072
+/*
47073
+** Returns non-zero if the specified path name starts with the "long path"
47074
+** prefix.
47075
+*/
47076
+static BOOL winIsLongPathPrefix(
47077
+ const char *zPathname
47078
+){
47079
+ return ( zPathname[0]=='\\' && zPathname[1]=='\\'
47080
+ && zPathname[2]=='?' && zPathname[3]=='\\' );
47081
+}
4697347082
4697447083
/*
4697547084
** Returns non-zero if the specified path name starts with a drive letter
4697647085
** followed by a colon character.
4697747086
*/
@@ -47033,14 +47142,15 @@
4703347142
DWORD nByte;
4703447143
void *zConverted;
4703547144
char *zOut;
4703647145
#endif
4703747146
47038
- /* If this path name begins with "/X:", where "X" is any alphabetic
47039
- ** character, discard the initial "/" from the pathname.
47147
+ /* If this path name begins with "/X:" or "\\?\", where "X" is any
47148
+ ** alphabetic character, discard the initial "/" from the pathname.
4704047149
*/
47041
- if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
47150
+ if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
47151
+ || winIsLongPathPrefix(zRelative+1)) ){
4704247152
zRelative++;
4704347153
}
4704447154
4704547155
#if defined(__CYGWIN__)
4704647156
SimulateIOError( return SQLITE_ERROR );
@@ -47792,11 +47902,11 @@
4779247902
if( newSz>p->szMax ){
4779347903
return SQLITE_FULL;
4779447904
}
4779547905
newSz *= 2;
4779647906
if( newSz>p->szMax ) newSz = p->szMax;
47797
- pNew = sqlite3_realloc64(p->aData, newSz);
47907
+ pNew = sqlite3Realloc(p->aData, newSz);
4779847908
if( pNew==0 ) return SQLITE_NOMEM;
4779947909
p->aData = pNew;
4780047910
p->szAlloc = newSz;
4780147911
return SQLITE_OK;
4780247912
}
@@ -48239,14 +48349,15 @@
4823948349
*/
4824048350
SQLITE_PRIVATE int sqlite3MemdbInit(void){
4824148351
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
4824248352
int sz = pLower->szOsFile;
4824348353
memdb_vfs.pAppData = pLower;
48244
- /* In all known configurations of SQLite, the size of a default
48245
- ** sqlite3_file is greater than the size of a memdb sqlite3_file.
48246
- ** Should that ever change, remove the following NEVER() */
48247
- if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
48354
+ /* The following conditional can only be true when compiled for
48355
+ ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
48356
+ ** it in, to be safe, but it is marked as NO_TEST since there
48357
+ ** is no way to reach it under most builds. */
48358
+ if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
4824848359
memdb_vfs.szOsFile = sz;
4824948360
return sqlite3_vfs_register(&memdb_vfs, 0);
4825048361
}
4825148362
#endif /* SQLITE_ENABLE_DESERIALIZE */
4825248363
@@ -51505,10 +51616,15 @@
5150551616
SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
5150651617
#endif
5150751618
5150851619
/* Return the sqlite3_file object for the WAL file */
5150951620
SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
51621
+
51622
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
51623
+SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
51624
+SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
51625
+#endif
5151051626
5151151627
#endif /* ifndef SQLITE_OMIT_WAL */
5151251628
#endif /* SQLITE_WAL_H */
5151351629
5151451630
/************** End of wal.h *************************************************/
@@ -54026,13 +54142,16 @@
5402654142
}
5402754143
if( exists ){
5402854144
/* One of the journals pointed to by the master journal exists.
5402954145
** Open it and check if it points at the master journal. If
5403054146
** so, return without deleting the master journal file.
54147
+ ** NB: zJournal is really a MAIN_JOURNAL. But call it a
54148
+ ** MASTER_JOURNAL here so that the VFS will not send the zJournal
54149
+ ** name into sqlite3_database_file_object().
5403154150
*/
5403254151
int c;
54033
- int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
54152
+ int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
5403454153
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
5403554154
if( rc!=SQLITE_OK ){
5403654155
goto delmaster_out;
5403754156
}
5403854157
@@ -56232,10 +56351,11 @@
5623256351
** Pager object (sizeof(Pager) bytes)
5623356352
** PCache object (sqlite3PcacheSize() bytes)
5623456353
** Database file handle (pVfs->szOsFile bytes)
5623556354
** Sub-journal file handle (journalFileSize bytes)
5623656355
** Main journal file handle (journalFileSize bytes)
56356
+ ** Ptr back to the Pager (sizeof(Pager*) bytes)
5623756357
** \0\0\0\0 database prefix (4 bytes)
5623856358
** Database file name (nPathname+1 bytes)
5623956359
** URI query parameters (nUriByte bytes)
5624056360
** Journal filename (nPathname+8+1 bytes)
5624156361
** WAL filename (nPathname+4+1 bytes)
@@ -56271,10 +56391,11 @@
5627156391
pPtr = (u8 *)sqlite3MallocZero(
5627256392
ROUND8(sizeof(*pPager)) + /* Pager structure */
5627356393
ROUND8(pcacheSize) + /* PCache object */
5627456394
ROUND8(pVfs->szOsFile) + /* The main db file */
5627556395
journalFileSize * 2 + /* The two journal files */
56396
+ sizeof(pPager) + /* Space to hold a pointer */
5627656397
4 + /* Database prefix */
5627756398
nPathname + 1 + /* database filename */
5627856399
nUriByte + /* query parameters */
5627956400
nPathname + 8 + 1 + /* Journal filename */
5628056401
#ifndef SQLITE_OMIT_WAL
@@ -56291,10 +56412,11 @@
5629156412
pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
5629256413
pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
5629356414
pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
5629456415
pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
5629556416
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
56417
+ memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager);
5629656418
5629756419
/* Fill in the Pager.zFilename and pPager.zQueryParam fields */
5629856420
pPtr += 4; /* Skip zero prefix */
5629956421
pPager->zFilename = (char*)pPtr;
5630056422
if( nPathname>0 ){
@@ -56491,10 +56613,23 @@
5649156613
5649256614
*ppPager = pPager;
5649356615
return SQLITE_OK;
5649456616
}
5649556617
56618
+/*
56619
+** Return the sqlite3_file for the main database given the name
56620
+** of the corresonding WAL or Journal name as passed into
56621
+** xOpen.
56622
+*/
56623
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){
56624
+ Pager *pPager;
56625
+ while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
56626
+ zName--;
56627
+ }
56628
+ pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
56629
+ return pPager->fd;
56630
+}
5649656631
5649756632
5649856633
/*
5649956634
** This function is called after transitioning from PAGER_UNLOCK to
5650056635
** PAGER_SHARED state. It tests if there is a hot journal present in
@@ -57176,11 +57311,10 @@
5717657311
Pager *pPager;
5717757312
assert( pPg!=0 );
5717857313
assert( pPg->pgno==1 );
5717957314
assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
5718057315
pPager = pPg->pPager;
57181
- sqlite3PagerResetLockTimeout(pPager);
5718257316
sqlite3PcacheRelease(pPg);
5718357317
pagerUnlockIfUnused(pPager);
5718457318
}
5718557319
5718657320
/*
@@ -58469,20 +58603,10 @@
5846958603
*/
5847058604
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
5847158605
return pPager->fd;
5847258606
}
5847358607
58474
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
58475
-/*
58476
-** Reset the lock timeout for pager.
58477
-*/
58478
-SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){
58479
- int x = 0;
58480
- sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
58481
-}
58482
-#endif
58483
-
5848458608
/*
5848558609
** Return the file handle for the journal file (if it exists).
5848658610
** This will be either the rollback journal or the WAL file.
5848758611
*/
5848858612
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
@@ -58892,11 +59016,10 @@
5889259016
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
5889359017
pPager->pBusyHandlerArg,
5889459018
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
5889559019
pnLog, pnCkpt
5889659020
);
58897
- sqlite3PagerResetLockTimeout(pPager);
5889859021
}
5889959022
return rc;
5890059023
}
5890159024
5890259025
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
@@ -59057,11 +59180,35 @@
5905759180
}
5905859181
}
5905959182
return rc;
5906059183
}
5906159184
59185
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
59186
+/*
59187
+** If pager pPager is a wal-mode database not in exclusive locking mode,
59188
+** invoke the sqlite3WalWriteLock() function on the associated Wal object
59189
+** with the same db and bLock parameters as were passed to this function.
59190
+** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
59191
+*/
59192
+SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
59193
+ int rc = SQLITE_OK;
59194
+ if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){
59195
+ rc = sqlite3WalWriteLock(pPager->pWal, bLock);
59196
+ }
59197
+ return rc;
59198
+}
5906259199
59200
+/*
59201
+** Set the database handle used by the wal layer to determine if
59202
+** blocking locks are required.
59203
+*/
59204
+SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
59205
+ if( pagerUseWal(pPager) ){
59206
+ sqlite3WalDb(pPager->pWal, db);
59207
+ }
59208
+}
59209
+#endif
5906359210
5906459211
#ifdef SQLITE_ENABLE_SNAPSHOT
5906559212
/*
5906659213
** If this is a WAL database, obtain a snapshot handle for the snapshot
5906759214
** currently open. Otherwise, return an error.
@@ -59077,11 +59224,14 @@
5907759224
/*
5907859225
** If this is a WAL database, store a pointer to pSnapshot. Next time a
5907959226
** read transaction is opened, attempt to read from the snapshot it
5908059227
** identifies. If this is not a WAL database, return an error.
5908159228
*/
59082
-SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
59229
+SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(
59230
+ Pager *pPager,
59231
+ sqlite3_snapshot *pSnapshot
59232
+){
5908359233
int rc = SQLITE_OK;
5908459234
if( pPager->pWal ){
5908559235
sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
5908659236
}else{
5908759237
rc = SQLITE_ERROR;
@@ -59622,10 +59772,13 @@
5962259772
u8 lockError; /* True if a locking error has occurred */
5962359773
#endif
5962459774
#ifdef SQLITE_ENABLE_SNAPSHOT
5962559775
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
5962659776
#endif
59777
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
59778
+ sqlite3 *db;
59779
+#endif
5962759780
};
5962859781
5962959782
/*
5963059783
** Candidate values for Wal.exclusiveMode.
5963159784
*/
@@ -59720,11 +59873,11 @@
5972059873
5972159874
/* Enlarge the pWal->apWiData[] array if required */
5972259875
if( pWal->nWiData<=iPage ){
5972359876
sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
5972459877
volatile u32 **apNew;
59725
- apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
59878
+ apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
5972659879
if( !apNew ){
5972759880
*ppPage = 0;
5972859881
return SQLITE_NOMEM_BKPT;
5972959882
}
5973059883
memset((void*)&apNew[pWal->nWiData], 0,
@@ -59841,29 +59994,47 @@
5984159994
5984259995
aOut[0] = s1;
5984359996
aOut[1] = s2;
5984459997
}
5984559998
59999
+/*
60000
+** If there is the possibility of concurrent access to the SHM file
60001
+** from multiple threads and/or processes, then do a memory barrier.
60002
+*/
5984660003
static void walShmBarrier(Wal *pWal){
5984760004
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
5984860005
sqlite3OsShmBarrier(pWal->pDbFd);
5984960006
}
5985060007
}
5985160008
60009
+/*
60010
+** Add the SQLITE_NO_TSAN as part of the return-type of a function
60011
+** definition as a hint that the function contains constructs that
60012
+** might give false-positive TSAN warnings.
60013
+**
60014
+** See tag-20200519-1.
60015
+*/
60016
+#if defined(__clang__) && !defined(SQLITE_NO_TSAN)
60017
+# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
60018
+#else
60019
+# define SQLITE_NO_TSAN
60020
+#endif
60021
+
5985260022
/*
5985360023
** Write the header information in pWal->hdr into the wal-index.
5985460024
**
5985560025
** The checksum on pWal->hdr is updated before it is written.
5985660026
*/
59857
-static void walIndexWriteHdr(Wal *pWal){
60027
+static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
5985860028
volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
5985960029
const int nCksum = offsetof(WalIndexHdr, aCksum);
5986060030
5986160031
assert( pWal->writeLock );
5986260032
pWal->hdr.isInit = 1;
5986360033
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
5986460034
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
60035
+ /* Possible TSAN false-positive. See tag-20200519-1 */
5986560036
memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
5986660037
walShmBarrier(pWal);
5986760038
memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
5986860039
}
5986960040
@@ -59995,11 +60166,11 @@
5999560166
if( pWal->exclusiveMode ) return SQLITE_OK;
5999660167
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
5999760168
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
5999860169
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
5999960170
walLockName(lockIdx), rc ? "failed" : "ok"));
60000
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
60171
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
6000160172
return rc;
6000260173
}
6000360174
static void walUnlockShared(Wal *pWal, int lockIdx){
6000460175
if( pWal->exclusiveMode ) return;
6000560176
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
@@ -60011,11 +60182,11 @@
6001160182
if( pWal->exclusiveMode ) return SQLITE_OK;
6001260183
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
6001360184
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
6001460185
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
6001560186
walLockName(lockIdx), n, rc ? "failed" : "ok"));
60016
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
60187
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
6001760188
return rc;
6001860189
}
6001960190
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
6002060191
if( pWal->exclusiveMode ) return;
6002160192
(void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
@@ -60283,15 +60454,10 @@
6028360454
int rc; /* Return Code */
6028460455
i64 nSize; /* Size of log file */
6028560456
u32 aFrameCksum[2] = {0, 0};
6028660457
int iLock; /* Lock offset to lock for checkpoint */
6028760458
60288
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
60289
- int tmout = 0;
60290
- sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
60291
-#endif
60292
-
6029360459
/* Obtain an exclusive lock on all byte in the locking range not already
6029460460
** locked by the caller. The caller is guaranteed to have locked the
6029560461
** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
6029660462
** If successful, the same bytes that are locked here are unlocked before
6029760463
** this function returns.
@@ -60835,10 +61001,93 @@
6083561001
p = 0;
6083661002
}
6083761003
*pp = p;
6083861004
return rc;
6083961005
}
61006
+
61007
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61008
+/*
61009
+** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
61010
+** they are supported by the VFS, and (b) the database handle is configured
61011
+** with a busy-timeout. Return 1 if blocking locks are successfully enabled,
61012
+** or 0 otherwise.
61013
+*/
61014
+static int walEnableBlocking(Wal *pWal){
61015
+ int res = 0;
61016
+ if( pWal->db ){
61017
+ int tmout = pWal->db->busyTimeout;
61018
+ if( tmout ){
61019
+ int rc;
61020
+ rc = sqlite3OsFileControl(
61021
+ pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
61022
+ );
61023
+ res = (rc==SQLITE_OK);
61024
+ }
61025
+ }
61026
+ return res;
61027
+}
61028
+
61029
+/*
61030
+** Disable blocking locks.
61031
+*/
61032
+static void walDisableBlocking(Wal *pWal){
61033
+ int tmout = 0;
61034
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
61035
+}
61036
+
61037
+/*
61038
+** If parameter bLock is true, attempt to enable blocking locks, take
61039
+** the WRITER lock, and then disable blocking locks. If blocking locks
61040
+** cannot be enabled, no attempt to obtain the WRITER lock is made. Return
61041
+** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not
61042
+** an error if blocking locks can not be enabled.
61043
+**
61044
+** If the bLock parameter is false and the WRITER lock is held, release it.
61045
+*/
61046
+SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock){
61047
+ int rc = SQLITE_OK;
61048
+ assert( pWal->readLock<0 || bLock==0 );
61049
+ if( bLock ){
61050
+ assert( pWal->db );
61051
+ if( walEnableBlocking(pWal) ){
61052
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
61053
+ if( rc==SQLITE_OK ){
61054
+ pWal->writeLock = 1;
61055
+ }
61056
+ walDisableBlocking(pWal);
61057
+ }
61058
+ }else if( pWal->writeLock ){
61059
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
61060
+ pWal->writeLock = 0;
61061
+ }
61062
+ return rc;
61063
+}
61064
+
61065
+/*
61066
+** Set the database handle used to determine if blocking locks are required.
61067
+*/
61068
+SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
61069
+ pWal->db = db;
61070
+}
61071
+
61072
+/*
61073
+** Take an exclusive WRITE lock. Blocking if so configured.
61074
+*/
61075
+static int walLockWriter(Wal *pWal){
61076
+ int rc;
61077
+ walEnableBlocking(pWal);
61078
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
61079
+ walDisableBlocking(pWal);
61080
+ return rc;
61081
+}
61082
+#else
61083
+# define walEnableBlocking(x) 0
61084
+# define walDisableBlocking(x)
61085
+# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
61086
+# define sqlite3WalDb(pWal, db)
61087
+#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
61088
+
6084061089
6084161090
/*
6084261091
** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
6084361092
** n. If the attempt fails and parameter xBusy is not NULL, then it is a
6084461093
** busy-handler function. Invoke it and retry the lock until either the
@@ -60853,10 +61102,16 @@
6085361102
){
6085461103
int rc;
6085561104
do {
6085661105
rc = walLockExclusive(pWal, lockIdx, n);
6085761106
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
61107
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61108
+ if( rc==SQLITE_BUSY_TIMEOUT ){
61109
+ walDisableBlocking(pWal);
61110
+ rc = SQLITE_BUSY;
61111
+ }
61112
+#endif
6085861113
return rc;
6085961114
}
6086061115
6086161116
/*
6086261117
** The cache of the wal-index header must be valid to call this function.
@@ -60890,11 +61145,11 @@
6089061145
pWal->nCkpt++;
6089161146
pWal->hdr.mxFrame = 0;
6089261147
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
6089361148
memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
6089461149
walIndexWriteHdr(pWal);
60895
- pInfo->nBackfill = 0;
61150
+ AtomicStore(&pInfo->nBackfill, 0);
6089661151
pInfo->nBackfillAttempted = 0;
6089761152
pInfo->aReadMark[1] = 0;
6089861153
for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
6089961154
assert( pInfo->aReadMark[0]==0 );
6090061155
}
@@ -60965,36 +61220,17 @@
6096561220
** cannot be backfilled from the WAL.
6096661221
*/
6096761222
mxSafeFrame = pWal->hdr.mxFrame;
6096861223
mxPage = pWal->hdr.nPage;
6096961224
for(i=1; i<WAL_NREADER; i++){
60970
- /* Thread-sanitizer reports that the following is an unsafe read,
60971
- ** as some other thread may be in the process of updating the value
60972
- ** of the aReadMark[] slot. The assumption here is that if that is
60973
- ** happening, the other client may only be increasing the value,
60974
- ** not decreasing it. So assuming either that either the "old" or
60975
- ** "new" version of the value is read, and not some arbitrary value
60976
- ** that would never be written by a real client, things are still
60977
- ** safe.
60978
- **
60979
- ** Astute readers have pointed out that the assumption stated in the
60980
- ** last sentence of the previous paragraph is not guaranteed to be
60981
- ** true for all conforming systems. However, the assumption is true
60982
- ** for all compilers and architectures in common use today (circa
60983
- ** 2019-11-27) and the alternatives are both slow and complex, and
60984
- ** so we will continue to go with the current design for now. If this
60985
- ** bothers you, or if you really are running on a system where aligned
60986
- ** 32-bit reads and writes are not atomic, then you can simply avoid
60987
- ** the use of WAL mode, or only use WAL mode together with
60988
- ** PRAGMA locking_mode=EXCLUSIVE and all will be well.
60989
- */
60990
- u32 y = pInfo->aReadMark[i];
61225
+ u32 y = AtomicLoad(pInfo->aReadMark+i);
6099161226
if( mxSafeFrame>y ){
6099261227
assert( y<=pWal->hdr.mxFrame );
6099361228
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
6099461229
if( rc==SQLITE_OK ){
60995
- pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
61230
+ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
61231
+ AtomicStore(pInfo->aReadMark+i, iMark);
6099661232
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
6099761233
}else if( rc==SQLITE_BUSY ){
6099861234
mxSafeFrame = y;
6099961235
xBusy = 0;
6100061236
}else{
@@ -61008,11 +61244,11 @@
6100861244
rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
6100961245
assert( rc==SQLITE_OK || pIter==0 );
6101061246
}
6101161247
6101261248
if( pIter
61013
- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
61249
+ && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
6101461250
){
6101561251
u32 nBackfill = pInfo->nBackfill;
6101661252
6101761253
pInfo->nBackfillAttempted = mxSafeFrame;
6101861254
@@ -61023,10 +61259,11 @@
6102361259
** about the eventual size of the db file to the VFS layer.
6102461260
*/
6102561261
if( rc==SQLITE_OK ){
6102661262
i64 nReq = ((i64)mxPage * szPage);
6102761263
i64 nSize; /* Current size of database file */
61264
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
6102861265
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
6102961266
if( rc==SQLITE_OK && nSize<nReq ){
6103061267
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
6103161268
}
6103261269
}
@@ -61050,10 +61287,11 @@
6105061287
iOffset = (iDbpage-1)*(i64)szPage;
6105161288
testcase( IS_BIG_INT(iOffset) );
6105261289
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
6105361290
if( rc!=SQLITE_OK ) break;
6105461291
}
61292
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
6105561293
6105661294
/* If work was actually accomplished... */
6105761295
if( rc==SQLITE_OK ){
6105861296
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
6105961297
i64 szDb = pWal->hdr.nPage*(i64)szPage;
@@ -61062,15 +61300,11 @@
6106261300
if( rc==SQLITE_OK ){
6106361301
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
6106461302
}
6106561303
}
6106661304
if( rc==SQLITE_OK ){
61067
- rc = sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
61068
- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
61069
- }
61070
- if( rc==SQLITE_OK ){
61071
- pInfo->nBackfill = mxSafeFrame;
61305
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame);
6107261306
}
6107361307
}
6107461308
6107561309
/* Release the reader lock held while backfilling */
6107661310
walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
@@ -61225,11 +61459,11 @@
6122561459
** and *pChanged is set to 1.
6122661460
**
6122761461
** If the checksum cannot be verified return non-zero. If the header
6122861462
** is read successfully and the checksum verified, return zero.
6122961463
*/
61230
-static int walIndexTryHdr(Wal *pWal, int *pChanged){
61464
+static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
6123161465
u32 aCksum[2]; /* Checksum on the header content */
6123261466
WalIndexHdr h1, h2; /* Two copies of the header content */
6123361467
WalIndexHdr volatile *aHdr; /* Header in shared memory */
6123461468
6123561469
/* The first page of the wal-index must be mapped at this point. */
@@ -61238,17 +61472,23 @@
6123861472
/* Read the header. This might happen concurrently with a write to the
6123961473
** same area of shared memory on a different CPU in a SMP,
6124061474
** meaning it is possible that an inconsistent snapshot is read
6124161475
** from the file. If this happens, return non-zero.
6124261476
**
61477
+ ** tag-20200519-1:
6124361478
** There are two copies of the header at the beginning of the wal-index.
6124461479
** When reading, read [0] first then [1]. Writes are in the reverse order.
6124561480
** Memory barriers are used to prevent the compiler or the hardware from
61246
- ** reordering the reads and writes.
61481
+ ** reordering the reads and writes. TSAN and similar tools can sometimes
61482
+ ** give false-positive warnings about these accesses because the tools do not
61483
+ ** account for the double-read and the memory barrier. The use of mutexes
61484
+ ** here would be problematic as the memory being accessed is potentially
61485
+ ** shared among multiple processes and not all mutex implementions work
61486
+ ** reliably in that environment.
6124761487
*/
6124861488
aHdr = walIndexHdr(pWal);
61249
- memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
61489
+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
6125061490
walShmBarrier(pWal);
6125161491
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
6125261492
6125361493
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
6125461494
return 1; /* Dirty read */
@@ -61334,32 +61574,36 @@
6133461574
badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
6133561575
6133661576
/* If the first attempt failed, it might have been due to a race
6133761577
** with a writer. So get a WRITE lock and try again.
6133861578
*/
61339
- assert( badHdr==0 || pWal->writeLock==0 );
6134061579
if( badHdr ){
6134161580
if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
6134261581
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
6134361582
walUnlockShared(pWal, WAL_WRITE_LOCK);
6134461583
rc = SQLITE_READONLY_RECOVERY;
6134561584
}
61346
- }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
61347
- pWal->writeLock = 1;
61348
- if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
61349
- badHdr = walIndexTryHdr(pWal, pChanged);
61350
- if( badHdr ){
61351
- /* If the wal-index header is still malformed even while holding
61352
- ** a WRITE lock, it can only mean that the header is corrupted and
61353
- ** needs to be reconstructed. So run recovery to do exactly that.
61354
- */
61355
- rc = walIndexRecover(pWal);
61356
- *pChanged = 1;
61357
- }
61358
- }
61359
- pWal->writeLock = 0;
61360
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
61585
+ }else{
61586
+ int bWriteLock = pWal->writeLock;
61587
+ if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
61588
+ pWal->writeLock = 1;
61589
+ if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
61590
+ badHdr = walIndexTryHdr(pWal, pChanged);
61591
+ if( badHdr ){
61592
+ /* If the wal-index header is still malformed even while holding
61593
+ ** a WRITE lock, it can only mean that the header is corrupted and
61594
+ ** needs to be reconstructed. So run recovery to do exactly that.
61595
+ */
61596
+ rc = walIndexRecover(pWal);
61597
+ *pChanged = 1;
61598
+ }
61599
+ }
61600
+ if( bWriteLock==0 ){
61601
+ pWal->writeLock = 0;
61602
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
61603
+ }
61604
+ }
6136161605
}
6136261606
}
6136361607
6136461608
/* If the header is read successfully, check the version number to make
6136561609
** sure the wal-index was not constructed with some future format that
@@ -61685,11 +61929,11 @@
6168561929
}
6168661930
6168761931
assert( pWal->nWiData>0 );
6168861932
assert( pWal->apWiData[0]!=0 );
6168961933
pInfo = walCkptInfo(pWal);
61690
- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
61934
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
6169161935
#ifdef SQLITE_ENABLE_SNAPSHOT
6169261936
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
6169361937
#endif
6169461938
){
6169561939
/* The WAL has been completely backfilled (or it is empty).
@@ -61852,11 +62096,11 @@
6185262096
void *pBuf2 = sqlite3_malloc(szPage);
6185362097
if( pBuf1==0 || pBuf2==0 ){
6185462098
rc = SQLITE_NOMEM;
6185562099
}else{
6185662100
u32 i = pInfo->nBackfillAttempted;
61857
- for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
62101
+ for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
6185862102
WalHashLoc sLoc; /* Hash table location */
6185962103
u32 pgno; /* Page number in db file */
6186062104
i64 iDbOff; /* Offset of db file entry */
6186162105
i64 iWalOff; /* Offset of wal file entry */
6186262106
@@ -61907,26 +62151,40 @@
6190762151
** needs to be flushed.
6190862152
*/
6190962153
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
6191062154
int rc; /* Return code */
6191162155
int cnt = 0; /* Number of TryBeginRead attempts */
61912
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61913
- int tmout = 0;
61914
-#endif
61915
-
6191662156
#ifdef SQLITE_ENABLE_SNAPSHOT
6191762157
int bChanged = 0;
6191862158
WalIndexHdr *pSnapshot = pWal->pSnapshot;
61919
- if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
61920
- bChanged = 1;
61921
- }
6192262159
#endif
6192362160
61924
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61925
- /* Disable blocking locks. They are not useful when trying to open a
61926
- ** read-transaction, and blocking may cause deadlock anyway. */
61927
- sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
62161
+ assert( pWal->ckptLock==0 );
62162
+
62163
+#ifdef SQLITE_ENABLE_SNAPSHOT
62164
+ if( pSnapshot ){
62165
+ if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
62166
+ bChanged = 1;
62167
+ }
62168
+
62169
+ /* It is possible that there is a checkpointer thread running
62170
+ ** concurrent with this code. If this is the case, it may be that the
62171
+ ** checkpointer has already determined that it will checkpoint
62172
+ ** snapshot X, where X is later in the wal file than pSnapshot, but
62173
+ ** has not yet set the pInfo->nBackfillAttempted variable to indicate
62174
+ ** its intent. To avoid the race condition this leads to, ensure that
62175
+ ** there is no checkpointer process by taking a shared CKPT lock
62176
+ ** before checking pInfo->nBackfillAttempted. */
62177
+ (void)walEnableBlocking(pWal);
62178
+ rc = walLockShared(pWal, WAL_CKPT_LOCK);
62179
+ walDisableBlocking(pWal);
62180
+
62181
+ if( rc!=SQLITE_OK ){
62182
+ return rc;
62183
+ }
62184
+ pWal->ckptLock = 1;
62185
+ }
6192862186
#endif
6192962187
6193062188
do{
6193162189
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
6193262190
}while( rc==WAL_RETRY );
@@ -61933,20 +62191,10 @@
6193362191
testcase( (rc&0xff)==SQLITE_BUSY );
6193462192
testcase( (rc&0xff)==SQLITE_IOERR );
6193562193
testcase( rc==SQLITE_PROTOCOL );
6193662194
testcase( rc==SQLITE_OK );
6193762195
61938
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61939
- /* If they were disabled earlier and the read-transaction has been
61940
- ** successfully opened, re-enable blocking locks. This is because the
61941
- ** connection may attempt to upgrade to a write-transaction, which does
61942
- ** benefit from using blocking locks. */
61943
- if( rc==SQLITE_OK ){
61944
- sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
61945
- }
61946
-#endif
61947
-
6194862196
#ifdef SQLITE_ENABLE_SNAPSHOT
6194962197
if( rc==SQLITE_OK ){
6195062198
if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
6195162199
/* At this point the client has a lock on an aReadMark[] slot holding
6195262200
** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr
@@ -61964,52 +62212,46 @@
6196462212
volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
6196562213
6196662214
assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
6196762215
assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
6196862216
61969
- /* It is possible that there is a checkpointer thread running
61970
- ** concurrent with this code. If this is the case, it may be that the
61971
- ** checkpointer has already determined that it will checkpoint
61972
- ** snapshot X, where X is later in the wal file than pSnapshot, but
61973
- ** has not yet set the pInfo->nBackfillAttempted variable to indicate
61974
- ** its intent. To avoid the race condition this leads to, ensure that
61975
- ** there is no checkpointer process by taking a shared CKPT lock
61976
- ** before checking pInfo->nBackfillAttempted.
61977
- **
61978
- ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
61979
- ** this already?
61980
- */
61981
- rc = walLockShared(pWal, WAL_CKPT_LOCK);
61982
-
61983
- if( rc==SQLITE_OK ){
61984
- /* Check that the wal file has not been wrapped. Assuming that it has
61985
- ** not, also check that no checkpointer has attempted to checkpoint any
61986
- ** frames beyond pSnapshot->mxFrame. If either of these conditions are
61987
- ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
61988
- ** with *pSnapshot and set *pChanged as appropriate for opening the
61989
- ** snapshot. */
61990
- if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
61991
- && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
61992
- ){
61993
- assert( pWal->readLock>0 );
61994
- memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
61995
- *pChanged = bChanged;
61996
- }else{
61997
- rc = SQLITE_ERROR_SNAPSHOT;
61998
- }
61999
-
62000
- /* Release the shared CKPT lock obtained above. */
62001
- walUnlockShared(pWal, WAL_CKPT_LOCK);
62002
- pWal->minFrame = 1;
62003
- }
62004
-
62217
+ /* Check that the wal file has not been wrapped. Assuming that it has
62218
+ ** not, also check that no checkpointer has attempted to checkpoint any
62219
+ ** frames beyond pSnapshot->mxFrame. If either of these conditions are
62220
+ ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
62221
+ ** with *pSnapshot and set *pChanged as appropriate for opening the
62222
+ ** snapshot. */
62223
+ if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
62224
+ && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
62225
+ ){
62226
+ assert( pWal->readLock>0 );
62227
+ memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
62228
+ *pChanged = bChanged;
62229
+ }else{
62230
+ rc = SQLITE_ERROR_SNAPSHOT;
62231
+ }
62232
+
62233
+ /* A client using a non-current snapshot may not ignore any frames
62234
+ ** from the start of the wal file. This is because, for a system
62235
+ ** where (minFrame < iSnapshot < maxFrame), a checkpointer may
62236
+ ** have omitted to checkpoint a frame earlier than minFrame in
62237
+ ** the file because there exists a frame after iSnapshot that
62238
+ ** is the same database page. */
62239
+ pWal->minFrame = 1;
6200562240
6200662241
if( rc!=SQLITE_OK ){
6200762242
sqlite3WalEndReadTransaction(pWal);
6200862243
}
6200962244
}
6201062245
}
62246
+
62247
+ /* Release the shared CKPT lock obtained above. */
62248
+ if( pWal->ckptLock ){
62249
+ assert( pSnapshot );
62250
+ walUnlockShared(pWal, WAL_CKPT_LOCK);
62251
+ pWal->ckptLock = 0;
62252
+ }
6201162253
#endif
6201262254
return rc;
6201362255
}
6201462256
6201562257
/*
@@ -62085,26 +62327,28 @@
6208562327
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
6208662328
WalHashLoc sLoc; /* Hash table location */
6208762329
int iKey; /* Hash slot index */
6208862330
int nCollide; /* Number of hash collisions remaining */
6208962331
int rc; /* Error code */
62332
+ u32 iH;
6209062333
6209162334
rc = walHashGet(pWal, iHash, &sLoc);
6209262335
if( rc!=SQLITE_OK ){
6209362336
return rc;
6209462337
}
6209562338
nCollide = HASHTABLE_NSLOT;
62096
- for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
62097
- u32 iH = sLoc.aHash[iKey];
62339
+ iKey = walHash(pgno);
62340
+ while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
6209862341
u32 iFrame = iH + sLoc.iZero;
6209962342
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
6210062343
assert( iFrame>iRead || CORRUPT_DB );
6210162344
iRead = iFrame;
6210262345
}
6210362346
if( (nCollide--)==0 ){
6210462347
return SQLITE_CORRUPT_BKPT;
6210562348
}
62349
+ iKey = walNextHash(iKey);
6210662350
}
6210762351
if( iRead ) break;
6210862352
}
6210962353
6211062354
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -62175,10 +62419,20 @@
6217562419
**
6217662420
** There can only be a single writer active at a time.
6217762421
*/
6217862422
SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
6217962423
int rc;
62424
+
62425
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
62426
+ /* If the write-lock is already held, then it was obtained before the
62427
+ ** read-transaction was even opened, making this call a no-op.
62428
+ ** Return early. */
62429
+ if( pWal->writeLock ){
62430
+ assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
62431
+ return SQLITE_OK;
62432
+ }
62433
+#endif
6218062434
6218162435
/* Cannot start a write transaction without first holding a read
6218262436
** transaction. */
6218362437
assert( pWal->readLock>=0 );
6218462438
assert( pWal->writeLock==0 && pWal->iReCksum==0 );
@@ -62751,50 +63005,57 @@
6275163005
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
6275263006
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
6275363007
6275463008
if( pWal->readOnly ) return SQLITE_READONLY;
6275563009
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
63010
+
63011
+ /* Enable blocking locks, if possible. If blocking locks are successfully
63012
+ ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
63013
+ sqlite3WalDb(pWal, db);
63014
+ (void)walEnableBlocking(pWal);
6275663015
6275763016
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
62758
- ** "checkpoint" lock on the database file. */
63017
+ ** "checkpoint" lock on the database file.
63018
+ ** EVIDENCE-OF: R-10421-19736 If any other process is running a
63019
+ ** checkpoint operation at the same time, the lock cannot be obtained and
63020
+ ** SQLITE_BUSY is returned.
63021
+ ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
63022
+ ** it will not be invoked in this case.
63023
+ */
6275963024
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
62760
- if( rc ){
62761
- /* EVIDENCE-OF: R-10421-19736 If any other process is running a
62762
- ** checkpoint operation at the same time, the lock cannot be obtained and
62763
- ** SQLITE_BUSY is returned.
62764
- ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
62765
- ** it will not be invoked in this case.
62766
- */
62767
- testcase( rc==SQLITE_BUSY );
62768
- testcase( xBusy!=0 );
62769
- return rc;
62770
- }
62771
- pWal->ckptLock = 1;
62772
-
62773
- /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
62774
- ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
62775
- ** file.
62776
- **
62777
- ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
62778
- ** immediately, and a busy-handler is configured, it is invoked and the
62779
- ** writer lock retried until either the busy-handler returns 0 or the
62780
- ** lock is successfully obtained.
62781
- */
62782
- if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
62783
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
62784
- if( rc==SQLITE_OK ){
62785
- pWal->writeLock = 1;
62786
- }else if( rc==SQLITE_BUSY ){
62787
- eMode2 = SQLITE_CHECKPOINT_PASSIVE;
62788
- xBusy2 = 0;
62789
- rc = SQLITE_OK;
62790
- }
62791
- }
63025
+ testcase( rc==SQLITE_BUSY );
63026
+ testcase( rc!=SQLITE_OK && xBusy2!=0 );
63027
+ if( rc==SQLITE_OK ){
63028
+ pWal->ckptLock = 1;
63029
+
63030
+ /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
63031
+ ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
63032
+ ** file.
63033
+ **
63034
+ ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
63035
+ ** immediately, and a busy-handler is configured, it is invoked and the
63036
+ ** writer lock retried until either the busy-handler returns 0 or the
63037
+ ** lock is successfully obtained.
63038
+ */
63039
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
63040
+ rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
63041
+ if( rc==SQLITE_OK ){
63042
+ pWal->writeLock = 1;
63043
+ }else if( rc==SQLITE_BUSY ){
63044
+ eMode2 = SQLITE_CHECKPOINT_PASSIVE;
63045
+ xBusy2 = 0;
63046
+ rc = SQLITE_OK;
63047
+ }
63048
+ }
63049
+ }
63050
+
6279263051
6279363052
/* Read the wal-index header. */
6279463053
if( rc==SQLITE_OK ){
63054
+ walDisableBlocking(pWal);
6279563055
rc = walIndexReadHdr(pWal, &isChanged);
63056
+ (void)walEnableBlocking(pWal);
6279663057
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
6279763058
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
6279863059
}
6279963060
}
6280063061
@@ -62821,16 +63082,24 @@
6282163082
** next time the pager opens a snapshot on this database it knows that
6282263083
** the cache needs to be reset.
6282363084
*/
6282463085
memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
6282563086
}
63087
+
63088
+ walDisableBlocking(pWal);
63089
+ sqlite3WalDb(pWal, 0);
6282663090
6282763091
/* Release the locks. */
6282863092
sqlite3WalEndWriteTransaction(pWal);
62829
- walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
62830
- pWal->ckptLock = 0;
63093
+ if( pWal->ckptLock ){
63094
+ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
63095
+ pWal->ckptLock = 0;
63096
+ }
6283163097
WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
63098
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
63099
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
63100
+#endif
6283263101
return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
6283363102
}
6283463103
6283563104
/* Return the value to pass to a sqlite3_wal_hook callback, the
6283663105
** number of frames in the WAL at the point of the last commit since
@@ -62943,11 +63212,14 @@
6294363212
return rc;
6294463213
}
6294563214
6294663215
/* Try to open on pSnapshot when the next read-transaction starts
6294763216
*/
62948
-SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
63217
+SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
63218
+ Wal *pWal,
63219
+ sqlite3_snapshot *pSnapshot
63220
+){
6294963221
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
6295063222
}
6295163223
6295263224
/*
6295363225
** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
@@ -63462,11 +63734,11 @@
6346263734
u8 incrVacuum; /* True if incr-vacuum is enabled */
6346363735
u8 bDoTruncate; /* True to truncate db on commit */
6346463736
#endif
6346563737
u8 inTransaction; /* Transaction state */
6346663738
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
63467
- u8 nReserveWanted; /* 1 more than desired number of extra bytes per page */
63739
+ u8 nReserveWanted; /* Desired number of extra bytes per page */
6346863740
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
6346963741
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
6347063742
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
6347163743
u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
6347263744
u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
@@ -66356,12 +66628,11 @@
6635666628
*/
6635766629
static int btreeInvokeBusyHandler(void *pArg){
6635866630
BtShared *pBt = (BtShared*)pArg;
6635966631
assert( pBt->db );
6636066632
assert( sqlite3_mutex_held(pBt->db->mutex) );
66361
- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
66362
- sqlite3PagerFile(pBt->pPager));
66633
+ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
6636366634
}
6636466635
6636566636
/*
6636666637
** Open a database file.
6636766638
**
@@ -66908,23 +67179,21 @@
6690867179
** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
6690967180
** and autovacuum mode can no longer be changed.
6691067181
*/
6691167182
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
6691267183
int rc = SQLITE_OK;
67184
+ int x;
6691367185
BtShared *pBt = p->pBt;
66914
- assert( nReserve>=-1 && nReserve<=254 );
67186
+ assert( nReserve>=0 && nReserve<=255 );
6691567187
sqlite3BtreeEnter(p);
66916
- if( nReserve>=0 ){
66917
- pBt->nReserveWanted = nReserve + 1;
66918
- }
67188
+ pBt->nReserveWanted = nReserve;
67189
+ x = pBt->pageSize - pBt->usableSize;
67190
+ if( nReserve<x ) nReserve = x;
6691967191
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
6692067192
sqlite3BtreeLeave(p);
6692167193
return SQLITE_READONLY;
6692267194
}
66923
- if( nReserve<0 ){
66924
- nReserve = pBt->pageSize - pBt->usableSize;
66925
- }
6692667195
assert( nReserve>=0 && nReserve<=255 );
6692767196
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
6692867197
((pageSize-1)&pageSize)==0 ){
6692967198
assert( (pageSize & 7)==0 );
6693067199
assert( !pBt->pCursor );
@@ -66965,18 +67234,22 @@
6696567234
6696667235
/*
6696767236
** Return the number of bytes of space at the end of every page that
6696867237
** are intentually left unused. This is the "reserved" space that is
6696967238
** sometimes used by extensions.
67239
+**
67240
+** The value returned is the larger of the current reserve size and
67241
+** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
67242
+** The amount of reserve can only grow - never shrink.
6697067243
*/
6697167244
SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){
66972
- int n;
67245
+ int n1, n2;
6697367246
sqlite3BtreeEnter(p);
66974
- n = ((int)p->pBt->nReserveWanted) - 1;
66975
- if( n<0 ) n = sqlite3BtreeGetReserveNoMutex(p);
67247
+ n1 = (int)p->pBt->nReserveWanted;
67248
+ n2 = sqlite3BtreeGetReserveNoMutex(p);
6697667249
sqlite3BtreeLeave(p);
66977
- return n;
67250
+ return n1>n2 ? n1 : n2;
6697867251
}
6697967252
6698067253
6698167254
/*
6698267255
** Set the maximum page count for a database if mxPage is positive.
@@ -67422,10 +67695,11 @@
6742267695
** when A already has a read lock, we encourage A to give up and let B
6742367696
** proceed.
6742467697
*/
6742567698
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
6742667699
BtShared *pBt = p->pBt;
67700
+ Pager *pPager = pBt->pPager;
6742767701
int rc = SQLITE_OK;
6742867702
6742967703
sqlite3BtreeEnter(p);
6743067704
btreeIntegrity(p);
6743167705
@@ -67437,11 +67711,11 @@
6743767711
goto trans_begun;
6743867712
}
6743967713
assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
6744067714
6744167715
if( (p->db->flags & SQLITE_ResetDatabase)
67442
- && sqlite3PagerIsreadonly(pBt->pPager)==0
67716
+ && sqlite3PagerIsreadonly(pPager)==0
6744367717
){
6744467718
pBt->btsFlags &= ~BTS_READ_ONLY;
6744567719
}
6744667720
6744767721
/* Write transactions are not possible on a read-only database */
@@ -67485,10 +67759,22 @@
6748567759
if( SQLITE_OK!=rc ) goto trans_begun;
6748667760
6748767761
pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
6748867762
if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
6748967763
do {
67764
+ sqlite3PagerWalDb(pPager, p->db);
67765
+
67766
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
67767
+ /* If transitioning from no transaction directly to a write transaction,
67768
+ ** block for the WRITER lock first if possible. */
67769
+ if( pBt->pPage1==0 && wrflag ){
67770
+ assert( pBt->inTransaction==TRANS_NONE );
67771
+ rc = sqlite3PagerWalWriteLock(pPager, 1);
67772
+ if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break;
67773
+ }
67774
+#endif
67775
+
6749067776
/* Call lockBtree() until either pBt->pPage1 is populated or
6749167777
** lockBtree() returns something other than SQLITE_OK. lockBtree()
6749267778
** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
6749367779
** reading page 1 it discovers that the page-size of the database
6749467780
** file is not pBt->pageSize. In this case lockBtree() will update
@@ -67498,11 +67784,11 @@
6749867784
6749967785
if( rc==SQLITE_OK && wrflag ){
6750067786
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
6750167787
rc = SQLITE_READONLY;
6750267788
}else{
67503
- rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
67789
+ rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db));
6750467790
if( rc==SQLITE_OK ){
6750567791
rc = newDatabase(pBt);
6750667792
}else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
6750767793
/* if there was no transaction opened when this function was
6750867794
** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
@@ -67511,15 +67797,19 @@
6751167797
}
6751267798
}
6751367799
}
6751467800
6751567801
if( rc!=SQLITE_OK ){
67802
+ (void)sqlite3PagerWalWriteLock(pPager, 0);
6751667803
unlockBtreeIfUnused(pBt);
6751767804
}
6751867805
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
6751967806
btreeInvokeBusyHandler(pBt) );
67520
- sqlite3PagerResetLockTimeout(pBt->pPager);
67807
+ sqlite3PagerWalDb(pPager, 0);
67808
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
67809
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
67810
+#endif
6752167811
6752267812
if( rc==SQLITE_OK ){
6752367813
if( p->inTrans==TRANS_NONE ){
6752467814
pBt->nTransaction++;
6752567815
#ifndef SQLITE_OMIT_SHARED_CACHE
@@ -67567,11 +67857,11 @@
6756767857
if( wrflag ){
6756867858
/* This call makes sure that the pager has the correct number of
6756967859
** open savepoints. If the second parameter is greater than 0 and
6757067860
** the sub-journal is not already open, then it will be opened here.
6757167861
*/
67572
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
67862
+ rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint);
6757367863
}
6757467864
}
6757567865
6757667866
btreeIntegrity(p);
6757767867
sqlite3BtreeLeave(p);
@@ -71203,11 +71493,11 @@
7120371493
7120471494
/* Remove cells from the start and end of the page */
7120571495
assert( nCell>=0 );
7120671496
if( iOld<iNew ){
7120771497
int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
71208
- if( nShift>nCell ) return SQLITE_CORRUPT_BKPT;
71498
+ if( NEVER(nShift>nCell) ) return SQLITE_CORRUPT_BKPT;
7120971499
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
7121071500
nCell -= nShift;
7121171501
}
7121271502
if( iNewEnd < iOldEnd ){
7121371503
int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
@@ -73560,11 +73850,10 @@
7356073850
}
7356173851
sqlite3BtreeLeave(p);
7356273852
return rc;
7356373853
}
7356473854
73565
-#ifndef SQLITE_OMIT_BTREECOUNT
7356673855
/*
7356773856
** The first argument, pCur, is a cursor opened on some b-tree. Count the
7356873857
** number of entries in the b-tree and write the result to *pnEntry.
7356973858
**
7357073859
** SQLITE_OK is returned if the operation is successfully executed.
@@ -73633,11 +73922,10 @@
7363373922
}
7363473923
7363573924
/* An error has occurred. Return an error code. */
7363673925
return rc;
7363773926
}
73638
-#endif
7363973927
7364073928
/*
7364173929
** Return the pager associated with a BTree. This routine is used for
7364273930
** testing and debugging only.
7364373931
*/
@@ -74684,11 +74972,11 @@
7468474972
** Attempt to set the page size of the destination to match the page size
7468574973
** of the source.
7468674974
*/
7468774975
static int setDestPgsz(sqlite3_backup *p){
7468874976
int rc;
74689
- rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
74977
+ rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
7469074978
return rc;
7469174979
}
7469274980
7469374981
/*
7469474982
** Check that there is no open read-transaction on the b-tree passed as the
@@ -78709,24 +78997,23 @@
7870978997
** "PX" -> "r[X]"
7871078998
** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
7871178999
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
7871279000
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
7871379001
*/
78714
-static int displayComment(
79002
+SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
79003
+ sqlite3 *db, /* Optional - Oom error reporting only */
7871579004
const Op *pOp, /* The opcode to be commented */
78716
- const char *zP4, /* Previously obtained value for P4 */
78717
- char *zTemp, /* Write result here */
78718
- int nTemp /* Space available in zTemp[] */
79005
+ const char *zP4 /* Previously obtained value for P4 */
7871979006
){
7872079007
const char *zOpName;
7872179008
const char *zSynopsis;
7872279009
int nOpName;
7872379010
int ii;
7872479011
char zAlt[50];
7872579012
StrAccum x;
78726
- sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
7872779013
79014
+ sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
7872879015
zOpName = sqlite3OpcodeName(pOp->opcode);
7872979016
nOpName = sqlite3Strlen30(zOpName);
7873079017
if( zOpName[nOpName+1] ){
7873179018
int seenCom = 0;
7873279019
char c;
@@ -78789,14 +79076,16 @@
7878979076
sqlite3_str_appendf(&x, "; %s", pOp->zComment);
7879079077
}
7879179078
}else if( pOp->zComment ){
7879279079
sqlite3_str_appendall(&x, pOp->zComment);
7879379080
}
78794
- sqlite3StrAccumFinish(&x);
78795
- return x.nChar;
79081
+ if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
79082
+ sqlite3OomFault(db);
79083
+ }
79084
+ return sqlite3StrAccumFinish(&x);
7879679085
}
78797
-#endif /* SQLITE_DEBUG */
79086
+#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */
7879879087
7879979088
#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
7880079089
/*
7880179090
** Translate the P4.pExpr value for an OP_CursorHint opcode into text
7880279091
** that can be displayed in the P4 column of EXPLAIN output.
@@ -78873,15 +79162,15 @@
7887379162
#if VDBE_DISPLAY_P4
7887479163
/*
7887579164
** Compute a string that describes the P4 parameter for an opcode.
7887679165
** Use zTemp for any required temporary buffer space.
7887779166
*/
78878
-static char *displayP4(Op *pOp, char *zTemp, int nTemp){
78879
- char *zP4 = zTemp;
79167
+SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
79168
+ char *zP4 = 0;
7888079169
StrAccum x;
78881
- assert( nTemp>=20 );
78882
- sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
79170
+
79171
+ sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
7888379172
switch( pOp->p4type ){
7888479173
case P4_KEYINFO: {
7888579174
int j;
7888679175
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
7888779176
assert( pKeyInfo->aSortFlags!=0 );
@@ -78961,40 +79250,36 @@
7896179250
int i;
7896279251
int *ai = pOp->p4.ai;
7896379252
int n = ai[0]; /* The first element of an INTARRAY is always the
7896479253
** count of the number of elements to follow */
7896579254
for(i=1; i<=n; i++){
78966
- sqlite3_str_appendf(&x, ",%d", ai[i]);
79255
+ sqlite3_str_appendf(&x, "%c%d", (i==1 ? '[' : ','), ai[i]);
7896779256
}
78968
- zTemp[0] = '[';
7896979257
sqlite3_str_append(&x, "]", 1);
7897079258
break;
7897179259
}
7897279260
case P4_SUBPROGRAM: {
78973
- sqlite3_str_appendf(&x, "program");
79261
+ zP4 = "program";
7897479262
break;
7897579263
}
7897679264
case P4_DYNBLOB:
7897779265
case P4_ADVANCE: {
78978
- zTemp[0] = 0;
7897979266
break;
7898079267
}
7898179268
case P4_TABLE: {
78982
- sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
79269
+ zP4 = pOp->p4.pTab->zName;
7898379270
break;
7898479271
}
7898579272
default: {
7898679273
zP4 = pOp->p4.z;
78987
- if( zP4==0 ){
78988
- zP4 = zTemp;
78989
- zTemp[0] = 0;
78990
- }
7899179274
}
7899279275
}
78993
- sqlite3StrAccumFinish(&x);
78994
- assert( zP4!=0 );
78995
- return zP4;
79276
+ if( zP4 ) sqlite3_str_appendall(&x, zP4);
79277
+ if( (x.accError & SQLITE_NOMEM)!=0 ){
79278
+ sqlite3OomFault(db);
79279
+ }
79280
+ return sqlite3StrAccumFinish(&x);
7899679281
}
7899779282
#endif /* VDBE_DISPLAY_P4 */
7899879283
7899979284
/*
7900079285
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
@@ -79080,28 +79365,34 @@
7908079365
/*
7908179366
** Print a single opcode. This routine is used for debugging only.
7908279367
*/
7908379368
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
7908479369
char *zP4;
79085
- char zPtr[50];
79086
- char zCom[100];
79370
+ char *zCom;
79371
+ sqlite3 dummyDb;
7908779372
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
7908879373
if( pOut==0 ) pOut = stdout;
79089
- zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
79374
+ sqlite3BeginBenignMalloc();
79375
+ dummyDb.mallocFailed = 1;
79376
+ zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
7909079377
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79091
- displayComment(pOp, zP4, zCom, sizeof(zCom));
79378
+ zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
7909279379
#else
79093
- zCom[0] = 0;
79380
+ zCom = 0;
7909479381
#endif
7909579382
/* NB: The sqlite3OpcodeName() function is implemented by code created
7909679383
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
7909779384
** information from the vdbe.c source text */
7909879385
fprintf(pOut, zFormat1, pc,
79099
- sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
79100
- zCom
79386
+ sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3,
79387
+ zP4 ? zP4 : "", pOp->p5,
79388
+ zCom ? zCom : ""
7910179389
);
7910279390
fflush(pOut);
79391
+ sqlite3_free(zP4);
79392
+ sqlite3_free(zCom);
79393
+ sqlite3EndBenignMalloc();
7910379394
}
7910479395
#endif
7910579396
7910679397
/*
7910779398
** Initialize an array of N Mem element.
@@ -79188,10 +79479,125 @@
7918879479
assert( sqlite3VdbeFrameIsValid(pFrame) );
7918979480
pFrame->pParent = pFrame->v->pDelFrame;
7919079481
pFrame->v->pDelFrame = pFrame;
7919179482
}
7919279483
79484
+#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN)
79485
+/*
79486
+** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
79487
+** QUERY PLAN output.
79488
+**
79489
+** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no
79490
+** more opcodes to be displayed.
79491
+*/
79492
+SQLITE_PRIVATE int sqlite3VdbeNextOpcode(
79493
+ Vdbe *p, /* The statement being explained */
79494
+ Mem *pSub, /* Storage for keeping track of subprogram nesting */
79495
+ int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */
79496
+ int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */
79497
+ int *piAddr, /* OUT: Write index into (*paOp)[] here */
79498
+ Op **paOp /* OUT: Write the opcode array here */
79499
+){
79500
+ int nRow; /* Stop when row count reaches this */
79501
+ int nSub = 0; /* Number of sub-vdbes seen so far */
79502
+ SubProgram **apSub = 0; /* Array of sub-vdbes */
79503
+ int i; /* Next instruction address */
79504
+ int rc = SQLITE_OK; /* Result code */
79505
+ Op *aOp = 0; /* Opcode array */
79506
+ int iPc; /* Rowid. Copy of value in *piPc */
79507
+
79508
+ /* When the number of output rows reaches nRow, that means the
79509
+ ** listing has finished and sqlite3_step() should return SQLITE_DONE.
79510
+ ** nRow is the sum of the number of rows in the main program, plus
79511
+ ** the sum of the number of rows in all trigger subprograms encountered
79512
+ ** so far. The nRow value will increase as new trigger subprograms are
79513
+ ** encountered, but p->pc will eventually catch up to nRow.
79514
+ */
79515
+ nRow = p->nOp;
79516
+ if( pSub!=0 ){
79517
+ if( pSub->flags&MEM_Blob ){
79518
+ /* pSub is initiallly NULL. It is initialized to a BLOB by
79519
+ ** the P4_SUBPROGRAM processing logic below */
79520
+ nSub = pSub->n/sizeof(Vdbe*);
79521
+ apSub = (SubProgram **)pSub->z;
79522
+ }
79523
+ for(i=0; i<nSub; i++){
79524
+ nRow += apSub[i]->nOp;
79525
+ }
79526
+ }
79527
+ iPc = *piPc;
79528
+ while(1){ /* Loop exits via break */
79529
+ i = iPc++;
79530
+ if( i>=nRow ){
79531
+ p->rc = SQLITE_OK;
79532
+ rc = SQLITE_DONE;
79533
+ break;
79534
+ }
79535
+ if( i<p->nOp ){
79536
+ /* The rowid is small enough that we are still in the
79537
+ ** main program. */
79538
+ aOp = p->aOp;
79539
+ }else{
79540
+ /* We are currently listing subprograms. Figure out which one and
79541
+ ** pick up the appropriate opcode. */
79542
+ int j;
79543
+ i -= p->nOp;
79544
+ assert( apSub!=0 );
79545
+ assert( nSub>0 );
79546
+ for(j=0; i>=apSub[j]->nOp; j++){
79547
+ i -= apSub[j]->nOp;
79548
+ assert( i<apSub[j]->nOp || j+1<nSub );
79549
+ }
79550
+ aOp = apSub[j]->aOp;
79551
+ }
79552
+
79553
+ /* When an OP_Program opcode is encounter (the only opcode that has
79554
+ ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
79555
+ ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
79556
+ ** has not already been seen.
79557
+ */
79558
+ if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
79559
+ int nByte = (nSub+1)*sizeof(SubProgram*);
79560
+ int j;
79561
+ for(j=0; j<nSub; j++){
79562
+ if( apSub[j]==aOp[i].p4.pProgram ) break;
79563
+ }
79564
+ if( j==nSub ){
79565
+ p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
79566
+ if( p->rc!=SQLITE_OK ){
79567
+ rc = SQLITE_ERROR;
79568
+ break;
79569
+ }
79570
+ apSub = (SubProgram **)pSub->z;
79571
+ apSub[nSub++] = aOp[i].p4.pProgram;
79572
+ MemSetTypeFlag(pSub, MEM_Blob);
79573
+ pSub->n = nSub*sizeof(SubProgram*);
79574
+ nRow += aOp[i].p4.pProgram->nOp;
79575
+ }
79576
+ }
79577
+ if( eMode==0 ) break;
79578
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
79579
+ if( eMode==2 ){
79580
+ Op *pOp = aOp + i;
79581
+ if( pOp->opcode==OP_OpenRead ) break;
79582
+ if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
79583
+ if( pOp->opcode==OP_ReopenIdx ) break;
79584
+ }else
79585
+#endif
79586
+ {
79587
+ assert( eMode==1 );
79588
+ if( aOp[i].opcode==OP_Explain ) break;
79589
+ if( aOp[i].opcode==OP_Init && iPc>1 ) break;
79590
+ }
79591
+ }
79592
+ *piPc = iPc;
79593
+ *piAddr = i;
79594
+ *paOp = aOp;
79595
+ return rc;
79596
+}
79597
+#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */
79598
+
7919379599
7919479600
/*
7919579601
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
7919679602
** allocated by the OP_Program opcode in sqlite3VdbeExec().
7919779603
*/
@@ -79228,20 +79634,18 @@
7922879634
** the trigger subprograms are listed one by one.
7922979635
*/
7923079636
SQLITE_PRIVATE int sqlite3VdbeList(
7923179637
Vdbe *p /* The VDBE */
7923279638
){
79233
- int nRow; /* Stop when row count reaches this */
79234
- int nSub = 0; /* Number of sub-vdbes seen so far */
79235
- SubProgram **apSub = 0; /* Array of sub-vdbes */
7923679639
Mem *pSub = 0; /* Memory cell hold array of subprogs */
7923779640
sqlite3 *db = p->db; /* The database connection */
7923879641
int i; /* Loop counter */
7923979642
int rc = SQLITE_OK; /* Return code */
7924079643
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
7924179644
int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
79242
- Op *pOp = 0;
79645
+ Op *aOp; /* Array of opcodes */
79646
+ Op *pOp; /* Current opcode */
7924379647
7924479648
assert( p->explain );
7924579649
assert( p->magic==VDBE_MAGIC_RUN );
7924679650
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
7924779651
@@ -79257,166 +79661,66 @@
7925779661
** sqlite3_column_text16() failed. */
7925879662
sqlite3OomFault(db);
7925979663
return SQLITE_ERROR;
7926079664
}
7926179665
79262
- /* When the number of output rows reaches nRow, that means the
79263
- ** listing has finished and sqlite3_step() should return SQLITE_DONE.
79264
- ** nRow is the sum of the number of rows in the main program, plus
79265
- ** the sum of the number of rows in all trigger subprograms encountered
79266
- ** so far. The nRow value will increase as new trigger subprograms are
79267
- ** encountered, but p->pc will eventually catch up to nRow.
79268
- */
79269
- nRow = p->nOp;
7927079666
if( bListSubprogs ){
7927179667
/* The first 8 memory cells are used for the result set. So we will
7927279668
** commandeer the 9th cell to use as storage for an array of pointers
7927379669
** to trigger subprograms. The VDBE is guaranteed to have at least 9
7927479670
** cells. */
7927579671
assert( p->nMem>9 );
7927679672
pSub = &p->aMem[9];
79277
- if( pSub->flags&MEM_Blob ){
79278
- /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
79279
- ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
79280
- nSub = pSub->n/sizeof(Vdbe*);
79281
- apSub = (SubProgram **)pSub->z;
79282
- }
79283
- for(i=0; i<nSub; i++){
79284
- nRow += apSub[i]->nOp;
79285
- }
79286
- }
79287
-
79288
- while(1){ /* Loop exits via break */
79289
- i = p->pc++;
79290
- if( i>=nRow ){
79291
- p->rc = SQLITE_OK;
79292
- rc = SQLITE_DONE;
79293
- break;
79294
- }
79295
- if( i<p->nOp ){
79296
- /* The output line number is small enough that we are still in the
79297
- ** main program. */
79298
- pOp = &p->aOp[i];
79299
- }else{
79300
- /* We are currently listing subprograms. Figure out which one and
79301
- ** pick up the appropriate opcode. */
79302
- int j;
79303
- i -= p->nOp;
79304
- assert( apSub!=0 );
79305
- assert( nSub>0 );
79306
- for(j=0; i>=apSub[j]->nOp; j++){
79307
- i -= apSub[j]->nOp;
79308
- assert( i<apSub[j]->nOp || j+1<nSub );
79309
- }
79310
- pOp = &apSub[j]->aOp[i];
79311
- }
79312
-
79313
- /* When an OP_Program opcode is encounter (the only opcode that has
79314
- ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
79315
- ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
79316
- ** has not already been seen.
79317
- */
79318
- if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
79319
- int nByte = (nSub+1)*sizeof(SubProgram*);
79320
- int j;
79321
- for(j=0; j<nSub; j++){
79322
- if( apSub[j]==pOp->p4.pProgram ) break;
79323
- }
79324
- if( j==nSub ){
79325
- p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
79326
- if( p->rc!=SQLITE_OK ){
79327
- rc = SQLITE_ERROR;
79328
- break;
79329
- }
79330
- apSub = (SubProgram **)pSub->z;
79331
- apSub[nSub++] = pOp->p4.pProgram;
79332
- pSub->flags |= MEM_Blob;
79333
- pSub->n = nSub*sizeof(SubProgram*);
79334
- nRow += pOp->p4.pProgram->nOp;
79335
- }
79336
- }
79337
- if( p->explain<2 ) break;
79338
- if( pOp->opcode==OP_Explain ) break;
79339
- if( pOp->opcode==OP_Init && p->pc>1 ) break;
79340
- }
79341
-
79342
- if( rc==SQLITE_OK ){
79673
+ }else{
79674
+ pSub = 0;
79675
+ }
79676
+
79677
+ /* Figure out which opcode is next to display */
79678
+ rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
79679
+
79680
+ if( rc==SQLITE_OK ){
79681
+ pOp = aOp + i;
7934379682
if( AtomicLoad(&db->u1.isInterrupted) ){
7934479683
p->rc = SQLITE_INTERRUPT;
7934579684
rc = SQLITE_ERROR;
7934679685
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
7934779686
}else{
79348
- char *zP4;
79349
- if( p->explain==1 ){
79350
- pMem->flags = MEM_Int;
79351
- pMem->u.i = i; /* Program counter */
79352
- pMem++;
79353
-
79354
- pMem->flags = MEM_Static|MEM_Str|MEM_Term;
79355
- pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
79356
- assert( pMem->z!=0 );
79357
- pMem->n = sqlite3Strlen30(pMem->z);
79358
- pMem->enc = SQLITE_UTF8;
79359
- pMem++;
79360
- }
79361
-
79362
- pMem->flags = MEM_Int;
79363
- pMem->u.i = pOp->p1; /* P1 */
79364
- pMem++;
79365
-
79366
- pMem->flags = MEM_Int;
79367
- pMem->u.i = pOp->p2; /* P2 */
79368
- pMem++;
79369
-
79370
- pMem->flags = MEM_Int;
79371
- pMem->u.i = pOp->p3; /* P3 */
79372
- pMem++;
79373
-
79374
- if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
79375
- assert( p->db->mallocFailed );
79376
- return SQLITE_ERROR;
79377
- }
79378
- pMem->flags = MEM_Str|MEM_Term;
79379
- zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
79380
- if( zP4!=pMem->z ){
79381
- pMem->n = 0;
79382
- sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
79687
+ char *zP4 = sqlite3VdbeDisplayP4(db, pOp);
79688
+ if( p->explain==2 ){
79689
+ sqlite3VdbeMemSetInt64(pMem, pOp->p1);
79690
+ sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
79691
+ sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
79692
+ sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);
79693
+ p->nResColumn = 4;
7938379694
}else{
79384
- assert( pMem->z!=0 );
79385
- pMem->n = sqlite3Strlen30(pMem->z);
79386
- pMem->enc = SQLITE_UTF8;
79387
- }
79388
- pMem++;
79389
-
79390
- if( p->explain==1 ){
79391
- if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
79392
- assert( p->db->mallocFailed );
79393
- return SQLITE_ERROR;
79394
- }
79395
- pMem->flags = MEM_Str|MEM_Term;
79396
- pMem->n = 2;
79397
- sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
79398
- pMem->enc = SQLITE_UTF8;
79399
- pMem++;
79400
-
79695
+ sqlite3VdbeMemSetInt64(pMem+0, i);
79696
+ sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
79697
+ -1, SQLITE_UTF8, SQLITE_STATIC);
79698
+ sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
79699
+ sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
79700
+ sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
79701
+ /* pMem+5 for p4 is done last */
79702
+ sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
7940179703
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79402
- if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
79403
- assert( p->db->mallocFailed );
79404
- return SQLITE_ERROR;
79405
- }
79406
- pMem->flags = MEM_Str|MEM_Term;
79407
- pMem->n = displayComment(pOp, zP4, pMem->z, 500);
79408
- pMem->enc = SQLITE_UTF8;
79409
-#else
79410
- pMem->flags = MEM_Null; /* Comment */
79411
-#endif
79412
- }
79413
-
79414
- p->nResColumn = 8 - 4*(p->explain-1);
79415
- p->pResultSet = &p->aMem[1];
79416
- p->rc = SQLITE_OK;
79417
- rc = SQLITE_ROW;
79704
+ {
79705
+ char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4);
79706
+ sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
79707
+ }
79708
+#else
79709
+ sqlite3VdbeMemSetNull(pMem+7);
79710
+#endif
79711
+ sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
79712
+ p->nResColumn = 8;
79713
+ }
79714
+ p->pResultSet = pMem;
79715
+ if( db->mallocFailed ){
79716
+ p->rc = SQLITE_NOMEM;
79717
+ rc = SQLITE_ERROR;
79718
+ }else{
79719
+ p->rc = SQLITE_OK;
79720
+ rc = SQLITE_ROW;
79721
+ }
7941879722
}
7941979723
}
7942079724
return rc;
7942179725
}
7942279726
#endif /* SQLITE_OMIT_EXPLAIN */
@@ -79982,12 +80286,13 @@
7998280286
int retryCount = 0;
7998380287
int nMainFile;
7998480288
7998580289
/* Select a master journal file name */
7998680290
nMainFile = sqlite3Strlen30(zMainFile);
79987
- zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz%c%c", zMainFile, 0, 0);
80291
+ zMaster = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0);
7998880292
if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
80293
+ zMaster += 4;
7998980294
do {
7999080295
u32 iRandom;
7999180296
if( retryCount ){
7999280297
if( retryCount>100 ){
7999380298
sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
@@ -80013,11 +80318,11 @@
8001380318
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
8001480319
SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
8001580320
);
8001680321
}
8001780322
if( rc!=SQLITE_OK ){
80018
- sqlite3DbFree(db, zMaster);
80323
+ sqlite3DbFree(db, zMaster-4);
8001980324
return rc;
8002080325
}
8002180326
8002280327
/* Write the name of each database file in the transaction into the new
8002380328
** master journal file. If an error occurs at this point close
@@ -80036,11 +80341,11 @@
8003680341
rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
8003780342
offset += sqlite3Strlen30(zFile)+1;
8003880343
if( rc!=SQLITE_OK ){
8003980344
sqlite3OsCloseFree(pMaster);
8004080345
sqlite3OsDelete(pVfs, zMaster, 0);
80041
- sqlite3DbFree(db, zMaster);
80346
+ sqlite3DbFree(db, zMaster-4);
8004280347
return rc;
8004380348
}
8004480349
}
8004580350
}
8004680351
@@ -80050,11 +80355,11 @@
8005080355
if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
8005180356
&& SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
8005280357
){
8005380358
sqlite3OsCloseFree(pMaster);
8005480359
sqlite3OsDelete(pVfs, zMaster, 0);
80055
- sqlite3DbFree(db, zMaster);
80360
+ sqlite3DbFree(db, zMaster-4);
8005680361
return rc;
8005780362
}
8005880363
8005980364
/* Sync all the db files involved in the transaction. The same call
8006080365
** sets the master journal pointer in each individual journal. If
@@ -80073,20 +80378,20 @@
8007380378
}
8007480379
}
8007580380
sqlite3OsCloseFree(pMaster);
8007680381
assert( rc!=SQLITE_BUSY );
8007780382
if( rc!=SQLITE_OK ){
80078
- sqlite3DbFree(db, zMaster);
80383
+ sqlite3DbFree(db, zMaster-4);
8007980384
return rc;
8008080385
}
8008180386
8008280387
/* Delete the master journal file. This commits the transaction. After
8008380388
** doing this the directory is synced again before any individual
8008480389
** transaction files are deleted.
8008580390
*/
8008680391
rc = sqlite3OsDelete(pVfs, zMaster, 1);
80087
- sqlite3DbFree(db, zMaster);
80392
+ sqlite3DbFree(db, zMaster-4);
8008880393
zMaster = 0;
8008980394
if( rc ){
8009080395
return rc;
8009180396
}
8009280397
@@ -83825,11 +84130,11 @@
8382584130
p->db->errCode = SQLITE_OK;
8382684131
8382784132
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
8382884133
** binding a new value to this variable invalidates the current query plan.
8382984134
**
83830
- ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
84135
+ ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
8383184136
** parameter in the WHERE clause might influence the choice of query plan
8383284137
** for a statement, then the statement will be automatically recompiled,
8383384138
** as if there had been a schema change, on the first sqlite3_step() call
8383484139
** following any change to the bindings of that parameter.
8383584140
*/
@@ -87998,32 +88303,38 @@
8799888303
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
8799988304
REGISTER_TRACE(pOp->p3, pOut);
8800088305
break;
8800188306
}
8800288307
88003
-/* Opcode: Count P1 P2 * * *
88308
+/* Opcode: Count P1 P2 p3 * *
8800488309
** Synopsis: r[P2]=count()
8800588310
**
8800688311
** Store the number of entries (an integer value) in the table or index
88007
-** opened by cursor P1 in register P2
88312
+** opened by cursor P1 in register P2.
88313
+**
88314
+** If P3==0, then an exact count is obtained, which involves visiting
88315
+** every btree page of the table. But if P3 is non-zero, an estimate
88316
+** is returned based on the current cursor position.
8800888317
*/
88009
-#ifndef SQLITE_OMIT_BTREECOUNT
8801088318
case OP_Count: { /* out2 */
8801188319
i64 nEntry;
8801288320
BtCursor *pCrsr;
8801388321
8801488322
assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
8801588323
pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
8801688324
assert( pCrsr );
88017
- nEntry = 0; /* Not needed. Only used to silence a warning. */
88018
- rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
88019
- if( rc ) goto abort_due_to_error;
88325
+ if( pOp->p3 ){
88326
+ nEntry = sqlite3BtreeRowCountEst(pCrsr);
88327
+ }else{
88328
+ nEntry = 0; /* Not needed. Only used to silence a warning. */
88329
+ rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
88330
+ if( rc ) goto abort_due_to_error;
88331
+ }
8802088332
pOut = out2Prerelease(p, pOp);
8802188333
pOut->u.i = nEntry;
8802288334
goto check_for_interrupt;
8802388335
}
88024
-#endif
8802588336
8802688337
/* Opcode: Savepoint P1 * * P4 *
8802788338
**
8802888339
** Open, release or rollback the savepoint named by parameter P4, depending
8802988340
** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN).
@@ -90457,16 +90768,23 @@
9045790768
rc = sqlite3VdbeSorterWrite(pC, pIn2);
9045890769
if( rc) goto abort_due_to_error;
9045990770
break;
9046090771
}
9046190772
90462
-/* Opcode: IdxDelete P1 P2 P3 * *
90773
+/* Opcode: IdxDelete P1 P2 P3 * P5
9046390774
** Synopsis: key=r[P2@P3]
9046490775
**
9046590776
** The content of P3 registers starting at register P2 form
9046690777
** an unpacked index key. This opcode removes that entry from the
9046790778
** index opened by cursor P1.
90779
+**
90780
+** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
90781
+** if no matching index entry is found. This happens when running
90782
+** an UPDATE or DELETE statement and the index entry to be updated
90783
+** or deleted is not found. For some uses of IdxDelete
90784
+** (example: the EXCEPT operator) it does not matter that no matching
90785
+** entry is found. For those cases, P5 is zero.
9046890786
*/
9046990787
case OP_IdxDelete: {
9047090788
VdbeCursor *pC;
9047190789
BtCursor *pCrsr;
9047290790
int res;
@@ -90479,20 +90797,22 @@
9047990797
assert( pC!=0 );
9048090798
assert( pC->eCurType==CURTYPE_BTREE );
9048190799
sqlite3VdbeIncrWriteCounter(p, pC);
9048290800
pCrsr = pC->uc.pCursor;
9048390801
assert( pCrsr!=0 );
90484
- assert( pOp->p5==0 );
9048590802
r.pKeyInfo = pC->pKeyInfo;
9048690803
r.nField = (u16)pOp->p3;
9048790804
r.default_rc = 0;
9048890805
r.aMem = &aMem[pOp->p2];
9048990806
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
9049090807
if( rc ) goto abort_due_to_error;
9049190808
if( res==0 ){
9049290809
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
9049390810
if( rc ) goto abort_due_to_error;
90811
+ }else if( pOp->p5 ){
90812
+ rc = SQLITE_CORRUPT_INDEX;
90813
+ goto abort_due_to_error;
9049490814
}
9049590815
assert( pC->deferredMoveto==0 );
9049690816
pC->cacheStatus = CACHE_STALE;
9049790817
pC->seekResult = 0;
9049890818
break;
@@ -96093,10 +96413,437 @@
9609396413
*pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
9609496414
return SQLITE_OK;
9609596415
}
9609696416
9609796417
/************** End of vdbesort.c ********************************************/
96418
+/************** Begin file vdbevtab.c ****************************************/
96419
+/*
96420
+** 2020-03-23
96421
+**
96422
+** The author disclaims copyright to this source code. In place of
96423
+** a legal notice, here is a blessing:
96424
+**
96425
+** May you do good and not evil.
96426
+** May you find forgiveness for yourself and forgive others.
96427
+** May you share freely, never taking more than you give.
96428
+**
96429
+*************************************************************************
96430
+**
96431
+** This file implements virtual-tables for examining the bytecode content
96432
+** of a prepared statement.
96433
+*/
96434
+/* #include "sqliteInt.h" */
96435
+#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
96436
+/* #include "vdbeInt.h" */
96437
+
96438
+/* An instance of the bytecode() table-valued function.
96439
+*/
96440
+typedef struct bytecodevtab bytecodevtab;
96441
+struct bytecodevtab {
96442
+ sqlite3_vtab base; /* Base class - must be first */
96443
+ sqlite3 *db; /* Database connection */
96444
+ int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */
96445
+};
96446
+
96447
+/* A cursor for scanning through the bytecode
96448
+*/
96449
+typedef struct bytecodevtab_cursor bytecodevtab_cursor;
96450
+struct bytecodevtab_cursor {
96451
+ sqlite3_vtab_cursor base; /* Base class - must be first */
96452
+ sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */
96453
+ int iRowid; /* The rowid of the output table */
96454
+ int iAddr; /* Address */
96455
+ int needFinalize; /* Cursors owns pStmt and must finalize it */
96456
+ int showSubprograms; /* Provide a listing of subprograms */
96457
+ Op *aOp; /* Operand array */
96458
+ char *zP4; /* Rendered P4 value */
96459
+ const char *zType; /* tables_used.type */
96460
+ const char *zSchema; /* tables_used.schema */
96461
+ const char *zName; /* tables_used.name */
96462
+ Mem sub; /* Subprograms */
96463
+};
96464
+
96465
+/*
96466
+** Create a new bytecode() table-valued function.
96467
+*/
96468
+static int bytecodevtabConnect(
96469
+ sqlite3 *db,
96470
+ void *pAux,
96471
+ int argc, const char *const*argv,
96472
+ sqlite3_vtab **ppVtab,
96473
+ char **pzErr
96474
+){
96475
+ bytecodevtab *pNew;
96476
+ int rc;
96477
+ int isTabUsed = pAux!=0;
96478
+ const char *azSchema[2] = {
96479
+ /* bytecode() schema */
96480
+ "CREATE TABLE x("
96481
+ "addr INT,"
96482
+ "opcode TEXT,"
96483
+ "p1 INT,"
96484
+ "p2 INT,"
96485
+ "p3 INT,"
96486
+ "p4 TEXT,"
96487
+ "p5 INT,"
96488
+ "comment TEXT,"
96489
+ "subprog TEXT,"
96490
+ "stmt HIDDEN"
96491
+ ");",
96492
+
96493
+ /* Tables_used() schema */
96494
+ "CREATE TABLE x("
96495
+ "type TEXT,"
96496
+ "schema TEXT,"
96497
+ "name TEXT,"
96498
+ "wr INT,"
96499
+ "subprog TEXT,"
96500
+ "stmt HIDDEN"
96501
+ ");"
96502
+ };
96503
+
96504
+ rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
96505
+ if( rc==SQLITE_OK ){
96506
+ pNew = sqlite3_malloc( sizeof(*pNew) );
96507
+ *ppVtab = (sqlite3_vtab*)pNew;
96508
+ if( pNew==0 ) return SQLITE_NOMEM;
96509
+ memset(pNew, 0, sizeof(*pNew));
96510
+ pNew->db = db;
96511
+ pNew->bTablesUsed = isTabUsed*2;
96512
+ }
96513
+ return rc;
96514
+}
96515
+
96516
+/*
96517
+** This method is the destructor for bytecodevtab objects.
96518
+*/
96519
+static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
96520
+ bytecodevtab *p = (bytecodevtab*)pVtab;
96521
+ sqlite3_free(p);
96522
+ return SQLITE_OK;
96523
+}
96524
+
96525
+/*
96526
+** Constructor for a new bytecodevtab_cursor object.
96527
+*/
96528
+static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
96529
+ bytecodevtab *pVTab = (bytecodevtab*)p;
96530
+ bytecodevtab_cursor *pCur;
96531
+ pCur = sqlite3_malloc( sizeof(*pCur) );
96532
+ if( pCur==0 ) return SQLITE_NOMEM;
96533
+ memset(pCur, 0, sizeof(*pCur));
96534
+ sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
96535
+ *ppCursor = &pCur->base;
96536
+ return SQLITE_OK;
96537
+}
96538
+
96539
+/*
96540
+** Clear all internal content from a bytecodevtab cursor.
96541
+*/
96542
+static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
96543
+ sqlite3_free(pCur->zP4);
96544
+ pCur->zP4 = 0;
96545
+ sqlite3VdbeMemRelease(&pCur->sub);
96546
+ sqlite3VdbeMemSetNull(&pCur->sub);
96547
+ if( pCur->needFinalize ){
96548
+ sqlite3_finalize(pCur->pStmt);
96549
+ }
96550
+ pCur->pStmt = 0;
96551
+ pCur->needFinalize = 0;
96552
+ pCur->zType = 0;
96553
+ pCur->zSchema = 0;
96554
+ pCur->zName = 0;
96555
+}
96556
+
96557
+/*
96558
+** Destructor for a bytecodevtab_cursor.
96559
+*/
96560
+static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
96561
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96562
+ bytecodevtabCursorClear(pCur);
96563
+ sqlite3_free(pCur);
96564
+ return SQLITE_OK;
96565
+}
96566
+
96567
+
96568
+/*
96569
+** Advance a bytecodevtab_cursor to its next row of output.
96570
+*/
96571
+static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
96572
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96573
+ bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
96574
+ int rc;
96575
+ if( pCur->zP4 ){
96576
+ sqlite3_free(pCur->zP4);
96577
+ pCur->zP4 = 0;
96578
+ }
96579
+ if( pCur->zName ){
96580
+ pCur->zName = 0;
96581
+ pCur->zType = 0;
96582
+ pCur->zSchema = 0;
96583
+ }
96584
+ rc = sqlite3VdbeNextOpcode(
96585
+ (Vdbe*)pCur->pStmt,
96586
+ pCur->showSubprograms ? &pCur->sub : 0,
96587
+ pTab->bTablesUsed,
96588
+ &pCur->iRowid,
96589
+ &pCur->iAddr,
96590
+ &pCur->aOp);
96591
+ if( rc!=SQLITE_OK ){
96592
+ sqlite3VdbeMemSetNull(&pCur->sub);
96593
+ pCur->aOp = 0;
96594
+ }
96595
+ return SQLITE_OK;
96596
+}
96597
+
96598
+/*
96599
+** Return TRUE if the cursor has been moved off of the last
96600
+** row of output.
96601
+*/
96602
+static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
96603
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96604
+ return pCur->aOp==0;
96605
+}
96606
+
96607
+/*
96608
+** Return values of columns for the row at which the bytecodevtab_cursor
96609
+** is currently pointing.
96610
+*/
96611
+static int bytecodevtabColumn(
96612
+ sqlite3_vtab_cursor *cur, /* The cursor */
96613
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
96614
+ int i /* Which column to return */
96615
+){
96616
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96617
+ bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
96618
+ Op *pOp = pCur->aOp + pCur->iAddr;
96619
+ if( pVTab->bTablesUsed ){
96620
+ if( i==4 ){
96621
+ i = 8;
96622
+ }else{
96623
+ if( i<=2 && pCur->zType==0 ){
96624
+ Schema *pSchema;
96625
+ HashElem *k;
96626
+ int iDb = pOp->p3;
96627
+ int iRoot = pOp->p2;
96628
+ sqlite3 *db = pVTab->db;
96629
+ pSchema = db->aDb[iDb].pSchema;
96630
+ pCur->zSchema = db->aDb[iDb].zDbSName;
96631
+ for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
96632
+ Table *pTab = (Table*)sqliteHashData(k);
96633
+ if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
96634
+ pCur->zName = pTab->zName;
96635
+ pCur->zType = "table";
96636
+ break;
96637
+ }
96638
+ }
96639
+ if( pCur->zName==0 ){
96640
+ for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
96641
+ Index *pIdx = (Index*)sqliteHashData(k);
96642
+ if( pIdx->tnum==iRoot ){
96643
+ pCur->zName = pIdx->zName;
96644
+ pCur->zType = "index";
96645
+ }
96646
+ }
96647
+ }
96648
+ }
96649
+ i += 10;
96650
+ }
96651
+ }
96652
+ switch( i ){
96653
+ case 0: /* addr */
96654
+ sqlite3_result_int(ctx, pCur->iAddr);
96655
+ break;
96656
+ case 1: /* opcode */
96657
+ sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
96658
+ -1, SQLITE_STATIC);
96659
+ break;
96660
+ case 2: /* p1 */
96661
+ sqlite3_result_int(ctx, pOp->p1);
96662
+ break;
96663
+ case 3: /* p2 */
96664
+ sqlite3_result_int(ctx, pOp->p2);
96665
+ break;
96666
+ case 4: /* p3 */
96667
+ sqlite3_result_int(ctx, pOp->p3);
96668
+ break;
96669
+ case 5: /* p4 */
96670
+ case 7: /* comment */
96671
+ if( pCur->zP4==0 ){
96672
+ pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
96673
+ }
96674
+ if( i==5 ){
96675
+ sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
96676
+ }else{
96677
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
96678
+ char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
96679
+ sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
96680
+#endif
96681
+ }
96682
+ break;
96683
+ case 6: /* p5 */
96684
+ sqlite3_result_int(ctx, pOp->p5);
96685
+ break;
96686
+ case 8: { /* subprog */
96687
+ Op *aOp = pCur->aOp;
96688
+ assert( aOp[0].opcode==OP_Init );
96689
+ assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
96690
+ if( pCur->iRowid==pCur->iAddr+1 ){
96691
+ break; /* Result is NULL for the main program */
96692
+ }else if( aOp[0].p4.z!=0 ){
96693
+ sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
96694
+ }else{
96695
+ sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
96696
+ }
96697
+ break;
96698
+ }
96699
+ case 10: /* tables_used.type */
96700
+ sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
96701
+ break;
96702
+ case 11: /* tables_used.schema */
96703
+ sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
96704
+ break;
96705
+ case 12: /* tables_used.name */
96706
+ sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
96707
+ break;
96708
+ case 13: /* tables_used.wr */
96709
+ sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
96710
+ break;
96711
+ }
96712
+ return SQLITE_OK;
96713
+}
96714
+
96715
+/*
96716
+** Return the rowid for the current row. In this implementation, the
96717
+** rowid is the same as the output value.
96718
+*/
96719
+static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
96720
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96721
+ *pRowid = pCur->iRowid;
96722
+ return SQLITE_OK;
96723
+}
96724
+
96725
+/*
96726
+** Initialize a cursor.
96727
+**
96728
+** idxNum==0 means show all subprograms
96729
+** idxNum==1 means show only the main bytecode and omit subprograms.
96730
+*/
96731
+static int bytecodevtabFilter(
96732
+ sqlite3_vtab_cursor *pVtabCursor,
96733
+ int idxNum, const char *idxStr,
96734
+ int argc, sqlite3_value **argv
96735
+){
96736
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
96737
+ bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
96738
+ int rc = SQLITE_OK;
96739
+
96740
+ bytecodevtabCursorClear(pCur);
96741
+ pCur->iRowid = 0;
96742
+ pCur->iAddr = 0;
96743
+ pCur->showSubprograms = idxNum==0;
96744
+ assert( argc==1 );
96745
+ if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
96746
+ const char *zSql = (const char*)sqlite3_value_text(argv[0]);
96747
+ if( zSql==0 ){
96748
+ rc = SQLITE_NOMEM;
96749
+ }else{
96750
+ rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
96751
+ pCur->needFinalize = 1;
96752
+ }
96753
+ }else{
96754
+ pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
96755
+ }
96756
+ if( pCur->pStmt==0 ){
96757
+ pVTab->base.zErrMsg = sqlite3_mprintf(
96758
+ "argument to %s() is not a valid SQL statement",
96759
+ pVTab->bTablesUsed ? "tables_used" : "bytecode"
96760
+ );
96761
+ rc = SQLITE_ERROR;
96762
+ }else{
96763
+ bytecodevtabNext(pVtabCursor);
96764
+ }
96765
+ return rc;
96766
+}
96767
+
96768
+/*
96769
+** We must have a single stmt=? constraint that will be passed through
96770
+** into the xFilter method. If there is no valid stmt=? constraint,
96771
+** then return an SQLITE_CONSTRAINT error.
96772
+*/
96773
+static int bytecodevtabBestIndex(
96774
+ sqlite3_vtab *tab,
96775
+ sqlite3_index_info *pIdxInfo
96776
+){
96777
+ int i;
96778
+ int rc = SQLITE_CONSTRAINT;
96779
+ struct sqlite3_index_constraint *p;
96780
+ bytecodevtab *pVTab = (bytecodevtab*)tab;
96781
+ int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
96782
+ pIdxInfo->estimatedCost = (double)100;
96783
+ pIdxInfo->estimatedRows = 100;
96784
+ pIdxInfo->idxNum = 0;
96785
+ for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
96786
+ if( p->usable==0 ) continue;
96787
+ if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
96788
+ rc = SQLITE_OK;
96789
+ pIdxInfo->aConstraintUsage[i].omit = 1;
96790
+ pIdxInfo->aConstraintUsage[i].argvIndex = 1;
96791
+ }
96792
+ if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
96793
+ pIdxInfo->aConstraintUsage[i].omit = 1;
96794
+ pIdxInfo->idxNum = 1;
96795
+ }
96796
+ }
96797
+ return rc;
96798
+}
96799
+
96800
+/*
96801
+** This following structure defines all the methods for the
96802
+** virtual table.
96803
+*/
96804
+static sqlite3_module bytecodevtabModule = {
96805
+ /* iVersion */ 0,
96806
+ /* xCreate */ 0,
96807
+ /* xConnect */ bytecodevtabConnect,
96808
+ /* xBestIndex */ bytecodevtabBestIndex,
96809
+ /* xDisconnect */ bytecodevtabDisconnect,
96810
+ /* xDestroy */ 0,
96811
+ /* xOpen */ bytecodevtabOpen,
96812
+ /* xClose */ bytecodevtabClose,
96813
+ /* xFilter */ bytecodevtabFilter,
96814
+ /* xNext */ bytecodevtabNext,
96815
+ /* xEof */ bytecodevtabEof,
96816
+ /* xColumn */ bytecodevtabColumn,
96817
+ /* xRowid */ bytecodevtabRowid,
96818
+ /* xUpdate */ 0,
96819
+ /* xBegin */ 0,
96820
+ /* xSync */ 0,
96821
+ /* xCommit */ 0,
96822
+ /* xRollback */ 0,
96823
+ /* xFindMethod */ 0,
96824
+ /* xRename */ 0,
96825
+ /* xSavepoint */ 0,
96826
+ /* xRelease */ 0,
96827
+ /* xRollbackTo */ 0,
96828
+ /* xShadowName */ 0
96829
+};
96830
+
96831
+
96832
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
96833
+ int rc;
96834
+ rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
96835
+ if( rc==SQLITE_OK ){
96836
+ rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
96837
+ }
96838
+ return rc;
96839
+}
96840
+#elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
96841
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
96842
+#endif /* SQLITE_ENABLE_BYTECODE_VTAB */
96843
+
96844
+/************** End of vdbevtab.c ********************************************/
9609896845
/************** Begin file memjournal.c **************************************/
9609996846
/*
9610096847
** 2008 October 7
9610196848
**
9610296849
** The author disclaims copyright to this source code. In place of
@@ -96735,10 +97482,47 @@
9673597482
}
9673697483
p = p->pPrior;
9673797484
}while( p!=0 );
9673897485
return WRC_Continue;
9673997486
}
97487
+
97488
+/* Increase the walkerDepth when entering a subquery, and
97489
+** descrease when leaving the subquery.
97490
+*/
97491
+SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){
97492
+ UNUSED_PARAMETER(pSelect);
97493
+ pWalker->walkerDepth++;
97494
+ return WRC_Continue;
97495
+}
97496
+SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){
97497
+ UNUSED_PARAMETER(pSelect);
97498
+ pWalker->walkerDepth--;
97499
+}
97500
+
97501
+
97502
+/*
97503
+** No-op routine for the parse-tree walker.
97504
+**
97505
+** When this routine is the Walker.xExprCallback then expression trees
97506
+** are walked without any actions being taken at each node. Presumably,
97507
+** when this routine is used for Walker.xExprCallback then
97508
+** Walker.xSelectCallback is set to do something useful for every
97509
+** subquery in the parser tree.
97510
+*/
97511
+SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
97512
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
97513
+ return WRC_Continue;
97514
+}
97515
+
97516
+/*
97517
+** No-op routine for the parse-tree walker for SELECT statements.
97518
+** subquery in the parser tree.
97519
+*/
97520
+SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
97521
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
97522
+ return WRC_Continue;
97523
+}
9674097524
9674197525
/************** End of walker.c **********************************************/
9674297526
/************** Begin file resolve.c *****************************************/
9674397527
/*
9674497528
** 2008 August 18
@@ -96764,10 +97548,12 @@
9676497548
** This needs to occur when copying a TK_AGG_FUNCTION node from an
9676597549
** outer query into an inner subquery.
9676697550
**
9676797551
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
9676897552
** is a helper function - a callback for the tree walker.
97553
+**
97554
+** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c
9676997555
*/
9677097556
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
9677197557
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
9677297558
return WRC_Continue;
9677397559
}
@@ -98739,11 +99525,11 @@
9873999525
** SELECT * FROM t1 WHERE (select a from t1);
9874099526
*/
9874199527
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
9874299528
int op;
9874399529
while( ExprHasProperty(pExpr, EP_Skip) ){
98744
- assert( pExpr->op==TK_COLLATE );
99530
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
9874599531
pExpr = pExpr->pLeft;
9874699532
assert( pExpr!=0 );
9874799533
}
9874899534
op = pExpr->op;
9874999535
if( op==TK_SELECT ){
@@ -98806,11 +99592,11 @@
9880699592
/*
9880799593
** Skip over any TK_COLLATE operators.
9880899594
*/
9880999595
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
9881099596
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
98811
- assert( pExpr->op==TK_COLLATE );
99597
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
9881299598
pExpr = pExpr->pLeft;
9881399599
}
9881499600
return pExpr;
9881599601
}
9881699602
@@ -98825,11 +99611,11 @@
9882599611
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
9882699612
assert( pExpr->x.pList->nExpr>0 );
9882799613
assert( pExpr->op==TK_FUNCTION );
9882899614
pExpr = pExpr->x.pList->a[0].pExpr;
9882999615
}else{
98830
- assert( pExpr->op==TK_COLLATE );
99616
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
9883199617
pExpr = pExpr->pLeft;
9883299618
}
9883399619
}
9883499620
return pExpr;
9883599621
}
@@ -102394,10 +103180,17 @@
102394103180
}
102395103181
setDoNotMergeFlagOnCopy(v);
102396103182
sqlite3VdbeResolveLabel(v, endCoalesce);
102397103183
break;
102398103184
}
103185
+ case INLINEFUNC_iif: {
103186
+ Expr caseExpr;
103187
+ memset(&caseExpr, 0, sizeof(caseExpr));
103188
+ caseExpr.op = TK_CASE;
103189
+ caseExpr.x.pList = pFarg;
103190
+ return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
103191
+ }
102399103192
102400103193
default: {
102401103194
/* The UNLIKELY() function is a no-op. The result is the value
102402103195
** of the first argument.
102403103196
*/
@@ -102498,11 +103291,14 @@
102498103291
op = pExpr->op;
102499103292
}
102500103293
switch( op ){
102501103294
case TK_AGG_COLUMN: {
102502103295
AggInfo *pAggInfo = pExpr->pAggInfo;
102503
- struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
103296
+ struct AggInfo_col *pCol;
103297
+ assert( pAggInfo!=0 );
103298
+ assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
103299
+ pCol = &pAggInfo->aCol[pExpr->iAgg];
102504103300
if( !pAggInfo->directMode ){
102505103301
assert( pCol->iMem>0 );
102506103302
return pCol->iMem;
102507103303
}else if( pAggInfo->useSortingIdx ){
102508103304
Table *pTab = pCol->pTab;
@@ -102798,11 +103594,14 @@
102798103594
sqlite3VdbeJumpHere(v, addr);
102799103595
break;
102800103596
}
102801103597
case TK_AGG_FUNCTION: {
102802103598
AggInfo *pInfo = pExpr->pAggInfo;
102803
- if( pInfo==0 ){
103599
+ if( pInfo==0
103600
+ || NEVER(pExpr->iAgg<0)
103601
+ || NEVER(pExpr->iAgg>=pInfo->nFunc)
103602
+ ){
102804103603
assert( !ExprHasProperty(pExpr, EP_IntValue) );
102805103604
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
102806103605
}else{
102807103606
return pInfo->aFunc[pExpr->iAgg].iMem;
102808103607
}
@@ -103176,11 +103975,11 @@
103176103975
assert( pExpr->affExpr==OE_Rollback
103177103976
|| pExpr->affExpr==OE_Abort
103178103977
|| pExpr->affExpr==OE_Fail
103179103978
|| pExpr->affExpr==OE_Ignore
103180103979
);
103181
- if( !pParse->pTriggerTab ){
103980
+ if( !pParse->pTriggerTab && !pParse->nested ){
103182103981
sqlite3ErrorMsg(pParse,
103183103982
"RAISE() may only be used within a trigger-program");
103184103983
return 0;
103185103984
}
103186103985
if( pExpr->affExpr==OE_Abort ){
@@ -103190,12 +103989,13 @@
103190103989
if( pExpr->affExpr==OE_Ignore ){
103191103990
sqlite3VdbeAddOp4(
103192103991
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
103193103992
VdbeCoverage(v);
103194103993
}else{
103195
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
103196
- pExpr->affExpr, pExpr->u.zToken, 0, 0);
103994
+ sqlite3HaltConstraint(pParse,
103995
+ pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
103996
+ pExpr->affExpr, pExpr->u.zToken, 0, 0);
103197103997
}
103198103998
103199103999
break;
103200104000
}
103201104001
#endif
@@ -104553,19 +105353,10 @@
104553105353
}
104554105354
}
104555105355
}
104556105356
return WRC_Continue;
104557105357
}
104558
-static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
104559
- UNUSED_PARAMETER(pSelect);
104560
- pWalker->walkerDepth++;
104561
- return WRC_Continue;
104562
-}
104563
-static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
104564
- UNUSED_PARAMETER(pSelect);
104565
- pWalker->walkerDepth--;
104566
-}
104567105358
104568105359
/*
104569105360
** Analyze the pExpr expression looking for aggregate functions and
104570105361
** for variables that need to be added to AggInfo object that pNC->pAggInfo
104571105362
** points to. Additional entries are made on the AggInfo object as
@@ -104575,12 +105366,12 @@
104575105366
** analyzed by sqlite3ResolveExprNames().
104576105367
*/
104577105368
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
104578105369
Walker w;
104579105370
w.xExprCallback = analyzeAggregate;
104580
- w.xSelectCallback = analyzeAggregatesInSelect;
104581
- w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
105371
+ w.xSelectCallback = sqlite3WalkerDepthIncrease;
105372
+ w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
104582105373
w.walkerDepth = 0;
104583105374
w.u.pNC = pNC;
104584105375
w.pParse = 0;
104585105376
assert( pNC->pSrcList!=0 );
104586105377
sqlite3WalkExpr(&w, pExpr);
@@ -104815,11 +105606,14 @@
104815105606
if( !zName ) goto exit_rename_table;
104816105607
104817105608
/* Check that a table or index named 'zName' does not already exist
104818105609
** in database iDb. If so, this is an error.
104819105610
*/
104820
- if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
105611
+ if( sqlite3FindTable(db, zName, zDb)
105612
+ || sqlite3FindIndex(db, zName, zDb)
105613
+ || sqlite3IsShadowTableOf(db, pTab, zName)
105614
+ ){
104821105615
sqlite3ErrorMsg(pParse,
104822105616
"there is already another table or index with this name: %s", zName);
104823105617
goto exit_rename_table;
104824105618
}
104825105619
@@ -104946,10 +105740,26 @@
104946105740
exit_rename_table:
104947105741
sqlite3SrcListDelete(db, pSrc);
104948105742
sqlite3DbFree(db, zName);
104949105743
db->mDbFlags = savedDbFlags;
104950105744
}
105745
+
105746
+/*
105747
+** Write code that will raise an error if the table described by
105748
+** zDb and zTab is not empty.
105749
+*/
105750
+static void sqlite3ErrorIfNotEmpty(
105751
+ Parse *pParse, /* Parsing context */
105752
+ const char *zDb, /* Schema holding the table */
105753
+ const char *zTab, /* Table to check for empty */
105754
+ const char *zErr /* Error message text */
105755
+){
105756
+ sqlite3NestedParse(pParse,
105757
+ "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",
105758
+ zErr, zDb, zTab
105759
+ );
105760
+}
104951105761
104952105762
/*
104953105763
** This function is called after an "ALTER TABLE ... ADD" statement
104954105764
** has been parsed. Argument pColDef contains the text of the new
104955105765
** column definition.
@@ -104999,11 +105809,12 @@
104999105809
if( pCol->colFlags & COLFLAG_PRIMKEY ){
105000105810
sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
105001105811
return;
105002105812
}
105003105813
if( pNew->pIndex ){
105004
- sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
105814
+ sqlite3ErrorMsg(pParse,
105815
+ "Cannot add a UNIQUE column");
105005105816
return;
105006105817
}
105007105818
if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
105008105819
/* If the default value for the new column was specified with a
105009105820
** literal NULL, then set pDflt to 0. This simplifies checking
@@ -105012,19 +105823,18 @@
105012105823
assert( pDflt==0 || pDflt->op==TK_SPAN );
105013105824
if( pDflt && pDflt->pLeft->op==TK_NULL ){
105014105825
pDflt = 0;
105015105826
}
105016105827
if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
105017
- sqlite3ErrorMsg(pParse,
105828
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
105018105829
"Cannot add a REFERENCES column with non-NULL default value");
105019
- return;
105020105830
}
105021105831
if( pCol->notNull && !pDflt ){
105022
- sqlite3ErrorMsg(pParse,
105832
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
105023105833
"Cannot add a NOT NULL column with default value NULL");
105024
- return;
105025105834
}
105835
+
105026105836
105027105837
/* Ensure the default expression is something that sqlite3ValueFromExpr()
105028105838
** can handle (i.e. not CURRENT_TIME etc.)
105029105839
*/
105030105840
if( pDflt ){
@@ -105035,18 +105845,17 @@
105035105845
if( rc!=SQLITE_OK ){
105036105846
assert( db->mallocFailed == 1 );
105037105847
return;
105038105848
}
105039105849
if( !pVal ){
105040
- sqlite3ErrorMsg(pParse,"Cannot add a column with non-constant default");
105041
- return;
105850
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
105851
+ "Cannot add a column with non-constant default");
105042105852
}
105043105853
sqlite3ValueFree(pVal);
105044105854
}
105045105855
}else if( pCol->colFlags & COLFLAG_STORED ){
105046
- sqlite3ErrorMsg(pParse, "cannot add a STORED column");
105047
- return;
105856
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column");
105048105857
}
105049105858
105050105859
105051105860
/* Modify the CREATE TABLE statement. */
105052105861
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
@@ -106605,10 +107414,15 @@
106605107414
sqlite3 *db = pParse->db;
106606107415
Db *pDb;
106607107416
Vdbe *v = sqlite3GetVdbe(pParse);
106608107417
int aRoot[ArraySize(aTable)];
106609107418
u8 aCreateTbl[ArraySize(aTable)];
107419
+#ifdef SQLITE_ENABLE_STAT4
107420
+ const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
107421
+#else
107422
+ const int nToOpen = 1;
107423
+#endif
106610107424
106611107425
if( v==0 ) return;
106612107426
assert( sqlite3BtreeHoldsAllMutexes(db) );
106613107427
assert( sqlite3VdbeDb(v)==db );
106614107428
pDb = &db->aDb[iDb];
@@ -106617,12 +107431,13 @@
106617107431
** if they do already exist.
106618107432
*/
106619107433
for(i=0; i<ArraySize(aTable); i++){
106620107434
const char *zTab = aTable[i].zName;
106621107435
Table *pStat;
107436
+ aCreateTbl[i] = 0;
106622107437
if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
106623
- if( aTable[i].zCols ){
107438
+ if( i<nToOpen ){
106624107439
/* The sqlite_statN table does not exist. Create it. Note that a
106625107440
** side-effect of the CREATE TABLE statement is to leave the rootpage
106626107441
** of the new table in register pParse->regRoot. This is important
106627107442
** because the OpenWrite opcode below will be needing it. */
106628107443
sqlite3NestedParse(pParse,
@@ -106634,11 +107449,10 @@
106634107449
}else{
106635107450
/* The table already exists. If zWhere is not NULL, delete all entries
106636107451
** associated with the table zWhere. If zWhere is NULL, delete the
106637107452
** entire contents of the table. */
106638107453
aRoot[i] = pStat->tnum;
106639
- aCreateTbl[i] = 0;
106640107454
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
106641107455
if( zWhere ){
106642107456
sqlite3NestedParse(pParse,
106643107457
"DELETE FROM %Q.%s WHERE %s=%Q",
106644107458
pDb->zDbSName, zTab, zWhereType, zWhere
@@ -106653,11 +107467,11 @@
106653107467
}
106654107468
}
106655107469
}
106656107470
106657107471
/* Open the sqlite_stat[134] tables for writing. */
106658
- for(i=0; aTable[i].zCols; i++){
107472
+ for(i=0; i<nToOpen; i++){
106659107473
assert( i<ArraySize(aTable) );
106660107474
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
106661107475
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
106662107476
VdbeComment((v, aTable[i].zName));
106663107477
}
@@ -106692,13 +107506,16 @@
106692107506
u32 iHash; /* Tiebreaker hash */
106693107507
#endif
106694107508
};
106695107509
struct StatAccum {
106696107510
sqlite3 *db; /* Database connection, for malloc() */
106697
- tRowcnt nRow; /* Number of rows in the entire table */
107511
+ tRowcnt nEst; /* Estimated number of rows */
107512
+ tRowcnt nRow; /* Number of rows visited so far */
107513
+ int nLimit; /* Analysis row-scan limit */
106698107514
int nCol; /* Number of columns in index + pk/rowid */
106699107515
int nKeyCol; /* Number of index columns w/o the pk/rowid */
107516
+ u8 nSkipAhead; /* Number of times of skip-ahead */
106700107517
StatSample current; /* Current row as a StatSample */
106701107518
#ifdef SQLITE_ENABLE_STAT4
106702107519
tRowcnt nPSample; /* How often to do a periodic sample */
106703107520
int mxSample; /* Maximum number of samples to accumulate */
106704107521
u32 iPrn; /* Pseudo-random number used for sampling */
@@ -106774,31 +107591,32 @@
106774107591
** Reclaim all memory of a StatAccum structure.
106775107592
*/
106776107593
static void statAccumDestructor(void *pOld){
106777107594
StatAccum *p = (StatAccum*)pOld;
106778107595
#ifdef SQLITE_ENABLE_STAT4
106779
- int i;
106780
- for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
106781
- for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
106782
- sampleClear(p->db, &p->current);
107596
+ if( p->mxSample ){
107597
+ int i;
107598
+ for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
107599
+ for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
107600
+ sampleClear(p->db, &p->current);
107601
+ }
106783107602
#endif
106784107603
sqlite3DbFree(p->db, p);
106785107604
}
106786107605
106787107606
/*
106788
-** Implementation of the stat_init(N,K,C) SQL function. The three parameters
107607
+** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters
106789107608
** are:
106790107609
** N: The number of columns in the index including the rowid/pk (note 1)
106791107610
** K: The number of columns in the index excluding the rowid/pk.
106792
-** C: The number of rows in the index (note 2)
107611
+** C: Estimated number of rows in the index
107612
+** L: A limit on the number of rows to scan, or 0 for no-limit
106793107613
**
106794107614
** Note 1: In the special case of the covering index that implements a
106795107615
** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
106796107616
** total number of columns in the table.
106797107617
**
106798
-** Note 2: C is only used for STAT4.
106799
-**
106800107618
** For indexes on ordinary rowid tables, N==K+1. But for indexes on
106801107619
** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
106802107620
** PRIMARY KEY of the table. The covering index that implements the
106803107621
** original WITHOUT ROWID table as N==K as a special case.
106804107622
**
@@ -106815,13 +107633,14 @@
106815107633
StatAccum *p;
106816107634
int nCol; /* Number of columns in index being sampled */
106817107635
int nKeyCol; /* Number of key columns */
106818107636
int nColUp; /* nCol rounded up for alignment */
106819107637
int n; /* Bytes of space to allocate */
106820
- sqlite3 *db; /* Database connection */
107638
+ sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */
106821107639
#ifdef SQLITE_ENABLE_STAT4
106822
- int mxSample = SQLITE_STAT4_SAMPLES;
107640
+ /* Maximum number of samples. 0 if STAT4 data is not collected */
107641
+ int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0;
106823107642
#endif
106824107643
106825107644
/* Decode the three function arguments */
106826107645
UNUSED_PARAMETER(argc);
106827107646
nCol = sqlite3_value_int(argv[0]);
@@ -106832,39 +107651,43 @@
106832107651
assert( nKeyCol>0 );
106833107652
106834107653
/* Allocate the space required for the StatAccum object */
106835107654
n = sizeof(*p)
106836107655
+ sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
106837
- + sizeof(tRowcnt)*nColUp /* StatAccum.anDLt */
107656
+ + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
106838107657
#ifdef SQLITE_ENABLE_STAT4
106839
- + sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
106840
- + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
106841
- + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
107658
+ if( mxSample ){
107659
+ n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
107660
+ + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
107661
+ + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
107662
+ }
106842107663
#endif
106843
- ;
106844107664
db = sqlite3_context_db_handle(context);
106845107665
p = sqlite3DbMallocZero(db, n);
106846107666
if( p==0 ){
106847107667
sqlite3_result_error_nomem(context);
106848107668
return;
106849107669
}
106850107670
106851107671
p->db = db;
107672
+ p->nEst = sqlite3_value_int64(argv[2]);
106852107673
p->nRow = 0;
107674
+ p->nLimit = sqlite3_value_int64(argv[3]);
106853107675
p->nCol = nCol;
106854107676
p->nKeyCol = nKeyCol;
107677
+ p->nSkipAhead = 0;
106855107678
p->current.anDLt = (tRowcnt*)&p[1];
106856107679
p->current.anEq = &p->current.anDLt[nColUp];
106857107680
106858107681
#ifdef SQLITE_ENABLE_STAT4
106859
- {
107682
+ p->mxSample = p->nLimit==0 ? mxSample : 0;
107683
+ if( mxSample ){
106860107684
u8 *pSpace; /* Allocated space not yet assigned */
106861107685
int i; /* Used to iterate through p->aSample[] */
106862107686
106863107687
p->iGet = -1;
106864
- p->mxSample = mxSample;
106865
- p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
107688
+ p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1);
106866107689
p->current.anLt = &p->current.anEq[nColUp];
106867107690
p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
106868107691
106869107692
/* Set up the StatAccum.a[] and aBest[] arrays */
106870107693
p->a = (struct StatSample*)&p->current.anLt[nColUp];
@@ -106888,11 +107711,11 @@
106888107711
** (given by the 3rd parameter) is never used and can be any positive
106889107712
** value. */
106890107713
sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
106891107714
}
106892107715
static const FuncDef statInitFuncdef = {
106893
- 2+IsStat4, /* nArg */
107716
+ 4, /* nArg */
106894107717
SQLITE_UTF8, /* funcFlags */
106895107718
0, /* pUserData */
106896107719
0, /* pNext */
106897107720
statInit, /* xSFunc */
106898107721
0, /* xFinalize */
@@ -107092,14 +107915,17 @@
107092107915
** P Pointer to the StatAccum object created by stat_init()
107093107916
** C Index of left-most column to differ from previous row
107094107917
** R Rowid for the current row. Might be a key record for
107095107918
** WITHOUT ROWID tables.
107096107919
**
107097
-** This SQL function always returns NULL. It's purpose it to accumulate
107098
-** statistical data and/or samples in the StatAccum object about the
107099
-** index being analyzed. The stat_get() SQL function will later be used to
107100
-** extract relevant information for constructing the sqlite_statN tables.
107920
+** The purpose of this routine is to collect statistical data and/or
107921
+** samples from the index being analyzed into the StatAccum object.
107922
+** The stat_get() SQL function will be used afterwards to
107923
+** retrieve the information gathered.
107924
+**
107925
+** This SQL function usually returns NULL, but might return an integer
107926
+** if it wants the byte-code to do special processing.
107101107927
**
107102107928
** The R parameter is only used for STAT4
107103107929
*/
107104107930
static void statPush(
107105107931
sqlite3_context *context,
@@ -107121,11 +107947,11 @@
107121107947
/* This is the first call to this function. Do initialization. */
107122107948
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
107123107949
}else{
107124107950
/* Second and subsequent calls get processed here */
107125107951
#ifdef SQLITE_ENABLE_STAT4
107126
- samplePushPrevious(p, iChng);
107952
+ if( p->mxSample ) samplePushPrevious(p, iChng);
107127107953
#endif
107128107954
107129107955
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
107130107956
** to the current row of the index. */
107131107957
for(i=0; i<iChng; i++){
@@ -107132,30 +107958,29 @@
107132107958
p->current.anEq[i]++;
107133107959
}
107134107960
for(i=iChng; i<p->nCol; i++){
107135107961
p->current.anDLt[i]++;
107136107962
#ifdef SQLITE_ENABLE_STAT4
107137
- p->current.anLt[i] += p->current.anEq[i];
107963
+ if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
107138107964
#endif
107139107965
p->current.anEq[i] = 1;
107140107966
}
107141107967
}
107968
+
107142107969
p->nRow++;
107143107970
#ifdef SQLITE_ENABLE_STAT4
107144
- if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
107145
- sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
107146
- }else{
107147
- sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
107148
- sqlite3_value_blob(argv[2]));
107149
- }
107150
- p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
107151
-#endif
107152
-
107153
-#ifdef SQLITE_ENABLE_STAT4
107154
- {
107155
- tRowcnt nLt = p->current.anLt[p->nCol-1];
107156
-
107971
+ if( p->mxSample ){
107972
+ tRowcnt nLt;
107973
+ if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
107974
+ sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
107975
+ }else{
107976
+ sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
107977
+ sqlite3_value_blob(argv[2]));
107978
+ }
107979
+ p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
107980
+
107981
+ nLt = p->current.anLt[p->nCol-1];
107157107982
/* Check if this is to be a periodic sample. If so, add it. */
107158107983
if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
107159107984
p->current.isPSample = 1;
107160107985
p->current.iCol = 0;
107161107986
sampleInsert(p, &p->current, p->nCol-1);
@@ -107167,13 +107992,18 @@
107167107992
p->current.iCol = i;
107168107993
if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
107169107994
sampleCopy(p, &p->aBest[i], &p->current);
107170107995
}
107171107996
}
107997
+ }else
107998
+#endif
107999
+ if( p->nLimit && p->nRow>(tRowcnt)p->nLimit*(p->nSkipAhead+1) ){
108000
+ p->nSkipAhead++;
108001
+ sqlite3_result_int(context, p->current.anDLt[0]>0);
107172108002
}
107173
-#endif
107174108003
}
108004
+
107175108005
static const FuncDef statPushFuncdef = {
107176108006
2+IsStat4, /* nArg */
107177108007
SQLITE_UTF8, /* funcFlags */
107178108008
0, /* pUserData */
107179108009
0, /* pNext */
@@ -107221,10 +108051,11 @@
107221108051
assert( argc==2 );
107222108052
assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
107223108053
|| eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
107224108054
|| eCall==STAT_GET_NDLT
107225108055
);
108056
+ assert( eCall==STAT_GET_STAT1 || p->mxSample );
107226108057
if( eCall==STAT_GET_STAT1 )
107227108058
#else
107228108059
assert( argc==1 );
107229108060
#endif
107230108061
{
@@ -107256,11 +108087,12 @@
107256108087
if( zRet==0 ){
107257108088
sqlite3_result_error_nomem(context);
107258108089
return;
107259108090
}
107260108091
107261
- sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
108092
+ sqlite3_snprintf(24, zRet, "%llu",
108093
+ p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
107262108094
z = zRet + sqlite3Strlen30(zRet);
107263108095
for(i=0; i<p->nKeyCol; i++){
107264108096
u64 nDistinct = p->current.anDLt[i] + 1;
107265108097
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
107266108098
sqlite3_snprintf(24, z, " %llu", iVal);
@@ -107332,20 +108164,20 @@
107332108164
0, 0, /* xValue, xInverse */
107333108165
"stat_get", /* zName */
107334108166
{0}
107335108167
};
107336108168
107337
-static void callStatGet(Parse *pParse, int regStat4, int iParam, int regOut){
108169
+static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
107338108170
#ifdef SQLITE_ENABLE_STAT4
107339
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat4+1);
108171
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1);
107340108172
#elif SQLITE_DEBUG
107341108173
assert( iParam==STAT_GET_STAT1 );
107342108174
#else
107343108175
UNUSED_PARAMETER( iParam );
107344108176
#endif
107345
- assert( regOut!=regStat4 && regOut!=regStat4+1 );
107346
- sqlite3VdbeAddFunctionCall(pParse, 0, regStat4, regOut, 1+IsStat4,
108177
+ assert( regOut!=regStat && regOut!=regStat+1 );
108178
+ sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4,
107347108179
&statGetFuncdef, 0);
107348108180
}
107349108181
107350108182
/*
107351108183
** Generate code to do an analysis of all indices associated with
@@ -107367,16 +108199,15 @@
107367108199
int i; /* Loop counter */
107368108200
int jZeroRows = -1; /* Jump from here if number of rows is zero */
107369108201
int iDb; /* Index of database containing pTab */
107370108202
u8 needTableCnt = 1; /* True to count the table */
107371108203
int regNewRowid = iMem++; /* Rowid for the inserted record */
107372
- int regStat4 = iMem++; /* Register to hold StatAccum object */
108204
+ int regStat = iMem++; /* Register to hold StatAccum object */
107373108205
int regChng = iMem++; /* Index of changed index field */
107374
-#ifdef SQLITE_ENABLE_STAT4
107375108206
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
107376
-#endif
107377108207
int regTemp = iMem++; /* Temporary use register */
108208
+ int regTemp2 = iMem++; /* Second temporary use register */
107378108209
int regTabname = iMem++; /* Register containing table name */
107379108210
int regIdxname = iMem++; /* Register containing index name */
107380108211
int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
107381108212
int regPrev = iMem; /* MUST BE LAST (see below) */
107382108213
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -107500,21 +108331,30 @@
107500108331
/* Invoke the stat_init() function. The arguments are:
107501108332
**
107502108333
** (1) the number of columns in the index including the rowid
107503108334
** (or for a WITHOUT ROWID table, the number of PK columns),
107504108335
** (2) the number of columns in the key without the rowid/pk
107505
- ** (3) the number of rows in the index,
107506
- **
107507
- **
107508
- ** The third argument is only used for STAT4
108336
+ ** (3) estimated number of rows in the index,
107509108337
*/
108338
+ sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
108339
+ assert( regRowid==regStat+2 );
108340
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
107510108341
#ifdef SQLITE_ENABLE_STAT4
107511
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
108342
+ if( OptimizationEnabled(db, SQLITE_Stat4) ){
108343
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
108344
+ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
108345
+ VdbeCoverage(v);
108346
+ }else
107512108347
#endif
107513
- sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
107514
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
107515
- sqlite3VdbeAddFunctionCall(pParse, 0, regStat4+1, regStat4, 2+IsStat4,
108348
+ {
108349
+ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
108350
+ VdbeCoverage(v);
108351
+ sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
108352
+ }
108353
+ assert( regTemp2==regStat+4 );
108354
+ sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
108355
+ sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
107516108356
&statInitFuncdef, 0);
107517108357
107518108358
/* Implementation of the following:
107519108359
**
107520108360
** Rewind csr
@@ -107521,12 +108361,10 @@
107521108361
** if eof(csr) goto end_of_scan;
107522108362
** regChng = 0
107523108363
** goto next_push_0;
107524108364
**
107525108365
*/
107526
- addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
107527
- VdbeCoverage(v);
107528108366
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
107529108367
addrNextRow = sqlite3VdbeCurrentAddr(v);
107530108368
107531108369
if( nColTest>0 ){
107532108370
int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
@@ -107555,10 +108393,11 @@
107555108393
}
107556108394
for(i=0; i<nColTest; i++){
107557108395
char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
107558108396
sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
107559108397
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
108398
+ VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
107560108399
aGotoChng[i] =
107561108400
sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
107562108401
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
107563108402
VdbeCoverage(v);
107564108403
}
@@ -107575,10 +108414,11 @@
107575108414
*/
107576108415
sqlite3VdbeJumpHere(v, addrNextRow-1);
107577108416
for(i=0; i<nColTest; i++){
107578108417
sqlite3VdbeJumpHere(v, aGotoChng[i]);
107579108418
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
108419
+ VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
107580108420
}
107581108421
sqlite3VdbeResolveLabel(v, endDistinctTest);
107582108422
sqlite3DbFree(db, aGotoChng);
107583108423
}
107584108424
@@ -107588,34 +108428,50 @@
107588108428
** stat_push(P, regChng, regRowid) // 3rd parameter STAT4 only
107589108429
** Next csr
107590108430
** if !eof(csr) goto next_row;
107591108431
*/
107592108432
#ifdef SQLITE_ENABLE_STAT4
107593
- assert( regRowid==(regStat4+2) );
107594
- if( HasRowid(pTab) ){
107595
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
107596
- }else{
107597
- Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
107598
- int j, k, regKey;
107599
- regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
107600
- for(j=0; j<pPk->nKeyCol; j++){
107601
- k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
107602
- assert( k>=0 && k<pIdx->nColumn );
107603
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
107604
- VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
107605
- }
107606
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
107607
- sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
108433
+ if( OptimizationEnabled(db, SQLITE_Stat4) ){
108434
+ assert( regRowid==(regStat+2) );
108435
+ if( HasRowid(pTab) ){
108436
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
108437
+ }else{
108438
+ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
108439
+ int j, k, regKey;
108440
+ regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
108441
+ for(j=0; j<pPk->nKeyCol; j++){
108442
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
108443
+ assert( k>=0 && k<pIdx->nColumn );
108444
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
108445
+ VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
108446
+ }
108447
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
108448
+ sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
108449
+ }
107608108450
}
107609108451
#endif
107610
- assert( regChng==(regStat4+1) );
107611
- sqlite3VdbeAddFunctionCall(pParse, 1, regStat4, regTemp, 2+IsStat4,
107612
- &statPushFuncdef, 0);
107613
- sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
108452
+ assert( regChng==(regStat+1) );
108453
+ {
108454
+ sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4,
108455
+ &statPushFuncdef, 0);
108456
+ if( db->nAnalysisLimit ){
108457
+ int j1, j2, j3;
108458
+ j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v);
108459
+ j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v);
108460
+ j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1);
108461
+ VdbeCoverage(v);
108462
+ sqlite3VdbeJumpHere(v, j1);
108463
+ sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
108464
+ sqlite3VdbeJumpHere(v, j2);
108465
+ sqlite3VdbeJumpHere(v, j3);
108466
+ }else{
108467
+ sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
108468
+ }
108469
+ }
107614108470
107615108471
/* Add the entry to the stat1 table. */
107616
- callStatGet(pParse, regStat4, STAT_GET_STAT1, regStat1);
108472
+ callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
107617108473
assert( "BBB"[0]==SQLITE_AFF_TEXT );
107618108474
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
107619108475
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
107620108476
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
107621108477
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -107623,11 +108479,11 @@
107623108479
#endif
107624108480
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
107625108481
107626108482
/* Add the entries to the stat4 table. */
107627108483
#ifdef SQLITE_ENABLE_STAT4
107628
- {
108484
+ if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){
107629108485
int regEq = regStat1;
107630108486
int regLt = regStat1+1;
107631108487
int regDLt = regStat1+2;
107632108488
int regSample = regStat1+3;
107633108489
int regCol = regStat1+4;
@@ -107637,16 +108493,16 @@
107637108493
u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
107638108494
107639108495
pParse->nMem = MAX(pParse->nMem, regCol+nCol);
107640108496
107641108497
addrNext = sqlite3VdbeCurrentAddr(v);
107642
- callStatGet(pParse, regStat4, STAT_GET_ROWID, regSampleRowid);
108498
+ callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
107643108499
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
107644108500
VdbeCoverage(v);
107645
- callStatGet(pParse, regStat4, STAT_GET_NEQ, regEq);
107646
- callStatGet(pParse, regStat4, STAT_GET_NLT, regLt);
107647
- callStatGet(pParse, regStat4, STAT_GET_NDLT, regDLt);
108501
+ callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
108502
+ callStatGet(pParse, regStat, STAT_GET_NLT, regLt);
108503
+ callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt);
107648108504
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
107649108505
VdbeCoverage(v);
107650108506
for(i=0; i<nCol; i++){
107651108507
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
107652108508
}
@@ -109500,26 +110356,43 @@
109500110356
** exists */
109501110357
if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
109502110358
return 0;
109503110359
}
109504110360
#endif
109505
- while(1){
109506
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
109507
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
109508
- if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
109509
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
109510
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
109511
- if( p ) return p;
109512
- }
109513
- }
109514
- /* Not found. If the name we were looking for was temp.sqlite_master
109515
- ** then change the name to sqlite_temp_master and try again. */
109516
- if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
109517
- if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
109518
- zName = TEMP_MASTER_NAME;
109519
- }
109520
- return 0;
110361
+ if( zDatabase ){
110362
+ for(i=0; i<db->nDb; i++){
110363
+ if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
110364
+ }
110365
+ if( i>=db->nDb ){
110366
+ /* No match against the official names. But always match "main"
110367
+ ** to schema 0 as a legacy fallback. */
110368
+ if( sqlite3StrICmp(zDatabase,"main")==0 ){
110369
+ i = 0;
110370
+ }else{
110371
+ return 0;
110372
+ }
110373
+ }
110374
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110375
+ if( p==0 && i==1 && sqlite3StrICmp(zName, MASTER_NAME)==0 ){
110376
+ /* All temp.sqlite_master to be an alias for sqlite_temp_master */
110377
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, TEMP_MASTER_NAME);
110378
+ }
110379
+ }else{
110380
+ /* Match against TEMP first */
110381
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
110382
+ if( p ) return p;
110383
+ /* The main database is second */
110384
+ p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
110385
+ if( p ) return p;
110386
+ /* Attached databases are in order of attachment */
110387
+ for(i=2; i<db->nDb; i++){
110388
+ assert( sqlite3SchemaMutexHeld(db, i, 0) );
110389
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110390
+ if( p ) break;
110391
+ }
110392
+ }
110393
+ return p;
109521110394
}
109522110395
109523110396
/*
109524110397
** Locate the in-memory structure that describes a particular database
109525110398
** table given the name of that table and (optionally) the name of the
@@ -111319,10 +112192,32 @@
111319112192
assert( pPk->nColumn==j );
111320112193
assert( pTab->nNVCol<=j );
111321112194
recomputeColumnsNotIndexed(pPk);
111322112195
}
111323112196
112197
+
112198
+#ifndef SQLITE_OMIT_VIRTUALTABLE
112199
+/*
112200
+** Return true if pTab is a virtual table and zName is a shadow table name
112201
+** for that virtual table.
112202
+*/
112203
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
112204
+ int nName; /* Length of zName */
112205
+ Module *pMod; /* Module for the virtual table */
112206
+
112207
+ if( !IsVirtual(pTab) ) return 0;
112208
+ nName = sqlite3Strlen30(pTab->zName);
112209
+ if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
112210
+ if( zName[nName]!='_' ) return 0;
112211
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
112212
+ if( pMod==0 ) return 0;
112213
+ if( pMod->pModule->iVersion<3 ) return 0;
112214
+ if( pMod->pModule->xShadowName==0 ) return 0;
112215
+ return pMod->pModule->xShadowName(zName+nName+1);
112216
+}
112217
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112218
+
111324112219
#ifndef SQLITE_OMIT_VIRTUALTABLE
111325112220
/*
111326112221
** Return true if zName is a shadow table name in the current database
111327112222
** connection.
111328112223
**
@@ -111330,26 +112225,21 @@
111330112225
** restored to its original value prior to this routine returning.
111331112226
*/
111332112227
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
111333112228
char *zTail; /* Pointer to the last "_" in zName */
111334112229
Table *pTab; /* Table that zName is a shadow of */
111335
- Module *pMod; /* Module for the virtual table */
111336
-
111337112230
zTail = strrchr(zName, '_');
111338112231
if( zTail==0 ) return 0;
111339112232
*zTail = 0;
111340112233
pTab = sqlite3FindTable(db, zName, 0);
111341112234
*zTail = '_';
111342112235
if( pTab==0 ) return 0;
111343112236
if( !IsVirtual(pTab) ) return 0;
111344
- pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
111345
- if( pMod==0 ) return 0;
111346
- if( pMod->pModule->iVersion<3 ) return 0;
111347
- if( pMod->pModule->xShadowName==0 ) return 0;
111348
- return pMod->pModule->xShadowName(zTail+1);
112237
+ return sqlite3IsShadowTableOf(db, pTab, zName);
111349112238
}
111350112239
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112240
+
111351112241
111352112242
#ifdef SQLITE_DEBUG
111353112243
/*
111354112244
** Mark all nodes of an expression as EP_Immutable, indicating that
111355112245
** they should not be changed. Expressions attached to a table or
@@ -113818,11 +114708,11 @@
113818114708
pParse->rc = rc;
113819114709
return 1;
113820114710
}
113821114711
db->aDb[1].pBt = pBt;
113822114712
assert( db->aDb[1].pSchema );
113823
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
114713
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){
113824114714
sqlite3OomFault(db);
113825114715
return 1;
113826114716
}
113827114717
}
113828114718
return 0;
@@ -113929,11 +114819,11 @@
113929114819
char *p4, /* Error message */
113930114820
i8 p4type, /* P4_STATIC or P4_TRANSIENT */
113931114821
u8 p5Errmsg /* P5_ErrMsg type */
113932114822
){
113933114823
Vdbe *v = sqlite3GetVdbe(pParse);
113934
- assert( (errCode&0xff)==SQLITE_CONSTRAINT );
114824
+ assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
113935114825
if( onError==OE_Abort ){
113936114826
sqlite3MayAbort(pParse);
113937114827
}
113938114828
sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
113939114829
sqlite3VdbeChangeP5(v, p5Errmsg);
@@ -115642,10 +116532,11 @@
115642116532
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
115643116533
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
115644116534
&iPartIdxLabel, pPrior, r1);
115645116535
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
115646116536
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
116537
+ sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
115647116538
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
115648116539
pPrior = pIdx;
115649116540
}
115650116541
}
115651116542
@@ -117035,11 +117926,11 @@
117035117926
if( (cntExpand&(cntExpand-1))==0 ){
117036117927
/* Grow the size of the output buffer only on substitutions
117037117928
** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
117038117929
u8 *zOld;
117039117930
zOld = zOut;
117040
- zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
117931
+ zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1));
117041117932
if( zOut==0 ){
117042117933
sqlite3_result_error_nomem(context);
117043117934
sqlite3_free(zOld);
117044117935
return;
117045117936
}
@@ -117732,11 +118623,11 @@
117732118623
FUNCTION(round, 2, 0, 0, roundFunc ),
117733118624
#endif
117734118625
FUNCTION(upper, 1, 0, 0, upperFunc ),
117735118626
FUNCTION(lower, 1, 0, 0, lowerFunc ),
117736118627
FUNCTION(hex, 1, 0, 0, hexFunc ),
117737
- INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
118628
+ INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
117738118629
VFUNCTION(random, 0, 0, 0, randomFunc ),
117739118630
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
117740118631
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
117741118632
DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
117742118633
DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -117772,11 +118663,12 @@
117772118663
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
117773118664
FUNCTION(unknown, -1, 0, 0, unknownFunc ),
117774118665
#endif
117775118666
FUNCTION(coalesce, 1, 0, 0, 0 ),
117776118667
FUNCTION(coalesce, 0, 0, 0, 0 ),
117777
- INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
118668
+ INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
118669
+ INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
117778118670
};
117779118671
#ifndef SQLITE_OMIT_ALTERTABLE
117780118672
sqlite3AlterFunctions();
117781118673
#endif
117782118674
sqlite3WindowFunctions();
@@ -121197,11 +122089,11 @@
121197122089
}
121198122090
if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
121199122091
sqlite3TableAffinity(v, pTab, regNewData+1);
121200122092
bAffinityDone = 1;
121201122093
}
121202
- VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
122094
+ VdbeNoopComment((v, "prep index %s", pIdx->zName));
121203122095
iThisCur = iIdxCur+ix;
121204122096
121205122097
121206122098
/* Skip partial indices for which the WHERE clause is not true */
121207122099
if( pIdx->pPartIdxWhere ){
@@ -122629,10 +123521,11 @@
122629123521
const char *(*filename_wal)(const char*);
122630123522
/* Version 3.32.0 and later */
122631123523
char *(*create_filename)(const char*,const char*,const char*,
122632123524
int,const char**);
122633123525
void (*free_filename)(char*);
123526
+ sqlite3_file *(*database_file_object)(const char*);
122634123527
};
122635123528
122636123529
/*
122637123530
** This is the function signature used for all extension entry points. It
122638123531
** is also defined in the file "loadext.c".
@@ -122932,10 +123825,11 @@
122932123825
#define sqlite3_filename_journal sqlite3_api->filename_journal
122933123826
#define sqlite3_filename_wal sqlite3_api->filename_wal
122934123827
/* Version 3.32.0 and later */
122935123828
#define sqlite3_create_filename sqlite3_api->create_filename
122936123829
#define sqlite3_free_filename sqlite3_api->free_filename
123830
+#define sqlite3_database_file_object sqlite3_api->database_file_object
122937123831
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
122938123832
122939123833
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
122940123834
/* This case when the file really is being compiled as a loadable
122941123835
** extension */
@@ -123413,11 +124307,20 @@
123413124307
sqlite3_filename_journal,
123414124308
sqlite3_filename_wal,
123415124309
/* Version 3.32.0 and later */
123416124310
sqlite3_create_filename,
123417124311
sqlite3_free_filename,
124312
+ sqlite3_database_file_object,
123418124313
};
124314
+
124315
+/* True if x is the directory separator character
124316
+*/
124317
+#if SQLITE_OS_WIN
124318
+# define DirSep(X) ((X)=='/'||(X)=='\\')
124319
+#else
124320
+# define DirSep(X) ((X)=='/')
124321
+#endif
123419124322
123420124323
/*
123421124324
** Attempt to load an SQLite extension library contained in the file
123422124325
** zFile. The entry point is zProc. zProc may be 0 in which case a
123423124326
** default entry point name (sqlite3_extension_init) is used. Use
@@ -123516,11 +124419,11 @@
123516124419
if( zAltEntry==0 ){
123517124420
sqlite3OsDlClose(pVfs, handle);
123518124421
return SQLITE_NOMEM_BKPT;
123519124422
}
123520124423
memcpy(zAltEntry, "sqlite3_", 8);
123521
- for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
124424
+ for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
123522124425
iFile++;
123523124426
if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
123524124427
for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
123525124428
if( sqlite3Isalpha(c) ){
123526124429
zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
@@ -123820,53 +124723,54 @@
123820124723
** that script and rerun it.
123821124724
*/
123822124725
123823124726
/* The various pragma types */
123824124727
#define PragTyp_ACTIVATE_EXTENSIONS 0
123825
-#define PragTyp_HEADER_VALUE 1
123826
-#define PragTyp_AUTO_VACUUM 2
123827
-#define PragTyp_FLAG 3
123828
-#define PragTyp_BUSY_TIMEOUT 4
123829
-#define PragTyp_CACHE_SIZE 5
123830
-#define PragTyp_CACHE_SPILL 6
123831
-#define PragTyp_CASE_SENSITIVE_LIKE 7
123832
-#define PragTyp_COLLATION_LIST 8
123833
-#define PragTyp_COMPILE_OPTIONS 9
123834
-#define PragTyp_DATA_STORE_DIRECTORY 10
123835
-#define PragTyp_DATABASE_LIST 11
123836
-#define PragTyp_DEFAULT_CACHE_SIZE 12
123837
-#define PragTyp_ENCODING 13
123838
-#define PragTyp_FOREIGN_KEY_CHECK 14
123839
-#define PragTyp_FOREIGN_KEY_LIST 15
123840
-#define PragTyp_FUNCTION_LIST 16
123841
-#define PragTyp_HARD_HEAP_LIMIT 17
123842
-#define PragTyp_INCREMENTAL_VACUUM 18
123843
-#define PragTyp_INDEX_INFO 19
123844
-#define PragTyp_INDEX_LIST 20
123845
-#define PragTyp_INTEGRITY_CHECK 21
123846
-#define PragTyp_JOURNAL_MODE 22
123847
-#define PragTyp_JOURNAL_SIZE_LIMIT 23
123848
-#define PragTyp_LOCK_PROXY_FILE 24
123849
-#define PragTyp_LOCKING_MODE 25
123850
-#define PragTyp_PAGE_COUNT 26
123851
-#define PragTyp_MMAP_SIZE 27
123852
-#define PragTyp_MODULE_LIST 28
123853
-#define PragTyp_OPTIMIZE 29
123854
-#define PragTyp_PAGE_SIZE 30
123855
-#define PragTyp_PRAGMA_LIST 31
123856
-#define PragTyp_SECURE_DELETE 32
123857
-#define PragTyp_SHRINK_MEMORY 33
123858
-#define PragTyp_SOFT_HEAP_LIMIT 34
123859
-#define PragTyp_SYNCHRONOUS 35
123860
-#define PragTyp_TABLE_INFO 36
123861
-#define PragTyp_TEMP_STORE 37
123862
-#define PragTyp_TEMP_STORE_DIRECTORY 38
123863
-#define PragTyp_THREADS 39
123864
-#define PragTyp_WAL_AUTOCHECKPOINT 40
123865
-#define PragTyp_WAL_CHECKPOINT 41
123866
-#define PragTyp_LOCK_STATUS 42
123867
-#define PragTyp_STATS 43
124728
+#define PragTyp_ANALYSIS_LIMIT 1
124729
+#define PragTyp_HEADER_VALUE 2
124730
+#define PragTyp_AUTO_VACUUM 3
124731
+#define PragTyp_FLAG 4
124732
+#define PragTyp_BUSY_TIMEOUT 5
124733
+#define PragTyp_CACHE_SIZE 6
124734
+#define PragTyp_CACHE_SPILL 7
124735
+#define PragTyp_CASE_SENSITIVE_LIKE 8
124736
+#define PragTyp_COLLATION_LIST 9
124737
+#define PragTyp_COMPILE_OPTIONS 10
124738
+#define PragTyp_DATA_STORE_DIRECTORY 11
124739
+#define PragTyp_DATABASE_LIST 12
124740
+#define PragTyp_DEFAULT_CACHE_SIZE 13
124741
+#define PragTyp_ENCODING 14
124742
+#define PragTyp_FOREIGN_KEY_CHECK 15
124743
+#define PragTyp_FOREIGN_KEY_LIST 16
124744
+#define PragTyp_FUNCTION_LIST 17
124745
+#define PragTyp_HARD_HEAP_LIMIT 18
124746
+#define PragTyp_INCREMENTAL_VACUUM 19
124747
+#define PragTyp_INDEX_INFO 20
124748
+#define PragTyp_INDEX_LIST 21
124749
+#define PragTyp_INTEGRITY_CHECK 22
124750
+#define PragTyp_JOURNAL_MODE 23
124751
+#define PragTyp_JOURNAL_SIZE_LIMIT 24
124752
+#define PragTyp_LOCK_PROXY_FILE 25
124753
+#define PragTyp_LOCKING_MODE 26
124754
+#define PragTyp_PAGE_COUNT 27
124755
+#define PragTyp_MMAP_SIZE 28
124756
+#define PragTyp_MODULE_LIST 29
124757
+#define PragTyp_OPTIMIZE 30
124758
+#define PragTyp_PAGE_SIZE 31
124759
+#define PragTyp_PRAGMA_LIST 32
124760
+#define PragTyp_SECURE_DELETE 33
124761
+#define PragTyp_SHRINK_MEMORY 34
124762
+#define PragTyp_SOFT_HEAP_LIMIT 35
124763
+#define PragTyp_SYNCHRONOUS 36
124764
+#define PragTyp_TABLE_INFO 37
124765
+#define PragTyp_TEMP_STORE 38
124766
+#define PragTyp_TEMP_STORE_DIRECTORY 39
124767
+#define PragTyp_THREADS 40
124768
+#define PragTyp_WAL_AUTOCHECKPOINT 41
124769
+#define PragTyp_WAL_CHECKPOINT 42
124770
+#define PragTyp_LOCK_STATUS 43
124771
+#define PragTyp_STATS 44
123868124772
123869124773
/* Property flags associated with various pragma. */
123870124774
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
123871124775
#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
123872124776
#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
@@ -123953,10 +124857,15 @@
123953124857
/* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
123954124858
/* ePragFlg: */ 0,
123955124859
/* ColNames: */ 0, 0,
123956124860
/* iArg: */ 0 },
123957124861
#endif
124862
+ {/* zName: */ "analysis_limit",
124863
+ /* ePragTyp: */ PragTyp_ANALYSIS_LIMIT,
124864
+ /* ePragFlg: */ PragFlg_Result0,
124865
+ /* ColNames: */ 0, 0,
124866
+ /* iArg: */ 0 },
123958124867
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
123959124868
{/* zName: */ "application_id",
123960124869
/* ePragTyp: */ PragTyp_HEADER_VALUE,
123961124870
/* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
123962124871
/* ColNames: */ 0, 0,
@@ -124453,11 +125362,11 @@
124453125362
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
124454125363
/* ColNames: */ 0, 0,
124455125364
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
124456125365
#endif
124457125366
};
124458
-/* Number of pragmas: 66 on by default, 76 total. */
125367
+/* Number of pragmas: 67 on by default, 77 total. */
124459125368
124460125369
/************** End of pragma.h **********************************************/
124461125370
/************** Continuing where we left off in pragma.c *********************/
124462125371
124463125372
/*
@@ -124983,11 +125892,11 @@
124983125892
}else{
124984125893
/* Malloc may fail when setting the page-size, as there is an internal
124985125894
** buffer that the pager module resizes using sqlite3_realloc().
124986125895
*/
124987125896
db->nextPagesize = sqlite3Atoi(zRight);
124988
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
125897
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,0,0) ){
124989125898
sqlite3OomFault(db);
124990125899
}
124991125900
}
124992125901
break;
124993125902
}
@@ -126157,11 +127066,10 @@
126157127066
sqlite3ResolvePartIdxLabel(pParse, jmp3);
126158127067
}
126159127068
}
126160127069
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
126161127070
sqlite3VdbeJumpHere(v, loopTop-1);
126162
-#ifndef SQLITE_OMIT_BTREECOUNT
126163127071
if( !isQuick ){
126164127072
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
126165127073
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
126166127074
if( pPk==pIdx ) continue;
126167127075
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
@@ -126171,11 +127079,10 @@
126171127079
sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
126172127080
integrityCheckResultRow(v);
126173127081
sqlite3VdbeJumpHere(v, addr);
126174127082
}
126175127083
}
126176
-#endif /* SQLITE_OMIT_BTREECOUNT */
126177127084
}
126178127085
}
126179127086
{
126180127087
static const int iLn = VDBE_OFFSET_LINENO(2);
126181127088
static const VdbeOpList endCode[] = {
@@ -126605,10 +127512,29 @@
126605127512
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
126606127513
}
126607127514
returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
126608127515
break;
126609127516
}
127517
+
127518
+ /*
127519
+ ** PRAGMA analysis_limit
127520
+ ** PRAGMA analysis_limit = N
127521
+ **
127522
+ ** Configure the maximum number of rows that ANALYZE will examine
127523
+ ** in each index that it looks at. Return the new limit.
127524
+ */
127525
+ case PragTyp_ANALYSIS_LIMIT: {
127526
+ sqlite3_int64 N;
127527
+ if( zRight
127528
+ && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
127529
+ && N>=0
127530
+ ){
127531
+ db->nAnalysisLimit = (int)(N&0x7fffffff);
127532
+ }
127533
+ returnSingleInt(v, db->nAnalysisLimit);
127534
+ break;
127535
+ }
126610127536
126611127537
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
126612127538
/*
126613127539
** Report the current state of file logs for all databases
126614127540
*/
@@ -131404,10 +132330,11 @@
131404132330
if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
131405132331
memset(&ifNullRow, 0, sizeof(ifNullRow));
131406132332
ifNullRow.op = TK_IF_NULL_ROW;
131407132333
ifNullRow.pLeft = pCopy;
131408132334
ifNullRow.iTable = pSubst->iNewTable;
132335
+ ifNullRow.flags = EP_Skip;
131409132336
pCopy = &ifNullRow;
131410132337
}
131411132338
testcase( ExprHasProperty(pCopy, EP_Subquery) );
131412132339
pNew = sqlite3ExprDup(db, pCopy, 0);
131413132340
if( pNew && pSubst->isLeftJoin ){
@@ -133134,33 +134061,10 @@
133134134061
}
133135134062
}
133136134063
return WRC_Continue;
133137134064
}
133138134065
133139
-/*
133140
-** No-op routine for the parse-tree walker.
133141
-**
133142
-** When this routine is the Walker.xExprCallback then expression trees
133143
-** are walked without any actions being taken at each node. Presumably,
133144
-** when this routine is used for Walker.xExprCallback then
133145
-** Walker.xSelectCallback is set to do something useful for every
133146
-** subquery in the parser tree.
133147
-*/
133148
-SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
133149
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
133150
- return WRC_Continue;
133151
-}
133152
-
133153
-/*
133154
-** No-op routine for the parse-tree walker for SELECT statements.
133155
-** subquery in the parser tree.
133156
-*/
133157
-SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
133158
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
133159
- return WRC_Continue;
133160
-}
133161
-
133162134066
#if SQLITE_DEBUG
133163134067
/*
133164134068
** Always assert. This xSelectCallback2 implementation proves that the
133165134069
** xSelectCallback2 is never invoked.
133166134070
*/
@@ -134327,11 +135231,11 @@
134327135231
sAggInfo.mxReg = pParse->nMem;
134328135232
if( db->mallocFailed ) goto select_end;
134329135233
#if SELECTTRACE_ENABLED
134330135234
if( sqlite3SelectTrace & 0x400 ){
134331135235
int ii;
134332
- SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
135236
+ SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", &sAggInfo));
134333135237
sqlite3TreeViewSelect(0, p, 0);
134334135238
for(ii=0; ii<sAggInfo.nColumn; ii++){
134335135239
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
134336135240
ii, sAggInfo.aCol[ii].iMem);
134337135241
sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
@@ -134568,11 +135472,10 @@
134568135472
VdbeComment((v, "indicate accumulator empty"));
134569135473
sqlite3VdbeAddOp1(v, OP_Return, regReset);
134570135474
134571135475
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
134572135476
else {
134573
-#ifndef SQLITE_OMIT_BTREECOUNT
134574135477
Table *pTab;
134575135478
if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
134576135479
/* If isSimpleCount() returns a pointer to a Table structure, then
134577135480
** the SQL statement is of the form:
134578135481
**
@@ -134604,17 +135507,19 @@
134604135507
**
134605135508
** In practice the KeyInfo structure will not be used. It is only
134606135509
** passed to keep OP_OpenRead happy.
134607135510
*/
134608135511
if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
134609
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
134610
- if( pIdx->bUnordered==0
134611
- && pIdx->szIdxRow<pTab->szTabRow
134612
- && pIdx->pPartIdxWhere==0
134613
- && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
134614
- ){
134615
- pBest = pIdx;
135512
+ if( !p->pSrc->a[0].fg.notIndexed ){
135513
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
135514
+ if( pIdx->bUnordered==0
135515
+ && pIdx->szIdxRow<pTab->szTabRow
135516
+ && pIdx->pPartIdxWhere==0
135517
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
135518
+ ){
135519
+ pBest = pIdx;
135520
+ }
134616135521
}
134617135522
}
134618135523
if( pBest ){
134619135524
iRoot = pBest->tnum;
134620135525
pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
@@ -134626,13 +135531,11 @@
134626135531
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
134627135532
}
134628135533
sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
134629135534
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
134630135535
explainSimpleCount(pParse, pTab, pBest);
134631
- }else
134632
-#endif /* SQLITE_OMIT_BTREECOUNT */
134633
- {
135536
+ }else{
134634135537
int regAcc = 0; /* "populate accumulators" flag */
134635135538
134636135539
/* If there are accumulator registers but no min() or max() functions
134637135540
** without FILTER clauses, allocate register regAcc. Register regAcc
134638135541
** will contain 0 the first time the inner loop runs, and 1 thereafter.
@@ -134791,11 +135694,11 @@
134791135694
need = nCol;
134792135695
}
134793135696
if( p->nData + need > p->nAlloc ){
134794135697
char **azNew;
134795135698
p->nAlloc = p->nAlloc*2 + need;
134796
- azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
135699
+ azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc );
134797135700
if( azNew==0 ) goto malloc_failed;
134798135701
p->azResult = azNew;
134799135702
}
134800135703
134801135704
/* If this is the first row, then generate an extra row containing
@@ -134900,11 +135803,11 @@
134900135803
sqlite3_free_table(&res.azResult[1]);
134901135804
return rc;
134902135805
}
134903135806
if( res.nAlloc>res.nData ){
134904135807
char **azNew;
134905
- azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
135808
+ azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData );
134906135809
if( azNew==0 ){
134907135810
sqlite3_free_table(&res.azResult[1]);
134908135811
db->errCode = SQLITE_NOMEM;
134909135812
return SQLITE_NOMEM_BKPT;
134910135813
}
@@ -136190,14 +137093,14 @@
136190137093
** Therefore, the P4 parameter is only required if the default value for
136191137094
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
136192137095
** function is capable of transforming these types of expressions into
136193137096
** sqlite3_value objects.
136194137097
**
136195
-** If parameter iReg is not negative, code an OP_RealAffinity instruction
136196
-** on register iReg. This is used when an equivalent integer value is
136197
-** stored in place of an 8-byte floating point value in order to save
136198
-** space.
137098
+** If column as REAL affinity and the table is an ordinary b-tree table
137099
+** (not a virtual table) then the value might have been stored as an
137100
+** integer. In that case, add an OP_RealAffinity opcode to make sure
137101
+** it has been converted into REAL.
136199137102
*/
136200137103
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
136201137104
assert( pTab!=0 );
136202137105
if( !pTab->pSelect ){
136203137106
sqlite3_value *pValue = 0;
@@ -136210,11 +137113,11 @@
136210137113
if( pValue ){
136211137114
sqlite3VdbeAppendP4(v, pValue, P4_MEM);
136212137115
}
136213137116
}
136214137117
#ifndef SQLITE_OMIT_FLOATING_POINT
136215
- if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
137118
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
136216137119
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
136217137120
}
136218137121
#endif
136219137122
}
136220137123
@@ -137852,11 +138755,11 @@
137852138755
db->mDbFlags = saved_mDbFlags;
137853138756
db->flags = saved_flags;
137854138757
db->nChange = saved_nChange;
137855138758
db->nTotalChange = saved_nTotalChange;
137856138759
db->mTrace = saved_mTrace;
137857
- sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
138760
+ sqlite3BtreeSetPageSize(pMain, -1, 0, 1);
137858138761
137859138762
/* Currently there is an SQL level transaction open on the vacuum
137860138763
** database. No locks are held on any other files (since the main file
137861138764
** was committed at the btree level). So it safe to end the transaction
137862138765
** by manually setting the autoCommit flag to true and detaching the
@@ -139059,11 +139962,11 @@
139059139962
assert( IsVirtual(pTab) );
139060139963
for(i=0; i<pToplevel->nVtabLock; i++){
139061139964
if( pTab==pToplevel->apVtabLock[i] ) return;
139062139965
}
139063139966
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
139064
- apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
139967
+ apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n);
139065139968
if( apVtabLock ){
139066139969
pToplevel->apVtabLock = apVtabLock;
139067139970
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
139068139971
}else{
139069139972
sqlite3OomFault(pToplevel->db);
@@ -150351,24 +151254,47 @@
150351151254
){
150352151255
if( pAppend ){
150353151256
int i;
150354151257
int nInit = pList ? pList->nExpr : 0;
150355151258
for(i=0; i<pAppend->nExpr; i++){
150356
- int iDummy;
150357151259
Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
150358151260
assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
150359
- if( bIntToNull && pDup && sqlite3ExprIsInteger(pDup, &iDummy) ){
150360
- pDup->op = TK_NULL;
150361
- pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
150362
- pDup->u.zToken = 0;
151261
+ if( bIntToNull && pDup ){
151262
+ int iDummy;
151263
+ Expr *pSub;
151264
+ for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
151265
+ assert( pSub );
151266
+ }
151267
+ if( sqlite3ExprIsInteger(pSub, &iDummy) ){
151268
+ pSub->op = TK_NULL;
151269
+ pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
151270
+ pSub->u.zToken = 0;
151271
+ }
150363151272
}
150364151273
pList = sqlite3ExprListAppend(pParse, pList, pDup);
150365151274
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
150366151275
}
150367151276
}
150368151277
return pList;
150369151278
}
151279
+
151280
+/*
151281
+** When rewriting a query, if the new subquery in the FROM clause
151282
+** contains TK_AGG_FUNCTION nodes that refer to an outer query,
151283
+** then we have to increase the Expr->op2 values of those nodes
151284
+** due to the extra subquery layer that was added.
151285
+**
151286
+** See also the incrAggDepth() routine in resolve.c
151287
+*/
151288
+static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
151289
+ if( pExpr->op==TK_AGG_FUNCTION
151290
+ && pExpr->op2>=pWalker->walkerDepth
151291
+ ){
151292
+ pExpr->op2++;
151293
+ }
151294
+ return WRC_Continue;
151295
+}
150370151296
150371151297
/*
150372151298
** If the SELECT statement passed as the second argument does not invoke
150373151299
** any SQL window functions, this function is a no-op. Otherwise, it
150374151300
** rewrites the SELECT statement so that window function xStep functions
@@ -150475,10 +151401,11 @@
150475151401
pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
150476151402
);
150477151403
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
150478151404
if( p->pSrc ){
150479151405
Table *pTab2;
151406
+ Walker w;
150480151407
p->pSrc->a[0].pSelect = pSub;
150481151408
sqlite3SrcListAssignCursors(pParse, p->pSrc);
150482151409
pSub->selFlags |= SF_Expanded;
150483151410
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
150484151411
pSub->selFlags |= (selFlags & SF_Aggregate);
@@ -150490,10 +151417,15 @@
150490151417
}else{
150491151418
memcpy(pTab, pTab2, sizeof(Table));
150492151419
pTab->tabFlags |= TF_Ephemeral;
150493151420
p->pSrc->a[0].pTab = pTab;
150494151421
pTab = pTab2;
151422
+ memset(&w, 0, sizeof(w));
151423
+ w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
151424
+ w.xSelectCallback = sqlite3WalkerDepthIncrease;
151425
+ w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
151426
+ sqlite3WalkSelect(&w, pSub);
150495151427
}
150496151428
}else{
150497151429
sqlite3SelectDelete(db, pSub);
150498151430
}
150499151431
if( db->mallocFailed ) rc = SQLITE_NOMEM;
@@ -159255,19 +160187,82 @@
159255160187
159256160188
159257160189
/************** End of sqliteicu.h *******************************************/
159258160190
/************** Continuing where we left off in main.c ***********************/
159259160191
#endif
160192
+
160193
+/*
160194
+** This is an extension initializer that is a no-op and always
160195
+** succeeds, except that it fails if the fault-simulation is set
160196
+** to 500.
160197
+*/
160198
+static int sqlite3TestExtInit(sqlite3 *db){
160199
+ (void)db;
160200
+ return sqlite3FaultSim(500);
160201
+}
160202
+
160203
+
160204
+/*
160205
+** Forward declarations of external module initializer functions
160206
+** for modules that need them.
160207
+*/
160208
+#ifdef SQLITE_ENABLE_FTS1
160209
+SQLITE_PRIVATE int sqlite3Fts1Init(sqlite3*);
160210
+#endif
160211
+#ifdef SQLITE_ENABLE_FTS2
160212
+SQLITE_PRIVATE int sqlite3Fts2Init(sqlite3*);
160213
+#endif
160214
+#ifdef SQLITE_ENABLE_FTS5
160215
+SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
160216
+#endif
159260160217
#ifdef SQLITE_ENABLE_JSON1
159261160218
SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*);
159262160219
#endif
159263160220
#ifdef SQLITE_ENABLE_STMTVTAB
159264160221
SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*);
159265160222
#endif
160223
+
160224
+/*
160225
+** An array of pointers to extension initializer functions for
160226
+** built-in extensions.
160227
+*/
160228
+static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
160229
+#ifdef SQLITE_ENABLE_FTS1
160230
+ sqlite3Fts1Init,
160231
+#endif
160232
+#ifdef SQLITE_ENABLE_FTS2
160233
+ sqlite3Fts2Init,
160234
+#endif
160235
+#ifdef SQLITE_ENABLE_FTS3
160236
+ sqlite3Fts3Init,
160237
+#endif
159266160238
#ifdef SQLITE_ENABLE_FTS5
159267
-SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
160239
+ sqlite3Fts5Init,
159268160240
#endif
160241
+#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
160242
+ sqlite3IcuInit,
160243
+#endif
160244
+#ifdef SQLITE_ENABLE_RTREE
160245
+ sqlite3RtreeInit,
160246
+#endif
160247
+#ifdef SQLITE_ENABLE_DBPAGE_VTAB
160248
+ sqlite3DbpageRegister,
160249
+#endif
160250
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB
160251
+ sqlite3DbstatRegister,
160252
+#endif
160253
+ sqlite3TestExtInit,
160254
+#ifdef SQLITE_ENABLE_JSON1
160255
+ sqlite3Json1Init,
160256
+#endif
160257
+#ifdef SQLITE_ENABLE_STMTVTAB
160258
+ sqlite3StmtVtabInit,
160259
+#endif
160260
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
160261
+ sqlite3VdbeBytecodeVtabInit,
160262
+#endif
160263
+};
159269160264
159270160265
#ifndef SQLITE_AMALGAMATION
159271160266
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
159272160267
** contains the text of SQLITE_VERSION macro.
159273160268
*/
@@ -159480,10 +160475,11 @@
159480160475
}
159481160476
#endif
159482160477
if( rc==SQLITE_OK ){
159483160478
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
159484160479
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
160480
+ sqlite3MemoryBarrier();
159485160481
sqlite3GlobalConfig.isInit = 1;
159486160482
#ifdef SQLITE_EXTRA_INIT
159487160483
bRunExtraInit = 1;
159488160484
#endif
159489160485
}
@@ -160781,12 +161777,11 @@
160781161777
** Return non-zero to retry the lock. Return zero to stop trying
160782161778
** and cause SQLite to return SQLITE_BUSY.
160783161779
*/
160784161780
static int sqliteDefaultBusyCallback(
160785161781
void *ptr, /* Database connection */
160786
- int count, /* Number of times table has been busy */
160787
- sqlite3_file *pFile /* The file on which the lock occurred */
161782
+ int count /* Number of times table has been busy */
160788161783
){
160789161784
#if SQLITE_OS_WIN || HAVE_USLEEP
160790161785
/* This case is for systems that have support for sleeping for fractions of
160791161786
** a second. Examples: All windows systems, unix systems with usleep() */
160792161787
static const u8 delays[] =
@@ -160796,35 +161791,10 @@
160796161791
# define NDELAY ArraySize(delays)
160797161792
sqlite3 *db = (sqlite3 *)ptr;
160798161793
int tmout = db->busyTimeout;
160799161794
int delay, prior;
160800161795
160801
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
160802
- if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
160803
- if( count ){
160804
- /* If this is the second or later invocation of the busy-handler,
160805
- ** but tmout==0, then code in wal.c must have disabled the blocking
160806
- ** lock before the SQLITE_BUSY error was hit. In this case, no delay
160807
- ** occurred while waiting for the lock, so fall through to the xSleep()
160808
- ** code below to delay a while before retrying the lock.
160809
- **
160810
- ** Alternatively, if tmout!=0, then SQLite has already waited
160811
- ** sqlite3.busyTimeout ms for a lock. In this case, return 0 to
160812
- ** indicate that the lock should not be retried and the SQLITE_BUSY
160813
- ** error returned to the application. */
160814
- if( tmout ){
160815
- tmout = 0;
160816
- sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
160817
- return 0;
160818
- }
160819
- }else{
160820
- return 1;
160821
- }
160822
- }
160823
-#else
160824
- UNUSED_PARAMETER(pFile);
160825
-#endif
160826161796
assert( count>=0 );
160827161797
if( count < NDELAY ){
160828161798
delay = delays[count];
160829161799
prior = totals[count];
160830161800
}else{
@@ -160840,11 +161810,10 @@
160840161810
#else
160841161811
/* This case for unix systems that lack usleep() support. Sleeping
160842161812
** must be done in increments of whole seconds */
160843161813
sqlite3 *db = (sqlite3 *)ptr;
160844161814
int tmout = ((sqlite3 *)ptr)->busyTimeout;
160845
- UNUSED_PARAMETER(pFile);
160846161815
if( (count+1)*1000 > tmout ){
160847161816
return 0;
160848161817
}
160849161818
sqlite3OsSleep(db->pVfs, 1000000);
160850161819
return 1;
@@ -160858,23 +161827,14 @@
160858161827
** lock on VFS file pFile.
160859161828
**
160860161829
** If this routine returns non-zero, the lock is retried. If it
160861161830
** returns 0, the operation aborts with an SQLITE_BUSY error.
160862161831
*/
160863
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
161832
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
160864161833
int rc;
160865161834
if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
160866
- if( p->bExtraFileArg ){
160867
- /* Add an extra parameter with the pFile pointer to the end of the
160868
- ** callback argument list */
160869
- int (*xTra)(void*,int,sqlite3_file*);
160870
- xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
160871
- rc = xTra(p->pBusyArg, p->nBusy, pFile);
160872
- }else{
160873
- /* Legacy style busy handler callback */
160874
- rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
160875
- }
161835
+ rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
160876161836
if( rc==0 ){
160877161837
p->nBusy = -1;
160878161838
}else{
160879161839
p->nBusy++;
160880161840
}
@@ -160895,11 +161855,10 @@
160895161855
#endif
160896161856
sqlite3_mutex_enter(db->mutex);
160897161857
db->busyHandler.xBusyHandler = xBusy;
160898161858
db->busyHandler.pBusyArg = pArg;
160899161859
db->busyHandler.nBusy = 0;
160900
- db->busyHandler.bExtraFileArg = 0;
160901161860
db->busyTimeout = 0;
160902161861
sqlite3_mutex_leave(db->mutex);
160903161862
return SQLITE_OK;
160904161863
}
160905161864
@@ -160946,11 +161905,10 @@
160946161905
#endif
160947161906
if( ms>0 ){
160948161907
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
160949161908
(void*)db);
160950161909
db->busyTimeout = ms;
160951
- db->busyHandler.bExtraFileArg = 1;
160952161910
}else{
160953161911
sqlite3_busy_handler(db, 0, 0);
160954161912
}
160955161913
return SQLITE_OK;
160956161914
}
@@ -162272,10 +163230,11 @@
162272163230
sqlite3 *db; /* Store allocated handle here */
162273163231
int rc; /* Return code */
162274163232
int isThreadsafe; /* True for threadsafe connections */
162275163233
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
162276163234
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
163235
+ int i; /* Loop counter */
162277163236
162278163237
#ifdef SQLITE_ENABLE_API_ARMOR
162279163238
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
162280163239
#endif
162281163240
*ppDb = 0;
@@ -162420,10 +163379,13 @@
162420163379
| SQLITE_EnableQPSG
162421163380
#endif
162422163381
#if defined(SQLITE_DEFAULT_DEFENSIVE)
162423163382
| SQLITE_Defensive
162424163383
#endif
163384
+#if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE)
163385
+ | SQLITE_LegacyAlter
163386
+#endif
162425163387
;
162426163388
sqlite3HashInit(&db->aCollSeq);
162427163389
#ifndef SQLITE_OMIT_VIRTUALTABLE
162428163390
sqlite3HashInit(&db->aModule);
162429163391
#endif
@@ -162462,11 +163424,11 @@
162462163424
assert( SQLITE_OPEN_CREATE == 0x04 );
162463163425
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
162464163426
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
162465163427
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
162466163428
if( ((1<<(flags&7)) & 0x46)==0 ){
162467
- rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
163429
+ rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
162468163430
}else{
162469163431
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
162470163432
}
162471163433
if( rc!=SQLITE_OK ){
162472163434
if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
@@ -162512,18 +163474,15 @@
162512163474
*/
162513163475
sqlite3Error(db, SQLITE_OK);
162514163476
sqlite3RegisterPerConnectionBuiltinFunctions(db);
162515163477
rc = sqlite3_errcode(db);
162516163478
162517
-#ifdef SQLITE_ENABLE_FTS5
162518
- /* Register any built-in FTS5 module before loading the automatic
162519
- ** extensions. This allows automatic extensions to register FTS5
162520
- ** tokenizers and auxiliary functions. */
162521
- if( !db->mallocFailed && rc==SQLITE_OK ){
162522
- rc = sqlite3Fts5Init(db);
162523
- }
162524
-#endif
163479
+
163480
+ /* Load compiled-in extensions */
163481
+ for(i=0; rc==SQLITE_OK && i<ArraySize(sqlite3BuiltinExtensions); i++){
163482
+ rc = sqlite3BuiltinExtensions[i](db);
163483
+ }
162525163484
162526163485
/* Load automatic extensions - extensions that have been registered
162527163486
** using the sqlite3_automatic_extension() API.
162528163487
*/
162529163488
if( rc==SQLITE_OK ){
@@ -162532,66 +163491,10 @@
162532163491
if( rc!=SQLITE_OK ){
162533163492
goto opendb_out;
162534163493
}
162535163494
}
162536163495
162537
-#ifdef SQLITE_ENABLE_FTS1
162538
- if( !db->mallocFailed ){
162539
- extern int sqlite3Fts1Init(sqlite3*);
162540
- rc = sqlite3Fts1Init(db);
162541
- }
162542
-#endif
162543
-
162544
-#ifdef SQLITE_ENABLE_FTS2
162545
- if( !db->mallocFailed && rc==SQLITE_OK ){
162546
- extern int sqlite3Fts2Init(sqlite3*);
162547
- rc = sqlite3Fts2Init(db);
162548
- }
162549
-#endif
162550
-
162551
-#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
162552
- if( !db->mallocFailed && rc==SQLITE_OK ){
162553
- rc = sqlite3Fts3Init(db);
162554
- }
162555
-#endif
162556
-
162557
-#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
162558
- if( !db->mallocFailed && rc==SQLITE_OK ){
162559
- rc = sqlite3IcuInit(db);
162560
- }
162561
-#endif
162562
-
162563
-#ifdef SQLITE_ENABLE_RTREE
162564
- if( !db->mallocFailed && rc==SQLITE_OK){
162565
- rc = sqlite3RtreeInit(db);
162566
- }
162567
-#endif
162568
-
162569
-#ifdef SQLITE_ENABLE_DBPAGE_VTAB
162570
- if( !db->mallocFailed && rc==SQLITE_OK){
162571
- rc = sqlite3DbpageRegister(db);
162572
- }
162573
-#endif
162574
-
162575
-#ifdef SQLITE_ENABLE_DBSTAT_VTAB
162576
- if( !db->mallocFailed && rc==SQLITE_OK){
162577
- rc = sqlite3DbstatRegister(db);
162578
- }
162579
-#endif
162580
-
162581
-#ifdef SQLITE_ENABLE_JSON1
162582
- if( !db->mallocFailed && rc==SQLITE_OK){
162583
- rc = sqlite3Json1Init(db);
162584
- }
162585
-#endif
162586
-
162587
-#ifdef SQLITE_ENABLE_STMTVTAB
162588
- if( !db->mallocFailed && rc==SQLITE_OK){
162589
- rc = sqlite3StmtVtabInit(db);
162590
- }
162591
-#endif
162592
-
162593163496
#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
162594163497
/* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
162595163498
** option gives access to internal functions by default.
162596163499
** Testing use only!!! */
162597163500
db->mDbFlags |= DBFLAG_InternalFunc;
@@ -163076,11 +163979,11 @@
163076163979
*(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
163077163980
rc = SQLITE_OK;
163078163981
}else if( op==SQLITE_FCNTL_RESERVE_BYTES ){
163079163982
int iNew = *(int*)pArg;
163080163983
*(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree);
163081
- if( iNew>=0 && iNew<=254 ){
163984
+ if( iNew>=0 && iNew<=255 ){
163082163985
sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
163083163986
}
163084163987
rc = SQLITE_OK;
163085163988
}else{
163086163989
rc = sqlite3OsFileControl(fd, op, pArg);
@@ -165357,10 +166260,11 @@
165357166260
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
165358166261
SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
165359166262
SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
165360166263
SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
165361166264
SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
166265
+SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut);
165362166266
165363166267
/* fts3_tokenizer.c */
165364166268
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
165365166269
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
165366166270
SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -166088,10 +166992,26 @@
166088166992
fts3Appendf(pRc, &zRet, ", ?");
166089166993
}
166090166994
sqlite3_free(zFree);
166091166995
return zRet;
166092166996
}
166997
+
166998
+/*
166999
+** Buffer z contains a positive integer value encoded as utf-8 text.
167000
+** Decode this value and store it in *pnOut, returning the number of bytes
167001
+** consumed. If an overflow error occurs return a negative value.
167002
+*/
167003
+SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut){
167004
+ u64 iVal = 0;
167005
+ int i;
167006
+ for(i=0; z[i]>='0' && z[i]<='9'; i++){
167007
+ iVal = iVal*10 + (z[i] - '0');
167008
+ if( iVal>0x7FFFFFFF ) return -1;
167009
+ }
167010
+ *pnOut = (int)iVal;
167011
+ return i;
167012
+}
166093167013
166094167014
/*
166095167015
** This function interprets the string at (*pp) as a non-negative integer
166096167016
** value. It reads the integer and sets *pnOut to the value read, then
166097167017
** sets *pp to point to the byte immediately following the last byte of
@@ -166104,23 +167024,21 @@
166104167024
**
166105167025
** This function is used when parsing the "prefix=" FTS4 parameter.
166106167026
*/
166107167027
static int fts3GobbleInt(const char **pp, int *pnOut){
166108167028
const int MAX_NPREFIX = 10000000;
166109
- const char *p; /* Iterator pointer */
166110167029
int nInt = 0; /* Output value */
166111
-
166112
- for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
166113
- nInt = nInt * 10 + (p[0] - '0');
166114
- if( nInt>MAX_NPREFIX ){
166115
- nInt = 0;
166116
- break;
166117
- }
166118
- }
166119
- if( p==*pp ) return SQLITE_ERROR;
167030
+ int nByte;
167031
+ nByte = sqlite3Fts3ReadInt(*pp, &nInt);
167032
+ if( nInt>MAX_NPREFIX ){
167033
+ nInt = 0;
167034
+ }
167035
+ if( nByte==0 ){
167036
+ return SQLITE_ERROR;
167037
+ }
166120167038
*pnOut = nInt;
166121
- *pp = p;
167039
+ *pp += nByte;
166122167040
return SQLITE_OK;
166123167041
}
166124167042
166125167043
/*
166126167044
** This function is called to allocate an array of Fts3Index structures
@@ -167298,11 +168216,13 @@
167298168216
static void fts3ReadNextPos(
167299168217
char **pp, /* IN/OUT: Pointer into position-list buffer */
167300168218
sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
167301168219
){
167302168220
if( (**pp)&0xFE ){
167303
- fts3GetDeltaVarint(pp, pi);
168221
+ int iVal;
168222
+ *pp += fts3GetVarint32((*pp), &iVal);
168223
+ *pi += iVal;
167304168224
*pi -= 2;
167305168225
}else{
167306168226
*pi = POSITION_LIST_END;
167307168227
}
167308168228
}
@@ -170428,10 +171348,11 @@
170428171348
while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
170429171349
memset(pDl->pList, 0, pDl->nList);
170430171350
fts3EvalNextRow(pCsr, pLeft, pRc);
170431171351
}
170432171352
}
171353
+ pRight->bEof = pLeft->bEof = 1;
170433171354
}
170434171355
}
170435171356
break;
170436171357
}
170437171358
@@ -172198,14 +173119,11 @@
172198173119
172199173120
/* If this is a "NEAR" keyword, check for an explicit nearness. */
172200173121
if( pKey->eType==FTSQUERY_NEAR ){
172201173122
assert( nKey==4 );
172202173123
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
172203
- nNear = 0;
172204
- for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
172205
- nNear = nNear * 10 + (zInput[nKey] - '0');
172206
- }
173124
+ nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
172207173125
}
172208173126
}
172209173127
172210173128
/* At this point this is probably a keyword. But for that to be true,
172211173129
** the next byte must contain either whitespace, an open or close
@@ -178384,25 +179302,25 @@
178384179302
){
178385179303
const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
178386179304
if( zText ){
178387179305
int i;
178388179306
int iMul = 1;
178389
- i64 iVal = 0;
179307
+ u64 iVal = 0;
178390179308
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
178391179309
iVal = iVal*10 + (zText[i] - '0');
178392179310
}
178393
- *piEndBlock = iVal;
179311
+ *piEndBlock = (i64)iVal;
178394179312
while( zText[i]==' ' ) i++;
178395179313
iVal = 0;
178396179314
if( zText[i]=='-' ){
178397179315
i++;
178398179316
iMul = -1;
178399179317
}
178400179318
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
178401179319
iVal = iVal*10 + (zText[i] - '0');
178402179320
}
178403
- *pnByte = (iVal * (i64)iMul);
179321
+ *pnByte = ((i64)iVal * (i64)iMul);
178404179322
}
178405179323
}
178406179324
178407179325
178408179326
/*
@@ -181976,11 +182894,11 @@
181976182894
iStart = pExpr->iPhrase * p->nCol;
181977182895
}else{
181978182896
iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
181979182897
}
181980182898
181981
- while( 1 ){
182899
+ if( pIter ) while( 1 ){
181982182900
int nHit = fts3ColumnlistCount(&pIter);
181983182901
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
181984182902
if( p->flag==FTS3_MATCHINFO_LHITS ){
181985182903
p->aMatchinfo[iStart + iCol] = (u32)nHit;
181986182904
}else if( nHit ){
@@ -183890,10 +184808,11 @@
183890184808
}
183891184809
183892184810
/* Append N bytes from zIn onto the end of the JsonString string.
183893184811
*/
183894184812
static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
184813
+ if( N==0 ) return;
183895184814
if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
183896184815
memcpy(p->zBuf+p->nUsed, zIn, N);
183897184816
p->nUsed += N;
183898184817
}
183899184818
@@ -223901,11 +224820,11 @@
223901224820
int nArg, /* Number of args */
223902224821
sqlite3_value **apUnused /* Function arguments */
223903224822
){
223904224823
assert( nArg==0 );
223905224824
UNUSED_PARAM2(nArg, apUnused);
223906
- sqlite3_result_text(pCtx, "fts5: 2020-03-03 20:04:29 bd94d7d052734460904c687756231f8aa243a2252f07f742dd1e437aa940f536", -1, SQLITE_TRANSIENT);
224825
+ sqlite3_result_text(pCtx, "fts5: 2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350", -1, SQLITE_TRANSIENT);
223907224826
}
223908224827
223909224828
/*
223910224829
** Return true if zName is the extension on one of the shadow tables used
223911224830
** by this module.
@@ -228552,11 +229471,12 @@
228552229471
}
228553229472
case STMT_COLUMN_BUSY: {
228554229473
sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
228555229474
break;
228556229475
}
228557
- case STMT_COLUMN_MEM: {
229476
+ default: {
229477
+ assert( i==STMT_COLUMN_MEM );
228558229478
i = SQLITE_STMTSTATUS_MEMUSED +
228559229479
STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
228560229480
/* Fall thru */
228561229481
}
228562229482
case STMT_COLUMN_NSCAN:
@@ -228683,12 +229603,12 @@
228683229603
}
228684229604
#endif /* SQLITE_CORE */
228685229605
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
228686229606
228687229607
/************** End of stmt.c ************************************************/
228688
-#if __LINE__!=228688
229608
+#if __LINE__!=229608
228689229609
#undef SQLITE_SOURCE_ID
228690
-#define SQLITE_SOURCE_ID "2020-04-20 17:35:32 2fc80ef16ce5878311ab88a0c64631813572ffbb71f75363b4619c9667e0alt2"
229610
+#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba8alt2"
228691229611
#endif
228692229612
/* Return the source-id for this library */
228693229613
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
228694229614
/************************** End of sqlite3.c ******************************/
228695229615
--- 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.32.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.
@@ -215,10 +215,13 @@
215 #if SQLITE_ENABLE_ATOMIC_WRITE
216 "ENABLE_ATOMIC_WRITE",
217 #endif
218 #if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
219 "ENABLE_BATCH_ATOMIC_WRITE",
 
 
 
220 #endif
221 #if SQLITE_ENABLE_CEROD
222 "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
223 #endif
224 #if SQLITE_ENABLE_COLUMN_METADATA
@@ -534,13 +537,10 @@
534 "OMIT_BETWEEN_OPTIMIZATION",
535 #endif
536 #if SQLITE_OMIT_BLOB_LITERAL
537 "OMIT_BLOB_LITERAL",
538 #endif
539 #if SQLITE_OMIT_BTREECOUNT
540 "OMIT_BTREECOUNT",
541 #endif
542 #if SQLITE_OMIT_CAST
543 "OMIT_CAST",
544 #endif
545 #if SQLITE_OMIT_CHECK
546 "OMIT_CHECK",
@@ -1160,13 +1160,13 @@
1160 **
1161 ** See also: [sqlite3_libversion()],
1162 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1163 ** [sqlite_version()] and [sqlite_source_id()].
1164 */
1165 #define SQLITE_VERSION "3.32.0"
1166 #define SQLITE_VERSION_NUMBER 3032000
1167 #define SQLITE_SOURCE_ID "2020-04-20 17:35:32 2fc80ef16ce5878311ab88a0c64631813572ffbb71f75363b4619c9667e0926b"
1168
1169 /*
1170 ** CAPI3REF: Run-Time Library Version Numbers
1171 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1172 **
@@ -1336,30 +1336,26 @@
1336 ** for the [sqlite3] object.
1337 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
1338 ** the [sqlite3] object is successfully destroyed and all associated
1339 ** resources are deallocated.
1340 **
 
 
 
 
1341 ** ^If the database connection is associated with unfinalized prepared
1342 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
1343 ** will leave the database connection open and return [SQLITE_BUSY].
1344 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
1345 ** and/or unfinished sqlite3_backups, then the database connection becomes
1346 ** an unusable "zombie" which will automatically be deallocated when the
1347 ** last prepared statement is finalized or the last sqlite3_backup is
1348 ** finished. The sqlite3_close_v2() interface is intended for use with
1349 ** host languages that are garbage collected, and where the order in which
1350 ** destructors are called is arbitrary.
1351 **
1352 ** Applications should [sqlite3_finalize | finalize] all [prepared statements],
1353 ** [sqlite3_blob_close | close] all [BLOB handles], and
1354 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
1355 ** with the [sqlite3] object prior to attempting to close the object. ^If
1356 ** sqlite3_close_v2() is called on a [database connection] that still has
1357 ** outstanding [prepared statements], [BLOB handles], and/or
1358 ** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
1359 ** of resources is deferred until all [prepared statements], [BLOB handles],
1360 ** and [sqlite3_backup] objects are also destroyed.
1361 **
1362 ** ^If an [sqlite3] object is destroyed while a transaction is open,
1363 ** the transaction is automatically rolled back.
1364 **
1365 ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
@@ -1544,22 +1540,25 @@
1544 #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
1545 #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
1546 #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
1547 #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
1548 #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
 
1549 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
1550 #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
1551 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1552 #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
 
1553 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1554 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
1555 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
1556 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
1557 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
1558 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
1559 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1560 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
 
1561 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
1562 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
1563 #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
1564 #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
1565 #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
@@ -2150,10 +2149,15 @@
2150 ** a single attached database that occur due to other database connections,
2151 ** but omits changes implemented by the database connection on which it is
2152 ** called. This file control is the only mechanism to detect changes that
2153 ** happen either internally or externally and that are associated with
2154 ** a particular attached database.
 
 
 
 
 
2155 **
2156 ** <li>[[SQLITE_FCNTL_CKPT_DONE]]
2157 ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
2158 ** in wal mode after the client has finished copying pages from the wal
2159 ** file to the database file, but before the *-shm file is updated to
@@ -2195,10 +2199,11 @@
2195 #define SQLITE_FCNTL_LOCK_TIMEOUT 34
2196 #define SQLITE_FCNTL_DATA_VERSION 35
2197 #define SQLITE_FCNTL_SIZE_LIMIT 36
2198 #define SQLITE_FCNTL_CKPT_DONE 37
2199 #define SQLITE_FCNTL_RESERVE_BYTES 38
 
2200
2201 /* deprecated names */
2202 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
2203 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
2204 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -4573,12 +4578,23 @@
4573 **
4574 ** These are utility routines, useful to [VFS|custom VFS implementations],
4575 ** that check if a database file was a URI that contained a specific query
4576 ** parameter, and if so obtains the value of that query parameter.
4577 **
4578 ** If F is the database filename pointer passed into the xOpen() method of
4579 ** a VFS implementation or it is the return value of [sqlite3_db_filename()]
 
 
 
 
 
 
 
 
 
 
 
4580 ** and if P is the name of the query parameter, then
4581 ** sqlite3_uri_parameter(F,P) returns the value of the P
4582 ** parameter if it exists or a NULL pointer if P does not appear as a
4583 ** query parameter on F. If P is a query parameter of F and it
4584 ** has no explicit value, then sqlite3_uri_parameter(F,P) returns
@@ -4657,10 +4673,29 @@
4657 */
4658 SQLITE_API const char *sqlite3_filename_database(const char*);
4659 SQLITE_API const char *sqlite3_filename_journal(const char*);
4660 SQLITE_API const char *sqlite3_filename_wal(const char*);
4661
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4662 /*
4663 ** CAPI3REF: Create and Destroy VFS Filenames
4664 **
4665 ** These interfces are provided for use by [VFS shim] implementations and
4666 ** are not useful outside of that context.
@@ -4691,11 +4726,11 @@
4691 ** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
4692 ** be NULL pointers, though they can be empty strings.
4693 **
4694 ** The sqlite3_free_filename(Y) routine releases a memory allocation
4695 ** previously obtained from sqlite3_create_filename(). Invoking
4696 ** sqlite3_free_filename(Y) is a NULL pointer is a harmless no-op.
4697 **
4698 ** If the Y parameter to sqlite3_free_filename(Y) is anything other
4699 ** than a NULL pointer or a pointer previously acquired from
4700 ** sqlite3_create_filename(), then bad things such as heap
4701 ** corruption or segfaults may occur. The value Y should be
@@ -6497,11 +6532,11 @@
6497 ** when first called if N is less than or equal to zero or if a memory
6498 ** allocate error occurs.
6499 **
6500 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
6501 ** determined by the N parameter on first successful call. Changing the
6502 ** value of N in any subsequents call to sqlite3_aggregate_context() within
6503 ** the same aggregate function instance will not resize the memory
6504 ** allocation.)^ Within the xFinal callback, it is customary to set
6505 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
6506 ** pointless memory allocations occur.
6507 **
@@ -14502,11 +14537,10 @@
14502 typedef struct BusyHandler BusyHandler;
14503 struct BusyHandler {
14504 int (*xBusyHandler)(void *,int); /* The busy callback */
14505 void *pBusyArg; /* First arg to busy callback */
14506 int nBusy; /* Incremented with each busy call */
14507 u8 bExtraFileArg; /* Include sqlite3_file as callback arg */
14508 };
14509
14510 /*
14511 ** Name of the master database table. The master database table
14512 ** is a special table that holds the names and attributes of all
@@ -15022,13 +15056,11 @@
15022 #ifndef NDEBUG
15023 SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
15024 #endif
15025 SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
15026
15027 #ifndef SQLITE_OMIT_BTREECOUNT
15028 SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
15029 #endif
15030
15031 #ifdef SQLITE_TEST
15032 SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
15033 SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
15034 #endif
@@ -15599,10 +15631,13 @@
15599
15600 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
15601 SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
15602
15603 SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
 
 
 
15604
15605 /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
15606 ** each VDBE opcode.
15607 **
15608 ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
@@ -15884,17 +15919,25 @@
15884 SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
15885 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
15886 SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
15887 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
15888 # ifdef SQLITE_ENABLE_SNAPSHOT
15889 SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
15890 SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
15891 SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
15892 SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
15893 SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
15894 # endif
15895 #endif
 
 
 
 
 
 
 
 
15896
15897 #ifdef SQLITE_DIRECT_OVERFLOW_READ
15898 SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
15899 #endif
15900
@@ -15917,15 +15960,10 @@
15917 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
15918 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
15919 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
15920 SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
15921 SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
15922 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
15923 SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager);
15924 #else
15925 # define sqlite3PagerResetLockTimeout(X)
15926 #endif
15927
15928 /* Functions used to truncate the database file. */
15929 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
15930
15931 SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
@@ -16855,10 +16893,11 @@
16855 Hash aFunc; /* Hash table of connection functions */
16856 Hash aCollSeq; /* All collating sequences */
16857 BusyHandler busyHandler; /* Busy callback */
16858 Db aDbStatic[2]; /* Static space for the 2 default backends */
16859 Savepoint *pSavepoint; /* List of active savepoints */
 
16860 int busyTimeout; /* Busy handler timeout, in msec */
16861 int nSavepoint; /* Number of non-transaction savepoints */
16862 int nStatement; /* Number of nested statement-transactions */
16863 i64 nDeferredCons; /* Net deferred constraints this transaction. */
16864 i64 nDeferredImmCons; /* Net deferred immediate constraints */
@@ -17080,11 +17119,11 @@
17080 #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
17081 #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
17082 #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
17083 #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
17084 #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
17085 #define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
17086 #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
17087 #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
17088 #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
17089 #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
17090 ** single query - might change over time */
@@ -17101,10 +17140,11 @@
17101 #define INLINEFUNC_coalesce 0
17102 #define INLINEFUNC_implies_nonnull_row 1
17103 #define INLINEFUNC_expr_implies_expr 2
17104 #define INLINEFUNC_expr_compare 3
17105 #define INLINEFUNC_affinity 4
 
17106 #define INLINEFUNC_unlikely 99 /* Default case */
17107
17108 /*
17109 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
17110 ** used to create the initializers for the FuncDef structures.
@@ -17801,11 +17841,11 @@
17801 /*
17802 ** An instance of this structure contains information needed to generate
17803 ** code for a SELECT that contains aggregate functions.
17804 **
17805 ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
17806 ** pointer to this structure. The Expr.iColumn field is the index in
17807 ** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
17808 ** code for that node.
17809 **
17810 ** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
17811 ** original Select structure that describes the SELECT statement. These
@@ -19040,10 +19080,13 @@
19040 SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
19041 SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
19042 SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
19043 SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
19044 SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
 
 
 
19045 #ifdef SQLITE_DEBUG
19046 SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
19047 #endif
19048
19049 /*
@@ -19900,11 +19943,11 @@
19900 SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
19901 SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
19902 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
19903 SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
19904 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
19905 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
19906 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
19907 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
19908 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
19909 SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*);
19910 SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
@@ -20025,12 +20068,14 @@
20025 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
20026 #endif
20027 SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
20028 #ifndef SQLITE_OMIT_VIRTUALTABLE
20029 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
 
20030 #else
20031 # define sqlite3ShadowTableName(A,B) 0
 
20032 #endif
20033 SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
20034 SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
20035 SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
20036 SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
@@ -20636,11 +20681,12 @@
20636 /*
20637 ** VDBE_DISPLAY_P4 is true or false depending on whether or not the
20638 ** "explain" P4 display logic is enabled.
20639 */
20640 #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
20641 || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
 
20642 # define VDBE_DISPLAY_P4 1
20643 #else
20644 # define VDBE_DISPLAY_P4 0
20645 #endif
20646
@@ -21101,11 +21147,18 @@
21101
21102 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
21103 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
21104 SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
21105 SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
21106 #ifndef SQLITE_OMIT_EXPLAIN
 
 
 
 
 
 
 
21107 SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
21108 #endif
21109 SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
21110 SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
21111 SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
@@ -21143,11 +21196,11 @@
21143 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
21144 SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
21145 #ifndef SQLITE_OMIT_WINDOWFUNC
21146 SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
21147 #endif
21148 #ifndef SQLITE_OMIT_EXPLAIN
21149 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
21150 #endif
21151 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
21152 SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
21153 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
@@ -27316,11 +27369,11 @@
27316 if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
27317 n = mem0.hardLimit;
27318 }
27319 mem0.alarmThreshold = n;
27320 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27321 mem0.nearlyFull = (n>0 && n<=nUsed);
27322 sqlite3_mutex_leave(mem0.mutex);
27323 excess = sqlite3_memory_used() - n;
27324 if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
27325 return priorLimit;
27326 }
@@ -27384,11 +27437,11 @@
27384 ** Return true if the heap is currently under memory pressure - in other
27385 ** words if the amount of heap used is close to the limit set by
27386 ** sqlite3_soft_heap_limit().
27387 */
27388 SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
27389 return mem0.nearlyFull;
27390 }
27391
27392 /*
27393 ** Deinitialize the memory allocation subsystem.
27394 */
@@ -27448,21 +27501,21 @@
27448
27449 sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
27450 if( mem0.alarmThreshold>0 ){
27451 sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27452 if( nUsed >= mem0.alarmThreshold - nFull ){
27453 mem0.nearlyFull = 1;
27454 sqlite3MallocAlarm(nFull);
27455 if( mem0.hardLimit ){
27456 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27457 if( nUsed >= mem0.hardLimit - nFull ){
27458 *pp = 0;
27459 return;
27460 }
27461 }
27462 }else{
27463 mem0.nearlyFull = 0;
27464 }
27465 }
27466 p = sqlite3GlobalConfig.m.xMalloc(nFull);
27467 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
27468 if( p==0 && mem0.alarmThreshold>0 ){
@@ -27687,14 +27740,16 @@
27687 if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
27688 mem0.alarmThreshold-nDiff ){
27689 sqlite3MallocAlarm(nDiff);
27690 }
27691 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
 
27692 if( pNew==0 && mem0.alarmThreshold>0 ){
27693 sqlite3MallocAlarm((int)nBytes);
27694 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
27695 }
 
27696 if( pNew ){
27697 nNew = sqlite3MallocSize(pNew);
27698 sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
27699 }
27700 sqlite3_mutex_leave(mem0.mutex);
@@ -27875,11 +27930,11 @@
27875 }
27876 }else{
27877 assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27878 assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27879 sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
27880 pNew = sqlite3_realloc64(p, n);
27881 if( !pNew ){
27882 sqlite3OomFault(db);
27883 }
27884 sqlite3MemdebugSetType(pNew,
27885 (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
@@ -28222,10 +28277,17 @@
28222 #ifndef SQLITE_PRINT_BUF_SIZE
28223 # define SQLITE_PRINT_BUF_SIZE 70
28224 #endif
28225 #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
28226
 
 
 
 
 
 
 
28227 /*
28228 ** Render a string given by "fmt" into the StrAccum object.
28229 */
28230 SQLITE_API void sqlite3_str_vappendf(
28231 sqlite3_str *pAccum, /* Accumulate results here */
@@ -28422,10 +28484,12 @@
28422 ** precision The specified precision. The default
28423 ** is -1.
28424 ** xtype The class of the conversion.
28425 ** infop Pointer to the appropriate info struct.
28426 */
 
 
28427 switch( xtype ){
28428 case etPOINTER:
28429 flag_long = sizeof(char*)==sizeof(i64) ? 2 :
28430 sizeof(char*)==sizeof(long int) ? 1 : 0;
28431 /* Fall through into the next case */
@@ -28543,10 +28607,15 @@
28543 }
28544 #ifdef SQLITE_OMIT_FLOATING_POINT
28545 length = 0;
28546 #else
28547 if( precision<0 ) precision = 6; /* Set default precision */
 
 
 
 
 
28548 if( realvalue<0.0 ){
28549 realvalue = -realvalue;
28550 prefix = '-';
28551 }else{
28552 prefix = flag_prefix;
@@ -28825,11 +28894,11 @@
28825 }else{
28826 escarg = va_arg(ap,char*);
28827 }
28828 isnull = escarg==0;
28829 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
28830 /* For %q, %Q, and %w, the precision is the number of byte (or
28831 ** characters if the ! flags is present) to use from the input.
28832 ** Because of the extra quoting characters inserted, the number
28833 ** of output characters may be larger than the precision.
28834 */
28835 k = precision;
@@ -28952,11 +29021,11 @@
28952 p->nAlloc = (int)szNew;
28953 }
28954 if( p->db ){
28955 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
28956 }else{
28957 zNew = sqlite3_realloc64(zOld, p->nAlloc);
28958 }
28959 if( zNew ){
28960 assert( p->zText!=0 || p->nChar==0 );
28961 if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
28962 p->zText = zNew;
@@ -29294,11 +29363,11 @@
29294 ** and segfaults if you give it a long long int.
29295 */
29296 SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
29297 va_list ap;
29298 StrAccum acc;
29299 char zBuf[500];
29300 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
29301 va_start(ap,zFormat);
29302 sqlite3_str_vappendf(&acc, zFormat, ap);
29303 va_end(ap);
29304 sqlite3StrAccumFinish(&acc);
@@ -29910,12 +29979,13 @@
29910 #else
29911 pWin = 0;
29912 #endif
29913 }
29914 if( pExpr->op==TK_AGG_FUNCTION ){
29915 sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s",
29916 pExpr->op2, pExpr->u.zToken, zFlgs);
 
29917 }else if( pExpr->op2!=0 ){
29918 const char *zOp2;
29919 char zBuf[8];
29920 sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
29921 zOp2 = zBuf;
@@ -30804,10 +30874,11 @@
30804 /* UTF-16 Little-endian -> UTF-8 */
30805 while( zIn<zTerm ){
30806 c = *(zIn++);
30807 c += (*(zIn++))<<8;
30808 if( c>=0xd800 && c<0xe000 ){
 
30809 if( c>=0xdc00 || zIn>=zTerm ){
30810 c = 0xfffd;
30811 }else{
30812 int c2 = *(zIn++);
30813 c2 += (*(zIn++))<<8;
@@ -30816,19 +30887,27 @@
30816 c = 0xfffd;
30817 }else{
30818 c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
30819 }
30820 }
 
 
 
 
 
 
 
30821 }
30822 WRITE_UTF8(z, c);
30823 }
30824 }else{
30825 /* UTF-16 Big-endian -> UTF-8 */
30826 while( zIn<zTerm ){
30827 c = (*(zIn++))<<8;
30828 c += *(zIn++);
30829 if( c>=0xd800 && c<0xe000 ){
 
30830 if( c>=0xdc00 || zIn>=zTerm ){
30831 c = 0xfffd;
30832 }else{
30833 int c2 = (*(zIn++))<<8;
30834 c2 += *(zIn++);
@@ -30837,10 +30916,17 @@
30837 c = 0xfffd;
30838 }else{
30839 c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
30840 }
30841 }
 
 
 
 
 
 
 
30842 }
30843 WRITE_UTF8(z, c);
30844 }
30845 }
30846 pMem->n = (int)(z - zOut);
@@ -34928,20 +35014,21 @@
34928 static int osSetPosixAdvisoryLock(
34929 int h, /* The file descriptor on which to take the lock */
34930 struct flock *pLock, /* The description of the lock */
34931 unixFile *pFile /* Structure holding timeout value */
34932 ){
 
34933 int rc = osFcntl(h,F_SETLK,pLock);
34934 while( rc<0 && pFile->iBusyTimeout>0 ){
34935 /* On systems that support some kind of blocking file lock with a timeout,
34936 ** make appropriate changes here to invoke that blocking file lock. On
34937 ** generic posix, however, there is no such API. So we simply try the
34938 ** lock once every millisecond until either the timeout expires, or until
34939 ** the lock is obtained. */
34940 usleep(1000);
34941 rc = osFcntl(h,F_SETLK,pLock);
34942 pFile->iBusyTimeout--;
34943 }
34944 return rc;
34945 }
34946 #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
34947
@@ -37679,17 +37766,24 @@
37679
37680 /* Locks are within range */
37681 assert( n>=1 && n<=SQLITE_SHM_NLOCK );
37682
37683 if( pShmNode->hShm>=0 ){
 
37684 /* Initialize the locking parameters */
37685 f.l_type = lockType;
37686 f.l_whence = SEEK_SET;
37687 f.l_start = ofst;
37688 f.l_len = n;
37689 rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
37690 rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
 
 
 
 
 
 
37691 }
37692
37693 /* Update the global lock state and do debug tracing */
37694 #ifdef SQLITE_DEBUG
37695 { u16 mask;
@@ -38182,26 +38276,27 @@
38182 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
38183 assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
38184 assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
38185 assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
38186
38187 /* Check that, if this to be a blocking lock, that locks have been
38188 ** obtained in the following order.
38189 **
38190 ** 1. Checkpointer lock (ofst==1).
38191 ** 2. Recover lock (ofst==2).
38192 ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
38193 ** 4. Write lock (ofst==0).
38194 **
38195 ** In other words, if this is a blocking lock, none of the locks that
38196 ** occur later in the above list than the lock being obtained may be
38197 ** held. */
38198 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
38199 assert( pDbFd->iBusyTimeout==0
38200 || (flags & SQLITE_SHM_UNLOCK) || ofst==0
38201 || ((p->exclMask|p->sharedMask)&~((1<<ofst)-2))==0
38202 );
 
 
38203 #endif
38204
38205 mask = (1<<(ofst+n)) - (1<<ofst);
38206 assert( n>1 || mask==(1<<ofst) );
38207 sqlite3_mutex_enter(pShmNode->pShmMutex);
@@ -44990,10 +45085,11 @@
44990 }
44991
44992 /* Forward references to VFS helper methods used for temporary files */
44993 static int winGetTempname(sqlite3_vfs *, char **);
44994 static int winIsDir(const void *);
 
44995 static BOOL winIsDriveLetterAndColon(const char *);
44996
44997 /*
44998 ** Control and query of the open file handle.
44999 */
@@ -46759,11 +46855,13 @@
46759 pFile->pVfs = pVfs;
46760 pFile->h = h;
46761 if( isReadonly ){
46762 pFile->ctrlFlags |= WINFILE_RDONLY;
46763 }
46764 if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
 
 
46765 pFile->ctrlFlags |= WINFILE_PSOW;
46766 }
46767 pFile->lastErrno = NO_ERROR;
46768 pFile->zPath = zName;
46769 #if SQLITE_MAX_MMAP_SIZE>0
@@ -46968,10 +47066,21 @@
46968 *pResOut = rc;
46969 OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
46970 zFilename, pResOut, *pResOut));
46971 return SQLITE_OK;
46972 }
 
 
 
 
 
 
 
 
 
 
 
46973
46974 /*
46975 ** Returns non-zero if the specified path name starts with a drive letter
46976 ** followed by a colon character.
46977 */
@@ -47033,14 +47142,15 @@
47033 DWORD nByte;
47034 void *zConverted;
47035 char *zOut;
47036 #endif
47037
47038 /* If this path name begins with "/X:", where "X" is any alphabetic
47039 ** character, discard the initial "/" from the pathname.
47040 */
47041 if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
 
47042 zRelative++;
47043 }
47044
47045 #if defined(__CYGWIN__)
47046 SimulateIOError( return SQLITE_ERROR );
@@ -47792,11 +47902,11 @@
47792 if( newSz>p->szMax ){
47793 return SQLITE_FULL;
47794 }
47795 newSz *= 2;
47796 if( newSz>p->szMax ) newSz = p->szMax;
47797 pNew = sqlite3_realloc64(p->aData, newSz);
47798 if( pNew==0 ) return SQLITE_NOMEM;
47799 p->aData = pNew;
47800 p->szAlloc = newSz;
47801 return SQLITE_OK;
47802 }
@@ -48239,14 +48349,15 @@
48239 */
48240 SQLITE_PRIVATE int sqlite3MemdbInit(void){
48241 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
48242 int sz = pLower->szOsFile;
48243 memdb_vfs.pAppData = pLower;
48244 /* In all known configurations of SQLite, the size of a default
48245 ** sqlite3_file is greater than the size of a memdb sqlite3_file.
48246 ** Should that ever change, remove the following NEVER() */
48247 if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
 
48248 memdb_vfs.szOsFile = sz;
48249 return sqlite3_vfs_register(&memdb_vfs, 0);
48250 }
48251 #endif /* SQLITE_ENABLE_DESERIALIZE */
48252
@@ -51505,10 +51616,15 @@
51505 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
51506 #endif
51507
51508 /* Return the sqlite3_file object for the WAL file */
51509 SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
 
 
 
 
 
51510
51511 #endif /* ifndef SQLITE_OMIT_WAL */
51512 #endif /* SQLITE_WAL_H */
51513
51514 /************** End of wal.h *************************************************/
@@ -54026,13 +54142,16 @@
54026 }
54027 if( exists ){
54028 /* One of the journals pointed to by the master journal exists.
54029 ** Open it and check if it points at the master journal. If
54030 ** so, return without deleting the master journal file.
 
 
 
54031 */
54032 int c;
54033 int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
54034 rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
54035 if( rc!=SQLITE_OK ){
54036 goto delmaster_out;
54037 }
54038
@@ -56232,10 +56351,11 @@
56232 ** Pager object (sizeof(Pager) bytes)
56233 ** PCache object (sqlite3PcacheSize() bytes)
56234 ** Database file handle (pVfs->szOsFile bytes)
56235 ** Sub-journal file handle (journalFileSize bytes)
56236 ** Main journal file handle (journalFileSize bytes)
 
56237 ** \0\0\0\0 database prefix (4 bytes)
56238 ** Database file name (nPathname+1 bytes)
56239 ** URI query parameters (nUriByte bytes)
56240 ** Journal filename (nPathname+8+1 bytes)
56241 ** WAL filename (nPathname+4+1 bytes)
@@ -56271,10 +56391,11 @@
56271 pPtr = (u8 *)sqlite3MallocZero(
56272 ROUND8(sizeof(*pPager)) + /* Pager structure */
56273 ROUND8(pcacheSize) + /* PCache object */
56274 ROUND8(pVfs->szOsFile) + /* The main db file */
56275 journalFileSize * 2 + /* The two journal files */
 
56276 4 + /* Database prefix */
56277 nPathname + 1 + /* database filename */
56278 nUriByte + /* query parameters */
56279 nPathname + 8 + 1 + /* Journal filename */
56280 #ifndef SQLITE_OMIT_WAL
@@ -56291,10 +56412,11 @@
56291 pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
56292 pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
56293 pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
56294 pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
56295 assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
 
56296
56297 /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
56298 pPtr += 4; /* Skip zero prefix */
56299 pPager->zFilename = (char*)pPtr;
56300 if( nPathname>0 ){
@@ -56491,10 +56613,23 @@
56491
56492 *ppPager = pPager;
56493 return SQLITE_OK;
56494 }
56495
 
 
 
 
 
 
 
 
 
 
 
 
 
56496
56497
56498 /*
56499 ** This function is called after transitioning from PAGER_UNLOCK to
56500 ** PAGER_SHARED state. It tests if there is a hot journal present in
@@ -57176,11 +57311,10 @@
57176 Pager *pPager;
57177 assert( pPg!=0 );
57178 assert( pPg->pgno==1 );
57179 assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
57180 pPager = pPg->pPager;
57181 sqlite3PagerResetLockTimeout(pPager);
57182 sqlite3PcacheRelease(pPg);
57183 pagerUnlockIfUnused(pPager);
57184 }
57185
57186 /*
@@ -58469,20 +58603,10 @@
58469 */
58470 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
58471 return pPager->fd;
58472 }
58473
58474 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
58475 /*
58476 ** Reset the lock timeout for pager.
58477 */
58478 SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){
58479 int x = 0;
58480 sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
58481 }
58482 #endif
58483
58484 /*
58485 ** Return the file handle for the journal file (if it exists).
58486 ** This will be either the rollback journal or the WAL file.
58487 */
58488 SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
@@ -58892,11 +59016,10 @@
58892 (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
58893 pPager->pBusyHandlerArg,
58894 pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
58895 pnLog, pnCkpt
58896 );
58897 sqlite3PagerResetLockTimeout(pPager);
58898 }
58899 return rc;
58900 }
58901
58902 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
@@ -59057,11 +59180,35 @@
59057 }
59058 }
59059 return rc;
59060 }
59061
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59062
 
 
 
 
 
 
 
 
 
 
59063
59064 #ifdef SQLITE_ENABLE_SNAPSHOT
59065 /*
59066 ** If this is a WAL database, obtain a snapshot handle for the snapshot
59067 ** currently open. Otherwise, return an error.
@@ -59077,11 +59224,14 @@
59077 /*
59078 ** If this is a WAL database, store a pointer to pSnapshot. Next time a
59079 ** read transaction is opened, attempt to read from the snapshot it
59080 ** identifies. If this is not a WAL database, return an error.
59081 */
59082 SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
 
 
 
59083 int rc = SQLITE_OK;
59084 if( pPager->pWal ){
59085 sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
59086 }else{
59087 rc = SQLITE_ERROR;
@@ -59622,10 +59772,13 @@
59622 u8 lockError; /* True if a locking error has occurred */
59623 #endif
59624 #ifdef SQLITE_ENABLE_SNAPSHOT
59625 WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
59626 #endif
 
 
 
59627 };
59628
59629 /*
59630 ** Candidate values for Wal.exclusiveMode.
59631 */
@@ -59720,11 +59873,11 @@
59720
59721 /* Enlarge the pWal->apWiData[] array if required */
59722 if( pWal->nWiData<=iPage ){
59723 sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
59724 volatile u32 **apNew;
59725 apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
59726 if( !apNew ){
59727 *ppPage = 0;
59728 return SQLITE_NOMEM_BKPT;
59729 }
59730 memset((void*)&apNew[pWal->nWiData], 0,
@@ -59841,29 +59994,47 @@
59841
59842 aOut[0] = s1;
59843 aOut[1] = s2;
59844 }
59845
 
 
 
 
59846 static void walShmBarrier(Wal *pWal){
59847 if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
59848 sqlite3OsShmBarrier(pWal->pDbFd);
59849 }
59850 }
59851
 
 
 
 
 
 
 
 
 
 
 
 
 
59852 /*
59853 ** Write the header information in pWal->hdr into the wal-index.
59854 **
59855 ** The checksum on pWal->hdr is updated before it is written.
59856 */
59857 static void walIndexWriteHdr(Wal *pWal){
59858 volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
59859 const int nCksum = offsetof(WalIndexHdr, aCksum);
59860
59861 assert( pWal->writeLock );
59862 pWal->hdr.isInit = 1;
59863 pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
59864 walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
 
59865 memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
59866 walShmBarrier(pWal);
59867 memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
59868 }
59869
@@ -59995,11 +60166,11 @@
59995 if( pWal->exclusiveMode ) return SQLITE_OK;
59996 rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
59997 SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
59998 WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
59999 walLockName(lockIdx), rc ? "failed" : "ok"));
60000 VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
60001 return rc;
60002 }
60003 static void walUnlockShared(Wal *pWal, int lockIdx){
60004 if( pWal->exclusiveMode ) return;
60005 (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
@@ -60011,11 +60182,11 @@
60011 if( pWal->exclusiveMode ) return SQLITE_OK;
60012 rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
60013 SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
60014 WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
60015 walLockName(lockIdx), n, rc ? "failed" : "ok"));
60016 VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
60017 return rc;
60018 }
60019 static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
60020 if( pWal->exclusiveMode ) return;
60021 (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
@@ -60283,15 +60454,10 @@
60283 int rc; /* Return Code */
60284 i64 nSize; /* Size of log file */
60285 u32 aFrameCksum[2] = {0, 0};
60286 int iLock; /* Lock offset to lock for checkpoint */
60287
60288 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
60289 int tmout = 0;
60290 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
60291 #endif
60292
60293 /* Obtain an exclusive lock on all byte in the locking range not already
60294 ** locked by the caller. The caller is guaranteed to have locked the
60295 ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
60296 ** If successful, the same bytes that are locked here are unlocked before
60297 ** this function returns.
@@ -60835,10 +61001,93 @@
60835 p = 0;
60836 }
60837 *pp = p;
60838 return rc;
60839 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60840
60841 /*
60842 ** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
60843 ** n. If the attempt fails and parameter xBusy is not NULL, then it is a
60844 ** busy-handler function. Invoke it and retry the lock until either the
@@ -60853,10 +61102,16 @@
60853 ){
60854 int rc;
60855 do {
60856 rc = walLockExclusive(pWal, lockIdx, n);
60857 }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
 
 
 
 
 
 
60858 return rc;
60859 }
60860
60861 /*
60862 ** The cache of the wal-index header must be valid to call this function.
@@ -60890,11 +61145,11 @@
60890 pWal->nCkpt++;
60891 pWal->hdr.mxFrame = 0;
60892 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
60893 memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
60894 walIndexWriteHdr(pWal);
60895 pInfo->nBackfill = 0;
60896 pInfo->nBackfillAttempted = 0;
60897 pInfo->aReadMark[1] = 0;
60898 for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
60899 assert( pInfo->aReadMark[0]==0 );
60900 }
@@ -60965,36 +61220,17 @@
60965 ** cannot be backfilled from the WAL.
60966 */
60967 mxSafeFrame = pWal->hdr.mxFrame;
60968 mxPage = pWal->hdr.nPage;
60969 for(i=1; i<WAL_NREADER; i++){
60970 /* Thread-sanitizer reports that the following is an unsafe read,
60971 ** as some other thread may be in the process of updating the value
60972 ** of the aReadMark[] slot. The assumption here is that if that is
60973 ** happening, the other client may only be increasing the value,
60974 ** not decreasing it. So assuming either that either the "old" or
60975 ** "new" version of the value is read, and not some arbitrary value
60976 ** that would never be written by a real client, things are still
60977 ** safe.
60978 **
60979 ** Astute readers have pointed out that the assumption stated in the
60980 ** last sentence of the previous paragraph is not guaranteed to be
60981 ** true for all conforming systems. However, the assumption is true
60982 ** for all compilers and architectures in common use today (circa
60983 ** 2019-11-27) and the alternatives are both slow and complex, and
60984 ** so we will continue to go with the current design for now. If this
60985 ** bothers you, or if you really are running on a system where aligned
60986 ** 32-bit reads and writes are not atomic, then you can simply avoid
60987 ** the use of WAL mode, or only use WAL mode together with
60988 ** PRAGMA locking_mode=EXCLUSIVE and all will be well.
60989 */
60990 u32 y = pInfo->aReadMark[i];
60991 if( mxSafeFrame>y ){
60992 assert( y<=pWal->hdr.mxFrame );
60993 rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
60994 if( rc==SQLITE_OK ){
60995 pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
 
60996 walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
60997 }else if( rc==SQLITE_BUSY ){
60998 mxSafeFrame = y;
60999 xBusy = 0;
61000 }else{
@@ -61008,11 +61244,11 @@
61008 rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
61009 assert( rc==SQLITE_OK || pIter==0 );
61010 }
61011
61012 if( pIter
61013 && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
61014 ){
61015 u32 nBackfill = pInfo->nBackfill;
61016
61017 pInfo->nBackfillAttempted = mxSafeFrame;
61018
@@ -61023,10 +61259,11 @@
61023 ** about the eventual size of the db file to the VFS layer.
61024 */
61025 if( rc==SQLITE_OK ){
61026 i64 nReq = ((i64)mxPage * szPage);
61027 i64 nSize; /* Current size of database file */
 
61028 rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
61029 if( rc==SQLITE_OK && nSize<nReq ){
61030 sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
61031 }
61032 }
@@ -61050,10 +61287,11 @@
61050 iOffset = (iDbpage-1)*(i64)szPage;
61051 testcase( IS_BIG_INT(iOffset) );
61052 rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
61053 if( rc!=SQLITE_OK ) break;
61054 }
 
61055
61056 /* If work was actually accomplished... */
61057 if( rc==SQLITE_OK ){
61058 if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
61059 i64 szDb = pWal->hdr.nPage*(i64)szPage;
@@ -61062,15 +61300,11 @@
61062 if( rc==SQLITE_OK ){
61063 rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
61064 }
61065 }
61066 if( rc==SQLITE_OK ){
61067 rc = sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
61068 if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
61069 }
61070 if( rc==SQLITE_OK ){
61071 pInfo->nBackfill = mxSafeFrame;
61072 }
61073 }
61074
61075 /* Release the reader lock held while backfilling */
61076 walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
@@ -61225,11 +61459,11 @@
61225 ** and *pChanged is set to 1.
61226 **
61227 ** If the checksum cannot be verified return non-zero. If the header
61228 ** is read successfully and the checksum verified, return zero.
61229 */
61230 static int walIndexTryHdr(Wal *pWal, int *pChanged){
61231 u32 aCksum[2]; /* Checksum on the header content */
61232 WalIndexHdr h1, h2; /* Two copies of the header content */
61233 WalIndexHdr volatile *aHdr; /* Header in shared memory */
61234
61235 /* The first page of the wal-index must be mapped at this point. */
@@ -61238,17 +61472,23 @@
61238 /* Read the header. This might happen concurrently with a write to the
61239 ** same area of shared memory on a different CPU in a SMP,
61240 ** meaning it is possible that an inconsistent snapshot is read
61241 ** from the file. If this happens, return non-zero.
61242 **
 
61243 ** There are two copies of the header at the beginning of the wal-index.
61244 ** When reading, read [0] first then [1]. Writes are in the reverse order.
61245 ** Memory barriers are used to prevent the compiler or the hardware from
61246 ** reordering the reads and writes.
 
 
 
 
 
61247 */
61248 aHdr = walIndexHdr(pWal);
61249 memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
61250 walShmBarrier(pWal);
61251 memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
61252
61253 if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
61254 return 1; /* Dirty read */
@@ -61334,32 +61574,36 @@
61334 badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
61335
61336 /* If the first attempt failed, it might have been due to a race
61337 ** with a writer. So get a WRITE lock and try again.
61338 */
61339 assert( badHdr==0 || pWal->writeLock==0 );
61340 if( badHdr ){
61341 if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
61342 if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
61343 walUnlockShared(pWal, WAL_WRITE_LOCK);
61344 rc = SQLITE_READONLY_RECOVERY;
61345 }
61346 }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
61347 pWal->writeLock = 1;
61348 if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
61349 badHdr = walIndexTryHdr(pWal, pChanged);
61350 if( badHdr ){
61351 /* If the wal-index header is still malformed even while holding
61352 ** a WRITE lock, it can only mean that the header is corrupted and
61353 ** needs to be reconstructed. So run recovery to do exactly that.
61354 */
61355 rc = walIndexRecover(pWal);
61356 *pChanged = 1;
61357 }
61358 }
61359 pWal->writeLock = 0;
61360 walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
 
 
 
 
 
61361 }
61362 }
61363
61364 /* If the header is read successfully, check the version number to make
61365 ** sure the wal-index was not constructed with some future format that
@@ -61685,11 +61929,11 @@
61685 }
61686
61687 assert( pWal->nWiData>0 );
61688 assert( pWal->apWiData[0]!=0 );
61689 pInfo = walCkptInfo(pWal);
61690 if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
61691 #ifdef SQLITE_ENABLE_SNAPSHOT
61692 && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
61693 #endif
61694 ){
61695 /* The WAL has been completely backfilled (or it is empty).
@@ -61852,11 +62096,11 @@
61852 void *pBuf2 = sqlite3_malloc(szPage);
61853 if( pBuf1==0 || pBuf2==0 ){
61854 rc = SQLITE_NOMEM;
61855 }else{
61856 u32 i = pInfo->nBackfillAttempted;
61857 for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
61858 WalHashLoc sLoc; /* Hash table location */
61859 u32 pgno; /* Page number in db file */
61860 i64 iDbOff; /* Offset of db file entry */
61861 i64 iWalOff; /* Offset of wal file entry */
61862
@@ -61907,26 +62151,40 @@
61907 ** needs to be flushed.
61908 */
61909 SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
61910 int rc; /* Return code */
61911 int cnt = 0; /* Number of TryBeginRead attempts */
61912 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61913 int tmout = 0;
61914 #endif
61915
61916 #ifdef SQLITE_ENABLE_SNAPSHOT
61917 int bChanged = 0;
61918 WalIndexHdr *pSnapshot = pWal->pSnapshot;
61919 if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
61920 bChanged = 1;
61921 }
61922 #endif
61923
61924 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61925 /* Disable blocking locks. They are not useful when trying to open a
61926 ** read-transaction, and blocking may cause deadlock anyway. */
61927 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61928 #endif
61929
61930 do{
61931 rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
61932 }while( rc==WAL_RETRY );
@@ -61933,20 +62191,10 @@
61933 testcase( (rc&0xff)==SQLITE_BUSY );
61934 testcase( (rc&0xff)==SQLITE_IOERR );
61935 testcase( rc==SQLITE_PROTOCOL );
61936 testcase( rc==SQLITE_OK );
61937
61938 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61939 /* If they were disabled earlier and the read-transaction has been
61940 ** successfully opened, re-enable blocking locks. This is because the
61941 ** connection may attempt to upgrade to a write-transaction, which does
61942 ** benefit from using blocking locks. */
61943 if( rc==SQLITE_OK ){
61944 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
61945 }
61946 #endif
61947
61948 #ifdef SQLITE_ENABLE_SNAPSHOT
61949 if( rc==SQLITE_OK ){
61950 if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
61951 /* At this point the client has a lock on an aReadMark[] slot holding
61952 ** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr
@@ -61964,52 +62212,46 @@
61964 volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
61965
61966 assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
61967 assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
61968
61969 /* It is possible that there is a checkpointer thread running
61970 ** concurrent with this code. If this is the case, it may be that the
61971 ** checkpointer has already determined that it will checkpoint
61972 ** snapshot X, where X is later in the wal file than pSnapshot, but
61973 ** has not yet set the pInfo->nBackfillAttempted variable to indicate
61974 ** its intent. To avoid the race condition this leads to, ensure that
61975 ** there is no checkpointer process by taking a shared CKPT lock
61976 ** before checking pInfo->nBackfillAttempted.
61977 **
61978 ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
61979 ** this already?
61980 */
61981 rc = walLockShared(pWal, WAL_CKPT_LOCK);
61982
61983 if( rc==SQLITE_OK ){
61984 /* Check that the wal file has not been wrapped. Assuming that it has
61985 ** not, also check that no checkpointer has attempted to checkpoint any
61986 ** frames beyond pSnapshot->mxFrame. If either of these conditions are
61987 ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
61988 ** with *pSnapshot and set *pChanged as appropriate for opening the
61989 ** snapshot. */
61990 if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
61991 && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
61992 ){
61993 assert( pWal->readLock>0 );
61994 memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
61995 *pChanged = bChanged;
61996 }else{
61997 rc = SQLITE_ERROR_SNAPSHOT;
61998 }
61999
62000 /* Release the shared CKPT lock obtained above. */
62001 walUnlockShared(pWal, WAL_CKPT_LOCK);
62002 pWal->minFrame = 1;
62003 }
62004
62005
62006 if( rc!=SQLITE_OK ){
62007 sqlite3WalEndReadTransaction(pWal);
62008 }
62009 }
62010 }
 
 
 
 
 
 
 
62011 #endif
62012 return rc;
62013 }
62014
62015 /*
@@ -62085,26 +62327,28 @@
62085 for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
62086 WalHashLoc sLoc; /* Hash table location */
62087 int iKey; /* Hash slot index */
62088 int nCollide; /* Number of hash collisions remaining */
62089 int rc; /* Error code */
 
62090
62091 rc = walHashGet(pWal, iHash, &sLoc);
62092 if( rc!=SQLITE_OK ){
62093 return rc;
62094 }
62095 nCollide = HASHTABLE_NSLOT;
62096 for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
62097 u32 iH = sLoc.aHash[iKey];
62098 u32 iFrame = iH + sLoc.iZero;
62099 if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
62100 assert( iFrame>iRead || CORRUPT_DB );
62101 iRead = iFrame;
62102 }
62103 if( (nCollide--)==0 ){
62104 return SQLITE_CORRUPT_BKPT;
62105 }
 
62106 }
62107 if( iRead ) break;
62108 }
62109
62110 #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -62175,10 +62419,20 @@
62175 **
62176 ** There can only be a single writer active at a time.
62177 */
62178 SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
62179 int rc;
 
 
 
 
 
 
 
 
 
 
62180
62181 /* Cannot start a write transaction without first holding a read
62182 ** transaction. */
62183 assert( pWal->readLock>=0 );
62184 assert( pWal->writeLock==0 && pWal->iReCksum==0 );
@@ -62751,50 +63005,57 @@
62751 ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
62752 assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
62753
62754 if( pWal->readOnly ) return SQLITE_READONLY;
62755 WALTRACE(("WAL%p: checkpoint begins\n", pWal));
 
 
 
 
 
62756
62757 /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
62758 ** "checkpoint" lock on the database file. */
 
 
 
 
 
 
62759 rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
62760 if( rc ){
62761 /* EVIDENCE-OF: R-10421-19736 If any other process is running a
62762 ** checkpoint operation at the same time, the lock cannot be obtained and
62763 ** SQLITE_BUSY is returned.
62764 ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
62765 ** it will not be invoked in this case.
62766 */
62767 testcase( rc==SQLITE_BUSY );
62768 testcase( xBusy!=0 );
62769 return rc;
62770 }
62771 pWal->ckptLock = 1;
62772
62773 /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
62774 ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
62775 ** file.
62776 **
62777 ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
62778 ** immediately, and a busy-handler is configured, it is invoked and the
62779 ** writer lock retried until either the busy-handler returns 0 or the
62780 ** lock is successfully obtained.
62781 */
62782 if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
62783 rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
62784 if( rc==SQLITE_OK ){
62785 pWal->writeLock = 1;
62786 }else if( rc==SQLITE_BUSY ){
62787 eMode2 = SQLITE_CHECKPOINT_PASSIVE;
62788 xBusy2 = 0;
62789 rc = SQLITE_OK;
62790 }
62791 }
62792
62793 /* Read the wal-index header. */
62794 if( rc==SQLITE_OK ){
 
62795 rc = walIndexReadHdr(pWal, &isChanged);
 
62796 if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
62797 sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
62798 }
62799 }
62800
@@ -62821,16 +63082,24 @@
62821 ** next time the pager opens a snapshot on this database it knows that
62822 ** the cache needs to be reset.
62823 */
62824 memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
62825 }
 
 
 
62826
62827 /* Release the locks. */
62828 sqlite3WalEndWriteTransaction(pWal);
62829 walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
62830 pWal->ckptLock = 0;
 
 
62831 WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
 
 
 
62832 return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
62833 }
62834
62835 /* Return the value to pass to a sqlite3_wal_hook callback, the
62836 ** number of frames in the WAL at the point of the last commit since
@@ -62943,11 +63212,14 @@
62943 return rc;
62944 }
62945
62946 /* Try to open on pSnapshot when the next read-transaction starts
62947 */
62948 SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
 
 
 
62949 pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
62950 }
62951
62952 /*
62953 ** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
@@ -63462,11 +63734,11 @@
63462 u8 incrVacuum; /* True if incr-vacuum is enabled */
63463 u8 bDoTruncate; /* True to truncate db on commit */
63464 #endif
63465 u8 inTransaction; /* Transaction state */
63466 u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
63467 u8 nReserveWanted; /* 1 more than desired number of extra bytes per page */
63468 u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
63469 u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
63470 u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
63471 u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
63472 u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
@@ -66356,12 +66628,11 @@
66356 */
66357 static int btreeInvokeBusyHandler(void *pArg){
66358 BtShared *pBt = (BtShared*)pArg;
66359 assert( pBt->db );
66360 assert( sqlite3_mutex_held(pBt->db->mutex) );
66361 return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
66362 sqlite3PagerFile(pBt->pPager));
66363 }
66364
66365 /*
66366 ** Open a database file.
66367 **
@@ -66908,23 +67179,21 @@
66908 ** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
66909 ** and autovacuum mode can no longer be changed.
66910 */
66911 SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
66912 int rc = SQLITE_OK;
 
66913 BtShared *pBt = p->pBt;
66914 assert( nReserve>=-1 && nReserve<=254 );
66915 sqlite3BtreeEnter(p);
66916 if( nReserve>=0 ){
66917 pBt->nReserveWanted = nReserve + 1;
66918 }
66919 if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
66920 sqlite3BtreeLeave(p);
66921 return SQLITE_READONLY;
66922 }
66923 if( nReserve<0 ){
66924 nReserve = pBt->pageSize - pBt->usableSize;
66925 }
66926 assert( nReserve>=0 && nReserve<=255 );
66927 if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
66928 ((pageSize-1)&pageSize)==0 ){
66929 assert( (pageSize & 7)==0 );
66930 assert( !pBt->pCursor );
@@ -66965,18 +67234,22 @@
66965
66966 /*
66967 ** Return the number of bytes of space at the end of every page that
66968 ** are intentually left unused. This is the "reserved" space that is
66969 ** sometimes used by extensions.
 
 
 
 
66970 */
66971 SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){
66972 int n;
66973 sqlite3BtreeEnter(p);
66974 n = ((int)p->pBt->nReserveWanted) - 1;
66975 if( n<0 ) n = sqlite3BtreeGetReserveNoMutex(p);
66976 sqlite3BtreeLeave(p);
66977 return n;
66978 }
66979
66980
66981 /*
66982 ** Set the maximum page count for a database if mxPage is positive.
@@ -67422,10 +67695,11 @@
67422 ** when A already has a read lock, we encourage A to give up and let B
67423 ** proceed.
67424 */
67425 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
67426 BtShared *pBt = p->pBt;
 
67427 int rc = SQLITE_OK;
67428
67429 sqlite3BtreeEnter(p);
67430 btreeIntegrity(p);
67431
@@ -67437,11 +67711,11 @@
67437 goto trans_begun;
67438 }
67439 assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
67440
67441 if( (p->db->flags & SQLITE_ResetDatabase)
67442 && sqlite3PagerIsreadonly(pBt->pPager)==0
67443 ){
67444 pBt->btsFlags &= ~BTS_READ_ONLY;
67445 }
67446
67447 /* Write transactions are not possible on a read-only database */
@@ -67485,10 +67759,22 @@
67485 if( SQLITE_OK!=rc ) goto trans_begun;
67486
67487 pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
67488 if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
67489 do {
 
 
 
 
 
 
 
 
 
 
 
 
67490 /* Call lockBtree() until either pBt->pPage1 is populated or
67491 ** lockBtree() returns something other than SQLITE_OK. lockBtree()
67492 ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
67493 ** reading page 1 it discovers that the page-size of the database
67494 ** file is not pBt->pageSize. In this case lockBtree() will update
@@ -67498,11 +67784,11 @@
67498
67499 if( rc==SQLITE_OK && wrflag ){
67500 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
67501 rc = SQLITE_READONLY;
67502 }else{
67503 rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
67504 if( rc==SQLITE_OK ){
67505 rc = newDatabase(pBt);
67506 }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
67507 /* if there was no transaction opened when this function was
67508 ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
@@ -67511,15 +67797,19 @@
67511 }
67512 }
67513 }
67514
67515 if( rc!=SQLITE_OK ){
 
67516 unlockBtreeIfUnused(pBt);
67517 }
67518 }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
67519 btreeInvokeBusyHandler(pBt) );
67520 sqlite3PagerResetLockTimeout(pBt->pPager);
 
 
 
67521
67522 if( rc==SQLITE_OK ){
67523 if( p->inTrans==TRANS_NONE ){
67524 pBt->nTransaction++;
67525 #ifndef SQLITE_OMIT_SHARED_CACHE
@@ -67567,11 +67857,11 @@
67567 if( wrflag ){
67568 /* This call makes sure that the pager has the correct number of
67569 ** open savepoints. If the second parameter is greater than 0 and
67570 ** the sub-journal is not already open, then it will be opened here.
67571 */
67572 rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
67573 }
67574 }
67575
67576 btreeIntegrity(p);
67577 sqlite3BtreeLeave(p);
@@ -71203,11 +71493,11 @@
71203
71204 /* Remove cells from the start and end of the page */
71205 assert( nCell>=0 );
71206 if( iOld<iNew ){
71207 int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
71208 if( nShift>nCell ) return SQLITE_CORRUPT_BKPT;
71209 memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
71210 nCell -= nShift;
71211 }
71212 if( iNewEnd < iOldEnd ){
71213 int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
@@ -73560,11 +73850,10 @@
73560 }
73561 sqlite3BtreeLeave(p);
73562 return rc;
73563 }
73564
73565 #ifndef SQLITE_OMIT_BTREECOUNT
73566 /*
73567 ** The first argument, pCur, is a cursor opened on some b-tree. Count the
73568 ** number of entries in the b-tree and write the result to *pnEntry.
73569 **
73570 ** SQLITE_OK is returned if the operation is successfully executed.
@@ -73633,11 +73922,10 @@
73633 }
73634
73635 /* An error has occurred. Return an error code. */
73636 return rc;
73637 }
73638 #endif
73639
73640 /*
73641 ** Return the pager associated with a BTree. This routine is used for
73642 ** testing and debugging only.
73643 */
@@ -74684,11 +74972,11 @@
74684 ** Attempt to set the page size of the destination to match the page size
74685 ** of the source.
74686 */
74687 static int setDestPgsz(sqlite3_backup *p){
74688 int rc;
74689 rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
74690 return rc;
74691 }
74692
74693 /*
74694 ** Check that there is no open read-transaction on the b-tree passed as the
@@ -78709,24 +78997,23 @@
78709 ** "PX" -> "r[X]"
78710 ** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
78711 ** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
78712 ** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
78713 */
78714 static int displayComment(
 
78715 const Op *pOp, /* The opcode to be commented */
78716 const char *zP4, /* Previously obtained value for P4 */
78717 char *zTemp, /* Write result here */
78718 int nTemp /* Space available in zTemp[] */
78719 ){
78720 const char *zOpName;
78721 const char *zSynopsis;
78722 int nOpName;
78723 int ii;
78724 char zAlt[50];
78725 StrAccum x;
78726 sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
78727
 
78728 zOpName = sqlite3OpcodeName(pOp->opcode);
78729 nOpName = sqlite3Strlen30(zOpName);
78730 if( zOpName[nOpName+1] ){
78731 int seenCom = 0;
78732 char c;
@@ -78789,14 +79076,16 @@
78789 sqlite3_str_appendf(&x, "; %s", pOp->zComment);
78790 }
78791 }else if( pOp->zComment ){
78792 sqlite3_str_appendall(&x, pOp->zComment);
78793 }
78794 sqlite3StrAccumFinish(&x);
78795 return x.nChar;
 
 
78796 }
78797 #endif /* SQLITE_DEBUG */
78798
78799 #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
78800 /*
78801 ** Translate the P4.pExpr value for an OP_CursorHint opcode into text
78802 ** that can be displayed in the P4 column of EXPLAIN output.
@@ -78873,15 +79162,15 @@
78873 #if VDBE_DISPLAY_P4
78874 /*
78875 ** Compute a string that describes the P4 parameter for an opcode.
78876 ** Use zTemp for any required temporary buffer space.
78877 */
78878 static char *displayP4(Op *pOp, char *zTemp, int nTemp){
78879 char *zP4 = zTemp;
78880 StrAccum x;
78881 assert( nTemp>=20 );
78882 sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
78883 switch( pOp->p4type ){
78884 case P4_KEYINFO: {
78885 int j;
78886 KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
78887 assert( pKeyInfo->aSortFlags!=0 );
@@ -78961,40 +79250,36 @@
78961 int i;
78962 int *ai = pOp->p4.ai;
78963 int n = ai[0]; /* The first element of an INTARRAY is always the
78964 ** count of the number of elements to follow */
78965 for(i=1; i<=n; i++){
78966 sqlite3_str_appendf(&x, ",%d", ai[i]);
78967 }
78968 zTemp[0] = '[';
78969 sqlite3_str_append(&x, "]", 1);
78970 break;
78971 }
78972 case P4_SUBPROGRAM: {
78973 sqlite3_str_appendf(&x, "program");
78974 break;
78975 }
78976 case P4_DYNBLOB:
78977 case P4_ADVANCE: {
78978 zTemp[0] = 0;
78979 break;
78980 }
78981 case P4_TABLE: {
78982 sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
78983 break;
78984 }
78985 default: {
78986 zP4 = pOp->p4.z;
78987 if( zP4==0 ){
78988 zP4 = zTemp;
78989 zTemp[0] = 0;
78990 }
78991 }
78992 }
78993 sqlite3StrAccumFinish(&x);
78994 assert( zP4!=0 );
78995 return zP4;
 
 
78996 }
78997 #endif /* VDBE_DISPLAY_P4 */
78998
78999 /*
79000 ** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
@@ -79080,28 +79365,34 @@
79080 /*
79081 ** Print a single opcode. This routine is used for debugging only.
79082 */
79083 SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
79084 char *zP4;
79085 char zPtr[50];
79086 char zCom[100];
79087 static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
79088 if( pOut==0 ) pOut = stdout;
79089 zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
 
 
79090 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79091 displayComment(pOp, zP4, zCom, sizeof(zCom));
79092 #else
79093 zCom[0] = 0;
79094 #endif
79095 /* NB: The sqlite3OpcodeName() function is implemented by code created
79096 ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
79097 ** information from the vdbe.c source text */
79098 fprintf(pOut, zFormat1, pc,
79099 sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
79100 zCom
 
79101 );
79102 fflush(pOut);
 
 
 
79103 }
79104 #endif
79105
79106 /*
79107 ** Initialize an array of N Mem element.
@@ -79188,10 +79479,125 @@
79188 assert( sqlite3VdbeFrameIsValid(pFrame) );
79189 pFrame->pParent = pFrame->v->pDelFrame;
79190 pFrame->v->pDelFrame = pFrame;
79191 }
79192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79193
79194 /*
79195 ** Delete a VdbeFrame object and its contents. VdbeFrame objects are
79196 ** allocated by the OP_Program opcode in sqlite3VdbeExec().
79197 */
@@ -79228,20 +79634,18 @@
79228 ** the trigger subprograms are listed one by one.
79229 */
79230 SQLITE_PRIVATE int sqlite3VdbeList(
79231 Vdbe *p /* The VDBE */
79232 ){
79233 int nRow; /* Stop when row count reaches this */
79234 int nSub = 0; /* Number of sub-vdbes seen so far */
79235 SubProgram **apSub = 0; /* Array of sub-vdbes */
79236 Mem *pSub = 0; /* Memory cell hold array of subprogs */
79237 sqlite3 *db = p->db; /* The database connection */
79238 int i; /* Loop counter */
79239 int rc = SQLITE_OK; /* Return code */
79240 Mem *pMem = &p->aMem[1]; /* First Mem of result set */
79241 int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
79242 Op *pOp = 0;
 
79243
79244 assert( p->explain );
79245 assert( p->magic==VDBE_MAGIC_RUN );
79246 assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
79247
@@ -79257,166 +79661,66 @@
79257 ** sqlite3_column_text16() failed. */
79258 sqlite3OomFault(db);
79259 return SQLITE_ERROR;
79260 }
79261
79262 /* When the number of output rows reaches nRow, that means the
79263 ** listing has finished and sqlite3_step() should return SQLITE_DONE.
79264 ** nRow is the sum of the number of rows in the main program, plus
79265 ** the sum of the number of rows in all trigger subprograms encountered
79266 ** so far. The nRow value will increase as new trigger subprograms are
79267 ** encountered, but p->pc will eventually catch up to nRow.
79268 */
79269 nRow = p->nOp;
79270 if( bListSubprogs ){
79271 /* The first 8 memory cells are used for the result set. So we will
79272 ** commandeer the 9th cell to use as storage for an array of pointers
79273 ** to trigger subprograms. The VDBE is guaranteed to have at least 9
79274 ** cells. */
79275 assert( p->nMem>9 );
79276 pSub = &p->aMem[9];
79277 if( pSub->flags&MEM_Blob ){
79278 /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
79279 ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
79280 nSub = pSub->n/sizeof(Vdbe*);
79281 apSub = (SubProgram **)pSub->z;
79282 }
79283 for(i=0; i<nSub; i++){
79284 nRow += apSub[i]->nOp;
79285 }
79286 }
79287
79288 while(1){ /* Loop exits via break */
79289 i = p->pc++;
79290 if( i>=nRow ){
79291 p->rc = SQLITE_OK;
79292 rc = SQLITE_DONE;
79293 break;
79294 }
79295 if( i<p->nOp ){
79296 /* The output line number is small enough that we are still in the
79297 ** main program. */
79298 pOp = &p->aOp[i];
79299 }else{
79300 /* We are currently listing subprograms. Figure out which one and
79301 ** pick up the appropriate opcode. */
79302 int j;
79303 i -= p->nOp;
79304 assert( apSub!=0 );
79305 assert( nSub>0 );
79306 for(j=0; i>=apSub[j]->nOp; j++){
79307 i -= apSub[j]->nOp;
79308 assert( i<apSub[j]->nOp || j+1<nSub );
79309 }
79310 pOp = &apSub[j]->aOp[i];
79311 }
79312
79313 /* When an OP_Program opcode is encounter (the only opcode that has
79314 ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
79315 ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
79316 ** has not already been seen.
79317 */
79318 if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
79319 int nByte = (nSub+1)*sizeof(SubProgram*);
79320 int j;
79321 for(j=0; j<nSub; j++){
79322 if( apSub[j]==pOp->p4.pProgram ) break;
79323 }
79324 if( j==nSub ){
79325 p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
79326 if( p->rc!=SQLITE_OK ){
79327 rc = SQLITE_ERROR;
79328 break;
79329 }
79330 apSub = (SubProgram **)pSub->z;
79331 apSub[nSub++] = pOp->p4.pProgram;
79332 pSub->flags |= MEM_Blob;
79333 pSub->n = nSub*sizeof(SubProgram*);
79334 nRow += pOp->p4.pProgram->nOp;
79335 }
79336 }
79337 if( p->explain<2 ) break;
79338 if( pOp->opcode==OP_Explain ) break;
79339 if( pOp->opcode==OP_Init && p->pc>1 ) break;
79340 }
79341
79342 if( rc==SQLITE_OK ){
79343 if( AtomicLoad(&db->u1.isInterrupted) ){
79344 p->rc = SQLITE_INTERRUPT;
79345 rc = SQLITE_ERROR;
79346 sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
79347 }else{
79348 char *zP4;
79349 if( p->explain==1 ){
79350 pMem->flags = MEM_Int;
79351 pMem->u.i = i; /* Program counter */
79352 pMem++;
79353
79354 pMem->flags = MEM_Static|MEM_Str|MEM_Term;
79355 pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
79356 assert( pMem->z!=0 );
79357 pMem->n = sqlite3Strlen30(pMem->z);
79358 pMem->enc = SQLITE_UTF8;
79359 pMem++;
79360 }
79361
79362 pMem->flags = MEM_Int;
79363 pMem->u.i = pOp->p1; /* P1 */
79364 pMem++;
79365
79366 pMem->flags = MEM_Int;
79367 pMem->u.i = pOp->p2; /* P2 */
79368 pMem++;
79369
79370 pMem->flags = MEM_Int;
79371 pMem->u.i = pOp->p3; /* P3 */
79372 pMem++;
79373
79374 if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
79375 assert( p->db->mallocFailed );
79376 return SQLITE_ERROR;
79377 }
79378 pMem->flags = MEM_Str|MEM_Term;
79379 zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
79380 if( zP4!=pMem->z ){
79381 pMem->n = 0;
79382 sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
79383 }else{
79384 assert( pMem->z!=0 );
79385 pMem->n = sqlite3Strlen30(pMem->z);
79386 pMem->enc = SQLITE_UTF8;
79387 }
79388 pMem++;
79389
79390 if( p->explain==1 ){
79391 if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
79392 assert( p->db->mallocFailed );
79393 return SQLITE_ERROR;
79394 }
79395 pMem->flags = MEM_Str|MEM_Term;
79396 pMem->n = 2;
79397 sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
79398 pMem->enc = SQLITE_UTF8;
79399 pMem++;
79400
79401 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79402 if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
79403 assert( p->db->mallocFailed );
79404 return SQLITE_ERROR;
79405 }
79406 pMem->flags = MEM_Str|MEM_Term;
79407 pMem->n = displayComment(pOp, zP4, pMem->z, 500);
79408 pMem->enc = SQLITE_UTF8;
79409 #else
79410 pMem->flags = MEM_Null; /* Comment */
79411 #endif
79412 }
79413
79414 p->nResColumn = 8 - 4*(p->explain-1);
79415 p->pResultSet = &p->aMem[1];
79416 p->rc = SQLITE_OK;
79417 rc = SQLITE_ROW;
 
 
79418 }
79419 }
79420 return rc;
79421 }
79422 #endif /* SQLITE_OMIT_EXPLAIN */
@@ -79982,12 +80286,13 @@
79982 int retryCount = 0;
79983 int nMainFile;
79984
79985 /* Select a master journal file name */
79986 nMainFile = sqlite3Strlen30(zMainFile);
79987 zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz%c%c", zMainFile, 0, 0);
79988 if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
 
79989 do {
79990 u32 iRandom;
79991 if( retryCount ){
79992 if( retryCount>100 ){
79993 sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
@@ -80013,11 +80318,11 @@
80013 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
80014 SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
80015 );
80016 }
80017 if( rc!=SQLITE_OK ){
80018 sqlite3DbFree(db, zMaster);
80019 return rc;
80020 }
80021
80022 /* Write the name of each database file in the transaction into the new
80023 ** master journal file. If an error occurs at this point close
@@ -80036,11 +80341,11 @@
80036 rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
80037 offset += sqlite3Strlen30(zFile)+1;
80038 if( rc!=SQLITE_OK ){
80039 sqlite3OsCloseFree(pMaster);
80040 sqlite3OsDelete(pVfs, zMaster, 0);
80041 sqlite3DbFree(db, zMaster);
80042 return rc;
80043 }
80044 }
80045 }
80046
@@ -80050,11 +80355,11 @@
80050 if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
80051 && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
80052 ){
80053 sqlite3OsCloseFree(pMaster);
80054 sqlite3OsDelete(pVfs, zMaster, 0);
80055 sqlite3DbFree(db, zMaster);
80056 return rc;
80057 }
80058
80059 /* Sync all the db files involved in the transaction. The same call
80060 ** sets the master journal pointer in each individual journal. If
@@ -80073,20 +80378,20 @@
80073 }
80074 }
80075 sqlite3OsCloseFree(pMaster);
80076 assert( rc!=SQLITE_BUSY );
80077 if( rc!=SQLITE_OK ){
80078 sqlite3DbFree(db, zMaster);
80079 return rc;
80080 }
80081
80082 /* Delete the master journal file. This commits the transaction. After
80083 ** doing this the directory is synced again before any individual
80084 ** transaction files are deleted.
80085 */
80086 rc = sqlite3OsDelete(pVfs, zMaster, 1);
80087 sqlite3DbFree(db, zMaster);
80088 zMaster = 0;
80089 if( rc ){
80090 return rc;
80091 }
80092
@@ -83825,11 +84130,11 @@
83825 p->db->errCode = SQLITE_OK;
83826
83827 /* If the bit corresponding to this variable in Vdbe.expmask is set, then
83828 ** binding a new value to this variable invalidates the current query plan.
83829 **
83830 ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
83831 ** parameter in the WHERE clause might influence the choice of query plan
83832 ** for a statement, then the statement will be automatically recompiled,
83833 ** as if there had been a schema change, on the first sqlite3_step() call
83834 ** following any change to the bindings of that parameter.
83835 */
@@ -87998,32 +88303,38 @@
87998 assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
87999 REGISTER_TRACE(pOp->p3, pOut);
88000 break;
88001 }
88002
88003 /* Opcode: Count P1 P2 * * *
88004 ** Synopsis: r[P2]=count()
88005 **
88006 ** Store the number of entries (an integer value) in the table or index
88007 ** opened by cursor P1 in register P2
 
 
 
 
88008 */
88009 #ifndef SQLITE_OMIT_BTREECOUNT
88010 case OP_Count: { /* out2 */
88011 i64 nEntry;
88012 BtCursor *pCrsr;
88013
88014 assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
88015 pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
88016 assert( pCrsr );
88017 nEntry = 0; /* Not needed. Only used to silence a warning. */
88018 rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
88019 if( rc ) goto abort_due_to_error;
 
 
 
 
88020 pOut = out2Prerelease(p, pOp);
88021 pOut->u.i = nEntry;
88022 goto check_for_interrupt;
88023 }
88024 #endif
88025
88026 /* Opcode: Savepoint P1 * * P4 *
88027 **
88028 ** Open, release or rollback the savepoint named by parameter P4, depending
88029 ** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN).
@@ -90457,16 +90768,23 @@
90457 rc = sqlite3VdbeSorterWrite(pC, pIn2);
90458 if( rc) goto abort_due_to_error;
90459 break;
90460 }
90461
90462 /* Opcode: IdxDelete P1 P2 P3 * *
90463 ** Synopsis: key=r[P2@P3]
90464 **
90465 ** The content of P3 registers starting at register P2 form
90466 ** an unpacked index key. This opcode removes that entry from the
90467 ** index opened by cursor P1.
 
 
 
 
 
 
 
90468 */
90469 case OP_IdxDelete: {
90470 VdbeCursor *pC;
90471 BtCursor *pCrsr;
90472 int res;
@@ -90479,20 +90797,22 @@
90479 assert( pC!=0 );
90480 assert( pC->eCurType==CURTYPE_BTREE );
90481 sqlite3VdbeIncrWriteCounter(p, pC);
90482 pCrsr = pC->uc.pCursor;
90483 assert( pCrsr!=0 );
90484 assert( pOp->p5==0 );
90485 r.pKeyInfo = pC->pKeyInfo;
90486 r.nField = (u16)pOp->p3;
90487 r.default_rc = 0;
90488 r.aMem = &aMem[pOp->p2];
90489 rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
90490 if( rc ) goto abort_due_to_error;
90491 if( res==0 ){
90492 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
90493 if( rc ) goto abort_due_to_error;
 
 
 
90494 }
90495 assert( pC->deferredMoveto==0 );
90496 pC->cacheStatus = CACHE_STALE;
90497 pC->seekResult = 0;
90498 break;
@@ -96093,10 +96413,437 @@
96093 *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
96094 return SQLITE_OK;
96095 }
96096
96097 /************** End of vdbesort.c ********************************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96098 /************** Begin file memjournal.c **************************************/
96099 /*
96100 ** 2008 October 7
96101 **
96102 ** The author disclaims copyright to this source code. In place of
@@ -96735,10 +97482,47 @@
96735 }
96736 p = p->pPrior;
96737 }while( p!=0 );
96738 return WRC_Continue;
96739 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96740
96741 /************** End of walker.c **********************************************/
96742 /************** Begin file resolve.c *****************************************/
96743 /*
96744 ** 2008 August 18
@@ -96764,10 +97548,12 @@
96764 ** This needs to occur when copying a TK_AGG_FUNCTION node from an
96765 ** outer query into an inner subquery.
96766 **
96767 ** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
96768 ** is a helper function - a callback for the tree walker.
 
 
96769 */
96770 static int incrAggDepth(Walker *pWalker, Expr *pExpr){
96771 if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
96772 return WRC_Continue;
96773 }
@@ -98739,11 +99525,11 @@
98739 ** SELECT * FROM t1 WHERE (select a from t1);
98740 */
98741 SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
98742 int op;
98743 while( ExprHasProperty(pExpr, EP_Skip) ){
98744 assert( pExpr->op==TK_COLLATE );
98745 pExpr = pExpr->pLeft;
98746 assert( pExpr!=0 );
98747 }
98748 op = pExpr->op;
98749 if( op==TK_SELECT ){
@@ -98806,11 +99592,11 @@
98806 /*
98807 ** Skip over any TK_COLLATE operators.
98808 */
98809 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
98810 while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
98811 assert( pExpr->op==TK_COLLATE );
98812 pExpr = pExpr->pLeft;
98813 }
98814 return pExpr;
98815 }
98816
@@ -98825,11 +99611,11 @@
98825 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
98826 assert( pExpr->x.pList->nExpr>0 );
98827 assert( pExpr->op==TK_FUNCTION );
98828 pExpr = pExpr->x.pList->a[0].pExpr;
98829 }else{
98830 assert( pExpr->op==TK_COLLATE );
98831 pExpr = pExpr->pLeft;
98832 }
98833 }
98834 return pExpr;
98835 }
@@ -102394,10 +103180,17 @@
102394 }
102395 setDoNotMergeFlagOnCopy(v);
102396 sqlite3VdbeResolveLabel(v, endCoalesce);
102397 break;
102398 }
 
 
 
 
 
 
 
102399
102400 default: {
102401 /* The UNLIKELY() function is a no-op. The result is the value
102402 ** of the first argument.
102403 */
@@ -102498,11 +103291,14 @@
102498 op = pExpr->op;
102499 }
102500 switch( op ){
102501 case TK_AGG_COLUMN: {
102502 AggInfo *pAggInfo = pExpr->pAggInfo;
102503 struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
 
 
 
102504 if( !pAggInfo->directMode ){
102505 assert( pCol->iMem>0 );
102506 return pCol->iMem;
102507 }else if( pAggInfo->useSortingIdx ){
102508 Table *pTab = pCol->pTab;
@@ -102798,11 +103594,14 @@
102798 sqlite3VdbeJumpHere(v, addr);
102799 break;
102800 }
102801 case TK_AGG_FUNCTION: {
102802 AggInfo *pInfo = pExpr->pAggInfo;
102803 if( pInfo==0 ){
 
 
 
102804 assert( !ExprHasProperty(pExpr, EP_IntValue) );
102805 sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
102806 }else{
102807 return pInfo->aFunc[pExpr->iAgg].iMem;
102808 }
@@ -103176,11 +103975,11 @@
103176 assert( pExpr->affExpr==OE_Rollback
103177 || pExpr->affExpr==OE_Abort
103178 || pExpr->affExpr==OE_Fail
103179 || pExpr->affExpr==OE_Ignore
103180 );
103181 if( !pParse->pTriggerTab ){
103182 sqlite3ErrorMsg(pParse,
103183 "RAISE() may only be used within a trigger-program");
103184 return 0;
103185 }
103186 if( pExpr->affExpr==OE_Abort ){
@@ -103190,12 +103989,13 @@
103190 if( pExpr->affExpr==OE_Ignore ){
103191 sqlite3VdbeAddOp4(
103192 v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
103193 VdbeCoverage(v);
103194 }else{
103195 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
103196 pExpr->affExpr, pExpr->u.zToken, 0, 0);
 
103197 }
103198
103199 break;
103200 }
103201 #endif
@@ -104553,19 +105353,10 @@
104553 }
104554 }
104555 }
104556 return WRC_Continue;
104557 }
104558 static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
104559 UNUSED_PARAMETER(pSelect);
104560 pWalker->walkerDepth++;
104561 return WRC_Continue;
104562 }
104563 static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
104564 UNUSED_PARAMETER(pSelect);
104565 pWalker->walkerDepth--;
104566 }
104567
104568 /*
104569 ** Analyze the pExpr expression looking for aggregate functions and
104570 ** for variables that need to be added to AggInfo object that pNC->pAggInfo
104571 ** points to. Additional entries are made on the AggInfo object as
@@ -104575,12 +105366,12 @@
104575 ** analyzed by sqlite3ResolveExprNames().
104576 */
104577 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
104578 Walker w;
104579 w.xExprCallback = analyzeAggregate;
104580 w.xSelectCallback = analyzeAggregatesInSelect;
104581 w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
104582 w.walkerDepth = 0;
104583 w.u.pNC = pNC;
104584 w.pParse = 0;
104585 assert( pNC->pSrcList!=0 );
104586 sqlite3WalkExpr(&w, pExpr);
@@ -104815,11 +105606,14 @@
104815 if( !zName ) goto exit_rename_table;
104816
104817 /* Check that a table or index named 'zName' does not already exist
104818 ** in database iDb. If so, this is an error.
104819 */
104820 if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
 
 
 
104821 sqlite3ErrorMsg(pParse,
104822 "there is already another table or index with this name: %s", zName);
104823 goto exit_rename_table;
104824 }
104825
@@ -104946,10 +105740,26 @@
104946 exit_rename_table:
104947 sqlite3SrcListDelete(db, pSrc);
104948 sqlite3DbFree(db, zName);
104949 db->mDbFlags = savedDbFlags;
104950 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104951
104952 /*
104953 ** This function is called after an "ALTER TABLE ... ADD" statement
104954 ** has been parsed. Argument pColDef contains the text of the new
104955 ** column definition.
@@ -104999,11 +105809,12 @@
104999 if( pCol->colFlags & COLFLAG_PRIMKEY ){
105000 sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
105001 return;
105002 }
105003 if( pNew->pIndex ){
105004 sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
 
105005 return;
105006 }
105007 if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
105008 /* If the default value for the new column was specified with a
105009 ** literal NULL, then set pDflt to 0. This simplifies checking
@@ -105012,19 +105823,18 @@
105012 assert( pDflt==0 || pDflt->op==TK_SPAN );
105013 if( pDflt && pDflt->pLeft->op==TK_NULL ){
105014 pDflt = 0;
105015 }
105016 if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
105017 sqlite3ErrorMsg(pParse,
105018 "Cannot add a REFERENCES column with non-NULL default value");
105019 return;
105020 }
105021 if( pCol->notNull && !pDflt ){
105022 sqlite3ErrorMsg(pParse,
105023 "Cannot add a NOT NULL column with default value NULL");
105024 return;
105025 }
 
105026
105027 /* Ensure the default expression is something that sqlite3ValueFromExpr()
105028 ** can handle (i.e. not CURRENT_TIME etc.)
105029 */
105030 if( pDflt ){
@@ -105035,18 +105845,17 @@
105035 if( rc!=SQLITE_OK ){
105036 assert( db->mallocFailed == 1 );
105037 return;
105038 }
105039 if( !pVal ){
105040 sqlite3ErrorMsg(pParse,"Cannot add a column with non-constant default");
105041 return;
105042 }
105043 sqlite3ValueFree(pVal);
105044 }
105045 }else if( pCol->colFlags & COLFLAG_STORED ){
105046 sqlite3ErrorMsg(pParse, "cannot add a STORED column");
105047 return;
105048 }
105049
105050
105051 /* Modify the CREATE TABLE statement. */
105052 zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
@@ -106605,10 +107414,15 @@
106605 sqlite3 *db = pParse->db;
106606 Db *pDb;
106607 Vdbe *v = sqlite3GetVdbe(pParse);
106608 int aRoot[ArraySize(aTable)];
106609 u8 aCreateTbl[ArraySize(aTable)];
 
 
 
 
 
106610
106611 if( v==0 ) return;
106612 assert( sqlite3BtreeHoldsAllMutexes(db) );
106613 assert( sqlite3VdbeDb(v)==db );
106614 pDb = &db->aDb[iDb];
@@ -106617,12 +107431,13 @@
106617 ** if they do already exist.
106618 */
106619 for(i=0; i<ArraySize(aTable); i++){
106620 const char *zTab = aTable[i].zName;
106621 Table *pStat;
 
106622 if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
106623 if( aTable[i].zCols ){
106624 /* The sqlite_statN table does not exist. Create it. Note that a
106625 ** side-effect of the CREATE TABLE statement is to leave the rootpage
106626 ** of the new table in register pParse->regRoot. This is important
106627 ** because the OpenWrite opcode below will be needing it. */
106628 sqlite3NestedParse(pParse,
@@ -106634,11 +107449,10 @@
106634 }else{
106635 /* The table already exists. If zWhere is not NULL, delete all entries
106636 ** associated with the table zWhere. If zWhere is NULL, delete the
106637 ** entire contents of the table. */
106638 aRoot[i] = pStat->tnum;
106639 aCreateTbl[i] = 0;
106640 sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
106641 if( zWhere ){
106642 sqlite3NestedParse(pParse,
106643 "DELETE FROM %Q.%s WHERE %s=%Q",
106644 pDb->zDbSName, zTab, zWhereType, zWhere
@@ -106653,11 +107467,11 @@
106653 }
106654 }
106655 }
106656
106657 /* Open the sqlite_stat[134] tables for writing. */
106658 for(i=0; aTable[i].zCols; i++){
106659 assert( i<ArraySize(aTable) );
106660 sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
106661 sqlite3VdbeChangeP5(v, aCreateTbl[i]);
106662 VdbeComment((v, aTable[i].zName));
106663 }
@@ -106692,13 +107506,16 @@
106692 u32 iHash; /* Tiebreaker hash */
106693 #endif
106694 };
106695 struct StatAccum {
106696 sqlite3 *db; /* Database connection, for malloc() */
106697 tRowcnt nRow; /* Number of rows in the entire table */
 
 
106698 int nCol; /* Number of columns in index + pk/rowid */
106699 int nKeyCol; /* Number of index columns w/o the pk/rowid */
 
106700 StatSample current; /* Current row as a StatSample */
106701 #ifdef SQLITE_ENABLE_STAT4
106702 tRowcnt nPSample; /* How often to do a periodic sample */
106703 int mxSample; /* Maximum number of samples to accumulate */
106704 u32 iPrn; /* Pseudo-random number used for sampling */
@@ -106774,31 +107591,32 @@
106774 ** Reclaim all memory of a StatAccum structure.
106775 */
106776 static void statAccumDestructor(void *pOld){
106777 StatAccum *p = (StatAccum*)pOld;
106778 #ifdef SQLITE_ENABLE_STAT4
106779 int i;
106780 for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
106781 for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
106782 sampleClear(p->db, &p->current);
 
 
106783 #endif
106784 sqlite3DbFree(p->db, p);
106785 }
106786
106787 /*
106788 ** Implementation of the stat_init(N,K,C) SQL function. The three parameters
106789 ** are:
106790 ** N: The number of columns in the index including the rowid/pk (note 1)
106791 ** K: The number of columns in the index excluding the rowid/pk.
106792 ** C: The number of rows in the index (note 2)
 
106793 **
106794 ** Note 1: In the special case of the covering index that implements a
106795 ** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
106796 ** total number of columns in the table.
106797 **
106798 ** Note 2: C is only used for STAT4.
106799 **
106800 ** For indexes on ordinary rowid tables, N==K+1. But for indexes on
106801 ** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
106802 ** PRIMARY KEY of the table. The covering index that implements the
106803 ** original WITHOUT ROWID table as N==K as a special case.
106804 **
@@ -106815,13 +107633,14 @@
106815 StatAccum *p;
106816 int nCol; /* Number of columns in index being sampled */
106817 int nKeyCol; /* Number of key columns */
106818 int nColUp; /* nCol rounded up for alignment */
106819 int n; /* Bytes of space to allocate */
106820 sqlite3 *db; /* Database connection */
106821 #ifdef SQLITE_ENABLE_STAT4
106822 int mxSample = SQLITE_STAT4_SAMPLES;
 
106823 #endif
106824
106825 /* Decode the three function arguments */
106826 UNUSED_PARAMETER(argc);
106827 nCol = sqlite3_value_int(argv[0]);
@@ -106832,39 +107651,43 @@
106832 assert( nKeyCol>0 );
106833
106834 /* Allocate the space required for the StatAccum object */
106835 n = sizeof(*p)
106836 + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
106837 + sizeof(tRowcnt)*nColUp /* StatAccum.anDLt */
106838 #ifdef SQLITE_ENABLE_STAT4
106839 + sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
106840 + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
106841 + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
 
 
106842 #endif
106843 ;
106844 db = sqlite3_context_db_handle(context);
106845 p = sqlite3DbMallocZero(db, n);
106846 if( p==0 ){
106847 sqlite3_result_error_nomem(context);
106848 return;
106849 }
106850
106851 p->db = db;
 
106852 p->nRow = 0;
 
106853 p->nCol = nCol;
106854 p->nKeyCol = nKeyCol;
 
106855 p->current.anDLt = (tRowcnt*)&p[1];
106856 p->current.anEq = &p->current.anDLt[nColUp];
106857
106858 #ifdef SQLITE_ENABLE_STAT4
106859 {
 
106860 u8 *pSpace; /* Allocated space not yet assigned */
106861 int i; /* Used to iterate through p->aSample[] */
106862
106863 p->iGet = -1;
106864 p->mxSample = mxSample;
106865 p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
106866 p->current.anLt = &p->current.anEq[nColUp];
106867 p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
106868
106869 /* Set up the StatAccum.a[] and aBest[] arrays */
106870 p->a = (struct StatSample*)&p->current.anLt[nColUp];
@@ -106888,11 +107711,11 @@
106888 ** (given by the 3rd parameter) is never used and can be any positive
106889 ** value. */
106890 sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
106891 }
106892 static const FuncDef statInitFuncdef = {
106893 2+IsStat4, /* nArg */
106894 SQLITE_UTF8, /* funcFlags */
106895 0, /* pUserData */
106896 0, /* pNext */
106897 statInit, /* xSFunc */
106898 0, /* xFinalize */
@@ -107092,14 +107915,17 @@
107092 ** P Pointer to the StatAccum object created by stat_init()
107093 ** C Index of left-most column to differ from previous row
107094 ** R Rowid for the current row. Might be a key record for
107095 ** WITHOUT ROWID tables.
107096 **
107097 ** This SQL function always returns NULL. It's purpose it to accumulate
107098 ** statistical data and/or samples in the StatAccum object about the
107099 ** index being analyzed. The stat_get() SQL function will later be used to
107100 ** extract relevant information for constructing the sqlite_statN tables.
 
 
 
107101 **
107102 ** The R parameter is only used for STAT4
107103 */
107104 static void statPush(
107105 sqlite3_context *context,
@@ -107121,11 +107947,11 @@
107121 /* This is the first call to this function. Do initialization. */
107122 for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
107123 }else{
107124 /* Second and subsequent calls get processed here */
107125 #ifdef SQLITE_ENABLE_STAT4
107126 samplePushPrevious(p, iChng);
107127 #endif
107128
107129 /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
107130 ** to the current row of the index. */
107131 for(i=0; i<iChng; i++){
@@ -107132,30 +107958,29 @@
107132 p->current.anEq[i]++;
107133 }
107134 for(i=iChng; i<p->nCol; i++){
107135 p->current.anDLt[i]++;
107136 #ifdef SQLITE_ENABLE_STAT4
107137 p->current.anLt[i] += p->current.anEq[i];
107138 #endif
107139 p->current.anEq[i] = 1;
107140 }
107141 }
 
107142 p->nRow++;
107143 #ifdef SQLITE_ENABLE_STAT4
107144 if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
107145 sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
107146 }else{
107147 sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
107148 sqlite3_value_blob(argv[2]));
107149 }
107150 p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
107151 #endif
107152
107153 #ifdef SQLITE_ENABLE_STAT4
107154 {
107155 tRowcnt nLt = p->current.anLt[p->nCol-1];
107156
107157 /* Check if this is to be a periodic sample. If so, add it. */
107158 if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
107159 p->current.isPSample = 1;
107160 p->current.iCol = 0;
107161 sampleInsert(p, &p->current, p->nCol-1);
@@ -107167,13 +107992,18 @@
107167 p->current.iCol = i;
107168 if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
107169 sampleCopy(p, &p->aBest[i], &p->current);
107170 }
107171 }
 
 
 
 
 
107172 }
107173 #endif
107174 }
 
107175 static const FuncDef statPushFuncdef = {
107176 2+IsStat4, /* nArg */
107177 SQLITE_UTF8, /* funcFlags */
107178 0, /* pUserData */
107179 0, /* pNext */
@@ -107221,10 +108051,11 @@
107221 assert( argc==2 );
107222 assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
107223 || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
107224 || eCall==STAT_GET_NDLT
107225 );
 
107226 if( eCall==STAT_GET_STAT1 )
107227 #else
107228 assert( argc==1 );
107229 #endif
107230 {
@@ -107256,11 +108087,12 @@
107256 if( zRet==0 ){
107257 sqlite3_result_error_nomem(context);
107258 return;
107259 }
107260
107261 sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
 
107262 z = zRet + sqlite3Strlen30(zRet);
107263 for(i=0; i<p->nKeyCol; i++){
107264 u64 nDistinct = p->current.anDLt[i] + 1;
107265 u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
107266 sqlite3_snprintf(24, z, " %llu", iVal);
@@ -107332,20 +108164,20 @@
107332 0, 0, /* xValue, xInverse */
107333 "stat_get", /* zName */
107334 {0}
107335 };
107336
107337 static void callStatGet(Parse *pParse, int regStat4, int iParam, int regOut){
107338 #ifdef SQLITE_ENABLE_STAT4
107339 sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat4+1);
107340 #elif SQLITE_DEBUG
107341 assert( iParam==STAT_GET_STAT1 );
107342 #else
107343 UNUSED_PARAMETER( iParam );
107344 #endif
107345 assert( regOut!=regStat4 && regOut!=regStat4+1 );
107346 sqlite3VdbeAddFunctionCall(pParse, 0, regStat4, regOut, 1+IsStat4,
107347 &statGetFuncdef, 0);
107348 }
107349
107350 /*
107351 ** Generate code to do an analysis of all indices associated with
@@ -107367,16 +108199,15 @@
107367 int i; /* Loop counter */
107368 int jZeroRows = -1; /* Jump from here if number of rows is zero */
107369 int iDb; /* Index of database containing pTab */
107370 u8 needTableCnt = 1; /* True to count the table */
107371 int regNewRowid = iMem++; /* Rowid for the inserted record */
107372 int regStat4 = iMem++; /* Register to hold StatAccum object */
107373 int regChng = iMem++; /* Index of changed index field */
107374 #ifdef SQLITE_ENABLE_STAT4
107375 int regRowid = iMem++; /* Rowid argument passed to stat_push() */
107376 #endif
107377 int regTemp = iMem++; /* Temporary use register */
 
107378 int regTabname = iMem++; /* Register containing table name */
107379 int regIdxname = iMem++; /* Register containing index name */
107380 int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
107381 int regPrev = iMem; /* MUST BE LAST (see below) */
107382 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -107500,21 +108331,30 @@
107500 /* Invoke the stat_init() function. The arguments are:
107501 **
107502 ** (1) the number of columns in the index including the rowid
107503 ** (or for a WITHOUT ROWID table, the number of PK columns),
107504 ** (2) the number of columns in the key without the rowid/pk
107505 ** (3) the number of rows in the index,
107506 **
107507 **
107508 ** The third argument is only used for STAT4
107509 */
 
 
 
107510 #ifdef SQLITE_ENABLE_STAT4
107511 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
 
 
 
 
107512 #endif
107513 sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
107514 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
107515 sqlite3VdbeAddFunctionCall(pParse, 0, regStat4+1, regStat4, 2+IsStat4,
 
 
 
 
 
107516 &statInitFuncdef, 0);
107517
107518 /* Implementation of the following:
107519 **
107520 ** Rewind csr
@@ -107521,12 +108361,10 @@
107521 ** if eof(csr) goto end_of_scan;
107522 ** regChng = 0
107523 ** goto next_push_0;
107524 **
107525 */
107526 addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
107527 VdbeCoverage(v);
107528 sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
107529 addrNextRow = sqlite3VdbeCurrentAddr(v);
107530
107531 if( nColTest>0 ){
107532 int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
@@ -107555,10 +108393,11 @@
107555 }
107556 for(i=0; i<nColTest; i++){
107557 char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
107558 sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
107559 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
 
107560 aGotoChng[i] =
107561 sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
107562 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
107563 VdbeCoverage(v);
107564 }
@@ -107575,10 +108414,11 @@
107575 */
107576 sqlite3VdbeJumpHere(v, addrNextRow-1);
107577 for(i=0; i<nColTest; i++){
107578 sqlite3VdbeJumpHere(v, aGotoChng[i]);
107579 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
 
107580 }
107581 sqlite3VdbeResolveLabel(v, endDistinctTest);
107582 sqlite3DbFree(db, aGotoChng);
107583 }
107584
@@ -107588,34 +108428,50 @@
107588 ** stat_push(P, regChng, regRowid) // 3rd parameter STAT4 only
107589 ** Next csr
107590 ** if !eof(csr) goto next_row;
107591 */
107592 #ifdef SQLITE_ENABLE_STAT4
107593 assert( regRowid==(regStat4+2) );
107594 if( HasRowid(pTab) ){
107595 sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
107596 }else{
107597 Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
107598 int j, k, regKey;
107599 regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
107600 for(j=0; j<pPk->nKeyCol; j++){
107601 k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
107602 assert( k>=0 && k<pIdx->nColumn );
107603 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
107604 VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
107605 }
107606 sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
107607 sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
 
 
107608 }
107609 #endif
107610 assert( regChng==(regStat4+1) );
107611 sqlite3VdbeAddFunctionCall(pParse, 1, regStat4, regTemp, 2+IsStat4,
107612 &statPushFuncdef, 0);
107613 sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107614
107615 /* Add the entry to the stat1 table. */
107616 callStatGet(pParse, regStat4, STAT_GET_STAT1, regStat1);
107617 assert( "BBB"[0]==SQLITE_AFF_TEXT );
107618 sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
107619 sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
107620 sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
107621 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -107623,11 +108479,11 @@
107623 #endif
107624 sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
107625
107626 /* Add the entries to the stat4 table. */
107627 #ifdef SQLITE_ENABLE_STAT4
107628 {
107629 int regEq = regStat1;
107630 int regLt = regStat1+1;
107631 int regDLt = regStat1+2;
107632 int regSample = regStat1+3;
107633 int regCol = regStat1+4;
@@ -107637,16 +108493,16 @@
107637 u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
107638
107639 pParse->nMem = MAX(pParse->nMem, regCol+nCol);
107640
107641 addrNext = sqlite3VdbeCurrentAddr(v);
107642 callStatGet(pParse, regStat4, STAT_GET_ROWID, regSampleRowid);
107643 addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
107644 VdbeCoverage(v);
107645 callStatGet(pParse, regStat4, STAT_GET_NEQ, regEq);
107646 callStatGet(pParse, regStat4, STAT_GET_NLT, regLt);
107647 callStatGet(pParse, regStat4, STAT_GET_NDLT, regDLt);
107648 sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
107649 VdbeCoverage(v);
107650 for(i=0; i<nCol; i++){
107651 sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
107652 }
@@ -109500,26 +110356,43 @@
109500 ** exists */
109501 if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
109502 return 0;
109503 }
109504 #endif
109505 while(1){
109506 for(i=OMIT_TEMPDB; i<db->nDb; i++){
109507 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
109508 if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
109509 assert( sqlite3SchemaMutexHeld(db, j, 0) );
109510 p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
109511 if( p ) return p;
109512 }
109513 }
109514 /* Not found. If the name we were looking for was temp.sqlite_master
109515 ** then change the name to sqlite_temp_master and try again. */
109516 if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
109517 if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
109518 zName = TEMP_MASTER_NAME;
109519 }
109520 return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109521 }
109522
109523 /*
109524 ** Locate the in-memory structure that describes a particular database
109525 ** table given the name of that table and (optionally) the name of the
@@ -111319,10 +112192,32 @@
111319 assert( pPk->nColumn==j );
111320 assert( pTab->nNVCol<=j );
111321 recomputeColumnsNotIndexed(pPk);
111322 }
111323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111324 #ifndef SQLITE_OMIT_VIRTUALTABLE
111325 /*
111326 ** Return true if zName is a shadow table name in the current database
111327 ** connection.
111328 **
@@ -111330,26 +112225,21 @@
111330 ** restored to its original value prior to this routine returning.
111331 */
111332 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
111333 char *zTail; /* Pointer to the last "_" in zName */
111334 Table *pTab; /* Table that zName is a shadow of */
111335 Module *pMod; /* Module for the virtual table */
111336
111337 zTail = strrchr(zName, '_');
111338 if( zTail==0 ) return 0;
111339 *zTail = 0;
111340 pTab = sqlite3FindTable(db, zName, 0);
111341 *zTail = '_';
111342 if( pTab==0 ) return 0;
111343 if( !IsVirtual(pTab) ) return 0;
111344 pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
111345 if( pMod==0 ) return 0;
111346 if( pMod->pModule->iVersion<3 ) return 0;
111347 if( pMod->pModule->xShadowName==0 ) return 0;
111348 return pMod->pModule->xShadowName(zTail+1);
111349 }
111350 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
 
111351
111352 #ifdef SQLITE_DEBUG
111353 /*
111354 ** Mark all nodes of an expression as EP_Immutable, indicating that
111355 ** they should not be changed. Expressions attached to a table or
@@ -113818,11 +114708,11 @@
113818 pParse->rc = rc;
113819 return 1;
113820 }
113821 db->aDb[1].pBt = pBt;
113822 assert( db->aDb[1].pSchema );
113823 if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
113824 sqlite3OomFault(db);
113825 return 1;
113826 }
113827 }
113828 return 0;
@@ -113929,11 +114819,11 @@
113929 char *p4, /* Error message */
113930 i8 p4type, /* P4_STATIC or P4_TRANSIENT */
113931 u8 p5Errmsg /* P5_ErrMsg type */
113932 ){
113933 Vdbe *v = sqlite3GetVdbe(pParse);
113934 assert( (errCode&0xff)==SQLITE_CONSTRAINT );
113935 if( onError==OE_Abort ){
113936 sqlite3MayAbort(pParse);
113937 }
113938 sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
113939 sqlite3VdbeChangeP5(v, p5Errmsg);
@@ -115642,10 +116532,11 @@
115642 VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
115643 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
115644 &iPartIdxLabel, pPrior, r1);
115645 sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
115646 pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
 
115647 sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
115648 pPrior = pIdx;
115649 }
115650 }
115651
@@ -117035,11 +117926,11 @@
117035 if( (cntExpand&(cntExpand-1))==0 ){
117036 /* Grow the size of the output buffer only on substitutions
117037 ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
117038 u8 *zOld;
117039 zOld = zOut;
117040 zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
117041 if( zOut==0 ){
117042 sqlite3_result_error_nomem(context);
117043 sqlite3_free(zOld);
117044 return;
117045 }
@@ -117732,11 +118623,11 @@
117732 FUNCTION(round, 2, 0, 0, roundFunc ),
117733 #endif
117734 FUNCTION(upper, 1, 0, 0, upperFunc ),
117735 FUNCTION(lower, 1, 0, 0, lowerFunc ),
117736 FUNCTION(hex, 1, 0, 0, hexFunc ),
117737 INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
117738 VFUNCTION(random, 0, 0, 0, randomFunc ),
117739 VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
117740 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
117741 DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
117742 DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -117772,11 +118663,12 @@
117772 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
117773 FUNCTION(unknown, -1, 0, 0, unknownFunc ),
117774 #endif
117775 FUNCTION(coalesce, 1, 0, 0, 0 ),
117776 FUNCTION(coalesce, 0, 0, 0, 0 ),
117777 INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
 
117778 };
117779 #ifndef SQLITE_OMIT_ALTERTABLE
117780 sqlite3AlterFunctions();
117781 #endif
117782 sqlite3WindowFunctions();
@@ -121197,11 +122089,11 @@
121197 }
121198 if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
121199 sqlite3TableAffinity(v, pTab, regNewData+1);
121200 bAffinityDone = 1;
121201 }
121202 VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
121203 iThisCur = iIdxCur+ix;
121204
121205
121206 /* Skip partial indices for which the WHERE clause is not true */
121207 if( pIdx->pPartIdxWhere ){
@@ -122629,10 +123521,11 @@
122629 const char *(*filename_wal)(const char*);
122630 /* Version 3.32.0 and later */
122631 char *(*create_filename)(const char*,const char*,const char*,
122632 int,const char**);
122633 void (*free_filename)(char*);
 
122634 };
122635
122636 /*
122637 ** This is the function signature used for all extension entry points. It
122638 ** is also defined in the file "loadext.c".
@@ -122932,10 +123825,11 @@
122932 #define sqlite3_filename_journal sqlite3_api->filename_journal
122933 #define sqlite3_filename_wal sqlite3_api->filename_wal
122934 /* Version 3.32.0 and later */
122935 #define sqlite3_create_filename sqlite3_api->create_filename
122936 #define sqlite3_free_filename sqlite3_api->free_filename
 
122937 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
122938
122939 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
122940 /* This case when the file really is being compiled as a loadable
122941 ** extension */
@@ -123413,11 +124307,20 @@
123413 sqlite3_filename_journal,
123414 sqlite3_filename_wal,
123415 /* Version 3.32.0 and later */
123416 sqlite3_create_filename,
123417 sqlite3_free_filename,
 
123418 };
 
 
 
 
 
 
 
 
123419
123420 /*
123421 ** Attempt to load an SQLite extension library contained in the file
123422 ** zFile. The entry point is zProc. zProc may be 0 in which case a
123423 ** default entry point name (sqlite3_extension_init) is used. Use
@@ -123516,11 +124419,11 @@
123516 if( zAltEntry==0 ){
123517 sqlite3OsDlClose(pVfs, handle);
123518 return SQLITE_NOMEM_BKPT;
123519 }
123520 memcpy(zAltEntry, "sqlite3_", 8);
123521 for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
123522 iFile++;
123523 if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
123524 for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
123525 if( sqlite3Isalpha(c) ){
123526 zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
@@ -123820,53 +124723,54 @@
123820 ** that script and rerun it.
123821 */
123822
123823 /* The various pragma types */
123824 #define PragTyp_ACTIVATE_EXTENSIONS 0
123825 #define PragTyp_HEADER_VALUE 1
123826 #define PragTyp_AUTO_VACUUM 2
123827 #define PragTyp_FLAG 3
123828 #define PragTyp_BUSY_TIMEOUT 4
123829 #define PragTyp_CACHE_SIZE 5
123830 #define PragTyp_CACHE_SPILL 6
123831 #define PragTyp_CASE_SENSITIVE_LIKE 7
123832 #define PragTyp_COLLATION_LIST 8
123833 #define PragTyp_COMPILE_OPTIONS 9
123834 #define PragTyp_DATA_STORE_DIRECTORY 10
123835 #define PragTyp_DATABASE_LIST 11
123836 #define PragTyp_DEFAULT_CACHE_SIZE 12
123837 #define PragTyp_ENCODING 13
123838 #define PragTyp_FOREIGN_KEY_CHECK 14
123839 #define PragTyp_FOREIGN_KEY_LIST 15
123840 #define PragTyp_FUNCTION_LIST 16
123841 #define PragTyp_HARD_HEAP_LIMIT 17
123842 #define PragTyp_INCREMENTAL_VACUUM 18
123843 #define PragTyp_INDEX_INFO 19
123844 #define PragTyp_INDEX_LIST 20
123845 #define PragTyp_INTEGRITY_CHECK 21
123846 #define PragTyp_JOURNAL_MODE 22
123847 #define PragTyp_JOURNAL_SIZE_LIMIT 23
123848 #define PragTyp_LOCK_PROXY_FILE 24
123849 #define PragTyp_LOCKING_MODE 25
123850 #define PragTyp_PAGE_COUNT 26
123851 #define PragTyp_MMAP_SIZE 27
123852 #define PragTyp_MODULE_LIST 28
123853 #define PragTyp_OPTIMIZE 29
123854 #define PragTyp_PAGE_SIZE 30
123855 #define PragTyp_PRAGMA_LIST 31
123856 #define PragTyp_SECURE_DELETE 32
123857 #define PragTyp_SHRINK_MEMORY 33
123858 #define PragTyp_SOFT_HEAP_LIMIT 34
123859 #define PragTyp_SYNCHRONOUS 35
123860 #define PragTyp_TABLE_INFO 36
123861 #define PragTyp_TEMP_STORE 37
123862 #define PragTyp_TEMP_STORE_DIRECTORY 38
123863 #define PragTyp_THREADS 39
123864 #define PragTyp_WAL_AUTOCHECKPOINT 40
123865 #define PragTyp_WAL_CHECKPOINT 41
123866 #define PragTyp_LOCK_STATUS 42
123867 #define PragTyp_STATS 43
 
123868
123869 /* Property flags associated with various pragma. */
123870 #define PragFlg_NeedSchema 0x01 /* Force schema load before running */
123871 #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
123872 #define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
@@ -123953,10 +124857,15 @@
123953 /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
123954 /* ePragFlg: */ 0,
123955 /* ColNames: */ 0, 0,
123956 /* iArg: */ 0 },
123957 #endif
 
 
 
 
 
123958 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
123959 {/* zName: */ "application_id",
123960 /* ePragTyp: */ PragTyp_HEADER_VALUE,
123961 /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
123962 /* ColNames: */ 0, 0,
@@ -124453,11 +125362,11 @@
124453 /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
124454 /* ColNames: */ 0, 0,
124455 /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
124456 #endif
124457 };
124458 /* Number of pragmas: 66 on by default, 76 total. */
124459
124460 /************** End of pragma.h **********************************************/
124461 /************** Continuing where we left off in pragma.c *********************/
124462
124463 /*
@@ -124983,11 +125892,11 @@
124983 }else{
124984 /* Malloc may fail when setting the page-size, as there is an internal
124985 ** buffer that the pager module resizes using sqlite3_realloc().
124986 */
124987 db->nextPagesize = sqlite3Atoi(zRight);
124988 if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
124989 sqlite3OomFault(db);
124990 }
124991 }
124992 break;
124993 }
@@ -126157,11 +127066,10 @@
126157 sqlite3ResolvePartIdxLabel(pParse, jmp3);
126158 }
126159 }
126160 sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
126161 sqlite3VdbeJumpHere(v, loopTop-1);
126162 #ifndef SQLITE_OMIT_BTREECOUNT
126163 if( !isQuick ){
126164 sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
126165 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
126166 if( pPk==pIdx ) continue;
126167 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
@@ -126171,11 +127079,10 @@
126171 sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
126172 integrityCheckResultRow(v);
126173 sqlite3VdbeJumpHere(v, addr);
126174 }
126175 }
126176 #endif /* SQLITE_OMIT_BTREECOUNT */
126177 }
126178 }
126179 {
126180 static const int iLn = VDBE_OFFSET_LINENO(2);
126181 static const VdbeOpList endCode[] = {
@@ -126605,10 +127512,29 @@
126605 sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
126606 }
126607 returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
126608 break;
126609 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126610
126611 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
126612 /*
126613 ** Report the current state of file logs for all databases
126614 */
@@ -131404,10 +132330,11 @@
131404 if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
131405 memset(&ifNullRow, 0, sizeof(ifNullRow));
131406 ifNullRow.op = TK_IF_NULL_ROW;
131407 ifNullRow.pLeft = pCopy;
131408 ifNullRow.iTable = pSubst->iNewTable;
 
131409 pCopy = &ifNullRow;
131410 }
131411 testcase( ExprHasProperty(pCopy, EP_Subquery) );
131412 pNew = sqlite3ExprDup(db, pCopy, 0);
131413 if( pNew && pSubst->isLeftJoin ){
@@ -133134,33 +134061,10 @@
133134 }
133135 }
133136 return WRC_Continue;
133137 }
133138
133139 /*
133140 ** No-op routine for the parse-tree walker.
133141 **
133142 ** When this routine is the Walker.xExprCallback then expression trees
133143 ** are walked without any actions being taken at each node. Presumably,
133144 ** when this routine is used for Walker.xExprCallback then
133145 ** Walker.xSelectCallback is set to do something useful for every
133146 ** subquery in the parser tree.
133147 */
133148 SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
133149 UNUSED_PARAMETER2(NotUsed, NotUsed2);
133150 return WRC_Continue;
133151 }
133152
133153 /*
133154 ** No-op routine for the parse-tree walker for SELECT statements.
133155 ** subquery in the parser tree.
133156 */
133157 SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
133158 UNUSED_PARAMETER2(NotUsed, NotUsed2);
133159 return WRC_Continue;
133160 }
133161
133162 #if SQLITE_DEBUG
133163 /*
133164 ** Always assert. This xSelectCallback2 implementation proves that the
133165 ** xSelectCallback2 is never invoked.
133166 */
@@ -134327,11 +135231,11 @@
134327 sAggInfo.mxReg = pParse->nMem;
134328 if( db->mallocFailed ) goto select_end;
134329 #if SELECTTRACE_ENABLED
134330 if( sqlite3SelectTrace & 0x400 ){
134331 int ii;
134332 SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
134333 sqlite3TreeViewSelect(0, p, 0);
134334 for(ii=0; ii<sAggInfo.nColumn; ii++){
134335 sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
134336 ii, sAggInfo.aCol[ii].iMem);
134337 sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
@@ -134568,11 +135472,10 @@
134568 VdbeComment((v, "indicate accumulator empty"));
134569 sqlite3VdbeAddOp1(v, OP_Return, regReset);
134570
134571 } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
134572 else {
134573 #ifndef SQLITE_OMIT_BTREECOUNT
134574 Table *pTab;
134575 if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
134576 /* If isSimpleCount() returns a pointer to a Table structure, then
134577 ** the SQL statement is of the form:
134578 **
@@ -134604,17 +135507,19 @@
134604 **
134605 ** In practice the KeyInfo structure will not be used. It is only
134606 ** passed to keep OP_OpenRead happy.
134607 */
134608 if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
134609 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
134610 if( pIdx->bUnordered==0
134611 && pIdx->szIdxRow<pTab->szTabRow
134612 && pIdx->pPartIdxWhere==0
134613 && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
134614 ){
134615 pBest = pIdx;
 
 
134616 }
134617 }
134618 if( pBest ){
134619 iRoot = pBest->tnum;
134620 pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
@@ -134626,13 +135531,11 @@
134626 sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
134627 }
134628 sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
134629 sqlite3VdbeAddOp1(v, OP_Close, iCsr);
134630 explainSimpleCount(pParse, pTab, pBest);
134631 }else
134632 #endif /* SQLITE_OMIT_BTREECOUNT */
134633 {
134634 int regAcc = 0; /* "populate accumulators" flag */
134635
134636 /* If there are accumulator registers but no min() or max() functions
134637 ** without FILTER clauses, allocate register regAcc. Register regAcc
134638 ** will contain 0 the first time the inner loop runs, and 1 thereafter.
@@ -134791,11 +135694,11 @@
134791 need = nCol;
134792 }
134793 if( p->nData + need > p->nAlloc ){
134794 char **azNew;
134795 p->nAlloc = p->nAlloc*2 + need;
134796 azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
134797 if( azNew==0 ) goto malloc_failed;
134798 p->azResult = azNew;
134799 }
134800
134801 /* If this is the first row, then generate an extra row containing
@@ -134900,11 +135803,11 @@
134900 sqlite3_free_table(&res.azResult[1]);
134901 return rc;
134902 }
134903 if( res.nAlloc>res.nData ){
134904 char **azNew;
134905 azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
134906 if( azNew==0 ){
134907 sqlite3_free_table(&res.azResult[1]);
134908 db->errCode = SQLITE_NOMEM;
134909 return SQLITE_NOMEM_BKPT;
134910 }
@@ -136190,14 +137093,14 @@
136190 ** Therefore, the P4 parameter is only required if the default value for
136191 ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
136192 ** function is capable of transforming these types of expressions into
136193 ** sqlite3_value objects.
136194 **
136195 ** If parameter iReg is not negative, code an OP_RealAffinity instruction
136196 ** on register iReg. This is used when an equivalent integer value is
136197 ** stored in place of an 8-byte floating point value in order to save
136198 ** space.
136199 */
136200 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
136201 assert( pTab!=0 );
136202 if( !pTab->pSelect ){
136203 sqlite3_value *pValue = 0;
@@ -136210,11 +137113,11 @@
136210 if( pValue ){
136211 sqlite3VdbeAppendP4(v, pValue, P4_MEM);
136212 }
136213 }
136214 #ifndef SQLITE_OMIT_FLOATING_POINT
136215 if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
136216 sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
136217 }
136218 #endif
136219 }
136220
@@ -137852,11 +138755,11 @@
137852 db->mDbFlags = saved_mDbFlags;
137853 db->flags = saved_flags;
137854 db->nChange = saved_nChange;
137855 db->nTotalChange = saved_nTotalChange;
137856 db->mTrace = saved_mTrace;
137857 sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
137858
137859 /* Currently there is an SQL level transaction open on the vacuum
137860 ** database. No locks are held on any other files (since the main file
137861 ** was committed at the btree level). So it safe to end the transaction
137862 ** by manually setting the autoCommit flag to true and detaching the
@@ -139059,11 +139962,11 @@
139059 assert( IsVirtual(pTab) );
139060 for(i=0; i<pToplevel->nVtabLock; i++){
139061 if( pTab==pToplevel->apVtabLock[i] ) return;
139062 }
139063 n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
139064 apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
139065 if( apVtabLock ){
139066 pToplevel->apVtabLock = apVtabLock;
139067 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
139068 }else{
139069 sqlite3OomFault(pToplevel->db);
@@ -150351,24 +151254,47 @@
150351 ){
150352 if( pAppend ){
150353 int i;
150354 int nInit = pList ? pList->nExpr : 0;
150355 for(i=0; i<pAppend->nExpr; i++){
150356 int iDummy;
150357 Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
150358 assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
150359 if( bIntToNull && pDup && sqlite3ExprIsInteger(pDup, &iDummy) ){
150360 pDup->op = TK_NULL;
150361 pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
150362 pDup->u.zToken = 0;
 
 
 
 
 
 
 
150363 }
150364 pList = sqlite3ExprListAppend(pParse, pList, pDup);
150365 if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
150366 }
150367 }
150368 return pList;
150369 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150370
150371 /*
150372 ** If the SELECT statement passed as the second argument does not invoke
150373 ** any SQL window functions, this function is a no-op. Otherwise, it
150374 ** rewrites the SELECT statement so that window function xStep functions
@@ -150475,10 +151401,11 @@
150475 pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
150476 );
150477 p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
150478 if( p->pSrc ){
150479 Table *pTab2;
 
150480 p->pSrc->a[0].pSelect = pSub;
150481 sqlite3SrcListAssignCursors(pParse, p->pSrc);
150482 pSub->selFlags |= SF_Expanded;
150483 pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
150484 pSub->selFlags |= (selFlags & SF_Aggregate);
@@ -150490,10 +151417,15 @@
150490 }else{
150491 memcpy(pTab, pTab2, sizeof(Table));
150492 pTab->tabFlags |= TF_Ephemeral;
150493 p->pSrc->a[0].pTab = pTab;
150494 pTab = pTab2;
 
 
 
 
 
150495 }
150496 }else{
150497 sqlite3SelectDelete(db, pSub);
150498 }
150499 if( db->mallocFailed ) rc = SQLITE_NOMEM;
@@ -159255,19 +160187,82 @@
159255
159256
159257 /************** End of sqliteicu.h *******************************************/
159258 /************** Continuing where we left off in main.c ***********************/
159259 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159260 #ifdef SQLITE_ENABLE_JSON1
159261 SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*);
159262 #endif
159263 #ifdef SQLITE_ENABLE_STMTVTAB
159264 SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*);
159265 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159266 #ifdef SQLITE_ENABLE_FTS5
159267 SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
159268 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159269
159270 #ifndef SQLITE_AMALGAMATION
159271 /* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
159272 ** contains the text of SQLITE_VERSION macro.
159273 */
@@ -159480,10 +160475,11 @@
159480 }
159481 #endif
159482 if( rc==SQLITE_OK ){
159483 sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
159484 sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
 
159485 sqlite3GlobalConfig.isInit = 1;
159486 #ifdef SQLITE_EXTRA_INIT
159487 bRunExtraInit = 1;
159488 #endif
159489 }
@@ -160781,12 +161777,11 @@
160781 ** Return non-zero to retry the lock. Return zero to stop trying
160782 ** and cause SQLite to return SQLITE_BUSY.
160783 */
160784 static int sqliteDefaultBusyCallback(
160785 void *ptr, /* Database connection */
160786 int count, /* Number of times table has been busy */
160787 sqlite3_file *pFile /* The file on which the lock occurred */
160788 ){
160789 #if SQLITE_OS_WIN || HAVE_USLEEP
160790 /* This case is for systems that have support for sleeping for fractions of
160791 ** a second. Examples: All windows systems, unix systems with usleep() */
160792 static const u8 delays[] =
@@ -160796,35 +161791,10 @@
160796 # define NDELAY ArraySize(delays)
160797 sqlite3 *db = (sqlite3 *)ptr;
160798 int tmout = db->busyTimeout;
160799 int delay, prior;
160800
160801 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
160802 if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
160803 if( count ){
160804 /* If this is the second or later invocation of the busy-handler,
160805 ** but tmout==0, then code in wal.c must have disabled the blocking
160806 ** lock before the SQLITE_BUSY error was hit. In this case, no delay
160807 ** occurred while waiting for the lock, so fall through to the xSleep()
160808 ** code below to delay a while before retrying the lock.
160809 **
160810 ** Alternatively, if tmout!=0, then SQLite has already waited
160811 ** sqlite3.busyTimeout ms for a lock. In this case, return 0 to
160812 ** indicate that the lock should not be retried and the SQLITE_BUSY
160813 ** error returned to the application. */
160814 if( tmout ){
160815 tmout = 0;
160816 sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
160817 return 0;
160818 }
160819 }else{
160820 return 1;
160821 }
160822 }
160823 #else
160824 UNUSED_PARAMETER(pFile);
160825 #endif
160826 assert( count>=0 );
160827 if( count < NDELAY ){
160828 delay = delays[count];
160829 prior = totals[count];
160830 }else{
@@ -160840,11 +161810,10 @@
160840 #else
160841 /* This case for unix systems that lack usleep() support. Sleeping
160842 ** must be done in increments of whole seconds */
160843 sqlite3 *db = (sqlite3 *)ptr;
160844 int tmout = ((sqlite3 *)ptr)->busyTimeout;
160845 UNUSED_PARAMETER(pFile);
160846 if( (count+1)*1000 > tmout ){
160847 return 0;
160848 }
160849 sqlite3OsSleep(db->pVfs, 1000000);
160850 return 1;
@@ -160858,23 +161827,14 @@
160858 ** lock on VFS file pFile.
160859 **
160860 ** If this routine returns non-zero, the lock is retried. If it
160861 ** returns 0, the operation aborts with an SQLITE_BUSY error.
160862 */
160863 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
160864 int rc;
160865 if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
160866 if( p->bExtraFileArg ){
160867 /* Add an extra parameter with the pFile pointer to the end of the
160868 ** callback argument list */
160869 int (*xTra)(void*,int,sqlite3_file*);
160870 xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
160871 rc = xTra(p->pBusyArg, p->nBusy, pFile);
160872 }else{
160873 /* Legacy style busy handler callback */
160874 rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
160875 }
160876 if( rc==0 ){
160877 p->nBusy = -1;
160878 }else{
160879 p->nBusy++;
160880 }
@@ -160895,11 +161855,10 @@
160895 #endif
160896 sqlite3_mutex_enter(db->mutex);
160897 db->busyHandler.xBusyHandler = xBusy;
160898 db->busyHandler.pBusyArg = pArg;
160899 db->busyHandler.nBusy = 0;
160900 db->busyHandler.bExtraFileArg = 0;
160901 db->busyTimeout = 0;
160902 sqlite3_mutex_leave(db->mutex);
160903 return SQLITE_OK;
160904 }
160905
@@ -160946,11 +161905,10 @@
160946 #endif
160947 if( ms>0 ){
160948 sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
160949 (void*)db);
160950 db->busyTimeout = ms;
160951 db->busyHandler.bExtraFileArg = 1;
160952 }else{
160953 sqlite3_busy_handler(db, 0, 0);
160954 }
160955 return SQLITE_OK;
160956 }
@@ -162272,10 +163230,11 @@
162272 sqlite3 *db; /* Store allocated handle here */
162273 int rc; /* Return code */
162274 int isThreadsafe; /* True for threadsafe connections */
162275 char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
162276 char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
 
162277
162278 #ifdef SQLITE_ENABLE_API_ARMOR
162279 if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
162280 #endif
162281 *ppDb = 0;
@@ -162420,10 +163379,13 @@
162420 | SQLITE_EnableQPSG
162421 #endif
162422 #if defined(SQLITE_DEFAULT_DEFENSIVE)
162423 | SQLITE_Defensive
162424 #endif
 
 
 
162425 ;
162426 sqlite3HashInit(&db->aCollSeq);
162427 #ifndef SQLITE_OMIT_VIRTUALTABLE
162428 sqlite3HashInit(&db->aModule);
162429 #endif
@@ -162462,11 +163424,11 @@
162462 assert( SQLITE_OPEN_CREATE == 0x04 );
162463 testcase( (1<<(flags&7))==0x02 ); /* READONLY */
162464 testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
162465 testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
162466 if( ((1<<(flags&7)) & 0x46)==0 ){
162467 rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
162468 }else{
162469 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
162470 }
162471 if( rc!=SQLITE_OK ){
162472 if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
@@ -162512,18 +163474,15 @@
162512 */
162513 sqlite3Error(db, SQLITE_OK);
162514 sqlite3RegisterPerConnectionBuiltinFunctions(db);
162515 rc = sqlite3_errcode(db);
162516
162517 #ifdef SQLITE_ENABLE_FTS5
162518 /* Register any built-in FTS5 module before loading the automatic
162519 ** extensions. This allows automatic extensions to register FTS5
162520 ** tokenizers and auxiliary functions. */
162521 if( !db->mallocFailed && rc==SQLITE_OK ){
162522 rc = sqlite3Fts5Init(db);
162523 }
162524 #endif
162525
162526 /* Load automatic extensions - extensions that have been registered
162527 ** using the sqlite3_automatic_extension() API.
162528 */
162529 if( rc==SQLITE_OK ){
@@ -162532,66 +163491,10 @@
162532 if( rc!=SQLITE_OK ){
162533 goto opendb_out;
162534 }
162535 }
162536
162537 #ifdef SQLITE_ENABLE_FTS1
162538 if( !db->mallocFailed ){
162539 extern int sqlite3Fts1Init(sqlite3*);
162540 rc = sqlite3Fts1Init(db);
162541 }
162542 #endif
162543
162544 #ifdef SQLITE_ENABLE_FTS2
162545 if( !db->mallocFailed && rc==SQLITE_OK ){
162546 extern int sqlite3Fts2Init(sqlite3*);
162547 rc = sqlite3Fts2Init(db);
162548 }
162549 #endif
162550
162551 #ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
162552 if( !db->mallocFailed && rc==SQLITE_OK ){
162553 rc = sqlite3Fts3Init(db);
162554 }
162555 #endif
162556
162557 #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
162558 if( !db->mallocFailed && rc==SQLITE_OK ){
162559 rc = sqlite3IcuInit(db);
162560 }
162561 #endif
162562
162563 #ifdef SQLITE_ENABLE_RTREE
162564 if( !db->mallocFailed && rc==SQLITE_OK){
162565 rc = sqlite3RtreeInit(db);
162566 }
162567 #endif
162568
162569 #ifdef SQLITE_ENABLE_DBPAGE_VTAB
162570 if( !db->mallocFailed && rc==SQLITE_OK){
162571 rc = sqlite3DbpageRegister(db);
162572 }
162573 #endif
162574
162575 #ifdef SQLITE_ENABLE_DBSTAT_VTAB
162576 if( !db->mallocFailed && rc==SQLITE_OK){
162577 rc = sqlite3DbstatRegister(db);
162578 }
162579 #endif
162580
162581 #ifdef SQLITE_ENABLE_JSON1
162582 if( !db->mallocFailed && rc==SQLITE_OK){
162583 rc = sqlite3Json1Init(db);
162584 }
162585 #endif
162586
162587 #ifdef SQLITE_ENABLE_STMTVTAB
162588 if( !db->mallocFailed && rc==SQLITE_OK){
162589 rc = sqlite3StmtVtabInit(db);
162590 }
162591 #endif
162592
162593 #ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
162594 /* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
162595 ** option gives access to internal functions by default.
162596 ** Testing use only!!! */
162597 db->mDbFlags |= DBFLAG_InternalFunc;
@@ -163076,11 +163979,11 @@
163076 *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
163077 rc = SQLITE_OK;
163078 }else if( op==SQLITE_FCNTL_RESERVE_BYTES ){
163079 int iNew = *(int*)pArg;
163080 *(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree);
163081 if( iNew>=0 && iNew<=254 ){
163082 sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
163083 }
163084 rc = SQLITE_OK;
163085 }else{
163086 rc = sqlite3OsFileControl(fd, op, pArg);
@@ -165357,10 +166260,11 @@
165357 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
165358 SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
165359 SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
165360 SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
165361 SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
 
165362
165363 /* fts3_tokenizer.c */
165364 SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
165365 SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
165366 SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -166088,10 +166992,26 @@
166088 fts3Appendf(pRc, &zRet, ", ?");
166089 }
166090 sqlite3_free(zFree);
166091 return zRet;
166092 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166093
166094 /*
166095 ** This function interprets the string at (*pp) as a non-negative integer
166096 ** value. It reads the integer and sets *pnOut to the value read, then
166097 ** sets *pp to point to the byte immediately following the last byte of
@@ -166104,23 +167024,21 @@
166104 **
166105 ** This function is used when parsing the "prefix=" FTS4 parameter.
166106 */
166107 static int fts3GobbleInt(const char **pp, int *pnOut){
166108 const int MAX_NPREFIX = 10000000;
166109 const char *p; /* Iterator pointer */
166110 int nInt = 0; /* Output value */
166111
166112 for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
166113 nInt = nInt * 10 + (p[0] - '0');
166114 if( nInt>MAX_NPREFIX ){
166115 nInt = 0;
166116 break;
166117 }
166118 }
166119 if( p==*pp ) return SQLITE_ERROR;
166120 *pnOut = nInt;
166121 *pp = p;
166122 return SQLITE_OK;
166123 }
166124
166125 /*
166126 ** This function is called to allocate an array of Fts3Index structures
@@ -167298,11 +168216,13 @@
167298 static void fts3ReadNextPos(
167299 char **pp, /* IN/OUT: Pointer into position-list buffer */
167300 sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
167301 ){
167302 if( (**pp)&0xFE ){
167303 fts3GetDeltaVarint(pp, pi);
 
 
167304 *pi -= 2;
167305 }else{
167306 *pi = POSITION_LIST_END;
167307 }
167308 }
@@ -170428,10 +171348,11 @@
170428 while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
170429 memset(pDl->pList, 0, pDl->nList);
170430 fts3EvalNextRow(pCsr, pLeft, pRc);
170431 }
170432 }
 
170433 }
170434 }
170435 break;
170436 }
170437
@@ -172198,14 +173119,11 @@
172198
172199 /* If this is a "NEAR" keyword, check for an explicit nearness. */
172200 if( pKey->eType==FTSQUERY_NEAR ){
172201 assert( nKey==4 );
172202 if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
172203 nNear = 0;
172204 for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
172205 nNear = nNear * 10 + (zInput[nKey] - '0');
172206 }
172207 }
172208 }
172209
172210 /* At this point this is probably a keyword. But for that to be true,
172211 ** the next byte must contain either whitespace, an open or close
@@ -178384,25 +179302,25 @@
178384 ){
178385 const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
178386 if( zText ){
178387 int i;
178388 int iMul = 1;
178389 i64 iVal = 0;
178390 for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
178391 iVal = iVal*10 + (zText[i] - '0');
178392 }
178393 *piEndBlock = iVal;
178394 while( zText[i]==' ' ) i++;
178395 iVal = 0;
178396 if( zText[i]=='-' ){
178397 i++;
178398 iMul = -1;
178399 }
178400 for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
178401 iVal = iVal*10 + (zText[i] - '0');
178402 }
178403 *pnByte = (iVal * (i64)iMul);
178404 }
178405 }
178406
178407
178408 /*
@@ -181976,11 +182894,11 @@
181976 iStart = pExpr->iPhrase * p->nCol;
181977 }else{
181978 iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
181979 }
181980
181981 while( 1 ){
181982 int nHit = fts3ColumnlistCount(&pIter);
181983 if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
181984 if( p->flag==FTS3_MATCHINFO_LHITS ){
181985 p->aMatchinfo[iStart + iCol] = (u32)nHit;
181986 }else if( nHit ){
@@ -183890,10 +184808,11 @@
183890 }
183891
183892 /* Append N bytes from zIn onto the end of the JsonString string.
183893 */
183894 static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
 
183895 if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
183896 memcpy(p->zBuf+p->nUsed, zIn, N);
183897 p->nUsed += N;
183898 }
183899
@@ -223901,11 +224820,11 @@
223901 int nArg, /* Number of args */
223902 sqlite3_value **apUnused /* Function arguments */
223903 ){
223904 assert( nArg==0 );
223905 UNUSED_PARAM2(nArg, apUnused);
223906 sqlite3_result_text(pCtx, "fts5: 2020-03-03 20:04:29 bd94d7d052734460904c687756231f8aa243a2252f07f742dd1e437aa940f536", -1, SQLITE_TRANSIENT);
223907 }
223908
223909 /*
223910 ** Return true if zName is the extension on one of the shadow tables used
223911 ** by this module.
@@ -228552,11 +229471,12 @@
228552 }
228553 case STMT_COLUMN_BUSY: {
228554 sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
228555 break;
228556 }
228557 case STMT_COLUMN_MEM: {
 
228558 i = SQLITE_STMTSTATUS_MEMUSED +
228559 STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
228560 /* Fall thru */
228561 }
228562 case STMT_COLUMN_NSCAN:
@@ -228683,12 +229603,12 @@
228683 }
228684 #endif /* SQLITE_CORE */
228685 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
228686
228687 /************** End of stmt.c ************************************************/
228688 #if __LINE__!=228688
228689 #undef SQLITE_SOURCE_ID
228690 #define SQLITE_SOURCE_ID "2020-04-20 17:35:32 2fc80ef16ce5878311ab88a0c64631813572ffbb71f75363b4619c9667e0alt2"
228691 #endif
228692 /* Return the source-id for this library */
228693 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
228694 /************************** End of sqlite3.c ******************************/
228695
--- 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.32.1. 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.
@@ -215,10 +215,13 @@
215 #if SQLITE_ENABLE_ATOMIC_WRITE
216 "ENABLE_ATOMIC_WRITE",
217 #endif
218 #if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
219 "ENABLE_BATCH_ATOMIC_WRITE",
220 #endif
221 #if SQLITE_ENABLE_BYTECODE_VTAB
222 "ENABLE_BYTECODE_VTAB",
223 #endif
224 #if SQLITE_ENABLE_CEROD
225 "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
226 #endif
227 #if SQLITE_ENABLE_COLUMN_METADATA
@@ -534,13 +537,10 @@
537 "OMIT_BETWEEN_OPTIMIZATION",
538 #endif
539 #if SQLITE_OMIT_BLOB_LITERAL
540 "OMIT_BLOB_LITERAL",
541 #endif
 
 
 
542 #if SQLITE_OMIT_CAST
543 "OMIT_CAST",
544 #endif
545 #if SQLITE_OMIT_CHECK
546 "OMIT_CHECK",
@@ -1160,13 +1160,13 @@
1160 **
1161 ** See also: [sqlite3_libversion()],
1162 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1163 ** [sqlite_version()] and [sqlite_source_id()].
1164 */
1165 #define SQLITE_VERSION "3.32.1"
1166 #define SQLITE_VERSION_NUMBER 3032001
1167 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
1168
1169 /*
1170 ** CAPI3REF: Run-Time Library Version Numbers
1171 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1172 **
@@ -1336,30 +1336,26 @@
1336 ** for the [sqlite3] object.
1337 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
1338 ** the [sqlite3] object is successfully destroyed and all associated
1339 ** resources are deallocated.
1340 **
1341 ** Ideally, applications should [sqlite3_finalize | finalize] all
1342 ** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
1343 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
1344 ** with the [sqlite3] object prior to attempting to close the object.
1345 ** ^If the database connection is associated with unfinalized prepared
1346 ** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
1347 ** sqlite3_close() will leave the database connection open and return
1348 ** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
1349 ** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
1350 ** it returns [SQLITE_OK] regardless, but instead of deallocating the database
1351 ** connection immediately, it marks the database connection as an unusable
1352 ** "zombie" and makes arrangements to automatically deallocate the database
1353 ** connection after all prepared statements are finalized, all BLOB handles
1354 ** are closed, and all backups have finished. The sqlite3_close_v2() interface
1355 ** is intended for use with host languages that are garbage collected, and
1356 ** where the order in which destructors are called is arbitrary.
 
 
 
 
 
 
 
 
1357 **
1358 ** ^If an [sqlite3] object is destroyed while a transaction is open,
1359 ** the transaction is automatically rolled back.
1360 **
1361 ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
@@ -1544,22 +1540,25 @@
1540 #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
1541 #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
1542 #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
1543 #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
1544 #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
1545 #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
1546 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
1547 #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
1548 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1549 #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
1550 #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
1551 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1552 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
1553 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
1554 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
1555 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
1556 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
1557 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1558 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
1559 #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
1560 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
1561 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
1562 #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
1563 #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
1564 #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
@@ -2150,10 +2149,15 @@
2149 ** a single attached database that occur due to other database connections,
2150 ** but omits changes implemented by the database connection on which it is
2151 ** called. This file control is the only mechanism to detect changes that
2152 ** happen either internally or externally and that are associated with
2153 ** a particular attached database.
2154 **
2155 ** <li>[[SQLITE_FCNTL_CKPT_START]]
2156 ** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
2157 ** in wal mode before the client starts to copy pages from the wal
2158 ** file to the database file.
2159 **
2160 ** <li>[[SQLITE_FCNTL_CKPT_DONE]]
2161 ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
2162 ** in wal mode after the client has finished copying pages from the wal
2163 ** file to the database file, but before the *-shm file is updated to
@@ -2195,10 +2199,11 @@
2199 #define SQLITE_FCNTL_LOCK_TIMEOUT 34
2200 #define SQLITE_FCNTL_DATA_VERSION 35
2201 #define SQLITE_FCNTL_SIZE_LIMIT 36
2202 #define SQLITE_FCNTL_CKPT_DONE 37
2203 #define SQLITE_FCNTL_RESERVE_BYTES 38
2204 #define SQLITE_FCNTL_CKPT_START 39
2205
2206 /* deprecated names */
2207 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
2208 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
2209 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -4573,12 +4578,23 @@
4578 **
4579 ** These are utility routines, useful to [VFS|custom VFS implementations],
4580 ** that check if a database file was a URI that contained a specific query
4581 ** parameter, and if so obtains the value of that query parameter.
4582 **
4583 ** The first parameter to these interfaces (hereafter referred to
4584 ** as F) must be one of:
4585 ** <ul>
4586 ** <li> A database filename pointer created by the SQLite core and
4587 ** passed into the xOpen() method of a VFS implemention, or
4588 ** <li> A filename obtained from [sqlite3_db_filename()], or
4589 ** <li> A new filename constructed using [sqlite3_create_filename()].
4590 ** </ul>
4591 ** If the F parameter is not one of the above, then the behavior is
4592 ** undefined and probably undesirable. Older versions of SQLite were
4593 ** more tolerant of invalid F parameters than newer versions.
4594 **
4595 ** If F is a suitable filename (as described in the previous paragraph)
4596 ** and if P is the name of the query parameter, then
4597 ** sqlite3_uri_parameter(F,P) returns the value of the P
4598 ** parameter if it exists or a NULL pointer if P does not appear as a
4599 ** query parameter on F. If P is a query parameter of F and it
4600 ** has no explicit value, then sqlite3_uri_parameter(F,P) returns
@@ -4657,10 +4673,29 @@
4673 */
4674 SQLITE_API const char *sqlite3_filename_database(const char*);
4675 SQLITE_API const char *sqlite3_filename_journal(const char*);
4676 SQLITE_API const char *sqlite3_filename_wal(const char*);
4677
4678 /*
4679 ** CAPI3REF: Database File Corresponding To A Journal
4680 **
4681 ** ^If X is the name of a rollback or WAL-mode journal file that is
4682 ** passed into the xOpen method of [sqlite3_vfs], then
4683 ** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
4684 ** object that represents the main database file.
4685 **
4686 ** This routine is intended for use in custom [VFS] implementations
4687 ** only. It is not a general-purpose interface.
4688 ** The argument sqlite3_file_object(X) must be a filename pointer that
4689 ** has been passed into [sqlite3_vfs].xOpen method where the
4690 ** flags parameter to xOpen contains one of the bits
4691 ** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
4692 ** of this routine results in undefined and probably undesirable
4693 ** behavior.
4694 */
4695 SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
4696
4697 /*
4698 ** CAPI3REF: Create and Destroy VFS Filenames
4699 **
4700 ** These interfces are provided for use by [VFS shim] implementations and
4701 ** are not useful outside of that context.
@@ -4691,11 +4726,11 @@
4726 ** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
4727 ** be NULL pointers, though they can be empty strings.
4728 **
4729 ** The sqlite3_free_filename(Y) routine releases a memory allocation
4730 ** previously obtained from sqlite3_create_filename(). Invoking
4731 ** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
4732 **
4733 ** If the Y parameter to sqlite3_free_filename(Y) is anything other
4734 ** than a NULL pointer or a pointer previously acquired from
4735 ** sqlite3_create_filename(), then bad things such as heap
4736 ** corruption or segfaults may occur. The value Y should be
@@ -6497,11 +6532,11 @@
6532 ** when first called if N is less than or equal to zero or if a memory
6533 ** allocate error occurs.
6534 **
6535 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
6536 ** determined by the N parameter on first successful call. Changing the
6537 ** value of N in any subsequent call to sqlite3_aggregate_context() within
6538 ** the same aggregate function instance will not resize the memory
6539 ** allocation.)^ Within the xFinal callback, it is customary to set
6540 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
6541 ** pointless memory allocations occur.
6542 **
@@ -14502,11 +14537,10 @@
14537 typedef struct BusyHandler BusyHandler;
14538 struct BusyHandler {
14539 int (*xBusyHandler)(void *,int); /* The busy callback */
14540 void *pBusyArg; /* First arg to busy callback */
14541 int nBusy; /* Incremented with each busy call */
 
14542 };
14543
14544 /*
14545 ** Name of the master database table. The master database table
14546 ** is a special table that holds the names and attributes of all
@@ -15022,13 +15056,11 @@
15056 #ifndef NDEBUG
15057 SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
15058 #endif
15059 SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
15060
 
15061 SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
 
15062
15063 #ifdef SQLITE_TEST
15064 SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
15065 SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
15066 #endif
@@ -15599,10 +15631,13 @@
15631
15632 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
15633 SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
15634
15635 SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
15636 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
15637 SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
15638 #endif
15639
15640 /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
15641 ** each VDBE opcode.
15642 **
15643 ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
@@ -15884,17 +15919,25 @@
15919 SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
15920 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
15921 SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
15922 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
15923 # ifdef SQLITE_ENABLE_SNAPSHOT
15924 SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
15925 SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot);
15926 SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
15927 SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
15928 SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
15929 # endif
15930 #endif
15931
15932 #if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT)
15933 SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int);
15934 SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*);
15935 #else
15936 # define sqlite3PagerWalWriteLock(y,z) SQLITE_OK
15937 # define sqlite3PagerWalDb(x,y)
15938 #endif
15939
15940 #ifdef SQLITE_DIRECT_OVERFLOW_READ
15941 SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
15942 #endif
15943
@@ -15917,15 +15960,10 @@
15960 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
15961 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
15962 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
15963 SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
15964 SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
 
 
 
 
 
15965
15966 /* Functions used to truncate the database file. */
15967 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
15968
15969 SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
@@ -16855,10 +16893,11 @@
16893 Hash aFunc; /* Hash table of connection functions */
16894 Hash aCollSeq; /* All collating sequences */
16895 BusyHandler busyHandler; /* Busy callback */
16896 Db aDbStatic[2]; /* Static space for the 2 default backends */
16897 Savepoint *pSavepoint; /* List of active savepoints */
16898 int nAnalysisLimit; /* Number of index rows to ANALYZE */
16899 int busyTimeout; /* Busy handler timeout, in msec */
16900 int nSavepoint; /* Number of non-transaction savepoints */
16901 int nStatement; /* Number of nested statement-transactions */
16902 i64 nDeferredCons; /* Net deferred constraints this transaction. */
16903 i64 nDeferredImmCons; /* Net deferred immediate constraints */
@@ -17080,11 +17119,11 @@
17119 #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
17120 #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
17121 #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
17122 #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
17123 #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
17124 /* 0x0200 -- available for reuse */
17125 #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
17126 #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
17127 #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
17128 #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
17129 ** single query - might change over time */
@@ -17101,10 +17140,11 @@
17140 #define INLINEFUNC_coalesce 0
17141 #define INLINEFUNC_implies_nonnull_row 1
17142 #define INLINEFUNC_expr_implies_expr 2
17143 #define INLINEFUNC_expr_compare 3
17144 #define INLINEFUNC_affinity 4
17145 #define INLINEFUNC_iif 5
17146 #define INLINEFUNC_unlikely 99 /* Default case */
17147
17148 /*
17149 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
17150 ** used to create the initializers for the FuncDef structures.
@@ -17801,11 +17841,11 @@
17841 /*
17842 ** An instance of this structure contains information needed to generate
17843 ** code for a SELECT that contains aggregate functions.
17844 **
17845 ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
17846 ** pointer to this structure. The Expr.iAgg field is the index in
17847 ** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
17848 ** code for that node.
17849 **
17850 ** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
17851 ** original Select structure that describes the SELECT statement. These
@@ -19040,10 +19080,13 @@
19080 SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
19081 SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
19082 SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
19083 SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
19084 SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
19085 SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*);
19086 SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*);
19087
19088 #ifdef SQLITE_DEBUG
19089 SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
19090 #endif
19091
19092 /*
@@ -19900,11 +19943,11 @@
19943 SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
19944 SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
19945 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
19946 SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
19947 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
19948 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
19949 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
19950 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
19951 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
19952 SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*);
19953 SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
@@ -20025,12 +20068,14 @@
20068 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
20069 #endif
20070 SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
20071 #ifndef SQLITE_OMIT_VIRTUALTABLE
20072 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
20073 SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
20074 #else
20075 # define sqlite3ShadowTableName(A,B) 0
20076 # define sqlite3IsShadowTableOf(A,B,C) 0
20077 #endif
20078 SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
20079 SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
20080 SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
20081 SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
@@ -20636,11 +20681,12 @@
20681 /*
20682 ** VDBE_DISPLAY_P4 is true or false depending on whether or not the
20683 ** "explain" P4 display logic is enabled.
20684 */
20685 #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
20686 || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
20687 || defined(SQLITE_ENABLE_BYTECODE_VTAB)
20688 # define VDBE_DISPLAY_P4 1
20689 #else
20690 # define VDBE_DISPLAY_P4 0
20691 #endif
20692
@@ -21101,11 +21147,18 @@
21147
21148 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
21149 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
21150 SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
21151 SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
21152 #if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
21153 SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
21154 SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
21155 #endif
21156 #if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
21157 SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
21158 #endif
21159 #if !defined(SQLITE_OMIT_EXPLAIN)
21160 SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
21161 #endif
21162 SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
21163 SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
21164 SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
@@ -21143,11 +21196,11 @@
21196 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
21197 SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
21198 #ifndef SQLITE_OMIT_WINDOWFUNC
21199 SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
21200 #endif
21201 #if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
21202 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
21203 #endif
21204 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
21205 SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
21206 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
@@ -27316,11 +27369,11 @@
27369 if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
27370 n = mem0.hardLimit;
27371 }
27372 mem0.alarmThreshold = n;
27373 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27374 AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
27375 sqlite3_mutex_leave(mem0.mutex);
27376 excess = sqlite3_memory_used() - n;
27377 if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
27378 return priorLimit;
27379 }
@@ -27384,11 +27437,11 @@
27437 ** Return true if the heap is currently under memory pressure - in other
27438 ** words if the amount of heap used is close to the limit set by
27439 ** sqlite3_soft_heap_limit().
27440 */
27441 SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
27442 return AtomicLoad(&mem0.nearlyFull);
27443 }
27444
27445 /*
27446 ** Deinitialize the memory allocation subsystem.
27447 */
@@ -27448,21 +27501,21 @@
27501
27502 sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
27503 if( mem0.alarmThreshold>0 ){
27504 sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27505 if( nUsed >= mem0.alarmThreshold - nFull ){
27506 AtomicStore(&mem0.nearlyFull, 1);
27507 sqlite3MallocAlarm(nFull);
27508 if( mem0.hardLimit ){
27509 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
27510 if( nUsed >= mem0.hardLimit - nFull ){
27511 *pp = 0;
27512 return;
27513 }
27514 }
27515 }else{
27516 AtomicStore(&mem0.nearlyFull, 0);
27517 }
27518 }
27519 p = sqlite3GlobalConfig.m.xMalloc(nFull);
27520 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
27521 if( p==0 && mem0.alarmThreshold>0 ){
@@ -27687,14 +27740,16 @@
27740 if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
27741 mem0.alarmThreshold-nDiff ){
27742 sqlite3MallocAlarm(nDiff);
27743 }
27744 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
27745 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
27746 if( pNew==0 && mem0.alarmThreshold>0 ){
27747 sqlite3MallocAlarm((int)nBytes);
27748 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
27749 }
27750 #endif
27751 if( pNew ){
27752 nNew = sqlite3MallocSize(pNew);
27753 sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
27754 }
27755 sqlite3_mutex_leave(mem0.mutex);
@@ -27875,11 +27930,11 @@
27930 }
27931 }else{
27932 assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27933 assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
27934 sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
27935 pNew = sqlite3Realloc(p, n);
27936 if( !pNew ){
27937 sqlite3OomFault(db);
27938 }
27939 sqlite3MemdebugSetType(pNew,
27940 (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
@@ -28222,10 +28277,17 @@
28277 #ifndef SQLITE_PRINT_BUF_SIZE
28278 # define SQLITE_PRINT_BUF_SIZE 70
28279 #endif
28280 #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
28281
28282 /*
28283 ** Hard limit on the precision of floating-point conversions.
28284 */
28285 #ifndef SQLITE_PRINTF_PRECISION_LIMIT
28286 # define SQLITE_FP_PRECISION_LIMIT 100000000
28287 #endif
28288
28289 /*
28290 ** Render a string given by "fmt" into the StrAccum object.
28291 */
28292 SQLITE_API void sqlite3_str_vappendf(
28293 sqlite3_str *pAccum, /* Accumulate results here */
@@ -28422,10 +28484,12 @@
28484 ** precision The specified precision. The default
28485 ** is -1.
28486 ** xtype The class of the conversion.
28487 ** infop Pointer to the appropriate info struct.
28488 */
28489 assert( width>=0 );
28490 assert( precision>=(-1) );
28491 switch( xtype ){
28492 case etPOINTER:
28493 flag_long = sizeof(char*)==sizeof(i64) ? 2 :
28494 sizeof(char*)==sizeof(long int) ? 1 : 0;
28495 /* Fall through into the next case */
@@ -28543,10 +28607,15 @@
28607 }
28608 #ifdef SQLITE_OMIT_FLOATING_POINT
28609 length = 0;
28610 #else
28611 if( precision<0 ) precision = 6; /* Set default precision */
28612 #ifdef SQLITE_FP_PRECISION_LIMIT
28613 if( precision>SQLITE_FP_PRECISION_LIMIT ){
28614 precision = SQLITE_FP_PRECISION_LIMIT;
28615 }
28616 #endif
28617 if( realvalue<0.0 ){
28618 realvalue = -realvalue;
28619 prefix = '-';
28620 }else{
28621 prefix = flag_prefix;
@@ -28825,11 +28894,11 @@
28894 }else{
28895 escarg = va_arg(ap,char*);
28896 }
28897 isnull = escarg==0;
28898 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
28899 /* For %q, %Q, and %w, the precision is the number of bytes (or
28900 ** characters if the ! flags is present) to use from the input.
28901 ** Because of the extra quoting characters inserted, the number
28902 ** of output characters may be larger than the precision.
28903 */
28904 k = precision;
@@ -28952,11 +29021,11 @@
29021 p->nAlloc = (int)szNew;
29022 }
29023 if( p->db ){
29024 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
29025 }else{
29026 zNew = sqlite3Realloc(zOld, p->nAlloc);
29027 }
29028 if( zNew ){
29029 assert( p->zText!=0 || p->nChar==0 );
29030 if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
29031 p->zText = zNew;
@@ -29294,11 +29363,11 @@
29363 ** and segfaults if you give it a long long int.
29364 */
29365 SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
29366 va_list ap;
29367 StrAccum acc;
29368 char zBuf[SQLITE_PRINT_BUF_SIZE*10];
29369 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
29370 va_start(ap,zFormat);
29371 sqlite3_str_vappendf(&acc, zFormat, ap);
29372 va_end(ap);
29373 sqlite3StrAccumFinish(&acc);
@@ -29910,12 +29979,13 @@
29979 #else
29980 pWin = 0;
29981 #endif
29982 }
29983 if( pExpr->op==TK_AGG_FUNCTION ){
29984 sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s iAgg=%d agg=%p",
29985 pExpr->op2, pExpr->u.zToken, zFlgs,
29986 pExpr->iAgg, pExpr->pAggInfo);
29987 }else if( pExpr->op2!=0 ){
29988 const char *zOp2;
29989 char zBuf[8];
29990 sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
29991 zOp2 = zBuf;
@@ -30804,10 +30874,11 @@
30874 /* UTF-16 Little-endian -> UTF-8 */
30875 while( zIn<zTerm ){
30876 c = *(zIn++);
30877 c += (*(zIn++))<<8;
30878 if( c>=0xd800 && c<0xe000 ){
30879 #ifdef SQLITE_REPLACE_INVALID_UTF
30880 if( c>=0xdc00 || zIn>=zTerm ){
30881 c = 0xfffd;
30882 }else{
30883 int c2 = *(zIn++);
30884 c2 += (*(zIn++))<<8;
@@ -30816,19 +30887,27 @@
30887 c = 0xfffd;
30888 }else{
30889 c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
30890 }
30891 }
30892 #else
30893 if( zIn<zTerm ){
30894 int c2 = (*zIn++);
30895 c2 += ((*zIn++)<<8);
30896 c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
30897 }
30898 #endif
30899 }
30900 WRITE_UTF8(z, c);
30901 }
30902 }else{
30903 /* UTF-16 Big-endian -> UTF-8 */
30904 while( zIn<zTerm ){
30905 c = (*(zIn++))<<8;
30906 c += *(zIn++);
30907 if( c>=0xd800 && c<0xe000 ){
30908 #ifdef SQLITE_REPLACE_INVALID_UTF
30909 if( c>=0xdc00 || zIn>=zTerm ){
30910 c = 0xfffd;
30911 }else{
30912 int c2 = (*(zIn++))<<8;
30913 c2 += *(zIn++);
@@ -30837,10 +30916,17 @@
30916 c = 0xfffd;
30917 }else{
30918 c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
30919 }
30920 }
30921 #else
30922 if( zIn<zTerm ){
30923 int c2 = ((*zIn++)<<8);
30924 c2 += (*zIn++);
30925 c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
30926 }
30927 #endif
30928 }
30929 WRITE_UTF8(z, c);
30930 }
30931 }
30932 pMem->n = (int)(z - zOut);
@@ -34928,20 +35014,21 @@
35014 static int osSetPosixAdvisoryLock(
35015 int h, /* The file descriptor on which to take the lock */
35016 struct flock *pLock, /* The description of the lock */
35017 unixFile *pFile /* Structure holding timeout value */
35018 ){
35019 int tm = pFile->iBusyTimeout;
35020 int rc = osFcntl(h,F_SETLK,pLock);
35021 while( rc<0 && tm>0 ){
35022 /* On systems that support some kind of blocking file lock with a timeout,
35023 ** make appropriate changes here to invoke that blocking file lock. On
35024 ** generic posix, however, there is no such API. So we simply try the
35025 ** lock once every millisecond until either the timeout expires, or until
35026 ** the lock is obtained. */
35027 usleep(1000);
35028 rc = osFcntl(h,F_SETLK,pLock);
35029 tm--;
35030 }
35031 return rc;
35032 }
35033 #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
35034
@@ -37679,17 +37766,24 @@
37766
37767 /* Locks are within range */
37768 assert( n>=1 && n<=SQLITE_SHM_NLOCK );
37769
37770 if( pShmNode->hShm>=0 ){
37771 int res;
37772 /* Initialize the locking parameters */
37773 f.l_type = lockType;
37774 f.l_whence = SEEK_SET;
37775 f.l_start = ofst;
37776 f.l_len = n;
37777 res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
37778 if( res==-1 ){
37779 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
37780 rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
37781 #else
37782 rc = SQLITE_BUSY;
37783 #endif
37784 }
37785 }
37786
37787 /* Update the global lock state and do debug tracing */
37788 #ifdef SQLITE_DEBUG
37789 { u16 mask;
@@ -38182,26 +38276,27 @@
38276 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
38277 assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
38278 assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
38279 assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
38280
38281 /* Check that, if this to be a blocking lock, no locks that occur later
38282 ** in the following list than the lock being obtained are already held:
38283 **
38284 ** 1. Checkpointer lock (ofst==1).
38285 ** 2. Write lock (ofst==0).
38286 ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
 
38287 **
38288 ** In other words, if this is a blocking lock, none of the locks that
38289 ** occur later in the above list than the lock being obtained may be
38290 ** held. */
38291 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
38292 assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
38293 (ofst!=2) /* not RECOVER */
38294 && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
38295 && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
38296 && (ofst<3 || (p->exclMask|p->sharedMask)<(1<<ofst))
38297 ));
38298 #endif
38299
38300 mask = (1<<(ofst+n)) - (1<<ofst);
38301 assert( n>1 || mask==(1<<ofst) );
38302 sqlite3_mutex_enter(pShmNode->pShmMutex);
@@ -44990,10 +45085,11 @@
45085 }
45086
45087 /* Forward references to VFS helper methods used for temporary files */
45088 static int winGetTempname(sqlite3_vfs *, char **);
45089 static int winIsDir(const void *);
45090 static BOOL winIsLongPathPrefix(const char *);
45091 static BOOL winIsDriveLetterAndColon(const char *);
45092
45093 /*
45094 ** Control and query of the open file handle.
45095 */
@@ -46759,11 +46855,13 @@
46855 pFile->pVfs = pVfs;
46856 pFile->h = h;
46857 if( isReadonly ){
46858 pFile->ctrlFlags |= WINFILE_RDONLY;
46859 }
46860 if( (flags & SQLITE_OPEN_MAIN_DB)
46861 && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
46862 ){
46863 pFile->ctrlFlags |= WINFILE_PSOW;
46864 }
46865 pFile->lastErrno = NO_ERROR;
46866 pFile->zPath = zName;
46867 #if SQLITE_MAX_MMAP_SIZE>0
@@ -46968,10 +47066,21 @@
47066 *pResOut = rc;
47067 OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
47068 zFilename, pResOut, *pResOut));
47069 return SQLITE_OK;
47070 }
47071
47072 /*
47073 ** Returns non-zero if the specified path name starts with the "long path"
47074 ** prefix.
47075 */
47076 static BOOL winIsLongPathPrefix(
47077 const char *zPathname
47078 ){
47079 return ( zPathname[0]=='\\' && zPathname[1]=='\\'
47080 && zPathname[2]=='?' && zPathname[3]=='\\' );
47081 }
47082
47083 /*
47084 ** Returns non-zero if the specified path name starts with a drive letter
47085 ** followed by a colon character.
47086 */
@@ -47033,14 +47142,15 @@
47142 DWORD nByte;
47143 void *zConverted;
47144 char *zOut;
47145 #endif
47146
47147 /* If this path name begins with "/X:" or "\\?\", where "X" is any
47148 ** alphabetic character, discard the initial "/" from the pathname.
47149 */
47150 if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
47151 || winIsLongPathPrefix(zRelative+1)) ){
47152 zRelative++;
47153 }
47154
47155 #if defined(__CYGWIN__)
47156 SimulateIOError( return SQLITE_ERROR );
@@ -47792,11 +47902,11 @@
47902 if( newSz>p->szMax ){
47903 return SQLITE_FULL;
47904 }
47905 newSz *= 2;
47906 if( newSz>p->szMax ) newSz = p->szMax;
47907 pNew = sqlite3Realloc(p->aData, newSz);
47908 if( pNew==0 ) return SQLITE_NOMEM;
47909 p->aData = pNew;
47910 p->szAlloc = newSz;
47911 return SQLITE_OK;
47912 }
@@ -48239,14 +48349,15 @@
48349 */
48350 SQLITE_PRIVATE int sqlite3MemdbInit(void){
48351 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
48352 int sz = pLower->szOsFile;
48353 memdb_vfs.pAppData = pLower;
48354 /* The following conditional can only be true when compiled for
48355 ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
48356 ** it in, to be safe, but it is marked as NO_TEST since there
48357 ** is no way to reach it under most builds. */
48358 if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
48359 memdb_vfs.szOsFile = sz;
48360 return sqlite3_vfs_register(&memdb_vfs, 0);
48361 }
48362 #endif /* SQLITE_ENABLE_DESERIALIZE */
48363
@@ -51505,10 +51616,15 @@
51616 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
51617 #endif
51618
51619 /* Return the sqlite3_file object for the WAL file */
51620 SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
51621
51622 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
51623 SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
51624 SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
51625 #endif
51626
51627 #endif /* ifndef SQLITE_OMIT_WAL */
51628 #endif /* SQLITE_WAL_H */
51629
51630 /************** End of wal.h *************************************************/
@@ -54026,13 +54142,16 @@
54142 }
54143 if( exists ){
54144 /* One of the journals pointed to by the master journal exists.
54145 ** Open it and check if it points at the master journal. If
54146 ** so, return without deleting the master journal file.
54147 ** NB: zJournal is really a MAIN_JOURNAL. But call it a
54148 ** MASTER_JOURNAL here so that the VFS will not send the zJournal
54149 ** name into sqlite3_database_file_object().
54150 */
54151 int c;
54152 int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
54153 rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
54154 if( rc!=SQLITE_OK ){
54155 goto delmaster_out;
54156 }
54157
@@ -56232,10 +56351,11 @@
56351 ** Pager object (sizeof(Pager) bytes)
56352 ** PCache object (sqlite3PcacheSize() bytes)
56353 ** Database file handle (pVfs->szOsFile bytes)
56354 ** Sub-journal file handle (journalFileSize bytes)
56355 ** Main journal file handle (journalFileSize bytes)
56356 ** Ptr back to the Pager (sizeof(Pager*) bytes)
56357 ** \0\0\0\0 database prefix (4 bytes)
56358 ** Database file name (nPathname+1 bytes)
56359 ** URI query parameters (nUriByte bytes)
56360 ** Journal filename (nPathname+8+1 bytes)
56361 ** WAL filename (nPathname+4+1 bytes)
@@ -56271,10 +56391,11 @@
56391 pPtr = (u8 *)sqlite3MallocZero(
56392 ROUND8(sizeof(*pPager)) + /* Pager structure */
56393 ROUND8(pcacheSize) + /* PCache object */
56394 ROUND8(pVfs->szOsFile) + /* The main db file */
56395 journalFileSize * 2 + /* The two journal files */
56396 sizeof(pPager) + /* Space to hold a pointer */
56397 4 + /* Database prefix */
56398 nPathname + 1 + /* database filename */
56399 nUriByte + /* query parameters */
56400 nPathname + 8 + 1 + /* Journal filename */
56401 #ifndef SQLITE_OMIT_WAL
@@ -56291,10 +56412,11 @@
56412 pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
56413 pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
56414 pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
56415 pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
56416 assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
56417 memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager);
56418
56419 /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
56420 pPtr += 4; /* Skip zero prefix */
56421 pPager->zFilename = (char*)pPtr;
56422 if( nPathname>0 ){
@@ -56491,10 +56613,23 @@
56613
56614 *ppPager = pPager;
56615 return SQLITE_OK;
56616 }
56617
56618 /*
56619 ** Return the sqlite3_file for the main database given the name
56620 ** of the corresonding WAL or Journal name as passed into
56621 ** xOpen.
56622 */
56623 SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){
56624 Pager *pPager;
56625 while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
56626 zName--;
56627 }
56628 pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
56629 return pPager->fd;
56630 }
56631
56632
56633 /*
56634 ** This function is called after transitioning from PAGER_UNLOCK to
56635 ** PAGER_SHARED state. It tests if there is a hot journal present in
@@ -57176,11 +57311,10 @@
57311 Pager *pPager;
57312 assert( pPg!=0 );
57313 assert( pPg->pgno==1 );
57314 assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
57315 pPager = pPg->pPager;
 
57316 sqlite3PcacheRelease(pPg);
57317 pagerUnlockIfUnused(pPager);
57318 }
57319
57320 /*
@@ -58469,20 +58603,10 @@
58603 */
58604 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
58605 return pPager->fd;
58606 }
58607
 
 
 
 
 
 
 
 
 
 
58608 /*
58609 ** Return the file handle for the journal file (if it exists).
58610 ** This will be either the rollback journal or the WAL file.
58611 */
58612 SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
@@ -58892,11 +59016,10 @@
59016 (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
59017 pPager->pBusyHandlerArg,
59018 pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
59019 pnLog, pnCkpt
59020 );
 
59021 }
59022 return rc;
59023 }
59024
59025 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
@@ -59057,11 +59180,35 @@
59180 }
59181 }
59182 return rc;
59183 }
59184
59185 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
59186 /*
59187 ** If pager pPager is a wal-mode database not in exclusive locking mode,
59188 ** invoke the sqlite3WalWriteLock() function on the associated Wal object
59189 ** with the same db and bLock parameters as were passed to this function.
59190 ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
59191 */
59192 SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
59193 int rc = SQLITE_OK;
59194 if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){
59195 rc = sqlite3WalWriteLock(pPager->pWal, bLock);
59196 }
59197 return rc;
59198 }
59199
59200 /*
59201 ** Set the database handle used by the wal layer to determine if
59202 ** blocking locks are required.
59203 */
59204 SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
59205 if( pagerUseWal(pPager) ){
59206 sqlite3WalDb(pPager->pWal, db);
59207 }
59208 }
59209 #endif
59210
59211 #ifdef SQLITE_ENABLE_SNAPSHOT
59212 /*
59213 ** If this is a WAL database, obtain a snapshot handle for the snapshot
59214 ** currently open. Otherwise, return an error.
@@ -59077,11 +59224,14 @@
59224 /*
59225 ** If this is a WAL database, store a pointer to pSnapshot. Next time a
59226 ** read transaction is opened, attempt to read from the snapshot it
59227 ** identifies. If this is not a WAL database, return an error.
59228 */
59229 SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(
59230 Pager *pPager,
59231 sqlite3_snapshot *pSnapshot
59232 ){
59233 int rc = SQLITE_OK;
59234 if( pPager->pWal ){
59235 sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
59236 }else{
59237 rc = SQLITE_ERROR;
@@ -59622,10 +59772,13 @@
59772 u8 lockError; /* True if a locking error has occurred */
59773 #endif
59774 #ifdef SQLITE_ENABLE_SNAPSHOT
59775 WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
59776 #endif
59777 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
59778 sqlite3 *db;
59779 #endif
59780 };
59781
59782 /*
59783 ** Candidate values for Wal.exclusiveMode.
59784 */
@@ -59720,11 +59873,11 @@
59873
59874 /* Enlarge the pWal->apWiData[] array if required */
59875 if( pWal->nWiData<=iPage ){
59876 sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
59877 volatile u32 **apNew;
59878 apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
59879 if( !apNew ){
59880 *ppPage = 0;
59881 return SQLITE_NOMEM_BKPT;
59882 }
59883 memset((void*)&apNew[pWal->nWiData], 0,
@@ -59841,29 +59994,47 @@
59994
59995 aOut[0] = s1;
59996 aOut[1] = s2;
59997 }
59998
59999 /*
60000 ** If there is the possibility of concurrent access to the SHM file
60001 ** from multiple threads and/or processes, then do a memory barrier.
60002 */
60003 static void walShmBarrier(Wal *pWal){
60004 if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
60005 sqlite3OsShmBarrier(pWal->pDbFd);
60006 }
60007 }
60008
60009 /*
60010 ** Add the SQLITE_NO_TSAN as part of the return-type of a function
60011 ** definition as a hint that the function contains constructs that
60012 ** might give false-positive TSAN warnings.
60013 **
60014 ** See tag-20200519-1.
60015 */
60016 #if defined(__clang__) && !defined(SQLITE_NO_TSAN)
60017 # define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
60018 #else
60019 # define SQLITE_NO_TSAN
60020 #endif
60021
60022 /*
60023 ** Write the header information in pWal->hdr into the wal-index.
60024 **
60025 ** The checksum on pWal->hdr is updated before it is written.
60026 */
60027 static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
60028 volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
60029 const int nCksum = offsetof(WalIndexHdr, aCksum);
60030
60031 assert( pWal->writeLock );
60032 pWal->hdr.isInit = 1;
60033 pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
60034 walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
60035 /* Possible TSAN false-positive. See tag-20200519-1 */
60036 memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
60037 walShmBarrier(pWal);
60038 memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
60039 }
60040
@@ -59995,11 +60166,11 @@
60166 if( pWal->exclusiveMode ) return SQLITE_OK;
60167 rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
60168 SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
60169 WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
60170 walLockName(lockIdx), rc ? "failed" : "ok"));
60171 VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
60172 return rc;
60173 }
60174 static void walUnlockShared(Wal *pWal, int lockIdx){
60175 if( pWal->exclusiveMode ) return;
60176 (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
@@ -60011,11 +60182,11 @@
60182 if( pWal->exclusiveMode ) return SQLITE_OK;
60183 rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
60184 SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
60185 WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
60186 walLockName(lockIdx), n, rc ? "failed" : "ok"));
60187 VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
60188 return rc;
60189 }
60190 static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
60191 if( pWal->exclusiveMode ) return;
60192 (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
@@ -60283,15 +60454,10 @@
60454 int rc; /* Return Code */
60455 i64 nSize; /* Size of log file */
60456 u32 aFrameCksum[2] = {0, 0};
60457 int iLock; /* Lock offset to lock for checkpoint */
60458
 
 
 
 
 
60459 /* Obtain an exclusive lock on all byte in the locking range not already
60460 ** locked by the caller. The caller is guaranteed to have locked the
60461 ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
60462 ** If successful, the same bytes that are locked here are unlocked before
60463 ** this function returns.
@@ -60835,10 +61001,93 @@
61001 p = 0;
61002 }
61003 *pp = p;
61004 return rc;
61005 }
61006
61007 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61008 /*
61009 ** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
61010 ** they are supported by the VFS, and (b) the database handle is configured
61011 ** with a busy-timeout. Return 1 if blocking locks are successfully enabled,
61012 ** or 0 otherwise.
61013 */
61014 static int walEnableBlocking(Wal *pWal){
61015 int res = 0;
61016 if( pWal->db ){
61017 int tmout = pWal->db->busyTimeout;
61018 if( tmout ){
61019 int rc;
61020 rc = sqlite3OsFileControl(
61021 pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
61022 );
61023 res = (rc==SQLITE_OK);
61024 }
61025 }
61026 return res;
61027 }
61028
61029 /*
61030 ** Disable blocking locks.
61031 */
61032 static void walDisableBlocking(Wal *pWal){
61033 int tmout = 0;
61034 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
61035 }
61036
61037 /*
61038 ** If parameter bLock is true, attempt to enable blocking locks, take
61039 ** the WRITER lock, and then disable blocking locks. If blocking locks
61040 ** cannot be enabled, no attempt to obtain the WRITER lock is made. Return
61041 ** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not
61042 ** an error if blocking locks can not be enabled.
61043 **
61044 ** If the bLock parameter is false and the WRITER lock is held, release it.
61045 */
61046 SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock){
61047 int rc = SQLITE_OK;
61048 assert( pWal->readLock<0 || bLock==0 );
61049 if( bLock ){
61050 assert( pWal->db );
61051 if( walEnableBlocking(pWal) ){
61052 rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
61053 if( rc==SQLITE_OK ){
61054 pWal->writeLock = 1;
61055 }
61056 walDisableBlocking(pWal);
61057 }
61058 }else if( pWal->writeLock ){
61059 walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
61060 pWal->writeLock = 0;
61061 }
61062 return rc;
61063 }
61064
61065 /*
61066 ** Set the database handle used to determine if blocking locks are required.
61067 */
61068 SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
61069 pWal->db = db;
61070 }
61071
61072 /*
61073 ** Take an exclusive WRITE lock. Blocking if so configured.
61074 */
61075 static int walLockWriter(Wal *pWal){
61076 int rc;
61077 walEnableBlocking(pWal);
61078 rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
61079 walDisableBlocking(pWal);
61080 return rc;
61081 }
61082 #else
61083 # define walEnableBlocking(x) 0
61084 # define walDisableBlocking(x)
61085 # define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
61086 # define sqlite3WalDb(pWal, db)
61087 #endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
61088
61089
61090 /*
61091 ** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
61092 ** n. If the attempt fails and parameter xBusy is not NULL, then it is a
61093 ** busy-handler function. Invoke it and retry the lock until either the
@@ -60853,10 +61102,16 @@
61102 ){
61103 int rc;
61104 do {
61105 rc = walLockExclusive(pWal, lockIdx, n);
61106 }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
61107 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
61108 if( rc==SQLITE_BUSY_TIMEOUT ){
61109 walDisableBlocking(pWal);
61110 rc = SQLITE_BUSY;
61111 }
61112 #endif
61113 return rc;
61114 }
61115
61116 /*
61117 ** The cache of the wal-index header must be valid to call this function.
@@ -60890,11 +61145,11 @@
61145 pWal->nCkpt++;
61146 pWal->hdr.mxFrame = 0;
61147 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
61148 memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
61149 walIndexWriteHdr(pWal);
61150 AtomicStore(&pInfo->nBackfill, 0);
61151 pInfo->nBackfillAttempted = 0;
61152 pInfo->aReadMark[1] = 0;
61153 for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
61154 assert( pInfo->aReadMark[0]==0 );
61155 }
@@ -60965,36 +61220,17 @@
61220 ** cannot be backfilled from the WAL.
61221 */
61222 mxSafeFrame = pWal->hdr.mxFrame;
61223 mxPage = pWal->hdr.nPage;
61224 for(i=1; i<WAL_NREADER; i++){
61225 u32 y = AtomicLoad(pInfo->aReadMark+i);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61226 if( mxSafeFrame>y ){
61227 assert( y<=pWal->hdr.mxFrame );
61228 rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
61229 if( rc==SQLITE_OK ){
61230 u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
61231 AtomicStore(pInfo->aReadMark+i, iMark);
61232 walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
61233 }else if( rc==SQLITE_BUSY ){
61234 mxSafeFrame = y;
61235 xBusy = 0;
61236 }else{
@@ -61008,11 +61244,11 @@
61244 rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
61245 assert( rc==SQLITE_OK || pIter==0 );
61246 }
61247
61248 if( pIter
61249 && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
61250 ){
61251 u32 nBackfill = pInfo->nBackfill;
61252
61253 pInfo->nBackfillAttempted = mxSafeFrame;
61254
@@ -61023,10 +61259,11 @@
61259 ** about the eventual size of the db file to the VFS layer.
61260 */
61261 if( rc==SQLITE_OK ){
61262 i64 nReq = ((i64)mxPage * szPage);
61263 i64 nSize; /* Current size of database file */
61264 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
61265 rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
61266 if( rc==SQLITE_OK && nSize<nReq ){
61267 sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
61268 }
61269 }
@@ -61050,10 +61287,11 @@
61287 iOffset = (iDbpage-1)*(i64)szPage;
61288 testcase( IS_BIG_INT(iOffset) );
61289 rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
61290 if( rc!=SQLITE_OK ) break;
61291 }
61292 sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
61293
61294 /* If work was actually accomplished... */
61295 if( rc==SQLITE_OK ){
61296 if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
61297 i64 szDb = pWal->hdr.nPage*(i64)szPage;
@@ -61062,15 +61300,11 @@
61300 if( rc==SQLITE_OK ){
61301 rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
61302 }
61303 }
61304 if( rc==SQLITE_OK ){
61305 AtomicStore(&pInfo->nBackfill, mxSafeFrame);
 
 
 
 
61306 }
61307 }
61308
61309 /* Release the reader lock held while backfilling */
61310 walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
@@ -61225,11 +61459,11 @@
61459 ** and *pChanged is set to 1.
61460 **
61461 ** If the checksum cannot be verified return non-zero. If the header
61462 ** is read successfully and the checksum verified, return zero.
61463 */
61464 static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
61465 u32 aCksum[2]; /* Checksum on the header content */
61466 WalIndexHdr h1, h2; /* Two copies of the header content */
61467 WalIndexHdr volatile *aHdr; /* Header in shared memory */
61468
61469 /* The first page of the wal-index must be mapped at this point. */
@@ -61238,17 +61472,23 @@
61472 /* Read the header. This might happen concurrently with a write to the
61473 ** same area of shared memory on a different CPU in a SMP,
61474 ** meaning it is possible that an inconsistent snapshot is read
61475 ** from the file. If this happens, return non-zero.
61476 **
61477 ** tag-20200519-1:
61478 ** There are two copies of the header at the beginning of the wal-index.
61479 ** When reading, read [0] first then [1]. Writes are in the reverse order.
61480 ** Memory barriers are used to prevent the compiler or the hardware from
61481 ** reordering the reads and writes. TSAN and similar tools can sometimes
61482 ** give false-positive warnings about these accesses because the tools do not
61483 ** account for the double-read and the memory barrier. The use of mutexes
61484 ** here would be problematic as the memory being accessed is potentially
61485 ** shared among multiple processes and not all mutex implementions work
61486 ** reliably in that environment.
61487 */
61488 aHdr = walIndexHdr(pWal);
61489 memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
61490 walShmBarrier(pWal);
61491 memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
61492
61493 if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
61494 return 1; /* Dirty read */
@@ -61334,32 +61574,36 @@
61574 badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
61575
61576 /* If the first attempt failed, it might have been due to a race
61577 ** with a writer. So get a WRITE lock and try again.
61578 */
 
61579 if( badHdr ){
61580 if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
61581 if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
61582 walUnlockShared(pWal, WAL_WRITE_LOCK);
61583 rc = SQLITE_READONLY_RECOVERY;
61584 }
61585 }else{
61586 int bWriteLock = pWal->writeLock;
61587 if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
61588 pWal->writeLock = 1;
61589 if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
61590 badHdr = walIndexTryHdr(pWal, pChanged);
61591 if( badHdr ){
61592 /* If the wal-index header is still malformed even while holding
61593 ** a WRITE lock, it can only mean that the header is corrupted and
61594 ** needs to be reconstructed. So run recovery to do exactly that.
61595 */
61596 rc = walIndexRecover(pWal);
61597 *pChanged = 1;
61598 }
61599 }
61600 if( bWriteLock==0 ){
61601 pWal->writeLock = 0;
61602 walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
61603 }
61604 }
61605 }
61606 }
61607
61608 /* If the header is read successfully, check the version number to make
61609 ** sure the wal-index was not constructed with some future format that
@@ -61685,11 +61929,11 @@
61929 }
61930
61931 assert( pWal->nWiData>0 );
61932 assert( pWal->apWiData[0]!=0 );
61933 pInfo = walCkptInfo(pWal);
61934 if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
61935 #ifdef SQLITE_ENABLE_SNAPSHOT
61936 && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
61937 #endif
61938 ){
61939 /* The WAL has been completely backfilled (or it is empty).
@@ -61852,11 +62096,11 @@
62096 void *pBuf2 = sqlite3_malloc(szPage);
62097 if( pBuf1==0 || pBuf2==0 ){
62098 rc = SQLITE_NOMEM;
62099 }else{
62100 u32 i = pInfo->nBackfillAttempted;
62101 for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
62102 WalHashLoc sLoc; /* Hash table location */
62103 u32 pgno; /* Page number in db file */
62104 i64 iDbOff; /* Offset of db file entry */
62105 i64 iWalOff; /* Offset of wal file entry */
62106
@@ -61907,26 +62151,40 @@
62151 ** needs to be flushed.
62152 */
62153 SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
62154 int rc; /* Return code */
62155 int cnt = 0; /* Number of TryBeginRead attempts */
 
 
 
 
62156 #ifdef SQLITE_ENABLE_SNAPSHOT
62157 int bChanged = 0;
62158 WalIndexHdr *pSnapshot = pWal->pSnapshot;
 
 
 
62159 #endif
62160
62161 assert( pWal->ckptLock==0 );
62162
62163 #ifdef SQLITE_ENABLE_SNAPSHOT
62164 if( pSnapshot ){
62165 if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
62166 bChanged = 1;
62167 }
62168
62169 /* It is possible that there is a checkpointer thread running
62170 ** concurrent with this code. If this is the case, it may be that the
62171 ** checkpointer has already determined that it will checkpoint
62172 ** snapshot X, where X is later in the wal file than pSnapshot, but
62173 ** has not yet set the pInfo->nBackfillAttempted variable to indicate
62174 ** its intent. To avoid the race condition this leads to, ensure that
62175 ** there is no checkpointer process by taking a shared CKPT lock
62176 ** before checking pInfo->nBackfillAttempted. */
62177 (void)walEnableBlocking(pWal);
62178 rc = walLockShared(pWal, WAL_CKPT_LOCK);
62179 walDisableBlocking(pWal);
62180
62181 if( rc!=SQLITE_OK ){
62182 return rc;
62183 }
62184 pWal->ckptLock = 1;
62185 }
62186 #endif
62187
62188 do{
62189 rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
62190 }while( rc==WAL_RETRY );
@@ -61933,20 +62191,10 @@
62191 testcase( (rc&0xff)==SQLITE_BUSY );
62192 testcase( (rc&0xff)==SQLITE_IOERR );
62193 testcase( rc==SQLITE_PROTOCOL );
62194 testcase( rc==SQLITE_OK );
62195
 
 
 
 
 
 
 
 
 
 
62196 #ifdef SQLITE_ENABLE_SNAPSHOT
62197 if( rc==SQLITE_OK ){
62198 if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
62199 /* At this point the client has a lock on an aReadMark[] slot holding
62200 ** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr
@@ -61964,52 +62212,46 @@
62212 volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
62213
62214 assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
62215 assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
62216
62217 /* Check that the wal file has not been wrapped. Assuming that it has
62218 ** not, also check that no checkpointer has attempted to checkpoint any
62219 ** frames beyond pSnapshot->mxFrame. If either of these conditions are
62220 ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
62221 ** with *pSnapshot and set *pChanged as appropriate for opening the
62222 ** snapshot. */
62223 if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
62224 && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
62225 ){
62226 assert( pWal->readLock>0 );
62227 memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
62228 *pChanged = bChanged;
62229 }else{
62230 rc = SQLITE_ERROR_SNAPSHOT;
62231 }
62232
62233 /* A client using a non-current snapshot may not ignore any frames
62234 ** from the start of the wal file. This is because, for a system
62235 ** where (minFrame < iSnapshot < maxFrame), a checkpointer may
62236 ** have omitted to checkpoint a frame earlier than minFrame in
62237 ** the file because there exists a frame after iSnapshot that
62238 ** is the same database page. */
62239 pWal->minFrame = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
62240
62241 if( rc!=SQLITE_OK ){
62242 sqlite3WalEndReadTransaction(pWal);
62243 }
62244 }
62245 }
62246
62247 /* Release the shared CKPT lock obtained above. */
62248 if( pWal->ckptLock ){
62249 assert( pSnapshot );
62250 walUnlockShared(pWal, WAL_CKPT_LOCK);
62251 pWal->ckptLock = 0;
62252 }
62253 #endif
62254 return rc;
62255 }
62256
62257 /*
@@ -62085,26 +62327,28 @@
62327 for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
62328 WalHashLoc sLoc; /* Hash table location */
62329 int iKey; /* Hash slot index */
62330 int nCollide; /* Number of hash collisions remaining */
62331 int rc; /* Error code */
62332 u32 iH;
62333
62334 rc = walHashGet(pWal, iHash, &sLoc);
62335 if( rc!=SQLITE_OK ){
62336 return rc;
62337 }
62338 nCollide = HASHTABLE_NSLOT;
62339 iKey = walHash(pgno);
62340 while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
62341 u32 iFrame = iH + sLoc.iZero;
62342 if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
62343 assert( iFrame>iRead || CORRUPT_DB );
62344 iRead = iFrame;
62345 }
62346 if( (nCollide--)==0 ){
62347 return SQLITE_CORRUPT_BKPT;
62348 }
62349 iKey = walNextHash(iKey);
62350 }
62351 if( iRead ) break;
62352 }
62353
62354 #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -62175,10 +62419,20 @@
62419 **
62420 ** There can only be a single writer active at a time.
62421 */
62422 SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
62423 int rc;
62424
62425 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
62426 /* If the write-lock is already held, then it was obtained before the
62427 ** read-transaction was even opened, making this call a no-op.
62428 ** Return early. */
62429 if( pWal->writeLock ){
62430 assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
62431 return SQLITE_OK;
62432 }
62433 #endif
62434
62435 /* Cannot start a write transaction without first holding a read
62436 ** transaction. */
62437 assert( pWal->readLock>=0 );
62438 assert( pWal->writeLock==0 && pWal->iReCksum==0 );
@@ -62751,50 +63005,57 @@
63005 ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
63006 assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
63007
63008 if( pWal->readOnly ) return SQLITE_READONLY;
63009 WALTRACE(("WAL%p: checkpoint begins\n", pWal));
63010
63011 /* Enable blocking locks, if possible. If blocking locks are successfully
63012 ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
63013 sqlite3WalDb(pWal, db);
63014 (void)walEnableBlocking(pWal);
63015
63016 /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
63017 ** "checkpoint" lock on the database file.
63018 ** EVIDENCE-OF: R-10421-19736 If any other process is running a
63019 ** checkpoint operation at the same time, the lock cannot be obtained and
63020 ** SQLITE_BUSY is returned.
63021 ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
63022 ** it will not be invoked in this case.
63023 */
63024 rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
63025 testcase( rc==SQLITE_BUSY );
63026 testcase( rc!=SQLITE_OK && xBusy2!=0 );
63027 if( rc==SQLITE_OK ){
63028 pWal->ckptLock = 1;
63029
63030 /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
63031 ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
63032 ** file.
63033 **
63034 ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
63035 ** immediately, and a busy-handler is configured, it is invoked and the
63036 ** writer lock retried until either the busy-handler returns 0 or the
63037 ** lock is successfully obtained.
63038 */
63039 if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
63040 rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
63041 if( rc==SQLITE_OK ){
63042 pWal->writeLock = 1;
63043 }else if( rc==SQLITE_BUSY ){
63044 eMode2 = SQLITE_CHECKPOINT_PASSIVE;
63045 xBusy2 = 0;
63046 rc = SQLITE_OK;
63047 }
63048 }
63049 }
63050
 
 
 
 
 
 
63051
63052 /* Read the wal-index header. */
63053 if( rc==SQLITE_OK ){
63054 walDisableBlocking(pWal);
63055 rc = walIndexReadHdr(pWal, &isChanged);
63056 (void)walEnableBlocking(pWal);
63057 if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
63058 sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
63059 }
63060 }
63061
@@ -62821,16 +63082,24 @@
63082 ** next time the pager opens a snapshot on this database it knows that
63083 ** the cache needs to be reset.
63084 */
63085 memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
63086 }
63087
63088 walDisableBlocking(pWal);
63089 sqlite3WalDb(pWal, 0);
63090
63091 /* Release the locks. */
63092 sqlite3WalEndWriteTransaction(pWal);
63093 if( pWal->ckptLock ){
63094 walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
63095 pWal->ckptLock = 0;
63096 }
63097 WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
63098 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
63099 if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
63100 #endif
63101 return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
63102 }
63103
63104 /* Return the value to pass to a sqlite3_wal_hook callback, the
63105 ** number of frames in the WAL at the point of the last commit since
@@ -62943,11 +63212,14 @@
63212 return rc;
63213 }
63214
63215 /* Try to open on pSnapshot when the next read-transaction starts
63216 */
63217 SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
63218 Wal *pWal,
63219 sqlite3_snapshot *pSnapshot
63220 ){
63221 pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
63222 }
63223
63224 /*
63225 ** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
@@ -63462,11 +63734,11 @@
63734 u8 incrVacuum; /* True if incr-vacuum is enabled */
63735 u8 bDoTruncate; /* True to truncate db on commit */
63736 #endif
63737 u8 inTransaction; /* Transaction state */
63738 u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
63739 u8 nReserveWanted; /* Desired number of extra bytes per page */
63740 u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
63741 u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
63742 u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
63743 u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
63744 u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
@@ -66356,12 +66628,11 @@
66628 */
66629 static int btreeInvokeBusyHandler(void *pArg){
66630 BtShared *pBt = (BtShared*)pArg;
66631 assert( pBt->db );
66632 assert( sqlite3_mutex_held(pBt->db->mutex) );
66633 return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
 
66634 }
66635
66636 /*
66637 ** Open a database file.
66638 **
@@ -66908,23 +67179,21 @@
67179 ** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
67180 ** and autovacuum mode can no longer be changed.
67181 */
67182 SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
67183 int rc = SQLITE_OK;
67184 int x;
67185 BtShared *pBt = p->pBt;
67186 assert( nReserve>=0 && nReserve<=255 );
67187 sqlite3BtreeEnter(p);
67188 pBt->nReserveWanted = nReserve;
67189 x = pBt->pageSize - pBt->usableSize;
67190 if( nReserve<x ) nReserve = x;
67191 if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
67192 sqlite3BtreeLeave(p);
67193 return SQLITE_READONLY;
67194 }
 
 
 
67195 assert( nReserve>=0 && nReserve<=255 );
67196 if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
67197 ((pageSize-1)&pageSize)==0 ){
67198 assert( (pageSize & 7)==0 );
67199 assert( !pBt->pCursor );
@@ -66965,18 +67234,22 @@
67234
67235 /*
67236 ** Return the number of bytes of space at the end of every page that
67237 ** are intentually left unused. This is the "reserved" space that is
67238 ** sometimes used by extensions.
67239 **
67240 ** The value returned is the larger of the current reserve size and
67241 ** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
67242 ** The amount of reserve can only grow - never shrink.
67243 */
67244 SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){
67245 int n1, n2;
67246 sqlite3BtreeEnter(p);
67247 n1 = (int)p->pBt->nReserveWanted;
67248 n2 = sqlite3BtreeGetReserveNoMutex(p);
67249 sqlite3BtreeLeave(p);
67250 return n1>n2 ? n1 : n2;
67251 }
67252
67253
67254 /*
67255 ** Set the maximum page count for a database if mxPage is positive.
@@ -67422,10 +67695,11 @@
67695 ** when A already has a read lock, we encourage A to give up and let B
67696 ** proceed.
67697 */
67698 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
67699 BtShared *pBt = p->pBt;
67700 Pager *pPager = pBt->pPager;
67701 int rc = SQLITE_OK;
67702
67703 sqlite3BtreeEnter(p);
67704 btreeIntegrity(p);
67705
@@ -67437,11 +67711,11 @@
67711 goto trans_begun;
67712 }
67713 assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
67714
67715 if( (p->db->flags & SQLITE_ResetDatabase)
67716 && sqlite3PagerIsreadonly(pPager)==0
67717 ){
67718 pBt->btsFlags &= ~BTS_READ_ONLY;
67719 }
67720
67721 /* Write transactions are not possible on a read-only database */
@@ -67485,10 +67759,22 @@
67759 if( SQLITE_OK!=rc ) goto trans_begun;
67760
67761 pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
67762 if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
67763 do {
67764 sqlite3PagerWalDb(pPager, p->db);
67765
67766 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
67767 /* If transitioning from no transaction directly to a write transaction,
67768 ** block for the WRITER lock first if possible. */
67769 if( pBt->pPage1==0 && wrflag ){
67770 assert( pBt->inTransaction==TRANS_NONE );
67771 rc = sqlite3PagerWalWriteLock(pPager, 1);
67772 if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break;
67773 }
67774 #endif
67775
67776 /* Call lockBtree() until either pBt->pPage1 is populated or
67777 ** lockBtree() returns something other than SQLITE_OK. lockBtree()
67778 ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
67779 ** reading page 1 it discovers that the page-size of the database
67780 ** file is not pBt->pageSize. In this case lockBtree() will update
@@ -67498,11 +67784,11 @@
67784
67785 if( rc==SQLITE_OK && wrflag ){
67786 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
67787 rc = SQLITE_READONLY;
67788 }else{
67789 rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db));
67790 if( rc==SQLITE_OK ){
67791 rc = newDatabase(pBt);
67792 }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
67793 /* if there was no transaction opened when this function was
67794 ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
@@ -67511,15 +67797,19 @@
67797 }
67798 }
67799 }
67800
67801 if( rc!=SQLITE_OK ){
67802 (void)sqlite3PagerWalWriteLock(pPager, 0);
67803 unlockBtreeIfUnused(pBt);
67804 }
67805 }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
67806 btreeInvokeBusyHandler(pBt) );
67807 sqlite3PagerWalDb(pPager, 0);
67808 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
67809 if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
67810 #endif
67811
67812 if( rc==SQLITE_OK ){
67813 if( p->inTrans==TRANS_NONE ){
67814 pBt->nTransaction++;
67815 #ifndef SQLITE_OMIT_SHARED_CACHE
@@ -67567,11 +67857,11 @@
67857 if( wrflag ){
67858 /* This call makes sure that the pager has the correct number of
67859 ** open savepoints. If the second parameter is greater than 0 and
67860 ** the sub-journal is not already open, then it will be opened here.
67861 */
67862 rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint);
67863 }
67864 }
67865
67866 btreeIntegrity(p);
67867 sqlite3BtreeLeave(p);
@@ -71203,11 +71493,11 @@
71493
71494 /* Remove cells from the start and end of the page */
71495 assert( nCell>=0 );
71496 if( iOld<iNew ){
71497 int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
71498 if( NEVER(nShift>nCell) ) return SQLITE_CORRUPT_BKPT;
71499 memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
71500 nCell -= nShift;
71501 }
71502 if( iNewEnd < iOldEnd ){
71503 int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
@@ -73560,11 +73850,10 @@
73850 }
73851 sqlite3BtreeLeave(p);
73852 return rc;
73853 }
73854
 
73855 /*
73856 ** The first argument, pCur, is a cursor opened on some b-tree. Count the
73857 ** number of entries in the b-tree and write the result to *pnEntry.
73858 **
73859 ** SQLITE_OK is returned if the operation is successfully executed.
@@ -73633,11 +73922,10 @@
73922 }
73923
73924 /* An error has occurred. Return an error code. */
73925 return rc;
73926 }
 
73927
73928 /*
73929 ** Return the pager associated with a BTree. This routine is used for
73930 ** testing and debugging only.
73931 */
@@ -74684,11 +74972,11 @@
74972 ** Attempt to set the page size of the destination to match the page size
74973 ** of the source.
74974 */
74975 static int setDestPgsz(sqlite3_backup *p){
74976 int rc;
74977 rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
74978 return rc;
74979 }
74980
74981 /*
74982 ** Check that there is no open read-transaction on the b-tree passed as the
@@ -78709,24 +78997,23 @@
78997 ** "PX" -> "r[X]"
78998 ** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
78999 ** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
79000 ** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
79001 */
79002 SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
79003 sqlite3 *db, /* Optional - Oom error reporting only */
79004 const Op *pOp, /* The opcode to be commented */
79005 const char *zP4 /* Previously obtained value for P4 */
 
 
79006 ){
79007 const char *zOpName;
79008 const char *zSynopsis;
79009 int nOpName;
79010 int ii;
79011 char zAlt[50];
79012 StrAccum x;
 
79013
79014 sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
79015 zOpName = sqlite3OpcodeName(pOp->opcode);
79016 nOpName = sqlite3Strlen30(zOpName);
79017 if( zOpName[nOpName+1] ){
79018 int seenCom = 0;
79019 char c;
@@ -78789,14 +79076,16 @@
79076 sqlite3_str_appendf(&x, "; %s", pOp->zComment);
79077 }
79078 }else if( pOp->zComment ){
79079 sqlite3_str_appendall(&x, pOp->zComment);
79080 }
79081 if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
79082 sqlite3OomFault(db);
79083 }
79084 return sqlite3StrAccumFinish(&x);
79085 }
79086 #endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */
79087
79088 #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
79089 /*
79090 ** Translate the P4.pExpr value for an OP_CursorHint opcode into text
79091 ** that can be displayed in the P4 column of EXPLAIN output.
@@ -78873,15 +79162,15 @@
79162 #if VDBE_DISPLAY_P4
79163 /*
79164 ** Compute a string that describes the P4 parameter for an opcode.
79165 ** Use zTemp for any required temporary buffer space.
79166 */
79167 SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
79168 char *zP4 = 0;
79169 StrAccum x;
79170
79171 sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
79172 switch( pOp->p4type ){
79173 case P4_KEYINFO: {
79174 int j;
79175 KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
79176 assert( pKeyInfo->aSortFlags!=0 );
@@ -78961,40 +79250,36 @@
79250 int i;
79251 int *ai = pOp->p4.ai;
79252 int n = ai[0]; /* The first element of an INTARRAY is always the
79253 ** count of the number of elements to follow */
79254 for(i=1; i<=n; i++){
79255 sqlite3_str_appendf(&x, "%c%d", (i==1 ? '[' : ','), ai[i]);
79256 }
 
79257 sqlite3_str_append(&x, "]", 1);
79258 break;
79259 }
79260 case P4_SUBPROGRAM: {
79261 zP4 = "program";
79262 break;
79263 }
79264 case P4_DYNBLOB:
79265 case P4_ADVANCE: {
 
79266 break;
79267 }
79268 case P4_TABLE: {
79269 zP4 = pOp->p4.pTab->zName;
79270 break;
79271 }
79272 default: {
79273 zP4 = pOp->p4.z;
 
 
 
 
79274 }
79275 }
79276 if( zP4 ) sqlite3_str_appendall(&x, zP4);
79277 if( (x.accError & SQLITE_NOMEM)!=0 ){
79278 sqlite3OomFault(db);
79279 }
79280 return sqlite3StrAccumFinish(&x);
79281 }
79282 #endif /* VDBE_DISPLAY_P4 */
79283
79284 /*
79285 ** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
@@ -79080,28 +79365,34 @@
79365 /*
79366 ** Print a single opcode. This routine is used for debugging only.
79367 */
79368 SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
79369 char *zP4;
79370 char *zCom;
79371 sqlite3 dummyDb;
79372 static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
79373 if( pOut==0 ) pOut = stdout;
79374 sqlite3BeginBenignMalloc();
79375 dummyDb.mallocFailed = 1;
79376 zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
79377 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79378 zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
79379 #else
79380 zCom = 0;
79381 #endif
79382 /* NB: The sqlite3OpcodeName() function is implemented by code created
79383 ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
79384 ** information from the vdbe.c source text */
79385 fprintf(pOut, zFormat1, pc,
79386 sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3,
79387 zP4 ? zP4 : "", pOp->p5,
79388 zCom ? zCom : ""
79389 );
79390 fflush(pOut);
79391 sqlite3_free(zP4);
79392 sqlite3_free(zCom);
79393 sqlite3EndBenignMalloc();
79394 }
79395 #endif
79396
79397 /*
79398 ** Initialize an array of N Mem element.
@@ -79188,10 +79479,125 @@
79479 assert( sqlite3VdbeFrameIsValid(pFrame) );
79480 pFrame->pParent = pFrame->v->pDelFrame;
79481 pFrame->v->pDelFrame = pFrame;
79482 }
79483
79484 #if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN)
79485 /*
79486 ** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
79487 ** QUERY PLAN output.
79488 **
79489 ** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no
79490 ** more opcodes to be displayed.
79491 */
79492 SQLITE_PRIVATE int sqlite3VdbeNextOpcode(
79493 Vdbe *p, /* The statement being explained */
79494 Mem *pSub, /* Storage for keeping track of subprogram nesting */
79495 int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */
79496 int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */
79497 int *piAddr, /* OUT: Write index into (*paOp)[] here */
79498 Op **paOp /* OUT: Write the opcode array here */
79499 ){
79500 int nRow; /* Stop when row count reaches this */
79501 int nSub = 0; /* Number of sub-vdbes seen so far */
79502 SubProgram **apSub = 0; /* Array of sub-vdbes */
79503 int i; /* Next instruction address */
79504 int rc = SQLITE_OK; /* Result code */
79505 Op *aOp = 0; /* Opcode array */
79506 int iPc; /* Rowid. Copy of value in *piPc */
79507
79508 /* When the number of output rows reaches nRow, that means the
79509 ** listing has finished and sqlite3_step() should return SQLITE_DONE.
79510 ** nRow is the sum of the number of rows in the main program, plus
79511 ** the sum of the number of rows in all trigger subprograms encountered
79512 ** so far. The nRow value will increase as new trigger subprograms are
79513 ** encountered, but p->pc will eventually catch up to nRow.
79514 */
79515 nRow = p->nOp;
79516 if( pSub!=0 ){
79517 if( pSub->flags&MEM_Blob ){
79518 /* pSub is initiallly NULL. It is initialized to a BLOB by
79519 ** the P4_SUBPROGRAM processing logic below */
79520 nSub = pSub->n/sizeof(Vdbe*);
79521 apSub = (SubProgram **)pSub->z;
79522 }
79523 for(i=0; i<nSub; i++){
79524 nRow += apSub[i]->nOp;
79525 }
79526 }
79527 iPc = *piPc;
79528 while(1){ /* Loop exits via break */
79529 i = iPc++;
79530 if( i>=nRow ){
79531 p->rc = SQLITE_OK;
79532 rc = SQLITE_DONE;
79533 break;
79534 }
79535 if( i<p->nOp ){
79536 /* The rowid is small enough that we are still in the
79537 ** main program. */
79538 aOp = p->aOp;
79539 }else{
79540 /* We are currently listing subprograms. Figure out which one and
79541 ** pick up the appropriate opcode. */
79542 int j;
79543 i -= p->nOp;
79544 assert( apSub!=0 );
79545 assert( nSub>0 );
79546 for(j=0; i>=apSub[j]->nOp; j++){
79547 i -= apSub[j]->nOp;
79548 assert( i<apSub[j]->nOp || j+1<nSub );
79549 }
79550 aOp = apSub[j]->aOp;
79551 }
79552
79553 /* When an OP_Program opcode is encounter (the only opcode that has
79554 ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
79555 ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
79556 ** has not already been seen.
79557 */
79558 if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
79559 int nByte = (nSub+1)*sizeof(SubProgram*);
79560 int j;
79561 for(j=0; j<nSub; j++){
79562 if( apSub[j]==aOp[i].p4.pProgram ) break;
79563 }
79564 if( j==nSub ){
79565 p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
79566 if( p->rc!=SQLITE_OK ){
79567 rc = SQLITE_ERROR;
79568 break;
79569 }
79570 apSub = (SubProgram **)pSub->z;
79571 apSub[nSub++] = aOp[i].p4.pProgram;
79572 MemSetTypeFlag(pSub, MEM_Blob);
79573 pSub->n = nSub*sizeof(SubProgram*);
79574 nRow += aOp[i].p4.pProgram->nOp;
79575 }
79576 }
79577 if( eMode==0 ) break;
79578 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
79579 if( eMode==2 ){
79580 Op *pOp = aOp + i;
79581 if( pOp->opcode==OP_OpenRead ) break;
79582 if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
79583 if( pOp->opcode==OP_ReopenIdx ) break;
79584 }else
79585 #endif
79586 {
79587 assert( eMode==1 );
79588 if( aOp[i].opcode==OP_Explain ) break;
79589 if( aOp[i].opcode==OP_Init && iPc>1 ) break;
79590 }
79591 }
79592 *piPc = iPc;
79593 *piAddr = i;
79594 *paOp = aOp;
79595 return rc;
79596 }
79597 #endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */
79598
79599
79600 /*
79601 ** Delete a VdbeFrame object and its contents. VdbeFrame objects are
79602 ** allocated by the OP_Program opcode in sqlite3VdbeExec().
79603 */
@@ -79228,20 +79634,18 @@
79634 ** the trigger subprograms are listed one by one.
79635 */
79636 SQLITE_PRIVATE int sqlite3VdbeList(
79637 Vdbe *p /* The VDBE */
79638 ){
 
 
 
79639 Mem *pSub = 0; /* Memory cell hold array of subprogs */
79640 sqlite3 *db = p->db; /* The database connection */
79641 int i; /* Loop counter */
79642 int rc = SQLITE_OK; /* Return code */
79643 Mem *pMem = &p->aMem[1]; /* First Mem of result set */
79644 int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
79645 Op *aOp; /* Array of opcodes */
79646 Op *pOp; /* Current opcode */
79647
79648 assert( p->explain );
79649 assert( p->magic==VDBE_MAGIC_RUN );
79650 assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
79651
@@ -79257,166 +79661,66 @@
79661 ** sqlite3_column_text16() failed. */
79662 sqlite3OomFault(db);
79663 return SQLITE_ERROR;
79664 }
79665
 
 
 
 
 
 
 
 
79666 if( bListSubprogs ){
79667 /* The first 8 memory cells are used for the result set. So we will
79668 ** commandeer the 9th cell to use as storage for an array of pointers
79669 ** to trigger subprograms. The VDBE is guaranteed to have at least 9
79670 ** cells. */
79671 assert( p->nMem>9 );
79672 pSub = &p->aMem[9];
79673 }else{
79674 pSub = 0;
79675 }
79676
79677 /* Figure out which opcode is next to display */
79678 rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
79679
79680 if( rc==SQLITE_OK ){
79681 pOp = aOp + i;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79682 if( AtomicLoad(&db->u1.isInterrupted) ){
79683 p->rc = SQLITE_INTERRUPT;
79684 rc = SQLITE_ERROR;
79685 sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
79686 }else{
79687 char *zP4 = sqlite3VdbeDisplayP4(db, pOp);
79688 if( p->explain==2 ){
79689 sqlite3VdbeMemSetInt64(pMem, pOp->p1);
79690 sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
79691 sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
79692 sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);
79693 p->nResColumn = 4;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79694 }else{
79695 sqlite3VdbeMemSetInt64(pMem+0, i);
79696 sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
79697 -1, SQLITE_UTF8, SQLITE_STATIC);
79698 sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
79699 sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
79700 sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
79701 /* pMem+5 for p4 is done last */
79702 sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
 
 
 
 
 
 
 
 
 
79703 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
79704 {
79705 char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4);
79706 sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
79707 }
79708 #else
79709 sqlite3VdbeMemSetNull(pMem+7);
79710 #endif
79711 sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
79712 p->nResColumn = 8;
79713 }
79714 p->pResultSet = pMem;
79715 if( db->mallocFailed ){
79716 p->rc = SQLITE_NOMEM;
79717 rc = SQLITE_ERROR;
79718 }else{
79719 p->rc = SQLITE_OK;
79720 rc = SQLITE_ROW;
79721 }
79722 }
79723 }
79724 return rc;
79725 }
79726 #endif /* SQLITE_OMIT_EXPLAIN */
@@ -79982,12 +80286,13 @@
80286 int retryCount = 0;
80287 int nMainFile;
80288
80289 /* Select a master journal file name */
80290 nMainFile = sqlite3Strlen30(zMainFile);
80291 zMaster = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0);
80292 if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
80293 zMaster += 4;
80294 do {
80295 u32 iRandom;
80296 if( retryCount ){
80297 if( retryCount>100 ){
80298 sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
@@ -80013,11 +80318,11 @@
80318 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
80319 SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
80320 );
80321 }
80322 if( rc!=SQLITE_OK ){
80323 sqlite3DbFree(db, zMaster-4);
80324 return rc;
80325 }
80326
80327 /* Write the name of each database file in the transaction into the new
80328 ** master journal file. If an error occurs at this point close
@@ -80036,11 +80341,11 @@
80341 rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
80342 offset += sqlite3Strlen30(zFile)+1;
80343 if( rc!=SQLITE_OK ){
80344 sqlite3OsCloseFree(pMaster);
80345 sqlite3OsDelete(pVfs, zMaster, 0);
80346 sqlite3DbFree(db, zMaster-4);
80347 return rc;
80348 }
80349 }
80350 }
80351
@@ -80050,11 +80355,11 @@
80355 if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
80356 && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
80357 ){
80358 sqlite3OsCloseFree(pMaster);
80359 sqlite3OsDelete(pVfs, zMaster, 0);
80360 sqlite3DbFree(db, zMaster-4);
80361 return rc;
80362 }
80363
80364 /* Sync all the db files involved in the transaction. The same call
80365 ** sets the master journal pointer in each individual journal. If
@@ -80073,20 +80378,20 @@
80378 }
80379 }
80380 sqlite3OsCloseFree(pMaster);
80381 assert( rc!=SQLITE_BUSY );
80382 if( rc!=SQLITE_OK ){
80383 sqlite3DbFree(db, zMaster-4);
80384 return rc;
80385 }
80386
80387 /* Delete the master journal file. This commits the transaction. After
80388 ** doing this the directory is synced again before any individual
80389 ** transaction files are deleted.
80390 */
80391 rc = sqlite3OsDelete(pVfs, zMaster, 1);
80392 sqlite3DbFree(db, zMaster-4);
80393 zMaster = 0;
80394 if( rc ){
80395 return rc;
80396 }
80397
@@ -83825,11 +84130,11 @@
84130 p->db->errCode = SQLITE_OK;
84131
84132 /* If the bit corresponding to this variable in Vdbe.expmask is set, then
84133 ** binding a new value to this variable invalidates the current query plan.
84134 **
84135 ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
84136 ** parameter in the WHERE clause might influence the choice of query plan
84137 ** for a statement, then the statement will be automatically recompiled,
84138 ** as if there had been a schema change, on the first sqlite3_step() call
84139 ** following any change to the bindings of that parameter.
84140 */
@@ -87998,32 +88303,38 @@
88303 assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
88304 REGISTER_TRACE(pOp->p3, pOut);
88305 break;
88306 }
88307
88308 /* Opcode: Count P1 P2 p3 * *
88309 ** Synopsis: r[P2]=count()
88310 **
88311 ** Store the number of entries (an integer value) in the table or index
88312 ** opened by cursor P1 in register P2.
88313 **
88314 ** If P3==0, then an exact count is obtained, which involves visiting
88315 ** every btree page of the table. But if P3 is non-zero, an estimate
88316 ** is returned based on the current cursor position.
88317 */
 
88318 case OP_Count: { /* out2 */
88319 i64 nEntry;
88320 BtCursor *pCrsr;
88321
88322 assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
88323 pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
88324 assert( pCrsr );
88325 if( pOp->p3 ){
88326 nEntry = sqlite3BtreeRowCountEst(pCrsr);
88327 }else{
88328 nEntry = 0; /* Not needed. Only used to silence a warning. */
88329 rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
88330 if( rc ) goto abort_due_to_error;
88331 }
88332 pOut = out2Prerelease(p, pOp);
88333 pOut->u.i = nEntry;
88334 goto check_for_interrupt;
88335 }
 
88336
88337 /* Opcode: Savepoint P1 * * P4 *
88338 **
88339 ** Open, release or rollback the savepoint named by parameter P4, depending
88340 ** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN).
@@ -90457,16 +90768,23 @@
90768 rc = sqlite3VdbeSorterWrite(pC, pIn2);
90769 if( rc) goto abort_due_to_error;
90770 break;
90771 }
90772
90773 /* Opcode: IdxDelete P1 P2 P3 * P5
90774 ** Synopsis: key=r[P2@P3]
90775 **
90776 ** The content of P3 registers starting at register P2 form
90777 ** an unpacked index key. This opcode removes that entry from the
90778 ** index opened by cursor P1.
90779 **
90780 ** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
90781 ** if no matching index entry is found. This happens when running
90782 ** an UPDATE or DELETE statement and the index entry to be updated
90783 ** or deleted is not found. For some uses of IdxDelete
90784 ** (example: the EXCEPT operator) it does not matter that no matching
90785 ** entry is found. For those cases, P5 is zero.
90786 */
90787 case OP_IdxDelete: {
90788 VdbeCursor *pC;
90789 BtCursor *pCrsr;
90790 int res;
@@ -90479,20 +90797,22 @@
90797 assert( pC!=0 );
90798 assert( pC->eCurType==CURTYPE_BTREE );
90799 sqlite3VdbeIncrWriteCounter(p, pC);
90800 pCrsr = pC->uc.pCursor;
90801 assert( pCrsr!=0 );
 
90802 r.pKeyInfo = pC->pKeyInfo;
90803 r.nField = (u16)pOp->p3;
90804 r.default_rc = 0;
90805 r.aMem = &aMem[pOp->p2];
90806 rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
90807 if( rc ) goto abort_due_to_error;
90808 if( res==0 ){
90809 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
90810 if( rc ) goto abort_due_to_error;
90811 }else if( pOp->p5 ){
90812 rc = SQLITE_CORRUPT_INDEX;
90813 goto abort_due_to_error;
90814 }
90815 assert( pC->deferredMoveto==0 );
90816 pC->cacheStatus = CACHE_STALE;
90817 pC->seekResult = 0;
90818 break;
@@ -96093,10 +96413,437 @@
96413 *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
96414 return SQLITE_OK;
96415 }
96416
96417 /************** End of vdbesort.c ********************************************/
96418 /************** Begin file vdbevtab.c ****************************************/
96419 /*
96420 ** 2020-03-23
96421 **
96422 ** The author disclaims copyright to this source code. In place of
96423 ** a legal notice, here is a blessing:
96424 **
96425 ** May you do good and not evil.
96426 ** May you find forgiveness for yourself and forgive others.
96427 ** May you share freely, never taking more than you give.
96428 **
96429 *************************************************************************
96430 **
96431 ** This file implements virtual-tables for examining the bytecode content
96432 ** of a prepared statement.
96433 */
96434 /* #include "sqliteInt.h" */
96435 #if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
96436 /* #include "vdbeInt.h" */
96437
96438 /* An instance of the bytecode() table-valued function.
96439 */
96440 typedef struct bytecodevtab bytecodevtab;
96441 struct bytecodevtab {
96442 sqlite3_vtab base; /* Base class - must be first */
96443 sqlite3 *db; /* Database connection */
96444 int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */
96445 };
96446
96447 /* A cursor for scanning through the bytecode
96448 */
96449 typedef struct bytecodevtab_cursor bytecodevtab_cursor;
96450 struct bytecodevtab_cursor {
96451 sqlite3_vtab_cursor base; /* Base class - must be first */
96452 sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */
96453 int iRowid; /* The rowid of the output table */
96454 int iAddr; /* Address */
96455 int needFinalize; /* Cursors owns pStmt and must finalize it */
96456 int showSubprograms; /* Provide a listing of subprograms */
96457 Op *aOp; /* Operand array */
96458 char *zP4; /* Rendered P4 value */
96459 const char *zType; /* tables_used.type */
96460 const char *zSchema; /* tables_used.schema */
96461 const char *zName; /* tables_used.name */
96462 Mem sub; /* Subprograms */
96463 };
96464
96465 /*
96466 ** Create a new bytecode() table-valued function.
96467 */
96468 static int bytecodevtabConnect(
96469 sqlite3 *db,
96470 void *pAux,
96471 int argc, const char *const*argv,
96472 sqlite3_vtab **ppVtab,
96473 char **pzErr
96474 ){
96475 bytecodevtab *pNew;
96476 int rc;
96477 int isTabUsed = pAux!=0;
96478 const char *azSchema[2] = {
96479 /* bytecode() schema */
96480 "CREATE TABLE x("
96481 "addr INT,"
96482 "opcode TEXT,"
96483 "p1 INT,"
96484 "p2 INT,"
96485 "p3 INT,"
96486 "p4 TEXT,"
96487 "p5 INT,"
96488 "comment TEXT,"
96489 "subprog TEXT,"
96490 "stmt HIDDEN"
96491 ");",
96492
96493 /* Tables_used() schema */
96494 "CREATE TABLE x("
96495 "type TEXT,"
96496 "schema TEXT,"
96497 "name TEXT,"
96498 "wr INT,"
96499 "subprog TEXT,"
96500 "stmt HIDDEN"
96501 ");"
96502 };
96503
96504 rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
96505 if( rc==SQLITE_OK ){
96506 pNew = sqlite3_malloc( sizeof(*pNew) );
96507 *ppVtab = (sqlite3_vtab*)pNew;
96508 if( pNew==0 ) return SQLITE_NOMEM;
96509 memset(pNew, 0, sizeof(*pNew));
96510 pNew->db = db;
96511 pNew->bTablesUsed = isTabUsed*2;
96512 }
96513 return rc;
96514 }
96515
96516 /*
96517 ** This method is the destructor for bytecodevtab objects.
96518 */
96519 static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
96520 bytecodevtab *p = (bytecodevtab*)pVtab;
96521 sqlite3_free(p);
96522 return SQLITE_OK;
96523 }
96524
96525 /*
96526 ** Constructor for a new bytecodevtab_cursor object.
96527 */
96528 static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
96529 bytecodevtab *pVTab = (bytecodevtab*)p;
96530 bytecodevtab_cursor *pCur;
96531 pCur = sqlite3_malloc( sizeof(*pCur) );
96532 if( pCur==0 ) return SQLITE_NOMEM;
96533 memset(pCur, 0, sizeof(*pCur));
96534 sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
96535 *ppCursor = &pCur->base;
96536 return SQLITE_OK;
96537 }
96538
96539 /*
96540 ** Clear all internal content from a bytecodevtab cursor.
96541 */
96542 static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
96543 sqlite3_free(pCur->zP4);
96544 pCur->zP4 = 0;
96545 sqlite3VdbeMemRelease(&pCur->sub);
96546 sqlite3VdbeMemSetNull(&pCur->sub);
96547 if( pCur->needFinalize ){
96548 sqlite3_finalize(pCur->pStmt);
96549 }
96550 pCur->pStmt = 0;
96551 pCur->needFinalize = 0;
96552 pCur->zType = 0;
96553 pCur->zSchema = 0;
96554 pCur->zName = 0;
96555 }
96556
96557 /*
96558 ** Destructor for a bytecodevtab_cursor.
96559 */
96560 static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
96561 bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96562 bytecodevtabCursorClear(pCur);
96563 sqlite3_free(pCur);
96564 return SQLITE_OK;
96565 }
96566
96567
96568 /*
96569 ** Advance a bytecodevtab_cursor to its next row of output.
96570 */
96571 static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
96572 bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96573 bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
96574 int rc;
96575 if( pCur->zP4 ){
96576 sqlite3_free(pCur->zP4);
96577 pCur->zP4 = 0;
96578 }
96579 if( pCur->zName ){
96580 pCur->zName = 0;
96581 pCur->zType = 0;
96582 pCur->zSchema = 0;
96583 }
96584 rc = sqlite3VdbeNextOpcode(
96585 (Vdbe*)pCur->pStmt,
96586 pCur->showSubprograms ? &pCur->sub : 0,
96587 pTab->bTablesUsed,
96588 &pCur->iRowid,
96589 &pCur->iAddr,
96590 &pCur->aOp);
96591 if( rc!=SQLITE_OK ){
96592 sqlite3VdbeMemSetNull(&pCur->sub);
96593 pCur->aOp = 0;
96594 }
96595 return SQLITE_OK;
96596 }
96597
96598 /*
96599 ** Return TRUE if the cursor has been moved off of the last
96600 ** row of output.
96601 */
96602 static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
96603 bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96604 return pCur->aOp==0;
96605 }
96606
96607 /*
96608 ** Return values of columns for the row at which the bytecodevtab_cursor
96609 ** is currently pointing.
96610 */
96611 static int bytecodevtabColumn(
96612 sqlite3_vtab_cursor *cur, /* The cursor */
96613 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
96614 int i /* Which column to return */
96615 ){
96616 bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96617 bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
96618 Op *pOp = pCur->aOp + pCur->iAddr;
96619 if( pVTab->bTablesUsed ){
96620 if( i==4 ){
96621 i = 8;
96622 }else{
96623 if( i<=2 && pCur->zType==0 ){
96624 Schema *pSchema;
96625 HashElem *k;
96626 int iDb = pOp->p3;
96627 int iRoot = pOp->p2;
96628 sqlite3 *db = pVTab->db;
96629 pSchema = db->aDb[iDb].pSchema;
96630 pCur->zSchema = db->aDb[iDb].zDbSName;
96631 for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
96632 Table *pTab = (Table*)sqliteHashData(k);
96633 if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
96634 pCur->zName = pTab->zName;
96635 pCur->zType = "table";
96636 break;
96637 }
96638 }
96639 if( pCur->zName==0 ){
96640 for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
96641 Index *pIdx = (Index*)sqliteHashData(k);
96642 if( pIdx->tnum==iRoot ){
96643 pCur->zName = pIdx->zName;
96644 pCur->zType = "index";
96645 }
96646 }
96647 }
96648 }
96649 i += 10;
96650 }
96651 }
96652 switch( i ){
96653 case 0: /* addr */
96654 sqlite3_result_int(ctx, pCur->iAddr);
96655 break;
96656 case 1: /* opcode */
96657 sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
96658 -1, SQLITE_STATIC);
96659 break;
96660 case 2: /* p1 */
96661 sqlite3_result_int(ctx, pOp->p1);
96662 break;
96663 case 3: /* p2 */
96664 sqlite3_result_int(ctx, pOp->p2);
96665 break;
96666 case 4: /* p3 */
96667 sqlite3_result_int(ctx, pOp->p3);
96668 break;
96669 case 5: /* p4 */
96670 case 7: /* comment */
96671 if( pCur->zP4==0 ){
96672 pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
96673 }
96674 if( i==5 ){
96675 sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
96676 }else{
96677 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
96678 char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
96679 sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
96680 #endif
96681 }
96682 break;
96683 case 6: /* p5 */
96684 sqlite3_result_int(ctx, pOp->p5);
96685 break;
96686 case 8: { /* subprog */
96687 Op *aOp = pCur->aOp;
96688 assert( aOp[0].opcode==OP_Init );
96689 assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
96690 if( pCur->iRowid==pCur->iAddr+1 ){
96691 break; /* Result is NULL for the main program */
96692 }else if( aOp[0].p4.z!=0 ){
96693 sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
96694 }else{
96695 sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
96696 }
96697 break;
96698 }
96699 case 10: /* tables_used.type */
96700 sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
96701 break;
96702 case 11: /* tables_used.schema */
96703 sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
96704 break;
96705 case 12: /* tables_used.name */
96706 sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
96707 break;
96708 case 13: /* tables_used.wr */
96709 sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
96710 break;
96711 }
96712 return SQLITE_OK;
96713 }
96714
96715 /*
96716 ** Return the rowid for the current row. In this implementation, the
96717 ** rowid is the same as the output value.
96718 */
96719 static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
96720 bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
96721 *pRowid = pCur->iRowid;
96722 return SQLITE_OK;
96723 }
96724
96725 /*
96726 ** Initialize a cursor.
96727 **
96728 ** idxNum==0 means show all subprograms
96729 ** idxNum==1 means show only the main bytecode and omit subprograms.
96730 */
96731 static int bytecodevtabFilter(
96732 sqlite3_vtab_cursor *pVtabCursor,
96733 int idxNum, const char *idxStr,
96734 int argc, sqlite3_value **argv
96735 ){
96736 bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
96737 bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
96738 int rc = SQLITE_OK;
96739
96740 bytecodevtabCursorClear(pCur);
96741 pCur->iRowid = 0;
96742 pCur->iAddr = 0;
96743 pCur->showSubprograms = idxNum==0;
96744 assert( argc==1 );
96745 if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
96746 const char *zSql = (const char*)sqlite3_value_text(argv[0]);
96747 if( zSql==0 ){
96748 rc = SQLITE_NOMEM;
96749 }else{
96750 rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
96751 pCur->needFinalize = 1;
96752 }
96753 }else{
96754 pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
96755 }
96756 if( pCur->pStmt==0 ){
96757 pVTab->base.zErrMsg = sqlite3_mprintf(
96758 "argument to %s() is not a valid SQL statement",
96759 pVTab->bTablesUsed ? "tables_used" : "bytecode"
96760 );
96761 rc = SQLITE_ERROR;
96762 }else{
96763 bytecodevtabNext(pVtabCursor);
96764 }
96765 return rc;
96766 }
96767
96768 /*
96769 ** We must have a single stmt=? constraint that will be passed through
96770 ** into the xFilter method. If there is no valid stmt=? constraint,
96771 ** then return an SQLITE_CONSTRAINT error.
96772 */
96773 static int bytecodevtabBestIndex(
96774 sqlite3_vtab *tab,
96775 sqlite3_index_info *pIdxInfo
96776 ){
96777 int i;
96778 int rc = SQLITE_CONSTRAINT;
96779 struct sqlite3_index_constraint *p;
96780 bytecodevtab *pVTab = (bytecodevtab*)tab;
96781 int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
96782 pIdxInfo->estimatedCost = (double)100;
96783 pIdxInfo->estimatedRows = 100;
96784 pIdxInfo->idxNum = 0;
96785 for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
96786 if( p->usable==0 ) continue;
96787 if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
96788 rc = SQLITE_OK;
96789 pIdxInfo->aConstraintUsage[i].omit = 1;
96790 pIdxInfo->aConstraintUsage[i].argvIndex = 1;
96791 }
96792 if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
96793 pIdxInfo->aConstraintUsage[i].omit = 1;
96794 pIdxInfo->idxNum = 1;
96795 }
96796 }
96797 return rc;
96798 }
96799
96800 /*
96801 ** This following structure defines all the methods for the
96802 ** virtual table.
96803 */
96804 static sqlite3_module bytecodevtabModule = {
96805 /* iVersion */ 0,
96806 /* xCreate */ 0,
96807 /* xConnect */ bytecodevtabConnect,
96808 /* xBestIndex */ bytecodevtabBestIndex,
96809 /* xDisconnect */ bytecodevtabDisconnect,
96810 /* xDestroy */ 0,
96811 /* xOpen */ bytecodevtabOpen,
96812 /* xClose */ bytecodevtabClose,
96813 /* xFilter */ bytecodevtabFilter,
96814 /* xNext */ bytecodevtabNext,
96815 /* xEof */ bytecodevtabEof,
96816 /* xColumn */ bytecodevtabColumn,
96817 /* xRowid */ bytecodevtabRowid,
96818 /* xUpdate */ 0,
96819 /* xBegin */ 0,
96820 /* xSync */ 0,
96821 /* xCommit */ 0,
96822 /* xRollback */ 0,
96823 /* xFindMethod */ 0,
96824 /* xRename */ 0,
96825 /* xSavepoint */ 0,
96826 /* xRelease */ 0,
96827 /* xRollbackTo */ 0,
96828 /* xShadowName */ 0
96829 };
96830
96831
96832 SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
96833 int rc;
96834 rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
96835 if( rc==SQLITE_OK ){
96836 rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
96837 }
96838 return rc;
96839 }
96840 #elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
96841 SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
96842 #endif /* SQLITE_ENABLE_BYTECODE_VTAB */
96843
96844 /************** End of vdbevtab.c ********************************************/
96845 /************** Begin file memjournal.c **************************************/
96846 /*
96847 ** 2008 October 7
96848 **
96849 ** The author disclaims copyright to this source code. In place of
@@ -96735,10 +97482,47 @@
97482 }
97483 p = p->pPrior;
97484 }while( p!=0 );
97485 return WRC_Continue;
97486 }
97487
97488 /* Increase the walkerDepth when entering a subquery, and
97489 ** descrease when leaving the subquery.
97490 */
97491 SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){
97492 UNUSED_PARAMETER(pSelect);
97493 pWalker->walkerDepth++;
97494 return WRC_Continue;
97495 }
97496 SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){
97497 UNUSED_PARAMETER(pSelect);
97498 pWalker->walkerDepth--;
97499 }
97500
97501
97502 /*
97503 ** No-op routine for the parse-tree walker.
97504 **
97505 ** When this routine is the Walker.xExprCallback then expression trees
97506 ** are walked without any actions being taken at each node. Presumably,
97507 ** when this routine is used for Walker.xExprCallback then
97508 ** Walker.xSelectCallback is set to do something useful for every
97509 ** subquery in the parser tree.
97510 */
97511 SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
97512 UNUSED_PARAMETER2(NotUsed, NotUsed2);
97513 return WRC_Continue;
97514 }
97515
97516 /*
97517 ** No-op routine for the parse-tree walker for SELECT statements.
97518 ** subquery in the parser tree.
97519 */
97520 SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
97521 UNUSED_PARAMETER2(NotUsed, NotUsed2);
97522 return WRC_Continue;
97523 }
97524
97525 /************** End of walker.c **********************************************/
97526 /************** Begin file resolve.c *****************************************/
97527 /*
97528 ** 2008 August 18
@@ -96764,10 +97548,12 @@
97548 ** This needs to occur when copying a TK_AGG_FUNCTION node from an
97549 ** outer query into an inner subquery.
97550 **
97551 ** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
97552 ** is a helper function - a callback for the tree walker.
97553 **
97554 ** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c
97555 */
97556 static int incrAggDepth(Walker *pWalker, Expr *pExpr){
97557 if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
97558 return WRC_Continue;
97559 }
@@ -98739,11 +99525,11 @@
99525 ** SELECT * FROM t1 WHERE (select a from t1);
99526 */
99527 SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
99528 int op;
99529 while( ExprHasProperty(pExpr, EP_Skip) ){
99530 assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
99531 pExpr = pExpr->pLeft;
99532 assert( pExpr!=0 );
99533 }
99534 op = pExpr->op;
99535 if( op==TK_SELECT ){
@@ -98806,11 +99592,11 @@
99592 /*
99593 ** Skip over any TK_COLLATE operators.
99594 */
99595 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
99596 while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
99597 assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
99598 pExpr = pExpr->pLeft;
99599 }
99600 return pExpr;
99601 }
99602
@@ -98825,11 +99611,11 @@
99611 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
99612 assert( pExpr->x.pList->nExpr>0 );
99613 assert( pExpr->op==TK_FUNCTION );
99614 pExpr = pExpr->x.pList->a[0].pExpr;
99615 }else{
99616 assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
99617 pExpr = pExpr->pLeft;
99618 }
99619 }
99620 return pExpr;
99621 }
@@ -102394,10 +103180,17 @@
103180 }
103181 setDoNotMergeFlagOnCopy(v);
103182 sqlite3VdbeResolveLabel(v, endCoalesce);
103183 break;
103184 }
103185 case INLINEFUNC_iif: {
103186 Expr caseExpr;
103187 memset(&caseExpr, 0, sizeof(caseExpr));
103188 caseExpr.op = TK_CASE;
103189 caseExpr.x.pList = pFarg;
103190 return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
103191 }
103192
103193 default: {
103194 /* The UNLIKELY() function is a no-op. The result is the value
103195 ** of the first argument.
103196 */
@@ -102498,11 +103291,14 @@
103291 op = pExpr->op;
103292 }
103293 switch( op ){
103294 case TK_AGG_COLUMN: {
103295 AggInfo *pAggInfo = pExpr->pAggInfo;
103296 struct AggInfo_col *pCol;
103297 assert( pAggInfo!=0 );
103298 assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
103299 pCol = &pAggInfo->aCol[pExpr->iAgg];
103300 if( !pAggInfo->directMode ){
103301 assert( pCol->iMem>0 );
103302 return pCol->iMem;
103303 }else if( pAggInfo->useSortingIdx ){
103304 Table *pTab = pCol->pTab;
@@ -102798,11 +103594,14 @@
103594 sqlite3VdbeJumpHere(v, addr);
103595 break;
103596 }
103597 case TK_AGG_FUNCTION: {
103598 AggInfo *pInfo = pExpr->pAggInfo;
103599 if( pInfo==0
103600 || NEVER(pExpr->iAgg<0)
103601 || NEVER(pExpr->iAgg>=pInfo->nFunc)
103602 ){
103603 assert( !ExprHasProperty(pExpr, EP_IntValue) );
103604 sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
103605 }else{
103606 return pInfo->aFunc[pExpr->iAgg].iMem;
103607 }
@@ -103176,11 +103975,11 @@
103975 assert( pExpr->affExpr==OE_Rollback
103976 || pExpr->affExpr==OE_Abort
103977 || pExpr->affExpr==OE_Fail
103978 || pExpr->affExpr==OE_Ignore
103979 );
103980 if( !pParse->pTriggerTab && !pParse->nested ){
103981 sqlite3ErrorMsg(pParse,
103982 "RAISE() may only be used within a trigger-program");
103983 return 0;
103984 }
103985 if( pExpr->affExpr==OE_Abort ){
@@ -103190,12 +103989,13 @@
103989 if( pExpr->affExpr==OE_Ignore ){
103990 sqlite3VdbeAddOp4(
103991 v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
103992 VdbeCoverage(v);
103993 }else{
103994 sqlite3HaltConstraint(pParse,
103995 pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
103996 pExpr->affExpr, pExpr->u.zToken, 0, 0);
103997 }
103998
103999 break;
104000 }
104001 #endif
@@ -104553,19 +105353,10 @@
105353 }
105354 }
105355 }
105356 return WRC_Continue;
105357 }
 
 
 
 
 
 
 
 
 
105358
105359 /*
105360 ** Analyze the pExpr expression looking for aggregate functions and
105361 ** for variables that need to be added to AggInfo object that pNC->pAggInfo
105362 ** points to. Additional entries are made on the AggInfo object as
@@ -104575,12 +105366,12 @@
105366 ** analyzed by sqlite3ResolveExprNames().
105367 */
105368 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
105369 Walker w;
105370 w.xExprCallback = analyzeAggregate;
105371 w.xSelectCallback = sqlite3WalkerDepthIncrease;
105372 w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
105373 w.walkerDepth = 0;
105374 w.u.pNC = pNC;
105375 w.pParse = 0;
105376 assert( pNC->pSrcList!=0 );
105377 sqlite3WalkExpr(&w, pExpr);
@@ -104815,11 +105606,14 @@
105606 if( !zName ) goto exit_rename_table;
105607
105608 /* Check that a table or index named 'zName' does not already exist
105609 ** in database iDb. If so, this is an error.
105610 */
105611 if( sqlite3FindTable(db, zName, zDb)
105612 || sqlite3FindIndex(db, zName, zDb)
105613 || sqlite3IsShadowTableOf(db, pTab, zName)
105614 ){
105615 sqlite3ErrorMsg(pParse,
105616 "there is already another table or index with this name: %s", zName);
105617 goto exit_rename_table;
105618 }
105619
@@ -104946,10 +105740,26 @@
105740 exit_rename_table:
105741 sqlite3SrcListDelete(db, pSrc);
105742 sqlite3DbFree(db, zName);
105743 db->mDbFlags = savedDbFlags;
105744 }
105745
105746 /*
105747 ** Write code that will raise an error if the table described by
105748 ** zDb and zTab is not empty.
105749 */
105750 static void sqlite3ErrorIfNotEmpty(
105751 Parse *pParse, /* Parsing context */
105752 const char *zDb, /* Schema holding the table */
105753 const char *zTab, /* Table to check for empty */
105754 const char *zErr /* Error message text */
105755 ){
105756 sqlite3NestedParse(pParse,
105757 "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",
105758 zErr, zDb, zTab
105759 );
105760 }
105761
105762 /*
105763 ** This function is called after an "ALTER TABLE ... ADD" statement
105764 ** has been parsed. Argument pColDef contains the text of the new
105765 ** column definition.
@@ -104999,11 +105809,12 @@
105809 if( pCol->colFlags & COLFLAG_PRIMKEY ){
105810 sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
105811 return;
105812 }
105813 if( pNew->pIndex ){
105814 sqlite3ErrorMsg(pParse,
105815 "Cannot add a UNIQUE column");
105816 return;
105817 }
105818 if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
105819 /* If the default value for the new column was specified with a
105820 ** literal NULL, then set pDflt to 0. This simplifies checking
@@ -105012,19 +105823,18 @@
105823 assert( pDflt==0 || pDflt->op==TK_SPAN );
105824 if( pDflt && pDflt->pLeft->op==TK_NULL ){
105825 pDflt = 0;
105826 }
105827 if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
105828 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
105829 "Cannot add a REFERENCES column with non-NULL default value");
 
105830 }
105831 if( pCol->notNull && !pDflt ){
105832 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
105833 "Cannot add a NOT NULL column with default value NULL");
 
105834 }
105835
105836
105837 /* Ensure the default expression is something that sqlite3ValueFromExpr()
105838 ** can handle (i.e. not CURRENT_TIME etc.)
105839 */
105840 if( pDflt ){
@@ -105035,18 +105845,17 @@
105845 if( rc!=SQLITE_OK ){
105846 assert( db->mallocFailed == 1 );
105847 return;
105848 }
105849 if( !pVal ){
105850 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
105851 "Cannot add a column with non-constant default");
105852 }
105853 sqlite3ValueFree(pVal);
105854 }
105855 }else if( pCol->colFlags & COLFLAG_STORED ){
105856 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column");
 
105857 }
105858
105859
105860 /* Modify the CREATE TABLE statement. */
105861 zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
@@ -106605,10 +107414,15 @@
107414 sqlite3 *db = pParse->db;
107415 Db *pDb;
107416 Vdbe *v = sqlite3GetVdbe(pParse);
107417 int aRoot[ArraySize(aTable)];
107418 u8 aCreateTbl[ArraySize(aTable)];
107419 #ifdef SQLITE_ENABLE_STAT4
107420 const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
107421 #else
107422 const int nToOpen = 1;
107423 #endif
107424
107425 if( v==0 ) return;
107426 assert( sqlite3BtreeHoldsAllMutexes(db) );
107427 assert( sqlite3VdbeDb(v)==db );
107428 pDb = &db->aDb[iDb];
@@ -106617,12 +107431,13 @@
107431 ** if they do already exist.
107432 */
107433 for(i=0; i<ArraySize(aTable); i++){
107434 const char *zTab = aTable[i].zName;
107435 Table *pStat;
107436 aCreateTbl[i] = 0;
107437 if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
107438 if( i<nToOpen ){
107439 /* The sqlite_statN table does not exist. Create it. Note that a
107440 ** side-effect of the CREATE TABLE statement is to leave the rootpage
107441 ** of the new table in register pParse->regRoot. This is important
107442 ** because the OpenWrite opcode below will be needing it. */
107443 sqlite3NestedParse(pParse,
@@ -106634,11 +107449,10 @@
107449 }else{
107450 /* The table already exists. If zWhere is not NULL, delete all entries
107451 ** associated with the table zWhere. If zWhere is NULL, delete the
107452 ** entire contents of the table. */
107453 aRoot[i] = pStat->tnum;
 
107454 sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
107455 if( zWhere ){
107456 sqlite3NestedParse(pParse,
107457 "DELETE FROM %Q.%s WHERE %s=%Q",
107458 pDb->zDbSName, zTab, zWhereType, zWhere
@@ -106653,11 +107467,11 @@
107467 }
107468 }
107469 }
107470
107471 /* Open the sqlite_stat[134] tables for writing. */
107472 for(i=0; i<nToOpen; i++){
107473 assert( i<ArraySize(aTable) );
107474 sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
107475 sqlite3VdbeChangeP5(v, aCreateTbl[i]);
107476 VdbeComment((v, aTable[i].zName));
107477 }
@@ -106692,13 +107506,16 @@
107506 u32 iHash; /* Tiebreaker hash */
107507 #endif
107508 };
107509 struct StatAccum {
107510 sqlite3 *db; /* Database connection, for malloc() */
107511 tRowcnt nEst; /* Estimated number of rows */
107512 tRowcnt nRow; /* Number of rows visited so far */
107513 int nLimit; /* Analysis row-scan limit */
107514 int nCol; /* Number of columns in index + pk/rowid */
107515 int nKeyCol; /* Number of index columns w/o the pk/rowid */
107516 u8 nSkipAhead; /* Number of times of skip-ahead */
107517 StatSample current; /* Current row as a StatSample */
107518 #ifdef SQLITE_ENABLE_STAT4
107519 tRowcnt nPSample; /* How often to do a periodic sample */
107520 int mxSample; /* Maximum number of samples to accumulate */
107521 u32 iPrn; /* Pseudo-random number used for sampling */
@@ -106774,31 +107591,32 @@
107591 ** Reclaim all memory of a StatAccum structure.
107592 */
107593 static void statAccumDestructor(void *pOld){
107594 StatAccum *p = (StatAccum*)pOld;
107595 #ifdef SQLITE_ENABLE_STAT4
107596 if( p->mxSample ){
107597 int i;
107598 for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
107599 for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
107600 sampleClear(p->db, &p->current);
107601 }
107602 #endif
107603 sqlite3DbFree(p->db, p);
107604 }
107605
107606 /*
107607 ** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters
107608 ** are:
107609 ** N: The number of columns in the index including the rowid/pk (note 1)
107610 ** K: The number of columns in the index excluding the rowid/pk.
107611 ** C: Estimated number of rows in the index
107612 ** L: A limit on the number of rows to scan, or 0 for no-limit
107613 **
107614 ** Note 1: In the special case of the covering index that implements a
107615 ** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
107616 ** total number of columns in the table.
107617 **
 
 
107618 ** For indexes on ordinary rowid tables, N==K+1. But for indexes on
107619 ** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
107620 ** PRIMARY KEY of the table. The covering index that implements the
107621 ** original WITHOUT ROWID table as N==K as a special case.
107622 **
@@ -106815,13 +107633,14 @@
107633 StatAccum *p;
107634 int nCol; /* Number of columns in index being sampled */
107635 int nKeyCol; /* Number of key columns */
107636 int nColUp; /* nCol rounded up for alignment */
107637 int n; /* Bytes of space to allocate */
107638 sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */
107639 #ifdef SQLITE_ENABLE_STAT4
107640 /* Maximum number of samples. 0 if STAT4 data is not collected */
107641 int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0;
107642 #endif
107643
107644 /* Decode the three function arguments */
107645 UNUSED_PARAMETER(argc);
107646 nCol = sqlite3_value_int(argv[0]);
@@ -106832,39 +107651,43 @@
107651 assert( nKeyCol>0 );
107652
107653 /* Allocate the space required for the StatAccum object */
107654 n = sizeof(*p)
107655 + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
107656 + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
107657 #ifdef SQLITE_ENABLE_STAT4
107658 if( mxSample ){
107659 n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
107660 + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
107661 + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
107662 }
107663 #endif
 
107664 db = sqlite3_context_db_handle(context);
107665 p = sqlite3DbMallocZero(db, n);
107666 if( p==0 ){
107667 sqlite3_result_error_nomem(context);
107668 return;
107669 }
107670
107671 p->db = db;
107672 p->nEst = sqlite3_value_int64(argv[2]);
107673 p->nRow = 0;
107674 p->nLimit = sqlite3_value_int64(argv[3]);
107675 p->nCol = nCol;
107676 p->nKeyCol = nKeyCol;
107677 p->nSkipAhead = 0;
107678 p->current.anDLt = (tRowcnt*)&p[1];
107679 p->current.anEq = &p->current.anDLt[nColUp];
107680
107681 #ifdef SQLITE_ENABLE_STAT4
107682 p->mxSample = p->nLimit==0 ? mxSample : 0;
107683 if( mxSample ){
107684 u8 *pSpace; /* Allocated space not yet assigned */
107685 int i; /* Used to iterate through p->aSample[] */
107686
107687 p->iGet = -1;
107688 p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1);
 
107689 p->current.anLt = &p->current.anEq[nColUp];
107690 p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
107691
107692 /* Set up the StatAccum.a[] and aBest[] arrays */
107693 p->a = (struct StatSample*)&p->current.anLt[nColUp];
@@ -106888,11 +107711,11 @@
107711 ** (given by the 3rd parameter) is never used and can be any positive
107712 ** value. */
107713 sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
107714 }
107715 static const FuncDef statInitFuncdef = {
107716 4, /* nArg */
107717 SQLITE_UTF8, /* funcFlags */
107718 0, /* pUserData */
107719 0, /* pNext */
107720 statInit, /* xSFunc */
107721 0, /* xFinalize */
@@ -107092,14 +107915,17 @@
107915 ** P Pointer to the StatAccum object created by stat_init()
107916 ** C Index of left-most column to differ from previous row
107917 ** R Rowid for the current row. Might be a key record for
107918 ** WITHOUT ROWID tables.
107919 **
107920 ** The purpose of this routine is to collect statistical data and/or
107921 ** samples from the index being analyzed into the StatAccum object.
107922 ** The stat_get() SQL function will be used afterwards to
107923 ** retrieve the information gathered.
107924 **
107925 ** This SQL function usually returns NULL, but might return an integer
107926 ** if it wants the byte-code to do special processing.
107927 **
107928 ** The R parameter is only used for STAT4
107929 */
107930 static void statPush(
107931 sqlite3_context *context,
@@ -107121,11 +107947,11 @@
107947 /* This is the first call to this function. Do initialization. */
107948 for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
107949 }else{
107950 /* Second and subsequent calls get processed here */
107951 #ifdef SQLITE_ENABLE_STAT4
107952 if( p->mxSample ) samplePushPrevious(p, iChng);
107953 #endif
107954
107955 /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
107956 ** to the current row of the index. */
107957 for(i=0; i<iChng; i++){
@@ -107132,30 +107958,29 @@
107958 p->current.anEq[i]++;
107959 }
107960 for(i=iChng; i<p->nCol; i++){
107961 p->current.anDLt[i]++;
107962 #ifdef SQLITE_ENABLE_STAT4
107963 if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
107964 #endif
107965 p->current.anEq[i] = 1;
107966 }
107967 }
107968
107969 p->nRow++;
107970 #ifdef SQLITE_ENABLE_STAT4
107971 if( p->mxSample ){
107972 tRowcnt nLt;
107973 if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
107974 sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
107975 }else{
107976 sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
107977 sqlite3_value_blob(argv[2]));
107978 }
107979 p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
107980
107981 nLt = p->current.anLt[p->nCol-1];
 
 
107982 /* Check if this is to be a periodic sample. If so, add it. */
107983 if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
107984 p->current.isPSample = 1;
107985 p->current.iCol = 0;
107986 sampleInsert(p, &p->current, p->nCol-1);
@@ -107167,13 +107992,18 @@
107992 p->current.iCol = i;
107993 if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
107994 sampleCopy(p, &p->aBest[i], &p->current);
107995 }
107996 }
107997 }else
107998 #endif
107999 if( p->nLimit && p->nRow>(tRowcnt)p->nLimit*(p->nSkipAhead+1) ){
108000 p->nSkipAhead++;
108001 sqlite3_result_int(context, p->current.anDLt[0]>0);
108002 }
 
108003 }
108004
108005 static const FuncDef statPushFuncdef = {
108006 2+IsStat4, /* nArg */
108007 SQLITE_UTF8, /* funcFlags */
108008 0, /* pUserData */
108009 0, /* pNext */
@@ -107221,10 +108051,11 @@
108051 assert( argc==2 );
108052 assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
108053 || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
108054 || eCall==STAT_GET_NDLT
108055 );
108056 assert( eCall==STAT_GET_STAT1 || p->mxSample );
108057 if( eCall==STAT_GET_STAT1 )
108058 #else
108059 assert( argc==1 );
108060 #endif
108061 {
@@ -107256,11 +108087,12 @@
108087 if( zRet==0 ){
108088 sqlite3_result_error_nomem(context);
108089 return;
108090 }
108091
108092 sqlite3_snprintf(24, zRet, "%llu",
108093 p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
108094 z = zRet + sqlite3Strlen30(zRet);
108095 for(i=0; i<p->nKeyCol; i++){
108096 u64 nDistinct = p->current.anDLt[i] + 1;
108097 u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
108098 sqlite3_snprintf(24, z, " %llu", iVal);
@@ -107332,20 +108164,20 @@
108164 0, 0, /* xValue, xInverse */
108165 "stat_get", /* zName */
108166 {0}
108167 };
108168
108169 static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
108170 #ifdef SQLITE_ENABLE_STAT4
108171 sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1);
108172 #elif SQLITE_DEBUG
108173 assert( iParam==STAT_GET_STAT1 );
108174 #else
108175 UNUSED_PARAMETER( iParam );
108176 #endif
108177 assert( regOut!=regStat && regOut!=regStat+1 );
108178 sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4,
108179 &statGetFuncdef, 0);
108180 }
108181
108182 /*
108183 ** Generate code to do an analysis of all indices associated with
@@ -107367,16 +108199,15 @@
108199 int i; /* Loop counter */
108200 int jZeroRows = -1; /* Jump from here if number of rows is zero */
108201 int iDb; /* Index of database containing pTab */
108202 u8 needTableCnt = 1; /* True to count the table */
108203 int regNewRowid = iMem++; /* Rowid for the inserted record */
108204 int regStat = iMem++; /* Register to hold StatAccum object */
108205 int regChng = iMem++; /* Index of changed index field */
 
108206 int regRowid = iMem++; /* Rowid argument passed to stat_push() */
 
108207 int regTemp = iMem++; /* Temporary use register */
108208 int regTemp2 = iMem++; /* Second temporary use register */
108209 int regTabname = iMem++; /* Register containing table name */
108210 int regIdxname = iMem++; /* Register containing index name */
108211 int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
108212 int regPrev = iMem; /* MUST BE LAST (see below) */
108213 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -107500,21 +108331,30 @@
108331 /* Invoke the stat_init() function. The arguments are:
108332 **
108333 ** (1) the number of columns in the index including the rowid
108334 ** (or for a WITHOUT ROWID table, the number of PK columns),
108335 ** (2) the number of columns in the key without the rowid/pk
108336 ** (3) estimated number of rows in the index,
 
 
 
108337 */
108338 sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
108339 assert( regRowid==regStat+2 );
108340 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
108341 #ifdef SQLITE_ENABLE_STAT4
108342 if( OptimizationEnabled(db, SQLITE_Stat4) ){
108343 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
108344 addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
108345 VdbeCoverage(v);
108346 }else
108347 #endif
108348 {
108349 addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
108350 VdbeCoverage(v);
108351 sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
108352 }
108353 assert( regTemp2==regStat+4 );
108354 sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
108355 sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
108356 &statInitFuncdef, 0);
108357
108358 /* Implementation of the following:
108359 **
108360 ** Rewind csr
@@ -107521,12 +108361,10 @@
108361 ** if eof(csr) goto end_of_scan;
108362 ** regChng = 0
108363 ** goto next_push_0;
108364 **
108365 */
 
 
108366 sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
108367 addrNextRow = sqlite3VdbeCurrentAddr(v);
108368
108369 if( nColTest>0 ){
108370 int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
@@ -107555,10 +108393,11 @@
108393 }
108394 for(i=0; i<nColTest; i++){
108395 char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
108396 sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
108397 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
108398 VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
108399 aGotoChng[i] =
108400 sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
108401 sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
108402 VdbeCoverage(v);
108403 }
@@ -107575,10 +108414,11 @@
108414 */
108415 sqlite3VdbeJumpHere(v, addrNextRow-1);
108416 for(i=0; i<nColTest; i++){
108417 sqlite3VdbeJumpHere(v, aGotoChng[i]);
108418 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
108419 VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
108420 }
108421 sqlite3VdbeResolveLabel(v, endDistinctTest);
108422 sqlite3DbFree(db, aGotoChng);
108423 }
108424
@@ -107588,34 +108428,50 @@
108428 ** stat_push(P, regChng, regRowid) // 3rd parameter STAT4 only
108429 ** Next csr
108430 ** if !eof(csr) goto next_row;
108431 */
108432 #ifdef SQLITE_ENABLE_STAT4
108433 if( OptimizationEnabled(db, SQLITE_Stat4) ){
108434 assert( regRowid==(regStat+2) );
108435 if( HasRowid(pTab) ){
108436 sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
108437 }else{
108438 Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
108439 int j, k, regKey;
108440 regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
108441 for(j=0; j<pPk->nKeyCol; j++){
108442 k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
108443 assert( k>=0 && k<pIdx->nColumn );
108444 sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
108445 VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
108446 }
108447 sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
108448 sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
108449 }
108450 }
108451 #endif
108452 assert( regChng==(regStat+1) );
108453 {
108454 sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4,
108455 &statPushFuncdef, 0);
108456 if( db->nAnalysisLimit ){
108457 int j1, j2, j3;
108458 j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v);
108459 j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v);
108460 j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1);
108461 VdbeCoverage(v);
108462 sqlite3VdbeJumpHere(v, j1);
108463 sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
108464 sqlite3VdbeJumpHere(v, j2);
108465 sqlite3VdbeJumpHere(v, j3);
108466 }else{
108467 sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
108468 }
108469 }
108470
108471 /* Add the entry to the stat1 table. */
108472 callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
108473 assert( "BBB"[0]==SQLITE_AFF_TEXT );
108474 sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
108475 sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
108476 sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
108477 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
@@ -107623,11 +108479,11 @@
108479 #endif
108480 sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
108481
108482 /* Add the entries to the stat4 table. */
108483 #ifdef SQLITE_ENABLE_STAT4
108484 if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){
108485 int regEq = regStat1;
108486 int regLt = regStat1+1;
108487 int regDLt = regStat1+2;
108488 int regSample = regStat1+3;
108489 int regCol = regStat1+4;
@@ -107637,16 +108493,16 @@
108493 u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
108494
108495 pParse->nMem = MAX(pParse->nMem, regCol+nCol);
108496
108497 addrNext = sqlite3VdbeCurrentAddr(v);
108498 callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
108499 addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
108500 VdbeCoverage(v);
108501 callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
108502 callStatGet(pParse, regStat, STAT_GET_NLT, regLt);
108503 callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt);
108504 sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
108505 VdbeCoverage(v);
108506 for(i=0; i<nCol; i++){
108507 sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
108508 }
@@ -109500,26 +110356,43 @@
110356 ** exists */
110357 if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
110358 return 0;
110359 }
110360 #endif
110361 if( zDatabase ){
110362 for(i=0; i<db->nDb; i++){
110363 if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
110364 }
110365 if( i>=db->nDb ){
110366 /* No match against the official names. But always match "main"
110367 ** to schema 0 as a legacy fallback. */
110368 if( sqlite3StrICmp(zDatabase,"main")==0 ){
110369 i = 0;
110370 }else{
110371 return 0;
110372 }
110373 }
110374 p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110375 if( p==0 && i==1 && sqlite3StrICmp(zName, MASTER_NAME)==0 ){
110376 /* All temp.sqlite_master to be an alias for sqlite_temp_master */
110377 p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, TEMP_MASTER_NAME);
110378 }
110379 }else{
110380 /* Match against TEMP first */
110381 p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
110382 if( p ) return p;
110383 /* The main database is second */
110384 p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
110385 if( p ) return p;
110386 /* Attached databases are in order of attachment */
110387 for(i=2; i<db->nDb; i++){
110388 assert( sqlite3SchemaMutexHeld(db, i, 0) );
110389 p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
110390 if( p ) break;
110391 }
110392 }
110393 return p;
110394 }
110395
110396 /*
110397 ** Locate the in-memory structure that describes a particular database
110398 ** table given the name of that table and (optionally) the name of the
@@ -111319,10 +112192,32 @@
112192 assert( pPk->nColumn==j );
112193 assert( pTab->nNVCol<=j );
112194 recomputeColumnsNotIndexed(pPk);
112195 }
112196
112197
112198 #ifndef SQLITE_OMIT_VIRTUALTABLE
112199 /*
112200 ** Return true if pTab is a virtual table and zName is a shadow table name
112201 ** for that virtual table.
112202 */
112203 SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
112204 int nName; /* Length of zName */
112205 Module *pMod; /* Module for the virtual table */
112206
112207 if( !IsVirtual(pTab) ) return 0;
112208 nName = sqlite3Strlen30(pTab->zName);
112209 if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
112210 if( zName[nName]!='_' ) return 0;
112211 pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
112212 if( pMod==0 ) return 0;
112213 if( pMod->pModule->iVersion<3 ) return 0;
112214 if( pMod->pModule->xShadowName==0 ) return 0;
112215 return pMod->pModule->xShadowName(zName+nName+1);
112216 }
112217 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112218
112219 #ifndef SQLITE_OMIT_VIRTUALTABLE
112220 /*
112221 ** Return true if zName is a shadow table name in the current database
112222 ** connection.
112223 **
@@ -111330,26 +112225,21 @@
112225 ** restored to its original value prior to this routine returning.
112226 */
112227 SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
112228 char *zTail; /* Pointer to the last "_" in zName */
112229 Table *pTab; /* Table that zName is a shadow of */
 
 
112230 zTail = strrchr(zName, '_');
112231 if( zTail==0 ) return 0;
112232 *zTail = 0;
112233 pTab = sqlite3FindTable(db, zName, 0);
112234 *zTail = '_';
112235 if( pTab==0 ) return 0;
112236 if( !IsVirtual(pTab) ) return 0;
112237 return sqlite3IsShadowTableOf(db, pTab, zName);
 
 
 
 
112238 }
112239 #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
112240
112241
112242 #ifdef SQLITE_DEBUG
112243 /*
112244 ** Mark all nodes of an expression as EP_Immutable, indicating that
112245 ** they should not be changed. Expressions attached to a table or
@@ -113818,11 +114708,11 @@
114708 pParse->rc = rc;
114709 return 1;
114710 }
114711 db->aDb[1].pBt = pBt;
114712 assert( db->aDb[1].pSchema );
114713 if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){
114714 sqlite3OomFault(db);
114715 return 1;
114716 }
114717 }
114718 return 0;
@@ -113929,11 +114819,11 @@
114819 char *p4, /* Error message */
114820 i8 p4type, /* P4_STATIC or P4_TRANSIENT */
114821 u8 p5Errmsg /* P5_ErrMsg type */
114822 ){
114823 Vdbe *v = sqlite3GetVdbe(pParse);
114824 assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
114825 if( onError==OE_Abort ){
114826 sqlite3MayAbort(pParse);
114827 }
114828 sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
114829 sqlite3VdbeChangeP5(v, p5Errmsg);
@@ -115642,10 +116532,11 @@
116532 VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
116533 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
116534 &iPartIdxLabel, pPrior, r1);
116535 sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
116536 pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
116537 sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
116538 sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
116539 pPrior = pIdx;
116540 }
116541 }
116542
@@ -117035,11 +117926,11 @@
117926 if( (cntExpand&(cntExpand-1))==0 ){
117927 /* Grow the size of the output buffer only on substitutions
117928 ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
117929 u8 *zOld;
117930 zOld = zOut;
117931 zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1));
117932 if( zOut==0 ){
117933 sqlite3_result_error_nomem(context);
117934 sqlite3_free(zOld);
117935 return;
117936 }
@@ -117732,11 +118623,11 @@
118623 FUNCTION(round, 2, 0, 0, roundFunc ),
118624 #endif
118625 FUNCTION(upper, 1, 0, 0, upperFunc ),
118626 FUNCTION(lower, 1, 0, 0, lowerFunc ),
118627 FUNCTION(hex, 1, 0, 0, hexFunc ),
118628 INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
118629 VFUNCTION(random, 0, 0, 0, randomFunc ),
118630 VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
118631 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
118632 DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
118633 DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -117772,11 +118663,12 @@
118663 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
118664 FUNCTION(unknown, -1, 0, 0, unknownFunc ),
118665 #endif
118666 FUNCTION(coalesce, 1, 0, 0, 0 ),
118667 FUNCTION(coalesce, 0, 0, 0, 0 ),
118668 INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
118669 INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
118670 };
118671 #ifndef SQLITE_OMIT_ALTERTABLE
118672 sqlite3AlterFunctions();
118673 #endif
118674 sqlite3WindowFunctions();
@@ -121197,11 +122089,11 @@
122089 }
122090 if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
122091 sqlite3TableAffinity(v, pTab, regNewData+1);
122092 bAffinityDone = 1;
122093 }
122094 VdbeNoopComment((v, "prep index %s", pIdx->zName));
122095 iThisCur = iIdxCur+ix;
122096
122097
122098 /* Skip partial indices for which the WHERE clause is not true */
122099 if( pIdx->pPartIdxWhere ){
@@ -122629,10 +123521,11 @@
123521 const char *(*filename_wal)(const char*);
123522 /* Version 3.32.0 and later */
123523 char *(*create_filename)(const char*,const char*,const char*,
123524 int,const char**);
123525 void (*free_filename)(char*);
123526 sqlite3_file *(*database_file_object)(const char*);
123527 };
123528
123529 /*
123530 ** This is the function signature used for all extension entry points. It
123531 ** is also defined in the file "loadext.c".
@@ -122932,10 +123825,11 @@
123825 #define sqlite3_filename_journal sqlite3_api->filename_journal
123826 #define sqlite3_filename_wal sqlite3_api->filename_wal
123827 /* Version 3.32.0 and later */
123828 #define sqlite3_create_filename sqlite3_api->create_filename
123829 #define sqlite3_free_filename sqlite3_api->free_filename
123830 #define sqlite3_database_file_object sqlite3_api->database_file_object
123831 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
123832
123833 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
123834 /* This case when the file really is being compiled as a loadable
123835 ** extension */
@@ -123413,11 +124307,20 @@
124307 sqlite3_filename_journal,
124308 sqlite3_filename_wal,
124309 /* Version 3.32.0 and later */
124310 sqlite3_create_filename,
124311 sqlite3_free_filename,
124312 sqlite3_database_file_object,
124313 };
124314
124315 /* True if x is the directory separator character
124316 */
124317 #if SQLITE_OS_WIN
124318 # define DirSep(X) ((X)=='/'||(X)=='\\')
124319 #else
124320 # define DirSep(X) ((X)=='/')
124321 #endif
124322
124323 /*
124324 ** Attempt to load an SQLite extension library contained in the file
124325 ** zFile. The entry point is zProc. zProc may be 0 in which case a
124326 ** default entry point name (sqlite3_extension_init) is used. Use
@@ -123516,11 +124419,11 @@
124419 if( zAltEntry==0 ){
124420 sqlite3OsDlClose(pVfs, handle);
124421 return SQLITE_NOMEM_BKPT;
124422 }
124423 memcpy(zAltEntry, "sqlite3_", 8);
124424 for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
124425 iFile++;
124426 if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
124427 for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
124428 if( sqlite3Isalpha(c) ){
124429 zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
@@ -123820,53 +124723,54 @@
124723 ** that script and rerun it.
124724 */
124725
124726 /* The various pragma types */
124727 #define PragTyp_ACTIVATE_EXTENSIONS 0
124728 #define PragTyp_ANALYSIS_LIMIT 1
124729 #define PragTyp_HEADER_VALUE 2
124730 #define PragTyp_AUTO_VACUUM 3
124731 #define PragTyp_FLAG 4
124732 #define PragTyp_BUSY_TIMEOUT 5
124733 #define PragTyp_CACHE_SIZE 6
124734 #define PragTyp_CACHE_SPILL 7
124735 #define PragTyp_CASE_SENSITIVE_LIKE 8
124736 #define PragTyp_COLLATION_LIST 9
124737 #define PragTyp_COMPILE_OPTIONS 10
124738 #define PragTyp_DATA_STORE_DIRECTORY 11
124739 #define PragTyp_DATABASE_LIST 12
124740 #define PragTyp_DEFAULT_CACHE_SIZE 13
124741 #define PragTyp_ENCODING 14
124742 #define PragTyp_FOREIGN_KEY_CHECK 15
124743 #define PragTyp_FOREIGN_KEY_LIST 16
124744 #define PragTyp_FUNCTION_LIST 17
124745 #define PragTyp_HARD_HEAP_LIMIT 18
124746 #define PragTyp_INCREMENTAL_VACUUM 19
124747 #define PragTyp_INDEX_INFO 20
124748 #define PragTyp_INDEX_LIST 21
124749 #define PragTyp_INTEGRITY_CHECK 22
124750 #define PragTyp_JOURNAL_MODE 23
124751 #define PragTyp_JOURNAL_SIZE_LIMIT 24
124752 #define PragTyp_LOCK_PROXY_FILE 25
124753 #define PragTyp_LOCKING_MODE 26
124754 #define PragTyp_PAGE_COUNT 27
124755 #define PragTyp_MMAP_SIZE 28
124756 #define PragTyp_MODULE_LIST 29
124757 #define PragTyp_OPTIMIZE 30
124758 #define PragTyp_PAGE_SIZE 31
124759 #define PragTyp_PRAGMA_LIST 32
124760 #define PragTyp_SECURE_DELETE 33
124761 #define PragTyp_SHRINK_MEMORY 34
124762 #define PragTyp_SOFT_HEAP_LIMIT 35
124763 #define PragTyp_SYNCHRONOUS 36
124764 #define PragTyp_TABLE_INFO 37
124765 #define PragTyp_TEMP_STORE 38
124766 #define PragTyp_TEMP_STORE_DIRECTORY 39
124767 #define PragTyp_THREADS 40
124768 #define PragTyp_WAL_AUTOCHECKPOINT 41
124769 #define PragTyp_WAL_CHECKPOINT 42
124770 #define PragTyp_LOCK_STATUS 43
124771 #define PragTyp_STATS 44
124772
124773 /* Property flags associated with various pragma. */
124774 #define PragFlg_NeedSchema 0x01 /* Force schema load before running */
124775 #define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
124776 #define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
@@ -123953,10 +124857,15 @@
124857 /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
124858 /* ePragFlg: */ 0,
124859 /* ColNames: */ 0, 0,
124860 /* iArg: */ 0 },
124861 #endif
124862 {/* zName: */ "analysis_limit",
124863 /* ePragTyp: */ PragTyp_ANALYSIS_LIMIT,
124864 /* ePragFlg: */ PragFlg_Result0,
124865 /* ColNames: */ 0, 0,
124866 /* iArg: */ 0 },
124867 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
124868 {/* zName: */ "application_id",
124869 /* ePragTyp: */ PragTyp_HEADER_VALUE,
124870 /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
124871 /* ColNames: */ 0, 0,
@@ -124453,11 +125362,11 @@
125362 /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
125363 /* ColNames: */ 0, 0,
125364 /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
125365 #endif
125366 };
125367 /* Number of pragmas: 67 on by default, 77 total. */
125368
125369 /************** End of pragma.h **********************************************/
125370 /************** Continuing where we left off in pragma.c *********************/
125371
125372 /*
@@ -124983,11 +125892,11 @@
125892 }else{
125893 /* Malloc may fail when setting the page-size, as there is an internal
125894 ** buffer that the pager module resizes using sqlite3_realloc().
125895 */
125896 db->nextPagesize = sqlite3Atoi(zRight);
125897 if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,0,0) ){
125898 sqlite3OomFault(db);
125899 }
125900 }
125901 break;
125902 }
@@ -126157,11 +127066,10 @@
127066 sqlite3ResolvePartIdxLabel(pParse, jmp3);
127067 }
127068 }
127069 sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
127070 sqlite3VdbeJumpHere(v, loopTop-1);
 
127071 if( !isQuick ){
127072 sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
127073 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
127074 if( pPk==pIdx ) continue;
127075 sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
@@ -126171,11 +127079,10 @@
127079 sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
127080 integrityCheckResultRow(v);
127081 sqlite3VdbeJumpHere(v, addr);
127082 }
127083 }
 
127084 }
127085 }
127086 {
127087 static const int iLn = VDBE_OFFSET_LINENO(2);
127088 static const VdbeOpList endCode[] = {
@@ -126605,10 +127512,29 @@
127512 sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
127513 }
127514 returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
127515 break;
127516 }
127517
127518 /*
127519 ** PRAGMA analysis_limit
127520 ** PRAGMA analysis_limit = N
127521 **
127522 ** Configure the maximum number of rows that ANALYZE will examine
127523 ** in each index that it looks at. Return the new limit.
127524 */
127525 case PragTyp_ANALYSIS_LIMIT: {
127526 sqlite3_int64 N;
127527 if( zRight
127528 && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
127529 && N>=0
127530 ){
127531 db->nAnalysisLimit = (int)(N&0x7fffffff);
127532 }
127533 returnSingleInt(v, db->nAnalysisLimit);
127534 break;
127535 }
127536
127537 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
127538 /*
127539 ** Report the current state of file logs for all databases
127540 */
@@ -131404,10 +132330,11 @@
132330 if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
132331 memset(&ifNullRow, 0, sizeof(ifNullRow));
132332 ifNullRow.op = TK_IF_NULL_ROW;
132333 ifNullRow.pLeft = pCopy;
132334 ifNullRow.iTable = pSubst->iNewTable;
132335 ifNullRow.flags = EP_Skip;
132336 pCopy = &ifNullRow;
132337 }
132338 testcase( ExprHasProperty(pCopy, EP_Subquery) );
132339 pNew = sqlite3ExprDup(db, pCopy, 0);
132340 if( pNew && pSubst->isLeftJoin ){
@@ -133134,33 +134061,10 @@
134061 }
134062 }
134063 return WRC_Continue;
134064 }
134065
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134066 #if SQLITE_DEBUG
134067 /*
134068 ** Always assert. This xSelectCallback2 implementation proves that the
134069 ** xSelectCallback2 is never invoked.
134070 */
@@ -134327,11 +135231,11 @@
135231 sAggInfo.mxReg = pParse->nMem;
135232 if( db->mallocFailed ) goto select_end;
135233 #if SELECTTRACE_ENABLED
135234 if( sqlite3SelectTrace & 0x400 ){
135235 int ii;
135236 SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", &sAggInfo));
135237 sqlite3TreeViewSelect(0, p, 0);
135238 for(ii=0; ii<sAggInfo.nColumn; ii++){
135239 sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
135240 ii, sAggInfo.aCol[ii].iMem);
135241 sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
@@ -134568,11 +135472,10 @@
135472 VdbeComment((v, "indicate accumulator empty"));
135473 sqlite3VdbeAddOp1(v, OP_Return, regReset);
135474
135475 } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
135476 else {
 
135477 Table *pTab;
135478 if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
135479 /* If isSimpleCount() returns a pointer to a Table structure, then
135480 ** the SQL statement is of the form:
135481 **
@@ -134604,17 +135507,19 @@
135507 **
135508 ** In practice the KeyInfo structure will not be used. It is only
135509 ** passed to keep OP_OpenRead happy.
135510 */
135511 if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
135512 if( !p->pSrc->a[0].fg.notIndexed ){
135513 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
135514 if( pIdx->bUnordered==0
135515 && pIdx->szIdxRow<pTab->szTabRow
135516 && pIdx->pPartIdxWhere==0
135517 && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
135518 ){
135519 pBest = pIdx;
135520 }
135521 }
135522 }
135523 if( pBest ){
135524 iRoot = pBest->tnum;
135525 pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
@@ -134626,13 +135531,11 @@
135531 sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
135532 }
135533 sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
135534 sqlite3VdbeAddOp1(v, OP_Close, iCsr);
135535 explainSimpleCount(pParse, pTab, pBest);
135536 }else{
 
 
135537 int regAcc = 0; /* "populate accumulators" flag */
135538
135539 /* If there are accumulator registers but no min() or max() functions
135540 ** without FILTER clauses, allocate register regAcc. Register regAcc
135541 ** will contain 0 the first time the inner loop runs, and 1 thereafter.
@@ -134791,11 +135694,11 @@
135694 need = nCol;
135695 }
135696 if( p->nData + need > p->nAlloc ){
135697 char **azNew;
135698 p->nAlloc = p->nAlloc*2 + need;
135699 azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc );
135700 if( azNew==0 ) goto malloc_failed;
135701 p->azResult = azNew;
135702 }
135703
135704 /* If this is the first row, then generate an extra row containing
@@ -134900,11 +135803,11 @@
135803 sqlite3_free_table(&res.azResult[1]);
135804 return rc;
135805 }
135806 if( res.nAlloc>res.nData ){
135807 char **azNew;
135808 azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData );
135809 if( azNew==0 ){
135810 sqlite3_free_table(&res.azResult[1]);
135811 db->errCode = SQLITE_NOMEM;
135812 return SQLITE_NOMEM_BKPT;
135813 }
@@ -136190,14 +137093,14 @@
137093 ** Therefore, the P4 parameter is only required if the default value for
137094 ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
137095 ** function is capable of transforming these types of expressions into
137096 ** sqlite3_value objects.
137097 **
137098 ** If column as REAL affinity and the table is an ordinary b-tree table
137099 ** (not a virtual table) then the value might have been stored as an
137100 ** integer. In that case, add an OP_RealAffinity opcode to make sure
137101 ** it has been converted into REAL.
137102 */
137103 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
137104 assert( pTab!=0 );
137105 if( !pTab->pSelect ){
137106 sqlite3_value *pValue = 0;
@@ -136210,11 +137113,11 @@
137113 if( pValue ){
137114 sqlite3VdbeAppendP4(v, pValue, P4_MEM);
137115 }
137116 }
137117 #ifndef SQLITE_OMIT_FLOATING_POINT
137118 if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
137119 sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
137120 }
137121 #endif
137122 }
137123
@@ -137852,11 +138755,11 @@
138755 db->mDbFlags = saved_mDbFlags;
138756 db->flags = saved_flags;
138757 db->nChange = saved_nChange;
138758 db->nTotalChange = saved_nTotalChange;
138759 db->mTrace = saved_mTrace;
138760 sqlite3BtreeSetPageSize(pMain, -1, 0, 1);
138761
138762 /* Currently there is an SQL level transaction open on the vacuum
138763 ** database. No locks are held on any other files (since the main file
138764 ** was committed at the btree level). So it safe to end the transaction
138765 ** by manually setting the autoCommit flag to true and detaching the
@@ -139059,11 +139962,11 @@
139962 assert( IsVirtual(pTab) );
139963 for(i=0; i<pToplevel->nVtabLock; i++){
139964 if( pTab==pToplevel->apVtabLock[i] ) return;
139965 }
139966 n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
139967 apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n);
139968 if( apVtabLock ){
139969 pToplevel->apVtabLock = apVtabLock;
139970 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
139971 }else{
139972 sqlite3OomFault(pToplevel->db);
@@ -150351,24 +151254,47 @@
151254 ){
151255 if( pAppend ){
151256 int i;
151257 int nInit = pList ? pList->nExpr : 0;
151258 for(i=0; i<pAppend->nExpr; i++){
 
151259 Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
151260 assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
151261 if( bIntToNull && pDup ){
151262 int iDummy;
151263 Expr *pSub;
151264 for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
151265 assert( pSub );
151266 }
151267 if( sqlite3ExprIsInteger(pSub, &iDummy) ){
151268 pSub->op = TK_NULL;
151269 pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
151270 pSub->u.zToken = 0;
151271 }
151272 }
151273 pList = sqlite3ExprListAppend(pParse, pList, pDup);
151274 if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
151275 }
151276 }
151277 return pList;
151278 }
151279
151280 /*
151281 ** When rewriting a query, if the new subquery in the FROM clause
151282 ** contains TK_AGG_FUNCTION nodes that refer to an outer query,
151283 ** then we have to increase the Expr->op2 values of those nodes
151284 ** due to the extra subquery layer that was added.
151285 **
151286 ** See also the incrAggDepth() routine in resolve.c
151287 */
151288 static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
151289 if( pExpr->op==TK_AGG_FUNCTION
151290 && pExpr->op2>=pWalker->walkerDepth
151291 ){
151292 pExpr->op2++;
151293 }
151294 return WRC_Continue;
151295 }
151296
151297 /*
151298 ** If the SELECT statement passed as the second argument does not invoke
151299 ** any SQL window functions, this function is a no-op. Otherwise, it
151300 ** rewrites the SELECT statement so that window function xStep functions
@@ -150475,10 +151401,11 @@
151401 pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
151402 );
151403 p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
151404 if( p->pSrc ){
151405 Table *pTab2;
151406 Walker w;
151407 p->pSrc->a[0].pSelect = pSub;
151408 sqlite3SrcListAssignCursors(pParse, p->pSrc);
151409 pSub->selFlags |= SF_Expanded;
151410 pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
151411 pSub->selFlags |= (selFlags & SF_Aggregate);
@@ -150490,10 +151417,15 @@
151417 }else{
151418 memcpy(pTab, pTab2, sizeof(Table));
151419 pTab->tabFlags |= TF_Ephemeral;
151420 p->pSrc->a[0].pTab = pTab;
151421 pTab = pTab2;
151422 memset(&w, 0, sizeof(w));
151423 w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
151424 w.xSelectCallback = sqlite3WalkerDepthIncrease;
151425 w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
151426 sqlite3WalkSelect(&w, pSub);
151427 }
151428 }else{
151429 sqlite3SelectDelete(db, pSub);
151430 }
151431 if( db->mallocFailed ) rc = SQLITE_NOMEM;
@@ -159255,19 +160187,82 @@
160187
160188
160189 /************** End of sqliteicu.h *******************************************/
160190 /************** Continuing where we left off in main.c ***********************/
160191 #endif
160192
160193 /*
160194 ** This is an extension initializer that is a no-op and always
160195 ** succeeds, except that it fails if the fault-simulation is set
160196 ** to 500.
160197 */
160198 static int sqlite3TestExtInit(sqlite3 *db){
160199 (void)db;
160200 return sqlite3FaultSim(500);
160201 }
160202
160203
160204 /*
160205 ** Forward declarations of external module initializer functions
160206 ** for modules that need them.
160207 */
160208 #ifdef SQLITE_ENABLE_FTS1
160209 SQLITE_PRIVATE int sqlite3Fts1Init(sqlite3*);
160210 #endif
160211 #ifdef SQLITE_ENABLE_FTS2
160212 SQLITE_PRIVATE int sqlite3Fts2Init(sqlite3*);
160213 #endif
160214 #ifdef SQLITE_ENABLE_FTS5
160215 SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
160216 #endif
160217 #ifdef SQLITE_ENABLE_JSON1
160218 SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*);
160219 #endif
160220 #ifdef SQLITE_ENABLE_STMTVTAB
160221 SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*);
160222 #endif
160223
160224 /*
160225 ** An array of pointers to extension initializer functions for
160226 ** built-in extensions.
160227 */
160228 static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
160229 #ifdef SQLITE_ENABLE_FTS1
160230 sqlite3Fts1Init,
160231 #endif
160232 #ifdef SQLITE_ENABLE_FTS2
160233 sqlite3Fts2Init,
160234 #endif
160235 #ifdef SQLITE_ENABLE_FTS3
160236 sqlite3Fts3Init,
160237 #endif
160238 #ifdef SQLITE_ENABLE_FTS5
160239 sqlite3Fts5Init,
160240 #endif
160241 #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
160242 sqlite3IcuInit,
160243 #endif
160244 #ifdef SQLITE_ENABLE_RTREE
160245 sqlite3RtreeInit,
160246 #endif
160247 #ifdef SQLITE_ENABLE_DBPAGE_VTAB
160248 sqlite3DbpageRegister,
160249 #endif
160250 #ifdef SQLITE_ENABLE_DBSTAT_VTAB
160251 sqlite3DbstatRegister,
160252 #endif
160253 sqlite3TestExtInit,
160254 #ifdef SQLITE_ENABLE_JSON1
160255 sqlite3Json1Init,
160256 #endif
160257 #ifdef SQLITE_ENABLE_STMTVTAB
160258 sqlite3StmtVtabInit,
160259 #endif
160260 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
160261 sqlite3VdbeBytecodeVtabInit,
160262 #endif
160263 };
160264
160265 #ifndef SQLITE_AMALGAMATION
160266 /* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
160267 ** contains the text of SQLITE_VERSION macro.
160268 */
@@ -159480,10 +160475,11 @@
160475 }
160476 #endif
160477 if( rc==SQLITE_OK ){
160478 sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
160479 sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
160480 sqlite3MemoryBarrier();
160481 sqlite3GlobalConfig.isInit = 1;
160482 #ifdef SQLITE_EXTRA_INIT
160483 bRunExtraInit = 1;
160484 #endif
160485 }
@@ -160781,12 +161777,11 @@
161777 ** Return non-zero to retry the lock. Return zero to stop trying
161778 ** and cause SQLite to return SQLITE_BUSY.
161779 */
161780 static int sqliteDefaultBusyCallback(
161781 void *ptr, /* Database connection */
161782 int count /* Number of times table has been busy */
 
161783 ){
161784 #if SQLITE_OS_WIN || HAVE_USLEEP
161785 /* This case is for systems that have support for sleeping for fractions of
161786 ** a second. Examples: All windows systems, unix systems with usleep() */
161787 static const u8 delays[] =
@@ -160796,35 +161791,10 @@
161791 # define NDELAY ArraySize(delays)
161792 sqlite3 *db = (sqlite3 *)ptr;
161793 int tmout = db->busyTimeout;
161794 int delay, prior;
161795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161796 assert( count>=0 );
161797 if( count < NDELAY ){
161798 delay = delays[count];
161799 prior = totals[count];
161800 }else{
@@ -160840,11 +161810,10 @@
161810 #else
161811 /* This case for unix systems that lack usleep() support. Sleeping
161812 ** must be done in increments of whole seconds */
161813 sqlite3 *db = (sqlite3 *)ptr;
161814 int tmout = ((sqlite3 *)ptr)->busyTimeout;
 
161815 if( (count+1)*1000 > tmout ){
161816 return 0;
161817 }
161818 sqlite3OsSleep(db->pVfs, 1000000);
161819 return 1;
@@ -160858,23 +161827,14 @@
161827 ** lock on VFS file pFile.
161828 **
161829 ** If this routine returns non-zero, the lock is retried. If it
161830 ** returns 0, the operation aborts with an SQLITE_BUSY error.
161831 */
161832 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
161833 int rc;
161834 if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
161835 rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
 
 
 
 
 
 
 
 
 
161836 if( rc==0 ){
161837 p->nBusy = -1;
161838 }else{
161839 p->nBusy++;
161840 }
@@ -160895,11 +161855,10 @@
161855 #endif
161856 sqlite3_mutex_enter(db->mutex);
161857 db->busyHandler.xBusyHandler = xBusy;
161858 db->busyHandler.pBusyArg = pArg;
161859 db->busyHandler.nBusy = 0;
 
161860 db->busyTimeout = 0;
161861 sqlite3_mutex_leave(db->mutex);
161862 return SQLITE_OK;
161863 }
161864
@@ -160946,11 +161905,10 @@
161905 #endif
161906 if( ms>0 ){
161907 sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
161908 (void*)db);
161909 db->busyTimeout = ms;
 
161910 }else{
161911 sqlite3_busy_handler(db, 0, 0);
161912 }
161913 return SQLITE_OK;
161914 }
@@ -162272,10 +163230,11 @@
163230 sqlite3 *db; /* Store allocated handle here */
163231 int rc; /* Return code */
163232 int isThreadsafe; /* True for threadsafe connections */
163233 char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
163234 char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
163235 int i; /* Loop counter */
163236
163237 #ifdef SQLITE_ENABLE_API_ARMOR
163238 if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
163239 #endif
163240 *ppDb = 0;
@@ -162420,10 +163379,13 @@
163379 | SQLITE_EnableQPSG
163380 #endif
163381 #if defined(SQLITE_DEFAULT_DEFENSIVE)
163382 | SQLITE_Defensive
163383 #endif
163384 #if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE)
163385 | SQLITE_LegacyAlter
163386 #endif
163387 ;
163388 sqlite3HashInit(&db->aCollSeq);
163389 #ifndef SQLITE_OMIT_VIRTUALTABLE
163390 sqlite3HashInit(&db->aModule);
163391 #endif
@@ -162462,11 +163424,11 @@
163424 assert( SQLITE_OPEN_CREATE == 0x04 );
163425 testcase( (1<<(flags&7))==0x02 ); /* READONLY */
163426 testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
163427 testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
163428 if( ((1<<(flags&7)) & 0x46)==0 ){
163429 rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
163430 }else{
163431 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
163432 }
163433 if( rc!=SQLITE_OK ){
163434 if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
@@ -162512,18 +163474,15 @@
163474 */
163475 sqlite3Error(db, SQLITE_OK);
163476 sqlite3RegisterPerConnectionBuiltinFunctions(db);
163477 rc = sqlite3_errcode(db);
163478
163479
163480 /* Load compiled-in extensions */
163481 for(i=0; rc==SQLITE_OK && i<ArraySize(sqlite3BuiltinExtensions); i++){
163482 rc = sqlite3BuiltinExtensions[i](db);
163483 }
 
 
 
163484
163485 /* Load automatic extensions - extensions that have been registered
163486 ** using the sqlite3_automatic_extension() API.
163487 */
163488 if( rc==SQLITE_OK ){
@@ -162532,66 +163491,10 @@
163491 if( rc!=SQLITE_OK ){
163492 goto opendb_out;
163493 }
163494 }
163495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163496 #ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
163497 /* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
163498 ** option gives access to internal functions by default.
163499 ** Testing use only!!! */
163500 db->mDbFlags |= DBFLAG_InternalFunc;
@@ -163076,11 +163979,11 @@
163979 *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
163980 rc = SQLITE_OK;
163981 }else if( op==SQLITE_FCNTL_RESERVE_BYTES ){
163982 int iNew = *(int*)pArg;
163983 *(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree);
163984 if( iNew>=0 && iNew<=255 ){
163985 sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
163986 }
163987 rc = SQLITE_OK;
163988 }else{
163989 rc = sqlite3OsFileControl(fd, op, pArg);
@@ -165357,10 +166260,11 @@
166260 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
166261 SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
166262 SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
166263 SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
166264 SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
166265 SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut);
166266
166267 /* fts3_tokenizer.c */
166268 SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
166269 SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
166270 SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -166088,10 +166992,26 @@
166992 fts3Appendf(pRc, &zRet, ", ?");
166993 }
166994 sqlite3_free(zFree);
166995 return zRet;
166996 }
166997
166998 /*
166999 ** Buffer z contains a positive integer value encoded as utf-8 text.
167000 ** Decode this value and store it in *pnOut, returning the number of bytes
167001 ** consumed. If an overflow error occurs return a negative value.
167002 */
167003 SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut){
167004 u64 iVal = 0;
167005 int i;
167006 for(i=0; z[i]>='0' && z[i]<='9'; i++){
167007 iVal = iVal*10 + (z[i] - '0');
167008 if( iVal>0x7FFFFFFF ) return -1;
167009 }
167010 *pnOut = (int)iVal;
167011 return i;
167012 }
167013
167014 /*
167015 ** This function interprets the string at (*pp) as a non-negative integer
167016 ** value. It reads the integer and sets *pnOut to the value read, then
167017 ** sets *pp to point to the byte immediately following the last byte of
@@ -166104,23 +167024,21 @@
167024 **
167025 ** This function is used when parsing the "prefix=" FTS4 parameter.
167026 */
167027 static int fts3GobbleInt(const char **pp, int *pnOut){
167028 const int MAX_NPREFIX = 10000000;
 
167029 int nInt = 0; /* Output value */
167030 int nByte;
167031 nByte = sqlite3Fts3ReadInt(*pp, &nInt);
167032 if( nInt>MAX_NPREFIX ){
167033 nInt = 0;
167034 }
167035 if( nByte==0 ){
167036 return SQLITE_ERROR;
167037 }
 
167038 *pnOut = nInt;
167039 *pp += nByte;
167040 return SQLITE_OK;
167041 }
167042
167043 /*
167044 ** This function is called to allocate an array of Fts3Index structures
@@ -167298,11 +168216,13 @@
168216 static void fts3ReadNextPos(
168217 char **pp, /* IN/OUT: Pointer into position-list buffer */
168218 sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
168219 ){
168220 if( (**pp)&0xFE ){
168221 int iVal;
168222 *pp += fts3GetVarint32((*pp), &iVal);
168223 *pi += iVal;
168224 *pi -= 2;
168225 }else{
168226 *pi = POSITION_LIST_END;
168227 }
168228 }
@@ -170428,10 +171348,11 @@
171348 while( *pRc==SQLITE_OK && pLeft->bEof==0 ){
171349 memset(pDl->pList, 0, pDl->nList);
171350 fts3EvalNextRow(pCsr, pLeft, pRc);
171351 }
171352 }
171353 pRight->bEof = pLeft->bEof = 1;
171354 }
171355 }
171356 break;
171357 }
171358
@@ -172198,14 +173119,11 @@
173119
173120 /* If this is a "NEAR" keyword, check for an explicit nearness. */
173121 if( pKey->eType==FTSQUERY_NEAR ){
173122 assert( nKey==4 );
173123 if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
173124 nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
 
 
 
173125 }
173126 }
173127
173128 /* At this point this is probably a keyword. But for that to be true,
173129 ** the next byte must contain either whitespace, an open or close
@@ -178384,25 +179302,25 @@
179302 ){
179303 const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
179304 if( zText ){
179305 int i;
179306 int iMul = 1;
179307 u64 iVal = 0;
179308 for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
179309 iVal = iVal*10 + (zText[i] - '0');
179310 }
179311 *piEndBlock = (i64)iVal;
179312 while( zText[i]==' ' ) i++;
179313 iVal = 0;
179314 if( zText[i]=='-' ){
179315 i++;
179316 iMul = -1;
179317 }
179318 for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
179319 iVal = iVal*10 + (zText[i] - '0');
179320 }
179321 *pnByte = ((i64)iVal * (i64)iMul);
179322 }
179323 }
179324
179325
179326 /*
@@ -181976,11 +182894,11 @@
182894 iStart = pExpr->iPhrase * p->nCol;
182895 }else{
182896 iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
182897 }
182898
182899 if( pIter ) while( 1 ){
182900 int nHit = fts3ColumnlistCount(&pIter);
182901 if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
182902 if( p->flag==FTS3_MATCHINFO_LHITS ){
182903 p->aMatchinfo[iStart + iCol] = (u32)nHit;
182904 }else if( nHit ){
@@ -183890,10 +184808,11 @@
184808 }
184809
184810 /* Append N bytes from zIn onto the end of the JsonString string.
184811 */
184812 static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
184813 if( N==0 ) return;
184814 if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
184815 memcpy(p->zBuf+p->nUsed, zIn, N);
184816 p->nUsed += N;
184817 }
184818
@@ -223901,11 +224820,11 @@
224820 int nArg, /* Number of args */
224821 sqlite3_value **apUnused /* Function arguments */
224822 ){
224823 assert( nArg==0 );
224824 UNUSED_PARAM2(nArg, apUnused);
224825 sqlite3_result_text(pCtx, "fts5: 2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350", -1, SQLITE_TRANSIENT);
224826 }
224827
224828 /*
224829 ** Return true if zName is the extension on one of the shadow tables used
224830 ** by this module.
@@ -228552,11 +229471,12 @@
229471 }
229472 case STMT_COLUMN_BUSY: {
229473 sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
229474 break;
229475 }
229476 default: {
229477 assert( i==STMT_COLUMN_MEM );
229478 i = SQLITE_STMTSTATUS_MEMUSED +
229479 STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
229480 /* Fall thru */
229481 }
229482 case STMT_COLUMN_NSCAN:
@@ -228683,12 +229603,12 @@
229603 }
229604 #endif /* SQLITE_CORE */
229605 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229606
229607 /************** End of stmt.c ************************************************/
229608 #if __LINE__!=229608
229609 #undef SQLITE_SOURCE_ID
229610 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba8alt2"
229611 #endif
229612 /* Return the source-id for this library */
229613 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229614 /************************** End of sqlite3.c ******************************/
229615
+61 -26
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,13 +121,13 @@
121121
**
122122
** See also: [sqlite3_libversion()],
123123
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124124
** [sqlite_version()] and [sqlite_source_id()].
125125
*/
126
-#define SQLITE_VERSION "3.32.0"
127
-#define SQLITE_VERSION_NUMBER 3032000
128
-#define SQLITE_SOURCE_ID "2020-04-20 17:35:32 2fc80ef16ce5878311ab88a0c64631813572ffbb71f75363b4619c9667e0926b"
126
+#define SQLITE_VERSION "3.32.1"
127
+#define SQLITE_VERSION_NUMBER 3032001
128
+#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
129129
130130
/*
131131
** CAPI3REF: Run-Time Library Version Numbers
132132
** KEYWORDS: sqlite3_version sqlite3_sourceid
133133
**
@@ -297,30 +297,26 @@
297297
** for the [sqlite3] object.
298298
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
299299
** the [sqlite3] object is successfully destroyed and all associated
300300
** resources are deallocated.
301301
**
302
+** Ideally, applications should [sqlite3_finalize | finalize] all
303
+** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
304
+** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
305
+** with the [sqlite3] object prior to attempting to close the object.
302306
** ^If the database connection is associated with unfinalized prepared
303
-** statements or unfinished sqlite3_backup objects then sqlite3_close()
304
-** will leave the database connection open and return [SQLITE_BUSY].
305
-** ^If sqlite3_close_v2() is called with unfinalized prepared statements
306
-** and/or unfinished sqlite3_backups, then the database connection becomes
307
-** an unusable "zombie" which will automatically be deallocated when the
308
-** last prepared statement is finalized or the last sqlite3_backup is
309
-** finished. The sqlite3_close_v2() interface is intended for use with
310
-** host languages that are garbage collected, and where the order in which
311
-** destructors are called is arbitrary.
312
-**
313
-** Applications should [sqlite3_finalize | finalize] all [prepared statements],
314
-** [sqlite3_blob_close | close] all [BLOB handles], and
315
-** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
316
-** with the [sqlite3] object prior to attempting to close the object. ^If
317
-** sqlite3_close_v2() is called on a [database connection] that still has
318
-** outstanding [prepared statements], [BLOB handles], and/or
319
-** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
320
-** of resources is deferred until all [prepared statements], [BLOB handles],
321
-** and [sqlite3_backup] objects are also destroyed.
307
+** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
308
+** sqlite3_close() will leave the database connection open and return
309
+** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
310
+** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
311
+** it returns [SQLITE_OK] regardless, but instead of deallocating the database
312
+** connection immediately, it marks the database connection as an unusable
313
+** "zombie" and makes arrangements to automatically deallocate the database
314
+** connection after all prepared statements are finalized, all BLOB handles
315
+** are closed, and all backups have finished. The sqlite3_close_v2() interface
316
+** is intended for use with host languages that are garbage collected, and
317
+** where the order in which destructors are called is arbitrary.
322318
**
323319
** ^If an [sqlite3] object is destroyed while a transaction is open,
324320
** the transaction is automatically rolled back.
325321
**
326322
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
@@ -505,22 +501,25 @@
505501
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
506502
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
507503
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
508504
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
509505
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
506
+#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
510507
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
511508
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
512509
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
513510
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
511
+#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
514512
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
515513
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
516514
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
517515
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
518516
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
519517
#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
520518
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
521519
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
520
+#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
522521
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
523522
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
524523
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
525524
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
526525
#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
@@ -1111,10 +1110,15 @@
11111110
** a single attached database that occur due to other database connections,
11121111
** but omits changes implemented by the database connection on which it is
11131112
** called. This file control is the only mechanism to detect changes that
11141113
** happen either internally or externally and that are associated with
11151114
** a particular attached database.
1115
+**
1116
+** <li>[[SQLITE_FCNTL_CKPT_START]]
1117
+** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
1118
+** in wal mode before the client starts to copy pages from the wal
1119
+** file to the database file.
11161120
**
11171121
** <li>[[SQLITE_FCNTL_CKPT_DONE]]
11181122
** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
11191123
** in wal mode after the client has finished copying pages from the wal
11201124
** file to the database file, but before the *-shm file is updated to
@@ -1156,10 +1160,11 @@
11561160
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
11571161
#define SQLITE_FCNTL_DATA_VERSION 35
11581162
#define SQLITE_FCNTL_SIZE_LIMIT 36
11591163
#define SQLITE_FCNTL_CKPT_DONE 37
11601164
#define SQLITE_FCNTL_RESERVE_BYTES 38
1165
+#define SQLITE_FCNTL_CKPT_START 39
11611166
11621167
/* deprecated names */
11631168
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
11641169
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
11651170
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -3534,12 +3539,23 @@
35343539
**
35353540
** These are utility routines, useful to [VFS|custom VFS implementations],
35363541
** that check if a database file was a URI that contained a specific query
35373542
** parameter, and if so obtains the value of that query parameter.
35383543
**
3539
-** If F is the database filename pointer passed into the xOpen() method of
3540
-** a VFS implementation or it is the return value of [sqlite3_db_filename()]
3544
+** The first parameter to these interfaces (hereafter referred to
3545
+** as F) must be one of:
3546
+** <ul>
3547
+** <li> A database filename pointer created by the SQLite core and
3548
+** passed into the xOpen() method of a VFS implemention, or
3549
+** <li> A filename obtained from [sqlite3_db_filename()], or
3550
+** <li> A new filename constructed using [sqlite3_create_filename()].
3551
+** </ul>
3552
+** If the F parameter is not one of the above, then the behavior is
3553
+** undefined and probably undesirable. Older versions of SQLite were
3554
+** more tolerant of invalid F parameters than newer versions.
3555
+**
3556
+** If F is a suitable filename (as described in the previous paragraph)
35413557
** and if P is the name of the query parameter, then
35423558
** sqlite3_uri_parameter(F,P) returns the value of the P
35433559
** parameter if it exists or a NULL pointer if P does not appear as a
35443560
** query parameter on F. If P is a query parameter of F and it
35453561
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
@@ -3618,10 +3634,29 @@
36183634
*/
36193635
SQLITE_API const char *sqlite3_filename_database(const char*);
36203636
SQLITE_API const char *sqlite3_filename_journal(const char*);
36213637
SQLITE_API const char *sqlite3_filename_wal(const char*);
36223638
3639
+/*
3640
+** CAPI3REF: Database File Corresponding To A Journal
3641
+**
3642
+** ^If X is the name of a rollback or WAL-mode journal file that is
3643
+** passed into the xOpen method of [sqlite3_vfs], then
3644
+** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
3645
+** object that represents the main database file.
3646
+**
3647
+** This routine is intended for use in custom [VFS] implementations
3648
+** only. It is not a general-purpose interface.
3649
+** The argument sqlite3_file_object(X) must be a filename pointer that
3650
+** has been passed into [sqlite3_vfs].xOpen method where the
3651
+** flags parameter to xOpen contains one of the bits
3652
+** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
3653
+** of this routine results in undefined and probably undesirable
3654
+** behavior.
3655
+*/
3656
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
3657
+
36233658
/*
36243659
** CAPI3REF: Create and Destroy VFS Filenames
36253660
**
36263661
** These interfces are provided for use by [VFS shim] implementations and
36273662
** are not useful outside of that context.
@@ -3652,11 +3687,11 @@
36523687
** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
36533688
** be NULL pointers, though they can be empty strings.
36543689
**
36553690
** The sqlite3_free_filename(Y) routine releases a memory allocation
36563691
** previously obtained from sqlite3_create_filename(). Invoking
3657
-** sqlite3_free_filename(Y) is a NULL pointer is a harmless no-op.
3692
+** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
36583693
**
36593694
** If the Y parameter to sqlite3_free_filename(Y) is anything other
36603695
** than a NULL pointer or a pointer previously acquired from
36613696
** sqlite3_create_filename(), then bad things such as heap
36623697
** corruption or segfaults may occur. The value Y should be
@@ -5458,11 +5493,11 @@
54585493
** when first called if N is less than or equal to zero or if a memory
54595494
** allocate error occurs.
54605495
**
54615496
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
54625497
** determined by the N parameter on first successful call. Changing the
5463
-** value of N in any subsequents call to sqlite3_aggregate_context() within
5498
+** value of N in any subsequent call to sqlite3_aggregate_context() within
54645499
** the same aggregate function instance will not resize the memory
54655500
** allocation.)^ Within the xFinal callback, it is customary to set
54665501
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
54675502
** pointless memory allocations occur.
54685503
**
54695504
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,13 +121,13 @@
121 **
122 ** See also: [sqlite3_libversion()],
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.32.0"
127 #define SQLITE_VERSION_NUMBER 3032000
128 #define SQLITE_SOURCE_ID "2020-04-20 17:35:32 2fc80ef16ce5878311ab88a0c64631813572ffbb71f75363b4619c9667e0926b"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
@@ -297,30 +297,26 @@
297 ** for the [sqlite3] object.
298 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
299 ** the [sqlite3] object is successfully destroyed and all associated
300 ** resources are deallocated.
301 **
 
 
 
 
302 ** ^If the database connection is associated with unfinalized prepared
303 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
304 ** will leave the database connection open and return [SQLITE_BUSY].
305 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
306 ** and/or unfinished sqlite3_backups, then the database connection becomes
307 ** an unusable "zombie" which will automatically be deallocated when the
308 ** last prepared statement is finalized or the last sqlite3_backup is
309 ** finished. The sqlite3_close_v2() interface is intended for use with
310 ** host languages that are garbage collected, and where the order in which
311 ** destructors are called is arbitrary.
312 **
313 ** Applications should [sqlite3_finalize | finalize] all [prepared statements],
314 ** [sqlite3_blob_close | close] all [BLOB handles], and
315 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
316 ** with the [sqlite3] object prior to attempting to close the object. ^If
317 ** sqlite3_close_v2() is called on a [database connection] that still has
318 ** outstanding [prepared statements], [BLOB handles], and/or
319 ** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
320 ** of resources is deferred until all [prepared statements], [BLOB handles],
321 ** and [sqlite3_backup] objects are also destroyed.
322 **
323 ** ^If an [sqlite3] object is destroyed while a transaction is open,
324 ** the transaction is automatically rolled back.
325 **
326 ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
@@ -505,22 +501,25 @@
505 #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
506 #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
507 #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
508 #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
509 #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
 
510 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
511 #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
512 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
513 #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
 
514 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
515 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
516 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
517 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
518 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
519 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
520 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
521 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
 
522 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
523 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
524 #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
525 #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
526 #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
@@ -1111,10 +1110,15 @@
1111 ** a single attached database that occur due to other database connections,
1112 ** but omits changes implemented by the database connection on which it is
1113 ** called. This file control is the only mechanism to detect changes that
1114 ** happen either internally or externally and that are associated with
1115 ** a particular attached database.
 
 
 
 
 
1116 **
1117 ** <li>[[SQLITE_FCNTL_CKPT_DONE]]
1118 ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
1119 ** in wal mode after the client has finished copying pages from the wal
1120 ** file to the database file, but before the *-shm file is updated to
@@ -1156,10 +1160,11 @@
1156 #define SQLITE_FCNTL_LOCK_TIMEOUT 34
1157 #define SQLITE_FCNTL_DATA_VERSION 35
1158 #define SQLITE_FCNTL_SIZE_LIMIT 36
1159 #define SQLITE_FCNTL_CKPT_DONE 37
1160 #define SQLITE_FCNTL_RESERVE_BYTES 38
 
1161
1162 /* deprecated names */
1163 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1164 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1165 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -3534,12 +3539,23 @@
3534 **
3535 ** These are utility routines, useful to [VFS|custom VFS implementations],
3536 ** that check if a database file was a URI that contained a specific query
3537 ** parameter, and if so obtains the value of that query parameter.
3538 **
3539 ** If F is the database filename pointer passed into the xOpen() method of
3540 ** a VFS implementation or it is the return value of [sqlite3_db_filename()]
 
 
 
 
 
 
 
 
 
 
 
3541 ** and if P is the name of the query parameter, then
3542 ** sqlite3_uri_parameter(F,P) returns the value of the P
3543 ** parameter if it exists or a NULL pointer if P does not appear as a
3544 ** query parameter on F. If P is a query parameter of F and it
3545 ** has no explicit value, then sqlite3_uri_parameter(F,P) returns
@@ -3618,10 +3634,29 @@
3618 */
3619 SQLITE_API const char *sqlite3_filename_database(const char*);
3620 SQLITE_API const char *sqlite3_filename_journal(const char*);
3621 SQLITE_API const char *sqlite3_filename_wal(const char*);
3622
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3623 /*
3624 ** CAPI3REF: Create and Destroy VFS Filenames
3625 **
3626 ** These interfces are provided for use by [VFS shim] implementations and
3627 ** are not useful outside of that context.
@@ -3652,11 +3687,11 @@
3652 ** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
3653 ** be NULL pointers, though they can be empty strings.
3654 **
3655 ** The sqlite3_free_filename(Y) routine releases a memory allocation
3656 ** previously obtained from sqlite3_create_filename(). Invoking
3657 ** sqlite3_free_filename(Y) is a NULL pointer is a harmless no-op.
3658 **
3659 ** If the Y parameter to sqlite3_free_filename(Y) is anything other
3660 ** than a NULL pointer or a pointer previously acquired from
3661 ** sqlite3_create_filename(), then bad things such as heap
3662 ** corruption or segfaults may occur. The value Y should be
@@ -5458,11 +5493,11 @@
5458 ** when first called if N is less than or equal to zero or if a memory
5459 ** allocate error occurs.
5460 **
5461 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
5462 ** determined by the N parameter on first successful call. Changing the
5463 ** value of N in any subsequents call to sqlite3_aggregate_context() within
5464 ** the same aggregate function instance will not resize the memory
5465 ** allocation.)^ Within the xFinal callback, it is customary to set
5466 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
5467 ** pointless memory allocations occur.
5468 **
5469
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,13 +121,13 @@
121 **
122 ** See also: [sqlite3_libversion()],
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.32.1"
127 #define SQLITE_VERSION_NUMBER 3032001
128 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
@@ -297,30 +297,26 @@
297 ** for the [sqlite3] object.
298 ** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
299 ** the [sqlite3] object is successfully destroyed and all associated
300 ** resources are deallocated.
301 **
302 ** Ideally, applications should [sqlite3_finalize | finalize] all
303 ** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
304 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
305 ** with the [sqlite3] object prior to attempting to close the object.
306 ** ^If the database connection is associated with unfinalized prepared
307 ** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
308 ** sqlite3_close() will leave the database connection open and return
309 ** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
310 ** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
311 ** it returns [SQLITE_OK] regardless, but instead of deallocating the database
312 ** connection immediately, it marks the database connection as an unusable
313 ** "zombie" and makes arrangements to automatically deallocate the database
314 ** connection after all prepared statements are finalized, all BLOB handles
315 ** are closed, and all backups have finished. The sqlite3_close_v2() interface
316 ** is intended for use with host languages that are garbage collected, and
317 ** where the order in which destructors are called is arbitrary.
 
 
 
 
 
 
 
 
318 **
319 ** ^If an [sqlite3] object is destroyed while a transaction is open,
320 ** the transaction is automatically rolled back.
321 **
322 ** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
@@ -505,22 +501,25 @@
501 #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
502 #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
503 #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
504 #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
505 #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
506 #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
507 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
508 #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
509 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
510 #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
511 #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
512 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
513 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
514 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
515 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
516 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
517 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
518 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
519 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
520 #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
521 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
522 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
523 #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
524 #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
525 #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
@@ -1111,10 +1110,15 @@
1110 ** a single attached database that occur due to other database connections,
1111 ** but omits changes implemented by the database connection on which it is
1112 ** called. This file control is the only mechanism to detect changes that
1113 ** happen either internally or externally and that are associated with
1114 ** a particular attached database.
1115 **
1116 ** <li>[[SQLITE_FCNTL_CKPT_START]]
1117 ** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
1118 ** in wal mode before the client starts to copy pages from the wal
1119 ** file to the database file.
1120 **
1121 ** <li>[[SQLITE_FCNTL_CKPT_DONE]]
1122 ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
1123 ** in wal mode after the client has finished copying pages from the wal
1124 ** file to the database file, but before the *-shm file is updated to
@@ -1156,10 +1160,11 @@
1160 #define SQLITE_FCNTL_LOCK_TIMEOUT 34
1161 #define SQLITE_FCNTL_DATA_VERSION 35
1162 #define SQLITE_FCNTL_SIZE_LIMIT 36
1163 #define SQLITE_FCNTL_CKPT_DONE 37
1164 #define SQLITE_FCNTL_RESERVE_BYTES 38
1165 #define SQLITE_FCNTL_CKPT_START 39
1166
1167 /* deprecated names */
1168 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1169 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1170 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -3534,12 +3539,23 @@
3539 **
3540 ** These are utility routines, useful to [VFS|custom VFS implementations],
3541 ** that check if a database file was a URI that contained a specific query
3542 ** parameter, and if so obtains the value of that query parameter.
3543 **
3544 ** The first parameter to these interfaces (hereafter referred to
3545 ** as F) must be one of:
3546 ** <ul>
3547 ** <li> A database filename pointer created by the SQLite core and
3548 ** passed into the xOpen() method of a VFS implemention, or
3549 ** <li> A filename obtained from [sqlite3_db_filename()], or
3550 ** <li> A new filename constructed using [sqlite3_create_filename()].
3551 ** </ul>
3552 ** If the F parameter is not one of the above, then the behavior is
3553 ** undefined and probably undesirable. Older versions of SQLite were
3554 ** more tolerant of invalid F parameters than newer versions.
3555 **
3556 ** If F is a suitable filename (as described in the previous paragraph)
3557 ** and if P is the name of the query parameter, then
3558 ** sqlite3_uri_parameter(F,P) returns the value of the P
3559 ** parameter if it exists or a NULL pointer if P does not appear as a
3560 ** query parameter on F. If P is a query parameter of F and it
3561 ** has no explicit value, then sqlite3_uri_parameter(F,P) returns
@@ -3618,10 +3634,29 @@
3634 */
3635 SQLITE_API const char *sqlite3_filename_database(const char*);
3636 SQLITE_API const char *sqlite3_filename_journal(const char*);
3637 SQLITE_API const char *sqlite3_filename_wal(const char*);
3638
3639 /*
3640 ** CAPI3REF: Database File Corresponding To A Journal
3641 **
3642 ** ^If X is the name of a rollback or WAL-mode journal file that is
3643 ** passed into the xOpen method of [sqlite3_vfs], then
3644 ** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
3645 ** object that represents the main database file.
3646 **
3647 ** This routine is intended for use in custom [VFS] implementations
3648 ** only. It is not a general-purpose interface.
3649 ** The argument sqlite3_file_object(X) must be a filename pointer that
3650 ** has been passed into [sqlite3_vfs].xOpen method where the
3651 ** flags parameter to xOpen contains one of the bits
3652 ** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
3653 ** of this routine results in undefined and probably undesirable
3654 ** behavior.
3655 */
3656 SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
3657
3658 /*
3659 ** CAPI3REF: Create and Destroy VFS Filenames
3660 **
3661 ** These interfces are provided for use by [VFS shim] implementations and
3662 ** are not useful outside of that context.
@@ -3652,11 +3687,11 @@
3687 ** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
3688 ** be NULL pointers, though they can be empty strings.
3689 **
3690 ** The sqlite3_free_filename(Y) routine releases a memory allocation
3691 ** previously obtained from sqlite3_create_filename(). Invoking
3692 ** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
3693 **
3694 ** If the Y parameter to sqlite3_free_filename(Y) is anything other
3695 ** than a NULL pointer or a pointer previously acquired from
3696 ** sqlite3_create_filename(), then bad things such as heap
3697 ** corruption or segfaults may occur. The value Y should be
@@ -5458,11 +5493,11 @@
5493 ** when first called if N is less than or equal to zero or if a memory
5494 ** allocate error occurs.
5495 **
5496 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
5497 ** determined by the N parameter on first successful call. Changing the
5498 ** value of N in any subsequent call to sqlite3_aggregate_context() within
5499 ** the same aggregate function instance will not resize the memory
5500 ** allocation.)^ Within the xFinal callback, it is customary to set
5501 ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
5502 ** pointless memory allocations occur.
5503 **
5504
+2 -1
--- src/style.c
+++ src/style.c
@@ -707,11 +707,11 @@
707707
708708
/*
709709
** Generate code to load a single javascript file
710710
*/
711711
void style_load_one_js_file(const char *zFile){
712
- @ <script src='%R/builtin/%s(zFile)?id=%S(MANIFEST_UUID)'></script>
712
+ @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
713713
}
714714
715715
/*
716716
** All extra JS files to load.
717717
*/
@@ -1259,10 +1259,11 @@
12591259
@ anonymous-adds = %s(find_anon_capabilities(zCap))<br />
12601260
}
12611261
@ g.zRepositoryName = %h(g.zRepositoryName)<br />
12621262
@ load_average() = %f(load_average())<br />
12631263
@ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
1264
+ @ fossil_exe_id() = %h(fossil_exe_id())<br />
12641265
@ <hr />
12651266
P("HTTP_USER_AGENT");
12661267
cgi_print_all(showAll, 0);
12671268
if( showAll && blob_size(&g.httpHeader)>0 ){
12681269
@ <hr />
12691270
--- src/style.c
+++ src/style.c
@@ -707,11 +707,11 @@
707
708 /*
709 ** Generate code to load a single javascript file
710 */
711 void style_load_one_js_file(const char *zFile){
712 @ <script src='%R/builtin/%s(zFile)?id=%S(MANIFEST_UUID)'></script>
713 }
714
715 /*
716 ** All extra JS files to load.
717 */
@@ -1259,10 +1259,11 @@
1259 @ anonymous-adds = %s(find_anon_capabilities(zCap))<br />
1260 }
1261 @ g.zRepositoryName = %h(g.zRepositoryName)<br />
1262 @ load_average() = %f(load_average())<br />
1263 @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
 
1264 @ <hr />
1265 P("HTTP_USER_AGENT");
1266 cgi_print_all(showAll, 0);
1267 if( showAll && blob_size(&g.httpHeader)>0 ){
1268 @ <hr />
1269
--- src/style.c
+++ src/style.c
@@ -707,11 +707,11 @@
707
708 /*
709 ** Generate code to load a single javascript file
710 */
711 void style_load_one_js_file(const char *zFile){
712 @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
713 }
714
715 /*
716 ** All extra JS files to load.
717 */
@@ -1259,10 +1259,11 @@
1259 @ anonymous-adds = %s(find_anon_capabilities(zCap))<br />
1260 }
1261 @ g.zRepositoryName = %h(g.zRepositoryName)<br />
1262 @ load_average() = %f(load_average())<br />
1263 @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
1264 @ fossil_exe_id() = %h(fossil_exe_id())<br />
1265 @ <hr />
1266 P("HTTP_USER_AGENT");
1267 cgi_print_all(showAll, 0);
1268 if( showAll && blob_size(&g.httpHeader)>0 ){
1269 @ <hr />
1270
+1 -1
--- src/tar.c
+++ src/tar.c
@@ -443,11 +443,11 @@
443443
tar_begin(-1);
444444
for(i=3; i<g.argc; i++){
445445
Blob file;
446446
blob_zero(&file);
447447
blob_read_from_file(&file, g.argv[i], eFType);
448
- tar_add_file(g.argv[i], &file, file_perm(0,0), file_mtime(0,0));
448
+ tar_add_file(g.argv[i], &file, file_perm(0,eFType), file_mtime(0,eFType));
449449
blob_reset(&file);
450450
}
451451
tar_finish(&zip);
452452
blob_write_to_file(&zip, g.argv[2]);
453453
}
454454
455455
ADDED src/terminal.c
--- src/tar.c
+++ src/tar.c
@@ -443,11 +443,11 @@
443 tar_begin(-1);
444 for(i=3; i<g.argc; i++){
445 Blob file;
446 blob_zero(&file);
447 blob_read_from_file(&file, g.argv[i], eFType);
448 tar_add_file(g.argv[i], &file, file_perm(0,0), file_mtime(0,0));
449 blob_reset(&file);
450 }
451 tar_finish(&zip);
452 blob_write_to_file(&zip, g.argv[2]);
453 }
454
455 DDED src/terminal.c
--- src/tar.c
+++ src/tar.c
@@ -443,11 +443,11 @@
443 tar_begin(-1);
444 for(i=3; i<g.argc; i++){
445 Blob file;
446 blob_zero(&file);
447 blob_read_from_file(&file, g.argv[i], eFType);
448 tar_add_file(g.argv[i], &file, file_perm(0,eFType), file_mtime(0,eFType));
449 blob_reset(&file);
450 }
451 tar_finish(&zip);
452 blob_write_to_file(&zip, g.argv[2]);
453 }
454
455 DDED src/terminal.c
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -0,0 +1,9 @@
1
+COMMAND: test-terminal-size
2
+**
3
+** Show the size of the terminal window from which the command is launched
4
+** as two integers, the width in characters and the height in lines.
5
+**
6
+** If the size cannot be determined, two zeros are shown.
7
+*/
8
+void test_terminal_size_cmd(void* Technically, this infosuch is supported; set;
9
+ fossil_print("%d %d\nchar *zNoC!=-1!=-1
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -0,0 +1,9 @@
1 COMMAND: test-terminal-size
2 **
3 ** Show the size of the terminal window from which the command is launched
4 ** as two integers, the width in characters and the height in lines.
5 **
6 ** If the size cannot be determined, two zeros are shown.
7 */
8 void test_terminal_size_cmd(void* Technically, this infosuch is supported; set;
9 fossil_print("%d %d\nchar *zNoC!=-1!=-1
+1 -1
--- src/th_main.c
+++ src/th_main.c
@@ -1500,11 +1500,11 @@
15001500
if( argc!=3 ){
15011501
return Th_WrongNumArgs(interp, "unversioned content FILENAME");
15021502
}
15031503
if( Th_IsRepositoryOpen() ){
15041504
Blob content;
1505
- if( unversioned_content(argv[2], &content)==0 ){
1505
+ if( unversioned_content(argv[2], &content)!=0 ){
15061506
Th_SetResult(interp, blob_str(&content), blob_size(&content));
15071507
blob_reset(&content);
15081508
return TH_OK;
15091509
}else{
15101510
return TH_ERROR;
15111511
--- src/th_main.c
+++ src/th_main.c
@@ -1500,11 +1500,11 @@
1500 if( argc!=3 ){
1501 return Th_WrongNumArgs(interp, "unversioned content FILENAME");
1502 }
1503 if( Th_IsRepositoryOpen() ){
1504 Blob content;
1505 if( unversioned_content(argv[2], &content)==0 ){
1506 Th_SetResult(interp, blob_str(&content), blob_size(&content));
1507 blob_reset(&content);
1508 return TH_OK;
1509 }else{
1510 return TH_ERROR;
1511
--- src/th_main.c
+++ src/th_main.c
@@ -1500,11 +1500,11 @@
1500 if( argc!=3 ){
1501 return Th_WrongNumArgs(interp, "unversioned content FILENAME");
1502 }
1503 if( Th_IsRepositoryOpen() ){
1504 Blob content;
1505 if( unversioned_content(argv[2], &content)!=0 ){
1506 Th_SetResult(interp, blob_str(&content), blob_size(&content));
1507 blob_reset(&content);
1508 return TH_OK;
1509 }else{
1510 return TH_ERROR;
1511
+28 -2
--- src/timeline.c
+++ src/timeline.c
@@ -1312,11 +1312,11 @@
13121312
){
13131313
if( zChng==0 || zChng[0]==0 ) return;
13141314
blob_append_sql(pSql," AND event.objid IN ("
13151315
"SELECT mlink.mid FROM mlink, filename"
13161316
" WHERE mlink.fnid=filename.fnid AND %s)",
1317
- glob_expr("filename.name", zChng));
1317
+ glob_expr("filename.name", mprintf("\"%s\"", zChng)));
13181318
}
13191319
static void addFileGlobDescription(
13201320
const char *zChng, /* The filename GLOB list */
13211321
Blob *pDescription /* Result description */
13221322
){
@@ -1742,10 +1742,11 @@
17421742
|| (bisectLocal && !g.perm.Setup)
17431743
){
17441744
login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
17451745
return;
17461746
}
1747
+ etag_check(ETAG_QUERY|ETAG_COOKIE|ETAG_DATA, 0);
17471748
cookie_read_parameter("y","y");
17481749
zType = P("y");
17491750
if( zType==0 ){
17501751
zType = g.perm.Read ? "ci" : "all";
17511752
cgi_set_parameter("y", zType);
@@ -1795,10 +1796,11 @@
17951796
}else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
17961797
matchStyle = MS_REGEXP;
17971798
}else{
17981799
/* For exact maching, inhibit links to the selected tag. */
17991800
zThisTag = zTagName;
1801
+ Th_Store("current_checkin", zTagName);
18001802
}
18011803
18021804
/* Display a checkbox to enable/disable display of related check-ins. */
18031805
if( advancedMenu ){
18041806
style_submenu_checkbox("rel", "Related", 0, 0);
@@ -1877,11 +1879,25 @@
18771879
" HAVING count(*)>1;\n"
18781880
"INSERT OR IGNORE INTO rnfork(rid)"
18791881
" SELECT cid FROM plink\n"
18801882
" WHERE (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
18811883
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n"
1882
- " AND pid IN rnfork;",
1884
+ " GROUP BY cid"
1885
+ " HAVING count(*)>1;\n",
1886
+ TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
1887
+ );
1888
+ db_multi_exec(
1889
+ "INSERT OR IGNORE INTO rnfork(rid)\n"
1890
+ " SELECT cid FROM plink\n"
1891
+ " WHERE pid IN rnfork"
1892
+ " AND (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
1893
+ " (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n"
1894
+ " UNION "
1895
+ " SELECT pid FROM plink\n"
1896
+ " WHERE cid IN rnfork"
1897
+ " AND (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
1898
+ " (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n",
18831899
TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
18841900
);
18851901
tmFlags |= TIMELINE_UNHIDE;
18861902
zType = "ci";
18871903
disableY = 1;
@@ -2186,10 +2202,17 @@
21862202
"CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
21872203
"INSERT OR IGNORE INTO selected_nodes"
21882204
" SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
21892205
" WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
21902206
);
2207
+ if( zMark ){
2208
+ /* If the t=release option is used with m=UUID, then also
2209
+ ** include the UUID check-in in the display list */
2210
+ int ridMark = name_to_rid(zMark);
2211
+ db_multi_exec(
2212
+ "INSERT OR IGNORE INTO selected_nodes(rid) VALUES(%d)", ridMark);
2213
+ }
21912214
if( !related ){
21922215
blob_append_sql(&cond, " AND blob.rid IN selected_nodes");
21932216
}else{
21942217
db_multi_exec(
21952218
"CREATE TEMP TABLE related_nodes(rid INTEGER PRIMARY KEY);"
@@ -2412,10 +2435,13 @@
24122435
blob_appendf(&desc, " related to tags matching %h", zMatchDesc);
24132436
}else{
24142437
blob_appendf(&desc, " with tags matching %h", zMatchDesc);
24152438
}
24162439
}
2440
+ if( zMark ){
2441
+ blob_appendf(&desc," plus check-in \"%h\"", zMark);
2442
+ }
24172443
tmFlags |= TIMELINE_XMERGE | TIMELINE_FILLGAPS;
24182444
}
24192445
addFileGlobDescription(zChng, &desc);
24202446
if( rAfter>0.0 ){
24212447
if( rBefore>0.0 ){
24222448
--- src/timeline.c
+++ src/timeline.c
@@ -1312,11 +1312,11 @@
1312 ){
1313 if( zChng==0 || zChng[0]==0 ) return;
1314 blob_append_sql(pSql," AND event.objid IN ("
1315 "SELECT mlink.mid FROM mlink, filename"
1316 " WHERE mlink.fnid=filename.fnid AND %s)",
1317 glob_expr("filename.name", zChng));
1318 }
1319 static void addFileGlobDescription(
1320 const char *zChng, /* The filename GLOB list */
1321 Blob *pDescription /* Result description */
1322 ){
@@ -1742,10 +1742,11 @@
1742 || (bisectLocal && !g.perm.Setup)
1743 ){
1744 login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
1745 return;
1746 }
 
1747 cookie_read_parameter("y","y");
1748 zType = P("y");
1749 if( zType==0 ){
1750 zType = g.perm.Read ? "ci" : "all";
1751 cgi_set_parameter("y", zType);
@@ -1795,10 +1796,11 @@
1795 }else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
1796 matchStyle = MS_REGEXP;
1797 }else{
1798 /* For exact maching, inhibit links to the selected tag. */
1799 zThisTag = zTagName;
 
1800 }
1801
1802 /* Display a checkbox to enable/disable display of related check-ins. */
1803 if( advancedMenu ){
1804 style_submenu_checkbox("rel", "Related", 0, 0);
@@ -1877,11 +1879,25 @@
1877 " HAVING count(*)>1;\n"
1878 "INSERT OR IGNORE INTO rnfork(rid)"
1879 " SELECT cid FROM plink\n"
1880 " WHERE (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
1881 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n"
1882 " AND pid IN rnfork;",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1883 TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
1884 );
1885 tmFlags |= TIMELINE_UNHIDE;
1886 zType = "ci";
1887 disableY = 1;
@@ -2186,10 +2202,17 @@
2186 "CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
2187 "INSERT OR IGNORE INTO selected_nodes"
2188 " SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
2189 " WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
2190 );
 
 
 
 
 
 
 
2191 if( !related ){
2192 blob_append_sql(&cond, " AND blob.rid IN selected_nodes");
2193 }else{
2194 db_multi_exec(
2195 "CREATE TEMP TABLE related_nodes(rid INTEGER PRIMARY KEY);"
@@ -2412,10 +2435,13 @@
2412 blob_appendf(&desc, " related to tags matching %h", zMatchDesc);
2413 }else{
2414 blob_appendf(&desc, " with tags matching %h", zMatchDesc);
2415 }
2416 }
 
 
 
2417 tmFlags |= TIMELINE_XMERGE | TIMELINE_FILLGAPS;
2418 }
2419 addFileGlobDescription(zChng, &desc);
2420 if( rAfter>0.0 ){
2421 if( rBefore>0.0 ){
2422
--- src/timeline.c
+++ src/timeline.c
@@ -1312,11 +1312,11 @@
1312 ){
1313 if( zChng==0 || zChng[0]==0 ) return;
1314 blob_append_sql(pSql," AND event.objid IN ("
1315 "SELECT mlink.mid FROM mlink, filename"
1316 " WHERE mlink.fnid=filename.fnid AND %s)",
1317 glob_expr("filename.name", mprintf("\"%s\"", zChng)));
1318 }
1319 static void addFileGlobDescription(
1320 const char *zChng, /* The filename GLOB list */
1321 Blob *pDescription /* Result description */
1322 ){
@@ -1742,10 +1742,11 @@
1742 || (bisectLocal && !g.perm.Setup)
1743 ){
1744 login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
1745 return;
1746 }
1747 etag_check(ETAG_QUERY|ETAG_COOKIE|ETAG_DATA, 0);
1748 cookie_read_parameter("y","y");
1749 zType = P("y");
1750 if( zType==0 ){
1751 zType = g.perm.Read ? "ci" : "all";
1752 cgi_set_parameter("y", zType);
@@ -1795,10 +1796,11 @@
1796 }else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
1797 matchStyle = MS_REGEXP;
1798 }else{
1799 /* For exact maching, inhibit links to the selected tag. */
1800 zThisTag = zTagName;
1801 Th_Store("current_checkin", zTagName);
1802 }
1803
1804 /* Display a checkbox to enable/disable display of related check-ins. */
1805 if( advancedMenu ){
1806 style_submenu_checkbox("rel", "Related", 0, 0);
@@ -1877,11 +1879,25 @@
1879 " HAVING count(*)>1;\n"
1880 "INSERT OR IGNORE INTO rnfork(rid)"
1881 " SELECT cid FROM plink\n"
1882 " WHERE (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
1883 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n"
1884 " GROUP BY cid"
1885 " HAVING count(*)>1;\n",
1886 TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
1887 );
1888 db_multi_exec(
1889 "INSERT OR IGNORE INTO rnfork(rid)\n"
1890 " SELECT cid FROM plink\n"
1891 " WHERE pid IN rnfork"
1892 " AND (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
1893 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n"
1894 " UNION "
1895 " SELECT pid FROM plink\n"
1896 " WHERE cid IN rnfork"
1897 " AND (SELECT value FROM tagxref WHERE tagid=%d AND rid=cid)=="
1898 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n",
1899 TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
1900 );
1901 tmFlags |= TIMELINE_UNHIDE;
1902 zType = "ci";
1903 disableY = 1;
@@ -2186,10 +2202,17 @@
2202 "CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
2203 "INSERT OR IGNORE INTO selected_nodes"
2204 " SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
2205 " WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
2206 );
2207 if( zMark ){
2208 /* If the t=release option is used with m=UUID, then also
2209 ** include the UUID check-in in the display list */
2210 int ridMark = name_to_rid(zMark);
2211 db_multi_exec(
2212 "INSERT OR IGNORE INTO selected_nodes(rid) VALUES(%d)", ridMark);
2213 }
2214 if( !related ){
2215 blob_append_sql(&cond, " AND blob.rid IN selected_nodes");
2216 }else{
2217 db_multi_exec(
2218 "CREATE TEMP TABLE related_nodes(rid INTEGER PRIMARY KEY);"
@@ -2412,10 +2435,13 @@
2435 blob_appendf(&desc, " related to tags matching %h", zMatchDesc);
2436 }else{
2437 blob_appendf(&desc, " with tags matching %h", zMatchDesc);
2438 }
2439 }
2440 if( zMark ){
2441 blob_appendf(&desc," plus check-in \"%h\"", zMark);
2442 }
2443 tmFlags |= TIMELINE_XMERGE | TIMELINE_FILLGAPS;
2444 }
2445 addFileGlobDescription(zChng, &desc);
2446 if( rAfter>0.0 ){
2447 if( rBefore>0.0 ){
2448
+73 -17
--- src/unversioned.c
+++ src/unversioned.c
@@ -85,25 +85,40 @@
8585
}
8686
8787
/*
8888
** Initialize pContent to be the content of an unversioned file zName.
8989
**
90
-** Return 0 on success. Return 1 if zName is not found.
90
+** Return 0 on failures.
91
+** Return 1 if the file is found by name.
92
+** Return 2 if the file is found by hash.
9193
*/
9294
int unversioned_content(const char *zName, Blob *pContent){
9395
Stmt q;
94
- int rc = 1;
96
+ int rc = 0;
9597
blob_init(pContent, 0, 0);
96
- db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q", zName);
98
+ db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q",
99
+ zName);
97100
if( db_step(&q)==SQLITE_ROW ){
98101
db_column_blob(&q, 1, pContent);
99102
if( db_column_int(&q, 0)==1 ){
100103
blob_uncompress(pContent, pContent);
101104
}
102
- rc = 0;
105
+ rc = 1;
103106
}
104107
db_finalize(&q);
108
+ if( rc==0 && validate16(zName,-1) ){
109
+ db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE hash=%Q",
110
+ zName);
111
+ if( db_step(&q)==SQLITE_ROW ){
112
+ db_column_blob(&q, 1, pContent);
113
+ if( db_column_int(&q, 0)==1 ){
114
+ blob_uncompress(pContent, pContent);
115
+ }
116
+ rc = 2;
117
+ }
118
+ db_finalize(&q);
119
+ }
105120
return rc;
106121
}
107122
108123
/*
109124
** Write unversioned content into the database.
@@ -237,11 +252,14 @@
237252
** edit FILE Bring up FILE in a text editor for modification.
238253
**
239254
** export FILE OUTPUT Write the content of FILE into OUTPUT on disk
240255
**
241256
** list | ls Show all unversioned files held in the local
242
-** repository.
257
+** repository. Options:
258
+**
259
+** --glob PATTERN Show only files that match
260
+** --like PATTERN Show only files that match
243261
**
244262
** revert ?URL? Restore the state of all unversioned files in the
245263
** local repository to match the remote repository
246264
** URL.
247265
**
@@ -250,11 +268,14 @@
250268
** -n|--dryrun Show what would have happened
251269
**
252270
** remove|rm|delete FILE ...
253271
** Remove unversioned files from the local repository.
254272
** Changes are not pushed to other repositories until
255
-** the next sync.
273
+** the next sync. Options:
274
+**
275
+** --glob PATTERN Remove files that match
276
+** --like PATTERN Remove files that match
256277
**
257278
** sync ?URL? Synchronize the state of all unversioned files with
258279
** the remote repository URL. The most recent version
259280
** of each file is propagated to all repositories and
260281
** all prior versions are permanently forgotten.
@@ -322,11 +343,11 @@
322343
int i;
323344
verify_all_options();
324345
db_begin_transaction();
325346
for(i=3; i<g.argc; i++){
326347
Blob content;
327
- if( unversioned_content(g.argv[i], &content)==0 ){
348
+ if( unversioned_content(g.argv[i], &content)!=0 ){
328349
blob_write_to_file(&content, "-");
329350
}
330351
blob_reset(&content);
331352
}
332353
db_end_transaction(0);
@@ -339,16 +360,18 @@
339360
340361
verify_all_options();
341362
if( g.argc!=4) usage("edit UVFILE");
342363
zUVFile = g.argv[3];
343364
zEditor = fossil_text_editor();
344
- if( zEditor==0 ) fossil_fatal("no text editor - set the VISUAL env variable");
365
+ if( zEditor==0 ){
366
+ fossil_fatal("no text editor - set the VISUAL env variable");
367
+ }
345368
zTFile = fossil_temp_filename();
346369
if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
347370
db_begin_transaction();
348371
content_rcvid_init("#!fossil unversioned edit");
349
- if( unversioned_content(zUVFile, &content) ){
372
+ if( unversioned_content(zUVFile, &content)==0 ){
350373
fossil_fatal("no such uv-file: %Q", zUVFile);
351374
}
352375
if( looks_like_binary(&content) ){
353376
fossil_fatal("cannot edit binary content");
354377
}
@@ -373,11 +396,11 @@
373396
blob_reset(&content);
374397
}else if( memcmp(zCmd, "export", nCmd)==0 ){
375398
Blob content;
376399
verify_all_options();
377400
if( g.argc!=5 ) usage("export UVFILE OUTPUT");
378
- if( unversioned_content(g.argv[3], &content) ){
401
+ if( unversioned_content(g.argv[3], &content)==0 ){
379402
fossil_fatal("no such uv-file: %Q", g.argv[3]);
380403
}
381404
blob_write_to_file(&content, g.argv[4]);
382405
blob_reset(&content);
383406
}else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
@@ -386,26 +409,40 @@
386409
fossil_print("%s\n", unversioned_content_hash(debugFlag));
387410
}else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
388411
Stmt q;
389412
int allFlag = find_option("all","a",0)!=0;
390413
int longFlag = find_option("l",0,0)!=0 || (nCmd>1 && zCmd[1]=='i');
414
+ char *zPattern = sqlite3_mprintf("true");
415
+ const char *zGlob;
416
+ zGlob = find_option("glob",0,1);
417
+ if( zGlob ){
418
+ sqlite3_free(zPattern);
419
+ zPattern = sqlite3_mprintf("(name GLOB %Q)", zGlob);
420
+ }
421
+ zGlob = find_option("like",0,1);
422
+ if( zGlob ){
423
+ sqlite3_free(zPattern);
424
+ zPattern = sqlite3_mprintf("(name LIKE %Q)", zGlob);
425
+ }
391426
verify_all_options();
392427
if( !longFlag ){
393428
if( allFlag ){
394
- db_prepare(&q, "SELECT name FROM unversioned ORDER BY name");
429
+ db_prepare(&q, "SELECT name FROM unversioned WHERE %s ORDER BY name",
430
+ zPattern/*safe-for-%s*/);
395431
}else{
396
- db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL"
397
- " ORDER BY name");
432
+ db_prepare(&q, "SELECT name FROM unversioned"
433
+ " WHERE %s AND hash IS NOT NULL"
434
+ " ORDER BY name", zPattern/*safe-for-%s*/);
398435
}
399436
while( db_step(&q)==SQLITE_ROW ){
400437
fossil_print("%s\n", db_column_text(&q,0));
401438
}
402439
}else{
403440
db_prepare(&q,
404441
"SELECT hash, datetime(mtime,'unixepoch'), sz, length(content), name"
405
- " FROM unversioned"
406
- " ORDER BY name;"
442
+ " FROM unversioned WHERE %s"
443
+ " ORDER BY name;", zPattern/*safe-for-%s*/
407444
);
408445
while( db_step(&q)==SQLITE_ROW ){
409446
const char *zHash = db_column_text(&q, 0);
410447
const char *zNoContent = "";
411448
if( zHash==0 ){
@@ -423,20 +460,37 @@
423460
zNoContent
424461
);
425462
}
426463
}
427464
db_finalize(&q);
465
+ sqlite3_free(zPattern);
428466
}else if( memcmp(zCmd, "revert", nCmd)==0 ){
429
- unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
467
+ unsigned syncFlags =
468
+ unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
430469
g.argv[1] = "sync";
431470
g.argv[2] = "--uv-noop";
432471
sync_unversioned(syncFlags);
433472
}else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0
434473
|| memcmp(zCmd, "delete", nCmd)==0 ){
435474
int i;
436
- verify_all_options();
475
+ const char *zGlob;
437476
db_begin_transaction();
477
+ while( (zGlob = find_option("glob",0,1))!=0 ){
478
+ db_multi_exec(
479
+ "UPDATE unversioned"
480
+ " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name GLOB %Q",
481
+ mtime, zGlob
482
+ );
483
+ }
484
+ while( (zGlob = find_option("like",0,1))!=0 ){
485
+ db_multi_exec(
486
+ "UPDATE unversioned"
487
+ " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name LIKE %Q",
488
+ mtime, zGlob
489
+ );
490
+ }
491
+ verify_all_options();
438492
for(i=3; i<g.argc; i++){
439493
db_multi_exec(
440494
"UPDATE unversioned"
441495
" SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name=%Q",
442496
mtime, g.argv[i]
@@ -485,10 +539,11 @@
485539
int showDel = 0;
486540
char zSzName[100];
487541
488542
login_check_credentials();
489543
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
544
+ etag_check(ETAG_DATA,0);
490545
style_header("Unversioned Files");
491546
if( !db_table_exists("repository","unversioned") ){
492547
@ No unversioned files on this server
493548
style_footer();
494549
return;
@@ -597,10 +652,11 @@
597652
Blob json;
598653
599654
login_check_credentials();
600655
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
601656
cgi_set_content_type("text/json");
657
+ etag_check(ETAG_DATA,0);
602658
if( !db_table_exists("repository","unversioned") ){
603659
blob_init(&json, "[]", -1);
604660
cgi_set_content(&json);
605661
return;
606662
}
607663
--- src/unversioned.c
+++ src/unversioned.c
@@ -85,25 +85,40 @@
85 }
86
87 /*
88 ** Initialize pContent to be the content of an unversioned file zName.
89 **
90 ** Return 0 on success. Return 1 if zName is not found.
 
 
91 */
92 int unversioned_content(const char *zName, Blob *pContent){
93 Stmt q;
94 int rc = 1;
95 blob_init(pContent, 0, 0);
96 db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q", zName);
 
97 if( db_step(&q)==SQLITE_ROW ){
98 db_column_blob(&q, 1, pContent);
99 if( db_column_int(&q, 0)==1 ){
100 blob_uncompress(pContent, pContent);
101 }
102 rc = 0;
103 }
104 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
105 return rc;
106 }
107
108 /*
109 ** Write unversioned content into the database.
@@ -237,11 +252,14 @@
237 ** edit FILE Bring up FILE in a text editor for modification.
238 **
239 ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk
240 **
241 ** list | ls Show all unversioned files held in the local
242 ** repository.
 
 
 
243 **
244 ** revert ?URL? Restore the state of all unversioned files in the
245 ** local repository to match the remote repository
246 ** URL.
247 **
@@ -250,11 +268,14 @@
250 ** -n|--dryrun Show what would have happened
251 **
252 ** remove|rm|delete FILE ...
253 ** Remove unversioned files from the local repository.
254 ** Changes are not pushed to other repositories until
255 ** the next sync.
 
 
 
256 **
257 ** sync ?URL? Synchronize the state of all unversioned files with
258 ** the remote repository URL. The most recent version
259 ** of each file is propagated to all repositories and
260 ** all prior versions are permanently forgotten.
@@ -322,11 +343,11 @@
322 int i;
323 verify_all_options();
324 db_begin_transaction();
325 for(i=3; i<g.argc; i++){
326 Blob content;
327 if( unversioned_content(g.argv[i], &content)==0 ){
328 blob_write_to_file(&content, "-");
329 }
330 blob_reset(&content);
331 }
332 db_end_transaction(0);
@@ -339,16 +360,18 @@
339
340 verify_all_options();
341 if( g.argc!=4) usage("edit UVFILE");
342 zUVFile = g.argv[3];
343 zEditor = fossil_text_editor();
344 if( zEditor==0 ) fossil_fatal("no text editor - set the VISUAL env variable");
 
 
345 zTFile = fossil_temp_filename();
346 if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
347 db_begin_transaction();
348 content_rcvid_init("#!fossil unversioned edit");
349 if( unversioned_content(zUVFile, &content) ){
350 fossil_fatal("no such uv-file: %Q", zUVFile);
351 }
352 if( looks_like_binary(&content) ){
353 fossil_fatal("cannot edit binary content");
354 }
@@ -373,11 +396,11 @@
373 blob_reset(&content);
374 }else if( memcmp(zCmd, "export", nCmd)==0 ){
375 Blob content;
376 verify_all_options();
377 if( g.argc!=5 ) usage("export UVFILE OUTPUT");
378 if( unversioned_content(g.argv[3], &content) ){
379 fossil_fatal("no such uv-file: %Q", g.argv[3]);
380 }
381 blob_write_to_file(&content, g.argv[4]);
382 blob_reset(&content);
383 }else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
@@ -386,26 +409,40 @@
386 fossil_print("%s\n", unversioned_content_hash(debugFlag));
387 }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
388 Stmt q;
389 int allFlag = find_option("all","a",0)!=0;
390 int longFlag = find_option("l",0,0)!=0 || (nCmd>1 && zCmd[1]=='i');
 
 
 
 
 
 
 
 
 
 
 
 
391 verify_all_options();
392 if( !longFlag ){
393 if( allFlag ){
394 db_prepare(&q, "SELECT name FROM unversioned ORDER BY name");
 
395 }else{
396 db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL"
397 " ORDER BY name");
 
398 }
399 while( db_step(&q)==SQLITE_ROW ){
400 fossil_print("%s\n", db_column_text(&q,0));
401 }
402 }else{
403 db_prepare(&q,
404 "SELECT hash, datetime(mtime,'unixepoch'), sz, length(content), name"
405 " FROM unversioned"
406 " ORDER BY name;"
407 );
408 while( db_step(&q)==SQLITE_ROW ){
409 const char *zHash = db_column_text(&q, 0);
410 const char *zNoContent = "";
411 if( zHash==0 ){
@@ -423,20 +460,37 @@
423 zNoContent
424 );
425 }
426 }
427 db_finalize(&q);
 
428 }else if( memcmp(zCmd, "revert", nCmd)==0 ){
429 unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
 
430 g.argv[1] = "sync";
431 g.argv[2] = "--uv-noop";
432 sync_unversioned(syncFlags);
433 }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0
434 || memcmp(zCmd, "delete", nCmd)==0 ){
435 int i;
436 verify_all_options();
437 db_begin_transaction();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438 for(i=3; i<g.argc; i++){
439 db_multi_exec(
440 "UPDATE unversioned"
441 " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name=%Q",
442 mtime, g.argv[i]
@@ -485,10 +539,11 @@
485 int showDel = 0;
486 char zSzName[100];
487
488 login_check_credentials();
489 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
 
490 style_header("Unversioned Files");
491 if( !db_table_exists("repository","unversioned") ){
492 @ No unversioned files on this server
493 style_footer();
494 return;
@@ -597,10 +652,11 @@
597 Blob json;
598
599 login_check_credentials();
600 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
601 cgi_set_content_type("text/json");
 
602 if( !db_table_exists("repository","unversioned") ){
603 blob_init(&json, "[]", -1);
604 cgi_set_content(&json);
605 return;
606 }
607
--- src/unversioned.c
+++ src/unversioned.c
@@ -85,25 +85,40 @@
85 }
86
87 /*
88 ** Initialize pContent to be the content of an unversioned file zName.
89 **
90 ** Return 0 on failures.
91 ** Return 1 if the file is found by name.
92 ** Return 2 if the file is found by hash.
93 */
94 int unversioned_content(const char *zName, Blob *pContent){
95 Stmt q;
96 int rc = 0;
97 blob_init(pContent, 0, 0);
98 db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q",
99 zName);
100 if( db_step(&q)==SQLITE_ROW ){
101 db_column_blob(&q, 1, pContent);
102 if( db_column_int(&q, 0)==1 ){
103 blob_uncompress(pContent, pContent);
104 }
105 rc = 1;
106 }
107 db_finalize(&q);
108 if( rc==0 && validate16(zName,-1) ){
109 db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE hash=%Q",
110 zName);
111 if( db_step(&q)==SQLITE_ROW ){
112 db_column_blob(&q, 1, pContent);
113 if( db_column_int(&q, 0)==1 ){
114 blob_uncompress(pContent, pContent);
115 }
116 rc = 2;
117 }
118 db_finalize(&q);
119 }
120 return rc;
121 }
122
123 /*
124 ** Write unversioned content into the database.
@@ -237,11 +252,14 @@
252 ** edit FILE Bring up FILE in a text editor for modification.
253 **
254 ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk
255 **
256 ** list | ls Show all unversioned files held in the local
257 ** repository. Options:
258 **
259 ** --glob PATTERN Show only files that match
260 ** --like PATTERN Show only files that match
261 **
262 ** revert ?URL? Restore the state of all unversioned files in the
263 ** local repository to match the remote repository
264 ** URL.
265 **
@@ -250,11 +268,14 @@
268 ** -n|--dryrun Show what would have happened
269 **
270 ** remove|rm|delete FILE ...
271 ** Remove unversioned files from the local repository.
272 ** Changes are not pushed to other repositories until
273 ** the next sync. Options:
274 **
275 ** --glob PATTERN Remove files that match
276 ** --like PATTERN Remove files that match
277 **
278 ** sync ?URL? Synchronize the state of all unversioned files with
279 ** the remote repository URL. The most recent version
280 ** of each file is propagated to all repositories and
281 ** all prior versions are permanently forgotten.
@@ -322,11 +343,11 @@
343 int i;
344 verify_all_options();
345 db_begin_transaction();
346 for(i=3; i<g.argc; i++){
347 Blob content;
348 if( unversioned_content(g.argv[i], &content)!=0 ){
349 blob_write_to_file(&content, "-");
350 }
351 blob_reset(&content);
352 }
353 db_end_transaction(0);
@@ -339,16 +360,18 @@
360
361 verify_all_options();
362 if( g.argc!=4) usage("edit UVFILE");
363 zUVFile = g.argv[3];
364 zEditor = fossil_text_editor();
365 if( zEditor==0 ){
366 fossil_fatal("no text editor - set the VISUAL env variable");
367 }
368 zTFile = fossil_temp_filename();
369 if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
370 db_begin_transaction();
371 content_rcvid_init("#!fossil unversioned edit");
372 if( unversioned_content(zUVFile, &content)==0 ){
373 fossil_fatal("no such uv-file: %Q", zUVFile);
374 }
375 if( looks_like_binary(&content) ){
376 fossil_fatal("cannot edit binary content");
377 }
@@ -373,11 +396,11 @@
396 blob_reset(&content);
397 }else if( memcmp(zCmd, "export", nCmd)==0 ){
398 Blob content;
399 verify_all_options();
400 if( g.argc!=5 ) usage("export UVFILE OUTPUT");
401 if( unversioned_content(g.argv[3], &content)==0 ){
402 fossil_fatal("no such uv-file: %Q", g.argv[3]);
403 }
404 blob_write_to_file(&content, g.argv[4]);
405 blob_reset(&content);
406 }else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
@@ -386,26 +409,40 @@
409 fossil_print("%s\n", unversioned_content_hash(debugFlag));
410 }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
411 Stmt q;
412 int allFlag = find_option("all","a",0)!=0;
413 int longFlag = find_option("l",0,0)!=0 || (nCmd>1 && zCmd[1]=='i');
414 char *zPattern = sqlite3_mprintf("true");
415 const char *zGlob;
416 zGlob = find_option("glob",0,1);
417 if( zGlob ){
418 sqlite3_free(zPattern);
419 zPattern = sqlite3_mprintf("(name GLOB %Q)", zGlob);
420 }
421 zGlob = find_option("like",0,1);
422 if( zGlob ){
423 sqlite3_free(zPattern);
424 zPattern = sqlite3_mprintf("(name LIKE %Q)", zGlob);
425 }
426 verify_all_options();
427 if( !longFlag ){
428 if( allFlag ){
429 db_prepare(&q, "SELECT name FROM unversioned WHERE %s ORDER BY name",
430 zPattern/*safe-for-%s*/);
431 }else{
432 db_prepare(&q, "SELECT name FROM unversioned"
433 " WHERE %s AND hash IS NOT NULL"
434 " ORDER BY name", zPattern/*safe-for-%s*/);
435 }
436 while( db_step(&q)==SQLITE_ROW ){
437 fossil_print("%s\n", db_column_text(&q,0));
438 }
439 }else{
440 db_prepare(&q,
441 "SELECT hash, datetime(mtime,'unixepoch'), sz, length(content), name"
442 " FROM unversioned WHERE %s"
443 " ORDER BY name;", zPattern/*safe-for-%s*/
444 );
445 while( db_step(&q)==SQLITE_ROW ){
446 const char *zHash = db_column_text(&q, 0);
447 const char *zNoContent = "";
448 if( zHash==0 ){
@@ -423,20 +460,37 @@
460 zNoContent
461 );
462 }
463 }
464 db_finalize(&q);
465 sqlite3_free(zPattern);
466 }else if( memcmp(zCmd, "revert", nCmd)==0 ){
467 unsigned syncFlags =
468 unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
469 g.argv[1] = "sync";
470 g.argv[2] = "--uv-noop";
471 sync_unversioned(syncFlags);
472 }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0
473 || memcmp(zCmd, "delete", nCmd)==0 ){
474 int i;
475 const char *zGlob;
476 db_begin_transaction();
477 while( (zGlob = find_option("glob",0,1))!=0 ){
478 db_multi_exec(
479 "UPDATE unversioned"
480 " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name GLOB %Q",
481 mtime, zGlob
482 );
483 }
484 while( (zGlob = find_option("like",0,1))!=0 ){
485 db_multi_exec(
486 "UPDATE unversioned"
487 " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name LIKE %Q",
488 mtime, zGlob
489 );
490 }
491 verify_all_options();
492 for(i=3; i<g.argc; i++){
493 db_multi_exec(
494 "UPDATE unversioned"
495 " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name=%Q",
496 mtime, g.argv[i]
@@ -485,10 +539,11 @@
539 int showDel = 0;
540 char zSzName[100];
541
542 login_check_credentials();
543 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
544 etag_check(ETAG_DATA,0);
545 style_header("Unversioned Files");
546 if( !db_table_exists("repository","unversioned") ){
547 @ No unversioned files on this server
548 style_footer();
549 return;
@@ -597,10 +652,11 @@
652 Blob json;
653
654 login_check_credentials();
655 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
656 cgi_set_content_type("text/json");
657 etag_check(ETAG_DATA,0);
658 if( !db_table_exists("repository","unversioned") ){
659 blob_init(&json, "[]", -1);
660 cgi_set_content(&json);
661 return;
662 }
663
+17 -3
--- src/url.c
+++ src/url.c
@@ -360,18 +360,32 @@
360360
/*
361361
** Extract any proxy options from the command-line.
362362
**
363363
** --proxy URL|off
364364
**
365
-** This also happens to be a convenient function to use to look for
366
-** the --nosync option that will temporarily disable the "autosync"
367
-** feature.
365
+** The original purpose of this routine is the above. But this
366
+** also happens to be a convenient place to look for other
367
+** network-related options:
368
+**
369
+** --nosync Temporarily disable "autosync"
370
+**
371
+** --ipv4 Disallow IPv6. Use only IPv4.
372
+**
373
+** --accept-any-cert Disable server SSL cert validation. Accept
374
+** any SSL cert that the server provides.
375
+** WARNING: this option opens you up to
376
+** forged-DNS and man-in-the-middle attacks!
368377
*/
369378
void url_proxy_options(void){
370379
zProxyOpt = find_option("proxy", 0, 1);
371380
if( find_option("nosync",0,0) ) g.fNoSync = 1;
372381
if( find_option("ipv4",0,0) ) g.fIPv4 = 1;
382
+#ifdef FOSSIL_ENABLE_SSL
383
+ if( find_option("accept-any-cert",0,0) ){
384
+ ssl_disable_cert_verification();
385
+ }
386
+#endif /* FOSSIL_ENABLE_SSL */
373387
}
374388
375389
/*
376390
** If the "proxy" setting is defined, then change the URL settings
377391
** (initialized by a prior call to url_parse()) so that the HTTP
378392
--- src/url.c
+++ src/url.c
@@ -360,18 +360,32 @@
360 /*
361 ** Extract any proxy options from the command-line.
362 **
363 ** --proxy URL|off
364 **
365 ** This also happens to be a convenient function to use to look for
366 ** the --nosync option that will temporarily disable the "autosync"
367 ** feature.
 
 
 
 
 
 
 
 
 
368 */
369 void url_proxy_options(void){
370 zProxyOpt = find_option("proxy", 0, 1);
371 if( find_option("nosync",0,0) ) g.fNoSync = 1;
372 if( find_option("ipv4",0,0) ) g.fIPv4 = 1;
 
 
 
 
 
373 }
374
375 /*
376 ** If the "proxy" setting is defined, then change the URL settings
377 ** (initialized by a prior call to url_parse()) so that the HTTP
378
--- src/url.c
+++ src/url.c
@@ -360,18 +360,32 @@
360 /*
361 ** Extract any proxy options from the command-line.
362 **
363 ** --proxy URL|off
364 **
365 ** The original purpose of this routine is the above. But this
366 ** also happens to be a convenient place to look for other
367 ** network-related options:
368 **
369 ** --nosync Temporarily disable "autosync"
370 **
371 ** --ipv4 Disallow IPv6. Use only IPv4.
372 **
373 ** --accept-any-cert Disable server SSL cert validation. Accept
374 ** any SSL cert that the server provides.
375 ** WARNING: this option opens you up to
376 ** forged-DNS and man-in-the-middle attacks!
377 */
378 void url_proxy_options(void){
379 zProxyOpt = find_option("proxy", 0, 1);
380 if( find_option("nosync",0,0) ) g.fNoSync = 1;
381 if( find_option("ipv4",0,0) ) g.fIPv4 = 1;
382 #ifdef FOSSIL_ENABLE_SSL
383 if( find_option("accept-any-cert",0,0) ){
384 ssl_disable_cert_verification();
385 }
386 #endif /* FOSSIL_ENABLE_SSL */
387 }
388
389 /*
390 ** If the "proxy" setting is defined, then change the URL settings
391 ** (initialized by a prior call to url_parse()) so that the HTTP
392
+1 -1
--- src/zip.c
+++ src/zip.c
@@ -592,11 +592,11 @@
592592
}
593593
zip_open();
594594
for(i=3; i<g.argc; i++){
595595
blob_zero(&file);
596596
blob_read_from_file(&file, g.argv[i], eFType);
597
- zip_add_file(&sArchive, g.argv[i], &file, file_perm(0,0));
597
+ zip_add_file(&sArchive, g.argv[i], &file, file_perm(0,eFType));
598598
blob_reset(&file);
599599
}
600600
zip_close(&sArchive);
601601
blob_write_to_file(&zip, g.argv[2]);
602602
}
603603
604604
ADDED test/subdir with spaces/filename with spaces.txt
--- src/zip.c
+++ src/zip.c
@@ -592,11 +592,11 @@
592 }
593 zip_open();
594 for(i=3; i<g.argc; i++){
595 blob_zero(&file);
596 blob_read_from_file(&file, g.argv[i], eFType);
597 zip_add_file(&sArchive, g.argv[i], &file, file_perm(0,0));
598 blob_reset(&file);
599 }
600 zip_close(&sArchive);
601 blob_write_to_file(&zip, g.argv[2]);
602 }
603
604 DDED test/subdir with spaces/filename with spaces.txt
--- src/zip.c
+++ src/zip.c
@@ -592,11 +592,11 @@
592 }
593 zip_open();
594 for(i=3; i<g.argc; i++){
595 blob_zero(&file);
596 blob_read_from_file(&file, g.argv[i], eFType);
597 zip_add_file(&sArchive, g.argv[i], &file, file_perm(0,eFType));
598 blob_reset(&file);
599 }
600 zip_close(&sArchive);
601 blob_write_to_file(&zip, g.argv[2]);
602 }
603
604 DDED test/subdir with spaces/filename with spaces.txt
--- a/test/subdir with spaces/filename with spaces.txt
+++ b/test/subdir with spaces/filename with spaces.txt
@@ -0,0 +1,2 @@
1
+This file has a name that contains spaces. It is used to help verify
2
+that fossil can handle filenames that contain spaces.
--- a/test/subdir with spaces/filename with spaces.txt
+++ b/test/subdir with spaces/filename with spaces.txt
@@ -0,0 +1,2 @@
 
 
--- a/test/subdir with spaces/filename with spaces.txt
+++ b/test/subdir with spaces/filename with spaces.txt
@@ -0,0 +1,2 @@
1 This file has a name that contains spaces. It is used to help verify
2 that fossil can handle filenames that contain spaces.
+1 -1
--- test/tester.tcl
+++ test/tester.tcl
@@ -391,11 +391,11 @@
391391
if {[info exists ::env(FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT)] && \
392392
$::env(FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT) eq "YES_DO_IT"} {
393393
return
394394
}
395395
catch {exec $::fossilexe info} res
396
- if {![regexp {use --repository} $res]} {
396
+ if {[regexp {local-root:} $res]} {
397397
set projectName <unknown>
398398
set localRoot <unknown>
399399
regexp -line -- {^project-name: (.*)$} $res dummy projectName
400400
set projectName [string trim $projectName]
401401
regexp -line -- {^local-root: (.*)$} $res dummy localRoot
402402
403403
ADDED tools/fossil-diff-log
--- test/tester.tcl
+++ test/tester.tcl
@@ -391,11 +391,11 @@
391 if {[info exists ::env(FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT)] && \
392 $::env(FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT) eq "YES_DO_IT"} {
393 return
394 }
395 catch {exec $::fossilexe info} res
396 if {![regexp {use --repository} $res]} {
397 set projectName <unknown>
398 set localRoot <unknown>
399 regexp -line -- {^project-name: (.*)$} $res dummy projectName
400 set projectName [string trim $projectName]
401 regexp -line -- {^local-root: (.*)$} $res dummy localRoot
402
403 DDED tools/fossil-diff-log
--- test/tester.tcl
+++ test/tester.tcl
@@ -391,11 +391,11 @@
391 if {[info exists ::env(FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT)] && \
392 $::env(FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT) eq "YES_DO_IT"} {
393 return
394 }
395 catch {exec $::fossilexe info} res
396 if {[regexp {local-root:} $res]} {
397 set projectName <unknown>
398 set localRoot <unknown>
399 regexp -line -- {^project-name: (.*)$} $res dummy projectName
400 set projectName [string trim $projectName]
401 regexp -line -- {^local-root: (.*)$} $res dummy localRoot
402
403 DDED tools/fossil-diff-log

No diff available

No diff available

No diff available

--- a/tools/fossil-diff-log
+++ b/tools/fossil-diff-log
@@ -0,0 +1,72 @@
1
+#!/usr/bin/env perl
2
+# Fossil emulation of the "git log --patch / -p" feature: emit a stream
3
+# of diffs from one version to the next for each file named on the
4
+# command line.
5
+#
6
+# LIMITATIONS: It does not assume "all files" if you give no args, and
7
+# it cannot take a directory to mean "all files under this parent".
8
+#
9
+# PREREQUISITES: This script needs several CPAN modules to run properly.
10
+# There are multiple methods to install them:
11
+#
12
+# sudo dnf install perl-File-Which perl-IO-Interactive
13
+# sudo apt install libfile-which-perl libio-interactive-perl
14
+# sudo cpanm File::Which IO::Interactive
15
+# ...etc...
16
+
17
+use strict;
18
+use warnings;
19
+
20
+use Carp;
21
+use File::Which;
22
+use IO::Interactive qw(is_interactive);
23
+
24
+die "usage: $0 <files...>\n\n" unless @ARGV;
25
+
26
+my $out;
27
+if (is_interactive()) {
28
+ my $pager = $ENV{PAGER} || which('less') || which('more');
29
+ open $out, '|-', $pager or croak "Cannot pipe to $pager: $!";
30
+}
31
+else {
32
+ $out = *STDOUT;
33
+}
34
+
35
+open my $bcmd, '-|', 'fossil branch current'
36
+ or die "Cannot get branch: $!\n";
37
+my $cbranch = <$bcmd>;
38
+chomp $cbranch;
39
+close $bcmd;
40
+
41
+for my $file (@ARGV) {
42
+ my $lastckid;
43
+ open my $finfo, '-|', "fossil finfo --brief --limit 0 '$file'"
44
+ or die "Failed to get file info: $!\n";
45
+ my @filines = <$finfo>;
46
+ close $finfo;
47
+
48
+ for my $line (@filines) {
49
+ my ($currckid, $date, $user, $branch, @cwords) = split ' ', $line;
50
+ next unless $branch eq $cbranch;
51
+ if (defined $lastckid and defined $branch) {
52
+ my $comment = join ' ', @cwords;
53
+ open my $diff, '-|', 'fossil', 'diff', $file,
54
+ '--from', $currckid,
55
+ '--to', $lastckid,
56
+ or die "Failed to diff $currckid -> $lastckid: $!\n";
57
+ my @dl = <$diff>;
58
+ close $diff;
59
+ my $patch = join '', @dl;
60
+
61
+ print $out <<"OUT"
62
+Checkin ID $currckid to $branch by $user on $date
63
+Comment: $comment
64
+
65
+$patch
66
+
67
+OUT
68
+ }
69
+
70
+ $lastckid = $currckid;
71
+ }
72
+}
--- a/tools/fossil-diff-log
+++ b/tools/fossil-diff-log
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/tools/fossil-diff-log
+++ b/tools/fossil-diff-log
@@ -0,0 +1,72 @@
1 #!/usr/bin/env perl
2 # Fossil emulation of the "git log --patch / -p" feature: emit a stream
3 # of diffs from one version to the next for each file named on the
4 # command line.
5 #
6 # LIMITATIONS: It does not assume "all files" if you give no args, and
7 # it cannot take a directory to mean "all files under this parent".
8 #
9 # PREREQUISITES: This script needs several CPAN modules to run properly.
10 # There are multiple methods to install them:
11 #
12 # sudo dnf install perl-File-Which perl-IO-Interactive
13 # sudo apt install libfile-which-perl libio-interactive-perl
14 # sudo cpanm File::Which IO::Interactive
15 # ...etc...
16
17 use strict;
18 use warnings;
19
20 use Carp;
21 use File::Which;
22 use IO::Interactive qw(is_interactive);
23
24 die "usage: $0 <files...>\n\n" unless @ARGV;
25
26 my $out;
27 if (is_interactive()) {
28 my $pager = $ENV{PAGER} || which('less') || which('more');
29 open $out, '|-', $pager or croak "Cannot pipe to $pager: $!";
30 }
31 else {
32 $out = *STDOUT;
33 }
34
35 open my $bcmd, '-|', 'fossil branch current'
36 or die "Cannot get branch: $!\n";
37 my $cbranch = <$bcmd>;
38 chomp $cbranch;
39 close $bcmd;
40
41 for my $file (@ARGV) {
42 my $lastckid;
43 open my $finfo, '-|', "fossil finfo --brief --limit 0 '$file'"
44 or die "Failed to get file info: $!\n";
45 my @filines = <$finfo>;
46 close $finfo;
47
48 for my $line (@filines) {
49 my ($currckid, $date, $user, $branch, @cwords) = split ' ', $line;
50 next unless $branch eq $cbranch;
51 if (defined $lastckid and defined $branch) {
52 my $comment = join ' ', @cwords;
53 open my $diff, '-|', 'fossil', 'diff', $file,
54 '--from', $currckid,
55 '--to', $lastckid,
56 or die "Failed to diff $currckid -> $lastckid: $!\n";
57 my @dl = <$diff>;
58 close $diff;
59 my $patch = join '', @dl;
60
61 print $out <<"OUT"
62 Checkin ID $currckid to $branch by $user on $date
63 Comment: $comment
64
65 $patch
66
67 OUT
68 }
69
70 $lastckid = $currckid;
71 }
72 }

No diff available

No diff available

+10 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
2828
2929
SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_GET_TABLE -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
3030
3131
SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_GET_TABLE -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
33
-SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$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)\capabilities$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)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\webmail$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)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$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)\capabilities$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)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\terminal$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)\webmail$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
3636
3737
3838
RC=$(DMDIR)\bin\rcc
3939
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
4040
@@ -49,11 +49,11 @@
4949
5050
$(OBJDIR)\fossil.res: $B\win\fossil.rc
5151
$(RC) $(RCFLAGS) -o$@ $**
5252
5353
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54
- +echo add alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum fshell fusefs fuzz 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum fshell fusefs fuzz 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -830,10 +830,16 @@
830830
$(OBJDIR)\tar$O : tar_.c tar.h
831831
$(TCC) -o$@ -c tar_.c
832832
833833
tar_.c : $(SRCDIR)\tar.c
834834
+translate$E $** > $@
835
+
836
+$(OBJDIR)\terminal$O : terminal_.c terminal.h
837
+ $(TCC) -o$@ -c terminal_.c
838
+
839
+terminal_.c : $(SRCDIR)\terminal.c
840
+ +translate$E $** > $@
835841
836842
$(OBJDIR)\th_main$O : th_main_.c th_main.h
837843
$(TCC) -o$@ -c th_main_.c
838844
839845
th_main_.c : $(SRCDIR)\th_main.c
@@ -970,7 +976,7 @@
970976
971977
zip_.c : $(SRCDIR)\zip.c
972978
+translate$E $** > $@
973979
974980
headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
975
- +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.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 etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.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 repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.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 smtp_.c:smtp.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 webmail_.c:webmail.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
981
+ +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.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 etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.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 repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.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 smtp_.c:smtp.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 terminal_.c:terminal.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 webmail_.c:webmail.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
976982
@copy /Y nul: headers
977983
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_GET_TABLE -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_GET_TABLE -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$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)\capabilities$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)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\webmail$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 alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum fshell fusefs fuzz 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail 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 >> $@
@@ -830,10 +830,16 @@
830 $(OBJDIR)\tar$O : tar_.c tar.h
831 $(TCC) -o$@ -c tar_.c
832
833 tar_.c : $(SRCDIR)\tar.c
834 +translate$E $** > $@
 
 
 
 
 
 
835
836 $(OBJDIR)\th_main$O : th_main_.c th_main.h
837 $(TCC) -o$@ -c th_main_.c
838
839 th_main_.c : $(SRCDIR)\th_main.c
@@ -970,7 +976,7 @@
970
971 zip_.c : $(SRCDIR)\zip.c
972 +translate$E $** > $@
973
974 headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
975 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.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 etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.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 repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.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 smtp_.c:smtp.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 webmail_.c:webmail.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
976 @copy /Y nul: headers
977
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_GET_TABLE -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_GET_TABLE -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$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)\capabilities$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)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\terminal$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)\webmail$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 alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum fshell fusefs fuzz 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail 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 >> $@
@@ -830,10 +830,16 @@
830 $(OBJDIR)\tar$O : tar_.c tar.h
831 $(TCC) -o$@ -c tar_.c
832
833 tar_.c : $(SRCDIR)\tar.c
834 +translate$E $** > $@
835
836 $(OBJDIR)\terminal$O : terminal_.c terminal.h
837 $(TCC) -o$@ -c terminal_.c
838
839 terminal_.c : $(SRCDIR)\terminal.c
840 +translate$E $** > $@
841
842 $(OBJDIR)\th_main$O : th_main_.c th_main.h
843 $(TCC) -o$@ -c th_main_.c
844
845 th_main_.c : $(SRCDIR)\th_main.c
@@ -970,7 +976,7 @@
976
977 zip_.c : $(SRCDIR)\zip.c
978 +translate$E $** > $@
979
980 headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
981 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.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 etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.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 repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.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 smtp_.c:smtp.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 terminal_.c:terminal.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 webmail_.c:webmail.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
982 @copy /Y nul: headers
983
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -553,10 +553,11 @@
553553
$(SRCDIR)/statrep.c \
554554
$(SRCDIR)/style.c \
555555
$(SRCDIR)/sync.c \
556556
$(SRCDIR)/tag.c \
557557
$(SRCDIR)/tar.c \
558
+ $(SRCDIR)/terminal.c \
558559
$(SRCDIR)/th_main.c \
559560
$(SRCDIR)/timeline.c \
560561
$(SRCDIR)/tkt.c \
561562
$(SRCDIR)/tktsetup.c \
562563
$(SRCDIR)/undo.c \
@@ -786,10 +787,11 @@
786787
$(OBJDIR)/statrep_.c \
787788
$(OBJDIR)/style_.c \
788789
$(OBJDIR)/sync_.c \
789790
$(OBJDIR)/tag_.c \
790791
$(OBJDIR)/tar_.c \
792
+ $(OBJDIR)/terminal_.c \
791793
$(OBJDIR)/th_main_.c \
792794
$(OBJDIR)/timeline_.c \
793795
$(OBJDIR)/tkt_.c \
794796
$(OBJDIR)/tktsetup_.c \
795797
$(OBJDIR)/undo_.c \
@@ -928,10 +930,11 @@
928930
$(OBJDIR)/statrep.o \
929931
$(OBJDIR)/style.o \
930932
$(OBJDIR)/sync.o \
931933
$(OBJDIR)/tag.o \
932934
$(OBJDIR)/tar.o \
935
+ $(OBJDIR)/terminal.o \
933936
$(OBJDIR)/th_main.o \
934937
$(OBJDIR)/timeline.o \
935938
$(OBJDIR)/tkt.o \
936939
$(OBJDIR)/tktsetup.o \
937940
$(OBJDIR)/undo.o \
@@ -1290,10 +1293,11 @@
12901293
$(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
12911294
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
12921295
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
12931296
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
12941297
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1298
+ $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
12951299
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
12961300
$(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
12971301
$(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
12981302
$(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
12991303
$(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -2257,10 +2261,18 @@
22572261
22582262
$(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
22592263
$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
22602264
22612265
$(OBJDIR)/tar.h: $(OBJDIR)/headers
2266
+
2267
+$(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(TRANSLATE)
2268
+ $(TRANSLATE) $(SRCDIR)/terminal.c >$@
2269
+
2270
+$(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
2271
+ $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
2272
+
2273
+$(OBJDIR)/terminal.h: $(OBJDIR)/headers
22622274
22632275
$(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(TRANSLATE)
22642276
$(TRANSLATE) $(SRCDIR)/th_main.c >$@
22652277
22662278
$(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
22672279
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -553,10 +553,11 @@
553 $(SRCDIR)/statrep.c \
554 $(SRCDIR)/style.c \
555 $(SRCDIR)/sync.c \
556 $(SRCDIR)/tag.c \
557 $(SRCDIR)/tar.c \
 
558 $(SRCDIR)/th_main.c \
559 $(SRCDIR)/timeline.c \
560 $(SRCDIR)/tkt.c \
561 $(SRCDIR)/tktsetup.c \
562 $(SRCDIR)/undo.c \
@@ -786,10 +787,11 @@
786 $(OBJDIR)/statrep_.c \
787 $(OBJDIR)/style_.c \
788 $(OBJDIR)/sync_.c \
789 $(OBJDIR)/tag_.c \
790 $(OBJDIR)/tar_.c \
 
791 $(OBJDIR)/th_main_.c \
792 $(OBJDIR)/timeline_.c \
793 $(OBJDIR)/tkt_.c \
794 $(OBJDIR)/tktsetup_.c \
795 $(OBJDIR)/undo_.c \
@@ -928,10 +930,11 @@
928 $(OBJDIR)/statrep.o \
929 $(OBJDIR)/style.o \
930 $(OBJDIR)/sync.o \
931 $(OBJDIR)/tag.o \
932 $(OBJDIR)/tar.o \
 
933 $(OBJDIR)/th_main.o \
934 $(OBJDIR)/timeline.o \
935 $(OBJDIR)/tkt.o \
936 $(OBJDIR)/tktsetup.o \
937 $(OBJDIR)/undo.o \
@@ -1290,10 +1293,11 @@
1290 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
1291 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1292 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1293 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1294 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
 
1295 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
1296 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
1297 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
1298 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
1299 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -2257,10 +2261,18 @@
2257
2258 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
2259 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
2260
2261 $(OBJDIR)/tar.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
2262
2263 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(TRANSLATE)
2264 $(TRANSLATE) $(SRCDIR)/th_main.c >$@
2265
2266 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
2267
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -553,10 +553,11 @@
553 $(SRCDIR)/statrep.c \
554 $(SRCDIR)/style.c \
555 $(SRCDIR)/sync.c \
556 $(SRCDIR)/tag.c \
557 $(SRCDIR)/tar.c \
558 $(SRCDIR)/terminal.c \
559 $(SRCDIR)/th_main.c \
560 $(SRCDIR)/timeline.c \
561 $(SRCDIR)/tkt.c \
562 $(SRCDIR)/tktsetup.c \
563 $(SRCDIR)/undo.c \
@@ -786,10 +787,11 @@
787 $(OBJDIR)/statrep_.c \
788 $(OBJDIR)/style_.c \
789 $(OBJDIR)/sync_.c \
790 $(OBJDIR)/tag_.c \
791 $(OBJDIR)/tar_.c \
792 $(OBJDIR)/terminal_.c \
793 $(OBJDIR)/th_main_.c \
794 $(OBJDIR)/timeline_.c \
795 $(OBJDIR)/tkt_.c \
796 $(OBJDIR)/tktsetup_.c \
797 $(OBJDIR)/undo_.c \
@@ -928,10 +930,11 @@
930 $(OBJDIR)/statrep.o \
931 $(OBJDIR)/style.o \
932 $(OBJDIR)/sync.o \
933 $(OBJDIR)/tag.o \
934 $(OBJDIR)/tar.o \
935 $(OBJDIR)/terminal.o \
936 $(OBJDIR)/th_main.o \
937 $(OBJDIR)/timeline.o \
938 $(OBJDIR)/tkt.o \
939 $(OBJDIR)/tktsetup.o \
940 $(OBJDIR)/undo.o \
@@ -1290,10 +1293,11 @@
1293 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
1294 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1295 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1296 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1297 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1298 $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
1299 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
1300 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
1301 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
1302 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
1303 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -2257,10 +2261,18 @@
2261
2262 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
2263 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
2264
2265 $(OBJDIR)/tar.h: $(OBJDIR)/headers
2266
2267 $(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(TRANSLATE)
2268 $(TRANSLATE) $(SRCDIR)/terminal.c >$@
2269
2270 $(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
2271 $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
2272
2273 $(OBJDIR)/terminal.h: $(OBJDIR)/headers
2274
2275 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(TRANSLATE)
2276 $(TRANSLATE) $(SRCDIR)/th_main.c >$@
2277
2278 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
2279
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -553,10 +553,11 @@
553553
$(SRCDIR)/statrep.c \
554554
$(SRCDIR)/style.c \
555555
$(SRCDIR)/sync.c \
556556
$(SRCDIR)/tag.c \
557557
$(SRCDIR)/tar.c \
558
+ $(SRCDIR)/terminal.c \
558559
$(SRCDIR)/th_main.c \
559560
$(SRCDIR)/timeline.c \
560561
$(SRCDIR)/tkt.c \
561562
$(SRCDIR)/tktsetup.c \
562563
$(SRCDIR)/undo.c \
@@ -786,10 +787,11 @@
786787
$(OBJDIR)/statrep_.c \
787788
$(OBJDIR)/style_.c \
788789
$(OBJDIR)/sync_.c \
789790
$(OBJDIR)/tag_.c \
790791
$(OBJDIR)/tar_.c \
792
+ $(OBJDIR)/terminal_.c \
791793
$(OBJDIR)/th_main_.c \
792794
$(OBJDIR)/timeline_.c \
793795
$(OBJDIR)/tkt_.c \
794796
$(OBJDIR)/tktsetup_.c \
795797
$(OBJDIR)/undo_.c \
@@ -928,10 +930,11 @@
928930
$(OBJDIR)/statrep.o \
929931
$(OBJDIR)/style.o \
930932
$(OBJDIR)/sync.o \
931933
$(OBJDIR)/tag.o \
932934
$(OBJDIR)/tar.o \
935
+ $(OBJDIR)/terminal.o \
933936
$(OBJDIR)/th_main.o \
934937
$(OBJDIR)/timeline.o \
935938
$(OBJDIR)/tkt.o \
936939
$(OBJDIR)/tktsetup.o \
937940
$(OBJDIR)/undo.o \
@@ -1290,10 +1293,11 @@
12901293
$(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
12911294
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
12921295
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
12931296
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
12941297
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1298
+ $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
12951299
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
12961300
$(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
12971301
$(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
12981302
$(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
12991303
$(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -2257,10 +2261,18 @@
22572261
22582262
$(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
22592263
$(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
22602264
22612265
$(OBJDIR)/tar.h: $(OBJDIR)/headers
2266
+
2267
+$(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(TRANSLATE)
2268
+ $(TRANSLATE) $(SRCDIR)/terminal.c >$@
2269
+
2270
+$(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
2271
+ $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
2272
+
2273
+$(OBJDIR)/terminal.h: $(OBJDIR)/headers
22622274
22632275
$(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(TRANSLATE)
22642276
$(TRANSLATE) $(SRCDIR)/th_main.c >$@
22652277
22662278
$(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
22672279
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -553,10 +553,11 @@
553 $(SRCDIR)/statrep.c \
554 $(SRCDIR)/style.c \
555 $(SRCDIR)/sync.c \
556 $(SRCDIR)/tag.c \
557 $(SRCDIR)/tar.c \
 
558 $(SRCDIR)/th_main.c \
559 $(SRCDIR)/timeline.c \
560 $(SRCDIR)/tkt.c \
561 $(SRCDIR)/tktsetup.c \
562 $(SRCDIR)/undo.c \
@@ -786,10 +787,11 @@
786 $(OBJDIR)/statrep_.c \
787 $(OBJDIR)/style_.c \
788 $(OBJDIR)/sync_.c \
789 $(OBJDIR)/tag_.c \
790 $(OBJDIR)/tar_.c \
 
791 $(OBJDIR)/th_main_.c \
792 $(OBJDIR)/timeline_.c \
793 $(OBJDIR)/tkt_.c \
794 $(OBJDIR)/tktsetup_.c \
795 $(OBJDIR)/undo_.c \
@@ -928,10 +930,11 @@
928 $(OBJDIR)/statrep.o \
929 $(OBJDIR)/style.o \
930 $(OBJDIR)/sync.o \
931 $(OBJDIR)/tag.o \
932 $(OBJDIR)/tar.o \
 
933 $(OBJDIR)/th_main.o \
934 $(OBJDIR)/timeline.o \
935 $(OBJDIR)/tkt.o \
936 $(OBJDIR)/tktsetup.o \
937 $(OBJDIR)/undo.o \
@@ -1290,10 +1293,11 @@
1290 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
1291 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1292 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1293 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1294 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
 
1295 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
1296 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
1297 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
1298 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
1299 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -2257,10 +2261,18 @@
2257
2258 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
2259 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
2260
2261 $(OBJDIR)/tar.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
2262
2263 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(TRANSLATE)
2264 $(TRANSLATE) $(SRCDIR)/th_main.c >$@
2265
2266 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
2267
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -553,10 +553,11 @@
553 $(SRCDIR)/statrep.c \
554 $(SRCDIR)/style.c \
555 $(SRCDIR)/sync.c \
556 $(SRCDIR)/tag.c \
557 $(SRCDIR)/tar.c \
558 $(SRCDIR)/terminal.c \
559 $(SRCDIR)/th_main.c \
560 $(SRCDIR)/timeline.c \
561 $(SRCDIR)/tkt.c \
562 $(SRCDIR)/tktsetup.c \
563 $(SRCDIR)/undo.c \
@@ -786,10 +787,11 @@
787 $(OBJDIR)/statrep_.c \
788 $(OBJDIR)/style_.c \
789 $(OBJDIR)/sync_.c \
790 $(OBJDIR)/tag_.c \
791 $(OBJDIR)/tar_.c \
792 $(OBJDIR)/terminal_.c \
793 $(OBJDIR)/th_main_.c \
794 $(OBJDIR)/timeline_.c \
795 $(OBJDIR)/tkt_.c \
796 $(OBJDIR)/tktsetup_.c \
797 $(OBJDIR)/undo_.c \
@@ -928,10 +930,11 @@
930 $(OBJDIR)/statrep.o \
931 $(OBJDIR)/style.o \
932 $(OBJDIR)/sync.o \
933 $(OBJDIR)/tag.o \
934 $(OBJDIR)/tar.o \
935 $(OBJDIR)/terminal.o \
936 $(OBJDIR)/th_main.o \
937 $(OBJDIR)/timeline.o \
938 $(OBJDIR)/tkt.o \
939 $(OBJDIR)/tktsetup.o \
940 $(OBJDIR)/undo.o \
@@ -1290,10 +1293,11 @@
1293 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
1294 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1295 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1296 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1297 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1298 $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \
1299 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
1300 $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \
1301 $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \
1302 $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \
1303 $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \
@@ -2257,10 +2261,18 @@
2261
2262 $(OBJDIR)/tar.o: $(OBJDIR)/tar_.c $(OBJDIR)/tar.h $(SRCDIR)/config.h
2263 $(XTCC) -o $(OBJDIR)/tar.o -c $(OBJDIR)/tar_.c
2264
2265 $(OBJDIR)/tar.h: $(OBJDIR)/headers
2266
2267 $(OBJDIR)/terminal_.c: $(SRCDIR)/terminal.c $(TRANSLATE)
2268 $(TRANSLATE) $(SRCDIR)/terminal.c >$@
2269
2270 $(OBJDIR)/terminal.o: $(OBJDIR)/terminal_.c $(OBJDIR)/terminal.h $(SRCDIR)/config.h
2271 $(XTCC) -o $(OBJDIR)/terminal.o -c $(OBJDIR)/terminal_.c
2272
2273 $(OBJDIR)/terminal.h: $(OBJDIR)/headers
2274
2275 $(OBJDIR)/th_main_.c: $(SRCDIR)/th_main.c $(TRANSLATE)
2276 $(TRANSLATE) $(SRCDIR)/th_main.c >$@
2277
2278 $(OBJDIR)/th_main.o: $(OBJDIR)/th_main_.c $(OBJDIR)/th_main.h $(SRCDIR)/config.h
2279
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -461,10 +461,11 @@
461461
statrep_.c \
462462
style_.c \
463463
sync_.c \
464464
tag_.c \
465465
tar_.c \
466
+ terminal_.c \
466467
th_main_.c \
467468
timeline_.c \
468469
tkt_.c \
469470
tktsetup_.c \
470471
undo_.c \
@@ -695,10 +696,11 @@
695696
$(OX)\statrep$O \
696697
$(OX)\style$O \
697698
$(OX)\sync$O \
698699
$(OX)\tag$O \
699700
$(OX)\tar$O \
701
+ $(OX)\terminal$O \
700702
$(OX)\th$O \
701703
$(OX)\th_lang$O \
702704
$(OX)\th_main$O \
703705
$(OX)\th_tcl$O \
704706
$(OX)\timeline$O \
@@ -899,10 +901,11 @@
899901
echo $(OX)\statrep.obj >> $@
900902
echo $(OX)\style.obj >> $@
901903
echo $(OX)\sync.obj >> $@
902904
echo $(OX)\tag.obj >> $@
903905
echo $(OX)\tar.obj >> $@
906
+ echo $(OX)\terminal.obj >> $@
904907
echo $(OX)\th.obj >> $@
905908
echo $(OX)\th_lang.obj >> $@
906909
echo $(OX)\th_main.obj >> $@
907910
echo $(OX)\th_tcl.obj >> $@
908911
echo $(OX)\timeline.obj >> $@
@@ -1744,10 +1747,16 @@
17441747
$(OX)\tar$O : tar_.c tar.h
17451748
$(TCC) /Fo$@ -c tar_.c
17461749
17471750
tar_.c : $(SRCDIR)\tar.c
17481751
translate$E $** > $@
1752
+
1753
+$(OX)\terminal$O : terminal_.c terminal.h
1754
+ $(TCC) /Fo$@ -c terminal_.c
1755
+
1756
+terminal_.c : $(SRCDIR)\terminal.c
1757
+ translate$E $** > $@
17491758
17501759
$(OX)\th_main$O : th_main_.c th_main.h
17511760
$(TCC) /Fo$@ -c th_main_.c
17521761
17531762
th_main_.c : $(SRCDIR)\th_main.c
@@ -2004,10 +2013,11 @@
20042013
statrep_.c:statrep.h \
20052014
style_.c:style.h \
20062015
sync_.c:sync.h \
20072016
tag_.c:tag.h \
20082017
tar_.c:tar.h \
2018
+ terminal_.c:terminal.h \
20092019
th_main_.c:th_main.h \
20102020
timeline_.c:timeline.h \
20112021
tkt_.c:tkt.h \
20122022
tktsetup_.c:tktsetup.h \
20132023
undo_.c:undo.h \
20142024
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -461,10 +461,11 @@
461 statrep_.c \
462 style_.c \
463 sync_.c \
464 tag_.c \
465 tar_.c \
 
466 th_main_.c \
467 timeline_.c \
468 tkt_.c \
469 tktsetup_.c \
470 undo_.c \
@@ -695,10 +696,11 @@
695 $(OX)\statrep$O \
696 $(OX)\style$O \
697 $(OX)\sync$O \
698 $(OX)\tag$O \
699 $(OX)\tar$O \
 
700 $(OX)\th$O \
701 $(OX)\th_lang$O \
702 $(OX)\th_main$O \
703 $(OX)\th_tcl$O \
704 $(OX)\timeline$O \
@@ -899,10 +901,11 @@
899 echo $(OX)\statrep.obj >> $@
900 echo $(OX)\style.obj >> $@
901 echo $(OX)\sync.obj >> $@
902 echo $(OX)\tag.obj >> $@
903 echo $(OX)\tar.obj >> $@
 
904 echo $(OX)\th.obj >> $@
905 echo $(OX)\th_lang.obj >> $@
906 echo $(OX)\th_main.obj >> $@
907 echo $(OX)\th_tcl.obj >> $@
908 echo $(OX)\timeline.obj >> $@
@@ -1744,10 +1747,16 @@
1744 $(OX)\tar$O : tar_.c tar.h
1745 $(TCC) /Fo$@ -c tar_.c
1746
1747 tar_.c : $(SRCDIR)\tar.c
1748 translate$E $** > $@
 
 
 
 
 
 
1749
1750 $(OX)\th_main$O : th_main_.c th_main.h
1751 $(TCC) /Fo$@ -c th_main_.c
1752
1753 th_main_.c : $(SRCDIR)\th_main.c
@@ -2004,10 +2013,11 @@
2004 statrep_.c:statrep.h \
2005 style_.c:style.h \
2006 sync_.c:sync.h \
2007 tag_.c:tag.h \
2008 tar_.c:tar.h \
 
2009 th_main_.c:th_main.h \
2010 timeline_.c:timeline.h \
2011 tkt_.c:tkt.h \
2012 tktsetup_.c:tktsetup.h \
2013 undo_.c:undo.h \
2014
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -461,10 +461,11 @@
461 statrep_.c \
462 style_.c \
463 sync_.c \
464 tag_.c \
465 tar_.c \
466 terminal_.c \
467 th_main_.c \
468 timeline_.c \
469 tkt_.c \
470 tktsetup_.c \
471 undo_.c \
@@ -695,10 +696,11 @@
696 $(OX)\statrep$O \
697 $(OX)\style$O \
698 $(OX)\sync$O \
699 $(OX)\tag$O \
700 $(OX)\tar$O \
701 $(OX)\terminal$O \
702 $(OX)\th$O \
703 $(OX)\th_lang$O \
704 $(OX)\th_main$O \
705 $(OX)\th_tcl$O \
706 $(OX)\timeline$O \
@@ -899,10 +901,11 @@
901 echo $(OX)\statrep.obj >> $@
902 echo $(OX)\style.obj >> $@
903 echo $(OX)\sync.obj >> $@
904 echo $(OX)\tag.obj >> $@
905 echo $(OX)\tar.obj >> $@
906 echo $(OX)\terminal.obj >> $@
907 echo $(OX)\th.obj >> $@
908 echo $(OX)\th_lang.obj >> $@
909 echo $(OX)\th_main.obj >> $@
910 echo $(OX)\th_tcl.obj >> $@
911 echo $(OX)\timeline.obj >> $@
@@ -1744,10 +1747,16 @@
1747 $(OX)\tar$O : tar_.c tar.h
1748 $(TCC) /Fo$@ -c tar_.c
1749
1750 tar_.c : $(SRCDIR)\tar.c
1751 translate$E $** > $@
1752
1753 $(OX)\terminal$O : terminal_.c terminal.h
1754 $(TCC) /Fo$@ -c terminal_.c
1755
1756 terminal_.c : $(SRCDIR)\terminal.c
1757 translate$E $** > $@
1758
1759 $(OX)\th_main$O : th_main_.c th_main.h
1760 $(TCC) /Fo$@ -c th_main_.c
1761
1762 th_main_.c : $(SRCDIR)\th_main.c
@@ -2004,10 +2013,11 @@
2013 statrep_.c:statrep.h \
2014 style_.c:style.h \
2015 sync_.c:sync.h \
2016 tag_.c:tag.h \
2017 tar_.c:tar.h \
2018 terminal_.c:terminal.h \
2019 th_main_.c:th_main.h \
2020 timeline_.c:timeline.h \
2021 tkt_.c:tkt.h \
2022 tktsetup_.c:tktsetup.h \
2023 undo_.c:undo.h \
2024
+2 -2
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -14,12 +14,12 @@
1414
script]. CGI is the technique that the three
1515
[./selfhost.wiki|self-hosting Fossil repositories] all use.
1616
1717
Setting up a Fossil server using CGI is mostly about writing a short
1818
script (usually just 2 lines line) in the cgi-bin folder of an ordinary
19
-web-browser. But there are a lot of extra options that can be added
20
-to this script, to customize the configuration. This article descripts
19
+web-server. But there are a lot of extra options that can be added
20
+to this script, to customize the configuration. This article describes
2121
those options.
2222
2323
<h1>CGI Script Options</h1>
2424
2525
The CGI script used to launch a Fossil server will usually look something
2626
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -14,12 +14,12 @@
14 script]. CGI is the technique that the three
15 [./selfhost.wiki|self-hosting Fossil repositories] all use.
16
17 Setting up a Fossil server using CGI is mostly about writing a short
18 script (usually just 2 lines line) in the cgi-bin folder of an ordinary
19 web-browser. But there are a lot of extra options that can be added
20 to this script, to customize the configuration. This article descripts
21 those options.
22
23 <h1>CGI Script Options</h1>
24
25 The CGI script used to launch a Fossil server will usually look something
26
--- www/cgi.wiki
+++ www/cgi.wiki
@@ -14,12 +14,12 @@
14 script]. CGI is the technique that the three
15 [./selfhost.wiki|self-hosting Fossil repositories] all use.
16
17 Setting up a Fossil server using CGI is mostly about writing a short
18 script (usually just 2 lines line) in the cgi-bin folder of an ordinary
19 web-server. But there are a lot of extra options that can be added
20 to this script, to customize the configuration. This article describes
21 those options.
22
23 <h1>CGI Script Options</h1>
24
25 The CGI script used to launch a Fossil server will usually look something
26
--- www/changes.wiki
+++ www/changes.wiki
@@ -55,10 +55,12 @@
5555
* Security: Fossil now puts the Content-Security-Policy in the
5656
HTTP reply header, in addition to also leaving it in the
5757
HTML &lt;head&gt; section, so that it is always available, even
5858
if a custom skin overrides the HTML &lt;head&gt; and omits
5959
the CSP in the process.
60
+ * Output of the [/help?cmd=diff|fossil diff -y] command automatically
61
+ adjusts according to the terminal width.
6062
* The Content-Security-Policy is now set using the
6163
[/help?cmd=default-csp|default-csp setting].
6264
* Merge conflicts caused via the [/help?cmd=merge|merge] and
6365
[/help?cmd=update|update] commands no longer leave temporary
6466
files behind unless the new <tt>--keep-merge-files</tt> flag
@@ -65,13 +67,18 @@
6567
is used.
6668
* The [/help?cmd=/artifact_stats|/artifact_stats page] is now accessible
6769
to all users if the new "artifact_stats_enable" setting is turned
6870
on. There is a new checkbox under the /Admin/Access menu to turn
6971
that capability on and off.
72
+ * Add the [/help?cmd=tls-config|fossil tls-config] command for viewing
73
+ the TLS configuration and the list of SSL Cert exceptions.
7074
* Captchas all include a button to read the captcha using an audio
7175
file, so that they can be completed by the visually impaired.
7276
* Stop using the IP address as part of the login cookie.
77
+ * Bug fix: fix the SSL cert validation logic so that if an exception
78
+ is allowed for particular site, the exception expires as soon as the
79
+ cert changes values.
7380
* Bug fix: the FTS search into for forum posts is now kept up-to-date
7481
correctly.
7582
* Bug fix: the "fossil git export" command is now working on Windows
7683
* Bug fix: display Technote items on the timeline correctly
7784
* Bug fix: fix the capability summary matrix of the Security Audit
7885
--- www/changes.wiki
+++ www/changes.wiki
@@ -55,10 +55,12 @@
55 * Security: Fossil now puts the Content-Security-Policy in the
56 HTTP reply header, in addition to also leaving it in the
57 HTML &lt;head&gt; section, so that it is always available, even
58 if a custom skin overrides the HTML &lt;head&gt; and omits
59 the CSP in the process.
 
 
60 * The Content-Security-Policy is now set using the
61 [/help?cmd=default-csp|default-csp setting].
62 * Merge conflicts caused via the [/help?cmd=merge|merge] and
63 [/help?cmd=update|update] commands no longer leave temporary
64 files behind unless the new <tt>--keep-merge-files</tt> flag
@@ -65,13 +67,18 @@
65 is used.
66 * The [/help?cmd=/artifact_stats|/artifact_stats page] is now accessible
67 to all users if the new "artifact_stats_enable" setting is turned
68 on. There is a new checkbox under the /Admin/Access menu to turn
69 that capability on and off.
 
 
70 * Captchas all include a button to read the captcha using an audio
71 file, so that they can be completed by the visually impaired.
72 * Stop using the IP address as part of the login cookie.
 
 
 
73 * Bug fix: the FTS search into for forum posts is now kept up-to-date
74 correctly.
75 * Bug fix: the "fossil git export" command is now working on Windows
76 * Bug fix: display Technote items on the timeline correctly
77 * Bug fix: fix the capability summary matrix of the Security Audit
78
--- www/changes.wiki
+++ www/changes.wiki
@@ -55,10 +55,12 @@
55 * Security: Fossil now puts the Content-Security-Policy in the
56 HTTP reply header, in addition to also leaving it in the
57 HTML &lt;head&gt; section, so that it is always available, even
58 if a custom skin overrides the HTML &lt;head&gt; and omits
59 the CSP in the process.
60 * Output of the [/help?cmd=diff|fossil diff -y] command automatically
61 adjusts according to the terminal width.
62 * The Content-Security-Policy is now set using the
63 [/help?cmd=default-csp|default-csp setting].
64 * Merge conflicts caused via the [/help?cmd=merge|merge] and
65 [/help?cmd=update|update] commands no longer leave temporary
66 files behind unless the new <tt>--keep-merge-files</tt> flag
@@ -65,13 +67,18 @@
67 is used.
68 * The [/help?cmd=/artifact_stats|/artifact_stats page] is now accessible
69 to all users if the new "artifact_stats_enable" setting is turned
70 on. There is a new checkbox under the /Admin/Access menu to turn
71 that capability on and off.
72 * Add the [/help?cmd=tls-config|fossil tls-config] command for viewing
73 the TLS configuration and the list of SSL Cert exceptions.
74 * Captchas all include a button to read the captcha using an audio
75 file, so that they can be completed by the visually impaired.
76 * Stop using the IP address as part of the login cookie.
77 * Bug fix: fix the SSL cert validation logic so that if an exception
78 is allowed for particular site, the exception expires as soon as the
79 cert changes values.
80 * Bug fix: the FTS search into for forum posts is now kept up-to-date
81 correctly.
82 * Bug fix: the "fossil git export" command is now working on Windows
83 * Bug fix: display Technote items on the timeline correctly
84 * Bug fix: fix the capability summary matrix of the Security Audit
85
+1 -1
--- www/index.wiki
+++ www/index.wiki
@@ -9,11 +9,11 @@
99
<li> [./build.wiki | Install]
1010
<li> [https://fossil-scm.org/forum | Support/Forum ]
1111
<li> [./hints.wiki | Tips &amp; Hints]
1212
<li> [./changes.wiki | Change Log]
1313
<li> [../COPYRIGHT-BSD2.txt | License]
14
-<li> [./userlinks.wiki | User inks]
14
+<li> [./userlinks.wiki | User Links]
1515
<li> [./hacker-howto.wiki | Hacker How-To]
1616
<li> [./fossil-v-git.wiki | Fossil vs. Git]
1717
<li> [./permutedindex.html | Documentation Index]
1818
</ul>
1919
<img src="fossil3.gif" align="center">
2020
--- www/index.wiki
+++ www/index.wiki
@@ -9,11 +9,11 @@
9 <li> [./build.wiki | Install]
10 <li> [https://fossil-scm.org/forum | Support/Forum ]
11 <li> [./hints.wiki | Tips &amp; Hints]
12 <li> [./changes.wiki | Change Log]
13 <li> [../COPYRIGHT-BSD2.txt | License]
14 <li> [./userlinks.wiki | User inks]
15 <li> [./hacker-howto.wiki | Hacker How-To]
16 <li> [./fossil-v-git.wiki | Fossil vs. Git]
17 <li> [./permutedindex.html | Documentation Index]
18 </ul>
19 <img src="fossil3.gif" align="center">
20
--- www/index.wiki
+++ www/index.wiki
@@ -9,11 +9,11 @@
9 <li> [./build.wiki | Install]
10 <li> [https://fossil-scm.org/forum | Support/Forum ]
11 <li> [./hints.wiki | Tips &amp; Hints]
12 <li> [./changes.wiki | Change Log]
13 <li> [../COPYRIGHT-BSD2.txt | License]
14 <li> [./userlinks.wiki | User Links]
15 <li> [./hacker-howto.wiki | Hacker How-To]
16 <li> [./fossil-v-git.wiki | Fossil vs. Git]
17 <li> [./permutedindex.html | Documentation Index]
18 </ul>
19 <img src="fossil3.gif" align="center">
20

Keyboard Shortcuts

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