Fossil SCM

Merge from trunk

george 2021-08-15 23:27 UTC wcontent-subsets merge
Commit 282c6f956fd1ab44e4aaa3b56500d15bc5c3e02a16787442559c0b32c951c2fd
99 files changed +1 -1 +9 -1 +2 -2 +1 -1 +10 -9 +12 -4 +52 +1 -1 +4 -3 +97 -3 +281 -64 +253 -7 +83 -17 +20 -1 +10 -1 +1 -3 +5 -9 +91 -58 +6 +23 -9 +23 -9 +4 +6 -6 +77 -66 +2 -1 +17 -1 +37 -9 -7 +127 -3 +6 -5 +3 -1 +2 -2 +117 -17 +1 -3 +18 -14 +51 -33 +7 -2 +3 -2 +1 +170 -47 +12 +12 +1 +26 -55 +1 -1 +7 +355 -275 +4 -2 +70 -24 +3 -2 +15 -15 +184 -83 +3 -5 +2538 -2253 +66 -17 +1 -2 +45 -20 +58 -21 +6 +14 +3 +27 -51 +22 -7 +7 -1 +2 -2 +4 -1 +20 -17 -9 +30 -14 +131 -4 +131 -4 +1 -1 +2 -2 +5 -5 +71 -40 +2 -2 +3 +1 +10 -4 +12 +10 +4 +26 -11 +2 -7 +60 -12 +60 -12 +2 -2 +2 -2 +4 -4 +8 -7 +1 +60 +1 +2 -2 +4 -1 +14 -9 +4 -3 +1 -1 +8 -6
~ VERSION ~ auto.def ~ fossil.1 ~ src/add.c ~ src/alerts.c ~ src/allrepo.c ~ src/attach.c ~ src/backlink.c ~ src/backoffice.c ~ src/bisect.c ~ src/blob.c ~ src/branch.c ~ src/cache.c ~ src/cgi.c ~ src/checkin.c ~ src/checkout.c ~ src/clone.c ~ src/codecheck1.c ~ src/config.h ~ src/db.c ~ src/db.c ~ src/default.css ~ src/diffcmd.c ~ src/dispatch.c ~ src/doc.c ~ src/etag.c ~ src/export.c ~ src/extcgi.c ~ src/file.c ~ src/finfo.c ~ src/forum.c ~ src/fossil.copybutton.js ~ src/fossil.page.wikiedit.js ~ src/http_ssl.c ~ src/http_transport.c ~ src/info.c ~ src/json_branch.c ~ src/linenoise.c ~ src/login.c ~ src/main.c ~ src/main.mk ~ src/main.mk ~ src/makemake.tcl ~ src/markdown.c ~ src/markdown.md ~ src/patch.c ~ src/pikchr.c ~ src/printf.c ~ src/report.c ~ src/search.c ~ src/setup.c ~ src/shell.c ~ src/skins.c ~ src/sqlite3.c ~ src/sqlite3.h ~ src/stash.c ~ src/stat.c ~ src/style.c ~ src/sync.c ~ src/tag.c ~ src/tar.c ~ src/th_main.c ~ src/timeline.c ~ src/tkt.c ~ src/tktsetup.c ~ src/unversioned.c ~ src/update.c ~ src/user.c ~ src/util.c ~ src/wiki.c ~ src/wiki.c ~ src/wiki.wiki ~ src/wikiformat.c ~ src/winhttp.c ~ src/xfer.c ~ src/xfersetup.c ~ src/zip.c ~ test/tester.tcl ~ win/Makefile.dmc ~ win/Makefile.mingw ~ win/Makefile.msc ~ www/aboutdownload.wiki ~ www/build.wiki ~ www/caps/index.md ~ www/changes.wiki ~ www/changes.wiki ~ www/customskin.md ~ www/defcsp.md ~ www/embeddeddoc.wiki ~ www/index.wiki ~ www/mkindex.tcl ~ www/patchcmd.md ~ www/permutedindex.html ~ www/selfhost.wiki ~ www/server/any/cgi.md ~ www/server/debian/service.md ~ www/serverext.wiki ~ www/ssl.wiki ~ www/th1.md
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-2.16
1
+2.17
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.16
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.17
2
+9 -1
--- auto.def
+++ auto.def
@@ -51,11 +51,11 @@
5151
# Use pread/pwrite system calls in place of seek + read/write if possible
5252
define USE_PREAD [cc-check-functions pread]
5353
5454
# If we have cscope here, we'll use it in the "tags" target
5555
if {[cc-check-progs cscope]} {
56
- define COLLECT_CSCOPE_DATA "cscope -bR -s$::autosetup(srcdir)/src"
56
+ define COLLECT_CSCOPE_DATA "cscope -bR $::autosetup(srcdir)/src/*.\[ch\]"
5757
} else {
5858
define COLLECT_CSCOPE_DATA ""
5959
}
6060
6161
# Find tclsh for the test suite.
@@ -101,10 +101,18 @@
101101
define USE_SYSTEM_SQLITE 0
102102
define USE_LINENOISE 0
103103
define FOSSIL_ENABLE_MINIZ 0
104104
define USE_MMAN_H 0
105105
define USE_SEE 0
106
+
107
+
108
+# Maintain the C89/C90-style order of variable declarations before statements.
109
+# Check if the compiler supports the respective warning flag.
110
+if {[cctest -cflags -Wdeclaration-after-statement]} {
111
+ define-append EXTRA_CFLAGS -Wdeclaration-after-statement
112
+}
113
+
106114
107115
# This procedure is a customized version of "cc-check-function-in-lib",
108116
# that does not modify the LIBS variable. Its use prevents prematurely
109117
# pulling in libraries that will be added later anyhow (e.g. "-ldl").
110118
proc check-function-in-lib {function libs {otherlibs {}}} {
111119
--- auto.def
+++ auto.def
@@ -51,11 +51,11 @@
51 # Use pread/pwrite system calls in place of seek + read/write if possible
52 define USE_PREAD [cc-check-functions pread]
53
54 # If we have cscope here, we'll use it in the "tags" target
55 if {[cc-check-progs cscope]} {
56 define COLLECT_CSCOPE_DATA "cscope -bR -s$::autosetup(srcdir)/src"
57 } else {
58 define COLLECT_CSCOPE_DATA ""
59 }
60
61 # Find tclsh for the test suite.
@@ -101,10 +101,18 @@
101 define USE_SYSTEM_SQLITE 0
102 define USE_LINENOISE 0
103 define FOSSIL_ENABLE_MINIZ 0
104 define USE_MMAN_H 0
105 define USE_SEE 0
 
 
 
 
 
 
 
 
106
107 # This procedure is a customized version of "cc-check-function-in-lib",
108 # that does not modify the LIBS variable. Its use prevents prematurely
109 # pulling in libraries that will be added later anyhow (e.g. "-ldl").
110 proc check-function-in-lib {function libs {otherlibs {}}} {
111
--- auto.def
+++ auto.def
@@ -51,11 +51,11 @@
51 # Use pread/pwrite system calls in place of seek + read/write if possible
52 define USE_PREAD [cc-check-functions pread]
53
54 # If we have cscope here, we'll use it in the "tags" target
55 if {[cc-check-progs cscope]} {
56 define COLLECT_CSCOPE_DATA "cscope -bR $::autosetup(srcdir)/src/*.\[ch\]"
57 } else {
58 define COLLECT_CSCOPE_DATA ""
59 }
60
61 # Find tclsh for the test suite.
@@ -101,10 +101,18 @@
101 define USE_SYSTEM_SQLITE 0
102 define USE_LINENOISE 0
103 define FOSSIL_ENABLE_MINIZ 0
104 define USE_MMAN_H 0
105 define USE_SEE 0
106
107
108 # Maintain the C89/C90-style order of variable declarations before statements.
109 # Check if the compiler supports the respective warning flag.
110 if {[cctest -cflags -Wdeclaration-after-statement]} {
111 define-append EXTRA_CFLAGS -Wdeclaration-after-statement
112 }
113
114
115 # This procedure is a customized version of "cc-check-function-in-lib",
116 # that does not modify the LIBS variable. Its use prevents prematurely
117 # pulling in libraries that will be added later anyhow (e.g. "-ldl").
118 proc check-function-in-lib {function libs {otherlibs {}}} {
119
+2 -2
--- fossil.1
+++ fossil.1
@@ -1,6 +1,6 @@
1
-.TH FOSSIL "1" "September 2018" "http://fossil-scm.org" "User Commands"
1
+.TH FOSSIL "1" "July 2021" "https://fossil-scm.org" "User Commands"
22
.SH NAME
33
fossil \- Distributed Version Control System
44
.SH SYNOPSIS
55
.B fossil
66
\fIhelp\fR
@@ -94,9 +94,9 @@
9494
8.
9595
.B Free and Open-Source
9696
- Uses the 2-clause BSD license.
9797
9898
.SH DOCUMENTATION
99
-http://fossil-scm.org/
99
+https://fossil-scm.org/
100100
.br
101101
.B fossil
102102
\fIui\fR
103103
--- fossil.1
+++ fossil.1
@@ -1,6 +1,6 @@
1 .TH FOSSIL "1" "September 2018" "http://fossil-scm.org" "User Commands"
2 .SH NAME
3 fossil \- Distributed Version Control System
4 .SH SYNOPSIS
5 .B fossil
6 \fIhelp\fR
@@ -94,9 +94,9 @@
94 8.
95 .B Free and Open-Source
96 - Uses the 2-clause BSD license.
97
98 .SH DOCUMENTATION
99 http://fossil-scm.org/
100 .br
101 .B fossil
102 \fIui\fR
103
--- fossil.1
+++ fossil.1
@@ -1,6 +1,6 @@
1 .TH FOSSIL "1" "July 2021" "https://fossil-scm.org" "User Commands"
2 .SH NAME
3 fossil \- Distributed Version Control System
4 .SH SYNOPSIS
5 .B fossil
6 \fIhelp\fR
@@ -94,9 +94,9 @@
94 8.
95 .B Free and Open-Source
96 - Uses the 2-clause BSD license.
97
98 .SH DOCUMENTATION
99 https://fossil-scm.org/
100 .br
101 .B fossil
102 \fIui\fR
103
+1 -1
--- src/add.c
+++ src/add.c
@@ -482,14 +482,14 @@
482482
** _silently_ skips over any names for which
483483
** file_is_reserved_name() returns true or which is in the
484484
** fossil_reserved_name() list. We do not need to warn for those,
485485
** as they're outright verboten. */
486486
if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
487
+ int reservedCount = 0;
487488
Stmt q = empty_Stmt;
488489
db_prepare(&q,"SELECT pathname FROM sfile "
489490
"WHERE win_reserved(pathname)");
490
- int reservedCount = 0;
491491
while( db_step(&q)==SQLITE_ROW ){
492492
const char * zName = db_column_text(&q, 0);
493493
++reservedCount;
494494
if(allowReservedFlag){
495495
fossil_warning("WARNING: Windows-reserved "
496496
--- src/add.c
+++ src/add.c
@@ -482,14 +482,14 @@
482 ** _silently_ skips over any names for which
483 ** file_is_reserved_name() returns true or which is in the
484 ** fossil_reserved_name() list. We do not need to warn for those,
485 ** as they're outright verboten. */
486 if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
 
487 Stmt q = empty_Stmt;
488 db_prepare(&q,"SELECT pathname FROM sfile "
489 "WHERE win_reserved(pathname)");
490 int reservedCount = 0;
491 while( db_step(&q)==SQLITE_ROW ){
492 const char * zName = db_column_text(&q, 0);
493 ++reservedCount;
494 if(allowReservedFlag){
495 fossil_warning("WARNING: Windows-reserved "
496
--- src/add.c
+++ src/add.c
@@ -482,14 +482,14 @@
482 ** _silently_ skips over any names for which
483 ** file_is_reserved_name() returns true or which is in the
484 ** fossil_reserved_name() list. We do not need to warn for those,
485 ** as they're outright verboten. */
486 if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
487 int reservedCount = 0;
488 Stmt q = empty_Stmt;
489 db_prepare(&q,"SELECT pathname FROM sfile "
490 "WHERE win_reserved(pathname)");
 
491 while( db_step(&q)==SQLITE_ROW ){
492 const char * zName = db_column_text(&q, 0);
493 ++reservedCount;
494 if(allowReservedFlag){
495 fossil_warning("WARNING: Windows-reserved "
496
+10 -9
--- src/alerts.c
+++ src/alerts.c
@@ -397,17 +397,10 @@
397397
iCol += 3;
398398
}
399399
}
400400
}
401401
402
-#if defined(_WIN32) || defined(WIN32)
403
-# undef popen
404
-# define popen _popen
405
-# undef pclose
406
-# define pclose _pclose
407
-#endif
408
-
409402
#if INTERFACE
410403
/*
411404
** An instance of the following object is used to send emails.
412405
*/
413406
struct AlertSender {
@@ -1160,11 +1153,11 @@
11601153
const char *zLabel = g.argv[3];
11611154
if( strncmp(zLabel, "email-", 6)!=0
11621155
|| (pSetting = db_find_setting(zLabel, 1))==0 ){
11631156
fossil_fatal("not a valid email setting: \"%s\"", zLabel);
11641157
}
1165
- db_set(pSetting->name, g.argv[4], isGlobal);
1158
+ db_set(pSetting->name/*works-like:""*/, g.argv[4], isGlobal);
11661159
g.argc = 3;
11671160
}
11681161
pSetting = setting_info(&nSetting);
11691162
for(; nSetting>0; nSetting--, pSetting++ ){
11701163
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
@@ -3255,18 +3248,26 @@
32553248
** also send a message to an arbitrary email address and/or to all
32563249
** subscribers regardless of whether or not they have elected to
32573250
** receive announcements.
32583251
*/
32593252
void announce_page(void){
3253
+ const char *zAction = "announce"
3254
+ /* Maintenance reminder: we need an explicit action=THIS_PAGE on the
3255
+ ** form element to avoid that a URL arg of to=... passed to this
3256
+ ** page ends up overwriting the form-posted "to" value. This
3257
+ ** action value differs for the test1 request path.
3258
+ */;
3259
+
32603260
login_check_credentials();
32613261
if( !g.perm.Announce ){
32623262
login_needed(0);
32633263
return;
32643264
}
32653265
style_set_current_feature("alerts");
32663266
if( fossil_strcmp(P("name"),"test1")==0 ){
32673267
/* Visit the /announce/test1 page to see the CGI variables */
3268
+ zAction = "announce/test1";
32683269
@ <p style='border: 1px solid black; padding: 1ex;'>
32693270
cgi_print_all(0, 0);
32703271
@ </p>
32713272
}else if( P("submit")!=0 && cgi_csrf_safe(1) ){
32723273
char *zErr = alert_send_announcement();
@@ -3290,11 +3291,11 @@
32903291
@ for this repository.</p>
32913292
return;
32923293
}
32933294
32943295
style_header("Send Announcement");
3295
- @ <form method="POST">
3296
+ @ <form method="POST" action="%R/%s(zAction)">
32963297
@ <table class="subscribe">
32973298
if( g.perm.Admin ){
32983299
int aa = PB("aa");
32993300
int all = PB("all");
33003301
int aMod = PB("mods");
33013302
--- src/alerts.c
+++ src/alerts.c
@@ -397,17 +397,10 @@
397 iCol += 3;
398 }
399 }
400 }
401
402 #if defined(_WIN32) || defined(WIN32)
403 # undef popen
404 # define popen _popen
405 # undef pclose
406 # define pclose _pclose
407 #endif
408
409 #if INTERFACE
410 /*
411 ** An instance of the following object is used to send emails.
412 */
413 struct AlertSender {
@@ -1160,11 +1153,11 @@
1160 const char *zLabel = g.argv[3];
1161 if( strncmp(zLabel, "email-", 6)!=0
1162 || (pSetting = db_find_setting(zLabel, 1))==0 ){
1163 fossil_fatal("not a valid email setting: \"%s\"", zLabel);
1164 }
1165 db_set(pSetting->name, g.argv[4], isGlobal);
1166 g.argc = 3;
1167 }
1168 pSetting = setting_info(&nSetting);
1169 for(; nSetting>0; nSetting--, pSetting++ ){
1170 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
@@ -3255,18 +3248,26 @@
3255 ** also send a message to an arbitrary email address and/or to all
3256 ** subscribers regardless of whether or not they have elected to
3257 ** receive announcements.
3258 */
3259 void announce_page(void){
 
 
 
 
 
 
 
3260 login_check_credentials();
3261 if( !g.perm.Announce ){
3262 login_needed(0);
3263 return;
3264 }
3265 style_set_current_feature("alerts");
3266 if( fossil_strcmp(P("name"),"test1")==0 ){
3267 /* Visit the /announce/test1 page to see the CGI variables */
 
3268 @ <p style='border: 1px solid black; padding: 1ex;'>
3269 cgi_print_all(0, 0);
3270 @ </p>
3271 }else if( P("submit")!=0 && cgi_csrf_safe(1) ){
3272 char *zErr = alert_send_announcement();
@@ -3290,11 +3291,11 @@
3290 @ for this repository.</p>
3291 return;
3292 }
3293
3294 style_header("Send Announcement");
3295 @ <form method="POST">
3296 @ <table class="subscribe">
3297 if( g.perm.Admin ){
3298 int aa = PB("aa");
3299 int all = PB("all");
3300 int aMod = PB("mods");
3301
--- src/alerts.c
+++ src/alerts.c
@@ -397,17 +397,10 @@
397 iCol += 3;
398 }
399 }
400 }
401
 
 
 
 
 
 
 
402 #if INTERFACE
403 /*
404 ** An instance of the following object is used to send emails.
405 */
406 struct AlertSender {
@@ -1160,11 +1153,11 @@
1153 const char *zLabel = g.argv[3];
1154 if( strncmp(zLabel, "email-", 6)!=0
1155 || (pSetting = db_find_setting(zLabel, 1))==0 ){
1156 fossil_fatal("not a valid email setting: \"%s\"", zLabel);
1157 }
1158 db_set(pSetting->name/*works-like:""*/, g.argv[4], isGlobal);
1159 g.argc = 3;
1160 }
1161 pSetting = setting_info(&nSetting);
1162 for(; nSetting>0; nSetting--, pSetting++ ){
1163 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
@@ -3255,18 +3248,26 @@
3248 ** also send a message to an arbitrary email address and/or to all
3249 ** subscribers regardless of whether or not they have elected to
3250 ** receive announcements.
3251 */
3252 void announce_page(void){
3253 const char *zAction = "announce"
3254 /* Maintenance reminder: we need an explicit action=THIS_PAGE on the
3255 ** form element to avoid that a URL arg of to=... passed to this
3256 ** page ends up overwriting the form-posted "to" value. This
3257 ** action value differs for the test1 request path.
3258 */;
3259
3260 login_check_credentials();
3261 if( !g.perm.Announce ){
3262 login_needed(0);
3263 return;
3264 }
3265 style_set_current_feature("alerts");
3266 if( fossil_strcmp(P("name"),"test1")==0 ){
3267 /* Visit the /announce/test1 page to see the CGI variables */
3268 zAction = "announce/test1";
3269 @ <p style='border: 1px solid black; padding: 1ex;'>
3270 cgi_print_all(0, 0);
3271 @ </p>
3272 }else if( P("submit")!=0 && cgi_csrf_safe(1) ){
3273 char *zErr = alert_send_announcement();
@@ -3290,11 +3291,11 @@
3291 @ for this repository.</p>
3292 return;
3293 }
3294
3295 style_header("Send Announcement");
3296 @ <form method="POST" action="%R/%s(zAction)">
3297 @ <table class="subscribe">
3298 if( g.perm.Admin ){
3299 int aa = PB("aa");
3300 int all = PB("all");
3301 int aMod = PB("mods");
3302
+12 -4
--- src/allrepo.c
+++ src/allrepo.c
@@ -110,17 +110,24 @@
110110
** --randomize options are not supported.
111111
**
112112
** sync Run a "sync" on all repositories. Only the --verbose
113113
** and --unversioned options are supported.
114114
**
115
-** set|unset Run the "setting", "set", or "unset" commands on all
115
+** set Run the "setting" or "set" commands on all
116116
** repositories. These command are particularly useful in
117117
** conjunction with the "max-loadavg" setting which cannot
118118
** otherwise be set globally.
119119
**
120
-** server Run the "ui" or "server" commands on all repositories.
121
-** ui The root URI gives a listing of all repos.
120
+** unset Run the "unset" command on all repositories
121
+**
122
+** server Run the "server" commands on all repositories.
123
+** The root URI gives a listing of all repos.
124
+**
125
+** ui Run the "ui" command on all repositories. Like "server"
126
+** but bind to the loopback TCP address only, enable
127
+** the --localauth option and automatically launch a
128
+** web-browser
122129
**
123130
**
124131
** In addition, the following maintenance operations are supported:
125132
**
126133
** add Add all the repositories named to the set of repositories
@@ -247,11 +254,12 @@
247254
}else{
248255
int n3 = (int)strlen(g.argv[3]);
249256
if( strncmp(g.argv[3], "export", n3)==0 ){
250257
zCmd = "git export --if-mirrored -R";
251258
}else if( strncmp(g.argv[3], "status", n3)==0 ){
252
- zCmd = "git status -R";
259
+ zCmd = "git status --by-all -q -R";
260
+ quiet = 1;
253261
}else{
254262
usage("git (export|status)");
255263
}
256264
}
257265
}else if( strncmp(zCmd, "push", n)==0 ){
258266
--- src/allrepo.c
+++ src/allrepo.c
@@ -110,17 +110,24 @@
110 ** --randomize options are not supported.
111 **
112 ** sync Run a "sync" on all repositories. Only the --verbose
113 ** and --unversioned options are supported.
114 **
115 ** set|unset Run the "setting", "set", or "unset" commands on all
116 ** repositories. These command are particularly useful in
117 ** conjunction with the "max-loadavg" setting which cannot
118 ** otherwise be set globally.
119 **
120 ** server Run the "ui" or "server" commands on all repositories.
121 ** ui The root URI gives a listing of all repos.
 
 
 
 
 
 
 
122 **
123 **
124 ** In addition, the following maintenance operations are supported:
125 **
126 ** add Add all the repositories named to the set of repositories
@@ -247,11 +254,12 @@
247 }else{
248 int n3 = (int)strlen(g.argv[3]);
249 if( strncmp(g.argv[3], "export", n3)==0 ){
250 zCmd = "git export --if-mirrored -R";
251 }else if( strncmp(g.argv[3], "status", n3)==0 ){
252 zCmd = "git status -R";
 
253 }else{
254 usage("git (export|status)");
255 }
256 }
257 }else if( strncmp(zCmd, "push", n)==0 ){
258
--- src/allrepo.c
+++ src/allrepo.c
@@ -110,17 +110,24 @@
110 ** --randomize options are not supported.
111 **
112 ** sync Run a "sync" on all repositories. Only the --verbose
113 ** and --unversioned options are supported.
114 **
115 ** set Run the "setting" or "set" commands on all
116 ** repositories. These command are particularly useful in
117 ** conjunction with the "max-loadavg" setting which cannot
118 ** otherwise be set globally.
119 **
120 ** unset Run the "unset" command on all repositories
121 **
122 ** server Run the "server" commands on all repositories.
123 ** The root URI gives a listing of all repos.
124 **
125 ** ui Run the "ui" command on all repositories. Like "server"
126 ** but bind to the loopback TCP address only, enable
127 ** the --localauth option and automatically launch a
128 ** web-browser
129 **
130 **
131 ** In addition, the following maintenance operations are supported:
132 **
133 ** add Add all the repositories named to the set of repositories
@@ -247,11 +254,12 @@
254 }else{
255 int n3 = (int)strlen(g.argv[3]);
256 if( strncmp(g.argv[3], "export", n3)==0 ){
257 zCmd = "git export --if-mirrored -R";
258 }else if( strncmp(g.argv[3], "status", n3)==0 ){
259 zCmd = "git status --by-all -q -R";
260 quiet = 1;
261 }else{
262 usage("git (export|status)");
263 }
264 }
265 }else if( strncmp(zCmd, "push", n)==0 ){
266
+52
--- src/attach.c
+++ src/attach.c
@@ -778,5 +778,57 @@
778778
return;
779779
780780
attachment_cmd_usage:
781781
usage("add ?PAGENAME? FILENAME [-t|--technote DATETIME ]");
782782
}
783
+
784
+
785
+/*
786
+** COMMAND: test-list-attachments
787
+**
788
+** Usage: %fossil test-list-attachments ?-latest? ?TargetName(s)...?
789
+**
790
+** List attachments for one or more attachment targets. The target
791
+** name arguments are glob prefixes for the attachment.target
792
+** field. If no names are provided then a prefix of [a-zA-Z] is used,
793
+** which will match most wiki page names and some ticket hashes.
794
+**
795
+** Options:
796
+**
797
+** -latest List only the latest version of a given attachment.
798
+**
799
+*/
800
+void test_list_attachments(void){
801
+ Stmt q;
802
+ int i;
803
+ const int fLatest = find_option("latest", 0, 0) != 0;
804
+
805
+ db_find_and_open_repository(0, 0);
806
+ verify_all_options();
807
+ db_prepare(&q,
808
+ "SELECT datetime(mtime,toLocal()), src, target, filename,"
809
+ " comment, user "
810
+ " FROM attachment"
811
+ " WHERE target GLOB :tgtname ||'*'"
812
+ " AND (isLatest OR %d)"
813
+ " ORDER BY target, isLatest DESC, mtime DESC",
814
+ !fLatest
815
+ );
816
+ if(g.argc<3){
817
+ static char * argv[3] = {0,0,"[a-zA-Z]"};
818
+ g.argc = 3;
819
+ g.argv = argv;
820
+ }
821
+ for(i = 2; i < g.argc; ++i){
822
+ const char *zPage = g.argv[i];
823
+ db_bind_text(&q, ":tgtname", zPage);
824
+ while(SQLITE_ROW == db_step(&q)){
825
+ const char * zTime = db_column_text(&q, 0);
826
+ const char * zSrc = db_column_text(&q, 1);
827
+ const char * zTarget = db_column_text(&q, 2);
828
+ const char * zName = db_column_text(&q, 3);
829
+ printf("%-20s %s %.12s %s\n", zTarget, zTime, zSrc, zName);
830
+ }
831
+ db_reset(&q);
832
+ }
833
+ db_finalize(&q);
834
+}
783835
--- src/attach.c
+++ src/attach.c
@@ -778,5 +778,57 @@
778 return;
779
780 attachment_cmd_usage:
781 usage("add ?PAGENAME? FILENAME [-t|--technote DATETIME ]");
782 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
783
--- src/attach.c
+++ src/attach.c
@@ -778,5 +778,57 @@
778 return;
779
780 attachment_cmd_usage:
781 usage("add ?PAGENAME? FILENAME [-t|--technote DATETIME ]");
782 }
783
784
785 /*
786 ** COMMAND: test-list-attachments
787 **
788 ** Usage: %fossil test-list-attachments ?-latest? ?TargetName(s)...?
789 **
790 ** List attachments for one or more attachment targets. The target
791 ** name arguments are glob prefixes for the attachment.target
792 ** field. If no names are provided then a prefix of [a-zA-Z] is used,
793 ** which will match most wiki page names and some ticket hashes.
794 **
795 ** Options:
796 **
797 ** -latest List only the latest version of a given attachment.
798 **
799 */
800 void test_list_attachments(void){
801 Stmt q;
802 int i;
803 const int fLatest = find_option("latest", 0, 0) != 0;
804
805 db_find_and_open_repository(0, 0);
806 verify_all_options();
807 db_prepare(&q,
808 "SELECT datetime(mtime,toLocal()), src, target, filename,"
809 " comment, user "
810 " FROM attachment"
811 " WHERE target GLOB :tgtname ||'*'"
812 " AND (isLatest OR %d)"
813 " ORDER BY target, isLatest DESC, mtime DESC",
814 !fLatest
815 );
816 if(g.argc<3){
817 static char * argv[3] = {0,0,"[a-zA-Z]"};
818 g.argc = 3;
819 g.argv = argv;
820 }
821 for(i = 2; i < g.argc; ++i){
822 const char *zPage = g.argv[i];
823 db_bind_text(&q, ":tgtname", zPage);
824 while(SQLITE_ROW == db_step(&q)){
825 const char * zTime = db_column_text(&q, 0);
826 const char * zSrc = db_column_text(&q, 1);
827 const char * zTarget = db_column_text(&q, 2);
828 const char * zName = db_column_text(&q, 3);
829 printf("%-20s %s %.12s %s\n", zTarget, zTime, zSrc, zName);
830 }
831 db_reset(&q);
832 }
833 db_finalize(&q);
834 }
835
+1 -1
--- src/backlink.c
+++ src/backlink.c
@@ -25,11 +25,11 @@
2525
#include "backlink.h"
2626
#include <assert.h>
2727
2828
2929
/*
30
-** Show a graph all wiki, tickets, and check-ins that refer to object zUuid.
30
+** Show a graph of all wiki, tickets, and check-ins that refer to object zUuid.
3131
**
3232
** If zLabel is not NULL and the graph is not empty, then output zLabel as
3333
** a prefix to the graph.
3434
*/
3535
void render_backlink_graph(const char *zUuid, const char *zLabel){
3636
--- src/backlink.c
+++ src/backlink.c
@@ -25,11 +25,11 @@
25 #include "backlink.h"
26 #include <assert.h>
27
28
29 /*
30 ** Show a graph all wiki, tickets, and check-ins that refer to object zUuid.
31 **
32 ** If zLabel is not NULL and the graph is not empty, then output zLabel as
33 ** a prefix to the graph.
34 */
35 void render_backlink_graph(const char *zUuid, const char *zLabel){
36
--- src/backlink.c
+++ src/backlink.c
@@ -25,11 +25,11 @@
25 #include "backlink.h"
26 #include <assert.h>
27
28
29 /*
30 ** Show a graph of all wiki, tickets, and check-ins that refer to object zUuid.
31 **
32 ** If zLabel is not NULL and the graph is not empty, then output zLabel as
33 ** a prefix to the graph.
34 */
35 void render_backlink_graph(const char *zUuid, const char *zLabel){
36
--- src/backoffice.c
+++ src/backoffice.c
@@ -484,10 +484,11 @@
484484
int lastWarning = 0;
485485
int warningDelay = 30;
486486
static int once = 0;
487487
488488
if( sqlite3_db_readonly(g.db, 0) ) return;
489
+ g.zPhase = "backoffice";
489490
backoffice_error_check_one(&once);
490491
idSelf = backofficeProcessId();
491492
while(1){
492493
tmNow = time(0);
493494
db_begin_write();
@@ -754,11 +755,11 @@
754755
&& (nMin<=0 || aLastRun[i]+nMin>iNow)
755756
){
756757
continue; /* Not yet time to run this one */
757758
}
758759
blob_init(&cmd, 0, 0);
759
- blob_append_escaped_arg(&cmd, g.nameOfExe);
760
+ blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
760761
blob_append(&cmd, " backoffice --nodelay", -1);
761762
if( g.fAnyTrace ){
762763
blob_append(&cmd, " --trace", -1);
763764
}
764765
if( bDebug ){
@@ -767,13 +768,13 @@
767768
if( nPoll>0 ){
768769
blob_append(&cmd, " --nolease", -1);
769770
}
770771
if( backofficeLogfile ){
771772
blob_append(&cmd, " --logfile", -1);
772
- blob_append_escaped_arg(&cmd, backofficeLogfile);
773
+ blob_append_escaped_arg(&cmd, backofficeLogfile, 1);
773774
}
774
- blob_append_escaped_arg(&cmd, g.argv[i]);
775
+ blob_append_escaped_arg(&cmd, g.argv[i], 1);
775776
nCmd++;
776777
if( bDebug ){
777778
fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
778779
}
779780
fossil_system(blob_str(&cmd));
780781
--- src/backoffice.c
+++ src/backoffice.c
@@ -484,10 +484,11 @@
484 int lastWarning = 0;
485 int warningDelay = 30;
486 static int once = 0;
487
488 if( sqlite3_db_readonly(g.db, 0) ) return;
 
489 backoffice_error_check_one(&once);
490 idSelf = backofficeProcessId();
491 while(1){
492 tmNow = time(0);
493 db_begin_write();
@@ -754,11 +755,11 @@
754 && (nMin<=0 || aLastRun[i]+nMin>iNow)
755 ){
756 continue; /* Not yet time to run this one */
757 }
758 blob_init(&cmd, 0, 0);
759 blob_append_escaped_arg(&cmd, g.nameOfExe);
760 blob_append(&cmd, " backoffice --nodelay", -1);
761 if( g.fAnyTrace ){
762 blob_append(&cmd, " --trace", -1);
763 }
764 if( bDebug ){
@@ -767,13 +768,13 @@
767 if( nPoll>0 ){
768 blob_append(&cmd, " --nolease", -1);
769 }
770 if( backofficeLogfile ){
771 blob_append(&cmd, " --logfile", -1);
772 blob_append_escaped_arg(&cmd, backofficeLogfile);
773 }
774 blob_append_escaped_arg(&cmd, g.argv[i]);
775 nCmd++;
776 if( bDebug ){
777 fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
778 }
779 fossil_system(blob_str(&cmd));
780
--- src/backoffice.c
+++ src/backoffice.c
@@ -484,10 +484,11 @@
484 int lastWarning = 0;
485 int warningDelay = 30;
486 static int once = 0;
487
488 if( sqlite3_db_readonly(g.db, 0) ) return;
489 g.zPhase = "backoffice";
490 backoffice_error_check_one(&once);
491 idSelf = backofficeProcessId();
492 while(1){
493 tmNow = time(0);
494 db_begin_write();
@@ -754,11 +755,11 @@
755 && (nMin<=0 || aLastRun[i]+nMin>iNow)
756 ){
757 continue; /* Not yet time to run this one */
758 }
759 blob_init(&cmd, 0, 0);
760 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
761 blob_append(&cmd, " backoffice --nodelay", -1);
762 if( g.fAnyTrace ){
763 blob_append(&cmd, " --trace", -1);
764 }
765 if( bDebug ){
@@ -767,13 +768,13 @@
768 if( nPoll>0 ){
769 blob_append(&cmd, " --nolease", -1);
770 }
771 if( backofficeLogfile ){
772 blob_append(&cmd, " --logfile", -1);
773 blob_append_escaped_arg(&cmd, backofficeLogfile, 1);
774 }
775 blob_append_escaped_arg(&cmd, g.argv[i], 1);
776 nCmd++;
777 if( bDebug ){
778 fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
779 }
780 fossil_system(blob_str(&cmd));
781
+97 -3
--- src/bisect.c
+++ src/bisect.c
@@ -373,13 +373,94 @@
373373
** Reset the bisect subsystem.
374374
*/
375375
void bisect_reset(void){
376376
db_multi_exec(
377377
"DELETE FROM vvar WHERE name IN "
378
- " ('bisect-good', 'bisect-bad', 'bisect-log')"
378
+ " ('bisect-good', 'bisect-bad', 'bisect-log', 'bisect-complete')"
379379
);
380380
}
381
+
382
+/*
383
+** fossil bisect run [OPTIONS] COMMAND
384
+**
385
+** Invoke COMMAND (with arguments) repeatedly to perform the bisect.
386
+** Options:
387
+**
388
+** -i|--interactive Prompt user for decisions rather than
389
+** using the return code from COMMAND
390
+*/
391
+static void bisect_run(void){
392
+ const char *zCmd;
393
+ int isInteractive = 0;
394
+ int i;
395
+ if( g.argc<4 ){
396
+ fossil_fatal("Usage: fossil bisect run [OPTIONS] COMMAND\n");
397
+ }
398
+ for(i=3; i<g.argc-1; i++){
399
+ const char *zArg = g.argv[i];
400
+ if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
401
+ if( strcmp(zArg, "-i")==0 || strcmp(zArg, "-interactive")==0 ){
402
+ isInteractive = 1;
403
+ continue;
404
+ }
405
+ fossil_fatal("unknown command-line option: \"%s\"\n", g.argv[i]);
406
+ }
407
+ zCmd = g.argv[i];
408
+ if( db_int(0, "SELECT count(*) FROM vvar"
409
+ " WHERE name IN ('bisect-good','bisect-bad')")!=2 ){
410
+ fossil_fatal("need good/bad boundaries to use \"fossil bisect run\"");
411
+ }
412
+ while( db_lget_int("bisect-complete",0)==0 ){
413
+ int rc;
414
+ Blob cmd;
415
+ blob_init(&cmd, 0, 0);
416
+ blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
417
+ rc = fossil_unsafe_system(zCmd);
418
+ if( isInteractive ){
419
+ Blob in;
420
+ fossil_print("test-command result: %d\n", rc);
421
+ while(1){
422
+ int n;
423
+ char *z;
424
+ prompt_user("Enter (g)ood, (b)ad, (s)kip, (a)uto, (h)alt: ", &in);
425
+ n = blob_size(&in);
426
+ z = blob_str(&in);
427
+ if( n<1 ) continue;
428
+ if( sqlite3_strnicmp("good", z, n)==0 ){
429
+ rc = 0;
430
+ break;
431
+ }
432
+ if( sqlite3_strnicmp("bad", z, n)==0 ){
433
+ rc = 1;
434
+ break;
435
+ }
436
+ if( sqlite3_strnicmp("skip", z, n)==0 ){
437
+ rc = 125;
438
+ break;
439
+ }
440
+ if( sqlite3_strnicmp("auto", z, n)==0 ){
441
+ isInteractive = 0;
442
+ break;
443
+ }
444
+ if( sqlite3_strnicmp("halt", z, n)==0 ){
445
+ return;
446
+ }
447
+ blob_reset(&in);
448
+ }
449
+ }
450
+ if( rc==0 ){
451
+ blob_append(&cmd, " bisect good", -1);
452
+ }else if( rc==125 ){
453
+ blob_append(&cmd, " bisect skip", -1);
454
+ }else{
455
+ blob_append(&cmd, " bisect bad", -1);
456
+ }
457
+ fossil_print("%s\n", blob_str(&cmd));
458
+ fossil_system(blob_str(&cmd));
459
+ blob_reset(&cmd);
460
+ }
461
+}
381462
382463
/*
383464
** COMMAND: bisect
384465
**
385466
** Usage: %fossil bisect SUBCOMMAND ...
@@ -417,10 +498,20 @@
417498
** > fossil bisect reset
418499
**
419500
** Reinitialize a bisect session. This cancels prior bisect history
420501
** and allows a bisect session to start over from the beginning.
421502
**
503
+** > fossil bisect run [OPTIONS] COMMAND
504
+**
505
+** Invoke COMMAND repeatedly to run the bisect. The exit code for
506
+** COMMAND should be 0 for "good", 125 for "skip", and any other value
507
+** for "bad". Options:
508
+**
509
+** -i|--interactive Prompt the user for the good/bad/skip decision
510
+** after each step, rather than using the exit
511
+** code from COMMAND
512
+**
422513
** > fossil bisect skip ?VERSION?
423514
**
424515
** Cause VERSION (or the current checkout if VERSION is omitted) to
425516
** be ignored for the purpose of the current bisect. This might
426517
** be done, for example, because VERSION does not compile correctly
@@ -540,10 +631,11 @@
540631
int m = (int)strlen(zDisplay);
541632
bisect_path();
542633
pMid = path_midpoint();
543634
if( pMid==0 ){
544635
fossil_print("bisect complete\n");
636
+ db_lset_int("bisect-complete",1);
545637
}else{
546638
int nSpan = path_length_not_hidden();
547639
int nStep = path_search_depth();
548640
g.argv[1] = "update";
549641
g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
@@ -562,10 +654,12 @@
562654
}
563655
}else if( strncmp(zCmd, "log", n)==0 ){
564656
bisect_chart(0);
565657
}else if( strncmp(zCmd, "chart", n)==0 ){
566658
bisect_chart(1);
659
+ }else if( strncmp(zCmd, "run", n)==0 ){
660
+ bisect_run();
567661
}else if( strncmp(zCmd, "options", n)==0 ){
568662
if( g.argc==3 ){
569663
unsigned int i;
570664
for(i=0; i<count(aBisectOption); i++){
571665
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
@@ -579,11 +673,11 @@
579673
n = strlen(g.argv[3]);
580674
for(i=0; i<count(aBisectOption); i++){
581675
if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
582676
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
583677
if( g.argc==5 ){
584
- db_lset(z, g.argv[4]);
678
+ db_lset(z/*works-like:"bisect-%s"*/, g.argv[4]);
585679
}
586680
fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
587681
fossil_free(z);
588682
break;
589683
}
@@ -612,8 +706,8 @@
612706
){
613707
int fAll = find_option("all", "a", 0)!=0;
614708
bisect_list(!fAll);
615709
}else if( !foundCmd ){
616710
usage:
617
- usage("bad|good|log|chart|next|options|reset|skip|status|ui|undo");
711
+ usage("bad|good|log|chart|next|options|reset|run|skip|status|ui|undo");
618712
}
619713
}
620714
--- src/bisect.c
+++ src/bisect.c
@@ -373,13 +373,94 @@
373 ** Reset the bisect subsystem.
374 */
375 void bisect_reset(void){
376 db_multi_exec(
377 "DELETE FROM vvar WHERE name IN "
378 " ('bisect-good', 'bisect-bad', 'bisect-log')"
379 );
380 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
382 /*
383 ** COMMAND: bisect
384 **
385 ** Usage: %fossil bisect SUBCOMMAND ...
@@ -417,10 +498,20 @@
417 ** > fossil bisect reset
418 **
419 ** Reinitialize a bisect session. This cancels prior bisect history
420 ** and allows a bisect session to start over from the beginning.
421 **
 
 
 
 
 
 
 
 
 
 
422 ** > fossil bisect skip ?VERSION?
423 **
424 ** Cause VERSION (or the current checkout if VERSION is omitted) to
425 ** be ignored for the purpose of the current bisect. This might
426 ** be done, for example, because VERSION does not compile correctly
@@ -540,10 +631,11 @@
540 int m = (int)strlen(zDisplay);
541 bisect_path();
542 pMid = path_midpoint();
543 if( pMid==0 ){
544 fossil_print("bisect complete\n");
 
545 }else{
546 int nSpan = path_length_not_hidden();
547 int nStep = path_search_depth();
548 g.argv[1] = "update";
549 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
@@ -562,10 +654,12 @@
562 }
563 }else if( strncmp(zCmd, "log", n)==0 ){
564 bisect_chart(0);
565 }else if( strncmp(zCmd, "chart", n)==0 ){
566 bisect_chart(1);
 
 
567 }else if( strncmp(zCmd, "options", n)==0 ){
568 if( g.argc==3 ){
569 unsigned int i;
570 for(i=0; i<count(aBisectOption); i++){
571 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
@@ -579,11 +673,11 @@
579 n = strlen(g.argv[3]);
580 for(i=0; i<count(aBisectOption); i++){
581 if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
582 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
583 if( g.argc==5 ){
584 db_lset(z, g.argv[4]);
585 }
586 fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
587 fossil_free(z);
588 break;
589 }
@@ -612,8 +706,8 @@
612 ){
613 int fAll = find_option("all", "a", 0)!=0;
614 bisect_list(!fAll);
615 }else if( !foundCmd ){
616 usage:
617 usage("bad|good|log|chart|next|options|reset|skip|status|ui|undo");
618 }
619 }
620
--- src/bisect.c
+++ src/bisect.c
@@ -373,13 +373,94 @@
373 ** Reset the bisect subsystem.
374 */
375 void bisect_reset(void){
376 db_multi_exec(
377 "DELETE FROM vvar WHERE name IN "
378 " ('bisect-good', 'bisect-bad', 'bisect-log', 'bisect-complete')"
379 );
380 }
381
382 /*
383 ** fossil bisect run [OPTIONS] COMMAND
384 **
385 ** Invoke COMMAND (with arguments) repeatedly to perform the bisect.
386 ** Options:
387 **
388 ** -i|--interactive Prompt user for decisions rather than
389 ** using the return code from COMMAND
390 */
391 static void bisect_run(void){
392 const char *zCmd;
393 int isInteractive = 0;
394 int i;
395 if( g.argc<4 ){
396 fossil_fatal("Usage: fossil bisect run [OPTIONS] COMMAND\n");
397 }
398 for(i=3; i<g.argc-1; i++){
399 const char *zArg = g.argv[i];
400 if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
401 if( strcmp(zArg, "-i")==0 || strcmp(zArg, "-interactive")==0 ){
402 isInteractive = 1;
403 continue;
404 }
405 fossil_fatal("unknown command-line option: \"%s\"\n", g.argv[i]);
406 }
407 zCmd = g.argv[i];
408 if( db_int(0, "SELECT count(*) FROM vvar"
409 " WHERE name IN ('bisect-good','bisect-bad')")!=2 ){
410 fossil_fatal("need good/bad boundaries to use \"fossil bisect run\"");
411 }
412 while( db_lget_int("bisect-complete",0)==0 ){
413 int rc;
414 Blob cmd;
415 blob_init(&cmd, 0, 0);
416 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
417 rc = fossil_unsafe_system(zCmd);
418 if( isInteractive ){
419 Blob in;
420 fossil_print("test-command result: %d\n", rc);
421 while(1){
422 int n;
423 char *z;
424 prompt_user("Enter (g)ood, (b)ad, (s)kip, (a)uto, (h)alt: ", &in);
425 n = blob_size(&in);
426 z = blob_str(&in);
427 if( n<1 ) continue;
428 if( sqlite3_strnicmp("good", z, n)==0 ){
429 rc = 0;
430 break;
431 }
432 if( sqlite3_strnicmp("bad", z, n)==0 ){
433 rc = 1;
434 break;
435 }
436 if( sqlite3_strnicmp("skip", z, n)==0 ){
437 rc = 125;
438 break;
439 }
440 if( sqlite3_strnicmp("auto", z, n)==0 ){
441 isInteractive = 0;
442 break;
443 }
444 if( sqlite3_strnicmp("halt", z, n)==0 ){
445 return;
446 }
447 blob_reset(&in);
448 }
449 }
450 if( rc==0 ){
451 blob_append(&cmd, " bisect good", -1);
452 }else if( rc==125 ){
453 blob_append(&cmd, " bisect skip", -1);
454 }else{
455 blob_append(&cmd, " bisect bad", -1);
456 }
457 fossil_print("%s\n", blob_str(&cmd));
458 fossil_system(blob_str(&cmd));
459 blob_reset(&cmd);
460 }
461 }
462
463 /*
464 ** COMMAND: bisect
465 **
466 ** Usage: %fossil bisect SUBCOMMAND ...
@@ -417,10 +498,20 @@
498 ** > fossil bisect reset
499 **
500 ** Reinitialize a bisect session. This cancels prior bisect history
501 ** and allows a bisect session to start over from the beginning.
502 **
503 ** > fossil bisect run [OPTIONS] COMMAND
504 **
505 ** Invoke COMMAND repeatedly to run the bisect. The exit code for
506 ** COMMAND should be 0 for "good", 125 for "skip", and any other value
507 ** for "bad". Options:
508 **
509 ** -i|--interactive Prompt the user for the good/bad/skip decision
510 ** after each step, rather than using the exit
511 ** code from COMMAND
512 **
513 ** > fossil bisect skip ?VERSION?
514 **
515 ** Cause VERSION (or the current checkout if VERSION is omitted) to
516 ** be ignored for the purpose of the current bisect. This might
517 ** be done, for example, because VERSION does not compile correctly
@@ -540,10 +631,11 @@
631 int m = (int)strlen(zDisplay);
632 bisect_path();
633 pMid = path_midpoint();
634 if( pMid==0 ){
635 fossil_print("bisect complete\n");
636 db_lset_int("bisect-complete",1);
637 }else{
638 int nSpan = path_length_not_hidden();
639 int nStep = path_search_depth();
640 g.argv[1] = "update";
641 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
@@ -562,10 +654,12 @@
654 }
655 }else if( strncmp(zCmd, "log", n)==0 ){
656 bisect_chart(0);
657 }else if( strncmp(zCmd, "chart", n)==0 ){
658 bisect_chart(1);
659 }else if( strncmp(zCmd, "run", n)==0 ){
660 bisect_run();
661 }else if( strncmp(zCmd, "options", n)==0 ){
662 if( g.argc==3 ){
663 unsigned int i;
664 for(i=0; i<count(aBisectOption); i++){
665 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
@@ -579,11 +673,11 @@
673 n = strlen(g.argv[3]);
674 for(i=0; i<count(aBisectOption); i++){
675 if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
676 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
677 if( g.argc==5 ){
678 db_lset(z/*works-like:"bisect-%s"*/, g.argv[4]);
679 }
680 fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
681 fossil_free(z);
682 break;
683 }
@@ -612,8 +706,8 @@
706 ){
707 int fAll = find_option("all", "a", 0)!=0;
708 bisect_list(!fAll);
709 }else if( !foundCmd ){
710 usage:
711 usage("bad|good|log|chart|next|options|reset|run|skip|status|ui|undo");
712 }
713 }
714
+281 -64
--- src/blob.c
+++ src/blob.c
@@ -460,11 +460,11 @@
460460
** Compare a blob to a string. Return TRUE if they are equal.
461461
*/
462462
int blob_eq_str(Blob *pBlob, const char *z, int n){
463463
Blob t;
464464
blob_is_init(pBlob);
465
- if( n<=0 ) n = strlen(z);
465
+ if( n<=0 ) n = (int)strlen(z);
466466
t.aData = (char*)z;
467467
t.nUsed = n;
468468
t.xRealloc = blobReallocStatic;
469469
return blob_compare(pBlob, &t)==0;
470470
}
@@ -474,11 +474,11 @@
474474
** operator on the string constant twice, so it really does need to be a
475475
** string literal or character array - not a character pointer.
476476
*/
477477
#if INTERFACE
478478
# define blob_eq(B,S) \
479
- ((B)->nUsed==sizeof(S)-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
479
+ ((B)->nUsed==sizeof(S"")-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
480480
#endif
481481
482482
483483
/*
484484
** Attempt to resize a blob so that its internal buffer is
@@ -1293,105 +1293,322 @@
12931293
z[--j] = z[i];
12941294
}
12951295
}
12961296
}
12971297
1298
+/*
1299
+** ASCII (for reference):
1300
+** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
1301
+** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o
1302
+** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^
1303
+** 2x () ! " # $ % & ' ( ) * + , - . /
1304
+** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1305
+** 4x @ A B C D E F G H I J K L M N O
1306
+** 5x P Q R S T U V W X Y Z [ \ ] ^ _
1307
+** 6x ` a b c d e f g h i j k l m n o
1308
+** 7x p q r s t u v w x y z { | } ~ ^_
1309
+*/
1310
+
1311
+/*
1312
+** Meanings for bytes in a filename:
1313
+**
1314
+** 0 Ordinary character. No encoding required
1315
+** 1 Needs to be escaped
1316
+** 2 Illegal character. Do not allow in a filename
1317
+** 3 First byte of a 2-byte UTF-8
1318
+** 4 First byte of a 3-byte UTF-8
1319
+** 5 First byte of a 4-byte UTF-8
1320
+*/
1321
+static const char aSafeChar[256] = {
1322
+#ifdef _WIN32
1323
+/* Windows
1324
+** Prohibit: all control characters, including tab, \r and \n
1325
+** Escape: (space) " # $ % & ' ( ) * ; < > ? [ ] ^ ` { | }
1326
+*/
1327
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1328
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1329
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1330
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 2x */
1331
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1332
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1333
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */
1334
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1335
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1336
+#else
1337
+/* Unix
1338
+** Prohibit: all control characters, including tab, \r and \n
1339
+** Escape: (space) ! " # $ % & ' ( ) * ; < > ? [ \ ] ^ ` { | }
1340
+*/
1341
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1342
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1343
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1344
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 2x */
1345
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1346
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1347
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */
1348
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1349
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1350
+#endif
1351
+ /* all bytes 0x80 through 0xbf are unescaped, being secondary
1352
+ ** bytes to UTF8 characters. Bytes 0xc0 through 0xff are the
1353
+ ** first byte of a UTF8 character and do get escaped */
1354
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 8x */
1355
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 9x */
1356
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* ax */
1357
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* bx */
1358
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* cx */
1359
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* dx */
1360
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* ex */
1361
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 /* fx */
1362
+};
1363
+
12981364
/*
12991365
** pBlob is a shell command under construction. This routine safely
1300
-** appends argument zIn.
1366
+** appends filename argument zIn.
13011367
**
13021368
** The argument is escaped if it contains white space or other characters
13031369
** that need to be escaped for the shell. If zIn contains characters
13041370
** that cannot be safely escaped, then throw a fatal error.
13051371
**
1306
-** The argument is expected to a filename of some kinds. As shell commands
1307
-** commonly have command-line options that begin with "-" and since we
1308
-** do not want an attacker to be able to invoke these switches using
1309
-** filenames that begin with "-", if zIn begins with "-", prepend
1310
-** an additional "./".
1372
+** If the isFilename argument is true, then the argument is expected
1373
+** to be a filename. As shell commands commonly have command-line
1374
+** options that begin with "-" and since we do not want an attacker
1375
+** to be able to invoke these switches using filenames that begin
1376
+** with "-", if zIn begins with "-", prepend an additional "./"
1377
+** (or ".\\" on Windows).
13111378
*/
1312
-void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
1379
+void blob_append_escaped_arg(Blob *pBlob, const char *zIn, int isFilename){
13131380
int i;
1314
- char c;
1381
+ unsigned char c;
13151382
int needEscape = 0;
13161383
int n = blob_size(pBlob);
13171384
char *z = blob_buffer(pBlob);
1318
-#if defined(_WIN32)
1319
- const char cDirSep = '\\'; /* Use \ as directory separator */
1320
- const char cQuote = '"'; /* Use "..." quoting on windows */
1321
- const char cEscape = '^'; /* Use ^X escaping on windows */
1322
-#else
1323
- const char cDirSep = '/'; /* Use / as directory separator */
1324
- const char cQuote = '\''; /* Use '...' quoting on unix */
1325
- const char cEscape = '\\'; /* Use \X escaping on unix */
1326
-#endif
1327
-
1328
- for(i=0; (c = zIn[i])!=0; i++){
1329
- if( c==cQuote || (unsigned char)c<' ' ||
1330
- c==cEscape || c==';' || c=='*' || c=='?' || c=='[' ){
1331
- Blob bad;
1332
- blob_token(pBlob, &bad);
1333
- fossil_fatal("the [%s] argument to the \"%s\" command contains "
1334
- "a character (ascii 0x%02x) that is a security risk",
1335
- zIn, blob_str(&bad), c);
1336
- }
1337
- if( !needEscape && !fossil_isalnum(c) && c!=cDirSep && c!='.' && c!='_' ){
1385
+
1386
+ /* Look for illegal byte-sequences and byte-sequences that require
1387
+ ** escaping. No control-characters are allowed. All spaces and
1388
+ ** non-ASCII unicode characters and some punctuation characters require
1389
+ ** escaping. */
1390
+ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1391
+ if( aSafeChar[c] ){
1392
+ unsigned char x = aSafeChar[c];
13381393
needEscape = 1;
1339
- }
1394
+ if( x==2 ){
1395
+ Blob bad;
1396
+ blob_token(pBlob, &bad);
1397
+ fossil_fatal("the [%s] argument to the \"%s\" command contains "
1398
+ "a character (ascii 0x%02x) that is not allowed in "
1399
+ "filename arguments",
1400
+ zIn, blob_str(&bad), c);
1401
+ }else if( x>2 ){
1402
+ if( (zIn[i+1]&0xc0)!=0x80
1403
+ || (x>=4 && (zIn[i+2]&0xc0)!=0x80)
1404
+ || (x==5 && (zIn[i+3]&0xc0)!=0x80)
1405
+ ){
1406
+ Blob bad;
1407
+ blob_token(pBlob, &bad);
1408
+ fossil_fatal("the [%s] argument to the \"%s\" command contains "
1409
+ "an illegal UTF-8 character",
1410
+ zIn, blob_str(&bad));
1411
+ }
1412
+ i += x-2;
1413
+ }
1414
+ }
13401415
}
1416
+
1417
+ /* Separate from the previous argument by a space */
13411418
if( n>0 && !fossil_isspace(z[n-1]) ){
13421419
blob_append_char(pBlob, ' ');
13431420
}
1344
- if( needEscape ) blob_append_char(pBlob, cQuote);
1345
- if( zIn[0]=='-' ){
1346
- blob_append_char(pBlob, '.');
1347
- blob_append_char(pBlob, cDirSep);
1348
-#if defined(_WIN32)
1349
- }else if( zIn[0]=='/' ){
1350
- blob_append_char(pBlob, '.');
1351
-#endif
1352
- }
1353
-#if defined(_WIN32)
1354
- if( needEscape ){
1355
- for(i=0; (c = zIn[i])!=0; i++){
1356
- if( c==cQuote ) blob_append_char(pBlob, cDirSep);
1357
- blob_append_char(pBlob, c);
1358
- }
1359
- }else{
1360
- blob_append(pBlob, zIn, -1);
1361
- }
1362
-#else
1363
- blob_append(pBlob, zIn, -1);
1364
-#endif
1365
- if( needEscape ){
1366
-#if defined(_WIN32)
1367
- /* NOTE: Trailing backslash must be doubled before final double quote. */
1368
- if( pBlob->aData[pBlob->nUsed-1]==cDirSep ){
1369
- blob_append_char(pBlob, cDirSep);
1370
- }
1371
-#endif
1372
- blob_append_char(pBlob, cQuote);
1421
+
1422
+ /* Check for characters that need quoting */
1423
+ if( !needEscape ){
1424
+ if( isFilename && zIn[0]=='-' ){
1425
+ blob_append_char(pBlob, '.');
1426
+#if defined(_WIN32)
1427
+ blob_append_char(pBlob, '\\');
1428
+#else
1429
+ blob_append_char(pBlob, '/');
1430
+#endif
1431
+ }
1432
+ blob_append(pBlob, zIn, -1);
1433
+ }else{
1434
+#if defined(_WIN32)
1435
+ /* Quoting strategy for windows:
1436
+ ** Put the entire name inside of "...". Any " characters within
1437
+ ** the name get doubled.
1438
+ */
1439
+ blob_append_char(pBlob, '"');
1440
+ if( isFilename && zIn[0]=='-' ){
1441
+ blob_append_char(pBlob, '.');
1442
+ blob_append_char(pBlob, '\\');
1443
+ }else if( zIn[0]=='/' ){
1444
+ blob_append_char(pBlob, '.');
1445
+ }
1446
+ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1447
+ blob_append_char(pBlob, (char)c);
1448
+ if( c=='"' ) blob_append_char(pBlob, '"');
1449
+ }
1450
+ blob_append_char(pBlob, '"');
1451
+#else
1452
+ /* Quoting strategy for unix:
1453
+ ** If the name does not contain ', then surround the whole thing
1454
+ ** with '...'. If there is one or more ' characters within the
1455
+ ** name, then put \ before each special character.
1456
+ */
1457
+ if( strchr(zIn,'\'') ){
1458
+ if( isFilename && zIn[0]=='-' ){
1459
+ blob_append_char(pBlob, '.');
1460
+ blob_append_char(pBlob, '/');
1461
+ }
1462
+ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1463
+ if( aSafeChar[c] && aSafeChar[c]!=2 ) blob_append_char(pBlob, '\\');
1464
+ blob_append_char(pBlob, (char)c);
1465
+ }
1466
+ }else{
1467
+ blob_append_char(pBlob, '\'');
1468
+ if( isFilename && zIn[0]=='-' ){
1469
+ blob_append_char(pBlob, '.');
1470
+ blob_append_char(pBlob, '/');
1471
+ }
1472
+ blob_append(pBlob, zIn, -1);
1473
+ blob_append_char(pBlob, '\'');
1474
+ }
1475
+#endif
13731476
}
13741477
}
13751478
13761479
/*
13771480
** COMMAND: test-escaped-arg
13781481
**
1379
-** Usage %fossil ARG ...
1482
+** Usage %fossil ARGS ...
13801483
**
13811484
** Run each argument through blob_append_escaped_arg() and show the
13821485
** result. Append each argument to "fossil test-echo" and run that
13831486
** using fossil_system() to verify that it really does get escaped
13841487
** correctly.
1488
+**
1489
+** Other options:
1490
+**
1491
+** --filename-args BOOL Subsequent arguments are assumed to be
1492
+** filenames if BOOL is true, or not if BOOL
1493
+** is false. Defaults on.
1494
+**
1495
+** --hex HEX Skip the --hex flag and instead decode HEX
1496
+** into ascii. This provides a way to insert
1497
+** unusual characters as an argument for testing.
1498
+**
1499
+** --compare HEX ASCII Verify that argument ASCII is identical to
1500
+** to decoded HEX.
1501
+**
1502
+** --fuzz N Run N fuzz cases. Each cases is a call
1503
+** to "fossil test-escaped-arg --compare HEX ARG"
1504
+** where HEX and ARG are the same argument.
1505
+** The argument is chosen at random.
13851506
*/
1386
-void test_escaped_arg__cmd(void){
1507
+void test_escaped_arg_command(void){
13871508
int i;
13881509
Blob x;
1510
+ const char *zArg;
1511
+ int isFilename = 1;
1512
+ char zBuf[100];
13891513
blob_init(&x, 0, 0);
13901514
for(i=2; i<g.argc; i++){
1391
- fossil_print("%3d [%s]: ", i, g.argv[i]);
1392
- blob_appendf(&x, "fossil test-echo %$", g.argv[i]);
1515
+ zArg = g.argv[i];
1516
+ if( fossil_strcmp(zArg, "--hex")==0 && i+1<g.argc ){
1517
+ size_t n = strlen(g.argv[++i]);
1518
+ if( n>=(sizeof(zBuf)-1)*2 ){
1519
+ fossil_fatal("Argument to --hex is too big");
1520
+ }
1521
+ memset(zBuf, 0, sizeof(zBuf));
1522
+ decode16((const unsigned char*)g.argv[i], (unsigned char*)zBuf, (int)n);
1523
+ zArg = zBuf;
1524
+ }else if( fossil_strcmp(zArg, "--compare")==0 && i+2<g.argc ){
1525
+ size_t n = strlen(g.argv[++i]);
1526
+ if( n>=(sizeof(zBuf)-1)*2 ){
1527
+ fossil_fatal("HEX argument to --compare is too big");
1528
+ }
1529
+ memset(zBuf, 0, sizeof(zBuf));
1530
+ if( decode16((const unsigned char*)g.argv[i], (unsigned char*)zBuf,
1531
+ (int)n) ){
1532
+ fossil_fatal("HEX decode of %s failed", g.argv[i]);
1533
+ }
1534
+ zArg = g.argv[++i];
1535
+ if( zArg[0]=='-' ){
1536
+ fossil_fatal("filename argument \"%s\" begins with \"-\"", zArg);
1537
+ }
1538
+#ifdef _WIN32
1539
+ if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='\\' ) zArg += 2;
1540
+#else
1541
+ if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='/' ) zArg += 2;
1542
+#endif
1543
+ if( strcmp(zBuf, zArg)!=0 ){
1544
+ fossil_fatal("argument disagree: \"%s\" (%s) versus \"%s\"",
1545
+ zBuf, g.argv[i-1], zArg);
1546
+ }
1547
+ continue;
1548
+ }else if( fossil_strcmp(zArg, "--fuzz")==0 && i+1<g.argc ){
1549
+ int n = atoi(g.argv[++i]);
1550
+ int j;
1551
+ for(j=0; j<n; j++){
1552
+ unsigned char m, k;
1553
+ int rc;
1554
+ unsigned char zWord[100];
1555
+ sqlite3_randomness(sizeof(m), &m);
1556
+ m = (m%40)+5;
1557
+ sqlite3_randomness(m, zWord); /* Between 5 and 45 bytes of randomness */
1558
+ for(k=0; k<m; k++){
1559
+ unsigned char cx = zWord[k];
1560
+ if( cx<0x20 || cx>=0x7f ){
1561
+ /* Translate illegal bytes into various non-ASCII unicode
1562
+ ** characters in order to exercise those code paths */
1563
+ unsigned int u;
1564
+ if( cx>=0x7f ){
1565
+ u = cx;
1566
+ }else if( cx>=0x08 ){
1567
+ u = 0x800 + cx;
1568
+ }else{
1569
+ u = 0x10000 + cx;
1570
+ }
1571
+ if( u<0x00080 ){
1572
+ zWord[k] = u & 0xFF;
1573
+ }else if( u<0x00800 ){
1574
+ zWord[k++] = 0xC0 + (u8)((u>>6)&0x1F);
1575
+ zWord[k] = 0x80 + (u8)(u & 0x3F);
1576
+ }else if( u<0x10000 ){
1577
+ zWord[k++] = 0xE0 + (u8)((u>>12)&0x0F);
1578
+ zWord[k++] = 0x80 + (u8)((u>>6) & 0x3F);
1579
+ zWord[k] = 0x80 + (u8)(u & 0x3F);
1580
+ }else{
1581
+ zWord[k++] = 0xF0 + (u8)((u>>18) & 0x07);
1582
+ zWord[k++] = 0x80 + (u8)((u>>12) & 0x3F);
1583
+ zWord[k++] = 0x80 + (u8)((u>>6) & 0x3F);
1584
+ zWord[k] = 0x80 + (u8)(u & 0x3F);
1585
+ }
1586
+ }
1587
+ }
1588
+ zWord[k] = 0;
1589
+ encode16(zWord, (unsigned char*)zBuf, (int)k);
1590
+ blob_appendf(&x, "%$ test-escaped-arg --compare %s %$",
1591
+ g.nameOfExe, zBuf,zWord);
1592
+ rc = fossil_system(blob_str(&x));
1593
+ if( rc ) fossil_fatal("failed test (%d): %s\n", rc, blob_str(&x));
1594
+ blob_reset(&x);
1595
+ }
1596
+ continue;
1597
+ }else if( fossil_strcmp(zArg, "--filename-args")==0 ){
1598
+ if( i+1<g.argc ){
1599
+ i++;
1600
+ isFilename = is_truth(g.argv[i]);
1601
+ }
1602
+ continue;
1603
+ }
1604
+ fossil_print("%3d [%s]: ", i, zArg);
1605
+ if( isFilename ){
1606
+ blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg);
1607
+ }else{
1608
+ blob_appendf(&x, "%$ test-echo %!$", g.nameOfExe, zArg);
1609
+ }
13931610
fossil_print("%s\n", blob_str(&x));
13941611
fossil_system(blob_str(&x));
13951612
blob_reset(&x);
13961613
}
13971614
}
13981615
--- src/blob.c
+++ src/blob.c
@@ -460,11 +460,11 @@
460 ** Compare a blob to a string. Return TRUE if they are equal.
461 */
462 int blob_eq_str(Blob *pBlob, const char *z, int n){
463 Blob t;
464 blob_is_init(pBlob);
465 if( n<=0 ) n = strlen(z);
466 t.aData = (char*)z;
467 t.nUsed = n;
468 t.xRealloc = blobReallocStatic;
469 return blob_compare(pBlob, &t)==0;
470 }
@@ -474,11 +474,11 @@
474 ** operator on the string constant twice, so it really does need to be a
475 ** string literal or character array - not a character pointer.
476 */
477 #if INTERFACE
478 # define blob_eq(B,S) \
479 ((B)->nUsed==sizeof(S)-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
480 #endif
481
482
483 /*
484 ** Attempt to resize a blob so that its internal buffer is
@@ -1293,105 +1293,322 @@
1293 z[--j] = z[i];
1294 }
1295 }
1296 }
1297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1298 /*
1299 ** pBlob is a shell command under construction. This routine safely
1300 ** appends argument zIn.
1301 **
1302 ** The argument is escaped if it contains white space or other characters
1303 ** that need to be escaped for the shell. If zIn contains characters
1304 ** that cannot be safely escaped, then throw a fatal error.
1305 **
1306 ** The argument is expected to a filename of some kinds. As shell commands
1307 ** commonly have command-line options that begin with "-" and since we
1308 ** do not want an attacker to be able to invoke these switches using
1309 ** filenames that begin with "-", if zIn begins with "-", prepend
1310 ** an additional "./".
 
1311 */
1312 void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
1313 int i;
1314 char c;
1315 int needEscape = 0;
1316 int n = blob_size(pBlob);
1317 char *z = blob_buffer(pBlob);
1318 #if defined(_WIN32)
1319 const char cDirSep = '\\'; /* Use \ as directory separator */
1320 const char cQuote = '"'; /* Use "..." quoting on windows */
1321 const char cEscape = '^'; /* Use ^X escaping on windows */
1322 #else
1323 const char cDirSep = '/'; /* Use / as directory separator */
1324 const char cQuote = '\''; /* Use '...' quoting on unix */
1325 const char cEscape = '\\'; /* Use \X escaping on unix */
1326 #endif
1327
1328 for(i=0; (c = zIn[i])!=0; i++){
1329 if( c==cQuote || (unsigned char)c<' ' ||
1330 c==cEscape || c==';' || c=='*' || c=='?' || c=='[' ){
1331 Blob bad;
1332 blob_token(pBlob, &bad);
1333 fossil_fatal("the [%s] argument to the \"%s\" command contains "
1334 "a character (ascii 0x%02x) that is a security risk",
1335 zIn, blob_str(&bad), c);
1336 }
1337 if( !needEscape && !fossil_isalnum(c) && c!=cDirSep && c!='.' && c!='_' ){
1338 needEscape = 1;
1339 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1340 }
 
 
1341 if( n>0 && !fossil_isspace(z[n-1]) ){
1342 blob_append_char(pBlob, ' ');
1343 }
1344 if( needEscape ) blob_append_char(pBlob, cQuote);
1345 if( zIn[0]=='-' ){
1346 blob_append_char(pBlob, '.');
1347 blob_append_char(pBlob, cDirSep);
1348 #if defined(_WIN32)
1349 }else if( zIn[0]=='/' ){
1350 blob_append_char(pBlob, '.');
1351 #endif
1352 }
1353 #if defined(_WIN32)
1354 if( needEscape ){
1355 for(i=0; (c = zIn[i])!=0; i++){
1356 if( c==cQuote ) blob_append_char(pBlob, cDirSep);
1357 blob_append_char(pBlob, c);
1358 }
1359 }else{
1360 blob_append(pBlob, zIn, -1);
1361 }
1362 #else
1363 blob_append(pBlob, zIn, -1);
1364 #endif
1365 if( needEscape ){
1366 #if defined(_WIN32)
1367 /* NOTE: Trailing backslash must be doubled before final double quote. */
1368 if( pBlob->aData[pBlob->nUsed-1]==cDirSep ){
1369 blob_append_char(pBlob, cDirSep);
1370 }
1371 #endif
1372 blob_append_char(pBlob, cQuote);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1373 }
1374 }
1375
1376 /*
1377 ** COMMAND: test-escaped-arg
1378 **
1379 ** Usage %fossil ARG ...
1380 **
1381 ** Run each argument through blob_append_escaped_arg() and show the
1382 ** result. Append each argument to "fossil test-echo" and run that
1383 ** using fossil_system() to verify that it really does get escaped
1384 ** correctly.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1385 */
1386 void test_escaped_arg__cmd(void){
1387 int i;
1388 Blob x;
 
 
 
1389 blob_init(&x, 0, 0);
1390 for(i=2; i<g.argc; i++){
1391 fossil_print("%3d [%s]: ", i, g.argv[i]);
1392 blob_appendf(&x, "fossil test-echo %$", g.argv[i]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393 fossil_print("%s\n", blob_str(&x));
1394 fossil_system(blob_str(&x));
1395 blob_reset(&x);
1396 }
1397 }
1398
--- src/blob.c
+++ src/blob.c
@@ -460,11 +460,11 @@
460 ** Compare a blob to a string. Return TRUE if they are equal.
461 */
462 int blob_eq_str(Blob *pBlob, const char *z, int n){
463 Blob t;
464 blob_is_init(pBlob);
465 if( n<=0 ) n = (int)strlen(z);
466 t.aData = (char*)z;
467 t.nUsed = n;
468 t.xRealloc = blobReallocStatic;
469 return blob_compare(pBlob, &t)==0;
470 }
@@ -474,11 +474,11 @@
474 ** operator on the string constant twice, so it really does need to be a
475 ** string literal or character array - not a character pointer.
476 */
477 #if INTERFACE
478 # define blob_eq(B,S) \
479 ((B)->nUsed==sizeof(S"")-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
480 #endif
481
482
483 /*
484 ** Attempt to resize a blob so that its internal buffer is
@@ -1293,105 +1293,322 @@
1293 z[--j] = z[i];
1294 }
1295 }
1296 }
1297
1298 /*
1299 ** ASCII (for reference):
1300 ** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
1301 ** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o
1302 ** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^
1303 ** 2x () ! " # $ % & ' ( ) * + , - . /
1304 ** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1305 ** 4x @ A B C D E F G H I J K L M N O
1306 ** 5x P Q R S T U V W X Y Z [ \ ] ^ _
1307 ** 6x ` a b c d e f g h i j k l m n o
1308 ** 7x p q r s t u v w x y z { | } ~ ^_
1309 */
1310
1311 /*
1312 ** Meanings for bytes in a filename:
1313 **
1314 ** 0 Ordinary character. No encoding required
1315 ** 1 Needs to be escaped
1316 ** 2 Illegal character. Do not allow in a filename
1317 ** 3 First byte of a 2-byte UTF-8
1318 ** 4 First byte of a 3-byte UTF-8
1319 ** 5 First byte of a 4-byte UTF-8
1320 */
1321 static const char aSafeChar[256] = {
1322 #ifdef _WIN32
1323 /* Windows
1324 ** Prohibit: all control characters, including tab, \r and \n
1325 ** Escape: (space) " # $ % & ' ( ) * ; < > ? [ ] ^ ` { | }
1326 */
1327 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1328 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1329 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1330 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 2x */
1331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1332 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */
1334 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1336 #else
1337 /* Unix
1338 ** Prohibit: all control characters, including tab, \r and \n
1339 ** Escape: (space) ! " # $ % & ' ( ) * ; < > ? [ \ ] ^ ` { | }
1340 */
1341 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
1342 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */
1343 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */
1344 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 2x */
1345 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */
1346 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
1347 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */
1348 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
1349 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */
1350 #endif
1351 /* all bytes 0x80 through 0xbf are unescaped, being secondary
1352 ** bytes to UTF8 characters. Bytes 0xc0 through 0xff are the
1353 ** first byte of a UTF8 character and do get escaped */
1354 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 8x */
1355 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 9x */
1356 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* ax */
1357 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* bx */
1358 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* cx */
1359 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* dx */
1360 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* ex */
1361 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 /* fx */
1362 };
1363
1364 /*
1365 ** pBlob is a shell command under construction. This routine safely
1366 ** appends filename argument zIn.
1367 **
1368 ** The argument is escaped if it contains white space or other characters
1369 ** that need to be escaped for the shell. If zIn contains characters
1370 ** that cannot be safely escaped, then throw a fatal error.
1371 **
1372 ** If the isFilename argument is true, then the argument is expected
1373 ** to be a filename. As shell commands commonly have command-line
1374 ** options that begin with "-" and since we do not want an attacker
1375 ** to be able to invoke these switches using filenames that begin
1376 ** with "-", if zIn begins with "-", prepend an additional "./"
1377 ** (or ".\\" on Windows).
1378 */
1379 void blob_append_escaped_arg(Blob *pBlob, const char *zIn, int isFilename){
1380 int i;
1381 unsigned char c;
1382 int needEscape = 0;
1383 int n = blob_size(pBlob);
1384 char *z = blob_buffer(pBlob);
1385
1386 /* Look for illegal byte-sequences and byte-sequences that require
1387 ** escaping. No control-characters are allowed. All spaces and
1388 ** non-ASCII unicode characters and some punctuation characters require
1389 ** escaping. */
1390 for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1391 if( aSafeChar[c] ){
1392 unsigned char x = aSafeChar[c];
 
 
 
 
 
 
 
 
 
 
 
 
1393 needEscape = 1;
1394 if( x==2 ){
1395 Blob bad;
1396 blob_token(pBlob, &bad);
1397 fossil_fatal("the [%s] argument to the \"%s\" command contains "
1398 "a character (ascii 0x%02x) that is not allowed in "
1399 "filename arguments",
1400 zIn, blob_str(&bad), c);
1401 }else if( x>2 ){
1402 if( (zIn[i+1]&0xc0)!=0x80
1403 || (x>=4 && (zIn[i+2]&0xc0)!=0x80)
1404 || (x==5 && (zIn[i+3]&0xc0)!=0x80)
1405 ){
1406 Blob bad;
1407 blob_token(pBlob, &bad);
1408 fossil_fatal("the [%s] argument to the \"%s\" command contains "
1409 "an illegal UTF-8 character",
1410 zIn, blob_str(&bad));
1411 }
1412 i += x-2;
1413 }
1414 }
1415 }
1416
1417 /* Separate from the previous argument by a space */
1418 if( n>0 && !fossil_isspace(z[n-1]) ){
1419 blob_append_char(pBlob, ' ');
1420 }
1421
1422 /* Check for characters that need quoting */
1423 if( !needEscape ){
1424 if( isFilename && zIn[0]=='-' ){
1425 blob_append_char(pBlob, '.');
1426 #if defined(_WIN32)
1427 blob_append_char(pBlob, '\\');
1428 #else
1429 blob_append_char(pBlob, '/');
1430 #endif
1431 }
1432 blob_append(pBlob, zIn, -1);
1433 }else{
1434 #if defined(_WIN32)
1435 /* Quoting strategy for windows:
1436 ** Put the entire name inside of "...". Any " characters within
1437 ** the name get doubled.
1438 */
1439 blob_append_char(pBlob, '"');
1440 if( isFilename && zIn[0]=='-' ){
1441 blob_append_char(pBlob, '.');
1442 blob_append_char(pBlob, '\\');
1443 }else if( zIn[0]=='/' ){
1444 blob_append_char(pBlob, '.');
1445 }
1446 for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1447 blob_append_char(pBlob, (char)c);
1448 if( c=='"' ) blob_append_char(pBlob, '"');
1449 }
1450 blob_append_char(pBlob, '"');
1451 #else
1452 /* Quoting strategy for unix:
1453 ** If the name does not contain ', then surround the whole thing
1454 ** with '...'. If there is one or more ' characters within the
1455 ** name, then put \ before each special character.
1456 */
1457 if( strchr(zIn,'\'') ){
1458 if( isFilename && zIn[0]=='-' ){
1459 blob_append_char(pBlob, '.');
1460 blob_append_char(pBlob, '/');
1461 }
1462 for(i=0; (c = (unsigned char)zIn[i])!=0; i++){
1463 if( aSafeChar[c] && aSafeChar[c]!=2 ) blob_append_char(pBlob, '\\');
1464 blob_append_char(pBlob, (char)c);
1465 }
1466 }else{
1467 blob_append_char(pBlob, '\'');
1468 if( isFilename && zIn[0]=='-' ){
1469 blob_append_char(pBlob, '.');
1470 blob_append_char(pBlob, '/');
1471 }
1472 blob_append(pBlob, zIn, -1);
1473 blob_append_char(pBlob, '\'');
1474 }
1475 #endif
1476 }
1477 }
1478
1479 /*
1480 ** COMMAND: test-escaped-arg
1481 **
1482 ** Usage %fossil ARGS ...
1483 **
1484 ** Run each argument through blob_append_escaped_arg() and show the
1485 ** result. Append each argument to "fossil test-echo" and run that
1486 ** using fossil_system() to verify that it really does get escaped
1487 ** correctly.
1488 **
1489 ** Other options:
1490 **
1491 ** --filename-args BOOL Subsequent arguments are assumed to be
1492 ** filenames if BOOL is true, or not if BOOL
1493 ** is false. Defaults on.
1494 **
1495 ** --hex HEX Skip the --hex flag and instead decode HEX
1496 ** into ascii. This provides a way to insert
1497 ** unusual characters as an argument for testing.
1498 **
1499 ** --compare HEX ASCII Verify that argument ASCII is identical to
1500 ** to decoded HEX.
1501 **
1502 ** --fuzz N Run N fuzz cases. Each cases is a call
1503 ** to "fossil test-escaped-arg --compare HEX ARG"
1504 ** where HEX and ARG are the same argument.
1505 ** The argument is chosen at random.
1506 */
1507 void test_escaped_arg_command(void){
1508 int i;
1509 Blob x;
1510 const char *zArg;
1511 int isFilename = 1;
1512 char zBuf[100];
1513 blob_init(&x, 0, 0);
1514 for(i=2; i<g.argc; i++){
1515 zArg = g.argv[i];
1516 if( fossil_strcmp(zArg, "--hex")==0 && i+1<g.argc ){
1517 size_t n = strlen(g.argv[++i]);
1518 if( n>=(sizeof(zBuf)-1)*2 ){
1519 fossil_fatal("Argument to --hex is too big");
1520 }
1521 memset(zBuf, 0, sizeof(zBuf));
1522 decode16((const unsigned char*)g.argv[i], (unsigned char*)zBuf, (int)n);
1523 zArg = zBuf;
1524 }else if( fossil_strcmp(zArg, "--compare")==0 && i+2<g.argc ){
1525 size_t n = strlen(g.argv[++i]);
1526 if( n>=(sizeof(zBuf)-1)*2 ){
1527 fossil_fatal("HEX argument to --compare is too big");
1528 }
1529 memset(zBuf, 0, sizeof(zBuf));
1530 if( decode16((const unsigned char*)g.argv[i], (unsigned char*)zBuf,
1531 (int)n) ){
1532 fossil_fatal("HEX decode of %s failed", g.argv[i]);
1533 }
1534 zArg = g.argv[++i];
1535 if( zArg[0]=='-' ){
1536 fossil_fatal("filename argument \"%s\" begins with \"-\"", zArg);
1537 }
1538 #ifdef _WIN32
1539 if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='\\' ) zArg += 2;
1540 #else
1541 if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='/' ) zArg += 2;
1542 #endif
1543 if( strcmp(zBuf, zArg)!=0 ){
1544 fossil_fatal("argument disagree: \"%s\" (%s) versus \"%s\"",
1545 zBuf, g.argv[i-1], zArg);
1546 }
1547 continue;
1548 }else if( fossil_strcmp(zArg, "--fuzz")==0 && i+1<g.argc ){
1549 int n = atoi(g.argv[++i]);
1550 int j;
1551 for(j=0; j<n; j++){
1552 unsigned char m, k;
1553 int rc;
1554 unsigned char zWord[100];
1555 sqlite3_randomness(sizeof(m), &m);
1556 m = (m%40)+5;
1557 sqlite3_randomness(m, zWord); /* Between 5 and 45 bytes of randomness */
1558 for(k=0; k<m; k++){
1559 unsigned char cx = zWord[k];
1560 if( cx<0x20 || cx>=0x7f ){
1561 /* Translate illegal bytes into various non-ASCII unicode
1562 ** characters in order to exercise those code paths */
1563 unsigned int u;
1564 if( cx>=0x7f ){
1565 u = cx;
1566 }else if( cx>=0x08 ){
1567 u = 0x800 + cx;
1568 }else{
1569 u = 0x10000 + cx;
1570 }
1571 if( u<0x00080 ){
1572 zWord[k] = u & 0xFF;
1573 }else if( u<0x00800 ){
1574 zWord[k++] = 0xC0 + (u8)((u>>6)&0x1F);
1575 zWord[k] = 0x80 + (u8)(u & 0x3F);
1576 }else if( u<0x10000 ){
1577 zWord[k++] = 0xE0 + (u8)((u>>12)&0x0F);
1578 zWord[k++] = 0x80 + (u8)((u>>6) & 0x3F);
1579 zWord[k] = 0x80 + (u8)(u & 0x3F);
1580 }else{
1581 zWord[k++] = 0xF0 + (u8)((u>>18) & 0x07);
1582 zWord[k++] = 0x80 + (u8)((u>>12) & 0x3F);
1583 zWord[k++] = 0x80 + (u8)((u>>6) & 0x3F);
1584 zWord[k] = 0x80 + (u8)(u & 0x3F);
1585 }
1586 }
1587 }
1588 zWord[k] = 0;
1589 encode16(zWord, (unsigned char*)zBuf, (int)k);
1590 blob_appendf(&x, "%$ test-escaped-arg --compare %s %$",
1591 g.nameOfExe, zBuf,zWord);
1592 rc = fossil_system(blob_str(&x));
1593 if( rc ) fossil_fatal("failed test (%d): %s\n", rc, blob_str(&x));
1594 blob_reset(&x);
1595 }
1596 continue;
1597 }else if( fossil_strcmp(zArg, "--filename-args")==0 ){
1598 if( i+1<g.argc ){
1599 i++;
1600 isFilename = is_truth(g.argv[i]);
1601 }
1602 continue;
1603 }
1604 fossil_print("%3d [%s]: ", i, zArg);
1605 if( isFilename ){
1606 blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg);
1607 }else{
1608 blob_appendf(&x, "%$ test-echo %!$", g.nameOfExe, zArg);
1609 }
1610 fossil_print("%s\n", blob_str(&x));
1611 fossil_system(blob_str(&x));
1612 blob_reset(&x);
1613 }
1614 }
1615
+253 -7
--- src/branch.c
+++ src/branch.c
@@ -81,13 +81,18 @@
8181
Manifest *pParent; /* Parsed parent manifest */
8282
Blob mcksum; /* Self-checksum on the manifest */
8383
const char *zDateOvrd; /* Override date string */
8484
const char *zUserOvrd; /* Override user name */
8585
int isPrivate = 0; /* True if the branch should be private */
86
+ int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
8687
8788
noSign = find_option("nosign","",0)!=0;
8889
zColor = find_option("bgcolor","c",1);
90
+ if( fossil_strncmp(zColor, "auto", 4)==0 ) {
91
+ bAutoColor = 1;
92
+ zColor = 0;
93
+ }
8994
isPrivate = find_option("private",0,0)!=0;
9095
zDateOvrd = find_option("date-override",0,1);
9196
zUserOvrd = find_option("user-override",0,1);
9297
verify_all_options();
9398
if( g.argc<5 ){
@@ -151,11 +156,11 @@
151156
manifest_destroy(pParent);
152157
153158
/* Add the symbolic branch name and the "branch" tag to identify
154159
** this as a new branch */
155160
if( content_is_private(rootid) ) isPrivate = 1;
156
- if( isPrivate && zColor==0 ) zColor = "#fec084";
161
+ if( isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
157162
if( zColor!=0 ){
158163
blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
159164
}
160165
blob_appendf(&branch, "T *branch * %F\n", zBranch);
161166
blob_appendf(&branch, "T *sym-%F *\n", zBranch);
@@ -339,22 +344,241 @@
339344
" AND ox.rid=ix.rid)",
340345
TAG_BRANCH, zBrName, TAG_CLOSED
341346
);
342347
}
343348
349
+/*
350
+** Internal helper for branch_cmd_close() and friends. Adds a row to
351
+** the to the brcmdtag TEMP table, initializing that table if needed,
352
+** holding a pending tag for the given blob.rid (which is assumed to
353
+** be valid). zTag must be a fully-formed tag name, including the
354
+** (+,-,*) prefix character.
355
+**
356
+*/
357
+static void branch_cmd_tag_add(int rid, const char *zTag){
358
+ static int once = 0;
359
+ assert(zTag && ('+'==zTag[0] || '-'==zTag[0] || '*'==zTag[0]));
360
+ if(0==once++){
361
+ db_multi_exec("CREATE TEMP TABLE brcmdtag("
362
+ "rid INTEGER UNIQUE ON CONFLICT IGNORE,"
363
+ "tag TEXT NOT NULL"
364
+ ")");
365
+ }
366
+ db_multi_exec("INSERT INTO brcmdtag(rid,tag) VALUES(%d,%Q)",
367
+ rid, zTag);
368
+}
369
+
370
+/*
371
+** Internal helper for branch_cmd_close() and friends. Creates and
372
+** saves a control artifact of tag changes stored via
373
+** branch_cmd_tag_add(). Fails fatally on error, returns 0 if it saves
374
+** an artifact, and a negative value if it does not save anything
375
+** because no tags were queued up. A positive return value is reserved
376
+** for potential future semantics.
377
+**
378
+** This function asserts that a transaction is underway and it ends
379
+** the transaction, committing or rolling back, as appropriate.
380
+*/
381
+static int branch_cmd_tag_finalize(int fDryRun /* roll back if true */,
382
+ int fVerbose /* output extra info */,
383
+ const char *zDateOvrd /* --date-override */,
384
+ const char *zUserOvrd /* --user-override */){
385
+ int nTags = 0;
386
+ Stmt q = empty_Stmt;
387
+ Blob manifest = empty_blob;
388
+ int doRollback = fDryRun!=0;
389
+
390
+ assert(db_transaction_nesting_depth() > 0);
391
+ if(!db_table_exists("temp","brcmdtag")){
392
+ fossil_warning("No tags added - nothing to do.");
393
+ db_end_transaction(1);
394
+ return -1;
395
+ }
396
+ db_prepare(&q, "SELECT b.uuid, t.tag "
397
+ "FROM blob b, brcmdtag t "
398
+ "WHERE b.rid=t.rid "
399
+ "ORDER BY t.tag, b.uuid");
400
+ blob_appendf(&manifest, "D %z\n",
401
+ date_in_standard_format( zDateOvrd ? zDateOvrd : "now"));
402
+ while(SQLITE_ROW==db_step(&q)){
403
+ const char * zHash = db_column_text(&q, 0);
404
+ const char * zTag = db_column_text(&q, 1);
405
+ blob_appendf(&manifest, "T %s %s\n", zTag, zHash);
406
+ ++nTags;
407
+ }
408
+ if(!nTags){
409
+ fossil_warning("No tags added - nothing to do.");
410
+ db_end_transaction(1);
411
+ blob_reset(&manifest);
412
+ return -1;
413
+ }
414
+ user_select();
415
+ blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
416
+ { /* Z-card and save artifact */
417
+ int newRid;
418
+ Blob cksum = empty_blob;
419
+ md5sum_blob(&manifest, &cksum);
420
+ blob_appendf(&manifest, "Z %b\n", &cksum);
421
+ blob_reset(&cksum);
422
+ if(fDryRun && fVerbose){
423
+ fossil_print("Dry-run mode: will roll back new artifact:\n%b",
424
+ &manifest);
425
+ /* Run through the saving steps, though, noting that doing so
426
+ ** will clear out &manifest, which is why we output it here
427
+ ** instead of after saving. */
428
+ }
429
+ newRid = content_put(&manifest);
430
+ if(0==newRid){
431
+ fossil_fatal("Problem saving new artifact: %s\n%b",
432
+ g.zErrMsg, &manifest);
433
+ }else if(manifest_crosslink(newRid, &manifest, 0)==0){
434
+ fossil_fatal("Crosslinking error: %s", g.zErrMsg);
435
+ }
436
+ fossil_print("Saved new control artifact %z (RID %d).\n",
437
+ rid_to_uuid(newRid), newRid);
438
+ db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", newRid);
439
+ if(fDryRun){
440
+ fossil_print("Dry-run mode: rolling back new artifact.\n");
441
+ assert(0!=doRollback);
442
+ }
443
+ }
444
+ db_multi_exec("DROP TABLE brcmdtag");
445
+ blob_reset(&manifest);
446
+ db_end_transaction(doRollback);
447
+ return 0;
448
+}
449
+
450
+/*
451
+** Internal helper for branch_cmd_close() and friends. zName is a
452
+** symbolic checkin name. Returns the blob.rid of the checkin or fails
453
+** fatally if the name does not resolve unambiguously. If zUuid is
454
+** not NULL, *zUuid is set to the resolved blob.uuid and must be freed
455
+** by the caller via fossil_free().
456
+*/
457
+static int branch_resolve_name(char const *zName, char **zUuid){
458
+ const int rid = name_to_uuid2(zName, "ci", zUuid);
459
+ if(0==rid){
460
+ fossil_fatal("Cannot resolve name: %s", zName);
461
+ }else if(rid<0){
462
+ fossil_fatal("Ambiguous name: %s", zName);
463
+ }
464
+ return rid;
465
+}
466
+
467
+/*
468
+** Implementation of (branch hide/unhide) subcommands. nStartAtArg is
469
+** the g.argv index to start reading branch/checkin names. fHide is
470
+** true for hiding, false for unhiding. Fails fatally on error.
471
+*/
472
+static void branch_cmd_hide(int nStartAtArg, int fHide){
473
+ int argPos = nStartAtArg; /* g.argv pos with first branch/ci name */
474
+ char * zUuid = 0; /* Resolved branch UUID. */
475
+ const int fVerbose = find_option("verbose","v",0)!=0;
476
+ const int fDryRun = find_option("dry-run","n",0)!=0;
477
+ const char *zDateOvrd = find_option("date-override",0,1);
478
+ const char *zUserOvrd = find_option("user-override",0,1);
479
+
480
+ verify_all_options();
481
+ db_begin_transaction();
482
+ for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){
483
+ const char * zName = g.argv[argPos];
484
+ const int rid = branch_resolve_name(zName, &zUuid);
485
+ const int isHidden = rid_has_tag(rid, TAG_HIDDEN);
486
+ /* Potential TODO: check for existing 'hidden' flag and skip this
487
+ ** entry if it already has (if fHide) or does not have (if !fHide)
488
+ ** that tag. FWIW, /ci_edit does not do so. */
489
+ if(fHide && isHidden){
490
+ fossil_warning("Skipping hidden checkin %s: %s.", zName, zUuid);
491
+ continue;
492
+ }else if(!fHide && !isHidden){
493
+ fossil_warning("Skipping non-hidden checkin %s: %s.", zName, zUuid);
494
+ continue;
495
+ }
496
+ branch_cmd_tag_add(rid, fHide ? "*hidden" : "-hidden");
497
+ if(fVerbose!=0){
498
+ fossil_print("%s checkin [%s] %s\n",
499
+ fHide ? "Hiding" : "Unhiding",
500
+ zName, zUuid);
501
+ }
502
+ }
503
+ branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd);
504
+}
505
+
506
+/*
507
+** Implementation of (branch close|reopen) subcommands. nStartAtArg is
508
+** the g.argv index to start reading branch/checkin names. The given
509
+** checkins are closed if fClose is true, else their "closed" tag (if
510
+** any) is cancelled. Fails fatally on error.
511
+*/
512
+static void branch_cmd_close(int nStartAtArg, int fClose){
513
+ int argPos = nStartAtArg; /* g.argv pos with first branch name */
514
+ char * zUuid = 0; /* Resolved branch UUID. */
515
+ const int fVerbose = find_option("verbose","v",0)!=0;
516
+ const int fDryRun = find_option("dry-run","n",0)!=0;
517
+ const char *zDateOvrd = find_option("date-override",0,1);
518
+ const char *zUserOvrd = find_option("user-override",0,1);
519
+
520
+ verify_all_options();
521
+ db_begin_transaction();
522
+ for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){
523
+ const char * zName = g.argv[argPos];
524
+ const int rid = branch_resolve_name(zName, &zUuid);
525
+ const int isClosed = leaf_is_closed(rid);
526
+ if(!is_a_leaf(rid)){
527
+ /* This behaviour is different from /ci_edit closing, where
528
+ ** is_a_leaf() adds a "+" tag and !is_a_leaf() adds a "*"
529
+ ** tag. We might want to change this to match for consistency's
530
+ ** sake, but it currently seems unnecessary to close/re-open a
531
+ ** non-leaf. */
532
+ fossil_warning("Skipping non-leaf [%s] %s", zName, zUuid);
533
+ continue;
534
+ }else if(fClose && isClosed){
535
+ fossil_warning("Skipping closed leaf [%s] %s", zName, zUuid);
536
+ continue;
537
+ }else if(!fClose && !isClosed){
538
+ fossil_warning("Skipping non-closed leaf [%s] %s", zName, zUuid);
539
+ continue;
540
+ }
541
+ branch_cmd_tag_add(rid, fClose ? "+closed" : "-closed");
542
+ if(fVerbose!=0){
543
+ fossil_print("%s branch [%s] %s\n",
544
+ fClose ? "Closing" : "Re-opening",
545
+ zName, zUuid);
546
+ }
547
+ }
548
+ branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd);
549
+}
344550
345551
/*
346552
** COMMAND: branch
347553
**
348554
** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
349555
**
350556
** Run various subcommands to manage branches of the open repository or
351557
** of the repository identified by the -R or --repository option.
352558
**
559
+** > fossil branch close|reopen ?OPTIONS? BRANCH-NAME ?...BRANCH-NAMES?
560
+**
561
+** Adds or cancels the "closed" tag to one or more branches.
562
+** It accepts arbitrary unambiguous symbolic names but
563
+** will only resolve checkin names and skips any which resolve
564
+** to non-leaf checkins. Options:
565
+** -n|--dry-run do not commit changes and dump artifact
566
+** to stdout
567
+** -v|--verbose output more information
568
+** --date-override DATE DATE to use instead of 'now'
569
+** --user-override USER USER to use instead of the current default
570
+**
353571
** > fossil branch current
354572
**
355573
** Print the name of the branch for the current check-out
574
+**
575
+** > fossil branch hide|unhide ?OPTIONS? BRANCH-NAME ?...BRANCH-NAMES?
576
+**
577
+** Adds or cancels the "hidden" tag for the specified branches or
578
+** or checkin IDs. Accepts the same options as the close
579
+** subcommand.
356580
**
357581
** > fossil branch info BRANCH-NAME
358582
**
359583
** Print information about a branch
360584
**
@@ -372,15 +596,17 @@
372596
**
373597
** > fossil branch new BRANCH-NAME BASIS ?OPTIONS?
374598
**
375599
** Create a new branch BRANCH-NAME off of check-in BASIS.
376600
** Supported options for this subcommand include:
377
-** --private branch is private (i.e., remains local)
378
-** --bgcolor COLOR use COLOR instead of automatic background
379
-** --nosign do not sign contents on this branch
380
-** --date-override DATE DATE to use instead of 'now'
381
-** --user-override USER USER to use instead of the current default
601
+** --private branch is private (i.e., remains local)
602
+** --bgcolor COLOR use COLOR instead of automatic background
603
+** ("auto" lets Fossil choose it automatically,
604
+** even for private branches)
605
+** --nosign do not sign contents on this branch
606
+** --date-override DATE DATE to use instead of 'now'
607
+** --user-override USER USER to use instead of the current default
382608
**
383609
** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
384610
** year-month-day form, it may be truncated, the "T" may be
385611
** replaced by a space, and it may also name a timezone offset
386612
** from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward).
@@ -445,13 +671,33 @@
445671
fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
446672
}
447673
db_finalize(&q);
448674
}else if( strncmp(zCmd,"new",n)==0 ){
449675
branch_new();
676
+ }else if( strncmp(zCmd,"close",5)==0 ){
677
+ if(g.argc<4){
678
+ usage("branch close branch-name(s)...");
679
+ }
680
+ branch_cmd_close(3, 1);
681
+ }else if( strncmp(zCmd,"reopen",6)==0 ){
682
+ if(g.argc<4){
683
+ usage("branch reopen branch-name(s)...");
684
+ }
685
+ branch_cmd_close(3, 0);
686
+ }else if( strncmp(zCmd,"hide",4)==0 ){
687
+ if(g.argc<4){
688
+ usage("branch hide branch-name(s)...");
689
+ }
690
+ branch_cmd_hide(3,1);
691
+ }else if( strncmp(zCmd,"unhide",6)==0 ){
692
+ if(g.argc<4){
693
+ usage("branch unhide branch-name(s)...");
694
+ }
695
+ branch_cmd_hide(3,0);
450696
}else{
451697
fossil_fatal("branch subcommand should be one of: "
452
- "current info list ls new");
698
+ "close current hide info list ls new reopen unhide");
453699
}
454700
}
455701
456702
/*
457703
** This is the new-style branch-list page that shows the branch names
458704
--- src/branch.c
+++ src/branch.c
@@ -81,13 +81,18 @@
81 Manifest *pParent; /* Parsed parent manifest */
82 Blob mcksum; /* Self-checksum on the manifest */
83 const char *zDateOvrd; /* Override date string */
84 const char *zUserOvrd; /* Override user name */
85 int isPrivate = 0; /* True if the branch should be private */
 
86
87 noSign = find_option("nosign","",0)!=0;
88 zColor = find_option("bgcolor","c",1);
 
 
 
 
89 isPrivate = find_option("private",0,0)!=0;
90 zDateOvrd = find_option("date-override",0,1);
91 zUserOvrd = find_option("user-override",0,1);
92 verify_all_options();
93 if( g.argc<5 ){
@@ -151,11 +156,11 @@
151 manifest_destroy(pParent);
152
153 /* Add the symbolic branch name and the "branch" tag to identify
154 ** this as a new branch */
155 if( content_is_private(rootid) ) isPrivate = 1;
156 if( isPrivate && zColor==0 ) zColor = "#fec084";
157 if( zColor!=0 ){
158 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
159 }
160 blob_appendf(&branch, "T *branch * %F\n", zBranch);
161 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
@@ -339,22 +344,241 @@
339 " AND ox.rid=ix.rid)",
340 TAG_BRANCH, zBrName, TAG_CLOSED
341 );
342 }
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
345 /*
346 ** COMMAND: branch
347 **
348 ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
349 **
350 ** Run various subcommands to manage branches of the open repository or
351 ** of the repository identified by the -R or --repository option.
352 **
 
 
 
 
 
 
 
 
 
 
 
 
353 ** > fossil branch current
354 **
355 ** Print the name of the branch for the current check-out
 
 
 
 
 
 
356 **
357 ** > fossil branch info BRANCH-NAME
358 **
359 ** Print information about a branch
360 **
@@ -372,15 +596,17 @@
372 **
373 ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS?
374 **
375 ** Create a new branch BRANCH-NAME off of check-in BASIS.
376 ** Supported options for this subcommand include:
377 ** --private branch is private (i.e., remains local)
378 ** --bgcolor COLOR use COLOR instead of automatic background
379 ** --nosign do not sign contents on this branch
380 ** --date-override DATE DATE to use instead of 'now'
381 ** --user-override USER USER to use instead of the current default
 
 
382 **
383 ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
384 ** year-month-day form, it may be truncated, the "T" may be
385 ** replaced by a space, and it may also name a timezone offset
386 ** from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward).
@@ -445,13 +671,33 @@
445 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
446 }
447 db_finalize(&q);
448 }else if( strncmp(zCmd,"new",n)==0 ){
449 branch_new();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450 }else{
451 fossil_fatal("branch subcommand should be one of: "
452 "current info list ls new");
453 }
454 }
455
456 /*
457 ** This is the new-style branch-list page that shows the branch names
458
--- src/branch.c
+++ src/branch.c
@@ -81,13 +81,18 @@
81 Manifest *pParent; /* Parsed parent manifest */
82 Blob mcksum; /* Self-checksum on the manifest */
83 const char *zDateOvrd; /* Override date string */
84 const char *zUserOvrd; /* Override user name */
85 int isPrivate = 0; /* True if the branch should be private */
86 int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
87
88 noSign = find_option("nosign","",0)!=0;
89 zColor = find_option("bgcolor","c",1);
90 if( fossil_strncmp(zColor, "auto", 4)==0 ) {
91 bAutoColor = 1;
92 zColor = 0;
93 }
94 isPrivate = find_option("private",0,0)!=0;
95 zDateOvrd = find_option("date-override",0,1);
96 zUserOvrd = find_option("user-override",0,1);
97 verify_all_options();
98 if( g.argc<5 ){
@@ -151,11 +156,11 @@
156 manifest_destroy(pParent);
157
158 /* Add the symbolic branch name and the "branch" tag to identify
159 ** this as a new branch */
160 if( content_is_private(rootid) ) isPrivate = 1;
161 if( isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
162 if( zColor!=0 ){
163 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
164 }
165 blob_appendf(&branch, "T *branch * %F\n", zBranch);
166 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
@@ -339,22 +344,241 @@
344 " AND ox.rid=ix.rid)",
345 TAG_BRANCH, zBrName, TAG_CLOSED
346 );
347 }
348
349 /*
350 ** Internal helper for branch_cmd_close() and friends. Adds a row to
351 ** the to the brcmdtag TEMP table, initializing that table if needed,
352 ** holding a pending tag for the given blob.rid (which is assumed to
353 ** be valid). zTag must be a fully-formed tag name, including the
354 ** (+,-,*) prefix character.
355 **
356 */
357 static void branch_cmd_tag_add(int rid, const char *zTag){
358 static int once = 0;
359 assert(zTag && ('+'==zTag[0] || '-'==zTag[0] || '*'==zTag[0]));
360 if(0==once++){
361 db_multi_exec("CREATE TEMP TABLE brcmdtag("
362 "rid INTEGER UNIQUE ON CONFLICT IGNORE,"
363 "tag TEXT NOT NULL"
364 ")");
365 }
366 db_multi_exec("INSERT INTO brcmdtag(rid,tag) VALUES(%d,%Q)",
367 rid, zTag);
368 }
369
370 /*
371 ** Internal helper for branch_cmd_close() and friends. Creates and
372 ** saves a control artifact of tag changes stored via
373 ** branch_cmd_tag_add(). Fails fatally on error, returns 0 if it saves
374 ** an artifact, and a negative value if it does not save anything
375 ** because no tags were queued up. A positive return value is reserved
376 ** for potential future semantics.
377 **
378 ** This function asserts that a transaction is underway and it ends
379 ** the transaction, committing or rolling back, as appropriate.
380 */
381 static int branch_cmd_tag_finalize(int fDryRun /* roll back if true */,
382 int fVerbose /* output extra info */,
383 const char *zDateOvrd /* --date-override */,
384 const char *zUserOvrd /* --user-override */){
385 int nTags = 0;
386 Stmt q = empty_Stmt;
387 Blob manifest = empty_blob;
388 int doRollback = fDryRun!=0;
389
390 assert(db_transaction_nesting_depth() > 0);
391 if(!db_table_exists("temp","brcmdtag")){
392 fossil_warning("No tags added - nothing to do.");
393 db_end_transaction(1);
394 return -1;
395 }
396 db_prepare(&q, "SELECT b.uuid, t.tag "
397 "FROM blob b, brcmdtag t "
398 "WHERE b.rid=t.rid "
399 "ORDER BY t.tag, b.uuid");
400 blob_appendf(&manifest, "D %z\n",
401 date_in_standard_format( zDateOvrd ? zDateOvrd : "now"));
402 while(SQLITE_ROW==db_step(&q)){
403 const char * zHash = db_column_text(&q, 0);
404 const char * zTag = db_column_text(&q, 1);
405 blob_appendf(&manifest, "T %s %s\n", zTag, zHash);
406 ++nTags;
407 }
408 if(!nTags){
409 fossil_warning("No tags added - nothing to do.");
410 db_end_transaction(1);
411 blob_reset(&manifest);
412 return -1;
413 }
414 user_select();
415 blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
416 { /* Z-card and save artifact */
417 int newRid;
418 Blob cksum = empty_blob;
419 md5sum_blob(&manifest, &cksum);
420 blob_appendf(&manifest, "Z %b\n", &cksum);
421 blob_reset(&cksum);
422 if(fDryRun && fVerbose){
423 fossil_print("Dry-run mode: will roll back new artifact:\n%b",
424 &manifest);
425 /* Run through the saving steps, though, noting that doing so
426 ** will clear out &manifest, which is why we output it here
427 ** instead of after saving. */
428 }
429 newRid = content_put(&manifest);
430 if(0==newRid){
431 fossil_fatal("Problem saving new artifact: %s\n%b",
432 g.zErrMsg, &manifest);
433 }else if(manifest_crosslink(newRid, &manifest, 0)==0){
434 fossil_fatal("Crosslinking error: %s", g.zErrMsg);
435 }
436 fossil_print("Saved new control artifact %z (RID %d).\n",
437 rid_to_uuid(newRid), newRid);
438 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", newRid);
439 if(fDryRun){
440 fossil_print("Dry-run mode: rolling back new artifact.\n");
441 assert(0!=doRollback);
442 }
443 }
444 db_multi_exec("DROP TABLE brcmdtag");
445 blob_reset(&manifest);
446 db_end_transaction(doRollback);
447 return 0;
448 }
449
450 /*
451 ** Internal helper for branch_cmd_close() and friends. zName is a
452 ** symbolic checkin name. Returns the blob.rid of the checkin or fails
453 ** fatally if the name does not resolve unambiguously. If zUuid is
454 ** not NULL, *zUuid is set to the resolved blob.uuid and must be freed
455 ** by the caller via fossil_free().
456 */
457 static int branch_resolve_name(char const *zName, char **zUuid){
458 const int rid = name_to_uuid2(zName, "ci", zUuid);
459 if(0==rid){
460 fossil_fatal("Cannot resolve name: %s", zName);
461 }else if(rid<0){
462 fossil_fatal("Ambiguous name: %s", zName);
463 }
464 return rid;
465 }
466
467 /*
468 ** Implementation of (branch hide/unhide) subcommands. nStartAtArg is
469 ** the g.argv index to start reading branch/checkin names. fHide is
470 ** true for hiding, false for unhiding. Fails fatally on error.
471 */
472 static void branch_cmd_hide(int nStartAtArg, int fHide){
473 int argPos = nStartAtArg; /* g.argv pos with first branch/ci name */
474 char * zUuid = 0; /* Resolved branch UUID. */
475 const int fVerbose = find_option("verbose","v",0)!=0;
476 const int fDryRun = find_option("dry-run","n",0)!=0;
477 const char *zDateOvrd = find_option("date-override",0,1);
478 const char *zUserOvrd = find_option("user-override",0,1);
479
480 verify_all_options();
481 db_begin_transaction();
482 for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){
483 const char * zName = g.argv[argPos];
484 const int rid = branch_resolve_name(zName, &zUuid);
485 const int isHidden = rid_has_tag(rid, TAG_HIDDEN);
486 /* Potential TODO: check for existing 'hidden' flag and skip this
487 ** entry if it already has (if fHide) or does not have (if !fHide)
488 ** that tag. FWIW, /ci_edit does not do so. */
489 if(fHide && isHidden){
490 fossil_warning("Skipping hidden checkin %s: %s.", zName, zUuid);
491 continue;
492 }else if(!fHide && !isHidden){
493 fossil_warning("Skipping non-hidden checkin %s: %s.", zName, zUuid);
494 continue;
495 }
496 branch_cmd_tag_add(rid, fHide ? "*hidden" : "-hidden");
497 if(fVerbose!=0){
498 fossil_print("%s checkin [%s] %s\n",
499 fHide ? "Hiding" : "Unhiding",
500 zName, zUuid);
501 }
502 }
503 branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd);
504 }
505
506 /*
507 ** Implementation of (branch close|reopen) subcommands. nStartAtArg is
508 ** the g.argv index to start reading branch/checkin names. The given
509 ** checkins are closed if fClose is true, else their "closed" tag (if
510 ** any) is cancelled. Fails fatally on error.
511 */
512 static void branch_cmd_close(int nStartAtArg, int fClose){
513 int argPos = nStartAtArg; /* g.argv pos with first branch name */
514 char * zUuid = 0; /* Resolved branch UUID. */
515 const int fVerbose = find_option("verbose","v",0)!=0;
516 const int fDryRun = find_option("dry-run","n",0)!=0;
517 const char *zDateOvrd = find_option("date-override",0,1);
518 const char *zUserOvrd = find_option("user-override",0,1);
519
520 verify_all_options();
521 db_begin_transaction();
522 for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){
523 const char * zName = g.argv[argPos];
524 const int rid = branch_resolve_name(zName, &zUuid);
525 const int isClosed = leaf_is_closed(rid);
526 if(!is_a_leaf(rid)){
527 /* This behaviour is different from /ci_edit closing, where
528 ** is_a_leaf() adds a "+" tag and !is_a_leaf() adds a "*"
529 ** tag. We might want to change this to match for consistency's
530 ** sake, but it currently seems unnecessary to close/re-open a
531 ** non-leaf. */
532 fossil_warning("Skipping non-leaf [%s] %s", zName, zUuid);
533 continue;
534 }else if(fClose && isClosed){
535 fossil_warning("Skipping closed leaf [%s] %s", zName, zUuid);
536 continue;
537 }else if(!fClose && !isClosed){
538 fossil_warning("Skipping non-closed leaf [%s] %s", zName, zUuid);
539 continue;
540 }
541 branch_cmd_tag_add(rid, fClose ? "+closed" : "-closed");
542 if(fVerbose!=0){
543 fossil_print("%s branch [%s] %s\n",
544 fClose ? "Closing" : "Re-opening",
545 zName, zUuid);
546 }
547 }
548 branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd);
549 }
550
551 /*
552 ** COMMAND: branch
553 **
554 ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
555 **
556 ** Run various subcommands to manage branches of the open repository or
557 ** of the repository identified by the -R or --repository option.
558 **
559 ** > fossil branch close|reopen ?OPTIONS? BRANCH-NAME ?...BRANCH-NAMES?
560 **
561 ** Adds or cancels the "closed" tag to one or more branches.
562 ** It accepts arbitrary unambiguous symbolic names but
563 ** will only resolve checkin names and skips any which resolve
564 ** to non-leaf checkins. Options:
565 ** -n|--dry-run do not commit changes and dump artifact
566 ** to stdout
567 ** -v|--verbose output more information
568 ** --date-override DATE DATE to use instead of 'now'
569 ** --user-override USER USER to use instead of the current default
570 **
571 ** > fossil branch current
572 **
573 ** Print the name of the branch for the current check-out
574 **
575 ** > fossil branch hide|unhide ?OPTIONS? BRANCH-NAME ?...BRANCH-NAMES?
576 **
577 ** Adds or cancels the "hidden" tag for the specified branches or
578 ** or checkin IDs. Accepts the same options as the close
579 ** subcommand.
580 **
581 ** > fossil branch info BRANCH-NAME
582 **
583 ** Print information about a branch
584 **
@@ -372,15 +596,17 @@
596 **
597 ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS?
598 **
599 ** Create a new branch BRANCH-NAME off of check-in BASIS.
600 ** Supported options for this subcommand include:
601 ** --private branch is private (i.e., remains local)
602 ** --bgcolor COLOR use COLOR instead of automatic background
603 ** ("auto" lets Fossil choose it automatically,
604 ** even for private branches)
605 ** --nosign do not sign contents on this branch
606 ** --date-override DATE DATE to use instead of 'now'
607 ** --user-override USER USER to use instead of the current default
608 **
609 ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
610 ** year-month-day form, it may be truncated, the "T" may be
611 ** replaced by a space, and it may also name a timezone offset
612 ** from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward).
@@ -445,13 +671,33 @@
671 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
672 }
673 db_finalize(&q);
674 }else if( strncmp(zCmd,"new",n)==0 ){
675 branch_new();
676 }else if( strncmp(zCmd,"close",5)==0 ){
677 if(g.argc<4){
678 usage("branch close branch-name(s)...");
679 }
680 branch_cmd_close(3, 1);
681 }else if( strncmp(zCmd,"reopen",6)==0 ){
682 if(g.argc<4){
683 usage("branch reopen branch-name(s)...");
684 }
685 branch_cmd_close(3, 0);
686 }else if( strncmp(zCmd,"hide",4)==0 ){
687 if(g.argc<4){
688 usage("branch hide branch-name(s)...");
689 }
690 branch_cmd_hide(3,1);
691 }else if( strncmp(zCmd,"unhide",6)==0 ){
692 if(g.argc<4){
693 usage("branch unhide branch-name(s)...");
694 }
695 branch_cmd_hide(3,0);
696 }else{
697 fossil_fatal("branch subcommand should be one of: "
698 "close current hide info list ls new reopen unhide");
699 }
700 }
701
702 /*
703 ** This is the new-style branch-list page that shows the branch names
704
+83 -17
--- src/cache.c
+++ src/cache.c
@@ -197,10 +197,17 @@
197197
sqlite3_finalize(pStmt);
198198
sqlite3_exec(db, rc ? "COMMIT" : "ROLLBACK", 0, 0, 0);
199199
sqlite3_close(db);
200200
}
201201
202
+/*
203
+** SETTING: max-cache-entry width=10 default=10
204
+**
205
+** This is the maximum number of entries to allow in the web-cache
206
+** for tarballs, ZIP-archives, and SQL-archives.
207
+*/
208
+
202209
/*
203210
** Attempt to read content out of the cache with the given zKey. Return
204211
** non-zero on success and zero if unable to locate the content.
205212
**
206213
** Possible reasons for returning zero:
@@ -262,10 +269,12 @@
262269
** init Create the cache file if it does not already exist.
263270
**
264271
** list|ls List the keys and content sizes and other stats for
265272
** all entries currently in the cache.
266273
**
274
+** size ?N? Query or set the maximum number of entries in the cache.
275
+**
267276
** status Show a summary of the cache status.
268277
**
269278
** The cache is stored in a file that is distinct from the repository
270279
** but that is held in the same directory as the repository. The cache
271280
** file can be deleted in order to completely disable the cache.
@@ -303,12 +312,14 @@
303312
sqlite3_close(db);
304313
fossil_print("cache cleared\n");
305314
}else{
306315
fossil_print("nothing to clear; cache does not exist\n");
307316
}
308
- }else if(( strncmp(zCmd, "list", nCmd)==0 )
309
- || ( strncmp(zCmd, "ls", nCmd)==0 )){
317
+ }else if( strncmp(zCmd, "list", nCmd)==0
318
+ || strncmp(zCmd, "ls", nCmd)==0
319
+ || strncmp(zCmd, "status", nCmd)==0
320
+ ){
310321
db = cacheOpen(0);
311322
if( db==0 ){
312323
fossil_print("cache does not exist\n");
313324
}else{
314325
int nEntry = 0;
@@ -319,31 +330,72 @@
319330
" FROM cache"
320331
" ORDER BY tm DESC"
321332
);
322333
if( pStmt ){
323334
while( sqlite3_step(pStmt)==SQLITE_ROW ){
324
- fossil_print("%s %4d %8s %s\n",
325
- sqlite3_column_text(pStmt, 3),
326
- sqlite3_column_int(pStmt, 2),
327
- sqlite3_column_text(pStmt, 1),
328
- sqlite3_column_text(pStmt, 0));
335
+ if( zCmd[0]=='l' ){
336
+ fossil_print("%s %4d %8s %s\n",
337
+ sqlite3_column_text(pStmt, 3),
338
+ sqlite3_column_int(pStmt, 2),
339
+ sqlite3_column_text(pStmt, 1),
340
+ sqlite3_column_text(pStmt, 0));
341
+ }
329342
nEntry++;
330343
}
331344
sqlite3_finalize(pStmt);
332345
}
333346
sqlite3_close(db);
334
- fossil_print("Entries: %d Cache-file Size: %lld\n",
335
- nEntry, file_size(zDbName, ExtFILE));
347
+ fossil_print(
348
+ "Filename: %s\n"
349
+ "Entries: %d\n"
350
+ "max-cache-entry: %d\n"
351
+ "Cache-file Size: %,lld\n",
352
+ zDbName,
353
+ nEntry,
354
+ db_get_int("max-cache-entry",10),
355
+ file_size(zDbName, ExtFILE)
356
+ );
336357
fossil_free(zDbName);
337358
}
338
- }else if( strncmp(zCmd, "status", nCmd)==0 ){
339
- fossil_print("TBD...\n");
359
+ }else if( strncmp(zCmd, "size", nCmd)==0 ){
360
+ if( g.argc>=4 ){
361
+ int n = atoi(g.argv[3]);
362
+ if( n>=5 ) db_set_int("max-cache-entry",n,0);
363
+ }
364
+ fossil_print("max-cache-entry: %d\n", db_get_int("max-cache-entry",10));
340365
}else{
341366
fossil_fatal("Unknown subcommand \"%s\"."
342
- " Should be one of: clear init list status", zCmd);
367
+ " Should be one of: clear init list size status", zCmd);
343368
}
344369
}
370
+
371
+/*
372
+** Given a cache key, find the check-in hash and return it as a separate
373
+** string. The returned string is obtained from fossil_malloc() and must
374
+** be freed by the caller.
375
+**
376
+** Return NULL if not found.
377
+**
378
+** The key is usually in a format like these:
379
+**
380
+** /tarball/HASH/NAME
381
+** /zip/HASH/NAME
382
+** /sqlar/HASH/NAME
383
+*/
384
+static char *cache_hash_of_key(const char *zKey){
385
+ int i;
386
+ if( zKey==0 ) return 0;
387
+ if( zKey[0]!='/' ) return 0;
388
+ zKey++;
389
+ while( zKey[0] && zKey[0]!='/' ) zKey++;
390
+ if( zKey[0]==0 ) return 0;
391
+ zKey++;
392
+ for(i=0; zKey[i] && zKey[i]!='/'; i++){}
393
+ if( !validate16(zKey, i) ) return 0;
394
+ return fossil_strndup(zKey, i);
395
+}
396
+
345397
346398
/*
347399
** WEBPAGE: cachestat
348400
**
349401
** Show information about the webpage cache. Requires Setup privilege.
@@ -362,30 +414,44 @@
362414
@ The web-page cache is disabled for this repository
363415
}else{
364416
char *zDbName = cacheName();
365417
cache_register_sizename(db);
366418
pStmt = cacheStmt(db,
367
- "SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')"
419
+ "SELECT key, sz, nRef, datetime(tm,'unixepoch')"
368420
" FROM cache"
369421
" ORDER BY (tm + 3600*min(nRef,48)) DESC"
370422
);
371423
if( pStmt ){
372424
@ <ol>
373425
while( sqlite3_step(pStmt)==SQLITE_ROW ){
374426
const unsigned char *zName = sqlite3_column_text(pStmt,0);
427
+ char *zHash = cache_hash_of_key((const char*)zName);
375428
@ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br />
376
- @ size: %s(sqlite3_column_text(pStmt,1))
429
+ @ size: %,lld(sqlite3_column_int64(pStmt,1))
377430
@ hit-count: %d(sqlite3_column_int(pStmt,2))
378
- @ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
431
+ @ last-access: %s(sqlite3_column_text(pStmt,3)) \
432
+ if( zHash ){
433
+ @ %z(href("%R/timeline?c=%S",zHash))check-in</a>\
434
+ fossil_free(zHash);
435
+ }
436
+ @ </p></li>
437
+
379438
}
380439
sqlite3_finalize(pStmt);
381440
@ </ol>
382441
}
383442
zDbName = cacheName();
384443
bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName, ExtFILE));
385
- @ <p>cache-file name: %h(zDbName)</p>
386
- @ <p>cache-file size: %s(zBuf)</p>
444
+ @ <p>
445
+ @ cache-file name: %h(zDbName)<br>
446
+ @ cache-file size: %s(zBuf)<br>
447
+ @ max-cache-entry: %d(db_get_int("max-cache-entry",10))
448
+ @ </p>
449
+ @ <p>
450
+ @ Use the "<a href="%R/help?cmd=cache">fossil cache</a>" command
451
+ @ on the command-line to create and configure the web-cache.
452
+ @ </p>
387453
fossil_free(zDbName);
388454
sqlite3_close(db);
389455
}
390456
style_finish_page();
391457
}
392458
--- src/cache.c
+++ src/cache.c
@@ -197,10 +197,17 @@
197 sqlite3_finalize(pStmt);
198 sqlite3_exec(db, rc ? "COMMIT" : "ROLLBACK", 0, 0, 0);
199 sqlite3_close(db);
200 }
201
 
 
 
 
 
 
 
202 /*
203 ** Attempt to read content out of the cache with the given zKey. Return
204 ** non-zero on success and zero if unable to locate the content.
205 **
206 ** Possible reasons for returning zero:
@@ -262,10 +269,12 @@
262 ** init Create the cache file if it does not already exist.
263 **
264 ** list|ls List the keys and content sizes and other stats for
265 ** all entries currently in the cache.
266 **
 
 
267 ** status Show a summary of the cache status.
268 **
269 ** The cache is stored in a file that is distinct from the repository
270 ** but that is held in the same directory as the repository. The cache
271 ** file can be deleted in order to completely disable the cache.
@@ -303,12 +312,14 @@
303 sqlite3_close(db);
304 fossil_print("cache cleared\n");
305 }else{
306 fossil_print("nothing to clear; cache does not exist\n");
307 }
308 }else if(( strncmp(zCmd, "list", nCmd)==0 )
309 || ( strncmp(zCmd, "ls", nCmd)==0 )){
 
 
310 db = cacheOpen(0);
311 if( db==0 ){
312 fossil_print("cache does not exist\n");
313 }else{
314 int nEntry = 0;
@@ -319,31 +330,72 @@
319 " FROM cache"
320 " ORDER BY tm DESC"
321 );
322 if( pStmt ){
323 while( sqlite3_step(pStmt)==SQLITE_ROW ){
324 fossil_print("%s %4d %8s %s\n",
325 sqlite3_column_text(pStmt, 3),
326 sqlite3_column_int(pStmt, 2),
327 sqlite3_column_text(pStmt, 1),
328 sqlite3_column_text(pStmt, 0));
 
 
329 nEntry++;
330 }
331 sqlite3_finalize(pStmt);
332 }
333 sqlite3_close(db);
334 fossil_print("Entries: %d Cache-file Size: %lld\n",
335 nEntry, file_size(zDbName, ExtFILE));
 
 
 
 
 
 
 
 
336 fossil_free(zDbName);
337 }
338 }else if( strncmp(zCmd, "status", nCmd)==0 ){
339 fossil_print("TBD...\n");
 
 
 
 
340 }else{
341 fossil_fatal("Unknown subcommand \"%s\"."
342 " Should be one of: clear init list status", zCmd);
343 }
344 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
346 /*
347 ** WEBPAGE: cachestat
348 **
349 ** Show information about the webpage cache. Requires Setup privilege.
@@ -362,30 +414,44 @@
362 @ The web-page cache is disabled for this repository
363 }else{
364 char *zDbName = cacheName();
365 cache_register_sizename(db);
366 pStmt = cacheStmt(db,
367 "SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')"
368 " FROM cache"
369 " ORDER BY (tm + 3600*min(nRef,48)) DESC"
370 );
371 if( pStmt ){
372 @ <ol>
373 while( sqlite3_step(pStmt)==SQLITE_ROW ){
374 const unsigned char *zName = sqlite3_column_text(pStmt,0);
 
375 @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br />
376 @ size: %s(sqlite3_column_text(pStmt,1))
377 @ hit-count: %d(sqlite3_column_int(pStmt,2))
378 @ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
 
 
 
 
 
 
379 }
380 sqlite3_finalize(pStmt);
381 @ </ol>
382 }
383 zDbName = cacheName();
384 bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName, ExtFILE));
385 @ <p>cache-file name: %h(zDbName)</p>
386 @ <p>cache-file size: %s(zBuf)</p>
 
 
 
 
 
 
 
387 fossil_free(zDbName);
388 sqlite3_close(db);
389 }
390 style_finish_page();
391 }
392
--- src/cache.c
+++ src/cache.c
@@ -197,10 +197,17 @@
197 sqlite3_finalize(pStmt);
198 sqlite3_exec(db, rc ? "COMMIT" : "ROLLBACK", 0, 0, 0);
199 sqlite3_close(db);
200 }
201
202 /*
203 ** SETTING: max-cache-entry width=10 default=10
204 **
205 ** This is the maximum number of entries to allow in the web-cache
206 ** for tarballs, ZIP-archives, and SQL-archives.
207 */
208
209 /*
210 ** Attempt to read content out of the cache with the given zKey. Return
211 ** non-zero on success and zero if unable to locate the content.
212 **
213 ** Possible reasons for returning zero:
@@ -262,10 +269,12 @@
269 ** init Create the cache file if it does not already exist.
270 **
271 ** list|ls List the keys and content sizes and other stats for
272 ** all entries currently in the cache.
273 **
274 ** size ?N? Query or set the maximum number of entries in the cache.
275 **
276 ** status Show a summary of the cache status.
277 **
278 ** The cache is stored in a file that is distinct from the repository
279 ** but that is held in the same directory as the repository. The cache
280 ** file can be deleted in order to completely disable the cache.
@@ -303,12 +312,14 @@
312 sqlite3_close(db);
313 fossil_print("cache cleared\n");
314 }else{
315 fossil_print("nothing to clear; cache does not exist\n");
316 }
317 }else if( strncmp(zCmd, "list", nCmd)==0
318 || strncmp(zCmd, "ls", nCmd)==0
319 || strncmp(zCmd, "status", nCmd)==0
320 ){
321 db = cacheOpen(0);
322 if( db==0 ){
323 fossil_print("cache does not exist\n");
324 }else{
325 int nEntry = 0;
@@ -319,31 +330,72 @@
330 " FROM cache"
331 " ORDER BY tm DESC"
332 );
333 if( pStmt ){
334 while( sqlite3_step(pStmt)==SQLITE_ROW ){
335 if( zCmd[0]=='l' ){
336 fossil_print("%s %4d %8s %s\n",
337 sqlite3_column_text(pStmt, 3),
338 sqlite3_column_int(pStmt, 2),
339 sqlite3_column_text(pStmt, 1),
340 sqlite3_column_text(pStmt, 0));
341 }
342 nEntry++;
343 }
344 sqlite3_finalize(pStmt);
345 }
346 sqlite3_close(db);
347 fossil_print(
348 "Filename: %s\n"
349 "Entries: %d\n"
350 "max-cache-entry: %d\n"
351 "Cache-file Size: %,lld\n",
352 zDbName,
353 nEntry,
354 db_get_int("max-cache-entry",10),
355 file_size(zDbName, ExtFILE)
356 );
357 fossil_free(zDbName);
358 }
359 }else if( strncmp(zCmd, "size", nCmd)==0 ){
360 if( g.argc>=4 ){
361 int n = atoi(g.argv[3]);
362 if( n>=5 ) db_set_int("max-cache-entry",n,0);
363 }
364 fossil_print("max-cache-entry: %d\n", db_get_int("max-cache-entry",10));
365 }else{
366 fossil_fatal("Unknown subcommand \"%s\"."
367 " Should be one of: clear init list size status", zCmd);
368 }
369 }
370
371 /*
372 ** Given a cache key, find the check-in hash and return it as a separate
373 ** string. The returned string is obtained from fossil_malloc() and must
374 ** be freed by the caller.
375 **
376 ** Return NULL if not found.
377 **
378 ** The key is usually in a format like these:
379 **
380 ** /tarball/HASH/NAME
381 ** /zip/HASH/NAME
382 ** /sqlar/HASH/NAME
383 */
384 static char *cache_hash_of_key(const char *zKey){
385 int i;
386 if( zKey==0 ) return 0;
387 if( zKey[0]!='/' ) return 0;
388 zKey++;
389 while( zKey[0] && zKey[0]!='/' ) zKey++;
390 if( zKey[0]==0 ) return 0;
391 zKey++;
392 for(i=0; zKey[i] && zKey[i]!='/'; i++){}
393 if( !validate16(zKey, i) ) return 0;
394 return fossil_strndup(zKey, i);
395 }
396
397
398 /*
399 ** WEBPAGE: cachestat
400 **
401 ** Show information about the webpage cache. Requires Setup privilege.
@@ -362,30 +414,44 @@
414 @ The web-page cache is disabled for this repository
415 }else{
416 char *zDbName = cacheName();
417 cache_register_sizename(db);
418 pStmt = cacheStmt(db,
419 "SELECT key, sz, nRef, datetime(tm,'unixepoch')"
420 " FROM cache"
421 " ORDER BY (tm + 3600*min(nRef,48)) DESC"
422 );
423 if( pStmt ){
424 @ <ol>
425 while( sqlite3_step(pStmt)==SQLITE_ROW ){
426 const unsigned char *zName = sqlite3_column_text(pStmt,0);
427 char *zHash = cache_hash_of_key((const char*)zName);
428 @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br />
429 @ size: %,lld(sqlite3_column_int64(pStmt,1))
430 @ hit-count: %d(sqlite3_column_int(pStmt,2))
431 @ last-access: %s(sqlite3_column_text(pStmt,3)) \
432 if( zHash ){
433 @ %z(href("%R/timeline?c=%S",zHash))check-in</a>\
434 fossil_free(zHash);
435 }
436 @ </p></li>
437
438 }
439 sqlite3_finalize(pStmt);
440 @ </ol>
441 }
442 zDbName = cacheName();
443 bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName, ExtFILE));
444 @ <p>
445 @ cache-file name: %h(zDbName)<br>
446 @ cache-file size: %s(zBuf)<br>
447 @ max-cache-entry: %d(db_get_int("max-cache-entry",10))
448 @ </p>
449 @ <p>
450 @ Use the "<a href="%R/help?cmd=cache">fossil cache</a>" command
451 @ on the command-line to create and configure the web-cache.
452 @ </p>
453 fossil_free(zDbName);
454 sqlite3_close(db);
455 }
456 style_finish_page();
457 }
458
+20 -1
--- src/cgi.c
+++ src/cgi.c
@@ -313,11 +313,11 @@
313313
cgi_rfc822_datestamp(etag_mtime()));
314314
}
315315
}else if( g.isConst ){
316316
/* isConst means that the reply is guaranteed to be invariant, even
317317
** after configuration changes and/or Fossil binary recompiles. */
318
- fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
318
+ fprintf(g.httpOut, "Cache-Control: max-age=315360000, immutable\r\n");
319319
}else{
320320
fprintf(g.httpOut, "Cache-control: no-cache\r\n");
321321
}
322322
323323
if( blob_size(&extraHeader)>0 ){
@@ -1321,10 +1321,29 @@
13211321
}
13221322
}
13231323
CGIDEBUG(("no-match [%s]\n", zName));
13241324
return zDefault;
13251325
}
1326
+
1327
+/*
1328
+** Return the value of the first defined query parameter or cookie whose
1329
+** name appears in the list of arguments. Or if no parameter is found,
1330
+** return NULL.
1331
+*/
1332
+const char *cgi_coalesce(const char *zName, ...){
1333
+ va_list ap;
1334
+ const char *z;
1335
+ const char *zX;
1336
+ if( zName==0 ) return 0;
1337
+ z = cgi_parameter(zName, 0);
1338
+ va_start(ap, zName);
1339
+ while( z==0 && (zX = va_arg(ap,const char*))!=0 ){
1340
+ z = cgi_parameter(zX, 0);
1341
+ }
1342
+ va_end(ap);
1343
+ return z;
1344
+}
13261345
13271346
/*
13281347
** Return the value of a CGI parameter with leading and trailing
13291348
** spaces removed and with internal \r\n changed to just \n
13301349
*/
13311350
--- src/cgi.c
+++ src/cgi.c
@@ -313,11 +313,11 @@
313 cgi_rfc822_datestamp(etag_mtime()));
314 }
315 }else if( g.isConst ){
316 /* isConst means that the reply is guaranteed to be invariant, even
317 ** after configuration changes and/or Fossil binary recompiles. */
318 fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
319 }else{
320 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
321 }
322
323 if( blob_size(&extraHeader)>0 ){
@@ -1321,10 +1321,29 @@
1321 }
1322 }
1323 CGIDEBUG(("no-match [%s]\n", zName));
1324 return zDefault;
1325 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1326
1327 /*
1328 ** Return the value of a CGI parameter with leading and trailing
1329 ** spaces removed and with internal \r\n changed to just \n
1330 */
1331
--- src/cgi.c
+++ src/cgi.c
@@ -313,11 +313,11 @@
313 cgi_rfc822_datestamp(etag_mtime()));
314 }
315 }else if( g.isConst ){
316 /* isConst means that the reply is guaranteed to be invariant, even
317 ** after configuration changes and/or Fossil binary recompiles. */
318 fprintf(g.httpOut, "Cache-Control: max-age=315360000, immutable\r\n");
319 }else{
320 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
321 }
322
323 if( blob_size(&extraHeader)>0 ){
@@ -1321,10 +1321,29 @@
1321 }
1322 }
1323 CGIDEBUG(("no-match [%s]\n", zName));
1324 return zDefault;
1325 }
1326
1327 /*
1328 ** Return the value of the first defined query parameter or cookie whose
1329 ** name appears in the list of arguments. Or if no parameter is found,
1330 ** return NULL.
1331 */
1332 const char *cgi_coalesce(const char *zName, ...){
1333 va_list ap;
1334 const char *z;
1335 const char *zX;
1336 if( zName==0 ) return 0;
1337 z = cgi_parameter(zName, 0);
1338 va_start(ap, zName);
1339 while( z==0 && (zX = va_arg(ap,const char*))!=0 ){
1340 z = cgi_parameter(zX, 0);
1341 }
1342 va_end(ap);
1343 return z;
1344 }
1345
1346 /*
1347 ** Return the value of a CGI parameter with leading and trailing
1348 ** spaces removed and with internal \r\n changed to just \n
1349 */
1350
+10 -1
--- src/checkin.c
+++ src/checkin.c
@@ -2127,10 +2127,12 @@
21272127
** --allow-older allow a commit older than its ancestor
21282128
** --baseline use a baseline manifest in the commit process
21292129
** --bgcolor COLOR apply COLOR to this one check-in only
21302130
** --branch NEW-BRANCH-NAME check in to this new branch
21312131
** --branchcolor COLOR apply given COLOR to the branch
2132
+** ("auto" lets Fossil choose it automatically,
2133
+** even for private branches)
21322134
** --close close the branch being committed
21332135
** --date-override DATETIME DATE to use instead of 'now'
21342136
** --delta use a delta manifest in the commit process
21352137
** --hash verify file status using hashing rather
21362138
** than relying on file mtimes
@@ -2204,10 +2206,11 @@
22042206
int nConflict = 0; /* Number of unresolved merge conflicts */
22052207
int abortCommit = 0; /* Abort the commit due to text format conversions */
22062208
Blob ans; /* Answer to continuation prompts */
22072209
char cReply; /* First character of ans */
22082210
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
2211
+ int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
22092212
22102213
memset(&sCiInfo, 0, sizeof(sCiInfo));
22112214
url_proxy_options();
22122215
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
22132216
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
@@ -2239,10 +2242,14 @@
22392242
noVerify = find_option("no-verify",0,0)!=0;
22402243
bTrace = find_option("trace",0,0)!=0;
22412244
sCiInfo.zBranch = find_option("branch","b",1);
22422245
sCiInfo.zColor = find_option("bgcolor",0,1);
22432246
sCiInfo.zBrClr = find_option("branchcolor",0,1);
2247
+ if ( fossil_strncmp(sCiInfo.zBrClr, "auto", 4)==0 ) {
2248
+ bAutoBrClr = 1;
2249
+ sCiInfo.zBrClr = 0;
2250
+ }
22442251
sCiInfo.closeFlag = find_option("close",0,0)!=0;
22452252
sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
22462253
sCiInfo.zMimetype = find_option("mimetype",0,1);
22472254
sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
22482255
while( (zTag = find_option("tag",0,1))!=0 ){
@@ -2278,11 +2285,13 @@
22782285
if( privateFlag && !privateParent ){
22792286
/* Apply default branch name ("private") and color ("orange") if not
22802287
** specified otherwise on the command-line, and if the parent is not
22812288
** already private. */
22822289
if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private";
2283
- if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 ) sCiInfo.zBrClr = "#fec084";
2290
+ if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 && !bAutoBrClr) {
2291
+ sCiInfo.zBrClr = "#fec084";
2292
+ }
22842293
}
22852294
22862295
/* Do not allow the creation of a new branch using an existing open
22872296
** branch name unless the --force flag is used */
22882297
if( sCiInfo.zBranch!=0
22892298
--- src/checkin.c
+++ src/checkin.c
@@ -2127,10 +2127,12 @@
2127 ** --allow-older allow a commit older than its ancestor
2128 ** --baseline use a baseline manifest in the commit process
2129 ** --bgcolor COLOR apply COLOR to this one check-in only
2130 ** --branch NEW-BRANCH-NAME check in to this new branch
2131 ** --branchcolor COLOR apply given COLOR to the branch
 
 
2132 ** --close close the branch being committed
2133 ** --date-override DATETIME DATE to use instead of 'now'
2134 ** --delta use a delta manifest in the commit process
2135 ** --hash verify file status using hashing rather
2136 ** than relying on file mtimes
@@ -2204,10 +2206,11 @@
2204 int nConflict = 0; /* Number of unresolved merge conflicts */
2205 int abortCommit = 0; /* Abort the commit due to text format conversions */
2206 Blob ans; /* Answer to continuation prompts */
2207 char cReply; /* First character of ans */
2208 int bRecheck = 0; /* Repeat fork and closed-branch checks*/
 
2209
2210 memset(&sCiInfo, 0, sizeof(sCiInfo));
2211 url_proxy_options();
2212 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2213 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
@@ -2239,10 +2242,14 @@
2239 noVerify = find_option("no-verify",0,0)!=0;
2240 bTrace = find_option("trace",0,0)!=0;
2241 sCiInfo.zBranch = find_option("branch","b",1);
2242 sCiInfo.zColor = find_option("bgcolor",0,1);
2243 sCiInfo.zBrClr = find_option("branchcolor",0,1);
 
 
 
 
2244 sCiInfo.closeFlag = find_option("close",0,0)!=0;
2245 sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
2246 sCiInfo.zMimetype = find_option("mimetype",0,1);
2247 sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
2248 while( (zTag = find_option("tag",0,1))!=0 ){
@@ -2278,11 +2285,13 @@
2278 if( privateFlag && !privateParent ){
2279 /* Apply default branch name ("private") and color ("orange") if not
2280 ** specified otherwise on the command-line, and if the parent is not
2281 ** already private. */
2282 if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private";
2283 if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 ) sCiInfo.zBrClr = "#fec084";
 
 
2284 }
2285
2286 /* Do not allow the creation of a new branch using an existing open
2287 ** branch name unless the --force flag is used */
2288 if( sCiInfo.zBranch!=0
2289
--- src/checkin.c
+++ src/checkin.c
@@ -2127,10 +2127,12 @@
2127 ** --allow-older allow a commit older than its ancestor
2128 ** --baseline use a baseline manifest in the commit process
2129 ** --bgcolor COLOR apply COLOR to this one check-in only
2130 ** --branch NEW-BRANCH-NAME check in to this new branch
2131 ** --branchcolor COLOR apply given COLOR to the branch
2132 ** ("auto" lets Fossil choose it automatically,
2133 ** even for private branches)
2134 ** --close close the branch being committed
2135 ** --date-override DATETIME DATE to use instead of 'now'
2136 ** --delta use a delta manifest in the commit process
2137 ** --hash verify file status using hashing rather
2138 ** than relying on file mtimes
@@ -2204,10 +2206,11 @@
2206 int nConflict = 0; /* Number of unresolved merge conflicts */
2207 int abortCommit = 0; /* Abort the commit due to text format conversions */
2208 Blob ans; /* Answer to continuation prompts */
2209 char cReply; /* First character of ans */
2210 int bRecheck = 0; /* Repeat fork and closed-branch checks*/
2211 int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
2212
2213 memset(&sCiInfo, 0, sizeof(sCiInfo));
2214 url_proxy_options();
2215 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2216 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
@@ -2239,10 +2242,14 @@
2242 noVerify = find_option("no-verify",0,0)!=0;
2243 bTrace = find_option("trace",0,0)!=0;
2244 sCiInfo.zBranch = find_option("branch","b",1);
2245 sCiInfo.zColor = find_option("bgcolor",0,1);
2246 sCiInfo.zBrClr = find_option("branchcolor",0,1);
2247 if ( fossil_strncmp(sCiInfo.zBrClr, "auto", 4)==0 ) {
2248 bAutoBrClr = 1;
2249 sCiInfo.zBrClr = 0;
2250 }
2251 sCiInfo.closeFlag = find_option("close",0,0)!=0;
2252 sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
2253 sCiInfo.zMimetype = find_option("mimetype",0,1);
2254 sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
2255 while( (zTag = find_option("tag",0,1))!=0 ){
@@ -2278,11 +2285,13 @@
2285 if( privateFlag && !privateParent ){
2286 /* Apply default branch name ("private") and color ("orange") if not
2287 ** specified otherwise on the command-line, and if the parent is not
2288 ** already private. */
2289 if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private";
2290 if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 && !bAutoBrClr) {
2291 sCiInfo.zBrClr = "#fec084";
2292 }
2293 }
2294
2295 /* Do not allow the creation of a new branch using an existing open
2296 ** branch name unless the --force flag is used */
2297 if( sCiInfo.zBranch!=0
2298
+1 -3
--- src/checkout.c
+++ src/checkout.c
@@ -418,13 +418,11 @@
418418
&& db_exists("SELECT 1 FROM localdb.stash")
419419
){
420420
fossil_fatal("closing the checkout will delete your stash");
421421
}
422422
if( db_is_writeable("repository") ){
423
- char *zUnset = mprintf("ckout:%q", g.zLocalRoot);
424
- db_unset(zUnset, 1);
425
- fossil_free(zUnset);
423
+ db_unset_mprintf(1, "ckout:%q", g.zLocalRoot);
426424
}
427425
unlink_local_database(1);
428426
db_close(1);
429427
unlink_local_database(0);
430428
}
431429
--- src/checkout.c
+++ src/checkout.c
@@ -418,13 +418,11 @@
418 && db_exists("SELECT 1 FROM localdb.stash")
419 ){
420 fossil_fatal("closing the checkout will delete your stash");
421 }
422 if( db_is_writeable("repository") ){
423 char *zUnset = mprintf("ckout:%q", g.zLocalRoot);
424 db_unset(zUnset, 1);
425 fossil_free(zUnset);
426 }
427 unlink_local_database(1);
428 db_close(1);
429 unlink_local_database(0);
430 }
431
--- src/checkout.c
+++ src/checkout.c
@@ -418,13 +418,11 @@
418 && db_exists("SELECT 1 FROM localdb.stash")
419 ){
420 fossil_fatal("closing the checkout will delete your stash");
421 }
422 if( db_is_writeable("repository") ){
423 db_unset_mprintf(1, "ckout:%q", g.zLocalRoot);
 
 
424 }
425 unlink_local_database(1);
426 db_close(1);
427 unlink_local_database(0);
428 }
429
+5 -9
--- src/clone.c
+++ src/clone.c
@@ -290,15 +290,15 @@
290290
if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
291291
Blob cmd;
292292
fossil_print("opening the new %s repository in directory %s...\n",
293293
zRepo, zWorkDir);
294294
blob_init(&cmd, 0, 0);
295
- blob_append_escaped_arg(&cmd, g.nameOfExe);
295
+ blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
296296
blob_append(&cmd, " open ", -1);
297
- blob_append_escaped_arg(&cmd, zRepo);
297
+ blob_append_escaped_arg(&cmd, zRepo, 1);
298298
blob_append(&cmd, " --workdir ", -1);
299
- blob_append_escaped_arg(&cmd, zWorkDir);
299
+ blob_append_escaped_arg(&cmd, zWorkDir, 1);
300300
if( allowNested ){
301301
blob_append(&cmd, " --nested", -1);
302302
}
303303
fossil_system(blob_str(&cmd));
304304
blob_reset(&cmd);
@@ -314,26 +314,24 @@
314314
void remember_or_get_http_auth(
315315
const char *zHttpAuth, /* Credentials in the form "user:password" */
316316
int fRemember, /* True to remember credentials for later reuse */
317317
const char *zUrl /* URL for which these credentials apply */
318318
){
319
- char *zKey = mprintf("http-auth:%s", g.url.canonical);
320319
if( zHttpAuth && zHttpAuth[0] ){
321320
g.zHttpAuth = mprintf("%s", zHttpAuth);
322321
}
323322
if( fRemember ){
324323
if( g.zHttpAuth && g.zHttpAuth[0] ){
325324
set_httpauth(g.zHttpAuth);
326325
}else if( zUrl && zUrl[0] ){
327
- db_unset(zKey, 0);
326
+ db_unset_mprintf(0, "http-auth:%s", g.url.canonical);
328327
}else{
329328
g.zHttpAuth = get_httpauth();
330329
}
331330
}else if( g.zHttpAuth==0 && zUrl==0 ){
332331
g.zHttpAuth = get_httpauth();
333332
}
334
- free(zKey);
335333
}
336334
337335
/*
338336
** Get the HTTP Authorization preference from db.
339337
*/
@@ -346,13 +344,11 @@
346344
347345
/*
348346
** Set the HTTP Authorization preference in db.
349347
*/
350348
void set_httpauth(const char *zHttpAuth){
351
- char *zKey = mprintf("http-auth:%s", g.url.canonical);
352
- db_set(zKey, obscure(zHttpAuth), 0);
353
- free(zKey);
349
+ db_set_mprintf(obscure(zHttpAuth), 0, "http-auth:%s", g.url.canonical);
354350
}
355351
356352
/*
357353
** Look for SSH clone command line options and setup in globals.
358354
*/
359355
--- src/clone.c
+++ src/clone.c
@@ -290,15 +290,15 @@
290 if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
291 Blob cmd;
292 fossil_print("opening the new %s repository in directory %s...\n",
293 zRepo, zWorkDir);
294 blob_init(&cmd, 0, 0);
295 blob_append_escaped_arg(&cmd, g.nameOfExe);
296 blob_append(&cmd, " open ", -1);
297 blob_append_escaped_arg(&cmd, zRepo);
298 blob_append(&cmd, " --workdir ", -1);
299 blob_append_escaped_arg(&cmd, zWorkDir);
300 if( allowNested ){
301 blob_append(&cmd, " --nested", -1);
302 }
303 fossil_system(blob_str(&cmd));
304 blob_reset(&cmd);
@@ -314,26 +314,24 @@
314 void remember_or_get_http_auth(
315 const char *zHttpAuth, /* Credentials in the form "user:password" */
316 int fRemember, /* True to remember credentials for later reuse */
317 const char *zUrl /* URL for which these credentials apply */
318 ){
319 char *zKey = mprintf("http-auth:%s", g.url.canonical);
320 if( zHttpAuth && zHttpAuth[0] ){
321 g.zHttpAuth = mprintf("%s", zHttpAuth);
322 }
323 if( fRemember ){
324 if( g.zHttpAuth && g.zHttpAuth[0] ){
325 set_httpauth(g.zHttpAuth);
326 }else if( zUrl && zUrl[0] ){
327 db_unset(zKey, 0);
328 }else{
329 g.zHttpAuth = get_httpauth();
330 }
331 }else if( g.zHttpAuth==0 && zUrl==0 ){
332 g.zHttpAuth = get_httpauth();
333 }
334 free(zKey);
335 }
336
337 /*
338 ** Get the HTTP Authorization preference from db.
339 */
@@ -346,13 +344,11 @@
346
347 /*
348 ** Set the HTTP Authorization preference in db.
349 */
350 void set_httpauth(const char *zHttpAuth){
351 char *zKey = mprintf("http-auth:%s", g.url.canonical);
352 db_set(zKey, obscure(zHttpAuth), 0);
353 free(zKey);
354 }
355
356 /*
357 ** Look for SSH clone command line options and setup in globals.
358 */
359
--- src/clone.c
+++ src/clone.c
@@ -290,15 +290,15 @@
290 if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
291 Blob cmd;
292 fossil_print("opening the new %s repository in directory %s...\n",
293 zRepo, zWorkDir);
294 blob_init(&cmd, 0, 0);
295 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
296 blob_append(&cmd, " open ", -1);
297 blob_append_escaped_arg(&cmd, zRepo, 1);
298 blob_append(&cmd, " --workdir ", -1);
299 blob_append_escaped_arg(&cmd, zWorkDir, 1);
300 if( allowNested ){
301 blob_append(&cmd, " --nested", -1);
302 }
303 fossil_system(blob_str(&cmd));
304 blob_reset(&cmd);
@@ -314,26 +314,24 @@
314 void remember_or_get_http_auth(
315 const char *zHttpAuth, /* Credentials in the form "user:password" */
316 int fRemember, /* True to remember credentials for later reuse */
317 const char *zUrl /* URL for which these credentials apply */
318 ){
 
319 if( zHttpAuth && zHttpAuth[0] ){
320 g.zHttpAuth = mprintf("%s", zHttpAuth);
321 }
322 if( fRemember ){
323 if( g.zHttpAuth && g.zHttpAuth[0] ){
324 set_httpauth(g.zHttpAuth);
325 }else if( zUrl && zUrl[0] ){
326 db_unset_mprintf(0, "http-auth:%s", g.url.canonical);
327 }else{
328 g.zHttpAuth = get_httpauth();
329 }
330 }else if( g.zHttpAuth==0 && zUrl==0 ){
331 g.zHttpAuth = get_httpauth();
332 }
 
333 }
334
335 /*
336 ** Get the HTTP Authorization preference from db.
337 */
@@ -346,13 +344,11 @@
344
345 /*
346 ** Set the HTTP Authorization preference in db.
347 */
348 void set_httpauth(const char *zHttpAuth){
349 db_set_mprintf(obscure(zHttpAuth), 0, "http-auth:%s", g.url.canonical);
 
 
350 }
351
352 /*
353 ** Look for SSH clone command line options and setup in globals.
354 */
355
+91 -58
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -347,10 +347,12 @@
347347
*/
348348
#define FMT_SQL 0x00001 /* Generator for SQL text */
349349
#define FMT_HTML 0x00002 /* Generator for HTML text */
350350
#define FMT_URL 0x00004 /* Generator for URLs */
351351
#define FMT_SAFE 0x00008 /* Generator for human-readable text */
352
+#define FMT_LIT 0x00010 /* Just verify that a string literal */
353
+#define FMT_PX 0x00020 /* Must have a literal prefix in format string */
352354
353355
/*
354356
** A list of internal Fossil interfaces that take a printf-style format
355357
** string.
356358
*/
@@ -357,65 +359,76 @@
357359
struct FmtFunc {
358360
const char *zFName; /* Name of the function */
359361
int iFmtArg; /* Index of format argument. Leftmost is 1. */
360362
unsigned fmtFlags; /* Processing flags */
361363
} aFmtFunc[] = {
362
- { "admin_log", 1, FMT_SAFE },
363
- { "audit_append", 3, FMT_SAFE },
364
- { "backofficeTrace", 1, FMT_SAFE },
365
- { "blob_append_sql", 2, FMT_SQL },
366
- { "blob_appendf", 2, FMT_SAFE },
367
- { "cgi_debug", 1, FMT_SAFE },
368
- { "cgi_panic", 1, FMT_SAFE },
369
- { "cgi_printf", 1, FMT_HTML },
370
- { "cgi_printf_header", 1, FMT_HTML },
371
- { "cgi_redirectf", 1, FMT_URL },
372
- { "chref", 2, FMT_URL },
373
- { "CX", 1, FMT_HTML },
374
- { "db_blob", 2, FMT_SQL },
375
- { "db_debug", 1, FMT_SQL },
376
- { "db_double", 2, FMT_SQL },
377
- { "db_err", 1, FMT_SAFE },
378
- { "db_exists", 1, FMT_SQL },
379
- { "db_get_mprintf", 2, FMT_SAFE },
380
- { "db_int", 2, FMT_SQL },
381
- { "db_int64", 2, FMT_SQL },
382
- { "db_multi_exec", 1, FMT_SQL },
383
- { "db_optional_sql", 2, FMT_SQL },
384
- { "db_prepare", 2, FMT_SQL },
385
- { "db_prepare_ignore_error", 2, FMT_SQL },
386
- { "db_set_mprintf", 3, FMT_SAFE },
387
- { "db_static_prepare", 2, FMT_SQL },
388
- { "db_text", 2, FMT_SQL },
389
- { "db_unset_mprintf", 2, FMT_SAFE },
390
- { "emailerError", 2, FMT_SAFE },
391
- { "fileedit_ajax_error", 2, FMT_SAFE },
392
- { "form_begin", 2, FMT_URL },
393
- { "fossil_error", 2, FMT_SAFE },
394
- { "fossil_errorlog", 1, FMT_SAFE },
395
- { "fossil_fatal", 1, FMT_SAFE },
396
- { "fossil_fatal_recursive", 1, FMT_SAFE },
397
- { "fossil_panic", 1, FMT_SAFE },
398
- { "fossil_print", 1, FMT_SAFE },
399
- { "fossil_trace", 1, FMT_SAFE },
400
- { "fossil_warning", 1, FMT_SAFE },
401
- { "href", 1, FMT_URL },
402
- { "json_new_string_f", 1, FMT_SAFE },
403
- { "json_set_err", 2, FMT_SAFE },
404
- { "json_warn", 2, FMT_SAFE },
405
- { "mprintf", 1, FMT_SAFE },
406
- { "pop3_print", 2, FMT_SAFE },
407
- { "smtp_send_line", 2, FMT_SAFE },
408
- { "smtp_server_send", 2, FMT_SAFE },
409
- { "socket_set_errmsg", 1, FMT_SAFE },
410
- { "ssl_set_errmsg", 1, FMT_SAFE },
411
- { "style_header", 1, FMT_HTML },
412
- { "style_set_current_page", 1, FMT_URL },
413
- { "style_submenu_element", 2, FMT_URL },
414
- { "style_submenu_sql", 3, FMT_SQL },
415
- { "webpage_error", 1, FMT_SAFE },
416
- { "xhref", 2, FMT_URL },
364
+ { "admin_log", 1, FMT_SAFE },
365
+ { "audit_append", 3, FMT_SAFE },
366
+ { "backofficeTrace", 1, FMT_SAFE },
367
+ { "blob_append_sql", 2, FMT_SQL },
368
+ { "blob_appendf", 2, FMT_SAFE },
369
+ { "cgi_debug", 1, FMT_SAFE },
370
+ { "cgi_panic", 1, FMT_SAFE },
371
+ { "cgi_printf", 1, FMT_HTML },
372
+ { "cgi_printf_header", 1, FMT_HTML },
373
+ { "cgi_redirectf", 1, FMT_URL },
374
+ { "chref", 2, FMT_URL },
375
+ { "CX", 1, FMT_HTML },
376
+ { "db_blob", 2, FMT_SQL },
377
+ { "db_debug", 1, FMT_SQL },
378
+ { "db_double", 2, FMT_SQL },
379
+ { "db_err", 1, FMT_SAFE },
380
+ { "db_exists", 1, FMT_SQL },
381
+ { "db_get_mprintf", 2, FMT_SAFE },
382
+ { "db_int", 2, FMT_SQL },
383
+ { "db_int64", 2, FMT_SQL },
384
+ { "db_lset", 1, FMT_LIT },
385
+ { "db_lset_int", 1, FMT_LIT },
386
+ { "db_multi_exec", 1, FMT_SQL },
387
+ { "db_optional_sql", 2, FMT_SQL },
388
+ { "db_prepare", 2, FMT_SQL },
389
+ { "db_prepare_ignore_error", 2, FMT_SQL },
390
+ { "db_set", 1, FMT_LIT },
391
+ { "db_set_int", 1, FMT_LIT },
392
+ { "db_set_mprintf", 3, FMT_PX },
393
+ { "db_static_prepare", 2, FMT_SQL },
394
+ { "db_text", 2, FMT_SQL },
395
+ { "db_unset", 1, FMT_LIT },
396
+ { "db_unset_mprintf", 2, FMT_PX },
397
+ { "emailerError", 2, FMT_SAFE },
398
+ { "entry_attribute", 4, FMT_LIT },
399
+ { "fileedit_ajax_error", 2, FMT_SAFE },
400
+ { "form_begin", 2, FMT_URL },
401
+ { "fossil_error", 2, FMT_SAFE },
402
+ { "fossil_errorlog", 1, FMT_SAFE },
403
+ { "fossil_fatal", 1, FMT_SAFE },
404
+ { "fossil_fatal_recursive", 1, FMT_SAFE },
405
+ { "fossil_panic", 1, FMT_SAFE },
406
+ { "fossil_print", 1, FMT_SAFE },
407
+ { "fossil_trace", 1, FMT_SAFE },
408
+ { "fossil_warning", 1, FMT_SAFE },
409
+ { "href", 1, FMT_URL },
410
+ { "json_new_string_f", 1, FMT_SAFE },
411
+ { "json_set_err", 2, FMT_SAFE },
412
+ { "json_warn", 2, FMT_SAFE },
413
+ { "mprintf", 1, FMT_SAFE },
414
+ { "multiple_choice_attribute", 3, FMT_LIT },
415
+ { "onoff_attribute", 3, FMT_LIT },
416
+ { "pop3_print", 2, FMT_SAFE },
417
+ { "smtp_send_line", 2, FMT_SAFE },
418
+ { "smtp_server_send", 2, FMT_SAFE },
419
+ { "socket_set_errmsg", 1, FMT_SAFE },
420
+ { "ssl_set_errmsg", 1, FMT_SAFE },
421
+ { "style_header", 1, FMT_HTML },
422
+ { "style_set_current_page", 1, FMT_URL },
423
+ { "style_submenu_element", 2, FMT_URL },
424
+ { "style_submenu_sql", 3, FMT_SQL },
425
+ { "textarea_attribute", 5, FMT_LIT },
426
+ { "tktsetup_generic", 1, FMT_LIT },
427
+ { "webpage_error", 1, FMT_SAFE },
428
+ { "xfersetup_generic", 1, FMT_LIT },
429
+ { "xhref", 2, FMT_URL },
417430
};
418431
419432
/*
420433
** Comparison function for two FmtFunc entries
421434
*/
@@ -459,20 +472,26 @@
459472
** Return the expected number of arguments for the format string.
460473
** Return -1 if the value cannot be computed.
461474
**
462475
** For each argument less than nType, store the conversion character
463476
** for that argument in cType[i].
477
+**
478
+** Store the number of initial literal characters of the format string
479
+** in *pInit.
464480
*/
465
-static int formatArgCount(const char *z, int nType, char *cType){
481
+static int formatArgCount(const char *z, int nType, char *cType, int *pInit){
466482
int nArg = 0;
467483
int i, k;
468484
int len;
469485
int eType;
470486
int ln = 0;
487
+ *pInit = 0;
471488
while( z[0] ){
472489
len = token_length(z, &eType, &ln);
473490
if( eType==TK_STR ){
491
+ for(i=1; i<len-1 && isalpha(z[i]); i++){}
492
+ *pInit = i-1;
474493
for(i=1; i<len-1; i++){
475494
if( z[i]!='%' ) continue;
476495
if( z[i+1]=='%' ){ i++; continue; }
477496
for(k=i+1; k<len && !isalpha(z[k]); k++){
478497
if( z[k]=='*' || z[k]=='#' ){
@@ -515,10 +534,11 @@
515534
int nArg = 0;
516535
const char **azArg = 0;
517536
int i, k;
518537
int nErr = 0;
519538
char *acType;
539
+ int nInit = 0;
520540
521541
szFName = token_length(zFCall, &eToken, &ln);
522542
zStart = next_non_whitespace(zFCall+szFName, &len, &eToken);
523543
assert( zStart[0]=='(' && len==1 );
524544
len = distance_to(zStart+1, ')');
@@ -545,21 +565,34 @@
545565
nErr++;
546566
}else{
547567
const char *zFmt = azArg[fmtArg-1];
548568
const char *zOverride = strstr(zFmt, "/*works-like:");
549569
if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1;
550
- if( !is_string_lit(zFmt) ){
570
+ if( fmtFlags & FMT_LIT ){
571
+ if( !is_string_lit(zFmt) ){
572
+ printf("%s:%d: argument %d to %.*s() should be a string literal\n",
573
+ zFilename, lnFCall, fmtArg, szFName, zFCall);
574
+ nErr++;
575
+ }
576
+ }else if( !is_string_lit(zFmt) ){
551577
printf("%s:%d: %.*s() has non-constant format on arg[%d]\n",
552578
zFilename, lnFCall, szFName, zFCall, fmtArg-1);
553579
nErr++;
554
- }else if( (k = formatArgCount(zFmt, nArg, acType))>=0
580
+ }else if( (k = formatArgCount(zFmt, nArg, acType, &nInit))>=0
555581
&& nArg!=fmtArg+k ){
556582
printf("%s:%d: too %s arguments to %.*s() "
557583
"- got %d and expected %d\n",
558584
zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
559585
szFName, zFCall, nArg, fmtArg+k);
560586
nErr++;
587
+ }else if( (fmtFlags & FMT_PX)!=0 ){
588
+ if( nInit==0 ){
589
+ printf("%s:%d: format string on %.*s() should have"
590
+ " an ASCII character prefix\n",
591
+ zFilename, lnFCall, szFName, zFCall);
592
+ nErr++;
593
+ }
561594
}else if( (fmtFlags & FMT_SAFE)==0 ){
562595
for(i=0; i<nArg && i<k; i++){
563596
if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
564597
const char *zExpr = azArg[fmtArg+i];
565598
if( never_safe(zExpr) ){
566599
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -347,10 +347,12 @@
347 */
348 #define FMT_SQL 0x00001 /* Generator for SQL text */
349 #define FMT_HTML 0x00002 /* Generator for HTML text */
350 #define FMT_URL 0x00004 /* Generator for URLs */
351 #define FMT_SAFE 0x00008 /* Generator for human-readable text */
 
 
352
353 /*
354 ** A list of internal Fossil interfaces that take a printf-style format
355 ** string.
356 */
@@ -357,65 +359,76 @@
357 struct FmtFunc {
358 const char *zFName; /* Name of the function */
359 int iFmtArg; /* Index of format argument. Leftmost is 1. */
360 unsigned fmtFlags; /* Processing flags */
361 } aFmtFunc[] = {
362 { "admin_log", 1, FMT_SAFE },
363 { "audit_append", 3, FMT_SAFE },
364 { "backofficeTrace", 1, FMT_SAFE },
365 { "blob_append_sql", 2, FMT_SQL },
366 { "blob_appendf", 2, FMT_SAFE },
367 { "cgi_debug", 1, FMT_SAFE },
368 { "cgi_panic", 1, FMT_SAFE },
369 { "cgi_printf", 1, FMT_HTML },
370 { "cgi_printf_header", 1, FMT_HTML },
371 { "cgi_redirectf", 1, FMT_URL },
372 { "chref", 2, FMT_URL },
373 { "CX", 1, FMT_HTML },
374 { "db_blob", 2, FMT_SQL },
375 { "db_debug", 1, FMT_SQL },
376 { "db_double", 2, FMT_SQL },
377 { "db_err", 1, FMT_SAFE },
378 { "db_exists", 1, FMT_SQL },
379 { "db_get_mprintf", 2, FMT_SAFE },
380 { "db_int", 2, FMT_SQL },
381 { "db_int64", 2, FMT_SQL },
382 { "db_multi_exec", 1, FMT_SQL },
383 { "db_optional_sql", 2, FMT_SQL },
384 { "db_prepare", 2, FMT_SQL },
385 { "db_prepare_ignore_error", 2, FMT_SQL },
386 { "db_set_mprintf", 3, FMT_SAFE },
387 { "db_static_prepare", 2, FMT_SQL },
388 { "db_text", 2, FMT_SQL },
389 { "db_unset_mprintf", 2, FMT_SAFE },
390 { "emailerError", 2, FMT_SAFE },
391 { "fileedit_ajax_error", 2, FMT_SAFE },
392 { "form_begin", 2, FMT_URL },
393 { "fossil_error", 2, FMT_SAFE },
394 { "fossil_errorlog", 1, FMT_SAFE },
395 { "fossil_fatal", 1, FMT_SAFE },
396 { "fossil_fatal_recursive", 1, FMT_SAFE },
397 { "fossil_panic", 1, FMT_SAFE },
398 { "fossil_print", 1, FMT_SAFE },
399 { "fossil_trace", 1, FMT_SAFE },
400 { "fossil_warning", 1, FMT_SAFE },
401 { "href", 1, FMT_URL },
402 { "json_new_string_f", 1, FMT_SAFE },
403 { "json_set_err", 2, FMT_SAFE },
404 { "json_warn", 2, FMT_SAFE },
405 { "mprintf", 1, FMT_SAFE },
406 { "pop3_print", 2, FMT_SAFE },
407 { "smtp_send_line", 2, FMT_SAFE },
408 { "smtp_server_send", 2, FMT_SAFE },
409 { "socket_set_errmsg", 1, FMT_SAFE },
410 { "ssl_set_errmsg", 1, FMT_SAFE },
411 { "style_header", 1, FMT_HTML },
412 { "style_set_current_page", 1, FMT_URL },
413 { "style_submenu_element", 2, FMT_URL },
414 { "style_submenu_sql", 3, FMT_SQL },
415 { "webpage_error", 1, FMT_SAFE },
416 { "xhref", 2, FMT_URL },
 
 
 
 
 
 
 
 
 
 
 
417 };
418
419 /*
420 ** Comparison function for two FmtFunc entries
421 */
@@ -459,20 +472,26 @@
459 ** Return the expected number of arguments for the format string.
460 ** Return -1 if the value cannot be computed.
461 **
462 ** For each argument less than nType, store the conversion character
463 ** for that argument in cType[i].
 
 
 
464 */
465 static int formatArgCount(const char *z, int nType, char *cType){
466 int nArg = 0;
467 int i, k;
468 int len;
469 int eType;
470 int ln = 0;
 
471 while( z[0] ){
472 len = token_length(z, &eType, &ln);
473 if( eType==TK_STR ){
 
 
474 for(i=1; i<len-1; i++){
475 if( z[i]!='%' ) continue;
476 if( z[i+1]=='%' ){ i++; continue; }
477 for(k=i+1; k<len && !isalpha(z[k]); k++){
478 if( z[k]=='*' || z[k]=='#' ){
@@ -515,10 +534,11 @@
515 int nArg = 0;
516 const char **azArg = 0;
517 int i, k;
518 int nErr = 0;
519 char *acType;
 
520
521 szFName = token_length(zFCall, &eToken, &ln);
522 zStart = next_non_whitespace(zFCall+szFName, &len, &eToken);
523 assert( zStart[0]=='(' && len==1 );
524 len = distance_to(zStart+1, ')');
@@ -545,21 +565,34 @@
545 nErr++;
546 }else{
547 const char *zFmt = azArg[fmtArg-1];
548 const char *zOverride = strstr(zFmt, "/*works-like:");
549 if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1;
550 if( !is_string_lit(zFmt) ){
 
 
 
 
 
 
551 printf("%s:%d: %.*s() has non-constant format on arg[%d]\n",
552 zFilename, lnFCall, szFName, zFCall, fmtArg-1);
553 nErr++;
554 }else if( (k = formatArgCount(zFmt, nArg, acType))>=0
555 && nArg!=fmtArg+k ){
556 printf("%s:%d: too %s arguments to %.*s() "
557 "- got %d and expected %d\n",
558 zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
559 szFName, zFCall, nArg, fmtArg+k);
560 nErr++;
 
 
 
 
 
 
 
561 }else if( (fmtFlags & FMT_SAFE)==0 ){
562 for(i=0; i<nArg && i<k; i++){
563 if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
564 const char *zExpr = azArg[fmtArg+i];
565 if( never_safe(zExpr) ){
566
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -347,10 +347,12 @@
347 */
348 #define FMT_SQL 0x00001 /* Generator for SQL text */
349 #define FMT_HTML 0x00002 /* Generator for HTML text */
350 #define FMT_URL 0x00004 /* Generator for URLs */
351 #define FMT_SAFE 0x00008 /* Generator for human-readable text */
352 #define FMT_LIT 0x00010 /* Just verify that a string literal */
353 #define FMT_PX 0x00020 /* Must have a literal prefix in format string */
354
355 /*
356 ** A list of internal Fossil interfaces that take a printf-style format
357 ** string.
358 */
@@ -357,65 +359,76 @@
359 struct FmtFunc {
360 const char *zFName; /* Name of the function */
361 int iFmtArg; /* Index of format argument. Leftmost is 1. */
362 unsigned fmtFlags; /* Processing flags */
363 } aFmtFunc[] = {
364 { "admin_log", 1, FMT_SAFE },
365 { "audit_append", 3, FMT_SAFE },
366 { "backofficeTrace", 1, FMT_SAFE },
367 { "blob_append_sql", 2, FMT_SQL },
368 { "blob_appendf", 2, FMT_SAFE },
369 { "cgi_debug", 1, FMT_SAFE },
370 { "cgi_panic", 1, FMT_SAFE },
371 { "cgi_printf", 1, FMT_HTML },
372 { "cgi_printf_header", 1, FMT_HTML },
373 { "cgi_redirectf", 1, FMT_URL },
374 { "chref", 2, FMT_URL },
375 { "CX", 1, FMT_HTML },
376 { "db_blob", 2, FMT_SQL },
377 { "db_debug", 1, FMT_SQL },
378 { "db_double", 2, FMT_SQL },
379 { "db_err", 1, FMT_SAFE },
380 { "db_exists", 1, FMT_SQL },
381 { "db_get_mprintf", 2, FMT_SAFE },
382 { "db_int", 2, FMT_SQL },
383 { "db_int64", 2, FMT_SQL },
384 { "db_lset", 1, FMT_LIT },
385 { "db_lset_int", 1, FMT_LIT },
386 { "db_multi_exec", 1, FMT_SQL },
387 { "db_optional_sql", 2, FMT_SQL },
388 { "db_prepare", 2, FMT_SQL },
389 { "db_prepare_ignore_error", 2, FMT_SQL },
390 { "db_set", 1, FMT_LIT },
391 { "db_set_int", 1, FMT_LIT },
392 { "db_set_mprintf", 3, FMT_PX },
393 { "db_static_prepare", 2, FMT_SQL },
394 { "db_text", 2, FMT_SQL },
395 { "db_unset", 1, FMT_LIT },
396 { "db_unset_mprintf", 2, FMT_PX },
397 { "emailerError", 2, FMT_SAFE },
398 { "entry_attribute", 4, FMT_LIT },
399 { "fileedit_ajax_error", 2, FMT_SAFE },
400 { "form_begin", 2, FMT_URL },
401 { "fossil_error", 2, FMT_SAFE },
402 { "fossil_errorlog", 1, FMT_SAFE },
403 { "fossil_fatal", 1, FMT_SAFE },
404 { "fossil_fatal_recursive", 1, FMT_SAFE },
405 { "fossil_panic", 1, FMT_SAFE },
406 { "fossil_print", 1, FMT_SAFE },
407 { "fossil_trace", 1, FMT_SAFE },
408 { "fossil_warning", 1, FMT_SAFE },
409 { "href", 1, FMT_URL },
410 { "json_new_string_f", 1, FMT_SAFE },
411 { "json_set_err", 2, FMT_SAFE },
412 { "json_warn", 2, FMT_SAFE },
413 { "mprintf", 1, FMT_SAFE },
414 { "multiple_choice_attribute", 3, FMT_LIT },
415 { "onoff_attribute", 3, FMT_LIT },
416 { "pop3_print", 2, FMT_SAFE },
417 { "smtp_send_line", 2, FMT_SAFE },
418 { "smtp_server_send", 2, FMT_SAFE },
419 { "socket_set_errmsg", 1, FMT_SAFE },
420 { "ssl_set_errmsg", 1, FMT_SAFE },
421 { "style_header", 1, FMT_HTML },
422 { "style_set_current_page", 1, FMT_URL },
423 { "style_submenu_element", 2, FMT_URL },
424 { "style_submenu_sql", 3, FMT_SQL },
425 { "textarea_attribute", 5, FMT_LIT },
426 { "tktsetup_generic", 1, FMT_LIT },
427 { "webpage_error", 1, FMT_SAFE },
428 { "xfersetup_generic", 1, FMT_LIT },
429 { "xhref", 2, FMT_URL },
430 };
431
432 /*
433 ** Comparison function for two FmtFunc entries
434 */
@@ -459,20 +472,26 @@
472 ** Return the expected number of arguments for the format string.
473 ** Return -1 if the value cannot be computed.
474 **
475 ** For each argument less than nType, store the conversion character
476 ** for that argument in cType[i].
477 **
478 ** Store the number of initial literal characters of the format string
479 ** in *pInit.
480 */
481 static int formatArgCount(const char *z, int nType, char *cType, int *pInit){
482 int nArg = 0;
483 int i, k;
484 int len;
485 int eType;
486 int ln = 0;
487 *pInit = 0;
488 while( z[0] ){
489 len = token_length(z, &eType, &ln);
490 if( eType==TK_STR ){
491 for(i=1; i<len-1 && isalpha(z[i]); i++){}
492 *pInit = i-1;
493 for(i=1; i<len-1; i++){
494 if( z[i]!='%' ) continue;
495 if( z[i+1]=='%' ){ i++; continue; }
496 for(k=i+1; k<len && !isalpha(z[k]); k++){
497 if( z[k]=='*' || z[k]=='#' ){
@@ -515,10 +534,11 @@
534 int nArg = 0;
535 const char **azArg = 0;
536 int i, k;
537 int nErr = 0;
538 char *acType;
539 int nInit = 0;
540
541 szFName = token_length(zFCall, &eToken, &ln);
542 zStart = next_non_whitespace(zFCall+szFName, &len, &eToken);
543 assert( zStart[0]=='(' && len==1 );
544 len = distance_to(zStart+1, ')');
@@ -545,21 +565,34 @@
565 nErr++;
566 }else{
567 const char *zFmt = azArg[fmtArg-1];
568 const char *zOverride = strstr(zFmt, "/*works-like:");
569 if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1;
570 if( fmtFlags & FMT_LIT ){
571 if( !is_string_lit(zFmt) ){
572 printf("%s:%d: argument %d to %.*s() should be a string literal\n",
573 zFilename, lnFCall, fmtArg, szFName, zFCall);
574 nErr++;
575 }
576 }else if( !is_string_lit(zFmt) ){
577 printf("%s:%d: %.*s() has non-constant format on arg[%d]\n",
578 zFilename, lnFCall, szFName, zFCall, fmtArg-1);
579 nErr++;
580 }else if( (k = formatArgCount(zFmt, nArg, acType, &nInit))>=0
581 && nArg!=fmtArg+k ){
582 printf("%s:%d: too %s arguments to %.*s() "
583 "- got %d and expected %d\n",
584 zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
585 szFName, zFCall, nArg, fmtArg+k);
586 nErr++;
587 }else if( (fmtFlags & FMT_PX)!=0 ){
588 if( nInit==0 ){
589 printf("%s:%d: format string on %.*s() should have"
590 " an ASCII character prefix\n",
591 zFilename, lnFCall, szFName, zFCall);
592 nErr++;
593 }
594 }else if( (fmtFlags & FMT_SAFE)==0 ){
595 for(i=0; i<nArg && i<k; i++){
596 if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
597 const char *zExpr = azArg[fmtArg+i];
598 if( never_safe(zExpr) ){
599
--- src/config.h
+++ src/config.h
@@ -66,10 +66,16 @@
6666
typedef int socklen_t;
6767
# endif
6868
# ifndef _WIN32
6969
# define _WIN32
7070
# endif
71
+# include <io.h>
72
+# include <fcntl.h>
73
+# undef popen
74
+# define popen _popen
75
+# undef pclose
76
+# define pclose _pclose
7177
#else
7278
# include <sys/types.h>
7379
# include <signal.h>
7480
# include <pwd.h>
7581
#endif
7682
--- src/config.h
+++ src/config.h
@@ -66,10 +66,16 @@
66 typedef int socklen_t;
67 # endif
68 # ifndef _WIN32
69 # define _WIN32
70 # endif
 
 
 
 
 
 
71 #else
72 # include <sys/types.h>
73 # include <signal.h>
74 # include <pwd.h>
75 #endif
76
--- src/config.h
+++ src/config.h
@@ -66,10 +66,16 @@
66 typedef int socklen_t;
67 # endif
68 # ifndef _WIN32
69 # define _WIN32
70 # endif
71 # include <io.h>
72 # include <fcntl.h>
73 # undef popen
74 # define popen _popen
75 # undef pclose
76 # define pclose _pclose
77 #else
78 # include <sys/types.h>
79 # include <signal.h>
80 # include <pwd.h>
81 #endif
82
+23 -9
--- src/db.c
+++ src/db.c
@@ -3321,10 +3321,15 @@
33213321
void db_lset_int(const char *zName, int value){
33223322
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
33233323
}
33243324
33253325
/* Va-args versions of db_get(), db_set(), and db_unset()
3326
+**
3327
+** codecheck1.c verifies that the format string for db_set_mprintf()
3328
+** and db_unset_mprintf() begins with an ASCII character prefix. We
3329
+** don't want that format string to begin with %s or %d as that might
3330
+** allow an injection attack to set or overwrite arbitrary settings.
33263331
*/
33273332
char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
33283333
va_list ap;
33293334
char *zName;
33303335
char *zResult;
@@ -3339,20 +3344,20 @@
33393344
va_list ap;
33403345
char *zName;
33413346
va_start(ap, zFormat);
33423347
zName = vmprintf(zFormat, ap);
33433348
va_end(ap);
3344
- db_set(zName, zNew, iGlobal);
3349
+ db_set(zName/*works-like:"x"*/, zNew, iGlobal);
33453350
fossil_free(zName);
33463351
}
33473352
void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
33483353
va_list ap;
33493354
char *zName;
33503355
va_start(ap, zFormat);
33513356
zName = vmprintf(zFormat, ap);
33523357
va_end(ap);
3353
- db_unset(zName, iGlobal);
3358
+ db_unset(zName/*works-like:"x"*/, iGlobal);
33543359
fossil_free(zName);
33553360
}
33563361
33573362
33583363
@@ -3498,10 +3503,11 @@
34983503
** -f|--force Continue with the open even if the working directory is
34993504
** not empty.
35003505
** --force-missing Force opening a repository with missing content
35013506
** --keep Only modify the manifest and manifest.uuid files
35023507
** --nested Allow opening a repository inside an opened checkout
3508
+** --nosync Do not auto-sync the repository prior to opening
35033509
** --repodir DIR If REPOSITORY is a URI that will be cloned, store
35043510
** the clone in DIR rather than in "."
35053511
** --setmtime Set timestamps of all files to match their SCM-side
35063512
** times (the timestamp of the last checkin which modified
35073513
** them).
@@ -3522,10 +3528,11 @@
35223528
const char *zRepo = 0; /* Name of the repository file */
35233529
const char *zRepoDir = 0; /* --repodir value */
35243530
char *zPwd; /* Initial working directory */
35253531
int isUri = 0; /* True if REPOSITORY is a URI */
35263532
int nLocal; /* Number of preexisting files in cwd */
3533
+ int bNosync = 0; /* --nosync. Omit auto-sync */
35273534
35283535
url_proxy_options();
35293536
emptyFlag = find_option("empty",0,0)!=0;
35303537
keepFlag = find_option("keep",0,0)!=0;
35313538
forceMissingFlag = find_option("force-missing",0,0)!=0;
@@ -3532,10 +3539,11 @@
35323539
allowNested = find_option("nested",0,0)!=0;
35333540
setmtimeFlag = find_option("setmtime",0,0)!=0;
35343541
zWorkDir = find_option("workdir",0,1);
35353542
zRepoDir = find_option("repodir",0,1);
35363543
bForce = find_option("force","f",0)!=0;
3544
+ bNosync = find_option("nosync",0,0)!=0;
35373545
zPwd = file_getcwd(0,0);
35383546
35393547
35403548
/* We should be done with options.. */
35413549
verify_all_options();
@@ -3599,14 +3607,14 @@
35993607
}
36003608
if( zRepoDir==0 ) zRepoDir = zPwd;
36013609
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
36023610
fossil_free(zNewBase);
36033611
blob_init(&cmd, 0, 0);
3604
- blob_append_escaped_arg(&cmd, g.nameOfExe);
3612
+ blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
36053613
blob_append(&cmd, " clone", -1);
3606
- blob_append_escaped_arg(&cmd, zUri);
3607
- blob_append_escaped_arg(&cmd, zRepo);
3614
+ blob_append_escaped_arg(&cmd, zUri, 1);
3615
+ blob_append_escaped_arg(&cmd, zRepo, 1);
36083616
zCmd = blob_str(&cmd);
36093617
fossil_print("%s\n", zCmd);
36103618
if( zWorkDir ) file_chdir(zPwd, 0);
36113619
rc = fossil_system(zCmd);
36123620
if( rc ){
@@ -3627,10 +3635,16 @@
36273635
if( g.argc==4 ){
36283636
g.zOpenRevision = g.argv[3];
36293637
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
36303638
g.zOpenRevision = db_get("main-branch", 0);
36313639
}
3640
+ if( !bNosync
3641
+ && autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1), 1)
3642
+ && !bForce
3643
+ ){
3644
+ fossil_fatal("unable to auto-sync the repository");
3645
+ }
36323646
}
36333647
36343648
36353649
#if defined(_WIN32) || defined(__CYGWIN__)
36363650
# define LOCALDB_NAME "./_FOSSIL_"
@@ -3984,11 +3998,11 @@
39843998
** The value is a graphical merge conflict resolver command operating
39853999
** on four files. Examples:
39864000
**
39874001
** kdiff3 "%baseline" "%original" "%merge" -o "%output"
39884002
** xxdiff "%original" "%baseline" "%merge" -M "%output"
3989
-** meld "%baseline" "%original" "%merge" "%output"
4003
+** meld "%baseline" "%original" "%merge" --output "%output"
39904004
*/
39914005
/*
39924006
** SETTING: hash-digits width=5 default=10
39934007
** The number of hexadecimal digits of the SHA3 hash to display.
39944008
*/
@@ -4060,11 +4074,11 @@
40604074
** check-in lock mechanism is only effective if all users are auto-syncing
40614075
** to the same server.
40624076
**
40634077
** Check-in locks are an advisory mechanism designed to help prevent
40644078
** accidental forks due to a check-in race in installations where many
4065
-** user are committing to the same branch and auto-sync is enabled.
4079
+** users are committing to the same branch and auto-sync is enabled.
40664080
** As forks are harmless, there is no danger in disabling this mechanism.
40674081
** However, keeping check-in locks turned on can help prevent unnecessary
40684082
** confusion.
40694083
*/
40704084
/*
@@ -4453,14 +4467,14 @@
44534467
}
44544468
if( globalFlag && isManifest ){
44554469
fossil_fatal("cannot set 'manifest' globally");
44564470
}
44574471
if( unsetFlag ){
4458
- db_unset(pSetting->name, globalFlag);
4472
+ db_unset(pSetting->name/*works-like:"x"*/, globalFlag);
44594473
}else{
44604474
db_protect_only(PROTECT_NONE);
4461
- db_set(pSetting->name, g.argv[3], globalFlag);
4475
+ db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag);
44624476
db_protect_pop();
44634477
}
44644478
if( isManifest && g.localOpen ){
44654479
manifest_to_disk(db_lget_int("checkout", 0));
44664480
}
44674481
--- src/db.c
+++ src/db.c
@@ -3321,10 +3321,15 @@
3321 void db_lset_int(const char *zName, int value){
3322 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
3323 }
3324
3325 /* Va-args versions of db_get(), db_set(), and db_unset()
 
 
 
 
 
3326 */
3327 char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
3328 va_list ap;
3329 char *zName;
3330 char *zResult;
@@ -3339,20 +3344,20 @@
3339 va_list ap;
3340 char *zName;
3341 va_start(ap, zFormat);
3342 zName = vmprintf(zFormat, ap);
3343 va_end(ap);
3344 db_set(zName, zNew, iGlobal);
3345 fossil_free(zName);
3346 }
3347 void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
3348 va_list ap;
3349 char *zName;
3350 va_start(ap, zFormat);
3351 zName = vmprintf(zFormat, ap);
3352 va_end(ap);
3353 db_unset(zName, iGlobal);
3354 fossil_free(zName);
3355 }
3356
3357
3358
@@ -3498,10 +3503,11 @@
3498 ** -f|--force Continue with the open even if the working directory is
3499 ** not empty.
3500 ** --force-missing Force opening a repository with missing content
3501 ** --keep Only modify the manifest and manifest.uuid files
3502 ** --nested Allow opening a repository inside an opened checkout
 
3503 ** --repodir DIR If REPOSITORY is a URI that will be cloned, store
3504 ** the clone in DIR rather than in "."
3505 ** --setmtime Set timestamps of all files to match their SCM-side
3506 ** times (the timestamp of the last checkin which modified
3507 ** them).
@@ -3522,10 +3528,11 @@
3522 const char *zRepo = 0; /* Name of the repository file */
3523 const char *zRepoDir = 0; /* --repodir value */
3524 char *zPwd; /* Initial working directory */
3525 int isUri = 0; /* True if REPOSITORY is a URI */
3526 int nLocal; /* Number of preexisting files in cwd */
 
3527
3528 url_proxy_options();
3529 emptyFlag = find_option("empty",0,0)!=0;
3530 keepFlag = find_option("keep",0,0)!=0;
3531 forceMissingFlag = find_option("force-missing",0,0)!=0;
@@ -3532,10 +3539,11 @@
3532 allowNested = find_option("nested",0,0)!=0;
3533 setmtimeFlag = find_option("setmtime",0,0)!=0;
3534 zWorkDir = find_option("workdir",0,1);
3535 zRepoDir = find_option("repodir",0,1);
3536 bForce = find_option("force","f",0)!=0;
 
3537 zPwd = file_getcwd(0,0);
3538
3539
3540 /* We should be done with options.. */
3541 verify_all_options();
@@ -3599,14 +3607,14 @@
3599 }
3600 if( zRepoDir==0 ) zRepoDir = zPwd;
3601 zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
3602 fossil_free(zNewBase);
3603 blob_init(&cmd, 0, 0);
3604 blob_append_escaped_arg(&cmd, g.nameOfExe);
3605 blob_append(&cmd, " clone", -1);
3606 blob_append_escaped_arg(&cmd, zUri);
3607 blob_append_escaped_arg(&cmd, zRepo);
3608 zCmd = blob_str(&cmd);
3609 fossil_print("%s\n", zCmd);
3610 if( zWorkDir ) file_chdir(zPwd, 0);
3611 rc = fossil_system(zCmd);
3612 if( rc ){
@@ -3627,10 +3635,16 @@
3627 if( g.argc==4 ){
3628 g.zOpenRevision = g.argv[3];
3629 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
3630 g.zOpenRevision = db_get("main-branch", 0);
3631 }
 
 
 
 
 
 
3632 }
3633
3634
3635 #if defined(_WIN32) || defined(__CYGWIN__)
3636 # define LOCALDB_NAME "./_FOSSIL_"
@@ -3984,11 +3998,11 @@
3984 ** The value is a graphical merge conflict resolver command operating
3985 ** on four files. Examples:
3986 **
3987 ** kdiff3 "%baseline" "%original" "%merge" -o "%output"
3988 ** xxdiff "%original" "%baseline" "%merge" -M "%output"
3989 ** meld "%baseline" "%original" "%merge" "%output"
3990 */
3991 /*
3992 ** SETTING: hash-digits width=5 default=10
3993 ** The number of hexadecimal digits of the SHA3 hash to display.
3994 */
@@ -4060,11 +4074,11 @@
4060 ** check-in lock mechanism is only effective if all users are auto-syncing
4061 ** to the same server.
4062 **
4063 ** Check-in locks are an advisory mechanism designed to help prevent
4064 ** accidental forks due to a check-in race in installations where many
4065 ** user are committing to the same branch and auto-sync is enabled.
4066 ** As forks are harmless, there is no danger in disabling this mechanism.
4067 ** However, keeping check-in locks turned on can help prevent unnecessary
4068 ** confusion.
4069 */
4070 /*
@@ -4453,14 +4467,14 @@
4453 }
4454 if( globalFlag && isManifest ){
4455 fossil_fatal("cannot set 'manifest' globally");
4456 }
4457 if( unsetFlag ){
4458 db_unset(pSetting->name, globalFlag);
4459 }else{
4460 db_protect_only(PROTECT_NONE);
4461 db_set(pSetting->name, g.argv[3], globalFlag);
4462 db_protect_pop();
4463 }
4464 if( isManifest && g.localOpen ){
4465 manifest_to_disk(db_lget_int("checkout", 0));
4466 }
4467
--- src/db.c
+++ src/db.c
@@ -3321,10 +3321,15 @@
3321 void db_lset_int(const char *zName, int value){
3322 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
3323 }
3324
3325 /* Va-args versions of db_get(), db_set(), and db_unset()
3326 **
3327 ** codecheck1.c verifies that the format string for db_set_mprintf()
3328 ** and db_unset_mprintf() begins with an ASCII character prefix. We
3329 ** don't want that format string to begin with %s or %d as that might
3330 ** allow an injection attack to set or overwrite arbitrary settings.
3331 */
3332 char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
3333 va_list ap;
3334 char *zName;
3335 char *zResult;
@@ -3339,20 +3344,20 @@
3344 va_list ap;
3345 char *zName;
3346 va_start(ap, zFormat);
3347 zName = vmprintf(zFormat, ap);
3348 va_end(ap);
3349 db_set(zName/*works-like:"x"*/, zNew, iGlobal);
3350 fossil_free(zName);
3351 }
3352 void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
3353 va_list ap;
3354 char *zName;
3355 va_start(ap, zFormat);
3356 zName = vmprintf(zFormat, ap);
3357 va_end(ap);
3358 db_unset(zName/*works-like:"x"*/, iGlobal);
3359 fossil_free(zName);
3360 }
3361
3362
3363
@@ -3498,10 +3503,11 @@
3503 ** -f|--force Continue with the open even if the working directory is
3504 ** not empty.
3505 ** --force-missing Force opening a repository with missing content
3506 ** --keep Only modify the manifest and manifest.uuid files
3507 ** --nested Allow opening a repository inside an opened checkout
3508 ** --nosync Do not auto-sync the repository prior to opening
3509 ** --repodir DIR If REPOSITORY is a URI that will be cloned, store
3510 ** the clone in DIR rather than in "."
3511 ** --setmtime Set timestamps of all files to match their SCM-side
3512 ** times (the timestamp of the last checkin which modified
3513 ** them).
@@ -3522,10 +3528,11 @@
3528 const char *zRepo = 0; /* Name of the repository file */
3529 const char *zRepoDir = 0; /* --repodir value */
3530 char *zPwd; /* Initial working directory */
3531 int isUri = 0; /* True if REPOSITORY is a URI */
3532 int nLocal; /* Number of preexisting files in cwd */
3533 int bNosync = 0; /* --nosync. Omit auto-sync */
3534
3535 url_proxy_options();
3536 emptyFlag = find_option("empty",0,0)!=0;
3537 keepFlag = find_option("keep",0,0)!=0;
3538 forceMissingFlag = find_option("force-missing",0,0)!=0;
@@ -3532,10 +3539,11 @@
3539 allowNested = find_option("nested",0,0)!=0;
3540 setmtimeFlag = find_option("setmtime",0,0)!=0;
3541 zWorkDir = find_option("workdir",0,1);
3542 zRepoDir = find_option("repodir",0,1);
3543 bForce = find_option("force","f",0)!=0;
3544 bNosync = find_option("nosync",0,0)!=0;
3545 zPwd = file_getcwd(0,0);
3546
3547
3548 /* We should be done with options.. */
3549 verify_all_options();
@@ -3599,14 +3607,14 @@
3607 }
3608 if( zRepoDir==0 ) zRepoDir = zPwd;
3609 zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
3610 fossil_free(zNewBase);
3611 blob_init(&cmd, 0, 0);
3612 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
3613 blob_append(&cmd, " clone", -1);
3614 blob_append_escaped_arg(&cmd, zUri, 1);
3615 blob_append_escaped_arg(&cmd, zRepo, 1);
3616 zCmd = blob_str(&cmd);
3617 fossil_print("%s\n", zCmd);
3618 if( zWorkDir ) file_chdir(zPwd, 0);
3619 rc = fossil_system(zCmd);
3620 if( rc ){
@@ -3627,10 +3635,16 @@
3635 if( g.argc==4 ){
3636 g.zOpenRevision = g.argv[3];
3637 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
3638 g.zOpenRevision = db_get("main-branch", 0);
3639 }
3640 if( !bNosync
3641 && autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1), 1)
3642 && !bForce
3643 ){
3644 fossil_fatal("unable to auto-sync the repository");
3645 }
3646 }
3647
3648
3649 #if defined(_WIN32) || defined(__CYGWIN__)
3650 # define LOCALDB_NAME "./_FOSSIL_"
@@ -3984,11 +3998,11 @@
3998 ** The value is a graphical merge conflict resolver command operating
3999 ** on four files. Examples:
4000 **
4001 ** kdiff3 "%baseline" "%original" "%merge" -o "%output"
4002 ** xxdiff "%original" "%baseline" "%merge" -M "%output"
4003 ** meld "%baseline" "%original" "%merge" --output "%output"
4004 */
4005 /*
4006 ** SETTING: hash-digits width=5 default=10
4007 ** The number of hexadecimal digits of the SHA3 hash to display.
4008 */
@@ -4060,11 +4074,11 @@
4074 ** check-in lock mechanism is only effective if all users are auto-syncing
4075 ** to the same server.
4076 **
4077 ** Check-in locks are an advisory mechanism designed to help prevent
4078 ** accidental forks due to a check-in race in installations where many
4079 ** users are committing to the same branch and auto-sync is enabled.
4080 ** As forks are harmless, there is no danger in disabling this mechanism.
4081 ** However, keeping check-in locks turned on can help prevent unnecessary
4082 ** confusion.
4083 */
4084 /*
@@ -4453,14 +4467,14 @@
4467 }
4468 if( globalFlag && isManifest ){
4469 fossil_fatal("cannot set 'manifest' globally");
4470 }
4471 if( unsetFlag ){
4472 db_unset(pSetting->name/*works-like:"x"*/, globalFlag);
4473 }else{
4474 db_protect_only(PROTECT_NONE);
4475 db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag);
4476 db_protect_pop();
4477 }
4478 if( isManifest && g.localOpen ){
4479 manifest_to_disk(db_lget_int("checkout", 0));
4480 }
4481
+23 -9
--- src/db.c
+++ src/db.c
@@ -3321,10 +3321,15 @@
33213321
void db_lset_int(const char *zName, int value){
33223322
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
33233323
}
33243324
33253325
/* Va-args versions of db_get(), db_set(), and db_unset()
3326
+**
3327
+** codecheck1.c verifies that the format string for db_set_mprintf()
3328
+** and db_unset_mprintf() begins with an ASCII character prefix. We
3329
+** don't want that format string to begin with %s or %d as that might
3330
+** allow an injection attack to set or overwrite arbitrary settings.
33263331
*/
33273332
char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
33283333
va_list ap;
33293334
char *zName;
33303335
char *zResult;
@@ -3339,20 +3344,20 @@
33393344
va_list ap;
33403345
char *zName;
33413346
va_start(ap, zFormat);
33423347
zName = vmprintf(zFormat, ap);
33433348
va_end(ap);
3344
- db_set(zName, zNew, iGlobal);
3349
+ db_set(zName/*works-like:"x"*/, zNew, iGlobal);
33453350
fossil_free(zName);
33463351
}
33473352
void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
33483353
va_list ap;
33493354
char *zName;
33503355
va_start(ap, zFormat);
33513356
zName = vmprintf(zFormat, ap);
33523357
va_end(ap);
3353
- db_unset(zName, iGlobal);
3358
+ db_unset(zName/*works-like:"x"*/, iGlobal);
33543359
fossil_free(zName);
33553360
}
33563361
33573362
33583363
@@ -3498,10 +3503,11 @@
34983503
** -f|--force Continue with the open even if the working directory is
34993504
** not empty.
35003505
** --force-missing Force opening a repository with missing content
35013506
** --keep Only modify the manifest and manifest.uuid files
35023507
** --nested Allow opening a repository inside an opened checkout
3508
+** --nosync Do not auto-sync the repository prior to opening
35033509
** --repodir DIR If REPOSITORY is a URI that will be cloned, store
35043510
** the clone in DIR rather than in "."
35053511
** --setmtime Set timestamps of all files to match their SCM-side
35063512
** times (the timestamp of the last checkin which modified
35073513
** them).
@@ -3522,10 +3528,11 @@
35223528
const char *zRepo = 0; /* Name of the repository file */
35233529
const char *zRepoDir = 0; /* --repodir value */
35243530
char *zPwd; /* Initial working directory */
35253531
int isUri = 0; /* True if REPOSITORY is a URI */
35263532
int nLocal; /* Number of preexisting files in cwd */
3533
+ int bNosync = 0; /* --nosync. Omit auto-sync */
35273534
35283535
url_proxy_options();
35293536
emptyFlag = find_option("empty",0,0)!=0;
35303537
keepFlag = find_option("keep",0,0)!=0;
35313538
forceMissingFlag = find_option("force-missing",0,0)!=0;
@@ -3532,10 +3539,11 @@
35323539
allowNested = find_option("nested",0,0)!=0;
35333540
setmtimeFlag = find_option("setmtime",0,0)!=0;
35343541
zWorkDir = find_option("workdir",0,1);
35353542
zRepoDir = find_option("repodir",0,1);
35363543
bForce = find_option("force","f",0)!=0;
3544
+ bNosync = find_option("nosync",0,0)!=0;
35373545
zPwd = file_getcwd(0,0);
35383546
35393547
35403548
/* We should be done with options.. */
35413549
verify_all_options();
@@ -3599,14 +3607,14 @@
35993607
}
36003608
if( zRepoDir==0 ) zRepoDir = zPwd;
36013609
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
36023610
fossil_free(zNewBase);
36033611
blob_init(&cmd, 0, 0);
3604
- blob_append_escaped_arg(&cmd, g.nameOfExe);
3612
+ blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
36053613
blob_append(&cmd, " clone", -1);
3606
- blob_append_escaped_arg(&cmd, zUri);
3607
- blob_append_escaped_arg(&cmd, zRepo);
3614
+ blob_append_escaped_arg(&cmd, zUri, 1);
3615
+ blob_append_escaped_arg(&cmd, zRepo, 1);
36083616
zCmd = blob_str(&cmd);
36093617
fossil_print("%s\n", zCmd);
36103618
if( zWorkDir ) file_chdir(zPwd, 0);
36113619
rc = fossil_system(zCmd);
36123620
if( rc ){
@@ -3627,10 +3635,16 @@
36273635
if( g.argc==4 ){
36283636
g.zOpenRevision = g.argv[3];
36293637
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
36303638
g.zOpenRevision = db_get("main-branch", 0);
36313639
}
3640
+ if( !bNosync
3641
+ && autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1), 1)
3642
+ && !bForce
3643
+ ){
3644
+ fossil_fatal("unable to auto-sync the repository");
3645
+ }
36323646
}
36333647
36343648
36353649
#if defined(_WIN32) || defined(__CYGWIN__)
36363650
# define LOCALDB_NAME "./_FOSSIL_"
@@ -3984,11 +3998,11 @@
39843998
** The value is a graphical merge conflict resolver command operating
39853999
** on four files. Examples:
39864000
**
39874001
** kdiff3 "%baseline" "%original" "%merge" -o "%output"
39884002
** xxdiff "%original" "%baseline" "%merge" -M "%output"
3989
-** meld "%baseline" "%original" "%merge" "%output"
4003
+** meld "%baseline" "%original" "%merge" --output "%output"
39904004
*/
39914005
/*
39924006
** SETTING: hash-digits width=5 default=10
39934007
** The number of hexadecimal digits of the SHA3 hash to display.
39944008
*/
@@ -4060,11 +4074,11 @@
40604074
** check-in lock mechanism is only effective if all users are auto-syncing
40614075
** to the same server.
40624076
**
40634077
** Check-in locks are an advisory mechanism designed to help prevent
40644078
** accidental forks due to a check-in race in installations where many
4065
-** user are committing to the same branch and auto-sync is enabled.
4079
+** users are committing to the same branch and auto-sync is enabled.
40664080
** As forks are harmless, there is no danger in disabling this mechanism.
40674081
** However, keeping check-in locks turned on can help prevent unnecessary
40684082
** confusion.
40694083
*/
40704084
/*
@@ -4453,14 +4467,14 @@
44534467
}
44544468
if( globalFlag && isManifest ){
44554469
fossil_fatal("cannot set 'manifest' globally");
44564470
}
44574471
if( unsetFlag ){
4458
- db_unset(pSetting->name, globalFlag);
4472
+ db_unset(pSetting->name/*works-like:"x"*/, globalFlag);
44594473
}else{
44604474
db_protect_only(PROTECT_NONE);
4461
- db_set(pSetting->name, g.argv[3], globalFlag);
4475
+ db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag);
44624476
db_protect_pop();
44634477
}
44644478
if( isManifest && g.localOpen ){
44654479
manifest_to_disk(db_lget_int("checkout", 0));
44664480
}
44674481
--- src/db.c
+++ src/db.c
@@ -3321,10 +3321,15 @@
3321 void db_lset_int(const char *zName, int value){
3322 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
3323 }
3324
3325 /* Va-args versions of db_get(), db_set(), and db_unset()
 
 
 
 
 
3326 */
3327 char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
3328 va_list ap;
3329 char *zName;
3330 char *zResult;
@@ -3339,20 +3344,20 @@
3339 va_list ap;
3340 char *zName;
3341 va_start(ap, zFormat);
3342 zName = vmprintf(zFormat, ap);
3343 va_end(ap);
3344 db_set(zName, zNew, iGlobal);
3345 fossil_free(zName);
3346 }
3347 void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
3348 va_list ap;
3349 char *zName;
3350 va_start(ap, zFormat);
3351 zName = vmprintf(zFormat, ap);
3352 va_end(ap);
3353 db_unset(zName, iGlobal);
3354 fossil_free(zName);
3355 }
3356
3357
3358
@@ -3498,10 +3503,11 @@
3498 ** -f|--force Continue with the open even if the working directory is
3499 ** not empty.
3500 ** --force-missing Force opening a repository with missing content
3501 ** --keep Only modify the manifest and manifest.uuid files
3502 ** --nested Allow opening a repository inside an opened checkout
 
3503 ** --repodir DIR If REPOSITORY is a URI that will be cloned, store
3504 ** the clone in DIR rather than in "."
3505 ** --setmtime Set timestamps of all files to match their SCM-side
3506 ** times (the timestamp of the last checkin which modified
3507 ** them).
@@ -3522,10 +3528,11 @@
3522 const char *zRepo = 0; /* Name of the repository file */
3523 const char *zRepoDir = 0; /* --repodir value */
3524 char *zPwd; /* Initial working directory */
3525 int isUri = 0; /* True if REPOSITORY is a URI */
3526 int nLocal; /* Number of preexisting files in cwd */
 
3527
3528 url_proxy_options();
3529 emptyFlag = find_option("empty",0,0)!=0;
3530 keepFlag = find_option("keep",0,0)!=0;
3531 forceMissingFlag = find_option("force-missing",0,0)!=0;
@@ -3532,10 +3539,11 @@
3532 allowNested = find_option("nested",0,0)!=0;
3533 setmtimeFlag = find_option("setmtime",0,0)!=0;
3534 zWorkDir = find_option("workdir",0,1);
3535 zRepoDir = find_option("repodir",0,1);
3536 bForce = find_option("force","f",0)!=0;
 
3537 zPwd = file_getcwd(0,0);
3538
3539
3540 /* We should be done with options.. */
3541 verify_all_options();
@@ -3599,14 +3607,14 @@
3599 }
3600 if( zRepoDir==0 ) zRepoDir = zPwd;
3601 zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
3602 fossil_free(zNewBase);
3603 blob_init(&cmd, 0, 0);
3604 blob_append_escaped_arg(&cmd, g.nameOfExe);
3605 blob_append(&cmd, " clone", -1);
3606 blob_append_escaped_arg(&cmd, zUri);
3607 blob_append_escaped_arg(&cmd, zRepo);
3608 zCmd = blob_str(&cmd);
3609 fossil_print("%s\n", zCmd);
3610 if( zWorkDir ) file_chdir(zPwd, 0);
3611 rc = fossil_system(zCmd);
3612 if( rc ){
@@ -3627,10 +3635,16 @@
3627 if( g.argc==4 ){
3628 g.zOpenRevision = g.argv[3];
3629 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
3630 g.zOpenRevision = db_get("main-branch", 0);
3631 }
 
 
 
 
 
 
3632 }
3633
3634
3635 #if defined(_WIN32) || defined(__CYGWIN__)
3636 # define LOCALDB_NAME "./_FOSSIL_"
@@ -3984,11 +3998,11 @@
3984 ** The value is a graphical merge conflict resolver command operating
3985 ** on four files. Examples:
3986 **
3987 ** kdiff3 "%baseline" "%original" "%merge" -o "%output"
3988 ** xxdiff "%original" "%baseline" "%merge" -M "%output"
3989 ** meld "%baseline" "%original" "%merge" "%output"
3990 */
3991 /*
3992 ** SETTING: hash-digits width=5 default=10
3993 ** The number of hexadecimal digits of the SHA3 hash to display.
3994 */
@@ -4060,11 +4074,11 @@
4060 ** check-in lock mechanism is only effective if all users are auto-syncing
4061 ** to the same server.
4062 **
4063 ** Check-in locks are an advisory mechanism designed to help prevent
4064 ** accidental forks due to a check-in race in installations where many
4065 ** user are committing to the same branch and auto-sync is enabled.
4066 ** As forks are harmless, there is no danger in disabling this mechanism.
4067 ** However, keeping check-in locks turned on can help prevent unnecessary
4068 ** confusion.
4069 */
4070 /*
@@ -4453,14 +4467,14 @@
4453 }
4454 if( globalFlag && isManifest ){
4455 fossil_fatal("cannot set 'manifest' globally");
4456 }
4457 if( unsetFlag ){
4458 db_unset(pSetting->name, globalFlag);
4459 }else{
4460 db_protect_only(PROTECT_NONE);
4461 db_set(pSetting->name, g.argv[3], globalFlag);
4462 db_protect_pop();
4463 }
4464 if( isManifest && g.localOpen ){
4465 manifest_to_disk(db_lget_int("checkout", 0));
4466 }
4467
--- src/db.c
+++ src/db.c
@@ -3321,10 +3321,15 @@
3321 void db_lset_int(const char *zName, int value){
3322 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
3323 }
3324
3325 /* Va-args versions of db_get(), db_set(), and db_unset()
3326 **
3327 ** codecheck1.c verifies that the format string for db_set_mprintf()
3328 ** and db_unset_mprintf() begins with an ASCII character prefix. We
3329 ** don't want that format string to begin with %s or %d as that might
3330 ** allow an injection attack to set or overwrite arbitrary settings.
3331 */
3332 char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){
3333 va_list ap;
3334 char *zName;
3335 char *zResult;
@@ -3339,20 +3344,20 @@
3344 va_list ap;
3345 char *zName;
3346 va_start(ap, zFormat);
3347 zName = vmprintf(zFormat, ap);
3348 va_end(ap);
3349 db_set(zName/*works-like:"x"*/, zNew, iGlobal);
3350 fossil_free(zName);
3351 }
3352 void db_unset_mprintf(int iGlobal, const char *zFormat, ...){
3353 va_list ap;
3354 char *zName;
3355 va_start(ap, zFormat);
3356 zName = vmprintf(zFormat, ap);
3357 va_end(ap);
3358 db_unset(zName/*works-like:"x"*/, iGlobal);
3359 fossil_free(zName);
3360 }
3361
3362
3363
@@ -3498,10 +3503,11 @@
3503 ** -f|--force Continue with the open even if the working directory is
3504 ** not empty.
3505 ** --force-missing Force opening a repository with missing content
3506 ** --keep Only modify the manifest and manifest.uuid files
3507 ** --nested Allow opening a repository inside an opened checkout
3508 ** --nosync Do not auto-sync the repository prior to opening
3509 ** --repodir DIR If REPOSITORY is a URI that will be cloned, store
3510 ** the clone in DIR rather than in "."
3511 ** --setmtime Set timestamps of all files to match their SCM-side
3512 ** times (the timestamp of the last checkin which modified
3513 ** them).
@@ -3522,10 +3528,11 @@
3528 const char *zRepo = 0; /* Name of the repository file */
3529 const char *zRepoDir = 0; /* --repodir value */
3530 char *zPwd; /* Initial working directory */
3531 int isUri = 0; /* True if REPOSITORY is a URI */
3532 int nLocal; /* Number of preexisting files in cwd */
3533 int bNosync = 0; /* --nosync. Omit auto-sync */
3534
3535 url_proxy_options();
3536 emptyFlag = find_option("empty",0,0)!=0;
3537 keepFlag = find_option("keep",0,0)!=0;
3538 forceMissingFlag = find_option("force-missing",0,0)!=0;
@@ -3532,10 +3539,11 @@
3539 allowNested = find_option("nested",0,0)!=0;
3540 setmtimeFlag = find_option("setmtime",0,0)!=0;
3541 zWorkDir = find_option("workdir",0,1);
3542 zRepoDir = find_option("repodir",0,1);
3543 bForce = find_option("force","f",0)!=0;
3544 bNosync = find_option("nosync",0,0)!=0;
3545 zPwd = file_getcwd(0,0);
3546
3547
3548 /* We should be done with options.. */
3549 verify_all_options();
@@ -3599,14 +3607,14 @@
3607 }
3608 if( zRepoDir==0 ) zRepoDir = zPwd;
3609 zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
3610 fossil_free(zNewBase);
3611 blob_init(&cmd, 0, 0);
3612 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
3613 blob_append(&cmd, " clone", -1);
3614 blob_append_escaped_arg(&cmd, zUri, 1);
3615 blob_append_escaped_arg(&cmd, zRepo, 1);
3616 zCmd = blob_str(&cmd);
3617 fossil_print("%s\n", zCmd);
3618 if( zWorkDir ) file_chdir(zPwd, 0);
3619 rc = fossil_system(zCmd);
3620 if( rc ){
@@ -3627,10 +3635,16 @@
3635 if( g.argc==4 ){
3636 g.zOpenRevision = g.argv[3];
3637 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
3638 g.zOpenRevision = db_get("main-branch", 0);
3639 }
3640 if( !bNosync
3641 && autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1), 1)
3642 && !bForce
3643 ){
3644 fossil_fatal("unable to auto-sync the repository");
3645 }
3646 }
3647
3648
3649 #if defined(_WIN32) || defined(__CYGWIN__)
3650 # define LOCALDB_NAME "./_FOSSIL_"
@@ -3984,11 +3998,11 @@
3998 ** The value is a graphical merge conflict resolver command operating
3999 ** on four files. Examples:
4000 **
4001 ** kdiff3 "%baseline" "%original" "%merge" -o "%output"
4002 ** xxdiff "%original" "%baseline" "%merge" -M "%output"
4003 ** meld "%baseline" "%original" "%merge" --output "%output"
4004 */
4005 /*
4006 ** SETTING: hash-digits width=5 default=10
4007 ** The number of hexadecimal digits of the SHA3 hash to display.
4008 */
@@ -4060,11 +4074,11 @@
4074 ** check-in lock mechanism is only effective if all users are auto-syncing
4075 ** to the same server.
4076 **
4077 ** Check-in locks are an advisory mechanism designed to help prevent
4078 ** accidental forks due to a check-in race in installations where many
4079 ** users are committing to the same branch and auto-sync is enabled.
4080 ** As forks are harmless, there is no danger in disabling this mechanism.
4081 ** However, keeping check-in locks turned on can help prevent unnecessary
4082 ** confusion.
4083 */
4084 /*
@@ -4453,14 +4467,14 @@
4467 }
4468 if( globalFlag && isManifest ){
4469 fossil_fatal("cannot set 'manifest' globally");
4470 }
4471 if( unsetFlag ){
4472 db_unset(pSetting->name/*works-like:"x"*/, globalFlag);
4473 }else{
4474 db_protect_only(PROTECT_NONE);
4475 db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag);
4476 db_protect_pop();
4477 }
4478 if( isManifest && g.localOpen ){
4479 manifest_to_disk(db_lget_int("checkout", 0));
4480 }
4481
--- src/default.css
+++ src/default.css
@@ -1795,10 +1795,14 @@
17951795
display: none;
17961796
}
17971797
body.branch .submenu > a.timeline-link.selected {
17981798
display: inline;
17991799
}
1800
+
1801
+.monospace {
1802
+ font-family: monospace;
1803
+}
18001804
18011805
/* Objects in the "desktoponly" class are invisible on mobile */
18021806
@media screen and (max-width: 600px) {
18031807
.desktoponly {
18041808
display: none;
18051809
--- src/default.css
+++ src/default.css
@@ -1795,10 +1795,14 @@
1795 display: none;
1796 }
1797 body.branch .submenu > a.timeline-link.selected {
1798 display: inline;
1799 }
 
 
 
 
1800
1801 /* Objects in the "desktoponly" class are invisible on mobile */
1802 @media screen and (max-width: 600px) {
1803 .desktoponly {
1804 display: none;
1805
--- src/default.css
+++ src/default.css
@@ -1795,10 +1795,14 @@
1795 display: none;
1796 }
1797 body.branch .submenu > a.timeline-link.selected {
1798 display: inline;
1799 }
1800
1801 .monospace {
1802 font-family: monospace;
1803 }
1804
1805 /* Objects in the "desktoponly" class are invisible on mobile */
1806 @media screen and (max-width: 600px) {
1807 .desktoponly {
1808 display: none;
1809
+6 -6
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -271,15 +271,15 @@
271271
272272
/* Construct the external diff command */
273273
blob_zero(&cmd);
274274
blob_append(&cmd, zDiffCmd, -1);
275275
if( fSwapDiff ){
276
- blob_append_escaped_arg(&cmd, zFile2);
277
- blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
276
+ blob_append_escaped_arg(&cmd, zFile2, 1);
277
+ blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1);
278278
}else{
279
- blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
280
- blob_append_escaped_arg(&cmd, zFile2);
279
+ blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1);
280
+ blob_append_escaped_arg(&cmd, zFile2, 1);
281281
}
282282
283283
/* Run the external diff command */
284284
fossil_system(blob_str(&cmd));
285285
@@ -357,12 +357,12 @@
357357
blob_write_to_file(pFile2, blob_str(&temp2));
358358
359359
/* Construct the external diff command */
360360
blob_zero(&cmd);
361361
blob_append(&cmd, zDiffCmd, -1);
362
- blob_append_escaped_arg(&cmd, blob_str(&temp1));
363
- blob_append_escaped_arg(&cmd, blob_str(&temp2));
362
+ blob_append_escaped_arg(&cmd, blob_str(&temp1), 1);
363
+ blob_append_escaped_arg(&cmd, blob_str(&temp2), 1);
364364
365365
/* Run the external diff command */
366366
fossil_system(blob_str(&cmd));
367367
368368
/* Delete the temporary file and clean up memory used */
369369
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -271,15 +271,15 @@
271
272 /* Construct the external diff command */
273 blob_zero(&cmd);
274 blob_append(&cmd, zDiffCmd, -1);
275 if( fSwapDiff ){
276 blob_append_escaped_arg(&cmd, zFile2);
277 blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
278 }else{
279 blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
280 blob_append_escaped_arg(&cmd, zFile2);
281 }
282
283 /* Run the external diff command */
284 fossil_system(blob_str(&cmd));
285
@@ -357,12 +357,12 @@
357 blob_write_to_file(pFile2, blob_str(&temp2));
358
359 /* Construct the external diff command */
360 blob_zero(&cmd);
361 blob_append(&cmd, zDiffCmd, -1);
362 blob_append_escaped_arg(&cmd, blob_str(&temp1));
363 blob_append_escaped_arg(&cmd, blob_str(&temp2));
364
365 /* Run the external diff command */
366 fossil_system(blob_str(&cmd));
367
368 /* Delete the temporary file and clean up memory used */
369
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -271,15 +271,15 @@
271
272 /* Construct the external diff command */
273 blob_zero(&cmd);
274 blob_append(&cmd, zDiffCmd, -1);
275 if( fSwapDiff ){
276 blob_append_escaped_arg(&cmd, zFile2, 1);
277 blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1);
278 }else{
279 blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1);
280 blob_append_escaped_arg(&cmd, zFile2, 1);
281 }
282
283 /* Run the external diff command */
284 fossil_system(blob_str(&cmd));
285
@@ -357,12 +357,12 @@
357 blob_write_to_file(pFile2, blob_str(&temp2));
358
359 /* Construct the external diff command */
360 blob_zero(&cmd);
361 blob_append(&cmd, zDiffCmd, -1);
362 blob_append_escaped_arg(&cmd, blob_str(&temp1), 1);
363 blob_append_escaped_arg(&cmd, blob_str(&temp2), 1);
364
365 /* Run the external diff command */
366 fossil_system(blob_str(&cmd));
367
368 /* Delete the temporary file and clean up memory used */
369
+77 -66
--- src/dispatch.c
+++ src/dispatch.c
@@ -565,11 +565,13 @@
565565
fossil_print("%s\n\n", aCommand[i].zHelp);
566566
}else{
567567
Blob txt;
568568
blob_init(&txt, 0, 0);
569569
help_to_text(aCommand[i].zHelp, &txt);
570
- fossil_print("# %s\n", aCommand[i].zName);
570
+ fossil_print("# %s%s\n", aCommand[i].zName,
571
+ (aCommand[i].eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ?
572
+ " (versionable)" : "");
571573
fossil_print("%s\n\n", blob_str(&txt));
572574
blob_reset(&txt);
573575
}
574576
}
575577
if( useHtml ){
@@ -975,21 +977,22 @@
975977
976978
977979
/*
978980
** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
979981
*/
980
-static void command_list(const char *zPrefix, int cmdMask){
981
- int i, nCmd;
982
- int nPrefix = zPrefix ? strlen(zPrefix) : 0;
983
- const char *aCmd[MX_COMMAND];
984
- for(i=nCmd=0; i<MX_COMMAND; i++){
985
- const char *z = aCommand[i].zName;
986
- if( (aCommand[i].eCmdFlags & cmdMask)==0 ) continue;
987
- if( zPrefix && memcmp(zPrefix, z, nPrefix)!=0 ) continue;
988
- aCmd[nCmd++] = aCommand[i].zName;
989
- }
990
- multi_column_list(aCmd, nCmd);
982
+static void command_list(int cmdMask, int verboseFlag, int useHtml){
983
+ if( verboseFlag ){
984
+ display_all_help(cmdMask, useHtml, 0);
985
+ }else{
986
+ int i, nCmd;
987
+ const char *aCmd[MX_COMMAND];
988
+ for(i=nCmd=0; i<MX_COMMAND; i++){
989
+ if( (aCommand[i].eCmdFlags & cmdMask)==0 ) continue;
990
+ aCmd[nCmd++] = aCommand[i].zName;
991
+ }
992
+ multi_column_list(aCmd, nCmd);
993
+ }
991994
}
992995
993996
/*
994997
** Documentation on universal command-line options.
995998
*/
@@ -1030,10 +1033,11 @@
10301033
**
10311034
** -a|--all List both common and auxiliary commands
10321035
** -o|--options List command-line options common to all commands
10331036
** -s|--setting List setting names
10341037
** -t|--test List unsupported "test" commands
1038
+** -v|--verbose List both names and help text
10351039
** -x|--aux List only auxiliary commands
10361040
** -w|--www List all web pages
10371041
** -f|--full List full set of commands (including auxiliary
10381042
** and unsupported "test" commands), options,
10391043
** settings, and web pages
@@ -1046,76 +1050,83 @@
10461050
*/
10471051
void help_cmd(void){
10481052
int rc;
10491053
int mask = CMDFLAG_ANY;
10501054
int isPage = 0;
1055
+ int verboseFlag = 0;
1056
+ int commandsFlag = 0;
10511057
const char *z;
10521058
const char *zCmdOrPage;
10531059
const CmdOrPage *pCmd = 0;
10541060
int useHtml = 0;
1061
+ const char *zTopic;
10551062
Blob txt;
1063
+ verboseFlag = find_option("verbose","v",0)!=0;
1064
+ commandsFlag = find_option("commands","c",0)!=0;
1065
+ useHtml = find_option("html","h",0)!=0;
1066
+ if( find_option("options","o",0) ){
1067
+ fossil_print("%s", zOptions);
1068
+ return;
1069
+ }
1070
+ else if( find_option("all","a",0) ){
1071
+ command_list(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1072
+ return;
1073
+ }
1074
+ else if( find_option("www","w",0) ){
1075
+ command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
1076
+ return;
1077
+ }
1078
+ else if( find_option("aux","x",0) ){
1079
+ command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1080
+ return;
1081
+ }
1082
+ else if( find_option("test","t",0) ){
1083
+ command_list(CMDFLAG_TEST, verboseFlag, useHtml);
1084
+ return;
1085
+ }
1086
+ else if( find_option("setting","s",0) ){
1087
+ command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1088
+ return;
1089
+ }
1090
+ else if( find_option("full","f",0) ){
1091
+ fossil_print("fossil commands:\n\n");
1092
+ command_list(CMDFLAG_1ST_TIER, verboseFlag, useHtml);
1093
+ fossil_print("\nfossil auxiliary commands:\n\n");
1094
+ command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1095
+ fossil_print("\n%s", zOptions);
1096
+ fossil_print("\nfossil settings:\n\n");
1097
+ command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1098
+ fossil_print("\nfossil web pages:\n\n");
1099
+ command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
1100
+ fossil_print("\nfossil test commands (unsupported):\n\n");
1101
+ command_list(CMDFLAG_TEST, verboseFlag, useHtml);
1102
+ fossil_print("\n");
1103
+ version_cmd();
1104
+ return;
1105
+ }
1106
+ else if( find_option("everything","e",0) ){
1107
+ display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1108
+ CMDFLAG_SETTING | CMDFLAG_TEST, useHtml, 0);
1109
+ return;
1110
+ }
1111
+ verify_all_options();
10561112
if( g.argc<3 ){
10571113
z = g.argv[0];
10581114
fossil_print(
10591115
"Usage: %s help TOPIC\n"
10601116
"Try \"%s help help\" or \"%s help -a\" for more options\n"
10611117
"Frequently used commands:\n",
10621118
z, z, z);
1063
- command_list(0, CMDFLAG_1ST_TIER);
1064
- version_cmd();
1065
- return;
1066
- }
1067
- if( find_option("options","o",0) ){
1068
- fossil_print("%s", zOptions);
1069
- return;
1070
- }
1071
- else if( find_option("all","a",0) ){
1072
- command_list(0, CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER);
1073
- return;
1074
- }
1075
- else if( find_option("www","w",0) ){
1076
- command_list(0, CMDFLAG_WEBPAGE);
1077
- return;
1078
- }
1079
- else if( find_option("aux","x",0) ){
1080
- command_list(0, CMDFLAG_2ND_TIER);
1081
- return;
1082
- }
1083
- else if( find_option("test","t",0) ){
1084
- command_list(0, CMDFLAG_TEST);
1085
- return;
1086
- }
1087
- else if( find_option("setting","s",0) ){
1088
- command_list(0, CMDFLAG_SETTING);
1089
- return;
1090
- }
1091
- else if( find_option("full","f",0) ){
1092
- fossil_print("fossil commands:\n\n");
1093
- command_list(0, CMDFLAG_1ST_TIER);
1094
- fossil_print("\nfossil auxiliary commands:\n\n");
1095
- command_list(0, CMDFLAG_2ND_TIER);
1096
- fossil_print("\n%s", zOptions);
1097
- fossil_print("\nfossil settings:\n\n");
1098
- command_list(0, CMDFLAG_SETTING);
1099
- fossil_print("\nfossil web pages:\n\n");
1100
- command_list(0, CMDFLAG_WEBPAGE);
1101
- fossil_print("\nfossil test commands (unsupported):\n\n");
1102
- command_list(0, CMDFLAG_TEST);
1103
- fossil_print("\n");
1104
- version_cmd();
1105
- return;
1106
- }
1107
- else if( find_option("everything","e",0) ){
1108
- display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1109
- CMDFLAG_SETTING | CMDFLAG_TEST, 0, 0);
1110
- return;
1111
- }
1112
- useHtml = find_option("html","h",0)!=0;
1113
- isPage = ('/' == *g.argv[2]) ? 1 : 0;
1114
- if(isPage){
1115
- zCmdOrPage = "page";
1116
- }else if( find_option("commands","c",0)!=0 ){
1119
+ command_list(CMDFLAG_1ST_TIER,verboseFlag,useHtml);
1120
+ if( !verboseFlag ) version_cmd();
1121
+ return;
1122
+ }
1123
+ zTopic = g.argv[2];
1124
+ isPage = ('/' == zTopic[0]) ? 1 : 0;
1125
+ if(isPage){
1126
+ zCmdOrPage = "page";
1127
+ }else if( commandsFlag ){
11171128
mask = CMDFLAG_COMMAND;
11181129
zCmdOrPage = "command";
11191130
}else{
11201131
zCmdOrPage = "command or setting";
11211132
}
11221133
--- src/dispatch.c
+++ src/dispatch.c
@@ -565,11 +565,13 @@
565 fossil_print("%s\n\n", aCommand[i].zHelp);
566 }else{
567 Blob txt;
568 blob_init(&txt, 0, 0);
569 help_to_text(aCommand[i].zHelp, &txt);
570 fossil_print("# %s\n", aCommand[i].zName);
 
 
571 fossil_print("%s\n\n", blob_str(&txt));
572 blob_reset(&txt);
573 }
574 }
575 if( useHtml ){
@@ -975,21 +977,22 @@
975
976
977 /*
978 ** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
979 */
980 static void command_list(const char *zPrefix, int cmdMask){
981 int i, nCmd;
982 int nPrefix = zPrefix ? strlen(zPrefix) : 0;
983 const char *aCmd[MX_COMMAND];
984 for(i=nCmd=0; i<MX_COMMAND; i++){
985 const char *z = aCommand[i].zName;
986 if( (aCommand[i].eCmdFlags & cmdMask)==0 ) continue;
987 if( zPrefix && memcmp(zPrefix, z, nPrefix)!=0 ) continue;
988 aCmd[nCmd++] = aCommand[i].zName;
989 }
990 multi_column_list(aCmd, nCmd);
 
991 }
992
993 /*
994 ** Documentation on universal command-line options.
995 */
@@ -1030,10 +1033,11 @@
1030 **
1031 ** -a|--all List both common and auxiliary commands
1032 ** -o|--options List command-line options common to all commands
1033 ** -s|--setting List setting names
1034 ** -t|--test List unsupported "test" commands
 
1035 ** -x|--aux List only auxiliary commands
1036 ** -w|--www List all web pages
1037 ** -f|--full List full set of commands (including auxiliary
1038 ** and unsupported "test" commands), options,
1039 ** settings, and web pages
@@ -1046,76 +1050,83 @@
1046 */
1047 void help_cmd(void){
1048 int rc;
1049 int mask = CMDFLAG_ANY;
1050 int isPage = 0;
 
 
1051 const char *z;
1052 const char *zCmdOrPage;
1053 const CmdOrPage *pCmd = 0;
1054 int useHtml = 0;
 
1055 Blob txt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1056 if( g.argc<3 ){
1057 z = g.argv[0];
1058 fossil_print(
1059 "Usage: %s help TOPIC\n"
1060 "Try \"%s help help\" or \"%s help -a\" for more options\n"
1061 "Frequently used commands:\n",
1062 z, z, z);
1063 command_list(0, CMDFLAG_1ST_TIER);
1064 version_cmd();
1065 return;
1066 }
1067 if( find_option("options","o",0) ){
1068 fossil_print("%s", zOptions);
1069 return;
1070 }
1071 else if( find_option("all","a",0) ){
1072 command_list(0, CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER);
1073 return;
1074 }
1075 else if( find_option("www","w",0) ){
1076 command_list(0, CMDFLAG_WEBPAGE);
1077 return;
1078 }
1079 else if( find_option("aux","x",0) ){
1080 command_list(0, CMDFLAG_2ND_TIER);
1081 return;
1082 }
1083 else if( find_option("test","t",0) ){
1084 command_list(0, CMDFLAG_TEST);
1085 return;
1086 }
1087 else if( find_option("setting","s",0) ){
1088 command_list(0, CMDFLAG_SETTING);
1089 return;
1090 }
1091 else if( find_option("full","f",0) ){
1092 fossil_print("fossil commands:\n\n");
1093 command_list(0, CMDFLAG_1ST_TIER);
1094 fossil_print("\nfossil auxiliary commands:\n\n");
1095 command_list(0, CMDFLAG_2ND_TIER);
1096 fossil_print("\n%s", zOptions);
1097 fossil_print("\nfossil settings:\n\n");
1098 command_list(0, CMDFLAG_SETTING);
1099 fossil_print("\nfossil web pages:\n\n");
1100 command_list(0, CMDFLAG_WEBPAGE);
1101 fossil_print("\nfossil test commands (unsupported):\n\n");
1102 command_list(0, CMDFLAG_TEST);
1103 fossil_print("\n");
1104 version_cmd();
1105 return;
1106 }
1107 else if( find_option("everything","e",0) ){
1108 display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1109 CMDFLAG_SETTING | CMDFLAG_TEST, 0, 0);
1110 return;
1111 }
1112 useHtml = find_option("html","h",0)!=0;
1113 isPage = ('/' == *g.argv[2]) ? 1 : 0;
1114 if(isPage){
1115 zCmdOrPage = "page";
1116 }else if( find_option("commands","c",0)!=0 ){
1117 mask = CMDFLAG_COMMAND;
1118 zCmdOrPage = "command";
1119 }else{
1120 zCmdOrPage = "command or setting";
1121 }
1122
--- src/dispatch.c
+++ src/dispatch.c
@@ -565,11 +565,13 @@
565 fossil_print("%s\n\n", aCommand[i].zHelp);
566 }else{
567 Blob txt;
568 blob_init(&txt, 0, 0);
569 help_to_text(aCommand[i].zHelp, &txt);
570 fossil_print("# %s%s\n", aCommand[i].zName,
571 (aCommand[i].eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ?
572 " (versionable)" : "");
573 fossil_print("%s\n\n", blob_str(&txt));
574 blob_reset(&txt);
575 }
576 }
577 if( useHtml ){
@@ -975,21 +977,22 @@
977
978
979 /*
980 ** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
981 */
982 static void command_list(int cmdMask, int verboseFlag, int useHtml){
983 if( verboseFlag ){
984 display_all_help(cmdMask, useHtml, 0);
985 }else{
986 int i, nCmd;
987 const char *aCmd[MX_COMMAND];
988 for(i=nCmd=0; i<MX_COMMAND; i++){
989 if( (aCommand[i].eCmdFlags & cmdMask)==0 ) continue;
990 aCmd[nCmd++] = aCommand[i].zName;
991 }
992 multi_column_list(aCmd, nCmd);
993 }
994 }
995
996 /*
997 ** Documentation on universal command-line options.
998 */
@@ -1030,10 +1033,11 @@
1033 **
1034 ** -a|--all List both common and auxiliary commands
1035 ** -o|--options List command-line options common to all commands
1036 ** -s|--setting List setting names
1037 ** -t|--test List unsupported "test" commands
1038 ** -v|--verbose List both names and help text
1039 ** -x|--aux List only auxiliary commands
1040 ** -w|--www List all web pages
1041 ** -f|--full List full set of commands (including auxiliary
1042 ** and unsupported "test" commands), options,
1043 ** settings, and web pages
@@ -1046,76 +1050,83 @@
1050 */
1051 void help_cmd(void){
1052 int rc;
1053 int mask = CMDFLAG_ANY;
1054 int isPage = 0;
1055 int verboseFlag = 0;
1056 int commandsFlag = 0;
1057 const char *z;
1058 const char *zCmdOrPage;
1059 const CmdOrPage *pCmd = 0;
1060 int useHtml = 0;
1061 const char *zTopic;
1062 Blob txt;
1063 verboseFlag = find_option("verbose","v",0)!=0;
1064 commandsFlag = find_option("commands","c",0)!=0;
1065 useHtml = find_option("html","h",0)!=0;
1066 if( find_option("options","o",0) ){
1067 fossil_print("%s", zOptions);
1068 return;
1069 }
1070 else if( find_option("all","a",0) ){
1071 command_list(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1072 return;
1073 }
1074 else if( find_option("www","w",0) ){
1075 command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
1076 return;
1077 }
1078 else if( find_option("aux","x",0) ){
1079 command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1080 return;
1081 }
1082 else if( find_option("test","t",0) ){
1083 command_list(CMDFLAG_TEST, verboseFlag, useHtml);
1084 return;
1085 }
1086 else if( find_option("setting","s",0) ){
1087 command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1088 return;
1089 }
1090 else if( find_option("full","f",0) ){
1091 fossil_print("fossil commands:\n\n");
1092 command_list(CMDFLAG_1ST_TIER, verboseFlag, useHtml);
1093 fossil_print("\nfossil auxiliary commands:\n\n");
1094 command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1095 fossil_print("\n%s", zOptions);
1096 fossil_print("\nfossil settings:\n\n");
1097 command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1098 fossil_print("\nfossil web pages:\n\n");
1099 command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
1100 fossil_print("\nfossil test commands (unsupported):\n\n");
1101 command_list(CMDFLAG_TEST, verboseFlag, useHtml);
1102 fossil_print("\n");
1103 version_cmd();
1104 return;
1105 }
1106 else if( find_option("everything","e",0) ){
1107 display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1108 CMDFLAG_SETTING | CMDFLAG_TEST, useHtml, 0);
1109 return;
1110 }
1111 verify_all_options();
1112 if( g.argc<3 ){
1113 z = g.argv[0];
1114 fossil_print(
1115 "Usage: %s help TOPIC\n"
1116 "Try \"%s help help\" or \"%s help -a\" for more options\n"
1117 "Frequently used commands:\n",
1118 z, z, z);
1119 command_list(CMDFLAG_1ST_TIER,verboseFlag,useHtml);
1120 if( !verboseFlag ) version_cmd();
1121 return;
1122 }
1123 zTopic = g.argv[2];
1124 isPage = ('/' == zTopic[0]) ? 1 : 0;
1125 if(isPage){
1126 zCmdOrPage = "page";
1127 }else if( commandsFlag ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1128 mask = CMDFLAG_COMMAND;
1129 zCmdOrPage = "command";
1130 }else{
1131 zCmdOrPage = "command or setting";
1132 }
1133
+2 -1
--- src/doc.c
+++ src/doc.c
@@ -1225,10 +1225,11 @@
12251225
** Query parameters:
12261226
**
12271227
** s=PATTERN Search for PATTERN
12281228
*/
12291229
void doc_search_page(void){
1230
+ const int isSearch = P("s")!=0;
12301231
login_check_credentials();
1231
- style_header("Document Search");
1232
+ style_header("Document Search%s", isSearch ? " Results" : "");
12321233
search_screen(SRCH_DOC, 0);
12331234
style_finish_page();
12341235
}
12351236
--- src/doc.c
+++ src/doc.c
@@ -1225,10 +1225,11 @@
1225 ** Query parameters:
1226 **
1227 ** s=PATTERN Search for PATTERN
1228 */
1229 void doc_search_page(void){
 
1230 login_check_credentials();
1231 style_header("Document Search");
1232 search_screen(SRCH_DOC, 0);
1233 style_finish_page();
1234 }
1235
--- src/doc.c
+++ src/doc.c
@@ -1225,10 +1225,11 @@
1225 ** Query parameters:
1226 **
1227 ** s=PATTERN Search for PATTERN
1228 */
1229 void doc_search_page(void){
1230 const int isSearch = P("s")!=0;
1231 login_check_credentials();
1232 style_header("Document Search%s", isSearch ? " Results" : "");
1233 search_screen(SRCH_DOC, 0);
1234 style_finish_page();
1235 }
1236
+17 -1
--- src/etag.c
+++ src/etag.c
@@ -173,10 +173,26 @@
173173
cgi_set_status(304, "Not Modified");
174174
cgi_reply();
175175
db_close(0);
176176
fossil_exit(0);
177177
}
178
+
179
+/*
180
+** If the output is determined purely by hash parameter and the hash
181
+** is long enough to be invariant, then set the g.isConst flag, indicating
182
+** that the output will never change.
183
+*/
184
+void etag_check_for_invariant_name(const char *zHash){
185
+ size_t nHash = strlen(zHash);
186
+ if( nHash<HNAME_MIN ){
187
+ return; /* Name is too short */
188
+ }
189
+ if( !validate16(zHash, (int)nHash) ){
190
+ return; /* Name is not pure hex */
191
+ }
192
+ g.isConst = 1; /* A long hex identifier must be a unique hash */
193
+}
178194
179195
/*
180196
** Accept a new Last-Modified time. This routine should be called by
181197
** page generators that know a valid last-modified time. This routine
182198
** might generate a 304 Not Modified reply and exit(), never returning.
@@ -212,11 +228,11 @@
212228
}
213229
214230
/* Return the ETag, if there is one.
215231
*/
216232
const char *etag_tag(void){
217
- return zETag;
233
+ return g.isConst ? "" : zETag;
218234
}
219235
220236
/* Return the recommended max-age
221237
*/
222238
int etag_maxage(void){
223239
--- src/etag.c
+++ src/etag.c
@@ -173,10 +173,26 @@
173 cgi_set_status(304, "Not Modified");
174 cgi_reply();
175 db_close(0);
176 fossil_exit(0);
177 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
179 /*
180 ** Accept a new Last-Modified time. This routine should be called by
181 ** page generators that know a valid last-modified time. This routine
182 ** might generate a 304 Not Modified reply and exit(), never returning.
@@ -212,11 +228,11 @@
212 }
213
214 /* Return the ETag, if there is one.
215 */
216 const char *etag_tag(void){
217 return zETag;
218 }
219
220 /* Return the recommended max-age
221 */
222 int etag_maxage(void){
223
--- src/etag.c
+++ src/etag.c
@@ -173,10 +173,26 @@
173 cgi_set_status(304, "Not Modified");
174 cgi_reply();
175 db_close(0);
176 fossil_exit(0);
177 }
178
179 /*
180 ** If the output is determined purely by hash parameter and the hash
181 ** is long enough to be invariant, then set the g.isConst flag, indicating
182 ** that the output will never change.
183 */
184 void etag_check_for_invariant_name(const char *zHash){
185 size_t nHash = strlen(zHash);
186 if( nHash<HNAME_MIN ){
187 return; /* Name is too short */
188 }
189 if( !validate16(zHash, (int)nHash) ){
190 return; /* Name is not pure hex */
191 }
192 g.isConst = 1; /* A long hex identifier must be a unique hash */
193 }
194
195 /*
196 ** Accept a new Last-Modified time. This routine should be called by
197 ** page generators that know a valid last-modified time. This routine
198 ** might generate a 304 Not Modified reply and exit(), never returning.
@@ -212,11 +228,11 @@
228 }
229
230 /* Return the ETag, if there is one.
231 */
232 const char *etag_tag(void){
233 return g.isConst ? "" : zETag;
234 }
235
236 /* Return the recommended max-age
237 */
238 int etag_maxage(void){
239
+37 -9
--- src/export.c
+++ src/export.c
@@ -38,17 +38,10 @@
3838
int rid; /* Corresponding object in the BLOB table */
3939
char uuid[65]; /* The GIT hash name for this object */
4040
};
4141
#endif
4242
43
-#if defined(_WIN32) || defined(WIN32)
44
-# undef popen
45
-# define popen _popen
46
-# undef pclose
47
-# define pclose _pclose
48
-#endif
49
-
5043
/*
5144
** Output a "committer" record for the given user.
5245
** NOTE: the given user name may be an email itself.
5346
*/
5447
static void print_person(const char *zUser){
@@ -1721,10 +1714,15 @@
17211714
fossil_free(zPushCmd);
17221715
zPushCmd = mprintf("git push --mirror %$", zPushUrl);
17231716
rc = fossil_system(zPushCmd);
17241717
if( rc ){
17251718
fossil_fatal("cannot push content using: %s", zPushCmd);
1719
+ }else if( db_is_writeable("repository") ){
1720
+ db_unprotect(PROTECT_CONFIG);
1721
+ db_multi_exec("REPLACE INTO config(name,value,mtime)"
1722
+ "VALUES('gitpush:%q',1,now())", zPushUrl);
1723
+ db_protect_pop();
17261724
}
17271725
fossil_free(zPushCmd);
17281726
}
17291727
}
17301728
@@ -1735,19 +1733,47 @@
17351733
*/
17361734
void gitmirror_status_command(void){
17371735
char *zMirror;
17381736
char *z;
17391737
int n, k;
1738
+ int rc;
1739
+ char *zSql;
1740
+ int bQuiet = 0;
1741
+ int bByAll = 0; /* Undocumented option meaning this command was invoked
1742
+ ** from "fossil all" and should modify output accordingly */
1743
+
17401744
db_find_and_open_repository(0, 0);
1745
+ bQuiet = find_option("quiet","q",0)!=0;
1746
+ bByAll = find_option("by-all",0,0)!=0;
17411747
verify_all_options();
17421748
zMirror = db_get("last-git-export-repo", 0);
17431749
if( zMirror==0 ){
1750
+ if( bQuiet ) return;
1751
+ if( bByAll ) return;
17441752
fossil_print("Git mirror: none\n");
17451753
return;
17461754
}
1755
+ zSql = sqlite3_mprintf("ATTACH '%q/.mirror_state/db' AS mirror", zMirror);
1756
+ if( zSql==0 ) fossil_fatal("out of memory");
1757
+ g.dbIgnoreErrors++;
1758
+ rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
1759
+ g.dbIgnoreErrors--;
1760
+ sqlite3_free(zSql);
1761
+ if( rc ){
1762
+ if( bQuiet ) return;
1763
+ if( bByAll ) return;
1764
+ fossil_print("Git mirror: %s (Inactive)\n", zMirror);
1765
+ return;
1766
+ }
1767
+ if( bByAll ){
1768
+ size_t len = strlen(g.zRepositoryName);
1769
+ int n;
1770
+ if( len>60 ) len = 60;
1771
+ n = (int)(65 - len);
1772
+ fossil_print("%.12c %s %.*c\n", '*', g.zRepositoryName, n, '*');
1773
+ }
17471774
fossil_print("Git mirror: %s\n", zMirror);
1748
- db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
17491775
z = db_text(0, "SELECT datetime(value) FROM mconfig WHERE key='start'");
17501776
if( z ){
17511777
double rAge = db_double(0.0, "SELECT julianday('now') - value"
17521778
" FROM mconfig WHERE key='start'");
17531779
if( rAge>1.0/86400.0 ){
@@ -1778,11 +1804,11 @@
17781804
}else{
17791805
fossil_print("Status: %d check-in%s awaiting export\n",
17801806
n, n==1 ? "" : "s");
17811807
}
17821808
n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile");
1783
- k = db_int(0, "SELECT count(*) FROm mmark WHERE NOT isfile");
1809
+ k = db_int(0, "SELECT count(*) FROM mmark WHERE NOT isfile");
17841810
fossil_print("Exported: %d check-ins and %d file blobs\n", k, n);
17851811
}
17861812
17871813
/*
17881814
** COMMAND: git*
@@ -1833,10 +1859,12 @@
18331859
** TBD...
18341860
**
18351861
** > fossil git status
18361862
**
18371863
** Show the status of the current Git mirror, if there is one.
1864
+**
1865
+** -q|--quiet No output if there is nothing to report
18381866
*/
18391867
void gitmirror_command(void){
18401868
char *zCmd;
18411869
int nCmd;
18421870
if( g.argc<3 ){
18431871
--- src/export.c
+++ src/export.c
@@ -38,17 +38,10 @@
38 int rid; /* Corresponding object in the BLOB table */
39 char uuid[65]; /* The GIT hash name for this object */
40 };
41 #endif
42
43 #if defined(_WIN32) || defined(WIN32)
44 # undef popen
45 # define popen _popen
46 # undef pclose
47 # define pclose _pclose
48 #endif
49
50 /*
51 ** Output a "committer" record for the given user.
52 ** NOTE: the given user name may be an email itself.
53 */
54 static void print_person(const char *zUser){
@@ -1721,10 +1714,15 @@
1721 fossil_free(zPushCmd);
1722 zPushCmd = mprintf("git push --mirror %$", zPushUrl);
1723 rc = fossil_system(zPushCmd);
1724 if( rc ){
1725 fossil_fatal("cannot push content using: %s", zPushCmd);
 
 
 
 
 
1726 }
1727 fossil_free(zPushCmd);
1728 }
1729 }
1730
@@ -1735,19 +1733,47 @@
1735 */
1736 void gitmirror_status_command(void){
1737 char *zMirror;
1738 char *z;
1739 int n, k;
 
 
 
 
 
 
1740 db_find_and_open_repository(0, 0);
 
 
1741 verify_all_options();
1742 zMirror = db_get("last-git-export-repo", 0);
1743 if( zMirror==0 ){
 
 
1744 fossil_print("Git mirror: none\n");
1745 return;
1746 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1747 fossil_print("Git mirror: %s\n", zMirror);
1748 db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
1749 z = db_text(0, "SELECT datetime(value) FROM mconfig WHERE key='start'");
1750 if( z ){
1751 double rAge = db_double(0.0, "SELECT julianday('now') - value"
1752 " FROM mconfig WHERE key='start'");
1753 if( rAge>1.0/86400.0 ){
@@ -1778,11 +1804,11 @@
1778 }else{
1779 fossil_print("Status: %d check-in%s awaiting export\n",
1780 n, n==1 ? "" : "s");
1781 }
1782 n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile");
1783 k = db_int(0, "SELECT count(*) FROm mmark WHERE NOT isfile");
1784 fossil_print("Exported: %d check-ins and %d file blobs\n", k, n);
1785 }
1786
1787 /*
1788 ** COMMAND: git*
@@ -1833,10 +1859,12 @@
1833 ** TBD...
1834 **
1835 ** > fossil git status
1836 **
1837 ** Show the status of the current Git mirror, if there is one.
 
 
1838 */
1839 void gitmirror_command(void){
1840 char *zCmd;
1841 int nCmd;
1842 if( g.argc<3 ){
1843
--- src/export.c
+++ src/export.c
@@ -38,17 +38,10 @@
38 int rid; /* Corresponding object in the BLOB table */
39 char uuid[65]; /* The GIT hash name for this object */
40 };
41 #endif
42
 
 
 
 
 
 
 
43 /*
44 ** Output a "committer" record for the given user.
45 ** NOTE: the given user name may be an email itself.
46 */
47 static void print_person(const char *zUser){
@@ -1721,10 +1714,15 @@
1714 fossil_free(zPushCmd);
1715 zPushCmd = mprintf("git push --mirror %$", zPushUrl);
1716 rc = fossil_system(zPushCmd);
1717 if( rc ){
1718 fossil_fatal("cannot push content using: %s", zPushCmd);
1719 }else if( db_is_writeable("repository") ){
1720 db_unprotect(PROTECT_CONFIG);
1721 db_multi_exec("REPLACE INTO config(name,value,mtime)"
1722 "VALUES('gitpush:%q',1,now())", zPushUrl);
1723 db_protect_pop();
1724 }
1725 fossil_free(zPushCmd);
1726 }
1727 }
1728
@@ -1735,19 +1733,47 @@
1733 */
1734 void gitmirror_status_command(void){
1735 char *zMirror;
1736 char *z;
1737 int n, k;
1738 int rc;
1739 char *zSql;
1740 int bQuiet = 0;
1741 int bByAll = 0; /* Undocumented option meaning this command was invoked
1742 ** from "fossil all" and should modify output accordingly */
1743
1744 db_find_and_open_repository(0, 0);
1745 bQuiet = find_option("quiet","q",0)!=0;
1746 bByAll = find_option("by-all",0,0)!=0;
1747 verify_all_options();
1748 zMirror = db_get("last-git-export-repo", 0);
1749 if( zMirror==0 ){
1750 if( bQuiet ) return;
1751 if( bByAll ) return;
1752 fossil_print("Git mirror: none\n");
1753 return;
1754 }
1755 zSql = sqlite3_mprintf("ATTACH '%q/.mirror_state/db' AS mirror", zMirror);
1756 if( zSql==0 ) fossil_fatal("out of memory");
1757 g.dbIgnoreErrors++;
1758 rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
1759 g.dbIgnoreErrors--;
1760 sqlite3_free(zSql);
1761 if( rc ){
1762 if( bQuiet ) return;
1763 if( bByAll ) return;
1764 fossil_print("Git mirror: %s (Inactive)\n", zMirror);
1765 return;
1766 }
1767 if( bByAll ){
1768 size_t len = strlen(g.zRepositoryName);
1769 int n;
1770 if( len>60 ) len = 60;
1771 n = (int)(65 - len);
1772 fossil_print("%.12c %s %.*c\n", '*', g.zRepositoryName, n, '*');
1773 }
1774 fossil_print("Git mirror: %s\n", zMirror);
 
1775 z = db_text(0, "SELECT datetime(value) FROM mconfig WHERE key='start'");
1776 if( z ){
1777 double rAge = db_double(0.0, "SELECT julianday('now') - value"
1778 " FROM mconfig WHERE key='start'");
1779 if( rAge>1.0/86400.0 ){
@@ -1778,11 +1804,11 @@
1804 }else{
1805 fossil_print("Status: %d check-in%s awaiting export\n",
1806 n, n==1 ? "" : "s");
1807 }
1808 n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile");
1809 k = db_int(0, "SELECT count(*) FROM mmark WHERE NOT isfile");
1810 fossil_print("Exported: %d check-ins and %d file blobs\n", k, n);
1811 }
1812
1813 /*
1814 ** COMMAND: git*
@@ -1833,10 +1859,12 @@
1859 ** TBD...
1860 **
1861 ** > fossil git status
1862 **
1863 ** Show the status of the current Git mirror, if there is one.
1864 **
1865 ** -q|--quiet No output if there is nothing to report
1866 */
1867 void gitmirror_command(void){
1868 char *zCmd;
1869 int nCmd;
1870 if( g.argc<3 ){
1871
--- src/extcgi.c
+++ src/extcgi.c
@@ -30,17 +30,10 @@
3030
*/
3131
#include "config.h"
3232
#include "extcgi.h"
3333
#include <assert.h>
3434
35
-#if defined(_WIN32) || defined(WIN32)
36
-# undef popen
37
-# define popen _popen
38
-# undef pclose
39
-# define pclose _pclose
40
-#endif
41
-
4235
/*
4336
** These are the environment variables that should be set for CGI
4437
** extension programs:
4538
*/
4639
static const char *azCgiEnv[] = {
4740
--- src/extcgi.c
+++ src/extcgi.c
@@ -30,17 +30,10 @@
30 */
31 #include "config.h"
32 #include "extcgi.h"
33 #include <assert.h>
34
35 #if defined(_WIN32) || defined(WIN32)
36 # undef popen
37 # define popen _popen
38 # undef pclose
39 # define pclose _pclose
40 #endif
41
42 /*
43 ** These are the environment variables that should be set for CGI
44 ** extension programs:
45 */
46 static const char *azCgiEnv[] = {
47
--- src/extcgi.c
+++ src/extcgi.c
@@ -30,17 +30,10 @@
30 */
31 #include "config.h"
32 #include "extcgi.h"
33 #include <assert.h>
34
 
 
 
 
 
 
 
35 /*
36 ** These are the environment variables that should be set for CGI
37 ** extension programs:
38 */
39 static const char *azCgiEnv[] = {
40
+127 -3
--- src/file.c
+++ src/file.c
@@ -909,10 +909,52 @@
909909
}else{
910910
rc = file_rmdir(zName);
911911
}
912912
sqlite3_result_int(context, rc);
913913
}
914
+
915
+/*
916
+** Check the input argument to see if it looks like it has an prefix that
917
+** indicates a remote file. If so, return the tail of the specification,
918
+** which is the name of the file on the remote system.
919
+**
920
+** If the input argument does not have a prefix that makes it look like
921
+** a remote file reference, then return NULL.
922
+**
923
+** Remote files look like: "HOST:PATH" or "USER@HOST:PATH". Host must
924
+** be a valid hostname, meaning it must follow these rules:
925
+**
926
+** * Only characters [-.a-zA-Z0-9]. No spaces or other punctuation
927
+** * Does not begin or end with -
928
+** * Name is two or more characters long (otherwise it might be
929
+** confused with a drive-letter on Windows).
930
+**
931
+** The USER section, if it exists, must not contain the '@' character.
932
+*/
933
+const char *file_skip_userhost(const char *zIn){
934
+ const char *zTail;
935
+ int n, i;
936
+ if( zIn[0]==':' ) return 0;
937
+ zTail = strchr(zIn, ':');
938
+ if( zTail==0 ) return 0;
939
+ if( zTail - zIn > 10000 ) return 0;
940
+ n = (int)(zTail - zIn);
941
+ if( n<2 ) return 0;
942
+ if( zIn[n-1]=='-' || zIn[n-1]=='.' ) return 0;
943
+ for(i=n-1; i>0 && zIn[i-1]!='@'; i--){
944
+ if( !fossil_isalnum(zIn[i]) && zIn[i]!='-' && zIn[i]!='.' ) return 0;
945
+ }
946
+ if( zIn[i]=='-' || zIn[i]=='.' || i==1 ) return 0;
947
+ if( i>1 ){
948
+ i -= 2;
949
+ while( i>=0 ){
950
+ if( zIn[i]=='@' ) return 0;
951
+ i--;
952
+ }
953
+ }
954
+ return zTail+1;
955
+}
914956
915957
/*
916958
** Return true if the filename given is a valid filename for
917959
** a file in a repository. Valid filenames follow all of the
918960
** following rules:
@@ -1113,17 +1155,29 @@
11131155
/*
11141156
** COMMAND: test-simplify-name
11151157
**
11161158
** Usage: %fossil test-simplify-name FILENAME...
11171159
**
1118
-** Print the simplified versions of each FILENAME.
1160
+** Print the simplified versions of each FILENAME. This is used to test
1161
+** the file_simplify_name() routine.
1162
+**
1163
+** If FILENAME is of the form "HOST:PATH" or "USER@HOST:PATH", then remove
1164
+** and print the remote host prefix first. This is used to test the
1165
+** file_skip_userhost() interface.
11191166
*/
11201167
void cmd_test_simplify_name(void){
11211168
int i;
11221169
char *z;
1170
+ const char *zTail;
11231171
for(i=2; i<g.argc; i++){
1124
- z = mprintf("%s", g.argv[i]);
1172
+ zTail = file_skip_userhost(g.argv[i]);
1173
+ if( zTail ){
1174
+ fossil_print("... ON REMOTE: %.*s\n", (int)(zTail-g.argv[i]), g.argv[i]);
1175
+ z = mprintf("%s", zTail);
1176
+ }else{
1177
+ z = mprintf("%s", g.argv[i]);
1178
+ }
11251179
fossil_print("[%s] -> ", z);
11261180
file_simplify_name(z, -1, 0);
11271181
fossil_print("[%s]\n", z);
11281182
fossil_free(z);
11291183
}
@@ -1247,10 +1301,54 @@
12471301
** This routine only works on unix. On Windows, simply return
12481302
** a copy of the input.
12491303
*/
12501304
char *file_fullexename(const char *zCmd){
12511305
#ifdef _WIN32
1306
+ char *zPath;
1307
+ char *z = 0;
1308
+ const char *zExe = "";
1309
+ if( sqlite3_strlike("%.exe",zCmd,0)!=0 ) zExe = ".exe";
1310
+ if( file_is_absolute_path(zCmd) ){
1311
+ return mprintf("%s%s", zCmd, zExe);
1312
+ }
1313
+ if( strchr(zCmd,'\\')!=0 && strchr(zCmd,'/')!=0 ){
1314
+ int i;
1315
+ Blob out = BLOB_INITIALIZER;
1316
+ file_canonical_name(zCmd, &out, 0);
1317
+ blob_append(&out, zExe, -1);
1318
+ z = fossil_strdup(blob_str(&out));
1319
+ blob_reset(&out);
1320
+ for(i=0; z[i]; i++){ if( z[i]=='/' ) z[i] = '\\'; }
1321
+ return z;
1322
+ }
1323
+ z = mprintf(".\\%s%s", zCmd, zExe);
1324
+ if( file_isfile(z, ExtFILE) ){
1325
+ int i;
1326
+ Blob out = BLOB_INITIALIZER;
1327
+ file_canonical_name(zCmd, &out, 0);
1328
+ blob_append(&out, zExe, -1);
1329
+ z = fossil_strdup(blob_str(&out));
1330
+ blob_reset(&out);
1331
+ for(i=0; z[i]; i++){ if( z[i]=='/' ) z[i] = '\\'; }
1332
+ return z;
1333
+ }
1334
+ fossil_free(z);
1335
+ zPath = fossil_getenv("PATH");
1336
+ while( zPath && zPath[0] ){
1337
+ int n;
1338
+ char *zColon;
1339
+ zColon = strchr(zPath, ';');
1340
+ n = zColon ? (int)(zColon-zPath) : (int)strlen(zPath);
1341
+ while( n>0 && zPath[n-1]=='\\' ){ n--; }
1342
+ z = mprintf("%.*s\\%s%s", n, zPath, zCmd, zExe);
1343
+ if( file_isfile(z, ExtFILE) ){
1344
+ return z;
1345
+ }
1346
+ fossil_free(z);
1347
+ if( zColon==0 ) break;
1348
+ zPath = zColon+1;
1349
+ }
12521350
return fossil_strdup(zCmd);
12531351
#else
12541352
char *zPath;
12551353
char *z;
12561354
if( zCmd[0]=='/' ){
@@ -1780,20 +1878,21 @@
17801878
** the root of zBasis in its name.
17811879
**
17821880
** If zTag is not NULL, then try to create the temp-file using zTag
17831881
** as a differentiator. If that fails, or if zTag is NULL, then use
17841882
** a bunch of random characters as the tag.
1883
+**
1884
+** Dangerous characters in zBasis are changed.
17851885
*/
17861886
void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
17871887
#if defined(_WIN32)
17881888
const char *azDirs[] = {
17891889
0, /* GetTempPath */
17901890
0, /* TEMP */
17911891
0, /* TMP */
17921892
".",
17931893
};
1794
- char *z;
17951894
#else
17961895
static const char *azDirs[] = {
17971896
0, /* TMPDIR */
17981897
"/var/tmp",
17991898
"/usr/tmp",
@@ -1810,10 +1909,11 @@
18101909
const char *zDir = ".";
18111910
int cnt = 0;
18121911
char zRand[16];
18131912
int nBasis;
18141913
const char *zSuffix;
1914
+ char *z;
18151915
18161916
#if defined(_WIN32)
18171917
wchar_t zTmpPath[MAX_PATH];
18181918
18191919
if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1868,10 +1968,13 @@
18681968
zRand[15] = 0;
18691969
zTag = zRand;
18701970
}
18711971
blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
18721972
zTag = 0;
1973
+ for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){
1974
+ z[0] = '_';
1975
+ }
18731976
}while( file_size(blob_str(pBuf), ExtFILE)>=0 );
18741977
18751978
#if defined(_WIN32)
18761979
fossil_path_free((char *)azDirs[0]);
18771980
fossil_path_free((char *)azDirs[1]);
@@ -2620,5 +2723,26 @@
26202723
for( i = 2; i < g.argc; ++i ){
26212724
const int check = file_is_reserved_name(g.argv[i], -1);
26222725
fossil_print("%d %s\n", check, g.argv[i]);
26232726
}
26242727
}
2728
+
2729
+
2730
+/*
2731
+** Returns 1 if the given directory contains a file named .fslckout, 2
2732
+** if it contains a file named _FOSSIL_, else returns 0.
2733
+*/
2734
+int dir_has_ckout_db(const char *zDir){
2735
+ int rc = 0;
2736
+ char * zCkoutDb = mprintf("%//.fslckout", zDir);
2737
+ if(file_isfile(zCkoutDb, ExtFILE)){
2738
+ rc = 1;
2739
+ }else{
2740
+ fossil_free(zCkoutDb);
2741
+ zCkoutDb = mprintf("%//_FOSSIL_", zDir);
2742
+ if(file_isfile(zCkoutDb, ExtFILE)){
2743
+ rc = 2;
2744
+ }
2745
+ }
2746
+ fossil_free(zCkoutDb);
2747
+ return rc;
2748
+}
26252749
--- src/file.c
+++ src/file.c
@@ -909,10 +909,52 @@
909 }else{
910 rc = file_rmdir(zName);
911 }
912 sqlite3_result_int(context, rc);
913 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
915 /*
916 ** Return true if the filename given is a valid filename for
917 ** a file in a repository. Valid filenames follow all of the
918 ** following rules:
@@ -1113,17 +1155,29 @@
1113 /*
1114 ** COMMAND: test-simplify-name
1115 **
1116 ** Usage: %fossil test-simplify-name FILENAME...
1117 **
1118 ** Print the simplified versions of each FILENAME.
 
 
 
 
 
1119 */
1120 void cmd_test_simplify_name(void){
1121 int i;
1122 char *z;
 
1123 for(i=2; i<g.argc; i++){
1124 z = mprintf("%s", g.argv[i]);
 
 
 
 
 
 
1125 fossil_print("[%s] -> ", z);
1126 file_simplify_name(z, -1, 0);
1127 fossil_print("[%s]\n", z);
1128 fossil_free(z);
1129 }
@@ -1247,10 +1301,54 @@
1247 ** This routine only works on unix. On Windows, simply return
1248 ** a copy of the input.
1249 */
1250 char *file_fullexename(const char *zCmd){
1251 #ifdef _WIN32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1252 return fossil_strdup(zCmd);
1253 #else
1254 char *zPath;
1255 char *z;
1256 if( zCmd[0]=='/' ){
@@ -1780,20 +1878,21 @@
1780 ** the root of zBasis in its name.
1781 **
1782 ** If zTag is not NULL, then try to create the temp-file using zTag
1783 ** as a differentiator. If that fails, or if zTag is NULL, then use
1784 ** a bunch of random characters as the tag.
 
 
1785 */
1786 void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
1787 #if defined(_WIN32)
1788 const char *azDirs[] = {
1789 0, /* GetTempPath */
1790 0, /* TEMP */
1791 0, /* TMP */
1792 ".",
1793 };
1794 char *z;
1795 #else
1796 static const char *azDirs[] = {
1797 0, /* TMPDIR */
1798 "/var/tmp",
1799 "/usr/tmp",
@@ -1810,10 +1909,11 @@
1810 const char *zDir = ".";
1811 int cnt = 0;
1812 char zRand[16];
1813 int nBasis;
1814 const char *zSuffix;
 
1815
1816 #if defined(_WIN32)
1817 wchar_t zTmpPath[MAX_PATH];
1818
1819 if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1868,10 +1968,13 @@
1868 zRand[15] = 0;
1869 zTag = zRand;
1870 }
1871 blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
1872 zTag = 0;
 
 
 
1873 }while( file_size(blob_str(pBuf), ExtFILE)>=0 );
1874
1875 #if defined(_WIN32)
1876 fossil_path_free((char *)azDirs[0]);
1877 fossil_path_free((char *)azDirs[1]);
@@ -2620,5 +2723,26 @@
2620 for( i = 2; i < g.argc; ++i ){
2621 const int check = file_is_reserved_name(g.argv[i], -1);
2622 fossil_print("%d %s\n", check, g.argv[i]);
2623 }
2624 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2625
--- src/file.c
+++ src/file.c
@@ -909,10 +909,52 @@
909 }else{
910 rc = file_rmdir(zName);
911 }
912 sqlite3_result_int(context, rc);
913 }
914
915 /*
916 ** Check the input argument to see if it looks like it has an prefix that
917 ** indicates a remote file. If so, return the tail of the specification,
918 ** which is the name of the file on the remote system.
919 **
920 ** If the input argument does not have a prefix that makes it look like
921 ** a remote file reference, then return NULL.
922 **
923 ** Remote files look like: "HOST:PATH" or "USER@HOST:PATH". Host must
924 ** be a valid hostname, meaning it must follow these rules:
925 **
926 ** * Only characters [-.a-zA-Z0-9]. No spaces or other punctuation
927 ** * Does not begin or end with -
928 ** * Name is two or more characters long (otherwise it might be
929 ** confused with a drive-letter on Windows).
930 **
931 ** The USER section, if it exists, must not contain the '@' character.
932 */
933 const char *file_skip_userhost(const char *zIn){
934 const char *zTail;
935 int n, i;
936 if( zIn[0]==':' ) return 0;
937 zTail = strchr(zIn, ':');
938 if( zTail==0 ) return 0;
939 if( zTail - zIn > 10000 ) return 0;
940 n = (int)(zTail - zIn);
941 if( n<2 ) return 0;
942 if( zIn[n-1]=='-' || zIn[n-1]=='.' ) return 0;
943 for(i=n-1; i>0 && zIn[i-1]!='@'; i--){
944 if( !fossil_isalnum(zIn[i]) && zIn[i]!='-' && zIn[i]!='.' ) return 0;
945 }
946 if( zIn[i]=='-' || zIn[i]=='.' || i==1 ) return 0;
947 if( i>1 ){
948 i -= 2;
949 while( i>=0 ){
950 if( zIn[i]=='@' ) return 0;
951 i--;
952 }
953 }
954 return zTail+1;
955 }
956
957 /*
958 ** Return true if the filename given is a valid filename for
959 ** a file in a repository. Valid filenames follow all of the
960 ** following rules:
@@ -1113,17 +1155,29 @@
1155 /*
1156 ** COMMAND: test-simplify-name
1157 **
1158 ** Usage: %fossil test-simplify-name FILENAME...
1159 **
1160 ** Print the simplified versions of each FILENAME. This is used to test
1161 ** the file_simplify_name() routine.
1162 **
1163 ** If FILENAME is of the form "HOST:PATH" or "USER@HOST:PATH", then remove
1164 ** and print the remote host prefix first. This is used to test the
1165 ** file_skip_userhost() interface.
1166 */
1167 void cmd_test_simplify_name(void){
1168 int i;
1169 char *z;
1170 const char *zTail;
1171 for(i=2; i<g.argc; i++){
1172 zTail = file_skip_userhost(g.argv[i]);
1173 if( zTail ){
1174 fossil_print("... ON REMOTE: %.*s\n", (int)(zTail-g.argv[i]), g.argv[i]);
1175 z = mprintf("%s", zTail);
1176 }else{
1177 z = mprintf("%s", g.argv[i]);
1178 }
1179 fossil_print("[%s] -> ", z);
1180 file_simplify_name(z, -1, 0);
1181 fossil_print("[%s]\n", z);
1182 fossil_free(z);
1183 }
@@ -1247,10 +1301,54 @@
1301 ** This routine only works on unix. On Windows, simply return
1302 ** a copy of the input.
1303 */
1304 char *file_fullexename(const char *zCmd){
1305 #ifdef _WIN32
1306 char *zPath;
1307 char *z = 0;
1308 const char *zExe = "";
1309 if( sqlite3_strlike("%.exe",zCmd,0)!=0 ) zExe = ".exe";
1310 if( file_is_absolute_path(zCmd) ){
1311 return mprintf("%s%s", zCmd, zExe);
1312 }
1313 if( strchr(zCmd,'\\')!=0 && strchr(zCmd,'/')!=0 ){
1314 int i;
1315 Blob out = BLOB_INITIALIZER;
1316 file_canonical_name(zCmd, &out, 0);
1317 blob_append(&out, zExe, -1);
1318 z = fossil_strdup(blob_str(&out));
1319 blob_reset(&out);
1320 for(i=0; z[i]; i++){ if( z[i]=='/' ) z[i] = '\\'; }
1321 return z;
1322 }
1323 z = mprintf(".\\%s%s", zCmd, zExe);
1324 if( file_isfile(z, ExtFILE) ){
1325 int i;
1326 Blob out = BLOB_INITIALIZER;
1327 file_canonical_name(zCmd, &out, 0);
1328 blob_append(&out, zExe, -1);
1329 z = fossil_strdup(blob_str(&out));
1330 blob_reset(&out);
1331 for(i=0; z[i]; i++){ if( z[i]=='/' ) z[i] = '\\'; }
1332 return z;
1333 }
1334 fossil_free(z);
1335 zPath = fossil_getenv("PATH");
1336 while( zPath && zPath[0] ){
1337 int n;
1338 char *zColon;
1339 zColon = strchr(zPath, ';');
1340 n = zColon ? (int)(zColon-zPath) : (int)strlen(zPath);
1341 while( n>0 && zPath[n-1]=='\\' ){ n--; }
1342 z = mprintf("%.*s\\%s%s", n, zPath, zCmd, zExe);
1343 if( file_isfile(z, ExtFILE) ){
1344 return z;
1345 }
1346 fossil_free(z);
1347 if( zColon==0 ) break;
1348 zPath = zColon+1;
1349 }
1350 return fossil_strdup(zCmd);
1351 #else
1352 char *zPath;
1353 char *z;
1354 if( zCmd[0]=='/' ){
@@ -1780,20 +1878,21 @@
1878 ** the root of zBasis in its name.
1879 **
1880 ** If zTag is not NULL, then try to create the temp-file using zTag
1881 ** as a differentiator. If that fails, or if zTag is NULL, then use
1882 ** a bunch of random characters as the tag.
1883 **
1884 ** Dangerous characters in zBasis are changed.
1885 */
1886 void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
1887 #if defined(_WIN32)
1888 const char *azDirs[] = {
1889 0, /* GetTempPath */
1890 0, /* TEMP */
1891 0, /* TMP */
1892 ".",
1893 };
 
1894 #else
1895 static const char *azDirs[] = {
1896 0, /* TMPDIR */
1897 "/var/tmp",
1898 "/usr/tmp",
@@ -1810,10 +1909,11 @@
1909 const char *zDir = ".";
1910 int cnt = 0;
1911 char zRand[16];
1912 int nBasis;
1913 const char *zSuffix;
1914 char *z;
1915
1916 #if defined(_WIN32)
1917 wchar_t zTmpPath[MAX_PATH];
1918
1919 if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1868,10 +1968,13 @@
1968 zRand[15] = 0;
1969 zTag = zRand;
1970 }
1971 blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
1972 zTag = 0;
1973 for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){
1974 z[0] = '_';
1975 }
1976 }while( file_size(blob_str(pBuf), ExtFILE)>=0 );
1977
1978 #if defined(_WIN32)
1979 fossil_path_free((char *)azDirs[0]);
1980 fossil_path_free((char *)azDirs[1]);
@@ -2620,5 +2723,26 @@
2723 for( i = 2; i < g.argc; ++i ){
2724 const int check = file_is_reserved_name(g.argv[i], -1);
2725 fossil_print("%d %s\n", check, g.argv[i]);
2726 }
2727 }
2728
2729
2730 /*
2731 ** Returns 1 if the given directory contains a file named .fslckout, 2
2732 ** if it contains a file named _FOSSIL_, else returns 0.
2733 */
2734 int dir_has_ckout_db(const char *zDir){
2735 int rc = 0;
2736 char * zCkoutDb = mprintf("%//.fslckout", zDir);
2737 if(file_isfile(zCkoutDb, ExtFILE)){
2738 rc = 1;
2739 }else{
2740 fossil_free(zCkoutDb);
2741 zCkoutDb = mprintf("%//_FOSSIL_", zDir);
2742 if(file_isfile(zCkoutDb, ExtFILE)){
2743 rc = 2;
2744 }
2745 }
2746 fossil_free(zCkoutDb);
2747 return rc;
2748 }
2749
+6 -5
--- src/finfo.c
+++ src/finfo.c
@@ -141,21 +141,22 @@
141141
blob_write_to_file(&record, "-");
142142
blob_reset(&record);
143143
blob_reset(&fname);
144144
}else if( find_option("id","i",0) ){
145145
Blob fname;
146
+ int rid;
146147
const char *zRevision = find_option("revision", "r", 1);
147148
148149
verify_all_options();
149150
150151
if( zRevision==0 ) usage("-i|--id also requires -r|--revision");
151152
if( g.argc!=3 ) usage("-r|--revision REVISION FILENAME");
152153
file_tree_name(g.argv[2], &fname, 0, 1);
153
- int rid = db_int(0, "SELECT rid FROM blob WHERE uuid ="
154
- " (SELECT uuid FROM files_of_checkin(%Q)"
155
- " WHERE filename=%B %s)",
156
- zRevision, &fname, filename_collation());
154
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid ="
155
+ " (SELECT uuid FROM files_of_checkin(%Q)"
156
+ " WHERE filename=%B %s)",
157
+ zRevision, &fname, filename_collation());
157158
if( rid==0 ) {
158159
fossil_fatal("file not found for revision %s: %s",
159160
zRevision, blob_str(&fname));
160161
}
161162
whatis_rid(rid,0);
@@ -900,11 +901,11 @@
900901
/* 7 */ " isaux"
901902
" FROM mlink WHERE mid=%d ORDER BY 1",
902903
mid
903904
);
904905
@ <h1>MLINK table for check-in %h(zCI)</h1>
905
- render_checkin_context(mid, 0, 1);
906
+ render_checkin_context(mid, 0, 1, 0);
906907
style_table_sorter();
907908
@ <hr />
908909
@ <div class='brlist'>
909910
@ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'>
910911
@ <thead><tr>
911912
--- src/finfo.c
+++ src/finfo.c
@@ -141,21 +141,22 @@
141 blob_write_to_file(&record, "-");
142 blob_reset(&record);
143 blob_reset(&fname);
144 }else if( find_option("id","i",0) ){
145 Blob fname;
 
146 const char *zRevision = find_option("revision", "r", 1);
147
148 verify_all_options();
149
150 if( zRevision==0 ) usage("-i|--id also requires -r|--revision");
151 if( g.argc!=3 ) usage("-r|--revision REVISION FILENAME");
152 file_tree_name(g.argv[2], &fname, 0, 1);
153 int rid = db_int(0, "SELECT rid FROM blob WHERE uuid ="
154 " (SELECT uuid FROM files_of_checkin(%Q)"
155 " WHERE filename=%B %s)",
156 zRevision, &fname, filename_collation());
157 if( rid==0 ) {
158 fossil_fatal("file not found for revision %s: %s",
159 zRevision, blob_str(&fname));
160 }
161 whatis_rid(rid,0);
@@ -900,11 +901,11 @@
900 /* 7 */ " isaux"
901 " FROM mlink WHERE mid=%d ORDER BY 1",
902 mid
903 );
904 @ <h1>MLINK table for check-in %h(zCI)</h1>
905 render_checkin_context(mid, 0, 1);
906 style_table_sorter();
907 @ <hr />
908 @ <div class='brlist'>
909 @ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'>
910 @ <thead><tr>
911
--- src/finfo.c
+++ src/finfo.c
@@ -141,21 +141,22 @@
141 blob_write_to_file(&record, "-");
142 blob_reset(&record);
143 blob_reset(&fname);
144 }else if( find_option("id","i",0) ){
145 Blob fname;
146 int rid;
147 const char *zRevision = find_option("revision", "r", 1);
148
149 verify_all_options();
150
151 if( zRevision==0 ) usage("-i|--id also requires -r|--revision");
152 if( g.argc!=3 ) usage("-r|--revision REVISION FILENAME");
153 file_tree_name(g.argv[2], &fname, 0, 1);
154 rid = db_int(0, "SELECT rid FROM blob WHERE uuid ="
155 " (SELECT uuid FROM files_of_checkin(%Q)"
156 " WHERE filename=%B %s)",
157 zRevision, &fname, filename_collation());
158 if( rid==0 ) {
159 fossil_fatal("file not found for revision %s: %s",
160 zRevision, blob_str(&fname));
161 }
162 whatis_rid(rid,0);
@@ -900,11 +901,11 @@
901 /* 7 */ " isaux"
902 " FROM mlink WHERE mid=%d ORDER BY 1",
903 mid
904 );
905 @ <h1>MLINK table for check-in %h(zCI)</h1>
906 render_checkin_context(mid, 0, 1, 0);
907 style_table_sorter();
908 @ <hr />
909 @ <div class='brlist'>
910 @ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'>
911 @ <thead><tr>
912
+3 -1
--- src/forum.c
+++ src/forum.c
@@ -1353,23 +1353,25 @@
13531353
**
13541354
** Query parameters:
13551355
**
13561356
** n=N The number of threads to show on each page
13571357
** x=X Skip the first X threads
1358
+** s=Y Search for term Y.
13581359
*/
13591360
void forum_main_page(void){
13601361
Stmt q;
13611362
int iLimit, iOfst, iCnt;
13621363
int srchFlags;
1364
+ const int isSearch = P("s")!=0;
13631365
login_check_credentials();
13641366
srchFlags = search_restrict(SRCH_FORUM);
13651367
if( !g.perm.RdForum ){
13661368
login_needed(g.anon.RdForum);
13671369
return;
13681370
}
13691371
style_set_current_feature("forum");
1370
- style_header("Forum");
1372
+ style_header( "%s", isSearch ? "Forum Search Results" : "Forum" );
13711373
if( g.perm.WrForum ){
13721374
style_submenu_element("New Thread","%R/forumnew");
13731375
}else{
13741376
/* Can't combine this with previous case using the ternary operator
13751377
* because that causes an error yelling about "non-constant format"
13761378
--- src/forum.c
+++ src/forum.c
@@ -1353,23 +1353,25 @@
1353 **
1354 ** Query parameters:
1355 **
1356 ** n=N The number of threads to show on each page
1357 ** x=X Skip the first X threads
 
1358 */
1359 void forum_main_page(void){
1360 Stmt q;
1361 int iLimit, iOfst, iCnt;
1362 int srchFlags;
 
1363 login_check_credentials();
1364 srchFlags = search_restrict(SRCH_FORUM);
1365 if( !g.perm.RdForum ){
1366 login_needed(g.anon.RdForum);
1367 return;
1368 }
1369 style_set_current_feature("forum");
1370 style_header("Forum");
1371 if( g.perm.WrForum ){
1372 style_submenu_element("New Thread","%R/forumnew");
1373 }else{
1374 /* Can't combine this with previous case using the ternary operator
1375 * because that causes an error yelling about "non-constant format"
1376
--- src/forum.c
+++ src/forum.c
@@ -1353,23 +1353,25 @@
1353 **
1354 ** Query parameters:
1355 **
1356 ** n=N The number of threads to show on each page
1357 ** x=X Skip the first X threads
1358 ** s=Y Search for term Y.
1359 */
1360 void forum_main_page(void){
1361 Stmt q;
1362 int iLimit, iOfst, iCnt;
1363 int srchFlags;
1364 const int isSearch = P("s")!=0;
1365 login_check_credentials();
1366 srchFlags = search_restrict(SRCH_FORUM);
1367 if( !g.perm.RdForum ){
1368 login_needed(g.anon.RdForum);
1369 return;
1370 }
1371 style_set_current_feature("forum");
1372 style_header( "%s", isSearch ? "Forum Search Results" : "Forum" );
1373 if( g.perm.WrForum ){
1374 style_submenu_element("New Thread","%R/forumnew");
1375 }else{
1376 /* Can't combine this with previous case using the ternary operator
1377 * because that causes an error yelling about "non-constant format"
1378
--- src/fossil.copybutton.js
+++ src/fossil.copybutton.js
@@ -21,11 +21,11 @@
2121
2222
One of copyFromElement or copyFromId must be provided, but copyFromId
2323
may optionally be provided via e.dataset.copyFromId.
2424
2525
.extractText: optional callback which is triggered when the copy
26
- button is clicked. I tmust return the text to copy to the
26
+ button is clicked. It must return the text to copy to the
2727
clipboard. The default is to extract it from the copy-from
2828
element, using its [value] member, if it has one, else its
2929
[innerText]. A client-provided callback may use any data source
3030
it likes, so long as it's synchronous. If this function returns a
3131
falsy value then the clipboard is not modified. This function is
@@ -81,11 +81,11 @@
8181
});
8282
*/
8383
F.copyButton = function f(e, opt){
8484
if('string'===typeof e){
8585
e = document.querySelector(e);
86
- }
86
+ }
8787
opt = F.mergeLastWins(f.defaultOptions, opt);
8888
if(opt.cssClass){
8989
D.addClass(e, opt.cssClass);
9090
}
9191
var srcId, srcElem;
9292
--- src/fossil.copybutton.js
+++ src/fossil.copybutton.js
@@ -21,11 +21,11 @@
21
22 One of copyFromElement or copyFromId must be provided, but copyFromId
23 may optionally be provided via e.dataset.copyFromId.
24
25 .extractText: optional callback which is triggered when the copy
26 button is clicked. I tmust return the text to copy to the
27 clipboard. The default is to extract it from the copy-from
28 element, using its [value] member, if it has one, else its
29 [innerText]. A client-provided callback may use any data source
30 it likes, so long as it's synchronous. If this function returns a
31 falsy value then the clipboard is not modified. This function is
@@ -81,11 +81,11 @@
81 });
82 */
83 F.copyButton = function f(e, opt){
84 if('string'===typeof e){
85 e = document.querySelector(e);
86 }
87 opt = F.mergeLastWins(f.defaultOptions, opt);
88 if(opt.cssClass){
89 D.addClass(e, opt.cssClass);
90 }
91 var srcId, srcElem;
92
--- src/fossil.copybutton.js
+++ src/fossil.copybutton.js
@@ -21,11 +21,11 @@
21
22 One of copyFromElement or copyFromId must be provided, but copyFromId
23 may optionally be provided via e.dataset.copyFromId.
24
25 .extractText: optional callback which is triggered when the copy
26 button is clicked. It must return the text to copy to the
27 clipboard. The default is to extract it from the copy-from
28 element, using its [value] member, if it has one, else its
29 [innerText]. A client-provided callback may use any data source
30 it likes, so long as it's synchronous. If this function returns a
31 falsy value then the clipboard is not modified. This function is
@@ -81,11 +81,11 @@
81 });
82 */
83 F.copyButton = function f(e, opt){
84 if('string'===typeof e){
85 e = document.querySelector(e);
86 }
87 opt = F.mergeLastWins(f.defaultOptions, opt);
88 if(opt.cssClass){
89 D.addClass(e, opt.cssClass);
90 }
91 var srcId, srcElem;
92
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -182,10 +182,11 @@
182182
record.type = winfo.type;
183183
record.parent = winfo.parent;
184184
record.version = winfo.version;
185185
record.stashTime = new Date().getTime();
186186
record.isEmpty = !!winfo.isEmpty;
187
+ record.attachments = winfo.attachments;
187188
this.storeIndex();
188189
if(arguments.length>1){
189190
if(content) delete record.isEmpty;
190191
F.storage.set(this.contentKey(key), content);
191192
}
@@ -526,11 +527,11 @@
526527
else if(0===name.indexOf('branch/')) wtype = 'branch';
527528
else if(0===name.indexOf('tag/')) wtype = 'tag';
528529
/* ^^^ note that we're not validating that, e.g., checkin/XYZ
529530
has a full artifact ID after "checkin/". */
530531
const winfo = {
531
- name: name, type: wtype, mimetype: 'text/x-fossil-wiki',
532
+ name: name, type: wtype, mimetype: 'text/x-markdown',
532533
version: null, parent: null
533534
};
534535
this.cache.pageList.push(
535536
winfo/*keeps entry from getting lost from the list on save*/
536537
);
@@ -818,11 +819,12 @@
818819
if(!ajaxState.toDisable){
819820
ajaxState.toDisable = document.querySelectorAll(
820821
['button:not([disabled])',
821822
'input:not([disabled])',
822823
'select:not([disabled])',
823
- 'textarea:not([disabled])'
824
+ 'textarea:not([disabled])',
825
+ 'fieldset:not([disabled])'
824826
].join(',')
825827
);
826828
}
827829
if(1===++ajaxState.count){
828830
D.addClass(document.body, 'waiting');
@@ -853,10 +855,11 @@
853855
cbAutoPreview: E('#cb-preview-autorefresh'),
854856
previewTarget: E('#wikiedit-tab-preview-wrapper'),
855857
diffTarget: E('#wikiedit-tab-diff-wrapper'),
856858
editStatus: E('#wikiedit-edit-status'),
857859
tabContainer: E('#wikiedit-tabs'),
860
+ attachmentContainer: E("#attachment-wrapper"),
858861
tabs:{
859862
pageList: E('#wikiedit-tab-pages'),
860863
content: E('#wikiedit-tab-content'),
861864
preview: E('#wikiedit-tab-preview'),
862865
diff: E('#wikiedit-tab-diff'),
@@ -1122,10 +1125,105 @@
11221125
*/
11231126
const affirmPageLoaded = function(quiet){
11241127
if(!P.winfo && !quiet) F.error("No wiki page is loaded.");
11251128
return !!P.winfo;
11261129
};
1130
+
1131
+ /**
1132
+ Updates the attachments list from this.winfo.
1133
+ */
1134
+ P.updateAttachmentsView = function f(){
1135
+ if(!f.eAttach){
1136
+ f.eAttach = P.e.attachmentContainer.querySelector('div');
1137
+ }
1138
+ D.clearElement(f.eAttach);
1139
+ const wi = this.winfo;
1140
+ if(!wi){
1141
+ D.append(f.eAttach,"No page loaded.");
1142
+ return this;
1143
+ }
1144
+ else if(!wi.version){
1145
+ D.append(f.eAttach,
1146
+ "Page ["+wi.name+"] cannot have ",
1147
+ "attachments until it is saved once.");
1148
+ return this;
1149
+ }
1150
+ const btnReload = D.button("Reload list");
1151
+ const self = this;
1152
+ btnReload.addEventListener('click', function(){
1153
+ const isStashed = $stash.hasStashedContent(wi);
1154
+ F.fetch('wikiajax/attachments',{
1155
+ responseType: 'json',
1156
+ urlParams: {page: wi.name},
1157
+ onload: function(r){
1158
+ wi.attachments = r;
1159
+ if(isStashed) self.stashContentChange(true);
1160
+ F.message("Reloaded attachment list for ["+wi.name+"].");
1161
+ self.updateAttachmentsView();
1162
+ }
1163
+ });
1164
+ });
1165
+ if(!wi.attachments || !wi.attachments.length){
1166
+ D.append(f.eAttach,
1167
+ btnReload,
1168
+ " No attachments found for page ["+wi.name+"]. ",
1169
+ D.a(F.repoUrl('attachadd',{
1170
+ page: wi.name,
1171
+ from: F.repoUrl('wikiedit',{name: wi.name})}),
1172
+ "Add attachments..." )
1173
+ );
1174
+ return this;
1175
+ }
1176
+ D.append(
1177
+ f.eAttach,
1178
+ D.append(D.p(),
1179
+ btnReload," ",
1180
+ D.a(F.repoUrl('attachlist',{page:wi.name}),
1181
+ "Attachments for page ["+wi.name+"]."),
1182
+ " ",
1183
+ D.a(F.repoUrl('attachadd',{
1184
+ page:wi.name,
1185
+ from: F.repoUrl('wikiedit',{name: wi.name})}),
1186
+ "Add attachments..." )
1187
+ )
1188
+ );
1189
+ wi.attachments.forEach(function(a){
1190
+ const wrap = D.div();
1191
+ D.append(f.eAttach, wrap);
1192
+ D.append(wrap,
1193
+ D.append(D.div(),
1194
+ "Attachment ",
1195
+ D.addClass(
1196
+ D.a(F.repoUrl('ainfo',{name:a.uuid}),
1197
+ F.hashDigits(a.uuid,true)),
1198
+ 'monospace'),
1199
+ " ",
1200
+ a.filename,
1201
+ (a.isLatest ? " (latest)" : "")
1202
+ )
1203
+ );
1204
+ //D.append(wrap,D.append(D.div(), "URLs:"));
1205
+ const ul = D.ul();
1206
+ D.append(wrap, ul);
1207
+ [ // List download URL variants for each attachment:
1208
+ [
1209
+ "attachdownload?page=",
1210
+ encodeURIComponent(wi.name),
1211
+ "&file=",
1212
+ encodeURIComponent(a.filename)
1213
+ ].join(''),
1214
+ "raw/"+a.src
1215
+ ].forEach(function(url){
1216
+ const imgUrl = D.append(D.addClass(D.span(), 'monospace'), url);
1217
+ const urlCopy = D.span();
1218
+ const li = D.li(ul);
1219
+ D.append(li, urlCopy, " ", imgUrl);
1220
+ F.copyButton(urlCopy, {copyFromElement: imgUrl});
1221
+ });
1222
+ });
1223
+ return this;
1224
+ };
11271225
11281226
/** Updates the in-tab title/edit status information */
11291227
P.updateEditStatus = function f(){
11301228
if(!f.eLinks){
11311229
f.eName = P.e.editStatus.querySelector('span.name');
@@ -1133,24 +1231,25 @@
11331231
}
11341232
const wi = this.winfo;
11351233
D.clearElement(f.eName, f.eLinks);
11361234
if(!wi){
11371235
D.append(f.eName, '(no page loaded)');
1138
- return;
1139
- }
1140
- var marker = getEditMarker(wi, false);
1141
- D.append(f.eName,marker,wi.name);
1142
- if(wi.version){
1143
- D.append(
1144
- f.eLinks,
1145
- D.a(F.repoUrl('wiki',{name:wi.name}),"viewer"),
1146
- D.a(F.repoUrl('whistory',{name:wi.name}),'history'),
1147
- D.a(F.repoUrl('attachlist',{page:wi.name}),"attachments"),
1148
- D.a(F.repoUrl('attachadd',{page:wi.name,from: F.repoUrl('wikiedit',{name: wi.name})}), "attach"),
1149
- D.a(F.repoUrl('wikiedit',{name:wi.name}),"editor permalink")
1150
- );
1151
- }
1236
+ this.updateAttachmentsView();
1237
+ return this;
1238
+ }
1239
+ D.append(f.eName,getEditMarker(wi, false),wi.name);
1240
+ this.updateAttachmentsView();
1241
+ if(!wi.version) return this;
1242
+ D.append(
1243
+ f.eLinks,
1244
+ D.a(F.repoUrl('wiki',{name:wi.name}),"viewer"),
1245
+ D.a(F.repoUrl('whistory',{name:wi.name}),'history'),
1246
+ D.a(F.repoUrl('attachlist',{page:wi.name}),"attachments"),
1247
+ D.a(F.repoUrl('attachadd',{page:wi.name,from: F.repoUrl('wikiedit',{name: wi.name})}), "attach"),
1248
+ D.a(F.repoUrl('wikiedit',{name:wi.name}),"editor permalink")
1249
+ );
1250
+ return this;
11521251
};
11531252
11541253
/**
11551254
Update the page title and header based on the state of
11561255
this.winfo. A no-op if this.winfo is not set. Returns this.
@@ -1313,11 +1412,12 @@
13131412
mimetype: stashWinfo.mimetype,
13141413
type: stashWinfo.type,
13151414
version: stashWinfo.version,
13161415
parent: stashWinfo.parent,
13171416
isEmpty: !!stashWinfo.isEmpty,
1318
- content: $stash.stashedContent(stashWinfo)
1417
+ content: $stash.stashedContent(stashWinfo),
1418
+ attachments: stashWinfo.attachments
13191419
});
13201420
this._isDirty = true/*b/c loading normally clears that flag*/;
13211421
return this;
13221422
}
13231423
F.message(
13241424
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -182,10 +182,11 @@
182 record.type = winfo.type;
183 record.parent = winfo.parent;
184 record.version = winfo.version;
185 record.stashTime = new Date().getTime();
186 record.isEmpty = !!winfo.isEmpty;
 
187 this.storeIndex();
188 if(arguments.length>1){
189 if(content) delete record.isEmpty;
190 F.storage.set(this.contentKey(key), content);
191 }
@@ -526,11 +527,11 @@
526 else if(0===name.indexOf('branch/')) wtype = 'branch';
527 else if(0===name.indexOf('tag/')) wtype = 'tag';
528 /* ^^^ note that we're not validating that, e.g., checkin/XYZ
529 has a full artifact ID after "checkin/". */
530 const winfo = {
531 name: name, type: wtype, mimetype: 'text/x-fossil-wiki',
532 version: null, parent: null
533 };
534 this.cache.pageList.push(
535 winfo/*keeps entry from getting lost from the list on save*/
536 );
@@ -818,11 +819,12 @@
818 if(!ajaxState.toDisable){
819 ajaxState.toDisable = document.querySelectorAll(
820 ['button:not([disabled])',
821 'input:not([disabled])',
822 'select:not([disabled])',
823 'textarea:not([disabled])'
 
824 ].join(',')
825 );
826 }
827 if(1===++ajaxState.count){
828 D.addClass(document.body, 'waiting');
@@ -853,10 +855,11 @@
853 cbAutoPreview: E('#cb-preview-autorefresh'),
854 previewTarget: E('#wikiedit-tab-preview-wrapper'),
855 diffTarget: E('#wikiedit-tab-diff-wrapper'),
856 editStatus: E('#wikiedit-edit-status'),
857 tabContainer: E('#wikiedit-tabs'),
 
858 tabs:{
859 pageList: E('#wikiedit-tab-pages'),
860 content: E('#wikiedit-tab-content'),
861 preview: E('#wikiedit-tab-preview'),
862 diff: E('#wikiedit-tab-diff'),
@@ -1122,10 +1125,105 @@
1122 */
1123 const affirmPageLoaded = function(quiet){
1124 if(!P.winfo && !quiet) F.error("No wiki page is loaded.");
1125 return !!P.winfo;
1126 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1127
1128 /** Updates the in-tab title/edit status information */
1129 P.updateEditStatus = function f(){
1130 if(!f.eLinks){
1131 f.eName = P.e.editStatus.querySelector('span.name');
@@ -1133,24 +1231,25 @@
1133 }
1134 const wi = this.winfo;
1135 D.clearElement(f.eName, f.eLinks);
1136 if(!wi){
1137 D.append(f.eName, '(no page loaded)');
1138 return;
1139 }
1140 var marker = getEditMarker(wi, false);
1141 D.append(f.eName,marker,wi.name);
1142 if(wi.version){
1143 D.append(
1144 f.eLinks,
1145 D.a(F.repoUrl('wiki',{name:wi.name}),"viewer"),
1146 D.a(F.repoUrl('whistory',{name:wi.name}),'history'),
1147 D.a(F.repoUrl('attachlist',{page:wi.name}),"attachments"),
1148 D.a(F.repoUrl('attachadd',{page:wi.name,from: F.repoUrl('wikiedit',{name: wi.name})}), "attach"),
1149 D.a(F.repoUrl('wikiedit',{name:wi.name}),"editor permalink")
1150 );
1151 }
 
1152 };
1153
1154 /**
1155 Update the page title and header based on the state of
1156 this.winfo. A no-op if this.winfo is not set. Returns this.
@@ -1313,11 +1412,12 @@
1313 mimetype: stashWinfo.mimetype,
1314 type: stashWinfo.type,
1315 version: stashWinfo.version,
1316 parent: stashWinfo.parent,
1317 isEmpty: !!stashWinfo.isEmpty,
1318 content: $stash.stashedContent(stashWinfo)
 
1319 });
1320 this._isDirty = true/*b/c loading normally clears that flag*/;
1321 return this;
1322 }
1323 F.message(
1324
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -182,10 +182,11 @@
182 record.type = winfo.type;
183 record.parent = winfo.parent;
184 record.version = winfo.version;
185 record.stashTime = new Date().getTime();
186 record.isEmpty = !!winfo.isEmpty;
187 record.attachments = winfo.attachments;
188 this.storeIndex();
189 if(arguments.length>1){
190 if(content) delete record.isEmpty;
191 F.storage.set(this.contentKey(key), content);
192 }
@@ -526,11 +527,11 @@
527 else if(0===name.indexOf('branch/')) wtype = 'branch';
528 else if(0===name.indexOf('tag/')) wtype = 'tag';
529 /* ^^^ note that we're not validating that, e.g., checkin/XYZ
530 has a full artifact ID after "checkin/". */
531 const winfo = {
532 name: name, type: wtype, mimetype: 'text/x-markdown',
533 version: null, parent: null
534 };
535 this.cache.pageList.push(
536 winfo/*keeps entry from getting lost from the list on save*/
537 );
@@ -818,11 +819,12 @@
819 if(!ajaxState.toDisable){
820 ajaxState.toDisable = document.querySelectorAll(
821 ['button:not([disabled])',
822 'input:not([disabled])',
823 'select:not([disabled])',
824 'textarea:not([disabled])',
825 'fieldset:not([disabled])'
826 ].join(',')
827 );
828 }
829 if(1===++ajaxState.count){
830 D.addClass(document.body, 'waiting');
@@ -853,10 +855,11 @@
855 cbAutoPreview: E('#cb-preview-autorefresh'),
856 previewTarget: E('#wikiedit-tab-preview-wrapper'),
857 diffTarget: E('#wikiedit-tab-diff-wrapper'),
858 editStatus: E('#wikiedit-edit-status'),
859 tabContainer: E('#wikiedit-tabs'),
860 attachmentContainer: E("#attachment-wrapper"),
861 tabs:{
862 pageList: E('#wikiedit-tab-pages'),
863 content: E('#wikiedit-tab-content'),
864 preview: E('#wikiedit-tab-preview'),
865 diff: E('#wikiedit-tab-diff'),
@@ -1122,10 +1125,105 @@
1125 */
1126 const affirmPageLoaded = function(quiet){
1127 if(!P.winfo && !quiet) F.error("No wiki page is loaded.");
1128 return !!P.winfo;
1129 };
1130
1131 /**
1132 Updates the attachments list from this.winfo.
1133 */
1134 P.updateAttachmentsView = function f(){
1135 if(!f.eAttach){
1136 f.eAttach = P.e.attachmentContainer.querySelector('div');
1137 }
1138 D.clearElement(f.eAttach);
1139 const wi = this.winfo;
1140 if(!wi){
1141 D.append(f.eAttach,"No page loaded.");
1142 return this;
1143 }
1144 else if(!wi.version){
1145 D.append(f.eAttach,
1146 "Page ["+wi.name+"] cannot have ",
1147 "attachments until it is saved once.");
1148 return this;
1149 }
1150 const btnReload = D.button("Reload list");
1151 const self = this;
1152 btnReload.addEventListener('click', function(){
1153 const isStashed = $stash.hasStashedContent(wi);
1154 F.fetch('wikiajax/attachments',{
1155 responseType: 'json',
1156 urlParams: {page: wi.name},
1157 onload: function(r){
1158 wi.attachments = r;
1159 if(isStashed) self.stashContentChange(true);
1160 F.message("Reloaded attachment list for ["+wi.name+"].");
1161 self.updateAttachmentsView();
1162 }
1163 });
1164 });
1165 if(!wi.attachments || !wi.attachments.length){
1166 D.append(f.eAttach,
1167 btnReload,
1168 " No attachments found for page ["+wi.name+"]. ",
1169 D.a(F.repoUrl('attachadd',{
1170 page: wi.name,
1171 from: F.repoUrl('wikiedit',{name: wi.name})}),
1172 "Add attachments..." )
1173 );
1174 return this;
1175 }
1176 D.append(
1177 f.eAttach,
1178 D.append(D.p(),
1179 btnReload," ",
1180 D.a(F.repoUrl('attachlist',{page:wi.name}),
1181 "Attachments for page ["+wi.name+"]."),
1182 " ",
1183 D.a(F.repoUrl('attachadd',{
1184 page:wi.name,
1185 from: F.repoUrl('wikiedit',{name: wi.name})}),
1186 "Add attachments..." )
1187 )
1188 );
1189 wi.attachments.forEach(function(a){
1190 const wrap = D.div();
1191 D.append(f.eAttach, wrap);
1192 D.append(wrap,
1193 D.append(D.div(),
1194 "Attachment ",
1195 D.addClass(
1196 D.a(F.repoUrl('ainfo',{name:a.uuid}),
1197 F.hashDigits(a.uuid,true)),
1198 'monospace'),
1199 " ",
1200 a.filename,
1201 (a.isLatest ? " (latest)" : "")
1202 )
1203 );
1204 //D.append(wrap,D.append(D.div(), "URLs:"));
1205 const ul = D.ul();
1206 D.append(wrap, ul);
1207 [ // List download URL variants for each attachment:
1208 [
1209 "attachdownload?page=",
1210 encodeURIComponent(wi.name),
1211 "&file=",
1212 encodeURIComponent(a.filename)
1213 ].join(''),
1214 "raw/"+a.src
1215 ].forEach(function(url){
1216 const imgUrl = D.append(D.addClass(D.span(), 'monospace'), url);
1217 const urlCopy = D.span();
1218 const li = D.li(ul);
1219 D.append(li, urlCopy, " ", imgUrl);
1220 F.copyButton(urlCopy, {copyFromElement: imgUrl});
1221 });
1222 });
1223 return this;
1224 };
1225
1226 /** Updates the in-tab title/edit status information */
1227 P.updateEditStatus = function f(){
1228 if(!f.eLinks){
1229 f.eName = P.e.editStatus.querySelector('span.name');
@@ -1133,24 +1231,25 @@
1231 }
1232 const wi = this.winfo;
1233 D.clearElement(f.eName, f.eLinks);
1234 if(!wi){
1235 D.append(f.eName, '(no page loaded)');
1236 this.updateAttachmentsView();
1237 return this;
1238 }
1239 D.append(f.eName,getEditMarker(wi, false),wi.name);
1240 this.updateAttachmentsView();
1241 if(!wi.version) return this;
1242 D.append(
1243 f.eLinks,
1244 D.a(F.repoUrl('wiki',{name:wi.name}),"viewer"),
1245 D.a(F.repoUrl('whistory',{name:wi.name}),'history'),
1246 D.a(F.repoUrl('attachlist',{page:wi.name}),"attachments"),
1247 D.a(F.repoUrl('attachadd',{page:wi.name,from: F.repoUrl('wikiedit',{name: wi.name})}), "attach"),
1248 D.a(F.repoUrl('wikiedit',{name:wi.name}),"editor permalink")
1249 );
1250 return this;
1251 };
1252
1253 /**
1254 Update the page title and header based on the state of
1255 this.winfo. A no-op if this.winfo is not set. Returns this.
@@ -1313,11 +1412,12 @@
1412 mimetype: stashWinfo.mimetype,
1413 type: stashWinfo.type,
1414 version: stashWinfo.version,
1415 parent: stashWinfo.parent,
1416 isEmpty: !!stashWinfo.isEmpty,
1417 content: $stash.stashedContent(stashWinfo),
1418 attachments: stashWinfo.attachments
1419 });
1420 this._isDirty = true/*b/c loading normally clears that flag*/;
1421 return this;
1422 }
1423 F.message(
1424
+1 -3
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -437,13 +437,11 @@
437437
*/
438438
LOCAL void ssl_remember_certificate_exception(
439439
UrlData *pUrlData,
440440
const char *zHash
441441
){
442
- char *zName = mprintf("cert:%s", pUrlData->name);
443
- db_set(zName, zHash, 1);
444
- fossil_free(zName);
442
+ db_set_mprintf(zHash, 1, "cert:%s", pUrlData->name);
445443
}
446444
447445
/*
448446
** Return true if the there exists a certificate exception for
449447
** pUrlData->name that matches the hash.
450448
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -437,13 +437,11 @@
437 */
438 LOCAL void ssl_remember_certificate_exception(
439 UrlData *pUrlData,
440 const char *zHash
441 ){
442 char *zName = mprintf("cert:%s", pUrlData->name);
443 db_set(zName, zHash, 1);
444 fossil_free(zName);
445 }
446
447 /*
448 ** Return true if the there exists a certificate exception for
449 ** pUrlData->name that matches the hash.
450
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -437,13 +437,11 @@
437 */
438 LOCAL void ssl_remember_certificate_exception(
439 UrlData *pUrlData,
440 const char *zHash
441 ){
442 db_set_mprintf(zHash, 1, "cert:%s", pUrlData->name);
 
 
443 }
444
445 /*
446 ** Return true if the there exists a certificate exception for
447 ** pUrlData->name that matches the hash.
448
--- src/http_transport.c
+++ src/http_transport.c
@@ -92,52 +92,56 @@
9292
}
9393
9494
/*
9595
** Default SSH command
9696
*/
97
-#ifdef _WIN32
98
-static const char zDefaultSshCmd[] = "plink -ssh -T";
97
+#if 0 /* was: defined(_WIN32). Windows generally has ssh now. */
98
+static const char zDefaultSshCmd[] = "plink -ssh";
9999
#else
100
-static const char zDefaultSshCmd[] = "ssh -e none -T";
100
+static const char zDefaultSshCmd[] = "ssh -e none";
101101
#endif
102
+
103
+/*
104
+** Initialize a Blob to the name of the configured SSH command.
105
+*/
106
+void transport_ssh_command(Blob *p){
107
+ char *zSsh; /* The base SSH command */
108
+ zSsh = db_get("ssh-command", zDefaultSshCmd);
109
+ blob_init(p, zSsh, -1);
110
+}
102111
103112
/*
104113
** SSH initialization of the transport layer
105114
*/
106115
int transport_ssh_open(UrlData *pUrlData){
107116
/* For SSH we need to create and run SSH fossil http
108117
** to talk to the remote machine.
109118
*/
110
- char *zSsh; /* The base SSH command */
111119
Blob zCmd; /* The SSH command */
112120
char *zHost; /* The host name to contact */
113121
114122
socket_ssh_resolve_addr(pUrlData);
115
- zSsh = db_get("ssh-command", zDefaultSshCmd);
116
- blob_init(&zCmd, zSsh, -1);
123
+ transport_ssh_command(&zCmd);
117124
if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
118
-#ifdef _WIN32
119
- blob_appendf(&zCmd, " -P %d", pUrlData->port);
120
-#else
121125
blob_appendf(&zCmd, " -p %d", pUrlData->port);
122
-#endif
123126
}
127
+ blob_appendf(&zCmd, " -T --"); /* End of switches */
124128
if( pUrlData->user && pUrlData->user[0] ){
125129
zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
126
- blob_append_escaped_arg(&zCmd, zHost);
130
+ blob_append_escaped_arg(&zCmd, zHost, 0);
127131
fossil_free(zHost);
128132
}else{
129
- blob_append_escaped_arg(&zCmd, pUrlData->name);
133
+ blob_append_escaped_arg(&zCmd, pUrlData->name, 0);
130134
}
131135
if( !is_safe_fossil_command(pUrlData->fossil) ){
132136
fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
133137
"the server.", pUrlData->fossil);
134138
}
135
- blob_append_escaped_arg(&zCmd, pUrlData->fossil);
139
+ blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1);
136140
blob_append(&zCmd, " test-http", 10);
137141
if( pUrlData->path && pUrlData->path[0] ){
138
- blob_append_escaped_arg(&zCmd, pUrlData->path);
142
+ blob_append_escaped_arg(&zCmd, pUrlData->path, 1);
139143
}else{
140144
fossil_fatal("ssh:// URI does not specify a path to the repository");
141145
}
142146
if( g.fSshTrace ){
143147
fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
144148
--- src/http_transport.c
+++ src/http_transport.c
@@ -92,52 +92,56 @@
92 }
93
94 /*
95 ** Default SSH command
96 */
97 #ifdef _WIN32
98 static const char zDefaultSshCmd[] = "plink -ssh -T";
99 #else
100 static const char zDefaultSshCmd[] = "ssh -e none -T";
101 #endif
 
 
 
 
 
 
 
 
 
102
103 /*
104 ** SSH initialization of the transport layer
105 */
106 int transport_ssh_open(UrlData *pUrlData){
107 /* For SSH we need to create and run SSH fossil http
108 ** to talk to the remote machine.
109 */
110 char *zSsh; /* The base SSH command */
111 Blob zCmd; /* The SSH command */
112 char *zHost; /* The host name to contact */
113
114 socket_ssh_resolve_addr(pUrlData);
115 zSsh = db_get("ssh-command", zDefaultSshCmd);
116 blob_init(&zCmd, zSsh, -1);
117 if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
118 #ifdef _WIN32
119 blob_appendf(&zCmd, " -P %d", pUrlData->port);
120 #else
121 blob_appendf(&zCmd, " -p %d", pUrlData->port);
122 #endif
123 }
 
124 if( pUrlData->user && pUrlData->user[0] ){
125 zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
126 blob_append_escaped_arg(&zCmd, zHost);
127 fossil_free(zHost);
128 }else{
129 blob_append_escaped_arg(&zCmd, pUrlData->name);
130 }
131 if( !is_safe_fossil_command(pUrlData->fossil) ){
132 fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
133 "the server.", pUrlData->fossil);
134 }
135 blob_append_escaped_arg(&zCmd, pUrlData->fossil);
136 blob_append(&zCmd, " test-http", 10);
137 if( pUrlData->path && pUrlData->path[0] ){
138 blob_append_escaped_arg(&zCmd, pUrlData->path);
139 }else{
140 fossil_fatal("ssh:// URI does not specify a path to the repository");
141 }
142 if( g.fSshTrace ){
143 fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
144
--- src/http_transport.c
+++ src/http_transport.c
@@ -92,52 +92,56 @@
92 }
93
94 /*
95 ** Default SSH command
96 */
97 #if 0 /* was: defined(_WIN32). Windows generally has ssh now. */
98 static const char zDefaultSshCmd[] = "plink -ssh";
99 #else
100 static const char zDefaultSshCmd[] = "ssh -e none";
101 #endif
102
103 /*
104 ** Initialize a Blob to the name of the configured SSH command.
105 */
106 void transport_ssh_command(Blob *p){
107 char *zSsh; /* The base SSH command */
108 zSsh = db_get("ssh-command", zDefaultSshCmd);
109 blob_init(p, zSsh, -1);
110 }
111
112 /*
113 ** SSH initialization of the transport layer
114 */
115 int transport_ssh_open(UrlData *pUrlData){
116 /* For SSH we need to create and run SSH fossil http
117 ** to talk to the remote machine.
118 */
 
119 Blob zCmd; /* The SSH command */
120 char *zHost; /* The host name to contact */
121
122 socket_ssh_resolve_addr(pUrlData);
123 transport_ssh_command(&zCmd);
 
124 if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
 
 
 
125 blob_appendf(&zCmd, " -p %d", pUrlData->port);
 
126 }
127 blob_appendf(&zCmd, " -T --"); /* End of switches */
128 if( pUrlData->user && pUrlData->user[0] ){
129 zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
130 blob_append_escaped_arg(&zCmd, zHost, 0);
131 fossil_free(zHost);
132 }else{
133 blob_append_escaped_arg(&zCmd, pUrlData->name, 0);
134 }
135 if( !is_safe_fossil_command(pUrlData->fossil) ){
136 fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
137 "the server.", pUrlData->fossil);
138 }
139 blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1);
140 blob_append(&zCmd, " test-http", 10);
141 if( pUrlData->path && pUrlData->path[0] ){
142 blob_append_escaped_arg(&zCmd, pUrlData->path, 1);
143 }else{
144 fossil_fatal("ssh:// URI does not specify a path to the repository");
145 }
146 if( g.fSshTrace ){
147 fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
148
+51 -33
--- src/info.c
+++ src/info.c
@@ -270,13 +270,13 @@
270270
}
271271
}
272272
273273
/*
274274
** Show the context graph (immediate parents and children) for
275
-** check-in rid.
275
+** check-in rid and rid2
276276
*/
277
-void render_checkin_context(int rid, int rid2, int parentsOnly){
277
+void render_checkin_context(int rid, int rid2, int parentsOnly, int mFlags){
278278
Blob sql;
279279
Stmt q;
280280
int rx[2];
281281
int i, n;
282282
rx[0] = rid;
@@ -313,11 +313,12 @@
313313
}
314314
}
315315
blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
316316
db_prepare(&q, "%s", blob_sql_text(&sql));
317317
www_print_timeline(&q,
318
- TIMELINE_GRAPH
318
+ mFlags
319
+ |TIMELINE_GRAPH
319320
|TIMELINE_FILLGAPS
320321
|TIMELINE_NOSCROLL
321322
|TIMELINE_XMERGE
322323
|TIMELINE_CHPICK,
323324
0, 0, 0, rid, rid2, 0);
@@ -880,11 +881,11 @@
880881
if( !PB("nowiki") ){
881882
wiki_render_associated("checkin", zUuid, 0);
882883
}
883884
render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n");
884885
@ <div class="section">Context</div>
885
- render_checkin_context(rid, 0, 0);
886
+ render_checkin_context(rid, 0, 0, 0);
886887
@ <div class="section">Changes</div>
887888
@ <div class="sectionmenu">
888889
diffFlags = construct_diff_flags(diffType);
889890
zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
890891
if( diffType!=0 ){
@@ -1164,11 +1165,12 @@
11641165
** diff=INTEGER 0: none, 1: unified, 2: side-by-side
11651166
** glob=STRING only diff files matching this glob
11661167
** dc=N show N lines of context around each diff
11671168
** w=BOOLEAN ignore whitespace when computing diffs
11681169
** nohdr omit the description at the top of the page
1169
-**
1170
+** nc omit branch coloration from the header graph
1171
+** inv "Invert". Exchange the roles of from= and to=
11701172
**
11711173
** Show all differences between two check-ins.
11721174
*/
11731175
void vdiff_page(void){
11741176
int ridFrom, ridTo;
@@ -1178,75 +1180,90 @@
11781180
ManifestFile *pFileFrom, *pFileTo;
11791181
const char *zBranch;
11801182
const char *zFrom;
11811183
const char *zTo;
11821184
const char *zRe;
1183
- const char *zW;
11841185
const char *zGlob;
1185
- char *zQuery;
11861186
char *zMergeOrigin = 0;
11871187
ReCompiled *pRe = 0;
1188
+ int graphFlags = 0;
1189
+ Blob qp;
1190
+ int bInvert = PB("inv");
1191
+
11881192
login_check_credentials();
11891193
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
11901194
login_anonymous_available();
11911195
load_control();
1196
+ blob_init(&qp, 0, 0);
11921197
diffType = preferred_diff_type();
11931198
zRe = P("regex");
11941199
if( zRe ) re_compile(&pRe, zRe, 0);
11951200
zBranch = P("branch");
11961201
if( zBranch && zBranch[0]==0 ) zBranch = 0;
11971202
if( zBranch ){
1198
- zQuery = mprintf("branch=%T", zBranch);
1203
+ blob_appendf(&qp, "branch=%T", zBranch);
11991204
zMergeOrigin = mprintf("merge-in:%s", zBranch);
12001205
cgi_replace_parameter("from", zMergeOrigin);
12011206
cgi_replace_parameter("to", zBranch);
12021207
}else{
1203
- zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to",""));
1208
+ if( bInvert ){
1209
+ blob_appendf(&qp, "to=%T&from=%T",PD("from",""),PD("to",""));
1210
+ }else{
1211
+ blob_appendf(&qp, "from=%T&to=%T",PD("from",""),PD("to",""));
1212
+ }
12041213
}
12051214
pTo = vdiff_parse_manifest("to", &ridTo);
12061215
if( pTo==0 ) return;
12071216
pFrom = vdiff_parse_manifest("from", &ridFrom);
12081217
if( pFrom==0 ) return;
12091218
zGlob = P("glob");
12101219
zFrom = P("from");
12111220
zTo = P("to");
1212
- if(zGlob && !*zGlob){
1213
- zGlob = NULL;
1221
+ if( bInvert ){
1222
+ Manifest *pTemp = pTo;
1223
+ const char *zTemp = zTo;
1224
+ pTo = pFrom;
1225
+ pFrom = pTemp;
1226
+ zTo = zFrom;
1227
+ zFrom = zTemp;
1228
+ }
1229
+ if( zGlob ){
1230
+ if( !*zGlob ){
1231
+ zGlob = NULL;
1232
+ }else{
1233
+ blob_appendf(&qp, "&glob=%T", zGlob);
1234
+ }
1235
+ }
1236
+ if( PB("nc") ){
1237
+ graphFlags |= TIMELINE_NOCOLOR;
1238
+ blob_appendf(&qp, "&nc");
12141239
}
12151240
diffFlags = construct_diff_flags(diffType);
1216
- zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1241
+ if( diffFlags & DIFF_IGNORE_ALLWS ){
1242
+ blob_appendf(&qp, "&w");
1243
+ }
12171244
style_set_current_feature("vdiff");
12181245
if( zBranch==0 ){
12191246
style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
12201247
}
12211248
if( diffType!=0 ){
1222
- style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s",
1223
- zQuery,
1224
- zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1249
+ style_submenu_element("Hide Diff", "%R/vdiff?diff=0&%b", &qp);
12251250
}
12261251
if( diffType!=2 ){
1227
- style_submenu_element("Side-by-Side Diff",
1228
- "%R/vdiff?%s&diff=2%s%T%s",
1229
- zQuery,
1230
- zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1252
+ style_submenu_element("Side-by-Side Diff", "%R/vdiff?diff=2&%b", &qp);
12311253
}
12321254
if( diffType!=1 ) {
1233
- style_submenu_element("Unified Diff",
1234
- "%R/vdiff?%s&diff=1%s%T%s",
1235
- zQuery,
1236
- zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1255
+ style_submenu_element("Unified Diff", "%R/vdiff?diff=1&%b", &qp);
12371256
}
12381257
if( zBranch==0 ){
1239
- style_submenu_element("Invert",
1240
- "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1241
- zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1258
+ style_submenu_element("Invert","%R/vdiff?diff=%d&inv&%b", diffType, &qp);
12421259
}
12431260
if( zGlob ){
1244
- style_submenu_element("Clear glob",
1245
- "%R/vdiff?%s&%s", zQuery, zW);
1261
+ style_submenu_element("Clear glob", "%R/vdiff?diff=%d&%b", diffType, &qp);
12461262
}else{
1247
- style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1263
+ style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo,
1264
+ (diffFlags & DIFF_IGNORE_ALLWS)?"&w":"");
12481265
}
12491266
if( diffType!=0 ){
12501267
style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
12511268
}
12521269
if( zBranch ){
@@ -1274,21 +1291,21 @@
12741291
@ <h2>Difference From <span class='timelineSelected'>\
12751292
@ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span>
12761293
@ To <span class='timelineSelected timelineSecondary'>\
12771294
@ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2>
12781295
}
1279
- render_checkin_context(ridFrom, ridTo, 0);
1296
+ render_checkin_context(ridFrom, ridTo, 0, graphFlags);
12801297
if( pRe ){
12811298
@ <p><b>Only differences that match regular expression "%h(zRe)"
12821299
@ are shown.</b></p>
12831300
}
12841301
if( zGlob ){
12851302
@ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
12861303
}
12871304
@<hr /><p>
12881305
}
1289
- fossil_free(zQuery);
1306
+ blob_reset(&qp);
12901307
12911308
manifest_file_rewind(pFrom);
12921309
pFileFrom = manifest_file_next(pFrom, 0);
12931310
manifest_file_rewind(pTo);
12941311
pFileTo = manifest_file_next(pTo, 0);
@@ -2339,11 +2356,11 @@
23392356
return;
23402357
}
23412358
23422359
url_initialize(&url, g.zPath);
23432360
url_add_parameter(&url, "name", zName);
2344
- url_add_parameter(&url, "ci", zCI);
2361
+ url_add_parameter(&url, "ci", zCI); /* no-op if zCI is NULL */
23452362
23462363
if( zCI==0 && !isFile ){
23472364
/* If there is no ci= query parameter, then prefer to interpret
23482365
** name= as a hash for /artifact and /whatis. But for not for /file.
23492366
** For /file, a name= without a ci= while prefer to use the default
@@ -2381,11 +2398,12 @@
23812398
" ORDER BY event.mtime DESC",
23822399
zName
23832400
);
23842401
if( db_step(&q)==SQLITE_ROW ){
23852402
rid = db_column_int(&q, 0);
2386
- zCI = zCIUuid = fossil_strdup(db_column_text(&q, 1));
2403
+ zCI = fossil_strdup(db_column_text(&q, 1));
2404
+ zCIUuid = fossil_strdup(zCI);
23872405
url_add_parameter(&url, "ci", zCI);
23882406
}
23892407
db_finalize(&q);
23902408
if( rid==0 ){
23912409
style_header("No such file");
23922410
--- src/info.c
+++ src/info.c
@@ -270,13 +270,13 @@
270 }
271 }
272
273 /*
274 ** Show the context graph (immediate parents and children) for
275 ** check-in rid.
276 */
277 void render_checkin_context(int rid, int rid2, int parentsOnly){
278 Blob sql;
279 Stmt q;
280 int rx[2];
281 int i, n;
282 rx[0] = rid;
@@ -313,11 +313,12 @@
313 }
314 }
315 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
316 db_prepare(&q, "%s", blob_sql_text(&sql));
317 www_print_timeline(&q,
318 TIMELINE_GRAPH
 
319 |TIMELINE_FILLGAPS
320 |TIMELINE_NOSCROLL
321 |TIMELINE_XMERGE
322 |TIMELINE_CHPICK,
323 0, 0, 0, rid, rid2, 0);
@@ -880,11 +881,11 @@
880 if( !PB("nowiki") ){
881 wiki_render_associated("checkin", zUuid, 0);
882 }
883 render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n");
884 @ <div class="section">Context</div>
885 render_checkin_context(rid, 0, 0);
886 @ <div class="section">Changes</div>
887 @ <div class="sectionmenu">
888 diffFlags = construct_diff_flags(diffType);
889 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
890 if( diffType!=0 ){
@@ -1164,11 +1165,12 @@
1164 ** diff=INTEGER 0: none, 1: unified, 2: side-by-side
1165 ** glob=STRING only diff files matching this glob
1166 ** dc=N show N lines of context around each diff
1167 ** w=BOOLEAN ignore whitespace when computing diffs
1168 ** nohdr omit the description at the top of the page
1169 **
 
1170 **
1171 ** Show all differences between two check-ins.
1172 */
1173 void vdiff_page(void){
1174 int ridFrom, ridTo;
@@ -1178,75 +1180,90 @@
1178 ManifestFile *pFileFrom, *pFileTo;
1179 const char *zBranch;
1180 const char *zFrom;
1181 const char *zTo;
1182 const char *zRe;
1183 const char *zW;
1184 const char *zGlob;
1185 char *zQuery;
1186 char *zMergeOrigin = 0;
1187 ReCompiled *pRe = 0;
 
 
 
 
1188 login_check_credentials();
1189 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1190 login_anonymous_available();
1191 load_control();
 
1192 diffType = preferred_diff_type();
1193 zRe = P("regex");
1194 if( zRe ) re_compile(&pRe, zRe, 0);
1195 zBranch = P("branch");
1196 if( zBranch && zBranch[0]==0 ) zBranch = 0;
1197 if( zBranch ){
1198 zQuery = mprintf("branch=%T", zBranch);
1199 zMergeOrigin = mprintf("merge-in:%s", zBranch);
1200 cgi_replace_parameter("from", zMergeOrigin);
1201 cgi_replace_parameter("to", zBranch);
1202 }else{
1203 zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to",""));
 
 
 
 
1204 }
1205 pTo = vdiff_parse_manifest("to", &ridTo);
1206 if( pTo==0 ) return;
1207 pFrom = vdiff_parse_manifest("from", &ridFrom);
1208 if( pFrom==0 ) return;
1209 zGlob = P("glob");
1210 zFrom = P("from");
1211 zTo = P("to");
1212 if(zGlob && !*zGlob){
1213 zGlob = NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1214 }
1215 diffFlags = construct_diff_flags(diffType);
1216 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
 
 
1217 style_set_current_feature("vdiff");
1218 if( zBranch==0 ){
1219 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1220 }
1221 if( diffType!=0 ){
1222 style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s",
1223 zQuery,
1224 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1225 }
1226 if( diffType!=2 ){
1227 style_submenu_element("Side-by-Side Diff",
1228 "%R/vdiff?%s&diff=2%s%T%s",
1229 zQuery,
1230 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1231 }
1232 if( diffType!=1 ) {
1233 style_submenu_element("Unified Diff",
1234 "%R/vdiff?%s&diff=1%s%T%s",
1235 zQuery,
1236 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1237 }
1238 if( zBranch==0 ){
1239 style_submenu_element("Invert",
1240 "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1241 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1242 }
1243 if( zGlob ){
1244 style_submenu_element("Clear glob",
1245 "%R/vdiff?%s&%s", zQuery, zW);
1246 }else{
1247 style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
 
1248 }
1249 if( diffType!=0 ){
1250 style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
1251 }
1252 if( zBranch ){
@@ -1274,21 +1291,21 @@
1274 @ <h2>Difference From <span class='timelineSelected'>\
1275 @ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span>
1276 @ To <span class='timelineSelected timelineSecondary'>\
1277 @ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2>
1278 }
1279 render_checkin_context(ridFrom, ridTo, 0);
1280 if( pRe ){
1281 @ <p><b>Only differences that match regular expression "%h(zRe)"
1282 @ are shown.</b></p>
1283 }
1284 if( zGlob ){
1285 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1286 }
1287 @<hr /><p>
1288 }
1289 fossil_free(zQuery);
1290
1291 manifest_file_rewind(pFrom);
1292 pFileFrom = manifest_file_next(pFrom, 0);
1293 manifest_file_rewind(pTo);
1294 pFileTo = manifest_file_next(pTo, 0);
@@ -2339,11 +2356,11 @@
2339 return;
2340 }
2341
2342 url_initialize(&url, g.zPath);
2343 url_add_parameter(&url, "name", zName);
2344 url_add_parameter(&url, "ci", zCI);
2345
2346 if( zCI==0 && !isFile ){
2347 /* If there is no ci= query parameter, then prefer to interpret
2348 ** name= as a hash for /artifact and /whatis. But for not for /file.
2349 ** For /file, a name= without a ci= while prefer to use the default
@@ -2381,11 +2398,12 @@
2381 " ORDER BY event.mtime DESC",
2382 zName
2383 );
2384 if( db_step(&q)==SQLITE_ROW ){
2385 rid = db_column_int(&q, 0);
2386 zCI = zCIUuid = fossil_strdup(db_column_text(&q, 1));
 
2387 url_add_parameter(&url, "ci", zCI);
2388 }
2389 db_finalize(&q);
2390 if( rid==0 ){
2391 style_header("No such file");
2392
--- src/info.c
+++ src/info.c
@@ -270,13 +270,13 @@
270 }
271 }
272
273 /*
274 ** Show the context graph (immediate parents and children) for
275 ** check-in rid and rid2
276 */
277 void render_checkin_context(int rid, int rid2, int parentsOnly, int mFlags){
278 Blob sql;
279 Stmt q;
280 int rx[2];
281 int i, n;
282 rx[0] = rid;
@@ -313,11 +313,12 @@
313 }
314 }
315 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
316 db_prepare(&q, "%s", blob_sql_text(&sql));
317 www_print_timeline(&q,
318 mFlags
319 |TIMELINE_GRAPH
320 |TIMELINE_FILLGAPS
321 |TIMELINE_NOSCROLL
322 |TIMELINE_XMERGE
323 |TIMELINE_CHPICK,
324 0, 0, 0, rid, rid2, 0);
@@ -880,11 +881,11 @@
881 if( !PB("nowiki") ){
882 wiki_render_associated("checkin", zUuid, 0);
883 }
884 render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n");
885 @ <div class="section">Context</div>
886 render_checkin_context(rid, 0, 0, 0);
887 @ <div class="section">Changes</div>
888 @ <div class="sectionmenu">
889 diffFlags = construct_diff_flags(diffType);
890 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
891 if( diffType!=0 ){
@@ -1164,11 +1165,12 @@
1165 ** diff=INTEGER 0: none, 1: unified, 2: side-by-side
1166 ** glob=STRING only diff files matching this glob
1167 ** dc=N show N lines of context around each diff
1168 ** w=BOOLEAN ignore whitespace when computing diffs
1169 ** nohdr omit the description at the top of the page
1170 ** nc omit branch coloration from the header graph
1171 ** inv "Invert". Exchange the roles of from= and to=
1172 **
1173 ** Show all differences between two check-ins.
1174 */
1175 void vdiff_page(void){
1176 int ridFrom, ridTo;
@@ -1178,75 +1180,90 @@
1180 ManifestFile *pFileFrom, *pFileTo;
1181 const char *zBranch;
1182 const char *zFrom;
1183 const char *zTo;
1184 const char *zRe;
 
1185 const char *zGlob;
 
1186 char *zMergeOrigin = 0;
1187 ReCompiled *pRe = 0;
1188 int graphFlags = 0;
1189 Blob qp;
1190 int bInvert = PB("inv");
1191
1192 login_check_credentials();
1193 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1194 login_anonymous_available();
1195 load_control();
1196 blob_init(&qp, 0, 0);
1197 diffType = preferred_diff_type();
1198 zRe = P("regex");
1199 if( zRe ) re_compile(&pRe, zRe, 0);
1200 zBranch = P("branch");
1201 if( zBranch && zBranch[0]==0 ) zBranch = 0;
1202 if( zBranch ){
1203 blob_appendf(&qp, "branch=%T", zBranch);
1204 zMergeOrigin = mprintf("merge-in:%s", zBranch);
1205 cgi_replace_parameter("from", zMergeOrigin);
1206 cgi_replace_parameter("to", zBranch);
1207 }else{
1208 if( bInvert ){
1209 blob_appendf(&qp, "to=%T&from=%T",PD("from",""),PD("to",""));
1210 }else{
1211 blob_appendf(&qp, "from=%T&to=%T",PD("from",""),PD("to",""));
1212 }
1213 }
1214 pTo = vdiff_parse_manifest("to", &ridTo);
1215 if( pTo==0 ) return;
1216 pFrom = vdiff_parse_manifest("from", &ridFrom);
1217 if( pFrom==0 ) return;
1218 zGlob = P("glob");
1219 zFrom = P("from");
1220 zTo = P("to");
1221 if( bInvert ){
1222 Manifest *pTemp = pTo;
1223 const char *zTemp = zTo;
1224 pTo = pFrom;
1225 pFrom = pTemp;
1226 zTo = zFrom;
1227 zFrom = zTemp;
1228 }
1229 if( zGlob ){
1230 if( !*zGlob ){
1231 zGlob = NULL;
1232 }else{
1233 blob_appendf(&qp, "&glob=%T", zGlob);
1234 }
1235 }
1236 if( PB("nc") ){
1237 graphFlags |= TIMELINE_NOCOLOR;
1238 blob_appendf(&qp, "&nc");
1239 }
1240 diffFlags = construct_diff_flags(diffType);
1241 if( diffFlags & DIFF_IGNORE_ALLWS ){
1242 blob_appendf(&qp, "&w");
1243 }
1244 style_set_current_feature("vdiff");
1245 if( zBranch==0 ){
1246 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1247 }
1248 if( diffType!=0 ){
1249 style_submenu_element("Hide Diff", "%R/vdiff?diff=0&%b", &qp);
 
 
1250 }
1251 if( diffType!=2 ){
1252 style_submenu_element("Side-by-Side Diff", "%R/vdiff?diff=2&%b", &qp);
 
 
 
1253 }
1254 if( diffType!=1 ) {
1255 style_submenu_element("Unified Diff", "%R/vdiff?diff=1&%b", &qp);
 
 
 
1256 }
1257 if( zBranch==0 ){
1258 style_submenu_element("Invert","%R/vdiff?diff=%d&inv&%b", diffType, &qp);
 
 
1259 }
1260 if( zGlob ){
1261 style_submenu_element("Clear glob", "%R/vdiff?diff=%d&%b", diffType, &qp);
 
1262 }else{
1263 style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo,
1264 (diffFlags & DIFF_IGNORE_ALLWS)?"&w":"");
1265 }
1266 if( diffType!=0 ){
1267 style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
1268 }
1269 if( zBranch ){
@@ -1274,21 +1291,21 @@
1291 @ <h2>Difference From <span class='timelineSelected'>\
1292 @ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span>
1293 @ To <span class='timelineSelected timelineSecondary'>\
1294 @ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2>
1295 }
1296 render_checkin_context(ridFrom, ridTo, 0, graphFlags);
1297 if( pRe ){
1298 @ <p><b>Only differences that match regular expression "%h(zRe)"
1299 @ are shown.</b></p>
1300 }
1301 if( zGlob ){
1302 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1303 }
1304 @<hr /><p>
1305 }
1306 blob_reset(&qp);
1307
1308 manifest_file_rewind(pFrom);
1309 pFileFrom = manifest_file_next(pFrom, 0);
1310 manifest_file_rewind(pTo);
1311 pFileTo = manifest_file_next(pTo, 0);
@@ -2339,11 +2356,11 @@
2356 return;
2357 }
2358
2359 url_initialize(&url, g.zPath);
2360 url_add_parameter(&url, "name", zName);
2361 url_add_parameter(&url, "ci", zCI); /* no-op if zCI is NULL */
2362
2363 if( zCI==0 && !isFile ){
2364 /* If there is no ci= query parameter, then prefer to interpret
2365 ** name= as a hash for /artifact and /whatis. But for not for /file.
2366 ** For /file, a name= without a ci= while prefer to use the default
@@ -2381,11 +2398,12 @@
2398 " ORDER BY event.mtime DESC",
2399 zName
2400 );
2401 if( db_step(&q)==SQLITE_ROW ){
2402 rid = db_column_int(&q, 0);
2403 zCI = fossil_strdup(db_column_text(&q, 1));
2404 zCIUuid = fossil_strdup(zCI);
2405 url_add_parameter(&url, "ci", zCI);
2406 }
2407 db_finalize(&q);
2408 if( rid==0 ){
2409 style_header("No such file");
2410
--- src/json_branch.c
+++ src/json_branch.c
@@ -154,11 +154,11 @@
154154
*/
155155
typedef struct BranchCreateOptions{
156156
char const * zName;
157157
char const * zBasis;
158158
char const * zColor;
159
- char isPrivate;
159
+ int isPrivate;
160160
/**
161161
Might be set to an error string by
162162
json_branch_new().
163163
*/
164164
char const * rcErrMsg;
@@ -197,11 +197,16 @@
197197
char *zDate; /* Date that branch was created */
198198
char *zComment; /* Check-in comment for the new branch */
199199
Blob branch; /* manifest for the new branch */
200200
Manifest *pParent; /* Parsed parent manifest */
201201
Blob mcksum; /* Self-checksum on the manifest */
202
+ int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
202203
204
+ if( fossil_strncmp(zColor, "auto", 4)==0 ) {
205
+ bAutoColor = 1;
206
+ zColor = 0;
207
+ }
203208
/* fossil branch new name */
204209
if( zBranch==0 || zBranch[0]==0 ){
205210
zOpt->rcErrMsg = "Branch name may not be null/empty.";
206211
return FSL_JSON_E_INVALID_ARGS;
207212
}
@@ -260,11 +265,11 @@
260265
manifest_destroy(pParent);
261266
262267
/* Add the symbolic branch name and the "branch" tag to identify
263268
** this as a new branch */
264269
if( content_is_private(rootid) ) zOpt->isPrivate = 1;
265
- if( zOpt->isPrivate && zColor==0 ) zColor = "#fec084";
270
+ if( zOpt->isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
266271
if( zColor!=0 ){
267272
blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
268273
}
269274
blob_appendf(&branch, "T *branch * %F\n", zBranch);
270275
blob_appendf(&branch, "T *sym-%F *\n", zBranch);
271276
--- src/json_branch.c
+++ src/json_branch.c
@@ -154,11 +154,11 @@
154 */
155 typedef struct BranchCreateOptions{
156 char const * zName;
157 char const * zBasis;
158 char const * zColor;
159 char isPrivate;
160 /**
161 Might be set to an error string by
162 json_branch_new().
163 */
164 char const * rcErrMsg;
@@ -197,11 +197,16 @@
197 char *zDate; /* Date that branch was created */
198 char *zComment; /* Check-in comment for the new branch */
199 Blob branch; /* manifest for the new branch */
200 Manifest *pParent; /* Parsed parent manifest */
201 Blob mcksum; /* Self-checksum on the manifest */
 
202
 
 
 
 
203 /* fossil branch new name */
204 if( zBranch==0 || zBranch[0]==0 ){
205 zOpt->rcErrMsg = "Branch name may not be null/empty.";
206 return FSL_JSON_E_INVALID_ARGS;
207 }
@@ -260,11 +265,11 @@
260 manifest_destroy(pParent);
261
262 /* Add the symbolic branch name and the "branch" tag to identify
263 ** this as a new branch */
264 if( content_is_private(rootid) ) zOpt->isPrivate = 1;
265 if( zOpt->isPrivate && zColor==0 ) zColor = "#fec084";
266 if( zColor!=0 ){
267 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
268 }
269 blob_appendf(&branch, "T *branch * %F\n", zBranch);
270 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
271
--- src/json_branch.c
+++ src/json_branch.c
@@ -154,11 +154,11 @@
154 */
155 typedef struct BranchCreateOptions{
156 char const * zName;
157 char const * zBasis;
158 char const * zColor;
159 int isPrivate;
160 /**
161 Might be set to an error string by
162 json_branch_new().
163 */
164 char const * rcErrMsg;
@@ -197,11 +197,16 @@
197 char *zDate; /* Date that branch was created */
198 char *zComment; /* Check-in comment for the new branch */
199 Blob branch; /* manifest for the new branch */
200 Manifest *pParent; /* Parsed parent manifest */
201 Blob mcksum; /* Self-checksum on the manifest */
202 int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
203
204 if( fossil_strncmp(zColor, "auto", 4)==0 ) {
205 bAutoColor = 1;
206 zColor = 0;
207 }
208 /* fossil branch new name */
209 if( zBranch==0 || zBranch[0]==0 ){
210 zOpt->rcErrMsg = "Branch name may not be null/empty.";
211 return FSL_JSON_E_INVALID_ARGS;
212 }
@@ -260,11 +265,11 @@
265 manifest_destroy(pParent);
266
267 /* Add the symbolic branch name and the "branch" tag to identify
268 ** this as a new branch */
269 if( content_is_private(rootid) ) zOpt->isPrivate = 1;
270 if( zOpt->isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084";
271 if( zColor!=0 ){
272 blob_appendf(&branch, "T *bgcolor * %F\n", zColor);
273 }
274 blob_appendf(&branch, "T *branch * %F\n", zBranch);
275 blob_appendf(&branch, "T *sym-%F *\n", zBranch);
276
+3 -2
--- src/linenoise.c
+++ src/linenoise.c
@@ -1028,21 +1028,22 @@
10281028
static char *linenoiseNoTTY(void) {
10291029
char *line = NULL;
10301030
size_t len = 0, maxlen = 0;
10311031
10321032
while(1) {
1033
+ int c;
10331034
if (len == maxlen) {
1035
+ char *oldval = line;
10341036
if (maxlen == 0) maxlen = 16;
10351037
maxlen *= 2;
1036
- char *oldval = line;
10371038
line = realloc(line,maxlen);
10381039
if (line == NULL) {
10391040
if (oldval) free(oldval);
10401041
return NULL;
10411042
}
10421043
}
1043
- int c = fgetc(stdin);
1044
+ c = fgetc(stdin);
10441045
if (c == EOF || c == '\n') {
10451046
if (c == EOF && len == 0) {
10461047
free(line);
10471048
return NULL;
10481049
} else {
10491050
--- src/linenoise.c
+++ src/linenoise.c
@@ -1028,21 +1028,22 @@
1028 static char *linenoiseNoTTY(void) {
1029 char *line = NULL;
1030 size_t len = 0, maxlen = 0;
1031
1032 while(1) {
 
1033 if (len == maxlen) {
 
1034 if (maxlen == 0) maxlen = 16;
1035 maxlen *= 2;
1036 char *oldval = line;
1037 line = realloc(line,maxlen);
1038 if (line == NULL) {
1039 if (oldval) free(oldval);
1040 return NULL;
1041 }
1042 }
1043 int c = fgetc(stdin);
1044 if (c == EOF || c == '\n') {
1045 if (c == EOF && len == 0) {
1046 free(line);
1047 return NULL;
1048 } else {
1049
--- src/linenoise.c
+++ src/linenoise.c
@@ -1028,21 +1028,22 @@
1028 static char *linenoiseNoTTY(void) {
1029 char *line = NULL;
1030 size_t len = 0, maxlen = 0;
1031
1032 while(1) {
1033 int c;
1034 if (len == maxlen) {
1035 char *oldval = line;
1036 if (maxlen == 0) maxlen = 16;
1037 maxlen *= 2;
 
1038 line = realloc(line,maxlen);
1039 if (line == NULL) {
1040 if (oldval) free(oldval);
1041 return NULL;
1042 }
1043 }
1044 c = fgetc(stdin);
1045 if (c == EOF || c == '\n') {
1046 if (c == EOF && len == 0) {
1047 free(line);
1048 return NULL;
1049 } else {
1050
--- src/login.c
+++ src/login.c
@@ -1778,10 +1778,11 @@
17781778
zDecoded = captcha_decode(uSeed);
17791779
zCaptcha = captcha_render(zDecoded);
17801780
17811781
style_header("Register");
17821782
/* Print out the registration form. */
1783
+ g.perm.Hyperlink = 1; /* Artificially enable hyperlinks */
17831784
form_begin(0, "%R/register");
17841785
if( P("g") ){
17851786
@ <input type="hidden" name="g" value="%h(P("g"))" />
17861787
}
17871788
@ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
17881789
--- src/login.c
+++ src/login.c
@@ -1778,10 +1778,11 @@
1778 zDecoded = captcha_decode(uSeed);
1779 zCaptcha = captcha_render(zDecoded);
1780
1781 style_header("Register");
1782 /* Print out the registration form. */
 
1783 form_begin(0, "%R/register");
1784 if( P("g") ){
1785 @ <input type="hidden" name="g" value="%h(P("g"))" />
1786 }
1787 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1788
--- src/login.c
+++ src/login.c
@@ -1778,10 +1778,11 @@
1778 zDecoded = captcha_decode(uSeed);
1779 zCaptcha = captcha_render(zDecoded);
1780
1781 style_header("Register");
1782 /* Print out the registration form. */
1783 g.perm.Hyperlink = 1; /* Artificially enable hyperlinks */
1784 form_begin(0, "%R/register");
1785 if( P("g") ){
1786 @ <input type="hidden" name="g" value="%h(P("g"))" />
1787 }
1788 @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
1789
+170 -47
--- src/main.c
+++ src/main.c
@@ -143,10 +143,11 @@
143143
144144
struct Global {
145145
int argc; char **argv; /* Command-line arguments to the program */
146146
char *nameOfExe; /* Full path of executable. */
147147
const char *zErrlog; /* Log errors to this file, if not NULL */
148
+ const char *zPhase; /* Phase of operation, for use by the error log */
148149
int isConst; /* True if the output is unchanging & cacheable */
149150
const char *zVfsName; /* The VFS to use for database connections */
150151
sqlite3 *db; /* The connection to the databases */
151152
sqlite3 *dbConfig; /* Separate connection for global_config table */
152153
char *zAuxSchema; /* Main repository aux-schema */
@@ -473,11 +474,17 @@
473474
nArg = g.argc + nLine*2;
474475
newArgv = fossil_malloc( sizeof(char*)*nArg );
475476
for(j=0; j<i; j++) newArgv[j] = g.argv[j];
476477
477478
blob_rewind(&file);
478
- while( (n = blob_line(&file, &line))>0 ){
479
+ while( nLine-->0 && (n = blob_line(&file, &line))>0 ){
480
+ /* Reminder: ^^^ nLine check avoids that embedded NUL bytes in the
481
+ ** --args file causes nLine to be less than blob_line() will end
482
+ ** up reporting, as such a miscount leads to an illegal memory
483
+ ** write. See forum post
484
+ ** https://fossil-scm.org/forum/forumpost/7b34eecc1b8c for
485
+ ** details */
479486
if( n<1 ){
480487
/* Reminder: corner-case: a line with 1 byte and no newline. */
481488
continue;
482489
}
483490
z = blob_buffer(&line);
@@ -667,10 +674,11 @@
667674
int fossil_main(int argc, char **argv){
668675
const char *zCmdName = "unknown";
669676
const CmdOrPage *pCmd = 0;
670677
int rc;
671678
679
+ g.zPhase = "init";
672680
#if !defined(_WIN32_WCE)
673681
if( fossil_getenv("FOSSIL_BREAK") ){
674682
if( isatty(0) && isatty(2) ){
675683
fprintf(stderr,
676684
"attach debugger to process %d and press any key to continue.\n",
@@ -951,11 +959,13 @@
951959
rc = TH_OK;
952960
}
953961
if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
954962
if( rc==TH_OK || rc==TH_RETURN ){
955963
#endif
964
+ g.zPhase = pCmd->zName;
956965
pCmd->xFunc();
966
+ g.zPhase = "shutdown";
957967
#ifdef FOSSIL_ENABLE_TH1_HOOKS
958968
}
959969
if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
960970
Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags);
961971
}
@@ -1403,11 +1413,24 @@
14031413
g.zTop = &g.zBaseURL[7+strlen(z)];
14041414
g.zHttpsURL = mprintf("https://%s%.*s", z, i, zCur);
14051415
}
14061416
fossil_free(z);
14071417
}
1408
- if( db_is_writeable("repository") ){
1418
+
1419
+ /* Try to record the base URL as a CONFIG table entry with a name
1420
+ ** of the form: "baseurl:BASE". This keeps a record of how the
1421
+ ** the repository is used as a server, to help in answering questions
1422
+ ** like "where is the CGI script that references this repository?"
1423
+ **
1424
+ ** This is just a logging hint. So don't worry if it cannot be done.
1425
+ ** Don't try this if the repository database is not writable, for
1426
+ ** example.
1427
+ **
1428
+ ** If g.useLocalauth is set, that (probably) means that we are running
1429
+ ** "fossil ui" and there is no point in logging those cases either.
1430
+ */
1431
+ if( db_is_writeable("repository") && !g.useLocalauth ){
14091432
int nBase = (int)strlen(g.zBaseURL);
14101433
char *zBase = g.zBaseURL;
14111434
if( g.nExtraURL>0 && g.nExtraURL<nBase-6 ){
14121435
zBase = fossil_strndup(g.zBaseURL, nBase - g.nExtraURL);
14131436
}
@@ -1508,17 +1531,17 @@
15081531
size_t i;
15091532
Blob out;
15101533
size = backtrace(array, sizeof(array)/sizeof(array[0]));
15111534
strings = backtrace_symbols(array, size);
15121535
blob_init(&out, 0, 0);
1513
- blob_appendf(&out, "Segfault");
1536
+ blob_appendf(&out, "Segfault during %s", g.zPhase);
15141537
for(i=0; i<size; i++){
15151538
blob_appendf(&out, "\n(%d) %s", i, strings[i]);
15161539
}
15171540
fossil_panic("%s", blob_str(&out));
15181541
#else
1519
- fossil_panic("Segfault");
1542
+ fossil_panic("Segfault during %s", g.zPhase);
15201543
#endif
15211544
exit(1);
15221545
}
15231546
15241547
/*
@@ -1529,10 +1552,11 @@
15291552
#ifndef _WIN32
15301553
if( g.fAnyTrace ){
15311554
fprintf(stderr,"/***** sigpipe received by subprocess %d ****\n", getpid());
15321555
}
15331556
#endif
1557
+ g.zPhase = "sigpipe shutdown";
15341558
db_panic_close();
15351559
exit(1);
15361560
}
15371561
15381562
/*
@@ -1601,10 +1625,11 @@
16011625
char *zPath = NULL;
16021626
int i;
16031627
const CmdOrPage *pCmd = 0;
16041628
const char *zBase = g.zRepositoryName;
16051629
1630
+ g.zPhase = "process_one_web_page";
16061631
#if !defined(_WIN32)
16071632
signal(SIGSEGV, sigsegv_handler);
16081633
#endif
16091634
16101635
/* Handle universal query parameters */
@@ -1824,20 +1849,14 @@
18241849
** been opened.
18251850
*/
18261851
18271852
18281853
/*
1829
- ** Check to see if the first term of PATH_INFO specifies an alternative
1830
- ** skin. This will be the case if the first term of PATH_INFO
1831
- ** begins with "draftN/" where N is an integer between 1 and 9 or
1832
- ** if it is "skn_X/" where X is one of the built-in skin names.
1833
- ** If either is true, then activate the alternative skin.a
1834
- **
1835
- ** If there are multiple skn_X entries (ex: /skn_default/skn_ardoise/...)
1836
- ** then skip over all but the last. This allows one to link to an
1837
- ** alternative skin in hyperlinks even if you are already in an alternative
1838
- ** skin.
1854
+ ** Check to see if the first term of PATH_INFO specifies an
1855
+ ** alternative skin. This will be the case if the first term of
1856
+ ** PATH_INFO begins with "draftN/" where N is an integer between 1
1857
+ ** and 9. If so, activate the skin associated with that draft.
18391858
*/
18401859
if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
18411860
&& zPathInfo[6]>='1' && zPathInfo[6]<='9'
18421861
&& (zPathInfo[7]=='/' || zPathInfo[7]==0)
18431862
){
@@ -2009,10 +2028,11 @@
20092028
rc = TH_OK;
20102029
}
20112030
if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
20122031
if( rc==TH_OK || rc==TH_RETURN ){
20132032
#endif
2033
+ g.zPhase = pCmd->zName;
20142034
pCmd->xFunc();
20152035
#ifdef FOSSIL_ENABLE_TH1_HOOKS
20162036
}
20172037
if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
20182038
Th_WebpageNotify(pCmd->zName+1, pCmd->eCmdFlags);
@@ -2022,10 +2042,11 @@
20222042
#endif
20232043
}
20242044
20252045
/* Return the result.
20262046
*/
2047
+ g.zPhase = "web-page reply";
20272048
cgi_reply();
20282049
}
20292050
20302051
/* If the CGI program contains one or more lines of the form
20312052
**
@@ -2728,11 +2749,11 @@
27282749
**
27292750
** Works like the [[http]] command but gives setup permission to all users.
27302751
**
27312752
** Options:
27322753
** --th-trace Trace TH1 execution (for debugging purposes)
2733
-** --usercap CAP User capability string (Default: "sx")
2754
+** --usercap CAP User capability string (Default: "sxy")
27342755
**
27352756
*/
27362757
void cmd_test_http(void){
27372758
const char *zIpAddr; /* IP address of remote client */
27382759
const char *zUserCap;
@@ -2739,11 +2760,11 @@
27392760
27402761
Th_InitTraceLog();
27412762
zUserCap = find_option("usercap",0,1);
27422763
if( zUserCap==0 ){
27432764
g.useLocalauth = 1;
2744
- zUserCap = "sx";
2765
+ zUserCap = "sxy";
27452766
}
27462767
login_set_capabilities(zUserCap, 0);
27472768
g.httpIn = stdin;
27482769
g.httpOut = stdout;
27492770
fossil_binary_mode(g.httpOut);
@@ -2768,12 +2789,17 @@
27682789
/*
27692790
** Respond to a SIGALRM by writing a message to the error log (if there
27702791
** is one) and exiting.
27712792
*/
27722793
#ifndef _WIN32
2794
+static int nAlarmSeconds = 0;
27732795
static void sigalrm_handler(int x){
2774
- fossil_panic("TIMEOUT");
2796
+ sqlite3_uint64 tmUser = 0, tmKernel = 0;
2797
+ fossil_cpu_times(&tmUser, &tmKernel);
2798
+ fossil_panic("Timeout after %d seconds during %s"
2799
+ " - user %,llu µs, sys %,llu µs",
2800
+ nAlarmSeconds, g.zPhase, tmUser, tmKernel);
27752801
}
27762802
#endif
27772803
27782804
/*
27792805
** Arrange to timeout using SIGALRM after N seconds. Or if N==0, cancel
@@ -2785,10 +2811,11 @@
27852811
*/
27862812
void fossil_set_timeout(int N){
27872813
#ifndef _WIN32
27882814
signal(SIGALRM, sigalrm_handler);
27892815
alarm(N);
2816
+ nAlarmSeconds = N;
27902817
#endif
27912818
}
27922819
27932820
/*
27942821
** COMMAND: server*
@@ -2797,19 +2824,30 @@
27972824
** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
27982825
** or: %fossil ui ?OPTIONS? ?REPOSITORY?
27992826
**
28002827
** Open a socket and begin listening and responding to HTTP requests on
28012828
** TCP port 8080, or on any other TCP port defined by the -P or
2802
-** --port option. The optional argument is the name of the repository.
2803
-** The repository argument may be omitted if the working directory is
2804
-** within an open checkout.
2829
+** --port option. The optional REPOSITORY argument is the name of the
2830
+** Fossil repository to be served. The REPOSITORY argument may be omitted
2831
+** if the working directory is within an open checkout, in which case the
2832
+** repository associated with that checkout is used.
28052833
**
28062834
** The "ui" command automatically starts a web browser after initializing
28072835
** the web server. The "ui" command also binds to 127.0.0.1 and so will
28082836
** only process HTTP traffic from the local machine.
28092837
**
2810
-** The REPOSITORY can be a directory (aka folder) that contains one or
2838
+** If REPOSITORY is a directory name which is the root of a
2839
+** checkout, then use the repository associated with that checkout.
2840
+** This only works for the "fossil ui" command, not the "fossil server"
2841
+** command.
2842
+**
2843
+** If REPOSITORY begins with a "HOST:" or "USER@HOST:" prefix, then
2844
+** the command is run on the remote host specified and the results are
2845
+** tunneled back to the local machine via SSH. This feature only works for
2846
+** the "fossil ui" command, not the "fossil server" command.
2847
+**
2848
+** REPOSITORY may also be a directory (aka folder) that contains one or
28112849
** more repositories with names ending in ".fossil". In this case, a
28122850
** prefix of the URL pathname is used to search the directory for an
28132851
** appropriate repository. To thwart mischief, the pathname in the URL must
28142852
** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
28152853
** occur after "/", and every "." must be surrounded on both sides by
@@ -2819,11 +2857,11 @@
28192857
** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
28202858
** "*.fossil*" will be served as static content. With the "ui" command,
28212859
** the REPOSITORY can only be a directory if the --notfound option is
28222860
** also present.
28232861
**
2824
-** For the special case REPOSITORY name of "/", the list global configuration
2862
+** For the special case REPOSITORY name of "/", the global configuration
28252863
** database is consulted for a list of all known repositories. The --repolist
28262864
** option is implied by this special case. See also the "fossil all ui"
28272865
** command.
28282866
**
28292867
** By default, the "ui" command provides full administrative access without
@@ -2838,10 +2876,12 @@
28382876
** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were
28392877
** /doc/ckout/...
28402878
** --create Create a new REPOSITORY if it does not already exist
28412879
** --extroot DIR Document root for the /ext extension mechanism
28422880
** --files GLOBLIST Comma-separated list of glob patterns for static files
2881
+** --fossilcmd PATH Full pathname of the "fossil" executable on the remote
2882
+** system when REPOSITORY is remote. Default: "fossil"
28432883
** --localauth enable automatic login for requests from localhost
28442884
** --localhost listen on 127.0.0.1 only (always true for "ui")
28452885
** --https Indicates that the input is coming through a reverse
28462886
** proxy that has already translated HTTPS into HTTP.
28472887
** --jsmode MODE Determine how JavaScript is delivered with pages.
@@ -2856,10 +2896,12 @@
28562896
** and bundled modes might result in a single
28572897
** amalgamated script or several, but both approaches
28582898
** result in fewer HTTP requests than the separate mode.
28592899
** --max-latency N Do not let any single HTTP request run for more than N
28602900
** seconds (only works on unix)
2901
+** --nobrowser Do not automatically launch a web-browser for the
2902
+** "fossil ui" command.
28612903
** --nocompress Do not compress HTTP replies
28622904
** --nojail Drop root privileges but do not enter the chroot jail
28632905
** --nossl signal that no SSL connections are available (Always
28642906
** set by default for the "ui" command)
28652907
** --notfound URL Redirect
@@ -2891,11 +2933,17 @@
28912933
int allowRepoList; /* List repositories on URL "/" */
28922934
const char *zAltBase; /* Argument to the --baseurl option */
28932935
const char *zFileGlob; /* Static content must match this */
28942936
char *zIpAddr = 0; /* Bind to this IP address */
28952937
int fCreate = 0; /* The --create flag */
2938
+ int fNoBrowser = 0; /* Do not auto-launch web-browser */
28962939
const char *zInitPage = 0; /* Start on this page. --page option */
2940
+ int findServerArg = 2; /* argv index for find_server_repository() */
2941
+ char *zRemote = 0; /* Remote host on which to run "fossil ui" */
2942
+ const char *zJsMode; /* The --jsmode parameter */
2943
+ const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */
2944
+
28972945
28982946
#if defined(_WIN32)
28992947
const char *zStopperFile; /* Name of file used to terminate server */
29002948
zStopperFile = find_option("stopper", 0, 1);
29012949
#endif
@@ -2902,11 +2950,12 @@
29022950
29032951
if( g.zErrlog==0 ){
29042952
g.zErrlog = "-";
29052953
}
29062954
g.zExtRoot = find_option("extroot",0,1);
2907
- builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
2955
+ zJsMode = find_option("jsmode",0,1);
2956
+ builtin_set_js_delivery_mode(zJsMode,0);
29082957
zFileGlob = find_option("files-urlenc",0,1);
29092958
if( zFileGlob ){
29102959
char *z = mprintf("%s", zFileGlob);
29112960
dehttpize(z);
29122961
zFileGlob = z;
@@ -2922,10 +2971,12 @@
29222971
Th_InitTraceLog();
29232972
zPort = find_option("port", "P", 1);
29242973
isUiCmd = g.argv[1][0]=='u';
29252974
if( isUiCmd ){
29262975
zInitPage = find_option("page", 0, 1);
2976
+ if( zInitPage && zInitPage[0]=='/' ) zInitPage++;
2977
+ zFossilCmd = find_option("fossilcmd", 0, 1);
29272978
}
29282979
zNotFound = find_option("notfound", 0, 1);
29292980
allowRepoList = find_option("repolist",0,0)!=0;
29302981
if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
29312982
zAltBase = find_option("baseurl", 0, 1);
@@ -2933,10 +2984,11 @@
29332984
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
29342985
if( zAltBase ){
29352986
set_base_url(zAltBase);
29362987
}
29372988
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
2989
+ fNoBrowser = find_option("nobrowser", 0, 0)!=0;
29382990
if( find_option("https",0,0)!=0 ){
29392991
cgi_replace_parameter("HTTPS","on");
29402992
}
29412993
if( find_option("localhost", 0, 0)!=0 ){
29422994
flags |= HTTP_SERVER_LOCALHOST;
@@ -2948,16 +3000,46 @@
29483000
}
29493001
/* We should be done with options.. */
29503002
verify_all_options();
29513003
29523004
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
3005
+ if( isUiCmd && 3==g.argc && file_isdir(g.argv[2], ExtFILE)>0 ){
3006
+ /* If REPOSITORY arg is the root of a checkout,
3007
+ ** chdir to that checkout so that the current version
3008
+ ** gets highlighted in the timeline by default. */
3009
+ const char * zDir = g.argv[2];
3010
+ if(dir_has_ckout_db(zDir)){
3011
+ if(0!=file_chdir(zDir, 0)){
3012
+ fossil_fatal("Cannot chdir to %s", zDir);
3013
+ }
3014
+ findServerArg = 99;
3015
+ fCreate = 0;
3016
+ g.argv[2] = 0;
3017
+ --g.argc;
3018
+ }
3019
+ }
3020
+ if( isUiCmd && 3==g.argc
3021
+ && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
3022
+ ){
3023
+ /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
3024
+ const char *zRepoTail = file_skip_userhost(g.argv[2]);
3025
+ unsigned x;
3026
+ int n;
3027
+ sqlite3_randomness(2,&x);
3028
+ zPort = mprintf("%d", 8100+(x%32000));
3029
+ n = (int)(zRepoTail - g.argv[2]) - 1;
3030
+ zRemote = mprintf("%.*s", n, g.argv[2]);
3031
+ g.argv[2] = (char*)zRepoTail;
3032
+ }
29533033
if( isUiCmd ){
29543034
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
29553035
g.useLocalauth = 1;
29563036
allowRepoList = 1;
29573037
}
2958
- find_server_repository(2, fCreate);
3038
+ if( !zRemote ){
3039
+ find_server_repository(findServerArg, fCreate);
3040
+ }
29593041
if( zInitPage==0 ){
29603042
if( isUiCmd && g.localOpen ){
29613043
zInitPage = "timeline?c=current";
29623044
}else{
29633045
zInitPage = "";
@@ -2979,25 +3061,73 @@
29793061
iPort = mxPort = atoi(zPort);
29803062
}else{
29813063
iPort = db_get_int("http-port", 8080);
29823064
mxPort = iPort+100;
29833065
}
2984
-#if !defined(_WIN32)
2985
- /* Unix implementation */
2986
- if( isUiCmd ){
3066
+ if( isUiCmd && !fNoBrowser ){
3067
+ char *zBrowserArg;
3068
+ if( zRemote ) db_open_config(0,0);
29873069
zBrowser = fossil_web_browser();
29883070
if( zIpAddr==0 ){
2989
- zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
2990
- zBrowser, zInitPage);
3071
+ zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
29913072
}else if( strchr(zIpAddr,':') ){
2992
- zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
2993
- zBrowser, zIpAddr, zInitPage);
3073
+ zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
29943074
}else{
2995
- zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
2996
- zBrowser, zIpAddr, zInitPage);
3075
+ zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3076
+ }
3077
+#ifdef _WIN32
3078
+ zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
3079
+#else
3080
+ zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3081
+#endif
3082
+ fossil_free(zBrowserArg);
3083
+ }
3084
+ if( zRemote ){
3085
+ /* If a USER@HOST:REPO argument is supplied, then use SSH to run
3086
+ ** "fossil ui --nobrowser" on the remote system and to set up a
3087
+ ** tunnel from the local machine to the remote. */
3088
+ FILE *sshIn;
3089
+ Blob ssh;
3090
+ char zLine[1000];
3091
+ blob_init(&ssh, 0, 0);
3092
+ transport_ssh_command(&ssh);
3093
+ db_close_config();
3094
+ if( zFossilCmd==0 ) zFossilCmd = "fossil";
3095
+ blob_appendf(&ssh,
3096
+ " -t -L 127.0.0.1:%d:127.0.0.1:%d %!$"
3097
+ " %$ ui --nobrowser --localauth --port %d",
3098
+ iPort, iPort, zRemote, zFossilCmd, iPort);
3099
+ if( zNotFound ) blob_appendf(&ssh, " --notfound %!$", zNotFound);
3100
+ if( zFileGlob ) blob_appendf(&ssh, " --files-urlenc %T", zFileGlob);
3101
+ if( g.zCkoutAlias ) blob_appendf(&ssh, " --ckout-alias %!$",g.zCkoutAlias);
3102
+ if( g.zExtRoot ) blob_appendf(&ssh, " --extroot %$", g.zExtRoot);
3103
+ if( skin_in_use() ) blob_appendf(&ssh, " --skin %s", skin_in_use());
3104
+ if( zJsMode ) blob_appendf(&ssh, " --jsmode %s", zJsMode);
3105
+ if( fCreate ) blob_appendf(&ssh, " --create");
3106
+ blob_appendf(&ssh, " %$", g.argv[2]);
3107
+ fossil_print("%s\n", blob_str(&ssh));
3108
+ sshIn = popen(blob_str(&ssh), "r");
3109
+ if( sshIn==0 ){
3110
+ fossil_fatal("unable to %s", blob_str(&ssh));
3111
+ }
3112
+ while( fgets(zLine, sizeof(zLine), sshIn) ){
3113
+ fputs(zLine, stdout);
3114
+ fflush(stdout);
3115
+ if( zBrowserCmd && sqlite3_strglob("*Listening for HTTP*",zLine)==0 ){
3116
+ char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
3117
+ fossil_system(zCmd);
3118
+ fossil_free(zCmd);
3119
+ fossil_free(zBrowserCmd);
3120
+ zBrowserCmd = 0;
3121
+ }
29973122
}
3123
+ pclose(sshIn);
3124
+ fossil_free(zBrowserCmd);
3125
+ return;
29983126
}
3127
+#if !defined(_WIN32)
3128
+ /* Unix implementation */
29993129
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
30003130
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
30013131
db_close(1);
30023132
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
30033133
fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3044,23 +3174,10 @@
30443174
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
30453175
getpid());
30463176
}
30473177
#else
30483178
/* Win32 implementation */
3049
- if( isUiCmd ){
3050
- zBrowser = fossil_web_browser();
3051
- if( zIpAddr==0 ){
3052
- zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
3053
- zBrowser, zInitPage);
3054
- }else if( strchr(zIpAddr,':') ){
3055
- zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
3056
- zBrowser, zIpAddr, zInitPage);
3057
- }else{
3058
- zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
3059
- zBrowser, zIpAddr, zInitPage);
3060
- }
3061
- }
30623179
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
30633180
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
30643181
db_close(1);
30653182
if( allowRepoList ){
30663183
flags |= HTTP_SERVER_REPOLIST;
@@ -3132,11 +3249,11 @@
31323249
@ <p>Generate a message to the <a href="%R/errorlog">error log</a>
31333250
@ by clicking on one of the following cases:
31343251
}else{
31353252
@ <p>This is the test page for case=%d(iCase). All possible cases:
31363253
}
3137
- for(i=1; i<=7; i++){
3254
+ for(i=1; i<=8; i++){
31383255
@ <a href='./test-warning?case=%d(i)'>[%d(i)]</a>
31393256
}
31403257
@ </p>
31413258
@ <p><ol>
31423259
@ <li value='1'> Call fossil_warning()
@@ -3169,10 +3286,16 @@
31693286
}
31703287
@ <li value='7'> call webpage_error()"
31713288
if( iCase==7 ){
31723289
cgi_reset_content();
31733290
webpage_error("Case 7 from /test-warning");
3291
+ }
3292
+ @ <li value='8'> simulated timeout"
3293
+ if( iCase==8 ){
3294
+ fossil_set_timeout(1);
3295
+ cgi_reset_content();
3296
+ sqlite3_sleep(1100);
31743297
}
31753298
@ </ol>
31763299
@ <p>End of test</p>
31773300
style_finish_page();
31783301
}
31793302
--- src/main.c
+++ src/main.c
@@ -143,10 +143,11 @@
143
144 struct Global {
145 int argc; char **argv; /* Command-line arguments to the program */
146 char *nameOfExe; /* Full path of executable. */
147 const char *zErrlog; /* Log errors to this file, if not NULL */
 
148 int isConst; /* True if the output is unchanging & cacheable */
149 const char *zVfsName; /* The VFS to use for database connections */
150 sqlite3 *db; /* The connection to the databases */
151 sqlite3 *dbConfig; /* Separate connection for global_config table */
152 char *zAuxSchema; /* Main repository aux-schema */
@@ -473,11 +474,17 @@
473 nArg = g.argc + nLine*2;
474 newArgv = fossil_malloc( sizeof(char*)*nArg );
475 for(j=0; j<i; j++) newArgv[j] = g.argv[j];
476
477 blob_rewind(&file);
478 while( (n = blob_line(&file, &line))>0 ){
 
 
 
 
 
 
479 if( n<1 ){
480 /* Reminder: corner-case: a line with 1 byte and no newline. */
481 continue;
482 }
483 z = blob_buffer(&line);
@@ -667,10 +674,11 @@
667 int fossil_main(int argc, char **argv){
668 const char *zCmdName = "unknown";
669 const CmdOrPage *pCmd = 0;
670 int rc;
671
 
672 #if !defined(_WIN32_WCE)
673 if( fossil_getenv("FOSSIL_BREAK") ){
674 if( isatty(0) && isatty(2) ){
675 fprintf(stderr,
676 "attach debugger to process %d and press any key to continue.\n",
@@ -951,11 +959,13 @@
951 rc = TH_OK;
952 }
953 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
954 if( rc==TH_OK || rc==TH_RETURN ){
955 #endif
 
956 pCmd->xFunc();
 
957 #ifdef FOSSIL_ENABLE_TH1_HOOKS
958 }
959 if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
960 Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags);
961 }
@@ -1403,11 +1413,24 @@
1403 g.zTop = &g.zBaseURL[7+strlen(z)];
1404 g.zHttpsURL = mprintf("https://%s%.*s", z, i, zCur);
1405 }
1406 fossil_free(z);
1407 }
1408 if( db_is_writeable("repository") ){
 
 
 
 
 
 
 
 
 
 
 
 
 
1409 int nBase = (int)strlen(g.zBaseURL);
1410 char *zBase = g.zBaseURL;
1411 if( g.nExtraURL>0 && g.nExtraURL<nBase-6 ){
1412 zBase = fossil_strndup(g.zBaseURL, nBase - g.nExtraURL);
1413 }
@@ -1508,17 +1531,17 @@
1508 size_t i;
1509 Blob out;
1510 size = backtrace(array, sizeof(array)/sizeof(array[0]));
1511 strings = backtrace_symbols(array, size);
1512 blob_init(&out, 0, 0);
1513 blob_appendf(&out, "Segfault");
1514 for(i=0; i<size; i++){
1515 blob_appendf(&out, "\n(%d) %s", i, strings[i]);
1516 }
1517 fossil_panic("%s", blob_str(&out));
1518 #else
1519 fossil_panic("Segfault");
1520 #endif
1521 exit(1);
1522 }
1523
1524 /*
@@ -1529,10 +1552,11 @@
1529 #ifndef _WIN32
1530 if( g.fAnyTrace ){
1531 fprintf(stderr,"/***** sigpipe received by subprocess %d ****\n", getpid());
1532 }
1533 #endif
 
1534 db_panic_close();
1535 exit(1);
1536 }
1537
1538 /*
@@ -1601,10 +1625,11 @@
1601 char *zPath = NULL;
1602 int i;
1603 const CmdOrPage *pCmd = 0;
1604 const char *zBase = g.zRepositoryName;
1605
 
1606 #if !defined(_WIN32)
1607 signal(SIGSEGV, sigsegv_handler);
1608 #endif
1609
1610 /* Handle universal query parameters */
@@ -1824,20 +1849,14 @@
1824 ** been opened.
1825 */
1826
1827
1828 /*
1829 ** Check to see if the first term of PATH_INFO specifies an alternative
1830 ** skin. This will be the case if the first term of PATH_INFO
1831 ** begins with "draftN/" where N is an integer between 1 and 9 or
1832 ** if it is "skn_X/" where X is one of the built-in skin names.
1833 ** If either is true, then activate the alternative skin.a
1834 **
1835 ** If there are multiple skn_X entries (ex: /skn_default/skn_ardoise/...)
1836 ** then skip over all but the last. This allows one to link to an
1837 ** alternative skin in hyperlinks even if you are already in an alternative
1838 ** skin.
1839 */
1840 if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
1841 && zPathInfo[6]>='1' && zPathInfo[6]<='9'
1842 && (zPathInfo[7]=='/' || zPathInfo[7]==0)
1843 ){
@@ -2009,10 +2028,11 @@
2009 rc = TH_OK;
2010 }
2011 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
2012 if( rc==TH_OK || rc==TH_RETURN ){
2013 #endif
 
2014 pCmd->xFunc();
2015 #ifdef FOSSIL_ENABLE_TH1_HOOKS
2016 }
2017 if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
2018 Th_WebpageNotify(pCmd->zName+1, pCmd->eCmdFlags);
@@ -2022,10 +2042,11 @@
2022 #endif
2023 }
2024
2025 /* Return the result.
2026 */
 
2027 cgi_reply();
2028 }
2029
2030 /* If the CGI program contains one or more lines of the form
2031 **
@@ -2728,11 +2749,11 @@
2728 **
2729 ** Works like the [[http]] command but gives setup permission to all users.
2730 **
2731 ** Options:
2732 ** --th-trace Trace TH1 execution (for debugging purposes)
2733 ** --usercap CAP User capability string (Default: "sx")
2734 **
2735 */
2736 void cmd_test_http(void){
2737 const char *zIpAddr; /* IP address of remote client */
2738 const char *zUserCap;
@@ -2739,11 +2760,11 @@
2739
2740 Th_InitTraceLog();
2741 zUserCap = find_option("usercap",0,1);
2742 if( zUserCap==0 ){
2743 g.useLocalauth = 1;
2744 zUserCap = "sx";
2745 }
2746 login_set_capabilities(zUserCap, 0);
2747 g.httpIn = stdin;
2748 g.httpOut = stdout;
2749 fossil_binary_mode(g.httpOut);
@@ -2768,12 +2789,17 @@
2768 /*
2769 ** Respond to a SIGALRM by writing a message to the error log (if there
2770 ** is one) and exiting.
2771 */
2772 #ifndef _WIN32
 
2773 static void sigalrm_handler(int x){
2774 fossil_panic("TIMEOUT");
 
 
 
 
2775 }
2776 #endif
2777
2778 /*
2779 ** Arrange to timeout using SIGALRM after N seconds. Or if N==0, cancel
@@ -2785,10 +2811,11 @@
2785 */
2786 void fossil_set_timeout(int N){
2787 #ifndef _WIN32
2788 signal(SIGALRM, sigalrm_handler);
2789 alarm(N);
 
2790 #endif
2791 }
2792
2793 /*
2794 ** COMMAND: server*
@@ -2797,19 +2824,30 @@
2797 ** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
2798 ** or: %fossil ui ?OPTIONS? ?REPOSITORY?
2799 **
2800 ** Open a socket and begin listening and responding to HTTP requests on
2801 ** TCP port 8080, or on any other TCP port defined by the -P or
2802 ** --port option. The optional argument is the name of the repository.
2803 ** The repository argument may be omitted if the working directory is
2804 ** within an open checkout.
 
2805 **
2806 ** The "ui" command automatically starts a web browser after initializing
2807 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
2808 ** only process HTTP traffic from the local machine.
2809 **
2810 ** The REPOSITORY can be a directory (aka folder) that contains one or
 
 
 
 
 
 
 
 
 
 
2811 ** more repositories with names ending in ".fossil". In this case, a
2812 ** prefix of the URL pathname is used to search the directory for an
2813 ** appropriate repository. To thwart mischief, the pathname in the URL must
2814 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
2815 ** occur after "/", and every "." must be surrounded on both sides by
@@ -2819,11 +2857,11 @@
2819 ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
2820 ** "*.fossil*" will be served as static content. With the "ui" command,
2821 ** the REPOSITORY can only be a directory if the --notfound option is
2822 ** also present.
2823 **
2824 ** For the special case REPOSITORY name of "/", the list global configuration
2825 ** database is consulted for a list of all known repositories. The --repolist
2826 ** option is implied by this special case. See also the "fossil all ui"
2827 ** command.
2828 **
2829 ** By default, the "ui" command provides full administrative access without
@@ -2838,10 +2876,12 @@
2838 ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were
2839 ** /doc/ckout/...
2840 ** --create Create a new REPOSITORY if it does not already exist
2841 ** --extroot DIR Document root for the /ext extension mechanism
2842 ** --files GLOBLIST Comma-separated list of glob patterns for static files
 
 
2843 ** --localauth enable automatic login for requests from localhost
2844 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2845 ** --https Indicates that the input is coming through a reverse
2846 ** proxy that has already translated HTTPS into HTTP.
2847 ** --jsmode MODE Determine how JavaScript is delivered with pages.
@@ -2856,10 +2896,12 @@
2856 ** and bundled modes might result in a single
2857 ** amalgamated script or several, but both approaches
2858 ** result in fewer HTTP requests than the separate mode.
2859 ** --max-latency N Do not let any single HTTP request run for more than N
2860 ** seconds (only works on unix)
 
 
2861 ** --nocompress Do not compress HTTP replies
2862 ** --nojail Drop root privileges but do not enter the chroot jail
2863 ** --nossl signal that no SSL connections are available (Always
2864 ** set by default for the "ui" command)
2865 ** --notfound URL Redirect
@@ -2891,11 +2933,17 @@
2891 int allowRepoList; /* List repositories on URL "/" */
2892 const char *zAltBase; /* Argument to the --baseurl option */
2893 const char *zFileGlob; /* Static content must match this */
2894 char *zIpAddr = 0; /* Bind to this IP address */
2895 int fCreate = 0; /* The --create flag */
 
2896 const char *zInitPage = 0; /* Start on this page. --page option */
 
 
 
 
 
2897
2898 #if defined(_WIN32)
2899 const char *zStopperFile; /* Name of file used to terminate server */
2900 zStopperFile = find_option("stopper", 0, 1);
2901 #endif
@@ -2902,11 +2950,12 @@
2902
2903 if( g.zErrlog==0 ){
2904 g.zErrlog = "-";
2905 }
2906 g.zExtRoot = find_option("extroot",0,1);
2907 builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
 
2908 zFileGlob = find_option("files-urlenc",0,1);
2909 if( zFileGlob ){
2910 char *z = mprintf("%s", zFileGlob);
2911 dehttpize(z);
2912 zFileGlob = z;
@@ -2922,10 +2971,12 @@
2922 Th_InitTraceLog();
2923 zPort = find_option("port", "P", 1);
2924 isUiCmd = g.argv[1][0]=='u';
2925 if( isUiCmd ){
2926 zInitPage = find_option("page", 0, 1);
 
 
2927 }
2928 zNotFound = find_option("notfound", 0, 1);
2929 allowRepoList = find_option("repolist",0,0)!=0;
2930 if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
2931 zAltBase = find_option("baseurl", 0, 1);
@@ -2933,10 +2984,11 @@
2933 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2934 if( zAltBase ){
2935 set_base_url(zAltBase);
2936 }
2937 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
 
2938 if( find_option("https",0,0)!=0 ){
2939 cgi_replace_parameter("HTTPS","on");
2940 }
2941 if( find_option("localhost", 0, 0)!=0 ){
2942 flags |= HTTP_SERVER_LOCALHOST;
@@ -2948,16 +3000,46 @@
2948 }
2949 /* We should be done with options.. */
2950 verify_all_options();
2951
2952 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2953 if( isUiCmd ){
2954 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2955 g.useLocalauth = 1;
2956 allowRepoList = 1;
2957 }
2958 find_server_repository(2, fCreate);
 
 
2959 if( zInitPage==0 ){
2960 if( isUiCmd && g.localOpen ){
2961 zInitPage = "timeline?c=current";
2962 }else{
2963 zInitPage = "";
@@ -2979,25 +3061,73 @@
2979 iPort = mxPort = atoi(zPort);
2980 }else{
2981 iPort = db_get_int("http-port", 8080);
2982 mxPort = iPort+100;
2983 }
2984 #if !defined(_WIN32)
2985 /* Unix implementation */
2986 if( isUiCmd ){
2987 zBrowser = fossil_web_browser();
2988 if( zIpAddr==0 ){
2989 zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
2990 zBrowser, zInitPage);
2991 }else if( strchr(zIpAddr,':') ){
2992 zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
2993 zBrowser, zIpAddr, zInitPage);
2994 }else{
2995 zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
2996 zBrowser, zIpAddr, zInitPage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2997 }
 
 
 
2998 }
 
 
2999 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3000 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3001 db_close(1);
3002 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
3003 fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3044,23 +3174,10 @@
3044 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3045 getpid());
3046 }
3047 #else
3048 /* Win32 implementation */
3049 if( isUiCmd ){
3050 zBrowser = fossil_web_browser();
3051 if( zIpAddr==0 ){
3052 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
3053 zBrowser, zInitPage);
3054 }else if( strchr(zIpAddr,':') ){
3055 zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
3056 zBrowser, zIpAddr, zInitPage);
3057 }else{
3058 zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
3059 zBrowser, zIpAddr, zInitPage);
3060 }
3061 }
3062 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3063 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3064 db_close(1);
3065 if( allowRepoList ){
3066 flags |= HTTP_SERVER_REPOLIST;
@@ -3132,11 +3249,11 @@
3132 @ <p>Generate a message to the <a href="%R/errorlog">error log</a>
3133 @ by clicking on one of the following cases:
3134 }else{
3135 @ <p>This is the test page for case=%d(iCase). All possible cases:
3136 }
3137 for(i=1; i<=7; i++){
3138 @ <a href='./test-warning?case=%d(i)'>[%d(i)]</a>
3139 }
3140 @ </p>
3141 @ <p><ol>
3142 @ <li value='1'> Call fossil_warning()
@@ -3169,10 +3286,16 @@
3169 }
3170 @ <li value='7'> call webpage_error()"
3171 if( iCase==7 ){
3172 cgi_reset_content();
3173 webpage_error("Case 7 from /test-warning");
 
 
 
 
 
 
3174 }
3175 @ </ol>
3176 @ <p>End of test</p>
3177 style_finish_page();
3178 }
3179
--- src/main.c
+++ src/main.c
@@ -143,10 +143,11 @@
143
144 struct Global {
145 int argc; char **argv; /* Command-line arguments to the program */
146 char *nameOfExe; /* Full path of executable. */
147 const char *zErrlog; /* Log errors to this file, if not NULL */
148 const char *zPhase; /* Phase of operation, for use by the error log */
149 int isConst; /* True if the output is unchanging & cacheable */
150 const char *zVfsName; /* The VFS to use for database connections */
151 sqlite3 *db; /* The connection to the databases */
152 sqlite3 *dbConfig; /* Separate connection for global_config table */
153 char *zAuxSchema; /* Main repository aux-schema */
@@ -473,11 +474,17 @@
474 nArg = g.argc + nLine*2;
475 newArgv = fossil_malloc( sizeof(char*)*nArg );
476 for(j=0; j<i; j++) newArgv[j] = g.argv[j];
477
478 blob_rewind(&file);
479 while( nLine-->0 && (n = blob_line(&file, &line))>0 ){
480 /* Reminder: ^^^ nLine check avoids that embedded NUL bytes in the
481 ** --args file causes nLine to be less than blob_line() will end
482 ** up reporting, as such a miscount leads to an illegal memory
483 ** write. See forum post
484 ** https://fossil-scm.org/forum/forumpost/7b34eecc1b8c for
485 ** details */
486 if( n<1 ){
487 /* Reminder: corner-case: a line with 1 byte and no newline. */
488 continue;
489 }
490 z = blob_buffer(&line);
@@ -667,10 +674,11 @@
674 int fossil_main(int argc, char **argv){
675 const char *zCmdName = "unknown";
676 const CmdOrPage *pCmd = 0;
677 int rc;
678
679 g.zPhase = "init";
680 #if !defined(_WIN32_WCE)
681 if( fossil_getenv("FOSSIL_BREAK") ){
682 if( isatty(0) && isatty(2) ){
683 fprintf(stderr,
684 "attach debugger to process %d and press any key to continue.\n",
@@ -951,11 +959,13 @@
959 rc = TH_OK;
960 }
961 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
962 if( rc==TH_OK || rc==TH_RETURN ){
963 #endif
964 g.zPhase = pCmd->zName;
965 pCmd->xFunc();
966 g.zPhase = "shutdown";
967 #ifdef FOSSIL_ENABLE_TH1_HOOKS
968 }
969 if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
970 Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags);
971 }
@@ -1403,11 +1413,24 @@
1413 g.zTop = &g.zBaseURL[7+strlen(z)];
1414 g.zHttpsURL = mprintf("https://%s%.*s", z, i, zCur);
1415 }
1416 fossil_free(z);
1417 }
1418
1419 /* Try to record the base URL as a CONFIG table entry with a name
1420 ** of the form: "baseurl:BASE". This keeps a record of how the
1421 ** the repository is used as a server, to help in answering questions
1422 ** like "where is the CGI script that references this repository?"
1423 **
1424 ** This is just a logging hint. So don't worry if it cannot be done.
1425 ** Don't try this if the repository database is not writable, for
1426 ** example.
1427 **
1428 ** If g.useLocalauth is set, that (probably) means that we are running
1429 ** "fossil ui" and there is no point in logging those cases either.
1430 */
1431 if( db_is_writeable("repository") && !g.useLocalauth ){
1432 int nBase = (int)strlen(g.zBaseURL);
1433 char *zBase = g.zBaseURL;
1434 if( g.nExtraURL>0 && g.nExtraURL<nBase-6 ){
1435 zBase = fossil_strndup(g.zBaseURL, nBase - g.nExtraURL);
1436 }
@@ -1508,17 +1531,17 @@
1531 size_t i;
1532 Blob out;
1533 size = backtrace(array, sizeof(array)/sizeof(array[0]));
1534 strings = backtrace_symbols(array, size);
1535 blob_init(&out, 0, 0);
1536 blob_appendf(&out, "Segfault during %s", g.zPhase);
1537 for(i=0; i<size; i++){
1538 blob_appendf(&out, "\n(%d) %s", i, strings[i]);
1539 }
1540 fossil_panic("%s", blob_str(&out));
1541 #else
1542 fossil_panic("Segfault during %s", g.zPhase);
1543 #endif
1544 exit(1);
1545 }
1546
1547 /*
@@ -1529,10 +1552,11 @@
1552 #ifndef _WIN32
1553 if( g.fAnyTrace ){
1554 fprintf(stderr,"/***** sigpipe received by subprocess %d ****\n", getpid());
1555 }
1556 #endif
1557 g.zPhase = "sigpipe shutdown";
1558 db_panic_close();
1559 exit(1);
1560 }
1561
1562 /*
@@ -1601,10 +1625,11 @@
1625 char *zPath = NULL;
1626 int i;
1627 const CmdOrPage *pCmd = 0;
1628 const char *zBase = g.zRepositoryName;
1629
1630 g.zPhase = "process_one_web_page";
1631 #if !defined(_WIN32)
1632 signal(SIGSEGV, sigsegv_handler);
1633 #endif
1634
1635 /* Handle universal query parameters */
@@ -1824,20 +1849,14 @@
1849 ** been opened.
1850 */
1851
1852
1853 /*
1854 ** Check to see if the first term of PATH_INFO specifies an
1855 ** alternative skin. This will be the case if the first term of
1856 ** PATH_INFO begins with "draftN/" where N is an integer between 1
1857 ** and 9. If so, activate the skin associated with that draft.
 
 
 
 
 
 
1858 */
1859 if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
1860 && zPathInfo[6]>='1' && zPathInfo[6]<='9'
1861 && (zPathInfo[7]=='/' || zPathInfo[7]==0)
1862 ){
@@ -2009,10 +2028,11 @@
2028 rc = TH_OK;
2029 }
2030 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
2031 if( rc==TH_OK || rc==TH_RETURN ){
2032 #endif
2033 g.zPhase = pCmd->zName;
2034 pCmd->xFunc();
2035 #ifdef FOSSIL_ENABLE_TH1_HOOKS
2036 }
2037 if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
2038 Th_WebpageNotify(pCmd->zName+1, pCmd->eCmdFlags);
@@ -2022,10 +2042,11 @@
2042 #endif
2043 }
2044
2045 /* Return the result.
2046 */
2047 g.zPhase = "web-page reply";
2048 cgi_reply();
2049 }
2050
2051 /* If the CGI program contains one or more lines of the form
2052 **
@@ -2728,11 +2749,11 @@
2749 **
2750 ** Works like the [[http]] command but gives setup permission to all users.
2751 **
2752 ** Options:
2753 ** --th-trace Trace TH1 execution (for debugging purposes)
2754 ** --usercap CAP User capability string (Default: "sxy")
2755 **
2756 */
2757 void cmd_test_http(void){
2758 const char *zIpAddr; /* IP address of remote client */
2759 const char *zUserCap;
@@ -2739,11 +2760,11 @@
2760
2761 Th_InitTraceLog();
2762 zUserCap = find_option("usercap",0,1);
2763 if( zUserCap==0 ){
2764 g.useLocalauth = 1;
2765 zUserCap = "sxy";
2766 }
2767 login_set_capabilities(zUserCap, 0);
2768 g.httpIn = stdin;
2769 g.httpOut = stdout;
2770 fossil_binary_mode(g.httpOut);
@@ -2768,12 +2789,17 @@
2789 /*
2790 ** Respond to a SIGALRM by writing a message to the error log (if there
2791 ** is one) and exiting.
2792 */
2793 #ifndef _WIN32
2794 static int nAlarmSeconds = 0;
2795 static void sigalrm_handler(int x){
2796 sqlite3_uint64 tmUser = 0, tmKernel = 0;
2797 fossil_cpu_times(&tmUser, &tmKernel);
2798 fossil_panic("Timeout after %d seconds during %s"
2799 " - user %,llu µs, sys %,llu µs",
2800 nAlarmSeconds, g.zPhase, tmUser, tmKernel);
2801 }
2802 #endif
2803
2804 /*
2805 ** Arrange to timeout using SIGALRM after N seconds. Or if N==0, cancel
@@ -2785,10 +2811,11 @@
2811 */
2812 void fossil_set_timeout(int N){
2813 #ifndef _WIN32
2814 signal(SIGALRM, sigalrm_handler);
2815 alarm(N);
2816 nAlarmSeconds = N;
2817 #endif
2818 }
2819
2820 /*
2821 ** COMMAND: server*
@@ -2797,19 +2824,30 @@
2824 ** Usage: %fossil server ?OPTIONS? ?REPOSITORY?
2825 ** or: %fossil ui ?OPTIONS? ?REPOSITORY?
2826 **
2827 ** Open a socket and begin listening and responding to HTTP requests on
2828 ** TCP port 8080, or on any other TCP port defined by the -P or
2829 ** --port option. The optional REPOSITORY argument is the name of the
2830 ** Fossil repository to be served. The REPOSITORY argument may be omitted
2831 ** if the working directory is within an open checkout, in which case the
2832 ** repository associated with that checkout is used.
2833 **
2834 ** The "ui" command automatically starts a web browser after initializing
2835 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
2836 ** only process HTTP traffic from the local machine.
2837 **
2838 ** If REPOSITORY is a directory name which is the root of a
2839 ** checkout, then use the repository associated with that checkout.
2840 ** This only works for the "fossil ui" command, not the "fossil server"
2841 ** command.
2842 **
2843 ** If REPOSITORY begins with a "HOST:" or "USER@HOST:" prefix, then
2844 ** the command is run on the remote host specified and the results are
2845 ** tunneled back to the local machine via SSH. This feature only works for
2846 ** the "fossil ui" command, not the "fossil server" command.
2847 **
2848 ** REPOSITORY may also be a directory (aka folder) that contains one or
2849 ** more repositories with names ending in ".fossil". In this case, a
2850 ** prefix of the URL pathname is used to search the directory for an
2851 ** appropriate repository. To thwart mischief, the pathname in the URL must
2852 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
2853 ** occur after "/", and every "." must be surrounded on both sides by
@@ -2819,11 +2857,11 @@
2857 ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern
2858 ** "*.fossil*" will be served as static content. With the "ui" command,
2859 ** the REPOSITORY can only be a directory if the --notfound option is
2860 ** also present.
2861 **
2862 ** For the special case REPOSITORY name of "/", the global configuration
2863 ** database is consulted for a list of all known repositories. The --repolist
2864 ** option is implied by this special case. See also the "fossil all ui"
2865 ** command.
2866 **
2867 ** By default, the "ui" command provides full administrative access without
@@ -2838,10 +2876,12 @@
2876 ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were
2877 ** /doc/ckout/...
2878 ** --create Create a new REPOSITORY if it does not already exist
2879 ** --extroot DIR Document root for the /ext extension mechanism
2880 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2881 ** --fossilcmd PATH Full pathname of the "fossil" executable on the remote
2882 ** system when REPOSITORY is remote. Default: "fossil"
2883 ** --localauth enable automatic login for requests from localhost
2884 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2885 ** --https Indicates that the input is coming through a reverse
2886 ** proxy that has already translated HTTPS into HTTP.
2887 ** --jsmode MODE Determine how JavaScript is delivered with pages.
@@ -2856,10 +2896,12 @@
2896 ** and bundled modes might result in a single
2897 ** amalgamated script or several, but both approaches
2898 ** result in fewer HTTP requests than the separate mode.
2899 ** --max-latency N Do not let any single HTTP request run for more than N
2900 ** seconds (only works on unix)
2901 ** --nobrowser Do not automatically launch a web-browser for the
2902 ** "fossil ui" command.
2903 ** --nocompress Do not compress HTTP replies
2904 ** --nojail Drop root privileges but do not enter the chroot jail
2905 ** --nossl signal that no SSL connections are available (Always
2906 ** set by default for the "ui" command)
2907 ** --notfound URL Redirect
@@ -2891,11 +2933,17 @@
2933 int allowRepoList; /* List repositories on URL "/" */
2934 const char *zAltBase; /* Argument to the --baseurl option */
2935 const char *zFileGlob; /* Static content must match this */
2936 char *zIpAddr = 0; /* Bind to this IP address */
2937 int fCreate = 0; /* The --create flag */
2938 int fNoBrowser = 0; /* Do not auto-launch web-browser */
2939 const char *zInitPage = 0; /* Start on this page. --page option */
2940 int findServerArg = 2; /* argv index for find_server_repository() */
2941 char *zRemote = 0; /* Remote host on which to run "fossil ui" */
2942 const char *zJsMode; /* The --jsmode parameter */
2943 const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */
2944
2945
2946 #if defined(_WIN32)
2947 const char *zStopperFile; /* Name of file used to terminate server */
2948 zStopperFile = find_option("stopper", 0, 1);
2949 #endif
@@ -2902,11 +2950,12 @@
2950
2951 if( g.zErrlog==0 ){
2952 g.zErrlog = "-";
2953 }
2954 g.zExtRoot = find_option("extroot",0,1);
2955 zJsMode = find_option("jsmode",0,1);
2956 builtin_set_js_delivery_mode(zJsMode,0);
2957 zFileGlob = find_option("files-urlenc",0,1);
2958 if( zFileGlob ){
2959 char *z = mprintf("%s", zFileGlob);
2960 dehttpize(z);
2961 zFileGlob = z;
@@ -2922,10 +2971,12 @@
2971 Th_InitTraceLog();
2972 zPort = find_option("port", "P", 1);
2973 isUiCmd = g.argv[1][0]=='u';
2974 if( isUiCmd ){
2975 zInitPage = find_option("page", 0, 1);
2976 if( zInitPage && zInitPage[0]=='/' ) zInitPage++;
2977 zFossilCmd = find_option("fossilcmd", 0, 1);
2978 }
2979 zNotFound = find_option("notfound", 0, 1);
2980 allowRepoList = find_option("repolist",0,0)!=0;
2981 if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1;
2982 zAltBase = find_option("baseurl", 0, 1);
@@ -2933,10 +2984,11 @@
2984 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2985 if( zAltBase ){
2986 set_base_url(zAltBase);
2987 }
2988 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
2989 fNoBrowser = find_option("nobrowser", 0, 0)!=0;
2990 if( find_option("https",0,0)!=0 ){
2991 cgi_replace_parameter("HTTPS","on");
2992 }
2993 if( find_option("localhost", 0, 0)!=0 ){
2994 flags |= HTTP_SERVER_LOCALHOST;
@@ -2948,16 +3000,46 @@
3000 }
3001 /* We should be done with options.. */
3002 verify_all_options();
3003
3004 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
3005 if( isUiCmd && 3==g.argc && file_isdir(g.argv[2], ExtFILE)>0 ){
3006 /* If REPOSITORY arg is the root of a checkout,
3007 ** chdir to that checkout so that the current version
3008 ** gets highlighted in the timeline by default. */
3009 const char * zDir = g.argv[2];
3010 if(dir_has_ckout_db(zDir)){
3011 if(0!=file_chdir(zDir, 0)){
3012 fossil_fatal("Cannot chdir to %s", zDir);
3013 }
3014 findServerArg = 99;
3015 fCreate = 0;
3016 g.argv[2] = 0;
3017 --g.argc;
3018 }
3019 }
3020 if( isUiCmd && 3==g.argc
3021 && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
3022 ){
3023 /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
3024 const char *zRepoTail = file_skip_userhost(g.argv[2]);
3025 unsigned x;
3026 int n;
3027 sqlite3_randomness(2,&x);
3028 zPort = mprintf("%d", 8100+(x%32000));
3029 n = (int)(zRepoTail - g.argv[2]) - 1;
3030 zRemote = mprintf("%.*s", n, g.argv[2]);
3031 g.argv[2] = (char*)zRepoTail;
3032 }
3033 if( isUiCmd ){
3034 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
3035 g.useLocalauth = 1;
3036 allowRepoList = 1;
3037 }
3038 if( !zRemote ){
3039 find_server_repository(findServerArg, fCreate);
3040 }
3041 if( zInitPage==0 ){
3042 if( isUiCmd && g.localOpen ){
3043 zInitPage = "timeline?c=current";
3044 }else{
3045 zInitPage = "";
@@ -2979,25 +3061,73 @@
3061 iPort = mxPort = atoi(zPort);
3062 }else{
3063 iPort = db_get_int("http-port", 8080);
3064 mxPort = iPort+100;
3065 }
3066 if( isUiCmd && !fNoBrowser ){
3067 char *zBrowserArg;
3068 if( zRemote ) db_open_config(0,0);
3069 zBrowser = fossil_web_browser();
3070 if( zIpAddr==0 ){
3071 zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
 
3072 }else if( strchr(zIpAddr,':') ){
3073 zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
 
3074 }else{
3075 zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3076 }
3077 #ifdef _WIN32
3078 zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
3079 #else
3080 zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3081 #endif
3082 fossil_free(zBrowserArg);
3083 }
3084 if( zRemote ){
3085 /* If a USER@HOST:REPO argument is supplied, then use SSH to run
3086 ** "fossil ui --nobrowser" on the remote system and to set up a
3087 ** tunnel from the local machine to the remote. */
3088 FILE *sshIn;
3089 Blob ssh;
3090 char zLine[1000];
3091 blob_init(&ssh, 0, 0);
3092 transport_ssh_command(&ssh);
3093 db_close_config();
3094 if( zFossilCmd==0 ) zFossilCmd = "fossil";
3095 blob_appendf(&ssh,
3096 " -t -L 127.0.0.1:%d:127.0.0.1:%d %!$"
3097 " %$ ui --nobrowser --localauth --port %d",
3098 iPort, iPort, zRemote, zFossilCmd, iPort);
3099 if( zNotFound ) blob_appendf(&ssh, " --notfound %!$", zNotFound);
3100 if( zFileGlob ) blob_appendf(&ssh, " --files-urlenc %T", zFileGlob);
3101 if( g.zCkoutAlias ) blob_appendf(&ssh, " --ckout-alias %!$",g.zCkoutAlias);
3102 if( g.zExtRoot ) blob_appendf(&ssh, " --extroot %$", g.zExtRoot);
3103 if( skin_in_use() ) blob_appendf(&ssh, " --skin %s", skin_in_use());
3104 if( zJsMode ) blob_appendf(&ssh, " --jsmode %s", zJsMode);
3105 if( fCreate ) blob_appendf(&ssh, " --create");
3106 blob_appendf(&ssh, " %$", g.argv[2]);
3107 fossil_print("%s\n", blob_str(&ssh));
3108 sshIn = popen(blob_str(&ssh), "r");
3109 if( sshIn==0 ){
3110 fossil_fatal("unable to %s", blob_str(&ssh));
3111 }
3112 while( fgets(zLine, sizeof(zLine), sshIn) ){
3113 fputs(zLine, stdout);
3114 fflush(stdout);
3115 if( zBrowserCmd && sqlite3_strglob("*Listening for HTTP*",zLine)==0 ){
3116 char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
3117 fossil_system(zCmd);
3118 fossil_free(zCmd);
3119 fossil_free(zBrowserCmd);
3120 zBrowserCmd = 0;
3121 }
3122 }
3123 pclose(sshIn);
3124 fossil_free(zBrowserCmd);
3125 return;
3126 }
3127 #if !defined(_WIN32)
3128 /* Unix implementation */
3129 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3130 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3131 db_close(1);
3132 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
3133 fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3044,23 +3174,10 @@
3174 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3175 getpid());
3176 }
3177 #else
3178 /* Win32 implementation */
 
 
 
 
 
 
 
 
 
 
 
 
 
3179 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3180 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3181 db_close(1);
3182 if( allowRepoList ){
3183 flags |= HTTP_SERVER_REPOLIST;
@@ -3132,11 +3249,11 @@
3249 @ <p>Generate a message to the <a href="%R/errorlog">error log</a>
3250 @ by clicking on one of the following cases:
3251 }else{
3252 @ <p>This is the test page for case=%d(iCase). All possible cases:
3253 }
3254 for(i=1; i<=8; i++){
3255 @ <a href='./test-warning?case=%d(i)'>[%d(i)]</a>
3256 }
3257 @ </p>
3258 @ <p><ol>
3259 @ <li value='1'> Call fossil_warning()
@@ -3169,10 +3286,16 @@
3286 }
3287 @ <li value='7'> call webpage_error()"
3288 if( iCase==7 ){
3289 cgi_reset_content();
3290 webpage_error("Case 7 from /test-warning");
3291 }
3292 @ <li value='8'> simulated timeout"
3293 if( iCase==8 ){
3294 fossil_set_timeout(1);
3295 cgi_reset_content();
3296 sqlite3_sleep(1100);
3297 }
3298 @ </ol>
3299 @ <p>End of test</p>
3300 style_finish_page();
3301 }
3302
+12
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104104
$(SRCDIR)/md5.c \
105105
$(SRCDIR)/merge.c \
106106
$(SRCDIR)/merge3.c \
107107
$(SRCDIR)/moderate.c \
108108
$(SRCDIR)/name.c \
109
+ $(SRCDIR)/patch.c \
109110
$(SRCDIR)/path.c \
110111
$(SRCDIR)/piechart.c \
111112
$(SRCDIR)/pikchr.c \
112113
$(SRCDIR)/pikchrshow.c \
113114
$(SRCDIR)/pivot.c \
@@ -362,10 +363,11 @@
362363
$(OBJDIR)/md5_.c \
363364
$(OBJDIR)/merge_.c \
364365
$(OBJDIR)/merge3_.c \
365366
$(OBJDIR)/moderate_.c \
366367
$(OBJDIR)/name_.c \
368
+ $(OBJDIR)/patch_.c \
367369
$(OBJDIR)/path_.c \
368370
$(OBJDIR)/piechart_.c \
369371
$(OBJDIR)/pikchr_.c \
370372
$(OBJDIR)/pikchrshow_.c \
371373
$(OBJDIR)/pivot_.c \
@@ -511,10 +513,11 @@
511513
$(OBJDIR)/md5.o \
512514
$(OBJDIR)/merge.o \
513515
$(OBJDIR)/merge3.o \
514516
$(OBJDIR)/moderate.o \
515517
$(OBJDIR)/name.o \
518
+ $(OBJDIR)/patch.o \
516519
$(OBJDIR)/path.o \
517520
$(OBJDIR)/piechart.o \
518521
$(OBJDIR)/pikchr.o \
519522
$(OBJDIR)/pikchrshow.o \
520523
$(OBJDIR)/pivot.o \
@@ -850,10 +853,11 @@
850853
$(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
851854
$(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
852855
$(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
853856
$(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
854857
$(OBJDIR)/name_.c:$(OBJDIR)/name.h \
858
+ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
855859
$(OBJDIR)/path_.c:$(OBJDIR)/path.h \
856860
$(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
857861
$(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
858862
$(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
859863
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -1633,10 +1637,18 @@
16331637
16341638
$(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
16351639
$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
16361640
16371641
$(OBJDIR)/name.h: $(OBJDIR)/headers
1642
+
1643
+$(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(OBJDIR)/translate
1644
+ $(OBJDIR)/translate $(SRCDIR)/patch.c >$@
1645
+
1646
+$(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h
1647
+ $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c
1648
+
1649
+$(OBJDIR)/patch.h: $(OBJDIR)/headers
16381650
16391651
$(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate
16401652
$(OBJDIR)/translate $(SRCDIR)/path.c >$@
16411653
16421654
$(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
16431655
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104 $(SRCDIR)/md5.c \
105 $(SRCDIR)/merge.c \
106 $(SRCDIR)/merge3.c \
107 $(SRCDIR)/moderate.c \
108 $(SRCDIR)/name.c \
 
109 $(SRCDIR)/path.c \
110 $(SRCDIR)/piechart.c \
111 $(SRCDIR)/pikchr.c \
112 $(SRCDIR)/pikchrshow.c \
113 $(SRCDIR)/pivot.c \
@@ -362,10 +363,11 @@
362 $(OBJDIR)/md5_.c \
363 $(OBJDIR)/merge_.c \
364 $(OBJDIR)/merge3_.c \
365 $(OBJDIR)/moderate_.c \
366 $(OBJDIR)/name_.c \
 
367 $(OBJDIR)/path_.c \
368 $(OBJDIR)/piechart_.c \
369 $(OBJDIR)/pikchr_.c \
370 $(OBJDIR)/pikchrshow_.c \
371 $(OBJDIR)/pivot_.c \
@@ -511,10 +513,11 @@
511 $(OBJDIR)/md5.o \
512 $(OBJDIR)/merge.o \
513 $(OBJDIR)/merge3.o \
514 $(OBJDIR)/moderate.o \
515 $(OBJDIR)/name.o \
 
516 $(OBJDIR)/path.o \
517 $(OBJDIR)/piechart.o \
518 $(OBJDIR)/pikchr.o \
519 $(OBJDIR)/pikchrshow.o \
520 $(OBJDIR)/pivot.o \
@@ -850,10 +853,11 @@
850 $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
851 $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
852 $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
853 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
854 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
 
855 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
856 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
857 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
858 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
859 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -1633,10 +1637,18 @@
1633
1634 $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
1635 $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
1636
1637 $(OBJDIR)/name.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1638
1639 $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate
1640 $(OBJDIR)/translate $(SRCDIR)/path.c >$@
1641
1642 $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
1643
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104 $(SRCDIR)/md5.c \
105 $(SRCDIR)/merge.c \
106 $(SRCDIR)/merge3.c \
107 $(SRCDIR)/moderate.c \
108 $(SRCDIR)/name.c \
109 $(SRCDIR)/patch.c \
110 $(SRCDIR)/path.c \
111 $(SRCDIR)/piechart.c \
112 $(SRCDIR)/pikchr.c \
113 $(SRCDIR)/pikchrshow.c \
114 $(SRCDIR)/pivot.c \
@@ -362,10 +363,11 @@
363 $(OBJDIR)/md5_.c \
364 $(OBJDIR)/merge_.c \
365 $(OBJDIR)/merge3_.c \
366 $(OBJDIR)/moderate_.c \
367 $(OBJDIR)/name_.c \
368 $(OBJDIR)/patch_.c \
369 $(OBJDIR)/path_.c \
370 $(OBJDIR)/piechart_.c \
371 $(OBJDIR)/pikchr_.c \
372 $(OBJDIR)/pikchrshow_.c \
373 $(OBJDIR)/pivot_.c \
@@ -511,10 +513,11 @@
513 $(OBJDIR)/md5.o \
514 $(OBJDIR)/merge.o \
515 $(OBJDIR)/merge3.o \
516 $(OBJDIR)/moderate.o \
517 $(OBJDIR)/name.o \
518 $(OBJDIR)/patch.o \
519 $(OBJDIR)/path.o \
520 $(OBJDIR)/piechart.o \
521 $(OBJDIR)/pikchr.o \
522 $(OBJDIR)/pikchrshow.o \
523 $(OBJDIR)/pivot.o \
@@ -850,10 +853,11 @@
853 $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
854 $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
855 $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
856 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
857 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
858 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
859 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
860 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
861 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
862 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
863 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -1633,10 +1637,18 @@
1637
1638 $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
1639 $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
1640
1641 $(OBJDIR)/name.h: $(OBJDIR)/headers
1642
1643 $(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(OBJDIR)/translate
1644 $(OBJDIR)/translate $(SRCDIR)/patch.c >$@
1645
1646 $(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h
1647 $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c
1648
1649 $(OBJDIR)/patch.h: $(OBJDIR)/headers
1650
1651 $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate
1652 $(OBJDIR)/translate $(SRCDIR)/path.c >$@
1653
1654 $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
1655
+12
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104104
$(SRCDIR)/md5.c \
105105
$(SRCDIR)/merge.c \
106106
$(SRCDIR)/merge3.c \
107107
$(SRCDIR)/moderate.c \
108108
$(SRCDIR)/name.c \
109
+ $(SRCDIR)/patch.c \
109110
$(SRCDIR)/path.c \
110111
$(SRCDIR)/piechart.c \
111112
$(SRCDIR)/pikchr.c \
112113
$(SRCDIR)/pikchrshow.c \
113114
$(SRCDIR)/pivot.c \
@@ -362,10 +363,11 @@
362363
$(OBJDIR)/md5_.c \
363364
$(OBJDIR)/merge_.c \
364365
$(OBJDIR)/merge3_.c \
365366
$(OBJDIR)/moderate_.c \
366367
$(OBJDIR)/name_.c \
368
+ $(OBJDIR)/patch_.c \
367369
$(OBJDIR)/path_.c \
368370
$(OBJDIR)/piechart_.c \
369371
$(OBJDIR)/pikchr_.c \
370372
$(OBJDIR)/pikchrshow_.c \
371373
$(OBJDIR)/pivot_.c \
@@ -511,10 +513,11 @@
511513
$(OBJDIR)/md5.o \
512514
$(OBJDIR)/merge.o \
513515
$(OBJDIR)/merge3.o \
514516
$(OBJDIR)/moderate.o \
515517
$(OBJDIR)/name.o \
518
+ $(OBJDIR)/patch.o \
516519
$(OBJDIR)/path.o \
517520
$(OBJDIR)/piechart.o \
518521
$(OBJDIR)/pikchr.o \
519522
$(OBJDIR)/pikchrshow.o \
520523
$(OBJDIR)/pivot.o \
@@ -850,10 +853,11 @@
850853
$(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
851854
$(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
852855
$(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
853856
$(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
854857
$(OBJDIR)/name_.c:$(OBJDIR)/name.h \
858
+ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
855859
$(OBJDIR)/path_.c:$(OBJDIR)/path.h \
856860
$(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
857861
$(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
858862
$(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
859863
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -1633,10 +1637,18 @@
16331637
16341638
$(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
16351639
$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
16361640
16371641
$(OBJDIR)/name.h: $(OBJDIR)/headers
1642
+
1643
+$(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(OBJDIR)/translate
1644
+ $(OBJDIR)/translate $(SRCDIR)/patch.c >$@
1645
+
1646
+$(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h
1647
+ $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c
1648
+
1649
+$(OBJDIR)/patch.h: $(OBJDIR)/headers
16381650
16391651
$(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate
16401652
$(OBJDIR)/translate $(SRCDIR)/path.c >$@
16411653
16421654
$(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
16431655
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104 $(SRCDIR)/md5.c \
105 $(SRCDIR)/merge.c \
106 $(SRCDIR)/merge3.c \
107 $(SRCDIR)/moderate.c \
108 $(SRCDIR)/name.c \
 
109 $(SRCDIR)/path.c \
110 $(SRCDIR)/piechart.c \
111 $(SRCDIR)/pikchr.c \
112 $(SRCDIR)/pikchrshow.c \
113 $(SRCDIR)/pivot.c \
@@ -362,10 +363,11 @@
362 $(OBJDIR)/md5_.c \
363 $(OBJDIR)/merge_.c \
364 $(OBJDIR)/merge3_.c \
365 $(OBJDIR)/moderate_.c \
366 $(OBJDIR)/name_.c \
 
367 $(OBJDIR)/path_.c \
368 $(OBJDIR)/piechart_.c \
369 $(OBJDIR)/pikchr_.c \
370 $(OBJDIR)/pikchrshow_.c \
371 $(OBJDIR)/pivot_.c \
@@ -511,10 +513,11 @@
511 $(OBJDIR)/md5.o \
512 $(OBJDIR)/merge.o \
513 $(OBJDIR)/merge3.o \
514 $(OBJDIR)/moderate.o \
515 $(OBJDIR)/name.o \
 
516 $(OBJDIR)/path.o \
517 $(OBJDIR)/piechart.o \
518 $(OBJDIR)/pikchr.o \
519 $(OBJDIR)/pikchrshow.o \
520 $(OBJDIR)/pivot.o \
@@ -850,10 +853,11 @@
850 $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
851 $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
852 $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
853 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
854 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
 
855 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
856 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
857 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
858 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
859 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -1633,10 +1637,18 @@
1633
1634 $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
1635 $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
1636
1637 $(OBJDIR)/name.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1638
1639 $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate
1640 $(OBJDIR)/translate $(SRCDIR)/path.c >$@
1641
1642 $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
1643
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104 $(SRCDIR)/md5.c \
105 $(SRCDIR)/merge.c \
106 $(SRCDIR)/merge3.c \
107 $(SRCDIR)/moderate.c \
108 $(SRCDIR)/name.c \
109 $(SRCDIR)/patch.c \
110 $(SRCDIR)/path.c \
111 $(SRCDIR)/piechart.c \
112 $(SRCDIR)/pikchr.c \
113 $(SRCDIR)/pikchrshow.c \
114 $(SRCDIR)/pivot.c \
@@ -362,10 +363,11 @@
363 $(OBJDIR)/md5_.c \
364 $(OBJDIR)/merge_.c \
365 $(OBJDIR)/merge3_.c \
366 $(OBJDIR)/moderate_.c \
367 $(OBJDIR)/name_.c \
368 $(OBJDIR)/patch_.c \
369 $(OBJDIR)/path_.c \
370 $(OBJDIR)/piechart_.c \
371 $(OBJDIR)/pikchr_.c \
372 $(OBJDIR)/pikchrshow_.c \
373 $(OBJDIR)/pivot_.c \
@@ -511,10 +513,11 @@
513 $(OBJDIR)/md5.o \
514 $(OBJDIR)/merge.o \
515 $(OBJDIR)/merge3.o \
516 $(OBJDIR)/moderate.o \
517 $(OBJDIR)/name.o \
518 $(OBJDIR)/patch.o \
519 $(OBJDIR)/path.o \
520 $(OBJDIR)/piechart.o \
521 $(OBJDIR)/pikchr.o \
522 $(OBJDIR)/pikchrshow.o \
523 $(OBJDIR)/pivot.o \
@@ -850,10 +853,11 @@
853 $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
854 $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
855 $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
856 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
857 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
858 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
859 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
860 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
861 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
862 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
863 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -1633,10 +1637,18 @@
1637
1638 $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
1639 $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
1640
1641 $(OBJDIR)/name.h: $(OBJDIR)/headers
1642
1643 $(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(OBJDIR)/translate
1644 $(OBJDIR)/translate $(SRCDIR)/patch.c >$@
1645
1646 $(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h
1647 $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c
1648
1649 $(OBJDIR)/patch.h: $(OBJDIR)/headers
1650
1651 $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate
1652 $(OBJDIR)/translate $(SRCDIR)/path.c >$@
1653
1654 $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
1655
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -125,10 +125,11 @@
125125
md5
126126
merge
127127
merge3
128128
moderate
129129
name
130
+ patch
130131
path
131132
piechart
132133
pikchr
133134
pikchrshow
134135
pivot
135136
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -125,10 +125,11 @@
125 md5
126 merge
127 merge3
128 moderate
129 name
 
130 path
131 piechart
132 pikchr
133 pikchrshow
134 pivot
135
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -125,10 +125,11 @@
125 md5
126 merge
127 merge3
128 moderate
129 name
130 patch
131 path
132 piechart
133 pikchr
134 pikchrshow
135 pivot
136
+26 -55
--- src/markdown.c
+++ src/markdown.c
@@ -171,39 +171,21 @@
171171
172172
/********************
173173
* GLOBAL VARIABLES *
174174
********************/
175175
176
-/* block_tags -- recognised block tags, sorted by cmp_html_tag */
176
+/* block_tags -- recognised block tags, sorted by cmp_html_tag.
177
+**
178
+** When these HTML tags are separated from other text by newlines
179
+** then they are rendered verbatim. Their content is not interpreted
180
+** in any way.
181
+*/
177182
static const struct html_tag block_tags[] = {
178
- { "p", 1 },
179
- { "dl", 2 },
180
- { "h1", 2 },
181
- { "h2", 2 },
182
- { "h3", 2 },
183
- { "h4", 2 },
184
- { "h5", 2 },
185
- { "h6", 2 },
186
- { "ol", 2 },
187
- { "ul", 2 },
188
- { "del", 3 },
189
- { "div", 3 },
190
- { "ins", 3 },
183
+ { "html", 4 },
191184
{ "pre", 3 },
192
- { "form", 4 },
193
- { "math", 4 },
194
- { "table", 5 },
195
- { "iframe", 6 },
196185
{ "script", 6 },
197
- { "fieldset", 8 },
198
- { "noscript", 8 },
199
- { "blockquote", 10 }
200186
};
201
-
202
-#define INS_TAG (block_tags + 12)
203
-#define DEL_TAG (block_tags + 10)
204
-
205187
206188
207189
/***************************
208190
* STATIC HELPER FUNCTIONS *
209191
***************************/
@@ -270,12 +252,16 @@
270252
271253
/* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */
272254
static int cmp_html_tag(const void *a, const void *b){
273255
const struct html_tag *hta = a;
274256
const struct html_tag *htb = b;
275
- if( hta->size!=htb->size ) return hta->size-htb->size;
276
- return fossil_strnicmp(hta->text, htb->text, hta->size);
257
+ int sz = hta->size;
258
+ int c;
259
+ if( htb->size<sz ) sz = htb->size;
260
+ c = fossil_strnicmp(hta->text, htb->text, sz);
261
+ if( c==0 ) c = hta->size - htb->size;
262
+ return c;
277263
}
278264
279265
280266
/* find_block_tag -- returns the current block tag */
281267
static const struct html_tag *find_block_tag(const char *data, size_t size){
@@ -1711,11 +1697,11 @@
17111697
size_t i, w;
17121698
17131699
/* assuming data[0]=='<' && data[1]=='/' already tested */
17141700
17151701
/* checking tag is a match */
1716
- if( (tag->size+3)>=size
1702
+ if( (tag->size+3)>size
17171703
|| fossil_strnicmp(data+2, tag->text, tag->size)
17181704
|| data[tag->size+2]!='>'
17191705
){
17201706
return 0;
17211707
}
@@ -1797,51 +1783,36 @@
17971783
17981784
/* no special case recognised */
17991785
return 0;
18001786
}
18011787
1802
- /* looking for an unindented matching closing tag */
1803
- /* followed by a blank line */
1788
+ /* looking for an matching closing tag */
1789
+ /* followed by a blank line */
18041790
i = 1;
18051791
found = 0;
1806
-#if 0
18071792
while( i<size ){
18081793
i++;
1809
- while( i<size && !(data[i-2]=='\n' && data[i-1]=='<' && data[i]=='/') ){
1810
- i++;
1811
- }
1812
- if( (i+2+curtag->size)>=size ) break;
1794
+ while( i<size && !(data[i-1]=='<' && data[i]=='/') ){ i++; }
1795
+ if( (i+2+curtag->size)>size ) break;
18131796
j = htmlblock_end(curtag, data+i-1, size-i+1);
18141797
if (j) {
18151798
i += j-1;
18161799
found = 1;
18171800
break;
18181801
}
18191802
}
1820
-#endif
1821
-
1822
- /* if not found, trying a second pass looking for indented match */
1823
- /* but not if tag is "ins" or "del" (following original Markdown.pl) */
1824
- if( !found && curtag!=INS_TAG && curtag!=DEL_TAG ){
1825
- i = 1;
1826
- while( i<size ){
1827
- i++;
1828
- while( i<size && !(data[i-1]=='<' && data[i]=='/') ){ i++; }
1829
- if( (i+2+curtag->size)>=size ) break;
1830
- j = htmlblock_end(curtag, data+i-1, size-i+1);
1831
- if (j) {
1832
- i += j-1;
1833
- found = 1;
1834
- break;
1835
- }
1836
- }
1837
- }
1838
-
18391803
if( !found ) return 0;
18401804
18411805
/* the end of the block has been found */
1842
- blob_init(&work, data, i);
1806
+ if( strcmp(curtag->text,"html")==0 ){
1807
+ /* Omit <html> tags */
1808
+ enum mkd_autolink dummy;
1809
+ int k = tag_length(data, size, &dummy);
1810
+ blob_init(&work, data+k, i-(j+k));
1811
+ }else{
1812
+ blob_init(&work, data, i);
1813
+ }
18431814
if( rndr->make.blockhtml ){
18441815
rndr->make.blockhtml(ob, &work, rndr->make.opaque);
18451816
}
18461817
return i;
18471818
}
18481819
--- src/markdown.c
+++ src/markdown.c
@@ -171,39 +171,21 @@
171
172 /********************
173 * GLOBAL VARIABLES *
174 ********************/
175
176 /* block_tags -- recognised block tags, sorted by cmp_html_tag */
 
 
 
 
 
177 static const struct html_tag block_tags[] = {
178 { "p", 1 },
179 { "dl", 2 },
180 { "h1", 2 },
181 { "h2", 2 },
182 { "h3", 2 },
183 { "h4", 2 },
184 { "h5", 2 },
185 { "h6", 2 },
186 { "ol", 2 },
187 { "ul", 2 },
188 { "del", 3 },
189 { "div", 3 },
190 { "ins", 3 },
191 { "pre", 3 },
192 { "form", 4 },
193 { "math", 4 },
194 { "table", 5 },
195 { "iframe", 6 },
196 { "script", 6 },
197 { "fieldset", 8 },
198 { "noscript", 8 },
199 { "blockquote", 10 }
200 };
201
202 #define INS_TAG (block_tags + 12)
203 #define DEL_TAG (block_tags + 10)
204
205
206
207 /***************************
208 * STATIC HELPER FUNCTIONS *
209 ***************************/
@@ -270,12 +252,16 @@
270
271 /* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */
272 static int cmp_html_tag(const void *a, const void *b){
273 const struct html_tag *hta = a;
274 const struct html_tag *htb = b;
275 if( hta->size!=htb->size ) return hta->size-htb->size;
276 return fossil_strnicmp(hta->text, htb->text, hta->size);
 
 
 
 
277 }
278
279
280 /* find_block_tag -- returns the current block tag */
281 static const struct html_tag *find_block_tag(const char *data, size_t size){
@@ -1711,11 +1697,11 @@
1711 size_t i, w;
1712
1713 /* assuming data[0]=='<' && data[1]=='/' already tested */
1714
1715 /* checking tag is a match */
1716 if( (tag->size+3)>=size
1717 || fossil_strnicmp(data+2, tag->text, tag->size)
1718 || data[tag->size+2]!='>'
1719 ){
1720 return 0;
1721 }
@@ -1797,51 +1783,36 @@
1797
1798 /* no special case recognised */
1799 return 0;
1800 }
1801
1802 /* looking for an unindented matching closing tag */
1803 /* followed by a blank line */
1804 i = 1;
1805 found = 0;
1806 #if 0
1807 while( i<size ){
1808 i++;
1809 while( i<size && !(data[i-2]=='\n' && data[i-1]=='<' && data[i]=='/') ){
1810 i++;
1811 }
1812 if( (i+2+curtag->size)>=size ) break;
1813 j = htmlblock_end(curtag, data+i-1, size-i+1);
1814 if (j) {
1815 i += j-1;
1816 found = 1;
1817 break;
1818 }
1819 }
1820 #endif
1821
1822 /* if not found, trying a second pass looking for indented match */
1823 /* but not if tag is "ins" or "del" (following original Markdown.pl) */
1824 if( !found && curtag!=INS_TAG && curtag!=DEL_TAG ){
1825 i = 1;
1826 while( i<size ){
1827 i++;
1828 while( i<size && !(data[i-1]=='<' && data[i]=='/') ){ i++; }
1829 if( (i+2+curtag->size)>=size ) break;
1830 j = htmlblock_end(curtag, data+i-1, size-i+1);
1831 if (j) {
1832 i += j-1;
1833 found = 1;
1834 break;
1835 }
1836 }
1837 }
1838
1839 if( !found ) return 0;
1840
1841 /* the end of the block has been found */
1842 blob_init(&work, data, i);
 
 
 
 
 
 
 
1843 if( rndr->make.blockhtml ){
1844 rndr->make.blockhtml(ob, &work, rndr->make.opaque);
1845 }
1846 return i;
1847 }
1848
--- src/markdown.c
+++ src/markdown.c
@@ -171,39 +171,21 @@
171
172 /********************
173 * GLOBAL VARIABLES *
174 ********************/
175
176 /* block_tags -- recognised block tags, sorted by cmp_html_tag.
177 **
178 ** When these HTML tags are separated from other text by newlines
179 ** then they are rendered verbatim. Their content is not interpreted
180 ** in any way.
181 */
182 static const struct html_tag block_tags[] = {
183 { "html", 4 },
 
 
 
 
 
 
 
 
 
 
 
 
184 { "pre", 3 },
 
 
 
 
185 { "script", 6 },
 
 
 
186 };
 
 
 
 
187
188
189 /***************************
190 * STATIC HELPER FUNCTIONS *
191 ***************************/
@@ -270,12 +252,16 @@
252
253 /* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */
254 static int cmp_html_tag(const void *a, const void *b){
255 const struct html_tag *hta = a;
256 const struct html_tag *htb = b;
257 int sz = hta->size;
258 int c;
259 if( htb->size<sz ) sz = htb->size;
260 c = fossil_strnicmp(hta->text, htb->text, sz);
261 if( c==0 ) c = hta->size - htb->size;
262 return c;
263 }
264
265
266 /* find_block_tag -- returns the current block tag */
267 static const struct html_tag *find_block_tag(const char *data, size_t size){
@@ -1711,11 +1697,11 @@
1697 size_t i, w;
1698
1699 /* assuming data[0]=='<' && data[1]=='/' already tested */
1700
1701 /* checking tag is a match */
1702 if( (tag->size+3)>size
1703 || fossil_strnicmp(data+2, tag->text, tag->size)
1704 || data[tag->size+2]!='>'
1705 ){
1706 return 0;
1707 }
@@ -1797,51 +1783,36 @@
1783
1784 /* no special case recognised */
1785 return 0;
1786 }
1787
1788 /* looking for an matching closing tag */
1789 /* followed by a blank line */
1790 i = 1;
1791 found = 0;
 
1792 while( i<size ){
1793 i++;
1794 while( i<size && !(data[i-1]=='<' && data[i]=='/') ){ i++; }
1795 if( (i+2+curtag->size)>size ) break;
 
 
1796 j = htmlblock_end(curtag, data+i-1, size-i+1);
1797 if (j) {
1798 i += j-1;
1799 found = 1;
1800 break;
1801 }
1802 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1803 if( !found ) return 0;
1804
1805 /* the end of the block has been found */
1806 if( strcmp(curtag->text,"html")==0 ){
1807 /* Omit <html> tags */
1808 enum mkd_autolink dummy;
1809 int k = tag_length(data, size, &dummy);
1810 blob_init(&work, data+k, i-(j+k));
1811 }else{
1812 blob_init(&work, data, i);
1813 }
1814 if( rndr->make.blockhtml ){
1815 rndr->make.blockhtml(ob, &work, rndr->make.opaque);
1816 }
1817 return i;
1818 }
1819
+1 -1
--- src/markdown.md
+++ src/markdown.md
@@ -173,6 +173,6 @@
173173
> document title displayed at the top of the Fossil page.
174174
175175
[daringfireball.net]: http://daringfireball.net/projects/markdown/syntax
176176
177177
<a name="intermap"></a>
178
-## Interwiki Tag Map
178
+## Interwiki Tag [Map](/intermap)
179179
180180
ADDED src/patch.c
--- src/markdown.md
+++ src/markdown.md
@@ -173,6 +173,6 @@
173 > document title displayed at the top of the Fossil page.
174
175 [daringfireball.net]: http://daringfireball.net/projects/markdown/syntax
176
177 <a name="intermap"></a>
178 ## Interwiki Tag Map
179
180 DDED src/patch.c
--- src/markdown.md
+++ src/markdown.md
@@ -173,6 +173,6 @@
173 > document title displayed at the top of the Fossil page.
174
175 [daringfireball.net]: http://daringfireball.net/projects/markdown/syntax
176
177 <a name="intermap"></a>
178 ## Interwiki Tag [Map](/intermap)
179
180 DDED src/patch.c
--- a/src/patch.c
+++ b/src/patch.c
@@ -0,0 +1,7 @@
1
+/*
2
+** Cconst char *zDiffCmd, /* BinGlob, /* GLOB pattern to determine binary files */
3
+ int fIncludeBinary, /* Doint isBin1, isBin2isBin2 = 0isBin1 = fIncludeBinaisBin1, isBin2, zName, zDiffCmdzBinGlob, fIncludeBinary, pCfg)isBin1 = 0;
4
+ isBin2 = fIncludeBinary ? 0 : looks_like_binary(empty, &a, isBizBinGlob, fIncludeBinary C->diffFlags);
5
+->diffFlags/*
6
+** Cconst char *zDiffCmd, /* BinGlob, /* GLOB pattern to determine binary files */
7
+ int fIncludeBi 1, is
--- a/src/patch.c
+++ b/src/patch.c
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
--- a/src/patch.c
+++ b/src/patch.c
@@ -0,0 +1,7 @@
1 /*
2 ** Cconst char *zDiffCmd, /* BinGlob, /* GLOB pattern to determine binary files */
3 int fIncludeBinary, /* Doint isBin1, isBin2isBin2 = 0isBin1 = fIncludeBinaisBin1, isBin2, zName, zDiffCmdzBinGlob, fIncludeBinary, pCfg)isBin1 = 0;
4 isBin2 = fIncludeBinary ? 0 : looks_like_binary(empty, &a, isBizBinGlob, fIncludeBinary C->diffFlags);
5 ->diffFlags/*
6 ** Cconst char *zDiffCmd, /* BinGlob, /* GLOB pattern to determine binary files */
7 int fIncludeBi 1, is
+355 -275
--- src/pikchr.c
+++ src/pikchr.c
@@ -317,10 +317,11 @@
317317
PToken aTxt[5]; /* Text with .eCode holding TP flags */
318318
int iLayer; /* Rendering order */
319319
int inDir, outDir; /* Entry and exit directions */
320320
int nPath; /* Number of path points */
321321
PPoint *aPath; /* Array of path points */
322
+ PObj *pFrom, *pTo; /* End-point objects of a path */
322323
PBox bbox; /* Bounding box */
323324
};
324325
325326
/* A list of graphics objects */
326327
struct PList {
@@ -347,10 +348,11 @@
347348
unsigned int nOut; /* Bytes written to zOut[] so far */
348349
unsigned int nOutAlloc; /* Space allocated to zOut[] */
349350
unsigned char eDir; /* Current direction */
350351
unsigned int mFlags; /* Flags passed to pikchr() */
351352
PObj *cur; /* Object under construction */
353
+ PObj *lastRef; /* Last object references by name */
352354
PList *list; /* Object list under construction */
353355
PMacro *pMacros; /* List of all defined macros */
354356
PVar *pVar; /* Application-defined variables */
355357
PBox bbox; /* Bounding box around all statements */
356358
/* Cache of layout values. <=0.0 for unknown... */
@@ -426,12 +428,14 @@
426428
static void pik_render(Pik*,PList*);
427429
static PList *pik_elist_append(Pik*,PList*,PObj*);
428430
static PObj *pik_elem_new(Pik*,PToken*,PToken*,PList*);
429431
static void pik_set_direction(Pik*,int);
430432
static void pik_elem_setname(Pik*,PObj*,PToken*);
433
+static int pik_round(PNum);
431434
static void pik_set_var(Pik*,PToken*,PNum,PToken*);
432435
static PNum pik_value(Pik*,const char*,int,int*);
436
+static int pik_value_int(Pik*,const char*,int,int*);
433437
static PNum pik_lookup_color(Pik*,PToken*);
434438
static PNum pik_get_var(Pik*,PToken*);
435439
static PNum pik_atof(PToken*);
436440
static void pik_after_adding_attributes(Pik*,PObj*);
437441
static void pik_elem_move(PObj*,PNum dx, PNum dy);
@@ -450,10 +454,11 @@
450454
static short int pik_nth_value(Pik*,PToken*);
451455
static PObj *pik_find_nth(Pik*,PObj*,PToken*);
452456
static PObj *pik_find_byname(Pik*,PObj*,PToken*);
453457
static PPoint pik_place_of_elem(Pik*,PObj*,PToken*);
454458
static int pik_bbox_isempty(PBox*);
459
+static int pik_bbox_contains_point(PBox*,PPoint*);
455460
static void pik_bbox_init(PBox*);
456461
static void pik_bbox_addbox(PBox*,PBox*);
457462
static void pik_bbox_add_xy(PBox*,PNum,PNum);
458463
static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry);
459464
static void pik_add_txt(Pik*,PToken*,int);
@@ -474,11 +479,11 @@
474479
static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*);
475480
static PNum pik_dist(PPoint*,PPoint*);
476481
static void pik_add_macro(Pik*,PToken *pId,PToken *pCode);
477482
478483
479
-#line 505 "pikchr.c"
484
+#line 510 "pikchr.c"
480485
/**************** End of %include directives **********************************/
481486
/* These constants specify the various numeric values for terminal symbols.
482487
***************** Begin token definitions *************************************/
483488
#ifndef T_ID
484489
#define T_ID 1
@@ -1703,22 +1708,22 @@
17031708
** inside the C code.
17041709
*/
17051710
/********* Begin destructor definitions ***************************************/
17061711
case 99: /* statement_list */
17071712
{
1708
-#line 494 "pikchr.y"
1713
+#line 499 "pikchr.y"
17091714
pik_elist_free(p,(yypminor->yy227));
1710
-#line 1735 "pikchr.c"
1715
+#line 1740 "pikchr.c"
17111716
}
17121717
break;
17131718
case 100: /* statement */
17141719
case 101: /* unnamed_statement */
17151720
case 102: /* basetype */
17161721
{
1717
-#line 496 "pikchr.y"
1722
+#line 501 "pikchr.y"
17181723
pik_elem_free(p,(yypminor->yy36));
1719
-#line 1744 "pikchr.c"
1724
+#line 1749 "pikchr.c"
17201725
}
17211726
break;
17221727
/********* End destructor definitions *****************************************/
17231728
default: break; /* If no destructor action specified: do nothing */
17241729
}
@@ -1932,14 +1937,14 @@
19321937
#endif
19331938
while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
19341939
/* Here code is inserted which will execute if the parser
19351940
** stack every overflows */
19361941
/******** Begin %stack_overflow code ******************************************/
1937
-#line 528 "pikchr.y"
1942
+#line 533 "pikchr.y"
19381943
19391944
pik_error(p, 0, "parser stack overflow");
1940
-#line 1965 "pikchr.c"
1945
+#line 1970 "pikchr.c"
19411946
/******** End %stack_overflow code ********************************************/
19421947
pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
19431948
pik_parserCTX_STORE
19441949
}
19451950
@@ -2415,619 +2420,619 @@
24152420
** break;
24162421
*/
24172422
/********** Begin reduce actions **********************************************/
24182423
YYMINORTYPE yylhsminor;
24192424
case 0: /* document ::= statement_list */
2420
-#line 532 "pikchr.y"
2425
+#line 537 "pikchr.y"
24212426
{pik_render(p,yymsp[0].minor.yy227);}
2422
-#line 2447 "pikchr.c"
2427
+#line 2452 "pikchr.c"
24232428
break;
24242429
case 1: /* statement_list ::= statement */
2425
-#line 535 "pikchr.y"
2430
+#line 540 "pikchr.y"
24262431
{ yylhsminor.yy227 = pik_elist_append(p,0,yymsp[0].minor.yy36); }
2427
-#line 2452 "pikchr.c"
2432
+#line 2457 "pikchr.c"
24282433
yymsp[0].minor.yy227 = yylhsminor.yy227;
24292434
break;
24302435
case 2: /* statement_list ::= statement_list EOL statement */
2431
-#line 537 "pikchr.y"
2436
+#line 542 "pikchr.y"
24322437
{ yylhsminor.yy227 = pik_elist_append(p,yymsp[-2].minor.yy227,yymsp[0].minor.yy36); }
2433
-#line 2458 "pikchr.c"
2438
+#line 2463 "pikchr.c"
24342439
yymsp[-2].minor.yy227 = yylhsminor.yy227;
24352440
break;
24362441
case 3: /* statement ::= */
2437
-#line 540 "pikchr.y"
2442
+#line 545 "pikchr.y"
24382443
{ yymsp[1].minor.yy36 = 0; }
2439
-#line 2464 "pikchr.c"
2444
+#line 2469 "pikchr.c"
24402445
break;
24412446
case 4: /* statement ::= direction */
2442
-#line 541 "pikchr.y"
2447
+#line 546 "pikchr.y"
24432448
{ pik_set_direction(p,yymsp[0].minor.yy0.eCode); yylhsminor.yy36=0; }
2444
-#line 2469 "pikchr.c"
2449
+#line 2474 "pikchr.c"
24452450
yymsp[0].minor.yy36 = yylhsminor.yy36;
24462451
break;
24472452
case 5: /* statement ::= lvalue ASSIGN rvalue */
2448
-#line 542 "pikchr.y"
2453
+#line 547 "pikchr.y"
24492454
{pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy153,&yymsp[-1].minor.yy0); yylhsminor.yy36=0;}
2450
-#line 2475 "pikchr.c"
2455
+#line 2480 "pikchr.c"
24512456
yymsp[-2].minor.yy36 = yylhsminor.yy36;
24522457
break;
24532458
case 6: /* statement ::= PLACENAME COLON unnamed_statement */
2454
-#line 544 "pikchr.y"
2459
+#line 549 "pikchr.y"
24552460
{ yylhsminor.yy36 = yymsp[0].minor.yy36; pik_elem_setname(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0); }
2456
-#line 2481 "pikchr.c"
2461
+#line 2486 "pikchr.c"
24572462
yymsp[-2].minor.yy36 = yylhsminor.yy36;
24582463
break;
24592464
case 7: /* statement ::= PLACENAME COLON position */
2460
-#line 546 "pikchr.y"
2465
+#line 551 "pikchr.y"
24612466
{ yylhsminor.yy36 = pik_elem_new(p,0,0,0);
24622467
if(yylhsminor.yy36){ yylhsminor.yy36->ptAt = yymsp[0].minor.yy79; pik_elem_setname(p,yylhsminor.yy36,&yymsp[-2].minor.yy0); }}
2463
-#line 2488 "pikchr.c"
2468
+#line 2493 "pikchr.c"
24642469
yymsp[-2].minor.yy36 = yylhsminor.yy36;
24652470
break;
24662471
case 8: /* statement ::= unnamed_statement */
2467
-#line 548 "pikchr.y"
2472
+#line 553 "pikchr.y"
24682473
{yylhsminor.yy36 = yymsp[0].minor.yy36;}
2469
-#line 2494 "pikchr.c"
2474
+#line 2499 "pikchr.c"
24702475
yymsp[0].minor.yy36 = yylhsminor.yy36;
24712476
break;
24722477
case 9: /* statement ::= print prlist */
2473
-#line 549 "pikchr.y"
2478
+#line 554 "pikchr.y"
24742479
{pik_append(p,"<br>\n",5); yymsp[-1].minor.yy36=0;}
2475
-#line 2500 "pikchr.c"
2480
+#line 2505 "pikchr.c"
24762481
break;
24772482
case 10: /* statement ::= ASSERT LP expr EQ expr RP */
2478
-#line 554 "pikchr.y"
2483
+#line 559 "pikchr.y"
24792484
{yymsp[-5].minor.yy36=pik_assert(p,yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy153);}
2480
-#line 2505 "pikchr.c"
2485
+#line 2510 "pikchr.c"
24812486
break;
24822487
case 11: /* statement ::= ASSERT LP position EQ position RP */
2483
-#line 556 "pikchr.y"
2488
+#line 561 "pikchr.y"
24842489
{yymsp[-5].minor.yy36=pik_position_assert(p,&yymsp[-3].minor.yy79,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy79);}
2485
-#line 2510 "pikchr.c"
2490
+#line 2515 "pikchr.c"
24862491
break;
24872492
case 12: /* statement ::= DEFINE ID CODEBLOCK */
2488
-#line 557 "pikchr.y"
2493
+#line 562 "pikchr.y"
24892494
{yymsp[-2].minor.yy36=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
2490
-#line 2515 "pikchr.c"
2495
+#line 2520 "pikchr.c"
24912496
break;
24922497
case 13: /* rvalue ::= PLACENAME */
2493
-#line 568 "pikchr.y"
2498
+#line 573 "pikchr.y"
24942499
{yylhsminor.yy153 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
2495
-#line 2520 "pikchr.c"
2500
+#line 2525 "pikchr.c"
24962501
yymsp[0].minor.yy153 = yylhsminor.yy153;
24972502
break;
24982503
case 14: /* pritem ::= FILL */
24992504
case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
25002505
case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
2501
-#line 573 "pikchr.y"
2506
+#line 578 "pikchr.y"
25022507
{pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
2503
-#line 2528 "pikchr.c"
2508
+#line 2533 "pikchr.c"
25042509
break;
25052510
case 17: /* pritem ::= rvalue */
2506
-#line 576 "pikchr.y"
2511
+#line 581 "pikchr.y"
25072512
{pik_append_num(p,"",yymsp[0].minor.yy153);}
2508
-#line 2533 "pikchr.c"
2513
+#line 2538 "pikchr.c"
25092514
break;
25102515
case 18: /* pritem ::= STRING */
2511
-#line 577 "pikchr.y"
2516
+#line 582 "pikchr.y"
25122517
{pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
2513
-#line 2538 "pikchr.c"
2518
+#line 2543 "pikchr.c"
25142519
break;
25152520
case 19: /* prsep ::= COMMA */
2516
-#line 578 "pikchr.y"
2521
+#line 583 "pikchr.y"
25172522
{pik_append(p, " ", 1);}
2518
-#line 2543 "pikchr.c"
2523
+#line 2548 "pikchr.c"
25192524
break;
25202525
case 20: /* unnamed_statement ::= basetype attribute_list */
2521
-#line 581 "pikchr.y"
2526
+#line 586 "pikchr.y"
25222527
{yylhsminor.yy36 = yymsp[-1].minor.yy36; pik_after_adding_attributes(p,yylhsminor.yy36);}
2523
-#line 2548 "pikchr.c"
2528
+#line 2553 "pikchr.c"
25242529
yymsp[-1].minor.yy36 = yylhsminor.yy36;
25252530
break;
25262531
case 21: /* basetype ::= CLASSNAME */
2527
-#line 583 "pikchr.y"
2532
+#line 588 "pikchr.y"
25282533
{yylhsminor.yy36 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
2529
-#line 2554 "pikchr.c"
2534
+#line 2559 "pikchr.c"
25302535
yymsp[0].minor.yy36 = yylhsminor.yy36;
25312536
break;
25322537
case 22: /* basetype ::= STRING textposition */
2533
-#line 585 "pikchr.y"
2538
+#line 590 "pikchr.y"
25342539
{yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy164; yylhsminor.yy36 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
2535
-#line 2560 "pikchr.c"
2540
+#line 2565 "pikchr.c"
25362541
yymsp[-1].minor.yy36 = yylhsminor.yy36;
25372542
break;
25382543
case 23: /* basetype ::= LB savelist statement_list RB */
2539
-#line 587 "pikchr.y"
2544
+#line 592 "pikchr.y"
25402545
{ p->list = yymsp[-2].minor.yy227; yymsp[-3].minor.yy36 = pik_elem_new(p,0,0,yymsp[-1].minor.yy227); if(yymsp[-3].minor.yy36) yymsp[-3].minor.yy36->errTok = yymsp[0].minor.yy0; }
2541
-#line 2566 "pikchr.c"
2546
+#line 2571 "pikchr.c"
25422547
break;
25432548
case 24: /* savelist ::= */
2544
-#line 592 "pikchr.y"
2549
+#line 597 "pikchr.y"
25452550
{yymsp[1].minor.yy227 = p->list; p->list = 0;}
2546
-#line 2571 "pikchr.c"
2551
+#line 2576 "pikchr.c"
25472552
break;
25482553
case 25: /* relexpr ::= expr */
2549
-#line 599 "pikchr.y"
2554
+#line 604 "pikchr.y"
25502555
{yylhsminor.yy10.rAbs = yymsp[0].minor.yy153; yylhsminor.yy10.rRel = 0;}
2551
-#line 2576 "pikchr.c"
2556
+#line 2581 "pikchr.c"
25522557
yymsp[0].minor.yy10 = yylhsminor.yy10;
25532558
break;
25542559
case 26: /* relexpr ::= expr PERCENT */
2555
-#line 600 "pikchr.y"
2560
+#line 605 "pikchr.y"
25562561
{yylhsminor.yy10.rAbs = 0; yylhsminor.yy10.rRel = yymsp[-1].minor.yy153/100;}
2557
-#line 2582 "pikchr.c"
2562
+#line 2587 "pikchr.c"
25582563
yymsp[-1].minor.yy10 = yylhsminor.yy10;
25592564
break;
25602565
case 27: /* optrelexpr ::= */
2561
-#line 602 "pikchr.y"
2566
+#line 607 "pikchr.y"
25622567
{yymsp[1].minor.yy10.rAbs = 0; yymsp[1].minor.yy10.rRel = 1.0;}
2563
-#line 2588 "pikchr.c"
2568
+#line 2593 "pikchr.c"
25642569
break;
25652570
case 28: /* attribute_list ::= relexpr alist */
2566
-#line 604 "pikchr.y"
2571
+#line 609 "pikchr.y"
25672572
{pik_add_direction(p,0,&yymsp[-1].minor.yy10);}
2568
-#line 2593 "pikchr.c"
2573
+#line 2598 "pikchr.c"
25692574
break;
25702575
case 29: /* attribute ::= numproperty relexpr */
2571
-#line 608 "pikchr.y"
2576
+#line 613 "pikchr.y"
25722577
{ pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10); }
2573
-#line 2598 "pikchr.c"
2578
+#line 2603 "pikchr.c"
25742579
break;
25752580
case 30: /* attribute ::= dashproperty expr */
2576
-#line 609 "pikchr.y"
2581
+#line 614 "pikchr.y"
25772582
{ pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy153); }
2578
-#line 2603 "pikchr.c"
2583
+#line 2608 "pikchr.c"
25792584
break;
25802585
case 31: /* attribute ::= dashproperty */
2581
-#line 610 "pikchr.y"
2586
+#line 615 "pikchr.y"
25822587
{ pik_set_dashed(p,&yymsp[0].minor.yy0,0); }
2583
-#line 2608 "pikchr.c"
2588
+#line 2613 "pikchr.c"
25842589
break;
25852590
case 32: /* attribute ::= colorproperty rvalue */
2586
-#line 611 "pikchr.y"
2591
+#line 616 "pikchr.y"
25872592
{ pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153); }
2588
-#line 2613 "pikchr.c"
2593
+#line 2618 "pikchr.c"
25892594
break;
25902595
case 33: /* attribute ::= go direction optrelexpr */
2591
-#line 612 "pikchr.y"
2596
+#line 617 "pikchr.y"
25922597
{ pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10);}
2593
-#line 2618 "pikchr.c"
2598
+#line 2623 "pikchr.c"
25942599
break;
25952600
case 34: /* attribute ::= go direction even position */
2596
-#line 613 "pikchr.y"
2601
+#line 618 "pikchr.y"
25972602
{pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79);}
2598
-#line 2623 "pikchr.c"
2603
+#line 2628 "pikchr.c"
25992604
break;
26002605
case 35: /* attribute ::= CLOSE */
2601
-#line 614 "pikchr.y"
2606
+#line 619 "pikchr.y"
26022607
{ pik_close_path(p,&yymsp[0].minor.yy0); }
2603
-#line 2628 "pikchr.c"
2608
+#line 2633 "pikchr.c"
26042609
break;
26052610
case 36: /* attribute ::= CHOP */
2606
-#line 615 "pikchr.y"
2611
+#line 620 "pikchr.y"
26072612
{ p->cur->bChop = 1; }
2608
-#line 2633 "pikchr.c"
2613
+#line 2638 "pikchr.c"
26092614
break;
26102615
case 37: /* attribute ::= FROM position */
2611
-#line 616 "pikchr.y"
2616
+#line 621 "pikchr.y"
26122617
{ pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
2613
-#line 2638 "pikchr.c"
2618
+#line 2643 "pikchr.c"
26142619
break;
26152620
case 38: /* attribute ::= TO position */
2616
-#line 617 "pikchr.y"
2621
+#line 622 "pikchr.y"
26172622
{ pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
2618
-#line 2643 "pikchr.c"
2623
+#line 2648 "pikchr.c"
26192624
break;
26202625
case 39: /* attribute ::= THEN */
2621
-#line 618 "pikchr.y"
2626
+#line 623 "pikchr.y"
26222627
{ pik_then(p, &yymsp[0].minor.yy0, p->cur); }
2623
-#line 2648 "pikchr.c"
2628
+#line 2653 "pikchr.c"
26242629
break;
26252630
case 40: /* attribute ::= THEN optrelexpr HEADING expr */
26262631
case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
2627
-#line 620 "pikchr.y"
2632
+#line 625 "pikchr.y"
26282633
{pik_move_hdg(p,&yymsp[-2].minor.yy10,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153,0,&yymsp[-3].minor.yy0);}
2629
-#line 2654 "pikchr.c"
2634
+#line 2659 "pikchr.c"
26302635
break;
26312636
case 41: /* attribute ::= THEN optrelexpr EDGEPT */
26322637
case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
2633
-#line 621 "pikchr.y"
2638
+#line 626 "pikchr.y"
26342639
{pik_move_hdg(p,&yymsp[-1].minor.yy10,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
2635
-#line 2660 "pikchr.c"
2640
+#line 2665 "pikchr.c"
26362641
break;
26372642
case 44: /* attribute ::= AT position */
2638
-#line 626 "pikchr.y"
2643
+#line 631 "pikchr.y"
26392644
{ pik_set_at(p,0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
2640
-#line 2665 "pikchr.c"
2645
+#line 2670 "pikchr.c"
26412646
break;
26422647
case 45: /* attribute ::= SAME */
2643
-#line 628 "pikchr.y"
2648
+#line 633 "pikchr.y"
26442649
{pik_same(p,0,&yymsp[0].minor.yy0);}
2645
-#line 2670 "pikchr.c"
2650
+#line 2675 "pikchr.c"
26462651
break;
26472652
case 46: /* attribute ::= SAME AS object */
2648
-#line 629 "pikchr.y"
2653
+#line 634 "pikchr.y"
26492654
{pik_same(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2650
-#line 2675 "pikchr.c"
2655
+#line 2680 "pikchr.c"
26512656
break;
26522657
case 47: /* attribute ::= STRING textposition */
2653
-#line 630 "pikchr.y"
2658
+#line 635 "pikchr.y"
26542659
{pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy164);}
2655
-#line 2680 "pikchr.c"
2660
+#line 2685 "pikchr.c"
26562661
break;
26572662
case 48: /* attribute ::= FIT */
2658
-#line 631 "pikchr.y"
2663
+#line 636 "pikchr.y"
26592664
{pik_size_to_fit(p,&yymsp[0].minor.yy0,3); }
2660
-#line 2685 "pikchr.c"
2665
+#line 2690 "pikchr.c"
26612666
break;
26622667
case 49: /* attribute ::= BEHIND object */
2663
-#line 632 "pikchr.y"
2668
+#line 637 "pikchr.y"
26642669
{pik_behind(p,yymsp[0].minor.yy36);}
2665
-#line 2690 "pikchr.c"
2670
+#line 2695 "pikchr.c"
26662671
break;
26672672
case 50: /* withclause ::= DOT_E edge AT position */
26682673
case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
2669
-#line 640 "pikchr.y"
2674
+#line 645 "pikchr.y"
26702675
{ pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
2671
-#line 2696 "pikchr.c"
2676
+#line 2701 "pikchr.c"
26722677
break;
26732678
case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
2674
-#line 644 "pikchr.y"
2679
+#line 649 "pikchr.y"
26752680
{yylhsminor.yy0 = yymsp[0].minor.yy0;}
2676
-#line 2701 "pikchr.c"
2681
+#line 2706 "pikchr.c"
26772682
yymsp[0].minor.yy0 = yylhsminor.yy0;
26782683
break;
26792684
case 53: /* boolproperty ::= CW */
2680
-#line 655 "pikchr.y"
2685
+#line 660 "pikchr.y"
26812686
{p->cur->cw = 1;}
2682
-#line 2707 "pikchr.c"
2687
+#line 2712 "pikchr.c"
26832688
break;
26842689
case 54: /* boolproperty ::= CCW */
2685
-#line 656 "pikchr.y"
2690
+#line 661 "pikchr.y"
26862691
{p->cur->cw = 0;}
2687
-#line 2712 "pikchr.c"
2692
+#line 2717 "pikchr.c"
26882693
break;
26892694
case 55: /* boolproperty ::= LARROW */
2690
-#line 657 "pikchr.y"
2695
+#line 662 "pikchr.y"
26912696
{p->cur->larrow=1; p->cur->rarrow=0; }
2692
-#line 2717 "pikchr.c"
2697
+#line 2722 "pikchr.c"
26932698
break;
26942699
case 56: /* boolproperty ::= RARROW */
2695
-#line 658 "pikchr.y"
2700
+#line 663 "pikchr.y"
26962701
{p->cur->larrow=0; p->cur->rarrow=1; }
2697
-#line 2722 "pikchr.c"
2702
+#line 2727 "pikchr.c"
26982703
break;
26992704
case 57: /* boolproperty ::= LRARROW */
2700
-#line 659 "pikchr.y"
2705
+#line 664 "pikchr.y"
27012706
{p->cur->larrow=1; p->cur->rarrow=1; }
2702
-#line 2727 "pikchr.c"
2707
+#line 2732 "pikchr.c"
27032708
break;
27042709
case 58: /* boolproperty ::= INVIS */
2705
-#line 660 "pikchr.y"
2710
+#line 665 "pikchr.y"
27062711
{p->cur->sw = 0.0;}
2707
-#line 2732 "pikchr.c"
2712
+#line 2737 "pikchr.c"
27082713
break;
27092714
case 59: /* boolproperty ::= THICK */
2710
-#line 661 "pikchr.y"
2715
+#line 666 "pikchr.y"
27112716
{p->cur->sw *= 1.5;}
2712
-#line 2737 "pikchr.c"
2717
+#line 2742 "pikchr.c"
27132718
break;
27142719
case 60: /* boolproperty ::= THIN */
2715
-#line 662 "pikchr.y"
2720
+#line 667 "pikchr.y"
27162721
{p->cur->sw *= 0.67;}
2717
-#line 2742 "pikchr.c"
2722
+#line 2747 "pikchr.c"
27182723
break;
27192724
case 61: /* boolproperty ::= SOLID */
2720
-#line 663 "pikchr.y"
2725
+#line 668 "pikchr.y"
27212726
{p->cur->sw = pik_value(p,"thickness",9,0);
27222727
p->cur->dotted = p->cur->dashed = 0.0;}
2723
-#line 2748 "pikchr.c"
2728
+#line 2753 "pikchr.c"
27242729
break;
27252730
case 62: /* textposition ::= */
2726
-#line 666 "pikchr.y"
2731
+#line 671 "pikchr.y"
27272732
{yymsp[1].minor.yy164 = 0;}
2728
-#line 2753 "pikchr.c"
2733
+#line 2758 "pikchr.c"
27292734
break;
27302735
case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|ALIGNED|BIG|SMALL */
2731
-#line 669 "pikchr.y"
2736
+#line 674 "pikchr.y"
27322737
{yylhsminor.yy164 = (short int)pik_text_position(yymsp[-1].minor.yy164,&yymsp[0].minor.yy0);}
2733
-#line 2758 "pikchr.c"
2738
+#line 2763 "pikchr.c"
27342739
yymsp[-1].minor.yy164 = yylhsminor.yy164;
27352740
break;
27362741
case 64: /* position ::= expr COMMA expr */
2737
-#line 672 "pikchr.y"
2742
+#line 677 "pikchr.y"
27382743
{yylhsminor.yy79.x=yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[0].minor.yy153;}
2739
-#line 2764 "pikchr.c"
2744
+#line 2769 "pikchr.c"
27402745
yymsp[-2].minor.yy79 = yylhsminor.yy79;
27412746
break;
27422747
case 65: /* position ::= place PLUS expr COMMA expr */
2743
-#line 674 "pikchr.y"
2748
+#line 679 "pikchr.y"
27442749
{yylhsminor.yy79.x=yymsp[-4].minor.yy79.x+yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y+yymsp[0].minor.yy153;}
2745
-#line 2770 "pikchr.c"
2750
+#line 2775 "pikchr.c"
27462751
yymsp[-4].minor.yy79 = yylhsminor.yy79;
27472752
break;
27482753
case 66: /* position ::= place MINUS expr COMMA expr */
2749
-#line 675 "pikchr.y"
2754
+#line 680 "pikchr.y"
27502755
{yylhsminor.yy79.x=yymsp[-4].minor.yy79.x-yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y-yymsp[0].minor.yy153;}
2751
-#line 2776 "pikchr.c"
2756
+#line 2781 "pikchr.c"
27522757
yymsp[-4].minor.yy79 = yylhsminor.yy79;
27532758
break;
27542759
case 67: /* position ::= place PLUS LP expr COMMA expr RP */
2755
-#line 677 "pikchr.y"
2760
+#line 682 "pikchr.y"
27562761
{yylhsminor.yy79.x=yymsp[-6].minor.yy79.x+yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y+yymsp[-1].minor.yy153;}
2757
-#line 2782 "pikchr.c"
2762
+#line 2787 "pikchr.c"
27582763
yymsp[-6].minor.yy79 = yylhsminor.yy79;
27592764
break;
27602765
case 68: /* position ::= place MINUS LP expr COMMA expr RP */
2761
-#line 679 "pikchr.y"
2766
+#line 684 "pikchr.y"
27622767
{yylhsminor.yy79.x=yymsp[-6].minor.yy79.x-yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y-yymsp[-1].minor.yy153;}
2763
-#line 2788 "pikchr.c"
2768
+#line 2793 "pikchr.c"
27642769
yymsp[-6].minor.yy79 = yylhsminor.yy79;
27652770
break;
27662771
case 69: /* position ::= LP position COMMA position RP */
2767
-#line 680 "pikchr.y"
2772
+#line 685 "pikchr.y"
27682773
{yymsp[-4].minor.yy79.x=yymsp[-3].minor.yy79.x; yymsp[-4].minor.yy79.y=yymsp[-1].minor.yy79.y;}
2769
-#line 2794 "pikchr.c"
2774
+#line 2799 "pikchr.c"
27702775
break;
27712776
case 70: /* position ::= LP position RP */
2772
-#line 681 "pikchr.y"
2777
+#line 686 "pikchr.y"
27732778
{yymsp[-2].minor.yy79=yymsp[-1].minor.yy79;}
2774
-#line 2799 "pikchr.c"
2779
+#line 2804 "pikchr.c"
27752780
break;
27762781
case 71: /* position ::= expr between position AND position */
2777
-#line 683 "pikchr.y"
2782
+#line 688 "pikchr.y"
27782783
{yylhsminor.yy79 = pik_position_between(yymsp[-4].minor.yy153,yymsp[-2].minor.yy79,yymsp[0].minor.yy79);}
2779
-#line 2804 "pikchr.c"
2784
+#line 2809 "pikchr.c"
27802785
yymsp[-4].minor.yy79 = yylhsminor.yy79;
27812786
break;
27822787
case 72: /* position ::= expr LT position COMMA position GT */
2783
-#line 685 "pikchr.y"
2788
+#line 690 "pikchr.y"
27842789
{yylhsminor.yy79 = pik_position_between(yymsp[-5].minor.yy153,yymsp[-3].minor.yy79,yymsp[-1].minor.yy79);}
2785
-#line 2810 "pikchr.c"
2790
+#line 2815 "pikchr.c"
27862791
yymsp[-5].minor.yy79 = yylhsminor.yy79;
27872792
break;
27882793
case 73: /* position ::= expr ABOVE position */
2789
-#line 686 "pikchr.y"
2794
+#line 691 "pikchr.y"
27902795
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y += yymsp[-2].minor.yy153;}
2791
-#line 2816 "pikchr.c"
2796
+#line 2821 "pikchr.c"
27922797
yymsp[-2].minor.yy79 = yylhsminor.yy79;
27932798
break;
27942799
case 74: /* position ::= expr BELOW position */
2795
-#line 687 "pikchr.y"
2800
+#line 692 "pikchr.y"
27962801
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y -= yymsp[-2].minor.yy153;}
2797
-#line 2822 "pikchr.c"
2802
+#line 2827 "pikchr.c"
27982803
yymsp[-2].minor.yy79 = yylhsminor.yy79;
27992804
break;
28002805
case 75: /* position ::= expr LEFT OF position */
2801
-#line 688 "pikchr.y"
2806
+#line 693 "pikchr.y"
28022807
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x -= yymsp[-3].minor.yy153;}
2803
-#line 2828 "pikchr.c"
2808
+#line 2833 "pikchr.c"
28042809
yymsp[-3].minor.yy79 = yylhsminor.yy79;
28052810
break;
28062811
case 76: /* position ::= expr RIGHT OF position */
2807
-#line 689 "pikchr.y"
2812
+#line 694 "pikchr.y"
28082813
{yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x += yymsp[-3].minor.yy153;}
2809
-#line 2834 "pikchr.c"
2814
+#line 2839 "pikchr.c"
28102815
yymsp[-3].minor.yy79 = yylhsminor.yy79;
28112816
break;
28122817
case 77: /* position ::= expr ON HEADING EDGEPT OF position */
2813
-#line 691 "pikchr.y"
2818
+#line 696 "pikchr.y"
28142819
{yylhsminor.yy79 = pik_position_at_hdg(yymsp[-5].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2815
-#line 2840 "pikchr.c"
2820
+#line 2845 "pikchr.c"
28162821
yymsp[-5].minor.yy79 = yylhsminor.yy79;
28172822
break;
28182823
case 78: /* position ::= expr HEADING EDGEPT OF position */
2819
-#line 693 "pikchr.y"
2824
+#line 698 "pikchr.y"
28202825
{yylhsminor.yy79 = pik_position_at_hdg(yymsp[-4].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2821
-#line 2846 "pikchr.c"
2826
+#line 2851 "pikchr.c"
28222827
yymsp[-4].minor.yy79 = yylhsminor.yy79;
28232828
break;
28242829
case 79: /* position ::= expr EDGEPT OF position */
2825
-#line 695 "pikchr.y"
2830
+#line 700 "pikchr.y"
28262831
{yylhsminor.yy79 = pik_position_at_hdg(yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2827
-#line 2852 "pikchr.c"
2832
+#line 2857 "pikchr.c"
28282833
yymsp[-3].minor.yy79 = yylhsminor.yy79;
28292834
break;
28302835
case 80: /* position ::= expr ON HEADING expr FROM position */
2831
-#line 697 "pikchr.y"
2836
+#line 702 "pikchr.y"
28322837
{yylhsminor.yy79 = pik_position_at_angle(yymsp[-5].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
2833
-#line 2858 "pikchr.c"
2838
+#line 2863 "pikchr.c"
28342839
yymsp[-5].minor.yy79 = yylhsminor.yy79;
28352840
break;
28362841
case 81: /* position ::= expr HEADING expr FROM position */
2837
-#line 699 "pikchr.y"
2842
+#line 704 "pikchr.y"
28382843
{yylhsminor.yy79 = pik_position_at_angle(yymsp[-4].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
2839
-#line 2864 "pikchr.c"
2844
+#line 2869 "pikchr.c"
28402845
yymsp[-4].minor.yy79 = yylhsminor.yy79;
28412846
break;
28422847
case 82: /* place ::= edge OF object */
2843
-#line 711 "pikchr.y"
2848
+#line 716 "pikchr.y"
28442849
{yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2845
-#line 2870 "pikchr.c"
2850
+#line 2875 "pikchr.c"
28462851
yymsp[-2].minor.yy79 = yylhsminor.yy79;
28472852
break;
28482853
case 83: /* place2 ::= object */
2849
-#line 712 "pikchr.y"
2854
+#line 717 "pikchr.y"
28502855
{yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,0);}
2851
-#line 2876 "pikchr.c"
2856
+#line 2881 "pikchr.c"
28522857
yymsp[0].minor.yy79 = yylhsminor.yy79;
28532858
break;
28542859
case 84: /* place2 ::= object DOT_E edge */
2855
-#line 713 "pikchr.y"
2860
+#line 718 "pikchr.y"
28562861
{yylhsminor.yy79 = pik_place_of_elem(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
2857
-#line 2882 "pikchr.c"
2862
+#line 2887 "pikchr.c"
28582863
yymsp[-2].minor.yy79 = yylhsminor.yy79;
28592864
break;
28602865
case 85: /* place2 ::= NTH VERTEX OF object */
2861
-#line 714 "pikchr.y"
2866
+#line 719 "pikchr.y"
28622867
{yylhsminor.yy79 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy36);}
2863
-#line 2888 "pikchr.c"
2868
+#line 2893 "pikchr.c"
28642869
yymsp[-3].minor.yy79 = yylhsminor.yy79;
28652870
break;
28662871
case 86: /* object ::= nth */
2867
-#line 726 "pikchr.y"
2872
+#line 731 "pikchr.y"
28682873
{yylhsminor.yy36 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
2869
-#line 2894 "pikchr.c"
2874
+#line 2899 "pikchr.c"
28702875
yymsp[0].minor.yy36 = yylhsminor.yy36;
28712876
break;
28722877
case 87: /* object ::= nth OF|IN object */
2873
-#line 727 "pikchr.y"
2878
+#line 732 "pikchr.y"
28742879
{yylhsminor.yy36 = pik_find_nth(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2875
-#line 2900 "pikchr.c"
2880
+#line 2905 "pikchr.c"
28762881
yymsp[-2].minor.yy36 = yylhsminor.yy36;
28772882
break;
28782883
case 88: /* objectname ::= THIS */
2879
-#line 729 "pikchr.y"
2884
+#line 734 "pikchr.y"
28802885
{yymsp[0].minor.yy36 = p->cur;}
2881
-#line 2906 "pikchr.c"
2886
+#line 2911 "pikchr.c"
28822887
break;
28832888
case 89: /* objectname ::= PLACENAME */
2884
-#line 730 "pikchr.y"
2889
+#line 735 "pikchr.y"
28852890
{yylhsminor.yy36 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
2886
-#line 2911 "pikchr.c"
2891
+#line 2916 "pikchr.c"
28872892
yymsp[0].minor.yy36 = yylhsminor.yy36;
28882893
break;
28892894
case 90: /* objectname ::= objectname DOT_U PLACENAME */
2890
-#line 732 "pikchr.y"
2895
+#line 737 "pikchr.y"
28912896
{yylhsminor.yy36 = pik_find_byname(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
2892
-#line 2917 "pikchr.c"
2897
+#line 2922 "pikchr.c"
28932898
yymsp[-2].minor.yy36 = yylhsminor.yy36;
28942899
break;
28952900
case 91: /* nth ::= NTH CLASSNAME */
2896
-#line 734 "pikchr.y"
2901
+#line 739 "pikchr.y"
28972902
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
2898
-#line 2923 "pikchr.c"
2903
+#line 2928 "pikchr.c"
28992904
yymsp[-1].minor.yy0 = yylhsminor.yy0;
29002905
break;
29012906
case 92: /* nth ::= NTH LAST CLASSNAME */
2902
-#line 735 "pikchr.y"
2907
+#line 740 "pikchr.y"
29032908
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
2904
-#line 2929 "pikchr.c"
2909
+#line 2934 "pikchr.c"
29052910
yymsp[-2].minor.yy0 = yylhsminor.yy0;
29062911
break;
29072912
case 93: /* nth ::= LAST CLASSNAME */
2908
-#line 736 "pikchr.y"
2913
+#line 741 "pikchr.y"
29092914
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
2910
-#line 2935 "pikchr.c"
2915
+#line 2940 "pikchr.c"
29112916
break;
29122917
case 94: /* nth ::= LAST */
2913
-#line 737 "pikchr.y"
2918
+#line 742 "pikchr.y"
29142919
{yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
2915
-#line 2940 "pikchr.c"
2920
+#line 2945 "pikchr.c"
29162921
yymsp[0].minor.yy0 = yylhsminor.yy0;
29172922
break;
29182923
case 95: /* nth ::= NTH LB RB */
2919
-#line 738 "pikchr.y"
2924
+#line 743 "pikchr.y"
29202925
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
2921
-#line 2946 "pikchr.c"
2926
+#line 2951 "pikchr.c"
29222927
yymsp[-2].minor.yy0 = yylhsminor.yy0;
29232928
break;
29242929
case 96: /* nth ::= NTH LAST LB RB */
2925
-#line 739 "pikchr.y"
2930
+#line 744 "pikchr.y"
29262931
{yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
2927
-#line 2952 "pikchr.c"
2932
+#line 2957 "pikchr.c"
29282933
yymsp[-3].minor.yy0 = yylhsminor.yy0;
29292934
break;
29302935
case 97: /* nth ::= LAST LB RB */
2931
-#line 740 "pikchr.y"
2936
+#line 745 "pikchr.y"
29322937
{yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
2933
-#line 2958 "pikchr.c"
2938
+#line 2963 "pikchr.c"
29342939
break;
29352940
case 98: /* expr ::= expr PLUS expr */
2936
-#line 742 "pikchr.y"
2941
+#line 747 "pikchr.y"
29372942
{yylhsminor.yy153=yymsp[-2].minor.yy153+yymsp[0].minor.yy153;}
2938
-#line 2963 "pikchr.c"
2943
+#line 2968 "pikchr.c"
29392944
yymsp[-2].minor.yy153 = yylhsminor.yy153;
29402945
break;
29412946
case 99: /* expr ::= expr MINUS expr */
2942
-#line 743 "pikchr.y"
2947
+#line 748 "pikchr.y"
29432948
{yylhsminor.yy153=yymsp[-2].minor.yy153-yymsp[0].minor.yy153;}
2944
-#line 2969 "pikchr.c"
2949
+#line 2974 "pikchr.c"
29452950
yymsp[-2].minor.yy153 = yylhsminor.yy153;
29462951
break;
29472952
case 100: /* expr ::= expr STAR expr */
2948
-#line 744 "pikchr.y"
2953
+#line 749 "pikchr.y"
29492954
{yylhsminor.yy153=yymsp[-2].minor.yy153*yymsp[0].minor.yy153;}
2950
-#line 2975 "pikchr.c"
2955
+#line 2980 "pikchr.c"
29512956
yymsp[-2].minor.yy153 = yylhsminor.yy153;
29522957
break;
29532958
case 101: /* expr ::= expr SLASH expr */
2954
-#line 745 "pikchr.y"
2959
+#line 750 "pikchr.y"
29552960
{
29562961
if( yymsp[0].minor.yy153==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy153 = 0.0; }
29572962
else{ yylhsminor.yy153 = yymsp[-2].minor.yy153/yymsp[0].minor.yy153; }
29582963
}
2959
-#line 2984 "pikchr.c"
2964
+#line 2989 "pikchr.c"
29602965
yymsp[-2].minor.yy153 = yylhsminor.yy153;
29612966
break;
29622967
case 102: /* expr ::= MINUS expr */
2963
-#line 749 "pikchr.y"
2968
+#line 754 "pikchr.y"
29642969
{yymsp[-1].minor.yy153=-yymsp[0].minor.yy153;}
2965
-#line 2990 "pikchr.c"
2970
+#line 2995 "pikchr.c"
29662971
break;
29672972
case 103: /* expr ::= PLUS expr */
2968
-#line 750 "pikchr.y"
2973
+#line 755 "pikchr.y"
29692974
{yymsp[-1].minor.yy153=yymsp[0].minor.yy153;}
2970
-#line 2995 "pikchr.c"
2975
+#line 3000 "pikchr.c"
29712976
break;
29722977
case 104: /* expr ::= LP expr RP */
2973
-#line 751 "pikchr.y"
2978
+#line 756 "pikchr.y"
29742979
{yymsp[-2].minor.yy153=yymsp[-1].minor.yy153;}
2975
-#line 3000 "pikchr.c"
2980
+#line 3005 "pikchr.c"
29762981
break;
29772982
case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
2978
-#line 752 "pikchr.y"
2983
+#line 757 "pikchr.y"
29792984
{yymsp[-2].minor.yy153=pik_get_var(p,&yymsp[-1].minor.yy0);}
2980
-#line 3005 "pikchr.c"
2985
+#line 3010 "pikchr.c"
29812986
break;
29822987
case 106: /* expr ::= NUMBER */
2983
-#line 753 "pikchr.y"
2988
+#line 758 "pikchr.y"
29842989
{yylhsminor.yy153=pik_atof(&yymsp[0].minor.yy0);}
2985
-#line 3010 "pikchr.c"
2990
+#line 3015 "pikchr.c"
29862991
yymsp[0].minor.yy153 = yylhsminor.yy153;
29872992
break;
29882993
case 107: /* expr ::= ID */
2989
-#line 754 "pikchr.y"
2994
+#line 759 "pikchr.y"
29902995
{yylhsminor.yy153=pik_get_var(p,&yymsp[0].minor.yy0);}
2991
-#line 3016 "pikchr.c"
2996
+#line 3021 "pikchr.c"
29922997
yymsp[0].minor.yy153 = yylhsminor.yy153;
29932998
break;
29942999
case 108: /* expr ::= FUNC1 LP expr RP */
2995
-#line 755 "pikchr.y"
3000
+#line 760 "pikchr.y"
29963001
{yylhsminor.yy153 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy153,0.0);}
2997
-#line 3022 "pikchr.c"
3002
+#line 3027 "pikchr.c"
29983003
yymsp[-3].minor.yy153 = yylhsminor.yy153;
29993004
break;
30003005
case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
3001
-#line 756 "pikchr.y"
3006
+#line 761 "pikchr.y"
30023007
{yylhsminor.yy153 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy153,yymsp[-1].minor.yy153);}
3003
-#line 3028 "pikchr.c"
3008
+#line 3033 "pikchr.c"
30043009
yymsp[-5].minor.yy153 = yylhsminor.yy153;
30053010
break;
30063011
case 110: /* expr ::= DIST LP position COMMA position RP */
3007
-#line 757 "pikchr.y"
3012
+#line 762 "pikchr.y"
30083013
{yymsp[-5].minor.yy153 = pik_dist(&yymsp[-3].minor.yy79,&yymsp[-1].minor.yy79);}
3009
-#line 3034 "pikchr.c"
3014
+#line 3039 "pikchr.c"
30103015
break;
30113016
case 111: /* expr ::= place2 DOT_XY X */
3012
-#line 758 "pikchr.y"
3017
+#line 763 "pikchr.y"
30133018
{yylhsminor.yy153 = yymsp[-2].minor.yy79.x;}
3014
-#line 3039 "pikchr.c"
3019
+#line 3044 "pikchr.c"
30153020
yymsp[-2].minor.yy153 = yylhsminor.yy153;
30163021
break;
30173022
case 112: /* expr ::= place2 DOT_XY Y */
3018
-#line 759 "pikchr.y"
3023
+#line 764 "pikchr.y"
30193024
{yylhsminor.yy153 = yymsp[-2].minor.yy79.y;}
3020
-#line 3045 "pikchr.c"
3025
+#line 3050 "pikchr.c"
30213026
yymsp[-2].minor.yy153 = yylhsminor.yy153;
30223027
break;
30233028
case 113: /* expr ::= object DOT_L numproperty */
30243029
case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
30253030
case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
3026
-#line 760 "pikchr.y"
3031
+#line 765 "pikchr.y"
30273032
{yylhsminor.yy153=pik_property_of(yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
3028
-#line 3053 "pikchr.c"
3033
+#line 3058 "pikchr.c"
30293034
yymsp[-2].minor.yy153 = yylhsminor.yy153;
30303035
break;
30313036
default:
30323037
/* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
30333038
/* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
@@ -3126,19 +3131,19 @@
31263131
){
31273132
pik_parserARG_FETCH
31283133
pik_parserCTX_FETCH
31293134
#define TOKEN yyminor
31303135
/************ Begin %syntax_error code ****************************************/
3131
-#line 520 "pikchr.y"
3136
+#line 525 "pikchr.y"
31323137
31333138
if( TOKEN.z && TOKEN.z[0] ){
31343139
pik_error(p, &TOKEN, "syntax error");
31353140
}else{
31363141
pik_error(p, 0, "syntax error");
31373142
}
31383143
UNUSED_PARAMETER(yymajor);
3139
-#line 3164 "pikchr.c"
3144
+#line 3169 "pikchr.c"
31403145
/************ End %syntax_error code ******************************************/
31413146
pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
31423147
pik_parserCTX_STORE
31433148
}
31443149
@@ -3367,11 +3372,11 @@
33673372
#else
33683373
(void)iToken;
33693374
return 0;
33703375
#endif
33713376
}
3372
-#line 765 "pikchr.y"
3377
+#line 770 "pikchr.y"
33733378
33743379
33753380
33763381
/* Chart of the 148 official CSS color names with their
33773382
** corresponding RGB values thru Color Module Level 4:
@@ -3811,11 +3816,11 @@
38113816
static PPoint circleChop(Pik *p, PObj *pObj, PPoint *pPt){
38123817
PPoint chop;
38133818
PNum dx = pPt->x - pObj->ptAt.x;
38143819
PNum dy = pPt->y - pObj->ptAt.y;
38153820
PNum dist = hypot(dx,dy);
3816
- if( dist<pObj->rad ) return pObj->ptAt;
3821
+ if( dist<pObj->rad || dist<=0 ) return pObj->ptAt;
38173822
chop.x = pObj->ptAt.x + dx*pObj->rad/dist;
38183823
chop.y = pObj->ptAt.y + dy*pObj->rad/dist;
38193824
UNUSED_PARAMETER(p);
38203825
return chop;
38213826
}
@@ -4510,11 +4515,11 @@
45104515
if( z==0 ){
45114516
pik_error(p, 0, 0);
45124517
return;
45134518
}
45144519
p->zOut = z;
4515
- p->nOutAlloc = n;
4520
+ p->nOutAlloc = nNew;
45164521
}
45174522
memcpy(p->zOut+p->nOut, zText, n);
45184523
p->nOut += n;
45194524
p->zOut[p->nOut] = 0;
45204525
}
@@ -4636,27 +4641,27 @@
46364641
** on the value.
46374642
*/
46384643
static void pik_append_x(Pik *p, const char *z1, PNum v, const char *z2){
46394644
char buf[200];
46404645
v -= p->bbox.sw.x;
4641
- snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, (int)(p->rScale*v), z2);
4646
+ snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, pik_round(p->rScale*v), z2);
46424647
buf[sizeof(buf)-1] = 0;
46434648
pik_append(p, buf, -1);
46444649
}
46454650
static void pik_append_y(Pik *p, const char *z1, PNum v, const char *z2){
46464651
char buf[200];
46474652
v = p->bbox.ne.y - v;
4648
- snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, (int)(p->rScale*v), z2);
4653
+ snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, pik_round(p->rScale*v), z2);
46494654
buf[sizeof(buf)-1] = 0;
46504655
pik_append(p, buf, -1);
46514656
}
46524657
static void pik_append_xy(Pik *p, const char *z1, PNum x, PNum y){
46534658
char buf[200];
46544659
x = x - p->bbox.sw.x;
46554660
y = p->bbox.ne.y - y;
46564661
snprintf(buf, sizeof(buf)-1, "%s%d,%d", z1,
4657
- (int)(p->rScale*x), (int)(p->rScale*y));
4662
+ pik_round(p->rScale*x), pik_round(p->rScale*y));
46584663
buf[sizeof(buf)-1] = 0;
46594664
pik_append(p, buf, -1);
46604665
}
46614666
static void pik_append_dis(Pik *p, const char *z1, PNum v, const char *z2){
46624667
char buf[200];
@@ -4672,11 +4677,11 @@
46724677
** foreground color if false. The distinction only matters for color
46734678
** inversions in PIKCHR_DARK_MODE.
46744679
*/
46754680
static void pik_append_clr(Pik *p,const char *z1,PNum v,const char *z2,int bg){
46764681
char buf[200];
4677
- int x = (int)v;
4682
+ int x = pik_round(v);
46784683
int r, g, b;
46794684
if( x==0 && p->fgcolor>0 && !bg ){
46804685
x = p->fgcolor;
46814686
}else if( bg && x>=0xffffff && p->bgcolor>0 ){
46824687
x = p->bgcolor;
@@ -4698,12 +4703,12 @@
46984703
static void pik_append_arc(Pik *p, PNum r1, PNum r2, PNum x, PNum y){
46994704
char buf[200];
47004705
x = x - p->bbox.sw.x;
47014706
y = p->bbox.ne.y - y;
47024707
snprintf(buf, sizeof(buf)-1, "A%d %d 0 0 0 %d %d",
4703
- (int)(p->rScale*r1), (int)(p->rScale*r2),
4704
- (int)(p->rScale*x), (int)(p->rScale*y));
4708
+ pik_round(p->rScale*r1), pik_round(p->rScale*r2),
4709
+ pik_round(p->rScale*x), pik_round(p->rScale*y));
47054710
buf[sizeof(buf)-1] = 0;
47064711
pik_append(p, buf, -1);
47074712
}
47084713
47094714
/* Append a style="..." text. But, leave the quote unterminated, in case
@@ -5241,10 +5246,21 @@
52415246
/* Return true if a bounding box is empty.
52425247
*/
52435248
static int pik_bbox_isempty(PBox *p){
52445249
return p->sw.x>p->ne.x;
52455250
}
5251
+
5252
+/* Return true if point pPt is contained within the bounding box pBox
5253
+*/
5254
+static int pik_bbox_contains_point(PBox *pBox, PPoint *pPt){
5255
+ if( pik_bbox_isempty(pBox) ) return 0;
5256
+ if( pPt->x < pBox->sw.x ) return 0;
5257
+ if( pPt->x > pBox->ne.x ) return 0;
5258
+ if( pPt->y < pBox->sw.y ) return 0;
5259
+ if( pPt->y > pBox->ne.y ) return 0;
5260
+ return 1;
5261
+}
52465262
52475263
/* Initialize a bounding box to an empty container
52485264
*/
52495265
static void pik_bbox_init(PBox *p){
52505266
p->sw.x = 1.0;
@@ -5391,11 +5407,11 @@
53915407
}
53925408
}
53935409
p->aTPath[0] = pNew->ptAt;
53945410
pNew->with = pNew->ptAt;
53955411
pNew->outDir = pNew->inDir = p->eDir;
5396
- pNew->iLayer = (int)pik_value(p, "layer", 5, &miss);
5412
+ pNew->iLayer = pik_value_int(p, "layer", 5, &miss);
53975413
if( miss ) pNew->iLayer = 1000;
53985414
if( pNew->iLayer<0 ) pNew->iLayer = 0;
53995415
if( pSublist ){
54005416
pNew->type = &sublistClass;
54015417
pNew->pSublist = pSublist;
@@ -5837,10 +5853,38 @@
58375853
p->mTPath |= 1;
58385854
break;
58395855
}
58405856
pObj->outDir = pDir->eCode;
58415857
}
5858
+
5859
+/* If the last referenced object is centered at point pPt then return
5860
+** a pointer to that object. If there is no prior object reference,
5861
+** or if the points are not the same, return NULL.
5862
+**
5863
+** This is a side-channel hack used to find the objects at which a
5864
+** line begins and ends. For example, in
5865
+**
5866
+** arrow from OBJ1 to OBJ2 chop
5867
+**
5868
+** The arrow object is normally just handed the coordinates of the
5869
+** centers for OBJ1 and OBJ2. But we also want to know the specific
5870
+** object named in case there are multiple objects centered at the
5871
+** same point.
5872
+**
5873
+** See forum post 1d46e3a0bc
5874
+*/
5875
+static PObj *pik_last_ref_object(Pik *p, PPoint *pPt){
5876
+ PObj *pRes = 0;
5877
+ if( p->lastRef==0 ) return 0;
5878
+ if( p->lastRef->ptAt.x==pPt->x
5879
+ && p->lastRef->ptAt.y==pPt->y
5880
+ ){
5881
+ pRes = p->lastRef;
5882
+ }
5883
+ p->lastRef = 0;
5884
+ return pRes;
5885
+}
58425886
58435887
/* Set the "from" of an object
58445888
*/
58455889
static void pik_set_from(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
58465890
if( !pObj->type->isLine ){
@@ -5865,10 +5909,11 @@
58655909
}
58665910
}
58675911
p->aTPath[0] = *pPt;
58685912
p->mTPath = 3;
58695913
pObj->mProp |= A_FROM;
5914
+ pObj->pFrom = pik_last_ref_object(p, pPt);
58705915
}
58715916
58725917
/* Set the "to" of an object
58735918
*/
58745919
static void pik_add_to(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
@@ -5885,10 +5930,11 @@
58855930
if( n==0 || p->mTPath==3 || p->thenFlag ){
58865931
n = pik_next_rpath(p, pTk);
58875932
}
58885933
p->aTPath[n] = *pPt;
58895934
p->mTPath = 3;
5935
+ pObj->pTo = pik_last_ref_object(p, pPt);
58905936
}
58915937
58925938
static void pik_close_path(Pik *p, PToken *pErr){
58935939
PObj *pObj = p->cur;
58945940
if( p->nTPath<3 ){
@@ -6220,10 +6266,20 @@
62206266
break;
62216267
default: pVar->val = val; break;
62226268
}
62236269
p->bLayoutVars = 0; /* Clear the layout setting cache */
62246270
}
6271
+
6272
+/*
6273
+** Round a PNum into the nearest integer
6274
+*/
6275
+static int pik_round(PNum v){
6276
+ if( isnan(v) ) return 0;
6277
+ if( v < -2147483647 ) return -2147483648;
6278
+ if( v >= 2147483647 ) return 2147483647;
6279
+ return (int)v;
6280
+}
62256281
62266282
/*
62276283
** Search for the variable named z[0..n-1] in:
62286284
**
62296285
** * Application defined variables
@@ -6258,10 +6314,13 @@
62586314
last = mid-1;
62596315
}
62606316
}
62616317
if( pMiss ) *pMiss = 1;
62626318
return 0.0;
6319
+}
6320
+static int pik_value_int(Pik *p, const char *z, int n, int *pMiss){
6321
+ return pik_round(pik_value(p,z,n,pMiss));
62636322
}
62646323
62656324
/*
62666325
** Look up a color-name. Unlike other names in this program, the
62676326
** color-names are not case sensitive. So "DarkBlue" and "darkblue"
@@ -6413,10 +6472,11 @@
64136472
}
64146473
/* First look explicitly tagged objects */
64156474
for(i=pList->n-1; i>=0; i--){
64166475
PObj *pObj = pList->a[i];
64176476
if( pObj->zName && pik_token_eq(pName,pObj->zName)==0 ){
6477
+ p->lastRef = pObj;
64186478
return pObj;
64196479
}
64206480
}
64216481
/* If not found, do a second pass looking for any object containing
64226482
** text which exactly matches pName */
@@ -6423,10 +6483,11 @@
64236483
for(i=pList->n-1; i>=0; i--){
64246484
PObj *pObj = pList->a[i];
64256485
for(j=0; j<pObj->nTxt; j++){
64266486
if( pObj->aTxt[j].n==pName->n+2
64276487
&& memcmp(pObj->aTxt[j].z+1,pName->z,pName->n)==0 ){
6488
+ p->lastRef = pObj;
64286489
return pObj;
64296490
}
64306491
}
64316492
}
64326493
pik_error(p, pName, "no such object");
@@ -6557,26 +6618,28 @@
65576618
65586619
/* Return the value of a property of an object.
65596620
*/
65606621
static PNum pik_property_of(PObj *pObj, PToken *pProp){
65616622
PNum v = 0.0;
6562
- switch( pProp->eType ){
6563
- case T_HEIGHT: v = pObj->h; break;
6564
- case T_WIDTH: v = pObj->w; break;
6565
- case T_RADIUS: v = pObj->rad; break;
6566
- case T_DIAMETER: v = pObj->rad*2.0; break;
6567
- case T_THICKNESS: v = pObj->sw; break;
6568
- case T_DASHED: v = pObj->dashed; break;
6569
- case T_DOTTED: v = pObj->dotted; break;
6570
- case T_FILL: v = pObj->fill; break;
6571
- case T_COLOR: v = pObj->color; break;
6572
- case T_X: v = pObj->ptAt.x; break;
6573
- case T_Y: v = pObj->ptAt.y; break;
6574
- case T_TOP: v = pObj->bbox.ne.y; break;
6575
- case T_BOTTOM: v = pObj->bbox.sw.y; break;
6576
- case T_LEFT: v = pObj->bbox.sw.x; break;
6577
- case T_RIGHT: v = pObj->bbox.ne.x; break;
6623
+ if( pObj ){
6624
+ switch( pProp->eType ){
6625
+ case T_HEIGHT: v = pObj->h; break;
6626
+ case T_WIDTH: v = pObj->w; break;
6627
+ case T_RADIUS: v = pObj->rad; break;
6628
+ case T_DIAMETER: v = pObj->rad*2.0; break;
6629
+ case T_THICKNESS: v = pObj->sw; break;
6630
+ case T_DASHED: v = pObj->dashed; break;
6631
+ case T_DOTTED: v = pObj->dotted; break;
6632
+ case T_FILL: v = pObj->fill; break;
6633
+ case T_COLOR: v = pObj->color; break;
6634
+ case T_X: v = pObj->ptAt.x; break;
6635
+ case T_Y: v = pObj->ptAt.y; break;
6636
+ case T_TOP: v = pObj->bbox.ne.y; break;
6637
+ case T_BOTTOM: v = pObj->bbox.sw.y; break;
6638
+ case T_LEFT: v = pObj->bbox.sw.x; break;
6639
+ case T_RIGHT: v = pObj->bbox.ne.x; break;
6640
+ }
65786641
}
65796642
return v;
65806643
}
65816644
65826645
/* Compute one of the built-in functions
@@ -6618,40 +6681,49 @@
66186681
}
66196682
return;
66206683
}
66216684
66226685
/*
6623
-** Search for object located at *pCenter that has an xChop method.
6686
+** Search for object located at *pCenter that has an xChop method and
6687
+** that does not enclose point pOther.
6688
+**
66246689
** Return a pointer to the object, or NULL if not found.
66256690
*/
6626
-static PObj *pik_find_chopper(PList *pList, PPoint *pCenter){
6691
+static PObj *pik_find_chopper(PList *pList, PPoint *pCenter, PPoint *pOther){
66276692
int i;
66286693
if( pList==0 ) return 0;
66296694
for(i=pList->n-1; i>=0; i--){
66306695
PObj *pObj = pList->a[i];
66316696
if( pObj->type->xChop!=0
66326697
&& pObj->ptAt.x==pCenter->x
66336698
&& pObj->ptAt.y==pCenter->y
6699
+ && !pik_bbox_contains_point(&pObj->bbox, pOther)
66346700
){
66356701
return pObj;
66366702
}else if( pObj->pSublist ){
6637
- pObj = pik_find_chopper(pObj->pSublist,pCenter);
6703
+ pObj = pik_find_chopper(pObj->pSublist,pCenter,pOther);
66386704
if( pObj ) return pObj;
66396705
}
66406706
}
66416707
return 0;
66426708
}
66436709
66446710
/*
66456711
** There is a line traveling from pFrom to pTo.
66466712
**
6647
-** If point pTo is the exact enter of a choppable object,
6648
-** then adjust pTo by the appropriate amount in the direction
6649
-** of pFrom.
6713
+** If pObj is not null and is a choppable object, then chop at
6714
+** the boundary of pObj - where the line crosses the boundary
6715
+** of pObj.
6716
+**
6717
+** If pObj is NULL or has no xChop method, then search for some
6718
+** other object centered at pTo that is choppable and use it
6719
+** instead.
66506720
*/
6651
-static void pik_autochop(Pik *p, PPoint *pFrom, PPoint *pTo){
6652
- PObj *pObj = pik_find_chopper(p->list, pTo);
6721
+static void pik_autochop(Pik *p, PPoint *pFrom, PPoint *pTo, PObj *pObj){
6722
+ if( pObj==0 || pObj->type->xChop==0 ){
6723
+ pObj = pik_find_chopper(p->list, pTo, pFrom);
6724
+ }
66536725
if( pObj ){
66546726
*pTo = pObj->type->xChop(p, pObj, pFrom);
66556727
}
66566728
}
66576729
@@ -6746,12 +6818,12 @@
67466818
** If the line goes to the center of an object with an
67476819
** xChop method, then use the xChop method to trim the line.
67486820
*/
67496821
if( pObj->bChop && pObj->nPath>=2 ){
67506822
int n = pObj->nPath;
6751
- pik_autochop(p, &pObj->aPath[n-2], &pObj->aPath[n-1]);
6752
- pik_autochop(p, &pObj->aPath[1], &pObj->aPath[0]);
6823
+ pik_autochop(p, &pObj->aPath[n-2], &pObj->aPath[n-1], pObj->pTo);
6824
+ pik_autochop(p, &pObj->aPath[1], &pObj->aPath[0], pObj->pFrom);
67536825
}
67546826
67556827
pObj->ptEnter = pObj->aPath[0];
67566828
pObj->ptExit = pObj->aPath[pObj->nPath-1];
67576829
@@ -6842,11 +6914,11 @@
68426914
int i;
68436915
int iNextLayer = 0;
68446916
int iThisLayer;
68456917
int bMoreToDo;
68466918
int miss = 0;
6847
- int mDebug = (int)pik_value(p, "debug", 5, 0);
6919
+ int mDebug = pik_value_int(p, "debug", 5, 0);
68486920
PNum colorLabel;
68496921
do{
68506922
bMoreToDo = 0;
68516923
iThisLayer = iNextLayer;
68526924
iNextLayer = 0x7fffffff;
@@ -6960,24 +7032,24 @@
69607032
if( thickness<=0.01 ) thickness = 0.01;
69617033
margin = pik_value(p,"margin",6,0);
69627034
margin += thickness;
69637035
wArrow = p->wArrow*thickness;
69647036
miss = 0;
6965
- p->fgcolor = (int)pik_value(p,"fgcolor",7,&miss);
7037
+ p->fgcolor = pik_value_int(p,"fgcolor",7,&miss);
69667038
if( miss ){
69677039
PToken t;
69687040
t.z = "fgcolor";
69697041
t.n = 7;
6970
- p->fgcolor = (int)pik_lookup_color(0, &t);
7042
+ p->fgcolor = pik_round(pik_lookup_color(0, &t));
69717043
}
69727044
miss = 0;
6973
- p->bgcolor = (int)pik_value(p,"bgcolor",7,&miss);
7045
+ p->bgcolor = pik_value_int(p,"bgcolor",7,&miss);
69747046
if( miss ){
69757047
PToken t;
69767048
t.z = "bgcolor";
69777049
t.n = 7;
6978
- p->bgcolor = (int)pik_lookup_color(0, &t);
7050
+ p->bgcolor = pik_round(pik_lookup_color(0, &t));
69797051
}
69807052
69817053
/* Compute a bounding box over all objects so that we can know
69827054
** how big to declare the SVG canvas */
69837055
pik_bbox_init(&p->bbox);
@@ -6997,18 +7069,18 @@
69977069
pik_append(p, p->zClass, -1);
69987070
pik_append(p, "\"", 1);
69997071
}
70007072
w = p->bbox.ne.x - p->bbox.sw.x;
70017073
h = p->bbox.ne.y - p->bbox.sw.y;
7002
- p->wSVG = (int)(p->rScale*w);
7003
- p->hSVG = (int)(p->rScale*h);
7074
+ p->wSVG = pik_round(p->rScale*w);
7075
+ p->hSVG = pik_round(p->rScale*h);
70047076
pikScale = pik_value(p,"scale",5,0);
70057077
if( pikScale>=0.001 && pikScale<=1000.0
70067078
&& (pikScale<0.99 || pikScale>1.01)
70077079
){
7008
- p->wSVG = (int)(p->wSVG*pikScale);
7009
- p->hSVG = (int)(p->hSVG*pikScale);
7080
+ p->wSVG = pik_round(p->wSVG*pikScale);
7081
+ p->hSVG = pik_round(p->hSVG*pikScale);
70107082
pik_append_num(p, " width=\"", p->wSVG);
70117083
pik_append_num(p, "\" height=\"", p->hSVG);
70127084
pik_append(p, "\"", 1);
70137085
}
70147086
pik_append_dis(p, " viewBox=\"0 0 ",w,"");
@@ -7749,15 +7821,16 @@
77497821
#if defined(PIKCHR_FUZZ)
77507822
#include <stdint.h>
77517823
int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
77527824
int w,h;
77537825
char *zIn, *zOut;
7826
+ unsigned int mFlags = nByte & 3;
77547827
zIn = malloc( nByte + 1 );
77557828
if( zIn==0 ) return 0;
77567829
memcpy(zIn, aData, nByte);
77577830
zIn[nByte] = 0;
7758
- zOut = pikchr(zIn, "pikchr", 0, &w, &h);
7831
+ zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
77597832
free(zIn);
77607833
free(zOut);
77617834
return 0;
77627835
}
77637836
#endif /* PIKCHR_FUZZ */
@@ -7988,19 +8061,26 @@
79888061
Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(w));
79898062
Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(h));
79908063
Tcl_SetObjResult(interp, pRes);
79918064
return TCL_OK;
79928065
}
8066
+
8067
+#ifndef PACKAGE_NAME
8068
+# define PACKAGE_NAME "pikchr"
8069
+#endif
8070
+#ifndef PACKAGE_VERSION
8071
+# define PACKAGE_VERSION "1.0"
8072
+#endif
79938073
79948074
/* Invoke this routine to register the "pikchr" command with the interpreter
79958075
** given in the argument */
79968076
int Pikchr_Init(Tcl_Interp *interp){
79978077
Tcl_CreateObjCommand(interp, "pikchr", pik_tcl_command, 0, 0);
7998
- Tcl_PkgProvide (interp, PACKAGE_NAME, PACKAGE_VERSION);
8078
+ Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION);
79998079
return TCL_OK;
80008080
}
80018081
80028082
80038083
#endif /* PIKCHR_TCL */
80048084
80058085
8006
-#line 8031 "pikchr.c"
8086
+#line 8111 "pikchr.c"
80078087
--- src/pikchr.c
+++ src/pikchr.c
@@ -317,10 +317,11 @@
317 PToken aTxt[5]; /* Text with .eCode holding TP flags */
318 int iLayer; /* Rendering order */
319 int inDir, outDir; /* Entry and exit directions */
320 int nPath; /* Number of path points */
321 PPoint *aPath; /* Array of path points */
 
322 PBox bbox; /* Bounding box */
323 };
324
325 /* A list of graphics objects */
326 struct PList {
@@ -347,10 +348,11 @@
347 unsigned int nOut; /* Bytes written to zOut[] so far */
348 unsigned int nOutAlloc; /* Space allocated to zOut[] */
349 unsigned char eDir; /* Current direction */
350 unsigned int mFlags; /* Flags passed to pikchr() */
351 PObj *cur; /* Object under construction */
 
352 PList *list; /* Object list under construction */
353 PMacro *pMacros; /* List of all defined macros */
354 PVar *pVar; /* Application-defined variables */
355 PBox bbox; /* Bounding box around all statements */
356 /* Cache of layout values. <=0.0 for unknown... */
@@ -426,12 +428,14 @@
426 static void pik_render(Pik*,PList*);
427 static PList *pik_elist_append(Pik*,PList*,PObj*);
428 static PObj *pik_elem_new(Pik*,PToken*,PToken*,PList*);
429 static void pik_set_direction(Pik*,int);
430 static void pik_elem_setname(Pik*,PObj*,PToken*);
 
431 static void pik_set_var(Pik*,PToken*,PNum,PToken*);
432 static PNum pik_value(Pik*,const char*,int,int*);
 
433 static PNum pik_lookup_color(Pik*,PToken*);
434 static PNum pik_get_var(Pik*,PToken*);
435 static PNum pik_atof(PToken*);
436 static void pik_after_adding_attributes(Pik*,PObj*);
437 static void pik_elem_move(PObj*,PNum dx, PNum dy);
@@ -450,10 +454,11 @@
450 static short int pik_nth_value(Pik*,PToken*);
451 static PObj *pik_find_nth(Pik*,PObj*,PToken*);
452 static PObj *pik_find_byname(Pik*,PObj*,PToken*);
453 static PPoint pik_place_of_elem(Pik*,PObj*,PToken*);
454 static int pik_bbox_isempty(PBox*);
 
455 static void pik_bbox_init(PBox*);
456 static void pik_bbox_addbox(PBox*,PBox*);
457 static void pik_bbox_add_xy(PBox*,PNum,PNum);
458 static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry);
459 static void pik_add_txt(Pik*,PToken*,int);
@@ -474,11 +479,11 @@
474 static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*);
475 static PNum pik_dist(PPoint*,PPoint*);
476 static void pik_add_macro(Pik*,PToken *pId,PToken *pCode);
477
478
479 #line 505 "pikchr.c"
480 /**************** End of %include directives **********************************/
481 /* These constants specify the various numeric values for terminal symbols.
482 ***************** Begin token definitions *************************************/
483 #ifndef T_ID
484 #define T_ID 1
@@ -1703,22 +1708,22 @@
1703 ** inside the C code.
1704 */
1705 /********* Begin destructor definitions ***************************************/
1706 case 99: /* statement_list */
1707 {
1708 #line 494 "pikchr.y"
1709 pik_elist_free(p,(yypminor->yy227));
1710 #line 1735 "pikchr.c"
1711 }
1712 break;
1713 case 100: /* statement */
1714 case 101: /* unnamed_statement */
1715 case 102: /* basetype */
1716 {
1717 #line 496 "pikchr.y"
1718 pik_elem_free(p,(yypminor->yy36));
1719 #line 1744 "pikchr.c"
1720 }
1721 break;
1722 /********* End destructor definitions *****************************************/
1723 default: break; /* If no destructor action specified: do nothing */
1724 }
@@ -1932,14 +1937,14 @@
1932 #endif
1933 while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
1934 /* Here code is inserted which will execute if the parser
1935 ** stack every overflows */
1936 /******** Begin %stack_overflow code ******************************************/
1937 #line 528 "pikchr.y"
1938
1939 pik_error(p, 0, "parser stack overflow");
1940 #line 1965 "pikchr.c"
1941 /******** End %stack_overflow code ********************************************/
1942 pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
1943 pik_parserCTX_STORE
1944 }
1945
@@ -2415,619 +2420,619 @@
2415 ** break;
2416 */
2417 /********** Begin reduce actions **********************************************/
2418 YYMINORTYPE yylhsminor;
2419 case 0: /* document ::= statement_list */
2420 #line 532 "pikchr.y"
2421 {pik_render(p,yymsp[0].minor.yy227);}
2422 #line 2447 "pikchr.c"
2423 break;
2424 case 1: /* statement_list ::= statement */
2425 #line 535 "pikchr.y"
2426 { yylhsminor.yy227 = pik_elist_append(p,0,yymsp[0].minor.yy36); }
2427 #line 2452 "pikchr.c"
2428 yymsp[0].minor.yy227 = yylhsminor.yy227;
2429 break;
2430 case 2: /* statement_list ::= statement_list EOL statement */
2431 #line 537 "pikchr.y"
2432 { yylhsminor.yy227 = pik_elist_append(p,yymsp[-2].minor.yy227,yymsp[0].minor.yy36); }
2433 #line 2458 "pikchr.c"
2434 yymsp[-2].minor.yy227 = yylhsminor.yy227;
2435 break;
2436 case 3: /* statement ::= */
2437 #line 540 "pikchr.y"
2438 { yymsp[1].minor.yy36 = 0; }
2439 #line 2464 "pikchr.c"
2440 break;
2441 case 4: /* statement ::= direction */
2442 #line 541 "pikchr.y"
2443 { pik_set_direction(p,yymsp[0].minor.yy0.eCode); yylhsminor.yy36=0; }
2444 #line 2469 "pikchr.c"
2445 yymsp[0].minor.yy36 = yylhsminor.yy36;
2446 break;
2447 case 5: /* statement ::= lvalue ASSIGN rvalue */
2448 #line 542 "pikchr.y"
2449 {pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy153,&yymsp[-1].minor.yy0); yylhsminor.yy36=0;}
2450 #line 2475 "pikchr.c"
2451 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2452 break;
2453 case 6: /* statement ::= PLACENAME COLON unnamed_statement */
2454 #line 544 "pikchr.y"
2455 { yylhsminor.yy36 = yymsp[0].minor.yy36; pik_elem_setname(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0); }
2456 #line 2481 "pikchr.c"
2457 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2458 break;
2459 case 7: /* statement ::= PLACENAME COLON position */
2460 #line 546 "pikchr.y"
2461 { yylhsminor.yy36 = pik_elem_new(p,0,0,0);
2462 if(yylhsminor.yy36){ yylhsminor.yy36->ptAt = yymsp[0].minor.yy79; pik_elem_setname(p,yylhsminor.yy36,&yymsp[-2].minor.yy0); }}
2463 #line 2488 "pikchr.c"
2464 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2465 break;
2466 case 8: /* statement ::= unnamed_statement */
2467 #line 548 "pikchr.y"
2468 {yylhsminor.yy36 = yymsp[0].minor.yy36;}
2469 #line 2494 "pikchr.c"
2470 yymsp[0].minor.yy36 = yylhsminor.yy36;
2471 break;
2472 case 9: /* statement ::= print prlist */
2473 #line 549 "pikchr.y"
2474 {pik_append(p,"<br>\n",5); yymsp[-1].minor.yy36=0;}
2475 #line 2500 "pikchr.c"
2476 break;
2477 case 10: /* statement ::= ASSERT LP expr EQ expr RP */
2478 #line 554 "pikchr.y"
2479 {yymsp[-5].minor.yy36=pik_assert(p,yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy153);}
2480 #line 2505 "pikchr.c"
2481 break;
2482 case 11: /* statement ::= ASSERT LP position EQ position RP */
2483 #line 556 "pikchr.y"
2484 {yymsp[-5].minor.yy36=pik_position_assert(p,&yymsp[-3].minor.yy79,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy79);}
2485 #line 2510 "pikchr.c"
2486 break;
2487 case 12: /* statement ::= DEFINE ID CODEBLOCK */
2488 #line 557 "pikchr.y"
2489 {yymsp[-2].minor.yy36=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
2490 #line 2515 "pikchr.c"
2491 break;
2492 case 13: /* rvalue ::= PLACENAME */
2493 #line 568 "pikchr.y"
2494 {yylhsminor.yy153 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
2495 #line 2520 "pikchr.c"
2496 yymsp[0].minor.yy153 = yylhsminor.yy153;
2497 break;
2498 case 14: /* pritem ::= FILL */
2499 case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
2500 case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
2501 #line 573 "pikchr.y"
2502 {pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
2503 #line 2528 "pikchr.c"
2504 break;
2505 case 17: /* pritem ::= rvalue */
2506 #line 576 "pikchr.y"
2507 {pik_append_num(p,"",yymsp[0].minor.yy153);}
2508 #line 2533 "pikchr.c"
2509 break;
2510 case 18: /* pritem ::= STRING */
2511 #line 577 "pikchr.y"
2512 {pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
2513 #line 2538 "pikchr.c"
2514 break;
2515 case 19: /* prsep ::= COMMA */
2516 #line 578 "pikchr.y"
2517 {pik_append(p, " ", 1);}
2518 #line 2543 "pikchr.c"
2519 break;
2520 case 20: /* unnamed_statement ::= basetype attribute_list */
2521 #line 581 "pikchr.y"
2522 {yylhsminor.yy36 = yymsp[-1].minor.yy36; pik_after_adding_attributes(p,yylhsminor.yy36);}
2523 #line 2548 "pikchr.c"
2524 yymsp[-1].minor.yy36 = yylhsminor.yy36;
2525 break;
2526 case 21: /* basetype ::= CLASSNAME */
2527 #line 583 "pikchr.y"
2528 {yylhsminor.yy36 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
2529 #line 2554 "pikchr.c"
2530 yymsp[0].minor.yy36 = yylhsminor.yy36;
2531 break;
2532 case 22: /* basetype ::= STRING textposition */
2533 #line 585 "pikchr.y"
2534 {yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy164; yylhsminor.yy36 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
2535 #line 2560 "pikchr.c"
2536 yymsp[-1].minor.yy36 = yylhsminor.yy36;
2537 break;
2538 case 23: /* basetype ::= LB savelist statement_list RB */
2539 #line 587 "pikchr.y"
2540 { p->list = yymsp[-2].minor.yy227; yymsp[-3].minor.yy36 = pik_elem_new(p,0,0,yymsp[-1].minor.yy227); if(yymsp[-3].minor.yy36) yymsp[-3].minor.yy36->errTok = yymsp[0].minor.yy0; }
2541 #line 2566 "pikchr.c"
2542 break;
2543 case 24: /* savelist ::= */
2544 #line 592 "pikchr.y"
2545 {yymsp[1].minor.yy227 = p->list; p->list = 0;}
2546 #line 2571 "pikchr.c"
2547 break;
2548 case 25: /* relexpr ::= expr */
2549 #line 599 "pikchr.y"
2550 {yylhsminor.yy10.rAbs = yymsp[0].minor.yy153; yylhsminor.yy10.rRel = 0;}
2551 #line 2576 "pikchr.c"
2552 yymsp[0].minor.yy10 = yylhsminor.yy10;
2553 break;
2554 case 26: /* relexpr ::= expr PERCENT */
2555 #line 600 "pikchr.y"
2556 {yylhsminor.yy10.rAbs = 0; yylhsminor.yy10.rRel = yymsp[-1].minor.yy153/100;}
2557 #line 2582 "pikchr.c"
2558 yymsp[-1].minor.yy10 = yylhsminor.yy10;
2559 break;
2560 case 27: /* optrelexpr ::= */
2561 #line 602 "pikchr.y"
2562 {yymsp[1].minor.yy10.rAbs = 0; yymsp[1].minor.yy10.rRel = 1.0;}
2563 #line 2588 "pikchr.c"
2564 break;
2565 case 28: /* attribute_list ::= relexpr alist */
2566 #line 604 "pikchr.y"
2567 {pik_add_direction(p,0,&yymsp[-1].minor.yy10);}
2568 #line 2593 "pikchr.c"
2569 break;
2570 case 29: /* attribute ::= numproperty relexpr */
2571 #line 608 "pikchr.y"
2572 { pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10); }
2573 #line 2598 "pikchr.c"
2574 break;
2575 case 30: /* attribute ::= dashproperty expr */
2576 #line 609 "pikchr.y"
2577 { pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy153); }
2578 #line 2603 "pikchr.c"
2579 break;
2580 case 31: /* attribute ::= dashproperty */
2581 #line 610 "pikchr.y"
2582 { pik_set_dashed(p,&yymsp[0].minor.yy0,0); }
2583 #line 2608 "pikchr.c"
2584 break;
2585 case 32: /* attribute ::= colorproperty rvalue */
2586 #line 611 "pikchr.y"
2587 { pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153); }
2588 #line 2613 "pikchr.c"
2589 break;
2590 case 33: /* attribute ::= go direction optrelexpr */
2591 #line 612 "pikchr.y"
2592 { pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10);}
2593 #line 2618 "pikchr.c"
2594 break;
2595 case 34: /* attribute ::= go direction even position */
2596 #line 613 "pikchr.y"
2597 {pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79);}
2598 #line 2623 "pikchr.c"
2599 break;
2600 case 35: /* attribute ::= CLOSE */
2601 #line 614 "pikchr.y"
2602 { pik_close_path(p,&yymsp[0].minor.yy0); }
2603 #line 2628 "pikchr.c"
2604 break;
2605 case 36: /* attribute ::= CHOP */
2606 #line 615 "pikchr.y"
2607 { p->cur->bChop = 1; }
2608 #line 2633 "pikchr.c"
2609 break;
2610 case 37: /* attribute ::= FROM position */
2611 #line 616 "pikchr.y"
2612 { pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
2613 #line 2638 "pikchr.c"
2614 break;
2615 case 38: /* attribute ::= TO position */
2616 #line 617 "pikchr.y"
2617 { pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
2618 #line 2643 "pikchr.c"
2619 break;
2620 case 39: /* attribute ::= THEN */
2621 #line 618 "pikchr.y"
2622 { pik_then(p, &yymsp[0].minor.yy0, p->cur); }
2623 #line 2648 "pikchr.c"
2624 break;
2625 case 40: /* attribute ::= THEN optrelexpr HEADING expr */
2626 case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
2627 #line 620 "pikchr.y"
2628 {pik_move_hdg(p,&yymsp[-2].minor.yy10,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153,0,&yymsp[-3].minor.yy0);}
2629 #line 2654 "pikchr.c"
2630 break;
2631 case 41: /* attribute ::= THEN optrelexpr EDGEPT */
2632 case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
2633 #line 621 "pikchr.y"
2634 {pik_move_hdg(p,&yymsp[-1].minor.yy10,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
2635 #line 2660 "pikchr.c"
2636 break;
2637 case 44: /* attribute ::= AT position */
2638 #line 626 "pikchr.y"
2639 { pik_set_at(p,0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
2640 #line 2665 "pikchr.c"
2641 break;
2642 case 45: /* attribute ::= SAME */
2643 #line 628 "pikchr.y"
2644 {pik_same(p,0,&yymsp[0].minor.yy0);}
2645 #line 2670 "pikchr.c"
2646 break;
2647 case 46: /* attribute ::= SAME AS object */
2648 #line 629 "pikchr.y"
2649 {pik_same(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2650 #line 2675 "pikchr.c"
2651 break;
2652 case 47: /* attribute ::= STRING textposition */
2653 #line 630 "pikchr.y"
2654 {pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy164);}
2655 #line 2680 "pikchr.c"
2656 break;
2657 case 48: /* attribute ::= FIT */
2658 #line 631 "pikchr.y"
2659 {pik_size_to_fit(p,&yymsp[0].minor.yy0,3); }
2660 #line 2685 "pikchr.c"
2661 break;
2662 case 49: /* attribute ::= BEHIND object */
2663 #line 632 "pikchr.y"
2664 {pik_behind(p,yymsp[0].minor.yy36);}
2665 #line 2690 "pikchr.c"
2666 break;
2667 case 50: /* withclause ::= DOT_E edge AT position */
2668 case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
2669 #line 640 "pikchr.y"
2670 { pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
2671 #line 2696 "pikchr.c"
2672 break;
2673 case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
2674 #line 644 "pikchr.y"
2675 {yylhsminor.yy0 = yymsp[0].minor.yy0;}
2676 #line 2701 "pikchr.c"
2677 yymsp[0].minor.yy0 = yylhsminor.yy0;
2678 break;
2679 case 53: /* boolproperty ::= CW */
2680 #line 655 "pikchr.y"
2681 {p->cur->cw = 1;}
2682 #line 2707 "pikchr.c"
2683 break;
2684 case 54: /* boolproperty ::= CCW */
2685 #line 656 "pikchr.y"
2686 {p->cur->cw = 0;}
2687 #line 2712 "pikchr.c"
2688 break;
2689 case 55: /* boolproperty ::= LARROW */
2690 #line 657 "pikchr.y"
2691 {p->cur->larrow=1; p->cur->rarrow=0; }
2692 #line 2717 "pikchr.c"
2693 break;
2694 case 56: /* boolproperty ::= RARROW */
2695 #line 658 "pikchr.y"
2696 {p->cur->larrow=0; p->cur->rarrow=1; }
2697 #line 2722 "pikchr.c"
2698 break;
2699 case 57: /* boolproperty ::= LRARROW */
2700 #line 659 "pikchr.y"
2701 {p->cur->larrow=1; p->cur->rarrow=1; }
2702 #line 2727 "pikchr.c"
2703 break;
2704 case 58: /* boolproperty ::= INVIS */
2705 #line 660 "pikchr.y"
2706 {p->cur->sw = 0.0;}
2707 #line 2732 "pikchr.c"
2708 break;
2709 case 59: /* boolproperty ::= THICK */
2710 #line 661 "pikchr.y"
2711 {p->cur->sw *= 1.5;}
2712 #line 2737 "pikchr.c"
2713 break;
2714 case 60: /* boolproperty ::= THIN */
2715 #line 662 "pikchr.y"
2716 {p->cur->sw *= 0.67;}
2717 #line 2742 "pikchr.c"
2718 break;
2719 case 61: /* boolproperty ::= SOLID */
2720 #line 663 "pikchr.y"
2721 {p->cur->sw = pik_value(p,"thickness",9,0);
2722 p->cur->dotted = p->cur->dashed = 0.0;}
2723 #line 2748 "pikchr.c"
2724 break;
2725 case 62: /* textposition ::= */
2726 #line 666 "pikchr.y"
2727 {yymsp[1].minor.yy164 = 0;}
2728 #line 2753 "pikchr.c"
2729 break;
2730 case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|ALIGNED|BIG|SMALL */
2731 #line 669 "pikchr.y"
2732 {yylhsminor.yy164 = (short int)pik_text_position(yymsp[-1].minor.yy164,&yymsp[0].minor.yy0);}
2733 #line 2758 "pikchr.c"
2734 yymsp[-1].minor.yy164 = yylhsminor.yy164;
2735 break;
2736 case 64: /* position ::= expr COMMA expr */
2737 #line 672 "pikchr.y"
2738 {yylhsminor.yy79.x=yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[0].minor.yy153;}
2739 #line 2764 "pikchr.c"
2740 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2741 break;
2742 case 65: /* position ::= place PLUS expr COMMA expr */
2743 #line 674 "pikchr.y"
2744 {yylhsminor.yy79.x=yymsp[-4].minor.yy79.x+yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y+yymsp[0].minor.yy153;}
2745 #line 2770 "pikchr.c"
2746 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2747 break;
2748 case 66: /* position ::= place MINUS expr COMMA expr */
2749 #line 675 "pikchr.y"
2750 {yylhsminor.yy79.x=yymsp[-4].minor.yy79.x-yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y-yymsp[0].minor.yy153;}
2751 #line 2776 "pikchr.c"
2752 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2753 break;
2754 case 67: /* position ::= place PLUS LP expr COMMA expr RP */
2755 #line 677 "pikchr.y"
2756 {yylhsminor.yy79.x=yymsp[-6].minor.yy79.x+yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y+yymsp[-1].minor.yy153;}
2757 #line 2782 "pikchr.c"
2758 yymsp[-6].minor.yy79 = yylhsminor.yy79;
2759 break;
2760 case 68: /* position ::= place MINUS LP expr COMMA expr RP */
2761 #line 679 "pikchr.y"
2762 {yylhsminor.yy79.x=yymsp[-6].minor.yy79.x-yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y-yymsp[-1].minor.yy153;}
2763 #line 2788 "pikchr.c"
2764 yymsp[-6].minor.yy79 = yylhsminor.yy79;
2765 break;
2766 case 69: /* position ::= LP position COMMA position RP */
2767 #line 680 "pikchr.y"
2768 {yymsp[-4].minor.yy79.x=yymsp[-3].minor.yy79.x; yymsp[-4].minor.yy79.y=yymsp[-1].minor.yy79.y;}
2769 #line 2794 "pikchr.c"
2770 break;
2771 case 70: /* position ::= LP position RP */
2772 #line 681 "pikchr.y"
2773 {yymsp[-2].minor.yy79=yymsp[-1].minor.yy79;}
2774 #line 2799 "pikchr.c"
2775 break;
2776 case 71: /* position ::= expr between position AND position */
2777 #line 683 "pikchr.y"
2778 {yylhsminor.yy79 = pik_position_between(yymsp[-4].minor.yy153,yymsp[-2].minor.yy79,yymsp[0].minor.yy79);}
2779 #line 2804 "pikchr.c"
2780 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2781 break;
2782 case 72: /* position ::= expr LT position COMMA position GT */
2783 #line 685 "pikchr.y"
2784 {yylhsminor.yy79 = pik_position_between(yymsp[-5].minor.yy153,yymsp[-3].minor.yy79,yymsp[-1].minor.yy79);}
2785 #line 2810 "pikchr.c"
2786 yymsp[-5].minor.yy79 = yylhsminor.yy79;
2787 break;
2788 case 73: /* position ::= expr ABOVE position */
2789 #line 686 "pikchr.y"
2790 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y += yymsp[-2].minor.yy153;}
2791 #line 2816 "pikchr.c"
2792 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2793 break;
2794 case 74: /* position ::= expr BELOW position */
2795 #line 687 "pikchr.y"
2796 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y -= yymsp[-2].minor.yy153;}
2797 #line 2822 "pikchr.c"
2798 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2799 break;
2800 case 75: /* position ::= expr LEFT OF position */
2801 #line 688 "pikchr.y"
2802 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x -= yymsp[-3].minor.yy153;}
2803 #line 2828 "pikchr.c"
2804 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2805 break;
2806 case 76: /* position ::= expr RIGHT OF position */
2807 #line 689 "pikchr.y"
2808 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x += yymsp[-3].minor.yy153;}
2809 #line 2834 "pikchr.c"
2810 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2811 break;
2812 case 77: /* position ::= expr ON HEADING EDGEPT OF position */
2813 #line 691 "pikchr.y"
2814 {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-5].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2815 #line 2840 "pikchr.c"
2816 yymsp[-5].minor.yy79 = yylhsminor.yy79;
2817 break;
2818 case 78: /* position ::= expr HEADING EDGEPT OF position */
2819 #line 693 "pikchr.y"
2820 {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-4].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2821 #line 2846 "pikchr.c"
2822 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2823 break;
2824 case 79: /* position ::= expr EDGEPT OF position */
2825 #line 695 "pikchr.y"
2826 {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2827 #line 2852 "pikchr.c"
2828 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2829 break;
2830 case 80: /* position ::= expr ON HEADING expr FROM position */
2831 #line 697 "pikchr.y"
2832 {yylhsminor.yy79 = pik_position_at_angle(yymsp[-5].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
2833 #line 2858 "pikchr.c"
2834 yymsp[-5].minor.yy79 = yylhsminor.yy79;
2835 break;
2836 case 81: /* position ::= expr HEADING expr FROM position */
2837 #line 699 "pikchr.y"
2838 {yylhsminor.yy79 = pik_position_at_angle(yymsp[-4].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
2839 #line 2864 "pikchr.c"
2840 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2841 break;
2842 case 82: /* place ::= edge OF object */
2843 #line 711 "pikchr.y"
2844 {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2845 #line 2870 "pikchr.c"
2846 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2847 break;
2848 case 83: /* place2 ::= object */
2849 #line 712 "pikchr.y"
2850 {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,0);}
2851 #line 2876 "pikchr.c"
2852 yymsp[0].minor.yy79 = yylhsminor.yy79;
2853 break;
2854 case 84: /* place2 ::= object DOT_E edge */
2855 #line 713 "pikchr.y"
2856 {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
2857 #line 2882 "pikchr.c"
2858 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2859 break;
2860 case 85: /* place2 ::= NTH VERTEX OF object */
2861 #line 714 "pikchr.y"
2862 {yylhsminor.yy79 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy36);}
2863 #line 2888 "pikchr.c"
2864 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2865 break;
2866 case 86: /* object ::= nth */
2867 #line 726 "pikchr.y"
2868 {yylhsminor.yy36 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
2869 #line 2894 "pikchr.c"
2870 yymsp[0].minor.yy36 = yylhsminor.yy36;
2871 break;
2872 case 87: /* object ::= nth OF|IN object */
2873 #line 727 "pikchr.y"
2874 {yylhsminor.yy36 = pik_find_nth(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2875 #line 2900 "pikchr.c"
2876 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2877 break;
2878 case 88: /* objectname ::= THIS */
2879 #line 729 "pikchr.y"
2880 {yymsp[0].minor.yy36 = p->cur;}
2881 #line 2906 "pikchr.c"
2882 break;
2883 case 89: /* objectname ::= PLACENAME */
2884 #line 730 "pikchr.y"
2885 {yylhsminor.yy36 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
2886 #line 2911 "pikchr.c"
2887 yymsp[0].minor.yy36 = yylhsminor.yy36;
2888 break;
2889 case 90: /* objectname ::= objectname DOT_U PLACENAME */
2890 #line 732 "pikchr.y"
2891 {yylhsminor.yy36 = pik_find_byname(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
2892 #line 2917 "pikchr.c"
2893 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2894 break;
2895 case 91: /* nth ::= NTH CLASSNAME */
2896 #line 734 "pikchr.y"
2897 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
2898 #line 2923 "pikchr.c"
2899 yymsp[-1].minor.yy0 = yylhsminor.yy0;
2900 break;
2901 case 92: /* nth ::= NTH LAST CLASSNAME */
2902 #line 735 "pikchr.y"
2903 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
2904 #line 2929 "pikchr.c"
2905 yymsp[-2].minor.yy0 = yylhsminor.yy0;
2906 break;
2907 case 93: /* nth ::= LAST CLASSNAME */
2908 #line 736 "pikchr.y"
2909 {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
2910 #line 2935 "pikchr.c"
2911 break;
2912 case 94: /* nth ::= LAST */
2913 #line 737 "pikchr.y"
2914 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
2915 #line 2940 "pikchr.c"
2916 yymsp[0].minor.yy0 = yylhsminor.yy0;
2917 break;
2918 case 95: /* nth ::= NTH LB RB */
2919 #line 738 "pikchr.y"
2920 {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
2921 #line 2946 "pikchr.c"
2922 yymsp[-2].minor.yy0 = yylhsminor.yy0;
2923 break;
2924 case 96: /* nth ::= NTH LAST LB RB */
2925 #line 739 "pikchr.y"
2926 {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
2927 #line 2952 "pikchr.c"
2928 yymsp[-3].minor.yy0 = yylhsminor.yy0;
2929 break;
2930 case 97: /* nth ::= LAST LB RB */
2931 #line 740 "pikchr.y"
2932 {yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
2933 #line 2958 "pikchr.c"
2934 break;
2935 case 98: /* expr ::= expr PLUS expr */
2936 #line 742 "pikchr.y"
2937 {yylhsminor.yy153=yymsp[-2].minor.yy153+yymsp[0].minor.yy153;}
2938 #line 2963 "pikchr.c"
2939 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2940 break;
2941 case 99: /* expr ::= expr MINUS expr */
2942 #line 743 "pikchr.y"
2943 {yylhsminor.yy153=yymsp[-2].minor.yy153-yymsp[0].minor.yy153;}
2944 #line 2969 "pikchr.c"
2945 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2946 break;
2947 case 100: /* expr ::= expr STAR expr */
2948 #line 744 "pikchr.y"
2949 {yylhsminor.yy153=yymsp[-2].minor.yy153*yymsp[0].minor.yy153;}
2950 #line 2975 "pikchr.c"
2951 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2952 break;
2953 case 101: /* expr ::= expr SLASH expr */
2954 #line 745 "pikchr.y"
2955 {
2956 if( yymsp[0].minor.yy153==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy153 = 0.0; }
2957 else{ yylhsminor.yy153 = yymsp[-2].minor.yy153/yymsp[0].minor.yy153; }
2958 }
2959 #line 2984 "pikchr.c"
2960 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2961 break;
2962 case 102: /* expr ::= MINUS expr */
2963 #line 749 "pikchr.y"
2964 {yymsp[-1].minor.yy153=-yymsp[0].minor.yy153;}
2965 #line 2990 "pikchr.c"
2966 break;
2967 case 103: /* expr ::= PLUS expr */
2968 #line 750 "pikchr.y"
2969 {yymsp[-1].minor.yy153=yymsp[0].minor.yy153;}
2970 #line 2995 "pikchr.c"
2971 break;
2972 case 104: /* expr ::= LP expr RP */
2973 #line 751 "pikchr.y"
2974 {yymsp[-2].minor.yy153=yymsp[-1].minor.yy153;}
2975 #line 3000 "pikchr.c"
2976 break;
2977 case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
2978 #line 752 "pikchr.y"
2979 {yymsp[-2].minor.yy153=pik_get_var(p,&yymsp[-1].minor.yy0);}
2980 #line 3005 "pikchr.c"
2981 break;
2982 case 106: /* expr ::= NUMBER */
2983 #line 753 "pikchr.y"
2984 {yylhsminor.yy153=pik_atof(&yymsp[0].minor.yy0);}
2985 #line 3010 "pikchr.c"
2986 yymsp[0].minor.yy153 = yylhsminor.yy153;
2987 break;
2988 case 107: /* expr ::= ID */
2989 #line 754 "pikchr.y"
2990 {yylhsminor.yy153=pik_get_var(p,&yymsp[0].minor.yy0);}
2991 #line 3016 "pikchr.c"
2992 yymsp[0].minor.yy153 = yylhsminor.yy153;
2993 break;
2994 case 108: /* expr ::= FUNC1 LP expr RP */
2995 #line 755 "pikchr.y"
2996 {yylhsminor.yy153 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy153,0.0);}
2997 #line 3022 "pikchr.c"
2998 yymsp[-3].minor.yy153 = yylhsminor.yy153;
2999 break;
3000 case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
3001 #line 756 "pikchr.y"
3002 {yylhsminor.yy153 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy153,yymsp[-1].minor.yy153);}
3003 #line 3028 "pikchr.c"
3004 yymsp[-5].minor.yy153 = yylhsminor.yy153;
3005 break;
3006 case 110: /* expr ::= DIST LP position COMMA position RP */
3007 #line 757 "pikchr.y"
3008 {yymsp[-5].minor.yy153 = pik_dist(&yymsp[-3].minor.yy79,&yymsp[-1].minor.yy79);}
3009 #line 3034 "pikchr.c"
3010 break;
3011 case 111: /* expr ::= place2 DOT_XY X */
3012 #line 758 "pikchr.y"
3013 {yylhsminor.yy153 = yymsp[-2].minor.yy79.x;}
3014 #line 3039 "pikchr.c"
3015 yymsp[-2].minor.yy153 = yylhsminor.yy153;
3016 break;
3017 case 112: /* expr ::= place2 DOT_XY Y */
3018 #line 759 "pikchr.y"
3019 {yylhsminor.yy153 = yymsp[-2].minor.yy79.y;}
3020 #line 3045 "pikchr.c"
3021 yymsp[-2].minor.yy153 = yylhsminor.yy153;
3022 break;
3023 case 113: /* expr ::= object DOT_L numproperty */
3024 case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
3025 case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
3026 #line 760 "pikchr.y"
3027 {yylhsminor.yy153=pik_property_of(yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
3028 #line 3053 "pikchr.c"
3029 yymsp[-2].minor.yy153 = yylhsminor.yy153;
3030 break;
3031 default:
3032 /* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
3033 /* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
@@ -3126,19 +3131,19 @@
3126 ){
3127 pik_parserARG_FETCH
3128 pik_parserCTX_FETCH
3129 #define TOKEN yyminor
3130 /************ Begin %syntax_error code ****************************************/
3131 #line 520 "pikchr.y"
3132
3133 if( TOKEN.z && TOKEN.z[0] ){
3134 pik_error(p, &TOKEN, "syntax error");
3135 }else{
3136 pik_error(p, 0, "syntax error");
3137 }
3138 UNUSED_PARAMETER(yymajor);
3139 #line 3164 "pikchr.c"
3140 /************ End %syntax_error code ******************************************/
3141 pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
3142 pik_parserCTX_STORE
3143 }
3144
@@ -3367,11 +3372,11 @@
3367 #else
3368 (void)iToken;
3369 return 0;
3370 #endif
3371 }
3372 #line 765 "pikchr.y"
3373
3374
3375
3376 /* Chart of the 148 official CSS color names with their
3377 ** corresponding RGB values thru Color Module Level 4:
@@ -3811,11 +3816,11 @@
3811 static PPoint circleChop(Pik *p, PObj *pObj, PPoint *pPt){
3812 PPoint chop;
3813 PNum dx = pPt->x - pObj->ptAt.x;
3814 PNum dy = pPt->y - pObj->ptAt.y;
3815 PNum dist = hypot(dx,dy);
3816 if( dist<pObj->rad ) return pObj->ptAt;
3817 chop.x = pObj->ptAt.x + dx*pObj->rad/dist;
3818 chop.y = pObj->ptAt.y + dy*pObj->rad/dist;
3819 UNUSED_PARAMETER(p);
3820 return chop;
3821 }
@@ -4510,11 +4515,11 @@
4510 if( z==0 ){
4511 pik_error(p, 0, 0);
4512 return;
4513 }
4514 p->zOut = z;
4515 p->nOutAlloc = n;
4516 }
4517 memcpy(p->zOut+p->nOut, zText, n);
4518 p->nOut += n;
4519 p->zOut[p->nOut] = 0;
4520 }
@@ -4636,27 +4641,27 @@
4636 ** on the value.
4637 */
4638 static void pik_append_x(Pik *p, const char *z1, PNum v, const char *z2){
4639 char buf[200];
4640 v -= p->bbox.sw.x;
4641 snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, (int)(p->rScale*v), z2);
4642 buf[sizeof(buf)-1] = 0;
4643 pik_append(p, buf, -1);
4644 }
4645 static void pik_append_y(Pik *p, const char *z1, PNum v, const char *z2){
4646 char buf[200];
4647 v = p->bbox.ne.y - v;
4648 snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, (int)(p->rScale*v), z2);
4649 buf[sizeof(buf)-1] = 0;
4650 pik_append(p, buf, -1);
4651 }
4652 static void pik_append_xy(Pik *p, const char *z1, PNum x, PNum y){
4653 char buf[200];
4654 x = x - p->bbox.sw.x;
4655 y = p->bbox.ne.y - y;
4656 snprintf(buf, sizeof(buf)-1, "%s%d,%d", z1,
4657 (int)(p->rScale*x), (int)(p->rScale*y));
4658 buf[sizeof(buf)-1] = 0;
4659 pik_append(p, buf, -1);
4660 }
4661 static void pik_append_dis(Pik *p, const char *z1, PNum v, const char *z2){
4662 char buf[200];
@@ -4672,11 +4677,11 @@
4672 ** foreground color if false. The distinction only matters for color
4673 ** inversions in PIKCHR_DARK_MODE.
4674 */
4675 static void pik_append_clr(Pik *p,const char *z1,PNum v,const char *z2,int bg){
4676 char buf[200];
4677 int x = (int)v;
4678 int r, g, b;
4679 if( x==0 && p->fgcolor>0 && !bg ){
4680 x = p->fgcolor;
4681 }else if( bg && x>=0xffffff && p->bgcolor>0 ){
4682 x = p->bgcolor;
@@ -4698,12 +4703,12 @@
4698 static void pik_append_arc(Pik *p, PNum r1, PNum r2, PNum x, PNum y){
4699 char buf[200];
4700 x = x - p->bbox.sw.x;
4701 y = p->bbox.ne.y - y;
4702 snprintf(buf, sizeof(buf)-1, "A%d %d 0 0 0 %d %d",
4703 (int)(p->rScale*r1), (int)(p->rScale*r2),
4704 (int)(p->rScale*x), (int)(p->rScale*y));
4705 buf[sizeof(buf)-1] = 0;
4706 pik_append(p, buf, -1);
4707 }
4708
4709 /* Append a style="..." text. But, leave the quote unterminated, in case
@@ -5241,10 +5246,21 @@
5241 /* Return true if a bounding box is empty.
5242 */
5243 static int pik_bbox_isempty(PBox *p){
5244 return p->sw.x>p->ne.x;
5245 }
 
 
 
 
 
 
 
 
 
 
 
5246
5247 /* Initialize a bounding box to an empty container
5248 */
5249 static void pik_bbox_init(PBox *p){
5250 p->sw.x = 1.0;
@@ -5391,11 +5407,11 @@
5391 }
5392 }
5393 p->aTPath[0] = pNew->ptAt;
5394 pNew->with = pNew->ptAt;
5395 pNew->outDir = pNew->inDir = p->eDir;
5396 pNew->iLayer = (int)pik_value(p, "layer", 5, &miss);
5397 if( miss ) pNew->iLayer = 1000;
5398 if( pNew->iLayer<0 ) pNew->iLayer = 0;
5399 if( pSublist ){
5400 pNew->type = &sublistClass;
5401 pNew->pSublist = pSublist;
@@ -5837,10 +5853,38 @@
5837 p->mTPath |= 1;
5838 break;
5839 }
5840 pObj->outDir = pDir->eCode;
5841 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5842
5843 /* Set the "from" of an object
5844 */
5845 static void pik_set_from(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
5846 if( !pObj->type->isLine ){
@@ -5865,10 +5909,11 @@
5865 }
5866 }
5867 p->aTPath[0] = *pPt;
5868 p->mTPath = 3;
5869 pObj->mProp |= A_FROM;
 
5870 }
5871
5872 /* Set the "to" of an object
5873 */
5874 static void pik_add_to(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
@@ -5885,10 +5930,11 @@
5885 if( n==0 || p->mTPath==3 || p->thenFlag ){
5886 n = pik_next_rpath(p, pTk);
5887 }
5888 p->aTPath[n] = *pPt;
5889 p->mTPath = 3;
 
5890 }
5891
5892 static void pik_close_path(Pik *p, PToken *pErr){
5893 PObj *pObj = p->cur;
5894 if( p->nTPath<3 ){
@@ -6220,10 +6266,20 @@
6220 break;
6221 default: pVar->val = val; break;
6222 }
6223 p->bLayoutVars = 0; /* Clear the layout setting cache */
6224 }
 
 
 
 
 
 
 
 
 
 
6225
6226 /*
6227 ** Search for the variable named z[0..n-1] in:
6228 **
6229 ** * Application defined variables
@@ -6258,10 +6314,13 @@
6258 last = mid-1;
6259 }
6260 }
6261 if( pMiss ) *pMiss = 1;
6262 return 0.0;
 
 
 
6263 }
6264
6265 /*
6266 ** Look up a color-name. Unlike other names in this program, the
6267 ** color-names are not case sensitive. So "DarkBlue" and "darkblue"
@@ -6413,10 +6472,11 @@
6413 }
6414 /* First look explicitly tagged objects */
6415 for(i=pList->n-1; i>=0; i--){
6416 PObj *pObj = pList->a[i];
6417 if( pObj->zName && pik_token_eq(pName,pObj->zName)==0 ){
 
6418 return pObj;
6419 }
6420 }
6421 /* If not found, do a second pass looking for any object containing
6422 ** text which exactly matches pName */
@@ -6423,10 +6483,11 @@
6423 for(i=pList->n-1; i>=0; i--){
6424 PObj *pObj = pList->a[i];
6425 for(j=0; j<pObj->nTxt; j++){
6426 if( pObj->aTxt[j].n==pName->n+2
6427 && memcmp(pObj->aTxt[j].z+1,pName->z,pName->n)==0 ){
 
6428 return pObj;
6429 }
6430 }
6431 }
6432 pik_error(p, pName, "no such object");
@@ -6557,26 +6618,28 @@
6557
6558 /* Return the value of a property of an object.
6559 */
6560 static PNum pik_property_of(PObj *pObj, PToken *pProp){
6561 PNum v = 0.0;
6562 switch( pProp->eType ){
6563 case T_HEIGHT: v = pObj->h; break;
6564 case T_WIDTH: v = pObj->w; break;
6565 case T_RADIUS: v = pObj->rad; break;
6566 case T_DIAMETER: v = pObj->rad*2.0; break;
6567 case T_THICKNESS: v = pObj->sw; break;
6568 case T_DASHED: v = pObj->dashed; break;
6569 case T_DOTTED: v = pObj->dotted; break;
6570 case T_FILL: v = pObj->fill; break;
6571 case T_COLOR: v = pObj->color; break;
6572 case T_X: v = pObj->ptAt.x; break;
6573 case T_Y: v = pObj->ptAt.y; break;
6574 case T_TOP: v = pObj->bbox.ne.y; break;
6575 case T_BOTTOM: v = pObj->bbox.sw.y; break;
6576 case T_LEFT: v = pObj->bbox.sw.x; break;
6577 case T_RIGHT: v = pObj->bbox.ne.x; break;
 
 
6578 }
6579 return v;
6580 }
6581
6582 /* Compute one of the built-in functions
@@ -6618,40 +6681,49 @@
6618 }
6619 return;
6620 }
6621
6622 /*
6623 ** Search for object located at *pCenter that has an xChop method.
 
 
6624 ** Return a pointer to the object, or NULL if not found.
6625 */
6626 static PObj *pik_find_chopper(PList *pList, PPoint *pCenter){
6627 int i;
6628 if( pList==0 ) return 0;
6629 for(i=pList->n-1; i>=0; i--){
6630 PObj *pObj = pList->a[i];
6631 if( pObj->type->xChop!=0
6632 && pObj->ptAt.x==pCenter->x
6633 && pObj->ptAt.y==pCenter->y
 
6634 ){
6635 return pObj;
6636 }else if( pObj->pSublist ){
6637 pObj = pik_find_chopper(pObj->pSublist,pCenter);
6638 if( pObj ) return pObj;
6639 }
6640 }
6641 return 0;
6642 }
6643
6644 /*
6645 ** There is a line traveling from pFrom to pTo.
6646 **
6647 ** If point pTo is the exact enter of a choppable object,
6648 ** then adjust pTo by the appropriate amount in the direction
6649 ** of pFrom.
 
 
 
 
6650 */
6651 static void pik_autochop(Pik *p, PPoint *pFrom, PPoint *pTo){
6652 PObj *pObj = pik_find_chopper(p->list, pTo);
 
 
6653 if( pObj ){
6654 *pTo = pObj->type->xChop(p, pObj, pFrom);
6655 }
6656 }
6657
@@ -6746,12 +6818,12 @@
6746 ** If the line goes to the center of an object with an
6747 ** xChop method, then use the xChop method to trim the line.
6748 */
6749 if( pObj->bChop && pObj->nPath>=2 ){
6750 int n = pObj->nPath;
6751 pik_autochop(p, &pObj->aPath[n-2], &pObj->aPath[n-1]);
6752 pik_autochop(p, &pObj->aPath[1], &pObj->aPath[0]);
6753 }
6754
6755 pObj->ptEnter = pObj->aPath[0];
6756 pObj->ptExit = pObj->aPath[pObj->nPath-1];
6757
@@ -6842,11 +6914,11 @@
6842 int i;
6843 int iNextLayer = 0;
6844 int iThisLayer;
6845 int bMoreToDo;
6846 int miss = 0;
6847 int mDebug = (int)pik_value(p, "debug", 5, 0);
6848 PNum colorLabel;
6849 do{
6850 bMoreToDo = 0;
6851 iThisLayer = iNextLayer;
6852 iNextLayer = 0x7fffffff;
@@ -6960,24 +7032,24 @@
6960 if( thickness<=0.01 ) thickness = 0.01;
6961 margin = pik_value(p,"margin",6,0);
6962 margin += thickness;
6963 wArrow = p->wArrow*thickness;
6964 miss = 0;
6965 p->fgcolor = (int)pik_value(p,"fgcolor",7,&miss);
6966 if( miss ){
6967 PToken t;
6968 t.z = "fgcolor";
6969 t.n = 7;
6970 p->fgcolor = (int)pik_lookup_color(0, &t);
6971 }
6972 miss = 0;
6973 p->bgcolor = (int)pik_value(p,"bgcolor",7,&miss);
6974 if( miss ){
6975 PToken t;
6976 t.z = "bgcolor";
6977 t.n = 7;
6978 p->bgcolor = (int)pik_lookup_color(0, &t);
6979 }
6980
6981 /* Compute a bounding box over all objects so that we can know
6982 ** how big to declare the SVG canvas */
6983 pik_bbox_init(&p->bbox);
@@ -6997,18 +7069,18 @@
6997 pik_append(p, p->zClass, -1);
6998 pik_append(p, "\"", 1);
6999 }
7000 w = p->bbox.ne.x - p->bbox.sw.x;
7001 h = p->bbox.ne.y - p->bbox.sw.y;
7002 p->wSVG = (int)(p->rScale*w);
7003 p->hSVG = (int)(p->rScale*h);
7004 pikScale = pik_value(p,"scale",5,0);
7005 if( pikScale>=0.001 && pikScale<=1000.0
7006 && (pikScale<0.99 || pikScale>1.01)
7007 ){
7008 p->wSVG = (int)(p->wSVG*pikScale);
7009 p->hSVG = (int)(p->hSVG*pikScale);
7010 pik_append_num(p, " width=\"", p->wSVG);
7011 pik_append_num(p, "\" height=\"", p->hSVG);
7012 pik_append(p, "\"", 1);
7013 }
7014 pik_append_dis(p, " viewBox=\"0 0 ",w,"");
@@ -7749,15 +7821,16 @@
7749 #if defined(PIKCHR_FUZZ)
7750 #include <stdint.h>
7751 int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
7752 int w,h;
7753 char *zIn, *zOut;
 
7754 zIn = malloc( nByte + 1 );
7755 if( zIn==0 ) return 0;
7756 memcpy(zIn, aData, nByte);
7757 zIn[nByte] = 0;
7758 zOut = pikchr(zIn, "pikchr", 0, &w, &h);
7759 free(zIn);
7760 free(zOut);
7761 return 0;
7762 }
7763 #endif /* PIKCHR_FUZZ */
@@ -7988,19 +8061,26 @@
7988 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(w));
7989 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(h));
7990 Tcl_SetObjResult(interp, pRes);
7991 return TCL_OK;
7992 }
 
 
 
 
 
 
 
7993
7994 /* Invoke this routine to register the "pikchr" command with the interpreter
7995 ** given in the argument */
7996 int Pikchr_Init(Tcl_Interp *interp){
7997 Tcl_CreateObjCommand(interp, "pikchr", pik_tcl_command, 0, 0);
7998 Tcl_PkgProvide (interp, PACKAGE_NAME, PACKAGE_VERSION);
7999 return TCL_OK;
8000 }
8001
8002
8003 #endif /* PIKCHR_TCL */
8004
8005
8006 #line 8031 "pikchr.c"
8007
--- src/pikchr.c
+++ src/pikchr.c
@@ -317,10 +317,11 @@
317 PToken aTxt[5]; /* Text with .eCode holding TP flags */
318 int iLayer; /* Rendering order */
319 int inDir, outDir; /* Entry and exit directions */
320 int nPath; /* Number of path points */
321 PPoint *aPath; /* Array of path points */
322 PObj *pFrom, *pTo; /* End-point objects of a path */
323 PBox bbox; /* Bounding box */
324 };
325
326 /* A list of graphics objects */
327 struct PList {
@@ -347,10 +348,11 @@
348 unsigned int nOut; /* Bytes written to zOut[] so far */
349 unsigned int nOutAlloc; /* Space allocated to zOut[] */
350 unsigned char eDir; /* Current direction */
351 unsigned int mFlags; /* Flags passed to pikchr() */
352 PObj *cur; /* Object under construction */
353 PObj *lastRef; /* Last object references by name */
354 PList *list; /* Object list under construction */
355 PMacro *pMacros; /* List of all defined macros */
356 PVar *pVar; /* Application-defined variables */
357 PBox bbox; /* Bounding box around all statements */
358 /* Cache of layout values. <=0.0 for unknown... */
@@ -426,12 +428,14 @@
428 static void pik_render(Pik*,PList*);
429 static PList *pik_elist_append(Pik*,PList*,PObj*);
430 static PObj *pik_elem_new(Pik*,PToken*,PToken*,PList*);
431 static void pik_set_direction(Pik*,int);
432 static void pik_elem_setname(Pik*,PObj*,PToken*);
433 static int pik_round(PNum);
434 static void pik_set_var(Pik*,PToken*,PNum,PToken*);
435 static PNum pik_value(Pik*,const char*,int,int*);
436 static int pik_value_int(Pik*,const char*,int,int*);
437 static PNum pik_lookup_color(Pik*,PToken*);
438 static PNum pik_get_var(Pik*,PToken*);
439 static PNum pik_atof(PToken*);
440 static void pik_after_adding_attributes(Pik*,PObj*);
441 static void pik_elem_move(PObj*,PNum dx, PNum dy);
@@ -450,10 +454,11 @@
454 static short int pik_nth_value(Pik*,PToken*);
455 static PObj *pik_find_nth(Pik*,PObj*,PToken*);
456 static PObj *pik_find_byname(Pik*,PObj*,PToken*);
457 static PPoint pik_place_of_elem(Pik*,PObj*,PToken*);
458 static int pik_bbox_isempty(PBox*);
459 static int pik_bbox_contains_point(PBox*,PPoint*);
460 static void pik_bbox_init(PBox*);
461 static void pik_bbox_addbox(PBox*,PBox*);
462 static void pik_bbox_add_xy(PBox*,PNum,PNum);
463 static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry);
464 static void pik_add_txt(Pik*,PToken*,int);
@@ -474,11 +479,11 @@
479 static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*);
480 static PNum pik_dist(PPoint*,PPoint*);
481 static void pik_add_macro(Pik*,PToken *pId,PToken *pCode);
482
483
484 #line 510 "pikchr.c"
485 /**************** End of %include directives **********************************/
486 /* These constants specify the various numeric values for terminal symbols.
487 ***************** Begin token definitions *************************************/
488 #ifndef T_ID
489 #define T_ID 1
@@ -1703,22 +1708,22 @@
1708 ** inside the C code.
1709 */
1710 /********* Begin destructor definitions ***************************************/
1711 case 99: /* statement_list */
1712 {
1713 #line 499 "pikchr.y"
1714 pik_elist_free(p,(yypminor->yy227));
1715 #line 1740 "pikchr.c"
1716 }
1717 break;
1718 case 100: /* statement */
1719 case 101: /* unnamed_statement */
1720 case 102: /* basetype */
1721 {
1722 #line 501 "pikchr.y"
1723 pik_elem_free(p,(yypminor->yy36));
1724 #line 1749 "pikchr.c"
1725 }
1726 break;
1727 /********* End destructor definitions *****************************************/
1728 default: break; /* If no destructor action specified: do nothing */
1729 }
@@ -1932,14 +1937,14 @@
1937 #endif
1938 while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
1939 /* Here code is inserted which will execute if the parser
1940 ** stack every overflows */
1941 /******** Begin %stack_overflow code ******************************************/
1942 #line 533 "pikchr.y"
1943
1944 pik_error(p, 0, "parser stack overflow");
1945 #line 1970 "pikchr.c"
1946 /******** End %stack_overflow code ********************************************/
1947 pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
1948 pik_parserCTX_STORE
1949 }
1950
@@ -2415,619 +2420,619 @@
2420 ** break;
2421 */
2422 /********** Begin reduce actions **********************************************/
2423 YYMINORTYPE yylhsminor;
2424 case 0: /* document ::= statement_list */
2425 #line 537 "pikchr.y"
2426 {pik_render(p,yymsp[0].minor.yy227);}
2427 #line 2452 "pikchr.c"
2428 break;
2429 case 1: /* statement_list ::= statement */
2430 #line 540 "pikchr.y"
2431 { yylhsminor.yy227 = pik_elist_append(p,0,yymsp[0].minor.yy36); }
2432 #line 2457 "pikchr.c"
2433 yymsp[0].minor.yy227 = yylhsminor.yy227;
2434 break;
2435 case 2: /* statement_list ::= statement_list EOL statement */
2436 #line 542 "pikchr.y"
2437 { yylhsminor.yy227 = pik_elist_append(p,yymsp[-2].minor.yy227,yymsp[0].minor.yy36); }
2438 #line 2463 "pikchr.c"
2439 yymsp[-2].minor.yy227 = yylhsminor.yy227;
2440 break;
2441 case 3: /* statement ::= */
2442 #line 545 "pikchr.y"
2443 { yymsp[1].minor.yy36 = 0; }
2444 #line 2469 "pikchr.c"
2445 break;
2446 case 4: /* statement ::= direction */
2447 #line 546 "pikchr.y"
2448 { pik_set_direction(p,yymsp[0].minor.yy0.eCode); yylhsminor.yy36=0; }
2449 #line 2474 "pikchr.c"
2450 yymsp[0].minor.yy36 = yylhsminor.yy36;
2451 break;
2452 case 5: /* statement ::= lvalue ASSIGN rvalue */
2453 #line 547 "pikchr.y"
2454 {pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy153,&yymsp[-1].minor.yy0); yylhsminor.yy36=0;}
2455 #line 2480 "pikchr.c"
2456 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2457 break;
2458 case 6: /* statement ::= PLACENAME COLON unnamed_statement */
2459 #line 549 "pikchr.y"
2460 { yylhsminor.yy36 = yymsp[0].minor.yy36; pik_elem_setname(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0); }
2461 #line 2486 "pikchr.c"
2462 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2463 break;
2464 case 7: /* statement ::= PLACENAME COLON position */
2465 #line 551 "pikchr.y"
2466 { yylhsminor.yy36 = pik_elem_new(p,0,0,0);
2467 if(yylhsminor.yy36){ yylhsminor.yy36->ptAt = yymsp[0].minor.yy79; pik_elem_setname(p,yylhsminor.yy36,&yymsp[-2].minor.yy0); }}
2468 #line 2493 "pikchr.c"
2469 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2470 break;
2471 case 8: /* statement ::= unnamed_statement */
2472 #line 553 "pikchr.y"
2473 {yylhsminor.yy36 = yymsp[0].minor.yy36;}
2474 #line 2499 "pikchr.c"
2475 yymsp[0].minor.yy36 = yylhsminor.yy36;
2476 break;
2477 case 9: /* statement ::= print prlist */
2478 #line 554 "pikchr.y"
2479 {pik_append(p,"<br>\n",5); yymsp[-1].minor.yy36=0;}
2480 #line 2505 "pikchr.c"
2481 break;
2482 case 10: /* statement ::= ASSERT LP expr EQ expr RP */
2483 #line 559 "pikchr.y"
2484 {yymsp[-5].minor.yy36=pik_assert(p,yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy153);}
2485 #line 2510 "pikchr.c"
2486 break;
2487 case 11: /* statement ::= ASSERT LP position EQ position RP */
2488 #line 561 "pikchr.y"
2489 {yymsp[-5].minor.yy36=pik_position_assert(p,&yymsp[-3].minor.yy79,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy79);}
2490 #line 2515 "pikchr.c"
2491 break;
2492 case 12: /* statement ::= DEFINE ID CODEBLOCK */
2493 #line 562 "pikchr.y"
2494 {yymsp[-2].minor.yy36=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
2495 #line 2520 "pikchr.c"
2496 break;
2497 case 13: /* rvalue ::= PLACENAME */
2498 #line 573 "pikchr.y"
2499 {yylhsminor.yy153 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
2500 #line 2525 "pikchr.c"
2501 yymsp[0].minor.yy153 = yylhsminor.yy153;
2502 break;
2503 case 14: /* pritem ::= FILL */
2504 case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
2505 case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
2506 #line 578 "pikchr.y"
2507 {pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
2508 #line 2533 "pikchr.c"
2509 break;
2510 case 17: /* pritem ::= rvalue */
2511 #line 581 "pikchr.y"
2512 {pik_append_num(p,"",yymsp[0].minor.yy153);}
2513 #line 2538 "pikchr.c"
2514 break;
2515 case 18: /* pritem ::= STRING */
2516 #line 582 "pikchr.y"
2517 {pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
2518 #line 2543 "pikchr.c"
2519 break;
2520 case 19: /* prsep ::= COMMA */
2521 #line 583 "pikchr.y"
2522 {pik_append(p, " ", 1);}
2523 #line 2548 "pikchr.c"
2524 break;
2525 case 20: /* unnamed_statement ::= basetype attribute_list */
2526 #line 586 "pikchr.y"
2527 {yylhsminor.yy36 = yymsp[-1].minor.yy36; pik_after_adding_attributes(p,yylhsminor.yy36);}
2528 #line 2553 "pikchr.c"
2529 yymsp[-1].minor.yy36 = yylhsminor.yy36;
2530 break;
2531 case 21: /* basetype ::= CLASSNAME */
2532 #line 588 "pikchr.y"
2533 {yylhsminor.yy36 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
2534 #line 2559 "pikchr.c"
2535 yymsp[0].minor.yy36 = yylhsminor.yy36;
2536 break;
2537 case 22: /* basetype ::= STRING textposition */
2538 #line 590 "pikchr.y"
2539 {yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy164; yylhsminor.yy36 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
2540 #line 2565 "pikchr.c"
2541 yymsp[-1].minor.yy36 = yylhsminor.yy36;
2542 break;
2543 case 23: /* basetype ::= LB savelist statement_list RB */
2544 #line 592 "pikchr.y"
2545 { p->list = yymsp[-2].minor.yy227; yymsp[-3].minor.yy36 = pik_elem_new(p,0,0,yymsp[-1].minor.yy227); if(yymsp[-3].minor.yy36) yymsp[-3].minor.yy36->errTok = yymsp[0].minor.yy0; }
2546 #line 2571 "pikchr.c"
2547 break;
2548 case 24: /* savelist ::= */
2549 #line 597 "pikchr.y"
2550 {yymsp[1].minor.yy227 = p->list; p->list = 0;}
2551 #line 2576 "pikchr.c"
2552 break;
2553 case 25: /* relexpr ::= expr */
2554 #line 604 "pikchr.y"
2555 {yylhsminor.yy10.rAbs = yymsp[0].minor.yy153; yylhsminor.yy10.rRel = 0;}
2556 #line 2581 "pikchr.c"
2557 yymsp[0].minor.yy10 = yylhsminor.yy10;
2558 break;
2559 case 26: /* relexpr ::= expr PERCENT */
2560 #line 605 "pikchr.y"
2561 {yylhsminor.yy10.rAbs = 0; yylhsminor.yy10.rRel = yymsp[-1].minor.yy153/100;}
2562 #line 2587 "pikchr.c"
2563 yymsp[-1].minor.yy10 = yylhsminor.yy10;
2564 break;
2565 case 27: /* optrelexpr ::= */
2566 #line 607 "pikchr.y"
2567 {yymsp[1].minor.yy10.rAbs = 0; yymsp[1].minor.yy10.rRel = 1.0;}
2568 #line 2593 "pikchr.c"
2569 break;
2570 case 28: /* attribute_list ::= relexpr alist */
2571 #line 609 "pikchr.y"
2572 {pik_add_direction(p,0,&yymsp[-1].minor.yy10);}
2573 #line 2598 "pikchr.c"
2574 break;
2575 case 29: /* attribute ::= numproperty relexpr */
2576 #line 613 "pikchr.y"
2577 { pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10); }
2578 #line 2603 "pikchr.c"
2579 break;
2580 case 30: /* attribute ::= dashproperty expr */
2581 #line 614 "pikchr.y"
2582 { pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy153); }
2583 #line 2608 "pikchr.c"
2584 break;
2585 case 31: /* attribute ::= dashproperty */
2586 #line 615 "pikchr.y"
2587 { pik_set_dashed(p,&yymsp[0].minor.yy0,0); }
2588 #line 2613 "pikchr.c"
2589 break;
2590 case 32: /* attribute ::= colorproperty rvalue */
2591 #line 616 "pikchr.y"
2592 { pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153); }
2593 #line 2618 "pikchr.c"
2594 break;
2595 case 33: /* attribute ::= go direction optrelexpr */
2596 #line 617 "pikchr.y"
2597 { pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10);}
2598 #line 2623 "pikchr.c"
2599 break;
2600 case 34: /* attribute ::= go direction even position */
2601 #line 618 "pikchr.y"
2602 {pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79);}
2603 #line 2628 "pikchr.c"
2604 break;
2605 case 35: /* attribute ::= CLOSE */
2606 #line 619 "pikchr.y"
2607 { pik_close_path(p,&yymsp[0].minor.yy0); }
2608 #line 2633 "pikchr.c"
2609 break;
2610 case 36: /* attribute ::= CHOP */
2611 #line 620 "pikchr.y"
2612 { p->cur->bChop = 1; }
2613 #line 2638 "pikchr.c"
2614 break;
2615 case 37: /* attribute ::= FROM position */
2616 #line 621 "pikchr.y"
2617 { pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
2618 #line 2643 "pikchr.c"
2619 break;
2620 case 38: /* attribute ::= TO position */
2621 #line 622 "pikchr.y"
2622 { pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); }
2623 #line 2648 "pikchr.c"
2624 break;
2625 case 39: /* attribute ::= THEN */
2626 #line 623 "pikchr.y"
2627 { pik_then(p, &yymsp[0].minor.yy0, p->cur); }
2628 #line 2653 "pikchr.c"
2629 break;
2630 case 40: /* attribute ::= THEN optrelexpr HEADING expr */
2631 case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
2632 #line 625 "pikchr.y"
2633 {pik_move_hdg(p,&yymsp[-2].minor.yy10,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153,0,&yymsp[-3].minor.yy0);}
2634 #line 2659 "pikchr.c"
2635 break;
2636 case 41: /* attribute ::= THEN optrelexpr EDGEPT */
2637 case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
2638 #line 626 "pikchr.y"
2639 {pik_move_hdg(p,&yymsp[-1].minor.yy10,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
2640 #line 2665 "pikchr.c"
2641 break;
2642 case 44: /* attribute ::= AT position */
2643 #line 631 "pikchr.y"
2644 { pik_set_at(p,0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
2645 #line 2670 "pikchr.c"
2646 break;
2647 case 45: /* attribute ::= SAME */
2648 #line 633 "pikchr.y"
2649 {pik_same(p,0,&yymsp[0].minor.yy0);}
2650 #line 2675 "pikchr.c"
2651 break;
2652 case 46: /* attribute ::= SAME AS object */
2653 #line 634 "pikchr.y"
2654 {pik_same(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2655 #line 2680 "pikchr.c"
2656 break;
2657 case 47: /* attribute ::= STRING textposition */
2658 #line 635 "pikchr.y"
2659 {pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy164);}
2660 #line 2685 "pikchr.c"
2661 break;
2662 case 48: /* attribute ::= FIT */
2663 #line 636 "pikchr.y"
2664 {pik_size_to_fit(p,&yymsp[0].minor.yy0,3); }
2665 #line 2690 "pikchr.c"
2666 break;
2667 case 49: /* attribute ::= BEHIND object */
2668 #line 637 "pikchr.y"
2669 {pik_behind(p,yymsp[0].minor.yy36);}
2670 #line 2695 "pikchr.c"
2671 break;
2672 case 50: /* withclause ::= DOT_E edge AT position */
2673 case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
2674 #line 645 "pikchr.y"
2675 { pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); }
2676 #line 2701 "pikchr.c"
2677 break;
2678 case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
2679 #line 649 "pikchr.y"
2680 {yylhsminor.yy0 = yymsp[0].minor.yy0;}
2681 #line 2706 "pikchr.c"
2682 yymsp[0].minor.yy0 = yylhsminor.yy0;
2683 break;
2684 case 53: /* boolproperty ::= CW */
2685 #line 660 "pikchr.y"
2686 {p->cur->cw = 1;}
2687 #line 2712 "pikchr.c"
2688 break;
2689 case 54: /* boolproperty ::= CCW */
2690 #line 661 "pikchr.y"
2691 {p->cur->cw = 0;}
2692 #line 2717 "pikchr.c"
2693 break;
2694 case 55: /* boolproperty ::= LARROW */
2695 #line 662 "pikchr.y"
2696 {p->cur->larrow=1; p->cur->rarrow=0; }
2697 #line 2722 "pikchr.c"
2698 break;
2699 case 56: /* boolproperty ::= RARROW */
2700 #line 663 "pikchr.y"
2701 {p->cur->larrow=0; p->cur->rarrow=1; }
2702 #line 2727 "pikchr.c"
2703 break;
2704 case 57: /* boolproperty ::= LRARROW */
2705 #line 664 "pikchr.y"
2706 {p->cur->larrow=1; p->cur->rarrow=1; }
2707 #line 2732 "pikchr.c"
2708 break;
2709 case 58: /* boolproperty ::= INVIS */
2710 #line 665 "pikchr.y"
2711 {p->cur->sw = 0.0;}
2712 #line 2737 "pikchr.c"
2713 break;
2714 case 59: /* boolproperty ::= THICK */
2715 #line 666 "pikchr.y"
2716 {p->cur->sw *= 1.5;}
2717 #line 2742 "pikchr.c"
2718 break;
2719 case 60: /* boolproperty ::= THIN */
2720 #line 667 "pikchr.y"
2721 {p->cur->sw *= 0.67;}
2722 #line 2747 "pikchr.c"
2723 break;
2724 case 61: /* boolproperty ::= SOLID */
2725 #line 668 "pikchr.y"
2726 {p->cur->sw = pik_value(p,"thickness",9,0);
2727 p->cur->dotted = p->cur->dashed = 0.0;}
2728 #line 2753 "pikchr.c"
2729 break;
2730 case 62: /* textposition ::= */
2731 #line 671 "pikchr.y"
2732 {yymsp[1].minor.yy164 = 0;}
2733 #line 2758 "pikchr.c"
2734 break;
2735 case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|ALIGNED|BIG|SMALL */
2736 #line 674 "pikchr.y"
2737 {yylhsminor.yy164 = (short int)pik_text_position(yymsp[-1].minor.yy164,&yymsp[0].minor.yy0);}
2738 #line 2763 "pikchr.c"
2739 yymsp[-1].minor.yy164 = yylhsminor.yy164;
2740 break;
2741 case 64: /* position ::= expr COMMA expr */
2742 #line 677 "pikchr.y"
2743 {yylhsminor.yy79.x=yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[0].minor.yy153;}
2744 #line 2769 "pikchr.c"
2745 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2746 break;
2747 case 65: /* position ::= place PLUS expr COMMA expr */
2748 #line 679 "pikchr.y"
2749 {yylhsminor.yy79.x=yymsp[-4].minor.yy79.x+yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y+yymsp[0].minor.yy153;}
2750 #line 2775 "pikchr.c"
2751 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2752 break;
2753 case 66: /* position ::= place MINUS expr COMMA expr */
2754 #line 680 "pikchr.y"
2755 {yylhsminor.yy79.x=yymsp[-4].minor.yy79.x-yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y-yymsp[0].minor.yy153;}
2756 #line 2781 "pikchr.c"
2757 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2758 break;
2759 case 67: /* position ::= place PLUS LP expr COMMA expr RP */
2760 #line 682 "pikchr.y"
2761 {yylhsminor.yy79.x=yymsp[-6].minor.yy79.x+yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y+yymsp[-1].minor.yy153;}
2762 #line 2787 "pikchr.c"
2763 yymsp[-6].minor.yy79 = yylhsminor.yy79;
2764 break;
2765 case 68: /* position ::= place MINUS LP expr COMMA expr RP */
2766 #line 684 "pikchr.y"
2767 {yylhsminor.yy79.x=yymsp[-6].minor.yy79.x-yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y-yymsp[-1].minor.yy153;}
2768 #line 2793 "pikchr.c"
2769 yymsp[-6].minor.yy79 = yylhsminor.yy79;
2770 break;
2771 case 69: /* position ::= LP position COMMA position RP */
2772 #line 685 "pikchr.y"
2773 {yymsp[-4].minor.yy79.x=yymsp[-3].minor.yy79.x; yymsp[-4].minor.yy79.y=yymsp[-1].minor.yy79.y;}
2774 #line 2799 "pikchr.c"
2775 break;
2776 case 70: /* position ::= LP position RP */
2777 #line 686 "pikchr.y"
2778 {yymsp[-2].minor.yy79=yymsp[-1].minor.yy79;}
2779 #line 2804 "pikchr.c"
2780 break;
2781 case 71: /* position ::= expr between position AND position */
2782 #line 688 "pikchr.y"
2783 {yylhsminor.yy79 = pik_position_between(yymsp[-4].minor.yy153,yymsp[-2].minor.yy79,yymsp[0].minor.yy79);}
2784 #line 2809 "pikchr.c"
2785 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2786 break;
2787 case 72: /* position ::= expr LT position COMMA position GT */
2788 #line 690 "pikchr.y"
2789 {yylhsminor.yy79 = pik_position_between(yymsp[-5].minor.yy153,yymsp[-3].minor.yy79,yymsp[-1].minor.yy79);}
2790 #line 2815 "pikchr.c"
2791 yymsp[-5].minor.yy79 = yylhsminor.yy79;
2792 break;
2793 case 73: /* position ::= expr ABOVE position */
2794 #line 691 "pikchr.y"
2795 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y += yymsp[-2].minor.yy153;}
2796 #line 2821 "pikchr.c"
2797 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2798 break;
2799 case 74: /* position ::= expr BELOW position */
2800 #line 692 "pikchr.y"
2801 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y -= yymsp[-2].minor.yy153;}
2802 #line 2827 "pikchr.c"
2803 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2804 break;
2805 case 75: /* position ::= expr LEFT OF position */
2806 #line 693 "pikchr.y"
2807 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x -= yymsp[-3].minor.yy153;}
2808 #line 2833 "pikchr.c"
2809 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2810 break;
2811 case 76: /* position ::= expr RIGHT OF position */
2812 #line 694 "pikchr.y"
2813 {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x += yymsp[-3].minor.yy153;}
2814 #line 2839 "pikchr.c"
2815 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2816 break;
2817 case 77: /* position ::= expr ON HEADING EDGEPT OF position */
2818 #line 696 "pikchr.y"
2819 {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-5].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2820 #line 2845 "pikchr.c"
2821 yymsp[-5].minor.yy79 = yylhsminor.yy79;
2822 break;
2823 case 78: /* position ::= expr HEADING EDGEPT OF position */
2824 #line 698 "pikchr.y"
2825 {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-4].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2826 #line 2851 "pikchr.c"
2827 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2828 break;
2829 case 79: /* position ::= expr EDGEPT OF position */
2830 #line 700 "pikchr.y"
2831 {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);}
2832 #line 2857 "pikchr.c"
2833 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2834 break;
2835 case 80: /* position ::= expr ON HEADING expr FROM position */
2836 #line 702 "pikchr.y"
2837 {yylhsminor.yy79 = pik_position_at_angle(yymsp[-5].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
2838 #line 2863 "pikchr.c"
2839 yymsp[-5].minor.yy79 = yylhsminor.yy79;
2840 break;
2841 case 81: /* position ::= expr HEADING expr FROM position */
2842 #line 704 "pikchr.y"
2843 {yylhsminor.yy79 = pik_position_at_angle(yymsp[-4].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);}
2844 #line 2869 "pikchr.c"
2845 yymsp[-4].minor.yy79 = yylhsminor.yy79;
2846 break;
2847 case 82: /* place ::= edge OF object */
2848 #line 716 "pikchr.y"
2849 {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2850 #line 2875 "pikchr.c"
2851 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2852 break;
2853 case 83: /* place2 ::= object */
2854 #line 717 "pikchr.y"
2855 {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,0);}
2856 #line 2881 "pikchr.c"
2857 yymsp[0].minor.yy79 = yylhsminor.yy79;
2858 break;
2859 case 84: /* place2 ::= object DOT_E edge */
2860 #line 718 "pikchr.y"
2861 {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
2862 #line 2887 "pikchr.c"
2863 yymsp[-2].minor.yy79 = yylhsminor.yy79;
2864 break;
2865 case 85: /* place2 ::= NTH VERTEX OF object */
2866 #line 719 "pikchr.y"
2867 {yylhsminor.yy79 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy36);}
2868 #line 2893 "pikchr.c"
2869 yymsp[-3].minor.yy79 = yylhsminor.yy79;
2870 break;
2871 case 86: /* object ::= nth */
2872 #line 731 "pikchr.y"
2873 {yylhsminor.yy36 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
2874 #line 2899 "pikchr.c"
2875 yymsp[0].minor.yy36 = yylhsminor.yy36;
2876 break;
2877 case 87: /* object ::= nth OF|IN object */
2878 #line 732 "pikchr.y"
2879 {yylhsminor.yy36 = pik_find_nth(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);}
2880 #line 2905 "pikchr.c"
2881 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2882 break;
2883 case 88: /* objectname ::= THIS */
2884 #line 734 "pikchr.y"
2885 {yymsp[0].minor.yy36 = p->cur;}
2886 #line 2911 "pikchr.c"
2887 break;
2888 case 89: /* objectname ::= PLACENAME */
2889 #line 735 "pikchr.y"
2890 {yylhsminor.yy36 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
2891 #line 2916 "pikchr.c"
2892 yymsp[0].minor.yy36 = yylhsminor.yy36;
2893 break;
2894 case 90: /* objectname ::= objectname DOT_U PLACENAME */
2895 #line 737 "pikchr.y"
2896 {yylhsminor.yy36 = pik_find_byname(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
2897 #line 2922 "pikchr.c"
2898 yymsp[-2].minor.yy36 = yylhsminor.yy36;
2899 break;
2900 case 91: /* nth ::= NTH CLASSNAME */
2901 #line 739 "pikchr.y"
2902 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
2903 #line 2928 "pikchr.c"
2904 yymsp[-1].minor.yy0 = yylhsminor.yy0;
2905 break;
2906 case 92: /* nth ::= NTH LAST CLASSNAME */
2907 #line 740 "pikchr.y"
2908 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
2909 #line 2934 "pikchr.c"
2910 yymsp[-2].minor.yy0 = yylhsminor.yy0;
2911 break;
2912 case 93: /* nth ::= LAST CLASSNAME */
2913 #line 741 "pikchr.y"
2914 {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
2915 #line 2940 "pikchr.c"
2916 break;
2917 case 94: /* nth ::= LAST */
2918 #line 742 "pikchr.y"
2919 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
2920 #line 2945 "pikchr.c"
2921 yymsp[0].minor.yy0 = yylhsminor.yy0;
2922 break;
2923 case 95: /* nth ::= NTH LB RB */
2924 #line 743 "pikchr.y"
2925 {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
2926 #line 2951 "pikchr.c"
2927 yymsp[-2].minor.yy0 = yylhsminor.yy0;
2928 break;
2929 case 96: /* nth ::= NTH LAST LB RB */
2930 #line 744 "pikchr.y"
2931 {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
2932 #line 2957 "pikchr.c"
2933 yymsp[-3].minor.yy0 = yylhsminor.yy0;
2934 break;
2935 case 97: /* nth ::= LAST LB RB */
2936 #line 745 "pikchr.y"
2937 {yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
2938 #line 2963 "pikchr.c"
2939 break;
2940 case 98: /* expr ::= expr PLUS expr */
2941 #line 747 "pikchr.y"
2942 {yylhsminor.yy153=yymsp[-2].minor.yy153+yymsp[0].minor.yy153;}
2943 #line 2968 "pikchr.c"
2944 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2945 break;
2946 case 99: /* expr ::= expr MINUS expr */
2947 #line 748 "pikchr.y"
2948 {yylhsminor.yy153=yymsp[-2].minor.yy153-yymsp[0].minor.yy153;}
2949 #line 2974 "pikchr.c"
2950 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2951 break;
2952 case 100: /* expr ::= expr STAR expr */
2953 #line 749 "pikchr.y"
2954 {yylhsminor.yy153=yymsp[-2].minor.yy153*yymsp[0].minor.yy153;}
2955 #line 2980 "pikchr.c"
2956 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2957 break;
2958 case 101: /* expr ::= expr SLASH expr */
2959 #line 750 "pikchr.y"
2960 {
2961 if( yymsp[0].minor.yy153==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy153 = 0.0; }
2962 else{ yylhsminor.yy153 = yymsp[-2].minor.yy153/yymsp[0].minor.yy153; }
2963 }
2964 #line 2989 "pikchr.c"
2965 yymsp[-2].minor.yy153 = yylhsminor.yy153;
2966 break;
2967 case 102: /* expr ::= MINUS expr */
2968 #line 754 "pikchr.y"
2969 {yymsp[-1].minor.yy153=-yymsp[0].minor.yy153;}
2970 #line 2995 "pikchr.c"
2971 break;
2972 case 103: /* expr ::= PLUS expr */
2973 #line 755 "pikchr.y"
2974 {yymsp[-1].minor.yy153=yymsp[0].minor.yy153;}
2975 #line 3000 "pikchr.c"
2976 break;
2977 case 104: /* expr ::= LP expr RP */
2978 #line 756 "pikchr.y"
2979 {yymsp[-2].minor.yy153=yymsp[-1].minor.yy153;}
2980 #line 3005 "pikchr.c"
2981 break;
2982 case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
2983 #line 757 "pikchr.y"
2984 {yymsp[-2].minor.yy153=pik_get_var(p,&yymsp[-1].minor.yy0);}
2985 #line 3010 "pikchr.c"
2986 break;
2987 case 106: /* expr ::= NUMBER */
2988 #line 758 "pikchr.y"
2989 {yylhsminor.yy153=pik_atof(&yymsp[0].minor.yy0);}
2990 #line 3015 "pikchr.c"
2991 yymsp[0].minor.yy153 = yylhsminor.yy153;
2992 break;
2993 case 107: /* expr ::= ID */
2994 #line 759 "pikchr.y"
2995 {yylhsminor.yy153=pik_get_var(p,&yymsp[0].minor.yy0);}
2996 #line 3021 "pikchr.c"
2997 yymsp[0].minor.yy153 = yylhsminor.yy153;
2998 break;
2999 case 108: /* expr ::= FUNC1 LP expr RP */
3000 #line 760 "pikchr.y"
3001 {yylhsminor.yy153 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy153,0.0);}
3002 #line 3027 "pikchr.c"
3003 yymsp[-3].minor.yy153 = yylhsminor.yy153;
3004 break;
3005 case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
3006 #line 761 "pikchr.y"
3007 {yylhsminor.yy153 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy153,yymsp[-1].minor.yy153);}
3008 #line 3033 "pikchr.c"
3009 yymsp[-5].minor.yy153 = yylhsminor.yy153;
3010 break;
3011 case 110: /* expr ::= DIST LP position COMMA position RP */
3012 #line 762 "pikchr.y"
3013 {yymsp[-5].minor.yy153 = pik_dist(&yymsp[-3].minor.yy79,&yymsp[-1].minor.yy79);}
3014 #line 3039 "pikchr.c"
3015 break;
3016 case 111: /* expr ::= place2 DOT_XY X */
3017 #line 763 "pikchr.y"
3018 {yylhsminor.yy153 = yymsp[-2].minor.yy79.x;}
3019 #line 3044 "pikchr.c"
3020 yymsp[-2].minor.yy153 = yylhsminor.yy153;
3021 break;
3022 case 112: /* expr ::= place2 DOT_XY Y */
3023 #line 764 "pikchr.y"
3024 {yylhsminor.yy153 = yymsp[-2].minor.yy79.y;}
3025 #line 3050 "pikchr.c"
3026 yymsp[-2].minor.yy153 = yylhsminor.yy153;
3027 break;
3028 case 113: /* expr ::= object DOT_L numproperty */
3029 case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
3030 case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
3031 #line 765 "pikchr.y"
3032 {yylhsminor.yy153=pik_property_of(yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);}
3033 #line 3058 "pikchr.c"
3034 yymsp[-2].minor.yy153 = yylhsminor.yy153;
3035 break;
3036 default:
3037 /* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
3038 /* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
@@ -3126,19 +3131,19 @@
3131 ){
3132 pik_parserARG_FETCH
3133 pik_parserCTX_FETCH
3134 #define TOKEN yyminor
3135 /************ Begin %syntax_error code ****************************************/
3136 #line 525 "pikchr.y"
3137
3138 if( TOKEN.z && TOKEN.z[0] ){
3139 pik_error(p, &TOKEN, "syntax error");
3140 }else{
3141 pik_error(p, 0, "syntax error");
3142 }
3143 UNUSED_PARAMETER(yymajor);
3144 #line 3169 "pikchr.c"
3145 /************ End %syntax_error code ******************************************/
3146 pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
3147 pik_parserCTX_STORE
3148 }
3149
@@ -3367,11 +3372,11 @@
3372 #else
3373 (void)iToken;
3374 return 0;
3375 #endif
3376 }
3377 #line 770 "pikchr.y"
3378
3379
3380
3381 /* Chart of the 148 official CSS color names with their
3382 ** corresponding RGB values thru Color Module Level 4:
@@ -3811,11 +3816,11 @@
3816 static PPoint circleChop(Pik *p, PObj *pObj, PPoint *pPt){
3817 PPoint chop;
3818 PNum dx = pPt->x - pObj->ptAt.x;
3819 PNum dy = pPt->y - pObj->ptAt.y;
3820 PNum dist = hypot(dx,dy);
3821 if( dist<pObj->rad || dist<=0 ) return pObj->ptAt;
3822 chop.x = pObj->ptAt.x + dx*pObj->rad/dist;
3823 chop.y = pObj->ptAt.y + dy*pObj->rad/dist;
3824 UNUSED_PARAMETER(p);
3825 return chop;
3826 }
@@ -4510,11 +4515,11 @@
4515 if( z==0 ){
4516 pik_error(p, 0, 0);
4517 return;
4518 }
4519 p->zOut = z;
4520 p->nOutAlloc = nNew;
4521 }
4522 memcpy(p->zOut+p->nOut, zText, n);
4523 p->nOut += n;
4524 p->zOut[p->nOut] = 0;
4525 }
@@ -4636,27 +4641,27 @@
4641 ** on the value.
4642 */
4643 static void pik_append_x(Pik *p, const char *z1, PNum v, const char *z2){
4644 char buf[200];
4645 v -= p->bbox.sw.x;
4646 snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, pik_round(p->rScale*v), z2);
4647 buf[sizeof(buf)-1] = 0;
4648 pik_append(p, buf, -1);
4649 }
4650 static void pik_append_y(Pik *p, const char *z1, PNum v, const char *z2){
4651 char buf[200];
4652 v = p->bbox.ne.y - v;
4653 snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, pik_round(p->rScale*v), z2);
4654 buf[sizeof(buf)-1] = 0;
4655 pik_append(p, buf, -1);
4656 }
4657 static void pik_append_xy(Pik *p, const char *z1, PNum x, PNum y){
4658 char buf[200];
4659 x = x - p->bbox.sw.x;
4660 y = p->bbox.ne.y - y;
4661 snprintf(buf, sizeof(buf)-1, "%s%d,%d", z1,
4662 pik_round(p->rScale*x), pik_round(p->rScale*y));
4663 buf[sizeof(buf)-1] = 0;
4664 pik_append(p, buf, -1);
4665 }
4666 static void pik_append_dis(Pik *p, const char *z1, PNum v, const char *z2){
4667 char buf[200];
@@ -4672,11 +4677,11 @@
4677 ** foreground color if false. The distinction only matters for color
4678 ** inversions in PIKCHR_DARK_MODE.
4679 */
4680 static void pik_append_clr(Pik *p,const char *z1,PNum v,const char *z2,int bg){
4681 char buf[200];
4682 int x = pik_round(v);
4683 int r, g, b;
4684 if( x==0 && p->fgcolor>0 && !bg ){
4685 x = p->fgcolor;
4686 }else if( bg && x>=0xffffff && p->bgcolor>0 ){
4687 x = p->bgcolor;
@@ -4698,12 +4703,12 @@
4703 static void pik_append_arc(Pik *p, PNum r1, PNum r2, PNum x, PNum y){
4704 char buf[200];
4705 x = x - p->bbox.sw.x;
4706 y = p->bbox.ne.y - y;
4707 snprintf(buf, sizeof(buf)-1, "A%d %d 0 0 0 %d %d",
4708 pik_round(p->rScale*r1), pik_round(p->rScale*r2),
4709 pik_round(p->rScale*x), pik_round(p->rScale*y));
4710 buf[sizeof(buf)-1] = 0;
4711 pik_append(p, buf, -1);
4712 }
4713
4714 /* Append a style="..." text. But, leave the quote unterminated, in case
@@ -5241,10 +5246,21 @@
5246 /* Return true if a bounding box is empty.
5247 */
5248 static int pik_bbox_isempty(PBox *p){
5249 return p->sw.x>p->ne.x;
5250 }
5251
5252 /* Return true if point pPt is contained within the bounding box pBox
5253 */
5254 static int pik_bbox_contains_point(PBox *pBox, PPoint *pPt){
5255 if( pik_bbox_isempty(pBox) ) return 0;
5256 if( pPt->x < pBox->sw.x ) return 0;
5257 if( pPt->x > pBox->ne.x ) return 0;
5258 if( pPt->y < pBox->sw.y ) return 0;
5259 if( pPt->y > pBox->ne.y ) return 0;
5260 return 1;
5261 }
5262
5263 /* Initialize a bounding box to an empty container
5264 */
5265 static void pik_bbox_init(PBox *p){
5266 p->sw.x = 1.0;
@@ -5391,11 +5407,11 @@
5407 }
5408 }
5409 p->aTPath[0] = pNew->ptAt;
5410 pNew->with = pNew->ptAt;
5411 pNew->outDir = pNew->inDir = p->eDir;
5412 pNew->iLayer = pik_value_int(p, "layer", 5, &miss);
5413 if( miss ) pNew->iLayer = 1000;
5414 if( pNew->iLayer<0 ) pNew->iLayer = 0;
5415 if( pSublist ){
5416 pNew->type = &sublistClass;
5417 pNew->pSublist = pSublist;
@@ -5837,10 +5853,38 @@
5853 p->mTPath |= 1;
5854 break;
5855 }
5856 pObj->outDir = pDir->eCode;
5857 }
5858
5859 /* If the last referenced object is centered at point pPt then return
5860 ** a pointer to that object. If there is no prior object reference,
5861 ** or if the points are not the same, return NULL.
5862 **
5863 ** This is a side-channel hack used to find the objects at which a
5864 ** line begins and ends. For example, in
5865 **
5866 ** arrow from OBJ1 to OBJ2 chop
5867 **
5868 ** The arrow object is normally just handed the coordinates of the
5869 ** centers for OBJ1 and OBJ2. But we also want to know the specific
5870 ** object named in case there are multiple objects centered at the
5871 ** same point.
5872 **
5873 ** See forum post 1d46e3a0bc
5874 */
5875 static PObj *pik_last_ref_object(Pik *p, PPoint *pPt){
5876 PObj *pRes = 0;
5877 if( p->lastRef==0 ) return 0;
5878 if( p->lastRef->ptAt.x==pPt->x
5879 && p->lastRef->ptAt.y==pPt->y
5880 ){
5881 pRes = p->lastRef;
5882 }
5883 p->lastRef = 0;
5884 return pRes;
5885 }
5886
5887 /* Set the "from" of an object
5888 */
5889 static void pik_set_from(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
5890 if( !pObj->type->isLine ){
@@ -5865,10 +5909,11 @@
5909 }
5910 }
5911 p->aTPath[0] = *pPt;
5912 p->mTPath = 3;
5913 pObj->mProp |= A_FROM;
5914 pObj->pFrom = pik_last_ref_object(p, pPt);
5915 }
5916
5917 /* Set the "to" of an object
5918 */
5919 static void pik_add_to(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
@@ -5885,10 +5930,11 @@
5930 if( n==0 || p->mTPath==3 || p->thenFlag ){
5931 n = pik_next_rpath(p, pTk);
5932 }
5933 p->aTPath[n] = *pPt;
5934 p->mTPath = 3;
5935 pObj->pTo = pik_last_ref_object(p, pPt);
5936 }
5937
5938 static void pik_close_path(Pik *p, PToken *pErr){
5939 PObj *pObj = p->cur;
5940 if( p->nTPath<3 ){
@@ -6220,10 +6266,20 @@
6266 break;
6267 default: pVar->val = val; break;
6268 }
6269 p->bLayoutVars = 0; /* Clear the layout setting cache */
6270 }
6271
6272 /*
6273 ** Round a PNum into the nearest integer
6274 */
6275 static int pik_round(PNum v){
6276 if( isnan(v) ) return 0;
6277 if( v < -2147483647 ) return -2147483648;
6278 if( v >= 2147483647 ) return 2147483647;
6279 return (int)v;
6280 }
6281
6282 /*
6283 ** Search for the variable named z[0..n-1] in:
6284 **
6285 ** * Application defined variables
@@ -6258,10 +6314,13 @@
6314 last = mid-1;
6315 }
6316 }
6317 if( pMiss ) *pMiss = 1;
6318 return 0.0;
6319 }
6320 static int pik_value_int(Pik *p, const char *z, int n, int *pMiss){
6321 return pik_round(pik_value(p,z,n,pMiss));
6322 }
6323
6324 /*
6325 ** Look up a color-name. Unlike other names in this program, the
6326 ** color-names are not case sensitive. So "DarkBlue" and "darkblue"
@@ -6413,10 +6472,11 @@
6472 }
6473 /* First look explicitly tagged objects */
6474 for(i=pList->n-1; i>=0; i--){
6475 PObj *pObj = pList->a[i];
6476 if( pObj->zName && pik_token_eq(pName,pObj->zName)==0 ){
6477 p->lastRef = pObj;
6478 return pObj;
6479 }
6480 }
6481 /* If not found, do a second pass looking for any object containing
6482 ** text which exactly matches pName */
@@ -6423,10 +6483,11 @@
6483 for(i=pList->n-1; i>=0; i--){
6484 PObj *pObj = pList->a[i];
6485 for(j=0; j<pObj->nTxt; j++){
6486 if( pObj->aTxt[j].n==pName->n+2
6487 && memcmp(pObj->aTxt[j].z+1,pName->z,pName->n)==0 ){
6488 p->lastRef = pObj;
6489 return pObj;
6490 }
6491 }
6492 }
6493 pik_error(p, pName, "no such object");
@@ -6557,26 +6618,28 @@
6618
6619 /* Return the value of a property of an object.
6620 */
6621 static PNum pik_property_of(PObj *pObj, PToken *pProp){
6622 PNum v = 0.0;
6623 if( pObj ){
6624 switch( pProp->eType ){
6625 case T_HEIGHT: v = pObj->h; break;
6626 case T_WIDTH: v = pObj->w; break;
6627 case T_RADIUS: v = pObj->rad; break;
6628 case T_DIAMETER: v = pObj->rad*2.0; break;
6629 case T_THICKNESS: v = pObj->sw; break;
6630 case T_DASHED: v = pObj->dashed; break;
6631 case T_DOTTED: v = pObj->dotted; break;
6632 case T_FILL: v = pObj->fill; break;
6633 case T_COLOR: v = pObj->color; break;
6634 case T_X: v = pObj->ptAt.x; break;
6635 case T_Y: v = pObj->ptAt.y; break;
6636 case T_TOP: v = pObj->bbox.ne.y; break;
6637 case T_BOTTOM: v = pObj->bbox.sw.y; break;
6638 case T_LEFT: v = pObj->bbox.sw.x; break;
6639 case T_RIGHT: v = pObj->bbox.ne.x; break;
6640 }
6641 }
6642 return v;
6643 }
6644
6645 /* Compute one of the built-in functions
@@ -6618,40 +6681,49 @@
6681 }
6682 return;
6683 }
6684
6685 /*
6686 ** Search for object located at *pCenter that has an xChop method and
6687 ** that does not enclose point pOther.
6688 **
6689 ** Return a pointer to the object, or NULL if not found.
6690 */
6691 static PObj *pik_find_chopper(PList *pList, PPoint *pCenter, PPoint *pOther){
6692 int i;
6693 if( pList==0 ) return 0;
6694 for(i=pList->n-1; i>=0; i--){
6695 PObj *pObj = pList->a[i];
6696 if( pObj->type->xChop!=0
6697 && pObj->ptAt.x==pCenter->x
6698 && pObj->ptAt.y==pCenter->y
6699 && !pik_bbox_contains_point(&pObj->bbox, pOther)
6700 ){
6701 return pObj;
6702 }else if( pObj->pSublist ){
6703 pObj = pik_find_chopper(pObj->pSublist,pCenter,pOther);
6704 if( pObj ) return pObj;
6705 }
6706 }
6707 return 0;
6708 }
6709
6710 /*
6711 ** There is a line traveling from pFrom to pTo.
6712 **
6713 ** If pObj is not null and is a choppable object, then chop at
6714 ** the boundary of pObj - where the line crosses the boundary
6715 ** of pObj.
6716 **
6717 ** If pObj is NULL or has no xChop method, then search for some
6718 ** other object centered at pTo that is choppable and use it
6719 ** instead.
6720 */
6721 static void pik_autochop(Pik *p, PPoint *pFrom, PPoint *pTo, PObj *pObj){
6722 if( pObj==0 || pObj->type->xChop==0 ){
6723 pObj = pik_find_chopper(p->list, pTo, pFrom);
6724 }
6725 if( pObj ){
6726 *pTo = pObj->type->xChop(p, pObj, pFrom);
6727 }
6728 }
6729
@@ -6746,12 +6818,12 @@
6818 ** If the line goes to the center of an object with an
6819 ** xChop method, then use the xChop method to trim the line.
6820 */
6821 if( pObj->bChop && pObj->nPath>=2 ){
6822 int n = pObj->nPath;
6823 pik_autochop(p, &pObj->aPath[n-2], &pObj->aPath[n-1], pObj->pTo);
6824 pik_autochop(p, &pObj->aPath[1], &pObj->aPath[0], pObj->pFrom);
6825 }
6826
6827 pObj->ptEnter = pObj->aPath[0];
6828 pObj->ptExit = pObj->aPath[pObj->nPath-1];
6829
@@ -6842,11 +6914,11 @@
6914 int i;
6915 int iNextLayer = 0;
6916 int iThisLayer;
6917 int bMoreToDo;
6918 int miss = 0;
6919 int mDebug = pik_value_int(p, "debug", 5, 0);
6920 PNum colorLabel;
6921 do{
6922 bMoreToDo = 0;
6923 iThisLayer = iNextLayer;
6924 iNextLayer = 0x7fffffff;
@@ -6960,24 +7032,24 @@
7032 if( thickness<=0.01 ) thickness = 0.01;
7033 margin = pik_value(p,"margin",6,0);
7034 margin += thickness;
7035 wArrow = p->wArrow*thickness;
7036 miss = 0;
7037 p->fgcolor = pik_value_int(p,"fgcolor",7,&miss);
7038 if( miss ){
7039 PToken t;
7040 t.z = "fgcolor";
7041 t.n = 7;
7042 p->fgcolor = pik_round(pik_lookup_color(0, &t));
7043 }
7044 miss = 0;
7045 p->bgcolor = pik_value_int(p,"bgcolor",7,&miss);
7046 if( miss ){
7047 PToken t;
7048 t.z = "bgcolor";
7049 t.n = 7;
7050 p->bgcolor = pik_round(pik_lookup_color(0, &t));
7051 }
7052
7053 /* Compute a bounding box over all objects so that we can know
7054 ** how big to declare the SVG canvas */
7055 pik_bbox_init(&p->bbox);
@@ -6997,18 +7069,18 @@
7069 pik_append(p, p->zClass, -1);
7070 pik_append(p, "\"", 1);
7071 }
7072 w = p->bbox.ne.x - p->bbox.sw.x;
7073 h = p->bbox.ne.y - p->bbox.sw.y;
7074 p->wSVG = pik_round(p->rScale*w);
7075 p->hSVG = pik_round(p->rScale*h);
7076 pikScale = pik_value(p,"scale",5,0);
7077 if( pikScale>=0.001 && pikScale<=1000.0
7078 && (pikScale<0.99 || pikScale>1.01)
7079 ){
7080 p->wSVG = pik_round(p->wSVG*pikScale);
7081 p->hSVG = pik_round(p->hSVG*pikScale);
7082 pik_append_num(p, " width=\"", p->wSVG);
7083 pik_append_num(p, "\" height=\"", p->hSVG);
7084 pik_append(p, "\"", 1);
7085 }
7086 pik_append_dis(p, " viewBox=\"0 0 ",w,"");
@@ -7749,15 +7821,16 @@
7821 #if defined(PIKCHR_FUZZ)
7822 #include <stdint.h>
7823 int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
7824 int w,h;
7825 char *zIn, *zOut;
7826 unsigned int mFlags = nByte & 3;
7827 zIn = malloc( nByte + 1 );
7828 if( zIn==0 ) return 0;
7829 memcpy(zIn, aData, nByte);
7830 zIn[nByte] = 0;
7831 zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
7832 free(zIn);
7833 free(zOut);
7834 return 0;
7835 }
7836 #endif /* PIKCHR_FUZZ */
@@ -7988,19 +8061,26 @@
8061 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(w));
8062 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(h));
8063 Tcl_SetObjResult(interp, pRes);
8064 return TCL_OK;
8065 }
8066
8067 #ifndef PACKAGE_NAME
8068 # define PACKAGE_NAME "pikchr"
8069 #endif
8070 #ifndef PACKAGE_VERSION
8071 # define PACKAGE_VERSION "1.0"
8072 #endif
8073
8074 /* Invoke this routine to register the "pikchr" command with the interpreter
8075 ** given in the argument */
8076 int Pikchr_Init(Tcl_Interp *interp){
8077 Tcl_CreateObjCommand(interp, "pikchr", pik_tcl_command, 0, 0);
8078 Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION);
8079 return TCL_OK;
8080 }
8081
8082
8083 #endif /* PIKCHR_TCL */
8084
8085
8086 #line 8111 "pikchr.c"
8087
+4 -2
--- src/printf.c
+++ src/printf.c
@@ -102,11 +102,13 @@
102102
#define etSTRINGID 23 /* String with length limit for a hash prefix: %S */
103103
#define etROOT 24 /* String value of g.zTop: %R */
104104
#define etJSONSTR 25 /* String encoded as a JSON string literal: %j
105105
Use %!j to include double-quotes around it. */
106106
#define etSHELLESC 26 /* Escape a filename for use in a shell command: %$
107
- See blob_append_escaped_arg() for details */
107
+ See blob_append_escaped_arg() for details
108
+ "%$" -> adds "./" prefix if necessary.
109
+ "%!$" -> omits the "./" prefix. */
108110
109111
110112
/*
111113
** An "etByte" is an 8-bit unsigned value.
112114
*/
@@ -838,11 +840,11 @@
838840
length = width = 0;
839841
break;
840842
}
841843
case etSHELLESC: {
842844
char *zArg = va_arg(ap, char*);
843
- blob_append_escaped_arg(pBlob, zArg);
845
+ blob_append_escaped_arg(pBlob, zArg, !flag_altform2);
844846
length = width = 0;
845847
break;
846848
}
847849
case etERROR:
848850
buf[0] = '%';
849851
--- src/printf.c
+++ src/printf.c
@@ -102,11 +102,13 @@
102 #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */
103 #define etROOT 24 /* String value of g.zTop: %R */
104 #define etJSONSTR 25 /* String encoded as a JSON string literal: %j
105 Use %!j to include double-quotes around it. */
106 #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$
107 See blob_append_escaped_arg() for details */
 
 
108
109
110 /*
111 ** An "etByte" is an 8-bit unsigned value.
112 */
@@ -838,11 +840,11 @@
838 length = width = 0;
839 break;
840 }
841 case etSHELLESC: {
842 char *zArg = va_arg(ap, char*);
843 blob_append_escaped_arg(pBlob, zArg);
844 length = width = 0;
845 break;
846 }
847 case etERROR:
848 buf[0] = '%';
849
--- src/printf.c
+++ src/printf.c
@@ -102,11 +102,13 @@
102 #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */
103 #define etROOT 24 /* String value of g.zTop: %R */
104 #define etJSONSTR 25 /* String encoded as a JSON string literal: %j
105 Use %!j to include double-quotes around it. */
106 #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$
107 See blob_append_escaped_arg() for details
108 "%$" -> adds "./" prefix if necessary.
109 "%!$" -> omits the "./" prefix. */
110
111
112 /*
113 ** An "etByte" is an 8-bit unsigned value.
114 */
@@ -838,11 +840,11 @@
840 length = width = 0;
841 break;
842 }
843 case etSHELLESC: {
844 char *zArg = va_arg(ap, char*);
845 blob_append_escaped_arg(pBlob, zArg, !flag_altform2);
846 length = width = 0;
847 break;
848 }
849 case etERROR:
850 buf[0] = '%';
851
+70 -24
--- src/report.c
+++ src/report.c
@@ -27,10 +27,18 @@
2727
2828
#ifndef SQLITE_RECURSIVE
2929
# define SQLITE_RECURSIVE 33
3030
#endif
3131
32
+/* Settings that can be used to control ticket reports */
33
+/*
34
+** SETTING: ticket-default-report width=80
35
+** If this setting has a string value, then when the ticket
36
+** search page query is blank, the report with this title is shown.
37
+** If the setting is blank (default), then no report is shown.
38
+*/
39
+
3240
/*
3341
** WEBPAGE: reportlist
3442
**
3543
** Main menu for Tickets.
3644
*/
@@ -38,10 +46,11 @@
3846
const char *zScript;
3947
Blob ril; /* Report Item List */
4048
Stmt q;
4149
int rn = 0;
4250
int cnt = 0;
51
+ char *defaultReport = db_get("ticket-default-report", 0);
4352
4453
login_check_credentials();
4554
if( !g.perm.RdTkt && !g.perm.NewTkt ){
4655
login_needed(g.anon.RdTkt || g.anon.NewTkt);
4756
return;
@@ -85,10 +94,13 @@
8594
href("%R/rptedit?rn=%d", rn));
8695
}
8796
if( g.perm.TktFmt ){
8897
blob_appendf(&ril, "[%zsql</a>]",
8998
href("%R/rptsql?rn=%d", rn));
99
+ }
100
+ if( fossil_strcmp(zTitle, defaultReport)==0 ){
101
+ blob_appendf(&ril, "&nbsp;← default");
90102
}
91103
blob_appendf(&ril, "</li>\n");
92104
}
93105
db_finalize(&q);
94106
@@ -352,11 +364,11 @@
352364
@ <td colspan="3">%h(zTitle)</td></tr>
353365
@ <tr><td valign="top" align="right">Owner:</td><td></td>
354366
@ <td colspan="3">%h(zOwner)</td></tr>
355367
@ <tr><td valign="top" align="right">SQL:</td><td></td>
356368
@ <td valign="top"><pre>
357
- @ %h(zSQL)
369
+ @ <code class="language-sql">%h(zSQL)</code>
358370
@ </pre></td>
359371
@ <td width=15></td><td valign="top">
360372
output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3");
361373
@ </td>
362374
@ </tr></table>
@@ -384,10 +396,11 @@
384396
const char *z;
385397
const char *zOwner;
386398
const char *zClrKey;
387399
char *zSQL;
388400
char *zErr = 0;
401
+ int dflt = P("dflt") ? 1 : 0;
389402
390403
login_check_credentials();
391404
if( !g.perm.TktFmt ){
392405
login_needed(g.anon.TktFmt);
393406
return;
@@ -452,10 +465,18 @@
452465
}else{
453466
db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) "
454467
"VALUES(%Q,%Q,%Q,%Q,now())",
455468
zTitle, zSQL, zOwner, zClrKey);
456469
rn = db_last_insert_rowid();
470
+ }
471
+ if( dflt ){
472
+ db_set("ticket-default-report", zTitle, 0);
473
+ }else{
474
+ char *defaultReport = db_get("ticket-default-report", 0);
475
+ if( fossil_strcmp(zTitle, defaultReport)==0 ){
476
+ db_set("ticket-default-report", "", 0);
477
+ }
457478
}
458479
cgi_redirect(mprintf("rptview?rn=%d", rn));
459480
return;
460481
}
461482
}else if( rn==0 ){
@@ -465,14 +486,16 @@
465486
}else{
466487
Stmt q;
467488
db_prepare(&q, "SELECT title, sqlcode, owner, cols "
468489
"FROM reportfmt WHERE rn=%d",rn);
469490
if( db_step(&q)==SQLITE_ROW ){
491
+ char *defaultReport = db_get("ticket-default-report", 0);
470492
zTitle = db_column_malloc(&q, 0);
471493
zSQL = db_column_malloc(&q, 1);
472494
zOwner = db_column_malloc(&q, 2);
473495
zClrKey = db_column_malloc(&q, 3);
496
+ dflt = fossil_strcmp(zTitle, defaultReport)==0;
474497
}
475498
db_finalize(&q);
476499
if( P("copy") ){
477500
rn = 0;
478501
zTitle = mprintf("Copy Of %s", zTitle);
@@ -507,10 +530,12 @@
507530
@ color key is displayed.) Each line contains the text for a single
508531
@ entry in the key. The first token of each line is the background
509532
@ color for that line.<br />
510533
@ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
511534
@ </p>
535
+ @ <p><label><input type="checkbox" name="dflt" %s(dflt?"checked":"")> \
536
+ @ Make this the default report</label></p>
512537
if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
513538
@ <p>This report format is owned by %h(zOwner). You are not allowed
514539
@ to change it.</p>
515540
@ </form>
516541
report_format_hints();
@@ -537,11 +562,11 @@
537562
zSchema = db_text(0,"SELECT sql FROM repository.sqlite_schema"
538563
" WHERE name='ticket'");
539564
}
540565
@ <hr /><h3>TICKET Schema</h3>
541566
@ <blockquote><pre>
542
- @ %h(zSchema)
567
+ @ <code class="language-sql">%h(zSchema)</code>
543568
@ </pre></blockquote>
544569
@ <h3>Notes</h3>
545570
@ <ul>
546571
@ <li><p>The SQL must consist of a single SELECT statement</p></li>
547572
@
@@ -982,10 +1007,22 @@
9821007
** corresponding to REPORTFMT.RN. If the tablist query parameter exists,
9831008
** then the output consists of lines of tab-separated fields instead of
9841009
** an HTML table.
9851010
*/
9861011
void rptview_page(void){
1012
+ rptview_page_content(0, 1, 1);
1013
+}
1014
+
1015
+/*
1016
+** Render a report.
1017
+*/
1018
+void rptview_page_content(
1019
+ const char *defaultTitleSearch, /* If rn and title query parameters are
1020
+ blank, search reports by this title. */
1021
+ int pageWrap, /* If true, render full page; otherwise, just the report */
1022
+ int redirectMissing /* If true and report not found, go to reportlist */
1023
+){
9871024
int count = 0;
9881025
int rn, rc;
9891026
char *zSql;
9901027
char *zTitle;
9911028
char *zOwner;
@@ -1001,19 +1038,24 @@
10011038
db_prepare(&q,
10021039
"SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE rn=%d",
10031040
atoi(PD("rn","0")));
10041041
rc = db_step(&q);
10051042
if( rc!=SQLITE_ROW ){
1043
+ const char *titleSearch =
1044
+ defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ?
1045
+ P("title") : defaultTitleSearch;
10061046
db_finalize(&q);
10071047
db_prepare(&q,
10081048
"SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE title GLOB %Q",
1009
- P("title"));
1049
+ titleSearch);
10101050
rc = db_step(&q);
10111051
}
10121052
if( rc!=SQLITE_ROW ){
10131053
db_finalize(&q);
1014
- cgi_redirect("reportlist");
1054
+ if( redirectMissing ) {
1055
+ cgi_redirect("reportlist");
1056
+ }
10151057
return;
10161058
}
10171059
zTitle = db_column_malloc(&q, 0);
10181060
zSql = db_column_malloc(&q, 1);
10191061
zOwner = db_column_malloc(&q, 2);
@@ -1041,29 +1083,31 @@
10411083
struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
10421084
const char *zQS = PD("QUERY_STRING","");
10431085
10441086
db_multi_exec("PRAGMA empty_result_callbacks=ON");
10451087
style_set_current_feature("report");
1046
- /* style_finish_page() should provide escaping via %h formatting */
1047
- if( zQS[0] ){
1048
- style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
1049
- style_submenu_element("Reports","%R/reportlist?%s",zQS);
1050
- } else {
1051
- style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1052
- style_submenu_element("Reports","%R/reportlist");
1053
- }
1054
- if( g.perm.Admin
1055
- || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1056
- style_submenu_element("Edit", "rptedit?rn=%d", rn);
1057
- }
1058
- if( g.perm.TktFmt ){
1059
- style_submenu_element("SQL", "rptsql?rn=%d",rn);
1060
- }
1061
- if( g.perm.NewTkt ){
1062
- style_submenu_element("New Ticket", "%R/tktnew");
1063
- }
1064
- style_header("%s", zTitle);
1088
+ if( pageWrap ) {
1089
+ /* style_finish_page() should provide escaping via %h formatting */
1090
+ if( zQS[0] ){
1091
+ style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
1092
+ style_submenu_element("Reports","%R/reportlist?%s",zQS);
1093
+ } else {
1094
+ style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1095
+ style_submenu_element("Reports","%R/reportlist");
1096
+ }
1097
+ if( g.perm.Admin
1098
+ || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1099
+ style_submenu_element("Edit", "rptedit?rn=%d", rn);
1100
+ }
1101
+ if( g.perm.TktFmt ){
1102
+ style_submenu_element("SQL", "rptsql?rn=%d",rn);
1103
+ }
1104
+ if( g.perm.NewTkt ){
1105
+ style_submenu_element("New Ticket", "%R/tktnew");
1106
+ }
1107
+ style_header("%s", zTitle);
1108
+ }
10651109
output_color_key(zClrKey, 1,
10661110
"border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
10671111
@ <table border="1" cellpadding="2" cellspacing="0" class="report sortable"
10681112
@ data-column-types='' data-init-sort='0'>
10691113
sState.rn = rn;
@@ -1076,11 +1120,13 @@
10761120
@ <p class="reportError">Error: %h(zErr1)</p>
10771121
}else if( zErr2 ){
10781122
@ <p class="reportError">Error: %h(zErr2)</p>
10791123
}
10801124
style_table_sorter();
1081
- style_finish_page();
1125
+ if( pageWrap ) {
1126
+ style_finish_page();
1127
+ }
10821128
}else{
10831129
report_restrict_sql(&zErr1);
10841130
db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
10851131
report_unrestrict_sql();
10861132
cgi_set_content_type("text/plain");
10871133
--- src/report.c
+++ src/report.c
@@ -27,10 +27,18 @@
27
28 #ifndef SQLITE_RECURSIVE
29 # define SQLITE_RECURSIVE 33
30 #endif
31
 
 
 
 
 
 
 
 
32 /*
33 ** WEBPAGE: reportlist
34 **
35 ** Main menu for Tickets.
36 */
@@ -38,10 +46,11 @@
38 const char *zScript;
39 Blob ril; /* Report Item List */
40 Stmt q;
41 int rn = 0;
42 int cnt = 0;
 
43
44 login_check_credentials();
45 if( !g.perm.RdTkt && !g.perm.NewTkt ){
46 login_needed(g.anon.RdTkt || g.anon.NewTkt);
47 return;
@@ -85,10 +94,13 @@
85 href("%R/rptedit?rn=%d", rn));
86 }
87 if( g.perm.TktFmt ){
88 blob_appendf(&ril, "[%zsql</a>]",
89 href("%R/rptsql?rn=%d", rn));
 
 
 
90 }
91 blob_appendf(&ril, "</li>\n");
92 }
93 db_finalize(&q);
94
@@ -352,11 +364,11 @@
352 @ <td colspan="3">%h(zTitle)</td></tr>
353 @ <tr><td valign="top" align="right">Owner:</td><td></td>
354 @ <td colspan="3">%h(zOwner)</td></tr>
355 @ <tr><td valign="top" align="right">SQL:</td><td></td>
356 @ <td valign="top"><pre>
357 @ %h(zSQL)
358 @ </pre></td>
359 @ <td width=15></td><td valign="top">
360 output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3");
361 @ </td>
362 @ </tr></table>
@@ -384,10 +396,11 @@
384 const char *z;
385 const char *zOwner;
386 const char *zClrKey;
387 char *zSQL;
388 char *zErr = 0;
 
389
390 login_check_credentials();
391 if( !g.perm.TktFmt ){
392 login_needed(g.anon.TktFmt);
393 return;
@@ -452,10 +465,18 @@
452 }else{
453 db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) "
454 "VALUES(%Q,%Q,%Q,%Q,now())",
455 zTitle, zSQL, zOwner, zClrKey);
456 rn = db_last_insert_rowid();
 
 
 
 
 
 
 
 
457 }
458 cgi_redirect(mprintf("rptview?rn=%d", rn));
459 return;
460 }
461 }else if( rn==0 ){
@@ -465,14 +486,16 @@
465 }else{
466 Stmt q;
467 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
468 "FROM reportfmt WHERE rn=%d",rn);
469 if( db_step(&q)==SQLITE_ROW ){
 
470 zTitle = db_column_malloc(&q, 0);
471 zSQL = db_column_malloc(&q, 1);
472 zOwner = db_column_malloc(&q, 2);
473 zClrKey = db_column_malloc(&q, 3);
 
474 }
475 db_finalize(&q);
476 if( P("copy") ){
477 rn = 0;
478 zTitle = mprintf("Copy Of %s", zTitle);
@@ -507,10 +530,12 @@
507 @ color key is displayed.) Each line contains the text for a single
508 @ entry in the key. The first token of each line is the background
509 @ color for that line.<br />
510 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
511 @ </p>
 
 
512 if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
513 @ <p>This report format is owned by %h(zOwner). You are not allowed
514 @ to change it.</p>
515 @ </form>
516 report_format_hints();
@@ -537,11 +562,11 @@
537 zSchema = db_text(0,"SELECT sql FROM repository.sqlite_schema"
538 " WHERE name='ticket'");
539 }
540 @ <hr /><h3>TICKET Schema</h3>
541 @ <blockquote><pre>
542 @ %h(zSchema)
543 @ </pre></blockquote>
544 @ <h3>Notes</h3>
545 @ <ul>
546 @ <li><p>The SQL must consist of a single SELECT statement</p></li>
547 @
@@ -982,10 +1007,22 @@
982 ** corresponding to REPORTFMT.RN. If the tablist query parameter exists,
983 ** then the output consists of lines of tab-separated fields instead of
984 ** an HTML table.
985 */
986 void rptview_page(void){
 
 
 
 
 
 
 
 
 
 
 
 
987 int count = 0;
988 int rn, rc;
989 char *zSql;
990 char *zTitle;
991 char *zOwner;
@@ -1001,19 +1038,24 @@
1001 db_prepare(&q,
1002 "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE rn=%d",
1003 atoi(PD("rn","0")));
1004 rc = db_step(&q);
1005 if( rc!=SQLITE_ROW ){
 
 
 
1006 db_finalize(&q);
1007 db_prepare(&q,
1008 "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE title GLOB %Q",
1009 P("title"));
1010 rc = db_step(&q);
1011 }
1012 if( rc!=SQLITE_ROW ){
1013 db_finalize(&q);
1014 cgi_redirect("reportlist");
 
 
1015 return;
1016 }
1017 zTitle = db_column_malloc(&q, 0);
1018 zSql = db_column_malloc(&q, 1);
1019 zOwner = db_column_malloc(&q, 2);
@@ -1041,29 +1083,31 @@
1041 struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1042 const char *zQS = PD("QUERY_STRING","");
1043
1044 db_multi_exec("PRAGMA empty_result_callbacks=ON");
1045 style_set_current_feature("report");
1046 /* style_finish_page() should provide escaping via %h formatting */
1047 if( zQS[0] ){
1048 style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
1049 style_submenu_element("Reports","%R/reportlist?%s",zQS);
1050 } else {
1051 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1052 style_submenu_element("Reports","%R/reportlist");
1053 }
1054 if( g.perm.Admin
1055 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1056 style_submenu_element("Edit", "rptedit?rn=%d", rn);
1057 }
1058 if( g.perm.TktFmt ){
1059 style_submenu_element("SQL", "rptsql?rn=%d",rn);
1060 }
1061 if( g.perm.NewTkt ){
1062 style_submenu_element("New Ticket", "%R/tktnew");
1063 }
1064 style_header("%s", zTitle);
 
 
1065 output_color_key(zClrKey, 1,
1066 "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
1067 @ <table border="1" cellpadding="2" cellspacing="0" class="report sortable"
1068 @ data-column-types='' data-init-sort='0'>
1069 sState.rn = rn;
@@ -1076,11 +1120,13 @@
1076 @ <p class="reportError">Error: %h(zErr1)</p>
1077 }else if( zErr2 ){
1078 @ <p class="reportError">Error: %h(zErr2)</p>
1079 }
1080 style_table_sorter();
1081 style_finish_page();
 
 
1082 }else{
1083 report_restrict_sql(&zErr1);
1084 db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1085 report_unrestrict_sql();
1086 cgi_set_content_type("text/plain");
1087
--- src/report.c
+++ src/report.c
@@ -27,10 +27,18 @@
27
28 #ifndef SQLITE_RECURSIVE
29 # define SQLITE_RECURSIVE 33
30 #endif
31
32 /* Settings that can be used to control ticket reports */
33 /*
34 ** SETTING: ticket-default-report width=80
35 ** If this setting has a string value, then when the ticket
36 ** search page query is blank, the report with this title is shown.
37 ** If the setting is blank (default), then no report is shown.
38 */
39
40 /*
41 ** WEBPAGE: reportlist
42 **
43 ** Main menu for Tickets.
44 */
@@ -38,10 +46,11 @@
46 const char *zScript;
47 Blob ril; /* Report Item List */
48 Stmt q;
49 int rn = 0;
50 int cnt = 0;
51 char *defaultReport = db_get("ticket-default-report", 0);
52
53 login_check_credentials();
54 if( !g.perm.RdTkt && !g.perm.NewTkt ){
55 login_needed(g.anon.RdTkt || g.anon.NewTkt);
56 return;
@@ -85,10 +94,13 @@
94 href("%R/rptedit?rn=%d", rn));
95 }
96 if( g.perm.TktFmt ){
97 blob_appendf(&ril, "[%zsql</a>]",
98 href("%R/rptsql?rn=%d", rn));
99 }
100 if( fossil_strcmp(zTitle, defaultReport)==0 ){
101 blob_appendf(&ril, "&nbsp;← default");
102 }
103 blob_appendf(&ril, "</li>\n");
104 }
105 db_finalize(&q);
106
@@ -352,11 +364,11 @@
364 @ <td colspan="3">%h(zTitle)</td></tr>
365 @ <tr><td valign="top" align="right">Owner:</td><td></td>
366 @ <td colspan="3">%h(zOwner)</td></tr>
367 @ <tr><td valign="top" align="right">SQL:</td><td></td>
368 @ <td valign="top"><pre>
369 @ <code class="language-sql">%h(zSQL)</code>
370 @ </pre></td>
371 @ <td width=15></td><td valign="top">
372 output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3");
373 @ </td>
374 @ </tr></table>
@@ -384,10 +396,11 @@
396 const char *z;
397 const char *zOwner;
398 const char *zClrKey;
399 char *zSQL;
400 char *zErr = 0;
401 int dflt = P("dflt") ? 1 : 0;
402
403 login_check_credentials();
404 if( !g.perm.TktFmt ){
405 login_needed(g.anon.TktFmt);
406 return;
@@ -452,10 +465,18 @@
465 }else{
466 db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) "
467 "VALUES(%Q,%Q,%Q,%Q,now())",
468 zTitle, zSQL, zOwner, zClrKey);
469 rn = db_last_insert_rowid();
470 }
471 if( dflt ){
472 db_set("ticket-default-report", zTitle, 0);
473 }else{
474 char *defaultReport = db_get("ticket-default-report", 0);
475 if( fossil_strcmp(zTitle, defaultReport)==0 ){
476 db_set("ticket-default-report", "", 0);
477 }
478 }
479 cgi_redirect(mprintf("rptview?rn=%d", rn));
480 return;
481 }
482 }else if( rn==0 ){
@@ -465,14 +486,16 @@
486 }else{
487 Stmt q;
488 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
489 "FROM reportfmt WHERE rn=%d",rn);
490 if( db_step(&q)==SQLITE_ROW ){
491 char *defaultReport = db_get("ticket-default-report", 0);
492 zTitle = db_column_malloc(&q, 0);
493 zSQL = db_column_malloc(&q, 1);
494 zOwner = db_column_malloc(&q, 2);
495 zClrKey = db_column_malloc(&q, 3);
496 dflt = fossil_strcmp(zTitle, defaultReport)==0;
497 }
498 db_finalize(&q);
499 if( P("copy") ){
500 rn = 0;
501 zTitle = mprintf("Copy Of %s", zTitle);
@@ -507,10 +530,12 @@
530 @ color key is displayed.) Each line contains the text for a single
531 @ entry in the key. The first token of each line is the background
532 @ color for that line.<br />
533 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
534 @ </p>
535 @ <p><label><input type="checkbox" name="dflt" %s(dflt?"checked":"")> \
536 @ Make this the default report</label></p>
537 if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){
538 @ <p>This report format is owned by %h(zOwner). You are not allowed
539 @ to change it.</p>
540 @ </form>
541 report_format_hints();
@@ -537,11 +562,11 @@
562 zSchema = db_text(0,"SELECT sql FROM repository.sqlite_schema"
563 " WHERE name='ticket'");
564 }
565 @ <hr /><h3>TICKET Schema</h3>
566 @ <blockquote><pre>
567 @ <code class="language-sql">%h(zSchema)</code>
568 @ </pre></blockquote>
569 @ <h3>Notes</h3>
570 @ <ul>
571 @ <li><p>The SQL must consist of a single SELECT statement</p></li>
572 @
@@ -982,10 +1007,22 @@
1007 ** corresponding to REPORTFMT.RN. If the tablist query parameter exists,
1008 ** then the output consists of lines of tab-separated fields instead of
1009 ** an HTML table.
1010 */
1011 void rptview_page(void){
1012 rptview_page_content(0, 1, 1);
1013 }
1014
1015 /*
1016 ** Render a report.
1017 */
1018 void rptview_page_content(
1019 const char *defaultTitleSearch, /* If rn and title query parameters are
1020 blank, search reports by this title. */
1021 int pageWrap, /* If true, render full page; otherwise, just the report */
1022 int redirectMissing /* If true and report not found, go to reportlist */
1023 ){
1024 int count = 0;
1025 int rn, rc;
1026 char *zSql;
1027 char *zTitle;
1028 char *zOwner;
@@ -1001,19 +1038,24 @@
1038 db_prepare(&q,
1039 "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE rn=%d",
1040 atoi(PD("rn","0")));
1041 rc = db_step(&q);
1042 if( rc!=SQLITE_ROW ){
1043 const char *titleSearch =
1044 defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ?
1045 P("title") : defaultTitleSearch;
1046 db_finalize(&q);
1047 db_prepare(&q,
1048 "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE title GLOB %Q",
1049 titleSearch);
1050 rc = db_step(&q);
1051 }
1052 if( rc!=SQLITE_ROW ){
1053 db_finalize(&q);
1054 if( redirectMissing ) {
1055 cgi_redirect("reportlist");
1056 }
1057 return;
1058 }
1059 zTitle = db_column_malloc(&q, 0);
1060 zSql = db_column_malloc(&q, 1);
1061 zOwner = db_column_malloc(&q, 2);
@@ -1041,29 +1083,31 @@
1083 struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1084 const char *zQS = PD("QUERY_STRING","");
1085
1086 db_multi_exec("PRAGMA empty_result_callbacks=ON");
1087 style_set_current_feature("report");
1088 if( pageWrap ) {
1089 /* style_finish_page() should provide escaping via %h formatting */
1090 if( zQS[0] ){
1091 style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
1092 style_submenu_element("Reports","%R/reportlist?%s",zQS);
1093 } else {
1094 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1095 style_submenu_element("Reports","%R/reportlist");
1096 }
1097 if( g.perm.Admin
1098 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1099 style_submenu_element("Edit", "rptedit?rn=%d", rn);
1100 }
1101 if( g.perm.TktFmt ){
1102 style_submenu_element("SQL", "rptsql?rn=%d",rn);
1103 }
1104 if( g.perm.NewTkt ){
1105 style_submenu_element("New Ticket", "%R/tktnew");
1106 }
1107 style_header("%s", zTitle);
1108 }
1109 output_color_key(zClrKey, 1,
1110 "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
1111 @ <table border="1" cellpadding="2" cellspacing="0" class="report sortable"
1112 @ data-column-types='' data-init-sort='0'>
1113 sState.rn = rn;
@@ -1076,11 +1120,13 @@
1120 @ <p class="reportError">Error: %h(zErr1)</p>
1121 }else if( zErr2 ){
1122 @ <p class="reportError">Error: %h(zErr2)</p>
1123 }
1124 style_table_sorter();
1125 if( pageWrap ) {
1126 style_finish_page();
1127 }
1128 }else{
1129 report_restrict_sql(&zErr1);
1130 db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1131 report_unrestrict_sql();
1132 cgi_set_content_type("text/plain");
1133
+3 -2
--- src/search.c
+++ src/search.c
@@ -1209,12 +1209,13 @@
12091209
** e -> tech notes
12101210
** f -> forum
12111211
** all -> everything
12121212
*/
12131213
void search_page(void){
1214
+ const int isSearch = P("s")!=0;
12141215
login_check_credentials();
1215
- style_header("Search");
1216
+ style_header("Search%s", isSearch ? " Results" : "");
12161217
search_screen(SRCH_ALL, 1);
12171218
style_finish_page();
12181219
}
12191220
12201221
@@ -1930,11 +1931,11 @@
19301931
const char *zCtrl;
19311932
if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd));
19321933
zCtrl = g.argv[3];
19331934
for(j=0; j<count(aSetng); j++){
19341935
if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){
1935
- db_set_int(aSetng[j].zSetting, iCmd-3, 0);
1936
+ db_set_int(aSetng[j].zSetting/*works-like:"x"*/, iCmd-3, 0);
19361937
}
19371938
}
19381939
}
19391940
if( iCmd==5 ){
19401941
if( g.argc<4 ) usage("porter ON/OFF");
19411942
--- src/search.c
+++ src/search.c
@@ -1209,12 +1209,13 @@
1209 ** e -> tech notes
1210 ** f -> forum
1211 ** all -> everything
1212 */
1213 void search_page(void){
 
1214 login_check_credentials();
1215 style_header("Search");
1216 search_screen(SRCH_ALL, 1);
1217 style_finish_page();
1218 }
1219
1220
@@ -1930,11 +1931,11 @@
1930 const char *zCtrl;
1931 if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd));
1932 zCtrl = g.argv[3];
1933 for(j=0; j<count(aSetng); j++){
1934 if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){
1935 db_set_int(aSetng[j].zSetting, iCmd-3, 0);
1936 }
1937 }
1938 }
1939 if( iCmd==5 ){
1940 if( g.argc<4 ) usage("porter ON/OFF");
1941
--- src/search.c
+++ src/search.c
@@ -1209,12 +1209,13 @@
1209 ** e -> tech notes
1210 ** f -> forum
1211 ** all -> everything
1212 */
1213 void search_page(void){
1214 const int isSearch = P("s")!=0;
1215 login_check_credentials();
1216 style_header("Search%s", isSearch ? " Results" : "");
1217 search_screen(SRCH_ALL, 1);
1218 style_finish_page();
1219 }
1220
1221
@@ -1930,11 +1931,11 @@
1931 const char *zCtrl;
1932 if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd));
1933 zCtrl = g.argv[3];
1934 for(j=0; j<count(aSetng); j++){
1935 if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){
1936 db_set_int(aSetng[j].zSetting/*works-like:"x"*/, iCmd-3, 0);
1937 }
1938 }
1939 }
1940 if( iCmd==5 ){
1941 if( g.argc<4 ) usage("porter ON/OFF");
1942
+15 -15
--- src/setup.c
+++ src/setup.c
@@ -186,13 +186,13 @@
186186
/*
187187
** Generate a checkbox for an attribute.
188188
*/
189189
void onoff_attribute(
190190
const char *zLabel, /* The text label on the checkbox */
191
- const char *zVar, /* The corresponding row in the VAR table */
191
+ const char *zVar, /* The corresponding row in the CONFIG table */
192192
const char *zQParm, /* The query parameter */
193
- int dfltVal, /* Default value if VAR table entry does not exist */
193
+ int dfltVal, /* Default value if CONFIG table entry does not exist */
194194
int disabled /* 1 if disabled */
195195
){
196196
const char *zQ = P(zQParm);
197197
int iVal = db_get_boolean(zVar, dfltVal);
198198
if( zQ==0 && !disabled && P("submit") ){
@@ -201,11 +201,11 @@
201201
if( zQ ){
202202
int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ);
203203
if( iQ!=iVal ){
204204
login_verify_csrf_secret();
205205
db_protect_only(PROTECT_NONE);
206
- db_set(zVar, iQ ? "1" : "0", 0);
206
+ db_set(zVar/*works-like:"x"*/, iQ ? "1" : "0", 0);
207207
db_protect_pop();
208208
setup_incr_cfgcnt();
209209
admin_log("Set option [%q] to [%q].",
210210
zVar, iQ ? "on" : "off");
211211
iVal = iQ;
@@ -226,23 +226,23 @@
226226
** Generate an entry box for an attribute.
227227
*/
228228
void entry_attribute(
229229
const char *zLabel, /* The text label on the entry box */
230230
int width, /* Width of the entry box */
231
- const char *zVar, /* The corresponding row in the VAR table */
231
+ const char *zVar, /* The corresponding row in the CONFIG table */
232232
const char *zQParm, /* The query parameter */
233
- const char *zDflt, /* Default value if VAR table entry does not exist */
233
+ const char *zDflt, /* Default value if CONFIG table entry does not exist */
234234
int disabled /* 1 if disabled */
235235
){
236236
const char *zVal = db_get(zVar, zDflt);
237237
const char *zQ = P(zQParm);
238238
if( zQ && fossil_strcmp(zQ,zVal)!=0 ){
239239
const int nZQ = (int)strlen(zQ);
240240
login_verify_csrf_secret();
241241
setup_incr_cfgcnt();
242242
db_protect_only(PROTECT_NONE);
243
- db_set(zVar, zQ, 0);
243
+ db_set(zVar/*works-like:"x"*/, zQ, 0);
244244
db_protect_pop();
245245
admin_log("Set entry_attribute %Q to: %.*s%s",
246246
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
247247
zVal = zQ;
248248
}
@@ -259,22 +259,22 @@
259259
*/
260260
const char *textarea_attribute(
261261
const char *zLabel, /* The text label on the textarea */
262262
int rows, /* Rows in the textarea */
263263
int cols, /* Columns in the textarea */
264
- const char *zVar, /* The corresponding row in the VAR table */
264
+ const char *zVar, /* The corresponding row in the CONFIG table */
265265
const char *zQP, /* The query parameter */
266
- const char *zDflt, /* Default value if VAR table entry does not exist */
266
+ const char *zDflt, /* Default value if CONFIG table entry does not exist */
267267
int disabled /* 1 if the textarea should not be editable */
268268
){
269269
const char *z = db_get(zVar, zDflt);
270270
const char *zQ = P(zQP);
271271
if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){
272272
const int nZQ = (int)strlen(zQ);
273273
login_verify_csrf_secret();
274274
db_protect_only(PROTECT_NONE);
275
- db_set(zVar, zQ, 0);
275
+ db_set(zVar/*works-like:"x"*/, zQ, 0);
276276
db_protect_pop();
277277
setup_incr_cfgcnt();
278278
admin_log("Set textarea_attribute %Q to: %.*s%s",
279279
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
280280
z = zQ;
@@ -296,13 +296,13 @@
296296
/*
297297
** Generate a text box for an attribute.
298298
*/
299299
void multiple_choice_attribute(
300300
const char *zLabel, /* The text label on the menu */
301
- const char *zVar, /* The corresponding row in the VAR table */
301
+ const char *zVar, /* The corresponding row in the CONFIG table */
302302
const char *zQP, /* The query parameter */
303
- const char *zDflt, /* Default value if VAR table entry does not exist */
303
+ const char *zDflt, /* Default value if CONFIG table entry does not exist */
304304
int nChoice, /* Number of choices */
305305
const char *const *azChoice /* Choices in pairs (VAR value, Display) */
306306
){
307307
const char *z = db_get(zVar, zDflt);
308308
const char *zQ = P(zQP);
@@ -309,11 +309,11 @@
309309
int i;
310310
if( zQ && fossil_strcmp(zQ,z)!=0){
311311
const int nZQ = (int)strlen(zQ);
312312
login_verify_csrf_secret();
313313
db_unprotect(PROTECT_ALL);
314
- db_set(zVar, zQ, 0);
314
+ db_set(zVar/*works-like:"x"*/, zQ, 0);
315315
setup_incr_cfgcnt();
316316
db_protect_pop();
317317
admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
318318
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
319319
z = zQ;
@@ -899,11 +899,11 @@
899899
for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
900900
if( pSet->width==0 ){
901901
int hasVersionableValue = pSet->versionable &&
902902
(db_get_versioned(pSet->name, NULL)!=0);
903903
onoff_attribute("", pSet->name,
904
- pSet->var!=0 ? pSet->var : pSet->name,
904
+ pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/,
905905
is_truth(pSet->def), hasVersionableValue);
906906
@ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
907907
if( pSet->versionable ){
908908
@ (v)<br />
909909
} else {
@@ -925,11 +925,11 @@
925925
} else {
926926
@
927927
}
928928
@</td><td>
929929
entry_attribute("", /*pSet->width*/ 25, pSet->name,
930
- pSet->var!=0 ? pSet->var : pSet->name,
930
+ pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/,
931931
(char*)pSet->def, hasVersionableValue);
932932
@</td></tr>
933933
}
934934
}
935935
@</table>
@@ -942,11 +942,11 @@
942942
@ (v)<br />
943943
} else {
944944
@ <br />
945945
}
946946
textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name,
947
- pSet->var!=0 ? pSet->var : pSet->name,
947
+ pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/,
948948
(char*)pSet->def, hasVersionableValue);
949949
@<br />
950950
}
951951
}
952952
@ </td></tr></table>
953953
--- src/setup.c
+++ src/setup.c
@@ -186,13 +186,13 @@
186 /*
187 ** Generate a checkbox for an attribute.
188 */
189 void onoff_attribute(
190 const char *zLabel, /* The text label on the checkbox */
191 const char *zVar, /* The corresponding row in the VAR table */
192 const char *zQParm, /* The query parameter */
193 int dfltVal, /* Default value if VAR table entry does not exist */
194 int disabled /* 1 if disabled */
195 ){
196 const char *zQ = P(zQParm);
197 int iVal = db_get_boolean(zVar, dfltVal);
198 if( zQ==0 && !disabled && P("submit") ){
@@ -201,11 +201,11 @@
201 if( zQ ){
202 int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ);
203 if( iQ!=iVal ){
204 login_verify_csrf_secret();
205 db_protect_only(PROTECT_NONE);
206 db_set(zVar, iQ ? "1" : "0", 0);
207 db_protect_pop();
208 setup_incr_cfgcnt();
209 admin_log("Set option [%q] to [%q].",
210 zVar, iQ ? "on" : "off");
211 iVal = iQ;
@@ -226,23 +226,23 @@
226 ** Generate an entry box for an attribute.
227 */
228 void entry_attribute(
229 const char *zLabel, /* The text label on the entry box */
230 int width, /* Width of the entry box */
231 const char *zVar, /* The corresponding row in the VAR table */
232 const char *zQParm, /* The query parameter */
233 const char *zDflt, /* Default value if VAR table entry does not exist */
234 int disabled /* 1 if disabled */
235 ){
236 const char *zVal = db_get(zVar, zDflt);
237 const char *zQ = P(zQParm);
238 if( zQ && fossil_strcmp(zQ,zVal)!=0 ){
239 const int nZQ = (int)strlen(zQ);
240 login_verify_csrf_secret();
241 setup_incr_cfgcnt();
242 db_protect_only(PROTECT_NONE);
243 db_set(zVar, zQ, 0);
244 db_protect_pop();
245 admin_log("Set entry_attribute %Q to: %.*s%s",
246 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
247 zVal = zQ;
248 }
@@ -259,22 +259,22 @@
259 */
260 const char *textarea_attribute(
261 const char *zLabel, /* The text label on the textarea */
262 int rows, /* Rows in the textarea */
263 int cols, /* Columns in the textarea */
264 const char *zVar, /* The corresponding row in the VAR table */
265 const char *zQP, /* The query parameter */
266 const char *zDflt, /* Default value if VAR table entry does not exist */
267 int disabled /* 1 if the textarea should not be editable */
268 ){
269 const char *z = db_get(zVar, zDflt);
270 const char *zQ = P(zQP);
271 if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){
272 const int nZQ = (int)strlen(zQ);
273 login_verify_csrf_secret();
274 db_protect_only(PROTECT_NONE);
275 db_set(zVar, zQ, 0);
276 db_protect_pop();
277 setup_incr_cfgcnt();
278 admin_log("Set textarea_attribute %Q to: %.*s%s",
279 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
280 z = zQ;
@@ -296,13 +296,13 @@
296 /*
297 ** Generate a text box for an attribute.
298 */
299 void multiple_choice_attribute(
300 const char *zLabel, /* The text label on the menu */
301 const char *zVar, /* The corresponding row in the VAR table */
302 const char *zQP, /* The query parameter */
303 const char *zDflt, /* Default value if VAR table entry does not exist */
304 int nChoice, /* Number of choices */
305 const char *const *azChoice /* Choices in pairs (VAR value, Display) */
306 ){
307 const char *z = db_get(zVar, zDflt);
308 const char *zQ = P(zQP);
@@ -309,11 +309,11 @@
309 int i;
310 if( zQ && fossil_strcmp(zQ,z)!=0){
311 const int nZQ = (int)strlen(zQ);
312 login_verify_csrf_secret();
313 db_unprotect(PROTECT_ALL);
314 db_set(zVar, zQ, 0);
315 setup_incr_cfgcnt();
316 db_protect_pop();
317 admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
318 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
319 z = zQ;
@@ -899,11 +899,11 @@
899 for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
900 if( pSet->width==0 ){
901 int hasVersionableValue = pSet->versionable &&
902 (db_get_versioned(pSet->name, NULL)!=0);
903 onoff_attribute("", pSet->name,
904 pSet->var!=0 ? pSet->var : pSet->name,
905 is_truth(pSet->def), hasVersionableValue);
906 @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
907 if( pSet->versionable ){
908 @ (v)<br />
909 } else {
@@ -925,11 +925,11 @@
925 } else {
926 @
927 }
928 @</td><td>
929 entry_attribute("", /*pSet->width*/ 25, pSet->name,
930 pSet->var!=0 ? pSet->var : pSet->name,
931 (char*)pSet->def, hasVersionableValue);
932 @</td></tr>
933 }
934 }
935 @</table>
@@ -942,11 +942,11 @@
942 @ (v)<br />
943 } else {
944 @ <br />
945 }
946 textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name,
947 pSet->var!=0 ? pSet->var : pSet->name,
948 (char*)pSet->def, hasVersionableValue);
949 @<br />
950 }
951 }
952 @ </td></tr></table>
953
--- src/setup.c
+++ src/setup.c
@@ -186,13 +186,13 @@
186 /*
187 ** Generate a checkbox for an attribute.
188 */
189 void onoff_attribute(
190 const char *zLabel, /* The text label on the checkbox */
191 const char *zVar, /* The corresponding row in the CONFIG table */
192 const char *zQParm, /* The query parameter */
193 int dfltVal, /* Default value if CONFIG table entry does not exist */
194 int disabled /* 1 if disabled */
195 ){
196 const char *zQ = P(zQParm);
197 int iVal = db_get_boolean(zVar, dfltVal);
198 if( zQ==0 && !disabled && P("submit") ){
@@ -201,11 +201,11 @@
201 if( zQ ){
202 int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ);
203 if( iQ!=iVal ){
204 login_verify_csrf_secret();
205 db_protect_only(PROTECT_NONE);
206 db_set(zVar/*works-like:"x"*/, iQ ? "1" : "0", 0);
207 db_protect_pop();
208 setup_incr_cfgcnt();
209 admin_log("Set option [%q] to [%q].",
210 zVar, iQ ? "on" : "off");
211 iVal = iQ;
@@ -226,23 +226,23 @@
226 ** Generate an entry box for an attribute.
227 */
228 void entry_attribute(
229 const char *zLabel, /* The text label on the entry box */
230 int width, /* Width of the entry box */
231 const char *zVar, /* The corresponding row in the CONFIG table */
232 const char *zQParm, /* The query parameter */
233 const char *zDflt, /* Default value if CONFIG table entry does not exist */
234 int disabled /* 1 if disabled */
235 ){
236 const char *zVal = db_get(zVar, zDflt);
237 const char *zQ = P(zQParm);
238 if( zQ && fossil_strcmp(zQ,zVal)!=0 ){
239 const int nZQ = (int)strlen(zQ);
240 login_verify_csrf_secret();
241 setup_incr_cfgcnt();
242 db_protect_only(PROTECT_NONE);
243 db_set(zVar/*works-like:"x"*/, zQ, 0);
244 db_protect_pop();
245 admin_log("Set entry_attribute %Q to: %.*s%s",
246 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
247 zVal = zQ;
248 }
@@ -259,22 +259,22 @@
259 */
260 const char *textarea_attribute(
261 const char *zLabel, /* The text label on the textarea */
262 int rows, /* Rows in the textarea */
263 int cols, /* Columns in the textarea */
264 const char *zVar, /* The corresponding row in the CONFIG table */
265 const char *zQP, /* The query parameter */
266 const char *zDflt, /* Default value if CONFIG table entry does not exist */
267 int disabled /* 1 if the textarea should not be editable */
268 ){
269 const char *z = db_get(zVar, zDflt);
270 const char *zQ = P(zQP);
271 if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){
272 const int nZQ = (int)strlen(zQ);
273 login_verify_csrf_secret();
274 db_protect_only(PROTECT_NONE);
275 db_set(zVar/*works-like:"x"*/, zQ, 0);
276 db_protect_pop();
277 setup_incr_cfgcnt();
278 admin_log("Set textarea_attribute %Q to: %.*s%s",
279 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
280 z = zQ;
@@ -296,13 +296,13 @@
296 /*
297 ** Generate a text box for an attribute.
298 */
299 void multiple_choice_attribute(
300 const char *zLabel, /* The text label on the menu */
301 const char *zVar, /* The corresponding row in the CONFIG table */
302 const char *zQP, /* The query parameter */
303 const char *zDflt, /* Default value if CONFIG table entry does not exist */
304 int nChoice, /* Number of choices */
305 const char *const *azChoice /* Choices in pairs (VAR value, Display) */
306 ){
307 const char *z = db_get(zVar, zDflt);
308 const char *zQ = P(zQP);
@@ -309,11 +309,11 @@
309 int i;
310 if( zQ && fossil_strcmp(zQ,z)!=0){
311 const int nZQ = (int)strlen(zQ);
312 login_verify_csrf_secret();
313 db_unprotect(PROTECT_ALL);
314 db_set(zVar/*works-like:"x"*/, zQ, 0);
315 setup_incr_cfgcnt();
316 db_protect_pop();
317 admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
318 zVar, 20, zQ, (nZQ>20 ? "..." : ""));
319 z = zQ;
@@ -899,11 +899,11 @@
899 for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
900 if( pSet->width==0 ){
901 int hasVersionableValue = pSet->versionable &&
902 (db_get_versioned(pSet->name, NULL)!=0);
903 onoff_attribute("", pSet->name,
904 pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/,
905 is_truth(pSet->def), hasVersionableValue);
906 @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
907 if( pSet->versionable ){
908 @ (v)<br />
909 } else {
@@ -925,11 +925,11 @@
925 } else {
926 @
927 }
928 @</td><td>
929 entry_attribute("", /*pSet->width*/ 25, pSet->name,
930 pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/,
931 (char*)pSet->def, hasVersionableValue);
932 @</td></tr>
933 }
934 }
935 @</table>
@@ -942,11 +942,11 @@
942 @ (v)<br />
943 } else {
944 @ <br />
945 }
946 textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name,
947 pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/,
948 (char*)pSet->def, hasVersionableValue);
949 @<br />
950 }
951 }
952 @ </td></tr></table>
953
+184 -83
--- src/shell.c
+++ src/shell.c
@@ -33,10 +33,22 @@
3333
#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
3434
/* This needs to come before any includes for MSVC compiler */
3535
#define _CRT_SECURE_NO_WARNINGS
3636
#endif
3737
38
+/*
39
+** Optionally #include a user-defined header, whereby compilation options
40
+** may be set prior to where they take effect, but after platform setup.
41
+** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
42
+** file. Note that this macro has a like effect on sqlite3.c compilation.
43
+*/
44
+#ifdef SQLITE_CUSTOM_INCLUDE
45
+# define INC_STRINGIFY_(f) #f
46
+# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
47
+# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
48
+#endif
49
+
3850
/*
3951
** Determine if we are dealing with WinRT, which provides only a subset of
4052
** the full Win32 API.
4153
*/
4254
#if !defined(SQLITE_OS_WINRT)
@@ -242,10 +254,11 @@
242254
/* Return the current wall-clock time */
243255
static sqlite3_int64 timeOfDay(void){
244256
static sqlite3_vfs *clockVfs = 0;
245257
sqlite3_int64 t;
246258
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
259
+ if( clockVfs==0 ) return 0; /* Never actually happens */
247260
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
248261
clockVfs->xCurrentTimeInt64(clockVfs, &t);
249262
}else{
250263
double r;
251264
clockVfs->xCurrentTime(clockVfs, &r);
@@ -986,11 +999,11 @@
986999
const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
9871000
const char *zName = (const char*)sqlite3_value_text(apVal[2]);
9881001
sqlite3 *db = sqlite3_context_db_handle(pCtx);
9891002
UNUSED_PARAMETER(nVal);
9901003
if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
991
- for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
1004
+ for(i=0; i<ArraySize(aPrefix); i++){
9921005
int n = strlen30(aPrefix[i]);
9931006
if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
9941007
char *z = 0;
9951008
char *zFake = 0;
9961009
if( zSchema ){
@@ -4281,10 +4294,11 @@
42814294
sqlite3_vfs *pOrig;
42824295
SQLITE_EXTENSION_INIT2(pApi);
42834296
(void)pzErrMsg;
42844297
(void)db;
42854298
pOrig = sqlite3_vfs_find(0);
4299
+ if( pOrig==0 ) return SQLITE_ERROR;
42864300
apnd_vfs.iVersion = pOrig->iVersion;
42874301
apnd_vfs.pAppData = pOrig;
42884302
apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
42894303
rc = sqlite3_vfs_register(&apnd_vfs, 0);
42904304
#ifdef APPENDVFS_TEST
@@ -5757,34 +5771,36 @@
57575771
** (2) stop = $value -- constraint exists
57585772
** (4) step = $value -- constraint exists
57595773
** (8) output in descending order
57605774
*/
57615775
static int seriesBestIndex(
5762
- sqlite3_vtab *tabUnused,
5776
+ sqlite3_vtab *pVTab,
57635777
sqlite3_index_info *pIdxInfo
57645778
){
57655779
int i, j; /* Loop over constraints */
57665780
int idxNum = 0; /* The query plan bitmask */
5781
+ int bStartSeen = 0; /* EQ constraint seen on the START column */
57675782
int unusableMask = 0; /* Mask of unusable constraints */
57685783
int nArg = 0; /* Number of arguments that seriesFilter() expects */
57695784
int aIdx[3]; /* Constraints on start, stop, and step */
57705785
const struct sqlite3_index_constraint *pConstraint;
57715786
57725787
/* This implementation assumes that the start, stop, and step columns
57735788
** are the last three columns in the virtual table. */
57745789
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
57755790
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
5776
- (void)tabUnused;
5791
+
57775792
aIdx[0] = aIdx[1] = aIdx[2] = -1;
57785793
pConstraint = pIdxInfo->aConstraint;
57795794
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
57805795
int iCol; /* 0 for start, 1 for stop, 2 for step */
57815796
int iMask; /* bitmask for those column */
57825797
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
57835798
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
57845799
assert( iCol>=0 && iCol<=2 );
57855800
iMask = 1 << iCol;
5801
+ if( iCol==0 ) bStartSeen = 1;
57865802
if( pConstraint->usable==0 ){
57875803
unusableMask |= iMask;
57885804
continue;
57895805
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
57905806
idxNum |= iMask;
@@ -5795,10 +5811,22 @@
57955811
if( (j = aIdx[i])>=0 ){
57965812
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
57975813
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
57985814
}
57995815
}
5816
+ /* The current generate_column() implementation requires at least one
5817
+ ** argument (the START value). Legacy versions assumed START=0 if the
5818
+ ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
5819
+ ** to obtain the legacy behavior */
5820
+#ifndef ZERO_ARGUMENT_GENERATE_SERIES
5821
+ if( !bStartSeen ){
5822
+ sqlite3_free(pVTab->zErrMsg);
5823
+ pVTab->zErrMsg = sqlite3_mprintf(
5824
+ "first argument to \"generate_series()\" missing or unusable");
5825
+ return SQLITE_ERROR;
5826
+ }
5827
+#endif
58005828
if( (unusableMask & ~idxNum)!=0 ){
58015829
/* The start, stop, and step columns are inputs. Therefore if there
58025830
** are unusable constraints on any of start, stop, or step then
58035831
** this plan is unusable */
58045832
return SQLITE_CONSTRAINT;
@@ -8143,10 +8171,11 @@
81438171
** time(2)).
81448172
*/
81458173
static u32 zipfileTime(void){
81468174
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
81478175
u32 ret;
8176
+ if( pVfs==0 ) return 0;
81488177
if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
81498178
i64 ms;
81508179
pVfs->xCurrentTimeInt64(pVfs, &ms);
81518180
ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
81528181
}else{
@@ -9847,15 +9876,17 @@
98479876
int nPk = 0;
98489877
98499878
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
98509879
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
98519880
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
9881
+ const char *zColSeq = 0;
98529882
nByte += 1 + STRLEN(zCol);
98539883
rc = sqlite3_table_column_metadata(
9854
- db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
9884
+ db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
98559885
);
9856
- nByte += 1 + STRLEN(zCol);
9886
+ if( zColSeq==0 ) zColSeq = "binary";
9887
+ nByte += 1 + STRLEN(zColSeq);
98579888
nCol++;
98589889
nPk += (sqlite3_column_int(p1, 5)>0);
98599890
}
98609891
rc2 = sqlite3_reset(p1);
98619892
if( rc==SQLITE_OK ) rc = rc2;
@@ -9871,23 +9902,25 @@
98719902
}
98729903
98739904
nCol = 0;
98749905
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
98759906
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
9907
+ const char *zColSeq = 0;
98769908
int nCopy = STRLEN(zCol) + 1;
98779909
pNew->aCol[nCol].zName = pCsr;
98789910
pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
98799911
memcpy(pCsr, zCol, nCopy);
98809912
pCsr += nCopy;
98819913
98829914
rc = sqlite3_table_column_metadata(
9883
- db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
9915
+ db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
98849916
);
98859917
if( rc==SQLITE_OK ){
9886
- nCopy = STRLEN(zCol) + 1;
9918
+ if( zColSeq==0 ) zColSeq = "binary";
9919
+ nCopy = STRLEN(zColSeq) + 1;
98879920
pNew->aCol[nCol].zColl = pCsr;
9888
- memcpy(pCsr, zCol, nCopy);
9921
+ memcpy(pCsr, zColSeq, nCopy);
98899922
pCsr += nCopy;
98909923
}
98919924
98929925
nCol++;
98939926
}
@@ -12065,23 +12098,26 @@
1206512098
int *actualWidth; /* Actual width of each column */
1206612099
int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
1206712100
char nullValue[20]; /* The text to print when a NULL comes back from
1206812101
** the database */
1206912102
char outfile[FILENAME_MAX]; /* Filename for *out */
12070
- const char *zDbFilename; /* name of the database file */
12071
- char *zFreeOnClose; /* Filename to free when closing */
12072
- const char *zVfs; /* Name of VFS to use */
1207312103
sqlite3_stmt *pStmt; /* Current statement if any. */
1207412104
FILE *pLog; /* Write log output here */
12105
+ struct AuxDb { /* Storage space for auxiliary database connections */
12106
+ sqlite3 *db; /* Connection pointer */
12107
+ const char *zDbFilename; /* Filename used to open the connection */
12108
+ char *zFreeOnClose; /* Free this memory allocation on close */
12109
+#if defined(SQLITE_ENABLE_SESSION)
12110
+ int nSession; /* Number of active sessions */
12111
+ OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
12112
+#endif
12113
+ } aAuxDb[5], /* Array of all database connections */
12114
+ *pAuxDb; /* Currently active database connection */
1207512115
int *aiIndent; /* Array of indents used in MODE_Explain */
1207612116
int nIndent; /* Size of array aiIndent[] */
1207712117
int iIndent; /* Index of current op in aiIndent[] */
1207812118
EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
12079
-#if defined(SQLITE_ENABLE_SESSION)
12080
- int nSession; /* Number of active sessions */
12081
- OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
12082
-#endif
1208312119
ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
1208412120
};
1208512121
1208612122
1208712123
/* Allowed values for ShellState.autoEQP
@@ -14829,10 +14865,11 @@
1482914865
".binary on|off Turn binary output on or off. Default OFF",
1483014866
".cd DIRECTORY Change the working directory to DIRECTORY",
1483114867
".changes on|off Show number of rows changed by SQL",
1483214868
".check GLOB Fail if output since .testcase does not match",
1483314869
".clone NEWDB Clone data into NEWDB from the existing database",
14870
+ ".connection [close] [#] Open or close an auxiliary database connection",
1483414871
".databases List names and files of attached databases",
1483514872
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
1483614873
".dbinfo ?DB? Show status information about the database",
1483714874
".dump ?OBJECTS? Render database content as SQL",
1483814875
" Options:",
@@ -15169,19 +15206,20 @@
1516915206
1517015207
/*
1517115208
** Close all OpenSession objects and release all associated resources.
1517215209
*/
1517315210
#if defined(SQLITE_ENABLE_SESSION)
15174
-static void session_close_all(ShellState *p){
15175
- int i;
15176
- for(i=0; i<p->nSession; i++){
15177
- session_close(&p->aSession[i]);
15211
+static void session_close_all(ShellState *p, int i){
15212
+ int j;
15213
+ struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
15214
+ for(j=0; j<pAuxDb->nSession; j++){
15215
+ session_close(&pAuxDb->aSession[j]);
1517815216
}
15179
- p->nSession = 0;
15217
+ pAuxDb->nSession = 0;
1518015218
}
1518115219
#else
15182
-# define session_close_all(X)
15220
+# define session_close_all(X,Y)
1518315221
#endif
1518415222
1518515223
/*
1518615224
** Implementation of the xFilter function for an open session. Omit
1518715225
** any tables named by ".session filter" but let all other table through.
@@ -15242,12 +15280,12 @@
1524215280
}
1524315281
1524415282
#ifndef SQLITE_OMIT_DESERIALIZE
1524515283
/*
1524615284
** Reconstruct an in-memory database using the output from the "dbtotxt"
15247
-** program. Read content from the file in p->zDbFilename. If p->zDbFilename
15248
-** is 0, then read from standard input.
15285
+** program. Read content from the file in p->aAuxDb[].zDbFilename.
15286
+** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
1524915287
*/
1525015288
static unsigned char *readHexDb(ShellState *p, int *pnData){
1525115289
unsigned char *a = 0;
1525215290
int nLine;
1525315291
int n = 0;
@@ -15254,16 +15292,17 @@
1525415292
int pgsz = 0;
1525515293
int iOffset = 0;
1525615294
int j, k;
1525715295
int rc;
1525815296
FILE *in;
15297
+ const char *zDbFilename = p->pAuxDb->zDbFilename;
1525915298
unsigned int x[16];
1526015299
char zLine[1000];
15261
- if( p->zDbFilename ){
15262
- in = fopen(p->zDbFilename, "r");
15300
+ if( zDbFilename ){
15301
+ in = fopen(zDbFilename, "r");
1526315302
if( in==0 ){
15264
- utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
15303
+ utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
1526515304
return 0;
1526615305
}
1526715306
nLine = 0;
1526815307
}else{
1526915308
in = p->in;
@@ -15501,21 +15540,22 @@
1550115540
** Make sure the database is open. If it is not, then open it. If
1550215541
** the database fails to open, print an error message and exit.
1550315542
*/
1550415543
static void open_db(ShellState *p, int openFlags){
1550515544
if( p->db==0 ){
15545
+ const char *zDbFilename = p->pAuxDb->zDbFilename;
1550615546
if( p->openMode==SHELL_OPEN_UNSPEC ){
15507
- if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
15547
+ if( zDbFilename==0 || zDbFilename[0]==0 ){
1550815548
p->openMode = SHELL_OPEN_NORMAL;
1550915549
}else{
15510
- p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
15550
+ p->openMode = (u8)deduceDatabaseType(zDbFilename,
1551115551
(openFlags & OPEN_DB_ZIPFILE)!=0);
1551215552
}
1551315553
}
1551415554
switch( p->openMode ){
1551515555
case SHELL_OPEN_APPENDVFS: {
15516
- sqlite3_open_v2(p->zDbFilename, &p->db,
15556
+ sqlite3_open_v2(zDbFilename, &p->db,
1551715557
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
1551815558
break;
1551915559
}
1552015560
case SHELL_OPEN_HEXDB:
1552115561
case SHELL_OPEN_DESERIALIZE: {
@@ -15525,25 +15565,25 @@
1552515565
case SHELL_OPEN_ZIPFILE: {
1552615566
sqlite3_open(":memory:", &p->db);
1552715567
break;
1552815568
}
1552915569
case SHELL_OPEN_READONLY: {
15530
- sqlite3_open_v2(p->zDbFilename, &p->db,
15570
+ sqlite3_open_v2(zDbFilename, &p->db,
1553115571
SQLITE_OPEN_READONLY|p->openFlags, 0);
1553215572
break;
1553315573
}
1553415574
case SHELL_OPEN_UNSPEC:
1553515575
case SHELL_OPEN_NORMAL: {
15536
- sqlite3_open_v2(p->zDbFilename, &p->db,
15576
+ sqlite3_open_v2(zDbFilename, &p->db,
1553715577
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
1553815578
break;
1553915579
}
1554015580
}
1554115581
globalDb = p->db;
1554215582
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
1554315583
utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
15544
- p->zDbFilename, sqlite3_errmsg(p->db));
15584
+ zDbFilename, sqlite3_errmsg(p->db));
1554515585
if( openFlags & OPEN_DB_KEEPALIVE ){
1554615586
sqlite3_open(":memory:", &p->db);
1554715587
return;
1554815588
}
1554915589
exit(1);
@@ -15586,11 +15626,11 @@
1558615626
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
1558715627
editFunc, 0, 0);
1558815628
#endif
1558915629
if( p->openMode==SHELL_OPEN_ZIPFILE ){
1559015630
char *zSql = sqlite3_mprintf(
15591
- "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
15631
+ "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
1559215632
sqlite3_exec(p->db, zSql, 0, 0, 0);
1559315633
sqlite3_free(zSql);
1559415634
}
1559515635
#ifndef SQLITE_OMIT_DESERIALIZE
1559615636
else
@@ -15597,11 +15637,11 @@
1559715637
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
1559815638
int rc;
1559915639
int nData = 0;
1560015640
unsigned char *aData;
1560115641
if( p->openMode==SHELL_OPEN_DESERIALIZE ){
15602
- aData = (unsigned char*)readFile(p->zDbFilename, &nData);
15642
+ aData = (unsigned char*)readFile(zDbFilename, &nData);
1560315643
}else{
1560415644
aData = readHexDb(p, &nData);
1560515645
if( aData==0 ){
1560615646
return;
1560715647
}
@@ -18318,11 +18358,10 @@
1831818358
sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
1831918359
return rc;
1832018360
}
1832118361
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
1832218362
18323
-
1832418363
/*
1832518364
** If an input line begins with "." then invoke this routine to
1832618365
** process that line.
1832718366
**
1832818367
** Return 1 on error, 2 to exit, and 0 otherwise.
@@ -18482,10 +18521,17 @@
1848218521
}else{
1848318522
raw_printf(stderr, "Usage: .binary on|off\n");
1848418523
rc = 1;
1848518524
}
1848618525
}else
18526
+
18527
+ /* The undocumented ".breakpoint" command causes a call to the no-op
18528
+ ** routine named test_breakpoint().
18529
+ */
18530
+ if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
18531
+ test_breakpoint();
18532
+ }else
1848718533
1848818534
if( c=='c' && strcmp(azArg[0],"cd")==0 ){
1848918535
if( nArg==2 ){
1849018536
#if defined(_WIN32) || defined(WIN32)
1849118537
wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
@@ -18502,17 +18548,10 @@
1850218548
raw_printf(stderr, "Usage: .cd DIRECTORY\n");
1850318549
rc = 1;
1850418550
}
1850518551
}else
1850618552
18507
- /* The undocumented ".breakpoint" command causes a call to the no-op
18508
- ** routine named test_breakpoint().
18509
- */
18510
- if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
18511
- test_breakpoint();
18512
- }else
18513
-
1851418553
if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
1851518554
if( nArg==2 ){
1851618555
setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
1851718556
}else{
1851818557
raw_printf(stderr, "Usage: .changes on|off\n");
@@ -18551,10 +18590,56 @@
1855118590
}else{
1855218591
raw_printf(stderr, "Usage: .clone FILENAME\n");
1855318592
rc = 1;
1855418593
}
1855518594
}else
18595
+
18596
+ if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
18597
+ if( nArg==1 ){
18598
+ /* List available connections */
18599
+ int i;
18600
+ for(i=0; i<ArraySize(p->aAuxDb); i++){
18601
+ const char *zFile = p->aAuxDb[i].zDbFilename;
18602
+ if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
18603
+ zFile = "(not open)";
18604
+ }else if( zFile==0 ){
18605
+ zFile = "(memory)";
18606
+ }else if( zFile[0]==0 ){
18607
+ zFile = "(temporary-file)";
18608
+ }
18609
+ if( p->pAuxDb == &p->aAuxDb[i] ){
18610
+ utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
18611
+ }else if( p->aAuxDb[i].db!=0 ){
18612
+ utf8_printf(stdout, " %d: %s\n", i, zFile);
18613
+ }
18614
+ }
18615
+ }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
18616
+ int i = azArg[1][0] - '0';
18617
+ if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
18618
+ p->pAuxDb->db = p->db;
18619
+ p->pAuxDb = &p->aAuxDb[i];
18620
+ globalDb = p->db = p->pAuxDb->db;
18621
+ p->pAuxDb->db = 0;
18622
+ }
18623
+ }else if( nArg==3 && strcmp(azArg[1], "close")==0
18624
+ && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
18625
+ int i = azArg[2][0] - '0';
18626
+ if( i<0 || i>=ArraySize(p->aAuxDb) ){
18627
+ /* No-op */
18628
+ }else if( p->pAuxDb == &p->aAuxDb[i] ){
18629
+ raw_printf(stderr, "cannot close the active database connection\n");
18630
+ rc = 1;
18631
+ }else if( p->aAuxDb[i].db ){
18632
+ session_close_all(p, i);
18633
+ close_db(p->aAuxDb[i].db);
18634
+ p->aAuxDb[i].db = 0;
18635
+ }
18636
+ }else{
18637
+ raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
18638
+ rc = 1;
18639
+ }
18640
+ }else
1855618641
1855718642
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
1855818643
char **azName = 0;
1855918644
int nName = 0;
1856018645
sqlite3_stmt *pStmt;
@@ -18997,11 +19082,11 @@
1899719082
"SELECT sql FROM"
1899819083
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
1899919084
" FROM sqlite_schema UNION ALL"
1900019085
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
1900119086
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
19002
- "ORDER BY rowid",
19087
+ "ORDER BY x",
1900319088
callback, &data, 0
1900419089
);
1900519090
if( rc==SQLITE_OK ){
1900619091
sqlite3_stmt *pStmt;
1900719092
rc = sqlite3_prepare_v2(p->db,
@@ -19013,12 +19098,10 @@
1901319098
}
1901419099
if( doStats==0 ){
1901519100
raw_printf(p->out, "/* No STAT tables available */\n");
1901619101
}else{
1901719102
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
19018
- sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
19019
- callback, &data, 0);
1902019103
data.cMode = data.mode = MODE_Insert;
1902119104
data.zDestTable = "sqlite_stat1";
1902219105
shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
1902319106
data.zDestTable = "sqlite_stat4";
1902419107
shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
@@ -19643,16 +19726,16 @@
1964319726
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
1964419727
char *zNewFilename = 0; /* Name of the database file to open */
1964519728
int iName = 1; /* Index in azArg[] of the filename */
1964619729
int newFlag = 0; /* True to delete file before opening */
1964719730
/* Close the existing database */
19648
- session_close_all(p);
19731
+ session_close_all(p, -1);
1964919732
close_db(p->db);
1965019733
p->db = 0;
19651
- p->zDbFilename = 0;
19652
- sqlite3_free(p->zFreeOnClose);
19653
- p->zFreeOnClose = 0;
19734
+ p->pAuxDb->zDbFilename = 0;
19735
+ sqlite3_free(p->pAuxDb->zFreeOnClose);
19736
+ p->pAuxDb->zFreeOnClose = 0;
1965419737
p->openMode = SHELL_OPEN_UNSPEC;
1965519738
p->openFlags = 0;
1965619739
p->szMax = 0;
1965719740
/* Check for command-line arguments */
1965819741
for(iName=1; iName<nArg; iName++){
@@ -19667,10 +19750,12 @@
1966719750
p->openMode = SHELL_OPEN_APPENDVFS;
1966819751
}else if( optionMatch(z, "readonly") ){
1966919752
p->openMode = SHELL_OPEN_READONLY;
1967019753
}else if( optionMatch(z, "nofollow") ){
1967119754
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
19755
+ }else if( optionMatch(z, "excl") ){
19756
+ p->openFlags |= SQLITE_OPEN_EXCLUSIVE;
1967219757
#ifndef SQLITE_OMIT_DESERIALIZE
1967319758
}else if( optionMatch(z, "deserialize") ){
1967419759
p->openMode = SHELL_OPEN_DESERIALIZE;
1967519760
}else if( optionMatch(z, "hexdb") ){
1967619761
p->openMode = SHELL_OPEN_HEXDB;
@@ -19690,22 +19775,22 @@
1969019775
}
1969119776
}
1969219777
/* If a filename is specified, try to open it first */
1969319778
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
1969419779
if( newFlag ) shellDeleteFile(zNewFilename);
19695
- p->zDbFilename = zNewFilename;
19780
+ p->pAuxDb->zDbFilename = zNewFilename;
1969619781
open_db(p, OPEN_DB_KEEPALIVE);
1969719782
if( p->db==0 ){
1969819783
utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
1969919784
sqlite3_free(zNewFilename);
1970019785
}else{
19701
- p->zFreeOnClose = zNewFilename;
19786
+ p->pAuxDb->zFreeOnClose = zNewFilename;
1970219787
}
1970319788
}
1970419789
if( p->db==0 ){
1970519790
/* As a fall-back open a TEMP database */
19706
- p->zDbFilename = 0;
19791
+ p->pAuxDb->zDbFilename = 0;
1970719792
open_db(p, 0);
1970819793
}
1970919794
}else
1971019795
1971119796
if( (c=='o'
@@ -20230,27 +20315,28 @@
2023020315
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
2023120316
}else
2023220317
2023320318
#if defined(SQLITE_ENABLE_SESSION)
2023420319
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
20235
- OpenSession *pSession = &p->aSession[0];
20320
+ struct AuxDb *pAuxDb = p->pAuxDb;
20321
+ OpenSession *pSession = &pAuxDb->aSession[0];
2023620322
char **azCmd = &azArg[1];
2023720323
int iSes = 0;
2023820324
int nCmd = nArg - 1;
2023920325
int i;
2024020326
if( nArg<=1 ) goto session_syntax_error;
2024120327
open_db(p, 0);
2024220328
if( nArg>=3 ){
20243
- for(iSes=0; iSes<p->nSession; iSes++){
20244
- if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
20329
+ for(iSes=0; iSes<pAuxDb->nSession; iSes++){
20330
+ if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
2024520331
}
20246
- if( iSes<p->nSession ){
20247
- pSession = &p->aSession[iSes];
20332
+ if( iSes<pAuxDb->nSession ){
20333
+ pSession = &pAuxDb->aSession[iSes];
2024820334
azCmd++;
2024920335
nCmd--;
2025020336
}else{
20251
- pSession = &p->aSession[0];
20337
+ pSession = &pAuxDb->aSession[0];
2025220338
iSes = 0;
2025320339
}
2025420340
}
2025520341
2025620342
/* .session attach TABLE
@@ -20308,13 +20394,13 @@
2030820394
/* .session close
2030920395
** Close the identified session
2031020396
*/
2031120397
if( strcmp(azCmd[0], "close")==0 ){
2031220398
if( nCmd!=1 ) goto session_syntax_error;
20313
- if( p->nSession ){
20399
+ if( pAuxDb->nSession ){
2031420400
session_close(pSession);
20315
- p->aSession[iSes] = p->aSession[--p->nSession];
20401
+ pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
2031620402
}
2031720403
}else
2031820404
2031920405
/* .session enable ?BOOLEAN?
2032020406
** Query or set the enable flag
@@ -20321,11 +20407,11 @@
2032120407
*/
2032220408
if( strcmp(azCmd[0], "enable")==0 ){
2032320409
int ii;
2032420410
if( nCmd>2 ) goto session_syntax_error;
2032520411
ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
20326
- if( p->nSession ){
20412
+ if( pAuxDb->nSession ){
2032720413
ii = sqlite3session_enable(pSession->p, ii);
2032820414
utf8_printf(p->out, "session %s enable flag = %d\n",
2032920415
pSession->zName, ii);
2033020416
}
2033120417
}else
@@ -20334,11 +20420,11 @@
2033420420
** Set a list of GLOB patterns of table names to be excluded.
2033520421
*/
2033620422
if( strcmp(azCmd[0], "filter")==0 ){
2033720423
int ii, nByte;
2033820424
if( nCmd<2 ) goto session_syntax_error;
20339
- if( p->nSession ){
20425
+ if( pAuxDb->nSession ){
2034020426
for(ii=0; ii<pSession->nFilter; ii++){
2034120427
sqlite3_free(pSession->azFilter[ii]);
2034220428
}
2034320429
sqlite3_free(pSession->azFilter);
2034420430
nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
@@ -20359,11 +20445,11 @@
2035920445
*/
2036020446
if( strcmp(azCmd[0], "indirect")==0 ){
2036120447
int ii;
2036220448
if( nCmd>2 ) goto session_syntax_error;
2036320449
ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
20364
- if( p->nSession ){
20450
+ if( pAuxDb->nSession ){
2036520451
ii = sqlite3session_indirect(pSession->p, ii);
2036620452
utf8_printf(p->out, "session %s indirect flag = %d\n",
2036720453
pSession->zName, ii);
2036820454
}
2036920455
}else
@@ -20372,11 +20458,11 @@
2037220458
** Determine if the session is empty
2037320459
*/
2037420460
if( strcmp(azCmd[0], "isempty")==0 ){
2037520461
int ii;
2037620462
if( nCmd!=1 ) goto session_syntax_error;
20377
- if( p->nSession ){
20463
+ if( pAuxDb->nSession ){
2037820464
ii = sqlite3session_isempty(pSession->p);
2037920465
utf8_printf(p->out, "session %s isempty flag = %d\n",
2038020466
pSession->zName, ii);
2038120467
}
2038220468
}else
@@ -20383,12 +20469,12 @@
2038320469
2038420470
/* .session list
2038520471
** List all currently open sessions
2038620472
*/
2038720473
if( strcmp(azCmd[0],"list")==0 ){
20388
- for(i=0; i<p->nSession; i++){
20389
- utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
20474
+ for(i=0; i<pAuxDb->nSession; i++){
20475
+ utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
2039020476
}
2039120477
}else
2039220478
2039320479
/* .session open DB NAME
2039420480
** Open a new session called NAME on the attached database DB.
@@ -20397,30 +20483,30 @@
2039720483
if( strcmp(azCmd[0],"open")==0 ){
2039820484
char *zName;
2039920485
if( nCmd!=3 ) goto session_syntax_error;
2040020486
zName = azCmd[2];
2040120487
if( zName[0]==0 ) goto session_syntax_error;
20402
- for(i=0; i<p->nSession; i++){
20403
- if( strcmp(p->aSession[i].zName,zName)==0 ){
20488
+ for(i=0; i<pAuxDb->nSession; i++){
20489
+ if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
2040420490
utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
2040520491
goto meta_command_exit;
2040620492
}
2040720493
}
20408
- if( p->nSession>=ArraySize(p->aSession) ){
20409
- raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
20494
+ if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
20495
+ raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
2041020496
goto meta_command_exit;
2041120497
}
20412
- pSession = &p->aSession[p->nSession];
20498
+ pSession = &pAuxDb->aSession[pAuxDb->nSession];
2041320499
rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
2041420500
if( rc ){
2041520501
raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
2041620502
rc = 0;
2041720503
goto meta_command_exit;
2041820504
}
2041920505
pSession->nFilter = 0;
2042020506
sqlite3session_table_filter(pSession->p, session_filter, pSession);
20421
- p->nSession++;
20507
+ pAuxDb->nSession++;
2042220508
pSession->zName = sqlite3_mprintf("%s", zName);
2042320509
}else
2042420510
/* If no command name matches, show a syntax error */
2042520511
session_syntax_error:
2042620512
showHelp(p->out, "session");
@@ -20745,11 +20831,11 @@
2074520831
for (i=0;i<p->nWidth;i++) {
2074620832
raw_printf(p->out, "%d ", p->colWidth[i]);
2074720833
}
2074820834
raw_printf(p->out, "\n");
2074920835
utf8_printf(p->out, "%12.12s: %s\n", "filename",
20750
- p->zDbFilename ? p->zDbFilename : "");
20836
+ p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
2075120837
}else
2075220838
2075320839
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
2075420840
if( nArg==2 ){
2075520841
if( strcmp(azArg[1],"stmt")==0 ){
@@ -20912,10 +20998,11 @@
2091220998
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
2091320999
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
2091421000
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
2091521001
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
2091621002
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
21003
+ { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" },
2091721004
{ "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
2091821005
};
2091921006
int testctrl = -1;
2092021007
int iCtrl = -1;
2092121008
int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
@@ -21092,10 +21179,17 @@
2109221179
isOk = 3;
2109321180
}
2109421181
break;
2109521182
}
2109621183
#endif
21184
+ case SQLITE_TESTCTRL_SORTER_MMAP:
21185
+ if( nArg==3 ){
21186
+ int opt = (unsigned int)integerValue(azArg[2]);
21187
+ rc2 = sqlite3_test_control(testctrl, p->db, opt);
21188
+ isOk = 3;
21189
+ }
21190
+ break;
2109721191
}
2109821192
}
2109921193
if( isOk==0 && iCtrl>=0 ){
2110021194
utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
2110121195
rc = 1;
@@ -21460,12 +21554,12 @@
2146021554
}else{
2146121555
utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
2146221556
}
2146321557
return 1;
2146421558
}else if( ShellHasFlag(p, SHFLG_CountChanges) ){
21465
- raw_printf(p->out, "changes: %3d total_changes: %d\n",
21466
- sqlite3_changes(p->db), sqlite3_total_changes(p->db));
21559
+ raw_printf(p->out, "changes: %3lld total_changes: %lld\n",
21560
+ sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
2146721561
}
2146821562
return 0;
2146921563
}
2147021564
2147121565
@@ -21766,10 +21860,11 @@
2176621860
*/
2176721861
static void main_init(ShellState *data) {
2176821862
memset(data, 0, sizeof(*data));
2176921863
data->normalMode = data->cMode = data->mode = MODE_List;
2177021864
data->autoExplain = 1;
21865
+ data->pAuxDb = &data->aAuxDb[0];
2177121866
memcpy(data->colSeparator,SEP_Column, 2);
2177221867
memcpy(data->rowSeparator,SEP_Row, 2);
2177321868
data->showHeader = 0;
2177421869
data->shellFlgs = SHFLG_Lookaside;
2177521870
verify_uninitialized();
@@ -21929,11 +22024,11 @@
2192922024
/* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
2193022025
** of a C-function that will provide the name of the database file. Use
2193122026
** this compile-time option to embed this shell program in larger
2193222027
** applications. */
2193322028
extern void SQLITE_SHELL_DBNAME_PROC(const char**);
21934
- SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
22029
+ SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
2193522030
warnInmemoryDb = 0;
2193622031
}
2193722032
#endif
2193822033
2193922034
/* Do an initial pass through the command-line argument to locate
@@ -21944,12 +22039,12 @@
2194422039
verify_uninitialized();
2194522040
for(i=1; i<argc; i++){
2194622041
char *z;
2194722042
z = argv[i];
2194822043
if( z[0]!='-' ){
21949
- if( data.zDbFilename==0 ){
21950
- data.zDbFilename = z;
22044
+ if( data.aAuxDb->zDbFilename==0 ){
22045
+ data.aAuxDb->zDbFilename = z;
2195122046
}else{
2195222047
/* Excesss arguments are interpreted as SQL (or dot-commands) and
2195322048
** mean that nothing is read from stdin */
2195422049
readStdin = 0;
2195522050
nCmd++;
@@ -22085,13 +22180,13 @@
2208522180
utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
2208622181
exit(1);
2208722182
}
2208822183
}
2208922184
22090
- if( data.zDbFilename==0 ){
22185
+ if( data.pAuxDb->zDbFilename==0 ){
2209122186
#ifndef SQLITE_OMIT_MEMORYDB
22092
- data.zDbFilename = ":memory:";
22187
+ data.pAuxDb->zDbFilename = ":memory:";
2209322188
warnInmemoryDb = argc==1;
2209422189
#else
2209522190
utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
2209622191
return 1;
2209722192
#endif
@@ -22102,11 +22197,11 @@
2210222197
/* Go ahead and open the database file if it already exists. If the
2210322198
** file does not exist, delay opening it. This prevents empty database
2210422199
** files from being created if a user mistypes the database name argument
2210522200
** to the sqlite command-line tool.
2210622201
*/
22107
- if( access(data.zDbFilename, 0)==0 ){
22202
+ if( access(data.pAuxDb->zDbFilename, 0)==0 ){
2210822203
open_db(&data, 0);
2210922204
}
2211022205
2211122206
/* Process the initialization file if there is one. If no -init option
2211222207
** is given on the command line, look for a file named ~/.sqliterc and
@@ -22356,14 +22451,20 @@
2235622451
}
2235722452
}
2235822453
free(azCmd);
2235922454
set_table_name(&data, 0);
2236022455
if( data.db ){
22361
- session_close_all(&data);
22456
+ session_close_all(&data, -1);
2236222457
close_db(data.db);
2236322458
}
22364
- sqlite3_free(data.zFreeOnClose);
22459
+ for(i=0; i<ArraySize(data.aAuxDb); i++){
22460
+ sqlite3_free(data.aAuxDb[i].zFreeOnClose);
22461
+ if( data.aAuxDb[i].db ){
22462
+ session_close_all(&data, i);
22463
+ close_db(data.aAuxDb[i].db);
22464
+ }
22465
+ }
2236522466
find_home_dir(1);
2236622467
output_reset(&data);
2236722468
data.doXdgOpen = 0;
2236822469
clearTempFile(&data);
2236922470
#if !SQLITE_SHELL_IS_UTF8
2237022471
--- src/shell.c
+++ src/shell.c
@@ -33,10 +33,22 @@
33 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
34 /* This needs to come before any includes for MSVC compiler */
35 #define _CRT_SECURE_NO_WARNINGS
36 #endif
37
 
 
 
 
 
 
 
 
 
 
 
 
38 /*
39 ** Determine if we are dealing with WinRT, which provides only a subset of
40 ** the full Win32 API.
41 */
42 #if !defined(SQLITE_OS_WINRT)
@@ -242,10 +254,11 @@
242 /* Return the current wall-clock time */
243 static sqlite3_int64 timeOfDay(void){
244 static sqlite3_vfs *clockVfs = 0;
245 sqlite3_int64 t;
246 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
 
247 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
248 clockVfs->xCurrentTimeInt64(clockVfs, &t);
249 }else{
250 double r;
251 clockVfs->xCurrentTime(clockVfs, &r);
@@ -986,11 +999,11 @@
986 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
987 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
988 sqlite3 *db = sqlite3_context_db_handle(pCtx);
989 UNUSED_PARAMETER(nVal);
990 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
991 for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
992 int n = strlen30(aPrefix[i]);
993 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
994 char *z = 0;
995 char *zFake = 0;
996 if( zSchema ){
@@ -4281,10 +4294,11 @@
4281 sqlite3_vfs *pOrig;
4282 SQLITE_EXTENSION_INIT2(pApi);
4283 (void)pzErrMsg;
4284 (void)db;
4285 pOrig = sqlite3_vfs_find(0);
 
4286 apnd_vfs.iVersion = pOrig->iVersion;
4287 apnd_vfs.pAppData = pOrig;
4288 apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
4289 rc = sqlite3_vfs_register(&apnd_vfs, 0);
4290 #ifdef APPENDVFS_TEST
@@ -5757,34 +5771,36 @@
5757 ** (2) stop = $value -- constraint exists
5758 ** (4) step = $value -- constraint exists
5759 ** (8) output in descending order
5760 */
5761 static int seriesBestIndex(
5762 sqlite3_vtab *tabUnused,
5763 sqlite3_index_info *pIdxInfo
5764 ){
5765 int i, j; /* Loop over constraints */
5766 int idxNum = 0; /* The query plan bitmask */
 
5767 int unusableMask = 0; /* Mask of unusable constraints */
5768 int nArg = 0; /* Number of arguments that seriesFilter() expects */
5769 int aIdx[3]; /* Constraints on start, stop, and step */
5770 const struct sqlite3_index_constraint *pConstraint;
5771
5772 /* This implementation assumes that the start, stop, and step columns
5773 ** are the last three columns in the virtual table. */
5774 assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
5775 assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
5776 (void)tabUnused;
5777 aIdx[0] = aIdx[1] = aIdx[2] = -1;
5778 pConstraint = pIdxInfo->aConstraint;
5779 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
5780 int iCol; /* 0 for start, 1 for stop, 2 for step */
5781 int iMask; /* bitmask for those column */
5782 if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
5783 iCol = pConstraint->iColumn - SERIES_COLUMN_START;
5784 assert( iCol>=0 && iCol<=2 );
5785 iMask = 1 << iCol;
 
5786 if( pConstraint->usable==0 ){
5787 unusableMask |= iMask;
5788 continue;
5789 }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
5790 idxNum |= iMask;
@@ -5795,10 +5811,22 @@
5795 if( (j = aIdx[i])>=0 ){
5796 pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
5797 pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
5798 }
5799 }
 
 
 
 
 
 
 
 
 
 
 
 
5800 if( (unusableMask & ~idxNum)!=0 ){
5801 /* The start, stop, and step columns are inputs. Therefore if there
5802 ** are unusable constraints on any of start, stop, or step then
5803 ** this plan is unusable */
5804 return SQLITE_CONSTRAINT;
@@ -8143,10 +8171,11 @@
8143 ** time(2)).
8144 */
8145 static u32 zipfileTime(void){
8146 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
8147 u32 ret;
 
8148 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
8149 i64 ms;
8150 pVfs->xCurrentTimeInt64(pVfs, &ms);
8151 ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
8152 }else{
@@ -9847,15 +9876,17 @@
9847 int nPk = 0;
9848
9849 rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
9850 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
9851 const char *zCol = (const char*)sqlite3_column_text(p1, 1);
 
9852 nByte += 1 + STRLEN(zCol);
9853 rc = sqlite3_table_column_metadata(
9854 db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
9855 );
9856 nByte += 1 + STRLEN(zCol);
 
9857 nCol++;
9858 nPk += (sqlite3_column_int(p1, 5)>0);
9859 }
9860 rc2 = sqlite3_reset(p1);
9861 if( rc==SQLITE_OK ) rc = rc2;
@@ -9871,23 +9902,25 @@
9871 }
9872
9873 nCol = 0;
9874 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
9875 const char *zCol = (const char*)sqlite3_column_text(p1, 1);
 
9876 int nCopy = STRLEN(zCol) + 1;
9877 pNew->aCol[nCol].zName = pCsr;
9878 pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
9879 memcpy(pCsr, zCol, nCopy);
9880 pCsr += nCopy;
9881
9882 rc = sqlite3_table_column_metadata(
9883 db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
9884 );
9885 if( rc==SQLITE_OK ){
9886 nCopy = STRLEN(zCol) + 1;
 
9887 pNew->aCol[nCol].zColl = pCsr;
9888 memcpy(pCsr, zCol, nCopy);
9889 pCsr += nCopy;
9890 }
9891
9892 nCol++;
9893 }
@@ -12065,23 +12098,26 @@
12065 int *actualWidth; /* Actual width of each column */
12066 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
12067 char nullValue[20]; /* The text to print when a NULL comes back from
12068 ** the database */
12069 char outfile[FILENAME_MAX]; /* Filename for *out */
12070 const char *zDbFilename; /* name of the database file */
12071 char *zFreeOnClose; /* Filename to free when closing */
12072 const char *zVfs; /* Name of VFS to use */
12073 sqlite3_stmt *pStmt; /* Current statement if any. */
12074 FILE *pLog; /* Write log output here */
 
 
 
 
 
 
 
 
 
 
12075 int *aiIndent; /* Array of indents used in MODE_Explain */
12076 int nIndent; /* Size of array aiIndent[] */
12077 int iIndent; /* Index of current op in aiIndent[] */
12078 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
12079 #if defined(SQLITE_ENABLE_SESSION)
12080 int nSession; /* Number of active sessions */
12081 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
12082 #endif
12083 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
12084 };
12085
12086
12087 /* Allowed values for ShellState.autoEQP
@@ -14829,10 +14865,11 @@
14829 ".binary on|off Turn binary output on or off. Default OFF",
14830 ".cd DIRECTORY Change the working directory to DIRECTORY",
14831 ".changes on|off Show number of rows changed by SQL",
14832 ".check GLOB Fail if output since .testcase does not match",
14833 ".clone NEWDB Clone data into NEWDB from the existing database",
 
14834 ".databases List names and files of attached databases",
14835 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
14836 ".dbinfo ?DB? Show status information about the database",
14837 ".dump ?OBJECTS? Render database content as SQL",
14838 " Options:",
@@ -15169,19 +15206,20 @@
15169
15170 /*
15171 ** Close all OpenSession objects and release all associated resources.
15172 */
15173 #if defined(SQLITE_ENABLE_SESSION)
15174 static void session_close_all(ShellState *p){
15175 int i;
15176 for(i=0; i<p->nSession; i++){
15177 session_close(&p->aSession[i]);
 
15178 }
15179 p->nSession = 0;
15180 }
15181 #else
15182 # define session_close_all(X)
15183 #endif
15184
15185 /*
15186 ** Implementation of the xFilter function for an open session. Omit
15187 ** any tables named by ".session filter" but let all other table through.
@@ -15242,12 +15280,12 @@
15242 }
15243
15244 #ifndef SQLITE_OMIT_DESERIALIZE
15245 /*
15246 ** Reconstruct an in-memory database using the output from the "dbtotxt"
15247 ** program. Read content from the file in p->zDbFilename. If p->zDbFilename
15248 ** is 0, then read from standard input.
15249 */
15250 static unsigned char *readHexDb(ShellState *p, int *pnData){
15251 unsigned char *a = 0;
15252 int nLine;
15253 int n = 0;
@@ -15254,16 +15292,17 @@
15254 int pgsz = 0;
15255 int iOffset = 0;
15256 int j, k;
15257 int rc;
15258 FILE *in;
 
15259 unsigned int x[16];
15260 char zLine[1000];
15261 if( p->zDbFilename ){
15262 in = fopen(p->zDbFilename, "r");
15263 if( in==0 ){
15264 utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
15265 return 0;
15266 }
15267 nLine = 0;
15268 }else{
15269 in = p->in;
@@ -15501,21 +15540,22 @@
15501 ** Make sure the database is open. If it is not, then open it. If
15502 ** the database fails to open, print an error message and exit.
15503 */
15504 static void open_db(ShellState *p, int openFlags){
15505 if( p->db==0 ){
 
15506 if( p->openMode==SHELL_OPEN_UNSPEC ){
15507 if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
15508 p->openMode = SHELL_OPEN_NORMAL;
15509 }else{
15510 p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
15511 (openFlags & OPEN_DB_ZIPFILE)!=0);
15512 }
15513 }
15514 switch( p->openMode ){
15515 case SHELL_OPEN_APPENDVFS: {
15516 sqlite3_open_v2(p->zDbFilename, &p->db,
15517 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
15518 break;
15519 }
15520 case SHELL_OPEN_HEXDB:
15521 case SHELL_OPEN_DESERIALIZE: {
@@ -15525,25 +15565,25 @@
15525 case SHELL_OPEN_ZIPFILE: {
15526 sqlite3_open(":memory:", &p->db);
15527 break;
15528 }
15529 case SHELL_OPEN_READONLY: {
15530 sqlite3_open_v2(p->zDbFilename, &p->db,
15531 SQLITE_OPEN_READONLY|p->openFlags, 0);
15532 break;
15533 }
15534 case SHELL_OPEN_UNSPEC:
15535 case SHELL_OPEN_NORMAL: {
15536 sqlite3_open_v2(p->zDbFilename, &p->db,
15537 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
15538 break;
15539 }
15540 }
15541 globalDb = p->db;
15542 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
15543 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
15544 p->zDbFilename, sqlite3_errmsg(p->db));
15545 if( openFlags & OPEN_DB_KEEPALIVE ){
15546 sqlite3_open(":memory:", &p->db);
15547 return;
15548 }
15549 exit(1);
@@ -15586,11 +15626,11 @@
15586 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
15587 editFunc, 0, 0);
15588 #endif
15589 if( p->openMode==SHELL_OPEN_ZIPFILE ){
15590 char *zSql = sqlite3_mprintf(
15591 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
15592 sqlite3_exec(p->db, zSql, 0, 0, 0);
15593 sqlite3_free(zSql);
15594 }
15595 #ifndef SQLITE_OMIT_DESERIALIZE
15596 else
@@ -15597,11 +15637,11 @@
15597 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
15598 int rc;
15599 int nData = 0;
15600 unsigned char *aData;
15601 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
15602 aData = (unsigned char*)readFile(p->zDbFilename, &nData);
15603 }else{
15604 aData = readHexDb(p, &nData);
15605 if( aData==0 ){
15606 return;
15607 }
@@ -18318,11 +18358,10 @@
18318 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
18319 return rc;
18320 }
18321 #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
18322
18323
18324 /*
18325 ** If an input line begins with "." then invoke this routine to
18326 ** process that line.
18327 **
18328 ** Return 1 on error, 2 to exit, and 0 otherwise.
@@ -18482,10 +18521,17 @@
18482 }else{
18483 raw_printf(stderr, "Usage: .binary on|off\n");
18484 rc = 1;
18485 }
18486 }else
 
 
 
 
 
 
 
18487
18488 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
18489 if( nArg==2 ){
18490 #if defined(_WIN32) || defined(WIN32)
18491 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
@@ -18502,17 +18548,10 @@
18502 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
18503 rc = 1;
18504 }
18505 }else
18506
18507 /* The undocumented ".breakpoint" command causes a call to the no-op
18508 ** routine named test_breakpoint().
18509 */
18510 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
18511 test_breakpoint();
18512 }else
18513
18514 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
18515 if( nArg==2 ){
18516 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
18517 }else{
18518 raw_printf(stderr, "Usage: .changes on|off\n");
@@ -18551,10 +18590,56 @@
18551 }else{
18552 raw_printf(stderr, "Usage: .clone FILENAME\n");
18553 rc = 1;
18554 }
18555 }else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18556
18557 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
18558 char **azName = 0;
18559 int nName = 0;
18560 sqlite3_stmt *pStmt;
@@ -18997,11 +19082,11 @@
18997 "SELECT sql FROM"
18998 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
18999 " FROM sqlite_schema UNION ALL"
19000 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
19001 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
19002 "ORDER BY rowid",
19003 callback, &data, 0
19004 );
19005 if( rc==SQLITE_OK ){
19006 sqlite3_stmt *pStmt;
19007 rc = sqlite3_prepare_v2(p->db,
@@ -19013,12 +19098,10 @@
19013 }
19014 if( doStats==0 ){
19015 raw_printf(p->out, "/* No STAT tables available */\n");
19016 }else{
19017 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
19018 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
19019 callback, &data, 0);
19020 data.cMode = data.mode = MODE_Insert;
19021 data.zDestTable = "sqlite_stat1";
19022 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
19023 data.zDestTable = "sqlite_stat4";
19024 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
@@ -19643,16 +19726,16 @@
19643 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
19644 char *zNewFilename = 0; /* Name of the database file to open */
19645 int iName = 1; /* Index in azArg[] of the filename */
19646 int newFlag = 0; /* True to delete file before opening */
19647 /* Close the existing database */
19648 session_close_all(p);
19649 close_db(p->db);
19650 p->db = 0;
19651 p->zDbFilename = 0;
19652 sqlite3_free(p->zFreeOnClose);
19653 p->zFreeOnClose = 0;
19654 p->openMode = SHELL_OPEN_UNSPEC;
19655 p->openFlags = 0;
19656 p->szMax = 0;
19657 /* Check for command-line arguments */
19658 for(iName=1; iName<nArg; iName++){
@@ -19667,10 +19750,12 @@
19667 p->openMode = SHELL_OPEN_APPENDVFS;
19668 }else if( optionMatch(z, "readonly") ){
19669 p->openMode = SHELL_OPEN_READONLY;
19670 }else if( optionMatch(z, "nofollow") ){
19671 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
 
 
19672 #ifndef SQLITE_OMIT_DESERIALIZE
19673 }else if( optionMatch(z, "deserialize") ){
19674 p->openMode = SHELL_OPEN_DESERIALIZE;
19675 }else if( optionMatch(z, "hexdb") ){
19676 p->openMode = SHELL_OPEN_HEXDB;
@@ -19690,22 +19775,22 @@
19690 }
19691 }
19692 /* If a filename is specified, try to open it first */
19693 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
19694 if( newFlag ) shellDeleteFile(zNewFilename);
19695 p->zDbFilename = zNewFilename;
19696 open_db(p, OPEN_DB_KEEPALIVE);
19697 if( p->db==0 ){
19698 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
19699 sqlite3_free(zNewFilename);
19700 }else{
19701 p->zFreeOnClose = zNewFilename;
19702 }
19703 }
19704 if( p->db==0 ){
19705 /* As a fall-back open a TEMP database */
19706 p->zDbFilename = 0;
19707 open_db(p, 0);
19708 }
19709 }else
19710
19711 if( (c=='o'
@@ -20230,27 +20315,28 @@
20230 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
20231 }else
20232
20233 #if defined(SQLITE_ENABLE_SESSION)
20234 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
20235 OpenSession *pSession = &p->aSession[0];
 
20236 char **azCmd = &azArg[1];
20237 int iSes = 0;
20238 int nCmd = nArg - 1;
20239 int i;
20240 if( nArg<=1 ) goto session_syntax_error;
20241 open_db(p, 0);
20242 if( nArg>=3 ){
20243 for(iSes=0; iSes<p->nSession; iSes++){
20244 if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
20245 }
20246 if( iSes<p->nSession ){
20247 pSession = &p->aSession[iSes];
20248 azCmd++;
20249 nCmd--;
20250 }else{
20251 pSession = &p->aSession[0];
20252 iSes = 0;
20253 }
20254 }
20255
20256 /* .session attach TABLE
@@ -20308,13 +20394,13 @@
20308 /* .session close
20309 ** Close the identified session
20310 */
20311 if( strcmp(azCmd[0], "close")==0 ){
20312 if( nCmd!=1 ) goto session_syntax_error;
20313 if( p->nSession ){
20314 session_close(pSession);
20315 p->aSession[iSes] = p->aSession[--p->nSession];
20316 }
20317 }else
20318
20319 /* .session enable ?BOOLEAN?
20320 ** Query or set the enable flag
@@ -20321,11 +20407,11 @@
20321 */
20322 if( strcmp(azCmd[0], "enable")==0 ){
20323 int ii;
20324 if( nCmd>2 ) goto session_syntax_error;
20325 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
20326 if( p->nSession ){
20327 ii = sqlite3session_enable(pSession->p, ii);
20328 utf8_printf(p->out, "session %s enable flag = %d\n",
20329 pSession->zName, ii);
20330 }
20331 }else
@@ -20334,11 +20420,11 @@
20334 ** Set a list of GLOB patterns of table names to be excluded.
20335 */
20336 if( strcmp(azCmd[0], "filter")==0 ){
20337 int ii, nByte;
20338 if( nCmd<2 ) goto session_syntax_error;
20339 if( p->nSession ){
20340 for(ii=0; ii<pSession->nFilter; ii++){
20341 sqlite3_free(pSession->azFilter[ii]);
20342 }
20343 sqlite3_free(pSession->azFilter);
20344 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
@@ -20359,11 +20445,11 @@
20359 */
20360 if( strcmp(azCmd[0], "indirect")==0 ){
20361 int ii;
20362 if( nCmd>2 ) goto session_syntax_error;
20363 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
20364 if( p->nSession ){
20365 ii = sqlite3session_indirect(pSession->p, ii);
20366 utf8_printf(p->out, "session %s indirect flag = %d\n",
20367 pSession->zName, ii);
20368 }
20369 }else
@@ -20372,11 +20458,11 @@
20372 ** Determine if the session is empty
20373 */
20374 if( strcmp(azCmd[0], "isempty")==0 ){
20375 int ii;
20376 if( nCmd!=1 ) goto session_syntax_error;
20377 if( p->nSession ){
20378 ii = sqlite3session_isempty(pSession->p);
20379 utf8_printf(p->out, "session %s isempty flag = %d\n",
20380 pSession->zName, ii);
20381 }
20382 }else
@@ -20383,12 +20469,12 @@
20383
20384 /* .session list
20385 ** List all currently open sessions
20386 */
20387 if( strcmp(azCmd[0],"list")==0 ){
20388 for(i=0; i<p->nSession; i++){
20389 utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
20390 }
20391 }else
20392
20393 /* .session open DB NAME
20394 ** Open a new session called NAME on the attached database DB.
@@ -20397,30 +20483,30 @@
20397 if( strcmp(azCmd[0],"open")==0 ){
20398 char *zName;
20399 if( nCmd!=3 ) goto session_syntax_error;
20400 zName = azCmd[2];
20401 if( zName[0]==0 ) goto session_syntax_error;
20402 for(i=0; i<p->nSession; i++){
20403 if( strcmp(p->aSession[i].zName,zName)==0 ){
20404 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
20405 goto meta_command_exit;
20406 }
20407 }
20408 if( p->nSession>=ArraySize(p->aSession) ){
20409 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
20410 goto meta_command_exit;
20411 }
20412 pSession = &p->aSession[p->nSession];
20413 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
20414 if( rc ){
20415 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
20416 rc = 0;
20417 goto meta_command_exit;
20418 }
20419 pSession->nFilter = 0;
20420 sqlite3session_table_filter(pSession->p, session_filter, pSession);
20421 p->nSession++;
20422 pSession->zName = sqlite3_mprintf("%s", zName);
20423 }else
20424 /* If no command name matches, show a syntax error */
20425 session_syntax_error:
20426 showHelp(p->out, "session");
@@ -20745,11 +20831,11 @@
20745 for (i=0;i<p->nWidth;i++) {
20746 raw_printf(p->out, "%d ", p->colWidth[i]);
20747 }
20748 raw_printf(p->out, "\n");
20749 utf8_printf(p->out, "%12.12s: %s\n", "filename",
20750 p->zDbFilename ? p->zDbFilename : "");
20751 }else
20752
20753 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
20754 if( nArg==2 ){
20755 if( strcmp(azArg[1],"stmt")==0 ){
@@ -20912,10 +20998,11 @@
20912 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
20913 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
20914 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
20915 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
20916 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
 
20917 { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
20918 };
20919 int testctrl = -1;
20920 int iCtrl = -1;
20921 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
@@ -21092,10 +21179,17 @@
21092 isOk = 3;
21093 }
21094 break;
21095 }
21096 #endif
 
 
 
 
 
 
 
21097 }
21098 }
21099 if( isOk==0 && iCtrl>=0 ){
21100 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
21101 rc = 1;
@@ -21460,12 +21554,12 @@
21460 }else{
21461 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
21462 }
21463 return 1;
21464 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
21465 raw_printf(p->out, "changes: %3d total_changes: %d\n",
21466 sqlite3_changes(p->db), sqlite3_total_changes(p->db));
21467 }
21468 return 0;
21469 }
21470
21471
@@ -21766,10 +21860,11 @@
21766 */
21767 static void main_init(ShellState *data) {
21768 memset(data, 0, sizeof(*data));
21769 data->normalMode = data->cMode = data->mode = MODE_List;
21770 data->autoExplain = 1;
 
21771 memcpy(data->colSeparator,SEP_Column, 2);
21772 memcpy(data->rowSeparator,SEP_Row, 2);
21773 data->showHeader = 0;
21774 data->shellFlgs = SHFLG_Lookaside;
21775 verify_uninitialized();
@@ -21929,11 +22024,11 @@
21929 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
21930 ** of a C-function that will provide the name of the database file. Use
21931 ** this compile-time option to embed this shell program in larger
21932 ** applications. */
21933 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
21934 SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
21935 warnInmemoryDb = 0;
21936 }
21937 #endif
21938
21939 /* Do an initial pass through the command-line argument to locate
@@ -21944,12 +22039,12 @@
21944 verify_uninitialized();
21945 for(i=1; i<argc; i++){
21946 char *z;
21947 z = argv[i];
21948 if( z[0]!='-' ){
21949 if( data.zDbFilename==0 ){
21950 data.zDbFilename = z;
21951 }else{
21952 /* Excesss arguments are interpreted as SQL (or dot-commands) and
21953 ** mean that nothing is read from stdin */
21954 readStdin = 0;
21955 nCmd++;
@@ -22085,13 +22180,13 @@
22085 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
22086 exit(1);
22087 }
22088 }
22089
22090 if( data.zDbFilename==0 ){
22091 #ifndef SQLITE_OMIT_MEMORYDB
22092 data.zDbFilename = ":memory:";
22093 warnInmemoryDb = argc==1;
22094 #else
22095 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
22096 return 1;
22097 #endif
@@ -22102,11 +22197,11 @@
22102 /* Go ahead and open the database file if it already exists. If the
22103 ** file does not exist, delay opening it. This prevents empty database
22104 ** files from being created if a user mistypes the database name argument
22105 ** to the sqlite command-line tool.
22106 */
22107 if( access(data.zDbFilename, 0)==0 ){
22108 open_db(&data, 0);
22109 }
22110
22111 /* Process the initialization file if there is one. If no -init option
22112 ** is given on the command line, look for a file named ~/.sqliterc and
@@ -22356,14 +22451,20 @@
22356 }
22357 }
22358 free(azCmd);
22359 set_table_name(&data, 0);
22360 if( data.db ){
22361 session_close_all(&data);
22362 close_db(data.db);
22363 }
22364 sqlite3_free(data.zFreeOnClose);
 
 
 
 
 
 
22365 find_home_dir(1);
22366 output_reset(&data);
22367 data.doXdgOpen = 0;
22368 clearTempFile(&data);
22369 #if !SQLITE_SHELL_IS_UTF8
22370
--- src/shell.c
+++ src/shell.c
@@ -33,10 +33,22 @@
33 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
34 /* This needs to come before any includes for MSVC compiler */
35 #define _CRT_SECURE_NO_WARNINGS
36 #endif
37
38 /*
39 ** Optionally #include a user-defined header, whereby compilation options
40 ** may be set prior to where they take effect, but after platform setup.
41 ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
42 ** file. Note that this macro has a like effect on sqlite3.c compilation.
43 */
44 #ifdef SQLITE_CUSTOM_INCLUDE
45 # define INC_STRINGIFY_(f) #f
46 # define INC_STRINGIFY(f) INC_STRINGIFY_(f)
47 # include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
48 #endif
49
50 /*
51 ** Determine if we are dealing with WinRT, which provides only a subset of
52 ** the full Win32 API.
53 */
54 #if !defined(SQLITE_OS_WINRT)
@@ -242,10 +254,11 @@
254 /* Return the current wall-clock time */
255 static sqlite3_int64 timeOfDay(void){
256 static sqlite3_vfs *clockVfs = 0;
257 sqlite3_int64 t;
258 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
259 if( clockVfs==0 ) return 0; /* Never actually happens */
260 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
261 clockVfs->xCurrentTimeInt64(clockVfs, &t);
262 }else{
263 double r;
264 clockVfs->xCurrentTime(clockVfs, &r);
@@ -986,11 +999,11 @@
999 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
1000 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
1001 sqlite3 *db = sqlite3_context_db_handle(pCtx);
1002 UNUSED_PARAMETER(nVal);
1003 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
1004 for(i=0; i<ArraySize(aPrefix); i++){
1005 int n = strlen30(aPrefix[i]);
1006 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
1007 char *z = 0;
1008 char *zFake = 0;
1009 if( zSchema ){
@@ -4281,10 +4294,11 @@
4294 sqlite3_vfs *pOrig;
4295 SQLITE_EXTENSION_INIT2(pApi);
4296 (void)pzErrMsg;
4297 (void)db;
4298 pOrig = sqlite3_vfs_find(0);
4299 if( pOrig==0 ) return SQLITE_ERROR;
4300 apnd_vfs.iVersion = pOrig->iVersion;
4301 apnd_vfs.pAppData = pOrig;
4302 apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
4303 rc = sqlite3_vfs_register(&apnd_vfs, 0);
4304 #ifdef APPENDVFS_TEST
@@ -5757,34 +5771,36 @@
5771 ** (2) stop = $value -- constraint exists
5772 ** (4) step = $value -- constraint exists
5773 ** (8) output in descending order
5774 */
5775 static int seriesBestIndex(
5776 sqlite3_vtab *pVTab,
5777 sqlite3_index_info *pIdxInfo
5778 ){
5779 int i, j; /* Loop over constraints */
5780 int idxNum = 0; /* The query plan bitmask */
5781 int bStartSeen = 0; /* EQ constraint seen on the START column */
5782 int unusableMask = 0; /* Mask of unusable constraints */
5783 int nArg = 0; /* Number of arguments that seriesFilter() expects */
5784 int aIdx[3]; /* Constraints on start, stop, and step */
5785 const struct sqlite3_index_constraint *pConstraint;
5786
5787 /* This implementation assumes that the start, stop, and step columns
5788 ** are the last three columns in the virtual table. */
5789 assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
5790 assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
5791
5792 aIdx[0] = aIdx[1] = aIdx[2] = -1;
5793 pConstraint = pIdxInfo->aConstraint;
5794 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
5795 int iCol; /* 0 for start, 1 for stop, 2 for step */
5796 int iMask; /* bitmask for those column */
5797 if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
5798 iCol = pConstraint->iColumn - SERIES_COLUMN_START;
5799 assert( iCol>=0 && iCol<=2 );
5800 iMask = 1 << iCol;
5801 if( iCol==0 ) bStartSeen = 1;
5802 if( pConstraint->usable==0 ){
5803 unusableMask |= iMask;
5804 continue;
5805 }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
5806 idxNum |= iMask;
@@ -5795,10 +5811,22 @@
5811 if( (j = aIdx[i])>=0 ){
5812 pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
5813 pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
5814 }
5815 }
5816 /* The current generate_column() implementation requires at least one
5817 ** argument (the START value). Legacy versions assumed START=0 if the
5818 ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
5819 ** to obtain the legacy behavior */
5820 #ifndef ZERO_ARGUMENT_GENERATE_SERIES
5821 if( !bStartSeen ){
5822 sqlite3_free(pVTab->zErrMsg);
5823 pVTab->zErrMsg = sqlite3_mprintf(
5824 "first argument to \"generate_series()\" missing or unusable");
5825 return SQLITE_ERROR;
5826 }
5827 #endif
5828 if( (unusableMask & ~idxNum)!=0 ){
5829 /* The start, stop, and step columns are inputs. Therefore if there
5830 ** are unusable constraints on any of start, stop, or step then
5831 ** this plan is unusable */
5832 return SQLITE_CONSTRAINT;
@@ -8143,10 +8171,11 @@
8171 ** time(2)).
8172 */
8173 static u32 zipfileTime(void){
8174 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
8175 u32 ret;
8176 if( pVfs==0 ) return 0;
8177 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
8178 i64 ms;
8179 pVfs->xCurrentTimeInt64(pVfs, &ms);
8180 ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
8181 }else{
@@ -9847,15 +9876,17 @@
9876 int nPk = 0;
9877
9878 rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
9879 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
9880 const char *zCol = (const char*)sqlite3_column_text(p1, 1);
9881 const char *zColSeq = 0;
9882 nByte += 1 + STRLEN(zCol);
9883 rc = sqlite3_table_column_metadata(
9884 db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
9885 );
9886 if( zColSeq==0 ) zColSeq = "binary";
9887 nByte += 1 + STRLEN(zColSeq);
9888 nCol++;
9889 nPk += (sqlite3_column_int(p1, 5)>0);
9890 }
9891 rc2 = sqlite3_reset(p1);
9892 if( rc==SQLITE_OK ) rc = rc2;
@@ -9871,23 +9902,25 @@
9902 }
9903
9904 nCol = 0;
9905 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
9906 const char *zCol = (const char*)sqlite3_column_text(p1, 1);
9907 const char *zColSeq = 0;
9908 int nCopy = STRLEN(zCol) + 1;
9909 pNew->aCol[nCol].zName = pCsr;
9910 pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
9911 memcpy(pCsr, zCol, nCopy);
9912 pCsr += nCopy;
9913
9914 rc = sqlite3_table_column_metadata(
9915 db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
9916 );
9917 if( rc==SQLITE_OK ){
9918 if( zColSeq==0 ) zColSeq = "binary";
9919 nCopy = STRLEN(zColSeq) + 1;
9920 pNew->aCol[nCol].zColl = pCsr;
9921 memcpy(pCsr, zColSeq, nCopy);
9922 pCsr += nCopy;
9923 }
9924
9925 nCol++;
9926 }
@@ -12065,23 +12098,26 @@
12098 int *actualWidth; /* Actual width of each column */
12099 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
12100 char nullValue[20]; /* The text to print when a NULL comes back from
12101 ** the database */
12102 char outfile[FILENAME_MAX]; /* Filename for *out */
 
 
 
12103 sqlite3_stmt *pStmt; /* Current statement if any. */
12104 FILE *pLog; /* Write log output here */
12105 struct AuxDb { /* Storage space for auxiliary database connections */
12106 sqlite3 *db; /* Connection pointer */
12107 const char *zDbFilename; /* Filename used to open the connection */
12108 char *zFreeOnClose; /* Free this memory allocation on close */
12109 #if defined(SQLITE_ENABLE_SESSION)
12110 int nSession; /* Number of active sessions */
12111 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
12112 #endif
12113 } aAuxDb[5], /* Array of all database connections */
12114 *pAuxDb; /* Currently active database connection */
12115 int *aiIndent; /* Array of indents used in MODE_Explain */
12116 int nIndent; /* Size of array aiIndent[] */
12117 int iIndent; /* Index of current op in aiIndent[] */
12118 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
 
 
 
 
12119 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
12120 };
12121
12122
12123 /* Allowed values for ShellState.autoEQP
@@ -14829,10 +14865,11 @@
14865 ".binary on|off Turn binary output on or off. Default OFF",
14866 ".cd DIRECTORY Change the working directory to DIRECTORY",
14867 ".changes on|off Show number of rows changed by SQL",
14868 ".check GLOB Fail if output since .testcase does not match",
14869 ".clone NEWDB Clone data into NEWDB from the existing database",
14870 ".connection [close] [#] Open or close an auxiliary database connection",
14871 ".databases List names and files of attached databases",
14872 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
14873 ".dbinfo ?DB? Show status information about the database",
14874 ".dump ?OBJECTS? Render database content as SQL",
14875 " Options:",
@@ -15169,19 +15206,20 @@
15206
15207 /*
15208 ** Close all OpenSession objects and release all associated resources.
15209 */
15210 #if defined(SQLITE_ENABLE_SESSION)
15211 static void session_close_all(ShellState *p, int i){
15212 int j;
15213 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
15214 for(j=0; j<pAuxDb->nSession; j++){
15215 session_close(&pAuxDb->aSession[j]);
15216 }
15217 pAuxDb->nSession = 0;
15218 }
15219 #else
15220 # define session_close_all(X,Y)
15221 #endif
15222
15223 /*
15224 ** Implementation of the xFilter function for an open session. Omit
15225 ** any tables named by ".session filter" but let all other table through.
@@ -15242,12 +15280,12 @@
15280 }
15281
15282 #ifndef SQLITE_OMIT_DESERIALIZE
15283 /*
15284 ** Reconstruct an in-memory database using the output from the "dbtotxt"
15285 ** program. Read content from the file in p->aAuxDb[].zDbFilename.
15286 ** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
15287 */
15288 static unsigned char *readHexDb(ShellState *p, int *pnData){
15289 unsigned char *a = 0;
15290 int nLine;
15291 int n = 0;
@@ -15254,16 +15292,17 @@
15292 int pgsz = 0;
15293 int iOffset = 0;
15294 int j, k;
15295 int rc;
15296 FILE *in;
15297 const char *zDbFilename = p->pAuxDb->zDbFilename;
15298 unsigned int x[16];
15299 char zLine[1000];
15300 if( zDbFilename ){
15301 in = fopen(zDbFilename, "r");
15302 if( in==0 ){
15303 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
15304 return 0;
15305 }
15306 nLine = 0;
15307 }else{
15308 in = p->in;
@@ -15501,21 +15540,22 @@
15540 ** Make sure the database is open. If it is not, then open it. If
15541 ** the database fails to open, print an error message and exit.
15542 */
15543 static void open_db(ShellState *p, int openFlags){
15544 if( p->db==0 ){
15545 const char *zDbFilename = p->pAuxDb->zDbFilename;
15546 if( p->openMode==SHELL_OPEN_UNSPEC ){
15547 if( zDbFilename==0 || zDbFilename[0]==0 ){
15548 p->openMode = SHELL_OPEN_NORMAL;
15549 }else{
15550 p->openMode = (u8)deduceDatabaseType(zDbFilename,
15551 (openFlags & OPEN_DB_ZIPFILE)!=0);
15552 }
15553 }
15554 switch( p->openMode ){
15555 case SHELL_OPEN_APPENDVFS: {
15556 sqlite3_open_v2(zDbFilename, &p->db,
15557 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
15558 break;
15559 }
15560 case SHELL_OPEN_HEXDB:
15561 case SHELL_OPEN_DESERIALIZE: {
@@ -15525,25 +15565,25 @@
15565 case SHELL_OPEN_ZIPFILE: {
15566 sqlite3_open(":memory:", &p->db);
15567 break;
15568 }
15569 case SHELL_OPEN_READONLY: {
15570 sqlite3_open_v2(zDbFilename, &p->db,
15571 SQLITE_OPEN_READONLY|p->openFlags, 0);
15572 break;
15573 }
15574 case SHELL_OPEN_UNSPEC:
15575 case SHELL_OPEN_NORMAL: {
15576 sqlite3_open_v2(zDbFilename, &p->db,
15577 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
15578 break;
15579 }
15580 }
15581 globalDb = p->db;
15582 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
15583 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
15584 zDbFilename, sqlite3_errmsg(p->db));
15585 if( openFlags & OPEN_DB_KEEPALIVE ){
15586 sqlite3_open(":memory:", &p->db);
15587 return;
15588 }
15589 exit(1);
@@ -15586,11 +15626,11 @@
15626 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
15627 editFunc, 0, 0);
15628 #endif
15629 if( p->openMode==SHELL_OPEN_ZIPFILE ){
15630 char *zSql = sqlite3_mprintf(
15631 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
15632 sqlite3_exec(p->db, zSql, 0, 0, 0);
15633 sqlite3_free(zSql);
15634 }
15635 #ifndef SQLITE_OMIT_DESERIALIZE
15636 else
@@ -15597,11 +15637,11 @@
15637 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
15638 int rc;
15639 int nData = 0;
15640 unsigned char *aData;
15641 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
15642 aData = (unsigned char*)readFile(zDbFilename, &nData);
15643 }else{
15644 aData = readHexDb(p, &nData);
15645 if( aData==0 ){
15646 return;
15647 }
@@ -18318,11 +18358,10 @@
18358 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
18359 return rc;
18360 }
18361 #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
18362
 
18363 /*
18364 ** If an input line begins with "." then invoke this routine to
18365 ** process that line.
18366 **
18367 ** Return 1 on error, 2 to exit, and 0 otherwise.
@@ -18482,10 +18521,17 @@
18521 }else{
18522 raw_printf(stderr, "Usage: .binary on|off\n");
18523 rc = 1;
18524 }
18525 }else
18526
18527 /* The undocumented ".breakpoint" command causes a call to the no-op
18528 ** routine named test_breakpoint().
18529 */
18530 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
18531 test_breakpoint();
18532 }else
18533
18534 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
18535 if( nArg==2 ){
18536 #if defined(_WIN32) || defined(WIN32)
18537 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
@@ -18502,17 +18548,10 @@
18548 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
18549 rc = 1;
18550 }
18551 }else
18552
 
 
 
 
 
 
 
18553 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
18554 if( nArg==2 ){
18555 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
18556 }else{
18557 raw_printf(stderr, "Usage: .changes on|off\n");
@@ -18551,10 +18590,56 @@
18590 }else{
18591 raw_printf(stderr, "Usage: .clone FILENAME\n");
18592 rc = 1;
18593 }
18594 }else
18595
18596 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
18597 if( nArg==1 ){
18598 /* List available connections */
18599 int i;
18600 for(i=0; i<ArraySize(p->aAuxDb); i++){
18601 const char *zFile = p->aAuxDb[i].zDbFilename;
18602 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
18603 zFile = "(not open)";
18604 }else if( zFile==0 ){
18605 zFile = "(memory)";
18606 }else if( zFile[0]==0 ){
18607 zFile = "(temporary-file)";
18608 }
18609 if( p->pAuxDb == &p->aAuxDb[i] ){
18610 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
18611 }else if( p->aAuxDb[i].db!=0 ){
18612 utf8_printf(stdout, " %d: %s\n", i, zFile);
18613 }
18614 }
18615 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
18616 int i = azArg[1][0] - '0';
18617 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
18618 p->pAuxDb->db = p->db;
18619 p->pAuxDb = &p->aAuxDb[i];
18620 globalDb = p->db = p->pAuxDb->db;
18621 p->pAuxDb->db = 0;
18622 }
18623 }else if( nArg==3 && strcmp(azArg[1], "close")==0
18624 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
18625 int i = azArg[2][0] - '0';
18626 if( i<0 || i>=ArraySize(p->aAuxDb) ){
18627 /* No-op */
18628 }else if( p->pAuxDb == &p->aAuxDb[i] ){
18629 raw_printf(stderr, "cannot close the active database connection\n");
18630 rc = 1;
18631 }else if( p->aAuxDb[i].db ){
18632 session_close_all(p, i);
18633 close_db(p->aAuxDb[i].db);
18634 p->aAuxDb[i].db = 0;
18635 }
18636 }else{
18637 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
18638 rc = 1;
18639 }
18640 }else
18641
18642 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
18643 char **azName = 0;
18644 int nName = 0;
18645 sqlite3_stmt *pStmt;
@@ -18997,11 +19082,11 @@
19082 "SELECT sql FROM"
19083 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
19084 " FROM sqlite_schema UNION ALL"
19085 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
19086 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
19087 "ORDER BY x",
19088 callback, &data, 0
19089 );
19090 if( rc==SQLITE_OK ){
19091 sqlite3_stmt *pStmt;
19092 rc = sqlite3_prepare_v2(p->db,
@@ -19013,12 +19098,10 @@
19098 }
19099 if( doStats==0 ){
19100 raw_printf(p->out, "/* No STAT tables available */\n");
19101 }else{
19102 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
 
 
19103 data.cMode = data.mode = MODE_Insert;
19104 data.zDestTable = "sqlite_stat1";
19105 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
19106 data.zDestTable = "sqlite_stat4";
19107 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
@@ -19643,16 +19726,16 @@
19726 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
19727 char *zNewFilename = 0; /* Name of the database file to open */
19728 int iName = 1; /* Index in azArg[] of the filename */
19729 int newFlag = 0; /* True to delete file before opening */
19730 /* Close the existing database */
19731 session_close_all(p, -1);
19732 close_db(p->db);
19733 p->db = 0;
19734 p->pAuxDb->zDbFilename = 0;
19735 sqlite3_free(p->pAuxDb->zFreeOnClose);
19736 p->pAuxDb->zFreeOnClose = 0;
19737 p->openMode = SHELL_OPEN_UNSPEC;
19738 p->openFlags = 0;
19739 p->szMax = 0;
19740 /* Check for command-line arguments */
19741 for(iName=1; iName<nArg; iName++){
@@ -19667,10 +19750,12 @@
19750 p->openMode = SHELL_OPEN_APPENDVFS;
19751 }else if( optionMatch(z, "readonly") ){
19752 p->openMode = SHELL_OPEN_READONLY;
19753 }else if( optionMatch(z, "nofollow") ){
19754 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
19755 }else if( optionMatch(z, "excl") ){
19756 p->openFlags |= SQLITE_OPEN_EXCLUSIVE;
19757 #ifndef SQLITE_OMIT_DESERIALIZE
19758 }else if( optionMatch(z, "deserialize") ){
19759 p->openMode = SHELL_OPEN_DESERIALIZE;
19760 }else if( optionMatch(z, "hexdb") ){
19761 p->openMode = SHELL_OPEN_HEXDB;
@@ -19690,22 +19775,22 @@
19775 }
19776 }
19777 /* If a filename is specified, try to open it first */
19778 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
19779 if( newFlag ) shellDeleteFile(zNewFilename);
19780 p->pAuxDb->zDbFilename = zNewFilename;
19781 open_db(p, OPEN_DB_KEEPALIVE);
19782 if( p->db==0 ){
19783 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
19784 sqlite3_free(zNewFilename);
19785 }else{
19786 p->pAuxDb->zFreeOnClose = zNewFilename;
19787 }
19788 }
19789 if( p->db==0 ){
19790 /* As a fall-back open a TEMP database */
19791 p->pAuxDb->zDbFilename = 0;
19792 open_db(p, 0);
19793 }
19794 }else
19795
19796 if( (c=='o'
@@ -20230,27 +20315,28 @@
20315 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
20316 }else
20317
20318 #if defined(SQLITE_ENABLE_SESSION)
20319 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
20320 struct AuxDb *pAuxDb = p->pAuxDb;
20321 OpenSession *pSession = &pAuxDb->aSession[0];
20322 char **azCmd = &azArg[1];
20323 int iSes = 0;
20324 int nCmd = nArg - 1;
20325 int i;
20326 if( nArg<=1 ) goto session_syntax_error;
20327 open_db(p, 0);
20328 if( nArg>=3 ){
20329 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
20330 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
20331 }
20332 if( iSes<pAuxDb->nSession ){
20333 pSession = &pAuxDb->aSession[iSes];
20334 azCmd++;
20335 nCmd--;
20336 }else{
20337 pSession = &pAuxDb->aSession[0];
20338 iSes = 0;
20339 }
20340 }
20341
20342 /* .session attach TABLE
@@ -20308,13 +20394,13 @@
20394 /* .session close
20395 ** Close the identified session
20396 */
20397 if( strcmp(azCmd[0], "close")==0 ){
20398 if( nCmd!=1 ) goto session_syntax_error;
20399 if( pAuxDb->nSession ){
20400 session_close(pSession);
20401 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
20402 }
20403 }else
20404
20405 /* .session enable ?BOOLEAN?
20406 ** Query or set the enable flag
@@ -20321,11 +20407,11 @@
20407 */
20408 if( strcmp(azCmd[0], "enable")==0 ){
20409 int ii;
20410 if( nCmd>2 ) goto session_syntax_error;
20411 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
20412 if( pAuxDb->nSession ){
20413 ii = sqlite3session_enable(pSession->p, ii);
20414 utf8_printf(p->out, "session %s enable flag = %d\n",
20415 pSession->zName, ii);
20416 }
20417 }else
@@ -20334,11 +20420,11 @@
20420 ** Set a list of GLOB patterns of table names to be excluded.
20421 */
20422 if( strcmp(azCmd[0], "filter")==0 ){
20423 int ii, nByte;
20424 if( nCmd<2 ) goto session_syntax_error;
20425 if( pAuxDb->nSession ){
20426 for(ii=0; ii<pSession->nFilter; ii++){
20427 sqlite3_free(pSession->azFilter[ii]);
20428 }
20429 sqlite3_free(pSession->azFilter);
20430 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
@@ -20359,11 +20445,11 @@
20445 */
20446 if( strcmp(azCmd[0], "indirect")==0 ){
20447 int ii;
20448 if( nCmd>2 ) goto session_syntax_error;
20449 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
20450 if( pAuxDb->nSession ){
20451 ii = sqlite3session_indirect(pSession->p, ii);
20452 utf8_printf(p->out, "session %s indirect flag = %d\n",
20453 pSession->zName, ii);
20454 }
20455 }else
@@ -20372,11 +20458,11 @@
20458 ** Determine if the session is empty
20459 */
20460 if( strcmp(azCmd[0], "isempty")==0 ){
20461 int ii;
20462 if( nCmd!=1 ) goto session_syntax_error;
20463 if( pAuxDb->nSession ){
20464 ii = sqlite3session_isempty(pSession->p);
20465 utf8_printf(p->out, "session %s isempty flag = %d\n",
20466 pSession->zName, ii);
20467 }
20468 }else
@@ -20383,12 +20469,12 @@
20469
20470 /* .session list
20471 ** List all currently open sessions
20472 */
20473 if( strcmp(azCmd[0],"list")==0 ){
20474 for(i=0; i<pAuxDb->nSession; i++){
20475 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
20476 }
20477 }else
20478
20479 /* .session open DB NAME
20480 ** Open a new session called NAME on the attached database DB.
@@ -20397,30 +20483,30 @@
20483 if( strcmp(azCmd[0],"open")==0 ){
20484 char *zName;
20485 if( nCmd!=3 ) goto session_syntax_error;
20486 zName = azCmd[2];
20487 if( zName[0]==0 ) goto session_syntax_error;
20488 for(i=0; i<pAuxDb->nSession; i++){
20489 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
20490 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
20491 goto meta_command_exit;
20492 }
20493 }
20494 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
20495 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
20496 goto meta_command_exit;
20497 }
20498 pSession = &pAuxDb->aSession[pAuxDb->nSession];
20499 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
20500 if( rc ){
20501 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
20502 rc = 0;
20503 goto meta_command_exit;
20504 }
20505 pSession->nFilter = 0;
20506 sqlite3session_table_filter(pSession->p, session_filter, pSession);
20507 pAuxDb->nSession++;
20508 pSession->zName = sqlite3_mprintf("%s", zName);
20509 }else
20510 /* If no command name matches, show a syntax error */
20511 session_syntax_error:
20512 showHelp(p->out, "session");
@@ -20745,11 +20831,11 @@
20831 for (i=0;i<p->nWidth;i++) {
20832 raw_printf(p->out, "%d ", p->colWidth[i]);
20833 }
20834 raw_printf(p->out, "\n");
20835 utf8_printf(p->out, "%12.12s: %s\n", "filename",
20836 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
20837 }else
20838
20839 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
20840 if( nArg==2 ){
20841 if( strcmp(azArg[1],"stmt")==0 ){
@@ -20912,10 +20998,11 @@
20998 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
20999 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
21000 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
21001 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
21002 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
21003 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" },
21004 { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
21005 };
21006 int testctrl = -1;
21007 int iCtrl = -1;
21008 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
@@ -21092,10 +21179,17 @@
21179 isOk = 3;
21180 }
21181 break;
21182 }
21183 #endif
21184 case SQLITE_TESTCTRL_SORTER_MMAP:
21185 if( nArg==3 ){
21186 int opt = (unsigned int)integerValue(azArg[2]);
21187 rc2 = sqlite3_test_control(testctrl, p->db, opt);
21188 isOk = 3;
21189 }
21190 break;
21191 }
21192 }
21193 if( isOk==0 && iCtrl>=0 ){
21194 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
21195 rc = 1;
@@ -21460,12 +21554,12 @@
21554 }else{
21555 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
21556 }
21557 return 1;
21558 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
21559 raw_printf(p->out, "changes: %3lld total_changes: %lld\n",
21560 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
21561 }
21562 return 0;
21563 }
21564
21565
@@ -21766,10 +21860,11 @@
21860 */
21861 static void main_init(ShellState *data) {
21862 memset(data, 0, sizeof(*data));
21863 data->normalMode = data->cMode = data->mode = MODE_List;
21864 data->autoExplain = 1;
21865 data->pAuxDb = &data->aAuxDb[0];
21866 memcpy(data->colSeparator,SEP_Column, 2);
21867 memcpy(data->rowSeparator,SEP_Row, 2);
21868 data->showHeader = 0;
21869 data->shellFlgs = SHFLG_Lookaside;
21870 verify_uninitialized();
@@ -21929,11 +22024,11 @@
22024 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
22025 ** of a C-function that will provide the name of the database file. Use
22026 ** this compile-time option to embed this shell program in larger
22027 ** applications. */
22028 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
22029 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
22030 warnInmemoryDb = 0;
22031 }
22032 #endif
22033
22034 /* Do an initial pass through the command-line argument to locate
@@ -21944,12 +22039,12 @@
22039 verify_uninitialized();
22040 for(i=1; i<argc; i++){
22041 char *z;
22042 z = argv[i];
22043 if( z[0]!='-' ){
22044 if( data.aAuxDb->zDbFilename==0 ){
22045 data.aAuxDb->zDbFilename = z;
22046 }else{
22047 /* Excesss arguments are interpreted as SQL (or dot-commands) and
22048 ** mean that nothing is read from stdin */
22049 readStdin = 0;
22050 nCmd++;
@@ -22085,13 +22180,13 @@
22180 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
22181 exit(1);
22182 }
22183 }
22184
22185 if( data.pAuxDb->zDbFilename==0 ){
22186 #ifndef SQLITE_OMIT_MEMORYDB
22187 data.pAuxDb->zDbFilename = ":memory:";
22188 warnInmemoryDb = argc==1;
22189 #else
22190 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
22191 return 1;
22192 #endif
@@ -22102,11 +22197,11 @@
22197 /* Go ahead and open the database file if it already exists. If the
22198 ** file does not exist, delay opening it. This prevents empty database
22199 ** files from being created if a user mistypes the database name argument
22200 ** to the sqlite command-line tool.
22201 */
22202 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
22203 open_db(&data, 0);
22204 }
22205
22206 /* Process the initialization file if there is one. If no -init option
22207 ** is given on the command line, look for a file named ~/.sqliterc and
@@ -22356,14 +22451,20 @@
22451 }
22452 }
22453 free(azCmd);
22454 set_table_name(&data, 0);
22455 if( data.db ){
22456 session_close_all(&data, -1);
22457 close_db(data.db);
22458 }
22459 for(i=0; i<ArraySize(data.aAuxDb); i++){
22460 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
22461 if( data.aAuxDb[i].db ){
22462 session_close_all(&data, i);
22463 close_db(data.aAuxDb[i].db);
22464 }
22465 }
22466 find_home_dir(1);
22467 output_reset(&data);
22468 data.doXdgOpen = 0;
22469 clearTempFile(&data);
22470 #if !SQLITE_SHELL_IS_UTF8
22471
+3 -5
--- src/skins.c
+++ src/skins.c
@@ -789,11 +789,10 @@
789789
const char *zBasis; /* The baseline file */
790790
const char *zOrig; /* Original content prior to editing */
791791
const char *zContent; /* Content after editing */
792792
const char *zDflt; /* Default content */
793793
char *zDraft; /* Which draft: "draft%d" */
794
- char *zKey; /* CONFIG table key name: "draft%d-%s" */
795794
char *zTitle; /* Title of this page */
796795
const char *zFile; /* One of "css", "footer", "header", "details" */
797796
int iSkin; /* draft number. 1..9 */
798797
int ii; /* Index in aSkinAttr[] of this file */
799798
int j; /* Loop counter */
@@ -827,15 +826,14 @@
827826
/* figure out which file is to be edited */
828827
ii = atoi(PD("w","0"));
829828
if( ii<0 || ii>count(aSkinAttr) ) ii = 0;
830829
zFile = aSkinAttr[ii].zFile;
831830
zDraft = mprintf("draft%d", iSkin);
832
- zKey = mprintf("draft%d-%s", iSkin, zFile);
833831
zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin);
834832
zBasis = PD("basis","current");
835833
zDflt = skin_file_content(zBasis, zFile);
836
- zOrig = db_get(zKey, zDflt);
834
+ zOrig = db_get_mprintf(zDflt, "draft%d-%s",iSkin,zFile);
837835
zContent = PD(zFile,zOrig);
838836
if( P("revert")!=0 && cgi_csrf_safe(0) ){
839837
zContent = zDflt;
840838
isRevert = 1;
841839
}
@@ -851,11 +849,11 @@
851849
login_insert_csrf_secret();
852850
@ <input type='hidden' name='w' value='%d(ii)'>
853851
@ <input type='hidden' name='sk' value='%d(iSkin)'>
854852
@ <h2>Edit %s(zTitle):</h2>
855853
if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){
856
- db_set(zKey, zContent, 0);
854
+ db_set_mprintf(zContent, 0, "draft%d-%s",iSkin,zFile);
857855
}
858856
@ <textarea name="%s(zFile)" rows="10" cols="80">\
859857
@ %h(zContent)</textarea>
860858
@ <br />
861859
@ <input type="submit" name="submit" value="Apply Changes" />
@@ -942,11 +940,11 @@
942940
}
943941
944942
/* Publish draft iSkin */
945943
for(i=0; i<count(azSkinFile); i++){
946944
char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]);
947
- db_set(azSkinFile[i], zNew, 0);
945
+ db_set(azSkinFile[i]/*works-like:"x"*/, zNew, 0);
948946
}
949947
}
950948
951949
/*
952950
** WEBPAGE: setup_skin
953951
--- src/skins.c
+++ src/skins.c
@@ -789,11 +789,10 @@
789 const char *zBasis; /* The baseline file */
790 const char *zOrig; /* Original content prior to editing */
791 const char *zContent; /* Content after editing */
792 const char *zDflt; /* Default content */
793 char *zDraft; /* Which draft: "draft%d" */
794 char *zKey; /* CONFIG table key name: "draft%d-%s" */
795 char *zTitle; /* Title of this page */
796 const char *zFile; /* One of "css", "footer", "header", "details" */
797 int iSkin; /* draft number. 1..9 */
798 int ii; /* Index in aSkinAttr[] of this file */
799 int j; /* Loop counter */
@@ -827,15 +826,14 @@
827 /* figure out which file is to be edited */
828 ii = atoi(PD("w","0"));
829 if( ii<0 || ii>count(aSkinAttr) ) ii = 0;
830 zFile = aSkinAttr[ii].zFile;
831 zDraft = mprintf("draft%d", iSkin);
832 zKey = mprintf("draft%d-%s", iSkin, zFile);
833 zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin);
834 zBasis = PD("basis","current");
835 zDflt = skin_file_content(zBasis, zFile);
836 zOrig = db_get(zKey, zDflt);
837 zContent = PD(zFile,zOrig);
838 if( P("revert")!=0 && cgi_csrf_safe(0) ){
839 zContent = zDflt;
840 isRevert = 1;
841 }
@@ -851,11 +849,11 @@
851 login_insert_csrf_secret();
852 @ <input type='hidden' name='w' value='%d(ii)'>
853 @ <input type='hidden' name='sk' value='%d(iSkin)'>
854 @ <h2>Edit %s(zTitle):</h2>
855 if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){
856 db_set(zKey, zContent, 0);
857 }
858 @ <textarea name="%s(zFile)" rows="10" cols="80">\
859 @ %h(zContent)</textarea>
860 @ <br />
861 @ <input type="submit" name="submit" value="Apply Changes" />
@@ -942,11 +940,11 @@
942 }
943
944 /* Publish draft iSkin */
945 for(i=0; i<count(azSkinFile); i++){
946 char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]);
947 db_set(azSkinFile[i], zNew, 0);
948 }
949 }
950
951 /*
952 ** WEBPAGE: setup_skin
953
--- src/skins.c
+++ src/skins.c
@@ -789,11 +789,10 @@
789 const char *zBasis; /* The baseline file */
790 const char *zOrig; /* Original content prior to editing */
791 const char *zContent; /* Content after editing */
792 const char *zDflt; /* Default content */
793 char *zDraft; /* Which draft: "draft%d" */
 
794 char *zTitle; /* Title of this page */
795 const char *zFile; /* One of "css", "footer", "header", "details" */
796 int iSkin; /* draft number. 1..9 */
797 int ii; /* Index in aSkinAttr[] of this file */
798 int j; /* Loop counter */
@@ -827,15 +826,14 @@
826 /* figure out which file is to be edited */
827 ii = atoi(PD("w","0"));
828 if( ii<0 || ii>count(aSkinAttr) ) ii = 0;
829 zFile = aSkinAttr[ii].zFile;
830 zDraft = mprintf("draft%d", iSkin);
 
831 zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin);
832 zBasis = PD("basis","current");
833 zDflt = skin_file_content(zBasis, zFile);
834 zOrig = db_get_mprintf(zDflt, "draft%d-%s",iSkin,zFile);
835 zContent = PD(zFile,zOrig);
836 if( P("revert")!=0 && cgi_csrf_safe(0) ){
837 zContent = zDflt;
838 isRevert = 1;
839 }
@@ -851,11 +849,11 @@
849 login_insert_csrf_secret();
850 @ <input type='hidden' name='w' value='%d(ii)'>
851 @ <input type='hidden' name='sk' value='%d(iSkin)'>
852 @ <h2>Edit %s(zTitle):</h2>
853 if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){
854 db_set_mprintf(zContent, 0, "draft%d-%s",iSkin,zFile);
855 }
856 @ <textarea name="%s(zFile)" rows="10" cols="80">\
857 @ %h(zContent)</textarea>
858 @ <br />
859 @ <input type="submit" name="submit" value="Apply Changes" />
@@ -942,11 +940,11 @@
940 }
941
942 /* Publish draft iSkin */
943 for(i=0; i<count(azSkinFile); i++){
944 char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]);
945 db_set(azSkinFile[i]/*works-like:"x"*/, zNew, 0);
946 }
947 }
948
949 /*
950 ** WEBPAGE: setup_skin
951
+2538 -2253
--- 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.36.0. By combining all the individual C code files into this
3
+** version 3.37.0. 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.
@@ -20,797 +20,10 @@
2020
#define SQLITE_CORE 1
2121
#define SQLITE_AMALGAMATION 1
2222
#ifndef SQLITE_PRIVATE
2323
# define SQLITE_PRIVATE static
2424
#endif
25
-/************** Begin file ctime.c *******************************************/
26
-/*
27
-** 2010 February 23
28
-**
29
-** The author disclaims copyright to this source code. In place of
30
-** a legal notice, here is a blessing:
31
-**
32
-** May you do good and not evil.
33
-** May you find forgiveness for yourself and forgive others.
34
-** May you share freely, never taking more than you give.
35
-**
36
-*************************************************************************
37
-**
38
-** This file implements routines used to report what compile-time options
39
-** SQLite was built with.
40
-*/
41
-
42
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
43
-
44
-/*
45
-** Include the configuration header output by 'configure' if we're using the
46
-** autoconf-based build
47
-*/
48
-#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
49
-#include "config.h"
50
-#define SQLITECONFIG_H 1
51
-#endif
52
-
53
-/* These macros are provided to "stringify" the value of the define
54
-** for those options in which the value is meaningful. */
55
-#define CTIMEOPT_VAL_(opt) #opt
56
-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
57
-
58
-/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
59
-** option requires a separate macro because legal values contain a single
60
-** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
61
-#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
62
-#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
63
-
64
-/*
65
-** An array of names of all compile-time options. This array should
66
-** be sorted A-Z.
67
-**
68
-** This array looks large, but in a typical installation actually uses
69
-** only a handful of compile-time options, so most times this array is usually
70
-** rather short and uses little memory space.
71
-*/
72
-static const char * const sqlite3azCompileOpt[] = {
73
-
74
-/*
75
-** BEGIN CODE GENERATED BY tool/mkctime.tcl
76
-*/
77
-#if SQLITE_32BIT_ROWID
78
- "32BIT_ROWID",
79
-#endif
80
-#if SQLITE_4_BYTE_ALIGNED_MALLOC
81
- "4_BYTE_ALIGNED_MALLOC",
82
-#endif
83
-#if SQLITE_64BIT_STATS
84
- "64BIT_STATS",
85
-#endif
86
-#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
87
-# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
88
- "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
89
-# endif
90
-#endif
91
-#if SQLITE_ALLOW_URI_AUTHORITY
92
- "ALLOW_URI_AUTHORITY",
93
-#endif
94
-#ifdef SQLITE_BITMASK_TYPE
95
- "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
96
-#endif
97
-#if SQLITE_BUG_COMPATIBLE_20160819
98
- "BUG_COMPATIBLE_20160819",
99
-#endif
100
-#if SQLITE_CASE_SENSITIVE_LIKE
101
- "CASE_SENSITIVE_LIKE",
102
-#endif
103
-#if SQLITE_CHECK_PAGES
104
- "CHECK_PAGES",
105
-#endif
106
-#if defined(__clang__) && defined(__clang_major__)
107
- "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
108
- CTIMEOPT_VAL(__clang_minor__) "."
109
- CTIMEOPT_VAL(__clang_patchlevel__),
110
-#elif defined(_MSC_VER)
111
- "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
112
-#elif defined(__GNUC__) && defined(__VERSION__)
113
- "COMPILER=gcc-" __VERSION__,
114
-#endif
115
-#if SQLITE_COVERAGE_TEST
116
- "COVERAGE_TEST",
117
-#endif
118
-#if SQLITE_DEBUG
119
- "DEBUG",
120
-#endif
121
-#if SQLITE_DEFAULT_AUTOMATIC_INDEX
122
- "DEFAULT_AUTOMATIC_INDEX",
123
-#endif
124
-#if SQLITE_DEFAULT_AUTOVACUUM
125
- "DEFAULT_AUTOVACUUM",
126
-#endif
127
-#ifdef SQLITE_DEFAULT_CACHE_SIZE
128
- "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
129
-#endif
130
-#if SQLITE_DEFAULT_CKPTFULLFSYNC
131
- "DEFAULT_CKPTFULLFSYNC",
132
-#endif
133
-#ifdef SQLITE_DEFAULT_FILE_FORMAT
134
- "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
135
-#endif
136
-#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
137
- "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
138
-#endif
139
-#if SQLITE_DEFAULT_FOREIGN_KEYS
140
- "DEFAULT_FOREIGN_KEYS",
141
-#endif
142
-#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
143
- "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
144
-#endif
145
-#ifdef SQLITE_DEFAULT_LOCKING_MODE
146
- "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
147
-#endif
148
-#ifdef SQLITE_DEFAULT_LOOKASIDE
149
- "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
150
-#endif
151
-#ifdef SQLITE_DEFAULT_MEMSTATUS
152
-# if SQLITE_DEFAULT_MEMSTATUS != 1
153
- "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
154
-# endif
155
-#endif
156
-#ifdef SQLITE_DEFAULT_MMAP_SIZE
157
- "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
158
-#endif
159
-#ifdef SQLITE_DEFAULT_PAGE_SIZE
160
- "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
161
-#endif
162
-#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
163
- "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
164
-#endif
165
-#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
166
- "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
167
-#endif
168
-#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
169
- "DEFAULT_RECURSIVE_TRIGGERS",
170
-#endif
171
-#ifdef SQLITE_DEFAULT_ROWEST
172
- "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
173
-#endif
174
-#ifdef SQLITE_DEFAULT_SECTOR_SIZE
175
- "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
176
-#endif
177
-#ifdef SQLITE_DEFAULT_SYNCHRONOUS
178
- "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
179
-#endif
180
-#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
181
- "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
182
-#endif
183
-#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
184
- "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
185
-#endif
186
-#ifdef SQLITE_DEFAULT_WORKER_THREADS
187
- "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
188
-#endif
189
-#if SQLITE_DIRECT_OVERFLOW_READ
190
- "DIRECT_OVERFLOW_READ",
191
-#endif
192
-#if SQLITE_DISABLE_DIRSYNC
193
- "DISABLE_DIRSYNC",
194
-#endif
195
-#if SQLITE_DISABLE_FTS3_UNICODE
196
- "DISABLE_FTS3_UNICODE",
197
-#endif
198
-#if SQLITE_DISABLE_FTS4_DEFERRED
199
- "DISABLE_FTS4_DEFERRED",
200
-#endif
201
-#if SQLITE_DISABLE_INTRINSIC
202
- "DISABLE_INTRINSIC",
203
-#endif
204
-#if SQLITE_DISABLE_LFS
205
- "DISABLE_LFS",
206
-#endif
207
-#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
208
- "DISABLE_PAGECACHE_OVERFLOW_STATS",
209
-#endif
210
-#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
211
- "DISABLE_SKIPAHEAD_DISTINCT",
212
-#endif
213
-#ifdef SQLITE_ENABLE_8_3_NAMES
214
- "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
215
-#endif
216
-#if SQLITE_ENABLE_API_ARMOR
217
- "ENABLE_API_ARMOR",
218
-#endif
219
-#if SQLITE_ENABLE_ATOMIC_WRITE
220
- "ENABLE_ATOMIC_WRITE",
221
-#endif
222
-#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
223
- "ENABLE_BATCH_ATOMIC_WRITE",
224
-#endif
225
-#if SQLITE_ENABLE_BYTECODE_VTAB
226
- "ENABLE_BYTECODE_VTAB",
227
-#endif
228
-#ifdef SQLITE_ENABLE_CEROD
229
- "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
230
-#endif
231
-#if SQLITE_ENABLE_COLUMN_METADATA
232
- "ENABLE_COLUMN_METADATA",
233
-#endif
234
-#if SQLITE_ENABLE_COLUMN_USED_MASK
235
- "ENABLE_COLUMN_USED_MASK",
236
-#endif
237
-#if SQLITE_ENABLE_COSTMULT
238
- "ENABLE_COSTMULT",
239
-#endif
240
-#if SQLITE_ENABLE_CURSOR_HINTS
241
- "ENABLE_CURSOR_HINTS",
242
-#endif
243
-#if SQLITE_ENABLE_DBPAGE_VTAB
244
- "ENABLE_DBPAGE_VTAB",
245
-#endif
246
-#if SQLITE_ENABLE_DBSTAT_VTAB
247
- "ENABLE_DBSTAT_VTAB",
248
-#endif
249
-#if SQLITE_ENABLE_EXPENSIVE_ASSERT
250
- "ENABLE_EXPENSIVE_ASSERT",
251
-#endif
252
-#if SQLITE_ENABLE_EXPLAIN_COMMENTS
253
- "ENABLE_EXPLAIN_COMMENTS",
254
-#endif
255
-#if SQLITE_ENABLE_FTS3
256
- "ENABLE_FTS3",
257
-#endif
258
-#if SQLITE_ENABLE_FTS3_PARENTHESIS
259
- "ENABLE_FTS3_PARENTHESIS",
260
-#endif
261
-#if SQLITE_ENABLE_FTS3_TOKENIZER
262
- "ENABLE_FTS3_TOKENIZER",
263
-#endif
264
-#if SQLITE_ENABLE_FTS4
265
- "ENABLE_FTS4",
266
-#endif
267
-#if SQLITE_ENABLE_FTS5
268
- "ENABLE_FTS5",
269
-#endif
270
-#if SQLITE_ENABLE_GEOPOLY
271
- "ENABLE_GEOPOLY",
272
-#endif
273
-#if SQLITE_ENABLE_HIDDEN_COLUMNS
274
- "ENABLE_HIDDEN_COLUMNS",
275
-#endif
276
-#if SQLITE_ENABLE_ICU
277
- "ENABLE_ICU",
278
-#endif
279
-#if SQLITE_ENABLE_IOTRACE
280
- "ENABLE_IOTRACE",
281
-#endif
282
-#if SQLITE_ENABLE_JSON1
283
- "ENABLE_JSON1",
284
-#endif
285
-#if SQLITE_ENABLE_LOAD_EXTENSION
286
- "ENABLE_LOAD_EXTENSION",
287
-#endif
288
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
289
- "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
290
-#endif
291
-#if SQLITE_ENABLE_MATH_FUNCTIONS
292
- "ENABLE_MATH_FUNCTIONS",
293
-#endif
294
-#if SQLITE_ENABLE_MEMORY_MANAGEMENT
295
- "ENABLE_MEMORY_MANAGEMENT",
296
-#endif
297
-#if SQLITE_ENABLE_MEMSYS3
298
- "ENABLE_MEMSYS3",
299
-#endif
300
-#if SQLITE_ENABLE_MEMSYS5
301
- "ENABLE_MEMSYS5",
302
-#endif
303
-#if SQLITE_ENABLE_MULTIPLEX
304
- "ENABLE_MULTIPLEX",
305
-#endif
306
-#if SQLITE_ENABLE_NORMALIZE
307
- "ENABLE_NORMALIZE",
308
-#endif
309
-#if SQLITE_ENABLE_NULL_TRIM
310
- "ENABLE_NULL_TRIM",
311
-#endif
312
-#if SQLITE_ENABLE_OFFSET_SQL_FUNC
313
- "ENABLE_OFFSET_SQL_FUNC",
314
-#endif
315
-#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
316
- "ENABLE_OVERSIZE_CELL_CHECK",
317
-#endif
318
-#if SQLITE_ENABLE_PREUPDATE_HOOK
319
- "ENABLE_PREUPDATE_HOOK",
320
-#endif
321
-#if SQLITE_ENABLE_QPSG
322
- "ENABLE_QPSG",
323
-#endif
324
-#if SQLITE_ENABLE_RBU
325
- "ENABLE_RBU",
326
-#endif
327
-#if SQLITE_ENABLE_RTREE
328
- "ENABLE_RTREE",
329
-#endif
330
-#if SQLITE_ENABLE_SELECTTRACE
331
- "ENABLE_SELECTTRACE",
332
-#endif
333
-#if SQLITE_ENABLE_SESSION
334
- "ENABLE_SESSION",
335
-#endif
336
-#if SQLITE_ENABLE_SNAPSHOT
337
- "ENABLE_SNAPSHOT",
338
-#endif
339
-#if SQLITE_ENABLE_SORTER_REFERENCES
340
- "ENABLE_SORTER_REFERENCES",
341
-#endif
342
-#if SQLITE_ENABLE_SQLLOG
343
- "ENABLE_SQLLOG",
344
-#endif
345
-#if SQLITE_ENABLE_STAT4
346
- "ENABLE_STAT4",
347
-#endif
348
-#if SQLITE_ENABLE_STMTVTAB
349
- "ENABLE_STMTVTAB",
350
-#endif
351
-#if SQLITE_ENABLE_STMT_SCANSTATUS
352
- "ENABLE_STMT_SCANSTATUS",
353
-#endif
354
-#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
355
- "ENABLE_UNKNOWN_SQL_FUNCTION",
356
-#endif
357
-#if SQLITE_ENABLE_UNLOCK_NOTIFY
358
- "ENABLE_UNLOCK_NOTIFY",
359
-#endif
360
-#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
361
- "ENABLE_UPDATE_DELETE_LIMIT",
362
-#endif
363
-#if SQLITE_ENABLE_URI_00_ERROR
364
- "ENABLE_URI_00_ERROR",
365
-#endif
366
-#if SQLITE_ENABLE_VFSTRACE
367
- "ENABLE_VFSTRACE",
368
-#endif
369
-#if SQLITE_ENABLE_WHERETRACE
370
- "ENABLE_WHERETRACE",
371
-#endif
372
-#if SQLITE_ENABLE_ZIPVFS
373
- "ENABLE_ZIPVFS",
374
-#endif
375
-#if SQLITE_EXPLAIN_ESTIMATED_ROWS
376
- "EXPLAIN_ESTIMATED_ROWS",
377
-#endif
378
-#if SQLITE_EXTRA_IFNULLROW
379
- "EXTRA_IFNULLROW",
380
-#endif
381
-#ifdef SQLITE_EXTRA_INIT
382
- "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
383
-#endif
384
-#ifdef SQLITE_EXTRA_SHUTDOWN
385
- "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
386
-#endif
387
-#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
388
- "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
389
-#endif
390
-#if SQLITE_FTS5_ENABLE_TEST_MI
391
- "FTS5_ENABLE_TEST_MI",
392
-#endif
393
-#if SQLITE_FTS5_NO_WITHOUT_ROWID
394
- "FTS5_NO_WITHOUT_ROWID",
395
-#endif
396
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
397
- "HAVE_ISNAN",
398
-#endif
399
-#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
400
-# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
401
- "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
402
-# endif
403
-#endif
404
-#if SQLITE_IGNORE_AFP_LOCK_ERRORS
405
- "IGNORE_AFP_LOCK_ERRORS",
406
-#endif
407
-#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
408
- "IGNORE_FLOCK_LOCK_ERRORS",
409
-#endif
410
-#if SQLITE_INLINE_MEMCPY
411
- "INLINE_MEMCPY",
412
-#endif
413
-#if SQLITE_INT64_TYPE
414
- "INT64_TYPE",
415
-#endif
416
-#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
417
- "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
418
-#endif
419
-#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
420
- "LIKE_DOESNT_MATCH_BLOBS",
421
-#endif
422
-#if SQLITE_LOCK_TRACE
423
- "LOCK_TRACE",
424
-#endif
425
-#if SQLITE_LOG_CACHE_SPILL
426
- "LOG_CACHE_SPILL",
427
-#endif
428
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
429
- "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
430
-#endif
431
-#ifdef SQLITE_MAX_ATTACHED
432
- "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
433
-#endif
434
-#ifdef SQLITE_MAX_COLUMN
435
- "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
436
-#endif
437
-#ifdef SQLITE_MAX_COMPOUND_SELECT
438
- "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
439
-#endif
440
-#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
441
- "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
442
-#endif
443
-#ifdef SQLITE_MAX_EXPR_DEPTH
444
- "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
445
-#endif
446
-#ifdef SQLITE_MAX_FUNCTION_ARG
447
- "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
448
-#endif
449
-#ifdef SQLITE_MAX_LENGTH
450
- "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
451
-#endif
452
-#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
453
- "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
454
-#endif
455
-#ifdef SQLITE_MAX_MEMORY
456
- "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
457
-#endif
458
-#ifdef SQLITE_MAX_MMAP_SIZE
459
- "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
460
-#endif
461
-#ifdef SQLITE_MAX_MMAP_SIZE_
462
- "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
463
-#endif
464
-#ifdef SQLITE_MAX_PAGE_COUNT
465
- "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
466
-#endif
467
-#ifdef SQLITE_MAX_PAGE_SIZE
468
- "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
469
-#endif
470
-#ifdef SQLITE_MAX_SCHEMA_RETRY
471
- "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
472
-#endif
473
-#ifdef SQLITE_MAX_SQL_LENGTH
474
- "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
475
-#endif
476
-#ifdef SQLITE_MAX_TRIGGER_DEPTH
477
- "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
478
-#endif
479
-#ifdef SQLITE_MAX_VARIABLE_NUMBER
480
- "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
481
-#endif
482
-#ifdef SQLITE_MAX_VDBE_OP
483
- "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
484
-#endif
485
-#ifdef SQLITE_MAX_WORKER_THREADS
486
- "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
487
-#endif
488
-#if SQLITE_MEMDEBUG
489
- "MEMDEBUG",
490
-#endif
491
-#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
492
- "MIXED_ENDIAN_64BIT_FLOAT",
493
-#endif
494
-#if SQLITE_MMAP_READWRITE
495
- "MMAP_READWRITE",
496
-#endif
497
-#if SQLITE_MUTEX_NOOP
498
- "MUTEX_NOOP",
499
-#endif
500
-#if SQLITE_MUTEX_OMIT
501
- "MUTEX_OMIT",
502
-#endif
503
-#if SQLITE_MUTEX_PTHREADS
504
- "MUTEX_PTHREADS",
505
-#endif
506
-#if SQLITE_MUTEX_W32
507
- "MUTEX_W32",
508
-#endif
509
-#if SQLITE_NEED_ERR_NAME
510
- "NEED_ERR_NAME",
511
-#endif
512
-#if SQLITE_NOINLINE
513
- "NOINLINE",
514
-#endif
515
-#if SQLITE_NO_SYNC
516
- "NO_SYNC",
517
-#endif
518
-#if SQLITE_OMIT_ALTERTABLE
519
- "OMIT_ALTERTABLE",
520
-#endif
521
-#if SQLITE_OMIT_ANALYZE
522
- "OMIT_ANALYZE",
523
-#endif
524
-#if SQLITE_OMIT_ATTACH
525
- "OMIT_ATTACH",
526
-#endif
527
-#if SQLITE_OMIT_AUTHORIZATION
528
- "OMIT_AUTHORIZATION",
529
-#endif
530
-#if SQLITE_OMIT_AUTOINCREMENT
531
- "OMIT_AUTOINCREMENT",
532
-#endif
533
-#if SQLITE_OMIT_AUTOINIT
534
- "OMIT_AUTOINIT",
535
-#endif
536
-#if SQLITE_OMIT_AUTOMATIC_INDEX
537
- "OMIT_AUTOMATIC_INDEX",
538
-#endif
539
-#if SQLITE_OMIT_AUTORESET
540
- "OMIT_AUTORESET",
541
-#endif
542
-#if SQLITE_OMIT_AUTOVACUUM
543
- "OMIT_AUTOVACUUM",
544
-#endif
545
-#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
546
- "OMIT_BETWEEN_OPTIMIZATION",
547
-#endif
548
-#if SQLITE_OMIT_BLOB_LITERAL
549
- "OMIT_BLOB_LITERAL",
550
-#endif
551
-#if SQLITE_OMIT_CAST
552
- "OMIT_CAST",
553
-#endif
554
-#if SQLITE_OMIT_CHECK
555
- "OMIT_CHECK",
556
-#endif
557
-#if SQLITE_OMIT_COMPLETE
558
- "OMIT_COMPLETE",
559
-#endif
560
-#if SQLITE_OMIT_COMPOUND_SELECT
561
- "OMIT_COMPOUND_SELECT",
562
-#endif
563
-#if SQLITE_OMIT_CONFLICT_CLAUSE
564
- "OMIT_CONFLICT_CLAUSE",
565
-#endif
566
-#if SQLITE_OMIT_CTE
567
- "OMIT_CTE",
568
-#endif
569
-#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
570
- "OMIT_DATETIME_FUNCS",
571
-#endif
572
-#if SQLITE_OMIT_DECLTYPE
573
- "OMIT_DECLTYPE",
574
-#endif
575
-#if SQLITE_OMIT_DEPRECATED
576
- "OMIT_DEPRECATED",
577
-#endif
578
-#if SQLITE_OMIT_DESERIALIZE
579
- "OMIT_DESERIALIZE",
580
-#endif
581
-#if SQLITE_OMIT_DISKIO
582
- "OMIT_DISKIO",
583
-#endif
584
-#if SQLITE_OMIT_EXPLAIN
585
- "OMIT_EXPLAIN",
586
-#endif
587
-#if SQLITE_OMIT_FLAG_PRAGMAS
588
- "OMIT_FLAG_PRAGMAS",
589
-#endif
590
-#if SQLITE_OMIT_FLOATING_POINT
591
- "OMIT_FLOATING_POINT",
592
-#endif
593
-#if SQLITE_OMIT_FOREIGN_KEY
594
- "OMIT_FOREIGN_KEY",
595
-#endif
596
-#if SQLITE_OMIT_GET_TABLE
597
- "OMIT_GET_TABLE",
598
-#endif
599
-#if SQLITE_OMIT_HEX_INTEGER
600
- "OMIT_HEX_INTEGER",
601
-#endif
602
-#if SQLITE_OMIT_INCRBLOB
603
- "OMIT_INCRBLOB",
604
-#endif
605
-#if SQLITE_OMIT_INTEGRITY_CHECK
606
- "OMIT_INTEGRITY_CHECK",
607
-#endif
608
-#if SQLITE_OMIT_INTROSPECTION_PRAGMAS
609
- "OMIT_INTROSPECTION_PRAGMAS",
610
-#endif
611
-#if SQLITE_OMIT_LIKE_OPTIMIZATION
612
- "OMIT_LIKE_OPTIMIZATION",
613
-#endif
614
-#if SQLITE_OMIT_LOAD_EXTENSION
615
- "OMIT_LOAD_EXTENSION",
616
-#endif
617
-#if SQLITE_OMIT_LOCALTIME
618
- "OMIT_LOCALTIME",
619
-#endif
620
-#if SQLITE_OMIT_LOOKASIDE
621
- "OMIT_LOOKASIDE",
622
-#endif
623
-#if SQLITE_OMIT_MEMORYDB
624
- "OMIT_MEMORYDB",
625
-#endif
626
-#if SQLITE_OMIT_OR_OPTIMIZATION
627
- "OMIT_OR_OPTIMIZATION",
628
-#endif
629
-#if SQLITE_OMIT_PAGER_PRAGMAS
630
- "OMIT_PAGER_PRAGMAS",
631
-#endif
632
-#if SQLITE_OMIT_PARSER_TRACE
633
- "OMIT_PARSER_TRACE",
634
-#endif
635
-#if SQLITE_OMIT_POPEN
636
- "OMIT_POPEN",
637
-#endif
638
-#if SQLITE_OMIT_PRAGMA
639
- "OMIT_PRAGMA",
640
-#endif
641
-#if SQLITE_OMIT_PROGRESS_CALLBACK
642
- "OMIT_PROGRESS_CALLBACK",
643
-#endif
644
-#if SQLITE_OMIT_QUICKBALANCE
645
- "OMIT_QUICKBALANCE",
646
-#endif
647
-#if SQLITE_OMIT_REINDEX
648
- "OMIT_REINDEX",
649
-#endif
650
-#if SQLITE_OMIT_SCHEMA_PRAGMAS
651
- "OMIT_SCHEMA_PRAGMAS",
652
-#endif
653
-#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
654
- "OMIT_SCHEMA_VERSION_PRAGMAS",
655
-#endif
656
-#if SQLITE_OMIT_SHARED_CACHE
657
- "OMIT_SHARED_CACHE",
658
-#endif
659
-#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
660
- "OMIT_SHUTDOWN_DIRECTORIES",
661
-#endif
662
-#if SQLITE_OMIT_SUBQUERY
663
- "OMIT_SUBQUERY",
664
-#endif
665
-#if SQLITE_OMIT_TCL_VARIABLE
666
- "OMIT_TCL_VARIABLE",
667
-#endif
668
-#if SQLITE_OMIT_TEMPDB
669
- "OMIT_TEMPDB",
670
-#endif
671
-#if SQLITE_OMIT_TEST_CONTROL
672
- "OMIT_TEST_CONTROL",
673
-#endif
674
-#ifdef SQLITE_OMIT_TRACE
675
-# if SQLITE_OMIT_TRACE != 1
676
- "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
677
-# endif
678
-#endif
679
-#if SQLITE_OMIT_TRIGGER
680
- "OMIT_TRIGGER",
681
-#endif
682
-#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
683
- "OMIT_TRUNCATE_OPTIMIZATION",
684
-#endif
685
-#if SQLITE_OMIT_UTF16
686
- "OMIT_UTF16",
687
-#endif
688
-#if SQLITE_OMIT_VACUUM
689
- "OMIT_VACUUM",
690
-#endif
691
-#if SQLITE_OMIT_VIEW
692
- "OMIT_VIEW",
693
-#endif
694
-#if SQLITE_OMIT_VIRTUALTABLE
695
- "OMIT_VIRTUALTABLE",
696
-#endif
697
-#if SQLITE_OMIT_WAL
698
- "OMIT_WAL",
699
-#endif
700
-#if SQLITE_OMIT_WSD
701
- "OMIT_WSD",
702
-#endif
703
-#if SQLITE_OMIT_XFER_OPT
704
- "OMIT_XFER_OPT",
705
-#endif
706
-#if SQLITE_PCACHE_SEPARATE_HEADER
707
- "PCACHE_SEPARATE_HEADER",
708
-#endif
709
-#if SQLITE_PERFORMANCE_TRACE
710
- "PERFORMANCE_TRACE",
711
-#endif
712
-#ifdef SQLITE_POWERSAFE_OVERWRITE
713
-# if SQLITE_POWERSAFE_OVERWRITE != 1
714
- "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
715
-# endif
716
-#endif
717
-#if SQLITE_PREFER_PROXY_LOCKING
718
- "PREFER_PROXY_LOCKING",
719
-#endif
720
-#if SQLITE_PROXY_DEBUG
721
- "PROXY_DEBUG",
722
-#endif
723
-#if SQLITE_REVERSE_UNORDERED_SELECTS
724
- "REVERSE_UNORDERED_SELECTS",
725
-#endif
726
-#if SQLITE_RTREE_INT_ONLY
727
- "RTREE_INT_ONLY",
728
-#endif
729
-#if SQLITE_SECURE_DELETE
730
- "SECURE_DELETE",
731
-#endif
732
-#if SQLITE_SMALL_STACK
733
- "SMALL_STACK",
734
-#endif
735
-#ifdef SQLITE_SORTER_PMASZ
736
- "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
737
-#endif
738
-#if SQLITE_SOUNDEX
739
- "SOUNDEX",
740
-#endif
741
-#ifdef SQLITE_STAT4_SAMPLES
742
- "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
743
-#endif
744
-#ifdef SQLITE_STMTJRNL_SPILL
745
- "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
746
-#endif
747
-#if SQLITE_SUBSTR_COMPATIBILITY
748
- "SUBSTR_COMPATIBILITY",
749
-#endif
750
-#if (!defined(SQLITE_WIN32_MALLOC) \
751
- && !defined(SQLITE_ZERO_MALLOC) \
752
- && !defined(SQLITE_MEMDEBUG) \
753
- ) || defined(SQLITE_SYSTEM_MALLOC)
754
- "SYSTEM_MALLOC",
755
-#endif
756
-#if SQLITE_TCL
757
- "TCL",
758
-#endif
759
-#ifdef SQLITE_TEMP_STORE
760
- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
761
-#endif
762
-#if SQLITE_TEST
763
- "TEST",
764
-#endif
765
-#if defined(SQLITE_THREADSAFE)
766
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
767
-#elif defined(THREADSAFE)
768
- "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
769
-#else
770
- "THREADSAFE=1",
771
-#endif
772
-#if SQLITE_UNLINK_AFTER_CLOSE
773
- "UNLINK_AFTER_CLOSE",
774
-#endif
775
-#if SQLITE_UNTESTABLE
776
- "UNTESTABLE",
777
-#endif
778
-#if SQLITE_USER_AUTHENTICATION
779
- "USER_AUTHENTICATION",
780
-#endif
781
-#if SQLITE_USE_ALLOCA
782
- "USE_ALLOCA",
783
-#endif
784
-#if SQLITE_USE_FCNTL_TRACE
785
- "USE_FCNTL_TRACE",
786
-#endif
787
-#if SQLITE_USE_URI
788
- "USE_URI",
789
-#endif
790
-#if SQLITE_VDBE_COVERAGE
791
- "VDBE_COVERAGE",
792
-#endif
793
-#if SQLITE_WIN32_MALLOC
794
- "WIN32_MALLOC",
795
-#endif
796
-#if SQLITE_ZERO_MALLOC
797
- "ZERO_MALLOC",
798
-#endif
799
-/*
800
-** END CODE GENERATED BY tool/mkctime.tcl
801
-*/
802
-};
803
-
804
-SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
805
- *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
806
- return (const char**)sqlite3azCompileOpt;
807
-}
808
-
809
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
810
-
811
-/************** End of ctime.c ***********************************************/
81225
/************** Begin file sqliteInt.h ***************************************/
81326
/*
81427
** 2001 September 15
81528
**
81629
** The author disclaims copyright to this source code. In place of
@@ -1071,10 +284,21 @@
1071284
defined(_WIN32) && !defined(_WIN64) && \
1072285
defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
1073286
defined(__MSVCRT__)
1074287
# define _USE_32BIT_TIME_T
1075288
#endif
289
+
290
+/* Optionally #include a user-defined header, whereby compilation options
291
+** may be set prior to where they take effect, but after platform setup.
292
+** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
293
+** file.
294
+*/
295
+#ifdef SQLITE_CUSTOM_INCLUDE
296
+# define INC_STRINGIFY_(f) #f
297
+# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
298
+# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
299
+#endif
1076300
1077301
/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
1078302
** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
1079303
** MinGW.
1080304
*/
@@ -1123,11 +347,34 @@
1123347
extern "C" {
1124348
#endif
1125349
1126350
1127351
/*
1128
-** Provide the ability to override linkage features of the interface.
352
+** Facilitate override of interface linkage and calling conventions.
353
+** Be aware that these macros may not be used within this particular
354
+** translation of the amalgamation and its associated header file.
355
+**
356
+** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
357
+** compiler that the target identifier should have external linkage.
358
+**
359
+** The SQLITE_CDECL macro is used to set the calling convention for
360
+** public functions that accept a variable number of arguments.
361
+**
362
+** The SQLITE_APICALL macro is used to set the calling convention for
363
+** public functions that accept a fixed number of arguments.
364
+**
365
+** The SQLITE_STDCALL macro is no longer used and is now deprecated.
366
+**
367
+** The SQLITE_CALLBACK macro is used to set the calling convention for
368
+** function pointers.
369
+**
370
+** The SQLITE_SYSAPI macro is used to set the calling convention for
371
+** functions provided by the operating system.
372
+**
373
+** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
374
+** SQLITE_SYSAPI macros are used only when building for environments
375
+** that require non-default calling conventions.
1129376
*/
1130377
#ifndef SQLITE_EXTERN
1131378
# define SQLITE_EXTERN extern
1132379
#endif
1133380
#ifndef SQLITE_API
@@ -1203,13 +450,13 @@
1203450
**
1204451
** See also: [sqlite3_libversion()],
1205452
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1206453
** [sqlite_version()] and [sqlite_source_id()].
1207454
*/
1208
-#define SQLITE_VERSION "3.36.0"
1209
-#define SQLITE_VERSION_NUMBER 3036000
1210
-#define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70"
455
+#define SQLITE_VERSION "3.37.0"
456
+#define SQLITE_VERSION_NUMBER 3037000
457
+#define SQLITE_SOURCE_ID "2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a"
1211458
1212459
/*
1213460
** CAPI3REF: Run-Time Library Version Numbers
1214461
** KEYWORDS: sqlite3_version sqlite3_sourceid
1215462
**
@@ -1596,10 +843,11 @@
1596843
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
1597844
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
1598845
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
1599846
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
1600847
#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
848
+#define SQLITE_CANTOPEN_EXISTS (SQLITE_CANTOPEN | (7<<8))
1601849
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1602850
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
1603851
#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
1604852
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
1605853
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -3544,15 +2792,18 @@
35442792
35452793
/*
35462794
** CAPI3REF: Count The Number Of Rows Modified
35472795
** METHOD: sqlite3
35482796
**
3549
-** ^This function returns the number of rows modified, inserted or
2797
+** ^These functions return the number of rows modified, inserted or
35502798
** deleted by the most recently completed INSERT, UPDATE or DELETE
35512799
** statement on the database connection specified by the only parameter.
3552
-** ^Executing any other type of SQL statement does not modify the value
3553
-** returned by this function.
2800
+** The two functions are identical except for the type of the return value
2801
+** and that if the number of rows modified by the most recent INSERT, UPDATE
2802
+** or DELETE is greater than the maximum value supported by type "int", then
2803
+** the return value of sqlite3_changes() is undefined. ^Executing any other
2804
+** type of SQL statement does not modify the value returned by these functions.
35542805
**
35552806
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
35562807
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
35572808
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
35582809
**
@@ -3597,20 +2848,25 @@
35972848
** <li> the [changes() SQL function]
35982849
** <li> the [data_version pragma]
35992850
** </ul>
36002851
*/
36012852
SQLITE_API int sqlite3_changes(sqlite3*);
2853
+SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
36022854
36032855
/*
36042856
** CAPI3REF: Total Number Of Rows Modified
36052857
** METHOD: sqlite3
36062858
**
3607
-** ^This function returns the total number of rows inserted, modified or
2859
+** ^These functions return the total number of rows inserted, modified or
36082860
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
36092861
** since the database connection was opened, including those executed as
3610
-** part of trigger programs. ^Executing any other type of SQL statement
3611
-** does not affect the value returned by sqlite3_total_changes().
2862
+** part of trigger programs. The two functions are identical except for the
2863
+** type of the return value and that if the number of rows modified by the
2864
+** connection exceeds the maximum value supported by type "int", then
2865
+** the return value of sqlite3_total_changes() is undefined. ^Executing
2866
+** any other type of SQL statement does not affect the value returned by
2867
+** sqlite3_total_changes().
36122868
**
36132869
** ^Changes made as part of [foreign key actions] are included in the
36142870
** count, but those made as part of REPLACE constraint resolution are
36152871
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
36162872
** are not counted.
@@ -3634,10 +2890,11 @@
36342890
** <li> the [data_version pragma]
36352891
** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
36362892
** </ul>
36372893
*/
36382894
SQLITE_API int sqlite3_total_changes(sqlite3*);
2895
+SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
36392896
36402897
/*
36412898
** CAPI3REF: Interrupt A Long-Running Query
36422899
** METHOD: sqlite3
36432900
**
@@ -4465,10 +3722,16 @@
44653722
** the default shared cache setting provided by
44663723
** [sqlite3_enable_shared_cache()].)^
44673724
**
44683725
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
44693726
** <dd>The database filename is not allowed to be a symbolic link</dd>
3727
+**
3728
+** [[OPEN_EXCLUSIVE]] ^(<dt>[SQLITE_OPEN_EXCLUSIVE]</dt>
3729
+** <dd>This flag causes the open to fail if the database file already
3730
+** exists. The open will only be success if this flag is used in combination
3731
+** with the SQLITE_OPEN_CREATE and SQLITE_OPEN_READWRITE flags and if
3732
+** the file does not previously exist.</dd>
44703733
** </dl>)^
44713734
**
44723735
** If the 3rd parameter to sqlite3_open_v2() is not one of the
44733736
** required combinations shown above optionally combined with other
44743737
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
@@ -5238,16 +4501,21 @@
52384501
**
52394502
** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
52404503
** are managed by SQLite and are automatically freed when the prepared
52414504
** statement is finalized.
52424505
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
5243
-** is obtained from [sqlite3_malloc()] and must be free by the application
4506
+** is obtained from [sqlite3_malloc()] and must be freed by the application
52444507
** by passing it to [sqlite3_free()].
4508
+**
4509
+** ^The sqlite3_normalized_sql() interface is only available if
4510
+** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
52454511
*/
52464512
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
52474513
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
4514
+#ifdef SQLITE_ENABLE_NORMALIZE
52484515
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
4516
+#endif
52494517
52504518
/*
52514519
** CAPI3REF: Determine If An SQL Statement Writes The Database
52524520
** METHOD: sqlite3_stmt
52534521
**
@@ -5458,21 +4726,21 @@
54584726
** contain embedded NULs. The result of expressions involving strings
54594727
** with embedded NULs is undefined.
54604728
**
54614729
** ^The fifth argument to the BLOB and string binding interfaces controls
54624730
** or indicates the lifetime of the object referenced by the third parameter.
5463
-** ^These three options exist:
5464
-** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
4731
+** These three options exist:
4732
+** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
54654733
** with it may be passed. ^It is called to dispose of the BLOB or string even
54664734
** if the call to the bind API fails, except the destructor is not called if
54674735
** the third parameter is a NULL pointer or the fourth parameter is negative.
5468
-** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
4736
+** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
54694737
** the application remains responsible for disposing of the object. ^In this
54704738
** case, the object and the provided pointer to it must remain valid until
54714739
** either the prepared statement is finalized or the same SQL parameter is
54724740
** bound to something else, whichever occurs sooner.
5473
-** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4741
+** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
54744742
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
54754743
** object and pointer to it must remain valid until then. ^SQLite will then
54764744
** manage the lifetime of its private copy.
54774745
**
54784746
** ^The sixth argument to sqlite3_bind_text64() must be one of
@@ -10090,12 +9358,13 @@
100909358
** that does not correspond to any valid SQLite error code, the results
100919359
** are undefined.
100929360
**
100939361
** A single database handle may have at most a single write-ahead log callback
100949362
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
10095
-** previously registered write-ahead log callback. ^Note that the
10096
-** [sqlite3_wal_autocheckpoint()] interface and the
9363
+** previously registered write-ahead log callback. ^The return value is
9364
+** a copy of the third parameter from the previous call, if any, or 0.
9365
+** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
100979366
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
100989367
** overwrite any prior [sqlite3_wal_hook()] settings.
100999368
*/
101009369
SQLITE_API void *sqlite3_wal_hook(
101019370
sqlite3*,
@@ -10957,10 +10226,14 @@
1095710226
** if writes on the database cause it to grow larger than M bytes.
1095810227
**
1095910228
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
1096010229
** database is currently in a read transaction or is involved in a backup
1096110230
** operation.
10231
+**
10232
+** It is not possible to deserialized into the TEMP database. If the
10233
+** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
10234
+** function returns SQLITE_ERROR.
1096210235
**
1096310236
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
1096410237
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
1096510238
** [sqlite3_free()] is invoked on argument P prior to returning.
1096610239
**
@@ -13440,11 +12713,11 @@
1344012713
/*
1344112714
** Include the configuration header output by 'configure' if we're using the
1344212715
** autoconf-based build
1344312716
*/
1344412717
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
13445
-/* #include "config.h" */
12718
+#include "config.h"
1344612719
#define SQLITECONFIG_H 1
1344712720
#endif
1344812721
1344912722
/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
1345012723
/************** Begin file sqliteLimit.h *************************************/
@@ -13676,15 +12949,16 @@
1367612949
** places. The following macros try to make this explicit.
1367712950
*/
1367812951
#ifndef __has_extension
1367912952
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
1368012953
#endif
13681
-#if GCC_VERSION>=4007000 || \
13682
- (__has_extension(c_atomic) && __has_extension(c_atomic_store_n))
12954
+#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
12955
+# define SQLITE_ATOMIC_INTRINSICS 1
1368312956
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
1368412957
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
1368512958
#else
12959
+# define SQLITE_ATOMIC_INTRINSICS 0
1368612960
# define AtomicLoad(PTR) (*(PTR))
1368712961
# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
1368812962
#endif
1368912963
1369012964
/*
@@ -14598,10 +13872,11 @@
1459813872
#ifndef SQLITE_PTRSIZE
1459913873
# if defined(__SIZEOF_POINTER__)
1460013874
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
1460113875
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
1460213876
defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
13877
+ (defined(__APPLE__) && defined(__POWERPC__)) || \
1460313878
(defined(__TOS_AIX__) && !defined(__64BIT__))
1460413879
# define SQLITE_PTRSIZE 4
1460513880
# else
1460613881
# define SQLITE_PTRSIZE 8
1460713882
# endif
@@ -15349,11 +14624,11 @@
1534914624
*/
1535014625
#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
1535114626
#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
1535214627
1535314628
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
15354
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
14629
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*);
1535514630
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
1535614631
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
1535714632
1535814633
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
1535914634
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
@@ -15473,16 +14748,20 @@
1547314748
#ifdef SQLITE_ENABLE_CURSOR_HINTS
1547414749
SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
1547514750
#endif
1547614751
1547714752
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
15478
-SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
14753
+SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
1547914754
BtCursor*,
15480
- UnpackedRecord *pUnKey,
1548114755
i64 intKey,
1548214756
int bias,
1548314757
int *pRes
14758
+);
14759
+SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
14760
+ BtCursor*,
14761
+ UnpackedRecord *pUnKey,
14762
+ int *pRes
1548414763
);
1548514764
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
1548614765
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
1548714766
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
1548814767
@@ -17110,12 +16389,12 @@
1711016389
u8 mTrace; /* zero or more SQLITE_TRACE flags */
1711116390
u8 noSharedCache; /* True if no shared-cache backends */
1711216391
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
1711316392
int nextPagesize; /* Pagesize after VACUUM if >0 */
1711416393
u32 magic; /* Magic number for detect library misuse */
17115
- int nChange; /* Value returned by sqlite3_changes() */
17116
- int nTotalChange; /* Value returned by sqlite3_total_changes() */
16394
+ i64 nChange; /* Value returned by sqlite3_changes() */
16395
+ i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
1711716396
int aLimit[SQLITE_N_LIMIT]; /* Limits */
1711816397
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
1711916398
struct sqlite3InitInfo { /* Information used during initialization */
1712016399
Pgno newTnum; /* Rootpage of table being initialized */
1712116400
u8 iDb; /* Which db file is being initialized */
@@ -17320,10 +16599,12 @@
1732016599
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
1732116600
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
1732216601
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
1732316602
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
1732416603
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
16604
+#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
16605
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
1732516606
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
1732616607
1732716608
/*
1732816609
** Macros for testing whether or not optimizations are enabled or disabled.
1732916610
*/
@@ -17399,16 +16680,17 @@
1739916680
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
1740016681
** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
1740116682
** are assert() statements in the code to verify this.
1740216683
**
1740316684
** Value constraints (enforced via assert()):
17404
-** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
17405
-** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
17406
-** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
17407
-** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
17408
-** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
17409
-** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
16685
+** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
16686
+** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
16687
+** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
16688
+** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
16689
+** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
16690
+** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
16691
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
1741016692
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
1741116693
*/
1741216694
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
1741316695
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
1741416696
#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
@@ -17429,10 +16711,11 @@
1742916711
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
1743016712
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
1743116713
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
1743216714
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
1743316715
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
16716
+#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
1743416717
1743516718
/* Identifier numbers for each in-line function */
1743616719
#define INLINEFUNC_coalesce 0
1743716720
#define INLINEFUNC_implies_nonnull_row 1
1743816721
#define INLINEFUNC_expr_implies_expr 2
@@ -17599,22 +16882,45 @@
1759916882
** record BLOB generated by the OP_MakeRecord
1760016883
** opcode. The storage column index is less than
1760116884
** or equal to the table column index. It is
1760216885
** equal if and only if there are no VIRTUAL
1760316886
** columns to the left.
16887
+**
16888
+** Notes on zCnName:
16889
+** The zCnName field stores the name of the column, the datatype of the
16890
+** column, and the collating sequence for the column, in that order, all in
16891
+** a single allocation. Each string is 0x00 terminated. The datatype
16892
+** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
16893
+** collating sequence name is only included if the COLFLAG_HASCOLL bit is
16894
+** set.
1760416895
*/
1760516896
struct Column {
17606
- char *zName; /* Name of this column, \000, then the type */
17607
- Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
17608
- char *zColl; /* Collating sequence. If NULL, use the default */
17609
- u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
17610
- char affinity; /* One of the SQLITE_AFF_... values */
17611
- u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
17612
- u8 hName; /* Column name hash for faster lookup */
17613
- u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
16897
+ char *zCnName; /* Name of this column */
16898
+ unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */
16899
+ unsigned eType :4; /* One of the standard types */
16900
+ char affinity; /* One of the SQLITE_AFF_... values */
16901
+ u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */
16902
+ u8 hName; /* Column name hash for faster lookup */
16903
+ u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */
16904
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
1761416905
};
1761516906
16907
+/* Allowed values for Column.eType.
16908
+**
16909
+** Values must match entries in the global constant arrays
16910
+** sqlite3StdTypeLen[] and sqlite3StdType[]. Each value is one more
16911
+** than the offset into these arrays for the corresponding name.
16912
+** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
16913
+*/
16914
+#define COLTYPE_CUSTOM 0 /* Type appended to zName */
16915
+#define COLTYPE_BLOB 1
16916
+#define COLTYPE_INT 2
16917
+#define COLTYPE_INTEGER 3
16918
+#define COLTYPE_REAL 4
16919
+#define COLTYPE_TEXT 5
16920
+#define SQLITE_N_STDTYPE 5 /* Number of standard types */
16921
+
1761616922
/* Allowed values for Column.colFlags.
1761716923
**
1761816924
** Constraints:
1761916925
** TF_HasVirtual == COLFLAG_VIRTUAL
1762016926
** TF_HasStored == COLFLAG_STORED
@@ -17627,10 +16933,11 @@
1762716933
#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
1762816934
#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
1762916935
#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
1763016936
#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
1763116937
#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
16938
+#define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */
1763216939
#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
1763316940
#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
1763416941
1763516942
/*
1763616943
** A "Collating Sequence" is defined by an instance of the following
@@ -17756,19 +17063,17 @@
1775617063
#define SQLITE_VTABRISK_Low 0
1775717064
#define SQLITE_VTABRISK_Normal 1
1775817065
#define SQLITE_VTABRISK_High 2
1775917066
1776017067
/*
17761
-** The schema for each SQL table and view is represented in memory
17762
-** by an instance of the following structure.
17068
+** The schema for each SQL table, virtual table, and view is represented
17069
+** in memory by an instance of the following structure.
1776317070
*/
1776417071
struct Table {
1776517072
char *zName; /* Name of the table or view */
1776617073
Column *aCol; /* Information about each column */
1776717074
Index *pIndex; /* List of SQL indexes on this table. */
17768
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
17769
- FKey *pFKey; /* Linked list of all foreign keys in this table */
1777017075
char *zColAff; /* String defining the affinity of each column */
1777117076
ExprList *pCheck; /* All CHECK constraints */
1777217077
/* ... also used as column name list in a VIEW */
1777317078
Pgno tnum; /* Root BTree page for this table */
1777417079
u32 nTabRef; /* Number of pointers to this Table */
@@ -17780,19 +17085,28 @@
1778017085
LogEst szTabRow; /* Estimated size of each table row in bytes */
1778117086
#ifdef SQLITE_ENABLE_COSTMULT
1778217087
LogEst costMult; /* Cost multiplier for using this table */
1778317088
#endif
1778417089
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
17785
-#ifndef SQLITE_OMIT_ALTERTABLE
17786
- int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
17787
-#endif
17788
-#ifndef SQLITE_OMIT_VIRTUALTABLE
17789
- int nModuleArg; /* Number of arguments to the module */
17790
- char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */
17791
- VTable *pVTable; /* List of VTable objects. */
17792
-#endif
17793
- Trigger *pTrigger; /* List of triggers stored in pSchema */
17090
+ u8 eTabType; /* 0: normal, 1: virtual, 2: view */
17091
+ union {
17092
+ struct { /* Used by ordinary tables: */
17093
+ int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
17094
+ FKey *pFKey; /* Linked list of all foreign keys in this table */
17095
+ ExprList *pDfltList; /* DEFAULT clauses on various columns.
17096
+ ** Or the AS clause for generated columns. */
17097
+ } tab;
17098
+ struct { /* Used by views: */
17099
+ Select *pSelect; /* View definition */
17100
+ } view;
17101
+ struct { /* Used by virtual tables only: */
17102
+ int nArg; /* Number of arguments to the module */
17103
+ char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */
17104
+ VTable *p; /* List of VTable objects. */
17105
+ } vtab;
17106
+ } u;
17107
+ Trigger *pTrigger; /* List of triggers on this object */
1779417108
Schema *pSchema; /* Schema that contains this table */
1779517109
};
1779617110
1779717111
/*
1779817112
** Allowed values for Table.tabFlags.
@@ -17807,38 +17121,48 @@
1780717121
**
1780817122
** TF_HasVirtual == COLFLAG_VIRTUAL
1780917123
** TF_HasStored == COLFLAG_STORED
1781017124
** TF_HasHidden == COLFLAG_HIDDEN
1781117125
*/
17812
-#define TF_Readonly 0x0001 /* Read-only system table */
17813
-#define TF_HasHidden 0x0002 /* Has one or more hidden columns */
17814
-#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
17815
-#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
17816
-#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
17817
-#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
17818
-#define TF_HasStored 0x0040 /* Has one or more STORED columns */
17819
-#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
17820
-#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
17821
-#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
17126
+#define TF_Readonly 0x00000001 /* Read-only system table */
17127
+#define TF_HasHidden 0x00000002 /* Has one or more hidden columns */
17128
+#define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */
17129
+#define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */
17130
+#define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */
17131
+#define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */
17132
+#define TF_HasStored 0x00000040 /* Has one or more STORED columns */
17133
+#define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
17134
+#define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
17135
+#define TF_StatsUsed 0x00000100 /* Query planner decisions affected by
1782217136
** Index.aiRowLogEst[] values */
17823
-#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
17824
-#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
17825
-#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
17826
-#define TF_Shadow 0x1000 /* True for a shadow table */
17827
-#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
17828
-#define TF_Ephemeral 0x4000 /* An ephemeral table */
17829
-#define TF_Eponymous 0x8000 /* An eponymous virtual table */
17137
+#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
17138
+#define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
17139
+#define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
17140
+#define TF_Shadow 0x00001000 /* True for a shadow table */
17141
+#define TF_HasStat4 0x00002000 /* STAT4 info available for this table */
17142
+#define TF_Ephemeral 0x00004000 /* An ephemeral table */
17143
+#define TF_Eponymous 0x00008000 /* An eponymous virtual table */
17144
+
17145
+/*
17146
+** Allowed values for Table.eTabType
17147
+*/
17148
+#define TABTYP_NORM 0 /* Ordinary table */
17149
+#define TABTYP_VTAB 1 /* Virtual table */
17150
+#define TABTYP_VIEW 2 /* A view */
17151
+
17152
+#define IsView(X) ((X)->eTabType==TABTYP_VIEW)
17153
+#define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM)
1783017154
1783117155
/*
1783217156
** Test to see whether or not a table is a virtual table. This is
1783317157
** done as a macro so that it will be optimized out when virtual
1783417158
** table support is omitted from the build.
1783517159
*/
1783617160
#ifndef SQLITE_OMIT_VIRTUALTABLE
17837
-# define IsVirtual(X) ((X)->nModuleArg)
17161
+# define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB)
1783817162
# define ExprIsVtab(X) \
17839
- ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg)
17163
+ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB)
1784017164
#else
1784117165
# define IsVirtual(X) 0
1784217166
# define ExprIsVtab(X) 0
1784317167
#endif
1784417168
@@ -18664,35 +17988,37 @@
1866417988
1866517989
/*
1866617990
** Allowed values for the NameContext, ncFlags field.
1866717991
**
1866817992
** Value constraints (all checked via assert()):
18669
-** NC_HasAgg == SF_HasAgg == EP_Agg
18670
-** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
17993
+** NC_HasAgg == SF_HasAgg == EP_Agg
17994
+** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
17995
+** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
1867117996
** NC_HasWin == EP_Win
1867217997
**
1867317998
*/
18674
-#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
18675
-#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
18676
-#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
18677
-#define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
18678
-#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
18679
-#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
18680
-#define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
18681
-#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
18682
-#define NC_UEList 0x00080 /* True if uNC.pEList is used */
18683
-#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
18684
-#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
18685
-#define NC_UBaseReg 0x00400 /* True if uNC.iBaseReg is used */
18686
-#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
18687
-#define NC_Complex 0x02000 /* True if a function or subquery seen */
18688
-#define NC_AllowWin 0x04000 /* Window functions are allowed here */
18689
-#define NC_HasWin 0x08000 /* One or more window functions seen */
18690
-#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
18691
-#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
18692
-#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
18693
-#define NC_NoSelect 0x80000 /* Do not descend into sub-selects */
17999
+#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
18000
+#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
18001
+#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
18002
+#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
18003
+#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
18004
+#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
18005
+#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
18006
+#define NC_VarSelect 0x000040 /* A correlated subquery has been seen */
18007
+#define NC_UEList 0x000080 /* True if uNC.pEList is used */
18008
+#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
18009
+#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
18010
+#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
18011
+#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
18012
+#define NC_Complex 0x002000 /* True if a function or subquery seen */
18013
+#define NC_AllowWin 0x004000 /* Window functions are allowed here */
18014
+#define NC_HasWin 0x008000 /* One or more window functions seen */
18015
+#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
18016
+#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
18017
+#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
18018
+#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
18019
+#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
1869418020
1869518021
/*
1869618022
** An instance of the following object describes a single ON CONFLICT
1869718023
** clause in an upsert.
1869818024
**
@@ -18771,13 +18097,14 @@
1877118097
/*
1877218098
** Allowed values for Select.selFlags. The "SF" prefix stands for
1877318099
** "Select Flag".
1877418100
**
1877518101
** Value constraints (all checked via assert())
18776
-** SF_HasAgg == NC_HasAgg
18777
-** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
18778
-** SF_FixedLimit == WHERE_USE_LIMIT
18102
+** SF_HasAgg == NC_HasAgg
18103
+** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
18104
+** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
18105
+** SF_FixedLimit == WHERE_USE_LIMIT
1877918106
*/
1878018107
#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
1878118108
#define SF_All 0x0000002 /* Includes the ALL keyword */
1878218109
#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
1878318110
#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
@@ -18798,14 +18125,15 @@
1879818125
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
1879918126
#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
1880018127
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
1880118128
#define SF_View 0x0200000 /* SELECT statement is a view */
1880218129
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
18803
-#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
18130
+#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
1880418131
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
1880518132
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
1880618133
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
18134
+#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
1880718135
1880818136
/*
1880918137
** The results of a SELECT can be distributed in several ways, as defined
1881018138
** by one of the following macros. The "SRT" prefix means "SELECT Result
1881118139
** Type".
@@ -19884,10 +19212,11 @@
1988419212
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
1988519213
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
1988619214
SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
1988719215
SQLITE_PRIVATE void sqlite3Dequote(char*);
1988819216
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
19217
+SQLITE_PRIVATE void sqlite3DequoteToken(Token*);
1988919218
SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
1989019219
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
1989119220
SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
1989219221
SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
1989319222
SQLITE_PRIVATE int sqlite3GetTempReg(Parse*);
@@ -19911,10 +19240,11 @@
1991119240
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
1991219241
SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
1991319242
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
1991419243
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
1991519244
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
19245
+SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
1991619246
SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
1991719247
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
1991819248
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
1991919249
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
1992019250
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
@@ -19928,10 +19258,14 @@
1992819258
#endif
1992919259
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
1993019260
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
1993119261
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
1993219262
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
19263
+SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
19264
+SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*);
19265
+SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
19266
+SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*);
1993319267
SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
1993419268
SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
1993519269
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
1993619270
SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
1993719271
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -19949,11 +19283,11 @@
1994919283
#if SQLITE_ENABLE_HIDDEN_COLUMNS
1995019284
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
1995119285
#else
1995219286
# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
1995319287
#endif
19954
-SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
19288
+SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token,Token);
1995519289
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
1995619290
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
1995719291
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
1995819292
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
1995919293
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
@@ -20066,11 +19400,11 @@
2006619400
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
2006719401
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
2006819402
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
2006919403
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
2007019404
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
20071
-SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
19405
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
2007219406
#endif
2007319407
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
2007419408
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
2007519409
SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
2007619410
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
@@ -20329,11 +19663,11 @@
2032919663
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
2033019664
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
2033119665
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
2033219666
SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
2033319667
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
20334
-SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
19668
+SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64);
2033519669
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
2033619670
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
2033719671
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
2033819672
SQLITE_PRIVATE int sqlite3AbsInt32(int);
2033919673
#ifdef SQLITE_ENABLE_8_3_NAMES
@@ -20359,10 +19693,13 @@
2035919693
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
2036019694
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
2036119695
#ifndef SQLITE_AMALGAMATION
2036219696
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
2036319697
SQLITE_PRIVATE const char sqlite3StrBINARY[];
19698
+SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[];
19699
+SQLITE_PRIVATE const char sqlite3StdTypeAffinity[];
19700
+SQLITE_PRIVATE const char *sqlite3StdType[];
2036419701
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
2036519702
SQLITE_PRIVATE const unsigned char *sqlite3aLTb;
2036619703
SQLITE_PRIVATE const unsigned char *sqlite3aEQb;
2036719704
SQLITE_PRIVATE const unsigned char *sqlite3aGTb;
2036819705
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
@@ -20779,20 +20116,1004 @@
2077920116
#endif
2078020117
2078120118
SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr);
2078220119
SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr);
2078320120
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
20784
-SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
20121
+SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
2078520122
SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
2078620123
2078720124
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
2078820125
SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
2078920126
#endif
2079020127
2079120128
#endif /* SQLITEINT_H */
2079220129
2079320130
/************** End of sqliteInt.h *******************************************/
20131
+/************** Begin file os_common.h ***************************************/
20132
+/*
20133
+** 2004 May 22
20134
+**
20135
+** The author disclaims copyright to this source code. In place of
20136
+** a legal notice, here is a blessing:
20137
+**
20138
+** May you do good and not evil.
20139
+** May you find forgiveness for yourself and forgive others.
20140
+** May you share freely, never taking more than you give.
20141
+**
20142
+******************************************************************************
20143
+**
20144
+** This file contains macros and a little bit of code that is common to
20145
+** all of the platform-specific files (os_*.c) and is #included into those
20146
+** files.
20147
+**
20148
+** This file should be #included by the os_*.c files only. It is not a
20149
+** general purpose header file.
20150
+*/
20151
+#ifndef _OS_COMMON_H_
20152
+#define _OS_COMMON_H_
20153
+
20154
+/*
20155
+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
20156
+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
20157
+** switch. The following code should catch this problem at compile-time.
20158
+*/
20159
+#ifdef MEMORY_DEBUG
20160
+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
20161
+#endif
20162
+
20163
+/*
20164
+** Macros for performance tracing. Normally turned off. Only works
20165
+** on i486 hardware.
20166
+*/
20167
+#ifdef SQLITE_PERFORMANCE_TRACE
20168
+
20169
+/*
20170
+** hwtime.h contains inline assembler code for implementing
20171
+** high-performance timing routines.
20172
+*/
20173
+/************** Include hwtime.h in the middle of os_common.h ****************/
20174
+/************** Begin file hwtime.h ******************************************/
20175
+/*
20176
+** 2008 May 27
20177
+**
20178
+** The author disclaims copyright to this source code. In place of
20179
+** a legal notice, here is a blessing:
20180
+**
20181
+** May you do good and not evil.
20182
+** May you find forgiveness for yourself and forgive others.
20183
+** May you share freely, never taking more than you give.
20184
+**
20185
+******************************************************************************
20186
+**
20187
+** This file contains inline asm code for retrieving "high-performance"
20188
+** counters for x86 and x86_64 class CPUs.
20189
+*/
20190
+#ifndef SQLITE_HWTIME_H
20191
+#define SQLITE_HWTIME_H
20192
+
20193
+/*
20194
+** The following routine only works on pentium-class (or newer) processors.
20195
+** It uses the RDTSC opcode to read the cycle count value out of the
20196
+** processor and returns that value. This can be used for high-res
20197
+** profiling.
20198
+*/
20199
+#if !defined(__STRICT_ANSI__) && \
20200
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
20201
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
20202
+
20203
+ #if defined(__GNUC__)
20204
+
20205
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
20206
+ unsigned int lo, hi;
20207
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
20208
+ return (sqlite_uint64)hi << 32 | lo;
20209
+ }
20210
+
20211
+ #elif defined(_MSC_VER)
20212
+
20213
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
20214
+ __asm {
20215
+ rdtsc
20216
+ ret ; return value at EDX:EAX
20217
+ }
20218
+ }
20219
+
20220
+ #endif
20221
+
20222
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
20223
+
20224
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
20225
+ unsigned long val;
20226
+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
20227
+ return val;
20228
+ }
20229
+
20230
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
20231
+
20232
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
20233
+ unsigned long long retval;
20234
+ unsigned long junk;
20235
+ __asm__ __volatile__ ("\n\
20236
+ 1: mftbu %1\n\
20237
+ mftb %L0\n\
20238
+ mftbu %0\n\
20239
+ cmpw %0,%1\n\
20240
+ bne 1b"
20241
+ : "=r" (retval), "=r" (junk));
20242
+ return retval;
20243
+ }
20244
+
20245
+#else
20246
+
20247
+ /*
20248
+ ** asm() is needed for hardware timing support. Without asm(),
20249
+ ** disable the sqlite3Hwtime() routine.
20250
+ **
20251
+ ** sqlite3Hwtime() is only used for some obscure debugging
20252
+ ** and analysis configurations, not in any deliverable, so this
20253
+ ** should not be a great loss.
20254
+ */
20255
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
20256
+
20257
+#endif
20258
+
20259
+#endif /* !defined(SQLITE_HWTIME_H) */
20260
+
20261
+/************** End of hwtime.h **********************************************/
20262
+/************** Continuing where we left off in os_common.h ******************/
20263
+
20264
+static sqlite_uint64 g_start;
20265
+static sqlite_uint64 g_elapsed;
20266
+#define TIMER_START g_start=sqlite3Hwtime()
20267
+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
20268
+#define TIMER_ELAPSED g_elapsed
20269
+#else
20270
+#define TIMER_START
20271
+#define TIMER_END
20272
+#define TIMER_ELAPSED ((sqlite_uint64)0)
20273
+#endif
20274
+
20275
+/*
20276
+** If we compile with the SQLITE_TEST macro set, then the following block
20277
+** of code will give us the ability to simulate a disk I/O error. This
20278
+** is used for testing the I/O recovery logic.
20279
+*/
20280
+#if defined(SQLITE_TEST)
20281
+SQLITE_API extern int sqlite3_io_error_hit;
20282
+SQLITE_API extern int sqlite3_io_error_hardhit;
20283
+SQLITE_API extern int sqlite3_io_error_pending;
20284
+SQLITE_API extern int sqlite3_io_error_persist;
20285
+SQLITE_API extern int sqlite3_io_error_benign;
20286
+SQLITE_API extern int sqlite3_diskfull_pending;
20287
+SQLITE_API extern int sqlite3_diskfull;
20288
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
20289
+#define SimulateIOError(CODE) \
20290
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
20291
+ || sqlite3_io_error_pending-- == 1 ) \
20292
+ { local_ioerr(); CODE; }
20293
+static void local_ioerr(){
20294
+ IOTRACE(("IOERR\n"));
20295
+ sqlite3_io_error_hit++;
20296
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
20297
+}
20298
+#define SimulateDiskfullError(CODE) \
20299
+ if( sqlite3_diskfull_pending ){ \
20300
+ if( sqlite3_diskfull_pending == 1 ){ \
20301
+ local_ioerr(); \
20302
+ sqlite3_diskfull = 1; \
20303
+ sqlite3_io_error_hit = 1; \
20304
+ CODE; \
20305
+ }else{ \
20306
+ sqlite3_diskfull_pending--; \
20307
+ } \
20308
+ }
20309
+#else
20310
+#define SimulateIOErrorBenign(X)
20311
+#define SimulateIOError(A)
20312
+#define SimulateDiskfullError(A)
20313
+#endif /* defined(SQLITE_TEST) */
20314
+
20315
+/*
20316
+** When testing, keep a count of the number of open files.
20317
+*/
20318
+#if defined(SQLITE_TEST)
20319
+SQLITE_API extern int sqlite3_open_file_count;
20320
+#define OpenCounter(X) sqlite3_open_file_count+=(X)
20321
+#else
20322
+#define OpenCounter(X)
20323
+#endif /* defined(SQLITE_TEST) */
20324
+
20325
+#endif /* !defined(_OS_COMMON_H_) */
20326
+
20327
+/************** End of os_common.h *******************************************/
20328
+/************** Begin file ctime.c *******************************************/
20329
+/*
20330
+** 2010 February 23
20331
+**
20332
+** The author disclaims copyright to this source code. In place of
20333
+** a legal notice, here is a blessing:
20334
+**
20335
+** May you do good and not evil.
20336
+** May you find forgiveness for yourself and forgive others.
20337
+** May you share freely, never taking more than you give.
20338
+**
20339
+*************************************************************************
20340
+**
20341
+** This file implements routines used to report what compile-time options
20342
+** SQLite was built with.
20343
+*/
20344
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
20345
+
20346
+/*
20347
+** Include the configuration header output by 'configure' if we're using the
20348
+** autoconf-based build
20349
+*/
20350
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
20351
+/* #include "config.h" */
20352
+#define SQLITECONFIG_H 1
20353
+#endif
20354
+
20355
+/* These macros are provided to "stringify" the value of the define
20356
+** for those options in which the value is meaningful. */
20357
+#define CTIMEOPT_VAL_(opt) #opt
20358
+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
20359
+
20360
+/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
20361
+** option requires a separate macro because legal values contain a single
20362
+** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
20363
+#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
20364
+#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
20365
+/* #include "sqliteInt.h" */
20366
+
20367
+/*
20368
+** An array of names of all compile-time options. This array should
20369
+** be sorted A-Z.
20370
+**
20371
+** This array looks large, but in a typical installation actually uses
20372
+** only a handful of compile-time options, so most times this array is usually
20373
+** rather short and uses little memory space.
20374
+*/
20375
+static const char * const sqlite3azCompileOpt[] = {
20376
+
20377
+/*
20378
+** BEGIN CODE GENERATED BY tool/mkctime.tcl
20379
+*/
20380
+#ifdef SQLITE_32BIT_ROWID
20381
+ "32BIT_ROWID",
20382
+#endif
20383
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
20384
+ "4_BYTE_ALIGNED_MALLOC",
20385
+#endif
20386
+#ifdef SQLITE_64BIT_STATS
20387
+ "64BIT_STATS",
20388
+#endif
20389
+#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
20390
+# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
20391
+ "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
20392
+# endif
20393
+#endif
20394
+#ifdef SQLITE_ALLOW_URI_AUTHORITY
20395
+ "ALLOW_URI_AUTHORITY",
20396
+#endif
20397
+#ifdef SQLITE_ATOMIC_INTRINSICS
20398
+ "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
20399
+#endif
20400
+#ifdef SQLITE_BITMASK_TYPE
20401
+ "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
20402
+#endif
20403
+#ifdef SQLITE_BUG_COMPATIBLE_20160819
20404
+ "BUG_COMPATIBLE_20160819",
20405
+#endif
20406
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
20407
+ "CASE_SENSITIVE_LIKE",
20408
+#endif
20409
+#ifdef SQLITE_CHECK_PAGES
20410
+ "CHECK_PAGES",
20411
+#endif
20412
+#if defined(__clang__) && defined(__clang_major__)
20413
+ "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
20414
+ CTIMEOPT_VAL(__clang_minor__) "."
20415
+ CTIMEOPT_VAL(__clang_patchlevel__),
20416
+#elif defined(_MSC_VER)
20417
+ "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
20418
+#elif defined(__GNUC__) && defined(__VERSION__)
20419
+ "COMPILER=gcc-" __VERSION__,
20420
+#endif
20421
+#ifdef SQLITE_COVERAGE_TEST
20422
+ "COVERAGE_TEST",
20423
+#endif
20424
+#ifdef SQLITE_DEBUG
20425
+ "DEBUG",
20426
+#endif
20427
+#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
20428
+ "DEFAULT_AUTOMATIC_INDEX",
20429
+#endif
20430
+#ifdef SQLITE_DEFAULT_AUTOVACUUM
20431
+ "DEFAULT_AUTOVACUUM",
20432
+#endif
20433
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
20434
+ "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
20435
+#endif
20436
+#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
20437
+ "DEFAULT_CKPTFULLFSYNC",
20438
+#endif
20439
+#ifdef SQLITE_DEFAULT_FILE_FORMAT
20440
+ "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
20441
+#endif
20442
+#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
20443
+ "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
20444
+#endif
20445
+#ifdef SQLITE_DEFAULT_FOREIGN_KEYS
20446
+ "DEFAULT_FOREIGN_KEYS",
20447
+#endif
20448
+#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
20449
+ "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
20450
+#endif
20451
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
20452
+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
20453
+#endif
20454
+#ifdef SQLITE_DEFAULT_LOOKASIDE
20455
+ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
20456
+#endif
20457
+#ifdef SQLITE_DEFAULT_MEMSTATUS
20458
+# if SQLITE_DEFAULT_MEMSTATUS != 1
20459
+ "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
20460
+# endif
20461
+#endif
20462
+#ifdef SQLITE_DEFAULT_MMAP_SIZE
20463
+ "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
20464
+#endif
20465
+#ifdef SQLITE_DEFAULT_PAGE_SIZE
20466
+ "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
20467
+#endif
20468
+#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
20469
+ "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
20470
+#endif
20471
+#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
20472
+ "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
20473
+#endif
20474
+#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
20475
+ "DEFAULT_RECURSIVE_TRIGGERS",
20476
+#endif
20477
+#ifdef SQLITE_DEFAULT_ROWEST
20478
+ "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
20479
+#endif
20480
+#ifdef SQLITE_DEFAULT_SECTOR_SIZE
20481
+ "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
20482
+#endif
20483
+#ifdef SQLITE_DEFAULT_SYNCHRONOUS
20484
+ "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
20485
+#endif
20486
+#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
20487
+ "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
20488
+#endif
20489
+#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
20490
+ "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
20491
+#endif
20492
+#ifdef SQLITE_DEFAULT_WORKER_THREADS
20493
+ "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
20494
+#endif
20495
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
20496
+ "DIRECT_OVERFLOW_READ",
20497
+#endif
20498
+#ifdef SQLITE_DISABLE_DIRSYNC
20499
+ "DISABLE_DIRSYNC",
20500
+#endif
20501
+#ifdef SQLITE_DISABLE_FTS3_UNICODE
20502
+ "DISABLE_FTS3_UNICODE",
20503
+#endif
20504
+#ifdef SQLITE_DISABLE_FTS4_DEFERRED
20505
+ "DISABLE_FTS4_DEFERRED",
20506
+#endif
20507
+#ifdef SQLITE_DISABLE_INTRINSIC
20508
+ "DISABLE_INTRINSIC",
20509
+#endif
20510
+#ifdef SQLITE_DISABLE_LFS
20511
+ "DISABLE_LFS",
20512
+#endif
20513
+#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
20514
+ "DISABLE_PAGECACHE_OVERFLOW_STATS",
20515
+#endif
20516
+#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
20517
+ "DISABLE_SKIPAHEAD_DISTINCT",
20518
+#endif
20519
+#ifdef SQLITE_ENABLE_8_3_NAMES
20520
+ "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
20521
+#endif
20522
+#ifdef SQLITE_ENABLE_API_ARMOR
20523
+ "ENABLE_API_ARMOR",
20524
+#endif
20525
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
20526
+ "ENABLE_ATOMIC_WRITE",
20527
+#endif
20528
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
20529
+ "ENABLE_BATCH_ATOMIC_WRITE",
20530
+#endif
20531
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
20532
+ "ENABLE_BYTECODE_VTAB",
20533
+#endif
20534
+#ifdef SQLITE_ENABLE_CEROD
20535
+ "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
20536
+#endif
20537
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
20538
+ "ENABLE_COLUMN_METADATA",
20539
+#endif
20540
+#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
20541
+ "ENABLE_COLUMN_USED_MASK",
20542
+#endif
20543
+#ifdef SQLITE_ENABLE_COSTMULT
20544
+ "ENABLE_COSTMULT",
20545
+#endif
20546
+#ifdef SQLITE_ENABLE_CURSOR_HINTS
20547
+ "ENABLE_CURSOR_HINTS",
20548
+#endif
20549
+#ifdef SQLITE_ENABLE_DBPAGE_VTAB
20550
+ "ENABLE_DBPAGE_VTAB",
20551
+#endif
20552
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB
20553
+ "ENABLE_DBSTAT_VTAB",
20554
+#endif
20555
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
20556
+ "ENABLE_EXPENSIVE_ASSERT",
20557
+#endif
20558
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
20559
+ "ENABLE_EXPLAIN_COMMENTS",
20560
+#endif
20561
+#ifdef SQLITE_ENABLE_FTS3
20562
+ "ENABLE_FTS3",
20563
+#endif
20564
+#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
20565
+ "ENABLE_FTS3_PARENTHESIS",
20566
+#endif
20567
+#ifdef SQLITE_ENABLE_FTS3_TOKENIZER
20568
+ "ENABLE_FTS3_TOKENIZER",
20569
+#endif
20570
+#ifdef SQLITE_ENABLE_FTS4
20571
+ "ENABLE_FTS4",
20572
+#endif
20573
+#ifdef SQLITE_ENABLE_FTS5
20574
+ "ENABLE_FTS5",
20575
+#endif
20576
+#ifdef SQLITE_ENABLE_GEOPOLY
20577
+ "ENABLE_GEOPOLY",
20578
+#endif
20579
+#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
20580
+ "ENABLE_HIDDEN_COLUMNS",
20581
+#endif
20582
+#ifdef SQLITE_ENABLE_ICU
20583
+ "ENABLE_ICU",
20584
+#endif
20585
+#ifdef SQLITE_ENABLE_IOTRACE
20586
+ "ENABLE_IOTRACE",
20587
+#endif
20588
+#ifdef SQLITE_ENABLE_JSON1
20589
+ "ENABLE_JSON1",
20590
+#endif
20591
+#ifdef SQLITE_ENABLE_LOAD_EXTENSION
20592
+ "ENABLE_LOAD_EXTENSION",
20593
+#endif
20594
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
20595
+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
20596
+#endif
20597
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
20598
+ "ENABLE_MATH_FUNCTIONS",
20599
+#endif
20600
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
20601
+ "ENABLE_MEMORY_MANAGEMENT",
20602
+#endif
20603
+#ifdef SQLITE_ENABLE_MEMSYS3
20604
+ "ENABLE_MEMSYS3",
20605
+#endif
20606
+#ifdef SQLITE_ENABLE_MEMSYS5
20607
+ "ENABLE_MEMSYS5",
20608
+#endif
20609
+#ifdef SQLITE_ENABLE_MULTIPLEX
20610
+ "ENABLE_MULTIPLEX",
20611
+#endif
20612
+#ifdef SQLITE_ENABLE_NORMALIZE
20613
+ "ENABLE_NORMALIZE",
20614
+#endif
20615
+#ifdef SQLITE_ENABLE_NULL_TRIM
20616
+ "ENABLE_NULL_TRIM",
20617
+#endif
20618
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
20619
+ "ENABLE_OFFSET_SQL_FUNC",
20620
+#endif
20621
+#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
20622
+ "ENABLE_OVERSIZE_CELL_CHECK",
20623
+#endif
20624
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
20625
+ "ENABLE_PREUPDATE_HOOK",
20626
+#endif
20627
+#ifdef SQLITE_ENABLE_QPSG
20628
+ "ENABLE_QPSG",
20629
+#endif
20630
+#ifdef SQLITE_ENABLE_RBU
20631
+ "ENABLE_RBU",
20632
+#endif
20633
+#ifdef SQLITE_ENABLE_RTREE
20634
+ "ENABLE_RTREE",
20635
+#endif
20636
+#ifdef SQLITE_ENABLE_SELECTTRACE
20637
+ "ENABLE_SELECTTRACE",
20638
+#endif
20639
+#ifdef SQLITE_ENABLE_SESSION
20640
+ "ENABLE_SESSION",
20641
+#endif
20642
+#ifdef SQLITE_ENABLE_SNAPSHOT
20643
+ "ENABLE_SNAPSHOT",
20644
+#endif
20645
+#ifdef SQLITE_ENABLE_SORTER_REFERENCES
20646
+ "ENABLE_SORTER_REFERENCES",
20647
+#endif
20648
+#ifdef SQLITE_ENABLE_SQLLOG
20649
+ "ENABLE_SQLLOG",
20650
+#endif
20651
+#ifdef SQLITE_ENABLE_STAT4
20652
+ "ENABLE_STAT4",
20653
+#endif
20654
+#ifdef SQLITE_ENABLE_STMTVTAB
20655
+ "ENABLE_STMTVTAB",
20656
+#endif
20657
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
20658
+ "ENABLE_STMT_SCANSTATUS",
20659
+#endif
20660
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
20661
+ "ENABLE_UNKNOWN_SQL_FUNCTION",
20662
+#endif
20663
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
20664
+ "ENABLE_UNLOCK_NOTIFY",
20665
+#endif
20666
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
20667
+ "ENABLE_UPDATE_DELETE_LIMIT",
20668
+#endif
20669
+#ifdef SQLITE_ENABLE_URI_00_ERROR
20670
+ "ENABLE_URI_00_ERROR",
20671
+#endif
20672
+#ifdef SQLITE_ENABLE_VFSTRACE
20673
+ "ENABLE_VFSTRACE",
20674
+#endif
20675
+#ifdef SQLITE_ENABLE_WHERETRACE
20676
+ "ENABLE_WHERETRACE",
20677
+#endif
20678
+#ifdef SQLITE_ENABLE_ZIPVFS
20679
+ "ENABLE_ZIPVFS",
20680
+#endif
20681
+#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
20682
+ "EXPLAIN_ESTIMATED_ROWS",
20683
+#endif
20684
+#ifdef SQLITE_EXTRA_IFNULLROW
20685
+ "EXTRA_IFNULLROW",
20686
+#endif
20687
+#ifdef SQLITE_EXTRA_INIT
20688
+ "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
20689
+#endif
20690
+#ifdef SQLITE_EXTRA_SHUTDOWN
20691
+ "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
20692
+#endif
20693
+#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
20694
+ "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
20695
+#endif
20696
+#ifdef SQLITE_FTS5_ENABLE_TEST_MI
20697
+ "FTS5_ENABLE_TEST_MI",
20698
+#endif
20699
+#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
20700
+ "FTS5_NO_WITHOUT_ROWID",
20701
+#endif
20702
+#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
20703
+ "HAVE_ISNAN",
20704
+#endif
20705
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
20706
+# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
20707
+ "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
20708
+# endif
20709
+#endif
20710
+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
20711
+ "IGNORE_AFP_LOCK_ERRORS",
20712
+#endif
20713
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
20714
+ "IGNORE_FLOCK_LOCK_ERRORS",
20715
+#endif
20716
+#ifdef SQLITE_INLINE_MEMCPY
20717
+ "INLINE_MEMCPY",
20718
+#endif
20719
+#ifdef SQLITE_INT64_TYPE
20720
+ "INT64_TYPE",
20721
+#endif
20722
+#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
20723
+ "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
20724
+#endif
20725
+#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
20726
+ "LIKE_DOESNT_MATCH_BLOBS",
20727
+#endif
20728
+#ifdef SQLITE_LOCK_TRACE
20729
+ "LOCK_TRACE",
20730
+#endif
20731
+#ifdef SQLITE_LOG_CACHE_SPILL
20732
+ "LOG_CACHE_SPILL",
20733
+#endif
20734
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
20735
+ "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
20736
+#endif
20737
+#ifdef SQLITE_MAX_ATTACHED
20738
+ "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
20739
+#endif
20740
+#ifdef SQLITE_MAX_COLUMN
20741
+ "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
20742
+#endif
20743
+#ifdef SQLITE_MAX_COMPOUND_SELECT
20744
+ "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
20745
+#endif
20746
+#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
20747
+ "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
20748
+#endif
20749
+#ifdef SQLITE_MAX_EXPR_DEPTH
20750
+ "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
20751
+#endif
20752
+#ifdef SQLITE_MAX_FUNCTION_ARG
20753
+ "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
20754
+#endif
20755
+#ifdef SQLITE_MAX_LENGTH
20756
+ "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
20757
+#endif
20758
+#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
20759
+ "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
20760
+#endif
20761
+#ifdef SQLITE_MAX_MEMORY
20762
+ "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
20763
+#endif
20764
+#ifdef SQLITE_MAX_MMAP_SIZE
20765
+ "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
20766
+#endif
20767
+#ifdef SQLITE_MAX_MMAP_SIZE_
20768
+ "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
20769
+#endif
20770
+#ifdef SQLITE_MAX_PAGE_COUNT
20771
+ "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
20772
+#endif
20773
+#ifdef SQLITE_MAX_PAGE_SIZE
20774
+ "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
20775
+#endif
20776
+#ifdef SQLITE_MAX_SCHEMA_RETRY
20777
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
20778
+#endif
20779
+#ifdef SQLITE_MAX_SQL_LENGTH
20780
+ "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
20781
+#endif
20782
+#ifdef SQLITE_MAX_TRIGGER_DEPTH
20783
+ "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
20784
+#endif
20785
+#ifdef SQLITE_MAX_VARIABLE_NUMBER
20786
+ "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
20787
+#endif
20788
+#ifdef SQLITE_MAX_VDBE_OP
20789
+ "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
20790
+#endif
20791
+#ifdef SQLITE_MAX_WORKER_THREADS
20792
+ "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
20793
+#endif
20794
+#ifdef SQLITE_MEMDEBUG
20795
+ "MEMDEBUG",
20796
+#endif
20797
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
20798
+ "MIXED_ENDIAN_64BIT_FLOAT",
20799
+#endif
20800
+#ifdef SQLITE_MMAP_READWRITE
20801
+ "MMAP_READWRITE",
20802
+#endif
20803
+#ifdef SQLITE_MUTEX_NOOP
20804
+ "MUTEX_NOOP",
20805
+#endif
20806
+#ifdef SQLITE_MUTEX_OMIT
20807
+ "MUTEX_OMIT",
20808
+#endif
20809
+#ifdef SQLITE_MUTEX_PTHREADS
20810
+ "MUTEX_PTHREADS",
20811
+#endif
20812
+#ifdef SQLITE_MUTEX_W32
20813
+ "MUTEX_W32",
20814
+#endif
20815
+#ifdef SQLITE_NEED_ERR_NAME
20816
+ "NEED_ERR_NAME",
20817
+#endif
20818
+#ifdef SQLITE_NO_SYNC
20819
+ "NO_SYNC",
20820
+#endif
20821
+#ifdef SQLITE_OMIT_ALTERTABLE
20822
+ "OMIT_ALTERTABLE",
20823
+#endif
20824
+#ifdef SQLITE_OMIT_ANALYZE
20825
+ "OMIT_ANALYZE",
20826
+#endif
20827
+#ifdef SQLITE_OMIT_ATTACH
20828
+ "OMIT_ATTACH",
20829
+#endif
20830
+#ifdef SQLITE_OMIT_AUTHORIZATION
20831
+ "OMIT_AUTHORIZATION",
20832
+#endif
20833
+#ifdef SQLITE_OMIT_AUTOINCREMENT
20834
+ "OMIT_AUTOINCREMENT",
20835
+#endif
20836
+#ifdef SQLITE_OMIT_AUTOINIT
20837
+ "OMIT_AUTOINIT",
20838
+#endif
20839
+#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
20840
+ "OMIT_AUTOMATIC_INDEX",
20841
+#endif
20842
+#ifdef SQLITE_OMIT_AUTORESET
20843
+ "OMIT_AUTORESET",
20844
+#endif
20845
+#ifdef SQLITE_OMIT_AUTOVACUUM
20846
+ "OMIT_AUTOVACUUM",
20847
+#endif
20848
+#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
20849
+ "OMIT_BETWEEN_OPTIMIZATION",
20850
+#endif
20851
+#ifdef SQLITE_OMIT_BLOB_LITERAL
20852
+ "OMIT_BLOB_LITERAL",
20853
+#endif
20854
+#ifdef SQLITE_OMIT_CAST
20855
+ "OMIT_CAST",
20856
+#endif
20857
+#ifdef SQLITE_OMIT_CHECK
20858
+ "OMIT_CHECK",
20859
+#endif
20860
+#ifdef SQLITE_OMIT_COMPLETE
20861
+ "OMIT_COMPLETE",
20862
+#endif
20863
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
20864
+ "OMIT_COMPOUND_SELECT",
20865
+#endif
20866
+#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
20867
+ "OMIT_CONFLICT_CLAUSE",
20868
+#endif
20869
+#ifdef SQLITE_OMIT_CTE
20870
+ "OMIT_CTE",
20871
+#endif
20872
+#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
20873
+ "OMIT_DATETIME_FUNCS",
20874
+#endif
20875
+#ifdef SQLITE_OMIT_DECLTYPE
20876
+ "OMIT_DECLTYPE",
20877
+#endif
20878
+#ifdef SQLITE_OMIT_DEPRECATED
20879
+ "OMIT_DEPRECATED",
20880
+#endif
20881
+#ifdef SQLITE_OMIT_DESERIALIZE
20882
+ "OMIT_DESERIALIZE",
20883
+#endif
20884
+#ifdef SQLITE_OMIT_DISKIO
20885
+ "OMIT_DISKIO",
20886
+#endif
20887
+#ifdef SQLITE_OMIT_EXPLAIN
20888
+ "OMIT_EXPLAIN",
20889
+#endif
20890
+#ifdef SQLITE_OMIT_FLAG_PRAGMAS
20891
+ "OMIT_FLAG_PRAGMAS",
20892
+#endif
20893
+#ifdef SQLITE_OMIT_FLOATING_POINT
20894
+ "OMIT_FLOATING_POINT",
20895
+#endif
20896
+#ifdef SQLITE_OMIT_FOREIGN_KEY
20897
+ "OMIT_FOREIGN_KEY",
20898
+#endif
20899
+#ifdef SQLITE_OMIT_GET_TABLE
20900
+ "OMIT_GET_TABLE",
20901
+#endif
20902
+#ifdef SQLITE_OMIT_HEX_INTEGER
20903
+ "OMIT_HEX_INTEGER",
20904
+#endif
20905
+#ifdef SQLITE_OMIT_INCRBLOB
20906
+ "OMIT_INCRBLOB",
20907
+#endif
20908
+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
20909
+ "OMIT_INTEGRITY_CHECK",
20910
+#endif
20911
+#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
20912
+ "OMIT_INTROSPECTION_PRAGMAS",
20913
+#endif
20914
+#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
20915
+ "OMIT_LIKE_OPTIMIZATION",
20916
+#endif
20917
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
20918
+ "OMIT_LOAD_EXTENSION",
20919
+#endif
20920
+#ifdef SQLITE_OMIT_LOCALTIME
20921
+ "OMIT_LOCALTIME",
20922
+#endif
20923
+#ifdef SQLITE_OMIT_LOOKASIDE
20924
+ "OMIT_LOOKASIDE",
20925
+#endif
20926
+#ifdef SQLITE_OMIT_MEMORYDB
20927
+ "OMIT_MEMORYDB",
20928
+#endif
20929
+#ifdef SQLITE_OMIT_OR_OPTIMIZATION
20930
+ "OMIT_OR_OPTIMIZATION",
20931
+#endif
20932
+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
20933
+ "OMIT_PAGER_PRAGMAS",
20934
+#endif
20935
+#ifdef SQLITE_OMIT_PARSER_TRACE
20936
+ "OMIT_PARSER_TRACE",
20937
+#endif
20938
+#ifdef SQLITE_OMIT_POPEN
20939
+ "OMIT_POPEN",
20940
+#endif
20941
+#ifdef SQLITE_OMIT_PRAGMA
20942
+ "OMIT_PRAGMA",
20943
+#endif
20944
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
20945
+ "OMIT_PROGRESS_CALLBACK",
20946
+#endif
20947
+#ifdef SQLITE_OMIT_QUICKBALANCE
20948
+ "OMIT_QUICKBALANCE",
20949
+#endif
20950
+#ifdef SQLITE_OMIT_REINDEX
20951
+ "OMIT_REINDEX",
20952
+#endif
20953
+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
20954
+ "OMIT_SCHEMA_PRAGMAS",
20955
+#endif
20956
+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
20957
+ "OMIT_SCHEMA_VERSION_PRAGMAS",
20958
+#endif
20959
+#ifdef SQLITE_OMIT_SHARED_CACHE
20960
+ "OMIT_SHARED_CACHE",
20961
+#endif
20962
+#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
20963
+ "OMIT_SHUTDOWN_DIRECTORIES",
20964
+#endif
20965
+#ifdef SQLITE_OMIT_SUBQUERY
20966
+ "OMIT_SUBQUERY",
20967
+#endif
20968
+#ifdef SQLITE_OMIT_TCL_VARIABLE
20969
+ "OMIT_TCL_VARIABLE",
20970
+#endif
20971
+#ifdef SQLITE_OMIT_TEMPDB
20972
+ "OMIT_TEMPDB",
20973
+#endif
20974
+#ifdef SQLITE_OMIT_TEST_CONTROL
20975
+ "OMIT_TEST_CONTROL",
20976
+#endif
20977
+#ifdef SQLITE_OMIT_TRACE
20978
+# if SQLITE_OMIT_TRACE != 1
20979
+ "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
20980
+# endif
20981
+#endif
20982
+#ifdef SQLITE_OMIT_TRIGGER
20983
+ "OMIT_TRIGGER",
20984
+#endif
20985
+#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
20986
+ "OMIT_TRUNCATE_OPTIMIZATION",
20987
+#endif
20988
+#ifdef SQLITE_OMIT_UTF16
20989
+ "OMIT_UTF16",
20990
+#endif
20991
+#ifdef SQLITE_OMIT_VACUUM
20992
+ "OMIT_VACUUM",
20993
+#endif
20994
+#ifdef SQLITE_OMIT_VIEW
20995
+ "OMIT_VIEW",
20996
+#endif
20997
+#ifdef SQLITE_OMIT_VIRTUALTABLE
20998
+ "OMIT_VIRTUALTABLE",
20999
+#endif
21000
+#ifdef SQLITE_OMIT_WAL
21001
+ "OMIT_WAL",
21002
+#endif
21003
+#ifdef SQLITE_OMIT_WSD
21004
+ "OMIT_WSD",
21005
+#endif
21006
+#ifdef SQLITE_OMIT_XFER_OPT
21007
+ "OMIT_XFER_OPT",
21008
+#endif
21009
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
21010
+ "PCACHE_SEPARATE_HEADER",
21011
+#endif
21012
+#ifdef SQLITE_PERFORMANCE_TRACE
21013
+ "PERFORMANCE_TRACE",
21014
+#endif
21015
+#ifdef SQLITE_POWERSAFE_OVERWRITE
21016
+# if SQLITE_POWERSAFE_OVERWRITE != 1
21017
+ "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
21018
+# endif
21019
+#endif
21020
+#ifdef SQLITE_PREFER_PROXY_LOCKING
21021
+ "PREFER_PROXY_LOCKING",
21022
+#endif
21023
+#ifdef SQLITE_PROXY_DEBUG
21024
+ "PROXY_DEBUG",
21025
+#endif
21026
+#ifdef SQLITE_REVERSE_UNORDERED_SELECTS
21027
+ "REVERSE_UNORDERED_SELECTS",
21028
+#endif
21029
+#ifdef SQLITE_RTREE_INT_ONLY
21030
+ "RTREE_INT_ONLY",
21031
+#endif
21032
+#ifdef SQLITE_SECURE_DELETE
21033
+ "SECURE_DELETE",
21034
+#endif
21035
+#ifdef SQLITE_SMALL_STACK
21036
+ "SMALL_STACK",
21037
+#endif
21038
+#ifdef SQLITE_SORTER_PMASZ
21039
+ "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
21040
+#endif
21041
+#ifdef SQLITE_SOUNDEX
21042
+ "SOUNDEX",
21043
+#endif
21044
+#ifdef SQLITE_STAT4_SAMPLES
21045
+ "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
21046
+#endif
21047
+#ifdef SQLITE_STMTJRNL_SPILL
21048
+ "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
21049
+#endif
21050
+#ifdef SQLITE_SUBSTR_COMPATIBILITY
21051
+ "SUBSTR_COMPATIBILITY",
21052
+#endif
21053
+#if (!defined(SQLITE_WIN32_MALLOC) \
21054
+ && !defined(SQLITE_ZERO_MALLOC) \
21055
+ && !defined(SQLITE_MEMDEBUG) \
21056
+ ) || defined(SQLITE_SYSTEM_MALLOC)
21057
+ "SYSTEM_MALLOC",
21058
+#endif
21059
+#ifdef SQLITE_TCL
21060
+ "TCL",
21061
+#endif
21062
+#ifdef SQLITE_TEMP_STORE
21063
+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
21064
+#endif
21065
+#ifdef SQLITE_TEST
21066
+ "TEST",
21067
+#endif
21068
+#if defined(SQLITE_THREADSAFE)
21069
+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
21070
+#elif defined(THREADSAFE)
21071
+ "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
21072
+#else
21073
+ "THREADSAFE=1",
21074
+#endif
21075
+#ifdef SQLITE_UNLINK_AFTER_CLOSE
21076
+ "UNLINK_AFTER_CLOSE",
21077
+#endif
21078
+#ifdef SQLITE_UNTESTABLE
21079
+ "UNTESTABLE",
21080
+#endif
21081
+#ifdef SQLITE_USER_AUTHENTICATION
21082
+ "USER_AUTHENTICATION",
21083
+#endif
21084
+#ifdef SQLITE_USE_ALLOCA
21085
+ "USE_ALLOCA",
21086
+#endif
21087
+#ifdef SQLITE_USE_FCNTL_TRACE
21088
+ "USE_FCNTL_TRACE",
21089
+#endif
21090
+#ifdef SQLITE_USE_URI
21091
+ "USE_URI",
21092
+#endif
21093
+#ifdef SQLITE_VDBE_COVERAGE
21094
+ "VDBE_COVERAGE",
21095
+#endif
21096
+#ifdef SQLITE_WIN32_MALLOC
21097
+ "WIN32_MALLOC",
21098
+#endif
21099
+#ifdef SQLITE_ZERO_MALLOC
21100
+ "ZERO_MALLOC",
21101
+#endif
21102
+/*
21103
+** END CODE GENERATED BY tool/mkctime.tcl
21104
+*/
21105
+};
21106
+
21107
+SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
21108
+ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
21109
+ return (const char**)sqlite3azCompileOpt;
21110
+}
21111
+
21112
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
21113
+
21114
+/************** End of ctime.c ***********************************************/
2079421115
/************** Begin file global.c ******************************************/
2079521116
/*
2079621117
** 2008 June 13
2079721118
**
2079821119
** The author disclaims copyright to this source code. In place of
@@ -21139,10 +21460,30 @@
2113921460
2114021461
/*
2114121462
** Name of the default collating sequence
2114221463
*/
2114321464
SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
21465
+
21466
+/*
21467
+** Standard typenames. These names must match the COLTYPE_* definitions.
21468
+** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
21469
+*/
21470
+SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 4, 3, 7, 4, 4 };
21471
+SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = {
21472
+ SQLITE_AFF_BLOB,
21473
+ SQLITE_AFF_INTEGER,
21474
+ SQLITE_AFF_INTEGER,
21475
+ SQLITE_AFF_REAL,
21476
+ SQLITE_AFF_TEXT
21477
+};
21478
+SQLITE_PRIVATE const char *sqlite3StdType[] = {
21479
+ "BLOB",
21480
+ "INT",
21481
+ "INTEGER",
21482
+ "REAL",
21483
+ "TEXT"
21484
+};
2114421485
2114521486
/************** End of global.c **********************************************/
2114621487
/************** Begin file status.c ******************************************/
2114721488
/*
2114821489
** 2008 June 18
@@ -21342,12 +21683,12 @@
2134221683
int pc; /* Program Counter in parent (calling) frame */
2134321684
int nOp; /* Size of aOp array */
2134421685
int nMem; /* Number of entries in aMem */
2134521686
int nChildMem; /* Number of memory cells for child frame */
2134621687
int nChildCsr; /* Number of cursors for child frame */
21347
- int nChange; /* Statement changes (Vdbe.nChange) */
21348
- int nDbChange; /* Value of db->nChange */
21688
+ i64 nChange; /* Statement changes (Vdbe.nChange) */
21689
+ i64 nDbChange; /* Value of db->nChange */
2134921690
};
2135021691
2135121692
/* Magic number for sanity checking on VdbeFrame objects */
2135221693
#define SQLITE_FRAME_MAGIC 0x879fb71e
2135321694
@@ -21550,11 +21891,11 @@
2155021891
int nMem; /* Number of memory locations currently allocated */
2155121892
int nCursor; /* Number of slots in apCsr[] */
2155221893
u32 cacheCtr; /* VdbeCursor row cache generation counter */
2155321894
int pc; /* The program counter */
2155421895
int rc; /* Value to return */
21555
- int nChange; /* Number of db changes made since last reset */
21896
+ i64 nChange; /* Number of db changes made since last reset */
2155621897
int iStatement; /* Statement number (or 0 if has no opened stmt) */
2155721898
i64 iCurrentTime; /* Value of julianday('now') for this statement */
2155821899
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
2155921900
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
2156021901
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
@@ -21695,10 +22036,11 @@
2169522036
SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
2169622037
#endif
2169722038
SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
2169822039
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
2169922040
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
22041
+SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
2170022042
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
2170122043
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
2170222044
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
2170322045
SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
2170422046
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
@@ -27108,209 +27450,11 @@
2710827450
2710927451
#if SQLITE_OS_WIN
2711027452
/*
2711127453
** Include code that is common to all os_*.c files
2711227454
*/
27113
-/************** Include os_common.h in the middle of mutex_w32.c *************/
27114
-/************** Begin file os_common.h ***************************************/
27115
-/*
27116
-** 2004 May 22
27117
-**
27118
-** The author disclaims copyright to this source code. In place of
27119
-** a legal notice, here is a blessing:
27120
-**
27121
-** May you do good and not evil.
27122
-** May you find forgiveness for yourself and forgive others.
27123
-** May you share freely, never taking more than you give.
27124
-**
27125
-******************************************************************************
27126
-**
27127
-** This file contains macros and a little bit of code that is common to
27128
-** all of the platform-specific files (os_*.c) and is #included into those
27129
-** files.
27130
-**
27131
-** This file should be #included by the os_*.c files only. It is not a
27132
-** general purpose header file.
27133
-*/
27134
-#ifndef _OS_COMMON_H_
27135
-#define _OS_COMMON_H_
27136
-
27137
-/*
27138
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
27139
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
27140
-** switch. The following code should catch this problem at compile-time.
27141
-*/
27142
-#ifdef MEMORY_DEBUG
27143
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
27144
-#endif
27145
-
27146
-/*
27147
-** Macros for performance tracing. Normally turned off. Only works
27148
-** on i486 hardware.
27149
-*/
27150
-#ifdef SQLITE_PERFORMANCE_TRACE
27151
-
27152
-/*
27153
-** hwtime.h contains inline assembler code for implementing
27154
-** high-performance timing routines.
27155
-*/
27156
-/************** Include hwtime.h in the middle of os_common.h ****************/
27157
-/************** Begin file hwtime.h ******************************************/
27158
-/*
27159
-** 2008 May 27
27160
-**
27161
-** The author disclaims copyright to this source code. In place of
27162
-** a legal notice, here is a blessing:
27163
-**
27164
-** May you do good and not evil.
27165
-** May you find forgiveness for yourself and forgive others.
27166
-** May you share freely, never taking more than you give.
27167
-**
27168
-******************************************************************************
27169
-**
27170
-** This file contains inline asm code for retrieving "high-performance"
27171
-** counters for x86 and x86_64 class CPUs.
27172
-*/
27173
-#ifndef SQLITE_HWTIME_H
27174
-#define SQLITE_HWTIME_H
27175
-
27176
-/*
27177
-** The following routine only works on pentium-class (or newer) processors.
27178
-** It uses the RDTSC opcode to read the cycle count value out of the
27179
-** processor and returns that value. This can be used for high-res
27180
-** profiling.
27181
-*/
27182
-#if !defined(__STRICT_ANSI__) && \
27183
- (defined(__GNUC__) || defined(_MSC_VER)) && \
27184
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
27185
-
27186
- #if defined(__GNUC__)
27187
-
27188
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
27189
- unsigned int lo, hi;
27190
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
27191
- return (sqlite_uint64)hi << 32 | lo;
27192
- }
27193
-
27194
- #elif defined(_MSC_VER)
27195
-
27196
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
27197
- __asm {
27198
- rdtsc
27199
- ret ; return value at EDX:EAX
27200
- }
27201
- }
27202
-
27203
- #endif
27204
-
27205
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
27206
-
27207
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
27208
- unsigned long val;
27209
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
27210
- return val;
27211
- }
27212
-
27213
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
27214
-
27215
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
27216
- unsigned long long retval;
27217
- unsigned long junk;
27218
- __asm__ __volatile__ ("\n\
27219
- 1: mftbu %1\n\
27220
- mftb %L0\n\
27221
- mftbu %0\n\
27222
- cmpw %0,%1\n\
27223
- bne 1b"
27224
- : "=r" (retval), "=r" (junk));
27225
- return retval;
27226
- }
27227
-
27228
-#else
27229
-
27230
- /*
27231
- ** asm() is needed for hardware timing support. Without asm(),
27232
- ** disable the sqlite3Hwtime() routine.
27233
- **
27234
- ** sqlite3Hwtime() is only used for some obscure debugging
27235
- ** and analysis configurations, not in any deliverable, so this
27236
- ** should not be a great loss.
27237
- */
27238
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
27239
-
27240
-#endif
27241
-
27242
-#endif /* !defined(SQLITE_HWTIME_H) */
27243
-
27244
-/************** End of hwtime.h **********************************************/
27245
-/************** Continuing where we left off in os_common.h ******************/
27246
-
27247
-static sqlite_uint64 g_start;
27248
-static sqlite_uint64 g_elapsed;
27249
-#define TIMER_START g_start=sqlite3Hwtime()
27250
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
27251
-#define TIMER_ELAPSED g_elapsed
27252
-#else
27253
-#define TIMER_START
27254
-#define TIMER_END
27255
-#define TIMER_ELAPSED ((sqlite_uint64)0)
27256
-#endif
27257
-
27258
-/*
27259
-** If we compile with the SQLITE_TEST macro set, then the following block
27260
-** of code will give us the ability to simulate a disk I/O error. This
27261
-** is used for testing the I/O recovery logic.
27262
-*/
27263
-#if defined(SQLITE_TEST)
27264
-SQLITE_API extern int sqlite3_io_error_hit;
27265
-SQLITE_API extern int sqlite3_io_error_hardhit;
27266
-SQLITE_API extern int sqlite3_io_error_pending;
27267
-SQLITE_API extern int sqlite3_io_error_persist;
27268
-SQLITE_API extern int sqlite3_io_error_benign;
27269
-SQLITE_API extern int sqlite3_diskfull_pending;
27270
-SQLITE_API extern int sqlite3_diskfull;
27271
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
27272
-#define SimulateIOError(CODE) \
27273
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
27274
- || sqlite3_io_error_pending-- == 1 ) \
27275
- { local_ioerr(); CODE; }
27276
-static void local_ioerr(){
27277
- IOTRACE(("IOERR\n"));
27278
- sqlite3_io_error_hit++;
27279
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
27280
-}
27281
-#define SimulateDiskfullError(CODE) \
27282
- if( sqlite3_diskfull_pending ){ \
27283
- if( sqlite3_diskfull_pending == 1 ){ \
27284
- local_ioerr(); \
27285
- sqlite3_diskfull = 1; \
27286
- sqlite3_io_error_hit = 1; \
27287
- CODE; \
27288
- }else{ \
27289
- sqlite3_diskfull_pending--; \
27290
- } \
27291
- }
27292
-#else
27293
-#define SimulateIOErrorBenign(X)
27294
-#define SimulateIOError(A)
27295
-#define SimulateDiskfullError(A)
27296
-#endif /* defined(SQLITE_TEST) */
27297
-
27298
-/*
27299
-** When testing, keep a count of the number of open files.
27300
-*/
27301
-#if defined(SQLITE_TEST)
27302
-SQLITE_API extern int sqlite3_open_file_count;
27303
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
27304
-#else
27305
-#define OpenCounter(X)
27306
-#endif /* defined(SQLITE_TEST) */
27307
-
27308
-#endif /* !defined(_OS_COMMON_H_) */
27309
-
27310
-/************** End of os_common.h *******************************************/
27311
-/************** Continuing where we left off in mutex_w32.c ******************/
27455
+/* #include "os_common.h" */
2731227456
2731327457
/*
2731427458
** Include the header file for the Windows VFS.
2731527459
*/
2731627460
/************** Include os_win.h in the middle of mutex_w32.c ****************/
@@ -30077,10 +30221,12 @@
3007730221
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
3007830222
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
3007930223
}
3008030224
if( pItem->fg.jointype & JT_LEFT ){
3008130225
sqlite3_str_appendf(&x, " LEFT-JOIN");
30226
+ }else if( pItem->fg.jointype & JT_CROSS ){
30227
+ sqlite3_str_appendf(&x, " CROSS-JOIN");
3008230228
}
3008330229
if( pItem->fg.fromDDL ){
3008430230
sqlite3_str_appendf(&x, " DDL");
3008530231
}
3008630232
if( pItem->fg.isCte ){
@@ -30407,12 +30553,12 @@
3040730553
case TK_NULL: {
3040830554
sqlite3TreeViewLine(pView,"NULL");
3040930555
break;
3041030556
}
3041130557
case TK_TRUEFALSE: {
30412
- sqlite3TreeViewLine(pView,
30413
- sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
30558
+ sqlite3TreeViewLine(pView,"%s%s",
30559
+ sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
3041430560
break;
3041530561
}
3041630562
#ifndef SQLITE_OMIT_BLOB_LITERAL
3041730563
case TK_BLOB: {
3041830564
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
@@ -30632,11 +30778,13 @@
3063230778
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
3063330779
sqlite3_free(z);
3063430780
break;
3063530781
}
3063630782
case TK_SELECT_COLUMN: {
30637
- sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
30783
+ sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
30784
+ pExpr->iColumn, pExpr->iTable-1,
30785
+ pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
3063830786
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
3063930787
break;
3064030788
}
3064130789
case TK_IF_NULL_ROW: {
3064230790
sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
@@ -30648,10 +30796,19 @@
3064830796
sqlite3TreeViewLine(pView, "ERROR");
3064930797
tmp = *pExpr;
3065030798
tmp.op = pExpr->op2;
3065130799
sqlite3TreeViewExpr(pView, &tmp, 0);
3065230800
break;
30801
+ }
30802
+ case TK_ROW: {
30803
+ if( pExpr->iColumn<=0 ){
30804
+ sqlite3TreeViewLine(pView, "First FROM table rowid");
30805
+ }else{
30806
+ sqlite3TreeViewLine(pView, "First FROM table column %d",
30807
+ pExpr->iColumn-1);
30808
+ }
30809
+ break;
3065330810
}
3065430811
default: {
3065530812
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
3065630813
break;
3065730814
}
@@ -30798,15 +30955,20 @@
3079830955
** Nothing in this file or anywhere else in SQLite does any kind of
3079930956
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
3080030957
** number generator) not as an encryption device.
3080130958
*/
3080230959
if( !wsdPrng.isInit ){
30960
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
3080330961
int i;
3080430962
char k[256];
3080530963
wsdPrng.j = 0;
3080630964
wsdPrng.i = 0;
30807
- sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
30965
+ if( NEVER(pVfs==0) ){
30966
+ memset(k, 0, sizeof(k));
30967
+ }else{
30968
+ sqlite3OsRandomness(pVfs, 256, k);
30969
+ }
3080830970
for(i=0; i<256; i++){
3080930971
wsdPrng.s[i] = (u8)i;
3081030972
}
3081130973
for(i=0; i<256; i++){
3081230974
wsdPrng.j += wsdPrng.s[i] + k[i];
@@ -31763,12 +31925,18 @@
3176331925
**
3176431926
** The column type is an extra string stored after the zero-terminator on
3176531927
** the column name if and only if the COLFLAG_HASTYPE flag is set.
3176631928
*/
3176731929
SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){
31768
- if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt;
31769
- return pCol->zName + strlen(pCol->zName) + 1;
31930
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
31931
+ return pCol->zCnName + strlen(pCol->zCnName) + 1;
31932
+ }else if( pCol->eType ){
31933
+ assert( pCol->eType<=SQLITE_N_STDTYPE );
31934
+ return (char*)sqlite3StdType[pCol->eType-1];
31935
+ }else{
31936
+ return zDflt;
31937
+ }
3177031938
}
3177131939
3177231940
/*
3177331941
** Helper function for sqlite3Error() - called rarely. Broken out into
3177431942
** a separate routine to avoid unnecessary register saves on entry to
@@ -31939,10 +32107,32 @@
3193932107
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
3194032108
assert( sqlite3Isquote(p->u.zToken[0]) );
3194132109
p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
3194232110
sqlite3Dequote(p->u.zToken);
3194332111
}
32112
+
32113
+/*
32114
+** If the input token p is quoted, try to adjust the token to remove
32115
+** the quotes. This is not always possible:
32116
+**
32117
+** "abc" -> abc
32118
+** "ab""cd" -> (not possible because of the interior "")
32119
+**
32120
+** Remove the quotes if possible. This is a optimization. The overall
32121
+** system should still return the correct answer even if this routine
32122
+** is always a no-op.
32123
+*/
32124
+SQLITE_PRIVATE void sqlite3DequoteToken(Token *p){
32125
+ unsigned int i;
32126
+ if( p->n<2 ) return;
32127
+ if( !sqlite3Isquote(p->z[0]) ) return;
32128
+ for(i=1; i<p->n-1; i++){
32129
+ if( sqlite3Isquote(p->z[i]) ) return;
32130
+ }
32131
+ p->n -= 2;
32132
+ p->z++;
32133
+}
3194432134
3194532135
/*
3194632136
** Generate a Token object from a string
3194732137
*/
3194832138
SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){
@@ -34150,209 +34340,11 @@
3415034340
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
3415134341
3415234342
/*
3415334343
** Include code that is common to all os_*.c files
3415434344
*/
34155
-/************** Include os_common.h in the middle of os_unix.c ***************/
34156
-/************** Begin file os_common.h ***************************************/
34157
-/*
34158
-** 2004 May 22
34159
-**
34160
-** The author disclaims copyright to this source code. In place of
34161
-** a legal notice, here is a blessing:
34162
-**
34163
-** May you do good and not evil.
34164
-** May you find forgiveness for yourself and forgive others.
34165
-** May you share freely, never taking more than you give.
34166
-**
34167
-******************************************************************************
34168
-**
34169
-** This file contains macros and a little bit of code that is common to
34170
-** all of the platform-specific files (os_*.c) and is #included into those
34171
-** files.
34172
-**
34173
-** This file should be #included by the os_*.c files only. It is not a
34174
-** general purpose header file.
34175
-*/
34176
-#ifndef _OS_COMMON_H_
34177
-#define _OS_COMMON_H_
34178
-
34179
-/*
34180
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
34181
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
34182
-** switch. The following code should catch this problem at compile-time.
34183
-*/
34184
-#ifdef MEMORY_DEBUG
34185
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
34186
-#endif
34187
-
34188
-/*
34189
-** Macros for performance tracing. Normally turned off. Only works
34190
-** on i486 hardware.
34191
-*/
34192
-#ifdef SQLITE_PERFORMANCE_TRACE
34193
-
34194
-/*
34195
-** hwtime.h contains inline assembler code for implementing
34196
-** high-performance timing routines.
34197
-*/
34198
-/************** Include hwtime.h in the middle of os_common.h ****************/
34199
-/************** Begin file hwtime.h ******************************************/
34200
-/*
34201
-** 2008 May 27
34202
-**
34203
-** The author disclaims copyright to this source code. In place of
34204
-** a legal notice, here is a blessing:
34205
-**
34206
-** May you do good and not evil.
34207
-** May you find forgiveness for yourself and forgive others.
34208
-** May you share freely, never taking more than you give.
34209
-**
34210
-******************************************************************************
34211
-**
34212
-** This file contains inline asm code for retrieving "high-performance"
34213
-** counters for x86 and x86_64 class CPUs.
34214
-*/
34215
-#ifndef SQLITE_HWTIME_H
34216
-#define SQLITE_HWTIME_H
34217
-
34218
-/*
34219
-** The following routine only works on pentium-class (or newer) processors.
34220
-** It uses the RDTSC opcode to read the cycle count value out of the
34221
-** processor and returns that value. This can be used for high-res
34222
-** profiling.
34223
-*/
34224
-#if !defined(__STRICT_ANSI__) && \
34225
- (defined(__GNUC__) || defined(_MSC_VER)) && \
34226
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
34227
-
34228
- #if defined(__GNUC__)
34229
-
34230
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
34231
- unsigned int lo, hi;
34232
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
34233
- return (sqlite_uint64)hi << 32 | lo;
34234
- }
34235
-
34236
- #elif defined(_MSC_VER)
34237
-
34238
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
34239
- __asm {
34240
- rdtsc
34241
- ret ; return value at EDX:EAX
34242
- }
34243
- }
34244
-
34245
- #endif
34246
-
34247
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
34248
-
34249
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
34250
- unsigned long val;
34251
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
34252
- return val;
34253
- }
34254
-
34255
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
34256
-
34257
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
34258
- unsigned long long retval;
34259
- unsigned long junk;
34260
- __asm__ __volatile__ ("\n\
34261
- 1: mftbu %1\n\
34262
- mftb %L0\n\
34263
- mftbu %0\n\
34264
- cmpw %0,%1\n\
34265
- bne 1b"
34266
- : "=r" (retval), "=r" (junk));
34267
- return retval;
34268
- }
34269
-
34270
-#else
34271
-
34272
- /*
34273
- ** asm() is needed for hardware timing support. Without asm(),
34274
- ** disable the sqlite3Hwtime() routine.
34275
- **
34276
- ** sqlite3Hwtime() is only used for some obscure debugging
34277
- ** and analysis configurations, not in any deliverable, so this
34278
- ** should not be a great loss.
34279
- */
34280
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
34281
-
34282
-#endif
34283
-
34284
-#endif /* !defined(SQLITE_HWTIME_H) */
34285
-
34286
-/************** End of hwtime.h **********************************************/
34287
-/************** Continuing where we left off in os_common.h ******************/
34288
-
34289
-static sqlite_uint64 g_start;
34290
-static sqlite_uint64 g_elapsed;
34291
-#define TIMER_START g_start=sqlite3Hwtime()
34292
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
34293
-#define TIMER_ELAPSED g_elapsed
34294
-#else
34295
-#define TIMER_START
34296
-#define TIMER_END
34297
-#define TIMER_ELAPSED ((sqlite_uint64)0)
34298
-#endif
34299
-
34300
-/*
34301
-** If we compile with the SQLITE_TEST macro set, then the following block
34302
-** of code will give us the ability to simulate a disk I/O error. This
34303
-** is used for testing the I/O recovery logic.
34304
-*/
34305
-#if defined(SQLITE_TEST)
34306
-SQLITE_API extern int sqlite3_io_error_hit;
34307
-SQLITE_API extern int sqlite3_io_error_hardhit;
34308
-SQLITE_API extern int sqlite3_io_error_pending;
34309
-SQLITE_API extern int sqlite3_io_error_persist;
34310
-SQLITE_API extern int sqlite3_io_error_benign;
34311
-SQLITE_API extern int sqlite3_diskfull_pending;
34312
-SQLITE_API extern int sqlite3_diskfull;
34313
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
34314
-#define SimulateIOError(CODE) \
34315
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
34316
- || sqlite3_io_error_pending-- == 1 ) \
34317
- { local_ioerr(); CODE; }
34318
-static void local_ioerr(){
34319
- IOTRACE(("IOERR\n"));
34320
- sqlite3_io_error_hit++;
34321
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
34322
-}
34323
-#define SimulateDiskfullError(CODE) \
34324
- if( sqlite3_diskfull_pending ){ \
34325
- if( sqlite3_diskfull_pending == 1 ){ \
34326
- local_ioerr(); \
34327
- sqlite3_diskfull = 1; \
34328
- sqlite3_io_error_hit = 1; \
34329
- CODE; \
34330
- }else{ \
34331
- sqlite3_diskfull_pending--; \
34332
- } \
34333
- }
34334
-#else
34335
-#define SimulateIOErrorBenign(X)
34336
-#define SimulateIOError(A)
34337
-#define SimulateDiskfullError(A)
34338
-#endif /* defined(SQLITE_TEST) */
34339
-
34340
-/*
34341
-** When testing, keep a count of the number of open files.
34342
-*/
34343
-#if defined(SQLITE_TEST)
34344
-SQLITE_API extern int sqlite3_open_file_count;
34345
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
34346
-#else
34347
-#define OpenCounter(X)
34348
-#endif /* defined(SQLITE_TEST) */
34349
-
34350
-#endif /* !defined(_OS_COMMON_H_) */
34351
-
34352
-/************** End of os_common.h *******************************************/
34353
-/************** Continuing where we left off in os_unix.c ********************/
34345
+/* #include "os_common.h" */
3435434346
3435534347
/*
3435634348
** Define various macros that are missing from some systems.
3435734349
*/
3435834350
#ifndef O_LARGEFILE
@@ -40236,10 +40228,12 @@
4023640228
if( fd<0 ){
4023740229
if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
4023840230
/* If unable to create a journal because the directory is not
4023940231
** writable, change the error code to indicate that. */
4024040232
rc = SQLITE_READONLY_DIRECTORY;
40233
+ }else if( errno==EEXIST ){
40234
+ rc = SQLITE_CANTOPEN_EXISTS;
4024140235
}else if( errno!=EISDIR && isReadWrite ){
4024240236
/* Failed to open the file for read/write access. Try read-only. */
4024340237
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
4024440238
openFlags &= ~(O_RDWR|O_CREAT);
4024540239
flags |= SQLITE_OPEN_READONLY;
@@ -42119,10 +42113,11 @@
4211942113
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
4212042114
sqlite3_vfs_register(&aVfs[i], i==0);
4212142115
}
4212242116
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
4212342117
42118
+#ifndef SQLITE_OMIT_WAL
4212442119
/* Validate lock assumptions */
4212542120
assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
4212642121
assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
4212742122
/* Locks:
4212842123
** WRITE UNIX_SHM_BASE 120
@@ -42134,10 +42129,12 @@
4213442129
** READ-3 UNIX_SHM_BASE+6 126
4213542130
** READ-4 UNIX_SHM_BASE+7 127
4213642131
** DMS UNIX_SHM_BASE+8 128
4213742132
*/
4213842133
assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
42134
+#endif
42135
+
4213942136
return SQLITE_OK;
4214042137
}
4214142138
4214242139
/*
4214342140
** Shutdown the operating system interface.
@@ -42173,209 +42170,11 @@
4217342170
#if SQLITE_OS_WIN /* This file is used for Windows only */
4217442171
4217542172
/*
4217642173
** Include code that is common to all os_*.c files
4217742174
*/
42178
-/************** Include os_common.h in the middle of os_win.c ****************/
42179
-/************** Begin file os_common.h ***************************************/
42180
-/*
42181
-** 2004 May 22
42182
-**
42183
-** The author disclaims copyright to this source code. In place of
42184
-** a legal notice, here is a blessing:
42185
-**
42186
-** May you do good and not evil.
42187
-** May you find forgiveness for yourself and forgive others.
42188
-** May you share freely, never taking more than you give.
42189
-**
42190
-******************************************************************************
42191
-**
42192
-** This file contains macros and a little bit of code that is common to
42193
-** all of the platform-specific files (os_*.c) and is #included into those
42194
-** files.
42195
-**
42196
-** This file should be #included by the os_*.c files only. It is not a
42197
-** general purpose header file.
42198
-*/
42199
-#ifndef _OS_COMMON_H_
42200
-#define _OS_COMMON_H_
42201
-
42202
-/*
42203
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
42204
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
42205
-** switch. The following code should catch this problem at compile-time.
42206
-*/
42207
-#ifdef MEMORY_DEBUG
42208
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
42209
-#endif
42210
-
42211
-/*
42212
-** Macros for performance tracing. Normally turned off. Only works
42213
-** on i486 hardware.
42214
-*/
42215
-#ifdef SQLITE_PERFORMANCE_TRACE
42216
-
42217
-/*
42218
-** hwtime.h contains inline assembler code for implementing
42219
-** high-performance timing routines.
42220
-*/
42221
-/************** Include hwtime.h in the middle of os_common.h ****************/
42222
-/************** Begin file hwtime.h ******************************************/
42223
-/*
42224
-** 2008 May 27
42225
-**
42226
-** The author disclaims copyright to this source code. In place of
42227
-** a legal notice, here is a blessing:
42228
-**
42229
-** May you do good and not evil.
42230
-** May you find forgiveness for yourself and forgive others.
42231
-** May you share freely, never taking more than you give.
42232
-**
42233
-******************************************************************************
42234
-**
42235
-** This file contains inline asm code for retrieving "high-performance"
42236
-** counters for x86 and x86_64 class CPUs.
42237
-*/
42238
-#ifndef SQLITE_HWTIME_H
42239
-#define SQLITE_HWTIME_H
42240
-
42241
-/*
42242
-** The following routine only works on pentium-class (or newer) processors.
42243
-** It uses the RDTSC opcode to read the cycle count value out of the
42244
-** processor and returns that value. This can be used for high-res
42245
-** profiling.
42246
-*/
42247
-#if !defined(__STRICT_ANSI__) && \
42248
- (defined(__GNUC__) || defined(_MSC_VER)) && \
42249
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
42250
-
42251
- #if defined(__GNUC__)
42252
-
42253
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
42254
- unsigned int lo, hi;
42255
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
42256
- return (sqlite_uint64)hi << 32 | lo;
42257
- }
42258
-
42259
- #elif defined(_MSC_VER)
42260
-
42261
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
42262
- __asm {
42263
- rdtsc
42264
- ret ; return value at EDX:EAX
42265
- }
42266
- }
42267
-
42268
- #endif
42269
-
42270
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
42271
-
42272
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
42273
- unsigned long val;
42274
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
42275
- return val;
42276
- }
42277
-
42278
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
42279
-
42280
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
42281
- unsigned long long retval;
42282
- unsigned long junk;
42283
- __asm__ __volatile__ ("\n\
42284
- 1: mftbu %1\n\
42285
- mftb %L0\n\
42286
- mftbu %0\n\
42287
- cmpw %0,%1\n\
42288
- bne 1b"
42289
- : "=r" (retval), "=r" (junk));
42290
- return retval;
42291
- }
42292
-
42293
-#else
42294
-
42295
- /*
42296
- ** asm() is needed for hardware timing support. Without asm(),
42297
- ** disable the sqlite3Hwtime() routine.
42298
- **
42299
- ** sqlite3Hwtime() is only used for some obscure debugging
42300
- ** and analysis configurations, not in any deliverable, so this
42301
- ** should not be a great loss.
42302
- */
42303
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
42304
-
42305
-#endif
42306
-
42307
-#endif /* !defined(SQLITE_HWTIME_H) */
42308
-
42309
-/************** End of hwtime.h **********************************************/
42310
-/************** Continuing where we left off in os_common.h ******************/
42311
-
42312
-static sqlite_uint64 g_start;
42313
-static sqlite_uint64 g_elapsed;
42314
-#define TIMER_START g_start=sqlite3Hwtime()
42315
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
42316
-#define TIMER_ELAPSED g_elapsed
42317
-#else
42318
-#define TIMER_START
42319
-#define TIMER_END
42320
-#define TIMER_ELAPSED ((sqlite_uint64)0)
42321
-#endif
42322
-
42323
-/*
42324
-** If we compile with the SQLITE_TEST macro set, then the following block
42325
-** of code will give us the ability to simulate a disk I/O error. This
42326
-** is used for testing the I/O recovery logic.
42327
-*/
42328
-#if defined(SQLITE_TEST)
42329
-SQLITE_API extern int sqlite3_io_error_hit;
42330
-SQLITE_API extern int sqlite3_io_error_hardhit;
42331
-SQLITE_API extern int sqlite3_io_error_pending;
42332
-SQLITE_API extern int sqlite3_io_error_persist;
42333
-SQLITE_API extern int sqlite3_io_error_benign;
42334
-SQLITE_API extern int sqlite3_diskfull_pending;
42335
-SQLITE_API extern int sqlite3_diskfull;
42336
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
42337
-#define SimulateIOError(CODE) \
42338
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
42339
- || sqlite3_io_error_pending-- == 1 ) \
42340
- { local_ioerr(); CODE; }
42341
-static void local_ioerr(){
42342
- IOTRACE(("IOERR\n"));
42343
- sqlite3_io_error_hit++;
42344
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
42345
-}
42346
-#define SimulateDiskfullError(CODE) \
42347
- if( sqlite3_diskfull_pending ){ \
42348
- if( sqlite3_diskfull_pending == 1 ){ \
42349
- local_ioerr(); \
42350
- sqlite3_diskfull = 1; \
42351
- sqlite3_io_error_hit = 1; \
42352
- CODE; \
42353
- }else{ \
42354
- sqlite3_diskfull_pending--; \
42355
- } \
42356
- }
42357
-#else
42358
-#define SimulateIOErrorBenign(X)
42359
-#define SimulateIOError(A)
42360
-#define SimulateDiskfullError(A)
42361
-#endif /* defined(SQLITE_TEST) */
42362
-
42363
-/*
42364
-** When testing, keep a count of the number of open files.
42365
-*/
42366
-#if defined(SQLITE_TEST)
42367
-SQLITE_API extern int sqlite3_open_file_count;
42368
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
42369
-#else
42370
-#define OpenCounter(X)
42371
-#endif /* defined(SQLITE_TEST) */
42372
-
42373
-#endif /* !defined(_OS_COMMON_H_) */
42374
-
42375
-/************** End of os_common.h *******************************************/
42376
-/************** Continuing where we left off in os_win.c *********************/
42175
+/* #include "os_common.h" */
4237742176
4237842177
/*
4237942178
** Include the header file for the Windows VFS.
4238042179
*/
4238142180
/* #include "os_win.h" */
@@ -49319,11 +49118,12 @@
4931949118
#endif
4932049119
4932149120
sqlite3_mutex_enter(db->mutex);
4932249121
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
4932349122
iDb = sqlite3FindDbName(db, zSchema);
49324
- if( iDb<0 ){
49123
+ testcase( iDb==1 );
49124
+ if( iDb<2 && iDb!=0 ){
4932549125
rc = SQLITE_ERROR;
4932649126
goto end_deserialize;
4932749127
}
4932849128
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
4932949129
if( zSql==0 ){
@@ -49371,11 +49171,13 @@
4937149171
** This routine is called when the extension is loaded.
4937249172
** Register the new VFS.
4937349173
*/
4937449174
SQLITE_PRIVATE int sqlite3MemdbInit(void){
4937549175
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
49376
- unsigned int sz = pLower->szOsFile;
49176
+ unsigned int sz;
49177
+ if( NEVER(pLower==0) ) return SQLITE_ERROR;
49178
+ sz = pLower->szOsFile;
4937749179
memdb_vfs.pAppData = pLower;
4937849180
/* The following conditional can only be true when compiled for
4937949181
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
4938049182
** it in, to be safe, but it is marked as NO_TEST since there
4938149183
** is no way to reach it under most builds. */
@@ -60504,11 +60306,14 @@
6050460306
** Each index block except for the first contains information on
6050560307
** HASHTABLE_NPAGE frames. The first index block contains information on
6050660308
** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
6050760309
** HASHTABLE_NPAGE are selected so that together the wal-index header and
6050860310
** first index block are the same size as all other index blocks in the
60509
-** wal-index.
60311
+** wal-index. The values are:
60312
+**
60313
+** HASHTABLE_NPAGE 4096
60314
+** HASHTABLE_NPAGE_ONE 4062
6051060315
**
6051160316
** Each index block contains two sections, a page-mapping that contains the
6051260317
** database page number associated with each wal frame, and a hash-table
6051360318
** that allows readers to query an index block for a specific page number.
6051460319
** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
@@ -60740,10 +60545,74 @@
6074060545
u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */
6074160546
u32 notUsed0; /* Available for future enhancements */
6074260547
};
6074360548
#define READMARK_NOT_USED 0xffffffff
6074460549
60550
+/*
60551
+** This is a schematic view of the complete 136-byte header of the
60552
+** wal-index file (also known as the -shm file):
60553
+**
60554
+** +-----------------------------+
60555
+** 0: | iVersion | \
60556
+** +-----------------------------+ |
60557
+** 4: | (unused padding) | |
60558
+** +-----------------------------+ |
60559
+** 8: | iChange | |
60560
+** +-------+-------+-------------+ |
60561
+** 12: | bInit | bBig | szPage | |
60562
+** +-------+-------+-------------+ |
60563
+** 16: | mxFrame | | First copy of the
60564
+** +-----------------------------+ | WalIndexHdr object
60565
+** 20: | nPage | |
60566
+** +-----------------------------+ |
60567
+** 24: | aFrameCksum | |
60568
+** | | |
60569
+** +-----------------------------+ |
60570
+** 32: | aSalt | |
60571
+** | | |
60572
+** +-----------------------------+ |
60573
+** 40: | aCksum | |
60574
+** | | /
60575
+** +-----------------------------+
60576
+** 48: | iVersion | \
60577
+** +-----------------------------+ |
60578
+** 52: | (unused padding) | |
60579
+** +-----------------------------+ |
60580
+** 56: | iChange | |
60581
+** +-------+-------+-------------+ |
60582
+** 60: | bInit | bBig | szPage | |
60583
+** +-------+-------+-------------+ | Second copy of the
60584
+** 64: | mxFrame | | WalIndexHdr
60585
+** +-----------------------------+ |
60586
+** 68: | nPage | |
60587
+** +-----------------------------+ |
60588
+** 72: | aFrameCksum | |
60589
+** | | |
60590
+** +-----------------------------+ |
60591
+** 80: | aSalt | |
60592
+** | | |
60593
+** +-----------------------------+ |
60594
+** 88: | aCksum | |
60595
+** | | /
60596
+** +-----------------------------+
60597
+** 96: | nBackfill |
60598
+** +-----------------------------+
60599
+** 100: | 5 read marks |
60600
+** | |
60601
+** | |
60602
+** | |
60603
+** | |
60604
+** +-------+-------+------+------+
60605
+** 120: | Write | Ckpt | Rcvr | Rd0 | \
60606
+** +-------+-------+------+------+ ) 8 lock bytes
60607
+** | Read1 | Read2 | Rd3 | Rd4 | /
60608
+** +-------+-------+------+------+
60609
+** 128: | nBackfillAttempted |
60610
+** +-----------------------------+
60611
+** 132: | (unused padding) |
60612
+** +-----------------------------+
60613
+*/
6074560614
6074660615
/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
6074760616
** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
6074860617
** only support mandatory file-locks, we do not read or write data
6074960618
** from the region of the file on which locks are applied.
@@ -61752,19 +61621,48 @@
6175261621
Wal *pRet; /* Object to allocate and return */
6175361622
int flags; /* Flags passed to OsOpen() */
6175461623
6175561624
assert( zWalName && zWalName[0] );
6175661625
assert( pDbFd );
61626
+
61627
+ /* Verify the values of various constants. Any changes to the values
61628
+ ** of these constants would result in an incompatible on-disk format
61629
+ ** for the -shm file. Any change that causes one of these asserts to
61630
+ ** fail is a backward compatibility problem, even if the change otherwise
61631
+ ** works.
61632
+ **
61633
+ ** This table also serves as a helpful cross-reference when trying to
61634
+ ** interpret hex dumps of the -shm file.
61635
+ */
61636
+ assert( 48 == sizeof(WalIndexHdr) );
61637
+ assert( 40 == sizeof(WalCkptInfo) );
61638
+ assert( 120 == WALINDEX_LOCK_OFFSET );
61639
+ assert( 136 == WALINDEX_HDR_SIZE );
61640
+ assert( 4096 == HASHTABLE_NPAGE );
61641
+ assert( 4062 == HASHTABLE_NPAGE_ONE );
61642
+ assert( 8192 == HASHTABLE_NSLOT );
61643
+ assert( 383 == HASHTABLE_HASH_1 );
61644
+ assert( 32768 == WALINDEX_PGSZ );
61645
+ assert( 8 == SQLITE_SHM_NLOCK );
61646
+ assert( 5 == WAL_NREADER );
61647
+ assert( 24 == WAL_FRAME_HDRSIZE );
61648
+ assert( 32 == WAL_HDRSIZE );
61649
+ assert( 120 == WALINDEX_LOCK_OFFSET + WAL_WRITE_LOCK );
61650
+ assert( 121 == WALINDEX_LOCK_OFFSET + WAL_CKPT_LOCK );
61651
+ assert( 122 == WALINDEX_LOCK_OFFSET + WAL_RECOVER_LOCK );
61652
+ assert( 123 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(0) );
61653
+ assert( 124 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(1) );
61654
+ assert( 125 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(2) );
61655
+ assert( 126 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(3) );
61656
+ assert( 127 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(4) );
6175761657
6175861658
/* In the amalgamation, the os_unix.c and os_win.c source files come before
6175961659
** this source file. Verify that the #defines of the locking byte offsets
6176061660
** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
6176161661
** For that matter, if the lock offset ever changes from its initial design
6176261662
** value of 120, we need to know that so there is an assert() to check it.
6176361663
*/
61764
- assert( 120==WALINDEX_LOCK_OFFSET );
61765
- assert( 136==WALINDEX_HDR_SIZE );
6176661664
#ifdef WIN_SHM_BASE
6176761665
assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
6176861666
#endif
6176961667
#ifdef UNIX_SHM_BASE
6177061668
assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
@@ -66267,19 +66165,17 @@
6626766165
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
6626866166
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
6626966167
sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
6627066168
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
6627166169
rc = SQLITE_CORRUPT_BKPT;
66272
- goto moveto_done;
66170
+ }else{
66171
+ rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes);
6627366172
}
66173
+ sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
6627466174
}else{
6627566175
pIdxKey = 0;
66276
- }
66277
- rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
66278
-moveto_done:
66279
- if( pIdxKey ){
66280
- sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
66176
+ rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes);
6628166177
}
6628266178
return rc;
6628366179
}
6628466180
6628566181
/*
@@ -67124,11 +67020,11 @@
6712467020
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
6712567021
if( pSpace ){
6712667022
int g2;
6712767023
assert( pSpace+nByte<=data+pPage->pBt->usableSize );
6712867024
*pIdx = g2 = (int)(pSpace-data);
67129
- if( NEVER(g2<=gap) ){
67025
+ if( g2<=gap ){
6713067026
return SQLITE_CORRUPT_PAGE(pPage);
6713167027
}else{
6713267028
return SQLITE_OK;
6713367029
}
6713467030
}else if( rc ){
@@ -70861,16 +70757,12 @@
7086170757
rc = SQLITE_OK;
7086270758
}
7086370759
return rc;
7086470760
}
7086570761
70866
-/* Move the cursor so that it points to an entry near the key
70867
-** specified by pIdxKey or intKey. Return a success code.
70868
-**
70869
-** For INTKEY tables, the intKey parameter is used. pIdxKey
70870
-** must be NULL. For index tables, pIdxKey is used and intKey
70871
-** is ignored.
70762
+/* Move the cursor so that it points to an entry in a table (a.k.a INTKEY)
70763
+** table near the key intKey. Return a success code.
7087270764
**
7087370765
** If an exact match is not found, then the cursor is always
7087470766
** left pointing at a leaf page which would hold the entry if it
7087570767
** were present. The cursor might point to an entry that comes
7087670768
** before or after the key.
@@ -70879,43 +70771,36 @@
7087970771
** comparing the key with the entry to which the cursor is
7088070772
** pointing. The meaning of the integer written into
7088170773
** *pRes is as follows:
7088270774
**
7088370775
** *pRes<0 The cursor is left pointing at an entry that
70884
-** is smaller than intKey/pIdxKey or if the table is empty
70776
+** is smaller than intKey or if the table is empty
7088570777
** and the cursor is therefore left point to nothing.
7088670778
**
7088770779
** *pRes==0 The cursor is left pointing at an entry that
70888
-** exactly matches intKey/pIdxKey.
70780
+** exactly matches intKey.
7088970781
**
7089070782
** *pRes>0 The cursor is left pointing at an entry that
70891
-** is larger than intKey/pIdxKey.
70892
-**
70893
-** For index tables, the pIdxKey->eqSeen field is set to 1 if there
70894
-** exists an entry in the table that exactly matches pIdxKey.
70783
+** is larger than intKey.
7089570784
*/
70896
-SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
70785
+SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
7089770786
BtCursor *pCur, /* The cursor to be moved */
70898
- UnpackedRecord *pIdxKey, /* Unpacked index key */
7089970787
i64 intKey, /* The table key */
7090070788
int biasRight, /* If true, bias the search to the high end */
7090170789
int *pRes /* Write search results here */
7090270790
){
7090370791
int rc;
70904
- RecordCompare xRecordCompare;
7090570792
7090670793
assert( cursorOwnsBtShared(pCur) );
7090770794
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
7090870795
assert( pRes );
70909
- assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
70910
- assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
70796
+ assert( pCur->pKeyInfo==0 );
70797
+ assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 );
7091170798
7091270799
/* If the cursor is already positioned at the point we are trying
7091370800
** to move to, then just return without doing any work */
70914
- if( pIdxKey==0
70915
- && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
70916
- ){
70801
+ if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){
7091770802
if( pCur->info.nKey==intKey ){
7091870803
*pRes = 0;
7091970804
return SQLITE_OK;
7092070805
}
7092170806
if( pCur->info.nKey<intKey ){
@@ -70946,20 +70831,153 @@
7094670831
7094770832
#ifdef SQLITE_DEBUG
7094870833
pCur->pBtree->nSeek++; /* Performance measurement during testing */
7094970834
#endif
7095070835
70951
- if( pIdxKey ){
70952
- xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
70953
- pIdxKey->errCode = 0;
70954
- assert( pIdxKey->default_rc==1
70955
- || pIdxKey->default_rc==0
70956
- || pIdxKey->default_rc==-1
70957
- );
70958
- }else{
70959
- xRecordCompare = 0; /* All keys are integers */
70960
- }
70836
+ rc = moveToRoot(pCur);
70837
+ if( rc ){
70838
+ if( rc==SQLITE_EMPTY ){
70839
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
70840
+ *pRes = -1;
70841
+ return SQLITE_OK;
70842
+ }
70843
+ return rc;
70844
+ }
70845
+ assert( pCur->pPage );
70846
+ assert( pCur->pPage->isInit );
70847
+ assert( pCur->eState==CURSOR_VALID );
70848
+ assert( pCur->pPage->nCell > 0 );
70849
+ assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
70850
+ assert( pCur->curIntKey );
70851
+
70852
+ for(;;){
70853
+ int lwr, upr, idx, c;
70854
+ Pgno chldPg;
70855
+ MemPage *pPage = pCur->pPage;
70856
+ u8 *pCell; /* Pointer to current cell in pPage */
70857
+
70858
+ /* pPage->nCell must be greater than zero. If this is the root-page
70859
+ ** the cursor would have been INVALID above and this for(;;) loop
70860
+ ** not run. If this is not the root-page, then the moveToChild() routine
70861
+ ** would have already detected db corruption. Similarly, pPage must
70862
+ ** be the right kind (index or table) of b-tree page. Otherwise
70863
+ ** a moveToChild() or moveToRoot() call would have detected corruption. */
70864
+ assert( pPage->nCell>0 );
70865
+ assert( pPage->intKey );
70866
+ lwr = 0;
70867
+ upr = pPage->nCell-1;
70868
+ assert( biasRight==0 || biasRight==1 );
70869
+ idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
70870
+ pCur->ix = (u16)idx;
70871
+ for(;;){
70872
+ i64 nCellKey;
70873
+ pCell = findCellPastPtr(pPage, idx);
70874
+ if( pPage->intKeyLeaf ){
70875
+ while( 0x80 <= *(pCell++) ){
70876
+ if( pCell>=pPage->aDataEnd ){
70877
+ return SQLITE_CORRUPT_PAGE(pPage);
70878
+ }
70879
+ }
70880
+ }
70881
+ getVarint(pCell, (u64*)&nCellKey);
70882
+ if( nCellKey<intKey ){
70883
+ lwr = idx+1;
70884
+ if( lwr>upr ){ c = -1; break; }
70885
+ }else if( nCellKey>intKey ){
70886
+ upr = idx-1;
70887
+ if( lwr>upr ){ c = +1; break; }
70888
+ }else{
70889
+ assert( nCellKey==intKey );
70890
+ pCur->ix = (u16)idx;
70891
+ if( !pPage->leaf ){
70892
+ lwr = idx;
70893
+ goto moveto_table_next_layer;
70894
+ }else{
70895
+ pCur->curFlags |= BTCF_ValidNKey;
70896
+ pCur->info.nKey = nCellKey;
70897
+ pCur->info.nSize = 0;
70898
+ *pRes = 0;
70899
+ return SQLITE_OK;
70900
+ }
70901
+ }
70902
+ assert( lwr+upr>=0 );
70903
+ idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
70904
+ }
70905
+ assert( lwr==upr+1 || !pPage->leaf );
70906
+ assert( pPage->isInit );
70907
+ if( pPage->leaf ){
70908
+ assert( pCur->ix<pCur->pPage->nCell );
70909
+ pCur->ix = (u16)idx;
70910
+ *pRes = c;
70911
+ rc = SQLITE_OK;
70912
+ goto moveto_table_finish;
70913
+ }
70914
+moveto_table_next_layer:
70915
+ if( lwr>=pPage->nCell ){
70916
+ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
70917
+ }else{
70918
+ chldPg = get4byte(findCell(pPage, lwr));
70919
+ }
70920
+ pCur->ix = (u16)lwr;
70921
+ rc = moveToChild(pCur, chldPg);
70922
+ if( rc ) break;
70923
+ }
70924
+moveto_table_finish:
70925
+ pCur->info.nSize = 0;
70926
+ assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
70927
+ return rc;
70928
+}
70929
+
70930
+/* Move the cursor so that it points to an entry in an index table
70931
+** near the key pIdxKey. Return a success code.
70932
+**
70933
+** If an exact match is not found, then the cursor is always
70934
+** left pointing at a leaf page which would hold the entry if it
70935
+** were present. The cursor might point to an entry that comes
70936
+** before or after the key.
70937
+**
70938
+** An integer is written into *pRes which is the result of
70939
+** comparing the key with the entry to which the cursor is
70940
+** pointing. The meaning of the integer written into
70941
+** *pRes is as follows:
70942
+**
70943
+** *pRes<0 The cursor is left pointing at an entry that
70944
+** is smaller than pIdxKey or if the table is empty
70945
+** and the cursor is therefore left point to nothing.
70946
+**
70947
+** *pRes==0 The cursor is left pointing at an entry that
70948
+** exactly matches pIdxKey.
70949
+**
70950
+** *pRes>0 The cursor is left pointing at an entry that
70951
+** is larger than pIdxKey.
70952
+**
70953
+** The pIdxKey->eqSeen field is set to 1 if there
70954
+** exists an entry in the table that exactly matches pIdxKey.
70955
+*/
70956
+SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
70957
+ BtCursor *pCur, /* The cursor to be moved */
70958
+ UnpackedRecord *pIdxKey, /* Unpacked index key */
70959
+ int *pRes /* Write search results here */
70960
+){
70961
+ int rc;
70962
+ RecordCompare xRecordCompare;
70963
+
70964
+ assert( cursorOwnsBtShared(pCur) );
70965
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
70966
+ assert( pRes );
70967
+ assert( pCur->pKeyInfo!=0 );
70968
+
70969
+#ifdef SQLITE_DEBUG
70970
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
70971
+#endif
70972
+
70973
+ xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
70974
+ pIdxKey->errCode = 0;
70975
+ assert( pIdxKey->default_rc==1
70976
+ || pIdxKey->default_rc==0
70977
+ || pIdxKey->default_rc==-1
70978
+ );
7096170979
7096270980
rc = moveToRoot(pCur);
7096370981
if( rc ){
7096470982
if( rc==SQLITE_EMPTY ){
7096570983
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
@@ -70988,155 +71006,116 @@
7098871006
** a moveToChild() or moveToRoot() call would have detected corruption. */
7098971007
assert( pPage->nCell>0 );
7099071008
assert( pPage->intKey==(pIdxKey==0) );
7099171009
lwr = 0;
7099271010
upr = pPage->nCell-1;
70993
- assert( biasRight==0 || biasRight==1 );
70994
- idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
70995
- pCur->ix = (u16)idx;
70996
- if( xRecordCompare==0 ){
70997
- for(;;){
70998
- i64 nCellKey;
70999
- pCell = findCellPastPtr(pPage, idx);
71000
- if( pPage->intKeyLeaf ){
71001
- while( 0x80 <= *(pCell++) ){
71002
- if( pCell>=pPage->aDataEnd ){
71003
- return SQLITE_CORRUPT_PAGE(pPage);
71004
- }
71005
- }
71006
- }
71007
- getVarint(pCell, (u64*)&nCellKey);
71008
- if( nCellKey<intKey ){
71009
- lwr = idx+1;
71010
- if( lwr>upr ){ c = -1; break; }
71011
- }else if( nCellKey>intKey ){
71012
- upr = idx-1;
71013
- if( lwr>upr ){ c = +1; break; }
71014
- }else{
71015
- assert( nCellKey==intKey );
71016
- pCur->ix = (u16)idx;
71017
- if( !pPage->leaf ){
71018
- lwr = idx;
71019
- goto moveto_next_layer;
71020
- }else{
71021
- pCur->curFlags |= BTCF_ValidNKey;
71022
- pCur->info.nKey = nCellKey;
71023
- pCur->info.nSize = 0;
71024
- *pRes = 0;
71025
- return SQLITE_OK;
71026
- }
71027
- }
71028
- assert( lwr+upr>=0 );
71029
- idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
71030
- }
71031
- }else{
71032
- for(;;){
71033
- int nCell; /* Size of the pCell cell in bytes */
71034
- pCell = findCellPastPtr(pPage, idx);
71035
-
71036
- /* The maximum supported page-size is 65536 bytes. This means that
71037
- ** the maximum number of record bytes stored on an index B-Tree
71038
- ** page is less than 16384 bytes and may be stored as a 2-byte
71039
- ** varint. This information is used to attempt to avoid parsing
71040
- ** the entire cell by checking for the cases where the record is
71041
- ** stored entirely within the b-tree page by inspecting the first
71042
- ** 2 bytes of the cell.
71043
- */
71044
- nCell = pCell[0];
71045
- if( nCell<=pPage->max1bytePayload ){
71046
- /* This branch runs if the record-size field of the cell is a
71047
- ** single byte varint and the record fits entirely on the main
71048
- ** b-tree page. */
71049
- testcase( pCell+nCell+1==pPage->aDataEnd );
71050
- c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
71051
- }else if( !(pCell[1] & 0x80)
71052
- && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
71053
- ){
71054
- /* The record-size field is a 2 byte varint and the record
71055
- ** fits entirely on the main b-tree page. */
71056
- testcase( pCell+nCell+2==pPage->aDataEnd );
71057
- c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
71058
- }else{
71059
- /* The record flows over onto one or more overflow pages. In
71060
- ** this case the whole cell needs to be parsed, a buffer allocated
71061
- ** and accessPayload() used to retrieve the record into the
71062
- ** buffer before VdbeRecordCompare() can be called.
71063
- **
71064
- ** If the record is corrupt, the xRecordCompare routine may read
71065
- ** up to two varints past the end of the buffer. An extra 18
71066
- ** bytes of padding is allocated at the end of the buffer in
71067
- ** case this happens. */
71068
- void *pCellKey;
71069
- u8 * const pCellBody = pCell - pPage->childPtrSize;
71070
- const int nOverrun = 18; /* Size of the overrun padding */
71071
- pPage->xParseCell(pPage, pCellBody, &pCur->info);
71072
- nCell = (int)pCur->info.nKey;
71073
- testcase( nCell<0 ); /* True if key size is 2^32 or more */
71074
- testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
71075
- testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
71076
- testcase( nCell==2 ); /* Minimum legal index key size */
71077
- if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
71078
- rc = SQLITE_CORRUPT_PAGE(pPage);
71079
- goto moveto_finish;
71080
- }
71081
- pCellKey = sqlite3Malloc( nCell+nOverrun );
71082
- if( pCellKey==0 ){
71083
- rc = SQLITE_NOMEM_BKPT;
71084
- goto moveto_finish;
71085
- }
71086
- pCur->ix = (u16)idx;
71087
- rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
71088
- memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
71089
- pCur->curFlags &= ~BTCF_ValidOvfl;
71090
- if( rc ){
71091
- sqlite3_free(pCellKey);
71092
- goto moveto_finish;
71093
- }
71094
- c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
71095
- sqlite3_free(pCellKey);
71096
- }
71097
- assert(
71098
- (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
71099
- && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
71100
- );
71101
- if( c<0 ){
71102
- lwr = idx+1;
71103
- }else if( c>0 ){
71104
- upr = idx-1;
71105
- }else{
71106
- assert( c==0 );
71107
- *pRes = 0;
71108
- rc = SQLITE_OK;
71109
- pCur->ix = (u16)idx;
71110
- if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
71111
- goto moveto_finish;
71112
- }
71113
- if( lwr>upr ) break;
71114
- assert( lwr+upr>=0 );
71115
- idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
71116
- }
71011
+ idx = upr>>1; /* idx = (lwr+upr)/2; */
71012
+ pCur->ix = (u16)idx;
71013
+ for(;;){
71014
+ int nCell; /* Size of the pCell cell in bytes */
71015
+ pCell = findCellPastPtr(pPage, idx);
71016
+
71017
+ /* The maximum supported page-size is 65536 bytes. This means that
71018
+ ** the maximum number of record bytes stored on an index B-Tree
71019
+ ** page is less than 16384 bytes and may be stored as a 2-byte
71020
+ ** varint. This information is used to attempt to avoid parsing
71021
+ ** the entire cell by checking for the cases where the record is
71022
+ ** stored entirely within the b-tree page by inspecting the first
71023
+ ** 2 bytes of the cell.
71024
+ */
71025
+ nCell = pCell[0];
71026
+ if( nCell<=pPage->max1bytePayload ){
71027
+ /* This branch runs if the record-size field of the cell is a
71028
+ ** single byte varint and the record fits entirely on the main
71029
+ ** b-tree page. */
71030
+ testcase( pCell+nCell+1==pPage->aDataEnd );
71031
+ c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
71032
+ }else if( !(pCell[1] & 0x80)
71033
+ && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
71034
+ ){
71035
+ /* The record-size field is a 2 byte varint and the record
71036
+ ** fits entirely on the main b-tree page. */
71037
+ testcase( pCell+nCell+2==pPage->aDataEnd );
71038
+ c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
71039
+ }else{
71040
+ /* The record flows over onto one or more overflow pages. In
71041
+ ** this case the whole cell needs to be parsed, a buffer allocated
71042
+ ** and accessPayload() used to retrieve the record into the
71043
+ ** buffer before VdbeRecordCompare() can be called.
71044
+ **
71045
+ ** If the record is corrupt, the xRecordCompare routine may read
71046
+ ** up to two varints past the end of the buffer. An extra 18
71047
+ ** bytes of padding is allocated at the end of the buffer in
71048
+ ** case this happens. */
71049
+ void *pCellKey;
71050
+ u8 * const pCellBody = pCell - pPage->childPtrSize;
71051
+ const int nOverrun = 18; /* Size of the overrun padding */
71052
+ pPage->xParseCell(pPage, pCellBody, &pCur->info);
71053
+ nCell = (int)pCur->info.nKey;
71054
+ testcase( nCell<0 ); /* True if key size is 2^32 or more */
71055
+ testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
71056
+ testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
71057
+ testcase( nCell==2 ); /* Minimum legal index key size */
71058
+ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
71059
+ rc = SQLITE_CORRUPT_PAGE(pPage);
71060
+ goto moveto_index_finish;
71061
+ }
71062
+ pCellKey = sqlite3Malloc( nCell+nOverrun );
71063
+ if( pCellKey==0 ){
71064
+ rc = SQLITE_NOMEM_BKPT;
71065
+ goto moveto_index_finish;
71066
+ }
71067
+ pCur->ix = (u16)idx;
71068
+ rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
71069
+ memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
71070
+ pCur->curFlags &= ~BTCF_ValidOvfl;
71071
+ if( rc ){
71072
+ sqlite3_free(pCellKey);
71073
+ goto moveto_index_finish;
71074
+ }
71075
+ c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
71076
+ sqlite3_free(pCellKey);
71077
+ }
71078
+ assert(
71079
+ (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
71080
+ && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
71081
+ );
71082
+ if( c<0 ){
71083
+ lwr = idx+1;
71084
+ }else if( c>0 ){
71085
+ upr = idx-1;
71086
+ }else{
71087
+ assert( c==0 );
71088
+ *pRes = 0;
71089
+ rc = SQLITE_OK;
71090
+ pCur->ix = (u16)idx;
71091
+ if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
71092
+ goto moveto_index_finish;
71093
+ }
71094
+ if( lwr>upr ) break;
71095
+ assert( lwr+upr>=0 );
71096
+ idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
7111771097
}
7111871098
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
7111971099
assert( pPage->isInit );
7112071100
if( pPage->leaf ){
7112171101
assert( pCur->ix<pCur->pPage->nCell );
7112271102
pCur->ix = (u16)idx;
7112371103
*pRes = c;
7112471104
rc = SQLITE_OK;
71125
- goto moveto_finish;
71105
+ goto moveto_index_finish;
7112671106
}
71127
-moveto_next_layer:
7112871107
if( lwr>=pPage->nCell ){
7112971108
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
7113071109
}else{
7113171110
chldPg = get4byte(findCell(pPage, lwr));
7113271111
}
7113371112
pCur->ix = (u16)lwr;
7113471113
rc = moveToChild(pCur, chldPg);
7113571114
if( rc ) break;
7113671115
}
71137
-moveto_finish:
71116
+moveto_index_finish:
7113871117
pCur->info.nSize = 0;
7113971118
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
7114071119
return rc;
7114171120
}
7114271121
@@ -73116,10 +73095,11 @@
7311673095
if( rc ){
7311773096
memset(apOld, 0, (i)*sizeof(MemPage*));
7311873097
goto balance_cleanup;
7311973098
}
7312073099
}
73100
+ nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl);
7312173101
if( (i--)==0 ) break;
7312273102
7312373103
if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
7312473104
apDiv[i] = pParent->apOvfl[0];
7312573105
pgno = get4byte(apDiv[i]);
@@ -73157,11 +73137,10 @@
7315773137
}
7315873138
}
7315973139
7316073140
/* Make nMaxCells a multiple of 4 in order to preserve 8-byte
7316173141
** alignment */
73162
- nMaxCells = nOld*(MX_CELL(pBt) + ArraySize(pParent->apOvfl));
7316373142
nMaxCells = (nMaxCells + 3)&~3;
7316473143
7316573144
/*
7316673145
** Allocate space for memory structures
7316773146
*/
@@ -73440,11 +73419,13 @@
7344073419
if( i<nOld ){
7344173420
pNew = apNew[i] = apOld[i];
7344273421
apOld[i] = 0;
7344373422
rc = sqlite3PagerWrite(pNew->pDbPage);
7344473423
nNew++;
73445
- if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) ){
73424
+ if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv))
73425
+ && rc==SQLITE_OK
73426
+ ){
7344673427
rc = SQLITE_CORRUPT_BKPT;
7344773428
}
7344873429
if( rc ) goto balance_cleanup;
7344973430
}else{
7345073431
assert( i>0 );
@@ -74238,11 +74219,12 @@
7423874219
}else if( loc==0 ){
7423974220
/* The cursor is *not* pointing to the cell to be overwritten, nor
7424074221
** to an adjacent cell. Move the cursor so that it is pointing either
7424174222
** to the cell to be overwritten or an adjacent cell.
7424274223
*/
74243
- rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
74224
+ rc = sqlite3BtreeTableMoveto(pCur, pX->nKey,
74225
+ (flags & BTREE_APPEND)!=0, &loc);
7424474226
if( rc ) return rc;
7424574227
}
7424674228
}else{
7424774229
/* This is an index or a WITHOUT ROWID table */
7424874230
@@ -74261,17 +74243,15 @@
7426174243
UnpackedRecord r;
7426274244
r.pKeyInfo = pCur->pKeyInfo;
7426374245
r.aMem = pX->aMem;
7426474246
r.nField = pX->nMem;
7426574247
r.default_rc = 0;
74266
- r.errCode = 0;
74267
- r.r1 = 0;
74268
- r.r2 = 0;
7426974248
r.eqSeen = 0;
74270
- rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
74249
+ rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc);
7427174250
}else{
74272
- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
74251
+ rc = btreeMoveto(pCur, pX->pKey, pX->nKey,
74252
+ (flags & BTREE_APPEND)!=0, &loc);
7427374253
}
7427474254
if( rc ) return rc;
7427574255
}
7427674256
7427774257
/* If the cursor is currently pointing to an entry to be overwritten
@@ -74901,11 +74881,11 @@
7490174881
*/
7490274882
static int clearDatabasePage(
7490374883
BtShared *pBt, /* The BTree that contains the table */
7490474884
Pgno pgno, /* Page number to clear */
7490574885
int freePageFlag, /* Deallocate page if true */
74906
- int *pnChange /* Add number of Cells freed to this counter */
74886
+ i64 *pnChange /* Add number of Cells freed to this counter */
7490774887
){
7490874888
MemPage *pPage;
7490974889
int rc;
7491074890
unsigned char *pCell;
7491174891
int i;
@@ -74934,10 +74914,11 @@
7493474914
if( rc ) goto cleardatabasepage_out;
7493574915
}
7493674916
if( !pPage->leaf ){
7493774917
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
7493874918
if( rc ) goto cleardatabasepage_out;
74919
+ if( pPage->intKey ) pnChange = 0;
7493974920
}
7494074921
if( pnChange ){
7494174922
testcase( !pPage->intKey );
7494274923
*pnChange += pPage->nCell;
7494374924
}
@@ -74963,11 +74944,11 @@
7496374944
** root of the table.
7496474945
**
7496574946
** If pnChange is not NULL, then the integer value pointed to by pnChange
7496674947
** is incremented by the number of entries in the table.
7496774948
*/
74968
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
74949
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){
7496974950
int rc;
7497074951
BtShared *pBt = p->pBt;
7497174952
sqlite3BtreeEnter(p);
7497274953
assert( p->inTrans==TRANS_WRITE );
7497374954
@@ -80557,11 +80538,11 @@
8055780538
}
8055880539
#endif
8055980540
case P4_COLLSEQ: {
8056080541
static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
8056180542
CollSeq *pColl = pOp->p4.pColl;
80562
- assert( pColl->enc>=0 && pColl->enc<4 );
80543
+ assert( pColl->enc<4 );
8056380544
sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
8056480545
encnames[pColl->enc]);
8056580546
break;
8056680547
}
8056780548
case P4_FUNCDEF: {
@@ -82398,11 +82379,11 @@
8239882379
extern int sqlite3_search_count;
8239982380
#endif
8240082381
assert( p->deferredMoveto );
8240182382
assert( p->isTable );
8240282383
assert( p->eCurType==CURTYPE_BTREE );
82403
- rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
82384
+ rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res);
8240482385
if( rc ) return rc;
8240582386
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
8240682387
#ifdef SQLITE_TEST
8240782388
sqlite3_search_count++;
8240882389
#endif
@@ -83182,11 +83163,11 @@
8318283163
/*
8318383164
** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
8318483165
** number. Return negative, zero, or positive if the first (i64) is less than,
8318583166
** equal to, or greater than the second (double).
8318683167
*/
83187
-static int sqlite3IntFloatCompare(i64 i, double r){
83168
+SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){
8318883169
if( sizeof(LONGDOUBLE_TYPE)>8 ){
8318983170
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
8319083171
testcase( x<r );
8319183172
testcase( x>r );
8319283173
testcase( x==r );
@@ -83906,11 +83887,11 @@
8390683887
8390783888
/*
8390883889
** This routine sets the value to be returned by subsequent calls to
8390983890
** sqlite3_changes() on the database handle 'db'.
8391083891
*/
83911
-SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
83892
+SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){
8391283893
assert( sqlite3_mutex_held(db->mutex) );
8391383894
db->nChange = nChange;
8391483895
db->nTotalChange += nChange;
8391583896
}
8391683897
@@ -87023,100 +87004,11 @@
8702387004
8702487005
/*
8702587006
** hwtime.h contains inline assembler code for implementing
8702687007
** high-performance timing routines.
8702787008
*/
87028
-/************** Include hwtime.h in the middle of vdbe.c *********************/
87029
-/************** Begin file hwtime.h ******************************************/
87030
-/*
87031
-** 2008 May 27
87032
-**
87033
-** The author disclaims copyright to this source code. In place of
87034
-** a legal notice, here is a blessing:
87035
-**
87036
-** May you do good and not evil.
87037
-** May you find forgiveness for yourself and forgive others.
87038
-** May you share freely, never taking more than you give.
87039
-**
87040
-******************************************************************************
87041
-**
87042
-** This file contains inline asm code for retrieving "high-performance"
87043
-** counters for x86 and x86_64 class CPUs.
87044
-*/
87045
-#ifndef SQLITE_HWTIME_H
87046
-#define SQLITE_HWTIME_H
87047
-
87048
-/*
87049
-** The following routine only works on pentium-class (or newer) processors.
87050
-** It uses the RDTSC opcode to read the cycle count value out of the
87051
-** processor and returns that value. This can be used for high-res
87052
-** profiling.
87053
-*/
87054
-#if !defined(__STRICT_ANSI__) && \
87055
- (defined(__GNUC__) || defined(_MSC_VER)) && \
87056
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
87057
-
87058
- #if defined(__GNUC__)
87059
-
87060
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
87061
- unsigned int lo, hi;
87062
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
87063
- return (sqlite_uint64)hi << 32 | lo;
87064
- }
87065
-
87066
- #elif defined(_MSC_VER)
87067
-
87068
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
87069
- __asm {
87070
- rdtsc
87071
- ret ; return value at EDX:EAX
87072
- }
87073
- }
87074
-
87075
- #endif
87076
-
87077
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
87078
-
87079
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
87080
- unsigned long val;
87081
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
87082
- return val;
87083
- }
87084
-
87085
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
87086
-
87087
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
87088
- unsigned long long retval;
87089
- unsigned long junk;
87090
- __asm__ __volatile__ ("\n\
87091
- 1: mftbu %1\n\
87092
- mftb %L0\n\
87093
- mftbu %0\n\
87094
- cmpw %0,%1\n\
87095
- bne 1b"
87096
- : "=r" (retval), "=r" (junk));
87097
- return retval;
87098
- }
87099
-
87100
-#else
87101
-
87102
- /*
87103
- ** asm() is needed for hardware timing support. Without asm(),
87104
- ** disable the sqlite3Hwtime() routine.
87105
- **
87106
- ** sqlite3Hwtime() is only used for some obscure debugging
87107
- ** and analysis configurations, not in any deliverable, so this
87108
- ** should not be a great loss.
87109
- */
87110
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
87111
-
87112
-#endif
87113
-
87114
-#endif /* !defined(SQLITE_HWTIME_H) */
87115
-
87116
-/************** End of hwtime.h **********************************************/
87117
-/************** Continuing where we left off in vdbe.c ***********************/
87009
+/* #include "hwtime.h" */
8711887010
8711987011
#endif
8712087012
8712187013
#ifndef NDEBUG
8712287014
/*
@@ -90274,10 +90166,12 @@
9027490166
assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
9027590167
assert( pOp->p4type==P4_KEYINFO );
9027690168
pCur = p->apCsr[pOp->p1];
9027790169
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
9027890170
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
90171
+ assert( pCur->eCurType==CURTYPE_BTREE );
90172
+ sqlite3BtreeClearCursor(pCur->uc.pCursor);
9027990173
goto open_cursor_set_hints;
9028090174
}
9028190175
/* If the cursor is not currently open or is open on a different
9028290176
** index, then fall through into OP_OpenRead to force a reopen */
9028390177
case OP_OpenRead:
@@ -90761,45 +90655,47 @@
9076190655
pIn3->flags = flags3; /* But convert the type back to its original */
9076290656
9076390657
/* If the P3 value could not be converted into an integer without
9076490658
** loss of information, then special processing is required... */
9076590659
if( (newType & (MEM_Int|MEM_IntReal))==0 ){
90660
+ int c;
9076690661
if( (newType & MEM_Real)==0 ){
9076790662
if( (newType & MEM_Null) || oc>=OP_SeekGE ){
9076890663
VdbeBranchTaken(1,2);
9076990664
goto jump_to_p2;
9077090665
}else{
9077190666
rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
9077290667
if( rc!=SQLITE_OK ) goto abort_due_to_error;
9077390668
goto seek_not_found;
9077490669
}
90775
- }else
90670
+ }
90671
+ c = sqlite3IntFloatCompare(iKey, pIn3->u.r);
9077690672
9077790673
/* If the approximation iKey is larger than the actual real search
9077890674
** term, substitute >= for > and < for <=. e.g. if the search term
9077990675
** is 4.9 and the integer approximation 5:
9078090676
**
9078190677
** (x > 4.9) -> (x >= 5)
9078290678
** (x <= 4.9) -> (x < 5)
9078390679
*/
90784
- if( pIn3->u.r<(double)iKey ){
90680
+ if( c>0 ){
9078590681
assert( OP_SeekGE==(OP_SeekGT-1) );
9078690682
assert( OP_SeekLT==(OP_SeekLE-1) );
9078790683
assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
9078890684
if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
9078990685
}
9079090686
9079190687
/* If the approximation iKey is smaller than the actual real search
9079290688
** term, substitute <= for < and > for >=. */
90793
- else if( pIn3->u.r>(double)iKey ){
90689
+ else if( c<0 ){
9079490690
assert( OP_SeekLE==(OP_SeekLT+1) );
9079590691
assert( OP_SeekGT==(OP_SeekGE+1) );
9079690692
assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
9079790693
if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
9079890694
}
9079990695
}
90800
- rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
90696
+ rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res);
9080190697
pC->movetoTarget = iKey; /* Used by OP_Delete */
9080290698
if( rc!=SQLITE_OK ){
9080390699
goto abort_due_to_error;
9080490700
}
9080590701
}else{
@@ -90842,11 +90738,11 @@
9084290738
r.aMem = &aMem[pOp->p3];
9084390739
#ifdef SQLITE_DEBUG
9084490740
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
9084590741
#endif
9084690742
r.eqSeen = 0;
90847
- rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
90743
+ rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res);
9084890744
if( rc!=SQLITE_OK ){
9084990745
goto abort_due_to_error;
9085090746
}
9085190747
if( eqOnly && r.eqSeen==0 ){
9085290748
assert( res!=0 );
@@ -91261,11 +91157,11 @@
9126191157
takeJump = 1;
9126291158
break;
9126391159
}
9126491160
}
9126591161
}
91266
- rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
91162
+ rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &res);
9126791163
if( pFree ) sqlite3DbFreeNN(db, pFree);
9126891164
if( rc!=SQLITE_OK ){
9126991165
goto abort_due_to_error;
9127091166
}
9127191167
pC->seekResult = res;
@@ -91370,11 +91266,11 @@
9137091266
assert( pC->isTable );
9137191267
assert( pC->eCurType==CURTYPE_BTREE );
9137291268
pCrsr = pC->uc.pCursor;
9137391269
assert( pCrsr!=0 );
9137491270
res = 0;
91375
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
91271
+ rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res);
9137691272
assert( rc==SQLITE_OK || res==0 );
9137791273
pC->movetoTarget = iKey; /* Used by OP_Delete */
9137891274
pC->nullRow = 0;
9137991275
pC->cacheStatus = CACHE_STALE;
9138091276
pC->deferredMoveto = 0;
@@ -91527,11 +91423,11 @@
9152791423
** an AUTOINCREMENT table. */
9152891424
cnt = 0;
9152991425
do{
9153091426
sqlite3_randomness(sizeof(v), &v);
9153191427
v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
91532
- }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
91428
+ }while( ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v,
9153391429
0, &res))==SQLITE_OK)
9153491430
&& (res==0)
9153591431
&& (++cnt<100));
9153691432
if( rc ) goto abort_due_to_error;
9153791433
if( res==0 ){
@@ -92425,11 +92321,11 @@
9242592321
assert( pCrsr!=0 );
9242692322
r.pKeyInfo = pC->pKeyInfo;
9242792323
r.nField = (u16)pOp->p3;
9242892324
r.default_rc = 0;
9242992325
r.aMem = &aMem[pOp->p2];
92430
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
92326
+ rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
9243192327
if( rc ) goto abort_due_to_error;
9243292328
if( res==0 ){
9243392329
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
9243492330
if( rc ) goto abort_due_to_error;
9243592331
}else if( pOp->p5 ){
@@ -92738,11 +92634,11 @@
9273892634
** by the number of rows in the table being cleared.
9273992635
**
9274092636
** See also: Destroy
9274192637
*/
9274292638
case OP_Clear: {
92743
- int nChange;
92639
+ i64 nChange;
9274492640
9274592641
sqlite3VdbeIncrWriteCounter(p, 0);
9274692642
nChange = 0;
9274792643
assert( p->readOnly==0 );
9274892644
assert( DbMaskTest(p->btreeMask, pOp->p2) );
@@ -94960,11 +94856,11 @@
9496094856
if( pTab && !HasRowid(pTab) ){
9496194857
pTab = 0;
9496294858
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
9496394859
}
9496494860
#ifndef SQLITE_OMIT_VIEW
94965
- if( pTab && pTab->pSelect ){
94861
+ if( pTab && IsView(pTab) ){
9496694862
pTab = 0;
9496794863
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
9496894864
}
9496994865
#endif
9497094866
if( !pTab ){
@@ -94980,11 +94876,11 @@
9498094876
pBlob->pTab = pTab;
9498194877
pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
9498294878
9498394879
/* Now search pTab for the exact column. */
9498494880
for(iCol=0; iCol<pTab->nCol; iCol++) {
94985
- if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
94881
+ if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
9498694882
break;
9498794883
}
9498894884
}
9498994885
if( iCol==pTab->nCol ){
9499094886
sqlite3DbFree(db, zErr);
@@ -95005,11 +94901,12 @@
9500594901
/* Check that the column is not part of an FK child key definition. It
9500694902
** is not necessary to check if it is part of a parent key, as parent
9500794903
** key columns must be indexed. The check below will pick up this
9500894904
** case. */
9500994905
FKey *pFKey;
95010
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
94906
+ assert( !IsVirtual(pTab) );
94907
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
9501194908
int j;
9501294909
for(j=0; j<pFKey->nCol; j++){
9501394910
if( pFKey->aCol[j].iFrom==iCol ){
9501494911
zFault = "foreign key";
9501594912
}
@@ -96378,12 +96275,13 @@
9637896275
int iTask = (pTask - pTask->pSorter->aTask);
9637996276
sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
9638096277
fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
9638196278
}
9638296279
static void vdbeSorterRewindDebug(const char *zEvent){
96383
- i64 t;
96384
- sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t);
96280
+ i64 t = 0;
96281
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
96282
+ if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t);
9638596283
fprintf(stderr, "%lld:X %s\n", t, zEvent);
9638696284
}
9638796285
static void vdbeSorterPopulateDebug(
9638896286
SortSubtask *pTask,
9638996287
const char *zEvent
@@ -99500,11 +99398,11 @@
9950099398
if( pSrcList ){
9950199399
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
9950299400
u8 hCol;
9950399401
pTab = pItem->pTab;
9950499402
assert( pTab!=0 && pTab->zName!=0 );
99505
- assert( pTab->nCol>0 );
99403
+ assert( pTab->nCol>0 || pParse->nErr );
9950699404
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
9950799405
int hit = 0;
9950899406
pEList = pItem->pSelect->pEList;
9950999407
for(j=0; j<pEList->nExpr; j++){
9951099408
if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
@@ -99528,16 +99426,15 @@
9952899426
}
9952999427
if( IN_RENAME_OBJECT && pItem->zAlias ){
9953099428
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
9953199429
}
9953299430
}
99533
- if( 0==(cntTab++) ){
99534
- pMatch = pItem;
99535
- }
9953699431
hCol = sqlite3StrIHash(zCol);
9953799432
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
99538
- if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
99433
+ if( pCol->hName==hCol
99434
+ && sqlite3StrICmp(pCol->zCnName, zCol)==0
99435
+ ){
9953999436
/* If there has been exactly one prior match and this match
9954099437
** is for the right-hand table of a NATURAL JOIN or is in a
9954199438
** USING clause, then skip this match.
9954299439
*/
9954399440
if( cnt==1 ){
@@ -99548,10 +99445,14 @@
9954899445
pMatch = pItem;
9954999446
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
9955099447
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
9955199448
break;
9955299449
}
99450
+ }
99451
+ if( 0==cnt && VisibleRowid(pTab) ){
99452
+ cntTab++;
99453
+ pMatch = pItem;
9955399454
}
9955499455
}
9955599456
if( pMatch ){
9955699457
pExpr->iTable = pMatch->iCursor;
9955799458
pExpr->y.pTab = pMatch->pTab;
@@ -99606,11 +99507,13 @@
9960699507
int iCol;
9960799508
u8 hCol = sqlite3StrIHash(zCol);
9960899509
pSchema = pTab->pSchema;
9960999510
cntTab++;
9961099511
for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
99611
- if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
99512
+ if( pCol->hName==hCol
99513
+ && sqlite3StrICmp(pCol->zCnName, zCol)==0
99514
+ ){
9961299515
if( iCol==pTab->iPKey ){
9961399516
iCol = -1;
9961499517
}
9961599518
break;
9961699519
}
@@ -99671,11 +99574,11 @@
9967199574
if( cnt==0
9967299575
&& cntTab==1
9967399576
&& pMatch
9967499577
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
9967599578
&& sqlite3IsRowid(zCol)
99676
- && VisibleRowid(pMatch->pTab)
99579
+ && ALWAYS(VisibleRowid(pMatch->pTab))
9967799580
){
9967899581
cnt = 1;
9967999582
pExpr->iColumn = -1;
9968099583
pExpr->affExpr = SQLITE_AFF_INTEGER;
9968199584
}
@@ -100014,10 +99917,11 @@
10001499917
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
10001599918
anRef[i] = p->nRef;
10001699919
}
10001799920
sqlite3WalkExpr(pWalker, pExpr->pLeft);
10001899921
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
99922
+ testcase( ExprHasProperty(pExpr, EP_FromJoin) );
10001999923
if( pExpr->op==TK_NOTNULL ){
10002099924
pExpr->u.zToken = "true";
10002199925
ExprSetProperty(pExpr, EP_IsTrue);
10002299926
}else{
10002399927
pExpr->u.zToken = "false";
@@ -100283,13 +100187,16 @@
100283100187
pNC2 = pNC2->pNext;
100284100188
}
100285100189
assert( pDef!=0 || IN_RENAME_OBJECT );
100286100190
if( pNC2 && pDef ){
100287100191
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
100192
+ assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
100288100193
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
100289
- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
100290
-
100194
+ testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 );
100195
+ pNC2->ncFlags |= NC_HasAgg
100196
+ | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER)
100197
+ & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER));
100291100198
}
100292100199
}
100293100200
pNC->ncFlags |= savedAllowFlags;
100294100201
}
100295100202
/* FIX ME: Compute pExpr->affinity based on the expected return
@@ -100828,11 +100735,11 @@
100828100735
assert( pSub->pPrior && pSub->pOrderBy==0 );
100829100736
pSub->pOrderBy = p->pOrderBy;
100830100737
p->pOrderBy = 0;
100831100738
}
100832100739
100833
- /* Recursively resolve names in all subqueries
100740
+ /* Recursively resolve names in all subqueries in the FROM clause
100834100741
*/
100835100742
for(i=0; i<p->pSrc->nSrc; i++){
100836100743
SrcItem *pItem = &p->pSrc->a[i];
100837100744
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
100838100745
int nRef = pOuterNC ? pOuterNC->nRef : 0;
@@ -100872,11 +100779,12 @@
100872100779
*/
100873100780
assert( (p->selFlags & SF_Aggregate)==0 );
100874100781
pGroupBy = p->pGroupBy;
100875100782
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
100876100783
assert( NC_MinMaxAgg==SF_MinMaxAgg );
100877
- p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
100784
+ assert( NC_OrderAgg==SF_OrderByReqd );
100785
+ p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg));
100878100786
}else{
100879100787
sNC.ncFlags &= ~NC_AllowAgg;
100880100788
}
100881100789
100882100790
/* Add the output column list to the name-context before parsing the
@@ -101055,12 +100963,12 @@
101055100963
){
101056100964
int savedHasAgg;
101057100965
Walker w;
101058100966
101059100967
if( pExpr==0 ) return SQLITE_OK;
101060
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101061
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
100968
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
100969
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101062100970
w.pParse = pNC->pParse;
101063100971
w.xExprCallback = resolveExprStep;
101064100972
w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
101065100973
w.xSelectCallback2 = 0;
101066100974
w.u.pNC = pNC;
@@ -101099,12 +101007,12 @@
101099101007
w.pParse = pNC->pParse;
101100101008
w.xExprCallback = resolveExprStep;
101101101009
w.xSelectCallback = resolveSelectStep;
101102101010
w.xSelectCallback2 = 0;
101103101011
w.u.pNC = pNC;
101104
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101105
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101012
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101013
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101106101014
for(i=0; i<pList->nExpr; i++){
101107101015
Expr *pExpr = pList->a[i].pExpr;
101108101016
if( pExpr==0 ) continue;
101109101017
#if SQLITE_MAX_EXPR_DEPTH>0
101110101018
w.pParse->nHeight += pExpr->nHeight;
@@ -101118,14 +101026,15 @@
101118101026
#endif
101119101027
assert( EP_Agg==NC_HasAgg );
101120101028
assert( EP_Win==NC_HasWin );
101121101029
testcase( pNC->ncFlags & NC_HasAgg );
101122101030
testcase( pNC->ncFlags & NC_HasWin );
101123
- if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
101031
+ if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){
101124101032
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
101125
- savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101126
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101033
+ savedHasAgg |= pNC->ncFlags &
101034
+ (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101035
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101127101036
}
101128101037
if( w.pParse->nErr>0 ) return WRC_Abort;
101129101038
}
101130101039
pNC->ncFlags |= savedHasAgg;
101131101040
return WRC_Continue;
@@ -101285,10 +101194,12 @@
101285101194
return sqlite3AffinityType(pExpr->u.zToken, 0);
101286101195
}
101287101196
#endif
101288101197
if( op==TK_SELECT_COLUMN ){
101289101198
assert( pExpr->pLeft->flags&EP_xIsSelect );
101199
+ assert( pExpr->iColumn < pExpr->iTable );
101200
+ assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr );
101290101201
return sqlite3ExprAffinity(
101291101202
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
101292101203
);
101293101204
}
101294101205
if( op==TK_VECTOR ){
@@ -101385,11 +101296,11 @@
101385101296
){
101386101297
/* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
101387101298
** a TK_COLUMN but was previously evaluated and cached in a register */
101388101299
int j = p->iColumn;
101389101300
if( j>=0 ){
101390
- const char *zColl = p->y.pTab->aCol[j].zColl;
101301
+ const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
101391101302
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
101392101303
}
101393101304
break;
101394101305
}
101395101306
if( op==TK_CAST || op==TK_UPLUS ){
@@ -101695,11 +101606,12 @@
101695101606
** of the returned TK_SELECT_COLUMN Expr object.
101696101607
*/
101697101608
SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
101698101609
Parse *pParse, /* Parsing context */
101699101610
Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
101700
- int iField /* Which column of the vector to return */
101611
+ int iField, /* Which column of the vector to return */
101612
+ int nField /* Total number of columns in the vector */
101701101613
){
101702101614
Expr *pRet;
101703101615
if( pVector->op==TK_SELECT ){
101704101616
assert( pVector->flags & EP_xIsSelect );
101705101617
/* The TK_SELECT_COLUMN Expr node:
@@ -101718,14 +101630,14 @@
101718101630
** with the same pLeft pointer to the pVector, but only one of them
101719101631
** will own the pVector.
101720101632
*/
101721101633
pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
101722101634
if( pRet ){
101635
+ pRet->iTable = nField;
101723101636
pRet->iColumn = iField;
101724101637
pRet->pLeft = pVector;
101725101638
}
101726
- assert( pRet==0 || pRet->iTable==0 );
101727101639
}else{
101728101640
if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
101729101641
pRet = sqlite3ExprDup(pParse->db, pVector, 0);
101730101642
sqlite3RenameTokenRemap(pParse, pRet, pVector);
101731101643
}
@@ -102156,10 +102068,60 @@
102156102068
assert( pParse->db->mallocFailed );
102157102069
sqlite3SelectDelete(pParse->db, pSelect);
102158102070
}
102159102071
}
102160102072
102073
+/*
102074
+** Expression list pEList is a list of vector values. This function
102075
+** converts the contents of pEList to a VALUES(...) Select statement
102076
+** returning 1 row for each element of the list. For example, the
102077
+** expression list:
102078
+**
102079
+** ( (1,2), (3,4) (5,6) )
102080
+**
102081
+** is translated to the equivalent of:
102082
+**
102083
+** VALUES(1,2), (3,4), (5,6)
102084
+**
102085
+** Each of the vector values in pEList must contain exactly nElem terms.
102086
+** If a list element that is not a vector or does not contain nElem terms,
102087
+** an error message is left in pParse.
102088
+**
102089
+** This is used as part of processing IN(...) expressions with a list
102090
+** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))".
102091
+*/
102092
+SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
102093
+ int ii;
102094
+ Select *pRet = 0;
102095
+ assert( nElem>1 );
102096
+ for(ii=0; ii<pEList->nExpr; ii++){
102097
+ Select *pSel;
102098
+ Expr *pExpr = pEList->a[ii].pExpr;
102099
+ int nExprElem = (pExpr->op==TK_VECTOR ? pExpr->x.pList->nExpr : 1);
102100
+ if( nExprElem!=nElem ){
102101
+ sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d",
102102
+ nExprElem, nExprElem>1?"s":"", nElem
102103
+ );
102104
+ break;
102105
+ }
102106
+ pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
102107
+ pExpr->x.pList = 0;
102108
+ if( pSel ){
102109
+ if( pRet ){
102110
+ pSel->op = TK_ALL;
102111
+ pSel->pPrior = pRet;
102112
+ }
102113
+ pRet = pSel;
102114
+ }
102115
+ }
102116
+
102117
+ if( pRet && pRet->pPrior ){
102118
+ pRet->selFlags |= SF_MultiValue;
102119
+ }
102120
+ sqlite3ExprListDelete(pParse->db, pEList);
102121
+ return pRet;
102122
+}
102161102123
102162102124
/*
102163102125
** Join two expressions using an AND operator. If either expression is
102164102126
** NULL, then just return the other expression.
102165102127
**
@@ -102200,11 +102162,14 @@
102200102162
pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
102201102163
if( pNew==0 ){
102202102164
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
102203102165
return 0;
102204102166
}
102205
- if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
102167
+ if( pList
102168
+ && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
102169
+ && !pParse->nested
102170
+ ){
102206102171
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
102207102172
}
102208102173
pNew->x.pList = pList;
102209102174
ExprSetProperty(pNew, EP_HasFunc);
102210102175
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
@@ -102608,11 +102573,10 @@
102608102573
}
102609102574
}else{
102610102575
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
102611102576
if( pNew->op==TK_SELECT_COLUMN ){
102612102577
pNew->pLeft = p->pLeft;
102613
- assert( p->iColumn==0 || p->pRight==0 );
102614102578
assert( p->pRight==0 || p->pRight==p->pLeft
102615102579
|| ExprHasProperty(p->pLeft, EP_Subquery) );
102616102580
}else{
102617102581
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
102618102582
}
@@ -102706,11 +102670,12 @@
102706102670
}
102707102671
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
102708102672
ExprList *pNew;
102709102673
struct ExprList_item *pItem, *pOldItem;
102710102674
int i;
102711
- Expr *pPriorSelectCol = 0;
102675
+ Expr *pPriorSelectColOld = 0;
102676
+ Expr *pPriorSelectColNew = 0;
102712102677
assert( db!=0 );
102713102678
if( p==0 ) return 0;
102714102679
pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
102715102680
if( pNew==0 ) return 0;
102716102681
pNew->nExpr = p->nExpr;
@@ -102723,21 +102688,21 @@
102723102688
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
102724102689
if( pOldExpr
102725102690
&& pOldExpr->op==TK_SELECT_COLUMN
102726102691
&& (pNewExpr = pItem->pExpr)!=0
102727102692
){
102728
- assert( pNewExpr->iColumn==0 || i>0 );
102729
- if( pNewExpr->iColumn==0 ){
102730
- assert( pOldExpr->pLeft==pOldExpr->pRight
102731
- || ExprHasProperty(pOldExpr->pLeft, EP_Subquery) );
102732
- pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
102693
+ if( pNewExpr->pRight ){
102694
+ pPriorSelectColOld = pOldExpr->pRight;
102695
+ pPriorSelectColNew = pNewExpr->pRight;
102696
+ pNewExpr->pLeft = pNewExpr->pRight;
102733102697
}else{
102734
- assert( i>0 );
102735
- assert( pItem[-1].pExpr!=0 );
102736
- assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
102737
- assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
102738
- pNewExpr->pLeft = pPriorSelectCol;
102698
+ if( pOldExpr->pLeft!=pPriorSelectColOld ){
102699
+ pPriorSelectColOld = pOldExpr->pLeft;
102700
+ pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags);
102701
+ pNewExpr->pRight = pPriorSelectColNew;
102702
+ }
102703
+ pNewExpr->pLeft = pPriorSelectColNew;
102739102704
}
102740102705
}
102741102706
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
102742102707
pItem->sortFlags = pOldItem->sortFlags;
102743102708
pItem->eEName = pOldItem->eEName;
@@ -102992,15 +102957,13 @@
102992102957
pColumns->nId, n);
102993102958
goto vector_append_error;
102994102959
}
102995102960
102996102961
for(i=0; i<pColumns->nId; i++){
102997
- Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
102962
+ Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId);
102998102963
assert( pSubExpr!=0 || db->mallocFailed );
102999
- assert( pSubExpr==0 || pSubExpr->iTable==0 );
103000102964
if( pSubExpr==0 ) continue;
103001
- pSubExpr->iTable = pColumns->nId;
103002102965
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
103003102966
if( pList ){
103004102967
assert( pList->nExpr==iFirst+i+1 );
103005102968
pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
103006102969
pColumns->a[i].zName = 0;
@@ -103673,11 +103636,11 @@
103673103636
assert( pSrc!=0 );
103674103637
if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
103675103638
if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
103676103639
pTab = pSrc->a[0].pTab;
103677103640
assert( pTab!=0 );
103678
- assert( pTab->pSelect==0 ); /* FROM clause is not a view */
103641
+ assert( !IsView(pTab) ); /* FROM clause is not a view */
103679103642
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
103680103643
pEList = p->pEList;
103681103644
assert( pEList!=0 );
103682103645
/* All SELECT results must be columns. */
103683103646
for(i=0; i<pEList->nExpr; i++){
@@ -104803,13 +104766,14 @@
104803104766
/*
104804104767
** Generate code that will compute the value of generated column pCol
104805104768
** and store the result in register regOut
104806104769
*/
104807104770
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
104808
- Parse *pParse,
104809
- Column *pCol,
104810
- int regOut
104771
+ Parse *pParse, /* Parsing context */
104772
+ Table *pTab, /* Table containing the generated column */
104773
+ Column *pCol, /* The generated column */
104774
+ int regOut /* Put the result in this register */
104811104775
){
104812104776
int iAddr;
104813104777
Vdbe *v = pParse->pVdbe;
104814104778
assert( v!=0 );
104815104779
assert( pParse->iSelfTab!=0 );
@@ -104816,11 +104780,11 @@
104816104780
if( pParse->iSelfTab>0 ){
104817104781
iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
104818104782
}else{
104819104783
iAddr = 0;
104820104784
}
104821
- sqlite3ExprCodeCopy(pParse, pCol->pDflt, regOut);
104785
+ sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
104822104786
if( pCol->affinity>=SQLITE_AFF_TEXT ){
104823104787
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
104824104788
}
104825104789
if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
104826104790
}
@@ -104852,16 +104816,17 @@
104852104816
x = iCol;
104853104817
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
104854104818
}else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
104855104819
Parse *pParse = sqlite3VdbeParser(v);
104856104820
if( pCol->colFlags & COLFLAG_BUSY ){
104857
- sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName);
104821
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
104822
+ pCol->zCnName);
104858104823
}else{
104859104824
int savedSelfTab = pParse->iSelfTab;
104860104825
pCol->colFlags |= COLFLAG_BUSY;
104861104826
pParse->iSelfTab = iTabCur+1;
104862
- sqlite3ExprCodeGeneratedColumn(pParse, pCol, regOut);
104827
+ sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut);
104863104828
pParse->iSelfTab = savedSelfTab;
104864104829
pCol->colFlags &= ~COLFLAG_BUSY;
104865104830
}
104866104831
return;
104867104832
#endif
@@ -105125,11 +105090,12 @@
105125105090
sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
105126105091
pCol->iSorterColumn, target);
105127105092
if( pCol->iColumn<0 ){
105128105093
VdbeComment((v,"%s.rowid",pTab->zName));
105129105094
}else{
105130
- VdbeComment((v,"%s.%s",pTab->zName,pTab->aCol[pCol->iColumn].zName));
105095
+ VdbeComment((v,"%s.%s",
105096
+ pTab->zName, pTab->aCol[pCol->iColumn].zCnName));
105131105097
if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
105132105098
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
105133105099
}
105134105100
}
105135105101
return target;
@@ -105186,16 +105152,16 @@
105186105152
iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
105187105153
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
105188105154
if( pCol->colFlags & COLFLAG_GENERATED ){
105189105155
if( pCol->colFlags & COLFLAG_BUSY ){
105190105156
sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
105191
- pCol->zName);
105157
+ pCol->zCnName);
105192105158
return 0;
105193105159
}
105194105160
pCol->colFlags |= COLFLAG_BUSY;
105195105161
if( pCol->colFlags & COLFLAG_NOTAVAIL ){
105196
- sqlite3ExprCodeGeneratedColumn(pParse, pCol, iSrc);
105162
+ sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc);
105197105163
}
105198105164
pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
105199105165
return iSrc;
105200105166
}else
105201105167
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
@@ -105586,15 +105552,13 @@
105586105552
case TK_SELECT_COLUMN: {
105587105553
int n;
105588105554
if( pExpr->pLeft->iTable==0 ){
105589105555
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
105590105556
}
105591
- assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT
105592
- || pExpr->pLeft->op==TK_ERROR );
105593
- if( pExpr->iTable!=0
105594
- && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
105595
- ){
105557
+ assert( pExpr->pLeft->op==TK_SELECT || pExpr->pLeft->op==TK_ERROR );
105558
+ n = sqlite3ExprVectorSize(pExpr->pLeft);
105559
+ if( pExpr->iTable!=n ){
105596105560
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
105597105561
pExpr->iTable, n);
105598105562
}
105599105563
return pExpr->pLeft->iTable + pExpr->iColumn;
105600105564
}
@@ -105671,11 +105635,11 @@
105671105635
assert( p1>=0 && p1<(pTab->nCol*2+2) );
105672105636
105673105637
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
105674105638
VdbeComment((v, "r[%d]=%s.%s", target,
105675105639
(pExpr->iTable ? "new" : "old"),
105676
- (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zName)
105640
+ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zCnName)
105677105641
));
105678105642
105679105643
#ifndef SQLITE_OMIT_FLOATING_POINT
105680105644
/* If the column has REAL affinity, it may currently be stored as an
105681105645
** integer. Use OP_RealAffinity to make sure it is really real.
@@ -106843,13 +106807,13 @@
106843106807
testcase( pExpr->op==TK_LE );
106844106808
testcase( pExpr->op==TK_GT );
106845106809
testcase( pExpr->op==TK_GE );
106846106810
/* The y.pTab=0 assignment in wherecode.c always happens after the
106847106811
** impliesNotNullRow() test */
106848
- if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0)
106812
+ if( (pLeft->op==TK_COLUMN && pLeft->y.pTab!=0
106849106813
&& IsVirtual(pLeft->y.pTab))
106850
- || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0)
106814
+ || (pRight->op==TK_COLUMN && pRight->y.pTab!=0
106851106815
&& IsVirtual(pRight->y.pTab))
106852106816
){
106853106817
return WRC_Prune;
106854106818
}
106855106819
/* no break */ deliberate_fall_through
@@ -107524,22 +107488,19 @@
107524107488
sqlite3 *db = pParse->db; /* Database connection */
107525107489
int nTabName; /* Number of UTF-8 characters in zTabName */
107526107490
const char *zTabName; /* Original name of the table */
107527107491
Vdbe *v;
107528107492
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
107529
- u32 savedDbFlags; /* Saved value of db->mDbFlags */
107530107493
107531
- savedDbFlags = db->mDbFlags;
107532107494
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
107533107495
assert( pSrc->nSrc==1 );
107534107496
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
107535107497
107536107498
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
107537107499
if( !pTab ) goto exit_rename_table;
107538107500
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
107539107501
zDb = db->aDb[iDb].zDbSName;
107540
- db->mDbFlags |= DBFLAG_PreferBuiltin;
107541107502
107542107503
/* Get a NULL terminated version of the new table name. */
107543107504
zName = sqlite3NameFromToken(db, pName);
107544107505
if( !zName ) goto exit_rename_table;
107545107506
@@ -107564,11 +107525,11 @@
107564107525
if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
107565107526
goto exit_rename_table;
107566107527
}
107567107528
107568107529
#ifndef SQLITE_OMIT_VIEW
107569
- if( pTab->pSelect ){
107530
+ if( IsView(pTab) ){
107570107531
sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
107571107532
goto exit_rename_table;
107572107533
}
107573107534
#endif
107574107535
@@ -107676,11 +107637,10 @@
107676107637
renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);
107677107638
107678107639
exit_rename_table:
107679107640
sqlite3SrcListDelete(db, pSrc);
107680107641
sqlite3DbFree(db, zName);
107681
- db->mDbFlags = savedDbFlags;
107682107642
}
107683107643
107684107644
/*
107685107645
** Write code that will raise an error if the table described by
107686107646
** zDb and zTab is not empty.
@@ -107726,11 +107686,11 @@
107726107686
assert( sqlite3BtreeHoldsAllMutexes(db) );
107727107687
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
107728107688
zDb = db->aDb[iDb].zDbSName;
107729107689
zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
107730107690
pCol = &pNew->aCol[pNew->nCol-1];
107731
- pDflt = pCol->pDflt;
107691
+ pDflt = sqlite3ColumnExpr(pNew, pCol);
107732107692
pTab = sqlite3FindTable(db, zTab, zDb);
107733107693
assert( pTab );
107734107694
107735107695
#ifndef SQLITE_OMIT_AUTHORIZATION
107736107696
/* Invoke the authorization callback. */
@@ -107760,11 +107720,11 @@
107760107720
*/
107761107721
assert( pDflt==0 || pDflt->op==TK_SPAN );
107762107722
if( pDflt && pDflt->pLeft->op==TK_NULL ){
107763107723
pDflt = 0;
107764107724
}
107765
- if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
107725
+ if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
107766107726
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
107767107727
"Cannot add a REFERENCES column with non-NULL default value");
107768107728
}
107769107729
if( pCol->notNull && !pDflt ){
107770107730
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
@@ -107797,47 +107757,60 @@
107797107757
107798107758
/* Modify the CREATE TABLE statement. */
107799107759
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
107800107760
if( zCol ){
107801107761
char *zEnd = &zCol[pColDef->n-1];
107802
- u32 savedDbFlags = db->mDbFlags;
107803107762
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
107804107763
*zEnd-- = '\0';
107805107764
}
107806
- db->mDbFlags |= DBFLAG_PreferBuiltin;
107807107765
/* substr() operations on characters, but addColOffset is in bytes. So we
107808107766
** have to use printf() to translate between these units: */
107767
+ assert( !IsVirtual(pTab) );
107809107768
sqlite3NestedParse(pParse,
107810107769
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
107811107770
"sql = printf('%%.%ds, ',sql) || %Q"
107812107771
" || substr(sql,1+length(printf('%%.%ds',sql))) "
107813107772
"WHERE type = 'table' AND name = %Q",
107814
- zDb, pNew->addColOffset, zCol, pNew->addColOffset,
107773
+ zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,
107815107774
zTab
107816107775
);
107817107776
sqlite3DbFree(db, zCol);
107818
- db->mDbFlags = savedDbFlags;
107819107777
}
107820107778
107821
- /* Make sure the schema version is at least 3. But do not upgrade
107822
- ** from less than 3 to 4, as that will corrupt any preexisting DESC
107823
- ** index.
107824
- */
107825107779
v = sqlite3GetVdbe(pParse);
107826107780
if( v ){
107781
+ /* Make sure the schema version is at least 3. But do not upgrade
107782
+ ** from less than 3 to 4, as that will corrupt any preexisting DESC
107783
+ ** index.
107784
+ */
107827107785
r1 = sqlite3GetTempReg(pParse);
107828107786
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
107829107787
sqlite3VdbeUsesBtree(v, iDb);
107830107788
sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
107831107789
sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
107832107790
VdbeCoverage(v);
107833107791
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
107834107792
sqlite3ReleaseTempReg(pParse, r1);
107793
+
107794
+ /* Reload the table definition */
107795
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
107796
+
107797
+ /* Verify that constraints are still satisfied */
107798
+ if( pNew->pCheck!=0
107799
+ || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)
107800
+ ){
107801
+ sqlite3NestedParse(pParse,
107802
+ "SELECT CASE WHEN quick_check GLOB 'CHECK*'"
107803
+ " THEN raise(ABORT,'CHECK constraint failed')"
107804
+ " ELSE raise(ABORT,'NOT NULL constraint failed')"
107805
+ " END"
107806
+ " FROM pragma_quick_check(\"%w\",\"%w\")"
107807
+ " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'",
107808
+ zTab, zDb
107809
+ );
107810
+ }
107835107811
}
107836
-
107837
- /* Reload the table definition */
107838
- renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
107839107812
}
107840107813
107841107814
/*
107842107815
** This function is called by the parser after the table-name in
107843107816
** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
@@ -107874,20 +107847,20 @@
107874107847
goto exit_begin_add_column;
107875107848
}
107876107849
#endif
107877107850
107878107851
/* Make sure this is not an attempt to ALTER a view. */
107879
- if( pTab->pSelect ){
107852
+ if( IsView(pTab) ){
107880107853
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
107881107854
goto exit_begin_add_column;
107882107855
}
107883107856
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
107884107857
goto exit_begin_add_column;
107885107858
}
107886107859
107887107860
sqlite3MayAbort(pParse);
107888
- assert( pTab->addColOffset>0 );
107861
+ assert( pTab->u.tab.addColOffset>0 );
107889107862
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
107890107863
107891107864
/* Put a copy of the Table struct in Parse.pNewTable for the
107892107865
** sqlite3AddColumn() function and friends to modify. But modify
107893107866
** the name by adding an "sqlite_altertab_" prefix. By adding this
@@ -107910,17 +107883,17 @@
107910107883
goto exit_begin_add_column;
107911107884
}
107912107885
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
107913107886
for(i=0; i<pNew->nCol; i++){
107914107887
Column *pCol = &pNew->aCol[i];
107915
- pCol->zName = sqlite3DbStrDup(db, pCol->zName);
107916
- pCol->hName = sqlite3StrIHash(pCol->zName);
107917
- pCol->zColl = 0;
107918
- pCol->pDflt = 0;
107888
+ pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
107889
+ pCol->hName = sqlite3StrIHash(pCol->zCnName);
107919107890
}
107891
+ assert( !IsVirtual(pNew) );
107892
+ pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
107920107893
pNew->pSchema = db->aDb[iDb].pSchema;
107921
- pNew->addColOffset = pTab->addColOffset;
107894
+ pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;
107922107895
pNew->nTabRef = 1;
107923107896
107924107897
exit_begin_add_column:
107925107898
sqlite3SrcListDelete(db, pSrc);
107926107899
return;
@@ -107936,11 +107909,11 @@
107936107909
*/
107937107910
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
107938107911
static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
107939107912
const char *zType = 0;
107940107913
#ifndef SQLITE_OMIT_VIEW
107941
- if( pTab->pSelect ){
107914
+ if( IsView(pTab) ){
107942107915
zType = "view";
107943107916
}
107944107917
#endif
107945107918
#ifndef SQLITE_OMIT_VIRTUALTABLE
107946107919
if( IsVirtual(pTab) ){
@@ -108003,11 +107976,11 @@
108003107976
/* Make sure the old name really is a column name in the table to be
108004107977
** altered. Set iCol to be the index of the column being renamed */
108005107978
zOld = sqlite3NameFromToken(db, pOld);
108006107979
if( !zOld ) goto exit_rename_column;
108007107980
for(iCol=0; iCol<pTab->nCol; iCol++){
108008
- if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
107981
+ if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
108009107982
}
108010107983
if( iCol==pTab->nCol ){
108011107984
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
108012107985
goto exit_rename_column;
108013107986
}
@@ -108240,12 +108213,12 @@
108240108213
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
108241108214
Parse *pParse = pWalker->pParse;
108242108215
int i;
108243108216
if( pParse->nErr ) return WRC_Abort;
108244108217
if( p->selFlags & (SF_View|SF_CopyCte) ){
108245
- testcase( pSelect->selFlags & SF_View );
108246
- testcase( pSelect->selFlags & SF_CopyCte );
108218
+ testcase( p->selFlags & SF_View );
108219
+ testcase( p->selFlags & SF_CopyCte );
108247108220
return WRC_Prune;
108248108221
}
108249108222
if( ALWAYS(p->pEList) ){
108250108223
ExprList *pList = p->pEList;
108251108224
for(i=0; i<pList->nExpr; i++){
@@ -108352,12 +108325,12 @@
108352108325
** because without a dummy callback, sqlite3WalkExpr() and similar do not
108353108326
** descend into sub-select statements.
108354108327
*/
108355108328
static int renameColumnSelectCb(Walker *pWalker, Select *p){
108356108329
if( p->selFlags & (SF_View|SF_CopyCte) ){
108357
- testcase( pSelect->selFlags & SF_View );
108358
- testcase( pSelect->selFlags & SF_CopyCte );
108330
+ testcase( p->selFlags & SF_View );
108331
+ testcase( p->selFlags & SF_CopyCte );
108359108332
return WRC_Prune;
108360108333
}
108361108334
renameWalkWith(pWalker, p);
108362108335
return WRC_Continue;
108363108336
}
@@ -108549,17 +108522,17 @@
108549108522
RenameCtx *pRename, /* Rename context */
108550108523
const char *zSql, /* SQL statement to edit */
108551108524
const char *zNew, /* New token text */
108552108525
int bQuote /* True to always quote token */
108553108526
){
108554
- int nNew = sqlite3Strlen30(zNew);
108555
- int nSql = sqlite3Strlen30(zSql);
108527
+ i64 nNew = sqlite3Strlen30(zNew);
108528
+ i64 nSql = sqlite3Strlen30(zSql);
108556108529
sqlite3 *db = sqlite3_context_db_handle(pCtx);
108557108530
int rc = SQLITE_OK;
108558108531
char *zQuot = 0;
108559108532
char *zOut;
108560
- int nQuot = 0;
108533
+ i64 nQuot = 0;
108561108534
char *zBuf1 = 0;
108562108535
char *zBuf2 = 0;
108563108536
108564108537
if( zNew ){
108565108538
/* Set zQuot to point to a buffer containing a quoted copy of the
@@ -108849,11 +108822,11 @@
108849108822
pTab = sqlite3FindTable(db, zTable, zDb);
108850108823
if( pTab==0 || iCol>=pTab->nCol ){
108851108824
sqlite3BtreeLeaveAll(db);
108852108825
return;
108853108826
}
108854
- zOld = pTab->aCol[iCol].zName;
108827
+ zOld = pTab->aCol[iCol].zCnName;
108855108828
memset(&sCtx, 0, sizeof(sCtx));
108856108829
sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);
108857108830
108858108831
#ifndef SQLITE_OMIT_AUTHORIZATION
108859108832
db->xAuth = 0;
@@ -108868,30 +108841,29 @@
108868108841
sWalker.u.pRename = &sCtx;
108869108842
108870108843
sCtx.pTab = pTab;
108871108844
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
108872108845
if( sParse.pNewTable ){
108873
- Select *pSelect = sParse.pNewTable->pSelect;
108874
- if( pSelect ){
108846
+ if( IsView(sParse.pNewTable) ){
108847
+ Select *pSelect = sParse.pNewTable->u.view.pSelect;
108875108848
pSelect->selFlags &= ~SF_View;
108876108849
sParse.rc = SQLITE_OK;
108877108850
sqlite3SelectPrep(&sParse, pSelect, 0);
108878108851
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
108879108852
if( rc==SQLITE_OK ){
108880108853
sqlite3WalkSelect(&sWalker, pSelect);
108881108854
}
108882108855
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
108883
- }else{
108856
+ }else if( ALWAYS(IsOrdinaryTable(sParse.pNewTable)) ){
108884108857
/* A regular table */
108885108858
int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
108886108859
FKey *pFKey;
108887
- assert( sParse.pNewTable->pSelect==0 );
108888108860
sCtx.pTab = sParse.pNewTable;
108889108861
if( bFKOnly==0 ){
108890108862
if( iCol<sParse.pNewTable->nCol ){
108891108863
renameTokenFind(
108892
- &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
108864
+ &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName
108893108865
);
108894108866
}
108895108867
if( sCtx.iCol<0 ){
108896108868
renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
108897108869
}
@@ -108902,16 +108874,19 @@
108902108874
for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
108903108875
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
108904108876
}
108905108877
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
108906108878
for(i=0; i<sParse.pNewTable->nCol; i++){
108907
- sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
108879
+ Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable,
108880
+ &sParse.pNewTable->aCol[i]);
108881
+ sqlite3WalkExpr(&sWalker, pExpr);
108908108882
}
108909108883
#endif
108910108884
}
108911108885
108912
- for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
108886
+ assert( !IsVirtual(sParse.pNewTable) );
108887
+ for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
108913108888
for(i=0; i<pFKey->nCol; i++){
108914108889
if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
108915108890
renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
108916108891
}
108917108892
if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
@@ -109073,32 +109048,35 @@
109073109048
if( rc==SQLITE_OK ){
109074109049
int isLegacy = (db->flags & SQLITE_LegacyAlter);
109075109050
if( sParse.pNewTable ){
109076109051
Table *pTab = sParse.pNewTable;
109077109052
109078
- if( pTab->pSelect ){
109053
+ if( IsView(pTab) ){
109079109054
if( isLegacy==0 ){
109080
- Select *pSelect = pTab->pSelect;
109055
+ Select *pSelect = pTab->u.view.pSelect;
109081109056
NameContext sNC;
109082109057
memset(&sNC, 0, sizeof(sNC));
109083109058
sNC.pParse = &sParse;
109084109059
109085109060
assert( pSelect->selFlags & SF_View );
109086109061
pSelect->selFlags &= ~SF_View;
109087
- sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
109062
+ sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
109088109063
if( sParse.nErr ){
109089109064
rc = sParse.rc;
109090109065
}else{
109091
- sqlite3WalkSelect(&sWalker, pTab->pSelect);
109066
+ sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect);
109092109067
}
109093109068
}
109094109069
}else{
109095109070
/* Modify any FK definitions to point to the new table. */
109096109071
#ifndef SQLITE_OMIT_FOREIGN_KEY
109097
- if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){
109072
+ if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
109073
+ && !IsVirtual(pTab)
109074
+ ){
109098109075
FKey *pFKey;
109099
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
109076
+ assert( !IsVirtual(pTab) );
109077
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
109100109078
if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
109101109079
renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
109102109080
}
109103109081
}
109104109082
}
@@ -109234,12 +109212,12 @@
109234109212
sWalker.xExprCallback = renameQuotefixExprCb;
109235109213
sWalker.xSelectCallback = renameColumnSelectCb;
109236109214
sWalker.u.pRename = &sCtx;
109237109215
109238109216
if( sParse.pNewTable ){
109239
- Select *pSelect = sParse.pNewTable->pSelect;
109240
- if( pSelect ){
109217
+ if( IsView(sParse.pNewTable) ){
109218
+ Select *pSelect = sParse.pNewTable->u.view.pSelect;
109241109219
pSelect->selFlags &= ~SF_View;
109242109220
sParse.rc = SQLITE_OK;
109243109221
sqlite3SelectPrep(&sParse, pSelect, 0);
109244109222
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
109245109223
if( rc==SQLITE_OK ){
@@ -109248,11 +109226,13 @@
109248109226
}else{
109249109227
int i;
109250109228
sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
109251109229
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
109252109230
for(i=0; i<sParse.pNewTable->nCol; i++){
109253
- sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
109231
+ sqlite3WalkExpr(&sWalker,
109232
+ sqlite3ColumnExpr(sParse.pNewTable,
109233
+ &sParse.pNewTable->aCol[i]));
109254109234
}
109255109235
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
109256109236
}
109257109237
}else if( sParse.pNewIndex ){
109258109238
sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
@@ -109331,15 +109311,15 @@
109331109311
int flags = db->flags;
109332109312
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
109333109313
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
109334109314
db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
109335109315
if( rc==SQLITE_OK ){
109336
- if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
109316
+ if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
109337109317
NameContext sNC;
109338109318
memset(&sNC, 0, sizeof(sNC));
109339109319
sNC.pParse = &sParse;
109340
- sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
109320
+ sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC);
109341109321
if( sParse.nErr ) rc = sParse.rc;
109342109322
}
109343109323
109344109324
else if( sParse.pNewTrigger ){
109345109325
if( isLegacy==0 ){
@@ -109406,17 +109386,18 @@
109406109386
/* This can happen if the sqlite_schema table is corrupt */
109407109387
rc = SQLITE_CORRUPT_BKPT;
109408109388
goto drop_column_done;
109409109389
}
109410109390
109411
- pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zName);
109391
+ pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
109412109392
if( iCol<pTab->nCol-1 ){
109413109393
RenameToken *pEnd;
109414
- pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName);
109394
+ pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
109415109395
zEnd = (const char*)pEnd->t.z;
109416109396
}else{
109417
- zEnd = (const char*)&zSql[pTab->addColOffset];
109397
+ assert( !IsVirtual(pTab) );
109398
+ zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
109418109399
while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
109419109400
}
109420109401
109421109402
zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
109422109403
sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
@@ -109547,10 +109528,16 @@
109547109528
}else{
109548109529
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
109549109530
}
109550109531
nField++;
109551109532
}
109533
+ }
109534
+ if( nField==0 ){
109535
+ /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */
109536
+ pParse->nMem++;
109537
+ sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1);
109538
+ nField = 1;
109552109539
}
109553109540
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
109554109541
if( pPk ){
109555109542
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
109556109543
}else{
@@ -110552,11 +110539,11 @@
110552110539
if( NEVER(i==XN_ROWID) ){
110553110540
VdbeComment((v,"%s.rowid",pIdx->zName));
110554110541
}else if( i==XN_EXPR ){
110555110542
VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
110556110543
}else{
110557
- VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zName));
110544
+ VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
110558110545
}
110559110546
}
110560110547
#else
110561110548
# define analyzeVdbeCommentIndexWithColumnName(a,b,c)
110562110549
#endif /* SQLITE_DEBUG */
@@ -112305,14 +112292,14 @@
112305112292
iCol = pExpr->iColumn;
112306112293
if( pTab==0 ) return;
112307112294
112308112295
if( iCol>=0 ){
112309112296
assert( iCol<pTab->nCol );
112310
- zCol = pTab->aCol[iCol].zName;
112297
+ zCol = pTab->aCol[iCol].zCnName;
112311112298
}else if( pTab->iPKey>=0 ){
112312112299
assert( pTab->iPKey<pTab->nCol );
112313
- zCol = pTab->aCol[pTab->iPKey].zName;
112300
+ zCol = pTab->aCol[pTab->iPKey].zCnName;
112314112301
}else{
112315112302
zCol = "ROWID";
112316112303
}
112317112304
assert( iDb>=0 && iDb<pParse->db->nDb );
112318112305
if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
@@ -112686,24 +112673,26 @@
112686112673
}
112687112674
112688112675
/*
112689112676
** Run the parser and code generator recursively in order to generate
112690112677
** code for the SQL statement given onto the end of the pParse context
112691
-** currently under construction. When the parser is run recursively
112692
-** this way, the final OP_Halt is not appended and other initialization
112693
-** and finalization steps are omitted because those are handling by the
112694
-** outermost parser.
112678
+** currently under construction. Notes:
112695112679
**
112696
-** Not everything is nestable. This facility is designed to permit
112697
-** INSERT, UPDATE, and DELETE operations against the schema table. Use
112698
-** care if you decide to try to use this routine for some other purposes.
112680
+** * The final OP_Halt is not appended and other initialization
112681
+** and finalization steps are omitted because those are handling by the
112682
+** outermost parser.
112683
+**
112684
+** * Built-in SQL functions always take precedence over application-defined
112685
+** SQL functions. In other words, it is not possible to override a
112686
+** built-in function.
112699112687
*/
112700112688
SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
112701112689
va_list ap;
112702112690
char *zSql;
112703112691
char *zErrMsg = 0;
112704112692
sqlite3 *db = pParse->db;
112693
+ u32 savedDbFlags = db->mDbFlags;
112705112694
char saveBuf[PARSE_TAIL_SZ];
112706112695
112707112696
if( pParse->nErr ) return;
112708112697
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
112709112698
va_start(ap, zFormat);
@@ -112718,11 +112707,13 @@
112718112707
return;
112719112708
}
112720112709
pParse->nested++;
112721112710
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
112722112711
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
112712
+ db->mDbFlags |= DBFLAG_PreferBuiltin;
112723112713
sqlite3RunParser(pParse, zSql, &zErrMsg);
112714
+ db->mDbFlags = savedDbFlags;
112724112715
sqlite3DbFree(db, zErrMsg);
112725112716
sqlite3DbFree(db, zSql);
112726112717
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
112727112718
pParse->nested--;
112728112719
}
@@ -112854,10 +112845,11 @@
112854112845
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
112855112846
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
112856112847
pMod = sqlite3PragmaVtabRegister(db, zName);
112857112848
}
112858112849
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
112850
+ testcase( pMod->pEpoTab==0 );
112859112851
return pMod->pEpoTab;
112860112852
}
112861112853
}
112862112854
#endif
112863112855
if( flags & LOCATE_NOERR ) return 0;
@@ -113066,10 +113058,88 @@
113066113058
** This routine is called when a commit occurs.
113067113059
*/
113068113060
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
113069113061
db->mDbFlags &= ~DBFLAG_SchemaChange;
113070113062
}
113063
+
113064
+/*
113065
+** Set the expression associated with a column. This is usually
113066
+** the DEFAULT value, but might also be the expression that computes
113067
+** the value for a generated column.
113068
+*/
113069
+SQLITE_PRIVATE void sqlite3ColumnSetExpr(
113070
+ Parse *pParse, /* Parsing context */
113071
+ Table *pTab, /* The table containing the column */
113072
+ Column *pCol, /* The column to receive the new DEFAULT expression */
113073
+ Expr *pExpr /* The new default expression */
113074
+){
113075
+ ExprList *pList;
113076
+ assert( !IsVirtual(pTab) );
113077
+ pList = pTab->u.tab.pDfltList;
113078
+ if( pCol->iDflt==0
113079
+ || NEVER(pList==0)
113080
+ || NEVER(pList->nExpr<pCol->iDflt)
113081
+ ){
113082
+ pCol->iDflt = pList==0 ? 1 : pList->nExpr+1;
113083
+ pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr);
113084
+ }else{
113085
+ sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr);
113086
+ pList->a[pCol->iDflt-1].pExpr = pExpr;
113087
+ }
113088
+}
113089
+
113090
+/*
113091
+** Return the expression associated with a column. The expression might be
113092
+** the DEFAULT clause or the AS clause of a generated column.
113093
+** Return NULL if the column has no associated expression.
113094
+*/
113095
+SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
113096
+ if( pCol->iDflt==0 ) return 0;
113097
+ if( NEVER(IsVirtual(pTab)) ) return 0;
113098
+ if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
113099
+ if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
113100
+ return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
113101
+}
113102
+
113103
+/*
113104
+** Set the collating sequence name for a column.
113105
+*/
113106
+SQLITE_PRIVATE void sqlite3ColumnSetColl(
113107
+ sqlite3 *db,
113108
+ Column *pCol,
113109
+ const char *zColl
113110
+){
113111
+ int nColl;
113112
+ int n;
113113
+ char *zNew;
113114
+ assert( zColl!=0 );
113115
+ n = sqlite3Strlen30(pCol->zCnName) + 1;
113116
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
113117
+ n += sqlite3Strlen30(pCol->zCnName+n) + 1;
113118
+ }
113119
+ nColl = sqlite3Strlen30(zColl) + 1;
113120
+ zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n);
113121
+ if( zNew ){
113122
+ pCol->zCnName = zNew;
113123
+ memcpy(pCol->zCnName + n, zColl, nColl);
113124
+ pCol->colFlags |= COLFLAG_HASCOLL;
113125
+ }
113126
+}
113127
+
113128
+/*
113129
+** Return the collating squence name for a column
113130
+*/
113131
+SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){
113132
+ const char *z;
113133
+ if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0;
113134
+ z = pCol->zCnName;
113135
+ while( *z ){ z++; }
113136
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
113137
+ do{ z++; }while( *z );
113138
+ }
113139
+ return z+1;
113140
+}
113071113141
113072113142
/*
113073113143
** Delete memory allocated for the column names of a table or view (the
113074113144
** Table.aCol[] array).
113075113145
*/
@@ -113077,16 +113147,24 @@
113077113147
int i;
113078113148
Column *pCol;
113079113149
assert( pTable!=0 );
113080113150
if( (pCol = pTable->aCol)!=0 ){
113081113151
for(i=0; i<pTable->nCol; i++, pCol++){
113082
- assert( pCol->zName==0 || pCol->hName==sqlite3StrIHash(pCol->zName) );
113083
- sqlite3DbFree(db, pCol->zName);
113084
- sqlite3ExprDelete(db, pCol->pDflt);
113085
- sqlite3DbFree(db, pCol->zColl);
113152
+ assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
113153
+ sqlite3DbFree(db, pCol->zCnName);
113086113154
}
113087113155
sqlite3DbFree(db, pTable->aCol);
113156
+ if( !IsVirtual(pTable) ){
113157
+ sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
113158
+ }
113159
+ if( db==0 || db->pnBytesFreed==0 ){
113160
+ pTable->aCol = 0;
113161
+ pTable->nCol = 0;
113162
+ if( !IsVirtual(pTable) ){
113163
+ pTable->u.tab.pDfltList = 0;
113164
+ }
113165
+ }
113088113166
}
113089113167
}
113090113168
113091113169
/*
113092113170
** Remove the memory data structures associated with the given
@@ -113134,23 +113212,29 @@
113134113212
assert( pOld==pIndex || pOld==0 );
113135113213
}
113136113214
sqlite3FreeIndex(db, pIndex);
113137113215
}
113138113216
113139
- /* Delete any foreign keys attached to this table. */
113140
- sqlite3FkDelete(db, pTable);
113217
+ if( IsOrdinaryTable(pTable) ){
113218
+ sqlite3FkDelete(db, pTable);
113219
+ }
113220
+#ifndef SQLITE_OMIT_VIRTUAL_TABLE
113221
+ else if( IsVirtual(pTable) ){
113222
+ sqlite3VtabClear(db, pTable);
113223
+ }
113224
+#endif
113225
+ else{
113226
+ assert( IsView(pTable) );
113227
+ sqlite3SelectDelete(db, pTable->u.view.pSelect);
113228
+ }
113141113229
113142113230
/* Delete the Table structure itself.
113143113231
*/
113144113232
sqlite3DeleteColumnNames(db, pTable);
113145113233
sqlite3DbFree(db, pTable->zName);
113146113234
sqlite3DbFree(db, pTable->zColAff);
113147
- sqlite3SelectDelete(db, pTable->pSelect);
113148113235
sqlite3ExprListDelete(db, pTable->pCheck);
113149
-#ifndef SQLITE_OMIT_VIRTUALTABLE
113150
- sqlite3VtabClear(db, pTable);
113151
-#endif
113152113236
sqlite3DbFree(db, pTable);
113153113237
113154113238
/* Verify that no lookaside memory was used by schema tables */
113155113239
assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
113156113240
}
@@ -113672,20 +113756,21 @@
113672113756
/* Normal (non-error) return. */
113673113757
return;
113674113758
113675113759
/* If an error occurs, we jump here */
113676113760
begin_table_error:
113761
+ pParse->checkSchema = 1;
113677113762
sqlite3DbFree(db, zName);
113678113763
return;
113679113764
}
113680113765
113681113766
/* Set properties of a table column based on the (magical)
113682113767
** name of the column.
113683113768
*/
113684113769
#if SQLITE_ENABLE_HIDDEN_COLUMNS
113685113770
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
113686
- if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
113771
+ if( sqlite3_strnicmp(pCol->zCnName, "__hidden__", 10)==0 ){
113687113772
pCol->colFlags |= COLFLAG_HIDDEN;
113688113773
if( pTab ) pTab->tabFlags |= TF_HasHidden;
113689113774
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
113690113775
pTab->tabFlags |= TF_OOOHidden;
113691113776
}
@@ -113772,67 +113857,108 @@
113772113857
** The parser calls this routine once for each column declaration
113773113858
** in a CREATE TABLE statement. sqlite3StartTable() gets called
113774113859
** first to get things going. Then this routine is called for each
113775113860
** column.
113776113861
*/
113777
-SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
113862
+SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
113778113863
Table *p;
113779113864
int i;
113780113865
char *z;
113781113866
char *zType;
113782113867
Column *pCol;
113783113868
sqlite3 *db = pParse->db;
113784113869
u8 hName;
113870
+ Column *aNew;
113871
+ u8 eType = COLTYPE_CUSTOM;
113872
+ u8 szEst = 1;
113873
+ char affinity = SQLITE_AFF_BLOB;
113785113874
113786113875
if( (p = pParse->pNewTable)==0 ) return;
113787113876
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
113788113877
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
113789113878
return;
113790113879
}
113791
- z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
113880
+ if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName);
113881
+
113882
+ /* Because keywords GENERATE ALWAYS can be converted into indentifiers
113883
+ ** by the parser, we can sometimes end up with a typename that ends
113884
+ ** with "generated always". Check for this case and omit the surplus
113885
+ ** text. */
113886
+ if( sType.n>=16
113887
+ && sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0
113888
+ ){
113889
+ sType.n -= 6;
113890
+ while( ALWAYS(sType.n>0) && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
113891
+ if( sType.n>=9
113892
+ && sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0
113893
+ ){
113894
+ sType.n -= 9;
113895
+ while( sType.n>0 && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
113896
+ }
113897
+ }
113898
+
113899
+ /* Check for standard typenames. For standard typenames we will
113900
+ ** set the Column.eType field rather than storing the typename after
113901
+ ** the column name, in order to save space. */
113902
+ if( sType.n>=3 ){
113903
+ sqlite3DequoteToken(&sType);
113904
+ for(i=0; i<SQLITE_N_STDTYPE; i++){
113905
+ if( sType.n==sqlite3StdTypeLen[i]
113906
+ && sqlite3_strnicmp(sType.z, sqlite3StdType[i], sType.n)==0
113907
+ ){
113908
+ sType.n = 0;
113909
+ eType = i+1;
113910
+ affinity = sqlite3StdTypeAffinity[i];
113911
+ if( affinity<=SQLITE_AFF_TEXT ) szEst = 5;
113912
+ break;
113913
+ }
113914
+ }
113915
+ }
113916
+
113917
+ z = sqlite3DbMallocRaw(db, sName.n + 1 + sType.n + (sType.n>0) );
113792113918
if( z==0 ) return;
113793
- if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName);
113794
- memcpy(z, pName->z, pName->n);
113795
- z[pName->n] = 0;
113919
+ if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName);
113920
+ memcpy(z, sName.z, sName.n);
113921
+ z[sName.n] = 0;
113796113922
sqlite3Dequote(z);
113797113923
hName = sqlite3StrIHash(z);
113798113924
for(i=0; i<p->nCol; i++){
113799
- if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
113925
+ if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
113800113926
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
113801113927
sqlite3DbFree(db, z);
113802113928
return;
113803113929
}
113804113930
}
113805
- if( (p->nCol & 0x7)==0 ){
113806
- Column *aNew;
113807
- aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
113808
- if( aNew==0 ){
113809
- sqlite3DbFree(db, z);
113810
- return;
113811
- }
113812
- p->aCol = aNew;
113813
- }
113931
+ aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+1)*sizeof(p->aCol[0]));
113932
+ if( aNew==0 ){
113933
+ sqlite3DbFree(db, z);
113934
+ return;
113935
+ }
113936
+ p->aCol = aNew;
113814113937
pCol = &p->aCol[p->nCol];
113815113938
memset(pCol, 0, sizeof(p->aCol[0]));
113816
- pCol->zName = z;
113939
+ pCol->zCnName = z;
113817113940
pCol->hName = hName;
113818113941
sqlite3ColumnPropertiesFromName(p, pCol);
113819113942
113820
- if( pType->n==0 ){
113943
+ if( sType.n==0 ){
113821113944
/* If there is no type specified, columns have the default affinity
113822113945
** 'BLOB' with a default size of 4 bytes. */
113823
- pCol->affinity = SQLITE_AFF_BLOB;
113824
- pCol->szEst = 1;
113946
+ pCol->affinity = affinity;
113947
+ pCol->eType = eType;
113948
+ pCol->szEst = szEst;
113825113949
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
113826
- if( 4>=sqlite3GlobalConfig.szSorterRef ){
113827
- pCol->colFlags |= COLFLAG_SORTERREF;
113950
+ if( affinity==SQLITE_AFF_BLOB ){
113951
+ if( 4>=sqlite3GlobalConfig.szSorterRef ){
113952
+ pCol->colFlags |= COLFLAG_SORTERREF;
113953
+ }
113828113954
}
113829113955
#endif
113830113956
}else{
113831113957
zType = z + sqlite3Strlen30(z) + 1;
113832
- memcpy(zType, pType->z, pType->n);
113833
- zType[pType->n] = 0;
113958
+ memcpy(zType, sType.z, sType.n);
113959
+ zType[sType.n] = 0;
113834113960
sqlite3Dequote(zType);
113835113961
pCol->affinity = sqlite3AffinityType(zType, pCol);
113836113962
pCol->colFlags |= COLFLAG_HASTYPE;
113837113963
}
113838113964
p->nCol++;
@@ -113983,11 +114109,11 @@
113983114109
if( p!=0 ){
113984114110
int isInit = db->init.busy && db->init.iDb!=1;
113985114111
pCol = &(p->aCol[p->nCol-1]);
113986114112
if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
113987114113
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
113988
- pCol->zName);
114114
+ pCol->zCnName);
113989114115
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
113990114116
}else if( pCol->colFlags & COLFLAG_GENERATED ){
113991114117
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
113992114118
testcase( pCol->colFlags & COLFLAG_STORED );
113993114119
sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
@@ -113994,19 +114120,19 @@
113994114120
#endif
113995114121
}else{
113996114122
/* A copy of pExpr is used instead of the original, as pExpr contains
113997114123
** tokens that point to volatile memory.
113998114124
*/
113999
- Expr x;
114000
- sqlite3ExprDelete(db, pCol->pDflt);
114125
+ Expr x, *pDfltExpr;
114001114126
memset(&x, 0, sizeof(x));
114002114127
x.op = TK_SPAN;
114003114128
x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
114004114129
x.pLeft = pExpr;
114005114130
x.flags = EP_Skip;
114006
- pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
114131
+ pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
114007114132
sqlite3DbFree(db, x.u.zToken);
114133
+ sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr);
114008114134
}
114009114135
}
114010114136
if( IN_RENAME_OBJECT ){
114011114137
sqlite3RenameExprUnmap(pParse, pExpr);
114012114138
}
@@ -114100,11 +114226,11 @@
114100114226
assert( pCExpr!=0 );
114101114227
sqlite3StringToId(pCExpr);
114102114228
if( pCExpr->op==TK_ID ){
114103114229
const char *zCName = pCExpr->u.zToken;
114104114230
for(iCol=0; iCol<pTab->nCol; iCol++){
114105
- if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
114231
+ if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
114106114232
pCol = &pTab->aCol[iCol];
114107114233
makeColumnPartOfPrimaryKey(pParse, pCol);
114108114234
break;
114109114235
}
114110114236
}
@@ -114111,11 +114237,11 @@
114111114237
}
114112114238
}
114113114239
}
114114114240
if( nTerm==1
114115114241
&& pCol
114116
- && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
114242
+ && pCol->eType==COLTYPE_INTEGER
114117114243
&& sortOrder!=SQLITE_SO_DESC
114118114244
){
114119114245
if( IN_RENAME_OBJECT && pList ){
114120114246
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr);
114121114247
sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr);
@@ -114191,26 +114317,24 @@
114191114317
zColl = sqlite3NameFromToken(db, pToken);
114192114318
if( !zColl ) return;
114193114319
114194114320
if( sqlite3LocateCollSeq(pParse, zColl) ){
114195114321
Index *pIdx;
114196
- sqlite3DbFree(db, p->aCol[i].zColl);
114197
- p->aCol[i].zColl = zColl;
114322
+ sqlite3ColumnSetColl(db, &p->aCol[i], zColl);
114198114323
114199114324
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
114200114325
** then an index may have been created on this column before the
114201114326
** collation type was added. Correct this if it is the case.
114202114327
*/
114203114328
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
114204114329
assert( pIdx->nKeyCol==1 );
114205114330
if( pIdx->aiColumn[0]==i ){
114206
- pIdx->azColl[0] = p->aCol[i].zColl;
114331
+ pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]);
114207114332
}
114208114333
}
114209
- }else{
114210
- sqlite3DbFree(db, zColl);
114211114334
}
114335
+ sqlite3DbFree(db, zColl);
114212114336
}
114213114337
114214114338
/* Change the most recently parsed column to be a GENERATED ALWAYS AS
114215114339
** column.
114216114340
*/
@@ -114226,11 +114350,11 @@
114226114350
pCol = &(pTab->aCol[pTab->nCol-1]);
114227114351
if( IN_DECLARE_VTAB ){
114228114352
sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
114229114353
goto generated_done;
114230114354
}
114231
- if( pCol->pDflt ) goto generated_error;
114355
+ if( pCol->iDflt>0 ) goto generated_error;
114232114356
if( pType ){
114233114357
if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
114234114358
/* no-op */
114235114359
}else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
114236114360
eType = COLFLAG_STORED;
@@ -114244,17 +114368,17 @@
114244114368
assert( TF_HasStored==COLFLAG_STORED );
114245114369
pTab->tabFlags |= eType;
114246114370
if( pCol->colFlags & COLFLAG_PRIMKEY ){
114247114371
makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
114248114372
}
114249
- pCol->pDflt = pExpr;
114373
+ sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr);
114250114374
pExpr = 0;
114251114375
goto generated_done;
114252114376
114253114377
generated_error:
114254114378
sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
114255
- pCol->zName);
114379
+ pCol->zCnName);
114256114380
generated_done:
114257114381
sqlite3ExprDelete(pParse->db, pExpr);
114258114382
#else
114259114383
/* Throw and error for the GENERATED ALWAYS AS clause if the
114260114384
** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
@@ -114352,11 +114476,11 @@
114352114476
char *zStmt;
114353114477
char *zSep, *zSep2, *zEnd;
114354114478
Column *pCol;
114355114479
n = 0;
114356114480
for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
114357
- n += identLength(pCol->zName) + 5;
114481
+ n += identLength(pCol->zCnName) + 5;
114358114482
}
114359114483
n += identLength(p->zName);
114360114484
if( n<50 ){
114361114485
zSep = "";
114362114486
zSep2 = ",";
@@ -114388,11 +114512,11 @@
114388114512
const char *zType;
114389114513
114390114514
sqlite3_snprintf(n-k, &zStmt[k], zSep);
114391114515
k += sqlite3Strlen30(&zStmt[k]);
114392114516
zSep = zSep2;
114393
- identPut(zStmt, &k, pCol->zName);
114517
+ identPut(zStmt, &k, pCol->zCnName);
114394114518
assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
114395114519
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
114396114520
testcase( pCol->affinity==SQLITE_AFF_BLOB );
114397114521
testcase( pCol->affinity==SQLITE_AFF_TEXT );
114398114522
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
@@ -114607,11 +114731,11 @@
114607114731
** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
114608114732
*/
114609114733
if( pTab->iPKey>=0 ){
114610114734
ExprList *pList;
114611114735
Token ipkToken;
114612
- sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
114736
+ sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName);
114613114737
pList = sqlite3ExprListAppend(pParse, 0,
114614114738
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
114615114739
if( pList==0 ){
114616114740
pTab->tabFlags &= ~TF_WithoutRowid;
114617114741
return;
@@ -114737,11 +114861,11 @@
114737114861
114738114862
if( !IsVirtual(pTab) ) return 0;
114739114863
nName = sqlite3Strlen30(pTab->zName);
114740114864
if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
114741114865
if( zName[nName]!='_' ) return 0;
114742
- pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
114866
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
114743114867
if( pMod==0 ) return 0;
114744114868
if( pMod->pModule->iVersion<3 ) return 0;
114745114869
if( pMod->pModule->xShadowName==0 ) return 0;
114746114870
return pMod->pModule->xShadowName(zName+nName+1);
114747114871
}
@@ -114898,22 +115022,22 @@
114898115022
testcase( p->tabFlags & TF_HasVirtual );
114899115023
testcase( p->tabFlags & TF_HasStored );
114900115024
for(ii=0; ii<p->nCol; ii++){
114901115025
u32 colFlags = p->aCol[ii].colFlags;
114902115026
if( (colFlags & COLFLAG_GENERATED)!=0 ){
114903
- Expr *pX = p->aCol[ii].pDflt;
115027
+ Expr *pX = sqlite3ColumnExpr(p, &p->aCol[ii]);
114904115028
testcase( colFlags & COLFLAG_VIRTUAL );
114905115029
testcase( colFlags & COLFLAG_STORED );
114906115030
if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
114907115031
/* If there are errors in resolving the expression, change the
114908115032
** expression to a NULL. This prevents code generators that operate
114909115033
** on the expression from inserting extra parts into the expression
114910115034
** tree that have been allocated from lookaside memory, which is
114911115035
** illegal in a schema and will lead to errors or heap corruption
114912115036
** when the database connection closes. */
114913
- sqlite3ExprDelete(db, pX);
114914
- p->aCol[ii].pDflt = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
115037
+ sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii],
115038
+ sqlite3ExprAlloc(db, TK_NULL, 0, 0));
114915115039
}
114916115040
}else{
114917115041
nNG++;
114918115042
}
114919115043
}
@@ -114949,11 +115073,11 @@
114949115073
sqlite3VdbeAddOp1(v, OP_Close, 0);
114950115074
114951115075
/*
114952115076
** Initialize zType for the new view or table.
114953115077
*/
114954
- if( p->pSelect==0 ){
115078
+ if( IsOrdinaryTable(p) ){
114955115079
/* A regular table */
114956115080
zType = "table";
114957115081
zType2 = "TABLE";
114958115082
#ifndef SQLITE_OMIT_VIEW
114959115083
}else{
@@ -115099,16 +115223,16 @@
115099115223
}
115100115224
#endif
115101115225
}
115102115226
115103115227
#ifndef SQLITE_OMIT_ALTERTABLE
115104
- if( !pSelect && !p->pSelect ){
115228
+ if( !pSelect && IsOrdinaryTable(p) ){
115105115229
assert( pCons && pEnd );
115106115230
if( pCons->z==0 ){
115107115231
pCons = pEnd;
115108115232
}
115109
- p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
115233
+ p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
115110115234
}
115111115235
#endif
115112115236
}
115113115237
115114115238
#ifndef SQLITE_OMIT_VIEW
@@ -115161,16 +115285,17 @@
115161115285
** allocated rather than point to the input string - which means that
115162115286
** they will persist after the current sqlite3_exec() call returns.
115163115287
*/
115164115288
pSelect->selFlags |= SF_View;
115165115289
if( IN_RENAME_OBJECT ){
115166
- p->pSelect = pSelect;
115290
+ p->u.view.pSelect = pSelect;
115167115291
pSelect = 0;
115168115292
}else{
115169
- p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
115293
+ p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
115170115294
}
115171115295
p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
115296
+ p->eTabType = TABTYP_VIEW;
115172115297
if( db->mallocFailed ) goto create_view_fail;
115173115298
115174115299
/* Locate the end of the CREATE VIEW statement. Make sEnd point to
115175115300
** the end.
115176115301
*/
@@ -115263,12 +115388,12 @@
115263115388
** "*" elements in the results set of the view and will assign cursors
115264115389
** to the elements of the FROM clause. But we do not want these changes
115265115390
** to be permanent. So the computation is done on a copy of the SELECT
115266115391
** statement that defines the view.
115267115392
*/
115268
- assert( pTable->pSelect );
115269
- pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
115393
+ assert( IsView(pTable) );
115394
+ pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
115270115395
if( pSel ){
115271115396
u8 eParseMode = pParse->eParseMode;
115272115397
pParse->eParseMode = PARSE_MODE_NORMAL;
115273115398
n = pParse->nTab;
115274115399
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
@@ -115323,12 +115448,10 @@
115323115448
nErr++;
115324115449
}
115325115450
pTable->pSchema->schemaFlags |= DB_UnresetViews;
115326115451
if( db->mallocFailed ){
115327115452
sqlite3DeleteColumnNames(db, pTable);
115328
- pTable->aCol = 0;
115329
- pTable->nCol = 0;
115330115453
}
115331115454
#endif /* SQLITE_OMIT_VIEW */
115332115455
return nErr;
115333115456
}
115334115457
#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -115341,14 +115464,12 @@
115341115464
HashElem *i;
115342115465
assert( sqlite3SchemaMutexHeld(db, idx, 0) );
115343115466
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
115344115467
for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
115345115468
Table *pTab = sqliteHashData(i);
115346
- if( pTab->pSelect ){
115469
+ if( IsView(pTab) ){
115347115470
sqlite3DeleteColumnNames(db, pTab);
115348
- pTab->aCol = 0;
115349
- pTab->nCol = 0;
115350115471
}
115351115472
}
115352115473
DbClearProperty(db, idx, DB_UnresetViews);
115353115474
}
115354115475
#else
@@ -115581,10 +115702,11 @@
115581115702
SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){
115582115703
#ifndef SQLITE_OMIT_VIRTUALTABLE
115583115704
if( (db->flags & SQLITE_Defensive)!=0
115584115705
&& db->pVtabCtx==0
115585115706
&& db->nVdbeExec==0
115707
+ && !sqlite3VtabInSync(db)
115586115708
){
115587115709
return 1;
115588115710
}
115589115711
#endif
115590115712
return 0;
@@ -115684,15 +115806,15 @@
115684115806
115685115807
#ifndef SQLITE_OMIT_VIEW
115686115808
/* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
115687115809
** on a table.
115688115810
*/
115689
- if( isView && pTab->pSelect==0 ){
115811
+ if( isView && !IsView(pTab) ){
115690115812
sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
115691115813
goto exit_drop_table;
115692115814
}
115693
- if( !isView && pTab->pSelect ){
115815
+ if( !isView && IsView(pTab) ){
115694115816
sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
115695115817
goto exit_drop_table;
115696115818
}
115697115819
#endif
115698115820
@@ -115752,11 +115874,11 @@
115752115874
int iCol = p->nCol-1;
115753115875
if( NEVER(iCol<0) ) goto fk_end;
115754115876
if( pToCol && pToCol->nExpr!=1 ){
115755115877
sqlite3ErrorMsg(pParse, "foreign key on %s"
115756115878
" should reference only one column of table %T",
115757
- p->aCol[iCol].zName, pTo);
115879
+ p->aCol[iCol].zCnName, pTo);
115758115880
goto fk_end;
115759115881
}
115760115882
nCol = 1;
115761115883
}else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
115762115884
sqlite3ErrorMsg(pParse,
@@ -115775,11 +115897,11 @@
115775115897
pFKey = sqlite3DbMallocZero(db, nByte );
115776115898
if( pFKey==0 ){
115777115899
goto fk_end;
115778115900
}
115779115901
pFKey->pFrom = p;
115780
- pFKey->pNextFrom = p->pFKey;
115902
+ pFKey->pNextFrom = p->u.tab.pFKey;
115781115903
z = (char*)&pFKey->aCol[nCol];
115782115904
pFKey->zTo = z;
115783115905
if( IN_RENAME_OBJECT ){
115784115906
sqlite3RenameTokenMap(pParse, (void*)z, pTo);
115785115907
}
@@ -115792,11 +115914,11 @@
115792115914
pFKey->aCol[0].iFrom = p->nCol-1;
115793115915
}else{
115794115916
for(i=0; i<nCol; i++){
115795115917
int j;
115796115918
for(j=0; j<p->nCol; j++){
115797
- if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
115919
+ if( sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){
115798115920
pFKey->aCol[i].iFrom = j;
115799115921
break;
115800115922
}
115801115923
}
115802115924
if( j>=p->nCol ){
@@ -115840,11 +115962,12 @@
115840115962
pNextTo->pPrevTo = pFKey;
115841115963
}
115842115964
115843115965
/* Link the foreign key to the table as the last step.
115844115966
*/
115845
- p->pFKey = pFKey;
115967
+ assert( !IsVirtual(p) );
115968
+ p->u.tab.pFKey = pFKey;
115846115969
pFKey = 0;
115847115970
115848115971
fk_end:
115849115972
sqlite3DbFree(db, pFKey);
115850115973
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
@@ -115861,11 +115984,13 @@
115861115984
*/
115862115985
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
115863115986
#ifndef SQLITE_OMIT_FOREIGN_KEY
115864115987
Table *pTab;
115865115988
FKey *pFKey;
115866
- if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
115989
+ if( (pTab = pParse->pNewTable)==0 ) return;
115990
+ if( NEVER(IsVirtual(pTab)) ) return;
115991
+ if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
115867115992
assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
115868115993
pFKey->isDeferred = (u8)isDeferred;
115869115994
#endif
115870115995
}
115871115996
@@ -116153,11 +116278,11 @@
116153116278
){
116154116279
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
116155116280
goto exit_create_index;
116156116281
}
116157116282
#ifndef SQLITE_OMIT_VIEW
116158
- if( pTab->pSelect ){
116283
+ if( IsView(pTab) ){
116159116284
sqlite3ErrorMsg(pParse, "views may not be indexed");
116160116285
goto exit_create_index;
116161116286
}
116162116287
#endif
116163116288
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -116244,11 +116369,11 @@
116244116369
*/
116245116370
if( pList==0 ){
116246116371
Token prevCol;
116247116372
Column *pCol = &pTab->aCol[pTab->nCol-1];
116248116373
pCol->colFlags |= COLFLAG_UNIQUE;
116249
- sqlite3TokenInit(&prevCol, pCol->zName);
116374
+ sqlite3TokenInit(&prevCol, pCol->zCnName);
116250116375
pList = sqlite3ExprListAppend(pParse, 0,
116251116376
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
116252116377
if( pList==0 ) goto exit_create_index;
116253116378
assert( pList->nExpr==1 );
116254116379
sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
@@ -116365,11 +116490,11 @@
116365116490
memcpy(zExtra, zColl, nColl);
116366116491
zColl = zExtra;
116367116492
zExtra += nColl;
116368116493
nExtra -= nColl;
116369116494
}else if( j>=0 ){
116370
- zColl = pTab->aCol[j].zColl;
116495
+ zColl = sqlite3ColumnColl(&pTab->aCol[j]);
116371116496
}
116372116497
if( !zColl ) zColl = sqlite3StrBINARY;
116373116498
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
116374116499
goto exit_create_index;
116375116500
}
@@ -117457,11 +117582,11 @@
117457117582
sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
117458117583
}else{
117459117584
for(j=0; j<pIdx->nKeyCol; j++){
117460117585
char *zCol;
117461117586
assert( pIdx->aiColumn[j]>=0 );
117462
- zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
117587
+ zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName;
117463117588
if( j ) sqlite3_str_append(&errMsg, ", ", 2);
117464117589
sqlite3_str_appendall(&errMsg, pTab->zName);
117465117590
sqlite3_str_append(&errMsg, ".", 1);
117466117591
sqlite3_str_appendall(&errMsg, zCol);
117467117592
}
@@ -117484,11 +117609,11 @@
117484117609
){
117485117610
char *zMsg;
117486117611
int rc;
117487117612
if( pTab->iPKey>=0 ){
117488117613
zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
117489
- pTab->aCol[pTab->iPKey].zName);
117614
+ pTab->aCol[pTab->iPKey].zCnName);
117490117615
rc = SQLITE_CONSTRAINT_PRIMARYKEY;
117491117616
}else{
117492117617
zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
117493117618
rc = SQLITE_CONSTRAINT_ROWID;
117494117619
}
@@ -118411,11 +118536,11 @@
118411118536
if( tabIsReadOnly(pParse, pTab) ){
118412118537
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
118413118538
return 1;
118414118539
}
118415118540
#ifndef SQLITE_OMIT_VIEW
118416
- if( !viewOk && pTab->pSelect ){
118541
+ if( !viewOk && IsView(pTab) ){
118417118542
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
118418118543
return 1;
118419118544
}
118420118545
#endif
118421118546
return 0;
@@ -118515,17 +118640,17 @@
118515118640
pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
118516118641
);
118517118642
}else{
118518118643
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
118519118644
if( pPk->nKeyCol==1 ){
118520
- const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
118645
+ const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName;
118521118646
pLhs = sqlite3Expr(db, TK_ID, zName);
118522118647
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
118523118648
}else{
118524118649
int i;
118525118650
for(i=0; i<pPk->nKeyCol; i++){
118526
- Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
118651
+ Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
118527118652
pEList = sqlite3ExprListAppend(pParse, pEList, p);
118528118653
}
118529118654
pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
118530118655
if( pLhs ){
118531118656
pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
@@ -118628,11 +118753,11 @@
118628118753
/* Figure out if we have any triggers and if the table being
118629118754
** deleted from is a view
118630118755
*/
118631118756
#ifndef SQLITE_OMIT_TRIGGER
118632118757
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
118633
- isView = pTab->pSelect!=0;
118758
+ isView = IsView(pTab);
118634118759
#else
118635118760
# define pTrigger 0
118636118761
# define isView 0
118637118762
#endif
118638118763
bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
@@ -118878,11 +119003,11 @@
118878119003
** where-clause loop above.
118879119004
*/
118880119005
if( eOnePass!=ONEPASS_OFF ){
118881119006
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
118882119007
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
118883
- assert( pPk!=0 || pTab->pSelect!=0 );
119008
+ assert( pPk!=0 || IsView(pTab) );
118884119009
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
118885119010
VdbeCoverage(v);
118886119011
}
118887119012
}else if( pPk ){
118888119013
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
@@ -119112,11 +119237,11 @@
119112119237
** invoke the update-hook. The pre-update-hook, on the other hand should
119113119238
** be invoked unless table pTab is a system table. The difference is that
119114119239
** the update-hook is not invoked for rows removed by REPLACE, but the
119115119240
** pre-update-hook is.
119116119241
*/
119117
- if( pTab->pSelect==0 ){
119242
+ if( !IsView(pTab) ){
119118119243
u8 p5 = 0;
119119119244
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
119120119245
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
119121119246
if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
119122119247
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
@@ -119873,37 +119998,37 @@
119873119998
119874119999
/*
119875120000
** Implementation of the changes() SQL function.
119876120001
**
119877120002
** IMP: R-62073-11209 The changes() SQL function is a wrapper
119878
-** around the sqlite3_changes() C/C++ function and hence follows the same
120003
+** around the sqlite3_changes64() C/C++ function and hence follows the same
119879120004
** rules for counting changes.
119880120005
*/
119881120006
static void changes(
119882120007
sqlite3_context *context,
119883120008
int NotUsed,
119884120009
sqlite3_value **NotUsed2
119885120010
){
119886120011
sqlite3 *db = sqlite3_context_db_handle(context);
119887120012
UNUSED_PARAMETER2(NotUsed, NotUsed2);
119888
- sqlite3_result_int(context, sqlite3_changes(db));
120013
+ sqlite3_result_int64(context, sqlite3_changes64(db));
119889120014
}
119890120015
119891120016
/*
119892120017
** Implementation of the total_changes() SQL function. The return value is
119893
-** the same as the sqlite3_total_changes() API function.
120018
+** the same as the sqlite3_total_changes64() API function.
119894120019
*/
119895120020
static void total_changes(
119896120021
sqlite3_context *context,
119897120022
int NotUsed,
119898120023
sqlite3_value **NotUsed2
119899120024
){
119900120025
sqlite3 *db = sqlite3_context_db_handle(context);
119901120026
UNUSED_PARAMETER2(NotUsed, NotUsed2);
119902
- /* IMP: R-52756-41993 This function is a wrapper around the
120027
+ /* IMP: R-52756-41993 This function was a wrapper around the
119903120028
** sqlite3_total_changes() C/C++ interface. */
119904
- sqlite3_result_int(context, sqlite3_total_changes(db));
120029
+ sqlite3_result_int64(context, sqlite3_total_changes64(db));
119905120030
}
119906120031
119907120032
/*
119908120033
** A structure defining how to do GLOB-style comparisons.
119909120034
*/
@@ -120617,29 +120742,29 @@
120617120742
int argc,
120618120743
sqlite3_value **argv
120619120744
){
120620120745
const unsigned char *zIn; /* Input string */
120621120746
const unsigned char *zCharSet; /* Set of characters to trim */
120622
- int nIn; /* Number of bytes in input */
120747
+ unsigned int nIn; /* Number of bytes in input */
120623120748
int flags; /* 1: trimleft 2: trimright 3: trim */
120624120749
int i; /* Loop counter */
120625
- unsigned char *aLen = 0; /* Length of each character in zCharSet */
120750
+ unsigned int *aLen = 0; /* Length of each character in zCharSet */
120626120751
unsigned char **azChar = 0; /* Individual characters in zCharSet */
120627120752
int nChar; /* Number of characters in zCharSet */
120628120753
120629120754
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
120630120755
return;
120631120756
}
120632120757
zIn = sqlite3_value_text(argv[0]);
120633120758
if( zIn==0 ) return;
120634
- nIn = sqlite3_value_bytes(argv[0]);
120759
+ nIn = (unsigned)sqlite3_value_bytes(argv[0]);
120635120760
assert( zIn==sqlite3_value_text(argv[0]) );
120636120761
if( argc==1 ){
120637
- static const unsigned char lenOne[] = { 1 };
120762
+ static const unsigned lenOne[] = { 1 };
120638120763
static unsigned char * const azOne[] = { (u8*)" " };
120639120764
nChar = 1;
120640
- aLen = (u8*)lenOne;
120765
+ aLen = (unsigned*)lenOne;
120641120766
azChar = (unsigned char **)azOne;
120642120767
zCharSet = 0;
120643120768
}else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
120644120769
return;
120645120770
}else{
@@ -120646,27 +120771,28 @@
120646120771
const unsigned char *z;
120647120772
for(z=zCharSet, nChar=0; *z; nChar++){
120648120773
SQLITE_SKIP_UTF8(z);
120649120774
}
120650120775
if( nChar>0 ){
120651
- azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
120776
+ azChar = contextMalloc(context,
120777
+ ((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
120652120778
if( azChar==0 ){
120653120779
return;
120654120780
}
120655
- aLen = (unsigned char*)&azChar[nChar];
120781
+ aLen = (unsigned*)&azChar[nChar];
120656120782
for(z=zCharSet, nChar=0; *z; nChar++){
120657120783
azChar[nChar] = (unsigned char *)z;
120658120784
SQLITE_SKIP_UTF8(z);
120659
- aLen[nChar] = (u8)(z - azChar[nChar]);
120785
+ aLen[nChar] = (unsigned)(z - azChar[nChar]);
120660120786
}
120661120787
}
120662120788
}
120663120789
if( nChar>0 ){
120664120790
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
120665120791
if( flags & 1 ){
120666120792
while( nIn>0 ){
120667
- int len = 0;
120793
+ unsigned int len = 0;
120668120794
for(i=0; i<nChar; i++){
120669120795
len = aLen[i];
120670120796
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
120671120797
}
120672120798
if( i>=nChar ) break;
@@ -120674,11 +120800,11 @@
120674120800
nIn -= len;
120675120801
}
120676120802
}
120677120803
if( flags & 2 ){
120678120804
while( nIn>0 ){
120679
- int len = 0;
120805
+ unsigned int len = 0;
120680120806
for(i=0; i<nChar; i++){
120681120807
len = aLen[i];
120682120808
if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
120683120809
}
120684120810
if( i>=nChar ) break;
@@ -121460,15 +121586,15 @@
121460121586
FUNCTION(trim, 1, 3, 0, trimFunc ),
121461121587
FUNCTION(trim, 2, 3, 0, trimFunc ),
121462121588
FUNCTION(min, -1, 0, 1, minmaxFunc ),
121463121589
FUNCTION(min, 0, 0, 1, 0 ),
121464121590
WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
121465
- SQLITE_FUNC_MINMAX ),
121591
+ SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
121466121592
FUNCTION(max, -1, 1, 1, minmaxFunc ),
121467121593
FUNCTION(max, 0, 1, 1, 0 ),
121468121594
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
121469
- SQLITE_FUNC_MINMAX ),
121595
+ SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
121470121596
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
121471121597
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
121472121598
FUNCTION(instr, 2, 0, 0, instrFunc ),
121473121599
FUNCTION(printf, -1, 0, 0, printfFunc ),
121474121600
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
@@ -121500,13 +121626,14 @@
121500121626
FUNCTION(substring, 3, 0, 0, substrFunc ),
121501121627
WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
121502121628
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
121503121629
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
121504121630
WAGGREGATE(count, 0,0,0, countStep,
121505
- countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
121631
+ countFinalize, countFinalize, countInverse,
121632
+ SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ),
121506121633
WAGGREGATE(count, 1,0,0, countStep,
121507
- countFinalize, countFinalize, countInverse, 0 ),
121634
+ countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
121508121635
WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
121509121636
groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
121510121637
WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
121511121638
groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
121512121639
@@ -121804,11 +121931,13 @@
121804121931
** 2) The FK is explicitly mapped to a column declared as INTEGER
121805121932
** PRIMARY KEY.
121806121933
*/
121807121934
if( pParent->iPKey>=0 ){
121808121935
if( !zKey ) return 0;
121809
- if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
121936
+ if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){
121937
+ return 0;
121938
+ }
121810121939
}
121811121940
}else if( paiCol ){
121812121941
assert( nCol>1 );
121813121942
aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
121814121943
if( !aiCol ) return 1;
@@ -121846,15 +121975,15 @@
121846121975
if( iCol<0 ) break; /* No foreign keys against expression indexes */
121847121976
121848121977
/* If the index uses a collation sequence that is different from
121849121978
** the default collation sequence for the column, this index is
121850121979
** unusable. Bail out early in this case. */
121851
- zDfltColl = pParent->aCol[iCol].zColl;
121980
+ zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]);
121852121981
if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
121853121982
if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
121854121983
121855
- zIdxCol = pParent->aCol[iCol].zName;
121984
+ zIdxCol = pParent->aCol[iCol].zCnName;
121856121985
for(j=0; j<nCol; j++){
121857121986
if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
121858121987
if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
121859121988
break;
121860121989
}
@@ -122074,11 +122203,11 @@
122074122203
if( pExpr ){
122075122204
if( iCol>=0 && iCol!=pTab->iPKey ){
122076122205
pCol = &pTab->aCol[iCol];
122077122206
pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
122078122207
pExpr->affExpr = pCol->affinity;
122079
- zColl = pCol->zColl;
122208
+ zColl = sqlite3ColumnColl(pCol);
122080122209
if( zColl==0 ) zColl = db->pDfltColl->zName;
122081122210
pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
122082122211
}else{
122083122212
pExpr->iTable = regBase;
122084122213
pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -122183,11 +122312,11 @@
122183122312
122184122313
iCol = pIdx ? pIdx->aiColumn[i] : -1;
122185122314
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
122186122315
iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
122187122316
assert( iCol>=0 );
122188
- zCol = pFKey->pFrom->aCol[iCol].zName;
122317
+ zCol = pFKey->pFrom->aCol[iCol].zCnName;
122189122318
pRight = sqlite3Expr(db, TK_ID, zCol);
122190122319
pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
122191122320
pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
122192122321
}
122193122322
@@ -122218,11 +122347,11 @@
122218122347
assert( pIdx!=0 );
122219122348
for(i=0; i<pIdx->nKeyCol; i++){
122220122349
i16 iCol = pIdx->aiColumn[i];
122221122350
assert( iCol>=0 );
122222122351
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
122223
- pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
122352
+ pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName);
122224122353
pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
122225122354
pAll = sqlite3ExprAnd(pParse, pAll, pEq);
122226122355
}
122227122356
pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
122228122357
}
@@ -122312,19 +122441,20 @@
122312122441
if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
122313122442
int iSkip = 0;
122314122443
Vdbe *v = sqlite3GetVdbe(pParse);
122315122444
122316122445
assert( v ); /* VDBE has already been allocated */
122317
- assert( pTab->pSelect==0 ); /* Not a view */
122446
+ assert( !IsView(pTab) ); /* Not a view */
122447
+ assert( !IsVirtual(pTab) );
122318122448
if( sqlite3FkReferences(pTab)==0 ){
122319122449
/* Search for a deferred foreign key constraint for which this table
122320122450
** is the child table. If one cannot be found, return without
122321122451
** generating any VDBE code. If one can be found, then jump over
122322122452
** the entire DELETE if there are no outstanding deferred constraints
122323122453
** when this statement is run. */
122324122454
FKey *p;
122325
- for(p=pTab->pFKey; p; p=p->pNextFrom){
122455
+ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
122326122456
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
122327122457
}
122328122458
if( !p ) return;
122329122459
iSkip = sqlite3VdbeMakeLabel(pParse);
122330122460
sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
@@ -122409,11 +122539,11 @@
122409122539
int iKey;
122410122540
for(iKey=0; iKey<pTab->nCol; iKey++){
122411122541
if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
122412122542
Column *pCol = &pTab->aCol[iKey];
122413122543
if( zKey ){
122414
- if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
122544
+ if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1;
122415122545
}else if( pCol->colFlags & COLFLAG_PRIMKEY ){
122416122546
return 1;
122417122547
}
122418122548
}
122419122549
}
@@ -122482,11 +122612,12 @@
122482122612
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
122483122613
zDb = db->aDb[iDb].zDbSName;
122484122614
122485122615
/* Loop through all the foreign key constraints for which pTab is the
122486122616
** child table (the table that the foreign key definition is part of). */
122487
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
122617
+ assert( !IsVirtual(pTab) );
122618
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
122488122619
Table *pTo; /* Parent table of foreign key pFKey */
122489122620
Index *pIdx = 0; /* Index on key columns in pTo */
122490122621
int *aiFree = 0;
122491122622
int *aiCol;
122492122623
int iCol;
@@ -122549,11 +122680,11 @@
122549122680
/* Request permission to read the parent key columns. If the
122550122681
** authorization callback returns SQLITE_IGNORE, behave as if any
122551122682
** values read from the parent table are NULL. */
122552122683
if( db->xAuth ){
122553122684
int rcauth;
122554
- char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
122685
+ char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName;
122555122686
rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
122556122687
bIgnore = (rcauth==SQLITE_IGNORE);
122557122688
}
122558122689
#endif
122559122690
}
@@ -122667,11 +122798,12 @@
122667122798
){
122668122799
u32 mask = 0;
122669122800
if( pParse->db->flags&SQLITE_ForeignKeys ){
122670122801
FKey *p;
122671122802
int i;
122672
- for(p=pTab->pFKey; p; p=p->pNextFrom){
122803
+ assert( !IsVirtual(pTab) );
122804
+ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
122673122805
for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
122674122806
}
122675122807
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
122676122808
Index *pIdx = 0;
122677122809
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
@@ -122717,23 +122849,23 @@
122717122849
int *aChange, /* Non-NULL for UPDATE operations */
122718122850
int chngRowid /* True for UPDATE that affects rowid */
122719122851
){
122720122852
int eRet = 1; /* Value to return if bHaveFK is true */
122721122853
int bHaveFK = 0; /* If FK processing is required */
122722
- if( pParse->db->flags&SQLITE_ForeignKeys ){
122854
+ if( pParse->db->flags&SQLITE_ForeignKeys && !IsVirtual(pTab) ){
122723122855
if( !aChange ){
122724122856
/* A DELETE operation. Foreign key processing is required if the
122725122857
** table in question is either the child or parent table for any
122726122858
** foreign key constraint. */
122727
- bHaveFK = (sqlite3FkReferences(pTab) || pTab->pFKey);
122859
+ bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
122728122860
}else{
122729122861
/* This is an UPDATE. Foreign key processing is only required if the
122730122862
** operation modifies one or more child or parent key columns. */
122731122863
FKey *p;
122732122864
122733122865
/* Check if any child key columns are being modified. */
122734
- for(p=pTab->pFKey; p; p=p->pNextFrom){
122866
+ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
122735122867
if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
122736122868
if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
122737122869
bHaveFK = 1;
122738122870
}
122739122871
}
@@ -122822,12 +122954,12 @@
122822122954
iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
122823122955
assert( iFromCol>=0 );
122824122956
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
122825122957
assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
122826122958
sqlite3TokenInit(&tToCol,
122827
- pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
122828
- sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
122959
+ pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName);
122960
+ sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName);
122829122961
122830122962
/* Create the expression "OLD.zToCol = zFromCol". It is important
122831122963
** that the "OLD.zToCol" term is on the LHS of the = operator, so
122832122964
** that the affinity and collation sequence associated with the
122833122965
** parent table are used for the comparison. */
@@ -122868,11 +123000,11 @@
122868123000
if( pCol->colFlags & COLFLAG_GENERATED ){
122869123001
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
122870123002
testcase( pCol->colFlags & COLFLAG_STORED );
122871123003
pDflt = 0;
122872123004
}else{
122873
- pDflt = pCol->pDflt;
123005
+ pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol);
122874123006
}
122875123007
if( pDflt ){
122876123008
pNew = sqlite3ExprDup(db, pDflt, 0);
122877123009
}else{
122878123010
pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
@@ -123005,13 +123137,13 @@
123005123137
*/
123006123138
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
123007123139
FKey *pFKey; /* Iterator variable */
123008123140
FKey *pNext; /* Copy of pFKey->pNextFrom */
123009123141
123010
- assert( db==0 || IsVirtual(pTab)
123011
- || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
123012
- for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
123142
+ assert( !IsVirtual(pTab) );
123143
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
123144
+ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
123013123145
123014123146
/* Remove the FK from the fkeyHash hash table. */
123015123147
if( !db || db->pnBytesFreed==0 ){
123016123148
if( pFKey->pPrevTo ){
123017123149
pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
@@ -123157,11 +123289,11 @@
123157123289
123158123290
/*
123159123291
** Compute the affinity string for table pTab, if it has not already been
123160123292
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
123161123293
**
123162
-** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
123294
+** If the affinity exists (if it is not entirely SQLITE_AFF_BLOB values) and
123163123295
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
123164123296
** for register iReg and following. Or if affinities exists and iReg==0,
123165123297
** then just set the P4 operand of the previous opcode (which should be
123166123298
** an OP_MakeRecord) to the affinity string.
123167123299
**
@@ -123337,26 +123469,26 @@
123337123469
Column *pCol = pTab->aCol + i;
123338123470
if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){
123339123471
int x;
123340123472
pCol->colFlags |= COLFLAG_BUSY;
123341123473
w.eCode = 0;
123342
- sqlite3WalkExpr(&w, pCol->pDflt);
123474
+ sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol));
123343123475
pCol->colFlags &= ~COLFLAG_BUSY;
123344123476
if( w.eCode & COLFLAG_NOTAVAIL ){
123345123477
pRedo = pCol;
123346123478
continue;
123347123479
}
123348123480
eProgress = 1;
123349123481
assert( pCol->colFlags & COLFLAG_GENERATED );
123350123482
x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
123351
- sqlite3ExprCodeGeneratedColumn(pParse, pCol, x);
123483
+ sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x);
123352123484
pCol->colFlags &= ~COLFLAG_NOTAVAIL;
123353123485
}
123354123486
}
123355123487
}while( pRedo && eProgress );
123356123488
if( pRedo ){
123357
- sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zName);
123489
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName);
123358123490
}
123359123491
pParse->iSelfTab = 0;
123360123492
}
123361123493
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
123362123494
@@ -123747,11 +123879,11 @@
123747123879
/* Figure out if we have any triggers and if the table being
123748123880
** inserted into is a view
123749123881
*/
123750123882
#ifndef SQLITE_OMIT_TRIGGER
123751123883
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
123752
- isView = pTab->pSelect!=0;
123884
+ isView = IsView(pTab);
123753123885
#else
123754123886
# define pTrigger 0
123755123887
# define tmask 0
123756123888
# define isView 0
123757123889
#endif
@@ -123838,21 +123970,21 @@
123838123970
for(i=0; i<pColumn->nId; i++){
123839123971
pColumn->a[i].idx = -1;
123840123972
}
123841123973
for(i=0; i<pColumn->nId; i++){
123842123974
for(j=0; j<pTab->nCol; j++){
123843
- if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
123975
+ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
123844123976
pColumn->a[i].idx = j;
123845123977
if( i!=j ) bIdListInOrder = 0;
123846123978
if( j==pTab->iPKey ){
123847123979
ipkColumn = i; assert( !withoutRowid );
123848123980
}
123849123981
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
123850123982
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
123851123983
sqlite3ErrorMsg(pParse,
123852123984
"cannot INSERT into generated column \"%s\"",
123853
- pTab->aCol[j].zName);
123985
+ pTab->aCol[j].zCnName);
123854123986
goto insert_cleanup;
123855123987
}
123856123988
#endif
123857123989
break;
123858123990
}
@@ -124033,11 +124165,11 @@
124033124165
if( IsVirtual(pTab) ){
124034124166
sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
124035124167
pTab->zName);
124036124168
goto insert_cleanup;
124037124169
}
124038
- if( pTab->pSelect ){
124170
+ if( IsView(pTab) ){
124039124171
sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
124040124172
goto insert_cleanup;
124041124173
}
124042124174
if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
124043124175
goto insert_cleanup;
@@ -124132,26 +124264,32 @@
124132124264
}
124133124265
continue;
124134124266
}else if( pColumn==0 ){
124135124267
/* Hidden columns that are not explicitly named in the INSERT
124136124268
** get there default value */
124137
- sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
124269
+ sqlite3ExprCodeFactorable(pParse,
124270
+ sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
124271
+ iRegStore);
124138124272
continue;
124139124273
}
124140124274
}
124141124275
if( pColumn ){
124142124276
for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
124143124277
if( j>=pColumn->nId ){
124144124278
/* A column not named in the insert column list gets its
124145124279
** default value */
124146
- sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
124280
+ sqlite3ExprCodeFactorable(pParse,
124281
+ sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
124282
+ iRegStore);
124147124283
continue;
124148124284
}
124149124285
k = j;
124150124286
}else if( nColumn==0 ){
124151124287
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
124152
- sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
124288
+ sqlite3ExprCodeFactorable(pParse,
124289
+ sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
124290
+ iRegStore);
124153124291
continue;
124154124292
}else{
124155124293
k = i - nHidden;
124156124294
}
124157124295
@@ -124662,11 +124800,11 @@
124662124800
124663124801
isUpdate = regOldData!=0;
124664124802
db = pParse->db;
124665124803
v = pParse->pVdbe;
124666124804
assert( v!=0 );
124667
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
124805
+ assert( !IsView(pTab) ); /* This table is not a VIEW */
124668124806
nCol = pTab->nCol;
124669124807
124670124808
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
124671124809
** normal rowid tables. nPkField is the number of key fields in the
124672124810
** pPk index or 1 for a rowid table. In other words, nPkField is the
@@ -124713,11 +124851,11 @@
124713124851
}else if( onError==OE_Default ){
124714124852
onError = OE_Abort;
124715124853
}
124716124854
if( onError==OE_Replace ){
124717124855
if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
124718
- || pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
124856
+ || pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */
124719124857
){
124720124858
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
124721124859
testcase( pCol->colFlags & COLFLAG_STORED );
124722124860
testcase( pCol->colFlags & COLFLAG_GENERATED );
124723124861
onError = OE_Abort;
@@ -124735,21 +124873,22 @@
124735124873
case OE_Replace: {
124736124874
int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
124737124875
VdbeCoverage(v);
124738124876
assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
124739124877
nSeenReplace++;
124740
- sqlite3ExprCodeCopy(pParse, pCol->pDflt, iReg);
124878
+ sqlite3ExprCodeCopy(pParse,
124879
+ sqlite3ColumnExpr(pTab, pCol), iReg);
124741124880
sqlite3VdbeJumpHere(v, addr1);
124742124881
break;
124743124882
}
124744124883
case OE_Abort:
124745124884
sqlite3MayAbort(pParse);
124746124885
/* no break */ deliberate_fall_through
124747124886
case OE_Rollback:
124748124887
case OE_Fail: {
124749124888
char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
124750
- pCol->zName);
124889
+ pCol->zCnName);
124751124890
sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
124752124891
onError, iReg);
124753124892
sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
124754124893
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
124755124894
VdbeCoverage(v);
@@ -125163,11 +125302,11 @@
125163125302
VdbeComment((v, "rowid"));
125164125303
}else{
125165125304
testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
125166125305
x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
125167125306
sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
125168
- VdbeComment((v, "%s", pTab->aCol[iField].zName));
125307
+ VdbeComment((v, "%s", pTab->aCol[iField].zCnName));
125169125308
}
125170125309
}
125171125310
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
125172125311
VdbeComment((v, "for %s", pIdx->zName));
125173125312
#ifdef SQLITE_ENABLE_NULL_TRIM
@@ -125222,11 +125361,11 @@
125222125361
&& pPk==pIdx /* Condition 2 */
125223125362
&& onError==OE_Replace /* Condition 1 */
125224125363
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
125225125364
0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
125226125365
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
125227
- (0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
125366
+ (0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab)))
125228125367
){
125229125368
sqlite3VdbeResolveLabel(v, addrUniqueOk);
125230125369
continue;
125231125370
}
125232125371
#endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -125257,11 +125396,11 @@
125257125396
for(i=0; i<pPk->nKeyCol; i++){
125258125397
assert( pPk->aiColumn[i]>=0 );
125259125398
x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
125260125399
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
125261125400
VdbeComment((v, "%s.%s", pTab->zName,
125262
- pTab->aCol[pPk->aiColumn[i]].zName));
125401
+ pTab->aCol[pPk->aiColumn[i]].zCnName));
125263125402
}
125264125403
}
125265125404
if( isUpdate ){
125266125405
/* If currently processing the PRIMARY KEY of a WITHOUT ROWID
125267125406
** table, only conflict if the new PRIMARY KEY values are actually
@@ -125456,11 +125595,11 @@
125456125595
/* Records with omitted columns are only allowed for schema format
125457125596
** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
125458125597
if( pTab->pSchema->file_format<2 ) return;
125459125598
125460125599
for(i=pTab->nCol-1; i>0; i--){
125461
- if( pTab->aCol[i].pDflt!=0 ) break;
125600
+ if( pTab->aCol[i].iDflt!=0 ) break;
125462125601
if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
125463125602
}
125464125603
sqlite3VdbeChangeP5(v, i+1);
125465125604
}
125466125605
#endif
@@ -125521,11 +125660,11 @@
125521125660
|| update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
125522125661
);
125523125662
125524125663
v = pParse->pVdbe;
125525125664
assert( v!=0 );
125526
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
125665
+ assert( !IsView(pTab) ); /* This table is not a VIEW */
125527125666
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
125528125667
/* All REPLACE indexes are at the end of the list */
125529125668
assert( pIdx->onError!=OE_Replace
125530125669
|| pIdx->pNext==0
125531125670
|| pIdx->pNext->onError==OE_Replace );
@@ -125823,17 +125962,12 @@
125823125962
return 0; /* tab1 and tab2 may not be the same table */
125824125963
}
125825125964
if( HasRowid(pDest)!=HasRowid(pSrc) ){
125826125965
return 0; /* source and destination must both be WITHOUT ROWID or not */
125827125966
}
125828
-#ifndef SQLITE_OMIT_VIRTUALTABLE
125829
- if( IsVirtual(pSrc) ){
125830
- return 0; /* tab2 must not be a virtual table */
125831
- }
125832
-#endif
125833
- if( pSrc->pSelect ){
125834
- return 0; /* tab2 may not be a view */
125967
+ if( !IsOrdinaryTable(pSrc) ){
125968
+ return 0; /* tab2 may not be a view or virtual table */
125835125969
}
125836125970
if( pDest->nCol!=pSrc->nCol ){
125837125971
return 0; /* Number of columns must be the same in tab1 and tab2 */
125838125972
}
125839125973
if( pDest->iPKey!=pSrc->iPKey ){
@@ -125873,33 +126007,38 @@
125873126007
/* But the transfer is only allowed if both the source and destination
125874126008
** tables have the exact same expressions for generated columns.
125875126009
** This requirement could be relaxed for VIRTUAL columns, I suppose.
125876126010
*/
125877126011
if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
125878
- if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
126012
+ if( sqlite3ExprCompare(0,
126013
+ sqlite3ColumnExpr(pSrc, pSrcCol),
126014
+ sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){
125879126015
testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
125880126016
testcase( pDestCol->colFlags & COLFLAG_STORED );
125881126017
return 0; /* Different generator expressions */
125882126018
}
125883126019
}
125884126020
#endif
125885126021
if( pDestCol->affinity!=pSrcCol->affinity ){
125886126022
return 0; /* Affinity must be the same on all columns */
125887126023
}
125888
- if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
126024
+ if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol),
126025
+ sqlite3ColumnColl(pSrcCol))!=0 ){
125889126026
return 0; /* Collating sequence must be the same on all columns */
125890126027
}
125891126028
if( pDestCol->notNull && !pSrcCol->notNull ){
125892126029
return 0; /* tab2 must be NOT NULL if tab1 is */
125893126030
}
125894126031
/* Default values for second and subsequent columns need to match. */
125895126032
if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
125896
- assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
125897
- assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
125898
- if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
125899
- || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken,
125900
- pSrcCol->pDflt->u.zToken)!=0)
126033
+ Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol);
126034
+ Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol);
126035
+ assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
126036
+ assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
126037
+ if( (pDestExpr==0)!=(pSrcExpr==0)
126038
+ || (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
126039
+ pSrcExpr->u.zToken)!=0)
125901126040
){
125902126041
return 0; /* Default values must be the same for all columns */
125903126042
}
125904126043
}
125905126044
}
@@ -125932,11 +126071,11 @@
125932126071
** But the main beneficiary of the transfer optimization is the VACUUM
125933126072
** command, and the VACUUM command disables foreign key constraints. So
125934126073
** the extra complication to make this rule less restrictive is probably
125935126074
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
125936126075
*/
125937
- if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
126076
+ if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
125938126077
return 0;
125939126078
}
125940126079
#endif
125941126080
if( (db->flags & SQLITE_CountRows)!=0 ){
125942126081
return 0; /* xfer opt does not play well with PRAGMA count_changes */
@@ -126610,10 +126749,13 @@
126610126749
int,const char**);
126611126750
void (*free_filename)(char*);
126612126751
sqlite3_file *(*database_file_object)(const char*);
126613126752
/* Version 3.34.0 and later */
126614126753
int (*txn_state)(sqlite3*,const char*);
126754
+ /* Version 3.36.1 and later */
126755
+ sqlite3_int64 (*changes64)(sqlite3*);
126756
+ sqlite3_int64 (*total_changes64)(sqlite3*);
126615126757
};
126616126758
126617126759
/*
126618126760
** This is the function signature used for all extension entry points. It
126619126761
** is also defined in the file "loadext.c".
@@ -127400,10 +127542,13 @@
127400127542
sqlite3_create_filename,
127401127543
sqlite3_free_filename,
127402127544
sqlite3_database_file_object,
127403127545
/* Version 3.34.0 and later */
127404127546
sqlite3_txn_state,
127547
+ /* Version 3.36.1 and later */
127548
+ sqlite3_changes64,
127549
+ sqlite3_total_changes64,
127405127550
};
127406127551
127407127552
/* True if x is the directory separator character
127408127553
*/
127409127554
#if SQLITE_OS_WIN
@@ -128189,11 +128334,11 @@
128189128334
/* iArg: */ 1 },
128190128335
#endif
128191128336
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
128192128337
{/* zName: */ "integrity_check",
128193128338
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
128194
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
128339
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
128195128340
/* ColNames: */ 0, 0,
128196128341
/* iArg: */ 0 },
128197128342
#endif
128198128343
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
128199128344
{/* zName: */ "journal_mode",
@@ -128297,11 +128442,11 @@
128297128442
/* iArg: */ SQLITE_QueryOnly },
128298128443
#endif
128299128444
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
128300128445
{/* zName: */ "quick_check",
128301128446
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
128302
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
128447
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
128303128448
/* ColNames: */ 0, 0,
128304128449
/* iArg: */ 0 },
128305128450
#endif
128306128451
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
128307128452
{/* zName: */ "read_uncommitted",
@@ -129616,17 +129761,20 @@
129616129761
}else if( pPk==0 ){
129617129762
k = 1;
129618129763
}else{
129619129764
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
129620129765
}
129621
- assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
129766
+ assert( sqlite3ColumnExpr(pTab,pCol)==0
129767
+ || sqlite3ColumnExpr(pTab,pCol)->op==TK_SPAN
129768
+ || isHidden>=2 );
129622129769
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
129623129770
i-nHidden,
129624
- pCol->zName,
129771
+ pCol->zCnName,
129625129772
sqlite3ColumnType(pCol,""),
129626129773
pCol->notNull ? 1 : 0,
129627
- pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
129774
+ isHidden>=2 || sqlite3ColumnExpr(pTab,pCol)==0 ? 0 :
129775
+ sqlite3ColumnExpr(pTab,pCol)->u.zToken,
129628129776
k,
129629129777
isHidden);
129630129778
}
129631129779
}
129632129780
}
@@ -129689,11 +129837,11 @@
129689129837
sqlite3CodeVerifySchema(pParse, iIdxDb);
129690129838
assert( pParse->nMem<=pPragma->nPragCName );
129691129839
for(i=0; i<mx; i++){
129692129840
i16 cnum = pIdx->aiColumn[i];
129693129841
sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
129694
- cnum<0 ? 0 : pTab->aCol[cnum].zName);
129842
+ cnum<0 ? 0 : pTab->aCol[cnum].zCnName);
129695129843
if( pPragma->iArg ){
129696129844
sqlite3VdbeMultiLoad(v, 4, "isiX",
129697129845
pIdx->aSortOrder[i],
129698129846
pIdx->azColl[i],
129699129847
i<pIdx->nKeyCol);
@@ -129796,12 +129944,12 @@
129796129944
#ifndef SQLITE_OMIT_FOREIGN_KEY
129797129945
case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
129798129946
FKey *pFK;
129799129947
Table *pTab;
129800129948
pTab = sqlite3FindTable(db, zRight, zDb);
129801
- if( pTab ){
129802
- pFK = pTab->pFKey;
129949
+ if( pTab && !IsVirtual(pTab) ){
129950
+ pFK = pTab->u.tab.pFKey;
129803129951
if( pFK ){
129804129952
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
129805129953
int i = 0;
129806129954
pParse->nMem = 8;
129807129955
sqlite3CodeVerifySchema(pParse, iTabDb);
@@ -129810,11 +129958,11 @@
129810129958
for(j=0; j<pFK->nCol; j++){
129811129959
sqlite3VdbeMultiLoad(v, 1, "iissssss",
129812129960
i,
129813129961
j,
129814129962
pFK->zTo,
129815
- pTab->aCol[pFK->aCol[j].iFrom].zName,
129963
+ pTab->aCol[pFK->aCol[j].iFrom].zCnName,
129816129964
pFK->aCol[j].zCol,
129817129965
actionName(pFK->aAction[1]), /* ON UPDATE */
129818129966
actionName(pFK->aAction[0]), /* ON DELETE */
129819129967
"NONE");
129820129968
}
@@ -129856,19 +130004,20 @@
129856130004
k = 0;
129857130005
}else{
129858130006
pTab = (Table*)sqliteHashData(k);
129859130007
k = sqliteHashNext(k);
129860130008
}
129861
- if( pTab==0 || pTab->pFKey==0 ) continue;
130009
+ if( pTab==0 || IsVirtual(pTab) || pTab->u.tab.pFKey==0 ) continue;
129862130010
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
129863130011
zDb = db->aDb[iDb].zDbSName;
129864130012
sqlite3CodeVerifySchema(pParse, iDb);
129865130013
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
129866130014
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
129867130015
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
129868130016
sqlite3VdbeLoadString(v, regResult, pTab->zName);
129869
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
130017
+ assert( !IsVirtual(pTab) );
130018
+ for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
129870130019
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
129871130020
if( pParent==0 ) continue;
129872130021
pIdx = 0;
129873130022
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
129874130023
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
@@ -129886,11 +130035,12 @@
129886130035
}
129887130036
assert( pParse->nErr>0 || pFK==0 );
129888130037
if( pFK ) break;
129889130038
if( pParse->nTab<i ) pParse->nTab = i;
129890130039
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
129891
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
130040
+ assert( !IsVirtual(pTab) );
130041
+ for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
129892130042
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
129893130043
pIdx = 0;
129894130044
aiCols = 0;
129895130045
if( pParent ){
129896130046
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
@@ -129900,10 +130050,11 @@
129900130050
129901130051
/* Generate code to read the child key values into registers
129902130052
** regRow..regRow+n. If any of the child key values are NULL, this
129903130053
** row cannot cause an FK violation. Jump directly to addrOk in
129904130054
** this case. */
130055
+ if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol;
129905130056
for(j=0; j<pFK->nCol; j++){
129906130057
int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
129907130058
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
129908130059
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
129909130060
}
@@ -130120,11 +130271,11 @@
130120130271
if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
130121130272
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
130122130273
}
130123130274
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
130124130275
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
130125
- pTab->aCol[j].zName);
130276
+ pTab->aCol[j].zCnName);
130126130277
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
130127130278
integrityCheckResultRow(v);
130128130279
sqlite3VdbeJumpHere(v, jmp2);
130129130280
}
130130130281
/* Verify CHECK constraints */
@@ -132328,11 +132479,11 @@
132328132479
SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
132329132480
int i;
132330132481
u8 h = sqlite3StrIHash(zCol);
132331132482
Column *pCol;
132332132483
for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
132333
- if( pCol->hName==h && sqlite3StrICmp(pCol->zName, zCol)==0 ) return i;
132484
+ if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
132334132485
}
132335132486
return -1;
132336132487
}
132337132488
132338132489
/*
@@ -132527,11 +132678,11 @@
132527132678
char *zName; /* Name of column in the right table */
132528132679
int iLeft; /* Matching left table */
132529132680
int iLeftCol; /* Matching column in the left table */
132530132681
132531132682
if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
132532
- zName = pRightTab->aCol[j].zName;
132683
+ zName = pRightTab->aCol[j].zCnName;
132533132684
if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
132534132685
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
132535132686
isOuter, &p->pWhere);
132536132687
}
132537132688
}
@@ -132930,11 +133081,13 @@
132930133081
Parse *pParse, /* Parsing and code generating context */
132931133082
int eTnctType, /* WHERE_DISTINCT_* value */
132932133083
int iVal, /* Value returned by codeDistinct() */
132933133084
int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
132934133085
){
132935
- if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
133086
+ if( pParse->nErr==0
133087
+ && (eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED)
133088
+ ){
132936133089
Vdbe *v = pParse->pVdbe;
132937133090
sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
132938133091
if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
132939133092
sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
132940133093
}
@@ -133892,11 +134045,11 @@
133892134045
assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
133893134046
if( iCol<0 ){
133894134047
zType = "INTEGER";
133895134048
zOrigCol = "rowid";
133896134049
}else{
133897
- zOrigCol = pTab->aCol[iCol].zName;
134050
+ zOrigCol = pTab->aCol[iCol].zCnName;
133898134051
zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
133899134052
}
133900134053
zOrigTab = pTab->zName;
133901134054
if( pNC->pParse && pTab->pSchema ){
133902134055
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
@@ -134064,11 +134217,11 @@
134064134217
if( iCol<0 ) iCol = pTab->iPKey;
134065134218
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
134066134219
if( iCol<0 ){
134067134220
zCol = "rowid";
134068134221
}else{
134069
- zCol = pTab->aCol[iCol].zName;
134222
+ zCol = pTab->aCol[iCol].zCnName;
134070134223
}
134071134224
if( fullName ){
134072134225
char *zName = 0;
134073134226
zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
134074134227
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
@@ -134149,11 +134302,11 @@
134149134302
}
134150134303
if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
134151134304
/* For columns use the column name name */
134152134305
int iCol = pColExpr->iColumn;
134153134306
if( iCol<0 ) iCol = pTab->iPKey;
134154
- zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
134307
+ zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid";
134155134308
}else if( pColExpr->op==TK_ID ){
134156134309
assert( !ExprHasProperty(pColExpr, EP_IntValue) );
134157134310
zName = pColExpr->u.zToken;
134158134311
}else{
134159134312
/* Use the original text of the column expression as its name */
@@ -134177,21 +134330,21 @@
134177134330
if( zName[j]==':' ) nName = j;
134178134331
}
134179134332
zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
134180134333
if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
134181134334
}
134182
- pCol->zName = zName;
134335
+ pCol->zCnName = zName;
134183134336
pCol->hName = sqlite3StrIHash(zName);
134184134337
sqlite3ColumnPropertiesFromName(0, pCol);
134185134338
if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
134186134339
sqlite3OomFault(db);
134187134340
}
134188134341
}
134189134342
sqlite3HashClear(&ht);
134190134343
if( db->mallocFailed ){
134191134344
for(j=0; j<i; j++){
134192
- sqlite3DbFree(db, aCol[j].zName);
134345
+ sqlite3DbFree(db, aCol[j].zCnName);
134193134346
}
134194134347
sqlite3DbFree(db, aCol);
134195134348
*paCol = 0;
134196134349
*pnCol = 0;
134197134350
return SQLITE_NOMEM_BKPT;
@@ -134239,21 +134392,22 @@
134239134392
zType = columnType(&sNC, p, 0, 0, 0);
134240134393
/* pCol->szEst = ... // Column size est for SELECT tables never used */
134241134394
pCol->affinity = sqlite3ExprAffinity(p);
134242134395
if( zType ){
134243134396
m = sqlite3Strlen30(zType);
134244
- n = sqlite3Strlen30(pCol->zName);
134245
- pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
134246
- if( pCol->zName ){
134247
- memcpy(&pCol->zName[n+1], zType, m+1);
134397
+ n = sqlite3Strlen30(pCol->zCnName);
134398
+ pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
134399
+ if( pCol->zCnName ){
134400
+ memcpy(&pCol->zCnName[n+1], zType, m+1);
134248134401
pCol->colFlags |= COLFLAG_HASTYPE;
134249134402
}
134250134403
}
134251134404
if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
134252134405
pColl = sqlite3ExprCollSeq(pParse, p);
134253
- if( pColl && pCol->zColl==0 ){
134254
- pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
134406
+ if( pColl && (pCol->colFlags & COLFLAG_HASCOLL)==0 ){
134407
+ assert( pTab->pIndex==0 );
134408
+ sqlite3ColumnSetColl(db, pCol, pColl->zName);
134255134409
}
134256134410
}
134257134411
pTab->szTabRow = 1; /* Any non-zero value works */
134258134412
}
134259134413
@@ -135811,14 +135965,14 @@
135811135965
/*
135812135966
** Assign new cursor numbers to each of the items in pSrc. For each
135813135967
** new cursor number assigned, set an entry in the aCsrMap[] array
135814135968
** to map the old cursor number to the new:
135815135969
**
135816
-** aCsrMap[iOld] = iNew;
135970
+** aCsrMap[iOld+1] = iNew;
135817135971
**
135818135972
** The array is guaranteed by the caller to be large enough for all
135819
-** existing cursor numbers in pSrc.
135973
+** existing cursor numbers in pSrc. aCsrMap[0] is the array size.
135820135974
**
135821135975
** If pSrc contains any sub-selects, call this routine recursively
135822135976
** on the FROM clause of each such sub-select, with iExcept set to -1.
135823135977
*/
135824135978
static void srclistRenumberCursors(
@@ -135830,33 +135984,44 @@
135830135984
int i;
135831135985
SrcItem *pItem;
135832135986
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
135833135987
if( i!=iExcept ){
135834135988
Select *p;
135835
- if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
135836
- aCsrMap[pItem->iCursor] = pParse->nTab++;
135989
+ assert( pItem->iCursor < aCsrMap[0] );
135990
+ if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){
135991
+ aCsrMap[pItem->iCursor+1] = pParse->nTab++;
135837135992
}
135838
- pItem->iCursor = aCsrMap[pItem->iCursor];
135993
+ pItem->iCursor = aCsrMap[pItem->iCursor+1];
135839135994
for(p=pItem->pSelect; p; p=p->pPrior){
135840135995
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
135841135996
}
135842135997
}
135843135998
}
135844135999
}
136000
+
136001
+/*
136002
+** *piCursor is a cursor number. Change it if it needs to be mapped.
136003
+*/
136004
+static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){
136005
+ int *aCsrMap = pWalker->u.aiCol;
136006
+ int iCsr = *piCursor;
136007
+ if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){
136008
+ *piCursor = aCsrMap[iCsr+1];
136009
+ }
136010
+}
135845136011
135846136012
/*
135847136013
** Expression walker callback used by renumberCursors() to update
135848136014
** Expr objects to match newly assigned cursor numbers.
135849136015
*/
135850136016
static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
135851
- int *aCsrMap = pWalker->u.aiCol;
135852136017
int op = pExpr->op;
135853
- if( (op==TK_COLUMN || op==TK_IF_NULL_ROW) && aCsrMap[pExpr->iTable] ){
135854
- pExpr->iTable = aCsrMap[pExpr->iTable];
136018
+ if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
136019
+ renumberCursorDoMapping(pWalker, &pExpr->iTable);
135855136020
}
135856
- if( ExprHasProperty(pExpr, EP_FromJoin) && aCsrMap[pExpr->iRightJoinTable] ){
135857
- pExpr->iRightJoinTable = aCsrMap[pExpr->iRightJoinTable];
136021
+ if( ExprHasProperty(pExpr, EP_FromJoin) ){
136022
+ renumberCursorDoMapping(pWalker, &pExpr->iRightJoinTable);
135858136023
}
135859136024
return WRC_Continue;
135860136025
}
135861136026
135862136027
/*
@@ -136196,11 +136361,12 @@
136196136361
/* Restriction (23) */
136197136362
if( (p->selFlags & SF_Recursive) ) return 0;
136198136363
136199136364
if( pSrc->nSrc>1 ){
136200136365
if( pParse->nSelect>500 ) return 0;
136201
- aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
136366
+ aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+1)*sizeof(int));
136367
+ if( aCsrMap ) aCsrMap[0] = pParse->nTab;
136202136368
}
136203136369
}
136204136370
136205136371
/***** If we reach this point, flattening is permitted. *****/
136206136372
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -136976,11 +137142,11 @@
136976137142
){
136977137143
return 0;
136978137144
}
136979137145
pTab = p->pSrc->a[0].pTab;
136980137146
pExpr = p->pEList->a[0].pExpr;
136981
- assert( pTab && !pTab->pSelect && pExpr );
137147
+ assert( pTab && !IsView(pTab) && pExpr );
136982137148
136983137149
if( IsVirtual(pTab) ) return 0;
136984137150
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
136985137151
if( NEVER(pAggInfo->nFunc==0) ) return 0;
136986137152
if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
@@ -137521,34 +137687,35 @@
137521137687
pTab->nTabRef++;
137522137688
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
137523137689
return WRC_Abort;
137524137690
}
137525137691
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
137526
- if( IsVirtual(pTab) || pTab->pSelect ){
137692
+ if( !IsOrdinaryTable(pTab) ){
137527137693
i16 nCol;
137528137694
u8 eCodeOrig = pWalker->eCode;
137529137695
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
137530137696
assert( pFrom->pSelect==0 );
137531
- if( pTab->pSelect
137532
- && (db->flags & SQLITE_EnableView)==0
137533
- && pTab->pSchema!=db->aDb[1].pSchema
137534
- ){
137535
- sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
137536
- pTab->zName);
137537
- }
137697
+ if( IsView(pTab) ){
137698
+ if( (db->flags & SQLITE_EnableView)==0
137699
+ && pTab->pSchema!=db->aDb[1].pSchema
137700
+ ){
137701
+ sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
137702
+ pTab->zName);
137703
+ }
137704
+ pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
137705
+ }else
137538137706
#ifndef SQLITE_OMIT_VIRTUALTABLE
137539
- assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
137540
- if( IsVirtual(pTab)
137707
+ if( ALWAYS(IsVirtual(pTab))
137541137708
&& pFrom->fg.fromDDL
137542
- && ALWAYS(pTab->pVTable!=0)
137543
- && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
137709
+ && ALWAYS(pTab->u.vtab.p!=0)
137710
+ && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
137544137711
){
137545137712
sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
137546137713
pTab->zName);
137547137714
}
137715
+ assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
137548137716
#endif
137549
- pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
137550137717
nCol = pTab->nCol;
137551137718
pTab->nCol = -1;
137552137719
pWalker->eCode = 1; /* Turn on Select.selId renumbering */
137553137720
sqlite3WalkSelect(pWalker, pFrom->pSelect);
137554137721
pWalker->eCode = eCodeOrig;
@@ -137644,11 +137811,11 @@
137644137811
}
137645137812
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
137646137813
zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
137647137814
}
137648137815
for(j=0; j<pTab->nCol; j++){
137649
- char *zName = pTab->aCol[j].zName;
137816
+ char *zName = pTab->aCol[j].zCnName;
137650137817
char *zColname; /* The computed column name */
137651137818
char *zToFree; /* Malloced string that needs to be freed */
137652137819
Token sColname; /* Computed column name as a token */
137653137820
137654137821
assert( zName );
@@ -138076,12 +138243,20 @@
138076138243
** within the HAVING expression with a constant "1".
138077138244
*/
138078138245
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
138079138246
if( pExpr->op!=TK_AND ){
138080138247
Select *pS = pWalker->u.pSelect;
138248
+ /* This routine is called before the HAVING clause of the current
138249
+ ** SELECT is analyzed for aggregates. So if pExpr->pAggInfo is set
138250
+ ** here, it indicates that the expression is a correlated reference to a
138251
+ ** column from an outer aggregate query, or an aggregate function that
138252
+ ** belongs to an outer query. Do not move the expression to the WHERE
138253
+ ** clause in this obscure case, as doing so may corrupt the outer Select
138254
+ ** statements AggInfo structure. */
138081138255
if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
138082138256
&& ExprAlwaysFalse(pExpr)==0
138257
+ && pExpr->pAggInfo==0
138083138258
){
138084138259
sqlite3 *db = pWalker->pParse->db;
138085138260
Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
138086138261
if( pNew ){
138087138262
Expr *pWhere = pS->pWhere;
@@ -138343,15 +138518,20 @@
138343138518
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
138344138519
sqlite3TreeViewSelect(0, p, 0);
138345138520
}
138346138521
#endif
138347138522
138348
- /* If the SF_UpdateFrom flag is set, then this function is being called
138523
+ /* If the SF_UFSrcCheck flag is set, then this function is being called
138349138524
** as part of populating the temp table for an UPDATE...FROM statement.
138350138525
** In this case, it is an error if the target object (pSrc->a[0]) name
138351
- ** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
138352
- if( p->selFlags & SF_UpdateFrom ){
138526
+ ** or alias is duplicated within FROM clause (pSrc->a[1..n]).
138527
+ **
138528
+ ** Postgres disallows this case too. The reason is that some other
138529
+ ** systems handle this case differently, and not all the same way,
138530
+ ** which is just confusing. To avoid this, we follow PG's lead and
138531
+ ** disallow it altogether. */
138532
+ if( p->selFlags & SF_UFSrcCheck ){
138353138533
SrcItem *p0 = &p->pSrc->a[0];
138354138534
for(i=1; i<p->pSrc->nSrc; i++){
138355138535
SrcItem *p1 = &p->pSrc->a[i];
138356138536
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
138357138537
sqlite3ErrorMsg(pParse,
@@ -138359,10 +138539,16 @@
138359138539
p0->zAlias ? p0->zAlias : p0->pTab->zName
138360138540
);
138361138541
goto select_end;
138362138542
}
138363138543
}
138544
+
138545
+ /* Clear the SF_UFSrcCheck flag. The check has already been performed,
138546
+ ** and leaving this flag set can cause errors if a compound sub-query
138547
+ ** in p->pSrc is flattened into this query and this function called
138548
+ ** again as part of compound SELECT processing. */
138549
+ p->selFlags &= ~SF_UFSrcCheck;
138364138550
}
138365138551
138366138552
if( pDest->eDest==SRT_Output ){
138367138553
sqlite3GenerateColumnNames(pParse, p);
138368138554
}
@@ -138429,10 +138615,43 @@
138429138615
** will be implemented as a co-routine and there is no advantage to
138430138616
** flattening in that case.
138431138617
*/
138432138618
if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
138433138619
assert( pSub->pGroupBy==0 );
138620
+
138621
+ /* If a FROM-clause subquery has an ORDER BY clause that is not
138622
+ ** really doing anything, then delete it now so that it does not
138623
+ ** interfere with query flattening. See the discussion at
138624
+ ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
138625
+ **
138626
+ ** Beware of these cases where the ORDER BY clause may not be safely
138627
+ ** omitted:
138628
+ **
138629
+ ** (1) There is also a LIMIT clause
138630
+ ** (2) The subquery was added to help with window-function
138631
+ ** processing
138632
+ ** (3) The subquery is in the FROM clause of an UPDATE
138633
+ ** (4) The outer query uses an aggregate function other than
138634
+ ** the built-in count(), min(), or max().
138635
+ ** (5) The ORDER BY isn't going to accomplish anything because
138636
+ ** one of:
138637
+ ** (a) The outer query has a different ORDER BY clause
138638
+ ** (b) The subquery is part of a join
138639
+ ** See forum post 062d576715d277c8
138640
+ */
138641
+ if( pSub->pOrderBy!=0
138642
+ && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
138643
+ && pSub->pLimit==0 /* Condition (1) */
138644
+ && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
138645
+ && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
138646
+ && OptimizationEnabled(db, SQLITE_OmitOrderBy)
138647
+ ){
138648
+ SELECTTRACE(0x100,pParse,p,
138649
+ ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
138650
+ sqlite3ExprListDelete(db, pSub->pOrderBy);
138651
+ pSub->pOrderBy = 0;
138652
+ }
138434138653
138435138654
/* If the outer query contains a "complex" result set (that is,
138436138655
** if the result set of the outer query uses functions or subqueries)
138437138656
** and if the subquery contains an ORDER BY clause and if
138438138657
** it will be implemented as a co-routine, then do not flatten. This
@@ -139877,16 +140096,16 @@
139877140096
}
139878140097
139879140098
/* INSTEAD of triggers are only for views and views only support INSTEAD
139880140099
** of triggers.
139881140100
*/
139882
- if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
140101
+ if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
139883140102
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
139884140103
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
139885140104
goto trigger_orphan_error;
139886140105
}
139887
- if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
140106
+ if( !IsView(pTab) && tr_tm==TK_INSTEAD ){
139888140107
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
139889140108
" trigger on table: %S", pTableName->a);
139890140109
goto trigger_orphan_error;
139891140110
}
139892140111
@@ -140535,15 +140754,15 @@
140535140754
if( isAsteriskTerm(pParse, pOldExpr) ){
140536140755
int jj;
140537140756
for(jj=0; jj<pTab->nCol; jj++){
140538140757
Expr *pNewExpr;
140539140758
if( IsHiddenColumn(pTab->aCol+jj) ) continue;
140540
- pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
140759
+ pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName);
140541140760
pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
140542140761
if( !db->mallocFailed ){
140543140762
struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
140544
- pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zName);
140763
+ pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName);
140545140764
pItem->eEName = ENAME_NAME;
140546140765
}
140547140766
}
140548140767
}else{
140549140768
Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
@@ -140584,10 +140803,11 @@
140584140803
memset(&sFrom, 0, sizeof(sFrom));
140585140804
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
140586140805
sSelect.pSrc = &sFrom;
140587140806
sFrom.nSrc = 1;
140588140807
sFrom.a[0].pTab = pTab;
140808
+ sFrom.a[0].iCursor = -1;
140589140809
sqlite3SelectPrep(pParse, &sSelect, 0);
140590140810
if( db->mallocFailed==0 && pParse->nErr==0 ){
140591140811
sqlite3GenerateColumnNames(pParse, &sSelect);
140592140812
}
140593140813
sqlite3ExprListDelete(db, sSelect.pEList);
@@ -141139,17 +141359,18 @@
141139141359
** integer. In that case, add an OP_RealAffinity opcode to make sure
141140141360
** it has been converted into REAL.
141141141361
*/
141142141362
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
141143141363
assert( pTab!=0 );
141144
- if( !pTab->pSelect ){
141364
+ if( !IsView(pTab) ){
141145141365
sqlite3_value *pValue = 0;
141146141366
u8 enc = ENC(sqlite3VdbeDb(v));
141147141367
Column *pCol = &pTab->aCol[i];
141148
- VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
141368
+ VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName));
141149141369
assert( i<pTab->nCol );
141150
- sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
141370
+ sqlite3ValueFromExpr(sqlite3VdbeDb(v),
141371
+ sqlite3ColumnExpr(pTab,pCol), enc,
141151141372
pCol->affinity, &pValue);
141152141373
if( pValue ){
141153141374
sqlite3VdbeAppendP4(v, pValue, P4_MEM);
141154141375
}
141155141376
}
@@ -141315,11 +141536,11 @@
141315141536
}
141316141537
#endif
141317141538
pList = sqlite3ExprListAppend(pParse, pList, pNew);
141318141539
}
141319141540
eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
141320
- }else if( pTab->pSelect ){
141541
+ }else if( IsView(pTab) ){
141321141542
for(i=0; i<pTab->nCol; i++){
141322141543
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
141323141544
}
141324141545
eDest = SRT_Table;
141325141546
}else{
@@ -141338,12 +141559,13 @@
141338141559
sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
141339141560
);
141340141561
}
141341141562
}
141342141563
pSelect = sqlite3SelectNew(pParse, pList,
141343
- pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UpdateFrom|SF_IncludeHidden, pLimit2
141564
+ pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UFSrcCheck|SF_IncludeHidden, pLimit2
141344141565
);
141566
+ if( pSelect ) pSelect->selFlags |= SF_OrderByReqd;
141345141567
sqlite3SelectDestInit(&dest, eDest, iEph);
141346141568
dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
141347141569
sqlite3Select(pParse, pSelect, &dest);
141348141570
sqlite3SelectDelete(db, pSelect);
141349141571
}
@@ -141439,11 +141661,11 @@
141439141661
/* Figure out if we have any triggers and if the table being
141440141662
** updated is a view.
141441141663
*/
141442141664
#ifndef SQLITE_OMIT_TRIGGER
141443141665
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
141444
- isView = pTab->pSelect!=0;
141666
+ isView = IsView(pTab);
141445141667
assert( pTrigger || tmask==0 );
141446141668
#else
141447141669
# define pTrigger 0
141448141670
# define isView 0
141449141671
# define tmask 0
@@ -141528,17 +141750,20 @@
141528141750
** column to be updated, make sure we have authorization to change
141529141751
** that column.
141530141752
*/
141531141753
chngRowid = chngPk = 0;
141532141754
for(i=0; i<pChanges->nExpr; i++){
141755
+ u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName);
141533141756
/* If this is an UPDATE with a FROM clause, do not resolve expressions
141534141757
** here. The call to sqlite3Select() below will do that. */
141535141758
if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
141536141759
goto update_cleanup;
141537141760
}
141538141761
for(j=0; j<pTab->nCol; j++){
141539
- if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
141762
+ if( pTab->aCol[j].hName==hCol
141763
+ && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
141764
+ ){
141540141765
if( j==pTab->iPKey ){
141541141766
chngRowid = 1;
141542141767
pRowidExpr = pChanges->a[i].pExpr;
141543141768
iRowidExpr = i;
141544141769
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
@@ -141548,11 +141773,11 @@
141548141773
else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
141549141774
testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
141550141775
testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
141551141776
sqlite3ErrorMsg(pParse,
141552141777
"cannot UPDATE generated column \"%s\"",
141553
- pTab->aCol[j].zName);
141778
+ pTab->aCol[j].zCnName);
141554141779
goto update_cleanup;
141555141780
}
141556141781
#endif
141557141782
aXRef[j] = i;
141558141783
break;
@@ -141572,11 +141797,11 @@
141572141797
}
141573141798
#ifndef SQLITE_OMIT_AUTHORIZATION
141574141799
{
141575141800
int rc;
141576141801
rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
141577
- j<0 ? "ROWID" : pTab->aCol[j].zName,
141802
+ j<0 ? "ROWID" : pTab->aCol[j].zCnName,
141578141803
db->aDb[iDb].zDbSName);
141579141804
if( rc==SQLITE_DENY ){
141580141805
goto update_cleanup;
141581141806
}else if( rc==SQLITE_IGNORE ){
141582141807
aXRef[j] = -1;
@@ -141604,12 +141829,14 @@
141604141829
do{
141605141830
bProgress = 0;
141606141831
for(i=0; i<pTab->nCol; i++){
141607141832
if( aXRef[i]>=0 ) continue;
141608141833
if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
141609
- if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
141610
- aXRef, chngRowid) ){
141834
+ if( sqlite3ExprReferencesUpdatedColumn(
141835
+ sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
141836
+ aXRef, chngRowid)
141837
+ ){
141611141838
aXRef[i] = 99999;
141612141839
bProgress = 1;
141613141840
}
141614141841
}
141615141842
}while( bProgress );
@@ -142697,11 +142924,11 @@
142697142924
int k;
142698142925
assert( pPk->aiColumn[i]>=0 );
142699142926
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
142700142927
sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
142701142928
VdbeComment((v, "%s.%s", pIdx->zName,
142702
- pTab->aCol[pPk->aiColumn[i]].zName));
142929
+ pTab->aCol[pPk->aiColumn[i]].zCnName));
142703142930
}
142704142931
sqlite3VdbeVerifyAbortable(v, OE_Abort);
142705142932
i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
142706142933
VdbeCoverage(v);
142707142934
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
@@ -142879,12 +143106,12 @@
142879143106
int rc = SQLITE_OK; /* Return code from service routines */
142880143107
Btree *pMain; /* The database being vacuumed */
142881143108
Btree *pTemp; /* The temporary database we vacuum into */
142882143109
u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
142883143110
u64 saved_flags; /* Saved value of db->flags */
142884
- int saved_nChange; /* Saved value of db->nChange */
142885
- int saved_nTotalChange; /* Saved value of db->nTotalChange */
143111
+ i64 saved_nChange; /* Saved value of db->nChange */
143112
+ i64 saved_nTotalChange; /* Saved value of db->nTotalChange */
142886143113
u32 saved_openFlags; /* Saved value of db->openFlags */
142887143114
u8 saved_mTrace; /* Saved trace settings */
142888143115
Db *pDb = 0; /* Database to detach at end of vacuum */
142889143116
int isMemDb; /* True if vacuuming a :memory: database */
142890143117
int nRes; /* Bytes of reserved space at the end of each page */
@@ -143327,11 +143554,11 @@
143327143554
** this virtual-table, if one has been created, or NULL otherwise.
143328143555
*/
143329143556
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
143330143557
VTable *pVtab;
143331143558
assert( IsVirtual(pTab) );
143332
- for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
143559
+ for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
143333143560
return pVtab;
143334143561
}
143335143562
143336143563
/*
143337143564
** Decrement the ref-count on a virtual table object. When the ref-count
@@ -143355,35 +143582,35 @@
143355143582
}
143356143583
}
143357143584
143358143585
/*
143359143586
** Table p is a virtual table. This function moves all elements in the
143360
-** p->pVTable list to the sqlite3.pDisconnect lists of their associated
143587
+** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
143361143588
** database connections to be disconnected at the next opportunity.
143362143589
** Except, if argument db is not NULL, then the entry associated with
143363
-** connection db is left in the p->pVTable list.
143590
+** connection db is left in the p->u.vtab.p list.
143364143591
*/
143365143592
static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
143366143593
VTable *pRet = 0;
143367
- VTable *pVTable = p->pVTable;
143368
- p->pVTable = 0;
143594
+ VTable *pVTable = p->u.vtab.p;
143595
+ p->u.vtab.p = 0;
143369143596
143370143597
/* Assert that the mutex (if any) associated with the BtShared database
143371143598
** that contains table p is held by the caller. See header comments
143372143599
** above function sqlite3VtabUnlockList() for an explanation of why
143373143600
** this makes it safe to access the sqlite3.pDisconnect list of any
143374
- ** database connection that may have an entry in the p->pVTable list.
143601
+ ** database connection that may have an entry in the p->u.vtab.p list.
143375143602
*/
143376143603
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
143377143604
143378143605
while( pVTable ){
143379143606
sqlite3 *db2 = pVTable->db;
143380143607
VTable *pNext = pVTable->pNext;
143381143608
assert( db2 );
143382143609
if( db2==db ){
143383143610
pRet = pVTable;
143384
- p->pVTable = pRet;
143611
+ p->u.vtab.p = pRet;
143385143612
pRet->pNext = 0;
143386143613
}else{
143387143614
pVTable->pNext = db2->pDisconnect;
143388143615
db2->pDisconnect = pVTable;
143389143616
}
@@ -143407,11 +143634,11 @@
143407143634
143408143635
assert( IsVirtual(p) );
143409143636
assert( sqlite3BtreeHoldsAllMutexes(db) );
143410143637
assert( sqlite3_mutex_held(db->mutex) );
143411143638
143412
- for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
143639
+ for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){
143413143640
if( (*ppVTab)->db==db ){
143414143641
VTable *pVTab = *ppVTab;
143415143642
*ppVTab = pVTab->pNext;
143416143643
sqlite3VtabUnlock(pVTab);
143417143644
break;
@@ -143471,40 +143698,40 @@
143471143698
** in the list are moved to the sqlite3.pDisconnect list of the associated
143472143699
** database connection.
143473143700
*/
143474143701
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
143475143702
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
143476
- if( p->azModuleArg ){
143703
+ if( p->u.vtab.azArg ){
143477143704
int i;
143478
- for(i=0; i<p->nModuleArg; i++){
143479
- if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
143705
+ for(i=0; i<p->u.vtab.nArg; i++){
143706
+ if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]);
143480143707
}
143481
- sqlite3DbFree(db, p->azModuleArg);
143708
+ sqlite3DbFree(db, p->u.vtab.azArg);
143482143709
}
143483143710
}
143484143711
143485143712
/*
143486
-** Add a new module argument to pTable->azModuleArg[].
143713
+** Add a new module argument to pTable->u.vtab.azArg[].
143487143714
** The string is not copied - the pointer is stored. The
143488143715
** string will be freed automatically when the table is
143489143716
** deleted.
143490143717
*/
143491143718
static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
143492
- sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->nModuleArg);
143719
+ sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg);
143493143720
char **azModuleArg;
143494143721
sqlite3 *db = pParse->db;
143495
- if( pTable->nModuleArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
143722
+ if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
143496143723
sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
143497143724
}
143498
- azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
143725
+ azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes);
143499143726
if( azModuleArg==0 ){
143500143727
sqlite3DbFree(db, zArg);
143501143728
}else{
143502
- int i = pTable->nModuleArg++;
143729
+ int i = pTable->u.vtab.nArg++;
143503143730
azModuleArg[i] = zArg;
143504143731
azModuleArg[i+1] = 0;
143505
- pTable->azModuleArg = azModuleArg;
143732
+ pTable->u.vtab.azArg = azModuleArg;
143506143733
}
143507143734
}
143508143735
143509143736
/*
143510143737
** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
@@ -143523,14 +143750,15 @@
143523143750
143524143751
sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
143525143752
pTable = pParse->pNewTable;
143526143753
if( pTable==0 ) return;
143527143754
assert( 0==pTable->pIndex );
143755
+ pTable->eTabType = TABTYP_VTAB;
143528143756
143529143757
db = pParse->db;
143530143758
143531
- assert( pTable->nModuleArg==0 );
143759
+ assert( pTable->u.vtab.nArg==0 );
143532143760
addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName));
143533143761
addModuleArgument(pParse, pTable, 0);
143534143762
addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName));
143535143763
assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0)
143536143764
|| (pParse->sNameToken.z==pName1->z && pName2->z==0)
@@ -143543,15 +143771,15 @@
143543143771
/* Creating a virtual table invokes the authorization callback twice.
143544143772
** The first invocation, to obtain permission to INSERT a row into the
143545143773
** sqlite_schema table, has already been made by sqlite3StartTable().
143546143774
** The second call, to obtain permission to create the table, is made now.
143547143775
*/
143548
- if( pTable->azModuleArg ){
143776
+ if( pTable->u.vtab.azArg ){
143549143777
int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
143550143778
assert( iDb>=0 ); /* The database the table is being created in */
143551143779
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
143552
- pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
143780
+ pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName);
143553143781
}
143554143782
#endif
143555143783
}
143556143784
143557143785
/*
@@ -143577,11 +143805,11 @@
143577143805
sqlite3 *db = pParse->db; /* The database connection */
143578143806
143579143807
if( pTab==0 ) return;
143580143808
addArgumentToVtab(pParse);
143581143809
pParse->sArg.z = 0;
143582
- if( pTab->nModuleArg<1 ) return;
143810
+ if( pTab->u.vtab.nArg<1 ) return;
143583143811
143584143812
/* If the CREATE VIRTUAL TABLE statement is being entered for the
143585143813
** first time (in other words if the virtual table is actually being
143586143814
** created now instead of just being read out of sqlite_schema) then
143587143815
** do additional initialization work and store the statement text
@@ -143692,12 +143920,12 @@
143692143920
char **pzErr
143693143921
){
143694143922
VtabCtx sCtx;
143695143923
VTable *pVTable;
143696143924
int rc;
143697
- const char *const*azArg = (const char *const*)pTab->azModuleArg;
143698
- int nArg = pTab->nModuleArg;
143925
+ const char *const*azArg = (const char *const*)pTab->u.vtab.azArg;
143926
+ int nArg = pTab->u.vtab.nArg;
143699143927
char *zErr = 0;
143700143928
char *zModuleName;
143701143929
int iDb;
143702143930
VtabCtx *pCtx;
143703143931
@@ -143725,11 +143953,11 @@
143725143953
pVTable->db = db;
143726143954
pVTable->pMod = pMod;
143727143955
pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
143728143956
143729143957
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
143730
- pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
143958
+ pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName;
143731143959
143732143960
/* Invoke the virtual table constructor */
143733143961
assert( &db->pVtabCtx );
143734143962
assert( xConstruct );
143735143963
sCtx.pTab = pTab;
@@ -143764,16 +143992,16 @@
143764143992
rc = SQLITE_ERROR;
143765143993
}else{
143766143994
int iCol;
143767143995
u16 oooHidden = 0;
143768143996
/* If everything went according to plan, link the new VTable structure
143769
- ** into the linked list headed by pTab->pVTable. Then loop through the
143997
+ ** into the linked list headed by pTab->u.vtab.p. Then loop through the
143770143998
** columns of the table to see if any of them contain the token "hidden".
143771143999
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
143772144000
** the type string. */
143773
- pVTable->pNext = pTab->pVTable;
143774
- pTab->pVTable = pVTable;
144001
+ pVTable->pNext = pTab->u.vtab.p;
144002
+ pTab->u.vtab.p = pVTable;
143775144003
143776144004
for(iCol=0; iCol<pTab->nCol; iCol++){
143777144005
char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
143778144006
int nType;
143779144007
int i = 0;
@@ -143827,15 +144055,15 @@
143827144055
if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
143828144056
return SQLITE_OK;
143829144057
}
143830144058
143831144059
/* Locate the required virtual table module */
143832
- zMod = pTab->azModuleArg[0];
144060
+ zMod = pTab->u.vtab.azArg[0];
143833144061
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
143834144062
143835144063
if( !pMod ){
143836
- const char *zModule = pTab->azModuleArg[0];
144064
+ const char *zModule = pTab->u.vtab.azArg[0];
143837144065
sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
143838144066
rc = SQLITE_ERROR;
143839144067
}else{
143840144068
char *zErr = 0;
143841144069
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
@@ -143894,14 +144122,14 @@
143894144122
Table *pTab;
143895144123
Module *pMod;
143896144124
const char *zMod;
143897144125
143898144126
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
143899
- assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
144127
+ assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p );
143900144128
143901144129
/* Locate the required virtual table module */
143902
- zMod = pTab->azModuleArg[0];
144130
+ zMod = pTab->u.vtab.azArg[0];
143903144131
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
143904144132
143905144133
/* If the module has been registered and includes a Create method,
143906144134
** invoke it now. If the module has not been registered, return an
143907144135
** error. Otherwise, do nothing.
@@ -143957,17 +144185,17 @@
143957144185
sParse.db = db;
143958144186
sParse.nQueryLoop = 1;
143959144187
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
143960144188
&& sParse.pNewTable
143961144189
&& !db->mallocFailed
143962
- && !sParse.pNewTable->pSelect
143963
- && !IsVirtual(sParse.pNewTable)
144190
+ && IsOrdinaryTable(sParse.pNewTable)
143964144191
){
143965144192
if( !pTab->aCol ){
143966144193
Table *pNew = sParse.pNewTable;
143967144194
Index *pIdx;
143968144195
pTab->aCol = pNew->aCol;
144196
+ sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
143969144197
pTab->nNVCol = pTab->nCol = pNew->nCol;
143970144198
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
143971144199
pNew->nCol = 0;
143972144200
pNew->aCol = 0;
143973144201
assert( pTab->pIndex==0 );
@@ -144018,14 +144246,14 @@
144018144246
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
144019144247
int rc = SQLITE_OK;
144020144248
Table *pTab;
144021144249
144022144250
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
144023
- if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){
144251
+ if( pTab!=0 && ALWAYS(pTab->u.vtab.p!=0) ){
144024144252
VTable *p;
144025144253
int (*xDestroy)(sqlite3_vtab *);
144026
- for(p=pTab->pVTable; p; p=p->pNext){
144254
+ for(p=pTab->u.vtab.p; p; p=p->pNext){
144027144255
assert( p->pVtab );
144028144256
if( p->pVtab->nRef>0 ){
144029144257
return SQLITE_LOCKED;
144030144258
}
144031144259
}
@@ -144035,13 +144263,13 @@
144035144263
assert( xDestroy!=0 );
144036144264
pTab->nTabRef++;
144037144265
rc = xDestroy(p->pVtab);
144038144266
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
144039144267
if( rc==SQLITE_OK ){
144040
- assert( pTab->pVTable==p && p->pNext==0 );
144268
+ assert( pTab->u.vtab.p==p && p->pNext==0 );
144041144269
p->pVtab = 0;
144042
- pTab->pVTable = 0;
144270
+ pTab->u.vtab.p = 0;
144043144271
sqlite3VtabUnlock(p);
144044144272
}
144045144273
sqlite3DeleteTable(db, pTab);
144046144274
}
144047144275
@@ -144325,12 +144553,13 @@
144325144553
}
144326144554
144327144555
/*
144328144556
** Check to see if virtual table module pMod can be have an eponymous
144329144557
** virtual table instance. If it can, create one if one does not already
144330
-** exist. Return non-zero if the eponymous virtual table instance exists
144331
-** when this routine returns, and return zero if it does not exist.
144558
+** exist. Return non-zero if either the eponymous virtual table instance
144559
+** exists when this routine returns or if an attempt to create it failed
144560
+** and an error message was left in pParse.
144332144561
**
144333144562
** An eponymous virtual table instance is one that is named after its
144334144563
** module, and more importantly, does not require a CREATE VIRTUAL TABLE
144335144564
** statement in order to come into existance. Eponymous virtual table
144336144565
** instances always exist. They cannot be DROP-ed.
@@ -144353,12 +144582,13 @@
144353144582
sqlite3DbFree(db, pTab);
144354144583
return 0;
144355144584
}
144356144585
pMod->pEpoTab = pTab;
144357144586
pTab->nTabRef = 1;
144587
+ pTab->eTabType = TABTYP_VTAB;
144358144588
pTab->pSchema = db->aDb[0].pSchema;
144359
- assert( pTab->nModuleArg==0 );
144589
+ assert( pTab->u.vtab.nArg==0 );
144360144590
pTab->iPKey = -1;
144361144591
pTab->tabFlags |= TF_Eponymous;
144362144592
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
144363144593
addModuleArgument(pParse, pTab, 0);
144364144594
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
@@ -144365,11 +144595,10 @@
144365144595
rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
144366144596
if( rc ){
144367144597
sqlite3ErrorMsg(pParse, "%s", zErr);
144368144598
sqlite3DbFree(db, zErr);
144369144599
sqlite3VtabEponymousTableClear(db, pMod);
144370
- return 0;
144371144600
}
144372144601
return 1;
144373144602
}
144374144603
144375144604
/*
@@ -145099,11 +145328,11 @@
145099145328
*/
145100145329
static const char *explainIndexColumnName(Index *pIdx, int i){
145101145330
i = pIdx->aiColumn[i];
145102145331
if( i==XN_EXPR ) return "<expr>";
145103145332
if( i==XN_ROWID ) return "rowid";
145104
- return pIdx->pTable->aCol[i].zName;
145333
+ return pIdx->pTable->aCol[i].zCnName;
145105145334
}
145106145335
145107145336
/*
145108145337
** This routine is a helper for explainIndexRange() below
145109145338
**
@@ -146311,12 +146540,13 @@
146311146540
if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
146312146541
w.xExprCallback = whereIndexExprTransNode;
146313146542
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
146314146543
}else if( iRef>=0
146315146544
&& (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
146316
- && (pTab->aCol[iRef].zColl==0
146317
- || sqlite3StrICmp(pTab->aCol[iRef].zColl, sqlite3StrBINARY)==0)
146545
+ && ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
146546
+ || sqlite3StrICmp(sqlite3ColumnColl(&pTab->aCol[iRef]),
146547
+ sqlite3StrBINARY)==0)
146318146548
){
146319146549
/* Check to see if there are direct references to generated columns
146320146550
** that are contained in the index. Pulling the generated column
146321146551
** out of the index is an optimization only - the main table is always
146322146552
** available if the index cannot be used. To avoid unnecessary
@@ -148731,11 +148961,15 @@
148731148961
pNew->u.x.leftColumn = aiCurCol[1];
148732148962
testcase( (prereqLeft | extraRight) != prereqLeft );
148733148963
pNew->prereqRight = prereqLeft | extraRight;
148734148964
pNew->prereqAll = prereqAll;
148735148965
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
148736
- }else if( op==TK_ISNULL && 0==sqlite3ExprCanBeNull(pLeft) ){
148966
+ }else
148967
+ if( op==TK_ISNULL
148968
+ && !ExprHasProperty(pExpr,EP_FromJoin)
148969
+ && 0==sqlite3ExprCanBeNull(pLeft)
148970
+ ){
148737148971
pExpr->op = TK_TRUEFALSE;
148738148972
pExpr->u.zToken = "false";
148739148973
ExprSetProperty(pExpr, EP_IsFalse);
148740148974
pTerm->prereqAll = 0;
148741148975
pTerm->eOperator = 0;
@@ -148928,12 +149162,12 @@
148928149162
){
148929149163
int i;
148930149164
for(i=0; i<nLeft; i++){
148931149165
int idxNew;
148932149166
Expr *pNew;
148933
- Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
148934
- Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
149167
+ Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, nLeft);
149168
+ Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft);
148935149169
148936149170
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
148937149171
transferJoinMarkings(pNew, pExpr);
148938149172
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
148939149173
exprAnalyze(pSrc, pWC, idxNew);
@@ -150018,11 +150252,11 @@
150018150252
testcase( iCol==BMS );
150019150253
testcase( iCol==BMS-1 );
150020150254
if( !sentWarning ){
150021150255
sqlite3_log(SQLITE_WARNING_AUTOINDEX,
150022150256
"automatic index on %s(%s)", pTable->zName,
150023
- pTable->aCol[iCol].zName);
150257
+ pTable->aCol[iCol].zCnName);
150024150258
sentWarning = 1;
150025150259
}
150026150260
if( (idxCols & cMask)==0 ){
150027150261
if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
150028150262
goto end_auto_index_create;
@@ -151932,11 +152166,11 @@
151932152166
}else{
151933152167
#ifdef SQLITE_ENABLE_STAT4
151934152168
tRowcnt nOut = 0;
151935152169
if( nInMul==0
151936152170
&& pProbe->nSample
151937
- && pNew->u.btree.nEq<=pProbe->nSampleCol
152171
+ && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
151938152172
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
151939152173
&& OptimizationEnabled(db, SQLITE_Stat4)
151940152174
){
151941152175
Expr *pExpr = pTerm->pExpr;
151942152176
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
@@ -152197,11 +152431,10 @@
152197152431
WhereLoop *pNew; /* Template WhereLoop object */
152198152432
int rc = SQLITE_OK; /* Return code */
152199152433
int iSortIdx = 1; /* Index number */
152200152434
int b; /* A boolean value */
152201152435
LogEst rSize; /* number of rows in the table */
152202
- LogEst rLogSize; /* Logarithm of the number of rows in the table */
152203152436
WhereClause *pWC; /* The parsed WHERE clause */
152204152437
Table *pTab; /* Table being queried */
152205152438
152206152439
pNew = pBuilder->pNew;
152207152440
pWInfo = pBuilder->pWInfo;
@@ -152240,11 +152473,10 @@
152240152473
sPk.pNext = pFirst;
152241152474
}
152242152475
pProbe = &sPk;
152243152476
}
152244152477
rSize = pTab->nRowLogEst;
152245
- rLogSize = estLog(rSize);
152246152478
152247152479
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
152248152480
/* Automatic indexes */
152249152481
if( !pBuilder->pOrSet /* Not part of an OR optimization */
152250152482
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
@@ -152254,12 +152486,14 @@
152254152486
&& HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
152255152487
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
152256152488
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
152257152489
){
152258152490
/* Generate auto-index WhereLoops */
152491
+ LogEst rLogSize; /* Logarithm of the number of rows in the table */
152259152492
WhereTerm *pTerm;
152260152493
WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
152494
+ rLogSize = estLog(rSize);
152261152495
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
152262152496
if( pTerm->prereqRight & pNew->maskSelf ) continue;
152263152497
if( termCanDriveIndex(pTerm, pSrc, 0) ){
152264152498
pNew->u.btree.nEq = 1;
152265152499
pNew->nSkip = 0;
@@ -152273,11 +152507,11 @@
152273152507
** of X is smaller for views and subqueries so that the query planner
152274152508
** will be more aggressive about generating automatic indexes for
152275152509
** those objects, since there is no opportunity to add schema
152276152510
** indexes on subqueries and views. */
152277152511
pNew->rSetup = rLogSize + rSize;
152278
- if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
152512
+ if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){
152279152513
pNew->rSetup += 28;
152280152514
}else{
152281152515
pNew->rSetup -= 10;
152282152516
}
152283152517
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
@@ -154424,11 +154658,11 @@
154424154658
154425154659
pTabItem = &pTabList->a[pLevel->iFrom];
154426154660
pTab = pTabItem->pTab;
154427154661
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
154428154662
pLoop = pLevel->pWLoop;
154429
- if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
154663
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
154430154664
/* Do nothing */
154431154665
}else
154432154666
#ifndef SQLITE_OMIT_VIRTUALTABLE
154433154667
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
154434154668
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
@@ -154741,10 +154975,16 @@
154741154975
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
154742154976
}
154743154977
if( (ws & WHERE_INDEXED)
154744154978
|| ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
154745154979
){
154980
+ if( ws & WHERE_MULTI_OR ){
154981
+ Index *pIx = pLevel->u.pCovidx;
154982
+ int iDb = sqlite3SchemaToIndex(db, pIx->pSchema);
154983
+ sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb);
154984
+ sqlite3VdbeSetP4KeyInfo(pParse, pIx);
154985
+ }
154746154986
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
154747154987
}
154748154988
if( pLevel->op==OP_Return ){
154749154989
sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
154750154990
}else{
@@ -154787,11 +155027,11 @@
154787155027
** Except, do not close cursors that will be reused by the OR optimization
154788155028
** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors
154789155029
** created for the ONEPASS optimization.
154790155030
*/
154791155031
if( (pTab->tabFlags & TF_Ephemeral)==0
154792
- && pTab->pSelect==0
155032
+ && !IsView(pTab)
154793155033
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
154794155034
){
154795155035
int ws = pLoop->wsFlags;
154796155036
if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
154797155037
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
@@ -155805,13 +156045,11 @@
155805156045
break;
155806156046
}
155807156047
if( bIntToNull ){
155808156048
int iDummy;
155809156049
Expr *pSub;
155810
- for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
155811
- assert( pSub );
155812
- }
156050
+ pSub = sqlite3ExprSkipCollateAndLikely(pDup);
155813156051
if( sqlite3ExprIsInteger(pSub, &iDummy) ){
155814156052
pSub->op = TK_NULL;
155815156053
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
155816156054
pSub->u.zToken = 0;
155817156055
}
@@ -155969,11 +156207,11 @@
155969156207
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
155970156208
if( p->pSrc ){
155971156209
Table *pTab2;
155972156210
p->pSrc->a[0].pSelect = pSub;
155973156211
sqlite3SrcListAssignCursors(pParse, p->pSrc);
155974
- pSub->selFlags |= SF_Expanded;
156212
+ pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
155975156213
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
155976156214
pSub->selFlags |= (selFlags & SF_Aggregate);
155977156215
if( pTab2==0 ){
155978156216
/* Might actually be some other kind of error, but in that case
155979156217
** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
@@ -161615,11 +161853,11 @@
161615161853
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
161616161854
}
161617161855
}
161618161856
break;
161619161857
case 23: /* columnname ::= nm typetoken */
161620
-{sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
161858
+{sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);}
161621161859
break;
161622161860
case 24: /* typetoken ::= */
161623161861
case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63);
161624161862
case 102: /* as ::= */ yytestcase(yyruleno==102);
161625161863
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
@@ -162419,24 +162657,32 @@
162419162657
** simplify to constants 0 (false) and 1 (true), respectively,
162420162658
** regardless of the value of expr1.
162421162659
*/
162422162660
sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy404);
162423162661
yymsp[-4].minor.yy404 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy376 ? "1" : "0");
162424
- }else if( yymsp[-1].minor.yy70->nExpr==1 && sqlite3ExprIsConstant(yymsp[-1].minor.yy70->a[0].pExpr) ){
162662
+ }else{
162425162663
Expr *pRHS = yymsp[-1].minor.yy70->a[0].pExpr;
162426
- yymsp[-1].minor.yy70->a[0].pExpr = 0;
162427
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162428
- pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
162429
- yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy404, pRHS);
162430
- if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
162431
- }else{
162432
- yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
162433
- if( yymsp[-4].minor.yy404 ){
162434
- yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy70;
162435
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404);
162436
- }else{
162437
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162664
+ if( yymsp[-1].minor.yy70->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy404->op!=TK_VECTOR ){
162665
+ yymsp[-1].minor.yy70->a[0].pExpr = 0;
162666
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162667
+ pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
162668
+ yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy404, pRHS);
162669
+ }else{
162670
+ yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
162671
+ if( yymsp[-4].minor.yy404==0 ){
162672
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162673
+ }else if( yymsp[-4].minor.yy404->pLeft->op==TK_VECTOR ){
162674
+ int nExpr = yymsp[-4].minor.yy404->pLeft->x.pList->nExpr;
162675
+ Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy70);
162676
+ if( pSelectRHS ){
162677
+ parserDoubleLinkSelect(pParse, pSelectRHS);
162678
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy404, pSelectRHS);
162679
+ }
162680
+ }else{
162681
+ yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy70;
162682
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404);
162683
+ }
162438162684
}
162439162685
if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
162440162686
}
162441162687
}
162442162688
break;
@@ -166151,31 +166397,37 @@
166151166397
}
166152166398
166153166399
/*
166154166400
** Return the number of changes in the most recent call to sqlite3_exec().
166155166401
*/
166156
-SQLITE_API int sqlite3_changes(sqlite3 *db){
166402
+SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
166157166403
#ifdef SQLITE_ENABLE_API_ARMOR
166158166404
if( !sqlite3SafetyCheckOk(db) ){
166159166405
(void)SQLITE_MISUSE_BKPT;
166160166406
return 0;
166161166407
}
166162166408
#endif
166163166409
return db->nChange;
166164166410
}
166411
+SQLITE_API int sqlite3_changes(sqlite3 *db){
166412
+ return (int)sqlite3_changes64(db);
166413
+}
166165166414
166166166415
/*
166167166416
** Return the number of changes since the database handle was opened.
166168166417
*/
166169
-SQLITE_API int sqlite3_total_changes(sqlite3 *db){
166418
+SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
166170166419
#ifdef SQLITE_ENABLE_API_ARMOR
166171166420
if( !sqlite3SafetyCheckOk(db) ){
166172166421
(void)SQLITE_MISUSE_BKPT;
166173166422
return 0;
166174166423
}
166175166424
#endif
166176166425
return db->nTotalChange;
166426
+}
166427
+SQLITE_API int sqlite3_total_changes(sqlite3 *db){
166428
+ return (int)sqlite3_total_changes64(db);
166177166429
}
166178166430
166179166431
/*
166180166432
** Close all open savepoints. This function only manipulates fields of the
166181166433
** database handle object, it does not close any savepoints that may be open
@@ -166913,26 +167165,37 @@
166913167165
** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
166914167166
**
166915167167
** If SQLITE_ANY is specified, add three versions of the function
166916167168
** to the hash table.
166917167169
*/
166918
- if( enc==SQLITE_UTF16 ){
166919
- enc = SQLITE_UTF16NATIVE;
166920
- }else if( enc==SQLITE_ANY ){
166921
- int rc;
166922
- rc = sqlite3CreateFunc(db, zFunctionName, nArg,
166923
- (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
166924
- pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
166925
- if( rc==SQLITE_OK ){
166926
- rc = sqlite3CreateFunc(db, zFunctionName, nArg,
166927
- (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
166928
- pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
166929
- }
166930
- if( rc!=SQLITE_OK ){
166931
- return rc;
166932
- }
166933
- enc = SQLITE_UTF16BE;
167170
+ switch( enc ){
167171
+ case SQLITE_UTF16:
167172
+ enc = SQLITE_UTF16NATIVE;
167173
+ break;
167174
+ case SQLITE_ANY: {
167175
+ int rc;
167176
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg,
167177
+ (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
167178
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
167179
+ if( rc==SQLITE_OK ){
167180
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg,
167181
+ (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
167182
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
167183
+ }
167184
+ if( rc!=SQLITE_OK ){
167185
+ return rc;
167186
+ }
167187
+ enc = SQLITE_UTF16BE;
167188
+ break;
167189
+ }
167190
+ case SQLITE_UTF8:
167191
+ case SQLITE_UTF16LE:
167192
+ case SQLITE_UTF16BE:
167193
+ break;
167194
+ default:
167195
+ enc = SQLITE_UTF8;
167196
+ break;
166934167197
}
166935167198
#else
166936167199
enc = SQLITE_UTF8;
166937167200
#endif
166938167201
@@ -167025,11 +167288,11 @@
167025167288
}
167026167289
rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p,
167027167290
xSFunc, xStep, xFinal, xValue, xInverse, pArg
167028167291
);
167029167292
if( pArg && pArg->nRef==0 ){
167030
- assert( rc!=SQLITE_OK );
167293
+ assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) );
167031167294
xDestroy(p);
167032167295
sqlite3_free(pArg);
167033167296
}
167034167297
167035167298
out:
@@ -168208,11 +168471,10 @@
168208168471
** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
168209168472
** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
168210168473
** off all other flags.
168211168474
*/
168212168475
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
168213
- SQLITE_OPEN_EXCLUSIVE |
168214168476
SQLITE_OPEN_MAIN_DB |
168215168477
SQLITE_OPEN_TEMP_DB |
168216168478
SQLITE_OPEN_TRANSIENT_DB |
168217168479
SQLITE_OPEN_MAIN_JOURNAL |
168218168480
SQLITE_OPEN_TEMP_JOURNAL |
@@ -168780,11 +169042,11 @@
168780169042
goto error_out;
168781169043
}
168782169044
168783169045
/* Locate the table in question */
168784169046
pTab = sqlite3FindTable(db, zTableName, zDbName);
168785
- if( !pTab || pTab->pSelect ){
169047
+ if( !pTab || IsView(pTab) ){
168786169048
pTab = 0;
168787169049
goto error_out;
168788169050
}
168789169051
168790169052
/* Find the column for which info is requested */
@@ -168791,11 +169053,11 @@
168791169053
if( zColumnName==0 ){
168792169054
/* Query for existance of table only */
168793169055
}else{
168794169056
for(iCol=0; iCol<pTab->nCol; iCol++){
168795169057
pCol = &pTab->aCol[iCol];
168796
- if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
169058
+ if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
168797169059
break;
168798169060
}
168799169061
}
168800169062
if( iCol==pTab->nCol ){
168801169063
if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
@@ -168818,11 +169080,11 @@
168818169080
** 2. The table is not a view and the column name identified an
168819169081
** explicitly declared column. Copy meta information from *pCol.
168820169082
*/
168821169083
if( pCol ){
168822169084
zDataType = sqlite3ColumnType(pCol,0);
168823
- zCollSeq = pCol->zColl;
169085
+ zCollSeq = sqlite3ColumnColl(pCol);
168824169086
notnull = pCol->notNull!=0;
168825169087
primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
168826169088
autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
168827169089
}else{
168828169090
zDataType = "INTEGER";
@@ -169349,11 +169611,11 @@
169349169611
case 3: sqlite3WhereTrace = *ptr; break;
169350169612
}
169351169613
break;
169352169614
}
169353169615
169354
-#ifdef SQLITE_DEBUG
169616
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
169355169617
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
169356169618
**
169357169619
** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
169358169620
** of the id-th tuning parameter to *piValue. If "id" is between -1
169359169621
** and -SQLITE_NTUNE, then write the current value of the (-id)-th
@@ -201251,11 +201513,13 @@
201251201513
*piPk = 0;
201252201514
201253201515
assert( p->rc==SQLITE_OK );
201254201516
p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
201255201517
sqlite3_mprintf(
201256
- "SELECT (sql LIKE 'create virtual%%'), rootpage"
201518
+ "SELECT "
201519
+ " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM'),"
201520
+ " rootpage"
201257201521
" FROM sqlite_schema"
201258201522
" WHERE name=%Q", zTab
201259201523
));
201260201524
if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){
201261201525
/* Either an error, or no such table. */
@@ -202784,11 +203048,11 @@
202784203048
case RBU_STATE_COOKIE:
202785203049
pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1);
202786203050
break;
202787203051
202788203052
case RBU_STATE_OALSZ:
202789
- pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1);
203053
+ pRet->iOalSz = sqlite3_column_int64(pStmt, 1);
202790203054
break;
202791203055
202792203056
case RBU_STATE_PHASEONESTEP:
202793203057
pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1);
202794203058
break;
@@ -213428,10 +213692,13 @@
213428213692
/*
213429213693
** This interface is used by the fts5vocab module.
213430213694
*/
213431213695
static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
213432213696
static int sqlite3Fts5IterNextScan(Fts5IndexIter*);
213697
+static void *sqlite3Fts5StructureRef(Fts5Index*);
213698
+static void sqlite3Fts5StructureRelease(void*);
213699
+static int sqlite3Fts5StructureTest(Fts5Index*, void*);
213433213700
213434213701
213435213702
/*
213436213703
** Insert or remove data to or from the index. Each time a document is
213437213704
** added to or removed from the index, this function is called one or more
@@ -216223,20 +216490,21 @@
216223216490
/* EOF */
216224216491
*piOff = -1;
216225216492
return 1;
216226216493
}else{
216227216494
i64 iOff = *piOff;
216228
- int iVal;
216495
+ u32 iVal;
216229216496
fts5FastGetVarint32(a, i, iVal);
216230216497
assert( iVal>=0 );
216231216498
if( iVal<=1 ){
216232216499
if( iVal==0 ){
216233216500
*pi = i;
216234216501
return 0;
216235216502
}
216236216503
fts5FastGetVarint32(a, i, iVal);
216237216504
iOff = ((i64)iVal) << 32;
216505
+ assert( iOff>=0 );
216238216506
fts5FastGetVarint32(a, i, iVal);
216239216507
if( iVal<2 ){
216240216508
/* This is a corrupt record. So stop parsing it here. */
216241216509
*piOff = -1;
216242216510
return 1;
@@ -216244,11 +216512,11 @@
216244216512
*piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
216245216513
}else{
216246216514
*piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
216247216515
}
216248216516
*pi = i;
216249
- assert( *piOff>=iOff );
216517
+ assert_nc( *piOff>=iOff );
216250216518
return 0;
216251216519
}
216252216520
}
216253216521
216254216522
@@ -217553,10 +217821,11 @@
217553217821
217554217822
static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
217555217823
va_list ap;
217556217824
va_start(ap, zFmt);
217557217825
if( pParse->rc==SQLITE_OK ){
217826
+ assert( pParse->zErr==0 );
217558217827
pParse->zErr = sqlite3_vmprintf(zFmt, ap);
217559217828
pParse->rc = SQLITE_ERROR;
217560217829
}
217561217830
va_end(ap);
217562217831
}
@@ -219562,13 +219831,12 @@
219562219831
Fts5ExprNode *pExpr,
219563219832
Fts5Colset *pColset
219564219833
){
219565219834
Fts5Colset *pFree = pColset;
219566219835
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
219567
- pParse->rc = SQLITE_ERROR;
219568
- pParse->zErr = sqlite3_mprintf(
219569
- "fts5: column queries are not supported (detail=none)"
219836
+ sqlite3Fts5ParseError(pParse,
219837
+ "fts5: column queries are not supported (detail=none)"
219570219838
);
219571219839
}else{
219572219840
fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
219573219841
}
219574219842
sqlite3_free(pFree);
@@ -219738,17 +220006,14 @@
219738220006
Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
219739220007
if( pNear->nPhrase!=1
219740220008
|| pPhrase->nTerm>1
219741220009
|| (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
219742220010
){
219743
- assert( pParse->rc==SQLITE_OK );
219744
- pParse->rc = SQLITE_ERROR;
219745
- assert( pParse->zErr==0 );
219746
- pParse->zErr = sqlite3_mprintf(
220011
+ sqlite3Fts5ParseError(pParse,
219747220012
"fts5: %s queries are not supported (detail!=full)",
219748220013
pNear->nPhrase==1 ? "phrase": "NEAR"
219749
- );
220014
+ );
219750220015
sqlite3_free(pRet);
219751220016
pRet = 0;
219752220017
}
219753220018
}
219754220019
}else{
@@ -221861,10 +222126,26 @@
221861222126
}
221862222127
221863222128
static void fts5StructureRef(Fts5Structure *pStruct){
221864222129
pStruct->nRef++;
221865222130
}
222131
+
222132
+static void *sqlite3Fts5StructureRef(Fts5Index *p){
222133
+ fts5StructureRef(p->pStruct);
222134
+ return (void*)p->pStruct;
222135
+}
222136
+static void sqlite3Fts5StructureRelease(void *p){
222137
+ if( p ){
222138
+ fts5StructureRelease((Fts5Structure*)p);
222139
+ }
222140
+}
222141
+static int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
222142
+ if( p->pStruct!=(Fts5Structure*)pStruct ){
222143
+ return SQLITE_ABORT;
222144
+ }
222145
+ return SQLITE_OK;
222146
+}
221866222147
221867222148
/*
221868222149
** Deserialize and return the structure record currently stored in serialized
221869222150
** form within buffer pData/nData.
221870222151
**
@@ -230568,11 +230849,11 @@
230568230849
int nArg, /* Number of args */
230569230850
sqlite3_value **apUnused /* Function arguments */
230570230851
){
230571230852
assert( nArg==0 );
230572230853
UNUSED_PARAM2(nArg, apUnused);
230573
- sqlite3_result_text(pCtx, "fts5: 2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70", -1, SQLITE_TRANSIENT);
230854
+ sqlite3_result_text(pCtx, "fts5: 2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a", -1, SQLITE_TRANSIENT);
230574230855
}
230575230856
230576230857
/*
230577230858
** Return true if zName is the extension on one of the shadow tables used
230578230859
** by this module.
@@ -234464,10 +234745,11 @@
234464234745
sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
234465234746
Fts5Table *pFts5; /* Associated FTS5 table */
234466234747
234467234748
int bEof; /* True if this cursor is at EOF */
234468234749
Fts5IndexIter *pIter; /* Term/rowid iterator object */
234750
+ void *pStruct; /* From sqlite3Fts5StructureRef() */
234469234751
234470234752
int nLeTerm; /* Size of zLeTerm in bytes */
234471234753
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
234472234754
234473234755
/* These are used by 'col' tables only */
@@ -234797,10 +235079,12 @@
234797235079
}
234798235080
234799235081
static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
234800235082
pCsr->rowid = 0;
234801235083
sqlite3Fts5IterClose(pCsr->pIter);
235084
+ sqlite3Fts5StructureRelease(pCsr->pStruct);
235085
+ pCsr->pStruct = 0;
234802235086
pCsr->pIter = 0;
234803235087
sqlite3_free(pCsr->zLeTerm);
234804235088
pCsr->nLeTerm = -1;
234805235089
pCsr->zLeTerm = 0;
234806235090
pCsr->bEof = 0;
@@ -234874,13 +235158,15 @@
234874235158
** Advance the cursor to the next row in the table.
234875235159
*/
234876235160
static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
234877235161
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
234878235162
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
234879
- int rc = SQLITE_OK;
234880235163
int nCol = pCsr->pFts5->pConfig->nCol;
235164
+ int rc;
234881235165
235166
+ rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct);
235167
+ if( rc!=SQLITE_OK ) return rc;
234882235168
pCsr->rowid++;
234883235169
234884235170
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
234885235171
return fts5VocabInstanceNext(pCsr);
234886235172
}
@@ -235050,10 +235336,13 @@
235050235336
}
235051235337
235052235338
if( rc==SQLITE_OK ){
235053235339
Fts5Index *pIndex = pCsr->pFts5->pIndex;
235054235340
rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
235341
+ if( rc==SQLITE_OK ){
235342
+ pCsr->pStruct = sqlite3Fts5StructureRef(pIndex);
235343
+ }
235055235344
}
235056235345
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
235057235346
rc = fts5VocabInstanceNewTerm(pCsr);
235058235347
}
235059235348
if( rc==SQLITE_OK && !pCsr->bEof
@@ -235494,12 +235783,8 @@
235494235783
}
235495235784
#endif /* SQLITE_CORE */
235496235785
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
235497235786
235498235787
/************** End of stmt.c ************************************************/
235499
-#if __LINE__!=235499
235500
-#undef SQLITE_SOURCE_ID
235501
-#define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9alt2"
235502
-#endif
235503235788
/* Return the source-id for this library */
235504235789
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
235505235790
/************************** End of sqlite3.c ******************************/
235506235791
--- 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.36.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.
@@ -20,797 +20,10 @@
20 #define SQLITE_CORE 1
21 #define SQLITE_AMALGAMATION 1
22 #ifndef SQLITE_PRIVATE
23 # define SQLITE_PRIVATE static
24 #endif
25 /************** Begin file ctime.c *******************************************/
26 /*
27 ** 2010 February 23
28 **
29 ** The author disclaims copyright to this source code. In place of
30 ** a legal notice, here is a blessing:
31 **
32 ** May you do good and not evil.
33 ** May you find forgiveness for yourself and forgive others.
34 ** May you share freely, never taking more than you give.
35 **
36 *************************************************************************
37 **
38 ** This file implements routines used to report what compile-time options
39 ** SQLite was built with.
40 */
41
42 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
43
44 /*
45 ** Include the configuration header output by 'configure' if we're using the
46 ** autoconf-based build
47 */
48 #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
49 #include "config.h"
50 #define SQLITECONFIG_H 1
51 #endif
52
53 /* These macros are provided to "stringify" the value of the define
54 ** for those options in which the value is meaningful. */
55 #define CTIMEOPT_VAL_(opt) #opt
56 #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
57
58 /* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
59 ** option requires a separate macro because legal values contain a single
60 ** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
61 #define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
62 #define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
63
64 /*
65 ** An array of names of all compile-time options. This array should
66 ** be sorted A-Z.
67 **
68 ** This array looks large, but in a typical installation actually uses
69 ** only a handful of compile-time options, so most times this array is usually
70 ** rather short and uses little memory space.
71 */
72 static const char * const sqlite3azCompileOpt[] = {
73
74 /*
75 ** BEGIN CODE GENERATED BY tool/mkctime.tcl
76 */
77 #if SQLITE_32BIT_ROWID
78 "32BIT_ROWID",
79 #endif
80 #if SQLITE_4_BYTE_ALIGNED_MALLOC
81 "4_BYTE_ALIGNED_MALLOC",
82 #endif
83 #if SQLITE_64BIT_STATS
84 "64BIT_STATS",
85 #endif
86 #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
87 # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
88 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
89 # endif
90 #endif
91 #if SQLITE_ALLOW_URI_AUTHORITY
92 "ALLOW_URI_AUTHORITY",
93 #endif
94 #ifdef SQLITE_BITMASK_TYPE
95 "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
96 #endif
97 #if SQLITE_BUG_COMPATIBLE_20160819
98 "BUG_COMPATIBLE_20160819",
99 #endif
100 #if SQLITE_CASE_SENSITIVE_LIKE
101 "CASE_SENSITIVE_LIKE",
102 #endif
103 #if SQLITE_CHECK_PAGES
104 "CHECK_PAGES",
105 #endif
106 #if defined(__clang__) && defined(__clang_major__)
107 "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
108 CTIMEOPT_VAL(__clang_minor__) "."
109 CTIMEOPT_VAL(__clang_patchlevel__),
110 #elif defined(_MSC_VER)
111 "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
112 #elif defined(__GNUC__) && defined(__VERSION__)
113 "COMPILER=gcc-" __VERSION__,
114 #endif
115 #if SQLITE_COVERAGE_TEST
116 "COVERAGE_TEST",
117 #endif
118 #if SQLITE_DEBUG
119 "DEBUG",
120 #endif
121 #if SQLITE_DEFAULT_AUTOMATIC_INDEX
122 "DEFAULT_AUTOMATIC_INDEX",
123 #endif
124 #if SQLITE_DEFAULT_AUTOVACUUM
125 "DEFAULT_AUTOVACUUM",
126 #endif
127 #ifdef SQLITE_DEFAULT_CACHE_SIZE
128 "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
129 #endif
130 #if SQLITE_DEFAULT_CKPTFULLFSYNC
131 "DEFAULT_CKPTFULLFSYNC",
132 #endif
133 #ifdef SQLITE_DEFAULT_FILE_FORMAT
134 "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
135 #endif
136 #ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
137 "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
138 #endif
139 #if SQLITE_DEFAULT_FOREIGN_KEYS
140 "DEFAULT_FOREIGN_KEYS",
141 #endif
142 #ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
143 "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
144 #endif
145 #ifdef SQLITE_DEFAULT_LOCKING_MODE
146 "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
147 #endif
148 #ifdef SQLITE_DEFAULT_LOOKASIDE
149 "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
150 #endif
151 #ifdef SQLITE_DEFAULT_MEMSTATUS
152 # if SQLITE_DEFAULT_MEMSTATUS != 1
153 "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
154 # endif
155 #endif
156 #ifdef SQLITE_DEFAULT_MMAP_SIZE
157 "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
158 #endif
159 #ifdef SQLITE_DEFAULT_PAGE_SIZE
160 "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
161 #endif
162 #ifdef SQLITE_DEFAULT_PCACHE_INITSZ
163 "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
164 #endif
165 #ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
166 "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
167 #endif
168 #if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
169 "DEFAULT_RECURSIVE_TRIGGERS",
170 #endif
171 #ifdef SQLITE_DEFAULT_ROWEST
172 "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
173 #endif
174 #ifdef SQLITE_DEFAULT_SECTOR_SIZE
175 "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
176 #endif
177 #ifdef SQLITE_DEFAULT_SYNCHRONOUS
178 "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
179 #endif
180 #ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
181 "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
182 #endif
183 #ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
184 "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
185 #endif
186 #ifdef SQLITE_DEFAULT_WORKER_THREADS
187 "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
188 #endif
189 #if SQLITE_DIRECT_OVERFLOW_READ
190 "DIRECT_OVERFLOW_READ",
191 #endif
192 #if SQLITE_DISABLE_DIRSYNC
193 "DISABLE_DIRSYNC",
194 #endif
195 #if SQLITE_DISABLE_FTS3_UNICODE
196 "DISABLE_FTS3_UNICODE",
197 #endif
198 #if SQLITE_DISABLE_FTS4_DEFERRED
199 "DISABLE_FTS4_DEFERRED",
200 #endif
201 #if SQLITE_DISABLE_INTRINSIC
202 "DISABLE_INTRINSIC",
203 #endif
204 #if SQLITE_DISABLE_LFS
205 "DISABLE_LFS",
206 #endif
207 #if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
208 "DISABLE_PAGECACHE_OVERFLOW_STATS",
209 #endif
210 #if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
211 "DISABLE_SKIPAHEAD_DISTINCT",
212 #endif
213 #ifdef SQLITE_ENABLE_8_3_NAMES
214 "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
215 #endif
216 #if SQLITE_ENABLE_API_ARMOR
217 "ENABLE_API_ARMOR",
218 #endif
219 #if SQLITE_ENABLE_ATOMIC_WRITE
220 "ENABLE_ATOMIC_WRITE",
221 #endif
222 #if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
223 "ENABLE_BATCH_ATOMIC_WRITE",
224 #endif
225 #if SQLITE_ENABLE_BYTECODE_VTAB
226 "ENABLE_BYTECODE_VTAB",
227 #endif
228 #ifdef SQLITE_ENABLE_CEROD
229 "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
230 #endif
231 #if SQLITE_ENABLE_COLUMN_METADATA
232 "ENABLE_COLUMN_METADATA",
233 #endif
234 #if SQLITE_ENABLE_COLUMN_USED_MASK
235 "ENABLE_COLUMN_USED_MASK",
236 #endif
237 #if SQLITE_ENABLE_COSTMULT
238 "ENABLE_COSTMULT",
239 #endif
240 #if SQLITE_ENABLE_CURSOR_HINTS
241 "ENABLE_CURSOR_HINTS",
242 #endif
243 #if SQLITE_ENABLE_DBPAGE_VTAB
244 "ENABLE_DBPAGE_VTAB",
245 #endif
246 #if SQLITE_ENABLE_DBSTAT_VTAB
247 "ENABLE_DBSTAT_VTAB",
248 #endif
249 #if SQLITE_ENABLE_EXPENSIVE_ASSERT
250 "ENABLE_EXPENSIVE_ASSERT",
251 #endif
252 #if SQLITE_ENABLE_EXPLAIN_COMMENTS
253 "ENABLE_EXPLAIN_COMMENTS",
254 #endif
255 #if SQLITE_ENABLE_FTS3
256 "ENABLE_FTS3",
257 #endif
258 #if SQLITE_ENABLE_FTS3_PARENTHESIS
259 "ENABLE_FTS3_PARENTHESIS",
260 #endif
261 #if SQLITE_ENABLE_FTS3_TOKENIZER
262 "ENABLE_FTS3_TOKENIZER",
263 #endif
264 #if SQLITE_ENABLE_FTS4
265 "ENABLE_FTS4",
266 #endif
267 #if SQLITE_ENABLE_FTS5
268 "ENABLE_FTS5",
269 #endif
270 #if SQLITE_ENABLE_GEOPOLY
271 "ENABLE_GEOPOLY",
272 #endif
273 #if SQLITE_ENABLE_HIDDEN_COLUMNS
274 "ENABLE_HIDDEN_COLUMNS",
275 #endif
276 #if SQLITE_ENABLE_ICU
277 "ENABLE_ICU",
278 #endif
279 #if SQLITE_ENABLE_IOTRACE
280 "ENABLE_IOTRACE",
281 #endif
282 #if SQLITE_ENABLE_JSON1
283 "ENABLE_JSON1",
284 #endif
285 #if SQLITE_ENABLE_LOAD_EXTENSION
286 "ENABLE_LOAD_EXTENSION",
287 #endif
288 #ifdef SQLITE_ENABLE_LOCKING_STYLE
289 "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
290 #endif
291 #if SQLITE_ENABLE_MATH_FUNCTIONS
292 "ENABLE_MATH_FUNCTIONS",
293 #endif
294 #if SQLITE_ENABLE_MEMORY_MANAGEMENT
295 "ENABLE_MEMORY_MANAGEMENT",
296 #endif
297 #if SQLITE_ENABLE_MEMSYS3
298 "ENABLE_MEMSYS3",
299 #endif
300 #if SQLITE_ENABLE_MEMSYS5
301 "ENABLE_MEMSYS5",
302 #endif
303 #if SQLITE_ENABLE_MULTIPLEX
304 "ENABLE_MULTIPLEX",
305 #endif
306 #if SQLITE_ENABLE_NORMALIZE
307 "ENABLE_NORMALIZE",
308 #endif
309 #if SQLITE_ENABLE_NULL_TRIM
310 "ENABLE_NULL_TRIM",
311 #endif
312 #if SQLITE_ENABLE_OFFSET_SQL_FUNC
313 "ENABLE_OFFSET_SQL_FUNC",
314 #endif
315 #if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
316 "ENABLE_OVERSIZE_CELL_CHECK",
317 #endif
318 #if SQLITE_ENABLE_PREUPDATE_HOOK
319 "ENABLE_PREUPDATE_HOOK",
320 #endif
321 #if SQLITE_ENABLE_QPSG
322 "ENABLE_QPSG",
323 #endif
324 #if SQLITE_ENABLE_RBU
325 "ENABLE_RBU",
326 #endif
327 #if SQLITE_ENABLE_RTREE
328 "ENABLE_RTREE",
329 #endif
330 #if SQLITE_ENABLE_SELECTTRACE
331 "ENABLE_SELECTTRACE",
332 #endif
333 #if SQLITE_ENABLE_SESSION
334 "ENABLE_SESSION",
335 #endif
336 #if SQLITE_ENABLE_SNAPSHOT
337 "ENABLE_SNAPSHOT",
338 #endif
339 #if SQLITE_ENABLE_SORTER_REFERENCES
340 "ENABLE_SORTER_REFERENCES",
341 #endif
342 #if SQLITE_ENABLE_SQLLOG
343 "ENABLE_SQLLOG",
344 #endif
345 #if SQLITE_ENABLE_STAT4
346 "ENABLE_STAT4",
347 #endif
348 #if SQLITE_ENABLE_STMTVTAB
349 "ENABLE_STMTVTAB",
350 #endif
351 #if SQLITE_ENABLE_STMT_SCANSTATUS
352 "ENABLE_STMT_SCANSTATUS",
353 #endif
354 #if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
355 "ENABLE_UNKNOWN_SQL_FUNCTION",
356 #endif
357 #if SQLITE_ENABLE_UNLOCK_NOTIFY
358 "ENABLE_UNLOCK_NOTIFY",
359 #endif
360 #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
361 "ENABLE_UPDATE_DELETE_LIMIT",
362 #endif
363 #if SQLITE_ENABLE_URI_00_ERROR
364 "ENABLE_URI_00_ERROR",
365 #endif
366 #if SQLITE_ENABLE_VFSTRACE
367 "ENABLE_VFSTRACE",
368 #endif
369 #if SQLITE_ENABLE_WHERETRACE
370 "ENABLE_WHERETRACE",
371 #endif
372 #if SQLITE_ENABLE_ZIPVFS
373 "ENABLE_ZIPVFS",
374 #endif
375 #if SQLITE_EXPLAIN_ESTIMATED_ROWS
376 "EXPLAIN_ESTIMATED_ROWS",
377 #endif
378 #if SQLITE_EXTRA_IFNULLROW
379 "EXTRA_IFNULLROW",
380 #endif
381 #ifdef SQLITE_EXTRA_INIT
382 "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
383 #endif
384 #ifdef SQLITE_EXTRA_SHUTDOWN
385 "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
386 #endif
387 #ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
388 "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
389 #endif
390 #if SQLITE_FTS5_ENABLE_TEST_MI
391 "FTS5_ENABLE_TEST_MI",
392 #endif
393 #if SQLITE_FTS5_NO_WITHOUT_ROWID
394 "FTS5_NO_WITHOUT_ROWID",
395 #endif
396 #if HAVE_ISNAN || SQLITE_HAVE_ISNAN
397 "HAVE_ISNAN",
398 #endif
399 #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
400 # if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
401 "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
402 # endif
403 #endif
404 #if SQLITE_IGNORE_AFP_LOCK_ERRORS
405 "IGNORE_AFP_LOCK_ERRORS",
406 #endif
407 #if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
408 "IGNORE_FLOCK_LOCK_ERRORS",
409 #endif
410 #if SQLITE_INLINE_MEMCPY
411 "INLINE_MEMCPY",
412 #endif
413 #if SQLITE_INT64_TYPE
414 "INT64_TYPE",
415 #endif
416 #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
417 "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
418 #endif
419 #if SQLITE_LIKE_DOESNT_MATCH_BLOBS
420 "LIKE_DOESNT_MATCH_BLOBS",
421 #endif
422 #if SQLITE_LOCK_TRACE
423 "LOCK_TRACE",
424 #endif
425 #if SQLITE_LOG_CACHE_SPILL
426 "LOG_CACHE_SPILL",
427 #endif
428 #ifdef SQLITE_MALLOC_SOFT_LIMIT
429 "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
430 #endif
431 #ifdef SQLITE_MAX_ATTACHED
432 "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
433 #endif
434 #ifdef SQLITE_MAX_COLUMN
435 "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
436 #endif
437 #ifdef SQLITE_MAX_COMPOUND_SELECT
438 "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
439 #endif
440 #ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
441 "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
442 #endif
443 #ifdef SQLITE_MAX_EXPR_DEPTH
444 "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
445 #endif
446 #ifdef SQLITE_MAX_FUNCTION_ARG
447 "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
448 #endif
449 #ifdef SQLITE_MAX_LENGTH
450 "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
451 #endif
452 #ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
453 "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
454 #endif
455 #ifdef SQLITE_MAX_MEMORY
456 "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
457 #endif
458 #ifdef SQLITE_MAX_MMAP_SIZE
459 "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
460 #endif
461 #ifdef SQLITE_MAX_MMAP_SIZE_
462 "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
463 #endif
464 #ifdef SQLITE_MAX_PAGE_COUNT
465 "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
466 #endif
467 #ifdef SQLITE_MAX_PAGE_SIZE
468 "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
469 #endif
470 #ifdef SQLITE_MAX_SCHEMA_RETRY
471 "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
472 #endif
473 #ifdef SQLITE_MAX_SQL_LENGTH
474 "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
475 #endif
476 #ifdef SQLITE_MAX_TRIGGER_DEPTH
477 "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
478 #endif
479 #ifdef SQLITE_MAX_VARIABLE_NUMBER
480 "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
481 #endif
482 #ifdef SQLITE_MAX_VDBE_OP
483 "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
484 #endif
485 #ifdef SQLITE_MAX_WORKER_THREADS
486 "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
487 #endif
488 #if SQLITE_MEMDEBUG
489 "MEMDEBUG",
490 #endif
491 #if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
492 "MIXED_ENDIAN_64BIT_FLOAT",
493 #endif
494 #if SQLITE_MMAP_READWRITE
495 "MMAP_READWRITE",
496 #endif
497 #if SQLITE_MUTEX_NOOP
498 "MUTEX_NOOP",
499 #endif
500 #if SQLITE_MUTEX_OMIT
501 "MUTEX_OMIT",
502 #endif
503 #if SQLITE_MUTEX_PTHREADS
504 "MUTEX_PTHREADS",
505 #endif
506 #if SQLITE_MUTEX_W32
507 "MUTEX_W32",
508 #endif
509 #if SQLITE_NEED_ERR_NAME
510 "NEED_ERR_NAME",
511 #endif
512 #if SQLITE_NOINLINE
513 "NOINLINE",
514 #endif
515 #if SQLITE_NO_SYNC
516 "NO_SYNC",
517 #endif
518 #if SQLITE_OMIT_ALTERTABLE
519 "OMIT_ALTERTABLE",
520 #endif
521 #if SQLITE_OMIT_ANALYZE
522 "OMIT_ANALYZE",
523 #endif
524 #if SQLITE_OMIT_ATTACH
525 "OMIT_ATTACH",
526 #endif
527 #if SQLITE_OMIT_AUTHORIZATION
528 "OMIT_AUTHORIZATION",
529 #endif
530 #if SQLITE_OMIT_AUTOINCREMENT
531 "OMIT_AUTOINCREMENT",
532 #endif
533 #if SQLITE_OMIT_AUTOINIT
534 "OMIT_AUTOINIT",
535 #endif
536 #if SQLITE_OMIT_AUTOMATIC_INDEX
537 "OMIT_AUTOMATIC_INDEX",
538 #endif
539 #if SQLITE_OMIT_AUTORESET
540 "OMIT_AUTORESET",
541 #endif
542 #if SQLITE_OMIT_AUTOVACUUM
543 "OMIT_AUTOVACUUM",
544 #endif
545 #if SQLITE_OMIT_BETWEEN_OPTIMIZATION
546 "OMIT_BETWEEN_OPTIMIZATION",
547 #endif
548 #if SQLITE_OMIT_BLOB_LITERAL
549 "OMIT_BLOB_LITERAL",
550 #endif
551 #if SQLITE_OMIT_CAST
552 "OMIT_CAST",
553 #endif
554 #if SQLITE_OMIT_CHECK
555 "OMIT_CHECK",
556 #endif
557 #if SQLITE_OMIT_COMPLETE
558 "OMIT_COMPLETE",
559 #endif
560 #if SQLITE_OMIT_COMPOUND_SELECT
561 "OMIT_COMPOUND_SELECT",
562 #endif
563 #if SQLITE_OMIT_CONFLICT_CLAUSE
564 "OMIT_CONFLICT_CLAUSE",
565 #endif
566 #if SQLITE_OMIT_CTE
567 "OMIT_CTE",
568 #endif
569 #if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
570 "OMIT_DATETIME_FUNCS",
571 #endif
572 #if SQLITE_OMIT_DECLTYPE
573 "OMIT_DECLTYPE",
574 #endif
575 #if SQLITE_OMIT_DEPRECATED
576 "OMIT_DEPRECATED",
577 #endif
578 #if SQLITE_OMIT_DESERIALIZE
579 "OMIT_DESERIALIZE",
580 #endif
581 #if SQLITE_OMIT_DISKIO
582 "OMIT_DISKIO",
583 #endif
584 #if SQLITE_OMIT_EXPLAIN
585 "OMIT_EXPLAIN",
586 #endif
587 #if SQLITE_OMIT_FLAG_PRAGMAS
588 "OMIT_FLAG_PRAGMAS",
589 #endif
590 #if SQLITE_OMIT_FLOATING_POINT
591 "OMIT_FLOATING_POINT",
592 #endif
593 #if SQLITE_OMIT_FOREIGN_KEY
594 "OMIT_FOREIGN_KEY",
595 #endif
596 #if SQLITE_OMIT_GET_TABLE
597 "OMIT_GET_TABLE",
598 #endif
599 #if SQLITE_OMIT_HEX_INTEGER
600 "OMIT_HEX_INTEGER",
601 #endif
602 #if SQLITE_OMIT_INCRBLOB
603 "OMIT_INCRBLOB",
604 #endif
605 #if SQLITE_OMIT_INTEGRITY_CHECK
606 "OMIT_INTEGRITY_CHECK",
607 #endif
608 #if SQLITE_OMIT_INTROSPECTION_PRAGMAS
609 "OMIT_INTROSPECTION_PRAGMAS",
610 #endif
611 #if SQLITE_OMIT_LIKE_OPTIMIZATION
612 "OMIT_LIKE_OPTIMIZATION",
613 #endif
614 #if SQLITE_OMIT_LOAD_EXTENSION
615 "OMIT_LOAD_EXTENSION",
616 #endif
617 #if SQLITE_OMIT_LOCALTIME
618 "OMIT_LOCALTIME",
619 #endif
620 #if SQLITE_OMIT_LOOKASIDE
621 "OMIT_LOOKASIDE",
622 #endif
623 #if SQLITE_OMIT_MEMORYDB
624 "OMIT_MEMORYDB",
625 #endif
626 #if SQLITE_OMIT_OR_OPTIMIZATION
627 "OMIT_OR_OPTIMIZATION",
628 #endif
629 #if SQLITE_OMIT_PAGER_PRAGMAS
630 "OMIT_PAGER_PRAGMAS",
631 #endif
632 #if SQLITE_OMIT_PARSER_TRACE
633 "OMIT_PARSER_TRACE",
634 #endif
635 #if SQLITE_OMIT_POPEN
636 "OMIT_POPEN",
637 #endif
638 #if SQLITE_OMIT_PRAGMA
639 "OMIT_PRAGMA",
640 #endif
641 #if SQLITE_OMIT_PROGRESS_CALLBACK
642 "OMIT_PROGRESS_CALLBACK",
643 #endif
644 #if SQLITE_OMIT_QUICKBALANCE
645 "OMIT_QUICKBALANCE",
646 #endif
647 #if SQLITE_OMIT_REINDEX
648 "OMIT_REINDEX",
649 #endif
650 #if SQLITE_OMIT_SCHEMA_PRAGMAS
651 "OMIT_SCHEMA_PRAGMAS",
652 #endif
653 #if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
654 "OMIT_SCHEMA_VERSION_PRAGMAS",
655 #endif
656 #if SQLITE_OMIT_SHARED_CACHE
657 "OMIT_SHARED_CACHE",
658 #endif
659 #if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
660 "OMIT_SHUTDOWN_DIRECTORIES",
661 #endif
662 #if SQLITE_OMIT_SUBQUERY
663 "OMIT_SUBQUERY",
664 #endif
665 #if SQLITE_OMIT_TCL_VARIABLE
666 "OMIT_TCL_VARIABLE",
667 #endif
668 #if SQLITE_OMIT_TEMPDB
669 "OMIT_TEMPDB",
670 #endif
671 #if SQLITE_OMIT_TEST_CONTROL
672 "OMIT_TEST_CONTROL",
673 #endif
674 #ifdef SQLITE_OMIT_TRACE
675 # if SQLITE_OMIT_TRACE != 1
676 "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
677 # endif
678 #endif
679 #if SQLITE_OMIT_TRIGGER
680 "OMIT_TRIGGER",
681 #endif
682 #if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
683 "OMIT_TRUNCATE_OPTIMIZATION",
684 #endif
685 #if SQLITE_OMIT_UTF16
686 "OMIT_UTF16",
687 #endif
688 #if SQLITE_OMIT_VACUUM
689 "OMIT_VACUUM",
690 #endif
691 #if SQLITE_OMIT_VIEW
692 "OMIT_VIEW",
693 #endif
694 #if SQLITE_OMIT_VIRTUALTABLE
695 "OMIT_VIRTUALTABLE",
696 #endif
697 #if SQLITE_OMIT_WAL
698 "OMIT_WAL",
699 #endif
700 #if SQLITE_OMIT_WSD
701 "OMIT_WSD",
702 #endif
703 #if SQLITE_OMIT_XFER_OPT
704 "OMIT_XFER_OPT",
705 #endif
706 #if SQLITE_PCACHE_SEPARATE_HEADER
707 "PCACHE_SEPARATE_HEADER",
708 #endif
709 #if SQLITE_PERFORMANCE_TRACE
710 "PERFORMANCE_TRACE",
711 #endif
712 #ifdef SQLITE_POWERSAFE_OVERWRITE
713 # if SQLITE_POWERSAFE_OVERWRITE != 1
714 "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
715 # endif
716 #endif
717 #if SQLITE_PREFER_PROXY_LOCKING
718 "PREFER_PROXY_LOCKING",
719 #endif
720 #if SQLITE_PROXY_DEBUG
721 "PROXY_DEBUG",
722 #endif
723 #if SQLITE_REVERSE_UNORDERED_SELECTS
724 "REVERSE_UNORDERED_SELECTS",
725 #endif
726 #if SQLITE_RTREE_INT_ONLY
727 "RTREE_INT_ONLY",
728 #endif
729 #if SQLITE_SECURE_DELETE
730 "SECURE_DELETE",
731 #endif
732 #if SQLITE_SMALL_STACK
733 "SMALL_STACK",
734 #endif
735 #ifdef SQLITE_SORTER_PMASZ
736 "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
737 #endif
738 #if SQLITE_SOUNDEX
739 "SOUNDEX",
740 #endif
741 #ifdef SQLITE_STAT4_SAMPLES
742 "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
743 #endif
744 #ifdef SQLITE_STMTJRNL_SPILL
745 "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
746 #endif
747 #if SQLITE_SUBSTR_COMPATIBILITY
748 "SUBSTR_COMPATIBILITY",
749 #endif
750 #if (!defined(SQLITE_WIN32_MALLOC) \
751 && !defined(SQLITE_ZERO_MALLOC) \
752 && !defined(SQLITE_MEMDEBUG) \
753 ) || defined(SQLITE_SYSTEM_MALLOC)
754 "SYSTEM_MALLOC",
755 #endif
756 #if SQLITE_TCL
757 "TCL",
758 #endif
759 #ifdef SQLITE_TEMP_STORE
760 "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
761 #endif
762 #if SQLITE_TEST
763 "TEST",
764 #endif
765 #if defined(SQLITE_THREADSAFE)
766 "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
767 #elif defined(THREADSAFE)
768 "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
769 #else
770 "THREADSAFE=1",
771 #endif
772 #if SQLITE_UNLINK_AFTER_CLOSE
773 "UNLINK_AFTER_CLOSE",
774 #endif
775 #if SQLITE_UNTESTABLE
776 "UNTESTABLE",
777 #endif
778 #if SQLITE_USER_AUTHENTICATION
779 "USER_AUTHENTICATION",
780 #endif
781 #if SQLITE_USE_ALLOCA
782 "USE_ALLOCA",
783 #endif
784 #if SQLITE_USE_FCNTL_TRACE
785 "USE_FCNTL_TRACE",
786 #endif
787 #if SQLITE_USE_URI
788 "USE_URI",
789 #endif
790 #if SQLITE_VDBE_COVERAGE
791 "VDBE_COVERAGE",
792 #endif
793 #if SQLITE_WIN32_MALLOC
794 "WIN32_MALLOC",
795 #endif
796 #if SQLITE_ZERO_MALLOC
797 "ZERO_MALLOC",
798 #endif
799 /*
800 ** END CODE GENERATED BY tool/mkctime.tcl
801 */
802 };
803
804 SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
805 *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
806 return (const char**)sqlite3azCompileOpt;
807 }
808
809 #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
810
811 /************** End of ctime.c ***********************************************/
812 /************** Begin file sqliteInt.h ***************************************/
813 /*
814 ** 2001 September 15
815 **
816 ** The author disclaims copyright to this source code. In place of
@@ -1071,10 +284,21 @@
1071 defined(_WIN32) && !defined(_WIN64) && \
1072 defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
1073 defined(__MSVCRT__)
1074 # define _USE_32BIT_TIME_T
1075 #endif
 
 
 
 
 
 
 
 
 
 
 
1076
1077 /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
1078 ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
1079 ** MinGW.
1080 */
@@ -1123,11 +347,34 @@
1123 extern "C" {
1124 #endif
1125
1126
1127 /*
1128 ** Provide the ability to override linkage features of the interface.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1129 */
1130 #ifndef SQLITE_EXTERN
1131 # define SQLITE_EXTERN extern
1132 #endif
1133 #ifndef SQLITE_API
@@ -1203,13 +450,13 @@
1203 **
1204 ** See also: [sqlite3_libversion()],
1205 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1206 ** [sqlite_version()] and [sqlite_source_id()].
1207 */
1208 #define SQLITE_VERSION "3.36.0"
1209 #define SQLITE_VERSION_NUMBER 3036000
1210 #define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70"
1211
1212 /*
1213 ** CAPI3REF: Run-Time Library Version Numbers
1214 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1215 **
@@ -1596,10 +843,11 @@
1596 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
1597 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
1598 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
1599 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
1600 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
 
1601 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1602 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
1603 #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
1604 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
1605 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -3544,15 +2792,18 @@
3544
3545 /*
3546 ** CAPI3REF: Count The Number Of Rows Modified
3547 ** METHOD: sqlite3
3548 **
3549 ** ^This function returns the number of rows modified, inserted or
3550 ** deleted by the most recently completed INSERT, UPDATE or DELETE
3551 ** statement on the database connection specified by the only parameter.
3552 ** ^Executing any other type of SQL statement does not modify the value
3553 ** returned by this function.
 
 
 
3554 **
3555 ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
3556 ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
3557 ** [foreign key actions] or [REPLACE] constraint resolution are not counted.
3558 **
@@ -3597,20 +2848,25 @@
3597 ** <li> the [changes() SQL function]
3598 ** <li> the [data_version pragma]
3599 ** </ul>
3600 */
3601 SQLITE_API int sqlite3_changes(sqlite3*);
 
3602
3603 /*
3604 ** CAPI3REF: Total Number Of Rows Modified
3605 ** METHOD: sqlite3
3606 **
3607 ** ^This function returns the total number of rows inserted, modified or
3608 ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
3609 ** since the database connection was opened, including those executed as
3610 ** part of trigger programs. ^Executing any other type of SQL statement
3611 ** does not affect the value returned by sqlite3_total_changes().
 
 
 
 
3612 **
3613 ** ^Changes made as part of [foreign key actions] are included in the
3614 ** count, but those made as part of REPLACE constraint resolution are
3615 ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
3616 ** are not counted.
@@ -3634,10 +2890,11 @@
3634 ** <li> the [data_version pragma]
3635 ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
3636 ** </ul>
3637 */
3638 SQLITE_API int sqlite3_total_changes(sqlite3*);
 
3639
3640 /*
3641 ** CAPI3REF: Interrupt A Long-Running Query
3642 ** METHOD: sqlite3
3643 **
@@ -4465,10 +3722,16 @@
4465 ** the default shared cache setting provided by
4466 ** [sqlite3_enable_shared_cache()].)^
4467 **
4468 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
4469 ** <dd>The database filename is not allowed to be a symbolic link</dd>
 
 
 
 
 
 
4470 ** </dl>)^
4471 **
4472 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
4473 ** required combinations shown above optionally combined with other
4474 ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
@@ -5238,16 +4501,21 @@
5238 **
5239 ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
5240 ** are managed by SQLite and are automatically freed when the prepared
5241 ** statement is finalized.
5242 ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
5243 ** is obtained from [sqlite3_malloc()] and must be free by the application
5244 ** by passing it to [sqlite3_free()].
 
 
 
5245 */
5246 SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
5247 SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
 
5248 SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
 
5249
5250 /*
5251 ** CAPI3REF: Determine If An SQL Statement Writes The Database
5252 ** METHOD: sqlite3_stmt
5253 **
@@ -5458,21 +4726,21 @@
5458 ** contain embedded NULs. The result of expressions involving strings
5459 ** with embedded NULs is undefined.
5460 **
5461 ** ^The fifth argument to the BLOB and string binding interfaces controls
5462 ** or indicates the lifetime of the object referenced by the third parameter.
5463 ** ^These three options exist:
5464 ** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
5465 ** with it may be passed. ^It is called to dispose of the BLOB or string even
5466 ** if the call to the bind API fails, except the destructor is not called if
5467 ** the third parameter is a NULL pointer or the fourth parameter is negative.
5468 ** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
5469 ** the application remains responsible for disposing of the object. ^In this
5470 ** case, the object and the provided pointer to it must remain valid until
5471 ** either the prepared statement is finalized or the same SQL parameter is
5472 ** bound to something else, whichever occurs sooner.
5473 ** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
5474 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
5475 ** object and pointer to it must remain valid until then. ^SQLite will then
5476 ** manage the lifetime of its private copy.
5477 **
5478 ** ^The sixth argument to sqlite3_bind_text64() must be one of
@@ -10090,12 +9358,13 @@
10090 ** that does not correspond to any valid SQLite error code, the results
10091 ** are undefined.
10092 **
10093 ** A single database handle may have at most a single write-ahead log callback
10094 ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
10095 ** previously registered write-ahead log callback. ^Note that the
10096 ** [sqlite3_wal_autocheckpoint()] interface and the
 
10097 ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
10098 ** overwrite any prior [sqlite3_wal_hook()] settings.
10099 */
10100 SQLITE_API void *sqlite3_wal_hook(
10101 sqlite3*,
@@ -10957,10 +10226,14 @@
10957 ** if writes on the database cause it to grow larger than M bytes.
10958 **
10959 ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
10960 ** database is currently in a read transaction or is involved in a backup
10961 ** operation.
 
 
 
 
10962 **
10963 ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
10964 ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
10965 ** [sqlite3_free()] is invoked on argument P prior to returning.
10966 **
@@ -13440,11 +12713,11 @@
13440 /*
13441 ** Include the configuration header output by 'configure' if we're using the
13442 ** autoconf-based build
13443 */
13444 #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
13445 /* #include "config.h" */
13446 #define SQLITECONFIG_H 1
13447 #endif
13448
13449 /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
13450 /************** Begin file sqliteLimit.h *************************************/
@@ -13676,15 +12949,16 @@
13676 ** places. The following macros try to make this explicit.
13677 */
13678 #ifndef __has_extension
13679 # define __has_extension(x) 0 /* compatibility with non-clang compilers */
13680 #endif
13681 #if GCC_VERSION>=4007000 || \
13682 (__has_extension(c_atomic) && __has_extension(c_atomic_store_n))
13683 # define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
13684 # define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
13685 #else
 
13686 # define AtomicLoad(PTR) (*(PTR))
13687 # define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
13688 #endif
13689
13690 /*
@@ -14598,10 +13872,11 @@
14598 #ifndef SQLITE_PTRSIZE
14599 # if defined(__SIZEOF_POINTER__)
14600 # define SQLITE_PTRSIZE __SIZEOF_POINTER__
14601 # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
14602 defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
 
14603 (defined(__TOS_AIX__) && !defined(__64BIT__))
14604 # define SQLITE_PTRSIZE 4
14605 # else
14606 # define SQLITE_PTRSIZE 8
14607 # endif
@@ -15349,11 +14624,11 @@
15349 */
15350 #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
15351 #define BTREE_BLOBKEY 2 /* Table has keys only - no data */
15352
15353 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
15354 SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
15355 SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
15356 SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
15357
15358 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
15359 SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
@@ -15473,16 +14748,20 @@
15473 #ifdef SQLITE_ENABLE_CURSOR_HINTS
15474 SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
15475 #endif
15476
15477 SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
15478 SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
15479 BtCursor*,
15480 UnpackedRecord *pUnKey,
15481 i64 intKey,
15482 int bias,
15483 int *pRes
 
 
 
 
 
15484 );
15485 SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
15486 SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
15487 SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
15488
@@ -17110,12 +16389,12 @@
17110 u8 mTrace; /* zero or more SQLITE_TRACE flags */
17111 u8 noSharedCache; /* True if no shared-cache backends */
17112 u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
17113 int nextPagesize; /* Pagesize after VACUUM if >0 */
17114 u32 magic; /* Magic number for detect library misuse */
17115 int nChange; /* Value returned by sqlite3_changes() */
17116 int nTotalChange; /* Value returned by sqlite3_total_changes() */
17117 int aLimit[SQLITE_N_LIMIT]; /* Limits */
17118 int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
17119 struct sqlite3InitInfo { /* Information used during initialization */
17120 Pgno newTnum; /* Rootpage of table being initialized */
17121 u8 iDb; /* Which db file is being initialized */
@@ -17320,10 +16599,12 @@
17320 #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
17321 #define SQLITE_SkipScan 0x00004000 /* Skip-scans */
17322 #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
17323 #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
17324 #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
 
 
17325 #define SQLITE_AllOpts 0xffffffff /* All optimizations */
17326
17327 /*
17328 ** Macros for testing whether or not optimizations are enabled or disabled.
17329 */
@@ -17399,16 +16680,17 @@
17399 ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
17400 ** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
17401 ** are assert() statements in the code to verify this.
17402 **
17403 ** Value constraints (enforced via assert()):
17404 ** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
17405 ** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
17406 ** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
17407 ** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
17408 ** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
17409 ** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
 
17410 ** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
17411 */
17412 #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
17413 #define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
17414 #define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
@@ -17429,10 +16711,11 @@
17429 #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
17430 #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
17431 #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
17432 #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
17433 #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
 
17434
17435 /* Identifier numbers for each in-line function */
17436 #define INLINEFUNC_coalesce 0
17437 #define INLINEFUNC_implies_nonnull_row 1
17438 #define INLINEFUNC_expr_implies_expr 2
@@ -17599,22 +16882,45 @@
17599 ** record BLOB generated by the OP_MakeRecord
17600 ** opcode. The storage column index is less than
17601 ** or equal to the table column index. It is
17602 ** equal if and only if there are no VIRTUAL
17603 ** columns to the left.
 
 
 
 
 
 
 
 
17604 */
17605 struct Column {
17606 char *zName; /* Name of this column, \000, then the type */
17607 Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
17608 char *zColl; /* Collating sequence. If NULL, use the default */
17609 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
17610 char affinity; /* One of the SQLITE_AFF_... values */
17611 u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
17612 u8 hName; /* Column name hash for faster lookup */
17613 u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
17614 };
17615
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17616 /* Allowed values for Column.colFlags.
17617 **
17618 ** Constraints:
17619 ** TF_HasVirtual == COLFLAG_VIRTUAL
17620 ** TF_HasStored == COLFLAG_STORED
@@ -17627,10 +16933,11 @@
17627 #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
17628 #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
17629 #define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
17630 #define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
17631 #define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
 
17632 #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
17633 #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
17634
17635 /*
17636 ** A "Collating Sequence" is defined by an instance of the following
@@ -17756,19 +17063,17 @@
17756 #define SQLITE_VTABRISK_Low 0
17757 #define SQLITE_VTABRISK_Normal 1
17758 #define SQLITE_VTABRISK_High 2
17759
17760 /*
17761 ** The schema for each SQL table and view is represented in memory
17762 ** by an instance of the following structure.
17763 */
17764 struct Table {
17765 char *zName; /* Name of the table or view */
17766 Column *aCol; /* Information about each column */
17767 Index *pIndex; /* List of SQL indexes on this table. */
17768 Select *pSelect; /* NULL for tables. Points to definition if a view. */
17769 FKey *pFKey; /* Linked list of all foreign keys in this table */
17770 char *zColAff; /* String defining the affinity of each column */
17771 ExprList *pCheck; /* All CHECK constraints */
17772 /* ... also used as column name list in a VIEW */
17773 Pgno tnum; /* Root BTree page for this table */
17774 u32 nTabRef; /* Number of pointers to this Table */
@@ -17780,19 +17085,28 @@
17780 LogEst szTabRow; /* Estimated size of each table row in bytes */
17781 #ifdef SQLITE_ENABLE_COSTMULT
17782 LogEst costMult; /* Cost multiplier for using this table */
17783 #endif
17784 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
17785 #ifndef SQLITE_OMIT_ALTERTABLE
17786 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
17787 #endif
17788 #ifndef SQLITE_OMIT_VIRTUALTABLE
17789 int nModuleArg; /* Number of arguments to the module */
17790 char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */
17791 VTable *pVTable; /* List of VTable objects. */
17792 #endif
17793 Trigger *pTrigger; /* List of triggers stored in pSchema */
 
 
 
 
 
 
 
 
 
17794 Schema *pSchema; /* Schema that contains this table */
17795 };
17796
17797 /*
17798 ** Allowed values for Table.tabFlags.
@@ -17807,38 +17121,48 @@
17807 **
17808 ** TF_HasVirtual == COLFLAG_VIRTUAL
17809 ** TF_HasStored == COLFLAG_STORED
17810 ** TF_HasHidden == COLFLAG_HIDDEN
17811 */
17812 #define TF_Readonly 0x0001 /* Read-only system table */
17813 #define TF_HasHidden 0x0002 /* Has one or more hidden columns */
17814 #define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
17815 #define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
17816 #define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
17817 #define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
17818 #define TF_HasStored 0x0040 /* Has one or more STORED columns */
17819 #define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
17820 #define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
17821 #define TF_StatsUsed 0x0100 /* Query planner decisions affected by
17822 ** Index.aiRowLogEst[] values */
17823 #define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
17824 #define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
17825 #define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
17826 #define TF_Shadow 0x1000 /* True for a shadow table */
17827 #define TF_HasStat4 0x2000 /* STAT4 info available for this table */
17828 #define TF_Ephemeral 0x4000 /* An ephemeral table */
17829 #define TF_Eponymous 0x8000 /* An eponymous virtual table */
 
 
 
 
 
 
 
 
 
 
17830
17831 /*
17832 ** Test to see whether or not a table is a virtual table. This is
17833 ** done as a macro so that it will be optimized out when virtual
17834 ** table support is omitted from the build.
17835 */
17836 #ifndef SQLITE_OMIT_VIRTUALTABLE
17837 # define IsVirtual(X) ((X)->nModuleArg)
17838 # define ExprIsVtab(X) \
17839 ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg)
17840 #else
17841 # define IsVirtual(X) 0
17842 # define ExprIsVtab(X) 0
17843 #endif
17844
@@ -18664,35 +17988,37 @@
18664
18665 /*
18666 ** Allowed values for the NameContext, ncFlags field.
18667 **
18668 ** Value constraints (all checked via assert()):
18669 ** NC_HasAgg == SF_HasAgg == EP_Agg
18670 ** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
 
18671 ** NC_HasWin == EP_Win
18672 **
18673 */
18674 #define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
18675 #define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
18676 #define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
18677 #define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
18678 #define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
18679 #define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
18680 #define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
18681 #define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
18682 #define NC_UEList 0x00080 /* True if uNC.pEList is used */
18683 #define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
18684 #define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
18685 #define NC_UBaseReg 0x00400 /* True if uNC.iBaseReg is used */
18686 #define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
18687 #define NC_Complex 0x02000 /* True if a function or subquery seen */
18688 #define NC_AllowWin 0x04000 /* Window functions are allowed here */
18689 #define NC_HasWin 0x08000 /* One or more window functions seen */
18690 #define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
18691 #define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
18692 #define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
18693 #define NC_NoSelect 0x80000 /* Do not descend into sub-selects */
 
18694
18695 /*
18696 ** An instance of the following object describes a single ON CONFLICT
18697 ** clause in an upsert.
18698 **
@@ -18771,13 +18097,14 @@
18771 /*
18772 ** Allowed values for Select.selFlags. The "SF" prefix stands for
18773 ** "Select Flag".
18774 **
18775 ** Value constraints (all checked via assert())
18776 ** SF_HasAgg == NC_HasAgg
18777 ** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
18778 ** SF_FixedLimit == WHERE_USE_LIMIT
 
18779 */
18780 #define SF_Distinct 0x0000001 /* Output should be DISTINCT */
18781 #define SF_All 0x0000002 /* Includes the ALL keyword */
18782 #define SF_Resolved 0x0000004 /* Identifiers have been resolved */
18783 #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
@@ -18798,14 +18125,15 @@
18798 #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
18799 #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
18800 #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
18801 #define SF_View 0x0200000 /* SELECT statement is a view */
18802 #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
18803 #define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
18804 #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
18805 #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
18806 #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
 
18807
18808 /*
18809 ** The results of a SELECT can be distributed in several ways, as defined
18810 ** by one of the following macros. The "SRT" prefix means "SELECT Result
18811 ** Type".
@@ -19884,10 +19212,11 @@
19884 SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
19885 SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
19886 SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
19887 SQLITE_PRIVATE void sqlite3Dequote(char*);
19888 SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
 
19889 SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
19890 SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
19891 SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
19892 SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
19893 SQLITE_PRIVATE int sqlite3GetTempReg(Parse*);
@@ -19911,10 +19240,11 @@
19911 SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
19912 SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
19913 SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
19914 SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
19915 SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
 
19916 SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
19917 SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
19918 SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
19919 SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
19920 SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
@@ -19928,10 +19258,14 @@
19928 #endif
19929 SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
19930 SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
19931 SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
19932 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
 
 
 
 
19933 SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
19934 SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
19935 SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
19936 SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
19937 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -19949,11 +19283,11 @@
19949 #if SQLITE_ENABLE_HIDDEN_COLUMNS
19950 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
19951 #else
19952 # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
19953 #endif
19954 SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
19955 SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
19956 SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
19957 SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
19958 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
19959 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
@@ -20066,11 +19400,11 @@
20066 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
20067 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
20068 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
20069 SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
20070 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
20071 SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
20072 #endif
20073 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
20074 SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
20075 SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
20076 SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
@@ -20329,11 +19663,11 @@
20329 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
20330 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
20331 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
20332 SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
20333 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
20334 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
20335 SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
20336 SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
20337 SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
20338 SQLITE_PRIVATE int sqlite3AbsInt32(int);
20339 #ifdef SQLITE_ENABLE_8_3_NAMES
@@ -20359,10 +19693,13 @@
20359 SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
20360 SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
20361 #ifndef SQLITE_AMALGAMATION
20362 SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
20363 SQLITE_PRIVATE const char sqlite3StrBINARY[];
 
 
 
20364 SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
20365 SQLITE_PRIVATE const unsigned char *sqlite3aLTb;
20366 SQLITE_PRIVATE const unsigned char *sqlite3aEQb;
20367 SQLITE_PRIVATE const unsigned char *sqlite3aGTb;
20368 SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
@@ -20779,20 +20116,1004 @@
20779 #endif
20780
20781 SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr);
20782 SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr);
20783 SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
20784 SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
20785 SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
20786
20787 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
20788 SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
20789 #endif
20790
20791 #endif /* SQLITEINT_H */
20792
20793 /************** End of sqliteInt.h *******************************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20794 /************** Begin file global.c ******************************************/
20795 /*
20796 ** 2008 June 13
20797 **
20798 ** The author disclaims copyright to this source code. In place of
@@ -21139,10 +21460,30 @@
21139
21140 /*
21141 ** Name of the default collating sequence
21142 */
21143 SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21144
21145 /************** End of global.c **********************************************/
21146 /************** Begin file status.c ******************************************/
21147 /*
21148 ** 2008 June 18
@@ -21342,12 +21683,12 @@
21342 int pc; /* Program Counter in parent (calling) frame */
21343 int nOp; /* Size of aOp array */
21344 int nMem; /* Number of entries in aMem */
21345 int nChildMem; /* Number of memory cells for child frame */
21346 int nChildCsr; /* Number of cursors for child frame */
21347 int nChange; /* Statement changes (Vdbe.nChange) */
21348 int nDbChange; /* Value of db->nChange */
21349 };
21350
21351 /* Magic number for sanity checking on VdbeFrame objects */
21352 #define SQLITE_FRAME_MAGIC 0x879fb71e
21353
@@ -21550,11 +21891,11 @@
21550 int nMem; /* Number of memory locations currently allocated */
21551 int nCursor; /* Number of slots in apCsr[] */
21552 u32 cacheCtr; /* VdbeCursor row cache generation counter */
21553 int pc; /* The program counter */
21554 int rc; /* Value to return */
21555 int nChange; /* Number of db changes made since last reset */
21556 int iStatement; /* Statement number (or 0 if has no opened stmt) */
21557 i64 iCurrentTime; /* Value of julianday('now') for this statement */
21558 i64 nFkConstraint; /* Number of imm. FK constraints this VM */
21559 i64 nStmtDefCons; /* Number of def. constraints when stmt started */
21560 i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
@@ -21695,10 +22036,11 @@
21695 SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
21696 #endif
21697 SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
21698 SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
21699 SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
 
21700 SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
21701 SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
21702 SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
21703 SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
21704 SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
@@ -27108,209 +27450,11 @@
27108
27109 #if SQLITE_OS_WIN
27110 /*
27111 ** Include code that is common to all os_*.c files
27112 */
27113 /************** Include os_common.h in the middle of mutex_w32.c *************/
27114 /************** Begin file os_common.h ***************************************/
27115 /*
27116 ** 2004 May 22
27117 **
27118 ** The author disclaims copyright to this source code. In place of
27119 ** a legal notice, here is a blessing:
27120 **
27121 ** May you do good and not evil.
27122 ** May you find forgiveness for yourself and forgive others.
27123 ** May you share freely, never taking more than you give.
27124 **
27125 ******************************************************************************
27126 **
27127 ** This file contains macros and a little bit of code that is common to
27128 ** all of the platform-specific files (os_*.c) and is #included into those
27129 ** files.
27130 **
27131 ** This file should be #included by the os_*.c files only. It is not a
27132 ** general purpose header file.
27133 */
27134 #ifndef _OS_COMMON_H_
27135 #define _OS_COMMON_H_
27136
27137 /*
27138 ** At least two bugs have slipped in because we changed the MEMORY_DEBUG
27139 ** macro to SQLITE_DEBUG and some older makefiles have not yet made the
27140 ** switch. The following code should catch this problem at compile-time.
27141 */
27142 #ifdef MEMORY_DEBUG
27143 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
27144 #endif
27145
27146 /*
27147 ** Macros for performance tracing. Normally turned off. Only works
27148 ** on i486 hardware.
27149 */
27150 #ifdef SQLITE_PERFORMANCE_TRACE
27151
27152 /*
27153 ** hwtime.h contains inline assembler code for implementing
27154 ** high-performance timing routines.
27155 */
27156 /************** Include hwtime.h in the middle of os_common.h ****************/
27157 /************** Begin file hwtime.h ******************************************/
27158 /*
27159 ** 2008 May 27
27160 **
27161 ** The author disclaims copyright to this source code. In place of
27162 ** a legal notice, here is a blessing:
27163 **
27164 ** May you do good and not evil.
27165 ** May you find forgiveness for yourself and forgive others.
27166 ** May you share freely, never taking more than you give.
27167 **
27168 ******************************************************************************
27169 **
27170 ** This file contains inline asm code for retrieving "high-performance"
27171 ** counters for x86 and x86_64 class CPUs.
27172 */
27173 #ifndef SQLITE_HWTIME_H
27174 #define SQLITE_HWTIME_H
27175
27176 /*
27177 ** The following routine only works on pentium-class (or newer) processors.
27178 ** It uses the RDTSC opcode to read the cycle count value out of the
27179 ** processor and returns that value. This can be used for high-res
27180 ** profiling.
27181 */
27182 #if !defined(__STRICT_ANSI__) && \
27183 (defined(__GNUC__) || defined(_MSC_VER)) && \
27184 (defined(i386) || defined(__i386__) || defined(_M_IX86))
27185
27186 #if defined(__GNUC__)
27187
27188 __inline__ sqlite_uint64 sqlite3Hwtime(void){
27189 unsigned int lo, hi;
27190 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
27191 return (sqlite_uint64)hi << 32 | lo;
27192 }
27193
27194 #elif defined(_MSC_VER)
27195
27196 __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
27197 __asm {
27198 rdtsc
27199 ret ; return value at EDX:EAX
27200 }
27201 }
27202
27203 #endif
27204
27205 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
27206
27207 __inline__ sqlite_uint64 sqlite3Hwtime(void){
27208 unsigned long val;
27209 __asm__ __volatile__ ("rdtsc" : "=A" (val));
27210 return val;
27211 }
27212
27213 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
27214
27215 __inline__ sqlite_uint64 sqlite3Hwtime(void){
27216 unsigned long long retval;
27217 unsigned long junk;
27218 __asm__ __volatile__ ("\n\
27219 1: mftbu %1\n\
27220 mftb %L0\n\
27221 mftbu %0\n\
27222 cmpw %0,%1\n\
27223 bne 1b"
27224 : "=r" (retval), "=r" (junk));
27225 return retval;
27226 }
27227
27228 #else
27229
27230 /*
27231 ** asm() is needed for hardware timing support. Without asm(),
27232 ** disable the sqlite3Hwtime() routine.
27233 **
27234 ** sqlite3Hwtime() is only used for some obscure debugging
27235 ** and analysis configurations, not in any deliverable, so this
27236 ** should not be a great loss.
27237 */
27238 SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
27239
27240 #endif
27241
27242 #endif /* !defined(SQLITE_HWTIME_H) */
27243
27244 /************** End of hwtime.h **********************************************/
27245 /************** Continuing where we left off in os_common.h ******************/
27246
27247 static sqlite_uint64 g_start;
27248 static sqlite_uint64 g_elapsed;
27249 #define TIMER_START g_start=sqlite3Hwtime()
27250 #define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
27251 #define TIMER_ELAPSED g_elapsed
27252 #else
27253 #define TIMER_START
27254 #define TIMER_END
27255 #define TIMER_ELAPSED ((sqlite_uint64)0)
27256 #endif
27257
27258 /*
27259 ** If we compile with the SQLITE_TEST macro set, then the following block
27260 ** of code will give us the ability to simulate a disk I/O error. This
27261 ** is used for testing the I/O recovery logic.
27262 */
27263 #if defined(SQLITE_TEST)
27264 SQLITE_API extern int sqlite3_io_error_hit;
27265 SQLITE_API extern int sqlite3_io_error_hardhit;
27266 SQLITE_API extern int sqlite3_io_error_pending;
27267 SQLITE_API extern int sqlite3_io_error_persist;
27268 SQLITE_API extern int sqlite3_io_error_benign;
27269 SQLITE_API extern int sqlite3_diskfull_pending;
27270 SQLITE_API extern int sqlite3_diskfull;
27271 #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
27272 #define SimulateIOError(CODE) \
27273 if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
27274 || sqlite3_io_error_pending-- == 1 ) \
27275 { local_ioerr(); CODE; }
27276 static void local_ioerr(){
27277 IOTRACE(("IOERR\n"));
27278 sqlite3_io_error_hit++;
27279 if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
27280 }
27281 #define SimulateDiskfullError(CODE) \
27282 if( sqlite3_diskfull_pending ){ \
27283 if( sqlite3_diskfull_pending == 1 ){ \
27284 local_ioerr(); \
27285 sqlite3_diskfull = 1; \
27286 sqlite3_io_error_hit = 1; \
27287 CODE; \
27288 }else{ \
27289 sqlite3_diskfull_pending--; \
27290 } \
27291 }
27292 #else
27293 #define SimulateIOErrorBenign(X)
27294 #define SimulateIOError(A)
27295 #define SimulateDiskfullError(A)
27296 #endif /* defined(SQLITE_TEST) */
27297
27298 /*
27299 ** When testing, keep a count of the number of open files.
27300 */
27301 #if defined(SQLITE_TEST)
27302 SQLITE_API extern int sqlite3_open_file_count;
27303 #define OpenCounter(X) sqlite3_open_file_count+=(X)
27304 #else
27305 #define OpenCounter(X)
27306 #endif /* defined(SQLITE_TEST) */
27307
27308 #endif /* !defined(_OS_COMMON_H_) */
27309
27310 /************** End of os_common.h *******************************************/
27311 /************** Continuing where we left off in mutex_w32.c ******************/
27312
27313 /*
27314 ** Include the header file for the Windows VFS.
27315 */
27316 /************** Include os_win.h in the middle of mutex_w32.c ****************/
@@ -30077,10 +30221,12 @@
30077 sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
30078 pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
30079 }
30080 if( pItem->fg.jointype & JT_LEFT ){
30081 sqlite3_str_appendf(&x, " LEFT-JOIN");
 
 
30082 }
30083 if( pItem->fg.fromDDL ){
30084 sqlite3_str_appendf(&x, " DDL");
30085 }
30086 if( pItem->fg.isCte ){
@@ -30407,12 +30553,12 @@
30407 case TK_NULL: {
30408 sqlite3TreeViewLine(pView,"NULL");
30409 break;
30410 }
30411 case TK_TRUEFALSE: {
30412 sqlite3TreeViewLine(pView,
30413 sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
30414 break;
30415 }
30416 #ifndef SQLITE_OMIT_BLOB_LITERAL
30417 case TK_BLOB: {
30418 sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
@@ -30632,11 +30778,13 @@
30632 sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
30633 sqlite3_free(z);
30634 break;
30635 }
30636 case TK_SELECT_COLUMN: {
30637 sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
 
 
30638 sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
30639 break;
30640 }
30641 case TK_IF_NULL_ROW: {
30642 sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
@@ -30648,10 +30796,19 @@
30648 sqlite3TreeViewLine(pView, "ERROR");
30649 tmp = *pExpr;
30650 tmp.op = pExpr->op2;
30651 sqlite3TreeViewExpr(pView, &tmp, 0);
30652 break;
 
 
 
 
 
 
 
 
 
30653 }
30654 default: {
30655 sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
30656 break;
30657 }
@@ -30798,15 +30955,20 @@
30798 ** Nothing in this file or anywhere else in SQLite does any kind of
30799 ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
30800 ** number generator) not as an encryption device.
30801 */
30802 if( !wsdPrng.isInit ){
 
30803 int i;
30804 char k[256];
30805 wsdPrng.j = 0;
30806 wsdPrng.i = 0;
30807 sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
 
 
 
 
30808 for(i=0; i<256; i++){
30809 wsdPrng.s[i] = (u8)i;
30810 }
30811 for(i=0; i<256; i++){
30812 wsdPrng.j += wsdPrng.s[i] + k[i];
@@ -31763,12 +31925,18 @@
31763 **
31764 ** The column type is an extra string stored after the zero-terminator on
31765 ** the column name if and only if the COLFLAG_HASTYPE flag is set.
31766 */
31767 SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){
31768 if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt;
31769 return pCol->zName + strlen(pCol->zName) + 1;
 
 
 
 
 
 
31770 }
31771
31772 /*
31773 ** Helper function for sqlite3Error() - called rarely. Broken out into
31774 ** a separate routine to avoid unnecessary register saves on entry to
@@ -31939,10 +32107,32 @@
31939 SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
31940 assert( sqlite3Isquote(p->u.zToken[0]) );
31941 p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
31942 sqlite3Dequote(p->u.zToken);
31943 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31944
31945 /*
31946 ** Generate a Token object from a string
31947 */
31948 SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){
@@ -34150,209 +34340,11 @@
34150 #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
34151
34152 /*
34153 ** Include code that is common to all os_*.c files
34154 */
34155 /************** Include os_common.h in the middle of os_unix.c ***************/
34156 /************** Begin file os_common.h ***************************************/
34157 /*
34158 ** 2004 May 22
34159 **
34160 ** The author disclaims copyright to this source code. In place of
34161 ** a legal notice, here is a blessing:
34162 **
34163 ** May you do good and not evil.
34164 ** May you find forgiveness for yourself and forgive others.
34165 ** May you share freely, never taking more than you give.
34166 **
34167 ******************************************************************************
34168 **
34169 ** This file contains macros and a little bit of code that is common to
34170 ** all of the platform-specific files (os_*.c) and is #included into those
34171 ** files.
34172 **
34173 ** This file should be #included by the os_*.c files only. It is not a
34174 ** general purpose header file.
34175 */
34176 #ifndef _OS_COMMON_H_
34177 #define _OS_COMMON_H_
34178
34179 /*
34180 ** At least two bugs have slipped in because we changed the MEMORY_DEBUG
34181 ** macro to SQLITE_DEBUG and some older makefiles have not yet made the
34182 ** switch. The following code should catch this problem at compile-time.
34183 */
34184 #ifdef MEMORY_DEBUG
34185 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
34186 #endif
34187
34188 /*
34189 ** Macros for performance tracing. Normally turned off. Only works
34190 ** on i486 hardware.
34191 */
34192 #ifdef SQLITE_PERFORMANCE_TRACE
34193
34194 /*
34195 ** hwtime.h contains inline assembler code for implementing
34196 ** high-performance timing routines.
34197 */
34198 /************** Include hwtime.h in the middle of os_common.h ****************/
34199 /************** Begin file hwtime.h ******************************************/
34200 /*
34201 ** 2008 May 27
34202 **
34203 ** The author disclaims copyright to this source code. In place of
34204 ** a legal notice, here is a blessing:
34205 **
34206 ** May you do good and not evil.
34207 ** May you find forgiveness for yourself and forgive others.
34208 ** May you share freely, never taking more than you give.
34209 **
34210 ******************************************************************************
34211 **
34212 ** This file contains inline asm code for retrieving "high-performance"
34213 ** counters for x86 and x86_64 class CPUs.
34214 */
34215 #ifndef SQLITE_HWTIME_H
34216 #define SQLITE_HWTIME_H
34217
34218 /*
34219 ** The following routine only works on pentium-class (or newer) processors.
34220 ** It uses the RDTSC opcode to read the cycle count value out of the
34221 ** processor and returns that value. This can be used for high-res
34222 ** profiling.
34223 */
34224 #if !defined(__STRICT_ANSI__) && \
34225 (defined(__GNUC__) || defined(_MSC_VER)) && \
34226 (defined(i386) || defined(__i386__) || defined(_M_IX86))
34227
34228 #if defined(__GNUC__)
34229
34230 __inline__ sqlite_uint64 sqlite3Hwtime(void){
34231 unsigned int lo, hi;
34232 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
34233 return (sqlite_uint64)hi << 32 | lo;
34234 }
34235
34236 #elif defined(_MSC_VER)
34237
34238 __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
34239 __asm {
34240 rdtsc
34241 ret ; return value at EDX:EAX
34242 }
34243 }
34244
34245 #endif
34246
34247 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
34248
34249 __inline__ sqlite_uint64 sqlite3Hwtime(void){
34250 unsigned long val;
34251 __asm__ __volatile__ ("rdtsc" : "=A" (val));
34252 return val;
34253 }
34254
34255 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
34256
34257 __inline__ sqlite_uint64 sqlite3Hwtime(void){
34258 unsigned long long retval;
34259 unsigned long junk;
34260 __asm__ __volatile__ ("\n\
34261 1: mftbu %1\n\
34262 mftb %L0\n\
34263 mftbu %0\n\
34264 cmpw %0,%1\n\
34265 bne 1b"
34266 : "=r" (retval), "=r" (junk));
34267 return retval;
34268 }
34269
34270 #else
34271
34272 /*
34273 ** asm() is needed for hardware timing support. Without asm(),
34274 ** disable the sqlite3Hwtime() routine.
34275 **
34276 ** sqlite3Hwtime() is only used for some obscure debugging
34277 ** and analysis configurations, not in any deliverable, so this
34278 ** should not be a great loss.
34279 */
34280 SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
34281
34282 #endif
34283
34284 #endif /* !defined(SQLITE_HWTIME_H) */
34285
34286 /************** End of hwtime.h **********************************************/
34287 /************** Continuing where we left off in os_common.h ******************/
34288
34289 static sqlite_uint64 g_start;
34290 static sqlite_uint64 g_elapsed;
34291 #define TIMER_START g_start=sqlite3Hwtime()
34292 #define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
34293 #define TIMER_ELAPSED g_elapsed
34294 #else
34295 #define TIMER_START
34296 #define TIMER_END
34297 #define TIMER_ELAPSED ((sqlite_uint64)0)
34298 #endif
34299
34300 /*
34301 ** If we compile with the SQLITE_TEST macro set, then the following block
34302 ** of code will give us the ability to simulate a disk I/O error. This
34303 ** is used for testing the I/O recovery logic.
34304 */
34305 #if defined(SQLITE_TEST)
34306 SQLITE_API extern int sqlite3_io_error_hit;
34307 SQLITE_API extern int sqlite3_io_error_hardhit;
34308 SQLITE_API extern int sqlite3_io_error_pending;
34309 SQLITE_API extern int sqlite3_io_error_persist;
34310 SQLITE_API extern int sqlite3_io_error_benign;
34311 SQLITE_API extern int sqlite3_diskfull_pending;
34312 SQLITE_API extern int sqlite3_diskfull;
34313 #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
34314 #define SimulateIOError(CODE) \
34315 if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
34316 || sqlite3_io_error_pending-- == 1 ) \
34317 { local_ioerr(); CODE; }
34318 static void local_ioerr(){
34319 IOTRACE(("IOERR\n"));
34320 sqlite3_io_error_hit++;
34321 if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
34322 }
34323 #define SimulateDiskfullError(CODE) \
34324 if( sqlite3_diskfull_pending ){ \
34325 if( sqlite3_diskfull_pending == 1 ){ \
34326 local_ioerr(); \
34327 sqlite3_diskfull = 1; \
34328 sqlite3_io_error_hit = 1; \
34329 CODE; \
34330 }else{ \
34331 sqlite3_diskfull_pending--; \
34332 } \
34333 }
34334 #else
34335 #define SimulateIOErrorBenign(X)
34336 #define SimulateIOError(A)
34337 #define SimulateDiskfullError(A)
34338 #endif /* defined(SQLITE_TEST) */
34339
34340 /*
34341 ** When testing, keep a count of the number of open files.
34342 */
34343 #if defined(SQLITE_TEST)
34344 SQLITE_API extern int sqlite3_open_file_count;
34345 #define OpenCounter(X) sqlite3_open_file_count+=(X)
34346 #else
34347 #define OpenCounter(X)
34348 #endif /* defined(SQLITE_TEST) */
34349
34350 #endif /* !defined(_OS_COMMON_H_) */
34351
34352 /************** End of os_common.h *******************************************/
34353 /************** Continuing where we left off in os_unix.c ********************/
34354
34355 /*
34356 ** Define various macros that are missing from some systems.
34357 */
34358 #ifndef O_LARGEFILE
@@ -40236,10 +40228,12 @@
40236 if( fd<0 ){
40237 if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
40238 /* If unable to create a journal because the directory is not
40239 ** writable, change the error code to indicate that. */
40240 rc = SQLITE_READONLY_DIRECTORY;
 
 
40241 }else if( errno!=EISDIR && isReadWrite ){
40242 /* Failed to open the file for read/write access. Try read-only. */
40243 flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
40244 openFlags &= ~(O_RDWR|O_CREAT);
40245 flags |= SQLITE_OPEN_READONLY;
@@ -42119,10 +42113,11 @@
42119 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
42120 sqlite3_vfs_register(&aVfs[i], i==0);
42121 }
42122 unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
42123
 
42124 /* Validate lock assumptions */
42125 assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
42126 assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
42127 /* Locks:
42128 ** WRITE UNIX_SHM_BASE 120
@@ -42134,10 +42129,12 @@
42134 ** READ-3 UNIX_SHM_BASE+6 126
42135 ** READ-4 UNIX_SHM_BASE+7 127
42136 ** DMS UNIX_SHM_BASE+8 128
42137 */
42138 assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
 
 
42139 return SQLITE_OK;
42140 }
42141
42142 /*
42143 ** Shutdown the operating system interface.
@@ -42173,209 +42170,11 @@
42173 #if SQLITE_OS_WIN /* This file is used for Windows only */
42174
42175 /*
42176 ** Include code that is common to all os_*.c files
42177 */
42178 /************** Include os_common.h in the middle of os_win.c ****************/
42179 /************** Begin file os_common.h ***************************************/
42180 /*
42181 ** 2004 May 22
42182 **
42183 ** The author disclaims copyright to this source code. In place of
42184 ** a legal notice, here is a blessing:
42185 **
42186 ** May you do good and not evil.
42187 ** May you find forgiveness for yourself and forgive others.
42188 ** May you share freely, never taking more than you give.
42189 **
42190 ******************************************************************************
42191 **
42192 ** This file contains macros and a little bit of code that is common to
42193 ** all of the platform-specific files (os_*.c) and is #included into those
42194 ** files.
42195 **
42196 ** This file should be #included by the os_*.c files only. It is not a
42197 ** general purpose header file.
42198 */
42199 #ifndef _OS_COMMON_H_
42200 #define _OS_COMMON_H_
42201
42202 /*
42203 ** At least two bugs have slipped in because we changed the MEMORY_DEBUG
42204 ** macro to SQLITE_DEBUG and some older makefiles have not yet made the
42205 ** switch. The following code should catch this problem at compile-time.
42206 */
42207 #ifdef MEMORY_DEBUG
42208 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
42209 #endif
42210
42211 /*
42212 ** Macros for performance tracing. Normally turned off. Only works
42213 ** on i486 hardware.
42214 */
42215 #ifdef SQLITE_PERFORMANCE_TRACE
42216
42217 /*
42218 ** hwtime.h contains inline assembler code for implementing
42219 ** high-performance timing routines.
42220 */
42221 /************** Include hwtime.h in the middle of os_common.h ****************/
42222 /************** Begin file hwtime.h ******************************************/
42223 /*
42224 ** 2008 May 27
42225 **
42226 ** The author disclaims copyright to this source code. In place of
42227 ** a legal notice, here is a blessing:
42228 **
42229 ** May you do good and not evil.
42230 ** May you find forgiveness for yourself and forgive others.
42231 ** May you share freely, never taking more than you give.
42232 **
42233 ******************************************************************************
42234 **
42235 ** This file contains inline asm code for retrieving "high-performance"
42236 ** counters for x86 and x86_64 class CPUs.
42237 */
42238 #ifndef SQLITE_HWTIME_H
42239 #define SQLITE_HWTIME_H
42240
42241 /*
42242 ** The following routine only works on pentium-class (or newer) processors.
42243 ** It uses the RDTSC opcode to read the cycle count value out of the
42244 ** processor and returns that value. This can be used for high-res
42245 ** profiling.
42246 */
42247 #if !defined(__STRICT_ANSI__) && \
42248 (defined(__GNUC__) || defined(_MSC_VER)) && \
42249 (defined(i386) || defined(__i386__) || defined(_M_IX86))
42250
42251 #if defined(__GNUC__)
42252
42253 __inline__ sqlite_uint64 sqlite3Hwtime(void){
42254 unsigned int lo, hi;
42255 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
42256 return (sqlite_uint64)hi << 32 | lo;
42257 }
42258
42259 #elif defined(_MSC_VER)
42260
42261 __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
42262 __asm {
42263 rdtsc
42264 ret ; return value at EDX:EAX
42265 }
42266 }
42267
42268 #endif
42269
42270 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
42271
42272 __inline__ sqlite_uint64 sqlite3Hwtime(void){
42273 unsigned long val;
42274 __asm__ __volatile__ ("rdtsc" : "=A" (val));
42275 return val;
42276 }
42277
42278 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
42279
42280 __inline__ sqlite_uint64 sqlite3Hwtime(void){
42281 unsigned long long retval;
42282 unsigned long junk;
42283 __asm__ __volatile__ ("\n\
42284 1: mftbu %1\n\
42285 mftb %L0\n\
42286 mftbu %0\n\
42287 cmpw %0,%1\n\
42288 bne 1b"
42289 : "=r" (retval), "=r" (junk));
42290 return retval;
42291 }
42292
42293 #else
42294
42295 /*
42296 ** asm() is needed for hardware timing support. Without asm(),
42297 ** disable the sqlite3Hwtime() routine.
42298 **
42299 ** sqlite3Hwtime() is only used for some obscure debugging
42300 ** and analysis configurations, not in any deliverable, so this
42301 ** should not be a great loss.
42302 */
42303 SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
42304
42305 #endif
42306
42307 #endif /* !defined(SQLITE_HWTIME_H) */
42308
42309 /************** End of hwtime.h **********************************************/
42310 /************** Continuing where we left off in os_common.h ******************/
42311
42312 static sqlite_uint64 g_start;
42313 static sqlite_uint64 g_elapsed;
42314 #define TIMER_START g_start=sqlite3Hwtime()
42315 #define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
42316 #define TIMER_ELAPSED g_elapsed
42317 #else
42318 #define TIMER_START
42319 #define TIMER_END
42320 #define TIMER_ELAPSED ((sqlite_uint64)0)
42321 #endif
42322
42323 /*
42324 ** If we compile with the SQLITE_TEST macro set, then the following block
42325 ** of code will give us the ability to simulate a disk I/O error. This
42326 ** is used for testing the I/O recovery logic.
42327 */
42328 #if defined(SQLITE_TEST)
42329 SQLITE_API extern int sqlite3_io_error_hit;
42330 SQLITE_API extern int sqlite3_io_error_hardhit;
42331 SQLITE_API extern int sqlite3_io_error_pending;
42332 SQLITE_API extern int sqlite3_io_error_persist;
42333 SQLITE_API extern int sqlite3_io_error_benign;
42334 SQLITE_API extern int sqlite3_diskfull_pending;
42335 SQLITE_API extern int sqlite3_diskfull;
42336 #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
42337 #define SimulateIOError(CODE) \
42338 if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
42339 || sqlite3_io_error_pending-- == 1 ) \
42340 { local_ioerr(); CODE; }
42341 static void local_ioerr(){
42342 IOTRACE(("IOERR\n"));
42343 sqlite3_io_error_hit++;
42344 if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
42345 }
42346 #define SimulateDiskfullError(CODE) \
42347 if( sqlite3_diskfull_pending ){ \
42348 if( sqlite3_diskfull_pending == 1 ){ \
42349 local_ioerr(); \
42350 sqlite3_diskfull = 1; \
42351 sqlite3_io_error_hit = 1; \
42352 CODE; \
42353 }else{ \
42354 sqlite3_diskfull_pending--; \
42355 } \
42356 }
42357 #else
42358 #define SimulateIOErrorBenign(X)
42359 #define SimulateIOError(A)
42360 #define SimulateDiskfullError(A)
42361 #endif /* defined(SQLITE_TEST) */
42362
42363 /*
42364 ** When testing, keep a count of the number of open files.
42365 */
42366 #if defined(SQLITE_TEST)
42367 SQLITE_API extern int sqlite3_open_file_count;
42368 #define OpenCounter(X) sqlite3_open_file_count+=(X)
42369 #else
42370 #define OpenCounter(X)
42371 #endif /* defined(SQLITE_TEST) */
42372
42373 #endif /* !defined(_OS_COMMON_H_) */
42374
42375 /************** End of os_common.h *******************************************/
42376 /************** Continuing where we left off in os_win.c *********************/
42377
42378 /*
42379 ** Include the header file for the Windows VFS.
42380 */
42381 /* #include "os_win.h" */
@@ -49319,11 +49118,12 @@
49319 #endif
49320
49321 sqlite3_mutex_enter(db->mutex);
49322 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
49323 iDb = sqlite3FindDbName(db, zSchema);
49324 if( iDb<0 ){
 
49325 rc = SQLITE_ERROR;
49326 goto end_deserialize;
49327 }
49328 zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
49329 if( zSql==0 ){
@@ -49371,11 +49171,13 @@
49371 ** This routine is called when the extension is loaded.
49372 ** Register the new VFS.
49373 */
49374 SQLITE_PRIVATE int sqlite3MemdbInit(void){
49375 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
49376 unsigned int sz = pLower->szOsFile;
 
 
49377 memdb_vfs.pAppData = pLower;
49378 /* The following conditional can only be true when compiled for
49379 ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
49380 ** it in, to be safe, but it is marked as NO_TEST since there
49381 ** is no way to reach it under most builds. */
@@ -60504,11 +60306,14 @@
60504 ** Each index block except for the first contains information on
60505 ** HASHTABLE_NPAGE frames. The first index block contains information on
60506 ** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
60507 ** HASHTABLE_NPAGE are selected so that together the wal-index header and
60508 ** first index block are the same size as all other index blocks in the
60509 ** wal-index.
 
 
 
60510 **
60511 ** Each index block contains two sections, a page-mapping that contains the
60512 ** database page number associated with each wal frame, and a hash-table
60513 ** that allows readers to query an index block for a specific page number.
60514 ** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
@@ -60740,10 +60545,74 @@
60740 u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */
60741 u32 notUsed0; /* Available for future enhancements */
60742 };
60743 #define READMARK_NOT_USED 0xffffffff
60744
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60745
60746 /* A block of WALINDEX_LOCK_RESERVED bytes beginning at
60747 ** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
60748 ** only support mandatory file-locks, we do not read or write data
60749 ** from the region of the file on which locks are applied.
@@ -61752,19 +61621,48 @@
61752 Wal *pRet; /* Object to allocate and return */
61753 int flags; /* Flags passed to OsOpen() */
61754
61755 assert( zWalName && zWalName[0] );
61756 assert( pDbFd );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61757
61758 /* In the amalgamation, the os_unix.c and os_win.c source files come before
61759 ** this source file. Verify that the #defines of the locking byte offsets
61760 ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
61761 ** For that matter, if the lock offset ever changes from its initial design
61762 ** value of 120, we need to know that so there is an assert() to check it.
61763 */
61764 assert( 120==WALINDEX_LOCK_OFFSET );
61765 assert( 136==WALINDEX_HDR_SIZE );
61766 #ifdef WIN_SHM_BASE
61767 assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
61768 #endif
61769 #ifdef UNIX_SHM_BASE
61770 assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
@@ -66267,19 +66165,17 @@
66267 pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
66268 if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
66269 sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
66270 if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
66271 rc = SQLITE_CORRUPT_BKPT;
66272 goto moveto_done;
 
66273 }
 
66274 }else{
66275 pIdxKey = 0;
66276 }
66277 rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
66278 moveto_done:
66279 if( pIdxKey ){
66280 sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
66281 }
66282 return rc;
66283 }
66284
66285 /*
@@ -67124,11 +67020,11 @@
67124 u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
67125 if( pSpace ){
67126 int g2;
67127 assert( pSpace+nByte<=data+pPage->pBt->usableSize );
67128 *pIdx = g2 = (int)(pSpace-data);
67129 if( NEVER(g2<=gap) ){
67130 return SQLITE_CORRUPT_PAGE(pPage);
67131 }else{
67132 return SQLITE_OK;
67133 }
67134 }else if( rc ){
@@ -70861,16 +70757,12 @@
70861 rc = SQLITE_OK;
70862 }
70863 return rc;
70864 }
70865
70866 /* Move the cursor so that it points to an entry near the key
70867 ** specified by pIdxKey or intKey. Return a success code.
70868 **
70869 ** For INTKEY tables, the intKey parameter is used. pIdxKey
70870 ** must be NULL. For index tables, pIdxKey is used and intKey
70871 ** is ignored.
70872 **
70873 ** If an exact match is not found, then the cursor is always
70874 ** left pointing at a leaf page which would hold the entry if it
70875 ** were present. The cursor might point to an entry that comes
70876 ** before or after the key.
@@ -70879,43 +70771,36 @@
70879 ** comparing the key with the entry to which the cursor is
70880 ** pointing. The meaning of the integer written into
70881 ** *pRes is as follows:
70882 **
70883 ** *pRes<0 The cursor is left pointing at an entry that
70884 ** is smaller than intKey/pIdxKey or if the table is empty
70885 ** and the cursor is therefore left point to nothing.
70886 **
70887 ** *pRes==0 The cursor is left pointing at an entry that
70888 ** exactly matches intKey/pIdxKey.
70889 **
70890 ** *pRes>0 The cursor is left pointing at an entry that
70891 ** is larger than intKey/pIdxKey.
70892 **
70893 ** For index tables, the pIdxKey->eqSeen field is set to 1 if there
70894 ** exists an entry in the table that exactly matches pIdxKey.
70895 */
70896 SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
70897 BtCursor *pCur, /* The cursor to be moved */
70898 UnpackedRecord *pIdxKey, /* Unpacked index key */
70899 i64 intKey, /* The table key */
70900 int biasRight, /* If true, bias the search to the high end */
70901 int *pRes /* Write search results here */
70902 ){
70903 int rc;
70904 RecordCompare xRecordCompare;
70905
70906 assert( cursorOwnsBtShared(pCur) );
70907 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
70908 assert( pRes );
70909 assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
70910 assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
70911
70912 /* If the cursor is already positioned at the point we are trying
70913 ** to move to, then just return without doing any work */
70914 if( pIdxKey==0
70915 && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
70916 ){
70917 if( pCur->info.nKey==intKey ){
70918 *pRes = 0;
70919 return SQLITE_OK;
70920 }
70921 if( pCur->info.nKey<intKey ){
@@ -70946,20 +70831,153 @@
70946
70947 #ifdef SQLITE_DEBUG
70948 pCur->pBtree->nSeek++; /* Performance measurement during testing */
70949 #endif
70950
70951 if( pIdxKey ){
70952 xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
70953 pIdxKey->errCode = 0;
70954 assert( pIdxKey->default_rc==1
70955 || pIdxKey->default_rc==0
70956 || pIdxKey->default_rc==-1
70957 );
70958 }else{
70959 xRecordCompare = 0; /* All keys are integers */
70960 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70961
70962 rc = moveToRoot(pCur);
70963 if( rc ){
70964 if( rc==SQLITE_EMPTY ){
70965 assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
@@ -70988,155 +71006,116 @@
70988 ** a moveToChild() or moveToRoot() call would have detected corruption. */
70989 assert( pPage->nCell>0 );
70990 assert( pPage->intKey==(pIdxKey==0) );
70991 lwr = 0;
70992 upr = pPage->nCell-1;
70993 assert( biasRight==0 || biasRight==1 );
70994 idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
70995 pCur->ix = (u16)idx;
70996 if( xRecordCompare==0 ){
70997 for(;;){
70998 i64 nCellKey;
70999 pCell = findCellPastPtr(pPage, idx);
71000 if( pPage->intKeyLeaf ){
71001 while( 0x80 <= *(pCell++) ){
71002 if( pCell>=pPage->aDataEnd ){
71003 return SQLITE_CORRUPT_PAGE(pPage);
71004 }
71005 }
71006 }
71007 getVarint(pCell, (u64*)&nCellKey);
71008 if( nCellKey<intKey ){
71009 lwr = idx+1;
71010 if( lwr>upr ){ c = -1; break; }
71011 }else if( nCellKey>intKey ){
71012 upr = idx-1;
71013 if( lwr>upr ){ c = +1; break; }
71014 }else{
71015 assert( nCellKey==intKey );
71016 pCur->ix = (u16)idx;
71017 if( !pPage->leaf ){
71018 lwr = idx;
71019 goto moveto_next_layer;
71020 }else{
71021 pCur->curFlags |= BTCF_ValidNKey;
71022 pCur->info.nKey = nCellKey;
71023 pCur->info.nSize = 0;
71024 *pRes = 0;
71025 return SQLITE_OK;
71026 }
71027 }
71028 assert( lwr+upr>=0 );
71029 idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
71030 }
71031 }else{
71032 for(;;){
71033 int nCell; /* Size of the pCell cell in bytes */
71034 pCell = findCellPastPtr(pPage, idx);
71035
71036 /* The maximum supported page-size is 65536 bytes. This means that
71037 ** the maximum number of record bytes stored on an index B-Tree
71038 ** page is less than 16384 bytes and may be stored as a 2-byte
71039 ** varint. This information is used to attempt to avoid parsing
71040 ** the entire cell by checking for the cases where the record is
71041 ** stored entirely within the b-tree page by inspecting the first
71042 ** 2 bytes of the cell.
71043 */
71044 nCell = pCell[0];
71045 if( nCell<=pPage->max1bytePayload ){
71046 /* This branch runs if the record-size field of the cell is a
71047 ** single byte varint and the record fits entirely on the main
71048 ** b-tree page. */
71049 testcase( pCell+nCell+1==pPage->aDataEnd );
71050 c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
71051 }else if( !(pCell[1] & 0x80)
71052 && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
71053 ){
71054 /* The record-size field is a 2 byte varint and the record
71055 ** fits entirely on the main b-tree page. */
71056 testcase( pCell+nCell+2==pPage->aDataEnd );
71057 c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
71058 }else{
71059 /* The record flows over onto one or more overflow pages. In
71060 ** this case the whole cell needs to be parsed, a buffer allocated
71061 ** and accessPayload() used to retrieve the record into the
71062 ** buffer before VdbeRecordCompare() can be called.
71063 **
71064 ** If the record is corrupt, the xRecordCompare routine may read
71065 ** up to two varints past the end of the buffer. An extra 18
71066 ** bytes of padding is allocated at the end of the buffer in
71067 ** case this happens. */
71068 void *pCellKey;
71069 u8 * const pCellBody = pCell - pPage->childPtrSize;
71070 const int nOverrun = 18; /* Size of the overrun padding */
71071 pPage->xParseCell(pPage, pCellBody, &pCur->info);
71072 nCell = (int)pCur->info.nKey;
71073 testcase( nCell<0 ); /* True if key size is 2^32 or more */
71074 testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
71075 testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
71076 testcase( nCell==2 ); /* Minimum legal index key size */
71077 if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
71078 rc = SQLITE_CORRUPT_PAGE(pPage);
71079 goto moveto_finish;
71080 }
71081 pCellKey = sqlite3Malloc( nCell+nOverrun );
71082 if( pCellKey==0 ){
71083 rc = SQLITE_NOMEM_BKPT;
71084 goto moveto_finish;
71085 }
71086 pCur->ix = (u16)idx;
71087 rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
71088 memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
71089 pCur->curFlags &= ~BTCF_ValidOvfl;
71090 if( rc ){
71091 sqlite3_free(pCellKey);
71092 goto moveto_finish;
71093 }
71094 c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
71095 sqlite3_free(pCellKey);
71096 }
71097 assert(
71098 (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
71099 && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
71100 );
71101 if( c<0 ){
71102 lwr = idx+1;
71103 }else if( c>0 ){
71104 upr = idx-1;
71105 }else{
71106 assert( c==0 );
71107 *pRes = 0;
71108 rc = SQLITE_OK;
71109 pCur->ix = (u16)idx;
71110 if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
71111 goto moveto_finish;
71112 }
71113 if( lwr>upr ) break;
71114 assert( lwr+upr>=0 );
71115 idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
71116 }
71117 }
71118 assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
71119 assert( pPage->isInit );
71120 if( pPage->leaf ){
71121 assert( pCur->ix<pCur->pPage->nCell );
71122 pCur->ix = (u16)idx;
71123 *pRes = c;
71124 rc = SQLITE_OK;
71125 goto moveto_finish;
71126 }
71127 moveto_next_layer:
71128 if( lwr>=pPage->nCell ){
71129 chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
71130 }else{
71131 chldPg = get4byte(findCell(pPage, lwr));
71132 }
71133 pCur->ix = (u16)lwr;
71134 rc = moveToChild(pCur, chldPg);
71135 if( rc ) break;
71136 }
71137 moveto_finish:
71138 pCur->info.nSize = 0;
71139 assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
71140 return rc;
71141 }
71142
@@ -73116,10 +73095,11 @@
73116 if( rc ){
73117 memset(apOld, 0, (i)*sizeof(MemPage*));
73118 goto balance_cleanup;
73119 }
73120 }
 
73121 if( (i--)==0 ) break;
73122
73123 if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
73124 apDiv[i] = pParent->apOvfl[0];
73125 pgno = get4byte(apDiv[i]);
@@ -73157,11 +73137,10 @@
73157 }
73158 }
73159
73160 /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
73161 ** alignment */
73162 nMaxCells = nOld*(MX_CELL(pBt) + ArraySize(pParent->apOvfl));
73163 nMaxCells = (nMaxCells + 3)&~3;
73164
73165 /*
73166 ** Allocate space for memory structures
73167 */
@@ -73440,11 +73419,13 @@
73440 if( i<nOld ){
73441 pNew = apNew[i] = apOld[i];
73442 apOld[i] = 0;
73443 rc = sqlite3PagerWrite(pNew->pDbPage);
73444 nNew++;
73445 if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) ){
 
 
73446 rc = SQLITE_CORRUPT_BKPT;
73447 }
73448 if( rc ) goto balance_cleanup;
73449 }else{
73450 assert( i>0 );
@@ -74238,11 +74219,12 @@
74238 }else if( loc==0 ){
74239 /* The cursor is *not* pointing to the cell to be overwritten, nor
74240 ** to an adjacent cell. Move the cursor so that it is pointing either
74241 ** to the cell to be overwritten or an adjacent cell.
74242 */
74243 rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
 
74244 if( rc ) return rc;
74245 }
74246 }else{
74247 /* This is an index or a WITHOUT ROWID table */
74248
@@ -74261,17 +74243,15 @@
74261 UnpackedRecord r;
74262 r.pKeyInfo = pCur->pKeyInfo;
74263 r.aMem = pX->aMem;
74264 r.nField = pX->nMem;
74265 r.default_rc = 0;
74266 r.errCode = 0;
74267 r.r1 = 0;
74268 r.r2 = 0;
74269 r.eqSeen = 0;
74270 rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
74271 }else{
74272 rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
 
74273 }
74274 if( rc ) return rc;
74275 }
74276
74277 /* If the cursor is currently pointing to an entry to be overwritten
@@ -74901,11 +74881,11 @@
74901 */
74902 static int clearDatabasePage(
74903 BtShared *pBt, /* The BTree that contains the table */
74904 Pgno pgno, /* Page number to clear */
74905 int freePageFlag, /* Deallocate page if true */
74906 int *pnChange /* Add number of Cells freed to this counter */
74907 ){
74908 MemPage *pPage;
74909 int rc;
74910 unsigned char *pCell;
74911 int i;
@@ -74934,10 +74914,11 @@
74934 if( rc ) goto cleardatabasepage_out;
74935 }
74936 if( !pPage->leaf ){
74937 rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
74938 if( rc ) goto cleardatabasepage_out;
 
74939 }
74940 if( pnChange ){
74941 testcase( !pPage->intKey );
74942 *pnChange += pPage->nCell;
74943 }
@@ -74963,11 +74944,11 @@
74963 ** root of the table.
74964 **
74965 ** If pnChange is not NULL, then the integer value pointed to by pnChange
74966 ** is incremented by the number of entries in the table.
74967 */
74968 SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
74969 int rc;
74970 BtShared *pBt = p->pBt;
74971 sqlite3BtreeEnter(p);
74972 assert( p->inTrans==TRANS_WRITE );
74973
@@ -80557,11 +80538,11 @@
80557 }
80558 #endif
80559 case P4_COLLSEQ: {
80560 static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
80561 CollSeq *pColl = pOp->p4.pColl;
80562 assert( pColl->enc>=0 && pColl->enc<4 );
80563 sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
80564 encnames[pColl->enc]);
80565 break;
80566 }
80567 case P4_FUNCDEF: {
@@ -82398,11 +82379,11 @@
82398 extern int sqlite3_search_count;
82399 #endif
82400 assert( p->deferredMoveto );
82401 assert( p->isTable );
82402 assert( p->eCurType==CURTYPE_BTREE );
82403 rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
82404 if( rc ) return rc;
82405 if( res!=0 ) return SQLITE_CORRUPT_BKPT;
82406 #ifdef SQLITE_TEST
82407 sqlite3_search_count++;
82408 #endif
@@ -83182,11 +83163,11 @@
83182 /*
83183 ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
83184 ** number. Return negative, zero, or positive if the first (i64) is less than,
83185 ** equal to, or greater than the second (double).
83186 */
83187 static int sqlite3IntFloatCompare(i64 i, double r){
83188 if( sizeof(LONGDOUBLE_TYPE)>8 ){
83189 LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
83190 testcase( x<r );
83191 testcase( x>r );
83192 testcase( x==r );
@@ -83906,11 +83887,11 @@
83906
83907 /*
83908 ** This routine sets the value to be returned by subsequent calls to
83909 ** sqlite3_changes() on the database handle 'db'.
83910 */
83911 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
83912 assert( sqlite3_mutex_held(db->mutex) );
83913 db->nChange = nChange;
83914 db->nTotalChange += nChange;
83915 }
83916
@@ -87023,100 +87004,11 @@
87023
87024 /*
87025 ** hwtime.h contains inline assembler code for implementing
87026 ** high-performance timing routines.
87027 */
87028 /************** Include hwtime.h in the middle of vdbe.c *********************/
87029 /************** Begin file hwtime.h ******************************************/
87030 /*
87031 ** 2008 May 27
87032 **
87033 ** The author disclaims copyright to this source code. In place of
87034 ** a legal notice, here is a blessing:
87035 **
87036 ** May you do good and not evil.
87037 ** May you find forgiveness for yourself and forgive others.
87038 ** May you share freely, never taking more than you give.
87039 **
87040 ******************************************************************************
87041 **
87042 ** This file contains inline asm code for retrieving "high-performance"
87043 ** counters for x86 and x86_64 class CPUs.
87044 */
87045 #ifndef SQLITE_HWTIME_H
87046 #define SQLITE_HWTIME_H
87047
87048 /*
87049 ** The following routine only works on pentium-class (or newer) processors.
87050 ** It uses the RDTSC opcode to read the cycle count value out of the
87051 ** processor and returns that value. This can be used for high-res
87052 ** profiling.
87053 */
87054 #if !defined(__STRICT_ANSI__) && \
87055 (defined(__GNUC__) || defined(_MSC_VER)) && \
87056 (defined(i386) || defined(__i386__) || defined(_M_IX86))
87057
87058 #if defined(__GNUC__)
87059
87060 __inline__ sqlite_uint64 sqlite3Hwtime(void){
87061 unsigned int lo, hi;
87062 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
87063 return (sqlite_uint64)hi << 32 | lo;
87064 }
87065
87066 #elif defined(_MSC_VER)
87067
87068 __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
87069 __asm {
87070 rdtsc
87071 ret ; return value at EDX:EAX
87072 }
87073 }
87074
87075 #endif
87076
87077 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
87078
87079 __inline__ sqlite_uint64 sqlite3Hwtime(void){
87080 unsigned long val;
87081 __asm__ __volatile__ ("rdtsc" : "=A" (val));
87082 return val;
87083 }
87084
87085 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
87086
87087 __inline__ sqlite_uint64 sqlite3Hwtime(void){
87088 unsigned long long retval;
87089 unsigned long junk;
87090 __asm__ __volatile__ ("\n\
87091 1: mftbu %1\n\
87092 mftb %L0\n\
87093 mftbu %0\n\
87094 cmpw %0,%1\n\
87095 bne 1b"
87096 : "=r" (retval), "=r" (junk));
87097 return retval;
87098 }
87099
87100 #else
87101
87102 /*
87103 ** asm() is needed for hardware timing support. Without asm(),
87104 ** disable the sqlite3Hwtime() routine.
87105 **
87106 ** sqlite3Hwtime() is only used for some obscure debugging
87107 ** and analysis configurations, not in any deliverable, so this
87108 ** should not be a great loss.
87109 */
87110 SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
87111
87112 #endif
87113
87114 #endif /* !defined(SQLITE_HWTIME_H) */
87115
87116 /************** End of hwtime.h **********************************************/
87117 /************** Continuing where we left off in vdbe.c ***********************/
87118
87119 #endif
87120
87121 #ifndef NDEBUG
87122 /*
@@ -90274,10 +90166,12 @@
90274 assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
90275 assert( pOp->p4type==P4_KEYINFO );
90276 pCur = p->apCsr[pOp->p1];
90277 if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
90278 assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
 
 
90279 goto open_cursor_set_hints;
90280 }
90281 /* If the cursor is not currently open or is open on a different
90282 ** index, then fall through into OP_OpenRead to force a reopen */
90283 case OP_OpenRead:
@@ -90761,45 +90655,47 @@
90761 pIn3->flags = flags3; /* But convert the type back to its original */
90762
90763 /* If the P3 value could not be converted into an integer without
90764 ** loss of information, then special processing is required... */
90765 if( (newType & (MEM_Int|MEM_IntReal))==0 ){
 
90766 if( (newType & MEM_Real)==0 ){
90767 if( (newType & MEM_Null) || oc>=OP_SeekGE ){
90768 VdbeBranchTaken(1,2);
90769 goto jump_to_p2;
90770 }else{
90771 rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
90772 if( rc!=SQLITE_OK ) goto abort_due_to_error;
90773 goto seek_not_found;
90774 }
90775 }else
 
90776
90777 /* If the approximation iKey is larger than the actual real search
90778 ** term, substitute >= for > and < for <=. e.g. if the search term
90779 ** is 4.9 and the integer approximation 5:
90780 **
90781 ** (x > 4.9) -> (x >= 5)
90782 ** (x <= 4.9) -> (x < 5)
90783 */
90784 if( pIn3->u.r<(double)iKey ){
90785 assert( OP_SeekGE==(OP_SeekGT-1) );
90786 assert( OP_SeekLT==(OP_SeekLE-1) );
90787 assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
90788 if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
90789 }
90790
90791 /* If the approximation iKey is smaller than the actual real search
90792 ** term, substitute <= for < and > for >=. */
90793 else if( pIn3->u.r>(double)iKey ){
90794 assert( OP_SeekLE==(OP_SeekLT+1) );
90795 assert( OP_SeekGT==(OP_SeekGE+1) );
90796 assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
90797 if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
90798 }
90799 }
90800 rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
90801 pC->movetoTarget = iKey; /* Used by OP_Delete */
90802 if( rc!=SQLITE_OK ){
90803 goto abort_due_to_error;
90804 }
90805 }else{
@@ -90842,11 +90738,11 @@
90842 r.aMem = &aMem[pOp->p3];
90843 #ifdef SQLITE_DEBUG
90844 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
90845 #endif
90846 r.eqSeen = 0;
90847 rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
90848 if( rc!=SQLITE_OK ){
90849 goto abort_due_to_error;
90850 }
90851 if( eqOnly && r.eqSeen==0 ){
90852 assert( res!=0 );
@@ -91261,11 +91157,11 @@
91261 takeJump = 1;
91262 break;
91263 }
91264 }
91265 }
91266 rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
91267 if( pFree ) sqlite3DbFreeNN(db, pFree);
91268 if( rc!=SQLITE_OK ){
91269 goto abort_due_to_error;
91270 }
91271 pC->seekResult = res;
@@ -91370,11 +91266,11 @@
91370 assert( pC->isTable );
91371 assert( pC->eCurType==CURTYPE_BTREE );
91372 pCrsr = pC->uc.pCursor;
91373 assert( pCrsr!=0 );
91374 res = 0;
91375 rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
91376 assert( rc==SQLITE_OK || res==0 );
91377 pC->movetoTarget = iKey; /* Used by OP_Delete */
91378 pC->nullRow = 0;
91379 pC->cacheStatus = CACHE_STALE;
91380 pC->deferredMoveto = 0;
@@ -91527,11 +91423,11 @@
91527 ** an AUTOINCREMENT table. */
91528 cnt = 0;
91529 do{
91530 sqlite3_randomness(sizeof(v), &v);
91531 v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
91532 }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
91533 0, &res))==SQLITE_OK)
91534 && (res==0)
91535 && (++cnt<100));
91536 if( rc ) goto abort_due_to_error;
91537 if( res==0 ){
@@ -92425,11 +92321,11 @@
92425 assert( pCrsr!=0 );
92426 r.pKeyInfo = pC->pKeyInfo;
92427 r.nField = (u16)pOp->p3;
92428 r.default_rc = 0;
92429 r.aMem = &aMem[pOp->p2];
92430 rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
92431 if( rc ) goto abort_due_to_error;
92432 if( res==0 ){
92433 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
92434 if( rc ) goto abort_due_to_error;
92435 }else if( pOp->p5 ){
@@ -92738,11 +92634,11 @@
92738 ** by the number of rows in the table being cleared.
92739 **
92740 ** See also: Destroy
92741 */
92742 case OP_Clear: {
92743 int nChange;
92744
92745 sqlite3VdbeIncrWriteCounter(p, 0);
92746 nChange = 0;
92747 assert( p->readOnly==0 );
92748 assert( DbMaskTest(p->btreeMask, pOp->p2) );
@@ -94960,11 +94856,11 @@
94960 if( pTab && !HasRowid(pTab) ){
94961 pTab = 0;
94962 sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
94963 }
94964 #ifndef SQLITE_OMIT_VIEW
94965 if( pTab && pTab->pSelect ){
94966 pTab = 0;
94967 sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
94968 }
94969 #endif
94970 if( !pTab ){
@@ -94980,11 +94876,11 @@
94980 pBlob->pTab = pTab;
94981 pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
94982
94983 /* Now search pTab for the exact column. */
94984 for(iCol=0; iCol<pTab->nCol; iCol++) {
94985 if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
94986 break;
94987 }
94988 }
94989 if( iCol==pTab->nCol ){
94990 sqlite3DbFree(db, zErr);
@@ -95005,11 +94901,12 @@
95005 /* Check that the column is not part of an FK child key definition. It
95006 ** is not necessary to check if it is part of a parent key, as parent
95007 ** key columns must be indexed. The check below will pick up this
95008 ** case. */
95009 FKey *pFKey;
95010 for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
 
95011 int j;
95012 for(j=0; j<pFKey->nCol; j++){
95013 if( pFKey->aCol[j].iFrom==iCol ){
95014 zFault = "foreign key";
95015 }
@@ -96378,12 +96275,13 @@
96378 int iTask = (pTask - pTask->pSorter->aTask);
96379 sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
96380 fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
96381 }
96382 static void vdbeSorterRewindDebug(const char *zEvent){
96383 i64 t;
96384 sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t);
 
96385 fprintf(stderr, "%lld:X %s\n", t, zEvent);
96386 }
96387 static void vdbeSorterPopulateDebug(
96388 SortSubtask *pTask,
96389 const char *zEvent
@@ -99500,11 +99398,11 @@
99500 if( pSrcList ){
99501 for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
99502 u8 hCol;
99503 pTab = pItem->pTab;
99504 assert( pTab!=0 && pTab->zName!=0 );
99505 assert( pTab->nCol>0 );
99506 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
99507 int hit = 0;
99508 pEList = pItem->pSelect->pEList;
99509 for(j=0; j<pEList->nExpr; j++){
99510 if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
@@ -99528,16 +99426,15 @@
99528 }
99529 if( IN_RENAME_OBJECT && pItem->zAlias ){
99530 sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
99531 }
99532 }
99533 if( 0==(cntTab++) ){
99534 pMatch = pItem;
99535 }
99536 hCol = sqlite3StrIHash(zCol);
99537 for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
99538 if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
 
 
99539 /* If there has been exactly one prior match and this match
99540 ** is for the right-hand table of a NATURAL JOIN or is in a
99541 ** USING clause, then skip this match.
99542 */
99543 if( cnt==1 ){
@@ -99548,10 +99445,14 @@
99548 pMatch = pItem;
99549 /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
99550 pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
99551 break;
99552 }
 
 
 
 
99553 }
99554 }
99555 if( pMatch ){
99556 pExpr->iTable = pMatch->iCursor;
99557 pExpr->y.pTab = pMatch->pTab;
@@ -99606,11 +99507,13 @@
99606 int iCol;
99607 u8 hCol = sqlite3StrIHash(zCol);
99608 pSchema = pTab->pSchema;
99609 cntTab++;
99610 for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
99611 if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
 
 
99612 if( iCol==pTab->iPKey ){
99613 iCol = -1;
99614 }
99615 break;
99616 }
@@ -99671,11 +99574,11 @@
99671 if( cnt==0
99672 && cntTab==1
99673 && pMatch
99674 && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
99675 && sqlite3IsRowid(zCol)
99676 && VisibleRowid(pMatch->pTab)
99677 ){
99678 cnt = 1;
99679 pExpr->iColumn = -1;
99680 pExpr->affExpr = SQLITE_AFF_INTEGER;
99681 }
@@ -100014,10 +99917,11 @@
100014 for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
100015 anRef[i] = p->nRef;
100016 }
100017 sqlite3WalkExpr(pWalker, pExpr->pLeft);
100018 if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
 
100019 if( pExpr->op==TK_NOTNULL ){
100020 pExpr->u.zToken = "true";
100021 ExprSetProperty(pExpr, EP_IsTrue);
100022 }else{
100023 pExpr->u.zToken = "false";
@@ -100283,13 +100187,16 @@
100283 pNC2 = pNC2->pNext;
100284 }
100285 assert( pDef!=0 || IN_RENAME_OBJECT );
100286 if( pNC2 && pDef ){
100287 assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
 
100288 testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
100289 pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
100290
 
 
100291 }
100292 }
100293 pNC->ncFlags |= savedAllowFlags;
100294 }
100295 /* FIX ME: Compute pExpr->affinity based on the expected return
@@ -100828,11 +100735,11 @@
100828 assert( pSub->pPrior && pSub->pOrderBy==0 );
100829 pSub->pOrderBy = p->pOrderBy;
100830 p->pOrderBy = 0;
100831 }
100832
100833 /* Recursively resolve names in all subqueries
100834 */
100835 for(i=0; i<p->pSrc->nSrc; i++){
100836 SrcItem *pItem = &p->pSrc->a[i];
100837 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
100838 int nRef = pOuterNC ? pOuterNC->nRef : 0;
@@ -100872,11 +100779,12 @@
100872 */
100873 assert( (p->selFlags & SF_Aggregate)==0 );
100874 pGroupBy = p->pGroupBy;
100875 if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
100876 assert( NC_MinMaxAgg==SF_MinMaxAgg );
100877 p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
 
100878 }else{
100879 sNC.ncFlags &= ~NC_AllowAgg;
100880 }
100881
100882 /* Add the output column list to the name-context before parsing the
@@ -101055,12 +100963,12 @@
101055 ){
101056 int savedHasAgg;
101057 Walker w;
101058
101059 if( pExpr==0 ) return SQLITE_OK;
101060 savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101061 pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101062 w.pParse = pNC->pParse;
101063 w.xExprCallback = resolveExprStep;
101064 w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
101065 w.xSelectCallback2 = 0;
101066 w.u.pNC = pNC;
@@ -101099,12 +101007,12 @@
101099 w.pParse = pNC->pParse;
101100 w.xExprCallback = resolveExprStep;
101101 w.xSelectCallback = resolveSelectStep;
101102 w.xSelectCallback2 = 0;
101103 w.u.pNC = pNC;
101104 savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101105 pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101106 for(i=0; i<pList->nExpr; i++){
101107 Expr *pExpr = pList->a[i].pExpr;
101108 if( pExpr==0 ) continue;
101109 #if SQLITE_MAX_EXPR_DEPTH>0
101110 w.pParse->nHeight += pExpr->nHeight;
@@ -101118,14 +101026,15 @@
101118 #endif
101119 assert( EP_Agg==NC_HasAgg );
101120 assert( EP_Win==NC_HasWin );
101121 testcase( pNC->ncFlags & NC_HasAgg );
101122 testcase( pNC->ncFlags & NC_HasWin );
101123 if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
101124 ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
101125 savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
101126 pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
 
101127 }
101128 if( w.pParse->nErr>0 ) return WRC_Abort;
101129 }
101130 pNC->ncFlags |= savedHasAgg;
101131 return WRC_Continue;
@@ -101285,10 +101194,12 @@
101285 return sqlite3AffinityType(pExpr->u.zToken, 0);
101286 }
101287 #endif
101288 if( op==TK_SELECT_COLUMN ){
101289 assert( pExpr->pLeft->flags&EP_xIsSelect );
 
 
101290 return sqlite3ExprAffinity(
101291 pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
101292 );
101293 }
101294 if( op==TK_VECTOR ){
@@ -101385,11 +101296,11 @@
101385 ){
101386 /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
101387 ** a TK_COLUMN but was previously evaluated and cached in a register */
101388 int j = p->iColumn;
101389 if( j>=0 ){
101390 const char *zColl = p->y.pTab->aCol[j].zColl;
101391 pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
101392 }
101393 break;
101394 }
101395 if( op==TK_CAST || op==TK_UPLUS ){
@@ -101695,11 +101606,12 @@
101695 ** of the returned TK_SELECT_COLUMN Expr object.
101696 */
101697 SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
101698 Parse *pParse, /* Parsing context */
101699 Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
101700 int iField /* Which column of the vector to return */
 
101701 ){
101702 Expr *pRet;
101703 if( pVector->op==TK_SELECT ){
101704 assert( pVector->flags & EP_xIsSelect );
101705 /* The TK_SELECT_COLUMN Expr node:
@@ -101718,14 +101630,14 @@
101718 ** with the same pLeft pointer to the pVector, but only one of them
101719 ** will own the pVector.
101720 */
101721 pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
101722 if( pRet ){
 
101723 pRet->iColumn = iField;
101724 pRet->pLeft = pVector;
101725 }
101726 assert( pRet==0 || pRet->iTable==0 );
101727 }else{
101728 if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
101729 pRet = sqlite3ExprDup(pParse->db, pVector, 0);
101730 sqlite3RenameTokenRemap(pParse, pRet, pVector);
101731 }
@@ -102156,10 +102068,60 @@
102156 assert( pParse->db->mallocFailed );
102157 sqlite3SelectDelete(pParse->db, pSelect);
102158 }
102159 }
102160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102161
102162 /*
102163 ** Join two expressions using an AND operator. If either expression is
102164 ** NULL, then just return the other expression.
102165 **
@@ -102200,11 +102162,14 @@
102200 pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
102201 if( pNew==0 ){
102202 sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
102203 return 0;
102204 }
102205 if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
 
 
 
102206 sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
102207 }
102208 pNew->x.pList = pList;
102209 ExprSetProperty(pNew, EP_HasFunc);
102210 assert( !ExprHasProperty(pNew, EP_xIsSelect) );
@@ -102608,11 +102573,10 @@
102608 }
102609 }else{
102610 if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
102611 if( pNew->op==TK_SELECT_COLUMN ){
102612 pNew->pLeft = p->pLeft;
102613 assert( p->iColumn==0 || p->pRight==0 );
102614 assert( p->pRight==0 || p->pRight==p->pLeft
102615 || ExprHasProperty(p->pLeft, EP_Subquery) );
102616 }else{
102617 pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
102618 }
@@ -102706,11 +102670,12 @@
102706 }
102707 SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
102708 ExprList *pNew;
102709 struct ExprList_item *pItem, *pOldItem;
102710 int i;
102711 Expr *pPriorSelectCol = 0;
 
102712 assert( db!=0 );
102713 if( p==0 ) return 0;
102714 pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
102715 if( pNew==0 ) return 0;
102716 pNew->nExpr = p->nExpr;
@@ -102723,21 +102688,21 @@
102723 pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
102724 if( pOldExpr
102725 && pOldExpr->op==TK_SELECT_COLUMN
102726 && (pNewExpr = pItem->pExpr)!=0
102727 ){
102728 assert( pNewExpr->iColumn==0 || i>0 );
102729 if( pNewExpr->iColumn==0 ){
102730 assert( pOldExpr->pLeft==pOldExpr->pRight
102731 || ExprHasProperty(pOldExpr->pLeft, EP_Subquery) );
102732 pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
102733 }else{
102734 assert( i>0 );
102735 assert( pItem[-1].pExpr!=0 );
102736 assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
102737 assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
102738 pNewExpr->pLeft = pPriorSelectCol;
 
102739 }
102740 }
102741 pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
102742 pItem->sortFlags = pOldItem->sortFlags;
102743 pItem->eEName = pOldItem->eEName;
@@ -102992,15 +102957,13 @@
102992 pColumns->nId, n);
102993 goto vector_append_error;
102994 }
102995
102996 for(i=0; i<pColumns->nId; i++){
102997 Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
102998 assert( pSubExpr!=0 || db->mallocFailed );
102999 assert( pSubExpr==0 || pSubExpr->iTable==0 );
103000 if( pSubExpr==0 ) continue;
103001 pSubExpr->iTable = pColumns->nId;
103002 pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
103003 if( pList ){
103004 assert( pList->nExpr==iFirst+i+1 );
103005 pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
103006 pColumns->a[i].zName = 0;
@@ -103673,11 +103636,11 @@
103673 assert( pSrc!=0 );
103674 if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
103675 if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
103676 pTab = pSrc->a[0].pTab;
103677 assert( pTab!=0 );
103678 assert( pTab->pSelect==0 ); /* FROM clause is not a view */
103679 if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
103680 pEList = p->pEList;
103681 assert( pEList!=0 );
103682 /* All SELECT results must be columns. */
103683 for(i=0; i<pEList->nExpr; i++){
@@ -104803,13 +104766,14 @@
104803 /*
104804 ** Generate code that will compute the value of generated column pCol
104805 ** and store the result in register regOut
104806 */
104807 SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
104808 Parse *pParse,
104809 Column *pCol,
104810 int regOut
 
104811 ){
104812 int iAddr;
104813 Vdbe *v = pParse->pVdbe;
104814 assert( v!=0 );
104815 assert( pParse->iSelfTab!=0 );
@@ -104816,11 +104780,11 @@
104816 if( pParse->iSelfTab>0 ){
104817 iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
104818 }else{
104819 iAddr = 0;
104820 }
104821 sqlite3ExprCodeCopy(pParse, pCol->pDflt, regOut);
104822 if( pCol->affinity>=SQLITE_AFF_TEXT ){
104823 sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
104824 }
104825 if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
104826 }
@@ -104852,16 +104816,17 @@
104852 x = iCol;
104853 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
104854 }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
104855 Parse *pParse = sqlite3VdbeParser(v);
104856 if( pCol->colFlags & COLFLAG_BUSY ){
104857 sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName);
 
104858 }else{
104859 int savedSelfTab = pParse->iSelfTab;
104860 pCol->colFlags |= COLFLAG_BUSY;
104861 pParse->iSelfTab = iTabCur+1;
104862 sqlite3ExprCodeGeneratedColumn(pParse, pCol, regOut);
104863 pParse->iSelfTab = savedSelfTab;
104864 pCol->colFlags &= ~COLFLAG_BUSY;
104865 }
104866 return;
104867 #endif
@@ -105125,11 +105090,12 @@
105125 sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
105126 pCol->iSorterColumn, target);
105127 if( pCol->iColumn<0 ){
105128 VdbeComment((v,"%s.rowid",pTab->zName));
105129 }else{
105130 VdbeComment((v,"%s.%s",pTab->zName,pTab->aCol[pCol->iColumn].zName));
 
105131 if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
105132 sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
105133 }
105134 }
105135 return target;
@@ -105186,16 +105152,16 @@
105186 iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
105187 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
105188 if( pCol->colFlags & COLFLAG_GENERATED ){
105189 if( pCol->colFlags & COLFLAG_BUSY ){
105190 sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
105191 pCol->zName);
105192 return 0;
105193 }
105194 pCol->colFlags |= COLFLAG_BUSY;
105195 if( pCol->colFlags & COLFLAG_NOTAVAIL ){
105196 sqlite3ExprCodeGeneratedColumn(pParse, pCol, iSrc);
105197 }
105198 pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
105199 return iSrc;
105200 }else
105201 #endif /* SQLITE_OMIT_GENERATED_COLUMNS */
@@ -105586,15 +105552,13 @@
105586 case TK_SELECT_COLUMN: {
105587 int n;
105588 if( pExpr->pLeft->iTable==0 ){
105589 pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
105590 }
105591 assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT
105592 || pExpr->pLeft->op==TK_ERROR );
105593 if( pExpr->iTable!=0
105594 && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
105595 ){
105596 sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
105597 pExpr->iTable, n);
105598 }
105599 return pExpr->pLeft->iTable + pExpr->iColumn;
105600 }
@@ -105671,11 +105635,11 @@
105671 assert( p1>=0 && p1<(pTab->nCol*2+2) );
105672
105673 sqlite3VdbeAddOp2(v, OP_Param, p1, target);
105674 VdbeComment((v, "r[%d]=%s.%s", target,
105675 (pExpr->iTable ? "new" : "old"),
105676 (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zName)
105677 ));
105678
105679 #ifndef SQLITE_OMIT_FLOATING_POINT
105680 /* If the column has REAL affinity, it may currently be stored as an
105681 ** integer. Use OP_RealAffinity to make sure it is really real.
@@ -106843,13 +106807,13 @@
106843 testcase( pExpr->op==TK_LE );
106844 testcase( pExpr->op==TK_GT );
106845 testcase( pExpr->op==TK_GE );
106846 /* The y.pTab=0 assignment in wherecode.c always happens after the
106847 ** impliesNotNullRow() test */
106848 if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0)
106849 && IsVirtual(pLeft->y.pTab))
106850 || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0)
106851 && IsVirtual(pRight->y.pTab))
106852 ){
106853 return WRC_Prune;
106854 }
106855 /* no break */ deliberate_fall_through
@@ -107524,22 +107488,19 @@
107524 sqlite3 *db = pParse->db; /* Database connection */
107525 int nTabName; /* Number of UTF-8 characters in zTabName */
107526 const char *zTabName; /* Original name of the table */
107527 Vdbe *v;
107528 VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
107529 u32 savedDbFlags; /* Saved value of db->mDbFlags */
107530
107531 savedDbFlags = db->mDbFlags;
107532 if( NEVER(db->mallocFailed) ) goto exit_rename_table;
107533 assert( pSrc->nSrc==1 );
107534 assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
107535
107536 pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
107537 if( !pTab ) goto exit_rename_table;
107538 iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
107539 zDb = db->aDb[iDb].zDbSName;
107540 db->mDbFlags |= DBFLAG_PreferBuiltin;
107541
107542 /* Get a NULL terminated version of the new table name. */
107543 zName = sqlite3NameFromToken(db, pName);
107544 if( !zName ) goto exit_rename_table;
107545
@@ -107564,11 +107525,11 @@
107564 if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
107565 goto exit_rename_table;
107566 }
107567
107568 #ifndef SQLITE_OMIT_VIEW
107569 if( pTab->pSelect ){
107570 sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
107571 goto exit_rename_table;
107572 }
107573 #endif
107574
@@ -107676,11 +107637,10 @@
107676 renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);
107677
107678 exit_rename_table:
107679 sqlite3SrcListDelete(db, pSrc);
107680 sqlite3DbFree(db, zName);
107681 db->mDbFlags = savedDbFlags;
107682 }
107683
107684 /*
107685 ** Write code that will raise an error if the table described by
107686 ** zDb and zTab is not empty.
@@ -107726,11 +107686,11 @@
107726 assert( sqlite3BtreeHoldsAllMutexes(db) );
107727 iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
107728 zDb = db->aDb[iDb].zDbSName;
107729 zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
107730 pCol = &pNew->aCol[pNew->nCol-1];
107731 pDflt = pCol->pDflt;
107732 pTab = sqlite3FindTable(db, zTab, zDb);
107733 assert( pTab );
107734
107735 #ifndef SQLITE_OMIT_AUTHORIZATION
107736 /* Invoke the authorization callback. */
@@ -107760,11 +107720,11 @@
107760 */
107761 assert( pDflt==0 || pDflt->op==TK_SPAN );
107762 if( pDflt && pDflt->pLeft->op==TK_NULL ){
107763 pDflt = 0;
107764 }
107765 if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
107766 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
107767 "Cannot add a REFERENCES column with non-NULL default value");
107768 }
107769 if( pCol->notNull && !pDflt ){
107770 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
@@ -107797,47 +107757,60 @@
107797
107798 /* Modify the CREATE TABLE statement. */
107799 zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
107800 if( zCol ){
107801 char *zEnd = &zCol[pColDef->n-1];
107802 u32 savedDbFlags = db->mDbFlags;
107803 while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
107804 *zEnd-- = '\0';
107805 }
107806 db->mDbFlags |= DBFLAG_PreferBuiltin;
107807 /* substr() operations on characters, but addColOffset is in bytes. So we
107808 ** have to use printf() to translate between these units: */
 
107809 sqlite3NestedParse(pParse,
107810 "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
107811 "sql = printf('%%.%ds, ',sql) || %Q"
107812 " || substr(sql,1+length(printf('%%.%ds',sql))) "
107813 "WHERE type = 'table' AND name = %Q",
107814 zDb, pNew->addColOffset, zCol, pNew->addColOffset,
107815 zTab
107816 );
107817 sqlite3DbFree(db, zCol);
107818 db->mDbFlags = savedDbFlags;
107819 }
107820
107821 /* Make sure the schema version is at least 3. But do not upgrade
107822 ** from less than 3 to 4, as that will corrupt any preexisting DESC
107823 ** index.
107824 */
107825 v = sqlite3GetVdbe(pParse);
107826 if( v ){
 
 
 
 
107827 r1 = sqlite3GetTempReg(pParse);
107828 sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
107829 sqlite3VdbeUsesBtree(v, iDb);
107830 sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
107831 sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
107832 VdbeCoverage(v);
107833 sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
107834 sqlite3ReleaseTempReg(pParse, r1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107835 }
107836
107837 /* Reload the table definition */
107838 renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
107839 }
107840
107841 /*
107842 ** This function is called by the parser after the table-name in
107843 ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
@@ -107874,20 +107847,20 @@
107874 goto exit_begin_add_column;
107875 }
107876 #endif
107877
107878 /* Make sure this is not an attempt to ALTER a view. */
107879 if( pTab->pSelect ){
107880 sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
107881 goto exit_begin_add_column;
107882 }
107883 if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
107884 goto exit_begin_add_column;
107885 }
107886
107887 sqlite3MayAbort(pParse);
107888 assert( pTab->addColOffset>0 );
107889 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
107890
107891 /* Put a copy of the Table struct in Parse.pNewTable for the
107892 ** sqlite3AddColumn() function and friends to modify. But modify
107893 ** the name by adding an "sqlite_altertab_" prefix. By adding this
@@ -107910,17 +107883,17 @@
107910 goto exit_begin_add_column;
107911 }
107912 memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
107913 for(i=0; i<pNew->nCol; i++){
107914 Column *pCol = &pNew->aCol[i];
107915 pCol->zName = sqlite3DbStrDup(db, pCol->zName);
107916 pCol->hName = sqlite3StrIHash(pCol->zName);
107917 pCol->zColl = 0;
107918 pCol->pDflt = 0;
107919 }
 
 
107920 pNew->pSchema = db->aDb[iDb].pSchema;
107921 pNew->addColOffset = pTab->addColOffset;
107922 pNew->nTabRef = 1;
107923
107924 exit_begin_add_column:
107925 sqlite3SrcListDelete(db, pSrc);
107926 return;
@@ -107936,11 +107909,11 @@
107936 */
107937 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
107938 static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
107939 const char *zType = 0;
107940 #ifndef SQLITE_OMIT_VIEW
107941 if( pTab->pSelect ){
107942 zType = "view";
107943 }
107944 #endif
107945 #ifndef SQLITE_OMIT_VIRTUALTABLE
107946 if( IsVirtual(pTab) ){
@@ -108003,11 +107976,11 @@
108003 /* Make sure the old name really is a column name in the table to be
108004 ** altered. Set iCol to be the index of the column being renamed */
108005 zOld = sqlite3NameFromToken(db, pOld);
108006 if( !zOld ) goto exit_rename_column;
108007 for(iCol=0; iCol<pTab->nCol; iCol++){
108008 if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
108009 }
108010 if( iCol==pTab->nCol ){
108011 sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
108012 goto exit_rename_column;
108013 }
@@ -108240,12 +108213,12 @@
108240 static int renameUnmapSelectCb(Walker *pWalker, Select *p){
108241 Parse *pParse = pWalker->pParse;
108242 int i;
108243 if( pParse->nErr ) return WRC_Abort;
108244 if( p->selFlags & (SF_View|SF_CopyCte) ){
108245 testcase( pSelect->selFlags & SF_View );
108246 testcase( pSelect->selFlags & SF_CopyCte );
108247 return WRC_Prune;
108248 }
108249 if( ALWAYS(p->pEList) ){
108250 ExprList *pList = p->pEList;
108251 for(i=0; i<pList->nExpr; i++){
@@ -108352,12 +108325,12 @@
108352 ** because without a dummy callback, sqlite3WalkExpr() and similar do not
108353 ** descend into sub-select statements.
108354 */
108355 static int renameColumnSelectCb(Walker *pWalker, Select *p){
108356 if( p->selFlags & (SF_View|SF_CopyCte) ){
108357 testcase( pSelect->selFlags & SF_View );
108358 testcase( pSelect->selFlags & SF_CopyCte );
108359 return WRC_Prune;
108360 }
108361 renameWalkWith(pWalker, p);
108362 return WRC_Continue;
108363 }
@@ -108549,17 +108522,17 @@
108549 RenameCtx *pRename, /* Rename context */
108550 const char *zSql, /* SQL statement to edit */
108551 const char *zNew, /* New token text */
108552 int bQuote /* True to always quote token */
108553 ){
108554 int nNew = sqlite3Strlen30(zNew);
108555 int nSql = sqlite3Strlen30(zSql);
108556 sqlite3 *db = sqlite3_context_db_handle(pCtx);
108557 int rc = SQLITE_OK;
108558 char *zQuot = 0;
108559 char *zOut;
108560 int nQuot = 0;
108561 char *zBuf1 = 0;
108562 char *zBuf2 = 0;
108563
108564 if( zNew ){
108565 /* Set zQuot to point to a buffer containing a quoted copy of the
@@ -108849,11 +108822,11 @@
108849 pTab = sqlite3FindTable(db, zTable, zDb);
108850 if( pTab==0 || iCol>=pTab->nCol ){
108851 sqlite3BtreeLeaveAll(db);
108852 return;
108853 }
108854 zOld = pTab->aCol[iCol].zName;
108855 memset(&sCtx, 0, sizeof(sCtx));
108856 sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);
108857
108858 #ifndef SQLITE_OMIT_AUTHORIZATION
108859 db->xAuth = 0;
@@ -108868,30 +108841,29 @@
108868 sWalker.u.pRename = &sCtx;
108869
108870 sCtx.pTab = pTab;
108871 if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
108872 if( sParse.pNewTable ){
108873 Select *pSelect = sParse.pNewTable->pSelect;
108874 if( pSelect ){
108875 pSelect->selFlags &= ~SF_View;
108876 sParse.rc = SQLITE_OK;
108877 sqlite3SelectPrep(&sParse, pSelect, 0);
108878 rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
108879 if( rc==SQLITE_OK ){
108880 sqlite3WalkSelect(&sWalker, pSelect);
108881 }
108882 if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
108883 }else{
108884 /* A regular table */
108885 int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
108886 FKey *pFKey;
108887 assert( sParse.pNewTable->pSelect==0 );
108888 sCtx.pTab = sParse.pNewTable;
108889 if( bFKOnly==0 ){
108890 if( iCol<sParse.pNewTable->nCol ){
108891 renameTokenFind(
108892 &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
108893 );
108894 }
108895 if( sCtx.iCol<0 ){
108896 renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
108897 }
@@ -108902,16 +108874,19 @@
108902 for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
108903 sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
108904 }
108905 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
108906 for(i=0; i<sParse.pNewTable->nCol; i++){
108907 sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
 
 
108908 }
108909 #endif
108910 }
108911
108912 for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
 
108913 for(i=0; i<pFKey->nCol; i++){
108914 if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
108915 renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
108916 }
108917 if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
@@ -109073,32 +109048,35 @@
109073 if( rc==SQLITE_OK ){
109074 int isLegacy = (db->flags & SQLITE_LegacyAlter);
109075 if( sParse.pNewTable ){
109076 Table *pTab = sParse.pNewTable;
109077
109078 if( pTab->pSelect ){
109079 if( isLegacy==0 ){
109080 Select *pSelect = pTab->pSelect;
109081 NameContext sNC;
109082 memset(&sNC, 0, sizeof(sNC));
109083 sNC.pParse = &sParse;
109084
109085 assert( pSelect->selFlags & SF_View );
109086 pSelect->selFlags &= ~SF_View;
109087 sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
109088 if( sParse.nErr ){
109089 rc = sParse.rc;
109090 }else{
109091 sqlite3WalkSelect(&sWalker, pTab->pSelect);
109092 }
109093 }
109094 }else{
109095 /* Modify any FK definitions to point to the new table. */
109096 #ifndef SQLITE_OMIT_FOREIGN_KEY
109097 if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){
 
 
109098 FKey *pFKey;
109099 for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
 
109100 if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
109101 renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
109102 }
109103 }
109104 }
@@ -109234,12 +109212,12 @@
109234 sWalker.xExprCallback = renameQuotefixExprCb;
109235 sWalker.xSelectCallback = renameColumnSelectCb;
109236 sWalker.u.pRename = &sCtx;
109237
109238 if( sParse.pNewTable ){
109239 Select *pSelect = sParse.pNewTable->pSelect;
109240 if( pSelect ){
109241 pSelect->selFlags &= ~SF_View;
109242 sParse.rc = SQLITE_OK;
109243 sqlite3SelectPrep(&sParse, pSelect, 0);
109244 rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
109245 if( rc==SQLITE_OK ){
@@ -109248,11 +109226,13 @@
109248 }else{
109249 int i;
109250 sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
109251 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
109252 for(i=0; i<sParse.pNewTable->nCol; i++){
109253 sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
 
 
109254 }
109255 #endif /* SQLITE_OMIT_GENERATED_COLUMNS */
109256 }
109257 }else if( sParse.pNewIndex ){
109258 sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
@@ -109331,15 +109311,15 @@
109331 int flags = db->flags;
109332 if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
109333 rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
109334 db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
109335 if( rc==SQLITE_OK ){
109336 if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
109337 NameContext sNC;
109338 memset(&sNC, 0, sizeof(sNC));
109339 sNC.pParse = &sParse;
109340 sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
109341 if( sParse.nErr ) rc = sParse.rc;
109342 }
109343
109344 else if( sParse.pNewTrigger ){
109345 if( isLegacy==0 ){
@@ -109406,17 +109386,18 @@
109406 /* This can happen if the sqlite_schema table is corrupt */
109407 rc = SQLITE_CORRUPT_BKPT;
109408 goto drop_column_done;
109409 }
109410
109411 pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zName);
109412 if( iCol<pTab->nCol-1 ){
109413 RenameToken *pEnd;
109414 pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName);
109415 zEnd = (const char*)pEnd->t.z;
109416 }else{
109417 zEnd = (const char*)&zSql[pTab->addColOffset];
 
109418 while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
109419 }
109420
109421 zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
109422 sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
@@ -109547,10 +109528,16 @@
109547 }else{
109548 sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
109549 }
109550 nField++;
109551 }
 
 
 
 
 
 
109552 }
109553 sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
109554 if( pPk ){
109555 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
109556 }else{
@@ -110552,11 +110539,11 @@
110552 if( NEVER(i==XN_ROWID) ){
110553 VdbeComment((v,"%s.rowid",pIdx->zName));
110554 }else if( i==XN_EXPR ){
110555 VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
110556 }else{
110557 VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zName));
110558 }
110559 }
110560 #else
110561 # define analyzeVdbeCommentIndexWithColumnName(a,b,c)
110562 #endif /* SQLITE_DEBUG */
@@ -112305,14 +112292,14 @@
112305 iCol = pExpr->iColumn;
112306 if( pTab==0 ) return;
112307
112308 if( iCol>=0 ){
112309 assert( iCol<pTab->nCol );
112310 zCol = pTab->aCol[iCol].zName;
112311 }else if( pTab->iPKey>=0 ){
112312 assert( pTab->iPKey<pTab->nCol );
112313 zCol = pTab->aCol[pTab->iPKey].zName;
112314 }else{
112315 zCol = "ROWID";
112316 }
112317 assert( iDb>=0 && iDb<pParse->db->nDb );
112318 if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
@@ -112686,24 +112673,26 @@
112686 }
112687
112688 /*
112689 ** Run the parser and code generator recursively in order to generate
112690 ** code for the SQL statement given onto the end of the pParse context
112691 ** currently under construction. When the parser is run recursively
112692 ** this way, the final OP_Halt is not appended and other initialization
112693 ** and finalization steps are omitted because those are handling by the
112694 ** outermost parser.
112695 **
112696 ** Not everything is nestable. This facility is designed to permit
112697 ** INSERT, UPDATE, and DELETE operations against the schema table. Use
112698 ** care if you decide to try to use this routine for some other purposes.
 
 
 
 
112699 */
112700 SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
112701 va_list ap;
112702 char *zSql;
112703 char *zErrMsg = 0;
112704 sqlite3 *db = pParse->db;
 
112705 char saveBuf[PARSE_TAIL_SZ];
112706
112707 if( pParse->nErr ) return;
112708 assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
112709 va_start(ap, zFormat);
@@ -112718,11 +112707,13 @@
112718 return;
112719 }
112720 pParse->nested++;
112721 memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
112722 memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
 
112723 sqlite3RunParser(pParse, zSql, &zErrMsg);
 
112724 sqlite3DbFree(db, zErrMsg);
112725 sqlite3DbFree(db, zSql);
112726 memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
112727 pParse->nested--;
112728 }
@@ -112854,10 +112845,11 @@
112854 Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
112855 if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
112856 pMod = sqlite3PragmaVtabRegister(db, zName);
112857 }
112858 if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
 
112859 return pMod->pEpoTab;
112860 }
112861 }
112862 #endif
112863 if( flags & LOCATE_NOERR ) return 0;
@@ -113066,10 +113058,88 @@
113066 ** This routine is called when a commit occurs.
113067 */
113068 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
113069 db->mDbFlags &= ~DBFLAG_SchemaChange;
113070 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113071
113072 /*
113073 ** Delete memory allocated for the column names of a table or view (the
113074 ** Table.aCol[] array).
113075 */
@@ -113077,16 +113147,24 @@
113077 int i;
113078 Column *pCol;
113079 assert( pTable!=0 );
113080 if( (pCol = pTable->aCol)!=0 ){
113081 for(i=0; i<pTable->nCol; i++, pCol++){
113082 assert( pCol->zName==0 || pCol->hName==sqlite3StrIHash(pCol->zName) );
113083 sqlite3DbFree(db, pCol->zName);
113084 sqlite3ExprDelete(db, pCol->pDflt);
113085 sqlite3DbFree(db, pCol->zColl);
113086 }
113087 sqlite3DbFree(db, pTable->aCol);
 
 
 
 
 
 
 
 
 
 
113088 }
113089 }
113090
113091 /*
113092 ** Remove the memory data structures associated with the given
@@ -113134,23 +113212,29 @@
113134 assert( pOld==pIndex || pOld==0 );
113135 }
113136 sqlite3FreeIndex(db, pIndex);
113137 }
113138
113139 /* Delete any foreign keys attached to this table. */
113140 sqlite3FkDelete(db, pTable);
 
 
 
 
 
 
 
 
 
 
113141
113142 /* Delete the Table structure itself.
113143 */
113144 sqlite3DeleteColumnNames(db, pTable);
113145 sqlite3DbFree(db, pTable->zName);
113146 sqlite3DbFree(db, pTable->zColAff);
113147 sqlite3SelectDelete(db, pTable->pSelect);
113148 sqlite3ExprListDelete(db, pTable->pCheck);
113149 #ifndef SQLITE_OMIT_VIRTUALTABLE
113150 sqlite3VtabClear(db, pTable);
113151 #endif
113152 sqlite3DbFree(db, pTable);
113153
113154 /* Verify that no lookaside memory was used by schema tables */
113155 assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
113156 }
@@ -113672,20 +113756,21 @@
113672 /* Normal (non-error) return. */
113673 return;
113674
113675 /* If an error occurs, we jump here */
113676 begin_table_error:
 
113677 sqlite3DbFree(db, zName);
113678 return;
113679 }
113680
113681 /* Set properties of a table column based on the (magical)
113682 ** name of the column.
113683 */
113684 #if SQLITE_ENABLE_HIDDEN_COLUMNS
113685 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
113686 if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
113687 pCol->colFlags |= COLFLAG_HIDDEN;
113688 if( pTab ) pTab->tabFlags |= TF_HasHidden;
113689 }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
113690 pTab->tabFlags |= TF_OOOHidden;
113691 }
@@ -113772,67 +113857,108 @@
113772 ** The parser calls this routine once for each column declaration
113773 ** in a CREATE TABLE statement. sqlite3StartTable() gets called
113774 ** first to get things going. Then this routine is called for each
113775 ** column.
113776 */
113777 SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
113778 Table *p;
113779 int i;
113780 char *z;
113781 char *zType;
113782 Column *pCol;
113783 sqlite3 *db = pParse->db;
113784 u8 hName;
 
 
 
 
113785
113786 if( (p = pParse->pNewTable)==0 ) return;
113787 if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
113788 sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
113789 return;
113790 }
113791 z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113792 if( z==0 ) return;
113793 if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName);
113794 memcpy(z, pName->z, pName->n);
113795 z[pName->n] = 0;
113796 sqlite3Dequote(z);
113797 hName = sqlite3StrIHash(z);
113798 for(i=0; i<p->nCol; i++){
113799 if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
113800 sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
113801 sqlite3DbFree(db, z);
113802 return;
113803 }
113804 }
113805 if( (p->nCol & 0x7)==0 ){
113806 Column *aNew;
113807 aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
113808 if( aNew==0 ){
113809 sqlite3DbFree(db, z);
113810 return;
113811 }
113812 p->aCol = aNew;
113813 }
113814 pCol = &p->aCol[p->nCol];
113815 memset(pCol, 0, sizeof(p->aCol[0]));
113816 pCol->zName = z;
113817 pCol->hName = hName;
113818 sqlite3ColumnPropertiesFromName(p, pCol);
113819
113820 if( pType->n==0 ){
113821 /* If there is no type specified, columns have the default affinity
113822 ** 'BLOB' with a default size of 4 bytes. */
113823 pCol->affinity = SQLITE_AFF_BLOB;
113824 pCol->szEst = 1;
 
113825 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
113826 if( 4>=sqlite3GlobalConfig.szSorterRef ){
113827 pCol->colFlags |= COLFLAG_SORTERREF;
 
 
113828 }
113829 #endif
113830 }else{
113831 zType = z + sqlite3Strlen30(z) + 1;
113832 memcpy(zType, pType->z, pType->n);
113833 zType[pType->n] = 0;
113834 sqlite3Dequote(zType);
113835 pCol->affinity = sqlite3AffinityType(zType, pCol);
113836 pCol->colFlags |= COLFLAG_HASTYPE;
113837 }
113838 p->nCol++;
@@ -113983,11 +114109,11 @@
113983 if( p!=0 ){
113984 int isInit = db->init.busy && db->init.iDb!=1;
113985 pCol = &(p->aCol[p->nCol-1]);
113986 if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
113987 sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
113988 pCol->zName);
113989 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
113990 }else if( pCol->colFlags & COLFLAG_GENERATED ){
113991 testcase( pCol->colFlags & COLFLAG_VIRTUAL );
113992 testcase( pCol->colFlags & COLFLAG_STORED );
113993 sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
@@ -113994,19 +114120,19 @@
113994 #endif
113995 }else{
113996 /* A copy of pExpr is used instead of the original, as pExpr contains
113997 ** tokens that point to volatile memory.
113998 */
113999 Expr x;
114000 sqlite3ExprDelete(db, pCol->pDflt);
114001 memset(&x, 0, sizeof(x));
114002 x.op = TK_SPAN;
114003 x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
114004 x.pLeft = pExpr;
114005 x.flags = EP_Skip;
114006 pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
114007 sqlite3DbFree(db, x.u.zToken);
 
114008 }
114009 }
114010 if( IN_RENAME_OBJECT ){
114011 sqlite3RenameExprUnmap(pParse, pExpr);
114012 }
@@ -114100,11 +114226,11 @@
114100 assert( pCExpr!=0 );
114101 sqlite3StringToId(pCExpr);
114102 if( pCExpr->op==TK_ID ){
114103 const char *zCName = pCExpr->u.zToken;
114104 for(iCol=0; iCol<pTab->nCol; iCol++){
114105 if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
114106 pCol = &pTab->aCol[iCol];
114107 makeColumnPartOfPrimaryKey(pParse, pCol);
114108 break;
114109 }
114110 }
@@ -114111,11 +114237,11 @@
114111 }
114112 }
114113 }
114114 if( nTerm==1
114115 && pCol
114116 && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
114117 && sortOrder!=SQLITE_SO_DESC
114118 ){
114119 if( IN_RENAME_OBJECT && pList ){
114120 Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr);
114121 sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr);
@@ -114191,26 +114317,24 @@
114191 zColl = sqlite3NameFromToken(db, pToken);
114192 if( !zColl ) return;
114193
114194 if( sqlite3LocateCollSeq(pParse, zColl) ){
114195 Index *pIdx;
114196 sqlite3DbFree(db, p->aCol[i].zColl);
114197 p->aCol[i].zColl = zColl;
114198
114199 /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
114200 ** then an index may have been created on this column before the
114201 ** collation type was added. Correct this if it is the case.
114202 */
114203 for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
114204 assert( pIdx->nKeyCol==1 );
114205 if( pIdx->aiColumn[0]==i ){
114206 pIdx->azColl[0] = p->aCol[i].zColl;
114207 }
114208 }
114209 }else{
114210 sqlite3DbFree(db, zColl);
114211 }
 
114212 }
114213
114214 /* Change the most recently parsed column to be a GENERATED ALWAYS AS
114215 ** column.
114216 */
@@ -114226,11 +114350,11 @@
114226 pCol = &(pTab->aCol[pTab->nCol-1]);
114227 if( IN_DECLARE_VTAB ){
114228 sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
114229 goto generated_done;
114230 }
114231 if( pCol->pDflt ) goto generated_error;
114232 if( pType ){
114233 if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
114234 /* no-op */
114235 }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
114236 eType = COLFLAG_STORED;
@@ -114244,17 +114368,17 @@
114244 assert( TF_HasStored==COLFLAG_STORED );
114245 pTab->tabFlags |= eType;
114246 if( pCol->colFlags & COLFLAG_PRIMKEY ){
114247 makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
114248 }
114249 pCol->pDflt = pExpr;
114250 pExpr = 0;
114251 goto generated_done;
114252
114253 generated_error:
114254 sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
114255 pCol->zName);
114256 generated_done:
114257 sqlite3ExprDelete(pParse->db, pExpr);
114258 #else
114259 /* Throw and error for the GENERATED ALWAYS AS clause if the
114260 ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
@@ -114352,11 +114476,11 @@
114352 char *zStmt;
114353 char *zSep, *zSep2, *zEnd;
114354 Column *pCol;
114355 n = 0;
114356 for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
114357 n += identLength(pCol->zName) + 5;
114358 }
114359 n += identLength(p->zName);
114360 if( n<50 ){
114361 zSep = "";
114362 zSep2 = ",";
@@ -114388,11 +114512,11 @@
114388 const char *zType;
114389
114390 sqlite3_snprintf(n-k, &zStmt[k], zSep);
114391 k += sqlite3Strlen30(&zStmt[k]);
114392 zSep = zSep2;
114393 identPut(zStmt, &k, pCol->zName);
114394 assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
114395 assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
114396 testcase( pCol->affinity==SQLITE_AFF_BLOB );
114397 testcase( pCol->affinity==SQLITE_AFF_TEXT );
114398 testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
@@ -114607,11 +114731,11 @@
114607 ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
114608 */
114609 if( pTab->iPKey>=0 ){
114610 ExprList *pList;
114611 Token ipkToken;
114612 sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
114613 pList = sqlite3ExprListAppend(pParse, 0,
114614 sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
114615 if( pList==0 ){
114616 pTab->tabFlags &= ~TF_WithoutRowid;
114617 return;
@@ -114737,11 +114861,11 @@
114737
114738 if( !IsVirtual(pTab) ) return 0;
114739 nName = sqlite3Strlen30(pTab->zName);
114740 if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
114741 if( zName[nName]!='_' ) return 0;
114742 pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
114743 if( pMod==0 ) return 0;
114744 if( pMod->pModule->iVersion<3 ) return 0;
114745 if( pMod->pModule->xShadowName==0 ) return 0;
114746 return pMod->pModule->xShadowName(zName+nName+1);
114747 }
@@ -114898,22 +115022,22 @@
114898 testcase( p->tabFlags & TF_HasVirtual );
114899 testcase( p->tabFlags & TF_HasStored );
114900 for(ii=0; ii<p->nCol; ii++){
114901 u32 colFlags = p->aCol[ii].colFlags;
114902 if( (colFlags & COLFLAG_GENERATED)!=0 ){
114903 Expr *pX = p->aCol[ii].pDflt;
114904 testcase( colFlags & COLFLAG_VIRTUAL );
114905 testcase( colFlags & COLFLAG_STORED );
114906 if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
114907 /* If there are errors in resolving the expression, change the
114908 ** expression to a NULL. This prevents code generators that operate
114909 ** on the expression from inserting extra parts into the expression
114910 ** tree that have been allocated from lookaside memory, which is
114911 ** illegal in a schema and will lead to errors or heap corruption
114912 ** when the database connection closes. */
114913 sqlite3ExprDelete(db, pX);
114914 p->aCol[ii].pDflt = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
114915 }
114916 }else{
114917 nNG++;
114918 }
114919 }
@@ -114949,11 +115073,11 @@
114949 sqlite3VdbeAddOp1(v, OP_Close, 0);
114950
114951 /*
114952 ** Initialize zType for the new view or table.
114953 */
114954 if( p->pSelect==0 ){
114955 /* A regular table */
114956 zType = "table";
114957 zType2 = "TABLE";
114958 #ifndef SQLITE_OMIT_VIEW
114959 }else{
@@ -115099,16 +115223,16 @@
115099 }
115100 #endif
115101 }
115102
115103 #ifndef SQLITE_OMIT_ALTERTABLE
115104 if( !pSelect && !p->pSelect ){
115105 assert( pCons && pEnd );
115106 if( pCons->z==0 ){
115107 pCons = pEnd;
115108 }
115109 p->addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
115110 }
115111 #endif
115112 }
115113
115114 #ifndef SQLITE_OMIT_VIEW
@@ -115161,16 +115285,17 @@
115161 ** allocated rather than point to the input string - which means that
115162 ** they will persist after the current sqlite3_exec() call returns.
115163 */
115164 pSelect->selFlags |= SF_View;
115165 if( IN_RENAME_OBJECT ){
115166 p->pSelect = pSelect;
115167 pSelect = 0;
115168 }else{
115169 p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
115170 }
115171 p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
 
115172 if( db->mallocFailed ) goto create_view_fail;
115173
115174 /* Locate the end of the CREATE VIEW statement. Make sEnd point to
115175 ** the end.
115176 */
@@ -115263,12 +115388,12 @@
115263 ** "*" elements in the results set of the view and will assign cursors
115264 ** to the elements of the FROM clause. But we do not want these changes
115265 ** to be permanent. So the computation is done on a copy of the SELECT
115266 ** statement that defines the view.
115267 */
115268 assert( pTable->pSelect );
115269 pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
115270 if( pSel ){
115271 u8 eParseMode = pParse->eParseMode;
115272 pParse->eParseMode = PARSE_MODE_NORMAL;
115273 n = pParse->nTab;
115274 sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
@@ -115323,12 +115448,10 @@
115323 nErr++;
115324 }
115325 pTable->pSchema->schemaFlags |= DB_UnresetViews;
115326 if( db->mallocFailed ){
115327 sqlite3DeleteColumnNames(db, pTable);
115328 pTable->aCol = 0;
115329 pTable->nCol = 0;
115330 }
115331 #endif /* SQLITE_OMIT_VIEW */
115332 return nErr;
115333 }
115334 #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -115341,14 +115464,12 @@
115341 HashElem *i;
115342 assert( sqlite3SchemaMutexHeld(db, idx, 0) );
115343 if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
115344 for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
115345 Table *pTab = sqliteHashData(i);
115346 if( pTab->pSelect ){
115347 sqlite3DeleteColumnNames(db, pTab);
115348 pTab->aCol = 0;
115349 pTab->nCol = 0;
115350 }
115351 }
115352 DbClearProperty(db, idx, DB_UnresetViews);
115353 }
115354 #else
@@ -115581,10 +115702,11 @@
115581 SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){
115582 #ifndef SQLITE_OMIT_VIRTUALTABLE
115583 if( (db->flags & SQLITE_Defensive)!=0
115584 && db->pVtabCtx==0
115585 && db->nVdbeExec==0
 
115586 ){
115587 return 1;
115588 }
115589 #endif
115590 return 0;
@@ -115684,15 +115806,15 @@
115684
115685 #ifndef SQLITE_OMIT_VIEW
115686 /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
115687 ** on a table.
115688 */
115689 if( isView && pTab->pSelect==0 ){
115690 sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
115691 goto exit_drop_table;
115692 }
115693 if( !isView && pTab->pSelect ){
115694 sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
115695 goto exit_drop_table;
115696 }
115697 #endif
115698
@@ -115752,11 +115874,11 @@
115752 int iCol = p->nCol-1;
115753 if( NEVER(iCol<0) ) goto fk_end;
115754 if( pToCol && pToCol->nExpr!=1 ){
115755 sqlite3ErrorMsg(pParse, "foreign key on %s"
115756 " should reference only one column of table %T",
115757 p->aCol[iCol].zName, pTo);
115758 goto fk_end;
115759 }
115760 nCol = 1;
115761 }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
115762 sqlite3ErrorMsg(pParse,
@@ -115775,11 +115897,11 @@
115775 pFKey = sqlite3DbMallocZero(db, nByte );
115776 if( pFKey==0 ){
115777 goto fk_end;
115778 }
115779 pFKey->pFrom = p;
115780 pFKey->pNextFrom = p->pFKey;
115781 z = (char*)&pFKey->aCol[nCol];
115782 pFKey->zTo = z;
115783 if( IN_RENAME_OBJECT ){
115784 sqlite3RenameTokenMap(pParse, (void*)z, pTo);
115785 }
@@ -115792,11 +115914,11 @@
115792 pFKey->aCol[0].iFrom = p->nCol-1;
115793 }else{
115794 for(i=0; i<nCol; i++){
115795 int j;
115796 for(j=0; j<p->nCol; j++){
115797 if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
115798 pFKey->aCol[i].iFrom = j;
115799 break;
115800 }
115801 }
115802 if( j>=p->nCol ){
@@ -115840,11 +115962,12 @@
115840 pNextTo->pPrevTo = pFKey;
115841 }
115842
115843 /* Link the foreign key to the table as the last step.
115844 */
115845 p->pFKey = pFKey;
 
115846 pFKey = 0;
115847
115848 fk_end:
115849 sqlite3DbFree(db, pFKey);
115850 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
@@ -115861,11 +115984,13 @@
115861 */
115862 SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
115863 #ifndef SQLITE_OMIT_FOREIGN_KEY
115864 Table *pTab;
115865 FKey *pFKey;
115866 if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
 
 
115867 assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
115868 pFKey->isDeferred = (u8)isDeferred;
115869 #endif
115870 }
115871
@@ -116153,11 +116278,11 @@
116153 ){
116154 sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
116155 goto exit_create_index;
116156 }
116157 #ifndef SQLITE_OMIT_VIEW
116158 if( pTab->pSelect ){
116159 sqlite3ErrorMsg(pParse, "views may not be indexed");
116160 goto exit_create_index;
116161 }
116162 #endif
116163 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -116244,11 +116369,11 @@
116244 */
116245 if( pList==0 ){
116246 Token prevCol;
116247 Column *pCol = &pTab->aCol[pTab->nCol-1];
116248 pCol->colFlags |= COLFLAG_UNIQUE;
116249 sqlite3TokenInit(&prevCol, pCol->zName);
116250 pList = sqlite3ExprListAppend(pParse, 0,
116251 sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
116252 if( pList==0 ) goto exit_create_index;
116253 assert( pList->nExpr==1 );
116254 sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
@@ -116365,11 +116490,11 @@
116365 memcpy(zExtra, zColl, nColl);
116366 zColl = zExtra;
116367 zExtra += nColl;
116368 nExtra -= nColl;
116369 }else if( j>=0 ){
116370 zColl = pTab->aCol[j].zColl;
116371 }
116372 if( !zColl ) zColl = sqlite3StrBINARY;
116373 if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
116374 goto exit_create_index;
116375 }
@@ -117457,11 +117582,11 @@
117457 sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
117458 }else{
117459 for(j=0; j<pIdx->nKeyCol; j++){
117460 char *zCol;
117461 assert( pIdx->aiColumn[j]>=0 );
117462 zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
117463 if( j ) sqlite3_str_append(&errMsg, ", ", 2);
117464 sqlite3_str_appendall(&errMsg, pTab->zName);
117465 sqlite3_str_append(&errMsg, ".", 1);
117466 sqlite3_str_appendall(&errMsg, zCol);
117467 }
@@ -117484,11 +117609,11 @@
117484 ){
117485 char *zMsg;
117486 int rc;
117487 if( pTab->iPKey>=0 ){
117488 zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
117489 pTab->aCol[pTab->iPKey].zName);
117490 rc = SQLITE_CONSTRAINT_PRIMARYKEY;
117491 }else{
117492 zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
117493 rc = SQLITE_CONSTRAINT_ROWID;
117494 }
@@ -118411,11 +118536,11 @@
118411 if( tabIsReadOnly(pParse, pTab) ){
118412 sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
118413 return 1;
118414 }
118415 #ifndef SQLITE_OMIT_VIEW
118416 if( !viewOk && pTab->pSelect ){
118417 sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
118418 return 1;
118419 }
118420 #endif
118421 return 0;
@@ -118515,17 +118640,17 @@
118515 pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
118516 );
118517 }else{
118518 Index *pPk = sqlite3PrimaryKeyIndex(pTab);
118519 if( pPk->nKeyCol==1 ){
118520 const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
118521 pLhs = sqlite3Expr(db, TK_ID, zName);
118522 pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
118523 }else{
118524 int i;
118525 for(i=0; i<pPk->nKeyCol; i++){
118526 Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
118527 pEList = sqlite3ExprListAppend(pParse, pEList, p);
118528 }
118529 pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
118530 if( pLhs ){
118531 pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
@@ -118628,11 +118753,11 @@
118628 /* Figure out if we have any triggers and if the table being
118629 ** deleted from is a view
118630 */
118631 #ifndef SQLITE_OMIT_TRIGGER
118632 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
118633 isView = pTab->pSelect!=0;
118634 #else
118635 # define pTrigger 0
118636 # define isView 0
118637 #endif
118638 bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
@@ -118878,11 +119003,11 @@
118878 ** where-clause loop above.
118879 */
118880 if( eOnePass!=ONEPASS_OFF ){
118881 assert( nKey==nPk ); /* OP_Found will use an unpacked key */
118882 if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
118883 assert( pPk!=0 || pTab->pSelect!=0 );
118884 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
118885 VdbeCoverage(v);
118886 }
118887 }else if( pPk ){
118888 addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
@@ -119112,11 +119237,11 @@
119112 ** invoke the update-hook. The pre-update-hook, on the other hand should
119113 ** be invoked unless table pTab is a system table. The difference is that
119114 ** the update-hook is not invoked for rows removed by REPLACE, but the
119115 ** pre-update-hook is.
119116 */
119117 if( pTab->pSelect==0 ){
119118 u8 p5 = 0;
119119 sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
119120 sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
119121 if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
119122 sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
@@ -119873,37 +119998,37 @@
119873
119874 /*
119875 ** Implementation of the changes() SQL function.
119876 **
119877 ** IMP: R-62073-11209 The changes() SQL function is a wrapper
119878 ** around the sqlite3_changes() C/C++ function and hence follows the same
119879 ** rules for counting changes.
119880 */
119881 static void changes(
119882 sqlite3_context *context,
119883 int NotUsed,
119884 sqlite3_value **NotUsed2
119885 ){
119886 sqlite3 *db = sqlite3_context_db_handle(context);
119887 UNUSED_PARAMETER2(NotUsed, NotUsed2);
119888 sqlite3_result_int(context, sqlite3_changes(db));
119889 }
119890
119891 /*
119892 ** Implementation of the total_changes() SQL function. The return value is
119893 ** the same as the sqlite3_total_changes() API function.
119894 */
119895 static void total_changes(
119896 sqlite3_context *context,
119897 int NotUsed,
119898 sqlite3_value **NotUsed2
119899 ){
119900 sqlite3 *db = sqlite3_context_db_handle(context);
119901 UNUSED_PARAMETER2(NotUsed, NotUsed2);
119902 /* IMP: R-52756-41993 This function is a wrapper around the
119903 ** sqlite3_total_changes() C/C++ interface. */
119904 sqlite3_result_int(context, sqlite3_total_changes(db));
119905 }
119906
119907 /*
119908 ** A structure defining how to do GLOB-style comparisons.
119909 */
@@ -120617,29 +120742,29 @@
120617 int argc,
120618 sqlite3_value **argv
120619 ){
120620 const unsigned char *zIn; /* Input string */
120621 const unsigned char *zCharSet; /* Set of characters to trim */
120622 int nIn; /* Number of bytes in input */
120623 int flags; /* 1: trimleft 2: trimright 3: trim */
120624 int i; /* Loop counter */
120625 unsigned char *aLen = 0; /* Length of each character in zCharSet */
120626 unsigned char **azChar = 0; /* Individual characters in zCharSet */
120627 int nChar; /* Number of characters in zCharSet */
120628
120629 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
120630 return;
120631 }
120632 zIn = sqlite3_value_text(argv[0]);
120633 if( zIn==0 ) return;
120634 nIn = sqlite3_value_bytes(argv[0]);
120635 assert( zIn==sqlite3_value_text(argv[0]) );
120636 if( argc==1 ){
120637 static const unsigned char lenOne[] = { 1 };
120638 static unsigned char * const azOne[] = { (u8*)" " };
120639 nChar = 1;
120640 aLen = (u8*)lenOne;
120641 azChar = (unsigned char **)azOne;
120642 zCharSet = 0;
120643 }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
120644 return;
120645 }else{
@@ -120646,27 +120771,28 @@
120646 const unsigned char *z;
120647 for(z=zCharSet, nChar=0; *z; nChar++){
120648 SQLITE_SKIP_UTF8(z);
120649 }
120650 if( nChar>0 ){
120651 azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
 
120652 if( azChar==0 ){
120653 return;
120654 }
120655 aLen = (unsigned char*)&azChar[nChar];
120656 for(z=zCharSet, nChar=0; *z; nChar++){
120657 azChar[nChar] = (unsigned char *)z;
120658 SQLITE_SKIP_UTF8(z);
120659 aLen[nChar] = (u8)(z - azChar[nChar]);
120660 }
120661 }
120662 }
120663 if( nChar>0 ){
120664 flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
120665 if( flags & 1 ){
120666 while( nIn>0 ){
120667 int len = 0;
120668 for(i=0; i<nChar; i++){
120669 len = aLen[i];
120670 if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
120671 }
120672 if( i>=nChar ) break;
@@ -120674,11 +120800,11 @@
120674 nIn -= len;
120675 }
120676 }
120677 if( flags & 2 ){
120678 while( nIn>0 ){
120679 int len = 0;
120680 for(i=0; i<nChar; i++){
120681 len = aLen[i];
120682 if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
120683 }
120684 if( i>=nChar ) break;
@@ -121460,15 +121586,15 @@
121460 FUNCTION(trim, 1, 3, 0, trimFunc ),
121461 FUNCTION(trim, 2, 3, 0, trimFunc ),
121462 FUNCTION(min, -1, 0, 1, minmaxFunc ),
121463 FUNCTION(min, 0, 0, 1, 0 ),
121464 WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
121465 SQLITE_FUNC_MINMAX ),
121466 FUNCTION(max, -1, 1, 1, minmaxFunc ),
121467 FUNCTION(max, 0, 1, 1, 0 ),
121468 WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
121469 SQLITE_FUNC_MINMAX ),
121470 FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
121471 FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
121472 FUNCTION(instr, 2, 0, 0, instrFunc ),
121473 FUNCTION(printf, -1, 0, 0, printfFunc ),
121474 FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
@@ -121500,13 +121626,14 @@
121500 FUNCTION(substring, 3, 0, 0, substrFunc ),
121501 WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
121502 WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
121503 WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
121504 WAGGREGATE(count, 0,0,0, countStep,
121505 countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
 
121506 WAGGREGATE(count, 1,0,0, countStep,
121507 countFinalize, countFinalize, countInverse, 0 ),
121508 WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
121509 groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
121510 WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
121511 groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
121512
@@ -121804,11 +121931,13 @@
121804 ** 2) The FK is explicitly mapped to a column declared as INTEGER
121805 ** PRIMARY KEY.
121806 */
121807 if( pParent->iPKey>=0 ){
121808 if( !zKey ) return 0;
121809 if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
 
 
121810 }
121811 }else if( paiCol ){
121812 assert( nCol>1 );
121813 aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
121814 if( !aiCol ) return 1;
@@ -121846,15 +121975,15 @@
121846 if( iCol<0 ) break; /* No foreign keys against expression indexes */
121847
121848 /* If the index uses a collation sequence that is different from
121849 ** the default collation sequence for the column, this index is
121850 ** unusable. Bail out early in this case. */
121851 zDfltColl = pParent->aCol[iCol].zColl;
121852 if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
121853 if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
121854
121855 zIdxCol = pParent->aCol[iCol].zName;
121856 for(j=0; j<nCol; j++){
121857 if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
121858 if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
121859 break;
121860 }
@@ -122074,11 +122203,11 @@
122074 if( pExpr ){
122075 if( iCol>=0 && iCol!=pTab->iPKey ){
122076 pCol = &pTab->aCol[iCol];
122077 pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
122078 pExpr->affExpr = pCol->affinity;
122079 zColl = pCol->zColl;
122080 if( zColl==0 ) zColl = db->pDfltColl->zName;
122081 pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
122082 }else{
122083 pExpr->iTable = regBase;
122084 pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -122183,11 +122312,11 @@
122183
122184 iCol = pIdx ? pIdx->aiColumn[i] : -1;
122185 pLeft = exprTableRegister(pParse, pTab, regData, iCol);
122186 iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
122187 assert( iCol>=0 );
122188 zCol = pFKey->pFrom->aCol[iCol].zName;
122189 pRight = sqlite3Expr(db, TK_ID, zCol);
122190 pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
122191 pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
122192 }
122193
@@ -122218,11 +122347,11 @@
122218 assert( pIdx!=0 );
122219 for(i=0; i<pIdx->nKeyCol; i++){
122220 i16 iCol = pIdx->aiColumn[i];
122221 assert( iCol>=0 );
122222 pLeft = exprTableRegister(pParse, pTab, regData, iCol);
122223 pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
122224 pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
122225 pAll = sqlite3ExprAnd(pParse, pAll, pEq);
122226 }
122227 pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
122228 }
@@ -122312,19 +122441,20 @@
122312 if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
122313 int iSkip = 0;
122314 Vdbe *v = sqlite3GetVdbe(pParse);
122315
122316 assert( v ); /* VDBE has already been allocated */
122317 assert( pTab->pSelect==0 ); /* Not a view */
 
122318 if( sqlite3FkReferences(pTab)==0 ){
122319 /* Search for a deferred foreign key constraint for which this table
122320 ** is the child table. If one cannot be found, return without
122321 ** generating any VDBE code. If one can be found, then jump over
122322 ** the entire DELETE if there are no outstanding deferred constraints
122323 ** when this statement is run. */
122324 FKey *p;
122325 for(p=pTab->pFKey; p; p=p->pNextFrom){
122326 if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
122327 }
122328 if( !p ) return;
122329 iSkip = sqlite3VdbeMakeLabel(pParse);
122330 sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
@@ -122409,11 +122539,11 @@
122409 int iKey;
122410 for(iKey=0; iKey<pTab->nCol; iKey++){
122411 if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
122412 Column *pCol = &pTab->aCol[iKey];
122413 if( zKey ){
122414 if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
122415 }else if( pCol->colFlags & COLFLAG_PRIMKEY ){
122416 return 1;
122417 }
122418 }
122419 }
@@ -122482,11 +122612,12 @@
122482 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
122483 zDb = db->aDb[iDb].zDbSName;
122484
122485 /* Loop through all the foreign key constraints for which pTab is the
122486 ** child table (the table that the foreign key definition is part of). */
122487 for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
 
122488 Table *pTo; /* Parent table of foreign key pFKey */
122489 Index *pIdx = 0; /* Index on key columns in pTo */
122490 int *aiFree = 0;
122491 int *aiCol;
122492 int iCol;
@@ -122549,11 +122680,11 @@
122549 /* Request permission to read the parent key columns. If the
122550 ** authorization callback returns SQLITE_IGNORE, behave as if any
122551 ** values read from the parent table are NULL. */
122552 if( db->xAuth ){
122553 int rcauth;
122554 char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
122555 rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
122556 bIgnore = (rcauth==SQLITE_IGNORE);
122557 }
122558 #endif
122559 }
@@ -122667,11 +122798,12 @@
122667 ){
122668 u32 mask = 0;
122669 if( pParse->db->flags&SQLITE_ForeignKeys ){
122670 FKey *p;
122671 int i;
122672 for(p=pTab->pFKey; p; p=p->pNextFrom){
 
122673 for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
122674 }
122675 for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
122676 Index *pIdx = 0;
122677 sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
@@ -122717,23 +122849,23 @@
122717 int *aChange, /* Non-NULL for UPDATE operations */
122718 int chngRowid /* True for UPDATE that affects rowid */
122719 ){
122720 int eRet = 1; /* Value to return if bHaveFK is true */
122721 int bHaveFK = 0; /* If FK processing is required */
122722 if( pParse->db->flags&SQLITE_ForeignKeys ){
122723 if( !aChange ){
122724 /* A DELETE operation. Foreign key processing is required if the
122725 ** table in question is either the child or parent table for any
122726 ** foreign key constraint. */
122727 bHaveFK = (sqlite3FkReferences(pTab) || pTab->pFKey);
122728 }else{
122729 /* This is an UPDATE. Foreign key processing is only required if the
122730 ** operation modifies one or more child or parent key columns. */
122731 FKey *p;
122732
122733 /* Check if any child key columns are being modified. */
122734 for(p=pTab->pFKey; p; p=p->pNextFrom){
122735 if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
122736 if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
122737 bHaveFK = 1;
122738 }
122739 }
@@ -122822,12 +122954,12 @@
122822 iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
122823 assert( iFromCol>=0 );
122824 assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
122825 assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
122826 sqlite3TokenInit(&tToCol,
122827 pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
122828 sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
122829
122830 /* Create the expression "OLD.zToCol = zFromCol". It is important
122831 ** that the "OLD.zToCol" term is on the LHS of the = operator, so
122832 ** that the affinity and collation sequence associated with the
122833 ** parent table are used for the comparison. */
@@ -122868,11 +123000,11 @@
122868 if( pCol->colFlags & COLFLAG_GENERATED ){
122869 testcase( pCol->colFlags & COLFLAG_VIRTUAL );
122870 testcase( pCol->colFlags & COLFLAG_STORED );
122871 pDflt = 0;
122872 }else{
122873 pDflt = pCol->pDflt;
122874 }
122875 if( pDflt ){
122876 pNew = sqlite3ExprDup(db, pDflt, 0);
122877 }else{
122878 pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
@@ -123005,13 +123137,13 @@
123005 */
123006 SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
123007 FKey *pFKey; /* Iterator variable */
123008 FKey *pNext; /* Copy of pFKey->pNextFrom */
123009
123010 assert( db==0 || IsVirtual(pTab)
123011 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
123012 for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
123013
123014 /* Remove the FK from the fkeyHash hash table. */
123015 if( !db || db->pnBytesFreed==0 ){
123016 if( pFKey->pPrevTo ){
123017 pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
@@ -123157,11 +123289,11 @@
123157
123158 /*
123159 ** Compute the affinity string for table pTab, if it has not already been
123160 ** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
123161 **
123162 ** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
123163 ** if iReg>0 then code an OP_Affinity opcode that will set the affinities
123164 ** for register iReg and following. Or if affinities exists and iReg==0,
123165 ** then just set the P4 operand of the previous opcode (which should be
123166 ** an OP_MakeRecord) to the affinity string.
123167 **
@@ -123337,26 +123469,26 @@
123337 Column *pCol = pTab->aCol + i;
123338 if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){
123339 int x;
123340 pCol->colFlags |= COLFLAG_BUSY;
123341 w.eCode = 0;
123342 sqlite3WalkExpr(&w, pCol->pDflt);
123343 pCol->colFlags &= ~COLFLAG_BUSY;
123344 if( w.eCode & COLFLAG_NOTAVAIL ){
123345 pRedo = pCol;
123346 continue;
123347 }
123348 eProgress = 1;
123349 assert( pCol->colFlags & COLFLAG_GENERATED );
123350 x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
123351 sqlite3ExprCodeGeneratedColumn(pParse, pCol, x);
123352 pCol->colFlags &= ~COLFLAG_NOTAVAIL;
123353 }
123354 }
123355 }while( pRedo && eProgress );
123356 if( pRedo ){
123357 sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zName);
123358 }
123359 pParse->iSelfTab = 0;
123360 }
123361 #endif /* SQLITE_OMIT_GENERATED_COLUMNS */
123362
@@ -123747,11 +123879,11 @@
123747 /* Figure out if we have any triggers and if the table being
123748 ** inserted into is a view
123749 */
123750 #ifndef SQLITE_OMIT_TRIGGER
123751 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
123752 isView = pTab->pSelect!=0;
123753 #else
123754 # define pTrigger 0
123755 # define tmask 0
123756 # define isView 0
123757 #endif
@@ -123838,21 +123970,21 @@
123838 for(i=0; i<pColumn->nId; i++){
123839 pColumn->a[i].idx = -1;
123840 }
123841 for(i=0; i<pColumn->nId; i++){
123842 for(j=0; j<pTab->nCol; j++){
123843 if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
123844 pColumn->a[i].idx = j;
123845 if( i!=j ) bIdListInOrder = 0;
123846 if( j==pTab->iPKey ){
123847 ipkColumn = i; assert( !withoutRowid );
123848 }
123849 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
123850 if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
123851 sqlite3ErrorMsg(pParse,
123852 "cannot INSERT into generated column \"%s\"",
123853 pTab->aCol[j].zName);
123854 goto insert_cleanup;
123855 }
123856 #endif
123857 break;
123858 }
@@ -124033,11 +124165,11 @@
124033 if( IsVirtual(pTab) ){
124034 sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
124035 pTab->zName);
124036 goto insert_cleanup;
124037 }
124038 if( pTab->pSelect ){
124039 sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
124040 goto insert_cleanup;
124041 }
124042 if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
124043 goto insert_cleanup;
@@ -124132,26 +124264,32 @@
124132 }
124133 continue;
124134 }else if( pColumn==0 ){
124135 /* Hidden columns that are not explicitly named in the INSERT
124136 ** get there default value */
124137 sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
 
 
124138 continue;
124139 }
124140 }
124141 if( pColumn ){
124142 for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
124143 if( j>=pColumn->nId ){
124144 /* A column not named in the insert column list gets its
124145 ** default value */
124146 sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
 
 
124147 continue;
124148 }
124149 k = j;
124150 }else if( nColumn==0 ){
124151 /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
124152 sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
 
 
124153 continue;
124154 }else{
124155 k = i - nHidden;
124156 }
124157
@@ -124662,11 +124800,11 @@
124662
124663 isUpdate = regOldData!=0;
124664 db = pParse->db;
124665 v = pParse->pVdbe;
124666 assert( v!=0 );
124667 assert( pTab->pSelect==0 ); /* This table is not a VIEW */
124668 nCol = pTab->nCol;
124669
124670 /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
124671 ** normal rowid tables. nPkField is the number of key fields in the
124672 ** pPk index or 1 for a rowid table. In other words, nPkField is the
@@ -124713,11 +124851,11 @@
124713 }else if( onError==OE_Default ){
124714 onError = OE_Abort;
124715 }
124716 if( onError==OE_Replace ){
124717 if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
124718 || pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
124719 ){
124720 testcase( pCol->colFlags & COLFLAG_VIRTUAL );
124721 testcase( pCol->colFlags & COLFLAG_STORED );
124722 testcase( pCol->colFlags & COLFLAG_GENERATED );
124723 onError = OE_Abort;
@@ -124735,21 +124873,22 @@
124735 case OE_Replace: {
124736 int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
124737 VdbeCoverage(v);
124738 assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
124739 nSeenReplace++;
124740 sqlite3ExprCodeCopy(pParse, pCol->pDflt, iReg);
 
124741 sqlite3VdbeJumpHere(v, addr1);
124742 break;
124743 }
124744 case OE_Abort:
124745 sqlite3MayAbort(pParse);
124746 /* no break */ deliberate_fall_through
124747 case OE_Rollback:
124748 case OE_Fail: {
124749 char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
124750 pCol->zName);
124751 sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
124752 onError, iReg);
124753 sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
124754 sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
124755 VdbeCoverage(v);
@@ -125163,11 +125302,11 @@
125163 VdbeComment((v, "rowid"));
125164 }else{
125165 testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
125166 x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
125167 sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
125168 VdbeComment((v, "%s", pTab->aCol[iField].zName));
125169 }
125170 }
125171 sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
125172 VdbeComment((v, "for %s", pIdx->zName));
125173 #ifdef SQLITE_ENABLE_NULL_TRIM
@@ -125222,11 +125361,11 @@
125222 && pPk==pIdx /* Condition 2 */
125223 && onError==OE_Replace /* Condition 1 */
125224 && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
125225 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
125226 && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
125227 (0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
125228 ){
125229 sqlite3VdbeResolveLabel(v, addrUniqueOk);
125230 continue;
125231 }
125232 #endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -125257,11 +125396,11 @@
125257 for(i=0; i<pPk->nKeyCol; i++){
125258 assert( pPk->aiColumn[i]>=0 );
125259 x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
125260 sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
125261 VdbeComment((v, "%s.%s", pTab->zName,
125262 pTab->aCol[pPk->aiColumn[i]].zName));
125263 }
125264 }
125265 if( isUpdate ){
125266 /* If currently processing the PRIMARY KEY of a WITHOUT ROWID
125267 ** table, only conflict if the new PRIMARY KEY values are actually
@@ -125456,11 +125595,11 @@
125456 /* Records with omitted columns are only allowed for schema format
125457 ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
125458 if( pTab->pSchema->file_format<2 ) return;
125459
125460 for(i=pTab->nCol-1; i>0; i--){
125461 if( pTab->aCol[i].pDflt!=0 ) break;
125462 if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
125463 }
125464 sqlite3VdbeChangeP5(v, i+1);
125465 }
125466 #endif
@@ -125521,11 +125660,11 @@
125521 || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
125522 );
125523
125524 v = pParse->pVdbe;
125525 assert( v!=0 );
125526 assert( pTab->pSelect==0 ); /* This table is not a VIEW */
125527 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
125528 /* All REPLACE indexes are at the end of the list */
125529 assert( pIdx->onError!=OE_Replace
125530 || pIdx->pNext==0
125531 || pIdx->pNext->onError==OE_Replace );
@@ -125823,17 +125962,12 @@
125823 return 0; /* tab1 and tab2 may not be the same table */
125824 }
125825 if( HasRowid(pDest)!=HasRowid(pSrc) ){
125826 return 0; /* source and destination must both be WITHOUT ROWID or not */
125827 }
125828 #ifndef SQLITE_OMIT_VIRTUALTABLE
125829 if( IsVirtual(pSrc) ){
125830 return 0; /* tab2 must not be a virtual table */
125831 }
125832 #endif
125833 if( pSrc->pSelect ){
125834 return 0; /* tab2 may not be a view */
125835 }
125836 if( pDest->nCol!=pSrc->nCol ){
125837 return 0; /* Number of columns must be the same in tab1 and tab2 */
125838 }
125839 if( pDest->iPKey!=pSrc->iPKey ){
@@ -125873,33 +126007,38 @@
125873 /* But the transfer is only allowed if both the source and destination
125874 ** tables have the exact same expressions for generated columns.
125875 ** This requirement could be relaxed for VIRTUAL columns, I suppose.
125876 */
125877 if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
125878 if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
 
 
125879 testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
125880 testcase( pDestCol->colFlags & COLFLAG_STORED );
125881 return 0; /* Different generator expressions */
125882 }
125883 }
125884 #endif
125885 if( pDestCol->affinity!=pSrcCol->affinity ){
125886 return 0; /* Affinity must be the same on all columns */
125887 }
125888 if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
 
125889 return 0; /* Collating sequence must be the same on all columns */
125890 }
125891 if( pDestCol->notNull && !pSrcCol->notNull ){
125892 return 0; /* tab2 must be NOT NULL if tab1 is */
125893 }
125894 /* Default values for second and subsequent columns need to match. */
125895 if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
125896 assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
125897 assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
125898 if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
125899 || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken,
125900 pSrcCol->pDflt->u.zToken)!=0)
 
 
125901 ){
125902 return 0; /* Default values must be the same for all columns */
125903 }
125904 }
125905 }
@@ -125932,11 +126071,11 @@
125932 ** But the main beneficiary of the transfer optimization is the VACUUM
125933 ** command, and the VACUUM command disables foreign key constraints. So
125934 ** the extra complication to make this rule less restrictive is probably
125935 ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
125936 */
125937 if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
125938 return 0;
125939 }
125940 #endif
125941 if( (db->flags & SQLITE_CountRows)!=0 ){
125942 return 0; /* xfer opt does not play well with PRAGMA count_changes */
@@ -126610,10 +126749,13 @@
126610 int,const char**);
126611 void (*free_filename)(char*);
126612 sqlite3_file *(*database_file_object)(const char*);
126613 /* Version 3.34.0 and later */
126614 int (*txn_state)(sqlite3*,const char*);
 
 
 
126615 };
126616
126617 /*
126618 ** This is the function signature used for all extension entry points. It
126619 ** is also defined in the file "loadext.c".
@@ -127400,10 +127542,13 @@
127400 sqlite3_create_filename,
127401 sqlite3_free_filename,
127402 sqlite3_database_file_object,
127403 /* Version 3.34.0 and later */
127404 sqlite3_txn_state,
 
 
 
127405 };
127406
127407 /* True if x is the directory separator character
127408 */
127409 #if SQLITE_OS_WIN
@@ -128189,11 +128334,11 @@
128189 /* iArg: */ 1 },
128190 #endif
128191 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
128192 {/* zName: */ "integrity_check",
128193 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
128194 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
128195 /* ColNames: */ 0, 0,
128196 /* iArg: */ 0 },
128197 #endif
128198 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
128199 {/* zName: */ "journal_mode",
@@ -128297,11 +128442,11 @@
128297 /* iArg: */ SQLITE_QueryOnly },
128298 #endif
128299 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
128300 {/* zName: */ "quick_check",
128301 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
128302 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
128303 /* ColNames: */ 0, 0,
128304 /* iArg: */ 0 },
128305 #endif
128306 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
128307 {/* zName: */ "read_uncommitted",
@@ -129616,17 +129761,20 @@
129616 }else if( pPk==0 ){
129617 k = 1;
129618 }else{
129619 for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
129620 }
129621 assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
 
 
129622 sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
129623 i-nHidden,
129624 pCol->zName,
129625 sqlite3ColumnType(pCol,""),
129626 pCol->notNull ? 1 : 0,
129627 pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
 
129628 k,
129629 isHidden);
129630 }
129631 }
129632 }
@@ -129689,11 +129837,11 @@
129689 sqlite3CodeVerifySchema(pParse, iIdxDb);
129690 assert( pParse->nMem<=pPragma->nPragCName );
129691 for(i=0; i<mx; i++){
129692 i16 cnum = pIdx->aiColumn[i];
129693 sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
129694 cnum<0 ? 0 : pTab->aCol[cnum].zName);
129695 if( pPragma->iArg ){
129696 sqlite3VdbeMultiLoad(v, 4, "isiX",
129697 pIdx->aSortOrder[i],
129698 pIdx->azColl[i],
129699 i<pIdx->nKeyCol);
@@ -129796,12 +129944,12 @@
129796 #ifndef SQLITE_OMIT_FOREIGN_KEY
129797 case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
129798 FKey *pFK;
129799 Table *pTab;
129800 pTab = sqlite3FindTable(db, zRight, zDb);
129801 if( pTab ){
129802 pFK = pTab->pFKey;
129803 if( pFK ){
129804 int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
129805 int i = 0;
129806 pParse->nMem = 8;
129807 sqlite3CodeVerifySchema(pParse, iTabDb);
@@ -129810,11 +129958,11 @@
129810 for(j=0; j<pFK->nCol; j++){
129811 sqlite3VdbeMultiLoad(v, 1, "iissssss",
129812 i,
129813 j,
129814 pFK->zTo,
129815 pTab->aCol[pFK->aCol[j].iFrom].zName,
129816 pFK->aCol[j].zCol,
129817 actionName(pFK->aAction[1]), /* ON UPDATE */
129818 actionName(pFK->aAction[0]), /* ON DELETE */
129819 "NONE");
129820 }
@@ -129856,19 +130004,20 @@
129856 k = 0;
129857 }else{
129858 pTab = (Table*)sqliteHashData(k);
129859 k = sqliteHashNext(k);
129860 }
129861 if( pTab==0 || pTab->pFKey==0 ) continue;
129862 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
129863 zDb = db->aDb[iDb].zDbSName;
129864 sqlite3CodeVerifySchema(pParse, iDb);
129865 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
129866 if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
129867 sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
129868 sqlite3VdbeLoadString(v, regResult, pTab->zName);
129869 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
 
129870 pParent = sqlite3FindTable(db, pFK->zTo, zDb);
129871 if( pParent==0 ) continue;
129872 pIdx = 0;
129873 sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
129874 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
@@ -129886,11 +130035,12 @@
129886 }
129887 assert( pParse->nErr>0 || pFK==0 );
129888 if( pFK ) break;
129889 if( pParse->nTab<i ) pParse->nTab = i;
129890 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
129891 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
 
129892 pParent = sqlite3FindTable(db, pFK->zTo, zDb);
129893 pIdx = 0;
129894 aiCols = 0;
129895 if( pParent ){
129896 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
@@ -129900,10 +130050,11 @@
129900
129901 /* Generate code to read the child key values into registers
129902 ** regRow..regRow+n. If any of the child key values are NULL, this
129903 ** row cannot cause an FK violation. Jump directly to addrOk in
129904 ** this case. */
 
129905 for(j=0; j<pFK->nCol; j++){
129906 int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
129907 sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
129908 sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
129909 }
@@ -130120,11 +130271,11 @@
130120 if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
130121 sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
130122 }
130123 jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
130124 zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
130125 pTab->aCol[j].zName);
130126 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
130127 integrityCheckResultRow(v);
130128 sqlite3VdbeJumpHere(v, jmp2);
130129 }
130130 /* Verify CHECK constraints */
@@ -132328,11 +132479,11 @@
132328 SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
132329 int i;
132330 u8 h = sqlite3StrIHash(zCol);
132331 Column *pCol;
132332 for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
132333 if( pCol->hName==h && sqlite3StrICmp(pCol->zName, zCol)==0 ) return i;
132334 }
132335 return -1;
132336 }
132337
132338 /*
@@ -132527,11 +132678,11 @@
132527 char *zName; /* Name of column in the right table */
132528 int iLeft; /* Matching left table */
132529 int iLeftCol; /* Matching column in the left table */
132530
132531 if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
132532 zName = pRightTab->aCol[j].zName;
132533 if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
132534 addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
132535 isOuter, &p->pWhere);
132536 }
132537 }
@@ -132930,11 +133081,13 @@
132930 Parse *pParse, /* Parsing and code generating context */
132931 int eTnctType, /* WHERE_DISTINCT_* value */
132932 int iVal, /* Value returned by codeDistinct() */
132933 int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
132934 ){
132935 if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
 
 
132936 Vdbe *v = pParse->pVdbe;
132937 sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
132938 if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
132939 sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
132940 }
@@ -133892,11 +134045,11 @@
133892 assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
133893 if( iCol<0 ){
133894 zType = "INTEGER";
133895 zOrigCol = "rowid";
133896 }else{
133897 zOrigCol = pTab->aCol[iCol].zName;
133898 zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
133899 }
133900 zOrigTab = pTab->zName;
133901 if( pNC->pParse && pTab->pSchema ){
133902 int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
@@ -134064,11 +134217,11 @@
134064 if( iCol<0 ) iCol = pTab->iPKey;
134065 assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
134066 if( iCol<0 ){
134067 zCol = "rowid";
134068 }else{
134069 zCol = pTab->aCol[iCol].zName;
134070 }
134071 if( fullName ){
134072 char *zName = 0;
134073 zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
134074 sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
@@ -134149,11 +134302,11 @@
134149 }
134150 if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
134151 /* For columns use the column name name */
134152 int iCol = pColExpr->iColumn;
134153 if( iCol<0 ) iCol = pTab->iPKey;
134154 zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
134155 }else if( pColExpr->op==TK_ID ){
134156 assert( !ExprHasProperty(pColExpr, EP_IntValue) );
134157 zName = pColExpr->u.zToken;
134158 }else{
134159 /* Use the original text of the column expression as its name */
@@ -134177,21 +134330,21 @@
134177 if( zName[j]==':' ) nName = j;
134178 }
134179 zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
134180 if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
134181 }
134182 pCol->zName = zName;
134183 pCol->hName = sqlite3StrIHash(zName);
134184 sqlite3ColumnPropertiesFromName(0, pCol);
134185 if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
134186 sqlite3OomFault(db);
134187 }
134188 }
134189 sqlite3HashClear(&ht);
134190 if( db->mallocFailed ){
134191 for(j=0; j<i; j++){
134192 sqlite3DbFree(db, aCol[j].zName);
134193 }
134194 sqlite3DbFree(db, aCol);
134195 *paCol = 0;
134196 *pnCol = 0;
134197 return SQLITE_NOMEM_BKPT;
@@ -134239,21 +134392,22 @@
134239 zType = columnType(&sNC, p, 0, 0, 0);
134240 /* pCol->szEst = ... // Column size est for SELECT tables never used */
134241 pCol->affinity = sqlite3ExprAffinity(p);
134242 if( zType ){
134243 m = sqlite3Strlen30(zType);
134244 n = sqlite3Strlen30(pCol->zName);
134245 pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
134246 if( pCol->zName ){
134247 memcpy(&pCol->zName[n+1], zType, m+1);
134248 pCol->colFlags |= COLFLAG_HASTYPE;
134249 }
134250 }
134251 if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
134252 pColl = sqlite3ExprCollSeq(pParse, p);
134253 if( pColl && pCol->zColl==0 ){
134254 pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
 
134255 }
134256 }
134257 pTab->szTabRow = 1; /* Any non-zero value works */
134258 }
134259
@@ -135811,14 +135965,14 @@
135811 /*
135812 ** Assign new cursor numbers to each of the items in pSrc. For each
135813 ** new cursor number assigned, set an entry in the aCsrMap[] array
135814 ** to map the old cursor number to the new:
135815 **
135816 ** aCsrMap[iOld] = iNew;
135817 **
135818 ** The array is guaranteed by the caller to be large enough for all
135819 ** existing cursor numbers in pSrc.
135820 **
135821 ** If pSrc contains any sub-selects, call this routine recursively
135822 ** on the FROM clause of each such sub-select, with iExcept set to -1.
135823 */
135824 static void srclistRenumberCursors(
@@ -135830,33 +135984,44 @@
135830 int i;
135831 SrcItem *pItem;
135832 for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
135833 if( i!=iExcept ){
135834 Select *p;
135835 if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
135836 aCsrMap[pItem->iCursor] = pParse->nTab++;
 
135837 }
135838 pItem->iCursor = aCsrMap[pItem->iCursor];
135839 for(p=pItem->pSelect; p; p=p->pPrior){
135840 srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
135841 }
135842 }
135843 }
135844 }
 
 
 
 
 
 
 
 
 
 
 
135845
135846 /*
135847 ** Expression walker callback used by renumberCursors() to update
135848 ** Expr objects to match newly assigned cursor numbers.
135849 */
135850 static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
135851 int *aCsrMap = pWalker->u.aiCol;
135852 int op = pExpr->op;
135853 if( (op==TK_COLUMN || op==TK_IF_NULL_ROW) && aCsrMap[pExpr->iTable] ){
135854 pExpr->iTable = aCsrMap[pExpr->iTable];
135855 }
135856 if( ExprHasProperty(pExpr, EP_FromJoin) && aCsrMap[pExpr->iRightJoinTable] ){
135857 pExpr->iRightJoinTable = aCsrMap[pExpr->iRightJoinTable];
135858 }
135859 return WRC_Continue;
135860 }
135861
135862 /*
@@ -136196,11 +136361,12 @@
136196 /* Restriction (23) */
136197 if( (p->selFlags & SF_Recursive) ) return 0;
136198
136199 if( pSrc->nSrc>1 ){
136200 if( pParse->nSelect>500 ) return 0;
136201 aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
 
136202 }
136203 }
136204
136205 /***** If we reach this point, flattening is permitted. *****/
136206 SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -136976,11 +137142,11 @@
136976 ){
136977 return 0;
136978 }
136979 pTab = p->pSrc->a[0].pTab;
136980 pExpr = p->pEList->a[0].pExpr;
136981 assert( pTab && !pTab->pSelect && pExpr );
136982
136983 if( IsVirtual(pTab) ) return 0;
136984 if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
136985 if( NEVER(pAggInfo->nFunc==0) ) return 0;
136986 if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
@@ -137521,34 +137687,35 @@
137521 pTab->nTabRef++;
137522 if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
137523 return WRC_Abort;
137524 }
137525 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
137526 if( IsVirtual(pTab) || pTab->pSelect ){
137527 i16 nCol;
137528 u8 eCodeOrig = pWalker->eCode;
137529 if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
137530 assert( pFrom->pSelect==0 );
137531 if( pTab->pSelect
137532 && (db->flags & SQLITE_EnableView)==0
137533 && pTab->pSchema!=db->aDb[1].pSchema
137534 ){
137535 sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
137536 pTab->zName);
137537 }
 
 
137538 #ifndef SQLITE_OMIT_VIRTUALTABLE
137539 assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
137540 if( IsVirtual(pTab)
137541 && pFrom->fg.fromDDL
137542 && ALWAYS(pTab->pVTable!=0)
137543 && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
137544 ){
137545 sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
137546 pTab->zName);
137547 }
 
137548 #endif
137549 pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
137550 nCol = pTab->nCol;
137551 pTab->nCol = -1;
137552 pWalker->eCode = 1; /* Turn on Select.selId renumbering */
137553 sqlite3WalkSelect(pWalker, pFrom->pSelect);
137554 pWalker->eCode = eCodeOrig;
@@ -137644,11 +137811,11 @@
137644 }
137645 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
137646 zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
137647 }
137648 for(j=0; j<pTab->nCol; j++){
137649 char *zName = pTab->aCol[j].zName;
137650 char *zColname; /* The computed column name */
137651 char *zToFree; /* Malloced string that needs to be freed */
137652 Token sColname; /* Computed column name as a token */
137653
137654 assert( zName );
@@ -138076,12 +138243,20 @@
138076 ** within the HAVING expression with a constant "1".
138077 */
138078 static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
138079 if( pExpr->op!=TK_AND ){
138080 Select *pS = pWalker->u.pSelect;
 
 
 
 
 
 
 
138081 if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
138082 && ExprAlwaysFalse(pExpr)==0
 
138083 ){
138084 sqlite3 *db = pWalker->pParse->db;
138085 Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
138086 if( pNew ){
138087 Expr *pWhere = pS->pWhere;
@@ -138343,15 +138518,20 @@
138343 SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
138344 sqlite3TreeViewSelect(0, p, 0);
138345 }
138346 #endif
138347
138348 /* If the SF_UpdateFrom flag is set, then this function is being called
138349 ** as part of populating the temp table for an UPDATE...FROM statement.
138350 ** In this case, it is an error if the target object (pSrc->a[0]) name
138351 ** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
138352 if( p->selFlags & SF_UpdateFrom ){
 
 
 
 
 
138353 SrcItem *p0 = &p->pSrc->a[0];
138354 for(i=1; i<p->pSrc->nSrc; i++){
138355 SrcItem *p1 = &p->pSrc->a[i];
138356 if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
138357 sqlite3ErrorMsg(pParse,
@@ -138359,10 +138539,16 @@
138359 p0->zAlias ? p0->zAlias : p0->pTab->zName
138360 );
138361 goto select_end;
138362 }
138363 }
 
 
 
 
 
 
138364 }
138365
138366 if( pDest->eDest==SRT_Output ){
138367 sqlite3GenerateColumnNames(pParse, p);
138368 }
@@ -138429,10 +138615,43 @@
138429 ** will be implemented as a co-routine and there is no advantage to
138430 ** flattening in that case.
138431 */
138432 if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
138433 assert( pSub->pGroupBy==0 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138434
138435 /* If the outer query contains a "complex" result set (that is,
138436 ** if the result set of the outer query uses functions or subqueries)
138437 ** and if the subquery contains an ORDER BY clause and if
138438 ** it will be implemented as a co-routine, then do not flatten. This
@@ -139877,16 +140096,16 @@
139877 }
139878
139879 /* INSTEAD of triggers are only for views and views only support INSTEAD
139880 ** of triggers.
139881 */
139882 if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
139883 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
139884 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
139885 goto trigger_orphan_error;
139886 }
139887 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
139888 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
139889 " trigger on table: %S", pTableName->a);
139890 goto trigger_orphan_error;
139891 }
139892
@@ -140535,15 +140754,15 @@
140535 if( isAsteriskTerm(pParse, pOldExpr) ){
140536 int jj;
140537 for(jj=0; jj<pTab->nCol; jj++){
140538 Expr *pNewExpr;
140539 if( IsHiddenColumn(pTab->aCol+jj) ) continue;
140540 pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
140541 pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
140542 if( !db->mallocFailed ){
140543 struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
140544 pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zName);
140545 pItem->eEName = ENAME_NAME;
140546 }
140547 }
140548 }else{
140549 Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
@@ -140584,10 +140803,11 @@
140584 memset(&sFrom, 0, sizeof(sFrom));
140585 sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
140586 sSelect.pSrc = &sFrom;
140587 sFrom.nSrc = 1;
140588 sFrom.a[0].pTab = pTab;
 
140589 sqlite3SelectPrep(pParse, &sSelect, 0);
140590 if( db->mallocFailed==0 && pParse->nErr==0 ){
140591 sqlite3GenerateColumnNames(pParse, &sSelect);
140592 }
140593 sqlite3ExprListDelete(db, sSelect.pEList);
@@ -141139,17 +141359,18 @@
141139 ** integer. In that case, add an OP_RealAffinity opcode to make sure
141140 ** it has been converted into REAL.
141141 */
141142 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
141143 assert( pTab!=0 );
141144 if( !pTab->pSelect ){
141145 sqlite3_value *pValue = 0;
141146 u8 enc = ENC(sqlite3VdbeDb(v));
141147 Column *pCol = &pTab->aCol[i];
141148 VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
141149 assert( i<pTab->nCol );
141150 sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
 
141151 pCol->affinity, &pValue);
141152 if( pValue ){
141153 sqlite3VdbeAppendP4(v, pValue, P4_MEM);
141154 }
141155 }
@@ -141315,11 +141536,11 @@
141315 }
141316 #endif
141317 pList = sqlite3ExprListAppend(pParse, pList, pNew);
141318 }
141319 eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
141320 }else if( pTab->pSelect ){
141321 for(i=0; i<pTab->nCol; i++){
141322 pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
141323 }
141324 eDest = SRT_Table;
141325 }else{
@@ -141338,12 +141559,13 @@
141338 sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
141339 );
141340 }
141341 }
141342 pSelect = sqlite3SelectNew(pParse, pList,
141343 pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UpdateFrom|SF_IncludeHidden, pLimit2
141344 );
 
141345 sqlite3SelectDestInit(&dest, eDest, iEph);
141346 dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
141347 sqlite3Select(pParse, pSelect, &dest);
141348 sqlite3SelectDelete(db, pSelect);
141349 }
@@ -141439,11 +141661,11 @@
141439 /* Figure out if we have any triggers and if the table being
141440 ** updated is a view.
141441 */
141442 #ifndef SQLITE_OMIT_TRIGGER
141443 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
141444 isView = pTab->pSelect!=0;
141445 assert( pTrigger || tmask==0 );
141446 #else
141447 # define pTrigger 0
141448 # define isView 0
141449 # define tmask 0
@@ -141528,17 +141750,20 @@
141528 ** column to be updated, make sure we have authorization to change
141529 ** that column.
141530 */
141531 chngRowid = chngPk = 0;
141532 for(i=0; i<pChanges->nExpr; i++){
 
141533 /* If this is an UPDATE with a FROM clause, do not resolve expressions
141534 ** here. The call to sqlite3Select() below will do that. */
141535 if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
141536 goto update_cleanup;
141537 }
141538 for(j=0; j<pTab->nCol; j++){
141539 if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
 
 
141540 if( j==pTab->iPKey ){
141541 chngRowid = 1;
141542 pRowidExpr = pChanges->a[i].pExpr;
141543 iRowidExpr = i;
141544 }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
@@ -141548,11 +141773,11 @@
141548 else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
141549 testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
141550 testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
141551 sqlite3ErrorMsg(pParse,
141552 "cannot UPDATE generated column \"%s\"",
141553 pTab->aCol[j].zName);
141554 goto update_cleanup;
141555 }
141556 #endif
141557 aXRef[j] = i;
141558 break;
@@ -141572,11 +141797,11 @@
141572 }
141573 #ifndef SQLITE_OMIT_AUTHORIZATION
141574 {
141575 int rc;
141576 rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
141577 j<0 ? "ROWID" : pTab->aCol[j].zName,
141578 db->aDb[iDb].zDbSName);
141579 if( rc==SQLITE_DENY ){
141580 goto update_cleanup;
141581 }else if( rc==SQLITE_IGNORE ){
141582 aXRef[j] = -1;
@@ -141604,12 +141829,14 @@
141604 do{
141605 bProgress = 0;
141606 for(i=0; i<pTab->nCol; i++){
141607 if( aXRef[i]>=0 ) continue;
141608 if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
141609 if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
141610 aXRef, chngRowid) ){
 
 
141611 aXRef[i] = 99999;
141612 bProgress = 1;
141613 }
141614 }
141615 }while( bProgress );
@@ -142697,11 +142924,11 @@
142697 int k;
142698 assert( pPk->aiColumn[i]>=0 );
142699 k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
142700 sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
142701 VdbeComment((v, "%s.%s", pIdx->zName,
142702 pTab->aCol[pPk->aiColumn[i]].zName));
142703 }
142704 sqlite3VdbeVerifyAbortable(v, OE_Abort);
142705 i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
142706 VdbeCoverage(v);
142707 sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
@@ -142879,12 +143106,12 @@
142879 int rc = SQLITE_OK; /* Return code from service routines */
142880 Btree *pMain; /* The database being vacuumed */
142881 Btree *pTemp; /* The temporary database we vacuum into */
142882 u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
142883 u64 saved_flags; /* Saved value of db->flags */
142884 int saved_nChange; /* Saved value of db->nChange */
142885 int saved_nTotalChange; /* Saved value of db->nTotalChange */
142886 u32 saved_openFlags; /* Saved value of db->openFlags */
142887 u8 saved_mTrace; /* Saved trace settings */
142888 Db *pDb = 0; /* Database to detach at end of vacuum */
142889 int isMemDb; /* True if vacuuming a :memory: database */
142890 int nRes; /* Bytes of reserved space at the end of each page */
@@ -143327,11 +143554,11 @@
143327 ** this virtual-table, if one has been created, or NULL otherwise.
143328 */
143329 SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
143330 VTable *pVtab;
143331 assert( IsVirtual(pTab) );
143332 for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
143333 return pVtab;
143334 }
143335
143336 /*
143337 ** Decrement the ref-count on a virtual table object. When the ref-count
@@ -143355,35 +143582,35 @@
143355 }
143356 }
143357
143358 /*
143359 ** Table p is a virtual table. This function moves all elements in the
143360 ** p->pVTable list to the sqlite3.pDisconnect lists of their associated
143361 ** database connections to be disconnected at the next opportunity.
143362 ** Except, if argument db is not NULL, then the entry associated with
143363 ** connection db is left in the p->pVTable list.
143364 */
143365 static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
143366 VTable *pRet = 0;
143367 VTable *pVTable = p->pVTable;
143368 p->pVTable = 0;
143369
143370 /* Assert that the mutex (if any) associated with the BtShared database
143371 ** that contains table p is held by the caller. See header comments
143372 ** above function sqlite3VtabUnlockList() for an explanation of why
143373 ** this makes it safe to access the sqlite3.pDisconnect list of any
143374 ** database connection that may have an entry in the p->pVTable list.
143375 */
143376 assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
143377
143378 while( pVTable ){
143379 sqlite3 *db2 = pVTable->db;
143380 VTable *pNext = pVTable->pNext;
143381 assert( db2 );
143382 if( db2==db ){
143383 pRet = pVTable;
143384 p->pVTable = pRet;
143385 pRet->pNext = 0;
143386 }else{
143387 pVTable->pNext = db2->pDisconnect;
143388 db2->pDisconnect = pVTable;
143389 }
@@ -143407,11 +143634,11 @@
143407
143408 assert( IsVirtual(p) );
143409 assert( sqlite3BtreeHoldsAllMutexes(db) );
143410 assert( sqlite3_mutex_held(db->mutex) );
143411
143412 for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
143413 if( (*ppVTab)->db==db ){
143414 VTable *pVTab = *ppVTab;
143415 *ppVTab = pVTab->pNext;
143416 sqlite3VtabUnlock(pVTab);
143417 break;
@@ -143471,40 +143698,40 @@
143471 ** in the list are moved to the sqlite3.pDisconnect list of the associated
143472 ** database connection.
143473 */
143474 SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
143475 if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
143476 if( p->azModuleArg ){
143477 int i;
143478 for(i=0; i<p->nModuleArg; i++){
143479 if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
143480 }
143481 sqlite3DbFree(db, p->azModuleArg);
143482 }
143483 }
143484
143485 /*
143486 ** Add a new module argument to pTable->azModuleArg[].
143487 ** The string is not copied - the pointer is stored. The
143488 ** string will be freed automatically when the table is
143489 ** deleted.
143490 */
143491 static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
143492 sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->nModuleArg);
143493 char **azModuleArg;
143494 sqlite3 *db = pParse->db;
143495 if( pTable->nModuleArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
143496 sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
143497 }
143498 azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
143499 if( azModuleArg==0 ){
143500 sqlite3DbFree(db, zArg);
143501 }else{
143502 int i = pTable->nModuleArg++;
143503 azModuleArg[i] = zArg;
143504 azModuleArg[i+1] = 0;
143505 pTable->azModuleArg = azModuleArg;
143506 }
143507 }
143508
143509 /*
143510 ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
@@ -143523,14 +143750,15 @@
143523
143524 sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
143525 pTable = pParse->pNewTable;
143526 if( pTable==0 ) return;
143527 assert( 0==pTable->pIndex );
 
143528
143529 db = pParse->db;
143530
143531 assert( pTable->nModuleArg==0 );
143532 addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName));
143533 addModuleArgument(pParse, pTable, 0);
143534 addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName));
143535 assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0)
143536 || (pParse->sNameToken.z==pName1->z && pName2->z==0)
@@ -143543,15 +143771,15 @@
143543 /* Creating a virtual table invokes the authorization callback twice.
143544 ** The first invocation, to obtain permission to INSERT a row into the
143545 ** sqlite_schema table, has already been made by sqlite3StartTable().
143546 ** The second call, to obtain permission to create the table, is made now.
143547 */
143548 if( pTable->azModuleArg ){
143549 int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
143550 assert( iDb>=0 ); /* The database the table is being created in */
143551 sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
143552 pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
143553 }
143554 #endif
143555 }
143556
143557 /*
@@ -143577,11 +143805,11 @@
143577 sqlite3 *db = pParse->db; /* The database connection */
143578
143579 if( pTab==0 ) return;
143580 addArgumentToVtab(pParse);
143581 pParse->sArg.z = 0;
143582 if( pTab->nModuleArg<1 ) return;
143583
143584 /* If the CREATE VIRTUAL TABLE statement is being entered for the
143585 ** first time (in other words if the virtual table is actually being
143586 ** created now instead of just being read out of sqlite_schema) then
143587 ** do additional initialization work and store the statement text
@@ -143692,12 +143920,12 @@
143692 char **pzErr
143693 ){
143694 VtabCtx sCtx;
143695 VTable *pVTable;
143696 int rc;
143697 const char *const*azArg = (const char *const*)pTab->azModuleArg;
143698 int nArg = pTab->nModuleArg;
143699 char *zErr = 0;
143700 char *zModuleName;
143701 int iDb;
143702 VtabCtx *pCtx;
143703
@@ -143725,11 +143953,11 @@
143725 pVTable->db = db;
143726 pVTable->pMod = pMod;
143727 pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
143728
143729 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
143730 pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
143731
143732 /* Invoke the virtual table constructor */
143733 assert( &db->pVtabCtx );
143734 assert( xConstruct );
143735 sCtx.pTab = pTab;
@@ -143764,16 +143992,16 @@
143764 rc = SQLITE_ERROR;
143765 }else{
143766 int iCol;
143767 u16 oooHidden = 0;
143768 /* If everything went according to plan, link the new VTable structure
143769 ** into the linked list headed by pTab->pVTable. Then loop through the
143770 ** columns of the table to see if any of them contain the token "hidden".
143771 ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
143772 ** the type string. */
143773 pVTable->pNext = pTab->pVTable;
143774 pTab->pVTable = pVTable;
143775
143776 for(iCol=0; iCol<pTab->nCol; iCol++){
143777 char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
143778 int nType;
143779 int i = 0;
@@ -143827,15 +144055,15 @@
143827 if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
143828 return SQLITE_OK;
143829 }
143830
143831 /* Locate the required virtual table module */
143832 zMod = pTab->azModuleArg[0];
143833 pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
143834
143835 if( !pMod ){
143836 const char *zModule = pTab->azModuleArg[0];
143837 sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
143838 rc = SQLITE_ERROR;
143839 }else{
143840 char *zErr = 0;
143841 rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
@@ -143894,14 +144122,14 @@
143894 Table *pTab;
143895 Module *pMod;
143896 const char *zMod;
143897
143898 pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
143899 assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
143900
143901 /* Locate the required virtual table module */
143902 zMod = pTab->azModuleArg[0];
143903 pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
143904
143905 /* If the module has been registered and includes a Create method,
143906 ** invoke it now. If the module has not been registered, return an
143907 ** error. Otherwise, do nothing.
@@ -143957,17 +144185,17 @@
143957 sParse.db = db;
143958 sParse.nQueryLoop = 1;
143959 if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
143960 && sParse.pNewTable
143961 && !db->mallocFailed
143962 && !sParse.pNewTable->pSelect
143963 && !IsVirtual(sParse.pNewTable)
143964 ){
143965 if( !pTab->aCol ){
143966 Table *pNew = sParse.pNewTable;
143967 Index *pIdx;
143968 pTab->aCol = pNew->aCol;
 
143969 pTab->nNVCol = pTab->nCol = pNew->nCol;
143970 pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
143971 pNew->nCol = 0;
143972 pNew->aCol = 0;
143973 assert( pTab->pIndex==0 );
@@ -144018,14 +144246,14 @@
144018 SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
144019 int rc = SQLITE_OK;
144020 Table *pTab;
144021
144022 pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
144023 if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){
144024 VTable *p;
144025 int (*xDestroy)(sqlite3_vtab *);
144026 for(p=pTab->pVTable; p; p=p->pNext){
144027 assert( p->pVtab );
144028 if( p->pVtab->nRef>0 ){
144029 return SQLITE_LOCKED;
144030 }
144031 }
@@ -144035,13 +144263,13 @@
144035 assert( xDestroy!=0 );
144036 pTab->nTabRef++;
144037 rc = xDestroy(p->pVtab);
144038 /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
144039 if( rc==SQLITE_OK ){
144040 assert( pTab->pVTable==p && p->pNext==0 );
144041 p->pVtab = 0;
144042 pTab->pVTable = 0;
144043 sqlite3VtabUnlock(p);
144044 }
144045 sqlite3DeleteTable(db, pTab);
144046 }
144047
@@ -144325,12 +144553,13 @@
144325 }
144326
144327 /*
144328 ** Check to see if virtual table module pMod can be have an eponymous
144329 ** virtual table instance. If it can, create one if one does not already
144330 ** exist. Return non-zero if the eponymous virtual table instance exists
144331 ** when this routine returns, and return zero if it does not exist.
 
144332 **
144333 ** An eponymous virtual table instance is one that is named after its
144334 ** module, and more importantly, does not require a CREATE VIRTUAL TABLE
144335 ** statement in order to come into existance. Eponymous virtual table
144336 ** instances always exist. They cannot be DROP-ed.
@@ -144353,12 +144582,13 @@
144353 sqlite3DbFree(db, pTab);
144354 return 0;
144355 }
144356 pMod->pEpoTab = pTab;
144357 pTab->nTabRef = 1;
 
144358 pTab->pSchema = db->aDb[0].pSchema;
144359 assert( pTab->nModuleArg==0 );
144360 pTab->iPKey = -1;
144361 pTab->tabFlags |= TF_Eponymous;
144362 addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
144363 addModuleArgument(pParse, pTab, 0);
144364 addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
@@ -144365,11 +144595,10 @@
144365 rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
144366 if( rc ){
144367 sqlite3ErrorMsg(pParse, "%s", zErr);
144368 sqlite3DbFree(db, zErr);
144369 sqlite3VtabEponymousTableClear(db, pMod);
144370 return 0;
144371 }
144372 return 1;
144373 }
144374
144375 /*
@@ -145099,11 +145328,11 @@
145099 */
145100 static const char *explainIndexColumnName(Index *pIdx, int i){
145101 i = pIdx->aiColumn[i];
145102 if( i==XN_EXPR ) return "<expr>";
145103 if( i==XN_ROWID ) return "rowid";
145104 return pIdx->pTable->aCol[i].zName;
145105 }
145106
145107 /*
145108 ** This routine is a helper for explainIndexRange() below
145109 **
@@ -146311,12 +146540,13 @@
146311 if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
146312 w.xExprCallback = whereIndexExprTransNode;
146313 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
146314 }else if( iRef>=0
146315 && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
146316 && (pTab->aCol[iRef].zColl==0
146317 || sqlite3StrICmp(pTab->aCol[iRef].zColl, sqlite3StrBINARY)==0)
 
146318 ){
146319 /* Check to see if there are direct references to generated columns
146320 ** that are contained in the index. Pulling the generated column
146321 ** out of the index is an optimization only - the main table is always
146322 ** available if the index cannot be used. To avoid unnecessary
@@ -148731,11 +148961,15 @@
148731 pNew->u.x.leftColumn = aiCurCol[1];
148732 testcase( (prereqLeft | extraRight) != prereqLeft );
148733 pNew->prereqRight = prereqLeft | extraRight;
148734 pNew->prereqAll = prereqAll;
148735 pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
148736 }else if( op==TK_ISNULL && 0==sqlite3ExprCanBeNull(pLeft) ){
 
 
 
 
148737 pExpr->op = TK_TRUEFALSE;
148738 pExpr->u.zToken = "false";
148739 ExprSetProperty(pExpr, EP_IsFalse);
148740 pTerm->prereqAll = 0;
148741 pTerm->eOperator = 0;
@@ -148928,12 +149162,12 @@
148928 ){
148929 int i;
148930 for(i=0; i<nLeft; i++){
148931 int idxNew;
148932 Expr *pNew;
148933 Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
148934 Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
148935
148936 pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
148937 transferJoinMarkings(pNew, pExpr);
148938 idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
148939 exprAnalyze(pSrc, pWC, idxNew);
@@ -150018,11 +150252,11 @@
150018 testcase( iCol==BMS );
150019 testcase( iCol==BMS-1 );
150020 if( !sentWarning ){
150021 sqlite3_log(SQLITE_WARNING_AUTOINDEX,
150022 "automatic index on %s(%s)", pTable->zName,
150023 pTable->aCol[iCol].zName);
150024 sentWarning = 1;
150025 }
150026 if( (idxCols & cMask)==0 ){
150027 if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
150028 goto end_auto_index_create;
@@ -151932,11 +152166,11 @@
151932 }else{
151933 #ifdef SQLITE_ENABLE_STAT4
151934 tRowcnt nOut = 0;
151935 if( nInMul==0
151936 && pProbe->nSample
151937 && pNew->u.btree.nEq<=pProbe->nSampleCol
151938 && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
151939 && OptimizationEnabled(db, SQLITE_Stat4)
151940 ){
151941 Expr *pExpr = pTerm->pExpr;
151942 if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
@@ -152197,11 +152431,10 @@
152197 WhereLoop *pNew; /* Template WhereLoop object */
152198 int rc = SQLITE_OK; /* Return code */
152199 int iSortIdx = 1; /* Index number */
152200 int b; /* A boolean value */
152201 LogEst rSize; /* number of rows in the table */
152202 LogEst rLogSize; /* Logarithm of the number of rows in the table */
152203 WhereClause *pWC; /* The parsed WHERE clause */
152204 Table *pTab; /* Table being queried */
152205
152206 pNew = pBuilder->pNew;
152207 pWInfo = pBuilder->pWInfo;
@@ -152240,11 +152473,10 @@
152240 sPk.pNext = pFirst;
152241 }
152242 pProbe = &sPk;
152243 }
152244 rSize = pTab->nRowLogEst;
152245 rLogSize = estLog(rSize);
152246
152247 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
152248 /* Automatic indexes */
152249 if( !pBuilder->pOrSet /* Not part of an OR optimization */
152250 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
@@ -152254,12 +152486,14 @@
152254 && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
152255 && !pSrc->fg.isCorrelated /* Not a correlated subquery */
152256 && !pSrc->fg.isRecursive /* Not a recursive common table expression. */
152257 ){
152258 /* Generate auto-index WhereLoops */
 
152259 WhereTerm *pTerm;
152260 WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
 
152261 for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
152262 if( pTerm->prereqRight & pNew->maskSelf ) continue;
152263 if( termCanDriveIndex(pTerm, pSrc, 0) ){
152264 pNew->u.btree.nEq = 1;
152265 pNew->nSkip = 0;
@@ -152273,11 +152507,11 @@
152273 ** of X is smaller for views and subqueries so that the query planner
152274 ** will be more aggressive about generating automatic indexes for
152275 ** those objects, since there is no opportunity to add schema
152276 ** indexes on subqueries and views. */
152277 pNew->rSetup = rLogSize + rSize;
152278 if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
152279 pNew->rSetup += 28;
152280 }else{
152281 pNew->rSetup -= 10;
152282 }
152283 ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
@@ -154424,11 +154658,11 @@
154424
154425 pTabItem = &pTabList->a[pLevel->iFrom];
154426 pTab = pTabItem->pTab;
154427 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
154428 pLoop = pLevel->pWLoop;
154429 if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
154430 /* Do nothing */
154431 }else
154432 #ifndef SQLITE_OMIT_VIRTUALTABLE
154433 if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
154434 const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
@@ -154741,10 +154975,16 @@
154741 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
154742 }
154743 if( (ws & WHERE_INDEXED)
154744 || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
154745 ){
 
 
 
 
 
 
154746 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
154747 }
154748 if( pLevel->op==OP_Return ){
154749 sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
154750 }else{
@@ -154787,11 +155027,11 @@
154787 ** Except, do not close cursors that will be reused by the OR optimization
154788 ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors
154789 ** created for the ONEPASS optimization.
154790 */
154791 if( (pTab->tabFlags & TF_Ephemeral)==0
154792 && pTab->pSelect==0
154793 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
154794 ){
154795 int ws = pLoop->wsFlags;
154796 if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
154797 sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
@@ -155805,13 +156045,11 @@
155805 break;
155806 }
155807 if( bIntToNull ){
155808 int iDummy;
155809 Expr *pSub;
155810 for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
155811 assert( pSub );
155812 }
155813 if( sqlite3ExprIsInteger(pSub, &iDummy) ){
155814 pSub->op = TK_NULL;
155815 pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
155816 pSub->u.zToken = 0;
155817 }
@@ -155969,11 +156207,11 @@
155969 p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
155970 if( p->pSrc ){
155971 Table *pTab2;
155972 p->pSrc->a[0].pSelect = pSub;
155973 sqlite3SrcListAssignCursors(pParse, p->pSrc);
155974 pSub->selFlags |= SF_Expanded;
155975 pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
155976 pSub->selFlags |= (selFlags & SF_Aggregate);
155977 if( pTab2==0 ){
155978 /* Might actually be some other kind of error, but in that case
155979 ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
@@ -161615,11 +161853,11 @@
161615 sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
161616 }
161617 }
161618 break;
161619 case 23: /* columnname ::= nm typetoken */
161620 {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
161621 break;
161622 case 24: /* typetoken ::= */
161623 case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63);
161624 case 102: /* as ::= */ yytestcase(yyruleno==102);
161625 {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
@@ -162419,24 +162657,32 @@
162419 ** simplify to constants 0 (false) and 1 (true), respectively,
162420 ** regardless of the value of expr1.
162421 */
162422 sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy404);
162423 yymsp[-4].minor.yy404 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy376 ? "1" : "0");
162424 }else if( yymsp[-1].minor.yy70->nExpr==1 && sqlite3ExprIsConstant(yymsp[-1].minor.yy70->a[0].pExpr) ){
162425 Expr *pRHS = yymsp[-1].minor.yy70->a[0].pExpr;
162426 yymsp[-1].minor.yy70->a[0].pExpr = 0;
162427 sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162428 pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
162429 yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy404, pRHS);
162430 if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
162431 }else{
162432 yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
162433 if( yymsp[-4].minor.yy404 ){
162434 yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy70;
162435 sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404);
162436 }else{
162437 sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
 
 
 
 
 
 
 
 
162438 }
162439 if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
162440 }
162441 }
162442 break;
@@ -166151,31 +166397,37 @@
166151 }
166152
166153 /*
166154 ** Return the number of changes in the most recent call to sqlite3_exec().
166155 */
166156 SQLITE_API int sqlite3_changes(sqlite3 *db){
166157 #ifdef SQLITE_ENABLE_API_ARMOR
166158 if( !sqlite3SafetyCheckOk(db) ){
166159 (void)SQLITE_MISUSE_BKPT;
166160 return 0;
166161 }
166162 #endif
166163 return db->nChange;
166164 }
 
 
 
166165
166166 /*
166167 ** Return the number of changes since the database handle was opened.
166168 */
166169 SQLITE_API int sqlite3_total_changes(sqlite3 *db){
166170 #ifdef SQLITE_ENABLE_API_ARMOR
166171 if( !sqlite3SafetyCheckOk(db) ){
166172 (void)SQLITE_MISUSE_BKPT;
166173 return 0;
166174 }
166175 #endif
166176 return db->nTotalChange;
 
 
 
166177 }
166178
166179 /*
166180 ** Close all open savepoints. This function only manipulates fields of the
166181 ** database handle object, it does not close any savepoints that may be open
@@ -166913,26 +167165,37 @@
166913 ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
166914 **
166915 ** If SQLITE_ANY is specified, add three versions of the function
166916 ** to the hash table.
166917 */
166918 if( enc==SQLITE_UTF16 ){
166919 enc = SQLITE_UTF16NATIVE;
166920 }else if( enc==SQLITE_ANY ){
166921 int rc;
166922 rc = sqlite3CreateFunc(db, zFunctionName, nArg,
166923 (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
166924 pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
166925 if( rc==SQLITE_OK ){
166926 rc = sqlite3CreateFunc(db, zFunctionName, nArg,
166927 (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
166928 pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
166929 }
166930 if( rc!=SQLITE_OK ){
166931 return rc;
166932 }
166933 enc = SQLITE_UTF16BE;
 
 
 
 
 
 
 
 
 
 
 
166934 }
166935 #else
166936 enc = SQLITE_UTF8;
166937 #endif
166938
@@ -167025,11 +167288,11 @@
167025 }
167026 rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p,
167027 xSFunc, xStep, xFinal, xValue, xInverse, pArg
167028 );
167029 if( pArg && pArg->nRef==0 ){
167030 assert( rc!=SQLITE_OK );
167031 xDestroy(p);
167032 sqlite3_free(pArg);
167033 }
167034
167035 out:
@@ -168208,11 +168471,10 @@
168208 ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
168209 ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
168210 ** off all other flags.
168211 */
168212 flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
168213 SQLITE_OPEN_EXCLUSIVE |
168214 SQLITE_OPEN_MAIN_DB |
168215 SQLITE_OPEN_TEMP_DB |
168216 SQLITE_OPEN_TRANSIENT_DB |
168217 SQLITE_OPEN_MAIN_JOURNAL |
168218 SQLITE_OPEN_TEMP_JOURNAL |
@@ -168780,11 +169042,11 @@
168780 goto error_out;
168781 }
168782
168783 /* Locate the table in question */
168784 pTab = sqlite3FindTable(db, zTableName, zDbName);
168785 if( !pTab || pTab->pSelect ){
168786 pTab = 0;
168787 goto error_out;
168788 }
168789
168790 /* Find the column for which info is requested */
@@ -168791,11 +169053,11 @@
168791 if( zColumnName==0 ){
168792 /* Query for existance of table only */
168793 }else{
168794 for(iCol=0; iCol<pTab->nCol; iCol++){
168795 pCol = &pTab->aCol[iCol];
168796 if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
168797 break;
168798 }
168799 }
168800 if( iCol==pTab->nCol ){
168801 if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
@@ -168818,11 +169080,11 @@
168818 ** 2. The table is not a view and the column name identified an
168819 ** explicitly declared column. Copy meta information from *pCol.
168820 */
168821 if( pCol ){
168822 zDataType = sqlite3ColumnType(pCol,0);
168823 zCollSeq = pCol->zColl;
168824 notnull = pCol->notNull!=0;
168825 primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
168826 autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
168827 }else{
168828 zDataType = "INTEGER";
@@ -169349,11 +169611,11 @@
169349 case 3: sqlite3WhereTrace = *ptr; break;
169350 }
169351 break;
169352 }
169353
169354 #ifdef SQLITE_DEBUG
169355 /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
169356 **
169357 ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
169358 ** of the id-th tuning parameter to *piValue. If "id" is between -1
169359 ** and -SQLITE_NTUNE, then write the current value of the (-id)-th
@@ -201251,11 +201513,13 @@
201251 *piPk = 0;
201252
201253 assert( p->rc==SQLITE_OK );
201254 p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
201255 sqlite3_mprintf(
201256 "SELECT (sql LIKE 'create virtual%%'), rootpage"
 
 
201257 " FROM sqlite_schema"
201258 " WHERE name=%Q", zTab
201259 ));
201260 if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){
201261 /* Either an error, or no such table. */
@@ -202784,11 +203048,11 @@
202784 case RBU_STATE_COOKIE:
202785 pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1);
202786 break;
202787
202788 case RBU_STATE_OALSZ:
202789 pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1);
202790 break;
202791
202792 case RBU_STATE_PHASEONESTEP:
202793 pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1);
202794 break;
@@ -213428,10 +213692,13 @@
213428 /*
213429 ** This interface is used by the fts5vocab module.
213430 */
213431 static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
213432 static int sqlite3Fts5IterNextScan(Fts5IndexIter*);
 
 
 
213433
213434
213435 /*
213436 ** Insert or remove data to or from the index. Each time a document is
213437 ** added to or removed from the index, this function is called one or more
@@ -216223,20 +216490,21 @@
216223 /* EOF */
216224 *piOff = -1;
216225 return 1;
216226 }else{
216227 i64 iOff = *piOff;
216228 int iVal;
216229 fts5FastGetVarint32(a, i, iVal);
216230 assert( iVal>=0 );
216231 if( iVal<=1 ){
216232 if( iVal==0 ){
216233 *pi = i;
216234 return 0;
216235 }
216236 fts5FastGetVarint32(a, i, iVal);
216237 iOff = ((i64)iVal) << 32;
 
216238 fts5FastGetVarint32(a, i, iVal);
216239 if( iVal<2 ){
216240 /* This is a corrupt record. So stop parsing it here. */
216241 *piOff = -1;
216242 return 1;
@@ -216244,11 +216512,11 @@
216244 *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
216245 }else{
216246 *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
216247 }
216248 *pi = i;
216249 assert( *piOff>=iOff );
216250 return 0;
216251 }
216252 }
216253
216254
@@ -217553,10 +217821,11 @@
217553
217554 static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
217555 va_list ap;
217556 va_start(ap, zFmt);
217557 if( pParse->rc==SQLITE_OK ){
 
217558 pParse->zErr = sqlite3_vmprintf(zFmt, ap);
217559 pParse->rc = SQLITE_ERROR;
217560 }
217561 va_end(ap);
217562 }
@@ -219562,13 +219831,12 @@
219562 Fts5ExprNode *pExpr,
219563 Fts5Colset *pColset
219564 ){
219565 Fts5Colset *pFree = pColset;
219566 if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
219567 pParse->rc = SQLITE_ERROR;
219568 pParse->zErr = sqlite3_mprintf(
219569 "fts5: column queries are not supported (detail=none)"
219570 );
219571 }else{
219572 fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
219573 }
219574 sqlite3_free(pFree);
@@ -219738,17 +220006,14 @@
219738 Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
219739 if( pNear->nPhrase!=1
219740 || pPhrase->nTerm>1
219741 || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
219742 ){
219743 assert( pParse->rc==SQLITE_OK );
219744 pParse->rc = SQLITE_ERROR;
219745 assert( pParse->zErr==0 );
219746 pParse->zErr = sqlite3_mprintf(
219747 "fts5: %s queries are not supported (detail!=full)",
219748 pNear->nPhrase==1 ? "phrase": "NEAR"
219749 );
219750 sqlite3_free(pRet);
219751 pRet = 0;
219752 }
219753 }
219754 }else{
@@ -221861,10 +222126,26 @@
221861 }
221862
221863 static void fts5StructureRef(Fts5Structure *pStruct){
221864 pStruct->nRef++;
221865 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221866
221867 /*
221868 ** Deserialize and return the structure record currently stored in serialized
221869 ** form within buffer pData/nData.
221870 **
@@ -230568,11 +230849,11 @@
230568 int nArg, /* Number of args */
230569 sqlite3_value **apUnused /* Function arguments */
230570 ){
230571 assert( nArg==0 );
230572 UNUSED_PARAM2(nArg, apUnused);
230573 sqlite3_result_text(pCtx, "fts5: 2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70", -1, SQLITE_TRANSIENT);
230574 }
230575
230576 /*
230577 ** Return true if zName is the extension on one of the shadow tables used
230578 ** by this module.
@@ -234464,10 +234745,11 @@
234464 sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
234465 Fts5Table *pFts5; /* Associated FTS5 table */
234466
234467 int bEof; /* True if this cursor is at EOF */
234468 Fts5IndexIter *pIter; /* Term/rowid iterator object */
 
234469
234470 int nLeTerm; /* Size of zLeTerm in bytes */
234471 char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
234472
234473 /* These are used by 'col' tables only */
@@ -234797,10 +235079,12 @@
234797 }
234798
234799 static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
234800 pCsr->rowid = 0;
234801 sqlite3Fts5IterClose(pCsr->pIter);
 
 
234802 pCsr->pIter = 0;
234803 sqlite3_free(pCsr->zLeTerm);
234804 pCsr->nLeTerm = -1;
234805 pCsr->zLeTerm = 0;
234806 pCsr->bEof = 0;
@@ -234874,13 +235158,15 @@
234874 ** Advance the cursor to the next row in the table.
234875 */
234876 static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
234877 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
234878 Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
234879 int rc = SQLITE_OK;
234880 int nCol = pCsr->pFts5->pConfig->nCol;
 
234881
 
 
234882 pCsr->rowid++;
234883
234884 if( pTab->eType==FTS5_VOCAB_INSTANCE ){
234885 return fts5VocabInstanceNext(pCsr);
234886 }
@@ -235050,10 +235336,13 @@
235050 }
235051
235052 if( rc==SQLITE_OK ){
235053 Fts5Index *pIndex = pCsr->pFts5->pIndex;
235054 rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
 
 
 
235055 }
235056 if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
235057 rc = fts5VocabInstanceNewTerm(pCsr);
235058 }
235059 if( rc==SQLITE_OK && !pCsr->bEof
@@ -235494,12 +235783,8 @@
235494 }
235495 #endif /* SQLITE_CORE */
235496 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
235497
235498 /************** End of stmt.c ************************************************/
235499 #if __LINE__!=235499
235500 #undef SQLITE_SOURCE_ID
235501 #define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9alt2"
235502 #endif
235503 /* Return the source-id for this library */
235504 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
235505 /************************** End of sqlite3.c ******************************/
235506
--- 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.37.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.
@@ -20,797 +20,10 @@
20 #define SQLITE_CORE 1
21 #define SQLITE_AMALGAMATION 1
22 #ifndef SQLITE_PRIVATE
23 # define SQLITE_PRIVATE static
24 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25 /************** Begin file sqliteInt.h ***************************************/
26 /*
27 ** 2001 September 15
28 **
29 ** The author disclaims copyright to this source code. In place of
@@ -1071,10 +284,21 @@
284 defined(_WIN32) && !defined(_WIN64) && \
285 defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
286 defined(__MSVCRT__)
287 # define _USE_32BIT_TIME_T
288 #endif
289
290 /* Optionally #include a user-defined header, whereby compilation options
291 ** may be set prior to where they take effect, but after platform setup.
292 ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
293 ** file.
294 */
295 #ifdef SQLITE_CUSTOM_INCLUDE
296 # define INC_STRINGIFY_(f) #f
297 # define INC_STRINGIFY(f) INC_STRINGIFY_(f)
298 # include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
299 #endif
300
301 /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
302 ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
303 ** MinGW.
304 */
@@ -1123,11 +347,34 @@
347 extern "C" {
348 #endif
349
350
351 /*
352 ** Facilitate override of interface linkage and calling conventions.
353 ** Be aware that these macros may not be used within this particular
354 ** translation of the amalgamation and its associated header file.
355 **
356 ** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
357 ** compiler that the target identifier should have external linkage.
358 **
359 ** The SQLITE_CDECL macro is used to set the calling convention for
360 ** public functions that accept a variable number of arguments.
361 **
362 ** The SQLITE_APICALL macro is used to set the calling convention for
363 ** public functions that accept a fixed number of arguments.
364 **
365 ** The SQLITE_STDCALL macro is no longer used and is now deprecated.
366 **
367 ** The SQLITE_CALLBACK macro is used to set the calling convention for
368 ** function pointers.
369 **
370 ** The SQLITE_SYSAPI macro is used to set the calling convention for
371 ** functions provided by the operating system.
372 **
373 ** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
374 ** SQLITE_SYSAPI macros are used only when building for environments
375 ** that require non-default calling conventions.
376 */
377 #ifndef SQLITE_EXTERN
378 # define SQLITE_EXTERN extern
379 #endif
380 #ifndef SQLITE_API
@@ -1203,13 +450,13 @@
450 **
451 ** See also: [sqlite3_libversion()],
452 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
453 ** [sqlite_version()] and [sqlite_source_id()].
454 */
455 #define SQLITE_VERSION "3.37.0"
456 #define SQLITE_VERSION_NUMBER 3037000
457 #define SQLITE_SOURCE_ID "2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a"
458
459 /*
460 ** CAPI3REF: Run-Time Library Version Numbers
461 ** KEYWORDS: sqlite3_version sqlite3_sourceid
462 **
@@ -1596,10 +843,11 @@
843 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
844 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
845 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
846 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
847 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
848 #define SQLITE_CANTOPEN_EXISTS (SQLITE_CANTOPEN | (7<<8))
849 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
850 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
851 #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
852 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
853 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -3544,15 +2792,18 @@
2792
2793 /*
2794 ** CAPI3REF: Count The Number Of Rows Modified
2795 ** METHOD: sqlite3
2796 **
2797 ** ^These functions return the number of rows modified, inserted or
2798 ** deleted by the most recently completed INSERT, UPDATE or DELETE
2799 ** statement on the database connection specified by the only parameter.
2800 ** The two functions are identical except for the type of the return value
2801 ** and that if the number of rows modified by the most recent INSERT, UPDATE
2802 ** or DELETE is greater than the maximum value supported by type "int", then
2803 ** the return value of sqlite3_changes() is undefined. ^Executing any other
2804 ** type of SQL statement does not modify the value returned by these functions.
2805 **
2806 ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
2807 ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
2808 ** [foreign key actions] or [REPLACE] constraint resolution are not counted.
2809 **
@@ -3597,20 +2848,25 @@
2848 ** <li> the [changes() SQL function]
2849 ** <li> the [data_version pragma]
2850 ** </ul>
2851 */
2852 SQLITE_API int sqlite3_changes(sqlite3*);
2853 SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
2854
2855 /*
2856 ** CAPI3REF: Total Number Of Rows Modified
2857 ** METHOD: sqlite3
2858 **
2859 ** ^These functions return the total number of rows inserted, modified or
2860 ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
2861 ** since the database connection was opened, including those executed as
2862 ** part of trigger programs. The two functions are identical except for the
2863 ** type of the return value and that if the number of rows modified by the
2864 ** connection exceeds the maximum value supported by type "int", then
2865 ** the return value of sqlite3_total_changes() is undefined. ^Executing
2866 ** any other type of SQL statement does not affect the value returned by
2867 ** sqlite3_total_changes().
2868 **
2869 ** ^Changes made as part of [foreign key actions] are included in the
2870 ** count, but those made as part of REPLACE constraint resolution are
2871 ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
2872 ** are not counted.
@@ -3634,10 +2890,11 @@
2890 ** <li> the [data_version pragma]
2891 ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
2892 ** </ul>
2893 */
2894 SQLITE_API int sqlite3_total_changes(sqlite3*);
2895 SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
2896
2897 /*
2898 ** CAPI3REF: Interrupt A Long-Running Query
2899 ** METHOD: sqlite3
2900 **
@@ -4465,10 +3722,16 @@
3722 ** the default shared cache setting provided by
3723 ** [sqlite3_enable_shared_cache()].)^
3724 **
3725 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
3726 ** <dd>The database filename is not allowed to be a symbolic link</dd>
3727 **
3728 ** [[OPEN_EXCLUSIVE]] ^(<dt>[SQLITE_OPEN_EXCLUSIVE]</dt>
3729 ** <dd>This flag causes the open to fail if the database file already
3730 ** exists. The open will only be success if this flag is used in combination
3731 ** with the SQLITE_OPEN_CREATE and SQLITE_OPEN_READWRITE flags and if
3732 ** the file does not previously exist.</dd>
3733 ** </dl>)^
3734 **
3735 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
3736 ** required combinations shown above optionally combined with other
3737 ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
@@ -5238,16 +4501,21 @@
4501 **
4502 ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
4503 ** are managed by SQLite and are automatically freed when the prepared
4504 ** statement is finalized.
4505 ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
4506 ** is obtained from [sqlite3_malloc()] and must be freed by the application
4507 ** by passing it to [sqlite3_free()].
4508 **
4509 ** ^The sqlite3_normalized_sql() interface is only available if
4510 ** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
4511 */
4512 SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
4513 SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
4514 #ifdef SQLITE_ENABLE_NORMALIZE
4515 SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
4516 #endif
4517
4518 /*
4519 ** CAPI3REF: Determine If An SQL Statement Writes The Database
4520 ** METHOD: sqlite3_stmt
4521 **
@@ -5458,21 +4726,21 @@
4726 ** contain embedded NULs. The result of expressions involving strings
4727 ** with embedded NULs is undefined.
4728 **
4729 ** ^The fifth argument to the BLOB and string binding interfaces controls
4730 ** or indicates the lifetime of the object referenced by the third parameter.
4731 ** These three options exist:
4732 ** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
4733 ** with it may be passed. ^It is called to dispose of the BLOB or string even
4734 ** if the call to the bind API fails, except the destructor is not called if
4735 ** the third parameter is a NULL pointer or the fourth parameter is negative.
4736 ** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
4737 ** the application remains responsible for disposing of the object. ^In this
4738 ** case, the object and the provided pointer to it must remain valid until
4739 ** either the prepared statement is finalized or the same SQL parameter is
4740 ** bound to something else, whichever occurs sooner.
4741 ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4742 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
4743 ** object and pointer to it must remain valid until then. ^SQLite will then
4744 ** manage the lifetime of its private copy.
4745 **
4746 ** ^The sixth argument to sqlite3_bind_text64() must be one of
@@ -10090,12 +9358,13 @@
9358 ** that does not correspond to any valid SQLite error code, the results
9359 ** are undefined.
9360 **
9361 ** A single database handle may have at most a single write-ahead log callback
9362 ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
9363 ** previously registered write-ahead log callback. ^The return value is
9364 ** a copy of the third parameter from the previous call, if any, or 0.
9365 ** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
9366 ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
9367 ** overwrite any prior [sqlite3_wal_hook()] settings.
9368 */
9369 SQLITE_API void *sqlite3_wal_hook(
9370 sqlite3*,
@@ -10957,10 +10226,14 @@
10226 ** if writes on the database cause it to grow larger than M bytes.
10227 **
10228 ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
10229 ** database is currently in a read transaction or is involved in a backup
10230 ** operation.
10231 **
10232 ** It is not possible to deserialized into the TEMP database. If the
10233 ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
10234 ** function returns SQLITE_ERROR.
10235 **
10236 ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
10237 ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
10238 ** [sqlite3_free()] is invoked on argument P prior to returning.
10239 **
@@ -13440,11 +12713,11 @@
12713 /*
12714 ** Include the configuration header output by 'configure' if we're using the
12715 ** autoconf-based build
12716 */
12717 #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
12718 #include "config.h"
12719 #define SQLITECONFIG_H 1
12720 #endif
12721
12722 /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
12723 /************** Begin file sqliteLimit.h *************************************/
@@ -13676,15 +12949,16 @@
12949 ** places. The following macros try to make this explicit.
12950 */
12951 #ifndef __has_extension
12952 # define __has_extension(x) 0 /* compatibility with non-clang compilers */
12953 #endif
12954 #if GCC_VERSION>=4007000 || __has_extension(c_atomic)
12955 # define SQLITE_ATOMIC_INTRINSICS 1
12956 # define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
12957 # define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
12958 #else
12959 # define SQLITE_ATOMIC_INTRINSICS 0
12960 # define AtomicLoad(PTR) (*(PTR))
12961 # define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
12962 #endif
12963
12964 /*
@@ -14598,10 +13872,11 @@
13872 #ifndef SQLITE_PTRSIZE
13873 # if defined(__SIZEOF_POINTER__)
13874 # define SQLITE_PTRSIZE __SIZEOF_POINTER__
13875 # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
13876 defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
13877 (defined(__APPLE__) && defined(__POWERPC__)) || \
13878 (defined(__TOS_AIX__) && !defined(__64BIT__))
13879 # define SQLITE_PTRSIZE 4
13880 # else
13881 # define SQLITE_PTRSIZE 8
13882 # endif
@@ -15349,11 +14624,11 @@
14624 */
14625 #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
14626 #define BTREE_BLOBKEY 2 /* Table has keys only - no data */
14627
14628 SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
14629 SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*);
14630 SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
14631 SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
14632
14633 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
14634 SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
@@ -15473,16 +14748,20 @@
14748 #ifdef SQLITE_ENABLE_CURSOR_HINTS
14749 SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
14750 #endif
14751
14752 SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
14753 SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
14754 BtCursor*,
 
14755 i64 intKey,
14756 int bias,
14757 int *pRes
14758 );
14759 SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
14760 BtCursor*,
14761 UnpackedRecord *pUnKey,
14762 int *pRes
14763 );
14764 SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
14765 SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
14766 SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
14767
@@ -17110,12 +16389,12 @@
16389 u8 mTrace; /* zero or more SQLITE_TRACE flags */
16390 u8 noSharedCache; /* True if no shared-cache backends */
16391 u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
16392 int nextPagesize; /* Pagesize after VACUUM if >0 */
16393 u32 magic; /* Magic number for detect library misuse */
16394 i64 nChange; /* Value returned by sqlite3_changes() */
16395 i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
16396 int aLimit[SQLITE_N_LIMIT]; /* Limits */
16397 int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
16398 struct sqlite3InitInfo { /* Information used during initialization */
16399 Pgno newTnum; /* Rootpage of table being initialized */
16400 u8 iDb; /* Which db file is being initialized */
@@ -17320,10 +16599,12 @@
16599 #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
16600 #define SQLITE_SkipScan 0x00004000 /* Skip-scans */
16601 #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
16602 #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
16603 #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
16604 #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
16605 /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
16606 #define SQLITE_AllOpts 0xffffffff /* All optimizations */
16607
16608 /*
16609 ** Macros for testing whether or not optimizations are enabled or disabled.
16610 */
@@ -17399,16 +16680,17 @@
16680 ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
16681 ** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
16682 ** are assert() statements in the code to verify this.
16683 **
16684 ** Value constraints (enforced via assert()):
16685 ** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
16686 ** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
16687 ** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
16688 ** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
16689 ** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
16690 ** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
16691 ** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
16692 ** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
16693 */
16694 #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
16695 #define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
16696 #define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
@@ -17429,10 +16711,11 @@
16711 #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
16712 #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
16713 #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
16714 #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
16715 #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
16716 #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
16717
16718 /* Identifier numbers for each in-line function */
16719 #define INLINEFUNC_coalesce 0
16720 #define INLINEFUNC_implies_nonnull_row 1
16721 #define INLINEFUNC_expr_implies_expr 2
@@ -17599,22 +16882,45 @@
16882 ** record BLOB generated by the OP_MakeRecord
16883 ** opcode. The storage column index is less than
16884 ** or equal to the table column index. It is
16885 ** equal if and only if there are no VIRTUAL
16886 ** columns to the left.
16887 **
16888 ** Notes on zCnName:
16889 ** The zCnName field stores the name of the column, the datatype of the
16890 ** column, and the collating sequence for the column, in that order, all in
16891 ** a single allocation. Each string is 0x00 terminated. The datatype
16892 ** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
16893 ** collating sequence name is only included if the COLFLAG_HASCOLL bit is
16894 ** set.
16895 */
16896 struct Column {
16897 char *zCnName; /* Name of this column */
16898 unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */
16899 unsigned eType :4; /* One of the standard types */
16900 char affinity; /* One of the SQLITE_AFF_... values */
16901 u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */
16902 u8 hName; /* Column name hash for faster lookup */
16903 u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */
16904 u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
16905 };
16906
16907 /* Allowed values for Column.eType.
16908 **
16909 ** Values must match entries in the global constant arrays
16910 ** sqlite3StdTypeLen[] and sqlite3StdType[]. Each value is one more
16911 ** than the offset into these arrays for the corresponding name.
16912 ** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
16913 */
16914 #define COLTYPE_CUSTOM 0 /* Type appended to zName */
16915 #define COLTYPE_BLOB 1
16916 #define COLTYPE_INT 2
16917 #define COLTYPE_INTEGER 3
16918 #define COLTYPE_REAL 4
16919 #define COLTYPE_TEXT 5
16920 #define SQLITE_N_STDTYPE 5 /* Number of standard types */
16921
16922 /* Allowed values for Column.colFlags.
16923 **
16924 ** Constraints:
16925 ** TF_HasVirtual == COLFLAG_VIRTUAL
16926 ** TF_HasStored == COLFLAG_STORED
@@ -17627,10 +16933,11 @@
16933 #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
16934 #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
16935 #define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
16936 #define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
16937 #define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
16938 #define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */
16939 #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
16940 #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
16941
16942 /*
16943 ** A "Collating Sequence" is defined by an instance of the following
@@ -17756,19 +17063,17 @@
17063 #define SQLITE_VTABRISK_Low 0
17064 #define SQLITE_VTABRISK_Normal 1
17065 #define SQLITE_VTABRISK_High 2
17066
17067 /*
17068 ** The schema for each SQL table, virtual table, and view is represented
17069 ** in memory by an instance of the following structure.
17070 */
17071 struct Table {
17072 char *zName; /* Name of the table or view */
17073 Column *aCol; /* Information about each column */
17074 Index *pIndex; /* List of SQL indexes on this table. */
 
 
17075 char *zColAff; /* String defining the affinity of each column */
17076 ExprList *pCheck; /* All CHECK constraints */
17077 /* ... also used as column name list in a VIEW */
17078 Pgno tnum; /* Root BTree page for this table */
17079 u32 nTabRef; /* Number of pointers to this Table */
@@ -17780,19 +17085,28 @@
17085 LogEst szTabRow; /* Estimated size of each table row in bytes */
17086 #ifdef SQLITE_ENABLE_COSTMULT
17087 LogEst costMult; /* Cost multiplier for using this table */
17088 #endif
17089 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
17090 u8 eTabType; /* 0: normal, 1: virtual, 2: view */
17091 union {
17092 struct { /* Used by ordinary tables: */
17093 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
17094 FKey *pFKey; /* Linked list of all foreign keys in this table */
17095 ExprList *pDfltList; /* DEFAULT clauses on various columns.
17096 ** Or the AS clause for generated columns. */
17097 } tab;
17098 struct { /* Used by views: */
17099 Select *pSelect; /* View definition */
17100 } view;
17101 struct { /* Used by virtual tables only: */
17102 int nArg; /* Number of arguments to the module */
17103 char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */
17104 VTable *p; /* List of VTable objects. */
17105 } vtab;
17106 } u;
17107 Trigger *pTrigger; /* List of triggers on this object */
17108 Schema *pSchema; /* Schema that contains this table */
17109 };
17110
17111 /*
17112 ** Allowed values for Table.tabFlags.
@@ -17807,38 +17121,48 @@
17121 **
17122 ** TF_HasVirtual == COLFLAG_VIRTUAL
17123 ** TF_HasStored == COLFLAG_STORED
17124 ** TF_HasHidden == COLFLAG_HIDDEN
17125 */
17126 #define TF_Readonly 0x00000001 /* Read-only system table */
17127 #define TF_HasHidden 0x00000002 /* Has one or more hidden columns */
17128 #define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */
17129 #define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */
17130 #define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */
17131 #define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */
17132 #define TF_HasStored 0x00000040 /* Has one or more STORED columns */
17133 #define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
17134 #define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
17135 #define TF_StatsUsed 0x00000100 /* Query planner decisions affected by
17136 ** Index.aiRowLogEst[] values */
17137 #define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
17138 #define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
17139 #define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
17140 #define TF_Shadow 0x00001000 /* True for a shadow table */
17141 #define TF_HasStat4 0x00002000 /* STAT4 info available for this table */
17142 #define TF_Ephemeral 0x00004000 /* An ephemeral table */
17143 #define TF_Eponymous 0x00008000 /* An eponymous virtual table */
17144
17145 /*
17146 ** Allowed values for Table.eTabType
17147 */
17148 #define TABTYP_NORM 0 /* Ordinary table */
17149 #define TABTYP_VTAB 1 /* Virtual table */
17150 #define TABTYP_VIEW 2 /* A view */
17151
17152 #define IsView(X) ((X)->eTabType==TABTYP_VIEW)
17153 #define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM)
17154
17155 /*
17156 ** Test to see whether or not a table is a virtual table. This is
17157 ** done as a macro so that it will be optimized out when virtual
17158 ** table support is omitted from the build.
17159 */
17160 #ifndef SQLITE_OMIT_VIRTUALTABLE
17161 # define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB)
17162 # define ExprIsVtab(X) \
17163 ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB)
17164 #else
17165 # define IsVirtual(X) 0
17166 # define ExprIsVtab(X) 0
17167 #endif
17168
@@ -18664,35 +17988,37 @@
17988
17989 /*
17990 ** Allowed values for the NameContext, ncFlags field.
17991 **
17992 ** Value constraints (all checked via assert()):
17993 ** NC_HasAgg == SF_HasAgg == EP_Agg
17994 ** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
17995 ** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
17996 ** NC_HasWin == EP_Win
17997 **
17998 */
17999 #define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
18000 #define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
18001 #define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
18002 #define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
18003 #define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
18004 #define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
18005 #define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
18006 #define NC_VarSelect 0x000040 /* A correlated subquery has been seen */
18007 #define NC_UEList 0x000080 /* True if uNC.pEList is used */
18008 #define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
18009 #define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
18010 #define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
18011 #define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
18012 #define NC_Complex 0x002000 /* True if a function or subquery seen */
18013 #define NC_AllowWin 0x004000 /* Window functions are allowed here */
18014 #define NC_HasWin 0x008000 /* One or more window functions seen */
18015 #define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
18016 #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
18017 #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
18018 #define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
18019 #define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
18020
18021 /*
18022 ** An instance of the following object describes a single ON CONFLICT
18023 ** clause in an upsert.
18024 **
@@ -18771,13 +18097,14 @@
18097 /*
18098 ** Allowed values for Select.selFlags. The "SF" prefix stands for
18099 ** "Select Flag".
18100 **
18101 ** Value constraints (all checked via assert())
18102 ** SF_HasAgg == NC_HasAgg
18103 ** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
18104 ** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
18105 ** SF_FixedLimit == WHERE_USE_LIMIT
18106 */
18107 #define SF_Distinct 0x0000001 /* Output should be DISTINCT */
18108 #define SF_All 0x0000002 /* Includes the ALL keyword */
18109 #define SF_Resolved 0x0000004 /* Identifiers have been resolved */
18110 #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
@@ -18798,14 +18125,15 @@
18125 #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
18126 #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
18127 #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
18128 #define SF_View 0x0200000 /* SELECT statement is a view */
18129 #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
18130 #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
18131 #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
18132 #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
18133 #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
18134 #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
18135
18136 /*
18137 ** The results of a SELECT can be distributed in several ways, as defined
18138 ** by one of the following macros. The "SRT" prefix means "SELECT Result
18139 ** Type".
@@ -19884,10 +19212,11 @@
19212 SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
19213 SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
19214 SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
19215 SQLITE_PRIVATE void sqlite3Dequote(char*);
19216 SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
19217 SQLITE_PRIVATE void sqlite3DequoteToken(Token*);
19218 SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
19219 SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
19220 SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
19221 SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
19222 SQLITE_PRIVATE int sqlite3GetTempReg(Parse*);
@@ -19911,10 +19240,11 @@
19240 SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
19241 SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
19242 SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
19243 SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
19244 SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
19245 SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
19246 SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
19247 SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
19248 SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
19249 SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
19250 SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
@@ -19928,10 +19258,14 @@
19258 #endif
19259 SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
19260 SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
19261 SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
19262 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
19263 SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
19264 SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*);
19265 SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
19266 SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*);
19267 SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
19268 SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
19269 SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
19270 SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
19271 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -19949,11 +19283,11 @@
19283 #if SQLITE_ENABLE_HIDDEN_COLUMNS
19284 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
19285 #else
19286 # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
19287 #endif
19288 SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token,Token);
19289 SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
19290 SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
19291 SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
19292 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
19293 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
@@ -20066,11 +19400,11 @@
19400 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
19401 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
19402 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
19403 SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
19404 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
19405 SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
19406 #endif
19407 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
19408 SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
19409 SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
19410 SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
@@ -20329,11 +19663,11 @@
19663 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
19664 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
19665 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
19666 SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
19667 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
19668 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64);
19669 SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
19670 SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
19671 SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
19672 SQLITE_PRIVATE int sqlite3AbsInt32(int);
19673 #ifdef SQLITE_ENABLE_8_3_NAMES
@@ -20359,10 +19693,13 @@
19693 SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
19694 SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
19695 #ifndef SQLITE_AMALGAMATION
19696 SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
19697 SQLITE_PRIVATE const char sqlite3StrBINARY[];
19698 SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[];
19699 SQLITE_PRIVATE const char sqlite3StdTypeAffinity[];
19700 SQLITE_PRIVATE const char *sqlite3StdType[];
19701 SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
19702 SQLITE_PRIVATE const unsigned char *sqlite3aLTb;
19703 SQLITE_PRIVATE const unsigned char *sqlite3aEQb;
19704 SQLITE_PRIVATE const unsigned char *sqlite3aGTb;
19705 SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
@@ -20779,20 +20116,1004 @@
20116 #endif
20117
20118 SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr);
20119 SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr);
20120 SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
20121 SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
20122 SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
20123
20124 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
20125 SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
20126 #endif
20127
20128 #endif /* SQLITEINT_H */
20129
20130 /************** End of sqliteInt.h *******************************************/
20131 /************** Begin file os_common.h ***************************************/
20132 /*
20133 ** 2004 May 22
20134 **
20135 ** The author disclaims copyright to this source code. In place of
20136 ** a legal notice, here is a blessing:
20137 **
20138 ** May you do good and not evil.
20139 ** May you find forgiveness for yourself and forgive others.
20140 ** May you share freely, never taking more than you give.
20141 **
20142 ******************************************************************************
20143 **
20144 ** This file contains macros and a little bit of code that is common to
20145 ** all of the platform-specific files (os_*.c) and is #included into those
20146 ** files.
20147 **
20148 ** This file should be #included by the os_*.c files only. It is not a
20149 ** general purpose header file.
20150 */
20151 #ifndef _OS_COMMON_H_
20152 #define _OS_COMMON_H_
20153
20154 /*
20155 ** At least two bugs have slipped in because we changed the MEMORY_DEBUG
20156 ** macro to SQLITE_DEBUG and some older makefiles have not yet made the
20157 ** switch. The following code should catch this problem at compile-time.
20158 */
20159 #ifdef MEMORY_DEBUG
20160 # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
20161 #endif
20162
20163 /*
20164 ** Macros for performance tracing. Normally turned off. Only works
20165 ** on i486 hardware.
20166 */
20167 #ifdef SQLITE_PERFORMANCE_TRACE
20168
20169 /*
20170 ** hwtime.h contains inline assembler code for implementing
20171 ** high-performance timing routines.
20172 */
20173 /************** Include hwtime.h in the middle of os_common.h ****************/
20174 /************** Begin file hwtime.h ******************************************/
20175 /*
20176 ** 2008 May 27
20177 **
20178 ** The author disclaims copyright to this source code. In place of
20179 ** a legal notice, here is a blessing:
20180 **
20181 ** May you do good and not evil.
20182 ** May you find forgiveness for yourself and forgive others.
20183 ** May you share freely, never taking more than you give.
20184 **
20185 ******************************************************************************
20186 **
20187 ** This file contains inline asm code for retrieving "high-performance"
20188 ** counters for x86 and x86_64 class CPUs.
20189 */
20190 #ifndef SQLITE_HWTIME_H
20191 #define SQLITE_HWTIME_H
20192
20193 /*
20194 ** The following routine only works on pentium-class (or newer) processors.
20195 ** It uses the RDTSC opcode to read the cycle count value out of the
20196 ** processor and returns that value. This can be used for high-res
20197 ** profiling.
20198 */
20199 #if !defined(__STRICT_ANSI__) && \
20200 (defined(__GNUC__) || defined(_MSC_VER)) && \
20201 (defined(i386) || defined(__i386__) || defined(_M_IX86))
20202
20203 #if defined(__GNUC__)
20204
20205 __inline__ sqlite_uint64 sqlite3Hwtime(void){
20206 unsigned int lo, hi;
20207 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
20208 return (sqlite_uint64)hi << 32 | lo;
20209 }
20210
20211 #elif defined(_MSC_VER)
20212
20213 __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
20214 __asm {
20215 rdtsc
20216 ret ; return value at EDX:EAX
20217 }
20218 }
20219
20220 #endif
20221
20222 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
20223
20224 __inline__ sqlite_uint64 sqlite3Hwtime(void){
20225 unsigned long val;
20226 __asm__ __volatile__ ("rdtsc" : "=A" (val));
20227 return val;
20228 }
20229
20230 #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
20231
20232 __inline__ sqlite_uint64 sqlite3Hwtime(void){
20233 unsigned long long retval;
20234 unsigned long junk;
20235 __asm__ __volatile__ ("\n\
20236 1: mftbu %1\n\
20237 mftb %L0\n\
20238 mftbu %0\n\
20239 cmpw %0,%1\n\
20240 bne 1b"
20241 : "=r" (retval), "=r" (junk));
20242 return retval;
20243 }
20244
20245 #else
20246
20247 /*
20248 ** asm() is needed for hardware timing support. Without asm(),
20249 ** disable the sqlite3Hwtime() routine.
20250 **
20251 ** sqlite3Hwtime() is only used for some obscure debugging
20252 ** and analysis configurations, not in any deliverable, so this
20253 ** should not be a great loss.
20254 */
20255 SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
20256
20257 #endif
20258
20259 #endif /* !defined(SQLITE_HWTIME_H) */
20260
20261 /************** End of hwtime.h **********************************************/
20262 /************** Continuing where we left off in os_common.h ******************/
20263
20264 static sqlite_uint64 g_start;
20265 static sqlite_uint64 g_elapsed;
20266 #define TIMER_START g_start=sqlite3Hwtime()
20267 #define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
20268 #define TIMER_ELAPSED g_elapsed
20269 #else
20270 #define TIMER_START
20271 #define TIMER_END
20272 #define TIMER_ELAPSED ((sqlite_uint64)0)
20273 #endif
20274
20275 /*
20276 ** If we compile with the SQLITE_TEST macro set, then the following block
20277 ** of code will give us the ability to simulate a disk I/O error. This
20278 ** is used for testing the I/O recovery logic.
20279 */
20280 #if defined(SQLITE_TEST)
20281 SQLITE_API extern int sqlite3_io_error_hit;
20282 SQLITE_API extern int sqlite3_io_error_hardhit;
20283 SQLITE_API extern int sqlite3_io_error_pending;
20284 SQLITE_API extern int sqlite3_io_error_persist;
20285 SQLITE_API extern int sqlite3_io_error_benign;
20286 SQLITE_API extern int sqlite3_diskfull_pending;
20287 SQLITE_API extern int sqlite3_diskfull;
20288 #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
20289 #define SimulateIOError(CODE) \
20290 if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
20291 || sqlite3_io_error_pending-- == 1 ) \
20292 { local_ioerr(); CODE; }
20293 static void local_ioerr(){
20294 IOTRACE(("IOERR\n"));
20295 sqlite3_io_error_hit++;
20296 if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
20297 }
20298 #define SimulateDiskfullError(CODE) \
20299 if( sqlite3_diskfull_pending ){ \
20300 if( sqlite3_diskfull_pending == 1 ){ \
20301 local_ioerr(); \
20302 sqlite3_diskfull = 1; \
20303 sqlite3_io_error_hit = 1; \
20304 CODE; \
20305 }else{ \
20306 sqlite3_diskfull_pending--; \
20307 } \
20308 }
20309 #else
20310 #define SimulateIOErrorBenign(X)
20311 #define SimulateIOError(A)
20312 #define SimulateDiskfullError(A)
20313 #endif /* defined(SQLITE_TEST) */
20314
20315 /*
20316 ** When testing, keep a count of the number of open files.
20317 */
20318 #if defined(SQLITE_TEST)
20319 SQLITE_API extern int sqlite3_open_file_count;
20320 #define OpenCounter(X) sqlite3_open_file_count+=(X)
20321 #else
20322 #define OpenCounter(X)
20323 #endif /* defined(SQLITE_TEST) */
20324
20325 #endif /* !defined(_OS_COMMON_H_) */
20326
20327 /************** End of os_common.h *******************************************/
20328 /************** Begin file ctime.c *******************************************/
20329 /*
20330 ** 2010 February 23
20331 **
20332 ** The author disclaims copyright to this source code. In place of
20333 ** a legal notice, here is a blessing:
20334 **
20335 ** May you do good and not evil.
20336 ** May you find forgiveness for yourself and forgive others.
20337 ** May you share freely, never taking more than you give.
20338 **
20339 *************************************************************************
20340 **
20341 ** This file implements routines used to report what compile-time options
20342 ** SQLite was built with.
20343 */
20344 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
20345
20346 /*
20347 ** Include the configuration header output by 'configure' if we're using the
20348 ** autoconf-based build
20349 */
20350 #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
20351 /* #include "config.h" */
20352 #define SQLITECONFIG_H 1
20353 #endif
20354
20355 /* These macros are provided to "stringify" the value of the define
20356 ** for those options in which the value is meaningful. */
20357 #define CTIMEOPT_VAL_(opt) #opt
20358 #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
20359
20360 /* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
20361 ** option requires a separate macro because legal values contain a single
20362 ** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
20363 #define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
20364 #define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
20365 /* #include "sqliteInt.h" */
20366
20367 /*
20368 ** An array of names of all compile-time options. This array should
20369 ** be sorted A-Z.
20370 **
20371 ** This array looks large, but in a typical installation actually uses
20372 ** only a handful of compile-time options, so most times this array is usually
20373 ** rather short and uses little memory space.
20374 */
20375 static const char * const sqlite3azCompileOpt[] = {
20376
20377 /*
20378 ** BEGIN CODE GENERATED BY tool/mkctime.tcl
20379 */
20380 #ifdef SQLITE_32BIT_ROWID
20381 "32BIT_ROWID",
20382 #endif
20383 #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
20384 "4_BYTE_ALIGNED_MALLOC",
20385 #endif
20386 #ifdef SQLITE_64BIT_STATS
20387 "64BIT_STATS",
20388 #endif
20389 #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
20390 # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
20391 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
20392 # endif
20393 #endif
20394 #ifdef SQLITE_ALLOW_URI_AUTHORITY
20395 "ALLOW_URI_AUTHORITY",
20396 #endif
20397 #ifdef SQLITE_ATOMIC_INTRINSICS
20398 "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
20399 #endif
20400 #ifdef SQLITE_BITMASK_TYPE
20401 "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
20402 #endif
20403 #ifdef SQLITE_BUG_COMPATIBLE_20160819
20404 "BUG_COMPATIBLE_20160819",
20405 #endif
20406 #ifdef SQLITE_CASE_SENSITIVE_LIKE
20407 "CASE_SENSITIVE_LIKE",
20408 #endif
20409 #ifdef SQLITE_CHECK_PAGES
20410 "CHECK_PAGES",
20411 #endif
20412 #if defined(__clang__) && defined(__clang_major__)
20413 "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
20414 CTIMEOPT_VAL(__clang_minor__) "."
20415 CTIMEOPT_VAL(__clang_patchlevel__),
20416 #elif defined(_MSC_VER)
20417 "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
20418 #elif defined(__GNUC__) && defined(__VERSION__)
20419 "COMPILER=gcc-" __VERSION__,
20420 #endif
20421 #ifdef SQLITE_COVERAGE_TEST
20422 "COVERAGE_TEST",
20423 #endif
20424 #ifdef SQLITE_DEBUG
20425 "DEBUG",
20426 #endif
20427 #ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
20428 "DEFAULT_AUTOMATIC_INDEX",
20429 #endif
20430 #ifdef SQLITE_DEFAULT_AUTOVACUUM
20431 "DEFAULT_AUTOVACUUM",
20432 #endif
20433 #ifdef SQLITE_DEFAULT_CACHE_SIZE
20434 "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
20435 #endif
20436 #ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
20437 "DEFAULT_CKPTFULLFSYNC",
20438 #endif
20439 #ifdef SQLITE_DEFAULT_FILE_FORMAT
20440 "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
20441 #endif
20442 #ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
20443 "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
20444 #endif
20445 #ifdef SQLITE_DEFAULT_FOREIGN_KEYS
20446 "DEFAULT_FOREIGN_KEYS",
20447 #endif
20448 #ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
20449 "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
20450 #endif
20451 #ifdef SQLITE_DEFAULT_LOCKING_MODE
20452 "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
20453 #endif
20454 #ifdef SQLITE_DEFAULT_LOOKASIDE
20455 "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
20456 #endif
20457 #ifdef SQLITE_DEFAULT_MEMSTATUS
20458 # if SQLITE_DEFAULT_MEMSTATUS != 1
20459 "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
20460 # endif
20461 #endif
20462 #ifdef SQLITE_DEFAULT_MMAP_SIZE
20463 "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
20464 #endif
20465 #ifdef SQLITE_DEFAULT_PAGE_SIZE
20466 "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
20467 #endif
20468 #ifdef SQLITE_DEFAULT_PCACHE_INITSZ
20469 "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
20470 #endif
20471 #ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
20472 "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
20473 #endif
20474 #ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
20475 "DEFAULT_RECURSIVE_TRIGGERS",
20476 #endif
20477 #ifdef SQLITE_DEFAULT_ROWEST
20478 "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
20479 #endif
20480 #ifdef SQLITE_DEFAULT_SECTOR_SIZE
20481 "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
20482 #endif
20483 #ifdef SQLITE_DEFAULT_SYNCHRONOUS
20484 "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
20485 #endif
20486 #ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
20487 "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
20488 #endif
20489 #ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
20490 "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
20491 #endif
20492 #ifdef SQLITE_DEFAULT_WORKER_THREADS
20493 "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
20494 #endif
20495 #ifdef SQLITE_DIRECT_OVERFLOW_READ
20496 "DIRECT_OVERFLOW_READ",
20497 #endif
20498 #ifdef SQLITE_DISABLE_DIRSYNC
20499 "DISABLE_DIRSYNC",
20500 #endif
20501 #ifdef SQLITE_DISABLE_FTS3_UNICODE
20502 "DISABLE_FTS3_UNICODE",
20503 #endif
20504 #ifdef SQLITE_DISABLE_FTS4_DEFERRED
20505 "DISABLE_FTS4_DEFERRED",
20506 #endif
20507 #ifdef SQLITE_DISABLE_INTRINSIC
20508 "DISABLE_INTRINSIC",
20509 #endif
20510 #ifdef SQLITE_DISABLE_LFS
20511 "DISABLE_LFS",
20512 #endif
20513 #ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
20514 "DISABLE_PAGECACHE_OVERFLOW_STATS",
20515 #endif
20516 #ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
20517 "DISABLE_SKIPAHEAD_DISTINCT",
20518 #endif
20519 #ifdef SQLITE_ENABLE_8_3_NAMES
20520 "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
20521 #endif
20522 #ifdef SQLITE_ENABLE_API_ARMOR
20523 "ENABLE_API_ARMOR",
20524 #endif
20525 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
20526 "ENABLE_ATOMIC_WRITE",
20527 #endif
20528 #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
20529 "ENABLE_BATCH_ATOMIC_WRITE",
20530 #endif
20531 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
20532 "ENABLE_BYTECODE_VTAB",
20533 #endif
20534 #ifdef SQLITE_ENABLE_CEROD
20535 "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
20536 #endif
20537 #ifdef SQLITE_ENABLE_COLUMN_METADATA
20538 "ENABLE_COLUMN_METADATA",
20539 #endif
20540 #ifdef SQLITE_ENABLE_COLUMN_USED_MASK
20541 "ENABLE_COLUMN_USED_MASK",
20542 #endif
20543 #ifdef SQLITE_ENABLE_COSTMULT
20544 "ENABLE_COSTMULT",
20545 #endif
20546 #ifdef SQLITE_ENABLE_CURSOR_HINTS
20547 "ENABLE_CURSOR_HINTS",
20548 #endif
20549 #ifdef SQLITE_ENABLE_DBPAGE_VTAB
20550 "ENABLE_DBPAGE_VTAB",
20551 #endif
20552 #ifdef SQLITE_ENABLE_DBSTAT_VTAB
20553 "ENABLE_DBSTAT_VTAB",
20554 #endif
20555 #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
20556 "ENABLE_EXPENSIVE_ASSERT",
20557 #endif
20558 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
20559 "ENABLE_EXPLAIN_COMMENTS",
20560 #endif
20561 #ifdef SQLITE_ENABLE_FTS3
20562 "ENABLE_FTS3",
20563 #endif
20564 #ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
20565 "ENABLE_FTS3_PARENTHESIS",
20566 #endif
20567 #ifdef SQLITE_ENABLE_FTS3_TOKENIZER
20568 "ENABLE_FTS3_TOKENIZER",
20569 #endif
20570 #ifdef SQLITE_ENABLE_FTS4
20571 "ENABLE_FTS4",
20572 #endif
20573 #ifdef SQLITE_ENABLE_FTS5
20574 "ENABLE_FTS5",
20575 #endif
20576 #ifdef SQLITE_ENABLE_GEOPOLY
20577 "ENABLE_GEOPOLY",
20578 #endif
20579 #ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
20580 "ENABLE_HIDDEN_COLUMNS",
20581 #endif
20582 #ifdef SQLITE_ENABLE_ICU
20583 "ENABLE_ICU",
20584 #endif
20585 #ifdef SQLITE_ENABLE_IOTRACE
20586 "ENABLE_IOTRACE",
20587 #endif
20588 #ifdef SQLITE_ENABLE_JSON1
20589 "ENABLE_JSON1",
20590 #endif
20591 #ifdef SQLITE_ENABLE_LOAD_EXTENSION
20592 "ENABLE_LOAD_EXTENSION",
20593 #endif
20594 #ifdef SQLITE_ENABLE_LOCKING_STYLE
20595 "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
20596 #endif
20597 #ifdef SQLITE_ENABLE_MATH_FUNCTIONS
20598 "ENABLE_MATH_FUNCTIONS",
20599 #endif
20600 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
20601 "ENABLE_MEMORY_MANAGEMENT",
20602 #endif
20603 #ifdef SQLITE_ENABLE_MEMSYS3
20604 "ENABLE_MEMSYS3",
20605 #endif
20606 #ifdef SQLITE_ENABLE_MEMSYS5
20607 "ENABLE_MEMSYS5",
20608 #endif
20609 #ifdef SQLITE_ENABLE_MULTIPLEX
20610 "ENABLE_MULTIPLEX",
20611 #endif
20612 #ifdef SQLITE_ENABLE_NORMALIZE
20613 "ENABLE_NORMALIZE",
20614 #endif
20615 #ifdef SQLITE_ENABLE_NULL_TRIM
20616 "ENABLE_NULL_TRIM",
20617 #endif
20618 #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
20619 "ENABLE_OFFSET_SQL_FUNC",
20620 #endif
20621 #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
20622 "ENABLE_OVERSIZE_CELL_CHECK",
20623 #endif
20624 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
20625 "ENABLE_PREUPDATE_HOOK",
20626 #endif
20627 #ifdef SQLITE_ENABLE_QPSG
20628 "ENABLE_QPSG",
20629 #endif
20630 #ifdef SQLITE_ENABLE_RBU
20631 "ENABLE_RBU",
20632 #endif
20633 #ifdef SQLITE_ENABLE_RTREE
20634 "ENABLE_RTREE",
20635 #endif
20636 #ifdef SQLITE_ENABLE_SELECTTRACE
20637 "ENABLE_SELECTTRACE",
20638 #endif
20639 #ifdef SQLITE_ENABLE_SESSION
20640 "ENABLE_SESSION",
20641 #endif
20642 #ifdef SQLITE_ENABLE_SNAPSHOT
20643 "ENABLE_SNAPSHOT",
20644 #endif
20645 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
20646 "ENABLE_SORTER_REFERENCES",
20647 #endif
20648 #ifdef SQLITE_ENABLE_SQLLOG
20649 "ENABLE_SQLLOG",
20650 #endif
20651 #ifdef SQLITE_ENABLE_STAT4
20652 "ENABLE_STAT4",
20653 #endif
20654 #ifdef SQLITE_ENABLE_STMTVTAB
20655 "ENABLE_STMTVTAB",
20656 #endif
20657 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
20658 "ENABLE_STMT_SCANSTATUS",
20659 #endif
20660 #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
20661 "ENABLE_UNKNOWN_SQL_FUNCTION",
20662 #endif
20663 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
20664 "ENABLE_UNLOCK_NOTIFY",
20665 #endif
20666 #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
20667 "ENABLE_UPDATE_DELETE_LIMIT",
20668 #endif
20669 #ifdef SQLITE_ENABLE_URI_00_ERROR
20670 "ENABLE_URI_00_ERROR",
20671 #endif
20672 #ifdef SQLITE_ENABLE_VFSTRACE
20673 "ENABLE_VFSTRACE",
20674 #endif
20675 #ifdef SQLITE_ENABLE_WHERETRACE
20676 "ENABLE_WHERETRACE",
20677 #endif
20678 #ifdef SQLITE_ENABLE_ZIPVFS
20679 "ENABLE_ZIPVFS",
20680 #endif
20681 #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
20682 "EXPLAIN_ESTIMATED_ROWS",
20683 #endif
20684 #ifdef SQLITE_EXTRA_IFNULLROW
20685 "EXTRA_IFNULLROW",
20686 #endif
20687 #ifdef SQLITE_EXTRA_INIT
20688 "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
20689 #endif
20690 #ifdef SQLITE_EXTRA_SHUTDOWN
20691 "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
20692 #endif
20693 #ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
20694 "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
20695 #endif
20696 #ifdef SQLITE_FTS5_ENABLE_TEST_MI
20697 "FTS5_ENABLE_TEST_MI",
20698 #endif
20699 #ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
20700 "FTS5_NO_WITHOUT_ROWID",
20701 #endif
20702 #if HAVE_ISNAN || SQLITE_HAVE_ISNAN
20703 "HAVE_ISNAN",
20704 #endif
20705 #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
20706 # if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
20707 "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
20708 # endif
20709 #endif
20710 #ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
20711 "IGNORE_AFP_LOCK_ERRORS",
20712 #endif
20713 #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
20714 "IGNORE_FLOCK_LOCK_ERRORS",
20715 #endif
20716 #ifdef SQLITE_INLINE_MEMCPY
20717 "INLINE_MEMCPY",
20718 #endif
20719 #ifdef SQLITE_INT64_TYPE
20720 "INT64_TYPE",
20721 #endif
20722 #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
20723 "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
20724 #endif
20725 #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
20726 "LIKE_DOESNT_MATCH_BLOBS",
20727 #endif
20728 #ifdef SQLITE_LOCK_TRACE
20729 "LOCK_TRACE",
20730 #endif
20731 #ifdef SQLITE_LOG_CACHE_SPILL
20732 "LOG_CACHE_SPILL",
20733 #endif
20734 #ifdef SQLITE_MALLOC_SOFT_LIMIT
20735 "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
20736 #endif
20737 #ifdef SQLITE_MAX_ATTACHED
20738 "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
20739 #endif
20740 #ifdef SQLITE_MAX_COLUMN
20741 "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
20742 #endif
20743 #ifdef SQLITE_MAX_COMPOUND_SELECT
20744 "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
20745 #endif
20746 #ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
20747 "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
20748 #endif
20749 #ifdef SQLITE_MAX_EXPR_DEPTH
20750 "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
20751 #endif
20752 #ifdef SQLITE_MAX_FUNCTION_ARG
20753 "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
20754 #endif
20755 #ifdef SQLITE_MAX_LENGTH
20756 "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
20757 #endif
20758 #ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
20759 "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
20760 #endif
20761 #ifdef SQLITE_MAX_MEMORY
20762 "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
20763 #endif
20764 #ifdef SQLITE_MAX_MMAP_SIZE
20765 "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
20766 #endif
20767 #ifdef SQLITE_MAX_MMAP_SIZE_
20768 "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
20769 #endif
20770 #ifdef SQLITE_MAX_PAGE_COUNT
20771 "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
20772 #endif
20773 #ifdef SQLITE_MAX_PAGE_SIZE
20774 "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
20775 #endif
20776 #ifdef SQLITE_MAX_SCHEMA_RETRY
20777 "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
20778 #endif
20779 #ifdef SQLITE_MAX_SQL_LENGTH
20780 "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
20781 #endif
20782 #ifdef SQLITE_MAX_TRIGGER_DEPTH
20783 "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
20784 #endif
20785 #ifdef SQLITE_MAX_VARIABLE_NUMBER
20786 "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
20787 #endif
20788 #ifdef SQLITE_MAX_VDBE_OP
20789 "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
20790 #endif
20791 #ifdef SQLITE_MAX_WORKER_THREADS
20792 "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
20793 #endif
20794 #ifdef SQLITE_MEMDEBUG
20795 "MEMDEBUG",
20796 #endif
20797 #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
20798 "MIXED_ENDIAN_64BIT_FLOAT",
20799 #endif
20800 #ifdef SQLITE_MMAP_READWRITE
20801 "MMAP_READWRITE",
20802 #endif
20803 #ifdef SQLITE_MUTEX_NOOP
20804 "MUTEX_NOOP",
20805 #endif
20806 #ifdef SQLITE_MUTEX_OMIT
20807 "MUTEX_OMIT",
20808 #endif
20809 #ifdef SQLITE_MUTEX_PTHREADS
20810 "MUTEX_PTHREADS",
20811 #endif
20812 #ifdef SQLITE_MUTEX_W32
20813 "MUTEX_W32",
20814 #endif
20815 #ifdef SQLITE_NEED_ERR_NAME
20816 "NEED_ERR_NAME",
20817 #endif
20818 #ifdef SQLITE_NO_SYNC
20819 "NO_SYNC",
20820 #endif
20821 #ifdef SQLITE_OMIT_ALTERTABLE
20822 "OMIT_ALTERTABLE",
20823 #endif
20824 #ifdef SQLITE_OMIT_ANALYZE
20825 "OMIT_ANALYZE",
20826 #endif
20827 #ifdef SQLITE_OMIT_ATTACH
20828 "OMIT_ATTACH",
20829 #endif
20830 #ifdef SQLITE_OMIT_AUTHORIZATION
20831 "OMIT_AUTHORIZATION",
20832 #endif
20833 #ifdef SQLITE_OMIT_AUTOINCREMENT
20834 "OMIT_AUTOINCREMENT",
20835 #endif
20836 #ifdef SQLITE_OMIT_AUTOINIT
20837 "OMIT_AUTOINIT",
20838 #endif
20839 #ifdef SQLITE_OMIT_AUTOMATIC_INDEX
20840 "OMIT_AUTOMATIC_INDEX",
20841 #endif
20842 #ifdef SQLITE_OMIT_AUTORESET
20843 "OMIT_AUTORESET",
20844 #endif
20845 #ifdef SQLITE_OMIT_AUTOVACUUM
20846 "OMIT_AUTOVACUUM",
20847 #endif
20848 #ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
20849 "OMIT_BETWEEN_OPTIMIZATION",
20850 #endif
20851 #ifdef SQLITE_OMIT_BLOB_LITERAL
20852 "OMIT_BLOB_LITERAL",
20853 #endif
20854 #ifdef SQLITE_OMIT_CAST
20855 "OMIT_CAST",
20856 #endif
20857 #ifdef SQLITE_OMIT_CHECK
20858 "OMIT_CHECK",
20859 #endif
20860 #ifdef SQLITE_OMIT_COMPLETE
20861 "OMIT_COMPLETE",
20862 #endif
20863 #ifdef SQLITE_OMIT_COMPOUND_SELECT
20864 "OMIT_COMPOUND_SELECT",
20865 #endif
20866 #ifdef SQLITE_OMIT_CONFLICT_CLAUSE
20867 "OMIT_CONFLICT_CLAUSE",
20868 #endif
20869 #ifdef SQLITE_OMIT_CTE
20870 "OMIT_CTE",
20871 #endif
20872 #if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
20873 "OMIT_DATETIME_FUNCS",
20874 #endif
20875 #ifdef SQLITE_OMIT_DECLTYPE
20876 "OMIT_DECLTYPE",
20877 #endif
20878 #ifdef SQLITE_OMIT_DEPRECATED
20879 "OMIT_DEPRECATED",
20880 #endif
20881 #ifdef SQLITE_OMIT_DESERIALIZE
20882 "OMIT_DESERIALIZE",
20883 #endif
20884 #ifdef SQLITE_OMIT_DISKIO
20885 "OMIT_DISKIO",
20886 #endif
20887 #ifdef SQLITE_OMIT_EXPLAIN
20888 "OMIT_EXPLAIN",
20889 #endif
20890 #ifdef SQLITE_OMIT_FLAG_PRAGMAS
20891 "OMIT_FLAG_PRAGMAS",
20892 #endif
20893 #ifdef SQLITE_OMIT_FLOATING_POINT
20894 "OMIT_FLOATING_POINT",
20895 #endif
20896 #ifdef SQLITE_OMIT_FOREIGN_KEY
20897 "OMIT_FOREIGN_KEY",
20898 #endif
20899 #ifdef SQLITE_OMIT_GET_TABLE
20900 "OMIT_GET_TABLE",
20901 #endif
20902 #ifdef SQLITE_OMIT_HEX_INTEGER
20903 "OMIT_HEX_INTEGER",
20904 #endif
20905 #ifdef SQLITE_OMIT_INCRBLOB
20906 "OMIT_INCRBLOB",
20907 #endif
20908 #ifdef SQLITE_OMIT_INTEGRITY_CHECK
20909 "OMIT_INTEGRITY_CHECK",
20910 #endif
20911 #ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
20912 "OMIT_INTROSPECTION_PRAGMAS",
20913 #endif
20914 #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
20915 "OMIT_LIKE_OPTIMIZATION",
20916 #endif
20917 #ifdef SQLITE_OMIT_LOAD_EXTENSION
20918 "OMIT_LOAD_EXTENSION",
20919 #endif
20920 #ifdef SQLITE_OMIT_LOCALTIME
20921 "OMIT_LOCALTIME",
20922 #endif
20923 #ifdef SQLITE_OMIT_LOOKASIDE
20924 "OMIT_LOOKASIDE",
20925 #endif
20926 #ifdef SQLITE_OMIT_MEMORYDB
20927 "OMIT_MEMORYDB",
20928 #endif
20929 #ifdef SQLITE_OMIT_OR_OPTIMIZATION
20930 "OMIT_OR_OPTIMIZATION",
20931 #endif
20932 #ifdef SQLITE_OMIT_PAGER_PRAGMAS
20933 "OMIT_PAGER_PRAGMAS",
20934 #endif
20935 #ifdef SQLITE_OMIT_PARSER_TRACE
20936 "OMIT_PARSER_TRACE",
20937 #endif
20938 #ifdef SQLITE_OMIT_POPEN
20939 "OMIT_POPEN",
20940 #endif
20941 #ifdef SQLITE_OMIT_PRAGMA
20942 "OMIT_PRAGMA",
20943 #endif
20944 #ifdef SQLITE_OMIT_PROGRESS_CALLBACK
20945 "OMIT_PROGRESS_CALLBACK",
20946 #endif
20947 #ifdef SQLITE_OMIT_QUICKBALANCE
20948 "OMIT_QUICKBALANCE",
20949 #endif
20950 #ifdef SQLITE_OMIT_REINDEX
20951 "OMIT_REINDEX",
20952 #endif
20953 #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
20954 "OMIT_SCHEMA_PRAGMAS",
20955 #endif
20956 #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
20957 "OMIT_SCHEMA_VERSION_PRAGMAS",
20958 #endif
20959 #ifdef SQLITE_OMIT_SHARED_CACHE
20960 "OMIT_SHARED_CACHE",
20961 #endif
20962 #ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
20963 "OMIT_SHUTDOWN_DIRECTORIES",
20964 #endif
20965 #ifdef SQLITE_OMIT_SUBQUERY
20966 "OMIT_SUBQUERY",
20967 #endif
20968 #ifdef SQLITE_OMIT_TCL_VARIABLE
20969 "OMIT_TCL_VARIABLE",
20970 #endif
20971 #ifdef SQLITE_OMIT_TEMPDB
20972 "OMIT_TEMPDB",
20973 #endif
20974 #ifdef SQLITE_OMIT_TEST_CONTROL
20975 "OMIT_TEST_CONTROL",
20976 #endif
20977 #ifdef SQLITE_OMIT_TRACE
20978 # if SQLITE_OMIT_TRACE != 1
20979 "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
20980 # endif
20981 #endif
20982 #ifdef SQLITE_OMIT_TRIGGER
20983 "OMIT_TRIGGER",
20984 #endif
20985 #ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
20986 "OMIT_TRUNCATE_OPTIMIZATION",
20987 #endif
20988 #ifdef SQLITE_OMIT_UTF16
20989 "OMIT_UTF16",
20990 #endif
20991 #ifdef SQLITE_OMIT_VACUUM
20992 "OMIT_VACUUM",
20993 #endif
20994 #ifdef SQLITE_OMIT_VIEW
20995 "OMIT_VIEW",
20996 #endif
20997 #ifdef SQLITE_OMIT_VIRTUALTABLE
20998 "OMIT_VIRTUALTABLE",
20999 #endif
21000 #ifdef SQLITE_OMIT_WAL
21001 "OMIT_WAL",
21002 #endif
21003 #ifdef SQLITE_OMIT_WSD
21004 "OMIT_WSD",
21005 #endif
21006 #ifdef SQLITE_OMIT_XFER_OPT
21007 "OMIT_XFER_OPT",
21008 #endif
21009 #ifdef SQLITE_PCACHE_SEPARATE_HEADER
21010 "PCACHE_SEPARATE_HEADER",
21011 #endif
21012 #ifdef SQLITE_PERFORMANCE_TRACE
21013 "PERFORMANCE_TRACE",
21014 #endif
21015 #ifdef SQLITE_POWERSAFE_OVERWRITE
21016 # if SQLITE_POWERSAFE_OVERWRITE != 1
21017 "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
21018 # endif
21019 #endif
21020 #ifdef SQLITE_PREFER_PROXY_LOCKING
21021 "PREFER_PROXY_LOCKING",
21022 #endif
21023 #ifdef SQLITE_PROXY_DEBUG
21024 "PROXY_DEBUG",
21025 #endif
21026 #ifdef SQLITE_REVERSE_UNORDERED_SELECTS
21027 "REVERSE_UNORDERED_SELECTS",
21028 #endif
21029 #ifdef SQLITE_RTREE_INT_ONLY
21030 "RTREE_INT_ONLY",
21031 #endif
21032 #ifdef SQLITE_SECURE_DELETE
21033 "SECURE_DELETE",
21034 #endif
21035 #ifdef SQLITE_SMALL_STACK
21036 "SMALL_STACK",
21037 #endif
21038 #ifdef SQLITE_SORTER_PMASZ
21039 "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
21040 #endif
21041 #ifdef SQLITE_SOUNDEX
21042 "SOUNDEX",
21043 #endif
21044 #ifdef SQLITE_STAT4_SAMPLES
21045 "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
21046 #endif
21047 #ifdef SQLITE_STMTJRNL_SPILL
21048 "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
21049 #endif
21050 #ifdef SQLITE_SUBSTR_COMPATIBILITY
21051 "SUBSTR_COMPATIBILITY",
21052 #endif
21053 #if (!defined(SQLITE_WIN32_MALLOC) \
21054 && !defined(SQLITE_ZERO_MALLOC) \
21055 && !defined(SQLITE_MEMDEBUG) \
21056 ) || defined(SQLITE_SYSTEM_MALLOC)
21057 "SYSTEM_MALLOC",
21058 #endif
21059 #ifdef SQLITE_TCL
21060 "TCL",
21061 #endif
21062 #ifdef SQLITE_TEMP_STORE
21063 "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
21064 #endif
21065 #ifdef SQLITE_TEST
21066 "TEST",
21067 #endif
21068 #if defined(SQLITE_THREADSAFE)
21069 "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
21070 #elif defined(THREADSAFE)
21071 "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
21072 #else
21073 "THREADSAFE=1",
21074 #endif
21075 #ifdef SQLITE_UNLINK_AFTER_CLOSE
21076 "UNLINK_AFTER_CLOSE",
21077 #endif
21078 #ifdef SQLITE_UNTESTABLE
21079 "UNTESTABLE",
21080 #endif
21081 #ifdef SQLITE_USER_AUTHENTICATION
21082 "USER_AUTHENTICATION",
21083 #endif
21084 #ifdef SQLITE_USE_ALLOCA
21085 "USE_ALLOCA",
21086 #endif
21087 #ifdef SQLITE_USE_FCNTL_TRACE
21088 "USE_FCNTL_TRACE",
21089 #endif
21090 #ifdef SQLITE_USE_URI
21091 "USE_URI",
21092 #endif
21093 #ifdef SQLITE_VDBE_COVERAGE
21094 "VDBE_COVERAGE",
21095 #endif
21096 #ifdef SQLITE_WIN32_MALLOC
21097 "WIN32_MALLOC",
21098 #endif
21099 #ifdef SQLITE_ZERO_MALLOC
21100 "ZERO_MALLOC",
21101 #endif
21102 /*
21103 ** END CODE GENERATED BY tool/mkctime.tcl
21104 */
21105 };
21106
21107 SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
21108 *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
21109 return (const char**)sqlite3azCompileOpt;
21110 }
21111
21112 #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
21113
21114 /************** End of ctime.c ***********************************************/
21115 /************** Begin file global.c ******************************************/
21116 /*
21117 ** 2008 June 13
21118 **
21119 ** The author disclaims copyright to this source code. In place of
@@ -21139,10 +21460,30 @@
21460
21461 /*
21462 ** Name of the default collating sequence
21463 */
21464 SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
21465
21466 /*
21467 ** Standard typenames. These names must match the COLTYPE_* definitions.
21468 ** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
21469 */
21470 SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 4, 3, 7, 4, 4 };
21471 SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = {
21472 SQLITE_AFF_BLOB,
21473 SQLITE_AFF_INTEGER,
21474 SQLITE_AFF_INTEGER,
21475 SQLITE_AFF_REAL,
21476 SQLITE_AFF_TEXT
21477 };
21478 SQLITE_PRIVATE const char *sqlite3StdType[] = {
21479 "BLOB",
21480 "INT",
21481 "INTEGER",
21482 "REAL",
21483 "TEXT"
21484 };
21485
21486 /************** End of global.c **********************************************/
21487 /************** Begin file status.c ******************************************/
21488 /*
21489 ** 2008 June 18
@@ -21342,12 +21683,12 @@
21683 int pc; /* Program Counter in parent (calling) frame */
21684 int nOp; /* Size of aOp array */
21685 int nMem; /* Number of entries in aMem */
21686 int nChildMem; /* Number of memory cells for child frame */
21687 int nChildCsr; /* Number of cursors for child frame */
21688 i64 nChange; /* Statement changes (Vdbe.nChange) */
21689 i64 nDbChange; /* Value of db->nChange */
21690 };
21691
21692 /* Magic number for sanity checking on VdbeFrame objects */
21693 #define SQLITE_FRAME_MAGIC 0x879fb71e
21694
@@ -21550,11 +21891,11 @@
21891 int nMem; /* Number of memory locations currently allocated */
21892 int nCursor; /* Number of slots in apCsr[] */
21893 u32 cacheCtr; /* VdbeCursor row cache generation counter */
21894 int pc; /* The program counter */
21895 int rc; /* Value to return */
21896 i64 nChange; /* Number of db changes made since last reset */
21897 int iStatement; /* Statement number (or 0 if has no opened stmt) */
21898 i64 iCurrentTime; /* Value of julianday('now') for this statement */
21899 i64 nFkConstraint; /* Number of imm. FK constraints this VM */
21900 i64 nStmtDefCons; /* Number of def. constraints when stmt started */
21901 i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
@@ -21695,10 +22036,11 @@
22036 SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
22037 #endif
22038 SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
22039 SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
22040 SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
22041 SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
22042 SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
22043 SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
22044 SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
22045 SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
22046 SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
@@ -27108,209 +27450,11 @@
27450
27451 #if SQLITE_OS_WIN
27452 /*
27453 ** Include code that is common to all os_*.c files
27454 */
27455 /* #include "os_common.h" */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27456
27457 /*
27458 ** Include the header file for the Windows VFS.
27459 */
27460 /************** Include os_win.h in the middle of mutex_w32.c ****************/
@@ -30077,10 +30221,12 @@
30221 sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
30222 pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
30223 }
30224 if( pItem->fg.jointype & JT_LEFT ){
30225 sqlite3_str_appendf(&x, " LEFT-JOIN");
30226 }else if( pItem->fg.jointype & JT_CROSS ){
30227 sqlite3_str_appendf(&x, " CROSS-JOIN");
30228 }
30229 if( pItem->fg.fromDDL ){
30230 sqlite3_str_appendf(&x, " DDL");
30231 }
30232 if( pItem->fg.isCte ){
@@ -30407,12 +30553,12 @@
30553 case TK_NULL: {
30554 sqlite3TreeViewLine(pView,"NULL");
30555 break;
30556 }
30557 case TK_TRUEFALSE: {
30558 sqlite3TreeViewLine(pView,"%s%s",
30559 sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
30560 break;
30561 }
30562 #ifndef SQLITE_OMIT_BLOB_LITERAL
30563 case TK_BLOB: {
30564 sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
@@ -30632,11 +30778,13 @@
30778 sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
30779 sqlite3_free(z);
30780 break;
30781 }
30782 case TK_SELECT_COLUMN: {
30783 sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
30784 pExpr->iColumn, pExpr->iTable-1,
30785 pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
30786 sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
30787 break;
30788 }
30789 case TK_IF_NULL_ROW: {
30790 sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
@@ -30648,10 +30796,19 @@
30796 sqlite3TreeViewLine(pView, "ERROR");
30797 tmp = *pExpr;
30798 tmp.op = pExpr->op2;
30799 sqlite3TreeViewExpr(pView, &tmp, 0);
30800 break;
30801 }
30802 case TK_ROW: {
30803 if( pExpr->iColumn<=0 ){
30804 sqlite3TreeViewLine(pView, "First FROM table rowid");
30805 }else{
30806 sqlite3TreeViewLine(pView, "First FROM table column %d",
30807 pExpr->iColumn-1);
30808 }
30809 break;
30810 }
30811 default: {
30812 sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
30813 break;
30814 }
@@ -30798,15 +30955,20 @@
30955 ** Nothing in this file or anywhere else in SQLite does any kind of
30956 ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
30957 ** number generator) not as an encryption device.
30958 */
30959 if( !wsdPrng.isInit ){
30960 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
30961 int i;
30962 char k[256];
30963 wsdPrng.j = 0;
30964 wsdPrng.i = 0;
30965 if( NEVER(pVfs==0) ){
30966 memset(k, 0, sizeof(k));
30967 }else{
30968 sqlite3OsRandomness(pVfs, 256, k);
30969 }
30970 for(i=0; i<256; i++){
30971 wsdPrng.s[i] = (u8)i;
30972 }
30973 for(i=0; i<256; i++){
30974 wsdPrng.j += wsdPrng.s[i] + k[i];
@@ -31763,12 +31925,18 @@
31925 **
31926 ** The column type is an extra string stored after the zero-terminator on
31927 ** the column name if and only if the COLFLAG_HASTYPE flag is set.
31928 */
31929 SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){
31930 if( pCol->colFlags & COLFLAG_HASTYPE ){
31931 return pCol->zCnName + strlen(pCol->zCnName) + 1;
31932 }else if( pCol->eType ){
31933 assert( pCol->eType<=SQLITE_N_STDTYPE );
31934 return (char*)sqlite3StdType[pCol->eType-1];
31935 }else{
31936 return zDflt;
31937 }
31938 }
31939
31940 /*
31941 ** Helper function for sqlite3Error() - called rarely. Broken out into
31942 ** a separate routine to avoid unnecessary register saves on entry to
@@ -31939,10 +32107,32 @@
32107 SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
32108 assert( sqlite3Isquote(p->u.zToken[0]) );
32109 p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
32110 sqlite3Dequote(p->u.zToken);
32111 }
32112
32113 /*
32114 ** If the input token p is quoted, try to adjust the token to remove
32115 ** the quotes. This is not always possible:
32116 **
32117 ** "abc" -> abc
32118 ** "ab""cd" -> (not possible because of the interior "")
32119 **
32120 ** Remove the quotes if possible. This is a optimization. The overall
32121 ** system should still return the correct answer even if this routine
32122 ** is always a no-op.
32123 */
32124 SQLITE_PRIVATE void sqlite3DequoteToken(Token *p){
32125 unsigned int i;
32126 if( p->n<2 ) return;
32127 if( !sqlite3Isquote(p->z[0]) ) return;
32128 for(i=1; i<p->n-1; i++){
32129 if( sqlite3Isquote(p->z[i]) ) return;
32130 }
32131 p->n -= 2;
32132 p->z++;
32133 }
32134
32135 /*
32136 ** Generate a Token object from a string
32137 */
32138 SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){
@@ -34150,209 +34340,11 @@
34340 #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
34341
34342 /*
34343 ** Include code that is common to all os_*.c files
34344 */
34345 /* #include "os_common.h" */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34346
34347 /*
34348 ** Define various macros that are missing from some systems.
34349 */
34350 #ifndef O_LARGEFILE
@@ -40236,10 +40228,12 @@
40228 if( fd<0 ){
40229 if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
40230 /* If unable to create a journal because the directory is not
40231 ** writable, change the error code to indicate that. */
40232 rc = SQLITE_READONLY_DIRECTORY;
40233 }else if( errno==EEXIST ){
40234 rc = SQLITE_CANTOPEN_EXISTS;
40235 }else if( errno!=EISDIR && isReadWrite ){
40236 /* Failed to open the file for read/write access. Try read-only. */
40237 flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
40238 openFlags &= ~(O_RDWR|O_CREAT);
40239 flags |= SQLITE_OPEN_READONLY;
@@ -42119,10 +42113,11 @@
42113 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
42114 sqlite3_vfs_register(&aVfs[i], i==0);
42115 }
42116 unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
42117
42118 #ifndef SQLITE_OMIT_WAL
42119 /* Validate lock assumptions */
42120 assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
42121 assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
42122 /* Locks:
42123 ** WRITE UNIX_SHM_BASE 120
@@ -42134,10 +42129,12 @@
42129 ** READ-3 UNIX_SHM_BASE+6 126
42130 ** READ-4 UNIX_SHM_BASE+7 127
42131 ** DMS UNIX_SHM_BASE+8 128
42132 */
42133 assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
42134 #endif
42135
42136 return SQLITE_OK;
42137 }
42138
42139 /*
42140 ** Shutdown the operating system interface.
@@ -42173,209 +42170,11 @@
42170 #if SQLITE_OS_WIN /* This file is used for Windows only */
42171
42172 /*
42173 ** Include code that is common to all os_*.c files
42174 */
42175 /* #include "os_common.h" */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42176
42177 /*
42178 ** Include the header file for the Windows VFS.
42179 */
42180 /* #include "os_win.h" */
@@ -49319,11 +49118,12 @@
49118 #endif
49119
49120 sqlite3_mutex_enter(db->mutex);
49121 if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
49122 iDb = sqlite3FindDbName(db, zSchema);
49123 testcase( iDb==1 );
49124 if( iDb<2 && iDb!=0 ){
49125 rc = SQLITE_ERROR;
49126 goto end_deserialize;
49127 }
49128 zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
49129 if( zSql==0 ){
@@ -49371,11 +49171,13 @@
49171 ** This routine is called when the extension is loaded.
49172 ** Register the new VFS.
49173 */
49174 SQLITE_PRIVATE int sqlite3MemdbInit(void){
49175 sqlite3_vfs *pLower = sqlite3_vfs_find(0);
49176 unsigned int sz;
49177 if( NEVER(pLower==0) ) return SQLITE_ERROR;
49178 sz = pLower->szOsFile;
49179 memdb_vfs.pAppData = pLower;
49180 /* The following conditional can only be true when compiled for
49181 ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
49182 ** it in, to be safe, but it is marked as NO_TEST since there
49183 ** is no way to reach it under most builds. */
@@ -60504,11 +60306,14 @@
60306 ** Each index block except for the first contains information on
60307 ** HASHTABLE_NPAGE frames. The first index block contains information on
60308 ** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
60309 ** HASHTABLE_NPAGE are selected so that together the wal-index header and
60310 ** first index block are the same size as all other index blocks in the
60311 ** wal-index. The values are:
60312 **
60313 ** HASHTABLE_NPAGE 4096
60314 ** HASHTABLE_NPAGE_ONE 4062
60315 **
60316 ** Each index block contains two sections, a page-mapping that contains the
60317 ** database page number associated with each wal frame, and a hash-table
60318 ** that allows readers to query an index block for a specific page number.
60319 ** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
@@ -60740,10 +60545,74 @@
60545 u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */
60546 u32 notUsed0; /* Available for future enhancements */
60547 };
60548 #define READMARK_NOT_USED 0xffffffff
60549
60550 /*
60551 ** This is a schematic view of the complete 136-byte header of the
60552 ** wal-index file (also known as the -shm file):
60553 **
60554 ** +-----------------------------+
60555 ** 0: | iVersion | \
60556 ** +-----------------------------+ |
60557 ** 4: | (unused padding) | |
60558 ** +-----------------------------+ |
60559 ** 8: | iChange | |
60560 ** +-------+-------+-------------+ |
60561 ** 12: | bInit | bBig | szPage | |
60562 ** +-------+-------+-------------+ |
60563 ** 16: | mxFrame | | First copy of the
60564 ** +-----------------------------+ | WalIndexHdr object
60565 ** 20: | nPage | |
60566 ** +-----------------------------+ |
60567 ** 24: | aFrameCksum | |
60568 ** | | |
60569 ** +-----------------------------+ |
60570 ** 32: | aSalt | |
60571 ** | | |
60572 ** +-----------------------------+ |
60573 ** 40: | aCksum | |
60574 ** | | /
60575 ** +-----------------------------+
60576 ** 48: | iVersion | \
60577 ** +-----------------------------+ |
60578 ** 52: | (unused padding) | |
60579 ** +-----------------------------+ |
60580 ** 56: | iChange | |
60581 ** +-------+-------+-------------+ |
60582 ** 60: | bInit | bBig | szPage | |
60583 ** +-------+-------+-------------+ | Second copy of the
60584 ** 64: | mxFrame | | WalIndexHdr
60585 ** +-----------------------------+ |
60586 ** 68: | nPage | |
60587 ** +-----------------------------+ |
60588 ** 72: | aFrameCksum | |
60589 ** | | |
60590 ** +-----------------------------+ |
60591 ** 80: | aSalt | |
60592 ** | | |
60593 ** +-----------------------------+ |
60594 ** 88: | aCksum | |
60595 ** | | /
60596 ** +-----------------------------+
60597 ** 96: | nBackfill |
60598 ** +-----------------------------+
60599 ** 100: | 5 read marks |
60600 ** | |
60601 ** | |
60602 ** | |
60603 ** | |
60604 ** +-------+-------+------+------+
60605 ** 120: | Write | Ckpt | Rcvr | Rd0 | \
60606 ** +-------+-------+------+------+ ) 8 lock bytes
60607 ** | Read1 | Read2 | Rd3 | Rd4 | /
60608 ** +-------+-------+------+------+
60609 ** 128: | nBackfillAttempted |
60610 ** +-----------------------------+
60611 ** 132: | (unused padding) |
60612 ** +-----------------------------+
60613 */
60614
60615 /* A block of WALINDEX_LOCK_RESERVED bytes beginning at
60616 ** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
60617 ** only support mandatory file-locks, we do not read or write data
60618 ** from the region of the file on which locks are applied.
@@ -61752,19 +61621,48 @@
61621 Wal *pRet; /* Object to allocate and return */
61622 int flags; /* Flags passed to OsOpen() */
61623
61624 assert( zWalName && zWalName[0] );
61625 assert( pDbFd );
61626
61627 /* Verify the values of various constants. Any changes to the values
61628 ** of these constants would result in an incompatible on-disk format
61629 ** for the -shm file. Any change that causes one of these asserts to
61630 ** fail is a backward compatibility problem, even if the change otherwise
61631 ** works.
61632 **
61633 ** This table also serves as a helpful cross-reference when trying to
61634 ** interpret hex dumps of the -shm file.
61635 */
61636 assert( 48 == sizeof(WalIndexHdr) );
61637 assert( 40 == sizeof(WalCkptInfo) );
61638 assert( 120 == WALINDEX_LOCK_OFFSET );
61639 assert( 136 == WALINDEX_HDR_SIZE );
61640 assert( 4096 == HASHTABLE_NPAGE );
61641 assert( 4062 == HASHTABLE_NPAGE_ONE );
61642 assert( 8192 == HASHTABLE_NSLOT );
61643 assert( 383 == HASHTABLE_HASH_1 );
61644 assert( 32768 == WALINDEX_PGSZ );
61645 assert( 8 == SQLITE_SHM_NLOCK );
61646 assert( 5 == WAL_NREADER );
61647 assert( 24 == WAL_FRAME_HDRSIZE );
61648 assert( 32 == WAL_HDRSIZE );
61649 assert( 120 == WALINDEX_LOCK_OFFSET + WAL_WRITE_LOCK );
61650 assert( 121 == WALINDEX_LOCK_OFFSET + WAL_CKPT_LOCK );
61651 assert( 122 == WALINDEX_LOCK_OFFSET + WAL_RECOVER_LOCK );
61652 assert( 123 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(0) );
61653 assert( 124 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(1) );
61654 assert( 125 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(2) );
61655 assert( 126 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(3) );
61656 assert( 127 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(4) );
61657
61658 /* In the amalgamation, the os_unix.c and os_win.c source files come before
61659 ** this source file. Verify that the #defines of the locking byte offsets
61660 ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
61661 ** For that matter, if the lock offset ever changes from its initial design
61662 ** value of 120, we need to know that so there is an assert() to check it.
61663 */
 
 
61664 #ifdef WIN_SHM_BASE
61665 assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
61666 #endif
61667 #ifdef UNIX_SHM_BASE
61668 assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
@@ -66267,19 +66165,17 @@
66165 pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
66166 if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
66167 sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
66168 if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
66169 rc = SQLITE_CORRUPT_BKPT;
66170 }else{
66171 rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes);
66172 }
66173 sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
66174 }else{
66175 pIdxKey = 0;
66176 rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes);
 
 
 
 
66177 }
66178 return rc;
66179 }
66180
66181 /*
@@ -67124,11 +67020,11 @@
67020 u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
67021 if( pSpace ){
67022 int g2;
67023 assert( pSpace+nByte<=data+pPage->pBt->usableSize );
67024 *pIdx = g2 = (int)(pSpace-data);
67025 if( g2<=gap ){
67026 return SQLITE_CORRUPT_PAGE(pPage);
67027 }else{
67028 return SQLITE_OK;
67029 }
67030 }else if( rc ){
@@ -70861,16 +70757,12 @@
70757 rc = SQLITE_OK;
70758 }
70759 return rc;
70760 }
70761
70762 /* Move the cursor so that it points to an entry in a table (a.k.a INTKEY)
70763 ** table near the key intKey. Return a success code.
 
 
 
 
70764 **
70765 ** If an exact match is not found, then the cursor is always
70766 ** left pointing at a leaf page which would hold the entry if it
70767 ** were present. The cursor might point to an entry that comes
70768 ** before or after the key.
@@ -70879,43 +70771,36 @@
70771 ** comparing the key with the entry to which the cursor is
70772 ** pointing. The meaning of the integer written into
70773 ** *pRes is as follows:
70774 **
70775 ** *pRes<0 The cursor is left pointing at an entry that
70776 ** is smaller than intKey or if the table is empty
70777 ** and the cursor is therefore left point to nothing.
70778 **
70779 ** *pRes==0 The cursor is left pointing at an entry that
70780 ** exactly matches intKey.
70781 **
70782 ** *pRes>0 The cursor is left pointing at an entry that
70783 ** is larger than intKey.
 
 
 
70784 */
70785 SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
70786 BtCursor *pCur, /* The cursor to be moved */
 
70787 i64 intKey, /* The table key */
70788 int biasRight, /* If true, bias the search to the high end */
70789 int *pRes /* Write search results here */
70790 ){
70791 int rc;
 
70792
70793 assert( cursorOwnsBtShared(pCur) );
70794 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
70795 assert( pRes );
70796 assert( pCur->pKeyInfo==0 );
70797 assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 );
70798
70799 /* If the cursor is already positioned at the point we are trying
70800 ** to move to, then just return without doing any work */
70801 if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){
 
 
70802 if( pCur->info.nKey==intKey ){
70803 *pRes = 0;
70804 return SQLITE_OK;
70805 }
70806 if( pCur->info.nKey<intKey ){
@@ -70946,20 +70831,153 @@
70831
70832 #ifdef SQLITE_DEBUG
70833 pCur->pBtree->nSeek++; /* Performance measurement during testing */
70834 #endif
70835
70836 rc = moveToRoot(pCur);
70837 if( rc ){
70838 if( rc==SQLITE_EMPTY ){
70839 assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
70840 *pRes = -1;
70841 return SQLITE_OK;
70842 }
70843 return rc;
70844 }
70845 assert( pCur->pPage );
70846 assert( pCur->pPage->isInit );
70847 assert( pCur->eState==CURSOR_VALID );
70848 assert( pCur->pPage->nCell > 0 );
70849 assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
70850 assert( pCur->curIntKey );
70851
70852 for(;;){
70853 int lwr, upr, idx, c;
70854 Pgno chldPg;
70855 MemPage *pPage = pCur->pPage;
70856 u8 *pCell; /* Pointer to current cell in pPage */
70857
70858 /* pPage->nCell must be greater than zero. If this is the root-page
70859 ** the cursor would have been INVALID above and this for(;;) loop
70860 ** not run. If this is not the root-page, then the moveToChild() routine
70861 ** would have already detected db corruption. Similarly, pPage must
70862 ** be the right kind (index or table) of b-tree page. Otherwise
70863 ** a moveToChild() or moveToRoot() call would have detected corruption. */
70864 assert( pPage->nCell>0 );
70865 assert( pPage->intKey );
70866 lwr = 0;
70867 upr = pPage->nCell-1;
70868 assert( biasRight==0 || biasRight==1 );
70869 idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
70870 pCur->ix = (u16)idx;
70871 for(;;){
70872 i64 nCellKey;
70873 pCell = findCellPastPtr(pPage, idx);
70874 if( pPage->intKeyLeaf ){
70875 while( 0x80 <= *(pCell++) ){
70876 if( pCell>=pPage->aDataEnd ){
70877 return SQLITE_CORRUPT_PAGE(pPage);
70878 }
70879 }
70880 }
70881 getVarint(pCell, (u64*)&nCellKey);
70882 if( nCellKey<intKey ){
70883 lwr = idx+1;
70884 if( lwr>upr ){ c = -1; break; }
70885 }else if( nCellKey>intKey ){
70886 upr = idx-1;
70887 if( lwr>upr ){ c = +1; break; }
70888 }else{
70889 assert( nCellKey==intKey );
70890 pCur->ix = (u16)idx;
70891 if( !pPage->leaf ){
70892 lwr = idx;
70893 goto moveto_table_next_layer;
70894 }else{
70895 pCur->curFlags |= BTCF_ValidNKey;
70896 pCur->info.nKey = nCellKey;
70897 pCur->info.nSize = 0;
70898 *pRes = 0;
70899 return SQLITE_OK;
70900 }
70901 }
70902 assert( lwr+upr>=0 );
70903 idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
70904 }
70905 assert( lwr==upr+1 || !pPage->leaf );
70906 assert( pPage->isInit );
70907 if( pPage->leaf ){
70908 assert( pCur->ix<pCur->pPage->nCell );
70909 pCur->ix = (u16)idx;
70910 *pRes = c;
70911 rc = SQLITE_OK;
70912 goto moveto_table_finish;
70913 }
70914 moveto_table_next_layer:
70915 if( lwr>=pPage->nCell ){
70916 chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
70917 }else{
70918 chldPg = get4byte(findCell(pPage, lwr));
70919 }
70920 pCur->ix = (u16)lwr;
70921 rc = moveToChild(pCur, chldPg);
70922 if( rc ) break;
70923 }
70924 moveto_table_finish:
70925 pCur->info.nSize = 0;
70926 assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
70927 return rc;
70928 }
70929
70930 /* Move the cursor so that it points to an entry in an index table
70931 ** near the key pIdxKey. Return a success code.
70932 **
70933 ** If an exact match is not found, then the cursor is always
70934 ** left pointing at a leaf page which would hold the entry if it
70935 ** were present. The cursor might point to an entry that comes
70936 ** before or after the key.
70937 **
70938 ** An integer is written into *pRes which is the result of
70939 ** comparing the key with the entry to which the cursor is
70940 ** pointing. The meaning of the integer written into
70941 ** *pRes is as follows:
70942 **
70943 ** *pRes<0 The cursor is left pointing at an entry that
70944 ** is smaller than pIdxKey or if the table is empty
70945 ** and the cursor is therefore left point to nothing.
70946 **
70947 ** *pRes==0 The cursor is left pointing at an entry that
70948 ** exactly matches pIdxKey.
70949 **
70950 ** *pRes>0 The cursor is left pointing at an entry that
70951 ** is larger than pIdxKey.
70952 **
70953 ** The pIdxKey->eqSeen field is set to 1 if there
70954 ** exists an entry in the table that exactly matches pIdxKey.
70955 */
70956 SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
70957 BtCursor *pCur, /* The cursor to be moved */
70958 UnpackedRecord *pIdxKey, /* Unpacked index key */
70959 int *pRes /* Write search results here */
70960 ){
70961 int rc;
70962 RecordCompare xRecordCompare;
70963
70964 assert( cursorOwnsBtShared(pCur) );
70965 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
70966 assert( pRes );
70967 assert( pCur->pKeyInfo!=0 );
70968
70969 #ifdef SQLITE_DEBUG
70970 pCur->pBtree->nSeek++; /* Performance measurement during testing */
70971 #endif
70972
70973 xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
70974 pIdxKey->errCode = 0;
70975 assert( pIdxKey->default_rc==1
70976 || pIdxKey->default_rc==0
70977 || pIdxKey->default_rc==-1
70978 );
70979
70980 rc = moveToRoot(pCur);
70981 if( rc ){
70982 if( rc==SQLITE_EMPTY ){
70983 assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
@@ -70988,155 +71006,116 @@
71006 ** a moveToChild() or moveToRoot() call would have detected corruption. */
71007 assert( pPage->nCell>0 );
71008 assert( pPage->intKey==(pIdxKey==0) );
71009 lwr = 0;
71010 upr = pPage->nCell-1;
71011 idx = upr>>1; /* idx = (lwr+upr)/2; */
71012 pCur->ix = (u16)idx;
71013 for(;;){
71014 int nCell; /* Size of the pCell cell in bytes */
71015 pCell = findCellPastPtr(pPage, idx);
71016
71017 /* The maximum supported page-size is 65536 bytes. This means that
71018 ** the maximum number of record bytes stored on an index B-Tree
71019 ** page is less than 16384 bytes and may be stored as a 2-byte
71020 ** varint. This information is used to attempt to avoid parsing
71021 ** the entire cell by checking for the cases where the record is
71022 ** stored entirely within the b-tree page by inspecting the first
71023 ** 2 bytes of the cell.
71024 */
71025 nCell = pCell[0];
71026 if( nCell<=pPage->max1bytePayload ){
71027 /* This branch runs if the record-size field of the cell is a
71028 ** single byte varint and the record fits entirely on the main
71029 ** b-tree page. */
71030 testcase( pCell+nCell+1==pPage->aDataEnd );
71031 c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
71032 }else if( !(pCell[1] & 0x80)
71033 && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
71034 ){
71035 /* The record-size field is a 2 byte varint and the record
71036 ** fits entirely on the main b-tree page. */
71037 testcase( pCell+nCell+2==pPage->aDataEnd );
71038 c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
71039 }else{
71040 /* The record flows over onto one or more overflow pages. In
71041 ** this case the whole cell needs to be parsed, a buffer allocated
71042 ** and accessPayload() used to retrieve the record into the
71043 ** buffer before VdbeRecordCompare() can be called.
71044 **
71045 ** If the record is corrupt, the xRecordCompare routine may read
71046 ** up to two varints past the end of the buffer. An extra 18
71047 ** bytes of padding is allocated at the end of the buffer in
71048 ** case this happens. */
71049 void *pCellKey;
71050 u8 * const pCellBody = pCell - pPage->childPtrSize;
71051 const int nOverrun = 18; /* Size of the overrun padding */
71052 pPage->xParseCell(pPage, pCellBody, &pCur->info);
71053 nCell = (int)pCur->info.nKey;
71054 testcase( nCell<0 ); /* True if key size is 2^32 or more */
71055 testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
71056 testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
71057 testcase( nCell==2 ); /* Minimum legal index key size */
71058 if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
71059 rc = SQLITE_CORRUPT_PAGE(pPage);
71060 goto moveto_index_finish;
71061 }
71062 pCellKey = sqlite3Malloc( nCell+nOverrun );
71063 if( pCellKey==0 ){
71064 rc = SQLITE_NOMEM_BKPT;
71065 goto moveto_index_finish;
71066 }
71067 pCur->ix = (u16)idx;
71068 rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
71069 memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
71070 pCur->curFlags &= ~BTCF_ValidOvfl;
71071 if( rc ){
71072 sqlite3_free(pCellKey);
71073 goto moveto_index_finish;
71074 }
71075 c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
71076 sqlite3_free(pCellKey);
71077 }
71078 assert(
71079 (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
71080 && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
71081 );
71082 if( c<0 ){
71083 lwr = idx+1;
71084 }else if( c>0 ){
71085 upr = idx-1;
71086 }else{
71087 assert( c==0 );
71088 *pRes = 0;
71089 rc = SQLITE_OK;
71090 pCur->ix = (u16)idx;
71091 if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
71092 goto moveto_index_finish;
71093 }
71094 if( lwr>upr ) break;
71095 assert( lwr+upr>=0 );
71096 idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71097 }
71098 assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
71099 assert( pPage->isInit );
71100 if( pPage->leaf ){
71101 assert( pCur->ix<pCur->pPage->nCell );
71102 pCur->ix = (u16)idx;
71103 *pRes = c;
71104 rc = SQLITE_OK;
71105 goto moveto_index_finish;
71106 }
 
71107 if( lwr>=pPage->nCell ){
71108 chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
71109 }else{
71110 chldPg = get4byte(findCell(pPage, lwr));
71111 }
71112 pCur->ix = (u16)lwr;
71113 rc = moveToChild(pCur, chldPg);
71114 if( rc ) break;
71115 }
71116 moveto_index_finish:
71117 pCur->info.nSize = 0;
71118 assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
71119 return rc;
71120 }
71121
@@ -73116,10 +73095,11 @@
73095 if( rc ){
73096 memset(apOld, 0, (i)*sizeof(MemPage*));
73097 goto balance_cleanup;
73098 }
73099 }
73100 nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl);
73101 if( (i--)==0 ) break;
73102
73103 if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
73104 apDiv[i] = pParent->apOvfl[0];
73105 pgno = get4byte(apDiv[i]);
@@ -73157,11 +73137,10 @@
73137 }
73138 }
73139
73140 /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
73141 ** alignment */
 
73142 nMaxCells = (nMaxCells + 3)&~3;
73143
73144 /*
73145 ** Allocate space for memory structures
73146 */
@@ -73440,11 +73419,13 @@
73419 if( i<nOld ){
73420 pNew = apNew[i] = apOld[i];
73421 apOld[i] = 0;
73422 rc = sqlite3PagerWrite(pNew->pDbPage);
73423 nNew++;
73424 if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv))
73425 && rc==SQLITE_OK
73426 ){
73427 rc = SQLITE_CORRUPT_BKPT;
73428 }
73429 if( rc ) goto balance_cleanup;
73430 }else{
73431 assert( i>0 );
@@ -74238,11 +74219,12 @@
74219 }else if( loc==0 ){
74220 /* The cursor is *not* pointing to the cell to be overwritten, nor
74221 ** to an adjacent cell. Move the cursor so that it is pointing either
74222 ** to the cell to be overwritten or an adjacent cell.
74223 */
74224 rc = sqlite3BtreeTableMoveto(pCur, pX->nKey,
74225 (flags & BTREE_APPEND)!=0, &loc);
74226 if( rc ) return rc;
74227 }
74228 }else{
74229 /* This is an index or a WITHOUT ROWID table */
74230
@@ -74261,17 +74243,15 @@
74243 UnpackedRecord r;
74244 r.pKeyInfo = pCur->pKeyInfo;
74245 r.aMem = pX->aMem;
74246 r.nField = pX->nMem;
74247 r.default_rc = 0;
 
 
 
74248 r.eqSeen = 0;
74249 rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc);
74250 }else{
74251 rc = btreeMoveto(pCur, pX->pKey, pX->nKey,
74252 (flags & BTREE_APPEND)!=0, &loc);
74253 }
74254 if( rc ) return rc;
74255 }
74256
74257 /* If the cursor is currently pointing to an entry to be overwritten
@@ -74901,11 +74881,11 @@
74881 */
74882 static int clearDatabasePage(
74883 BtShared *pBt, /* The BTree that contains the table */
74884 Pgno pgno, /* Page number to clear */
74885 int freePageFlag, /* Deallocate page if true */
74886 i64 *pnChange /* Add number of Cells freed to this counter */
74887 ){
74888 MemPage *pPage;
74889 int rc;
74890 unsigned char *pCell;
74891 int i;
@@ -74934,10 +74914,11 @@
74914 if( rc ) goto cleardatabasepage_out;
74915 }
74916 if( !pPage->leaf ){
74917 rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
74918 if( rc ) goto cleardatabasepage_out;
74919 if( pPage->intKey ) pnChange = 0;
74920 }
74921 if( pnChange ){
74922 testcase( !pPage->intKey );
74923 *pnChange += pPage->nCell;
74924 }
@@ -74963,11 +74944,11 @@
74944 ** root of the table.
74945 **
74946 ** If pnChange is not NULL, then the integer value pointed to by pnChange
74947 ** is incremented by the number of entries in the table.
74948 */
74949 SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){
74950 int rc;
74951 BtShared *pBt = p->pBt;
74952 sqlite3BtreeEnter(p);
74953 assert( p->inTrans==TRANS_WRITE );
74954
@@ -80557,11 +80538,11 @@
80538 }
80539 #endif
80540 case P4_COLLSEQ: {
80541 static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
80542 CollSeq *pColl = pOp->p4.pColl;
80543 assert( pColl->enc<4 );
80544 sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
80545 encnames[pColl->enc]);
80546 break;
80547 }
80548 case P4_FUNCDEF: {
@@ -82398,11 +82379,11 @@
82379 extern int sqlite3_search_count;
82380 #endif
82381 assert( p->deferredMoveto );
82382 assert( p->isTable );
82383 assert( p->eCurType==CURTYPE_BTREE );
82384 rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res);
82385 if( rc ) return rc;
82386 if( res!=0 ) return SQLITE_CORRUPT_BKPT;
82387 #ifdef SQLITE_TEST
82388 sqlite3_search_count++;
82389 #endif
@@ -83182,11 +83163,11 @@
83163 /*
83164 ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
83165 ** number. Return negative, zero, or positive if the first (i64) is less than,
83166 ** equal to, or greater than the second (double).
83167 */
83168 SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){
83169 if( sizeof(LONGDOUBLE_TYPE)>8 ){
83170 LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
83171 testcase( x<r );
83172 testcase( x>r );
83173 testcase( x==r );
@@ -83906,11 +83887,11 @@
83887
83888 /*
83889 ** This routine sets the value to be returned by subsequent calls to
83890 ** sqlite3_changes() on the database handle 'db'.
83891 */
83892 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){
83893 assert( sqlite3_mutex_held(db->mutex) );
83894 db->nChange = nChange;
83895 db->nTotalChange += nChange;
83896 }
83897
@@ -87023,100 +87004,11 @@
87004
87005 /*
87006 ** hwtime.h contains inline assembler code for implementing
87007 ** high-performance timing routines.
87008 */
87009 /* #include "hwtime.h" */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87010
87011 #endif
87012
87013 #ifndef NDEBUG
87014 /*
@@ -90274,10 +90166,12 @@
90166 assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
90167 assert( pOp->p4type==P4_KEYINFO );
90168 pCur = p->apCsr[pOp->p1];
90169 if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
90170 assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
90171 assert( pCur->eCurType==CURTYPE_BTREE );
90172 sqlite3BtreeClearCursor(pCur->uc.pCursor);
90173 goto open_cursor_set_hints;
90174 }
90175 /* If the cursor is not currently open or is open on a different
90176 ** index, then fall through into OP_OpenRead to force a reopen */
90177 case OP_OpenRead:
@@ -90761,45 +90655,47 @@
90655 pIn3->flags = flags3; /* But convert the type back to its original */
90656
90657 /* If the P3 value could not be converted into an integer without
90658 ** loss of information, then special processing is required... */
90659 if( (newType & (MEM_Int|MEM_IntReal))==0 ){
90660 int c;
90661 if( (newType & MEM_Real)==0 ){
90662 if( (newType & MEM_Null) || oc>=OP_SeekGE ){
90663 VdbeBranchTaken(1,2);
90664 goto jump_to_p2;
90665 }else{
90666 rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
90667 if( rc!=SQLITE_OK ) goto abort_due_to_error;
90668 goto seek_not_found;
90669 }
90670 }
90671 c = sqlite3IntFloatCompare(iKey, pIn3->u.r);
90672
90673 /* If the approximation iKey is larger than the actual real search
90674 ** term, substitute >= for > and < for <=. e.g. if the search term
90675 ** is 4.9 and the integer approximation 5:
90676 **
90677 ** (x > 4.9) -> (x >= 5)
90678 ** (x <= 4.9) -> (x < 5)
90679 */
90680 if( c>0 ){
90681 assert( OP_SeekGE==(OP_SeekGT-1) );
90682 assert( OP_SeekLT==(OP_SeekLE-1) );
90683 assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
90684 if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
90685 }
90686
90687 /* If the approximation iKey is smaller than the actual real search
90688 ** term, substitute <= for < and > for >=. */
90689 else if( c<0 ){
90690 assert( OP_SeekLE==(OP_SeekLT+1) );
90691 assert( OP_SeekGT==(OP_SeekGE+1) );
90692 assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
90693 if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
90694 }
90695 }
90696 rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res);
90697 pC->movetoTarget = iKey; /* Used by OP_Delete */
90698 if( rc!=SQLITE_OK ){
90699 goto abort_due_to_error;
90700 }
90701 }else{
@@ -90842,11 +90738,11 @@
90738 r.aMem = &aMem[pOp->p3];
90739 #ifdef SQLITE_DEBUG
90740 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
90741 #endif
90742 r.eqSeen = 0;
90743 rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res);
90744 if( rc!=SQLITE_OK ){
90745 goto abort_due_to_error;
90746 }
90747 if( eqOnly && r.eqSeen==0 ){
90748 assert( res!=0 );
@@ -91261,11 +91157,11 @@
91157 takeJump = 1;
91158 break;
91159 }
91160 }
91161 }
91162 rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &res);
91163 if( pFree ) sqlite3DbFreeNN(db, pFree);
91164 if( rc!=SQLITE_OK ){
91165 goto abort_due_to_error;
91166 }
91167 pC->seekResult = res;
@@ -91370,11 +91266,11 @@
91266 assert( pC->isTable );
91267 assert( pC->eCurType==CURTYPE_BTREE );
91268 pCrsr = pC->uc.pCursor;
91269 assert( pCrsr!=0 );
91270 res = 0;
91271 rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res);
91272 assert( rc==SQLITE_OK || res==0 );
91273 pC->movetoTarget = iKey; /* Used by OP_Delete */
91274 pC->nullRow = 0;
91275 pC->cacheStatus = CACHE_STALE;
91276 pC->deferredMoveto = 0;
@@ -91527,11 +91423,11 @@
91423 ** an AUTOINCREMENT table. */
91424 cnt = 0;
91425 do{
91426 sqlite3_randomness(sizeof(v), &v);
91427 v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
91428 }while( ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v,
91429 0, &res))==SQLITE_OK)
91430 && (res==0)
91431 && (++cnt<100));
91432 if( rc ) goto abort_due_to_error;
91433 if( res==0 ){
@@ -92425,11 +92321,11 @@
92321 assert( pCrsr!=0 );
92322 r.pKeyInfo = pC->pKeyInfo;
92323 r.nField = (u16)pOp->p3;
92324 r.default_rc = 0;
92325 r.aMem = &aMem[pOp->p2];
92326 rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
92327 if( rc ) goto abort_due_to_error;
92328 if( res==0 ){
92329 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
92330 if( rc ) goto abort_due_to_error;
92331 }else if( pOp->p5 ){
@@ -92738,11 +92634,11 @@
92634 ** by the number of rows in the table being cleared.
92635 **
92636 ** See also: Destroy
92637 */
92638 case OP_Clear: {
92639 i64 nChange;
92640
92641 sqlite3VdbeIncrWriteCounter(p, 0);
92642 nChange = 0;
92643 assert( p->readOnly==0 );
92644 assert( DbMaskTest(p->btreeMask, pOp->p2) );
@@ -94960,11 +94856,11 @@
94856 if( pTab && !HasRowid(pTab) ){
94857 pTab = 0;
94858 sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
94859 }
94860 #ifndef SQLITE_OMIT_VIEW
94861 if( pTab && IsView(pTab) ){
94862 pTab = 0;
94863 sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
94864 }
94865 #endif
94866 if( !pTab ){
@@ -94980,11 +94876,11 @@
94876 pBlob->pTab = pTab;
94877 pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
94878
94879 /* Now search pTab for the exact column. */
94880 for(iCol=0; iCol<pTab->nCol; iCol++) {
94881 if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
94882 break;
94883 }
94884 }
94885 if( iCol==pTab->nCol ){
94886 sqlite3DbFree(db, zErr);
@@ -95005,11 +94901,12 @@
94901 /* Check that the column is not part of an FK child key definition. It
94902 ** is not necessary to check if it is part of a parent key, as parent
94903 ** key columns must be indexed. The check below will pick up this
94904 ** case. */
94905 FKey *pFKey;
94906 assert( !IsVirtual(pTab) );
94907 for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
94908 int j;
94909 for(j=0; j<pFKey->nCol; j++){
94910 if( pFKey->aCol[j].iFrom==iCol ){
94911 zFault = "foreign key";
94912 }
@@ -96378,12 +96275,13 @@
96275 int iTask = (pTask - pTask->pSorter->aTask);
96276 sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t);
96277 fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
96278 }
96279 static void vdbeSorterRewindDebug(const char *zEvent){
96280 i64 t = 0;
96281 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
96282 if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t);
96283 fprintf(stderr, "%lld:X %s\n", t, zEvent);
96284 }
96285 static void vdbeSorterPopulateDebug(
96286 SortSubtask *pTask,
96287 const char *zEvent
@@ -99500,11 +99398,11 @@
99398 if( pSrcList ){
99399 for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
99400 u8 hCol;
99401 pTab = pItem->pTab;
99402 assert( pTab!=0 && pTab->zName!=0 );
99403 assert( pTab->nCol>0 || pParse->nErr );
99404 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
99405 int hit = 0;
99406 pEList = pItem->pSelect->pEList;
99407 for(j=0; j<pEList->nExpr; j++){
99408 if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
@@ -99528,16 +99426,15 @@
99426 }
99427 if( IN_RENAME_OBJECT && pItem->zAlias ){
99428 sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
99429 }
99430 }
 
 
 
99431 hCol = sqlite3StrIHash(zCol);
99432 for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
99433 if( pCol->hName==hCol
99434 && sqlite3StrICmp(pCol->zCnName, zCol)==0
99435 ){
99436 /* If there has been exactly one prior match and this match
99437 ** is for the right-hand table of a NATURAL JOIN or is in a
99438 ** USING clause, then skip this match.
99439 */
99440 if( cnt==1 ){
@@ -99548,10 +99445,14 @@
99445 pMatch = pItem;
99446 /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
99447 pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
99448 break;
99449 }
99450 }
99451 if( 0==cnt && VisibleRowid(pTab) ){
99452 cntTab++;
99453 pMatch = pItem;
99454 }
99455 }
99456 if( pMatch ){
99457 pExpr->iTable = pMatch->iCursor;
99458 pExpr->y.pTab = pMatch->pTab;
@@ -99606,11 +99507,13 @@
99507 int iCol;
99508 u8 hCol = sqlite3StrIHash(zCol);
99509 pSchema = pTab->pSchema;
99510 cntTab++;
99511 for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
99512 if( pCol->hName==hCol
99513 && sqlite3StrICmp(pCol->zCnName, zCol)==0
99514 ){
99515 if( iCol==pTab->iPKey ){
99516 iCol = -1;
99517 }
99518 break;
99519 }
@@ -99671,11 +99574,11 @@
99574 if( cnt==0
99575 && cntTab==1
99576 && pMatch
99577 && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
99578 && sqlite3IsRowid(zCol)
99579 && ALWAYS(VisibleRowid(pMatch->pTab))
99580 ){
99581 cnt = 1;
99582 pExpr->iColumn = -1;
99583 pExpr->affExpr = SQLITE_AFF_INTEGER;
99584 }
@@ -100014,10 +99917,11 @@
99917 for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
99918 anRef[i] = p->nRef;
99919 }
99920 sqlite3WalkExpr(pWalker, pExpr->pLeft);
99921 if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
99922 testcase( ExprHasProperty(pExpr, EP_FromJoin) );
99923 if( pExpr->op==TK_NOTNULL ){
99924 pExpr->u.zToken = "true";
99925 ExprSetProperty(pExpr, EP_IsTrue);
99926 }else{
99927 pExpr->u.zToken = "false";
@@ -100283,13 +100187,16 @@
100187 pNC2 = pNC2->pNext;
100188 }
100189 assert( pDef!=0 || IN_RENAME_OBJECT );
100190 if( pNC2 && pDef ){
100191 assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
100192 assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
100193 testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
100194 testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 );
100195 pNC2->ncFlags |= NC_HasAgg
100196 | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER)
100197 & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER));
100198 }
100199 }
100200 pNC->ncFlags |= savedAllowFlags;
100201 }
100202 /* FIX ME: Compute pExpr->affinity based on the expected return
@@ -100828,11 +100735,11 @@
100735 assert( pSub->pPrior && pSub->pOrderBy==0 );
100736 pSub->pOrderBy = p->pOrderBy;
100737 p->pOrderBy = 0;
100738 }
100739
100740 /* Recursively resolve names in all subqueries in the FROM clause
100741 */
100742 for(i=0; i<p->pSrc->nSrc; i++){
100743 SrcItem *pItem = &p->pSrc->a[i];
100744 if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
100745 int nRef = pOuterNC ? pOuterNC->nRef : 0;
@@ -100872,11 +100779,12 @@
100779 */
100780 assert( (p->selFlags & SF_Aggregate)==0 );
100781 pGroupBy = p->pGroupBy;
100782 if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
100783 assert( NC_MinMaxAgg==SF_MinMaxAgg );
100784 assert( NC_OrderAgg==SF_OrderByReqd );
100785 p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg));
100786 }else{
100787 sNC.ncFlags &= ~NC_AllowAgg;
100788 }
100789
100790 /* Add the output column list to the name-context before parsing the
@@ -101055,12 +100963,12 @@
100963 ){
100964 int savedHasAgg;
100965 Walker w;
100966
100967 if( pExpr==0 ) return SQLITE_OK;
100968 savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
100969 pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
100970 w.pParse = pNC->pParse;
100971 w.xExprCallback = resolveExprStep;
100972 w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
100973 w.xSelectCallback2 = 0;
100974 w.u.pNC = pNC;
@@ -101099,12 +101007,12 @@
101007 w.pParse = pNC->pParse;
101008 w.xExprCallback = resolveExprStep;
101009 w.xSelectCallback = resolveSelectStep;
101010 w.xSelectCallback2 = 0;
101011 w.u.pNC = pNC;
101012 savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101013 pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101014 for(i=0; i<pList->nExpr; i++){
101015 Expr *pExpr = pList->a[i].pExpr;
101016 if( pExpr==0 ) continue;
101017 #if SQLITE_MAX_EXPR_DEPTH>0
101018 w.pParse->nHeight += pExpr->nHeight;
@@ -101118,14 +101026,15 @@
101026 #endif
101027 assert( EP_Agg==NC_HasAgg );
101028 assert( EP_Win==NC_HasWin );
101029 testcase( pNC->ncFlags & NC_HasAgg );
101030 testcase( pNC->ncFlags & NC_HasWin );
101031 if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){
101032 ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
101033 savedHasAgg |= pNC->ncFlags &
101034 (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101035 pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
101036 }
101037 if( w.pParse->nErr>0 ) return WRC_Abort;
101038 }
101039 pNC->ncFlags |= savedHasAgg;
101040 return WRC_Continue;
@@ -101285,10 +101194,12 @@
101194 return sqlite3AffinityType(pExpr->u.zToken, 0);
101195 }
101196 #endif
101197 if( op==TK_SELECT_COLUMN ){
101198 assert( pExpr->pLeft->flags&EP_xIsSelect );
101199 assert( pExpr->iColumn < pExpr->iTable );
101200 assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr );
101201 return sqlite3ExprAffinity(
101202 pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
101203 );
101204 }
101205 if( op==TK_VECTOR ){
@@ -101385,11 +101296,11 @@
101296 ){
101297 /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
101298 ** a TK_COLUMN but was previously evaluated and cached in a register */
101299 int j = p->iColumn;
101300 if( j>=0 ){
101301 const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
101302 pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
101303 }
101304 break;
101305 }
101306 if( op==TK_CAST || op==TK_UPLUS ){
@@ -101695,11 +101606,12 @@
101606 ** of the returned TK_SELECT_COLUMN Expr object.
101607 */
101608 SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
101609 Parse *pParse, /* Parsing context */
101610 Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
101611 int iField, /* Which column of the vector to return */
101612 int nField /* Total number of columns in the vector */
101613 ){
101614 Expr *pRet;
101615 if( pVector->op==TK_SELECT ){
101616 assert( pVector->flags & EP_xIsSelect );
101617 /* The TK_SELECT_COLUMN Expr node:
@@ -101718,14 +101630,14 @@
101630 ** with the same pLeft pointer to the pVector, but only one of them
101631 ** will own the pVector.
101632 */
101633 pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
101634 if( pRet ){
101635 pRet->iTable = nField;
101636 pRet->iColumn = iField;
101637 pRet->pLeft = pVector;
101638 }
 
101639 }else{
101640 if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
101641 pRet = sqlite3ExprDup(pParse->db, pVector, 0);
101642 sqlite3RenameTokenRemap(pParse, pRet, pVector);
101643 }
@@ -102156,10 +102068,60 @@
102068 assert( pParse->db->mallocFailed );
102069 sqlite3SelectDelete(pParse->db, pSelect);
102070 }
102071 }
102072
102073 /*
102074 ** Expression list pEList is a list of vector values. This function
102075 ** converts the contents of pEList to a VALUES(...) Select statement
102076 ** returning 1 row for each element of the list. For example, the
102077 ** expression list:
102078 **
102079 ** ( (1,2), (3,4) (5,6) )
102080 **
102081 ** is translated to the equivalent of:
102082 **
102083 ** VALUES(1,2), (3,4), (5,6)
102084 **
102085 ** Each of the vector values in pEList must contain exactly nElem terms.
102086 ** If a list element that is not a vector or does not contain nElem terms,
102087 ** an error message is left in pParse.
102088 **
102089 ** This is used as part of processing IN(...) expressions with a list
102090 ** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))".
102091 */
102092 SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
102093 int ii;
102094 Select *pRet = 0;
102095 assert( nElem>1 );
102096 for(ii=0; ii<pEList->nExpr; ii++){
102097 Select *pSel;
102098 Expr *pExpr = pEList->a[ii].pExpr;
102099 int nExprElem = (pExpr->op==TK_VECTOR ? pExpr->x.pList->nExpr : 1);
102100 if( nExprElem!=nElem ){
102101 sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d",
102102 nExprElem, nExprElem>1?"s":"", nElem
102103 );
102104 break;
102105 }
102106 pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
102107 pExpr->x.pList = 0;
102108 if( pSel ){
102109 if( pRet ){
102110 pSel->op = TK_ALL;
102111 pSel->pPrior = pRet;
102112 }
102113 pRet = pSel;
102114 }
102115 }
102116
102117 if( pRet && pRet->pPrior ){
102118 pRet->selFlags |= SF_MultiValue;
102119 }
102120 sqlite3ExprListDelete(pParse->db, pEList);
102121 return pRet;
102122 }
102123
102124 /*
102125 ** Join two expressions using an AND operator. If either expression is
102126 ** NULL, then just return the other expression.
102127 **
@@ -102200,11 +102162,14 @@
102162 pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
102163 if( pNew==0 ){
102164 sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
102165 return 0;
102166 }
102167 if( pList
102168 && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
102169 && !pParse->nested
102170 ){
102171 sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
102172 }
102173 pNew->x.pList = pList;
102174 ExprSetProperty(pNew, EP_HasFunc);
102175 assert( !ExprHasProperty(pNew, EP_xIsSelect) );
@@ -102608,11 +102573,10 @@
102573 }
102574 }else{
102575 if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
102576 if( pNew->op==TK_SELECT_COLUMN ){
102577 pNew->pLeft = p->pLeft;
 
102578 assert( p->pRight==0 || p->pRight==p->pLeft
102579 || ExprHasProperty(p->pLeft, EP_Subquery) );
102580 }else{
102581 pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
102582 }
@@ -102706,11 +102670,12 @@
102670 }
102671 SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
102672 ExprList *pNew;
102673 struct ExprList_item *pItem, *pOldItem;
102674 int i;
102675 Expr *pPriorSelectColOld = 0;
102676 Expr *pPriorSelectColNew = 0;
102677 assert( db!=0 );
102678 if( p==0 ) return 0;
102679 pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
102680 if( pNew==0 ) return 0;
102681 pNew->nExpr = p->nExpr;
@@ -102723,21 +102688,21 @@
102688 pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
102689 if( pOldExpr
102690 && pOldExpr->op==TK_SELECT_COLUMN
102691 && (pNewExpr = pItem->pExpr)!=0
102692 ){
102693 if( pNewExpr->pRight ){
102694 pPriorSelectColOld = pOldExpr->pRight;
102695 pPriorSelectColNew = pNewExpr->pRight;
102696 pNewExpr->pLeft = pNewExpr->pRight;
 
102697 }else{
102698 if( pOldExpr->pLeft!=pPriorSelectColOld ){
102699 pPriorSelectColOld = pOldExpr->pLeft;
102700 pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags);
102701 pNewExpr->pRight = pPriorSelectColNew;
102702 }
102703 pNewExpr->pLeft = pPriorSelectColNew;
102704 }
102705 }
102706 pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
102707 pItem->sortFlags = pOldItem->sortFlags;
102708 pItem->eEName = pOldItem->eEName;
@@ -102992,15 +102957,13 @@
102957 pColumns->nId, n);
102958 goto vector_append_error;
102959 }
102960
102961 for(i=0; i<pColumns->nId; i++){
102962 Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId);
102963 assert( pSubExpr!=0 || db->mallocFailed );
 
102964 if( pSubExpr==0 ) continue;
 
102965 pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
102966 if( pList ){
102967 assert( pList->nExpr==iFirst+i+1 );
102968 pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
102969 pColumns->a[i].zName = 0;
@@ -103673,11 +103636,11 @@
103636 assert( pSrc!=0 );
103637 if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
103638 if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
103639 pTab = pSrc->a[0].pTab;
103640 assert( pTab!=0 );
103641 assert( !IsView(pTab) ); /* FROM clause is not a view */
103642 if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
103643 pEList = p->pEList;
103644 assert( pEList!=0 );
103645 /* All SELECT results must be columns. */
103646 for(i=0; i<pEList->nExpr; i++){
@@ -104803,13 +104766,14 @@
104766 /*
104767 ** Generate code that will compute the value of generated column pCol
104768 ** and store the result in register regOut
104769 */
104770 SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
104771 Parse *pParse, /* Parsing context */
104772 Table *pTab, /* Table containing the generated column */
104773 Column *pCol, /* The generated column */
104774 int regOut /* Put the result in this register */
104775 ){
104776 int iAddr;
104777 Vdbe *v = pParse->pVdbe;
104778 assert( v!=0 );
104779 assert( pParse->iSelfTab!=0 );
@@ -104816,11 +104780,11 @@
104780 if( pParse->iSelfTab>0 ){
104781 iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
104782 }else{
104783 iAddr = 0;
104784 }
104785 sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
104786 if( pCol->affinity>=SQLITE_AFF_TEXT ){
104787 sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
104788 }
104789 if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
104790 }
@@ -104852,16 +104816,17 @@
104816 x = iCol;
104817 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
104818 }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
104819 Parse *pParse = sqlite3VdbeParser(v);
104820 if( pCol->colFlags & COLFLAG_BUSY ){
104821 sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
104822 pCol->zCnName);
104823 }else{
104824 int savedSelfTab = pParse->iSelfTab;
104825 pCol->colFlags |= COLFLAG_BUSY;
104826 pParse->iSelfTab = iTabCur+1;
104827 sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut);
104828 pParse->iSelfTab = savedSelfTab;
104829 pCol->colFlags &= ~COLFLAG_BUSY;
104830 }
104831 return;
104832 #endif
@@ -105125,11 +105090,12 @@
105090 sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
105091 pCol->iSorterColumn, target);
105092 if( pCol->iColumn<0 ){
105093 VdbeComment((v,"%s.rowid",pTab->zName));
105094 }else{
105095 VdbeComment((v,"%s.%s",
105096 pTab->zName, pTab->aCol[pCol->iColumn].zCnName));
105097 if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
105098 sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
105099 }
105100 }
105101 return target;
@@ -105186,16 +105152,16 @@
105152 iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
105153 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
105154 if( pCol->colFlags & COLFLAG_GENERATED ){
105155 if( pCol->colFlags & COLFLAG_BUSY ){
105156 sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
105157 pCol->zCnName);
105158 return 0;
105159 }
105160 pCol->colFlags |= COLFLAG_BUSY;
105161 if( pCol->colFlags & COLFLAG_NOTAVAIL ){
105162 sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc);
105163 }
105164 pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
105165 return iSrc;
105166 }else
105167 #endif /* SQLITE_OMIT_GENERATED_COLUMNS */
@@ -105586,15 +105552,13 @@
105552 case TK_SELECT_COLUMN: {
105553 int n;
105554 if( pExpr->pLeft->iTable==0 ){
105555 pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
105556 }
105557 assert( pExpr->pLeft->op==TK_SELECT || pExpr->pLeft->op==TK_ERROR );
105558 n = sqlite3ExprVectorSize(pExpr->pLeft);
105559 if( pExpr->iTable!=n ){
 
 
105560 sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
105561 pExpr->iTable, n);
105562 }
105563 return pExpr->pLeft->iTable + pExpr->iColumn;
105564 }
@@ -105671,11 +105635,11 @@
105635 assert( p1>=0 && p1<(pTab->nCol*2+2) );
105636
105637 sqlite3VdbeAddOp2(v, OP_Param, p1, target);
105638 VdbeComment((v, "r[%d]=%s.%s", target,
105639 (pExpr->iTable ? "new" : "old"),
105640 (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zCnName)
105641 ));
105642
105643 #ifndef SQLITE_OMIT_FLOATING_POINT
105644 /* If the column has REAL affinity, it may currently be stored as an
105645 ** integer. Use OP_RealAffinity to make sure it is really real.
@@ -106843,13 +106807,13 @@
106807 testcase( pExpr->op==TK_LE );
106808 testcase( pExpr->op==TK_GT );
106809 testcase( pExpr->op==TK_GE );
106810 /* The y.pTab=0 assignment in wherecode.c always happens after the
106811 ** impliesNotNullRow() test */
106812 if( (pLeft->op==TK_COLUMN && pLeft->y.pTab!=0
106813 && IsVirtual(pLeft->y.pTab))
106814 || (pRight->op==TK_COLUMN && pRight->y.pTab!=0
106815 && IsVirtual(pRight->y.pTab))
106816 ){
106817 return WRC_Prune;
106818 }
106819 /* no break */ deliberate_fall_through
@@ -107524,22 +107488,19 @@
107488 sqlite3 *db = pParse->db; /* Database connection */
107489 int nTabName; /* Number of UTF-8 characters in zTabName */
107490 const char *zTabName; /* Original name of the table */
107491 Vdbe *v;
107492 VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
 
107493
 
107494 if( NEVER(db->mallocFailed) ) goto exit_rename_table;
107495 assert( pSrc->nSrc==1 );
107496 assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
107497
107498 pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
107499 if( !pTab ) goto exit_rename_table;
107500 iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
107501 zDb = db->aDb[iDb].zDbSName;
 
107502
107503 /* Get a NULL terminated version of the new table name. */
107504 zName = sqlite3NameFromToken(db, pName);
107505 if( !zName ) goto exit_rename_table;
107506
@@ -107564,11 +107525,11 @@
107525 if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
107526 goto exit_rename_table;
107527 }
107528
107529 #ifndef SQLITE_OMIT_VIEW
107530 if( IsView(pTab) ){
107531 sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
107532 goto exit_rename_table;
107533 }
107534 #endif
107535
@@ -107676,11 +107637,10 @@
107637 renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);
107638
107639 exit_rename_table:
107640 sqlite3SrcListDelete(db, pSrc);
107641 sqlite3DbFree(db, zName);
 
107642 }
107643
107644 /*
107645 ** Write code that will raise an error if the table described by
107646 ** zDb and zTab is not empty.
@@ -107726,11 +107686,11 @@
107686 assert( sqlite3BtreeHoldsAllMutexes(db) );
107687 iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
107688 zDb = db->aDb[iDb].zDbSName;
107689 zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
107690 pCol = &pNew->aCol[pNew->nCol-1];
107691 pDflt = sqlite3ColumnExpr(pNew, pCol);
107692 pTab = sqlite3FindTable(db, zTab, zDb);
107693 assert( pTab );
107694
107695 #ifndef SQLITE_OMIT_AUTHORIZATION
107696 /* Invoke the authorization callback. */
@@ -107760,11 +107720,11 @@
107720 */
107721 assert( pDflt==0 || pDflt->op==TK_SPAN );
107722 if( pDflt && pDflt->pLeft->op==TK_NULL ){
107723 pDflt = 0;
107724 }
107725 if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
107726 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
107727 "Cannot add a REFERENCES column with non-NULL default value");
107728 }
107729 if( pCol->notNull && !pDflt ){
107730 sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
@@ -107797,47 +107757,60 @@
107757
107758 /* Modify the CREATE TABLE statement. */
107759 zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
107760 if( zCol ){
107761 char *zEnd = &zCol[pColDef->n-1];
 
107762 while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
107763 *zEnd-- = '\0';
107764 }
 
107765 /* substr() operations on characters, but addColOffset is in bytes. So we
107766 ** have to use printf() to translate between these units: */
107767 assert( !IsVirtual(pTab) );
107768 sqlite3NestedParse(pParse,
107769 "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
107770 "sql = printf('%%.%ds, ',sql) || %Q"
107771 " || substr(sql,1+length(printf('%%.%ds',sql))) "
107772 "WHERE type = 'table' AND name = %Q",
107773 zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,
107774 zTab
107775 );
107776 sqlite3DbFree(db, zCol);
 
107777 }
107778
 
 
 
 
107779 v = sqlite3GetVdbe(pParse);
107780 if( v ){
107781 /* Make sure the schema version is at least 3. But do not upgrade
107782 ** from less than 3 to 4, as that will corrupt any preexisting DESC
107783 ** index.
107784 */
107785 r1 = sqlite3GetTempReg(pParse);
107786 sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
107787 sqlite3VdbeUsesBtree(v, iDb);
107788 sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
107789 sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
107790 VdbeCoverage(v);
107791 sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
107792 sqlite3ReleaseTempReg(pParse, r1);
107793
107794 /* Reload the table definition */
107795 renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
107796
107797 /* Verify that constraints are still satisfied */
107798 if( pNew->pCheck!=0
107799 || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)
107800 ){
107801 sqlite3NestedParse(pParse,
107802 "SELECT CASE WHEN quick_check GLOB 'CHECK*'"
107803 " THEN raise(ABORT,'CHECK constraint failed')"
107804 " ELSE raise(ABORT,'NOT NULL constraint failed')"
107805 " END"
107806 " FROM pragma_quick_check(\"%w\",\"%w\")"
107807 " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'",
107808 zTab, zDb
107809 );
107810 }
107811 }
 
 
 
107812 }
107813
107814 /*
107815 ** This function is called by the parser after the table-name in
107816 ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
@@ -107874,20 +107847,20 @@
107847 goto exit_begin_add_column;
107848 }
107849 #endif
107850
107851 /* Make sure this is not an attempt to ALTER a view. */
107852 if( IsView(pTab) ){
107853 sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
107854 goto exit_begin_add_column;
107855 }
107856 if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
107857 goto exit_begin_add_column;
107858 }
107859
107860 sqlite3MayAbort(pParse);
107861 assert( pTab->u.tab.addColOffset>0 );
107862 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
107863
107864 /* Put a copy of the Table struct in Parse.pNewTable for the
107865 ** sqlite3AddColumn() function and friends to modify. But modify
107866 ** the name by adding an "sqlite_altertab_" prefix. By adding this
@@ -107910,17 +107883,17 @@
107883 goto exit_begin_add_column;
107884 }
107885 memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
107886 for(i=0; i<pNew->nCol; i++){
107887 Column *pCol = &pNew->aCol[i];
107888 pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
107889 pCol->hName = sqlite3StrIHash(pCol->zCnName);
 
 
107890 }
107891 assert( !IsVirtual(pNew) );
107892 pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
107893 pNew->pSchema = db->aDb[iDb].pSchema;
107894 pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;
107895 pNew->nTabRef = 1;
107896
107897 exit_begin_add_column:
107898 sqlite3SrcListDelete(db, pSrc);
107899 return;
@@ -107936,11 +107909,11 @@
107909 */
107910 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
107911 static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
107912 const char *zType = 0;
107913 #ifndef SQLITE_OMIT_VIEW
107914 if( IsView(pTab) ){
107915 zType = "view";
107916 }
107917 #endif
107918 #ifndef SQLITE_OMIT_VIRTUALTABLE
107919 if( IsVirtual(pTab) ){
@@ -108003,11 +107976,11 @@
107976 /* Make sure the old name really is a column name in the table to be
107977 ** altered. Set iCol to be the index of the column being renamed */
107978 zOld = sqlite3NameFromToken(db, pOld);
107979 if( !zOld ) goto exit_rename_column;
107980 for(iCol=0; iCol<pTab->nCol; iCol++){
107981 if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
107982 }
107983 if( iCol==pTab->nCol ){
107984 sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
107985 goto exit_rename_column;
107986 }
@@ -108240,12 +108213,12 @@
108213 static int renameUnmapSelectCb(Walker *pWalker, Select *p){
108214 Parse *pParse = pWalker->pParse;
108215 int i;
108216 if( pParse->nErr ) return WRC_Abort;
108217 if( p->selFlags & (SF_View|SF_CopyCte) ){
108218 testcase( p->selFlags & SF_View );
108219 testcase( p->selFlags & SF_CopyCte );
108220 return WRC_Prune;
108221 }
108222 if( ALWAYS(p->pEList) ){
108223 ExprList *pList = p->pEList;
108224 for(i=0; i<pList->nExpr; i++){
@@ -108352,12 +108325,12 @@
108325 ** because without a dummy callback, sqlite3WalkExpr() and similar do not
108326 ** descend into sub-select statements.
108327 */
108328 static int renameColumnSelectCb(Walker *pWalker, Select *p){
108329 if( p->selFlags & (SF_View|SF_CopyCte) ){
108330 testcase( p->selFlags & SF_View );
108331 testcase( p->selFlags & SF_CopyCte );
108332 return WRC_Prune;
108333 }
108334 renameWalkWith(pWalker, p);
108335 return WRC_Continue;
108336 }
@@ -108549,17 +108522,17 @@
108522 RenameCtx *pRename, /* Rename context */
108523 const char *zSql, /* SQL statement to edit */
108524 const char *zNew, /* New token text */
108525 int bQuote /* True to always quote token */
108526 ){
108527 i64 nNew = sqlite3Strlen30(zNew);
108528 i64 nSql = sqlite3Strlen30(zSql);
108529 sqlite3 *db = sqlite3_context_db_handle(pCtx);
108530 int rc = SQLITE_OK;
108531 char *zQuot = 0;
108532 char *zOut;
108533 i64 nQuot = 0;
108534 char *zBuf1 = 0;
108535 char *zBuf2 = 0;
108536
108537 if( zNew ){
108538 /* Set zQuot to point to a buffer containing a quoted copy of the
@@ -108849,11 +108822,11 @@
108822 pTab = sqlite3FindTable(db, zTable, zDb);
108823 if( pTab==0 || iCol>=pTab->nCol ){
108824 sqlite3BtreeLeaveAll(db);
108825 return;
108826 }
108827 zOld = pTab->aCol[iCol].zCnName;
108828 memset(&sCtx, 0, sizeof(sCtx));
108829 sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);
108830
108831 #ifndef SQLITE_OMIT_AUTHORIZATION
108832 db->xAuth = 0;
@@ -108868,30 +108841,29 @@
108841 sWalker.u.pRename = &sCtx;
108842
108843 sCtx.pTab = pTab;
108844 if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
108845 if( sParse.pNewTable ){
108846 if( IsView(sParse.pNewTable) ){
108847 Select *pSelect = sParse.pNewTable->u.view.pSelect;
108848 pSelect->selFlags &= ~SF_View;
108849 sParse.rc = SQLITE_OK;
108850 sqlite3SelectPrep(&sParse, pSelect, 0);
108851 rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
108852 if( rc==SQLITE_OK ){
108853 sqlite3WalkSelect(&sWalker, pSelect);
108854 }
108855 if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
108856 }else if( ALWAYS(IsOrdinaryTable(sParse.pNewTable)) ){
108857 /* A regular table */
108858 int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
108859 FKey *pFKey;
 
108860 sCtx.pTab = sParse.pNewTable;
108861 if( bFKOnly==0 ){
108862 if( iCol<sParse.pNewTable->nCol ){
108863 renameTokenFind(
108864 &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName
108865 );
108866 }
108867 if( sCtx.iCol<0 ){
108868 renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
108869 }
@@ -108902,16 +108874,19 @@
108874 for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
108875 sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
108876 }
108877 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
108878 for(i=0; i<sParse.pNewTable->nCol; i++){
108879 Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable,
108880 &sParse.pNewTable->aCol[i]);
108881 sqlite3WalkExpr(&sWalker, pExpr);
108882 }
108883 #endif
108884 }
108885
108886 assert( !IsVirtual(sParse.pNewTable) );
108887 for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
108888 for(i=0; i<pFKey->nCol; i++){
108889 if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
108890 renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
108891 }
108892 if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
@@ -109073,32 +109048,35 @@
109048 if( rc==SQLITE_OK ){
109049 int isLegacy = (db->flags & SQLITE_LegacyAlter);
109050 if( sParse.pNewTable ){
109051 Table *pTab = sParse.pNewTable;
109052
109053 if( IsView(pTab) ){
109054 if( isLegacy==0 ){
109055 Select *pSelect = pTab->u.view.pSelect;
109056 NameContext sNC;
109057 memset(&sNC, 0, sizeof(sNC));
109058 sNC.pParse = &sParse;
109059
109060 assert( pSelect->selFlags & SF_View );
109061 pSelect->selFlags &= ~SF_View;
109062 sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
109063 if( sParse.nErr ){
109064 rc = sParse.rc;
109065 }else{
109066 sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect);
109067 }
109068 }
109069 }else{
109070 /* Modify any FK definitions to point to the new table. */
109071 #ifndef SQLITE_OMIT_FOREIGN_KEY
109072 if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
109073 && !IsVirtual(pTab)
109074 ){
109075 FKey *pFKey;
109076 assert( !IsVirtual(pTab) );
109077 for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
109078 if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
109079 renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
109080 }
109081 }
109082 }
@@ -109234,12 +109212,12 @@
109212 sWalker.xExprCallback = renameQuotefixExprCb;
109213 sWalker.xSelectCallback = renameColumnSelectCb;
109214 sWalker.u.pRename = &sCtx;
109215
109216 if( sParse.pNewTable ){
109217 if( IsView(sParse.pNewTable) ){
109218 Select *pSelect = sParse.pNewTable->u.view.pSelect;
109219 pSelect->selFlags &= ~SF_View;
109220 sParse.rc = SQLITE_OK;
109221 sqlite3SelectPrep(&sParse, pSelect, 0);
109222 rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
109223 if( rc==SQLITE_OK ){
@@ -109248,11 +109226,13 @@
109226 }else{
109227 int i;
109228 sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
109229 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
109230 for(i=0; i<sParse.pNewTable->nCol; i++){
109231 sqlite3WalkExpr(&sWalker,
109232 sqlite3ColumnExpr(sParse.pNewTable,
109233 &sParse.pNewTable->aCol[i]));
109234 }
109235 #endif /* SQLITE_OMIT_GENERATED_COLUMNS */
109236 }
109237 }else if( sParse.pNewIndex ){
109238 sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
@@ -109331,15 +109311,15 @@
109311 int flags = db->flags;
109312 if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
109313 rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
109314 db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
109315 if( rc==SQLITE_OK ){
109316 if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
109317 NameContext sNC;
109318 memset(&sNC, 0, sizeof(sNC));
109319 sNC.pParse = &sParse;
109320 sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC);
109321 if( sParse.nErr ) rc = sParse.rc;
109322 }
109323
109324 else if( sParse.pNewTrigger ){
109325 if( isLegacy==0 ){
@@ -109406,17 +109386,18 @@
109386 /* This can happen if the sqlite_schema table is corrupt */
109387 rc = SQLITE_CORRUPT_BKPT;
109388 goto drop_column_done;
109389 }
109390
109391 pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
109392 if( iCol<pTab->nCol-1 ){
109393 RenameToken *pEnd;
109394 pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
109395 zEnd = (const char*)pEnd->t.z;
109396 }else{
109397 assert( !IsVirtual(pTab) );
109398 zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
109399 while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
109400 }
109401
109402 zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
109403 sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
@@ -109547,10 +109528,16 @@
109528 }else{
109529 sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
109530 }
109531 nField++;
109532 }
109533 }
109534 if( nField==0 ){
109535 /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */
109536 pParse->nMem++;
109537 sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1);
109538 nField = 1;
109539 }
109540 sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
109541 if( pPk ){
109542 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
109543 }else{
@@ -110552,11 +110539,11 @@
110539 if( NEVER(i==XN_ROWID) ){
110540 VdbeComment((v,"%s.rowid",pIdx->zName));
110541 }else if( i==XN_EXPR ){
110542 VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
110543 }else{
110544 VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
110545 }
110546 }
110547 #else
110548 # define analyzeVdbeCommentIndexWithColumnName(a,b,c)
110549 #endif /* SQLITE_DEBUG */
@@ -112305,14 +112292,14 @@
112292 iCol = pExpr->iColumn;
112293 if( pTab==0 ) return;
112294
112295 if( iCol>=0 ){
112296 assert( iCol<pTab->nCol );
112297 zCol = pTab->aCol[iCol].zCnName;
112298 }else if( pTab->iPKey>=0 ){
112299 assert( pTab->iPKey<pTab->nCol );
112300 zCol = pTab->aCol[pTab->iPKey].zCnName;
112301 }else{
112302 zCol = "ROWID";
112303 }
112304 assert( iDb>=0 && iDb<pParse->db->nDb );
112305 if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
@@ -112686,24 +112673,26 @@
112673 }
112674
112675 /*
112676 ** Run the parser and code generator recursively in order to generate
112677 ** code for the SQL statement given onto the end of the pParse context
112678 ** currently under construction. Notes:
 
 
 
112679 **
112680 ** * The final OP_Halt is not appended and other initialization
112681 ** and finalization steps are omitted because those are handling by the
112682 ** outermost parser.
112683 **
112684 ** * Built-in SQL functions always take precedence over application-defined
112685 ** SQL functions. In other words, it is not possible to override a
112686 ** built-in function.
112687 */
112688 SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
112689 va_list ap;
112690 char *zSql;
112691 char *zErrMsg = 0;
112692 sqlite3 *db = pParse->db;
112693 u32 savedDbFlags = db->mDbFlags;
112694 char saveBuf[PARSE_TAIL_SZ];
112695
112696 if( pParse->nErr ) return;
112697 assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
112698 va_start(ap, zFormat);
@@ -112718,11 +112707,13 @@
112707 return;
112708 }
112709 pParse->nested++;
112710 memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
112711 memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
112712 db->mDbFlags |= DBFLAG_PreferBuiltin;
112713 sqlite3RunParser(pParse, zSql, &zErrMsg);
112714 db->mDbFlags = savedDbFlags;
112715 sqlite3DbFree(db, zErrMsg);
112716 sqlite3DbFree(db, zSql);
112717 memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
112718 pParse->nested--;
112719 }
@@ -112854,10 +112845,11 @@
112845 Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
112846 if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
112847 pMod = sqlite3PragmaVtabRegister(db, zName);
112848 }
112849 if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
112850 testcase( pMod->pEpoTab==0 );
112851 return pMod->pEpoTab;
112852 }
112853 }
112854 #endif
112855 if( flags & LOCATE_NOERR ) return 0;
@@ -113066,10 +113058,88 @@
113058 ** This routine is called when a commit occurs.
113059 */
113060 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
113061 db->mDbFlags &= ~DBFLAG_SchemaChange;
113062 }
113063
113064 /*
113065 ** Set the expression associated with a column. This is usually
113066 ** the DEFAULT value, but might also be the expression that computes
113067 ** the value for a generated column.
113068 */
113069 SQLITE_PRIVATE void sqlite3ColumnSetExpr(
113070 Parse *pParse, /* Parsing context */
113071 Table *pTab, /* The table containing the column */
113072 Column *pCol, /* The column to receive the new DEFAULT expression */
113073 Expr *pExpr /* The new default expression */
113074 ){
113075 ExprList *pList;
113076 assert( !IsVirtual(pTab) );
113077 pList = pTab->u.tab.pDfltList;
113078 if( pCol->iDflt==0
113079 || NEVER(pList==0)
113080 || NEVER(pList->nExpr<pCol->iDflt)
113081 ){
113082 pCol->iDflt = pList==0 ? 1 : pList->nExpr+1;
113083 pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr);
113084 }else{
113085 sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr);
113086 pList->a[pCol->iDflt-1].pExpr = pExpr;
113087 }
113088 }
113089
113090 /*
113091 ** Return the expression associated with a column. The expression might be
113092 ** the DEFAULT clause or the AS clause of a generated column.
113093 ** Return NULL if the column has no associated expression.
113094 */
113095 SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
113096 if( pCol->iDflt==0 ) return 0;
113097 if( NEVER(IsVirtual(pTab)) ) return 0;
113098 if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
113099 if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
113100 return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
113101 }
113102
113103 /*
113104 ** Set the collating sequence name for a column.
113105 */
113106 SQLITE_PRIVATE void sqlite3ColumnSetColl(
113107 sqlite3 *db,
113108 Column *pCol,
113109 const char *zColl
113110 ){
113111 int nColl;
113112 int n;
113113 char *zNew;
113114 assert( zColl!=0 );
113115 n = sqlite3Strlen30(pCol->zCnName) + 1;
113116 if( pCol->colFlags & COLFLAG_HASTYPE ){
113117 n += sqlite3Strlen30(pCol->zCnName+n) + 1;
113118 }
113119 nColl = sqlite3Strlen30(zColl) + 1;
113120 zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n);
113121 if( zNew ){
113122 pCol->zCnName = zNew;
113123 memcpy(pCol->zCnName + n, zColl, nColl);
113124 pCol->colFlags |= COLFLAG_HASCOLL;
113125 }
113126 }
113127
113128 /*
113129 ** Return the collating squence name for a column
113130 */
113131 SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){
113132 const char *z;
113133 if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0;
113134 z = pCol->zCnName;
113135 while( *z ){ z++; }
113136 if( pCol->colFlags & COLFLAG_HASTYPE ){
113137 do{ z++; }while( *z );
113138 }
113139 return z+1;
113140 }
113141
113142 /*
113143 ** Delete memory allocated for the column names of a table or view (the
113144 ** Table.aCol[] array).
113145 */
@@ -113077,16 +113147,24 @@
113147 int i;
113148 Column *pCol;
113149 assert( pTable!=0 );
113150 if( (pCol = pTable->aCol)!=0 ){
113151 for(i=0; i<pTable->nCol; i++, pCol++){
113152 assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
113153 sqlite3DbFree(db, pCol->zCnName);
 
 
113154 }
113155 sqlite3DbFree(db, pTable->aCol);
113156 if( !IsVirtual(pTable) ){
113157 sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
113158 }
113159 if( db==0 || db->pnBytesFreed==0 ){
113160 pTable->aCol = 0;
113161 pTable->nCol = 0;
113162 if( !IsVirtual(pTable) ){
113163 pTable->u.tab.pDfltList = 0;
113164 }
113165 }
113166 }
113167 }
113168
113169 /*
113170 ** Remove the memory data structures associated with the given
@@ -113134,23 +113212,29 @@
113212 assert( pOld==pIndex || pOld==0 );
113213 }
113214 sqlite3FreeIndex(db, pIndex);
113215 }
113216
113217 if( IsOrdinaryTable(pTable) ){
113218 sqlite3FkDelete(db, pTable);
113219 }
113220 #ifndef SQLITE_OMIT_VIRTUAL_TABLE
113221 else if( IsVirtual(pTable) ){
113222 sqlite3VtabClear(db, pTable);
113223 }
113224 #endif
113225 else{
113226 assert( IsView(pTable) );
113227 sqlite3SelectDelete(db, pTable->u.view.pSelect);
113228 }
113229
113230 /* Delete the Table structure itself.
113231 */
113232 sqlite3DeleteColumnNames(db, pTable);
113233 sqlite3DbFree(db, pTable->zName);
113234 sqlite3DbFree(db, pTable->zColAff);
 
113235 sqlite3ExprListDelete(db, pTable->pCheck);
 
 
 
113236 sqlite3DbFree(db, pTable);
113237
113238 /* Verify that no lookaside memory was used by schema tables */
113239 assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
113240 }
@@ -113672,20 +113756,21 @@
113756 /* Normal (non-error) return. */
113757 return;
113758
113759 /* If an error occurs, we jump here */
113760 begin_table_error:
113761 pParse->checkSchema = 1;
113762 sqlite3DbFree(db, zName);
113763 return;
113764 }
113765
113766 /* Set properties of a table column based on the (magical)
113767 ** name of the column.
113768 */
113769 #if SQLITE_ENABLE_HIDDEN_COLUMNS
113770 SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
113771 if( sqlite3_strnicmp(pCol->zCnName, "__hidden__", 10)==0 ){
113772 pCol->colFlags |= COLFLAG_HIDDEN;
113773 if( pTab ) pTab->tabFlags |= TF_HasHidden;
113774 }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
113775 pTab->tabFlags |= TF_OOOHidden;
113776 }
@@ -113772,67 +113857,108 @@
113857 ** The parser calls this routine once for each column declaration
113858 ** in a CREATE TABLE statement. sqlite3StartTable() gets called
113859 ** first to get things going. Then this routine is called for each
113860 ** column.
113861 */
113862 SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
113863 Table *p;
113864 int i;
113865 char *z;
113866 char *zType;
113867 Column *pCol;
113868 sqlite3 *db = pParse->db;
113869 u8 hName;
113870 Column *aNew;
113871 u8 eType = COLTYPE_CUSTOM;
113872 u8 szEst = 1;
113873 char affinity = SQLITE_AFF_BLOB;
113874
113875 if( (p = pParse->pNewTable)==0 ) return;
113876 if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
113877 sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
113878 return;
113879 }
113880 if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName);
113881
113882 /* Because keywords GENERATE ALWAYS can be converted into indentifiers
113883 ** by the parser, we can sometimes end up with a typename that ends
113884 ** with "generated always". Check for this case and omit the surplus
113885 ** text. */
113886 if( sType.n>=16
113887 && sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0
113888 ){
113889 sType.n -= 6;
113890 while( ALWAYS(sType.n>0) && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
113891 if( sType.n>=9
113892 && sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0
113893 ){
113894 sType.n -= 9;
113895 while( sType.n>0 && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
113896 }
113897 }
113898
113899 /* Check for standard typenames. For standard typenames we will
113900 ** set the Column.eType field rather than storing the typename after
113901 ** the column name, in order to save space. */
113902 if( sType.n>=3 ){
113903 sqlite3DequoteToken(&sType);
113904 for(i=0; i<SQLITE_N_STDTYPE; i++){
113905 if( sType.n==sqlite3StdTypeLen[i]
113906 && sqlite3_strnicmp(sType.z, sqlite3StdType[i], sType.n)==0
113907 ){
113908 sType.n = 0;
113909 eType = i+1;
113910 affinity = sqlite3StdTypeAffinity[i];
113911 if( affinity<=SQLITE_AFF_TEXT ) szEst = 5;
113912 break;
113913 }
113914 }
113915 }
113916
113917 z = sqlite3DbMallocRaw(db, sName.n + 1 + sType.n + (sType.n>0) );
113918 if( z==0 ) return;
113919 if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName);
113920 memcpy(z, sName.z, sName.n);
113921 z[sName.n] = 0;
113922 sqlite3Dequote(z);
113923 hName = sqlite3StrIHash(z);
113924 for(i=0; i<p->nCol; i++){
113925 if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
113926 sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
113927 sqlite3DbFree(db, z);
113928 return;
113929 }
113930 }
113931 aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+1)*sizeof(p->aCol[0]));
113932 if( aNew==0 ){
113933 sqlite3DbFree(db, z);
113934 return;
113935 }
113936 p->aCol = aNew;
 
 
 
113937 pCol = &p->aCol[p->nCol];
113938 memset(pCol, 0, sizeof(p->aCol[0]));
113939 pCol->zCnName = z;
113940 pCol->hName = hName;
113941 sqlite3ColumnPropertiesFromName(p, pCol);
113942
113943 if( sType.n==0 ){
113944 /* If there is no type specified, columns have the default affinity
113945 ** 'BLOB' with a default size of 4 bytes. */
113946 pCol->affinity = affinity;
113947 pCol->eType = eType;
113948 pCol->szEst = szEst;
113949 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
113950 if( affinity==SQLITE_AFF_BLOB ){
113951 if( 4>=sqlite3GlobalConfig.szSorterRef ){
113952 pCol->colFlags |= COLFLAG_SORTERREF;
113953 }
113954 }
113955 #endif
113956 }else{
113957 zType = z + sqlite3Strlen30(z) + 1;
113958 memcpy(zType, sType.z, sType.n);
113959 zType[sType.n] = 0;
113960 sqlite3Dequote(zType);
113961 pCol->affinity = sqlite3AffinityType(zType, pCol);
113962 pCol->colFlags |= COLFLAG_HASTYPE;
113963 }
113964 p->nCol++;
@@ -113983,11 +114109,11 @@
114109 if( p!=0 ){
114110 int isInit = db->init.busy && db->init.iDb!=1;
114111 pCol = &(p->aCol[p->nCol-1]);
114112 if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
114113 sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
114114 pCol->zCnName);
114115 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
114116 }else if( pCol->colFlags & COLFLAG_GENERATED ){
114117 testcase( pCol->colFlags & COLFLAG_VIRTUAL );
114118 testcase( pCol->colFlags & COLFLAG_STORED );
114119 sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
@@ -113994,19 +114120,19 @@
114120 #endif
114121 }else{
114122 /* A copy of pExpr is used instead of the original, as pExpr contains
114123 ** tokens that point to volatile memory.
114124 */
114125 Expr x, *pDfltExpr;
 
114126 memset(&x, 0, sizeof(x));
114127 x.op = TK_SPAN;
114128 x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
114129 x.pLeft = pExpr;
114130 x.flags = EP_Skip;
114131 pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
114132 sqlite3DbFree(db, x.u.zToken);
114133 sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr);
114134 }
114135 }
114136 if( IN_RENAME_OBJECT ){
114137 sqlite3RenameExprUnmap(pParse, pExpr);
114138 }
@@ -114100,11 +114226,11 @@
114226 assert( pCExpr!=0 );
114227 sqlite3StringToId(pCExpr);
114228 if( pCExpr->op==TK_ID ){
114229 const char *zCName = pCExpr->u.zToken;
114230 for(iCol=0; iCol<pTab->nCol; iCol++){
114231 if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
114232 pCol = &pTab->aCol[iCol];
114233 makeColumnPartOfPrimaryKey(pParse, pCol);
114234 break;
114235 }
114236 }
@@ -114111,11 +114237,11 @@
114237 }
114238 }
114239 }
114240 if( nTerm==1
114241 && pCol
114242 && pCol->eType==COLTYPE_INTEGER
114243 && sortOrder!=SQLITE_SO_DESC
114244 ){
114245 if( IN_RENAME_OBJECT && pList ){
114246 Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr);
114247 sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr);
@@ -114191,26 +114317,24 @@
114317 zColl = sqlite3NameFromToken(db, pToken);
114318 if( !zColl ) return;
114319
114320 if( sqlite3LocateCollSeq(pParse, zColl) ){
114321 Index *pIdx;
114322 sqlite3ColumnSetColl(db, &p->aCol[i], zColl);
 
114323
114324 /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
114325 ** then an index may have been created on this column before the
114326 ** collation type was added. Correct this if it is the case.
114327 */
114328 for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
114329 assert( pIdx->nKeyCol==1 );
114330 if( pIdx->aiColumn[0]==i ){
114331 pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]);
114332 }
114333 }
 
 
114334 }
114335 sqlite3DbFree(db, zColl);
114336 }
114337
114338 /* Change the most recently parsed column to be a GENERATED ALWAYS AS
114339 ** column.
114340 */
@@ -114226,11 +114350,11 @@
114350 pCol = &(pTab->aCol[pTab->nCol-1]);
114351 if( IN_DECLARE_VTAB ){
114352 sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
114353 goto generated_done;
114354 }
114355 if( pCol->iDflt>0 ) goto generated_error;
114356 if( pType ){
114357 if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
114358 /* no-op */
114359 }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
114360 eType = COLFLAG_STORED;
@@ -114244,17 +114368,17 @@
114368 assert( TF_HasStored==COLFLAG_STORED );
114369 pTab->tabFlags |= eType;
114370 if( pCol->colFlags & COLFLAG_PRIMKEY ){
114371 makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
114372 }
114373 sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr);
114374 pExpr = 0;
114375 goto generated_done;
114376
114377 generated_error:
114378 sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
114379 pCol->zCnName);
114380 generated_done:
114381 sqlite3ExprDelete(pParse->db, pExpr);
114382 #else
114383 /* Throw and error for the GENERATED ALWAYS AS clause if the
114384 ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
@@ -114352,11 +114476,11 @@
114476 char *zStmt;
114477 char *zSep, *zSep2, *zEnd;
114478 Column *pCol;
114479 n = 0;
114480 for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
114481 n += identLength(pCol->zCnName) + 5;
114482 }
114483 n += identLength(p->zName);
114484 if( n<50 ){
114485 zSep = "";
114486 zSep2 = ",";
@@ -114388,11 +114512,11 @@
114512 const char *zType;
114513
114514 sqlite3_snprintf(n-k, &zStmt[k], zSep);
114515 k += sqlite3Strlen30(&zStmt[k]);
114516 zSep = zSep2;
114517 identPut(zStmt, &k, pCol->zCnName);
114518 assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
114519 assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
114520 testcase( pCol->affinity==SQLITE_AFF_BLOB );
114521 testcase( pCol->affinity==SQLITE_AFF_TEXT );
114522 testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
@@ -114607,11 +114731,11 @@
114731 ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
114732 */
114733 if( pTab->iPKey>=0 ){
114734 ExprList *pList;
114735 Token ipkToken;
114736 sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName);
114737 pList = sqlite3ExprListAppend(pParse, 0,
114738 sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
114739 if( pList==0 ){
114740 pTab->tabFlags &= ~TF_WithoutRowid;
114741 return;
@@ -114737,11 +114861,11 @@
114861
114862 if( !IsVirtual(pTab) ) return 0;
114863 nName = sqlite3Strlen30(pTab->zName);
114864 if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
114865 if( zName[nName]!='_' ) return 0;
114866 pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
114867 if( pMod==0 ) return 0;
114868 if( pMod->pModule->iVersion<3 ) return 0;
114869 if( pMod->pModule->xShadowName==0 ) return 0;
114870 return pMod->pModule->xShadowName(zName+nName+1);
114871 }
@@ -114898,22 +115022,22 @@
115022 testcase( p->tabFlags & TF_HasVirtual );
115023 testcase( p->tabFlags & TF_HasStored );
115024 for(ii=0; ii<p->nCol; ii++){
115025 u32 colFlags = p->aCol[ii].colFlags;
115026 if( (colFlags & COLFLAG_GENERATED)!=0 ){
115027 Expr *pX = sqlite3ColumnExpr(p, &p->aCol[ii]);
115028 testcase( colFlags & COLFLAG_VIRTUAL );
115029 testcase( colFlags & COLFLAG_STORED );
115030 if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
115031 /* If there are errors in resolving the expression, change the
115032 ** expression to a NULL. This prevents code generators that operate
115033 ** on the expression from inserting extra parts into the expression
115034 ** tree that have been allocated from lookaside memory, which is
115035 ** illegal in a schema and will lead to errors or heap corruption
115036 ** when the database connection closes. */
115037 sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii],
115038 sqlite3ExprAlloc(db, TK_NULL, 0, 0));
115039 }
115040 }else{
115041 nNG++;
115042 }
115043 }
@@ -114949,11 +115073,11 @@
115073 sqlite3VdbeAddOp1(v, OP_Close, 0);
115074
115075 /*
115076 ** Initialize zType for the new view or table.
115077 */
115078 if( IsOrdinaryTable(p) ){
115079 /* A regular table */
115080 zType = "table";
115081 zType2 = "TABLE";
115082 #ifndef SQLITE_OMIT_VIEW
115083 }else{
@@ -115099,16 +115223,16 @@
115223 }
115224 #endif
115225 }
115226
115227 #ifndef SQLITE_OMIT_ALTERTABLE
115228 if( !pSelect && IsOrdinaryTable(p) ){
115229 assert( pCons && pEnd );
115230 if( pCons->z==0 ){
115231 pCons = pEnd;
115232 }
115233 p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
115234 }
115235 #endif
115236 }
115237
115238 #ifndef SQLITE_OMIT_VIEW
@@ -115161,16 +115285,17 @@
115285 ** allocated rather than point to the input string - which means that
115286 ** they will persist after the current sqlite3_exec() call returns.
115287 */
115288 pSelect->selFlags |= SF_View;
115289 if( IN_RENAME_OBJECT ){
115290 p->u.view.pSelect = pSelect;
115291 pSelect = 0;
115292 }else{
115293 p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
115294 }
115295 p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
115296 p->eTabType = TABTYP_VIEW;
115297 if( db->mallocFailed ) goto create_view_fail;
115298
115299 /* Locate the end of the CREATE VIEW statement. Make sEnd point to
115300 ** the end.
115301 */
@@ -115263,12 +115388,12 @@
115388 ** "*" elements in the results set of the view and will assign cursors
115389 ** to the elements of the FROM clause. But we do not want these changes
115390 ** to be permanent. So the computation is done on a copy of the SELECT
115391 ** statement that defines the view.
115392 */
115393 assert( IsView(pTable) );
115394 pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
115395 if( pSel ){
115396 u8 eParseMode = pParse->eParseMode;
115397 pParse->eParseMode = PARSE_MODE_NORMAL;
115398 n = pParse->nTab;
115399 sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
@@ -115323,12 +115448,10 @@
115448 nErr++;
115449 }
115450 pTable->pSchema->schemaFlags |= DB_UnresetViews;
115451 if( db->mallocFailed ){
115452 sqlite3DeleteColumnNames(db, pTable);
 
 
115453 }
115454 #endif /* SQLITE_OMIT_VIEW */
115455 return nErr;
115456 }
115457 #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -115341,14 +115464,12 @@
115464 HashElem *i;
115465 assert( sqlite3SchemaMutexHeld(db, idx, 0) );
115466 if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
115467 for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
115468 Table *pTab = sqliteHashData(i);
115469 if( IsView(pTab) ){
115470 sqlite3DeleteColumnNames(db, pTab);
 
 
115471 }
115472 }
115473 DbClearProperty(db, idx, DB_UnresetViews);
115474 }
115475 #else
@@ -115581,10 +115702,11 @@
115702 SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){
115703 #ifndef SQLITE_OMIT_VIRTUALTABLE
115704 if( (db->flags & SQLITE_Defensive)!=0
115705 && db->pVtabCtx==0
115706 && db->nVdbeExec==0
115707 && !sqlite3VtabInSync(db)
115708 ){
115709 return 1;
115710 }
115711 #endif
115712 return 0;
@@ -115684,15 +115806,15 @@
115806
115807 #ifndef SQLITE_OMIT_VIEW
115808 /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
115809 ** on a table.
115810 */
115811 if( isView && !IsView(pTab) ){
115812 sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
115813 goto exit_drop_table;
115814 }
115815 if( !isView && IsView(pTab) ){
115816 sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
115817 goto exit_drop_table;
115818 }
115819 #endif
115820
@@ -115752,11 +115874,11 @@
115874 int iCol = p->nCol-1;
115875 if( NEVER(iCol<0) ) goto fk_end;
115876 if( pToCol && pToCol->nExpr!=1 ){
115877 sqlite3ErrorMsg(pParse, "foreign key on %s"
115878 " should reference only one column of table %T",
115879 p->aCol[iCol].zCnName, pTo);
115880 goto fk_end;
115881 }
115882 nCol = 1;
115883 }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
115884 sqlite3ErrorMsg(pParse,
@@ -115775,11 +115897,11 @@
115897 pFKey = sqlite3DbMallocZero(db, nByte );
115898 if( pFKey==0 ){
115899 goto fk_end;
115900 }
115901 pFKey->pFrom = p;
115902 pFKey->pNextFrom = p->u.tab.pFKey;
115903 z = (char*)&pFKey->aCol[nCol];
115904 pFKey->zTo = z;
115905 if( IN_RENAME_OBJECT ){
115906 sqlite3RenameTokenMap(pParse, (void*)z, pTo);
115907 }
@@ -115792,11 +115914,11 @@
115914 pFKey->aCol[0].iFrom = p->nCol-1;
115915 }else{
115916 for(i=0; i<nCol; i++){
115917 int j;
115918 for(j=0; j<p->nCol; j++){
115919 if( sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){
115920 pFKey->aCol[i].iFrom = j;
115921 break;
115922 }
115923 }
115924 if( j>=p->nCol ){
@@ -115840,11 +115962,12 @@
115962 pNextTo->pPrevTo = pFKey;
115963 }
115964
115965 /* Link the foreign key to the table as the last step.
115966 */
115967 assert( !IsVirtual(p) );
115968 p->u.tab.pFKey = pFKey;
115969 pFKey = 0;
115970
115971 fk_end:
115972 sqlite3DbFree(db, pFKey);
115973 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
@@ -115861,11 +115984,13 @@
115984 */
115985 SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
115986 #ifndef SQLITE_OMIT_FOREIGN_KEY
115987 Table *pTab;
115988 FKey *pFKey;
115989 if( (pTab = pParse->pNewTable)==0 ) return;
115990 if( NEVER(IsVirtual(pTab)) ) return;
115991 if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
115992 assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
115993 pFKey->isDeferred = (u8)isDeferred;
115994 #endif
115995 }
115996
@@ -116153,11 +116278,11 @@
116278 ){
116279 sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
116280 goto exit_create_index;
116281 }
116282 #ifndef SQLITE_OMIT_VIEW
116283 if( IsView(pTab) ){
116284 sqlite3ErrorMsg(pParse, "views may not be indexed");
116285 goto exit_create_index;
116286 }
116287 #endif
116288 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -116244,11 +116369,11 @@
116369 */
116370 if( pList==0 ){
116371 Token prevCol;
116372 Column *pCol = &pTab->aCol[pTab->nCol-1];
116373 pCol->colFlags |= COLFLAG_UNIQUE;
116374 sqlite3TokenInit(&prevCol, pCol->zCnName);
116375 pList = sqlite3ExprListAppend(pParse, 0,
116376 sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
116377 if( pList==0 ) goto exit_create_index;
116378 assert( pList->nExpr==1 );
116379 sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
@@ -116365,11 +116490,11 @@
116490 memcpy(zExtra, zColl, nColl);
116491 zColl = zExtra;
116492 zExtra += nColl;
116493 nExtra -= nColl;
116494 }else if( j>=0 ){
116495 zColl = sqlite3ColumnColl(&pTab->aCol[j]);
116496 }
116497 if( !zColl ) zColl = sqlite3StrBINARY;
116498 if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
116499 goto exit_create_index;
116500 }
@@ -117457,11 +117582,11 @@
117582 sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
117583 }else{
117584 for(j=0; j<pIdx->nKeyCol; j++){
117585 char *zCol;
117586 assert( pIdx->aiColumn[j]>=0 );
117587 zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName;
117588 if( j ) sqlite3_str_append(&errMsg, ", ", 2);
117589 sqlite3_str_appendall(&errMsg, pTab->zName);
117590 sqlite3_str_append(&errMsg, ".", 1);
117591 sqlite3_str_appendall(&errMsg, zCol);
117592 }
@@ -117484,11 +117609,11 @@
117609 ){
117610 char *zMsg;
117611 int rc;
117612 if( pTab->iPKey>=0 ){
117613 zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
117614 pTab->aCol[pTab->iPKey].zCnName);
117615 rc = SQLITE_CONSTRAINT_PRIMARYKEY;
117616 }else{
117617 zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
117618 rc = SQLITE_CONSTRAINT_ROWID;
117619 }
@@ -118411,11 +118536,11 @@
118536 if( tabIsReadOnly(pParse, pTab) ){
118537 sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
118538 return 1;
118539 }
118540 #ifndef SQLITE_OMIT_VIEW
118541 if( !viewOk && IsView(pTab) ){
118542 sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
118543 return 1;
118544 }
118545 #endif
118546 return 0;
@@ -118515,17 +118640,17 @@
118640 pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
118641 );
118642 }else{
118643 Index *pPk = sqlite3PrimaryKeyIndex(pTab);
118644 if( pPk->nKeyCol==1 ){
118645 const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName;
118646 pLhs = sqlite3Expr(db, TK_ID, zName);
118647 pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
118648 }else{
118649 int i;
118650 for(i=0; i<pPk->nKeyCol; i++){
118651 Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
118652 pEList = sqlite3ExprListAppend(pParse, pEList, p);
118653 }
118654 pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
118655 if( pLhs ){
118656 pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
@@ -118628,11 +118753,11 @@
118753 /* Figure out if we have any triggers and if the table being
118754 ** deleted from is a view
118755 */
118756 #ifndef SQLITE_OMIT_TRIGGER
118757 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
118758 isView = IsView(pTab);
118759 #else
118760 # define pTrigger 0
118761 # define isView 0
118762 #endif
118763 bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
@@ -118878,11 +119003,11 @@
119003 ** where-clause loop above.
119004 */
119005 if( eOnePass!=ONEPASS_OFF ){
119006 assert( nKey==nPk ); /* OP_Found will use an unpacked key */
119007 if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
119008 assert( pPk!=0 || IsView(pTab) );
119009 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
119010 VdbeCoverage(v);
119011 }
119012 }else if( pPk ){
119013 addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
@@ -119112,11 +119237,11 @@
119237 ** invoke the update-hook. The pre-update-hook, on the other hand should
119238 ** be invoked unless table pTab is a system table. The difference is that
119239 ** the update-hook is not invoked for rows removed by REPLACE, but the
119240 ** pre-update-hook is.
119241 */
119242 if( !IsView(pTab) ){
119243 u8 p5 = 0;
119244 sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
119245 sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
119246 if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
119247 sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
@@ -119873,37 +119998,37 @@
119998
119999 /*
120000 ** Implementation of the changes() SQL function.
120001 **
120002 ** IMP: R-62073-11209 The changes() SQL function is a wrapper
120003 ** around the sqlite3_changes64() C/C++ function and hence follows the same
120004 ** rules for counting changes.
120005 */
120006 static void changes(
120007 sqlite3_context *context,
120008 int NotUsed,
120009 sqlite3_value **NotUsed2
120010 ){
120011 sqlite3 *db = sqlite3_context_db_handle(context);
120012 UNUSED_PARAMETER2(NotUsed, NotUsed2);
120013 sqlite3_result_int64(context, sqlite3_changes64(db));
120014 }
120015
120016 /*
120017 ** Implementation of the total_changes() SQL function. The return value is
120018 ** the same as the sqlite3_total_changes64() API function.
120019 */
120020 static void total_changes(
120021 sqlite3_context *context,
120022 int NotUsed,
120023 sqlite3_value **NotUsed2
120024 ){
120025 sqlite3 *db = sqlite3_context_db_handle(context);
120026 UNUSED_PARAMETER2(NotUsed, NotUsed2);
120027 /* IMP: R-52756-41993 This function was a wrapper around the
120028 ** sqlite3_total_changes() C/C++ interface. */
120029 sqlite3_result_int64(context, sqlite3_total_changes64(db));
120030 }
120031
120032 /*
120033 ** A structure defining how to do GLOB-style comparisons.
120034 */
@@ -120617,29 +120742,29 @@
120742 int argc,
120743 sqlite3_value **argv
120744 ){
120745 const unsigned char *zIn; /* Input string */
120746 const unsigned char *zCharSet; /* Set of characters to trim */
120747 unsigned int nIn; /* Number of bytes in input */
120748 int flags; /* 1: trimleft 2: trimright 3: trim */
120749 int i; /* Loop counter */
120750 unsigned int *aLen = 0; /* Length of each character in zCharSet */
120751 unsigned char **azChar = 0; /* Individual characters in zCharSet */
120752 int nChar; /* Number of characters in zCharSet */
120753
120754 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
120755 return;
120756 }
120757 zIn = sqlite3_value_text(argv[0]);
120758 if( zIn==0 ) return;
120759 nIn = (unsigned)sqlite3_value_bytes(argv[0]);
120760 assert( zIn==sqlite3_value_text(argv[0]) );
120761 if( argc==1 ){
120762 static const unsigned lenOne[] = { 1 };
120763 static unsigned char * const azOne[] = { (u8*)" " };
120764 nChar = 1;
120765 aLen = (unsigned*)lenOne;
120766 azChar = (unsigned char **)azOne;
120767 zCharSet = 0;
120768 }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
120769 return;
120770 }else{
@@ -120646,27 +120771,28 @@
120771 const unsigned char *z;
120772 for(z=zCharSet, nChar=0; *z; nChar++){
120773 SQLITE_SKIP_UTF8(z);
120774 }
120775 if( nChar>0 ){
120776 azChar = contextMalloc(context,
120777 ((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
120778 if( azChar==0 ){
120779 return;
120780 }
120781 aLen = (unsigned*)&azChar[nChar];
120782 for(z=zCharSet, nChar=0; *z; nChar++){
120783 azChar[nChar] = (unsigned char *)z;
120784 SQLITE_SKIP_UTF8(z);
120785 aLen[nChar] = (unsigned)(z - azChar[nChar]);
120786 }
120787 }
120788 }
120789 if( nChar>0 ){
120790 flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
120791 if( flags & 1 ){
120792 while( nIn>0 ){
120793 unsigned int len = 0;
120794 for(i=0; i<nChar; i++){
120795 len = aLen[i];
120796 if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
120797 }
120798 if( i>=nChar ) break;
@@ -120674,11 +120800,11 @@
120800 nIn -= len;
120801 }
120802 }
120803 if( flags & 2 ){
120804 while( nIn>0 ){
120805 unsigned int len = 0;
120806 for(i=0; i<nChar; i++){
120807 len = aLen[i];
120808 if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
120809 }
120810 if( i>=nChar ) break;
@@ -121460,15 +121586,15 @@
121586 FUNCTION(trim, 1, 3, 0, trimFunc ),
121587 FUNCTION(trim, 2, 3, 0, trimFunc ),
121588 FUNCTION(min, -1, 0, 1, minmaxFunc ),
121589 FUNCTION(min, 0, 0, 1, 0 ),
121590 WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
121591 SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
121592 FUNCTION(max, -1, 1, 1, minmaxFunc ),
121593 FUNCTION(max, 0, 1, 1, 0 ),
121594 WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
121595 SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
121596 FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
121597 FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
121598 FUNCTION(instr, 2, 0, 0, instrFunc ),
121599 FUNCTION(printf, -1, 0, 0, printfFunc ),
121600 FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
@@ -121500,13 +121626,14 @@
121626 FUNCTION(substring, 3, 0, 0, substrFunc ),
121627 WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
121628 WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
121629 WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
121630 WAGGREGATE(count, 0,0,0, countStep,
121631 countFinalize, countFinalize, countInverse,
121632 SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ),
121633 WAGGREGATE(count, 1,0,0, countStep,
121634 countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
121635 WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
121636 groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
121637 WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
121638 groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
121639
@@ -121804,11 +121931,13 @@
121931 ** 2) The FK is explicitly mapped to a column declared as INTEGER
121932 ** PRIMARY KEY.
121933 */
121934 if( pParent->iPKey>=0 ){
121935 if( !zKey ) return 0;
121936 if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){
121937 return 0;
121938 }
121939 }
121940 }else if( paiCol ){
121941 assert( nCol>1 );
121942 aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
121943 if( !aiCol ) return 1;
@@ -121846,15 +121975,15 @@
121975 if( iCol<0 ) break; /* No foreign keys against expression indexes */
121976
121977 /* If the index uses a collation sequence that is different from
121978 ** the default collation sequence for the column, this index is
121979 ** unusable. Bail out early in this case. */
121980 zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]);
121981 if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
121982 if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
121983
121984 zIdxCol = pParent->aCol[iCol].zCnName;
121985 for(j=0; j<nCol; j++){
121986 if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
121987 if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
121988 break;
121989 }
@@ -122074,11 +122203,11 @@
122203 if( pExpr ){
122204 if( iCol>=0 && iCol!=pTab->iPKey ){
122205 pCol = &pTab->aCol[iCol];
122206 pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
122207 pExpr->affExpr = pCol->affinity;
122208 zColl = sqlite3ColumnColl(pCol);
122209 if( zColl==0 ) zColl = db->pDfltColl->zName;
122210 pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
122211 }else{
122212 pExpr->iTable = regBase;
122213 pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -122183,11 +122312,11 @@
122312
122313 iCol = pIdx ? pIdx->aiColumn[i] : -1;
122314 pLeft = exprTableRegister(pParse, pTab, regData, iCol);
122315 iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
122316 assert( iCol>=0 );
122317 zCol = pFKey->pFrom->aCol[iCol].zCnName;
122318 pRight = sqlite3Expr(db, TK_ID, zCol);
122319 pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
122320 pWhere = sqlite3ExprAnd(pParse, pWhere, pEq);
122321 }
122322
@@ -122218,11 +122347,11 @@
122347 assert( pIdx!=0 );
122348 for(i=0; i<pIdx->nKeyCol; i++){
122349 i16 iCol = pIdx->aiColumn[i];
122350 assert( iCol>=0 );
122351 pLeft = exprTableRegister(pParse, pTab, regData, iCol);
122352 pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName);
122353 pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
122354 pAll = sqlite3ExprAnd(pParse, pAll, pEq);
122355 }
122356 pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
122357 }
@@ -122312,19 +122441,20 @@
122441 if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
122442 int iSkip = 0;
122443 Vdbe *v = sqlite3GetVdbe(pParse);
122444
122445 assert( v ); /* VDBE has already been allocated */
122446 assert( !IsView(pTab) ); /* Not a view */
122447 assert( !IsVirtual(pTab) );
122448 if( sqlite3FkReferences(pTab)==0 ){
122449 /* Search for a deferred foreign key constraint for which this table
122450 ** is the child table. If one cannot be found, return without
122451 ** generating any VDBE code. If one can be found, then jump over
122452 ** the entire DELETE if there are no outstanding deferred constraints
122453 ** when this statement is run. */
122454 FKey *p;
122455 for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
122456 if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
122457 }
122458 if( !p ) return;
122459 iSkip = sqlite3VdbeMakeLabel(pParse);
122460 sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
@@ -122409,11 +122539,11 @@
122539 int iKey;
122540 for(iKey=0; iKey<pTab->nCol; iKey++){
122541 if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
122542 Column *pCol = &pTab->aCol[iKey];
122543 if( zKey ){
122544 if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1;
122545 }else if( pCol->colFlags & COLFLAG_PRIMKEY ){
122546 return 1;
122547 }
122548 }
122549 }
@@ -122482,11 +122612,12 @@
122612 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
122613 zDb = db->aDb[iDb].zDbSName;
122614
122615 /* Loop through all the foreign key constraints for which pTab is the
122616 ** child table (the table that the foreign key definition is part of). */
122617 assert( !IsVirtual(pTab) );
122618 for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
122619 Table *pTo; /* Parent table of foreign key pFKey */
122620 Index *pIdx = 0; /* Index on key columns in pTo */
122621 int *aiFree = 0;
122622 int *aiCol;
122623 int iCol;
@@ -122549,11 +122680,11 @@
122680 /* Request permission to read the parent key columns. If the
122681 ** authorization callback returns SQLITE_IGNORE, behave as if any
122682 ** values read from the parent table are NULL. */
122683 if( db->xAuth ){
122684 int rcauth;
122685 char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName;
122686 rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
122687 bIgnore = (rcauth==SQLITE_IGNORE);
122688 }
122689 #endif
122690 }
@@ -122667,11 +122798,12 @@
122798 ){
122799 u32 mask = 0;
122800 if( pParse->db->flags&SQLITE_ForeignKeys ){
122801 FKey *p;
122802 int i;
122803 assert( !IsVirtual(pTab) );
122804 for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
122805 for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
122806 }
122807 for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
122808 Index *pIdx = 0;
122809 sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
@@ -122717,23 +122849,23 @@
122849 int *aChange, /* Non-NULL for UPDATE operations */
122850 int chngRowid /* True for UPDATE that affects rowid */
122851 ){
122852 int eRet = 1; /* Value to return if bHaveFK is true */
122853 int bHaveFK = 0; /* If FK processing is required */
122854 if( pParse->db->flags&SQLITE_ForeignKeys && !IsVirtual(pTab) ){
122855 if( !aChange ){
122856 /* A DELETE operation. Foreign key processing is required if the
122857 ** table in question is either the child or parent table for any
122858 ** foreign key constraint. */
122859 bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
122860 }else{
122861 /* This is an UPDATE. Foreign key processing is only required if the
122862 ** operation modifies one or more child or parent key columns. */
122863 FKey *p;
122864
122865 /* Check if any child key columns are being modified. */
122866 for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
122867 if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
122868 if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
122869 bHaveFK = 1;
122870 }
122871 }
@@ -122822,12 +122954,12 @@
122954 iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
122955 assert( iFromCol>=0 );
122956 assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
122957 assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
122958 sqlite3TokenInit(&tToCol,
122959 pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName);
122960 sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName);
122961
122962 /* Create the expression "OLD.zToCol = zFromCol". It is important
122963 ** that the "OLD.zToCol" term is on the LHS of the = operator, so
122964 ** that the affinity and collation sequence associated with the
122965 ** parent table are used for the comparison. */
@@ -122868,11 +123000,11 @@
123000 if( pCol->colFlags & COLFLAG_GENERATED ){
123001 testcase( pCol->colFlags & COLFLAG_VIRTUAL );
123002 testcase( pCol->colFlags & COLFLAG_STORED );
123003 pDflt = 0;
123004 }else{
123005 pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol);
123006 }
123007 if( pDflt ){
123008 pNew = sqlite3ExprDup(db, pDflt, 0);
123009 }else{
123010 pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
@@ -123005,13 +123137,13 @@
123137 */
123138 SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
123139 FKey *pFKey; /* Iterator variable */
123140 FKey *pNext; /* Copy of pFKey->pNextFrom */
123141
123142 assert( !IsVirtual(pTab) );
123143 for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
123144 assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
123145
123146 /* Remove the FK from the fkeyHash hash table. */
123147 if( !db || db->pnBytesFreed==0 ){
123148 if( pFKey->pPrevTo ){
123149 pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
@@ -123157,11 +123289,11 @@
123289
123290 /*
123291 ** Compute the affinity string for table pTab, if it has not already been
123292 ** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
123293 **
123294 ** If the affinity exists (if it is not entirely SQLITE_AFF_BLOB values) and
123295 ** if iReg>0 then code an OP_Affinity opcode that will set the affinities
123296 ** for register iReg and following. Or if affinities exists and iReg==0,
123297 ** then just set the P4 operand of the previous opcode (which should be
123298 ** an OP_MakeRecord) to the affinity string.
123299 **
@@ -123337,26 +123469,26 @@
123469 Column *pCol = pTab->aCol + i;
123470 if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){
123471 int x;
123472 pCol->colFlags |= COLFLAG_BUSY;
123473 w.eCode = 0;
123474 sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol));
123475 pCol->colFlags &= ~COLFLAG_BUSY;
123476 if( w.eCode & COLFLAG_NOTAVAIL ){
123477 pRedo = pCol;
123478 continue;
123479 }
123480 eProgress = 1;
123481 assert( pCol->colFlags & COLFLAG_GENERATED );
123482 x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
123483 sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x);
123484 pCol->colFlags &= ~COLFLAG_NOTAVAIL;
123485 }
123486 }
123487 }while( pRedo && eProgress );
123488 if( pRedo ){
123489 sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName);
123490 }
123491 pParse->iSelfTab = 0;
123492 }
123493 #endif /* SQLITE_OMIT_GENERATED_COLUMNS */
123494
@@ -123747,11 +123879,11 @@
123879 /* Figure out if we have any triggers and if the table being
123880 ** inserted into is a view
123881 */
123882 #ifndef SQLITE_OMIT_TRIGGER
123883 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
123884 isView = IsView(pTab);
123885 #else
123886 # define pTrigger 0
123887 # define tmask 0
123888 # define isView 0
123889 #endif
@@ -123838,21 +123970,21 @@
123970 for(i=0; i<pColumn->nId; i++){
123971 pColumn->a[i].idx = -1;
123972 }
123973 for(i=0; i<pColumn->nId; i++){
123974 for(j=0; j<pTab->nCol; j++){
123975 if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
123976 pColumn->a[i].idx = j;
123977 if( i!=j ) bIdListInOrder = 0;
123978 if( j==pTab->iPKey ){
123979 ipkColumn = i; assert( !withoutRowid );
123980 }
123981 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
123982 if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
123983 sqlite3ErrorMsg(pParse,
123984 "cannot INSERT into generated column \"%s\"",
123985 pTab->aCol[j].zCnName);
123986 goto insert_cleanup;
123987 }
123988 #endif
123989 break;
123990 }
@@ -124033,11 +124165,11 @@
124165 if( IsVirtual(pTab) ){
124166 sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
124167 pTab->zName);
124168 goto insert_cleanup;
124169 }
124170 if( IsView(pTab) ){
124171 sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
124172 goto insert_cleanup;
124173 }
124174 if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
124175 goto insert_cleanup;
@@ -124132,26 +124264,32 @@
124264 }
124265 continue;
124266 }else if( pColumn==0 ){
124267 /* Hidden columns that are not explicitly named in the INSERT
124268 ** get there default value */
124269 sqlite3ExprCodeFactorable(pParse,
124270 sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
124271 iRegStore);
124272 continue;
124273 }
124274 }
124275 if( pColumn ){
124276 for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
124277 if( j>=pColumn->nId ){
124278 /* A column not named in the insert column list gets its
124279 ** default value */
124280 sqlite3ExprCodeFactorable(pParse,
124281 sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
124282 iRegStore);
124283 continue;
124284 }
124285 k = j;
124286 }else if( nColumn==0 ){
124287 /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
124288 sqlite3ExprCodeFactorable(pParse,
124289 sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
124290 iRegStore);
124291 continue;
124292 }else{
124293 k = i - nHidden;
124294 }
124295
@@ -124662,11 +124800,11 @@
124800
124801 isUpdate = regOldData!=0;
124802 db = pParse->db;
124803 v = pParse->pVdbe;
124804 assert( v!=0 );
124805 assert( !IsView(pTab) ); /* This table is not a VIEW */
124806 nCol = pTab->nCol;
124807
124808 /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
124809 ** normal rowid tables. nPkField is the number of key fields in the
124810 ** pPk index or 1 for a rowid table. In other words, nPkField is the
@@ -124713,11 +124851,11 @@
124851 }else if( onError==OE_Default ){
124852 onError = OE_Abort;
124853 }
124854 if( onError==OE_Replace ){
124855 if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
124856 || pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */
124857 ){
124858 testcase( pCol->colFlags & COLFLAG_VIRTUAL );
124859 testcase( pCol->colFlags & COLFLAG_STORED );
124860 testcase( pCol->colFlags & COLFLAG_GENERATED );
124861 onError = OE_Abort;
@@ -124735,21 +124873,22 @@
124873 case OE_Replace: {
124874 int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
124875 VdbeCoverage(v);
124876 assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
124877 nSeenReplace++;
124878 sqlite3ExprCodeCopy(pParse,
124879 sqlite3ColumnExpr(pTab, pCol), iReg);
124880 sqlite3VdbeJumpHere(v, addr1);
124881 break;
124882 }
124883 case OE_Abort:
124884 sqlite3MayAbort(pParse);
124885 /* no break */ deliberate_fall_through
124886 case OE_Rollback:
124887 case OE_Fail: {
124888 char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
124889 pCol->zCnName);
124890 sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
124891 onError, iReg);
124892 sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
124893 sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
124894 VdbeCoverage(v);
@@ -125163,11 +125302,11 @@
125302 VdbeComment((v, "rowid"));
125303 }else{
125304 testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
125305 x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
125306 sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
125307 VdbeComment((v, "%s", pTab->aCol[iField].zCnName));
125308 }
125309 }
125310 sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
125311 VdbeComment((v, "for %s", pIdx->zName));
125312 #ifdef SQLITE_ENABLE_NULL_TRIM
@@ -125222,11 +125361,11 @@
125361 && pPk==pIdx /* Condition 2 */
125362 && onError==OE_Replace /* Condition 1 */
125363 && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
125364 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
125365 && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
125366 (0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab)))
125367 ){
125368 sqlite3VdbeResolveLabel(v, addrUniqueOk);
125369 continue;
125370 }
125371 #endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -125257,11 +125396,11 @@
125396 for(i=0; i<pPk->nKeyCol; i++){
125397 assert( pPk->aiColumn[i]>=0 );
125398 x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
125399 sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
125400 VdbeComment((v, "%s.%s", pTab->zName,
125401 pTab->aCol[pPk->aiColumn[i]].zCnName));
125402 }
125403 }
125404 if( isUpdate ){
125405 /* If currently processing the PRIMARY KEY of a WITHOUT ROWID
125406 ** table, only conflict if the new PRIMARY KEY values are actually
@@ -125456,11 +125595,11 @@
125595 /* Records with omitted columns are only allowed for schema format
125596 ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
125597 if( pTab->pSchema->file_format<2 ) return;
125598
125599 for(i=pTab->nCol-1; i>0; i--){
125600 if( pTab->aCol[i].iDflt!=0 ) break;
125601 if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
125602 }
125603 sqlite3VdbeChangeP5(v, i+1);
125604 }
125605 #endif
@@ -125521,11 +125660,11 @@
125660 || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
125661 );
125662
125663 v = pParse->pVdbe;
125664 assert( v!=0 );
125665 assert( !IsView(pTab) ); /* This table is not a VIEW */
125666 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
125667 /* All REPLACE indexes are at the end of the list */
125668 assert( pIdx->onError!=OE_Replace
125669 || pIdx->pNext==0
125670 || pIdx->pNext->onError==OE_Replace );
@@ -125823,17 +125962,12 @@
125962 return 0; /* tab1 and tab2 may not be the same table */
125963 }
125964 if( HasRowid(pDest)!=HasRowid(pSrc) ){
125965 return 0; /* source and destination must both be WITHOUT ROWID or not */
125966 }
125967 if( !IsOrdinaryTable(pSrc) ){
125968 return 0; /* tab2 may not be a view or virtual table */
 
 
 
 
 
125969 }
125970 if( pDest->nCol!=pSrc->nCol ){
125971 return 0; /* Number of columns must be the same in tab1 and tab2 */
125972 }
125973 if( pDest->iPKey!=pSrc->iPKey ){
@@ -125873,33 +126007,38 @@
126007 /* But the transfer is only allowed if both the source and destination
126008 ** tables have the exact same expressions for generated columns.
126009 ** This requirement could be relaxed for VIRTUAL columns, I suppose.
126010 */
126011 if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
126012 if( sqlite3ExprCompare(0,
126013 sqlite3ColumnExpr(pSrc, pSrcCol),
126014 sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){
126015 testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
126016 testcase( pDestCol->colFlags & COLFLAG_STORED );
126017 return 0; /* Different generator expressions */
126018 }
126019 }
126020 #endif
126021 if( pDestCol->affinity!=pSrcCol->affinity ){
126022 return 0; /* Affinity must be the same on all columns */
126023 }
126024 if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol),
126025 sqlite3ColumnColl(pSrcCol))!=0 ){
126026 return 0; /* Collating sequence must be the same on all columns */
126027 }
126028 if( pDestCol->notNull && !pSrcCol->notNull ){
126029 return 0; /* tab2 must be NOT NULL if tab1 is */
126030 }
126031 /* Default values for second and subsequent columns need to match. */
126032 if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
126033 Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol);
126034 Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol);
126035 assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
126036 assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
126037 if( (pDestExpr==0)!=(pSrcExpr==0)
126038 || (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
126039 pSrcExpr->u.zToken)!=0)
126040 ){
126041 return 0; /* Default values must be the same for all columns */
126042 }
126043 }
126044 }
@@ -125932,11 +126071,11 @@
126071 ** But the main beneficiary of the transfer optimization is the VACUUM
126072 ** command, and the VACUUM command disables foreign key constraints. So
126073 ** the extra complication to make this rule less restrictive is probably
126074 ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
126075 */
126076 if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
126077 return 0;
126078 }
126079 #endif
126080 if( (db->flags & SQLITE_CountRows)!=0 ){
126081 return 0; /* xfer opt does not play well with PRAGMA count_changes */
@@ -126610,10 +126749,13 @@
126749 int,const char**);
126750 void (*free_filename)(char*);
126751 sqlite3_file *(*database_file_object)(const char*);
126752 /* Version 3.34.0 and later */
126753 int (*txn_state)(sqlite3*,const char*);
126754 /* Version 3.36.1 and later */
126755 sqlite3_int64 (*changes64)(sqlite3*);
126756 sqlite3_int64 (*total_changes64)(sqlite3*);
126757 };
126758
126759 /*
126760 ** This is the function signature used for all extension entry points. It
126761 ** is also defined in the file "loadext.c".
@@ -127400,10 +127542,13 @@
127542 sqlite3_create_filename,
127543 sqlite3_free_filename,
127544 sqlite3_database_file_object,
127545 /* Version 3.34.0 and later */
127546 sqlite3_txn_state,
127547 /* Version 3.36.1 and later */
127548 sqlite3_changes64,
127549 sqlite3_total_changes64,
127550 };
127551
127552 /* True if x is the directory separator character
127553 */
127554 #if SQLITE_OS_WIN
@@ -128189,11 +128334,11 @@
128334 /* iArg: */ 1 },
128335 #endif
128336 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
128337 {/* zName: */ "integrity_check",
128338 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
128339 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
128340 /* ColNames: */ 0, 0,
128341 /* iArg: */ 0 },
128342 #endif
128343 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
128344 {/* zName: */ "journal_mode",
@@ -128297,11 +128442,11 @@
128442 /* iArg: */ SQLITE_QueryOnly },
128443 #endif
128444 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
128445 {/* zName: */ "quick_check",
128446 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
128447 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
128448 /* ColNames: */ 0, 0,
128449 /* iArg: */ 0 },
128450 #endif
128451 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
128452 {/* zName: */ "read_uncommitted",
@@ -129616,17 +129761,20 @@
129761 }else if( pPk==0 ){
129762 k = 1;
129763 }else{
129764 for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
129765 }
129766 assert( sqlite3ColumnExpr(pTab,pCol)==0
129767 || sqlite3ColumnExpr(pTab,pCol)->op==TK_SPAN
129768 || isHidden>=2 );
129769 sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
129770 i-nHidden,
129771 pCol->zCnName,
129772 sqlite3ColumnType(pCol,""),
129773 pCol->notNull ? 1 : 0,
129774 isHidden>=2 || sqlite3ColumnExpr(pTab,pCol)==0 ? 0 :
129775 sqlite3ColumnExpr(pTab,pCol)->u.zToken,
129776 k,
129777 isHidden);
129778 }
129779 }
129780 }
@@ -129689,11 +129837,11 @@
129837 sqlite3CodeVerifySchema(pParse, iIdxDb);
129838 assert( pParse->nMem<=pPragma->nPragCName );
129839 for(i=0; i<mx; i++){
129840 i16 cnum = pIdx->aiColumn[i];
129841 sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
129842 cnum<0 ? 0 : pTab->aCol[cnum].zCnName);
129843 if( pPragma->iArg ){
129844 sqlite3VdbeMultiLoad(v, 4, "isiX",
129845 pIdx->aSortOrder[i],
129846 pIdx->azColl[i],
129847 i<pIdx->nKeyCol);
@@ -129796,12 +129944,12 @@
129944 #ifndef SQLITE_OMIT_FOREIGN_KEY
129945 case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
129946 FKey *pFK;
129947 Table *pTab;
129948 pTab = sqlite3FindTable(db, zRight, zDb);
129949 if( pTab && !IsVirtual(pTab) ){
129950 pFK = pTab->u.tab.pFKey;
129951 if( pFK ){
129952 int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
129953 int i = 0;
129954 pParse->nMem = 8;
129955 sqlite3CodeVerifySchema(pParse, iTabDb);
@@ -129810,11 +129958,11 @@
129958 for(j=0; j<pFK->nCol; j++){
129959 sqlite3VdbeMultiLoad(v, 1, "iissssss",
129960 i,
129961 j,
129962 pFK->zTo,
129963 pTab->aCol[pFK->aCol[j].iFrom].zCnName,
129964 pFK->aCol[j].zCol,
129965 actionName(pFK->aAction[1]), /* ON UPDATE */
129966 actionName(pFK->aAction[0]), /* ON DELETE */
129967 "NONE");
129968 }
@@ -129856,19 +130004,20 @@
130004 k = 0;
130005 }else{
130006 pTab = (Table*)sqliteHashData(k);
130007 k = sqliteHashNext(k);
130008 }
130009 if( pTab==0 || IsVirtual(pTab) || pTab->u.tab.pFKey==0 ) continue;
130010 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
130011 zDb = db->aDb[iDb].zDbSName;
130012 sqlite3CodeVerifySchema(pParse, iDb);
130013 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
130014 if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
130015 sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
130016 sqlite3VdbeLoadString(v, regResult, pTab->zName);
130017 assert( !IsVirtual(pTab) );
130018 for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
130019 pParent = sqlite3FindTable(db, pFK->zTo, zDb);
130020 if( pParent==0 ) continue;
130021 pIdx = 0;
130022 sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
130023 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
@@ -129886,11 +130035,12 @@
130035 }
130036 assert( pParse->nErr>0 || pFK==0 );
130037 if( pFK ) break;
130038 if( pParse->nTab<i ) pParse->nTab = i;
130039 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
130040 assert( !IsVirtual(pTab) );
130041 for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
130042 pParent = sqlite3FindTable(db, pFK->zTo, zDb);
130043 pIdx = 0;
130044 aiCols = 0;
130045 if( pParent ){
130046 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
@@ -129900,10 +130050,11 @@
130050
130051 /* Generate code to read the child key values into registers
130052 ** regRow..regRow+n. If any of the child key values are NULL, this
130053 ** row cannot cause an FK violation. Jump directly to addrOk in
130054 ** this case. */
130055 if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol;
130056 for(j=0; j<pFK->nCol; j++){
130057 int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
130058 sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
130059 sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
130060 }
@@ -130120,11 +130271,11 @@
130271 if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
130272 sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
130273 }
130274 jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
130275 zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
130276 pTab->aCol[j].zCnName);
130277 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
130278 integrityCheckResultRow(v);
130279 sqlite3VdbeJumpHere(v, jmp2);
130280 }
130281 /* Verify CHECK constraints */
@@ -132328,11 +132479,11 @@
132479 SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
132480 int i;
132481 u8 h = sqlite3StrIHash(zCol);
132482 Column *pCol;
132483 for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
132484 if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
132485 }
132486 return -1;
132487 }
132488
132489 /*
@@ -132527,11 +132678,11 @@
132678 char *zName; /* Name of column in the right table */
132679 int iLeft; /* Matching left table */
132680 int iLeftCol; /* Matching column in the left table */
132681
132682 if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
132683 zName = pRightTab->aCol[j].zCnName;
132684 if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
132685 addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
132686 isOuter, &p->pWhere);
132687 }
132688 }
@@ -132930,11 +133081,13 @@
133081 Parse *pParse, /* Parsing and code generating context */
133082 int eTnctType, /* WHERE_DISTINCT_* value */
133083 int iVal, /* Value returned by codeDistinct() */
133084 int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
133085 ){
133086 if( pParse->nErr==0
133087 && (eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED)
133088 ){
133089 Vdbe *v = pParse->pVdbe;
133090 sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
133091 if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
133092 sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
133093 }
@@ -133892,11 +134045,11 @@
134045 assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
134046 if( iCol<0 ){
134047 zType = "INTEGER";
134048 zOrigCol = "rowid";
134049 }else{
134050 zOrigCol = pTab->aCol[iCol].zCnName;
134051 zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
134052 }
134053 zOrigTab = pTab->zName;
134054 if( pNC->pParse && pTab->pSchema ){
134055 int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
@@ -134064,11 +134217,11 @@
134217 if( iCol<0 ) iCol = pTab->iPKey;
134218 assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
134219 if( iCol<0 ){
134220 zCol = "rowid";
134221 }else{
134222 zCol = pTab->aCol[iCol].zCnName;
134223 }
134224 if( fullName ){
134225 char *zName = 0;
134226 zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
134227 sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
@@ -134149,11 +134302,11 @@
134302 }
134303 if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
134304 /* For columns use the column name name */
134305 int iCol = pColExpr->iColumn;
134306 if( iCol<0 ) iCol = pTab->iPKey;
134307 zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid";
134308 }else if( pColExpr->op==TK_ID ){
134309 assert( !ExprHasProperty(pColExpr, EP_IntValue) );
134310 zName = pColExpr->u.zToken;
134311 }else{
134312 /* Use the original text of the column expression as its name */
@@ -134177,21 +134330,21 @@
134330 if( zName[j]==':' ) nName = j;
134331 }
134332 zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
134333 if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
134334 }
134335 pCol->zCnName = zName;
134336 pCol->hName = sqlite3StrIHash(zName);
134337 sqlite3ColumnPropertiesFromName(0, pCol);
134338 if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
134339 sqlite3OomFault(db);
134340 }
134341 }
134342 sqlite3HashClear(&ht);
134343 if( db->mallocFailed ){
134344 for(j=0; j<i; j++){
134345 sqlite3DbFree(db, aCol[j].zCnName);
134346 }
134347 sqlite3DbFree(db, aCol);
134348 *paCol = 0;
134349 *pnCol = 0;
134350 return SQLITE_NOMEM_BKPT;
@@ -134239,21 +134392,22 @@
134392 zType = columnType(&sNC, p, 0, 0, 0);
134393 /* pCol->szEst = ... // Column size est for SELECT tables never used */
134394 pCol->affinity = sqlite3ExprAffinity(p);
134395 if( zType ){
134396 m = sqlite3Strlen30(zType);
134397 n = sqlite3Strlen30(pCol->zCnName);
134398 pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
134399 if( pCol->zCnName ){
134400 memcpy(&pCol->zCnName[n+1], zType, m+1);
134401 pCol->colFlags |= COLFLAG_HASTYPE;
134402 }
134403 }
134404 if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
134405 pColl = sqlite3ExprCollSeq(pParse, p);
134406 if( pColl && (pCol->colFlags & COLFLAG_HASCOLL)==0 ){
134407 assert( pTab->pIndex==0 );
134408 sqlite3ColumnSetColl(db, pCol, pColl->zName);
134409 }
134410 }
134411 pTab->szTabRow = 1; /* Any non-zero value works */
134412 }
134413
@@ -135811,14 +135965,14 @@
135965 /*
135966 ** Assign new cursor numbers to each of the items in pSrc. For each
135967 ** new cursor number assigned, set an entry in the aCsrMap[] array
135968 ** to map the old cursor number to the new:
135969 **
135970 ** aCsrMap[iOld+1] = iNew;
135971 **
135972 ** The array is guaranteed by the caller to be large enough for all
135973 ** existing cursor numbers in pSrc. aCsrMap[0] is the array size.
135974 **
135975 ** If pSrc contains any sub-selects, call this routine recursively
135976 ** on the FROM clause of each such sub-select, with iExcept set to -1.
135977 */
135978 static void srclistRenumberCursors(
@@ -135830,33 +135984,44 @@
135984 int i;
135985 SrcItem *pItem;
135986 for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
135987 if( i!=iExcept ){
135988 Select *p;
135989 assert( pItem->iCursor < aCsrMap[0] );
135990 if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){
135991 aCsrMap[pItem->iCursor+1] = pParse->nTab++;
135992 }
135993 pItem->iCursor = aCsrMap[pItem->iCursor+1];
135994 for(p=pItem->pSelect; p; p=p->pPrior){
135995 srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
135996 }
135997 }
135998 }
135999 }
136000
136001 /*
136002 ** *piCursor is a cursor number. Change it if it needs to be mapped.
136003 */
136004 static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){
136005 int *aCsrMap = pWalker->u.aiCol;
136006 int iCsr = *piCursor;
136007 if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){
136008 *piCursor = aCsrMap[iCsr+1];
136009 }
136010 }
136011
136012 /*
136013 ** Expression walker callback used by renumberCursors() to update
136014 ** Expr objects to match newly assigned cursor numbers.
136015 */
136016 static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
 
136017 int op = pExpr->op;
136018 if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
136019 renumberCursorDoMapping(pWalker, &pExpr->iTable);
136020 }
136021 if( ExprHasProperty(pExpr, EP_FromJoin) ){
136022 renumberCursorDoMapping(pWalker, &pExpr->iRightJoinTable);
136023 }
136024 return WRC_Continue;
136025 }
136026
136027 /*
@@ -136196,11 +136361,12 @@
136361 /* Restriction (23) */
136362 if( (p->selFlags & SF_Recursive) ) return 0;
136363
136364 if( pSrc->nSrc>1 ){
136365 if( pParse->nSelect>500 ) return 0;
136366 aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+1)*sizeof(int));
136367 if( aCsrMap ) aCsrMap[0] = pParse->nTab;
136368 }
136369 }
136370
136371 /***** If we reach this point, flattening is permitted. *****/
136372 SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -136976,11 +137142,11 @@
137142 ){
137143 return 0;
137144 }
137145 pTab = p->pSrc->a[0].pTab;
137146 pExpr = p->pEList->a[0].pExpr;
137147 assert( pTab && !IsView(pTab) && pExpr );
137148
137149 if( IsVirtual(pTab) ) return 0;
137150 if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
137151 if( NEVER(pAggInfo->nFunc==0) ) return 0;
137152 if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
@@ -137521,34 +137687,35 @@
137687 pTab->nTabRef++;
137688 if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
137689 return WRC_Abort;
137690 }
137691 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
137692 if( !IsOrdinaryTable(pTab) ){
137693 i16 nCol;
137694 u8 eCodeOrig = pWalker->eCode;
137695 if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
137696 assert( pFrom->pSelect==0 );
137697 if( IsView(pTab) ){
137698 if( (db->flags & SQLITE_EnableView)==0
137699 && pTab->pSchema!=db->aDb[1].pSchema
137700 ){
137701 sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
137702 pTab->zName);
137703 }
137704 pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
137705 }else
137706 #ifndef SQLITE_OMIT_VIRTUALTABLE
137707 if( ALWAYS(IsVirtual(pTab))
 
137708 && pFrom->fg.fromDDL
137709 && ALWAYS(pTab->u.vtab.p!=0)
137710 && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
137711 ){
137712 sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
137713 pTab->zName);
137714 }
137715 assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
137716 #endif
 
137717 nCol = pTab->nCol;
137718 pTab->nCol = -1;
137719 pWalker->eCode = 1; /* Turn on Select.selId renumbering */
137720 sqlite3WalkSelect(pWalker, pFrom->pSelect);
137721 pWalker->eCode = eCodeOrig;
@@ -137644,11 +137811,11 @@
137811 }
137812 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
137813 zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
137814 }
137815 for(j=0; j<pTab->nCol; j++){
137816 char *zName = pTab->aCol[j].zCnName;
137817 char *zColname; /* The computed column name */
137818 char *zToFree; /* Malloced string that needs to be freed */
137819 Token sColname; /* Computed column name as a token */
137820
137821 assert( zName );
@@ -138076,12 +138243,20 @@
138243 ** within the HAVING expression with a constant "1".
138244 */
138245 static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
138246 if( pExpr->op!=TK_AND ){
138247 Select *pS = pWalker->u.pSelect;
138248 /* This routine is called before the HAVING clause of the current
138249 ** SELECT is analyzed for aggregates. So if pExpr->pAggInfo is set
138250 ** here, it indicates that the expression is a correlated reference to a
138251 ** column from an outer aggregate query, or an aggregate function that
138252 ** belongs to an outer query. Do not move the expression to the WHERE
138253 ** clause in this obscure case, as doing so may corrupt the outer Select
138254 ** statements AggInfo structure. */
138255 if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
138256 && ExprAlwaysFalse(pExpr)==0
138257 && pExpr->pAggInfo==0
138258 ){
138259 sqlite3 *db = pWalker->pParse->db;
138260 Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
138261 if( pNew ){
138262 Expr *pWhere = pS->pWhere;
@@ -138343,15 +138518,20 @@
138518 SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
138519 sqlite3TreeViewSelect(0, p, 0);
138520 }
138521 #endif
138522
138523 /* If the SF_UFSrcCheck flag is set, then this function is being called
138524 ** as part of populating the temp table for an UPDATE...FROM statement.
138525 ** In this case, it is an error if the target object (pSrc->a[0]) name
138526 ** or alias is duplicated within FROM clause (pSrc->a[1..n]).
138527 **
138528 ** Postgres disallows this case too. The reason is that some other
138529 ** systems handle this case differently, and not all the same way,
138530 ** which is just confusing. To avoid this, we follow PG's lead and
138531 ** disallow it altogether. */
138532 if( p->selFlags & SF_UFSrcCheck ){
138533 SrcItem *p0 = &p->pSrc->a[0];
138534 for(i=1; i<p->pSrc->nSrc; i++){
138535 SrcItem *p1 = &p->pSrc->a[i];
138536 if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
138537 sqlite3ErrorMsg(pParse,
@@ -138359,10 +138539,16 @@
138539 p0->zAlias ? p0->zAlias : p0->pTab->zName
138540 );
138541 goto select_end;
138542 }
138543 }
138544
138545 /* Clear the SF_UFSrcCheck flag. The check has already been performed,
138546 ** and leaving this flag set can cause errors if a compound sub-query
138547 ** in p->pSrc is flattened into this query and this function called
138548 ** again as part of compound SELECT processing. */
138549 p->selFlags &= ~SF_UFSrcCheck;
138550 }
138551
138552 if( pDest->eDest==SRT_Output ){
138553 sqlite3GenerateColumnNames(pParse, p);
138554 }
@@ -138429,10 +138615,43 @@
138615 ** will be implemented as a co-routine and there is no advantage to
138616 ** flattening in that case.
138617 */
138618 if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
138619 assert( pSub->pGroupBy==0 );
138620
138621 /* If a FROM-clause subquery has an ORDER BY clause that is not
138622 ** really doing anything, then delete it now so that it does not
138623 ** interfere with query flattening. See the discussion at
138624 ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
138625 **
138626 ** Beware of these cases where the ORDER BY clause may not be safely
138627 ** omitted:
138628 **
138629 ** (1) There is also a LIMIT clause
138630 ** (2) The subquery was added to help with window-function
138631 ** processing
138632 ** (3) The subquery is in the FROM clause of an UPDATE
138633 ** (4) The outer query uses an aggregate function other than
138634 ** the built-in count(), min(), or max().
138635 ** (5) The ORDER BY isn't going to accomplish anything because
138636 ** one of:
138637 ** (a) The outer query has a different ORDER BY clause
138638 ** (b) The subquery is part of a join
138639 ** See forum post 062d576715d277c8
138640 */
138641 if( pSub->pOrderBy!=0
138642 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
138643 && pSub->pLimit==0 /* Condition (1) */
138644 && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
138645 && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
138646 && OptimizationEnabled(db, SQLITE_OmitOrderBy)
138647 ){
138648 SELECTTRACE(0x100,pParse,p,
138649 ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
138650 sqlite3ExprListDelete(db, pSub->pOrderBy);
138651 pSub->pOrderBy = 0;
138652 }
138653
138654 /* If the outer query contains a "complex" result set (that is,
138655 ** if the result set of the outer query uses functions or subqueries)
138656 ** and if the subquery contains an ORDER BY clause and if
138657 ** it will be implemented as a co-routine, then do not flatten. This
@@ -139877,16 +140096,16 @@
140096 }
140097
140098 /* INSTEAD of triggers are only for views and views only support INSTEAD
140099 ** of triggers.
140100 */
140101 if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
140102 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
140103 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
140104 goto trigger_orphan_error;
140105 }
140106 if( !IsView(pTab) && tr_tm==TK_INSTEAD ){
140107 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
140108 " trigger on table: %S", pTableName->a);
140109 goto trigger_orphan_error;
140110 }
140111
@@ -140535,15 +140754,15 @@
140754 if( isAsteriskTerm(pParse, pOldExpr) ){
140755 int jj;
140756 for(jj=0; jj<pTab->nCol; jj++){
140757 Expr *pNewExpr;
140758 if( IsHiddenColumn(pTab->aCol+jj) ) continue;
140759 pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName);
140760 pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
140761 if( !db->mallocFailed ){
140762 struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
140763 pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName);
140764 pItem->eEName = ENAME_NAME;
140765 }
140766 }
140767 }else{
140768 Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0);
@@ -140584,10 +140803,11 @@
140803 memset(&sFrom, 0, sizeof(sFrom));
140804 sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
140805 sSelect.pSrc = &sFrom;
140806 sFrom.nSrc = 1;
140807 sFrom.a[0].pTab = pTab;
140808 sFrom.a[0].iCursor = -1;
140809 sqlite3SelectPrep(pParse, &sSelect, 0);
140810 if( db->mallocFailed==0 && pParse->nErr==0 ){
140811 sqlite3GenerateColumnNames(pParse, &sSelect);
140812 }
140813 sqlite3ExprListDelete(db, sSelect.pEList);
@@ -141139,17 +141359,18 @@
141359 ** integer. In that case, add an OP_RealAffinity opcode to make sure
141360 ** it has been converted into REAL.
141361 */
141362 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
141363 assert( pTab!=0 );
141364 if( !IsView(pTab) ){
141365 sqlite3_value *pValue = 0;
141366 u8 enc = ENC(sqlite3VdbeDb(v));
141367 Column *pCol = &pTab->aCol[i];
141368 VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName));
141369 assert( i<pTab->nCol );
141370 sqlite3ValueFromExpr(sqlite3VdbeDb(v),
141371 sqlite3ColumnExpr(pTab,pCol), enc,
141372 pCol->affinity, &pValue);
141373 if( pValue ){
141374 sqlite3VdbeAppendP4(v, pValue, P4_MEM);
141375 }
141376 }
@@ -141315,11 +141536,11 @@
141536 }
141537 #endif
141538 pList = sqlite3ExprListAppend(pParse, pList, pNew);
141539 }
141540 eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
141541 }else if( IsView(pTab) ){
141542 for(i=0; i<pTab->nCol; i++){
141543 pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
141544 }
141545 eDest = SRT_Table;
141546 }else{
@@ -141338,12 +141559,13 @@
141559 sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
141560 );
141561 }
141562 }
141563 pSelect = sqlite3SelectNew(pParse, pList,
141564 pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UFSrcCheck|SF_IncludeHidden, pLimit2
141565 );
141566 if( pSelect ) pSelect->selFlags |= SF_OrderByReqd;
141567 sqlite3SelectDestInit(&dest, eDest, iEph);
141568 dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
141569 sqlite3Select(pParse, pSelect, &dest);
141570 sqlite3SelectDelete(db, pSelect);
141571 }
@@ -141439,11 +141661,11 @@
141661 /* Figure out if we have any triggers and if the table being
141662 ** updated is a view.
141663 */
141664 #ifndef SQLITE_OMIT_TRIGGER
141665 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
141666 isView = IsView(pTab);
141667 assert( pTrigger || tmask==0 );
141668 #else
141669 # define pTrigger 0
141670 # define isView 0
141671 # define tmask 0
@@ -141528,17 +141750,20 @@
141750 ** column to be updated, make sure we have authorization to change
141751 ** that column.
141752 */
141753 chngRowid = chngPk = 0;
141754 for(i=0; i<pChanges->nExpr; i++){
141755 u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName);
141756 /* If this is an UPDATE with a FROM clause, do not resolve expressions
141757 ** here. The call to sqlite3Select() below will do that. */
141758 if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
141759 goto update_cleanup;
141760 }
141761 for(j=0; j<pTab->nCol; j++){
141762 if( pTab->aCol[j].hName==hCol
141763 && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
141764 ){
141765 if( j==pTab->iPKey ){
141766 chngRowid = 1;
141767 pRowidExpr = pChanges->a[i].pExpr;
141768 iRowidExpr = i;
141769 }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
@@ -141548,11 +141773,11 @@
141773 else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
141774 testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
141775 testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
141776 sqlite3ErrorMsg(pParse,
141777 "cannot UPDATE generated column \"%s\"",
141778 pTab->aCol[j].zCnName);
141779 goto update_cleanup;
141780 }
141781 #endif
141782 aXRef[j] = i;
141783 break;
@@ -141572,11 +141797,11 @@
141797 }
141798 #ifndef SQLITE_OMIT_AUTHORIZATION
141799 {
141800 int rc;
141801 rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
141802 j<0 ? "ROWID" : pTab->aCol[j].zCnName,
141803 db->aDb[iDb].zDbSName);
141804 if( rc==SQLITE_DENY ){
141805 goto update_cleanup;
141806 }else if( rc==SQLITE_IGNORE ){
141807 aXRef[j] = -1;
@@ -141604,12 +141829,14 @@
141829 do{
141830 bProgress = 0;
141831 for(i=0; i<pTab->nCol; i++){
141832 if( aXRef[i]>=0 ) continue;
141833 if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
141834 if( sqlite3ExprReferencesUpdatedColumn(
141835 sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
141836 aXRef, chngRowid)
141837 ){
141838 aXRef[i] = 99999;
141839 bProgress = 1;
141840 }
141841 }
141842 }while( bProgress );
@@ -142697,11 +142924,11 @@
142924 int k;
142925 assert( pPk->aiColumn[i]>=0 );
142926 k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
142927 sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
142928 VdbeComment((v, "%s.%s", pIdx->zName,
142929 pTab->aCol[pPk->aiColumn[i]].zCnName));
142930 }
142931 sqlite3VdbeVerifyAbortable(v, OE_Abort);
142932 i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
142933 VdbeCoverage(v);
142934 sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
@@ -142879,12 +143106,12 @@
143106 int rc = SQLITE_OK; /* Return code from service routines */
143107 Btree *pMain; /* The database being vacuumed */
143108 Btree *pTemp; /* The temporary database we vacuum into */
143109 u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
143110 u64 saved_flags; /* Saved value of db->flags */
143111 i64 saved_nChange; /* Saved value of db->nChange */
143112 i64 saved_nTotalChange; /* Saved value of db->nTotalChange */
143113 u32 saved_openFlags; /* Saved value of db->openFlags */
143114 u8 saved_mTrace; /* Saved trace settings */
143115 Db *pDb = 0; /* Database to detach at end of vacuum */
143116 int isMemDb; /* True if vacuuming a :memory: database */
143117 int nRes; /* Bytes of reserved space at the end of each page */
@@ -143327,11 +143554,11 @@
143554 ** this virtual-table, if one has been created, or NULL otherwise.
143555 */
143556 SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
143557 VTable *pVtab;
143558 assert( IsVirtual(pTab) );
143559 for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
143560 return pVtab;
143561 }
143562
143563 /*
143564 ** Decrement the ref-count on a virtual table object. When the ref-count
@@ -143355,35 +143582,35 @@
143582 }
143583 }
143584
143585 /*
143586 ** Table p is a virtual table. This function moves all elements in the
143587 ** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
143588 ** database connections to be disconnected at the next opportunity.
143589 ** Except, if argument db is not NULL, then the entry associated with
143590 ** connection db is left in the p->u.vtab.p list.
143591 */
143592 static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
143593 VTable *pRet = 0;
143594 VTable *pVTable = p->u.vtab.p;
143595 p->u.vtab.p = 0;
143596
143597 /* Assert that the mutex (if any) associated with the BtShared database
143598 ** that contains table p is held by the caller. See header comments
143599 ** above function sqlite3VtabUnlockList() for an explanation of why
143600 ** this makes it safe to access the sqlite3.pDisconnect list of any
143601 ** database connection that may have an entry in the p->u.vtab.p list.
143602 */
143603 assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
143604
143605 while( pVTable ){
143606 sqlite3 *db2 = pVTable->db;
143607 VTable *pNext = pVTable->pNext;
143608 assert( db2 );
143609 if( db2==db ){
143610 pRet = pVTable;
143611 p->u.vtab.p = pRet;
143612 pRet->pNext = 0;
143613 }else{
143614 pVTable->pNext = db2->pDisconnect;
143615 db2->pDisconnect = pVTable;
143616 }
@@ -143407,11 +143634,11 @@
143634
143635 assert( IsVirtual(p) );
143636 assert( sqlite3BtreeHoldsAllMutexes(db) );
143637 assert( sqlite3_mutex_held(db->mutex) );
143638
143639 for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){
143640 if( (*ppVTab)->db==db ){
143641 VTable *pVTab = *ppVTab;
143642 *ppVTab = pVTab->pNext;
143643 sqlite3VtabUnlock(pVTab);
143644 break;
@@ -143471,40 +143698,40 @@
143698 ** in the list are moved to the sqlite3.pDisconnect list of the associated
143699 ** database connection.
143700 */
143701 SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
143702 if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
143703 if( p->u.vtab.azArg ){
143704 int i;
143705 for(i=0; i<p->u.vtab.nArg; i++){
143706 if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]);
143707 }
143708 sqlite3DbFree(db, p->u.vtab.azArg);
143709 }
143710 }
143711
143712 /*
143713 ** Add a new module argument to pTable->u.vtab.azArg[].
143714 ** The string is not copied - the pointer is stored. The
143715 ** string will be freed automatically when the table is
143716 ** deleted.
143717 */
143718 static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
143719 sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg);
143720 char **azModuleArg;
143721 sqlite3 *db = pParse->db;
143722 if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
143723 sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
143724 }
143725 azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes);
143726 if( azModuleArg==0 ){
143727 sqlite3DbFree(db, zArg);
143728 }else{
143729 int i = pTable->u.vtab.nArg++;
143730 azModuleArg[i] = zArg;
143731 azModuleArg[i+1] = 0;
143732 pTable->u.vtab.azArg = azModuleArg;
143733 }
143734 }
143735
143736 /*
143737 ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
@@ -143523,14 +143750,15 @@
143750
143751 sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
143752 pTable = pParse->pNewTable;
143753 if( pTable==0 ) return;
143754 assert( 0==pTable->pIndex );
143755 pTable->eTabType = TABTYP_VTAB;
143756
143757 db = pParse->db;
143758
143759 assert( pTable->u.vtab.nArg==0 );
143760 addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName));
143761 addModuleArgument(pParse, pTable, 0);
143762 addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName));
143763 assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0)
143764 || (pParse->sNameToken.z==pName1->z && pName2->z==0)
@@ -143543,15 +143771,15 @@
143771 /* Creating a virtual table invokes the authorization callback twice.
143772 ** The first invocation, to obtain permission to INSERT a row into the
143773 ** sqlite_schema table, has already been made by sqlite3StartTable().
143774 ** The second call, to obtain permission to create the table, is made now.
143775 */
143776 if( pTable->u.vtab.azArg ){
143777 int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
143778 assert( iDb>=0 ); /* The database the table is being created in */
143779 sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
143780 pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName);
143781 }
143782 #endif
143783 }
143784
143785 /*
@@ -143577,11 +143805,11 @@
143805 sqlite3 *db = pParse->db; /* The database connection */
143806
143807 if( pTab==0 ) return;
143808 addArgumentToVtab(pParse);
143809 pParse->sArg.z = 0;
143810 if( pTab->u.vtab.nArg<1 ) return;
143811
143812 /* If the CREATE VIRTUAL TABLE statement is being entered for the
143813 ** first time (in other words if the virtual table is actually being
143814 ** created now instead of just being read out of sqlite_schema) then
143815 ** do additional initialization work and store the statement text
@@ -143692,12 +143920,12 @@
143920 char **pzErr
143921 ){
143922 VtabCtx sCtx;
143923 VTable *pVTable;
143924 int rc;
143925 const char *const*azArg = (const char *const*)pTab->u.vtab.azArg;
143926 int nArg = pTab->u.vtab.nArg;
143927 char *zErr = 0;
143928 char *zModuleName;
143929 int iDb;
143930 VtabCtx *pCtx;
143931
@@ -143725,11 +143953,11 @@
143953 pVTable->db = db;
143954 pVTable->pMod = pMod;
143955 pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
143956
143957 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
143958 pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName;
143959
143960 /* Invoke the virtual table constructor */
143961 assert( &db->pVtabCtx );
143962 assert( xConstruct );
143963 sCtx.pTab = pTab;
@@ -143764,16 +143992,16 @@
143992 rc = SQLITE_ERROR;
143993 }else{
143994 int iCol;
143995 u16 oooHidden = 0;
143996 /* If everything went according to plan, link the new VTable structure
143997 ** into the linked list headed by pTab->u.vtab.p. Then loop through the
143998 ** columns of the table to see if any of them contain the token "hidden".
143999 ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
144000 ** the type string. */
144001 pVTable->pNext = pTab->u.vtab.p;
144002 pTab->u.vtab.p = pVTable;
144003
144004 for(iCol=0; iCol<pTab->nCol; iCol++){
144005 char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
144006 int nType;
144007 int i = 0;
@@ -143827,15 +144055,15 @@
144055 if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
144056 return SQLITE_OK;
144057 }
144058
144059 /* Locate the required virtual table module */
144060 zMod = pTab->u.vtab.azArg[0];
144061 pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
144062
144063 if( !pMod ){
144064 const char *zModule = pTab->u.vtab.azArg[0];
144065 sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
144066 rc = SQLITE_ERROR;
144067 }else{
144068 char *zErr = 0;
144069 rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
@@ -143894,14 +144122,14 @@
144122 Table *pTab;
144123 Module *pMod;
144124 const char *zMod;
144125
144126 pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
144127 assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p );
144128
144129 /* Locate the required virtual table module */
144130 zMod = pTab->u.vtab.azArg[0];
144131 pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
144132
144133 /* If the module has been registered and includes a Create method,
144134 ** invoke it now. If the module has not been registered, return an
144135 ** error. Otherwise, do nothing.
@@ -143957,17 +144185,17 @@
144185 sParse.db = db;
144186 sParse.nQueryLoop = 1;
144187 if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
144188 && sParse.pNewTable
144189 && !db->mallocFailed
144190 && IsOrdinaryTable(sParse.pNewTable)
 
144191 ){
144192 if( !pTab->aCol ){
144193 Table *pNew = sParse.pNewTable;
144194 Index *pIdx;
144195 pTab->aCol = pNew->aCol;
144196 sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
144197 pTab->nNVCol = pTab->nCol = pNew->nCol;
144198 pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
144199 pNew->nCol = 0;
144200 pNew->aCol = 0;
144201 assert( pTab->pIndex==0 );
@@ -144018,14 +144246,14 @@
144246 SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
144247 int rc = SQLITE_OK;
144248 Table *pTab;
144249
144250 pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
144251 if( pTab!=0 && ALWAYS(pTab->u.vtab.p!=0) ){
144252 VTable *p;
144253 int (*xDestroy)(sqlite3_vtab *);
144254 for(p=pTab->u.vtab.p; p; p=p->pNext){
144255 assert( p->pVtab );
144256 if( p->pVtab->nRef>0 ){
144257 return SQLITE_LOCKED;
144258 }
144259 }
@@ -144035,13 +144263,13 @@
144263 assert( xDestroy!=0 );
144264 pTab->nTabRef++;
144265 rc = xDestroy(p->pVtab);
144266 /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
144267 if( rc==SQLITE_OK ){
144268 assert( pTab->u.vtab.p==p && p->pNext==0 );
144269 p->pVtab = 0;
144270 pTab->u.vtab.p = 0;
144271 sqlite3VtabUnlock(p);
144272 }
144273 sqlite3DeleteTable(db, pTab);
144274 }
144275
@@ -144325,12 +144553,13 @@
144553 }
144554
144555 /*
144556 ** Check to see if virtual table module pMod can be have an eponymous
144557 ** virtual table instance. If it can, create one if one does not already
144558 ** exist. Return non-zero if either the eponymous virtual table instance
144559 ** exists when this routine returns or if an attempt to create it failed
144560 ** and an error message was left in pParse.
144561 **
144562 ** An eponymous virtual table instance is one that is named after its
144563 ** module, and more importantly, does not require a CREATE VIRTUAL TABLE
144564 ** statement in order to come into existance. Eponymous virtual table
144565 ** instances always exist. They cannot be DROP-ed.
@@ -144353,12 +144582,13 @@
144582 sqlite3DbFree(db, pTab);
144583 return 0;
144584 }
144585 pMod->pEpoTab = pTab;
144586 pTab->nTabRef = 1;
144587 pTab->eTabType = TABTYP_VTAB;
144588 pTab->pSchema = db->aDb[0].pSchema;
144589 assert( pTab->u.vtab.nArg==0 );
144590 pTab->iPKey = -1;
144591 pTab->tabFlags |= TF_Eponymous;
144592 addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
144593 addModuleArgument(pParse, pTab, 0);
144594 addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
@@ -144365,11 +144595,10 @@
144595 rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
144596 if( rc ){
144597 sqlite3ErrorMsg(pParse, "%s", zErr);
144598 sqlite3DbFree(db, zErr);
144599 sqlite3VtabEponymousTableClear(db, pMod);
 
144600 }
144601 return 1;
144602 }
144603
144604 /*
@@ -145099,11 +145328,11 @@
145328 */
145329 static const char *explainIndexColumnName(Index *pIdx, int i){
145330 i = pIdx->aiColumn[i];
145331 if( i==XN_EXPR ) return "<expr>";
145332 if( i==XN_ROWID ) return "rowid";
145333 return pIdx->pTable->aCol[i].zCnName;
145334 }
145335
145336 /*
145337 ** This routine is a helper for explainIndexRange() below
145338 **
@@ -146311,12 +146540,13 @@
146540 if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
146541 w.xExprCallback = whereIndexExprTransNode;
146542 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
146543 }else if( iRef>=0
146544 && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
146545 && ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
146546 || sqlite3StrICmp(sqlite3ColumnColl(&pTab->aCol[iRef]),
146547 sqlite3StrBINARY)==0)
146548 ){
146549 /* Check to see if there are direct references to generated columns
146550 ** that are contained in the index. Pulling the generated column
146551 ** out of the index is an optimization only - the main table is always
146552 ** available if the index cannot be used. To avoid unnecessary
@@ -148731,11 +148961,15 @@
148961 pNew->u.x.leftColumn = aiCurCol[1];
148962 testcase( (prereqLeft | extraRight) != prereqLeft );
148963 pNew->prereqRight = prereqLeft | extraRight;
148964 pNew->prereqAll = prereqAll;
148965 pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
148966 }else
148967 if( op==TK_ISNULL
148968 && !ExprHasProperty(pExpr,EP_FromJoin)
148969 && 0==sqlite3ExprCanBeNull(pLeft)
148970 ){
148971 pExpr->op = TK_TRUEFALSE;
148972 pExpr->u.zToken = "false";
148973 ExprSetProperty(pExpr, EP_IsFalse);
148974 pTerm->prereqAll = 0;
148975 pTerm->eOperator = 0;
@@ -148928,12 +149162,12 @@
149162 ){
149163 int i;
149164 for(i=0; i<nLeft; i++){
149165 int idxNew;
149166 Expr *pNew;
149167 Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, nLeft);
149168 Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft);
149169
149170 pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
149171 transferJoinMarkings(pNew, pExpr);
149172 idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
149173 exprAnalyze(pSrc, pWC, idxNew);
@@ -150018,11 +150252,11 @@
150252 testcase( iCol==BMS );
150253 testcase( iCol==BMS-1 );
150254 if( !sentWarning ){
150255 sqlite3_log(SQLITE_WARNING_AUTOINDEX,
150256 "automatic index on %s(%s)", pTable->zName,
150257 pTable->aCol[iCol].zCnName);
150258 sentWarning = 1;
150259 }
150260 if( (idxCols & cMask)==0 ){
150261 if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
150262 goto end_auto_index_create;
@@ -151932,11 +152166,11 @@
152166 }else{
152167 #ifdef SQLITE_ENABLE_STAT4
152168 tRowcnt nOut = 0;
152169 if( nInMul==0
152170 && pProbe->nSample
152171 && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
152172 && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
152173 && OptimizationEnabled(db, SQLITE_Stat4)
152174 ){
152175 Expr *pExpr = pTerm->pExpr;
152176 if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
@@ -152197,11 +152431,10 @@
152431 WhereLoop *pNew; /* Template WhereLoop object */
152432 int rc = SQLITE_OK; /* Return code */
152433 int iSortIdx = 1; /* Index number */
152434 int b; /* A boolean value */
152435 LogEst rSize; /* number of rows in the table */
 
152436 WhereClause *pWC; /* The parsed WHERE clause */
152437 Table *pTab; /* Table being queried */
152438
152439 pNew = pBuilder->pNew;
152440 pWInfo = pBuilder->pWInfo;
@@ -152240,11 +152473,10 @@
152473 sPk.pNext = pFirst;
152474 }
152475 pProbe = &sPk;
152476 }
152477 rSize = pTab->nRowLogEst;
 
152478
152479 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
152480 /* Automatic indexes */
152481 if( !pBuilder->pOrSet /* Not part of an OR optimization */
152482 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
@@ -152254,12 +152486,14 @@
152486 && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
152487 && !pSrc->fg.isCorrelated /* Not a correlated subquery */
152488 && !pSrc->fg.isRecursive /* Not a recursive common table expression. */
152489 ){
152490 /* Generate auto-index WhereLoops */
152491 LogEst rLogSize; /* Logarithm of the number of rows in the table */
152492 WhereTerm *pTerm;
152493 WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
152494 rLogSize = estLog(rSize);
152495 for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
152496 if( pTerm->prereqRight & pNew->maskSelf ) continue;
152497 if( termCanDriveIndex(pTerm, pSrc, 0) ){
152498 pNew->u.btree.nEq = 1;
152499 pNew->nSkip = 0;
@@ -152273,11 +152507,11 @@
152507 ** of X is smaller for views and subqueries so that the query planner
152508 ** will be more aggressive about generating automatic indexes for
152509 ** those objects, since there is no opportunity to add schema
152510 ** indexes on subqueries and views. */
152511 pNew->rSetup = rLogSize + rSize;
152512 if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){
152513 pNew->rSetup += 28;
152514 }else{
152515 pNew->rSetup -= 10;
152516 }
152517 ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
@@ -154424,11 +154658,11 @@
154658
154659 pTabItem = &pTabList->a[pLevel->iFrom];
154660 pTab = pTabItem->pTab;
154661 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
154662 pLoop = pLevel->pWLoop;
154663 if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
154664 /* Do nothing */
154665 }else
154666 #ifndef SQLITE_OMIT_VIRTUALTABLE
154667 if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
154668 const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
@@ -154741,10 +154975,16 @@
154975 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
154976 }
154977 if( (ws & WHERE_INDEXED)
154978 || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
154979 ){
154980 if( ws & WHERE_MULTI_OR ){
154981 Index *pIx = pLevel->u.pCovidx;
154982 int iDb = sqlite3SchemaToIndex(db, pIx->pSchema);
154983 sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb);
154984 sqlite3VdbeSetP4KeyInfo(pParse, pIx);
154985 }
154986 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
154987 }
154988 if( pLevel->op==OP_Return ){
154989 sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
154990 }else{
@@ -154787,11 +155027,11 @@
155027 ** Except, do not close cursors that will be reused by the OR optimization
155028 ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors
155029 ** created for the ONEPASS optimization.
155030 */
155031 if( (pTab->tabFlags & TF_Ephemeral)==0
155032 && !IsView(pTab)
155033 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
155034 ){
155035 int ws = pLoop->wsFlags;
155036 if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
155037 sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
@@ -155805,13 +156045,11 @@
156045 break;
156046 }
156047 if( bIntToNull ){
156048 int iDummy;
156049 Expr *pSub;
156050 pSub = sqlite3ExprSkipCollateAndLikely(pDup);
 
 
156051 if( sqlite3ExprIsInteger(pSub, &iDummy) ){
156052 pSub->op = TK_NULL;
156053 pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
156054 pSub->u.zToken = 0;
156055 }
@@ -155969,11 +156207,11 @@
156207 p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
156208 if( p->pSrc ){
156209 Table *pTab2;
156210 p->pSrc->a[0].pSelect = pSub;
156211 sqlite3SrcListAssignCursors(pParse, p->pSrc);
156212 pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
156213 pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
156214 pSub->selFlags |= (selFlags & SF_Aggregate);
156215 if( pTab2==0 ){
156216 /* Might actually be some other kind of error, but in that case
156217 ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
@@ -161615,11 +161853,11 @@
161853 sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
161854 }
161855 }
161856 break;
161857 case 23: /* columnname ::= nm typetoken */
161858 {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);}
161859 break;
161860 case 24: /* typetoken ::= */
161861 case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63);
161862 case 102: /* as ::= */ yytestcase(yyruleno==102);
161863 {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
@@ -162419,24 +162657,32 @@
162657 ** simplify to constants 0 (false) and 1 (true), respectively,
162658 ** regardless of the value of expr1.
162659 */
162660 sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy404);
162661 yymsp[-4].minor.yy404 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy376 ? "1" : "0");
162662 }else{
162663 Expr *pRHS = yymsp[-1].minor.yy70->a[0].pExpr;
162664 if( yymsp[-1].minor.yy70->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy404->op!=TK_VECTOR ){
162665 yymsp[-1].minor.yy70->a[0].pExpr = 0;
162666 sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162667 pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
162668 yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy404, pRHS);
162669 }else{
162670 yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
162671 if( yymsp[-4].minor.yy404==0 ){
162672 sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
162673 }else if( yymsp[-4].minor.yy404->pLeft->op==TK_VECTOR ){
162674 int nExpr = yymsp[-4].minor.yy404->pLeft->x.pList->nExpr;
162675 Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy70);
162676 if( pSelectRHS ){
162677 parserDoubleLinkSelect(pParse, pSelectRHS);
162678 sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy404, pSelectRHS);
162679 }
162680 }else{
162681 yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy70;
162682 sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404);
162683 }
162684 }
162685 if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
162686 }
162687 }
162688 break;
@@ -166151,31 +166397,37 @@
166397 }
166398
166399 /*
166400 ** Return the number of changes in the most recent call to sqlite3_exec().
166401 */
166402 SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
166403 #ifdef SQLITE_ENABLE_API_ARMOR
166404 if( !sqlite3SafetyCheckOk(db) ){
166405 (void)SQLITE_MISUSE_BKPT;
166406 return 0;
166407 }
166408 #endif
166409 return db->nChange;
166410 }
166411 SQLITE_API int sqlite3_changes(sqlite3 *db){
166412 return (int)sqlite3_changes64(db);
166413 }
166414
166415 /*
166416 ** Return the number of changes since the database handle was opened.
166417 */
166418 SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
166419 #ifdef SQLITE_ENABLE_API_ARMOR
166420 if( !sqlite3SafetyCheckOk(db) ){
166421 (void)SQLITE_MISUSE_BKPT;
166422 return 0;
166423 }
166424 #endif
166425 return db->nTotalChange;
166426 }
166427 SQLITE_API int sqlite3_total_changes(sqlite3 *db){
166428 return (int)sqlite3_total_changes64(db);
166429 }
166430
166431 /*
166432 ** Close all open savepoints. This function only manipulates fields of the
166433 ** database handle object, it does not close any savepoints that may be open
@@ -166913,26 +167165,37 @@
167165 ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
167166 **
167167 ** If SQLITE_ANY is specified, add three versions of the function
167168 ** to the hash table.
167169 */
167170 switch( enc ){
167171 case SQLITE_UTF16:
167172 enc = SQLITE_UTF16NATIVE;
167173 break;
167174 case SQLITE_ANY: {
167175 int rc;
167176 rc = sqlite3CreateFunc(db, zFunctionName, nArg,
167177 (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
167178 pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
167179 if( rc==SQLITE_OK ){
167180 rc = sqlite3CreateFunc(db, zFunctionName, nArg,
167181 (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
167182 pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
167183 }
167184 if( rc!=SQLITE_OK ){
167185 return rc;
167186 }
167187 enc = SQLITE_UTF16BE;
167188 break;
167189 }
167190 case SQLITE_UTF8:
167191 case SQLITE_UTF16LE:
167192 case SQLITE_UTF16BE:
167193 break;
167194 default:
167195 enc = SQLITE_UTF8;
167196 break;
167197 }
167198 #else
167199 enc = SQLITE_UTF8;
167200 #endif
167201
@@ -167025,11 +167288,11 @@
167288 }
167289 rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p,
167290 xSFunc, xStep, xFinal, xValue, xInverse, pArg
167291 );
167292 if( pArg && pArg->nRef==0 ){
167293 assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) );
167294 xDestroy(p);
167295 sqlite3_free(pArg);
167296 }
167297
167298 out:
@@ -168208,11 +168471,10 @@
168471 ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
168472 ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
168473 ** off all other flags.
168474 */
168475 flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
 
168476 SQLITE_OPEN_MAIN_DB |
168477 SQLITE_OPEN_TEMP_DB |
168478 SQLITE_OPEN_TRANSIENT_DB |
168479 SQLITE_OPEN_MAIN_JOURNAL |
168480 SQLITE_OPEN_TEMP_JOURNAL |
@@ -168780,11 +169042,11 @@
169042 goto error_out;
169043 }
169044
169045 /* Locate the table in question */
169046 pTab = sqlite3FindTable(db, zTableName, zDbName);
169047 if( !pTab || IsView(pTab) ){
169048 pTab = 0;
169049 goto error_out;
169050 }
169051
169052 /* Find the column for which info is requested */
@@ -168791,11 +169053,11 @@
169053 if( zColumnName==0 ){
169054 /* Query for existance of table only */
169055 }else{
169056 for(iCol=0; iCol<pTab->nCol; iCol++){
169057 pCol = &pTab->aCol[iCol];
169058 if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){
169059 break;
169060 }
169061 }
169062 if( iCol==pTab->nCol ){
169063 if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
@@ -168818,11 +169080,11 @@
169080 ** 2. The table is not a view and the column name identified an
169081 ** explicitly declared column. Copy meta information from *pCol.
169082 */
169083 if( pCol ){
169084 zDataType = sqlite3ColumnType(pCol,0);
169085 zCollSeq = sqlite3ColumnColl(pCol);
169086 notnull = pCol->notNull!=0;
169087 primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
169088 autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
169089 }else{
169090 zDataType = "INTEGER";
@@ -169349,11 +169611,11 @@
169611 case 3: sqlite3WhereTrace = *ptr; break;
169612 }
169613 break;
169614 }
169615
169616 #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
169617 /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
169618 **
169619 ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
169620 ** of the id-th tuning parameter to *piValue. If "id" is between -1
169621 ** and -SQLITE_NTUNE, then write the current value of the (-id)-th
@@ -201251,11 +201513,13 @@
201513 *piPk = 0;
201514
201515 assert( p->rc==SQLITE_OK );
201516 p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
201517 sqlite3_mprintf(
201518 "SELECT "
201519 " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM'),"
201520 " rootpage"
201521 " FROM sqlite_schema"
201522 " WHERE name=%Q", zTab
201523 ));
201524 if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){
201525 /* Either an error, or no such table. */
@@ -202784,11 +203048,11 @@
203048 case RBU_STATE_COOKIE:
203049 pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1);
203050 break;
203051
203052 case RBU_STATE_OALSZ:
203053 pRet->iOalSz = sqlite3_column_int64(pStmt, 1);
203054 break;
203055
203056 case RBU_STATE_PHASEONESTEP:
203057 pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1);
203058 break;
@@ -213428,10 +213692,13 @@
213692 /*
213693 ** This interface is used by the fts5vocab module.
213694 */
213695 static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
213696 static int sqlite3Fts5IterNextScan(Fts5IndexIter*);
213697 static void *sqlite3Fts5StructureRef(Fts5Index*);
213698 static void sqlite3Fts5StructureRelease(void*);
213699 static int sqlite3Fts5StructureTest(Fts5Index*, void*);
213700
213701
213702 /*
213703 ** Insert or remove data to or from the index. Each time a document is
213704 ** added to or removed from the index, this function is called one or more
@@ -216223,20 +216490,21 @@
216490 /* EOF */
216491 *piOff = -1;
216492 return 1;
216493 }else{
216494 i64 iOff = *piOff;
216495 u32 iVal;
216496 fts5FastGetVarint32(a, i, iVal);
216497 assert( iVal>=0 );
216498 if( iVal<=1 ){
216499 if( iVal==0 ){
216500 *pi = i;
216501 return 0;
216502 }
216503 fts5FastGetVarint32(a, i, iVal);
216504 iOff = ((i64)iVal) << 32;
216505 assert( iOff>=0 );
216506 fts5FastGetVarint32(a, i, iVal);
216507 if( iVal<2 ){
216508 /* This is a corrupt record. So stop parsing it here. */
216509 *piOff = -1;
216510 return 1;
@@ -216244,11 +216512,11 @@
216512 *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
216513 }else{
216514 *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
216515 }
216516 *pi = i;
216517 assert_nc( *piOff>=iOff );
216518 return 0;
216519 }
216520 }
216521
216522
@@ -217553,10 +217821,11 @@
217821
217822 static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
217823 va_list ap;
217824 va_start(ap, zFmt);
217825 if( pParse->rc==SQLITE_OK ){
217826 assert( pParse->zErr==0 );
217827 pParse->zErr = sqlite3_vmprintf(zFmt, ap);
217828 pParse->rc = SQLITE_ERROR;
217829 }
217830 va_end(ap);
217831 }
@@ -219562,13 +219831,12 @@
219831 Fts5ExprNode *pExpr,
219832 Fts5Colset *pColset
219833 ){
219834 Fts5Colset *pFree = pColset;
219835 if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
219836 sqlite3Fts5ParseError(pParse,
219837 "fts5: column queries are not supported (detail=none)"
 
219838 );
219839 }else{
219840 fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
219841 }
219842 sqlite3_free(pFree);
@@ -219738,17 +220006,14 @@
220006 Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
220007 if( pNear->nPhrase!=1
220008 || pPhrase->nTerm>1
220009 || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
220010 ){
220011 sqlite3Fts5ParseError(pParse,
 
 
 
220012 "fts5: %s queries are not supported (detail!=full)",
220013 pNear->nPhrase==1 ? "phrase": "NEAR"
220014 );
220015 sqlite3_free(pRet);
220016 pRet = 0;
220017 }
220018 }
220019 }else{
@@ -221861,10 +222126,26 @@
222126 }
222127
222128 static void fts5StructureRef(Fts5Structure *pStruct){
222129 pStruct->nRef++;
222130 }
222131
222132 static void *sqlite3Fts5StructureRef(Fts5Index *p){
222133 fts5StructureRef(p->pStruct);
222134 return (void*)p->pStruct;
222135 }
222136 static void sqlite3Fts5StructureRelease(void *p){
222137 if( p ){
222138 fts5StructureRelease((Fts5Structure*)p);
222139 }
222140 }
222141 static int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
222142 if( p->pStruct!=(Fts5Structure*)pStruct ){
222143 return SQLITE_ABORT;
222144 }
222145 return SQLITE_OK;
222146 }
222147
222148 /*
222149 ** Deserialize and return the structure record currently stored in serialized
222150 ** form within buffer pData/nData.
222151 **
@@ -230568,11 +230849,11 @@
230849 int nArg, /* Number of args */
230850 sqlite3_value **apUnused /* Function arguments */
230851 ){
230852 assert( nArg==0 );
230853 UNUSED_PARAM2(nArg, apUnused);
230854 sqlite3_result_text(pCtx, "fts5: 2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a", -1, SQLITE_TRANSIENT);
230855 }
230856
230857 /*
230858 ** Return true if zName is the extension on one of the shadow tables used
230859 ** by this module.
@@ -234464,10 +234745,11 @@
234745 sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
234746 Fts5Table *pFts5; /* Associated FTS5 table */
234747
234748 int bEof; /* True if this cursor is at EOF */
234749 Fts5IndexIter *pIter; /* Term/rowid iterator object */
234750 void *pStruct; /* From sqlite3Fts5StructureRef() */
234751
234752 int nLeTerm; /* Size of zLeTerm in bytes */
234753 char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
234754
234755 /* These are used by 'col' tables only */
@@ -234797,10 +235079,12 @@
235079 }
235080
235081 static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
235082 pCsr->rowid = 0;
235083 sqlite3Fts5IterClose(pCsr->pIter);
235084 sqlite3Fts5StructureRelease(pCsr->pStruct);
235085 pCsr->pStruct = 0;
235086 pCsr->pIter = 0;
235087 sqlite3_free(pCsr->zLeTerm);
235088 pCsr->nLeTerm = -1;
235089 pCsr->zLeTerm = 0;
235090 pCsr->bEof = 0;
@@ -234874,13 +235158,15 @@
235158 ** Advance the cursor to the next row in the table.
235159 */
235160 static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
235161 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
235162 Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
 
235163 int nCol = pCsr->pFts5->pConfig->nCol;
235164 int rc;
235165
235166 rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct);
235167 if( rc!=SQLITE_OK ) return rc;
235168 pCsr->rowid++;
235169
235170 if( pTab->eType==FTS5_VOCAB_INSTANCE ){
235171 return fts5VocabInstanceNext(pCsr);
235172 }
@@ -235050,10 +235336,13 @@
235336 }
235337
235338 if( rc==SQLITE_OK ){
235339 Fts5Index *pIndex = pCsr->pFts5->pIndex;
235340 rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
235341 if( rc==SQLITE_OK ){
235342 pCsr->pStruct = sqlite3Fts5StructureRef(pIndex);
235343 }
235344 }
235345 if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
235346 rc = fts5VocabInstanceNewTerm(pCsr);
235347 }
235348 if( rc==SQLITE_OK && !pCsr->bEof
@@ -235494,12 +235783,8 @@
235783 }
235784 #endif /* SQLITE_CORE */
235785 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
235786
235787 /************** End of stmt.c ************************************************/
 
 
 
 
235788 /* Return the source-id for this library */
235789 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
235790 /************************** End of sqlite3.c ******************************/
235791
+66 -17
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -41,11 +41,34 @@
4141
extern "C" {
4242
#endif
4343
4444
4545
/*
46
-** Provide the ability to override linkage features of the interface.
46
+** Facilitate override of interface linkage and calling conventions.
47
+** Be aware that these macros may not be used within this particular
48
+** translation of the amalgamation and its associated header file.
49
+**
50
+** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
51
+** compiler that the target identifier should have external linkage.
52
+**
53
+** The SQLITE_CDECL macro is used to set the calling convention for
54
+** public functions that accept a variable number of arguments.
55
+**
56
+** The SQLITE_APICALL macro is used to set the calling convention for
57
+** public functions that accept a fixed number of arguments.
58
+**
59
+** The SQLITE_STDCALL macro is no longer used and is now deprecated.
60
+**
61
+** The SQLITE_CALLBACK macro is used to set the calling convention for
62
+** function pointers.
63
+**
64
+** The SQLITE_SYSAPI macro is used to set the calling convention for
65
+** functions provided by the operating system.
66
+**
67
+** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
68
+** SQLITE_SYSAPI macros are used only when building for environments
69
+** that require non-default calling conventions.
4770
*/
4871
#ifndef SQLITE_EXTERN
4972
# define SQLITE_EXTERN extern
5073
#endif
5174
#ifndef SQLITE_API
@@ -121,13 +144,13 @@
121144
**
122145
** See also: [sqlite3_libversion()],
123146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124147
** [sqlite_version()] and [sqlite_source_id()].
125148
*/
126
-#define SQLITE_VERSION "3.36.0"
127
-#define SQLITE_VERSION_NUMBER 3036000
128
-#define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70"
149
+#define SQLITE_VERSION "3.37.0"
150
+#define SQLITE_VERSION_NUMBER 3037000
151
+#define SQLITE_SOURCE_ID "2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a"
129152
130153
/*
131154
** CAPI3REF: Run-Time Library Version Numbers
132155
** KEYWORDS: sqlite3_version sqlite3_sourceid
133156
**
@@ -514,10 +537,11 @@
514537
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
515538
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
516539
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
517540
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
518541
#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
542
+#define SQLITE_CANTOPEN_EXISTS (SQLITE_CANTOPEN | (7<<8))
519543
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
520544
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
521545
#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
522546
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
523547
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -2462,15 +2486,18 @@
24622486
24632487
/*
24642488
** CAPI3REF: Count The Number Of Rows Modified
24652489
** METHOD: sqlite3
24662490
**
2467
-** ^This function returns the number of rows modified, inserted or
2491
+** ^These functions return the number of rows modified, inserted or
24682492
** deleted by the most recently completed INSERT, UPDATE or DELETE
24692493
** statement on the database connection specified by the only parameter.
2470
-** ^Executing any other type of SQL statement does not modify the value
2471
-** returned by this function.
2494
+** The two functions are identical except for the type of the return value
2495
+** and that if the number of rows modified by the most recent INSERT, UPDATE
2496
+** or DELETE is greater than the maximum value supported by type "int", then
2497
+** the return value of sqlite3_changes() is undefined. ^Executing any other
2498
+** type of SQL statement does not modify the value returned by these functions.
24722499
**
24732500
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
24742501
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
24752502
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
24762503
**
@@ -2515,20 +2542,25 @@
25152542
** <li> the [changes() SQL function]
25162543
** <li> the [data_version pragma]
25172544
** </ul>
25182545
*/
25192546
SQLITE_API int sqlite3_changes(sqlite3*);
2547
+SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
25202548
25212549
/*
25222550
** CAPI3REF: Total Number Of Rows Modified
25232551
** METHOD: sqlite3
25242552
**
2525
-** ^This function returns the total number of rows inserted, modified or
2553
+** ^These functions return the total number of rows inserted, modified or
25262554
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
25272555
** since the database connection was opened, including those executed as
2528
-** part of trigger programs. ^Executing any other type of SQL statement
2529
-** does not affect the value returned by sqlite3_total_changes().
2556
+** part of trigger programs. The two functions are identical except for the
2557
+** type of the return value and that if the number of rows modified by the
2558
+** connection exceeds the maximum value supported by type "int", then
2559
+** the return value of sqlite3_total_changes() is undefined. ^Executing
2560
+** any other type of SQL statement does not affect the value returned by
2561
+** sqlite3_total_changes().
25302562
**
25312563
** ^Changes made as part of [foreign key actions] are included in the
25322564
** count, but those made as part of REPLACE constraint resolution are
25332565
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
25342566
** are not counted.
@@ -2552,10 +2584,11 @@
25522584
** <li> the [data_version pragma]
25532585
** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
25542586
** </ul>
25552587
*/
25562588
SQLITE_API int sqlite3_total_changes(sqlite3*);
2589
+SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
25572590
25582591
/*
25592592
** CAPI3REF: Interrupt A Long-Running Query
25602593
** METHOD: sqlite3
25612594
**
@@ -3383,10 +3416,16 @@
33833416
** the default shared cache setting provided by
33843417
** [sqlite3_enable_shared_cache()].)^
33853418
**
33863419
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
33873420
** <dd>The database filename is not allowed to be a symbolic link</dd>
3421
+**
3422
+** [[OPEN_EXCLUSIVE]] ^(<dt>[SQLITE_OPEN_EXCLUSIVE]</dt>
3423
+** <dd>This flag causes the open to fail if the database file already
3424
+** exists. The open will only be success if this flag is used in combination
3425
+** with the SQLITE_OPEN_CREATE and SQLITE_OPEN_READWRITE flags and if
3426
+** the file does not previously exist.</dd>
33883427
** </dl>)^
33893428
**
33903429
** If the 3rd parameter to sqlite3_open_v2() is not one of the
33913430
** required combinations shown above optionally combined with other
33923431
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
@@ -4156,16 +4195,21 @@
41564195
**
41574196
** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
41584197
** are managed by SQLite and are automatically freed when the prepared
41594198
** statement is finalized.
41604199
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
4161
-** is obtained from [sqlite3_malloc()] and must be free by the application
4200
+** is obtained from [sqlite3_malloc()] and must be freed by the application
41624201
** by passing it to [sqlite3_free()].
4202
+**
4203
+** ^The sqlite3_normalized_sql() interface is only available if
4204
+** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
41634205
*/
41644206
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
41654207
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
4208
+#ifdef SQLITE_ENABLE_NORMALIZE
41664209
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
4210
+#endif
41674211
41684212
/*
41694213
** CAPI3REF: Determine If An SQL Statement Writes The Database
41704214
** METHOD: sqlite3_stmt
41714215
**
@@ -4376,21 +4420,21 @@
43764420
** contain embedded NULs. The result of expressions involving strings
43774421
** with embedded NULs is undefined.
43784422
**
43794423
** ^The fifth argument to the BLOB and string binding interfaces controls
43804424
** or indicates the lifetime of the object referenced by the third parameter.
4381
-** ^These three options exist:
4382
-** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
4425
+** These three options exist:
4426
+** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
43834427
** with it may be passed. ^It is called to dispose of the BLOB or string even
43844428
** if the call to the bind API fails, except the destructor is not called if
43854429
** the third parameter is a NULL pointer or the fourth parameter is negative.
4386
-** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
4430
+** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
43874431
** the application remains responsible for disposing of the object. ^In this
43884432
** case, the object and the provided pointer to it must remain valid until
43894433
** either the prepared statement is finalized or the same SQL parameter is
43904434
** bound to something else, whichever occurs sooner.
4391
-** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4435
+** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
43924436
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
43934437
** object and pointer to it must remain valid until then. ^SQLite will then
43944438
** manage the lifetime of its private copy.
43954439
**
43964440
** ^The sixth argument to sqlite3_bind_text64() must be one of
@@ -9008,12 +9052,13 @@
90089052
** that does not correspond to any valid SQLite error code, the results
90099053
** are undefined.
90109054
**
90119055
** A single database handle may have at most a single write-ahead log callback
90129056
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
9013
-** previously registered write-ahead log callback. ^Note that the
9014
-** [sqlite3_wal_autocheckpoint()] interface and the
9057
+** previously registered write-ahead log callback. ^The return value is
9058
+** a copy of the third parameter from the previous call, if any, or 0.
9059
+** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
90159060
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
90169061
** overwrite any prior [sqlite3_wal_hook()] settings.
90179062
*/
90189063
SQLITE_API void *sqlite3_wal_hook(
90199064
sqlite3*,
@@ -9875,10 +9920,14 @@
98759920
** if writes on the database cause it to grow larger than M bytes.
98769921
**
98779922
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
98789923
** database is currently in a read transaction or is involved in a backup
98799924
** operation.
9925
+**
9926
+** It is not possible to deserialized into the TEMP database. If the
9927
+** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
9928
+** function returns SQLITE_ERROR.
98809929
**
98819930
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
98829931
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
98839932
** [sqlite3_free()] is invoked on argument P prior to returning.
98849933
**
98859934
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -41,11 +41,34 @@
41 extern "C" {
42 #endif
43
44
45 /*
46 ** Provide the ability to override linkage features of the interface.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47 */
48 #ifndef SQLITE_EXTERN
49 # define SQLITE_EXTERN extern
50 #endif
51 #ifndef SQLITE_API
@@ -121,13 +144,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.36.0"
127 #define SQLITE_VERSION_NUMBER 3036000
128 #define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
@@ -514,10 +537,11 @@
514 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
515 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
516 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
517 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
518 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
 
519 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
520 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
521 #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
522 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
523 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -2462,15 +2486,18 @@
2462
2463 /*
2464 ** CAPI3REF: Count The Number Of Rows Modified
2465 ** METHOD: sqlite3
2466 **
2467 ** ^This function returns the number of rows modified, inserted or
2468 ** deleted by the most recently completed INSERT, UPDATE or DELETE
2469 ** statement on the database connection specified by the only parameter.
2470 ** ^Executing any other type of SQL statement does not modify the value
2471 ** returned by this function.
 
 
 
2472 **
2473 ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
2474 ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
2475 ** [foreign key actions] or [REPLACE] constraint resolution are not counted.
2476 **
@@ -2515,20 +2542,25 @@
2515 ** <li> the [changes() SQL function]
2516 ** <li> the [data_version pragma]
2517 ** </ul>
2518 */
2519 SQLITE_API int sqlite3_changes(sqlite3*);
 
2520
2521 /*
2522 ** CAPI3REF: Total Number Of Rows Modified
2523 ** METHOD: sqlite3
2524 **
2525 ** ^This function returns the total number of rows inserted, modified or
2526 ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
2527 ** since the database connection was opened, including those executed as
2528 ** part of trigger programs. ^Executing any other type of SQL statement
2529 ** does not affect the value returned by sqlite3_total_changes().
 
 
 
 
2530 **
2531 ** ^Changes made as part of [foreign key actions] are included in the
2532 ** count, but those made as part of REPLACE constraint resolution are
2533 ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
2534 ** are not counted.
@@ -2552,10 +2584,11 @@
2552 ** <li> the [data_version pragma]
2553 ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
2554 ** </ul>
2555 */
2556 SQLITE_API int sqlite3_total_changes(sqlite3*);
 
2557
2558 /*
2559 ** CAPI3REF: Interrupt A Long-Running Query
2560 ** METHOD: sqlite3
2561 **
@@ -3383,10 +3416,16 @@
3383 ** the default shared cache setting provided by
3384 ** [sqlite3_enable_shared_cache()].)^
3385 **
3386 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
3387 ** <dd>The database filename is not allowed to be a symbolic link</dd>
 
 
 
 
 
 
3388 ** </dl>)^
3389 **
3390 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
3391 ** required combinations shown above optionally combined with other
3392 ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
@@ -4156,16 +4195,21 @@
4156 **
4157 ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
4158 ** are managed by SQLite and are automatically freed when the prepared
4159 ** statement is finalized.
4160 ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
4161 ** is obtained from [sqlite3_malloc()] and must be free by the application
4162 ** by passing it to [sqlite3_free()].
 
 
 
4163 */
4164 SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
4165 SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
 
4166 SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
 
4167
4168 /*
4169 ** CAPI3REF: Determine If An SQL Statement Writes The Database
4170 ** METHOD: sqlite3_stmt
4171 **
@@ -4376,21 +4420,21 @@
4376 ** contain embedded NULs. The result of expressions involving strings
4377 ** with embedded NULs is undefined.
4378 **
4379 ** ^The fifth argument to the BLOB and string binding interfaces controls
4380 ** or indicates the lifetime of the object referenced by the third parameter.
4381 ** ^These three options exist:
4382 ** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
4383 ** with it may be passed. ^It is called to dispose of the BLOB or string even
4384 ** if the call to the bind API fails, except the destructor is not called if
4385 ** the third parameter is a NULL pointer or the fourth parameter is negative.
4386 ** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
4387 ** the application remains responsible for disposing of the object. ^In this
4388 ** case, the object and the provided pointer to it must remain valid until
4389 ** either the prepared statement is finalized or the same SQL parameter is
4390 ** bound to something else, whichever occurs sooner.
4391 ** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4392 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
4393 ** object and pointer to it must remain valid until then. ^SQLite will then
4394 ** manage the lifetime of its private copy.
4395 **
4396 ** ^The sixth argument to sqlite3_bind_text64() must be one of
@@ -9008,12 +9052,13 @@
9008 ** that does not correspond to any valid SQLite error code, the results
9009 ** are undefined.
9010 **
9011 ** A single database handle may have at most a single write-ahead log callback
9012 ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
9013 ** previously registered write-ahead log callback. ^Note that the
9014 ** [sqlite3_wal_autocheckpoint()] interface and the
 
9015 ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
9016 ** overwrite any prior [sqlite3_wal_hook()] settings.
9017 */
9018 SQLITE_API void *sqlite3_wal_hook(
9019 sqlite3*,
@@ -9875,10 +9920,14 @@
9875 ** if writes on the database cause it to grow larger than M bytes.
9876 **
9877 ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
9878 ** database is currently in a read transaction or is involved in a backup
9879 ** operation.
 
 
 
 
9880 **
9881 ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
9882 ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
9883 ** [sqlite3_free()] is invoked on argument P prior to returning.
9884 **
9885
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -41,11 +41,34 @@
41 extern "C" {
42 #endif
43
44
45 /*
46 ** Facilitate override of interface linkage and calling conventions.
47 ** Be aware that these macros may not be used within this particular
48 ** translation of the amalgamation and its associated header file.
49 **
50 ** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
51 ** compiler that the target identifier should have external linkage.
52 **
53 ** The SQLITE_CDECL macro is used to set the calling convention for
54 ** public functions that accept a variable number of arguments.
55 **
56 ** The SQLITE_APICALL macro is used to set the calling convention for
57 ** public functions that accept a fixed number of arguments.
58 **
59 ** The SQLITE_STDCALL macro is no longer used and is now deprecated.
60 **
61 ** The SQLITE_CALLBACK macro is used to set the calling convention for
62 ** function pointers.
63 **
64 ** The SQLITE_SYSAPI macro is used to set the calling convention for
65 ** functions provided by the operating system.
66 **
67 ** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
68 ** SQLITE_SYSAPI macros are used only when building for environments
69 ** that require non-default calling conventions.
70 */
71 #ifndef SQLITE_EXTERN
72 # define SQLITE_EXTERN extern
73 #endif
74 #ifndef SQLITE_API
@@ -121,13 +144,13 @@
144 **
145 ** See also: [sqlite3_libversion()],
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.37.0"
150 #define SQLITE_VERSION_NUMBER 3037000
151 #define SQLITE_SOURCE_ID "2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -514,10 +537,11 @@
537 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
538 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
539 #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
540 #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
541 #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
542 #define SQLITE_CANTOPEN_EXISTS (SQLITE_CANTOPEN | (7<<8))
543 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
544 #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
545 #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
546 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
547 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -2462,15 +2486,18 @@
2486
2487 /*
2488 ** CAPI3REF: Count The Number Of Rows Modified
2489 ** METHOD: sqlite3
2490 **
2491 ** ^These functions return the number of rows modified, inserted or
2492 ** deleted by the most recently completed INSERT, UPDATE or DELETE
2493 ** statement on the database connection specified by the only parameter.
2494 ** The two functions are identical except for the type of the return value
2495 ** and that if the number of rows modified by the most recent INSERT, UPDATE
2496 ** or DELETE is greater than the maximum value supported by type "int", then
2497 ** the return value of sqlite3_changes() is undefined. ^Executing any other
2498 ** type of SQL statement does not modify the value returned by these functions.
2499 **
2500 ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
2501 ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
2502 ** [foreign key actions] or [REPLACE] constraint resolution are not counted.
2503 **
@@ -2515,20 +2542,25 @@
2542 ** <li> the [changes() SQL function]
2543 ** <li> the [data_version pragma]
2544 ** </ul>
2545 */
2546 SQLITE_API int sqlite3_changes(sqlite3*);
2547 SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
2548
2549 /*
2550 ** CAPI3REF: Total Number Of Rows Modified
2551 ** METHOD: sqlite3
2552 **
2553 ** ^These functions return the total number of rows inserted, modified or
2554 ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
2555 ** since the database connection was opened, including those executed as
2556 ** part of trigger programs. The two functions are identical except for the
2557 ** type of the return value and that if the number of rows modified by the
2558 ** connection exceeds the maximum value supported by type "int", then
2559 ** the return value of sqlite3_total_changes() is undefined. ^Executing
2560 ** any other type of SQL statement does not affect the value returned by
2561 ** sqlite3_total_changes().
2562 **
2563 ** ^Changes made as part of [foreign key actions] are included in the
2564 ** count, but those made as part of REPLACE constraint resolution are
2565 ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
2566 ** are not counted.
@@ -2552,10 +2584,11 @@
2584 ** <li> the [data_version pragma]
2585 ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
2586 ** </ul>
2587 */
2588 SQLITE_API int sqlite3_total_changes(sqlite3*);
2589 SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
2590
2591 /*
2592 ** CAPI3REF: Interrupt A Long-Running Query
2593 ** METHOD: sqlite3
2594 **
@@ -3383,10 +3416,16 @@
3416 ** the default shared cache setting provided by
3417 ** [sqlite3_enable_shared_cache()].)^
3418 **
3419 ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
3420 ** <dd>The database filename is not allowed to be a symbolic link</dd>
3421 **
3422 ** [[OPEN_EXCLUSIVE]] ^(<dt>[SQLITE_OPEN_EXCLUSIVE]</dt>
3423 ** <dd>This flag causes the open to fail if the database file already
3424 ** exists. The open will only be success if this flag is used in combination
3425 ** with the SQLITE_OPEN_CREATE and SQLITE_OPEN_READWRITE flags and if
3426 ** the file does not previously exist.</dd>
3427 ** </dl>)^
3428 **
3429 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
3430 ** required combinations shown above optionally combined with other
3431 ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
@@ -4156,16 +4195,21 @@
4195 **
4196 ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
4197 ** are managed by SQLite and are automatically freed when the prepared
4198 ** statement is finalized.
4199 ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
4200 ** is obtained from [sqlite3_malloc()] and must be freed by the application
4201 ** by passing it to [sqlite3_free()].
4202 **
4203 ** ^The sqlite3_normalized_sql() interface is only available if
4204 ** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
4205 */
4206 SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
4207 SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
4208 #ifdef SQLITE_ENABLE_NORMALIZE
4209 SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
4210 #endif
4211
4212 /*
4213 ** CAPI3REF: Determine If An SQL Statement Writes The Database
4214 ** METHOD: sqlite3_stmt
4215 **
@@ -4376,21 +4420,21 @@
4420 ** contain embedded NULs. The result of expressions involving strings
4421 ** with embedded NULs is undefined.
4422 **
4423 ** ^The fifth argument to the BLOB and string binding interfaces controls
4424 ** or indicates the lifetime of the object referenced by the third parameter.
4425 ** These three options exist:
4426 ** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
4427 ** with it may be passed. ^It is called to dispose of the BLOB or string even
4428 ** if the call to the bind API fails, except the destructor is not called if
4429 ** the third parameter is a NULL pointer or the fourth parameter is negative.
4430 ** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
4431 ** the application remains responsible for disposing of the object. ^In this
4432 ** case, the object and the provided pointer to it must remain valid until
4433 ** either the prepared statement is finalized or the same SQL parameter is
4434 ** bound to something else, whichever occurs sooner.
4435 ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4436 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
4437 ** object and pointer to it must remain valid until then. ^SQLite will then
4438 ** manage the lifetime of its private copy.
4439 **
4440 ** ^The sixth argument to sqlite3_bind_text64() must be one of
@@ -9008,12 +9052,13 @@
9052 ** that does not correspond to any valid SQLite error code, the results
9053 ** are undefined.
9054 **
9055 ** A single database handle may have at most a single write-ahead log callback
9056 ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
9057 ** previously registered write-ahead log callback. ^The return value is
9058 ** a copy of the third parameter from the previous call, if any, or 0.
9059 ** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
9060 ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
9061 ** overwrite any prior [sqlite3_wal_hook()] settings.
9062 */
9063 SQLITE_API void *sqlite3_wal_hook(
9064 sqlite3*,
@@ -9875,10 +9920,14 @@
9920 ** if writes on the database cause it to grow larger than M bytes.
9921 **
9922 ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
9923 ** database is currently in a read transaction or is involved in a backup
9924 ** operation.
9925 **
9926 ** It is not possible to deserialized into the TEMP database. If the
9927 ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
9928 ** function returns SQLITE_ERROR.
9929 **
9930 ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
9931 ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
9932 ** [sqlite3_free()] is invoked on argument P prior to returning.
9933 **
9934
+1 -2
--- src/stash.c
+++ src/stash.c
@@ -442,11 +442,10 @@
442442
if( fBaseline ){
443443
content_get(rid, &a);
444444
isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
445445
diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
446446
zBinGlob, fIncludeBinary, diffFlags);
447
- }else{
448447
}
449448
}else{
450449
Blob delta;
451450
int isOrigLink = file_islink(zOPath);
452451
db_ephemeral_blob(&q, 6, &delta);
@@ -472,11 +471,11 @@
472471
blob_reset(&a);
473472
blob_reset(&b);
474473
}
475474
blob_reset(&delta);
476475
}
477
- }
476
+ }
478477
db_finalize(&q);
479478
}
480479
481480
/*
482481
** Drop the indicated stash
483482
--- src/stash.c
+++ src/stash.c
@@ -442,11 +442,10 @@
442 if( fBaseline ){
443 content_get(rid, &a);
444 isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
445 diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
446 zBinGlob, fIncludeBinary, diffFlags);
447 }else{
448 }
449 }else{
450 Blob delta;
451 int isOrigLink = file_islink(zOPath);
452 db_ephemeral_blob(&q, 6, &delta);
@@ -472,11 +471,11 @@
472 blob_reset(&a);
473 blob_reset(&b);
474 }
475 blob_reset(&delta);
476 }
477 }
478 db_finalize(&q);
479 }
480
481 /*
482 ** Drop the indicated stash
483
--- src/stash.c
+++ src/stash.c
@@ -442,11 +442,10 @@
442 if( fBaseline ){
443 content_get(rid, &a);
444 isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a);
445 diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd,
446 zBinGlob, fIncludeBinary, diffFlags);
 
447 }
448 }else{
449 Blob delta;
450 int isOrigLink = file_islink(zOPath);
451 db_ephemeral_blob(&q, 6, &delta);
@@ -472,11 +471,11 @@
471 blob_reset(&a);
472 blob_reset(&b);
473 }
474 blob_reset(&delta);
475 }
476 }
477 db_finalize(&q);
478 }
479
480 /*
481 ** Drop the indicated stash
482
+45 -20
--- src/stat.c
+++ src/stat.c
@@ -169,11 +169,11 @@
169169
@ </td></tr>
170170
if( !brief ){
171171
@ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
172172
n = db_int(0, "SELECT count(*) FROM blob WHERE content IS NOT NULL");
173173
m = db_int(0, "SELECT count(*) FROM delta");
174
- @ %.d(n) (%,d(n-m) fulltext and %,d(m) deltas)
174
+ @ %,d(n) (%,d(n-m) fulltext and %,d(m) deltas)
175175
if( g.perm.Write ){
176176
@ <a href='%R/artifact_stats'>Details</a>
177177
}
178178
@ </td></tr>
179179
if( n>0 ){
@@ -480,21 +480,21 @@
480480
Stmt q;
481481
int cnt;
482482
int showAll = P("all")!=0;
483483
int nOmitted;
484484
sqlite3_int64 iNow;
485
- char *zRemote;
485
+
486486
login_check_credentials();
487487
if( !g.perm.Admin ){ login_needed(0); return; }
488488
489489
style_set_current_feature("stat");
490490
style_header("URLs and Checkouts");
491491
style_adunit_config(ADUNIT_RIGHT_OK);
492492
style_submenu_element("Stat", "stat");
493493
style_submenu_element("Schema", "repo_schema");
494494
iNow = db_int64(0, "SELECT strftime('%%s','now')");
495
- @ <div class="section">URLs</div>
495
+ @ <div class="section">URLs used to access</div>
496496
@ <table border="0" width='100%%'>
497497
db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch'), mtime"
498498
" FROM config WHERE name GLOB 'baseurl:*' ORDER BY 3 DESC");
499499
cnt = 0;
500500
nOmitted = 0;
@@ -512,39 +512,64 @@
512512
@ <tr><td>(none)</td>
513513
}else if( nOmitted ){
514514
@ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a>
515515
}
516516
@ </table>
517
- @ <div class="section">Checkouts</div>
518
- @ <table border="0" width='100%%'>
519517
db_prepare(&q, "SELECT substr(name,7), datetime(mtime,'unixepoch')"
520518
" FROM config WHERE name GLOB 'ckout:*' ORDER BY 2 DESC");
521519
cnt = 0;
522520
while( db_step(&q)==SQLITE_ROW ){
523521
const char *zPath = db_column_text(&q,0);
524522
if( vfile_top_of_checkout(zPath) ){
523
+ if( cnt==0 ){
524
+ @ <div class="section">Checkouts</div>
525
+ @ <table border="0" width='100%%'>
526
+ }
525527
@ <tr><td width='100%%'>%h(zPath)</td>
526528
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
529
+ cnt++;
530
+ }
531
+ }
532
+ db_finalize(&q);
533
+ if( cnt ){
534
+ @ </table>
535
+ }
536
+ cnt = 0;
537
+ db_prepare(&q, "SELECT substr(name,10), datetime(mtime,'unixepoch')"
538
+ " FROM config WHERE name GLOB 'syncwith:*' ORDER BY 2 DESC");
539
+ while( db_step(&q)==SQLITE_ROW ){
540
+ const char *zURL = db_column_text(&q,0);
541
+ if( cnt==0 ){
542
+ @ <div class="section">Sync to these URLs</div>
543
+ @ <table border='0' width='100%%'>
544
+ }
545
+ @ <tr><td width='100%%'><a href='%h(zURL)'>%h(zURL)</a>
546
+ @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
547
+ cnt++;
548
+ }
549
+ db_finalize(&q);
550
+ if( cnt ){
551
+ @ </table>
552
+ }
553
+ cnt = 0;
554
+ db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')"
555
+ " FROM config WHERE name GLOB 'gitpush:*' ORDER BY 2 DESC");
556
+ while( db_step(&q)==SQLITE_ROW ){
557
+ const char *zURL = db_column_text(&q,0);
558
+ UrlData x;
559
+ if( cnt==0 ){
560
+ @ <div class="section">Git Mirrors</div>
561
+ @ <table border='0' width='100%%'>
527562
}
563
+ url_parse_local(zURL, URL_OMIT_USER, &x);
564
+ @ <tr><td width='100%%'><a href='%h(x.canonical)'>%h(x.canonical)</a>
565
+ @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
528566
cnt++;
529567
}
530568
db_finalize(&q);
531
- if( cnt==0 ){
532
- @ <tr><td>(none)</td>
533
- }
534
- @ </table>
535
- zRemote = db_text(0, "SELECT value FROM config WHERE name='last-sync-url'");
536
- if( zRemote ){
537
- @ <div class="section">Last Sync URL</div>
538
- if( sqlite3_strlike("http%", zRemote, 0)==0 ){
539
- UrlData x;
540
- url_parse_local(zRemote, URL_OMIT_USER, &x);
541
- @ <p><a href='%h(x.canonical)'>%h(zRemote)</a>
542
- }else{
543
- @ <p>%h(zRemote)</p>
544
- }
545
- @ </div>
569
+ if( cnt ){
570
+ @ </table>
546571
}
547572
style_finish_page();
548573
}
549574
550575
/*
551576
--- src/stat.c
+++ src/stat.c
@@ -169,11 +169,11 @@
169 @ </td></tr>
170 if( !brief ){
171 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
172 n = db_int(0, "SELECT count(*) FROM blob WHERE content IS NOT NULL");
173 m = db_int(0, "SELECT count(*) FROM delta");
174 @ %.d(n) (%,d(n-m) fulltext and %,d(m) deltas)
175 if( g.perm.Write ){
176 @ <a href='%R/artifact_stats'>Details</a>
177 }
178 @ </td></tr>
179 if( n>0 ){
@@ -480,21 +480,21 @@
480 Stmt q;
481 int cnt;
482 int showAll = P("all")!=0;
483 int nOmitted;
484 sqlite3_int64 iNow;
485 char *zRemote;
486 login_check_credentials();
487 if( !g.perm.Admin ){ login_needed(0); return; }
488
489 style_set_current_feature("stat");
490 style_header("URLs and Checkouts");
491 style_adunit_config(ADUNIT_RIGHT_OK);
492 style_submenu_element("Stat", "stat");
493 style_submenu_element("Schema", "repo_schema");
494 iNow = db_int64(0, "SELECT strftime('%%s','now')");
495 @ <div class="section">URLs</div>
496 @ <table border="0" width='100%%'>
497 db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch'), mtime"
498 " FROM config WHERE name GLOB 'baseurl:*' ORDER BY 3 DESC");
499 cnt = 0;
500 nOmitted = 0;
@@ -512,39 +512,64 @@
512 @ <tr><td>(none)</td>
513 }else if( nOmitted ){
514 @ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a>
515 }
516 @ </table>
517 @ <div class="section">Checkouts</div>
518 @ <table border="0" width='100%%'>
519 db_prepare(&q, "SELECT substr(name,7), datetime(mtime,'unixepoch')"
520 " FROM config WHERE name GLOB 'ckout:*' ORDER BY 2 DESC");
521 cnt = 0;
522 while( db_step(&q)==SQLITE_ROW ){
523 const char *zPath = db_column_text(&q,0);
524 if( vfile_top_of_checkout(zPath) ){
 
 
 
 
525 @ <tr><td width='100%%'>%h(zPath)</td>
526 @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527 }
 
 
 
528 cnt++;
529 }
530 db_finalize(&q);
531 if( cnt==0 ){
532 @ <tr><td>(none)</td>
533 }
534 @ </table>
535 zRemote = db_text(0, "SELECT value FROM config WHERE name='last-sync-url'");
536 if( zRemote ){
537 @ <div class="section">Last Sync URL</div>
538 if( sqlite3_strlike("http%", zRemote, 0)==0 ){
539 UrlData x;
540 url_parse_local(zRemote, URL_OMIT_USER, &x);
541 @ <p><a href='%h(x.canonical)'>%h(zRemote)</a>
542 }else{
543 @ <p>%h(zRemote)</p>
544 }
545 @ </div>
546 }
547 style_finish_page();
548 }
549
550 /*
551
--- src/stat.c
+++ src/stat.c
@@ -169,11 +169,11 @@
169 @ </td></tr>
170 if( !brief ){
171 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
172 n = db_int(0, "SELECT count(*) FROM blob WHERE content IS NOT NULL");
173 m = db_int(0, "SELECT count(*) FROM delta");
174 @ %,d(n) (%,d(n-m) fulltext and %,d(m) deltas)
175 if( g.perm.Write ){
176 @ <a href='%R/artifact_stats'>Details</a>
177 }
178 @ </td></tr>
179 if( n>0 ){
@@ -480,21 +480,21 @@
480 Stmt q;
481 int cnt;
482 int showAll = P("all")!=0;
483 int nOmitted;
484 sqlite3_int64 iNow;
485
486 login_check_credentials();
487 if( !g.perm.Admin ){ login_needed(0); return; }
488
489 style_set_current_feature("stat");
490 style_header("URLs and Checkouts");
491 style_adunit_config(ADUNIT_RIGHT_OK);
492 style_submenu_element("Stat", "stat");
493 style_submenu_element("Schema", "repo_schema");
494 iNow = db_int64(0, "SELECT strftime('%%s','now')");
495 @ <div class="section">URLs used to access</div>
496 @ <table border="0" width='100%%'>
497 db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch'), mtime"
498 " FROM config WHERE name GLOB 'baseurl:*' ORDER BY 3 DESC");
499 cnt = 0;
500 nOmitted = 0;
@@ -512,39 +512,64 @@
512 @ <tr><td>(none)</td>
513 }else if( nOmitted ){
514 @ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a>
515 }
516 @ </table>
 
 
517 db_prepare(&q, "SELECT substr(name,7), datetime(mtime,'unixepoch')"
518 " FROM config WHERE name GLOB 'ckout:*' ORDER BY 2 DESC");
519 cnt = 0;
520 while( db_step(&q)==SQLITE_ROW ){
521 const char *zPath = db_column_text(&q,0);
522 if( vfile_top_of_checkout(zPath) ){
523 if( cnt==0 ){
524 @ <div class="section">Checkouts</div>
525 @ <table border="0" width='100%%'>
526 }
527 @ <tr><td width='100%%'>%h(zPath)</td>
528 @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
529 cnt++;
530 }
531 }
532 db_finalize(&q);
533 if( cnt ){
534 @ </table>
535 }
536 cnt = 0;
537 db_prepare(&q, "SELECT substr(name,10), datetime(mtime,'unixepoch')"
538 " FROM config WHERE name GLOB 'syncwith:*' ORDER BY 2 DESC");
539 while( db_step(&q)==SQLITE_ROW ){
540 const char *zURL = db_column_text(&q,0);
541 if( cnt==0 ){
542 @ <div class="section">Sync to these URLs</div>
543 @ <table border='0' width='100%%'>
544 }
545 @ <tr><td width='100%%'><a href='%h(zURL)'>%h(zURL)</a>
546 @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
547 cnt++;
548 }
549 db_finalize(&q);
550 if( cnt ){
551 @ </table>
552 }
553 cnt = 0;
554 db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')"
555 " FROM config WHERE name GLOB 'gitpush:*' ORDER BY 2 DESC");
556 while( db_step(&q)==SQLITE_ROW ){
557 const char *zURL = db_column_text(&q,0);
558 UrlData x;
559 if( cnt==0 ){
560 @ <div class="section">Git Mirrors</div>
561 @ <table border='0' width='100%%'>
562 }
563 url_parse_local(zURL, URL_OMIT_USER, &x);
564 @ <tr><td width='100%%'><a href='%h(x.canonical)'>%h(x.canonical)</a>
565 @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
566 cnt++;
567 }
568 db_finalize(&q);
569 if( cnt ){
570 @ </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
571 }
572 style_finish_page();
573 }
574
575 /*
576
+58 -21
--- src/style.c
+++ src/style.c
@@ -107,27 +107,49 @@
107107
**
108108
** <a href="URL">
109109
** or <a id="ID">
110110
**
111111
** The form of the anchor tag is determined by the g.javascriptHyperlink
112
-** variable. The href="URL" form is used if g.javascriptHyperlink is false.
113
-** If g.javascriptHyperlink is true then the
114
-** id="ID" form is used and javascript is generated in the footer to cause
115
-** href values to be inserted after the page has loaded. If
116
-** g.perm.History is false, then the <a id="ID"> form is still
117
-** generated but the javascript is not generated so the links never
118
-** activate.
112
+** and g.perm.Hyperlink variables.
113
+**
114
+** g.perm.Hyperlink g.javascriptHyperlink Returned anchor format
115
+** ---------------- --------------------- ------------------------
116
+** 0 0 (empty string)
117
+** 0 1 (empty string)
118
+** 1 0 <a href="URL">
119
+** 1 1 <a id="ID">
120
+**
121
+** No anchor tag is generated if g.perm.Hyperlink is false.
122
+** The href="URL" form is used if g.javascriptHyperlink is false.
123
+** If g.javascriptHyperlink is true then the id="ID" form is used and
124
+** javascript is generated in the footer to cause href values to be
125
+** inserted after the page has loaded. The use of the id="ID" form
126
+** instead of href="URL" is a defense against bots.
119127
**
120128
** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
121129
** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
122
-** g.javascriptHyperlink is set to 1. The g.javascriptHyperlink defaults
123
-** to 0 and only changes to one if the user lacks the Hyperlink (h) property
124
-** and the "auto-hyperlink" setting is enabled.
130
+** g.javascriptHyperlink is set to 1 by login_check_credentials(). Thus
131
+** the g.perm.Hyperlink property will be true even if the user does not
132
+** have the "h" privilege if the "auto-hyperlink" setting is true.
133
+**
134
+** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
135
+** ------------ -------------- ---------------- ---------------------
136
+** 0 0 0 0
137
+** 1 0 1 0
138
+** 0 1 1 1
139
+** 1 1 1 0
140
+**
141
+** So, in other words, tracing input configuration to final actions we have:
142
+**
143
+** User has "h" auto-hyperlink Returned anchor format
144
+** ------------ -------------- ----------------------
145
+** 0 0 (empty string)
146
+** 1 0 <a href="URL">
147
+** 0 1 <a id="ID">
148
+** 1 1 (can't happen)
125149
**
126
-** Filling in the href="URL" using javascript is a defense against bots.
127
-**
128
-** The name of this routine is deliberately kept short so that can be
150
+** The name of these routines are deliberately kept short so that can be
129151
** easily used within @-lines. Example:
130152
**
131153
** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a>
132154
**
133155
** Note %z format. The string returned by this function is always
@@ -150,11 +172,11 @@
150172
va_list ap;
151173
if( !g.perm.Hyperlink ) return fossil_strdup("");
152174
va_start(ap, zFormat);
153175
zUrl = vmprintf(zFormat, ap);
154176
va_end(ap);
155
- if( g.perm.Hyperlink && !g.javascriptHyperlink ){
177
+ if( !g.javascriptHyperlink ){
156178
char *zHUrl;
157179
if( zExtra ){
158180
zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
159181
}else{
160182
zHUrl = mprintf("<a href=\"%h\">", zUrl);
@@ -175,11 +197,11 @@
175197
va_list ap;
176198
if( !g.perm.Hyperlink ) return fossil_strdup("");
177199
va_start(ap, zFormat);
178200
zUrl = vmprintf(zFormat, ap);
179201
va_end(ap);
180
- if( g.perm.Hyperlink && !g.javascriptHyperlink ){
202
+ if( !g.javascriptHyperlink ){
181203
char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl);
182204
fossil_free(zUrl);
183205
return zHUrl;
184206
}
185207
needHrefJs = 1;
@@ -191,11 +213,11 @@
191213
va_list ap;
192214
if( !g.perm.Hyperlink ) return fossil_strdup("");
193215
va_start(ap, zFormat);
194216
zUrl = vmprintf(zFormat, ap);
195217
va_end(ap);
196
- if( g.perm.Hyperlink && !g.javascriptHyperlink ){
218
+ if( !g.javascriptHyperlink ){
197219
char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
198220
fossil_free(zUrl);
199221
return zHUrl;
200222
}
201223
needHrefJs = 1;
@@ -202,23 +224,38 @@
202224
return mprintf("<a data-href='%s' href='%R/honeypot'>",
203225
zUrl);
204226
}
205227
206228
/*
207
-** Generate <form method="post" action=ARG>. The ARG value is inserted
208
-** by javascript.
229
+** Generate <form method="post" action=ARG>. The ARG value is determined
230
+** by the arguments.
231
+**
232
+** As a defense against robots, the action=ARG might instead by data-action=ARG
233
+** and javascript (href.js) added to the page so that the data-action= is
234
+** changed into action= after the page loads. Whether or not this happens
235
+** depends on if the user has the "h" privilege and whether or not the
236
+** auto-hyperlink setting is on. These setings determine the values of
237
+** variables g.perm.Hyperlink and g.javascriptHyperlink.
238
+**
239
+** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
240
+** ------------ -------------- ---------------- ---------------------
241
+** 1: 0 0 0 0
242
+** 2: 1 0 1 0
243
+** 3: 0 1 1 1
244
+** 4: 1 1 1 0
245
+**
246
+** The data-action=ARG form is used for cases 1 and 3. In case 1, the href.js
247
+** javascript is omitted and so the form is effectively disabled.
209248
*/
210249
void form_begin(const char *zOtherArgs, const char *zAction, ...){
211250
char *zLink;
212251
va_list ap;
213252
if( zOtherArgs==0 ) zOtherArgs = "";
214253
va_start(ap, zAction);
215254
zLink = vmprintf(zAction, ap);
216255
va_end(ap);
217
- if( fossil_strcmp(zLink,"/register")==0
218
- || (g.perm.Hyperlink && !g.javascriptHyperlink)
219
- ){
256
+ if( g.perm.Hyperlink ){
220257
@ <form method="POST" action="%z(zLink)" %s(zOtherArgs)>
221258
}else{
222259
needHrefJs = 1;
223260
@ <form method="POST" data-action='%s(zLink)' action='%R/login' \
224261
@ %s(zOtherArgs)>
225262
--- src/style.c
+++ src/style.c
@@ -107,27 +107,49 @@
107 **
108 ** <a href="URL">
109 ** or <a id="ID">
110 **
111 ** The form of the anchor tag is determined by the g.javascriptHyperlink
112 ** variable. The href="URL" form is used if g.javascriptHyperlink is false.
113 ** If g.javascriptHyperlink is true then the
114 ** id="ID" form is used and javascript is generated in the footer to cause
115 ** href values to be inserted after the page has loaded. If
116 ** g.perm.History is false, then the <a id="ID"> form is still
117 ** generated but the javascript is not generated so the links never
118 ** activate.
 
 
 
 
 
 
 
 
119 **
120 ** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
121 ** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
122 ** g.javascriptHyperlink is set to 1. The g.javascriptHyperlink defaults
123 ** to 0 and only changes to one if the user lacks the Hyperlink (h) property
124 ** and the "auto-hyperlink" setting is enabled.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125 **
126 ** Filling in the href="URL" using javascript is a defense against bots.
127 **
128 ** The name of this routine is deliberately kept short so that can be
129 ** easily used within @-lines. Example:
130 **
131 ** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a>
132 **
133 ** Note %z format. The string returned by this function is always
@@ -150,11 +172,11 @@
150 va_list ap;
151 if( !g.perm.Hyperlink ) return fossil_strdup("");
152 va_start(ap, zFormat);
153 zUrl = vmprintf(zFormat, ap);
154 va_end(ap);
155 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
156 char *zHUrl;
157 if( zExtra ){
158 zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
159 }else{
160 zHUrl = mprintf("<a href=\"%h\">", zUrl);
@@ -175,11 +197,11 @@
175 va_list ap;
176 if( !g.perm.Hyperlink ) return fossil_strdup("");
177 va_start(ap, zFormat);
178 zUrl = vmprintf(zFormat, ap);
179 va_end(ap);
180 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
181 char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl);
182 fossil_free(zUrl);
183 return zHUrl;
184 }
185 needHrefJs = 1;
@@ -191,11 +213,11 @@
191 va_list ap;
192 if( !g.perm.Hyperlink ) return fossil_strdup("");
193 va_start(ap, zFormat);
194 zUrl = vmprintf(zFormat, ap);
195 va_end(ap);
196 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
197 char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
198 fossil_free(zUrl);
199 return zHUrl;
200 }
201 needHrefJs = 1;
@@ -202,23 +224,38 @@
202 return mprintf("<a data-href='%s' href='%R/honeypot'>",
203 zUrl);
204 }
205
206 /*
207 ** Generate <form method="post" action=ARG>. The ARG value is inserted
208 ** by javascript.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209 */
210 void form_begin(const char *zOtherArgs, const char *zAction, ...){
211 char *zLink;
212 va_list ap;
213 if( zOtherArgs==0 ) zOtherArgs = "";
214 va_start(ap, zAction);
215 zLink = vmprintf(zAction, ap);
216 va_end(ap);
217 if( fossil_strcmp(zLink,"/register")==0
218 || (g.perm.Hyperlink && !g.javascriptHyperlink)
219 ){
220 @ <form method="POST" action="%z(zLink)" %s(zOtherArgs)>
221 }else{
222 needHrefJs = 1;
223 @ <form method="POST" data-action='%s(zLink)' action='%R/login' \
224 @ %s(zOtherArgs)>
225
--- src/style.c
+++ src/style.c
@@ -107,27 +107,49 @@
107 **
108 ** <a href="URL">
109 ** or <a id="ID">
110 **
111 ** The form of the anchor tag is determined by the g.javascriptHyperlink
112 ** and g.perm.Hyperlink variables.
113 **
114 ** g.perm.Hyperlink g.javascriptHyperlink Returned anchor format
115 ** ---------------- --------------------- ------------------------
116 ** 0 0 (empty string)
117 ** 0 1 (empty string)
118 ** 1 0 <a href="URL">
119 ** 1 1 <a id="ID">
120 **
121 ** No anchor tag is generated if g.perm.Hyperlink is false.
122 ** The href="URL" form is used if g.javascriptHyperlink is false.
123 ** If g.javascriptHyperlink is true then the id="ID" form is used and
124 ** javascript is generated in the footer to cause href values to be
125 ** inserted after the page has loaded. The use of the id="ID" form
126 ** instead of href="URL" is a defense against bots.
127 **
128 ** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
129 ** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
130 ** g.javascriptHyperlink is set to 1 by login_check_credentials(). Thus
131 ** the g.perm.Hyperlink property will be true even if the user does not
132 ** have the "h" privilege if the "auto-hyperlink" setting is true.
133 **
134 ** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
135 ** ------------ -------------- ---------------- ---------------------
136 ** 0 0 0 0
137 ** 1 0 1 0
138 ** 0 1 1 1
139 ** 1 1 1 0
140 **
141 ** So, in other words, tracing input configuration to final actions we have:
142 **
143 ** User has "h" auto-hyperlink Returned anchor format
144 ** ------------ -------------- ----------------------
145 ** 0 0 (empty string)
146 ** 1 0 <a href="URL">
147 ** 0 1 <a id="ID">
148 ** 1 1 (can't happen)
149 **
150 ** The name of these routines are deliberately kept short so that can be
 
 
151 ** easily used within @-lines. Example:
152 **
153 ** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a>
154 **
155 ** Note %z format. The string returned by this function is always
@@ -150,11 +172,11 @@
172 va_list ap;
173 if( !g.perm.Hyperlink ) return fossil_strdup("");
174 va_start(ap, zFormat);
175 zUrl = vmprintf(zFormat, ap);
176 va_end(ap);
177 if( !g.javascriptHyperlink ){
178 char *zHUrl;
179 if( zExtra ){
180 zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
181 }else{
182 zHUrl = mprintf("<a href=\"%h\">", zUrl);
@@ -175,11 +197,11 @@
197 va_list ap;
198 if( !g.perm.Hyperlink ) return fossil_strdup("");
199 va_start(ap, zFormat);
200 zUrl = vmprintf(zFormat, ap);
201 va_end(ap);
202 if( !g.javascriptHyperlink ){
203 char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl);
204 fossil_free(zUrl);
205 return zHUrl;
206 }
207 needHrefJs = 1;
@@ -191,11 +213,11 @@
213 va_list ap;
214 if( !g.perm.Hyperlink ) return fossil_strdup("");
215 va_start(ap, zFormat);
216 zUrl = vmprintf(zFormat, ap);
217 va_end(ap);
218 if( !g.javascriptHyperlink ){
219 char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
220 fossil_free(zUrl);
221 return zHUrl;
222 }
223 needHrefJs = 1;
@@ -202,23 +224,38 @@
224 return mprintf("<a data-href='%s' href='%R/honeypot'>",
225 zUrl);
226 }
227
228 /*
229 ** Generate <form method="post" action=ARG>. The ARG value is determined
230 ** by the arguments.
231 **
232 ** As a defense against robots, the action=ARG might instead by data-action=ARG
233 ** and javascript (href.js) added to the page so that the data-action= is
234 ** changed into action= after the page loads. Whether or not this happens
235 ** depends on if the user has the "h" privilege and whether or not the
236 ** auto-hyperlink setting is on. These setings determine the values of
237 ** variables g.perm.Hyperlink and g.javascriptHyperlink.
238 **
239 ** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink
240 ** ------------ -------------- ---------------- ---------------------
241 ** 1: 0 0 0 0
242 ** 2: 1 0 1 0
243 ** 3: 0 1 1 1
244 ** 4: 1 1 1 0
245 **
246 ** The data-action=ARG form is used for cases 1 and 3. In case 1, the href.js
247 ** javascript is omitted and so the form is effectively disabled.
248 */
249 void form_begin(const char *zOtherArgs, const char *zAction, ...){
250 char *zLink;
251 va_list ap;
252 if( zOtherArgs==0 ) zOtherArgs = "";
253 va_start(ap, zAction);
254 zLink = vmprintf(zAction, ap);
255 va_end(ap);
256 if( g.perm.Hyperlink ){
 
 
257 @ <form method="POST" action="%z(zLink)" %s(zOtherArgs)>
258 }else{
259 needHrefJs = 1;
260 @ <form method="POST" data-action='%s(zLink)' action='%R/login' \
261 @ %s(zOtherArgs)>
262
+6
--- src/sync.c
+++ src/sync.c
@@ -146,10 +146,13 @@
146146
*pSyncFlags |= SYNC_PRIVATE;
147147
}
148148
if( find_option("verbose","v",0)!=0 ){
149149
*pSyncFlags |= SYNC_VERBOSE;
150150
}
151
+ if( find_option("no-http-compression",0,0)!=0 ){
152
+ *pSyncFlags |= SYNC_NOHTTPCOMPRESS;
153
+ }
151154
url_proxy_options();
152155
clone_ssh_find_options();
153156
if( !uvOnly ) db_find_and_open_repository(0, 0);
154157
db_open_config(0, 1);
155158
if( g.argc==2 ){
@@ -206,10 +209,11 @@
206209
**
207210
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
208211
** if required by the remote website
209212
** --from-parent-project Pull content from the parent project
210213
** --ipv4 Use only IPv4, not IPv6
214
+** --no-http-compression Do not compress HTTP traffic
211215
** --once Do not remember URL for subsequent syncs
212216
** --private Pull private branches too
213217
** --project-code CODE Use CODE as the project code
214218
** --proxy PROXY Use the specified HTTP proxy
215219
** -R|--repository REPO Local repository to pull into
@@ -256,10 +260,11 @@
256260
** Options:
257261
**
258262
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
259263
** if required by the remote website
260264
** --ipv4 Use only IPv4, not IPv6
265
+** --no-http-compression Do not compress HTTP traffic
261266
** --once Do not remember URL for subsequent syncs
262267
** --proxy PROXY Use the specified HTTP proxy
263268
** --private Push private branches too
264269
** -R|--repository REPO Local repository to push from
265270
** --ssl-identity FILE Local SSL credentials, if requested by remote
@@ -301,10 +306,11 @@
301306
** Options:
302307
**
303308
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
304309
** if required by the remote website
305310
** --ipv4 Use only IPv4, not IPv6
311
+** --no-http-compression Do not compress HTTP traffic
306312
** --once Do not remember URL for subsequent syncs
307313
** --proxy PROXY Use the specified HTTP proxy
308314
** --private Sync private branches too
309315
** -R|--repository REPO Local repository to sync with
310316
** --ssl-identity FILE Local SSL credentials, if requested by remote
311317
--- src/sync.c
+++ src/sync.c
@@ -146,10 +146,13 @@
146 *pSyncFlags |= SYNC_PRIVATE;
147 }
148 if( find_option("verbose","v",0)!=0 ){
149 *pSyncFlags |= SYNC_VERBOSE;
150 }
 
 
 
151 url_proxy_options();
152 clone_ssh_find_options();
153 if( !uvOnly ) db_find_and_open_repository(0, 0);
154 db_open_config(0, 1);
155 if( g.argc==2 ){
@@ -206,10 +209,11 @@
206 **
207 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
208 ** if required by the remote website
209 ** --from-parent-project Pull content from the parent project
210 ** --ipv4 Use only IPv4, not IPv6
 
211 ** --once Do not remember URL for subsequent syncs
212 ** --private Pull private branches too
213 ** --project-code CODE Use CODE as the project code
214 ** --proxy PROXY Use the specified HTTP proxy
215 ** -R|--repository REPO Local repository to pull into
@@ -256,10 +260,11 @@
256 ** Options:
257 **
258 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
259 ** if required by the remote website
260 ** --ipv4 Use only IPv4, not IPv6
 
261 ** --once Do not remember URL for subsequent syncs
262 ** --proxy PROXY Use the specified HTTP proxy
263 ** --private Push private branches too
264 ** -R|--repository REPO Local repository to push from
265 ** --ssl-identity FILE Local SSL credentials, if requested by remote
@@ -301,10 +306,11 @@
301 ** Options:
302 **
303 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
304 ** if required by the remote website
305 ** --ipv4 Use only IPv4, not IPv6
 
306 ** --once Do not remember URL for subsequent syncs
307 ** --proxy PROXY Use the specified HTTP proxy
308 ** --private Sync private branches too
309 ** -R|--repository REPO Local repository to sync with
310 ** --ssl-identity FILE Local SSL credentials, if requested by remote
311
--- src/sync.c
+++ src/sync.c
@@ -146,10 +146,13 @@
146 *pSyncFlags |= SYNC_PRIVATE;
147 }
148 if( find_option("verbose","v",0)!=0 ){
149 *pSyncFlags |= SYNC_VERBOSE;
150 }
151 if( find_option("no-http-compression",0,0)!=0 ){
152 *pSyncFlags |= SYNC_NOHTTPCOMPRESS;
153 }
154 url_proxy_options();
155 clone_ssh_find_options();
156 if( !uvOnly ) db_find_and_open_repository(0, 0);
157 db_open_config(0, 1);
158 if( g.argc==2 ){
@@ -206,10 +209,11 @@
209 **
210 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
211 ** if required by the remote website
212 ** --from-parent-project Pull content from the parent project
213 ** --ipv4 Use only IPv4, not IPv6
214 ** --no-http-compression Do not compress HTTP traffic
215 ** --once Do not remember URL for subsequent syncs
216 ** --private Pull private branches too
217 ** --project-code CODE Use CODE as the project code
218 ** --proxy PROXY Use the specified HTTP proxy
219 ** -R|--repository REPO Local repository to pull into
@@ -256,10 +260,11 @@
260 ** Options:
261 **
262 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
263 ** if required by the remote website
264 ** --ipv4 Use only IPv4, not IPv6
265 ** --no-http-compression Do not compress HTTP traffic
266 ** --once Do not remember URL for subsequent syncs
267 ** --proxy PROXY Use the specified HTTP proxy
268 ** --private Push private branches too
269 ** -R|--repository REPO Local repository to push from
270 ** --ssl-identity FILE Local SSL credentials, if requested by remote
@@ -301,10 +306,11 @@
306 ** Options:
307 **
308 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
309 ** if required by the remote website
310 ** --ipv4 Use only IPv4, not IPv6
311 ** --no-http-compression Do not compress HTTP traffic
312 ** --once Do not remember URL for subsequent syncs
313 ** --proxy PROXY Use the specified HTTP proxy
314 ** --private Sync private branches too
315 ** -R|--repository REPO Local repository to sync with
316 ** --ssl-identity FILE Local SSL credentials, if requested by remote
317
+14
--- src/tag.c
+++ src/tag.c
@@ -889,5 +889,19 @@
889889
www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
890890
db_finalize(&q);
891891
@ <br />
892892
style_finish_page();
893893
}
894
+
895
+/*
896
+** Returns true if the given blob.rid value has the given tag ID
897
+** applied to it, else false.
898
+*/
899
+int rid_has_tag(int rid, int tagId){
900
+ return db_exists(
901
+ "SELECT tag.tagid FROM tagxref, tag"
902
+ " WHERE tagxref.rid=%d AND tagtype>0 "
903
+ " AND tag.tagid=%d"
904
+ " AND tagxref.tagid=tag.tagid",
905
+ rid, tagId
906
+ );
907
+}
894908
--- src/tag.c
+++ src/tag.c
@@ -889,5 +889,19 @@
889 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
890 db_finalize(&q);
891 @ <br />
892 style_finish_page();
893 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
894
--- src/tag.c
+++ src/tag.c
@@ -889,5 +889,19 @@
889 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
890 db_finalize(&q);
891 @ <br />
892 style_finish_page();
893 }
894
895 /*
896 ** Returns true if the given blob.rid value has the given tag ID
897 ** applied to it, else false.
898 */
899 int rid_has_tag(int rid, int tagId){
900 return db_exists(
901 "SELECT tag.tagid FROM tagxref, tag"
902 " WHERE tagxref.rid=%d AND tagtype>0 "
903 " AND tag.tagid=%d"
904 " AND tagxref.tagid=tag.tagid",
905 rid, tagId
906 );
907 }
908
+3
--- src/tar.c
+++ src/tar.c
@@ -774,10 +774,13 @@
774774
nRid = strlen(zRid);
775775
zInclude = P("in");
776776
if( zInclude ) pInclude = glob_create(zInclude);
777777
zExclude = P("ex");
778778
if( zExclude ) pExclude = glob_create(zExclude);
779
+ if( zInclude==0 && zExclude==0 ){
780
+ etag_check_for_invariant_name(z);
781
+ }
779782
nName = strlen(zName);
780783
if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
781784
/* Special case: Remove the ".tar.gz" suffix. */
782785
nName -= 7;
783786
zName[nName] = 0;
784787
--- src/tar.c
+++ src/tar.c
@@ -774,10 +774,13 @@
774 nRid = strlen(zRid);
775 zInclude = P("in");
776 if( zInclude ) pInclude = glob_create(zInclude);
777 zExclude = P("ex");
778 if( zExclude ) pExclude = glob_create(zExclude);
 
 
 
779 nName = strlen(zName);
780 if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
781 /* Special case: Remove the ".tar.gz" suffix. */
782 nName -= 7;
783 zName[nName] = 0;
784
--- src/tar.c
+++ src/tar.c
@@ -774,10 +774,13 @@
774 nRid = strlen(zRid);
775 zInclude = P("in");
776 if( zInclude ) pInclude = glob_create(zInclude);
777 zExclude = P("ex");
778 if( zExclude ) pExclude = glob_create(zExclude);
779 if( zInclude==0 && zExclude==0 ){
780 etag_check_for_invariant_name(z);
781 }
782 nName = strlen(zName);
783 if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
784 /* Special case: Remove the ".tar.gz" suffix. */
785 nName -= 7;
786 zName[nName] = 0;
787
+27 -51
--- src/th_main.c
+++ src/th_main.c
@@ -46,13 +46,13 @@
4646
4747
/*
4848
** Flags set by functions in this file to keep track of integration state
4949
** information. These flags should not be used outside of this file.
5050
*/
51
-#define TH_STATE_CONFIG ((u32)0x00000020) /* We opened the config. */
52
-#define TH_STATE_REPOSITORY ((u32)0x00000040) /* We opened the repository. */
53
-#define TH_STATE_MASK ((u32)0x00000060) /* All possible state flags. */
51
+#define TH_STATE_CONFIG ((u32)0x00000200) /* We opened the config. */
52
+#define TH_STATE_REPOSITORY ((u32)0x00000400) /* We opened the repository. */
53
+#define TH_STATE_MASK ((u32)0x00000600) /* All possible state flags. */
5454
5555
#ifdef FOSSIL_ENABLE_TH1_HOOKS
5656
/*
5757
** These are the "well-known" TH1 error messages that occur when no hook is
5858
** registered to be called prior to executing a command or processing a web
@@ -361,11 +361,11 @@
361361
static Blob * pThOut = 0;
362362
/*
363363
** Sets the th1-internal output-redirection blob and returns the
364364
** previous value. That blob is used by certain output-generation
365365
** routines to emit its output. It returns the previous value so that
366
-** a routing can temporarily replace the buffer with its own and
366
+** a routine can temporarily replace the buffer with its own and
367367
** restore it when it's done.
368368
*/
369369
Blob * Th_SetOutputBlob(Blob * pOut){
370370
Blob * tmp = pThOut;
371371
pThOut = pOut;
@@ -1749,47 +1749,10 @@
17491749
{ 0, 0 }
17501750
};
17511751
return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
17521752
}
17531753
1754
-#ifdef _WIN32
1755
-# include <windows.h>
1756
-#else
1757
-# include <sys/time.h>
1758
-# include <sys/resource.h>
1759
-#endif
1760
-
1761
-/*
1762
-** Get user and kernel times in microseconds.
1763
-*/
1764
-static void getCpuTimes(sqlite3_uint64 *piUser, sqlite3_uint64 *piKernel){
1765
-#ifdef _WIN32
1766
- FILETIME not_used;
1767
- FILETIME kernel_time;
1768
- FILETIME user_time;
1769
- GetProcessTimes(GetCurrentProcess(), &not_used, &not_used,
1770
- &kernel_time, &user_time);
1771
- if( piUser ){
1772
- *piUser = ((((sqlite3_uint64)user_time.dwHighDateTime)<<32) +
1773
- (sqlite3_uint64)user_time.dwLowDateTime + 5)/10;
1774
- }
1775
- if( piKernel ){
1776
- *piKernel = ((((sqlite3_uint64)kernel_time.dwHighDateTime)<<32) +
1777
- (sqlite3_uint64)kernel_time.dwLowDateTime + 5)/10;
1778
- }
1779
-#else
1780
- struct rusage s;
1781
- getrusage(RUSAGE_SELF, &s);
1782
- if( piUser ){
1783
- *piUser = ((sqlite3_uint64)s.ru_utime.tv_sec)*1000000 + s.ru_utime.tv_usec;
1784
- }
1785
- if( piKernel ){
1786
- *piKernel =
1787
- ((sqlite3_uint64)s.ru_stime.tv_sec)*1000000 + s.ru_stime.tv_usec;
1788
- }
1789
-#endif
1790
-}
17911754
17921755
/*
17931756
** TH1 command: utime
17941757
**
17951758
** Return the number of microseconds of CPU time consumed by the current
@@ -1802,11 +1765,11 @@
18021765
const char **argv,
18031766
int *argl
18041767
){
18051768
sqlite3_uint64 x;
18061769
char zUTime[50];
1807
- getCpuTimes(&x, 0);
1770
+ fossil_cpu_times(&x, 0);
18081771
sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
18091772
Th_SetResult(interp, zUTime, -1);
18101773
return TH_OK;
18111774
}
18121775
@@ -1823,11 +1786,11 @@
18231786
const char **argv,
18241787
int *argl
18251788
){
18261789
sqlite3_uint64 x;
18271790
char zUTime[50];
1828
- getCpuTimes(0, &x);
1791
+ fossil_cpu_times(0, &x);
18291792
sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
18301793
Th_SetResult(interp, zUTime, -1);
18311794
return TH_OK;
18321795
}
18331796
@@ -2834,17 +2797,18 @@
28342797
#define TH_R2B_MASK ((u32)0x0f000)
28352798
#define TH_R2B_NO_VARS ((u32)0x01000) /* Disables eval of $vars and $<vars> */
28362799
#endif
28372800
28382801
/*
2839
-** If pOut is NULL, this works identically to Th_Render(), else it
2840
-** works just like that function but appends any TH1-generated output
2841
-** to the given blob. A bitmask of TH_R2B_xxx and/or TH_INIT_xxx flags
2842
-** may be passed as the 3rd argument, or 0 for default options. Note
2843
-** that this function necessarily calls Th_FossilInit(), which may
2844
-** unset flags used on previous calls unless mFlags is explicitly
2845
-** passed in.
2802
+** If pOut is NULL, this works identically to Th_Render() and sends
2803
+** any TH1-generated output to stdin (in CLI mode) or the CGI buffer
2804
+** (in CGI mode), else it works just like that function but appends
2805
+** any TH1-generated output to the given blob. A bitmask of TH_R2B_xxx
2806
+** and/or TH_INIT_xxx flags may be passed as the 3rd argument, or 0
2807
+** for default options. Note that this function necessarily calls
2808
+** Th_FossilInit(), which may unset flags used on previous calls
2809
+** unless mFlags is explicitly passed in.
28462810
*/
28472811
int Th_RenderToBlob(const char *z, Blob * pOut, u32 mFlags){
28482812
int i = 0;
28492813
int n;
28502814
int rc = TH_OK;
@@ -2917,11 +2881,23 @@
29172881
** This routine processes the template and writes the results to one
29182882
** of stdout, CGI, or an internal blob which was set up via a prior
29192883
** call to Th_SetOutputBlob().
29202884
*/
29212885
int Th_Render(const char *z){
2922
- return Th_RenderToBlob(z, 0, 0);
2886
+ return Th_RenderToBlob(z, pThOut, g.th1Flags)
2887
+ /* Maintenance reminder: on most calls to Th_Render(), e.g. for
2888
+ ** outputing the site skin, pThOut will be 0, which means that
2889
+ ** Th_RenderToBlob() will output directly to the CGI buffer (in
2890
+ ** CGI mode) or stdout (in CLI mode). Recursive calls, however,
2891
+ ** e.g. via the "render" script function binding, need to use the
2892
+ ** pThOut blob in order to avoid out-of-order output if
2893
+ ** Th_SetOutputBlob() has been called. If it has not been called,
2894
+ ** pThOut will be 0, which will redirect the output to CGI/stdout,
2895
+ ** as appropriate. We need to pass on g.th1Flags for the case of
2896
+ ** recursive calls, so that, e.g., TH_INIT_NO_ENCODE does not get
2897
+ ** inadvertently toggled off by a recursive call.
2898
+ */;
29232899
}
29242900
29252901
/*
29262902
** COMMAND: test-th-render
29272903
**
29282904
--- src/th_main.c
+++ src/th_main.c
@@ -46,13 +46,13 @@
46
47 /*
48 ** Flags set by functions in this file to keep track of integration state
49 ** information. These flags should not be used outside of this file.
50 */
51 #define TH_STATE_CONFIG ((u32)0x00000020) /* We opened the config. */
52 #define TH_STATE_REPOSITORY ((u32)0x00000040) /* We opened the repository. */
53 #define TH_STATE_MASK ((u32)0x00000060) /* All possible state flags. */
54
55 #ifdef FOSSIL_ENABLE_TH1_HOOKS
56 /*
57 ** These are the "well-known" TH1 error messages that occur when no hook is
58 ** registered to be called prior to executing a command or processing a web
@@ -361,11 +361,11 @@
361 static Blob * pThOut = 0;
362 /*
363 ** Sets the th1-internal output-redirection blob and returns the
364 ** previous value. That blob is used by certain output-generation
365 ** routines to emit its output. It returns the previous value so that
366 ** a routing can temporarily replace the buffer with its own and
367 ** restore it when it's done.
368 */
369 Blob * Th_SetOutputBlob(Blob * pOut){
370 Blob * tmp = pThOut;
371 pThOut = pOut;
@@ -1749,47 +1749,10 @@
1749 { 0, 0 }
1750 };
1751 return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
1752 }
1753
1754 #ifdef _WIN32
1755 # include <windows.h>
1756 #else
1757 # include <sys/time.h>
1758 # include <sys/resource.h>
1759 #endif
1760
1761 /*
1762 ** Get user and kernel times in microseconds.
1763 */
1764 static void getCpuTimes(sqlite3_uint64 *piUser, sqlite3_uint64 *piKernel){
1765 #ifdef _WIN32
1766 FILETIME not_used;
1767 FILETIME kernel_time;
1768 FILETIME user_time;
1769 GetProcessTimes(GetCurrentProcess(), &not_used, &not_used,
1770 &kernel_time, &user_time);
1771 if( piUser ){
1772 *piUser = ((((sqlite3_uint64)user_time.dwHighDateTime)<<32) +
1773 (sqlite3_uint64)user_time.dwLowDateTime + 5)/10;
1774 }
1775 if( piKernel ){
1776 *piKernel = ((((sqlite3_uint64)kernel_time.dwHighDateTime)<<32) +
1777 (sqlite3_uint64)kernel_time.dwLowDateTime + 5)/10;
1778 }
1779 #else
1780 struct rusage s;
1781 getrusage(RUSAGE_SELF, &s);
1782 if( piUser ){
1783 *piUser = ((sqlite3_uint64)s.ru_utime.tv_sec)*1000000 + s.ru_utime.tv_usec;
1784 }
1785 if( piKernel ){
1786 *piKernel =
1787 ((sqlite3_uint64)s.ru_stime.tv_sec)*1000000 + s.ru_stime.tv_usec;
1788 }
1789 #endif
1790 }
1791
1792 /*
1793 ** TH1 command: utime
1794 **
1795 ** Return the number of microseconds of CPU time consumed by the current
@@ -1802,11 +1765,11 @@
1802 const char **argv,
1803 int *argl
1804 ){
1805 sqlite3_uint64 x;
1806 char zUTime[50];
1807 getCpuTimes(&x, 0);
1808 sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
1809 Th_SetResult(interp, zUTime, -1);
1810 return TH_OK;
1811 }
1812
@@ -1823,11 +1786,11 @@
1823 const char **argv,
1824 int *argl
1825 ){
1826 sqlite3_uint64 x;
1827 char zUTime[50];
1828 getCpuTimes(0, &x);
1829 sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
1830 Th_SetResult(interp, zUTime, -1);
1831 return TH_OK;
1832 }
1833
@@ -2834,17 +2797,18 @@
2834 #define TH_R2B_MASK ((u32)0x0f000)
2835 #define TH_R2B_NO_VARS ((u32)0x01000) /* Disables eval of $vars and $<vars> */
2836 #endif
2837
2838 /*
2839 ** If pOut is NULL, this works identically to Th_Render(), else it
2840 ** works just like that function but appends any TH1-generated output
2841 ** to the given blob. A bitmask of TH_R2B_xxx and/or TH_INIT_xxx flags
2842 ** may be passed as the 3rd argument, or 0 for default options. Note
2843 ** that this function necessarily calls Th_FossilInit(), which may
2844 ** unset flags used on previous calls unless mFlags is explicitly
2845 ** passed in.
 
2846 */
2847 int Th_RenderToBlob(const char *z, Blob * pOut, u32 mFlags){
2848 int i = 0;
2849 int n;
2850 int rc = TH_OK;
@@ -2917,11 +2881,23 @@
2917 ** This routine processes the template and writes the results to one
2918 ** of stdout, CGI, or an internal blob which was set up via a prior
2919 ** call to Th_SetOutputBlob().
2920 */
2921 int Th_Render(const char *z){
2922 return Th_RenderToBlob(z, 0, 0);
 
 
 
 
 
 
 
 
 
 
 
 
2923 }
2924
2925 /*
2926 ** COMMAND: test-th-render
2927 **
2928
--- src/th_main.c
+++ src/th_main.c
@@ -46,13 +46,13 @@
46
47 /*
48 ** Flags set by functions in this file to keep track of integration state
49 ** information. These flags should not be used outside of this file.
50 */
51 #define TH_STATE_CONFIG ((u32)0x00000200) /* We opened the config. */
52 #define TH_STATE_REPOSITORY ((u32)0x00000400) /* We opened the repository. */
53 #define TH_STATE_MASK ((u32)0x00000600) /* All possible state flags. */
54
55 #ifdef FOSSIL_ENABLE_TH1_HOOKS
56 /*
57 ** These are the "well-known" TH1 error messages that occur when no hook is
58 ** registered to be called prior to executing a command or processing a web
@@ -361,11 +361,11 @@
361 static Blob * pThOut = 0;
362 /*
363 ** Sets the th1-internal output-redirection blob and returns the
364 ** previous value. That blob is used by certain output-generation
365 ** routines to emit its output. It returns the previous value so that
366 ** a routine can temporarily replace the buffer with its own and
367 ** restore it when it's done.
368 */
369 Blob * Th_SetOutputBlob(Blob * pOut){
370 Blob * tmp = pThOut;
371 pThOut = pOut;
@@ -1749,47 +1749,10 @@
1749 { 0, 0 }
1750 };
1751 return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
1752 }
1753
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1754
1755 /*
1756 ** TH1 command: utime
1757 **
1758 ** Return the number of microseconds of CPU time consumed by the current
@@ -1802,11 +1765,11 @@
1765 const char **argv,
1766 int *argl
1767 ){
1768 sqlite3_uint64 x;
1769 char zUTime[50];
1770 fossil_cpu_times(&x, 0);
1771 sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
1772 Th_SetResult(interp, zUTime, -1);
1773 return TH_OK;
1774 }
1775
@@ -1823,11 +1786,11 @@
1786 const char **argv,
1787 int *argl
1788 ){
1789 sqlite3_uint64 x;
1790 char zUTime[50];
1791 fossil_cpu_times(0, &x);
1792 sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x);
1793 Th_SetResult(interp, zUTime, -1);
1794 return TH_OK;
1795 }
1796
@@ -2834,17 +2797,18 @@
2797 #define TH_R2B_MASK ((u32)0x0f000)
2798 #define TH_R2B_NO_VARS ((u32)0x01000) /* Disables eval of $vars and $<vars> */
2799 #endif
2800
2801 /*
2802 ** If pOut is NULL, this works identically to Th_Render() and sends
2803 ** any TH1-generated output to stdin (in CLI mode) or the CGI buffer
2804 ** (in CGI mode), else it works just like that function but appends
2805 ** any TH1-generated output to the given blob. A bitmask of TH_R2B_xxx
2806 ** and/or TH_INIT_xxx flags may be passed as the 3rd argument, or 0
2807 ** for default options. Note that this function necessarily calls
2808 ** Th_FossilInit(), which may unset flags used on previous calls
2809 ** unless mFlags is explicitly passed in.
2810 */
2811 int Th_RenderToBlob(const char *z, Blob * pOut, u32 mFlags){
2812 int i = 0;
2813 int n;
2814 int rc = TH_OK;
@@ -2917,11 +2881,23 @@
2881 ** This routine processes the template and writes the results to one
2882 ** of stdout, CGI, or an internal blob which was set up via a prior
2883 ** call to Th_SetOutputBlob().
2884 */
2885 int Th_Render(const char *z){
2886 return Th_RenderToBlob(z, pThOut, g.th1Flags)
2887 /* Maintenance reminder: on most calls to Th_Render(), e.g. for
2888 ** outputing the site skin, pThOut will be 0, which means that
2889 ** Th_RenderToBlob() will output directly to the CGI buffer (in
2890 ** CGI mode) or stdout (in CLI mode). Recursive calls, however,
2891 ** e.g. via the "render" script function binding, need to use the
2892 ** pThOut blob in order to avoid out-of-order output if
2893 ** Th_SetOutputBlob() has been called. If it has not been called,
2894 ** pThOut will be 0, which will redirect the output to CGI/stdout,
2895 ** as appropriate. We need to pass on g.th1Flags for the case of
2896 ** recursive calls, so that, e.g., TH_INIT_NO_ENCODE does not get
2897 ** inadvertently toggled off by a recursive call.
2898 */;
2899 }
2900
2901 /*
2902 ** COMMAND: test-th-render
2903 **
2904
+22 -7
--- src/timeline.c
+++ src/timeline.c
@@ -118,10 +118,11 @@
118118
#define TIMELINE_XMERGE 0x1000000 /* Omit merges from off-graph nodes */
119119
#define TIMELINE_NOTKT 0x2000000 /* Omit extra ticket classes */
120120
#define TIMELINE_FORUMTXT 0x4000000 /* Render all forum messages */
121121
#define TIMELINE_REFS 0x8000000 /* Output intended for References tab */
122122
#define TIMELINE_DELTA 0x10000000 /* Background color shows delta manifests */
123
+#define TIMELINE_NOCOLOR 0x20000000 /* No colors except for highlights */
123124
#endif
124125
125126
/*
126127
** Return a new timelineTable id.
127128
*/
@@ -363,13 +364,15 @@
363364
}else{
364365
zDateLink = mprintf("<a>");
365366
}
366367
@ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td>
367368
@ <td class="timelineGraph">
368
- if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA) ){
369
+ if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
369370
if( tmFlags & TIMELINE_UCOLOR ){
370371
zBgClr = zUser ? user_color(zUser) : 0;
372
+ }else if( tmFlags & TIMELINE_NOCOLOR ){
373
+ zBgClr = 0;
371374
}else if( zType[0]=='c' ){
372375
static Stmt qdelta;
373376
db_static_prepare(&qdelta, "SELECT baseid IS NULL FROM plink"
374377
" WHERE cid=:rid");
375378
db_bind_int(&qdelta, ":rid", rid);
@@ -392,11 +395,11 @@
392395
zBr = db_column_text(&qbranch, 0);
393396
}else{
394397
zBr = "trunk";
395398
}
396399
if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
397
- if( tmFlags & TIMELINE_DELTA ){
400
+ if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
398401
}else if( zBr==0 || strcmp(zBr,"trunk")==0 ){
399402
zBgClr = 0;
400403
}else{
401404
zBgClr = hash_color(zBr);
402405
}
@@ -1544,11 +1547,18 @@
15441547
** a=TIMEORTAG Show events after TIMEORTAG
15451548
** b=TIMEORTAG Show events before TIMEORTAG
15461549
** c=TIMEORTAG Show events that happen "circa" TIMEORTAG
15471550
** cf=FILEHASH Show events around the time of the first use of
15481551
** the file with FILEHASH
1549
-** m=TIMEORTAG Highlight the event at TIMEORTAG
1552
+** m=TIMEORTAG Highlight the event at TIMEORTAG, or the closest available
1553
+** event if TIMEORTAG is not part of the timeline. If
1554
+** the t= or r= is used, the m event is added to the timeline
1555
+** if it isn't there already.
1556
+** sel1=TIMEORTAG Highlight the check-in at TIMEORTAG if it is part of
1557
+** the timeline. Similar to m= except TIMEORTAG must
1558
+** match a check-in that is already in the timeline.
1559
+** sel2=TIMEORTAG Like sel1= but use the secondary highlight.
15501560
** n=COUNT Maximum number of events. "all" for no limit
15511561
** n1=COUNT Same as "n" but doesn't set the display-preference cookie
15521562
** Use "n1=COUNT" for a one-time display change
15531563
** p=CHECKIN Parents and ancestors of CHECKIN
15541564
** bt=PRIOR ... going back to PRIOR
@@ -1572,10 +1582,11 @@
15721582
** advm Use the "Advanced" or "Busy" menu design.
15731583
** ng No Graph.
15741584
** ncp Omit cherrypick merges
15751585
** nd Do not highlight the focus check-in
15761586
** nsm Omit the submenu
1587
+** nc Omit all graph colors other than highlights
15771588
** v Show details of files changed
15781589
** vfx Show complete text of forum messages
15791590
** f=CHECKIN Show family (immediate parents and children) of CHECKIN
15801591
** from=CHECKIN Path from...
15811592
** to=CHECKIN ... to this
@@ -1861,10 +1872,14 @@
18611872
tmFlags |= TIMELINE_UCOLOR;
18621873
}
18631874
if( PB("deltabg") ){
18641875
tmFlags |= TIMELINE_DELTA;
18651876
}
1877
+ if( PB("nc") ){
1878
+ tmFlags &= ~(TIMELINE_DELTA|TIMELINE_BRCOLOR|TIMELINE_UCOLOR);
1879
+ tmFlags |= TIMELINE_NOCOLOR;
1880
+ }
18661881
if( zUses!=0 ){
18671882
int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses);
18681883
if( ufid ){
18691884
zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid);
18701885
db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)");
@@ -2077,11 +2092,11 @@
20772092
nd = db_int(0, "SELECT count(*)-1 FROM ok");
20782093
if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
20792094
if( nd>0 || p_rid==0 ){
20802095
blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
20812096
}
2082
- if( useDividers ) selectedRid = d_rid;
2097
+ if( useDividers && !selectedRid ) selectedRid = d_rid;
20832098
db_multi_exec("DELETE FROM ok");
20842099
}
20852100
if( p_rid ){
20862101
zBackTo = P("bt");
20872102
ridBackTo = zBackTo ? name_to_typed_rid(zBackTo,"ci") : 0;
@@ -2091,11 +2106,11 @@
20912106
if( np>0 || nd==0 ){
20922107
if( nd>0 ) blob_appendf(&desc, " and ");
20932108
blob_appendf(&desc, "%d ancestor%s", np, (1==np)?"":"s");
20942109
db_multi_exec("%s", blob_sql_text(&sql));
20952110
}
2096
- if( useDividers ) selectedRid = p_rid;
2111
+ if( useDividers && !selectedRid ) selectedRid = p_rid;
20972112
}
20982113
20992114
blob_appendf(&desc, " of %z%h</a>",
21002115
href("%R/info?name=%h", zCiName), zCiName);
21012116
if( ridBackTo ){
@@ -2140,11 +2155,11 @@
21402155
f_rid, f_rid
21412156
);
21422157
}
21432158
blob_append_sql(&sql, " AND event.objid IN ok");
21442159
db_multi_exec("%s", blob_sql_text(&sql));
2145
- if( useDividers ) selectedRid = f_rid;
2160
+ if( useDividers && !selectedRid ) selectedRid = f_rid;
21462161
blob_appendf(&desc, "Parents and children of check-in ");
21472162
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
21482163
blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
21492164
tmFlags |= TIMELINE_XMERGE;
21502165
if( advancedMenu ){
@@ -2634,11 +2649,11 @@
26342649
url_render(&url, "advm", "1", "udc", "1"));
26352650
}
26362651
if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
26372652
if( useDividers && zMark && zMark[0] ){
26382653
double r = symbolic_name_to_mtime(zMark, 0);
2639
- if( r>0.0 ) selectedRid = timeline_add_divider(r);
2654
+ if( r>0.0 && !selectedRid ) selectedRid = timeline_add_divider(r);
26402655
}
26412656
blob_zero(&sql);
26422657
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
26432658
if( fossil_islower(desc.aData[0]) ){
26442659
desc.aData[0] = fossil_toupper(desc.aData[0]);
26452660
--- src/timeline.c
+++ src/timeline.c
@@ -118,10 +118,11 @@
118 #define TIMELINE_XMERGE 0x1000000 /* Omit merges from off-graph nodes */
119 #define TIMELINE_NOTKT 0x2000000 /* Omit extra ticket classes */
120 #define TIMELINE_FORUMTXT 0x4000000 /* Render all forum messages */
121 #define TIMELINE_REFS 0x8000000 /* Output intended for References tab */
122 #define TIMELINE_DELTA 0x10000000 /* Background color shows delta manifests */
 
123 #endif
124
125 /*
126 ** Return a new timelineTable id.
127 */
@@ -363,13 +364,15 @@
363 }else{
364 zDateLink = mprintf("<a>");
365 }
366 @ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td>
367 @ <td class="timelineGraph">
368 if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA) ){
369 if( tmFlags & TIMELINE_UCOLOR ){
370 zBgClr = zUser ? user_color(zUser) : 0;
 
 
371 }else if( zType[0]=='c' ){
372 static Stmt qdelta;
373 db_static_prepare(&qdelta, "SELECT baseid IS NULL FROM plink"
374 " WHERE cid=:rid");
375 db_bind_int(&qdelta, ":rid", rid);
@@ -392,11 +395,11 @@
392 zBr = db_column_text(&qbranch, 0);
393 }else{
394 zBr = "trunk";
395 }
396 if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
397 if( tmFlags & TIMELINE_DELTA ){
398 }else if( zBr==0 || strcmp(zBr,"trunk")==0 ){
399 zBgClr = 0;
400 }else{
401 zBgClr = hash_color(zBr);
402 }
@@ -1544,11 +1547,18 @@
1544 ** a=TIMEORTAG Show events after TIMEORTAG
1545 ** b=TIMEORTAG Show events before TIMEORTAG
1546 ** c=TIMEORTAG Show events that happen "circa" TIMEORTAG
1547 ** cf=FILEHASH Show events around the time of the first use of
1548 ** the file with FILEHASH
1549 ** m=TIMEORTAG Highlight the event at TIMEORTAG
 
 
 
 
 
 
 
1550 ** n=COUNT Maximum number of events. "all" for no limit
1551 ** n1=COUNT Same as "n" but doesn't set the display-preference cookie
1552 ** Use "n1=COUNT" for a one-time display change
1553 ** p=CHECKIN Parents and ancestors of CHECKIN
1554 ** bt=PRIOR ... going back to PRIOR
@@ -1572,10 +1582,11 @@
1572 ** advm Use the "Advanced" or "Busy" menu design.
1573 ** ng No Graph.
1574 ** ncp Omit cherrypick merges
1575 ** nd Do not highlight the focus check-in
1576 ** nsm Omit the submenu
 
1577 ** v Show details of files changed
1578 ** vfx Show complete text of forum messages
1579 ** f=CHECKIN Show family (immediate parents and children) of CHECKIN
1580 ** from=CHECKIN Path from...
1581 ** to=CHECKIN ... to this
@@ -1861,10 +1872,14 @@
1861 tmFlags |= TIMELINE_UCOLOR;
1862 }
1863 if( PB("deltabg") ){
1864 tmFlags |= TIMELINE_DELTA;
1865 }
 
 
 
 
1866 if( zUses!=0 ){
1867 int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses);
1868 if( ufid ){
1869 zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid);
1870 db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)");
@@ -2077,11 +2092,11 @@
2077 nd = db_int(0, "SELECT count(*)-1 FROM ok");
2078 if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
2079 if( nd>0 || p_rid==0 ){
2080 blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
2081 }
2082 if( useDividers ) selectedRid = d_rid;
2083 db_multi_exec("DELETE FROM ok");
2084 }
2085 if( p_rid ){
2086 zBackTo = P("bt");
2087 ridBackTo = zBackTo ? name_to_typed_rid(zBackTo,"ci") : 0;
@@ -2091,11 +2106,11 @@
2091 if( np>0 || nd==0 ){
2092 if( nd>0 ) blob_appendf(&desc, " and ");
2093 blob_appendf(&desc, "%d ancestor%s", np, (1==np)?"":"s");
2094 db_multi_exec("%s", blob_sql_text(&sql));
2095 }
2096 if( useDividers ) selectedRid = p_rid;
2097 }
2098
2099 blob_appendf(&desc, " of %z%h</a>",
2100 href("%R/info?name=%h", zCiName), zCiName);
2101 if( ridBackTo ){
@@ -2140,11 +2155,11 @@
2140 f_rid, f_rid
2141 );
2142 }
2143 blob_append_sql(&sql, " AND event.objid IN ok");
2144 db_multi_exec("%s", blob_sql_text(&sql));
2145 if( useDividers ) selectedRid = f_rid;
2146 blob_appendf(&desc, "Parents and children of check-in ");
2147 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
2148 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
2149 tmFlags |= TIMELINE_XMERGE;
2150 if( advancedMenu ){
@@ -2634,11 +2649,11 @@
2634 url_render(&url, "advm", "1", "udc", "1"));
2635 }
2636 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
2637 if( useDividers && zMark && zMark[0] ){
2638 double r = symbolic_name_to_mtime(zMark, 0);
2639 if( r>0.0 ) selectedRid = timeline_add_divider(r);
2640 }
2641 blob_zero(&sql);
2642 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
2643 if( fossil_islower(desc.aData[0]) ){
2644 desc.aData[0] = fossil_toupper(desc.aData[0]);
2645
--- src/timeline.c
+++ src/timeline.c
@@ -118,10 +118,11 @@
118 #define TIMELINE_XMERGE 0x1000000 /* Omit merges from off-graph nodes */
119 #define TIMELINE_NOTKT 0x2000000 /* Omit extra ticket classes */
120 #define TIMELINE_FORUMTXT 0x4000000 /* Render all forum messages */
121 #define TIMELINE_REFS 0x8000000 /* Output intended for References tab */
122 #define TIMELINE_DELTA 0x10000000 /* Background color shows delta manifests */
123 #define TIMELINE_NOCOLOR 0x20000000 /* No colors except for highlights */
124 #endif
125
126 /*
127 ** Return a new timelineTable id.
128 */
@@ -363,13 +364,15 @@
364 }else{
365 zDateLink = mprintf("<a>");
366 }
367 @ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td>
368 @ <td class="timelineGraph">
369 if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
370 if( tmFlags & TIMELINE_UCOLOR ){
371 zBgClr = zUser ? user_color(zUser) : 0;
372 }else if( tmFlags & TIMELINE_NOCOLOR ){
373 zBgClr = 0;
374 }else if( zType[0]=='c' ){
375 static Stmt qdelta;
376 db_static_prepare(&qdelta, "SELECT baseid IS NULL FROM plink"
377 " WHERE cid=:rid");
378 db_bind_int(&qdelta, ":rid", rid);
@@ -392,11 +395,11 @@
395 zBr = db_column_text(&qbranch, 0);
396 }else{
397 zBr = "trunk";
398 }
399 if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
400 if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
401 }else if( zBr==0 || strcmp(zBr,"trunk")==0 ){
402 zBgClr = 0;
403 }else{
404 zBgClr = hash_color(zBr);
405 }
@@ -1544,11 +1547,18 @@
1547 ** a=TIMEORTAG Show events after TIMEORTAG
1548 ** b=TIMEORTAG Show events before TIMEORTAG
1549 ** c=TIMEORTAG Show events that happen "circa" TIMEORTAG
1550 ** cf=FILEHASH Show events around the time of the first use of
1551 ** the file with FILEHASH
1552 ** m=TIMEORTAG Highlight the event at TIMEORTAG, or the closest available
1553 ** event if TIMEORTAG is not part of the timeline. If
1554 ** the t= or r= is used, the m event is added to the timeline
1555 ** if it isn't there already.
1556 ** sel1=TIMEORTAG Highlight the check-in at TIMEORTAG if it is part of
1557 ** the timeline. Similar to m= except TIMEORTAG must
1558 ** match a check-in that is already in the timeline.
1559 ** sel2=TIMEORTAG Like sel1= but use the secondary highlight.
1560 ** n=COUNT Maximum number of events. "all" for no limit
1561 ** n1=COUNT Same as "n" but doesn't set the display-preference cookie
1562 ** Use "n1=COUNT" for a one-time display change
1563 ** p=CHECKIN Parents and ancestors of CHECKIN
1564 ** bt=PRIOR ... going back to PRIOR
@@ -1572,10 +1582,11 @@
1582 ** advm Use the "Advanced" or "Busy" menu design.
1583 ** ng No Graph.
1584 ** ncp Omit cherrypick merges
1585 ** nd Do not highlight the focus check-in
1586 ** nsm Omit the submenu
1587 ** nc Omit all graph colors other than highlights
1588 ** v Show details of files changed
1589 ** vfx Show complete text of forum messages
1590 ** f=CHECKIN Show family (immediate parents and children) of CHECKIN
1591 ** from=CHECKIN Path from...
1592 ** to=CHECKIN ... to this
@@ -1861,10 +1872,14 @@
1872 tmFlags |= TIMELINE_UCOLOR;
1873 }
1874 if( PB("deltabg") ){
1875 tmFlags |= TIMELINE_DELTA;
1876 }
1877 if( PB("nc") ){
1878 tmFlags &= ~(TIMELINE_DELTA|TIMELINE_BRCOLOR|TIMELINE_UCOLOR);
1879 tmFlags |= TIMELINE_NOCOLOR;
1880 }
1881 if( zUses!=0 ){
1882 int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses);
1883 if( ufid ){
1884 zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid);
1885 db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)");
@@ -2077,11 +2092,11 @@
2092 nd = db_int(0, "SELECT count(*)-1 FROM ok");
2093 if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
2094 if( nd>0 || p_rid==0 ){
2095 blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
2096 }
2097 if( useDividers && !selectedRid ) selectedRid = d_rid;
2098 db_multi_exec("DELETE FROM ok");
2099 }
2100 if( p_rid ){
2101 zBackTo = P("bt");
2102 ridBackTo = zBackTo ? name_to_typed_rid(zBackTo,"ci") : 0;
@@ -2091,11 +2106,11 @@
2106 if( np>0 || nd==0 ){
2107 if( nd>0 ) blob_appendf(&desc, " and ");
2108 blob_appendf(&desc, "%d ancestor%s", np, (1==np)?"":"s");
2109 db_multi_exec("%s", blob_sql_text(&sql));
2110 }
2111 if( useDividers && !selectedRid ) selectedRid = p_rid;
2112 }
2113
2114 blob_appendf(&desc, " of %z%h</a>",
2115 href("%R/info?name=%h", zCiName), zCiName);
2116 if( ridBackTo ){
@@ -2140,11 +2155,11 @@
2155 f_rid, f_rid
2156 );
2157 }
2158 blob_append_sql(&sql, " AND event.objid IN ok");
2159 db_multi_exec("%s", blob_sql_text(&sql));
2160 if( useDividers && !selectedRid ) selectedRid = f_rid;
2161 blob_appendf(&desc, "Parents and children of check-in ");
2162 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
2163 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
2164 tmFlags |= TIMELINE_XMERGE;
2165 if( advancedMenu ){
@@ -2634,11 +2649,11 @@
2649 url_render(&url, "advm", "1", "udc", "1"));
2650 }
2651 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
2652 if( useDividers && zMark && zMark[0] ){
2653 double r = symbolic_name_to_mtime(zMark, 0);
2654 if( r>0.0 && !selectedRid ) selectedRid = timeline_add_divider(r);
2655 }
2656 blob_zero(&sql);
2657 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
2658 if( fossil_islower(desc.aData[0]) ){
2659 desc.aData[0] = fossil_toupper(desc.aData[0]);
2660
+7 -1
--- src/tkt.c
+++ src/tkt.c
@@ -1636,12 +1636,18 @@
16361636
** Usage: /tktsrch?s=PATTERN
16371637
**
16381638
** Full-text search of all current tickets
16391639
*/
16401640
void tkt_srchpage(void){
1641
+ char *defaultReport;
16411642
login_check_credentials();
16421643
style_set_current_feature("tkt");
16431644
style_header("Ticket Search");
16441645
ticket_standard_submenu(T_ALL_BUT(T_SRCH));
1645
- search_screen(SRCH_TKT, 0);
1646
+ if( !search_screen(SRCH_TKT, 0) ){
1647
+ defaultReport = db_get("ticket-default-report", 0);
1648
+ if( defaultReport ){
1649
+ rptview_page_content(defaultReport, 0, 0);
1650
+ }
1651
+ }
16461652
style_finish_page();
16471653
}
16481654
--- src/tkt.c
+++ src/tkt.c
@@ -1636,12 +1636,18 @@
1636 ** Usage: /tktsrch?s=PATTERN
1637 **
1638 ** Full-text search of all current tickets
1639 */
1640 void tkt_srchpage(void){
 
1641 login_check_credentials();
1642 style_set_current_feature("tkt");
1643 style_header("Ticket Search");
1644 ticket_standard_submenu(T_ALL_BUT(T_SRCH));
1645 search_screen(SRCH_TKT, 0);
 
 
 
 
 
1646 style_finish_page();
1647 }
1648
--- src/tkt.c
+++ src/tkt.c
@@ -1636,12 +1636,18 @@
1636 ** Usage: /tktsrch?s=PATTERN
1637 **
1638 ** Full-text search of all current tickets
1639 */
1640 void tkt_srchpage(void){
1641 char *defaultReport;
1642 login_check_credentials();
1643 style_set_current_feature("tkt");
1644 style_header("Ticket Search");
1645 ticket_standard_submenu(T_ALL_BUT(T_SRCH));
1646 if( !search_screen(SRCH_TKT, 0) ){
1647 defaultReport = db_get("ticket-default-report", 0);
1648 if( defaultReport ){
1649 rptview_page_content(defaultReport, 0, 0);
1650 }
1651 }
1652 style_finish_page();
1653 }
1654
+2 -2
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -136,20 +136,20 @@
136136
}
137137
style_set_current_feature("tktsetup");
138138
style_header("Edit %s", zTitle);
139139
if( P("clear")!=0 ){
140140
login_verify_csrf_secret();
141
- db_unset(zDbField, 0);
141
+ db_unset(zDbField/*works-like:"x"*/, 0);
142142
if( xRebuild ) xRebuild();
143143
cgi_redirect("tktsetup");
144144
}else if( isSubmit ){
145145
char *zErr = 0;
146146
login_verify_csrf_secret();
147147
if( xText && (zErr = xText(z))!=0 ){
148148
@ <p class="tktsetupError">ERROR: %h(zErr)</p>
149149
}else{
150
- db_set(zDbField, z, 0);
150
+ db_set(zDbField/*works-like:"x"*/, z, 0);
151151
if( xRebuild ) xRebuild();
152152
cgi_redirect("tktsetup");
153153
}
154154
}
155155
@ <form action="%R/%s(g.zPath)" method="post"><div>
156156
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -136,20 +136,20 @@
136 }
137 style_set_current_feature("tktsetup");
138 style_header("Edit %s", zTitle);
139 if( P("clear")!=0 ){
140 login_verify_csrf_secret();
141 db_unset(zDbField, 0);
142 if( xRebuild ) xRebuild();
143 cgi_redirect("tktsetup");
144 }else if( isSubmit ){
145 char *zErr = 0;
146 login_verify_csrf_secret();
147 if( xText && (zErr = xText(z))!=0 ){
148 @ <p class="tktsetupError">ERROR: %h(zErr)</p>
149 }else{
150 db_set(zDbField, z, 0);
151 if( xRebuild ) xRebuild();
152 cgi_redirect("tktsetup");
153 }
154 }
155 @ <form action="%R/%s(g.zPath)" method="post"><div>
156
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -136,20 +136,20 @@
136 }
137 style_set_current_feature("tktsetup");
138 style_header("Edit %s", zTitle);
139 if( P("clear")!=0 ){
140 login_verify_csrf_secret();
141 db_unset(zDbField/*works-like:"x"*/, 0);
142 if( xRebuild ) xRebuild();
143 cgi_redirect("tktsetup");
144 }else if( isSubmit ){
145 char *zErr = 0;
146 login_verify_csrf_secret();
147 if( xText && (zErr = xText(z))!=0 ){
148 @ <p class="tktsetupError">ERROR: %h(zErr)</p>
149 }else{
150 db_set(zDbField/*works-like:"x"*/, z, 0);
151 if( xRebuild ) xRebuild();
152 cgi_redirect("tktsetup");
153 }
154 }
155 @ <form action="%R/%s(g.zPath)" method="post"><div>
156
--- src/unversioned.c
+++ src/unversioned.c
@@ -62,11 +62,14 @@
6262
** If debugFlag is set, force the value to be recomputed and write
6363
** the text of the hashed string to stdout.
6464
*/
6565
const char *unversioned_content_hash(int debugFlag){
6666
const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0);
67
- if( zHash==0 ){
67
+ if( zHash ) return zHash;
68
+ if( !db_table_exists("repository","unversioned") ){
69
+ return "da39a3ee5e6b4b0d3255bfef95601890afd80709";
70
+ }else{
6871
Stmt q;
6972
db_prepare(&q,
7073
"SELECT printf('%%s %%s %%s\n',name,datetime(mtime,'unixepoch'),hash)"
7174
" FROM unversioned"
7275
" WHERE hash IS NOT NULL"
7376
--- src/unversioned.c
+++ src/unversioned.c
@@ -62,11 +62,14 @@
62 ** If debugFlag is set, force the value to be recomputed and write
63 ** the text of the hashed string to stdout.
64 */
65 const char *unversioned_content_hash(int debugFlag){
66 const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0);
67 if( zHash==0 ){
 
 
 
68 Stmt q;
69 db_prepare(&q,
70 "SELECT printf('%%s %%s %%s\n',name,datetime(mtime,'unixepoch'),hash)"
71 " FROM unversioned"
72 " WHERE hash IS NOT NULL"
73
--- src/unversioned.c
+++ src/unversioned.c
@@ -62,11 +62,14 @@
62 ** If debugFlag is set, force the value to be recomputed and write
63 ** the text of the hashed string to stdout.
64 */
65 const char *unversioned_content_hash(int debugFlag){
66 const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0);
67 if( zHash ) return zHash;
68 if( !db_table_exists("repository","unversioned") ){
69 return "da39a3ee5e6b4b0d3255bfef95601890afd80709";
70 }else{
71 Stmt q;
72 db_prepare(&q,
73 "SELECT printf('%%s %%s %%s\n',name,datetime(mtime,'unixepoch'),hash)"
74 " FROM unversioned"
75 " WHERE hash IS NOT NULL"
76
+20 -17
--- src/update.c
+++ src/update.c
@@ -91,26 +91,27 @@
9191
**
9292
** The -v or --verbose option prints status information about
9393
** unchanged files in addition to those file that actually do change.
9494
**
9595
** Options:
96
-** --case-sensitive BOOL Override case-sensitive setting
97
-** --debug Print debug information on stdout
98
-** --latest Acceptable in place of VERSION, update to
99
-** latest version
100
-** --force-missing Force update if missing content after sync
101
-** -n|--dry-run If given, display instead of run actions
102
-** -v|--verbose Print status information about all files
103
-** -W|--width WIDTH Width of lines (default is to auto-detect).
104
-** Must be more than 20 or 0 (= no limit,
105
-** resulting in a single line per entry).
106
-** --setmtime Set timestamps of all files to match their
107
-** SCM-side times (the timestamp of the last
108
-** checkin which modified them).
109
-** -K|--keep-merge-files On merge conflict, retain the temporary files
110
-** used for merging, named *-baseline, *-original,
111
-** and *-merge.
96
+** --case-sensitive BOOL Override case-sensitive setting
97
+** --debug Print debug information on stdout
98
+** -n|--dry-run If given, display instead of run actions
99
+** --force-missing Force update if missing content after sync
100
+** -K|--keep-merge-files On merge conflict, retain the temporary files
101
+** used for merging, named *-baseline, *-original,
102
+** and *-merge.
103
+** --latest Acceptable in place of VERSION, update to
104
+** latest version
105
+** --nosync Do not auto-sync prior to update
106
+** --setmtime Set timestamps of all files to match their
107
+** SCM-side times (the timestamp of the last
108
+** checkin which modified them).
109
+** -v|--verbose Print status information about all files
110
+** -W|--width WIDTH Width of lines (default is to auto-detect).
111
+** Must be more than 20 or 0 (= no limit,
112
+** resulting in a single line per entry).
112113
**
113114
** See also: [[revert]]
114115
*/
115116
void update_cmd(void){
116117
int vid; /* Current version */
@@ -127,10 +128,11 @@
127128
int *aChng; /* Array of file renames */
128129
int i; /* Loop counter */
129130
int nConflict = 0; /* Number of merge conflicts */
130131
int nOverwrite = 0; /* Number of unmanaged files overwritten */
131132
int nUpdate = 0; /* Number of changes of any kind */
133
+ int bNosync = 0; /* --nosync. Omit the auto-sync */
132134
int width; /* Width of printed comment lines */
133135
Stmt mtimeXfer; /* Statement to transfer mtimes */
134136
const char *zWidth; /* Width option string value */
135137
136138
if( !internalUpdate ){
@@ -154,18 +156,19 @@
154156
verboseFlag = find_option("verbose","v",0)!=0;
155157
forceMissingFlag = find_option("force-missing",0,0)!=0;
156158
debugFlag = find_option("debug",0,0)!=0;
157159
setmtimeFlag = find_option("setmtime",0,0)!=0;
158160
keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
161
+ bNosync = find_option("nosync",0,0)!=0;
159162
160163
/* We should be done with options.. */
161164
verify_all_options();
162165
163166
db_must_be_within_tree();
164167
vid = db_lget_int("checkout", 0);
165168
user_select();
166
- if( !dryRunFlag && !internalUpdate ){
169
+ if( !dryRunFlag && !internalUpdate && !bNosync ){
167170
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
168171
db_get_int("autosync-tries", 1), 1) ){
169172
fossil_fatal("update abandoned due to sync failure");
170173
}
171174
}
172175
--- src/update.c
+++ src/update.c
@@ -91,26 +91,27 @@
91 **
92 ** The -v or --verbose option prints status information about
93 ** unchanged files in addition to those file that actually do change.
94 **
95 ** Options:
96 ** --case-sensitive BOOL Override case-sensitive setting
97 ** --debug Print debug information on stdout
98 ** --latest Acceptable in place of VERSION, update to
99 ** latest version
100 ** --force-missing Force update if missing content after sync
101 ** -n|--dry-run If given, display instead of run actions
102 ** -v|--verbose Print status information about all files
103 ** -W|--width WIDTH Width of lines (default is to auto-detect).
104 ** Must be more than 20 or 0 (= no limit,
105 ** resulting in a single line per entry).
106 ** --setmtime Set timestamps of all files to match their
107 ** SCM-side times (the timestamp of the last
108 ** checkin which modified them).
109 ** -K|--keep-merge-files On merge conflict, retain the temporary files
110 ** used for merging, named *-baseline, *-original,
111 ** and *-merge.
 
112 **
113 ** See also: [[revert]]
114 */
115 void update_cmd(void){
116 int vid; /* Current version */
@@ -127,10 +128,11 @@
127 int *aChng; /* Array of file renames */
128 int i; /* Loop counter */
129 int nConflict = 0; /* Number of merge conflicts */
130 int nOverwrite = 0; /* Number of unmanaged files overwritten */
131 int nUpdate = 0; /* Number of changes of any kind */
 
132 int width; /* Width of printed comment lines */
133 Stmt mtimeXfer; /* Statement to transfer mtimes */
134 const char *zWidth; /* Width option string value */
135
136 if( !internalUpdate ){
@@ -154,18 +156,19 @@
154 verboseFlag = find_option("verbose","v",0)!=0;
155 forceMissingFlag = find_option("force-missing",0,0)!=0;
156 debugFlag = find_option("debug",0,0)!=0;
157 setmtimeFlag = find_option("setmtime",0,0)!=0;
158 keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
 
159
160 /* We should be done with options.. */
161 verify_all_options();
162
163 db_must_be_within_tree();
164 vid = db_lget_int("checkout", 0);
165 user_select();
166 if( !dryRunFlag && !internalUpdate ){
167 if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
168 db_get_int("autosync-tries", 1), 1) ){
169 fossil_fatal("update abandoned due to sync failure");
170 }
171 }
172
--- src/update.c
+++ src/update.c
@@ -91,26 +91,27 @@
91 **
92 ** The -v or --verbose option prints status information about
93 ** unchanged files in addition to those file that actually do change.
94 **
95 ** Options:
96 ** --case-sensitive BOOL Override case-sensitive setting
97 ** --debug Print debug information on stdout
98 ** -n|--dry-run If given, display instead of run actions
99 ** --force-missing Force update if missing content after sync
100 ** -K|--keep-merge-files On merge conflict, retain the temporary files
101 ** used for merging, named *-baseline, *-original,
102 ** and *-merge.
103 ** --latest Acceptable in place of VERSION, update to
104 ** latest version
105 ** --nosync Do not auto-sync prior to update
106 ** --setmtime Set timestamps of all files to match their
107 ** SCM-side times (the timestamp of the last
108 ** checkin which modified them).
109 ** -v|--verbose Print status information about all files
110 ** -W|--width WIDTH Width of lines (default is to auto-detect).
111 ** Must be more than 20 or 0 (= no limit,
112 ** resulting in a single line per entry).
113 **
114 ** See also: [[revert]]
115 */
116 void update_cmd(void){
117 int vid; /* Current version */
@@ -127,10 +128,11 @@
128 int *aChng; /* Array of file renames */
129 int i; /* Loop counter */
130 int nConflict = 0; /* Number of merge conflicts */
131 int nOverwrite = 0; /* Number of unmanaged files overwritten */
132 int nUpdate = 0; /* Number of changes of any kind */
133 int bNosync = 0; /* --nosync. Omit the auto-sync */
134 int width; /* Width of printed comment lines */
135 Stmt mtimeXfer; /* Statement to transfer mtimes */
136 const char *zWidth; /* Width option string value */
137
138 if( !internalUpdate ){
@@ -154,18 +156,19 @@
156 verboseFlag = find_option("verbose","v",0)!=0;
157 forceMissingFlag = find_option("force-missing",0,0)!=0;
158 debugFlag = find_option("debug",0,0)!=0;
159 setmtimeFlag = find_option("setmtime",0,0)!=0;
160 keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
161 bNosync = find_option("nosync",0,0)!=0;
162
163 /* We should be done with options.. */
164 verify_all_options();
165
166 db_must_be_within_tree();
167 vid = db_lget_int("checkout", 0);
168 user_select();
169 if( !dryRunFlag && !internalUpdate && !bNosync ){
170 if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
171 db_get_int("autosync-tries", 1), 1) ){
172 fossil_fatal("update abandoned due to sync failure");
173 }
174 }
175
-9
--- src/user.c
+++ src/user.c
@@ -112,19 +112,10 @@
112112
assert( nPwdBuffer>0 );
113113
fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
114114
}
115115
#endif
116116
117
-#if defined(_WIN32) || defined(WIN32)
118
-# include <io.h>
119
-# include <fcntl.h>
120
-# undef popen
121
-# define popen _popen
122
-# undef pclose
123
-# define pclose _pclose
124
-#endif
125
-
126117
/*
127118
** Scramble substitution matrix:
128119
*/
129120
static char aSubst[256];
130121
131122
--- src/user.c
+++ src/user.c
@@ -112,19 +112,10 @@
112 assert( nPwdBuffer>0 );
113 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
114 }
115 #endif
116
117 #if defined(_WIN32) || defined(WIN32)
118 # include <io.h>
119 # include <fcntl.h>
120 # undef popen
121 # define popen _popen
122 # undef pclose
123 # define pclose _pclose
124 #endif
125
126 /*
127 ** Scramble substitution matrix:
128 */
129 static char aSubst[256];
130
131
--- src/user.c
+++ src/user.c
@@ -112,19 +112,10 @@
112 assert( nPwdBuffer>0 );
113 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
114 }
115 #endif
116
 
 
 
 
 
 
 
 
 
117 /*
118 ** Scramble substitution matrix:
119 */
120 static char aSubst[256];
121
122
+30 -14
--- src/util.c
+++ src/util.c
@@ -36,11 +36,10 @@
3636
# include <unistd.h>
3737
# include <fcntl.h>
3838
# include <errno.h>
3939
#endif
4040
41
-
4241
/*
4342
** Exit. Take care to close the database first.
4443
*/
4544
NORETURN void fossil_exit(int rc){
4645
db_close(1);
@@ -164,21 +163,29 @@
164163
}
165164
return zStart;
166165
}
167166
168167
/*
169
-** If this local variable is set, fossil_assert_safe_command_string()
170
-** returns false on an unsafe command-string rather than abort. Set
171
-** this variable for testing.
168
+** This local variable determines the behavior of
169
+** fossil_assert_safe_command_string():
170
+**
171
+** 0 (default) fossil_panic() on an unsafe command string
172
+**
173
+** 1 Print an error but continue process. Used for
174
+** testing of fossil_assert_safe_command_string().
175
+**
176
+** 2 No-op. Used to allow any arbitrary command string
177
+** through fossil_system(), such as when invoking
178
+** COMMAND in "fossil bisect run COMMAND".
172179
*/
173180
static int safeCmdStrTest = 0;
174181
175182
/*
176183
** Check the input string to ensure that it is safe to pass into system().
177184
** A string is unsafe for system() on unix if it contains any of the following:
178185
**
179
-** * Any occurrance of '$' or '`' except after \
186
+** * Any occurrance of '$' or '`' except single-quoted or after \
180187
** * Any of the following characters, unquoted: ;|& or \n except
181188
** these characters are allowed as the very last character in the
182189
** string.
183190
** * Unbalanced single or double quotes
184191
**
@@ -242,39 +249,34 @@
242249
case '&':
243250
case '\n': {
244251
if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1;
245252
break;
246253
}
247
- case '\\': {
248
- if( z[i+1]=='"' ){ i++; }
249
- break;
250
- }
251254
case '"': {
252255
if( inQuote==c ){
253256
inQuote = 0;
254257
}else{
255258
inQuote = c;
256259
}
257260
break;
258261
}
259262
case '^': {
260
- if( z[i+1]=='"' ){
261
- unsafe = i+2;
262
- }else if( z[i+1]!=0 ){
263
+ if( !inQuote && z[i+1]!=0 ){
263264
i++;
264265
}
265266
break;
266267
}
267268
}
268269
}
269270
if( inQuote ) unsafe = i;
270271
#endif
271
- if( unsafe ){
272
+ if( unsafe && safeCmdStrTest<2 ){
272273
char *zMsg = mprintf("Unsafe command string: %s\n%*shere ----^",
273274
z, unsafe+13, "");
274275
if( safeCmdStrTest ){
275276
fossil_print("%z\n", zMsg);
277
+ fossil_free(zMsg);
276278
}else{
277279
fossil_panic("%s", zMsg);
278280
}
279281
}
280282
}
@@ -315,10 +317,22 @@
315317
rc = system(zOrigCmd);
316318
fossil_limit_memory(1);
317319
#endif
318320
return rc;
319321
}
322
+
323
+/*
324
+** Like "fossil_system()" but does not check the command-string for
325
+** potential security problems.
326
+*/
327
+int fossil_unsafe_system(const char *zOrigCmd){
328
+ int rc;
329
+ safeCmdStrTest = 2;
330
+ rc = fossil_system(zOrigCmd);
331
+ safeCmdStrTest = 0;
332
+ return rc;
333
+}
320334
321335
/*
322336
** COMMAND: test-fossil-system
323337
**
324338
** Read lines of input and send them to fossil_system() for evaluation.
@@ -328,19 +342,21 @@
328342
void test_fossil_system_cmd(void){
329343
char zLine[10000];
330344
safeCmdStrTest = 1;
331345
while(1){
332346
size_t n;
347
+ int rc;
333348
printf("system-test> ");
334349
fflush(stdout);
335350
if( !fgets(zLine, sizeof(zLine), stdin) ) break;
336351
n = strlen(zLine);
337352
while( n>0 && fossil_isspace(zLine[n-1]) ) n--;
338353
zLine[n] = 0;
339354
printf("cmd: [%s]\n", zLine);
340355
fflush(stdout);
341
- fossil_system(zLine);
356
+ rc = fossil_system(zLine);
357
+ printf("result: %d\n", rc);
342358
}
343359
}
344360
345361
/*
346362
** Like strcmp() except that it accepts NULL pointers. NULL sorts before
347363
--- src/util.c
+++ src/util.c
@@ -36,11 +36,10 @@
36 # include <unistd.h>
37 # include <fcntl.h>
38 # include <errno.h>
39 #endif
40
41
42 /*
43 ** Exit. Take care to close the database first.
44 */
45 NORETURN void fossil_exit(int rc){
46 db_close(1);
@@ -164,21 +163,29 @@
164 }
165 return zStart;
166 }
167
168 /*
169 ** If this local variable is set, fossil_assert_safe_command_string()
170 ** returns false on an unsafe command-string rather than abort. Set
171 ** this variable for testing.
 
 
 
 
 
 
 
 
172 */
173 static int safeCmdStrTest = 0;
174
175 /*
176 ** Check the input string to ensure that it is safe to pass into system().
177 ** A string is unsafe for system() on unix if it contains any of the following:
178 **
179 ** * Any occurrance of '$' or '`' except after \
180 ** * Any of the following characters, unquoted: ;|& or \n except
181 ** these characters are allowed as the very last character in the
182 ** string.
183 ** * Unbalanced single or double quotes
184 **
@@ -242,39 +249,34 @@
242 case '&':
243 case '\n': {
244 if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1;
245 break;
246 }
247 case '\\': {
248 if( z[i+1]=='"' ){ i++; }
249 break;
250 }
251 case '"': {
252 if( inQuote==c ){
253 inQuote = 0;
254 }else{
255 inQuote = c;
256 }
257 break;
258 }
259 case '^': {
260 if( z[i+1]=='"' ){
261 unsafe = i+2;
262 }else if( z[i+1]!=0 ){
263 i++;
264 }
265 break;
266 }
267 }
268 }
269 if( inQuote ) unsafe = i;
270 #endif
271 if( unsafe ){
272 char *zMsg = mprintf("Unsafe command string: %s\n%*shere ----^",
273 z, unsafe+13, "");
274 if( safeCmdStrTest ){
275 fossil_print("%z\n", zMsg);
 
276 }else{
277 fossil_panic("%s", zMsg);
278 }
279 }
280 }
@@ -315,10 +317,22 @@
315 rc = system(zOrigCmd);
316 fossil_limit_memory(1);
317 #endif
318 return rc;
319 }
 
 
 
 
 
 
 
 
 
 
 
 
320
321 /*
322 ** COMMAND: test-fossil-system
323 **
324 ** Read lines of input and send them to fossil_system() for evaluation.
@@ -328,19 +342,21 @@
328 void test_fossil_system_cmd(void){
329 char zLine[10000];
330 safeCmdStrTest = 1;
331 while(1){
332 size_t n;
 
333 printf("system-test> ");
334 fflush(stdout);
335 if( !fgets(zLine, sizeof(zLine), stdin) ) break;
336 n = strlen(zLine);
337 while( n>0 && fossil_isspace(zLine[n-1]) ) n--;
338 zLine[n] = 0;
339 printf("cmd: [%s]\n", zLine);
340 fflush(stdout);
341 fossil_system(zLine);
 
342 }
343 }
344
345 /*
346 ** Like strcmp() except that it accepts NULL pointers. NULL sorts before
347
--- src/util.c
+++ src/util.c
@@ -36,11 +36,10 @@
36 # include <unistd.h>
37 # include <fcntl.h>
38 # include <errno.h>
39 #endif
40
 
41 /*
42 ** Exit. Take care to close the database first.
43 */
44 NORETURN void fossil_exit(int rc){
45 db_close(1);
@@ -164,21 +163,29 @@
163 }
164 return zStart;
165 }
166
167 /*
168 ** This local variable determines the behavior of
169 ** fossil_assert_safe_command_string():
170 **
171 ** 0 (default) fossil_panic() on an unsafe command string
172 **
173 ** 1 Print an error but continue process. Used for
174 ** testing of fossil_assert_safe_command_string().
175 **
176 ** 2 No-op. Used to allow any arbitrary command string
177 ** through fossil_system(), such as when invoking
178 ** COMMAND in "fossil bisect run COMMAND".
179 */
180 static int safeCmdStrTest = 0;
181
182 /*
183 ** Check the input string to ensure that it is safe to pass into system().
184 ** A string is unsafe for system() on unix if it contains any of the following:
185 **
186 ** * Any occurrance of '$' or '`' except single-quoted or after \
187 ** * Any of the following characters, unquoted: ;|& or \n except
188 ** these characters are allowed as the very last character in the
189 ** string.
190 ** * Unbalanced single or double quotes
191 **
@@ -242,39 +249,34 @@
249 case '&':
250 case '\n': {
251 if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1;
252 break;
253 }
 
 
 
 
254 case '"': {
255 if( inQuote==c ){
256 inQuote = 0;
257 }else{
258 inQuote = c;
259 }
260 break;
261 }
262 case '^': {
263 if( !inQuote && z[i+1]!=0 ){
 
 
264 i++;
265 }
266 break;
267 }
268 }
269 }
270 if( inQuote ) unsafe = i;
271 #endif
272 if( unsafe && safeCmdStrTest<2 ){
273 char *zMsg = mprintf("Unsafe command string: %s\n%*shere ----^",
274 z, unsafe+13, "");
275 if( safeCmdStrTest ){
276 fossil_print("%z\n", zMsg);
277 fossil_free(zMsg);
278 }else{
279 fossil_panic("%s", zMsg);
280 }
281 }
282 }
@@ -315,10 +317,22 @@
317 rc = system(zOrigCmd);
318 fossil_limit_memory(1);
319 #endif
320 return rc;
321 }
322
323 /*
324 ** Like "fossil_system()" but does not check the command-string for
325 ** potential security problems.
326 */
327 int fossil_unsafe_system(const char *zOrigCmd){
328 int rc;
329 safeCmdStrTest = 2;
330 rc = fossil_system(zOrigCmd);
331 safeCmdStrTest = 0;
332 return rc;
333 }
334
335 /*
336 ** COMMAND: test-fossil-system
337 **
338 ** Read lines of input and send them to fossil_system() for evaluation.
@@ -328,19 +342,21 @@
342 void test_fossil_system_cmd(void){
343 char zLine[10000];
344 safeCmdStrTest = 1;
345 while(1){
346 size_t n;
347 int rc;
348 printf("system-test> ");
349 fflush(stdout);
350 if( !fgets(zLine, sizeof(zLine), stdin) ) break;
351 n = strlen(zLine);
352 while( n>0 && fossil_isspace(zLine[n-1]) ) n--;
353 zLine[n] = 0;
354 printf("cmd: [%s]\n", zLine);
355 fflush(stdout);
356 rc = fossil_system(zLine);
357 printf("result: %d\n", rc);
358 }
359 }
360
361 /*
362 ** Like strcmp() except that it accepts NULL pointers. NULL sorts before
363
+131 -4
--- src/wiki.c
+++ src/wiki.c
@@ -679,11 +679,11 @@
679679
Manifest *pWiki = 0;
680680
const char *zPageName;
681681
const char *zMimetype = 0;
682682
int isPopup = P("popup")!=0;
683683
char *zBody = mprintf("%s","<i>Empty Page</i>");
684
- int noSubmenu = P("nsm")!=0;
684
+ int noSubmenu = P("nsm")!=0 || g.isHome;
685685
686686
login_check_credentials();
687687
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
688688
zPageName = P("name");
689689
if( zPageName==0 ){
@@ -717,11 +717,11 @@
717717
zBody = pWiki->zWiki;
718718
zMimetype = pWiki->zMimetype;
719719
}
720720
}
721721
zMimetype = wiki_filter_mimetypes(zMimetype);
722
- if( !g.isHome && !noSubmenu ){
722
+ if( !noSubmenu ){
723723
if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
724724
&& wiki_special_permission(zPageName)
725725
){
726726
style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
727727
}else if( rid && g.perm.ApndWiki ){
@@ -893,10 +893,99 @@
893893
}
894894
}
895895
ajax_route_error(403, "%s", zErr);
896896
return 0;
897897
}
898
+
899
+
900
+/*
901
+** Emits an array of attachment info records for the given wiki page
902
+** artifact.
903
+**
904
+** Output format:
905
+**
906
+** [{
907
+** "uuid": attachment artifact hash,
908
+** "src": hash of the attachment blob,
909
+** "target": wiki page name or ticket/event ID,
910
+** "filename": filename of attachment,
911
+** "mtime": ISO-8601 timestamp UTC,
912
+** "isLatest": true this is the latest version of this file
913
+** else false,
914
+** }, ...once per attachment]
915
+**
916
+** If there are no matching attachments then it will emit a JSON
917
+** null (if nullIfEmpty) or an empty JSON array.
918
+**
919
+** If latestOnly is true then only the most recent entry for a given
920
+** attachment is emitted, else all versions are emitted in descending
921
+** mtime order.
922
+*/
923
+static void wiki_ajax_emit_page_attachments(Manifest * pWiki,
924
+ int latestOnly,
925
+ int nullIfEmpty){
926
+ int i = 0;
927
+ Stmt q = empty_Stmt;
928
+ db_prepare(&q,
929
+ "SELECT datetime(mtime), src, target, filename, isLatest,"
930
+ " (SELECT uuid FROM blob WHERE rid=attachid) uuid"
931
+ " FROM attachment"
932
+ " WHERE target=%Q"
933
+ " AND (isLatest OR %d)"
934
+ " ORDER BY target, isLatest DESC, mtime DESC",
935
+ pWiki->zWikiTitle, !latestOnly
936
+ );
937
+ while(SQLITE_ROW == db_step(&q)){
938
+ const char * zTime = db_column_text(&q, 0);
939
+ const char * zSrc = db_column_text(&q, 1);
940
+ const char * zTarget = db_column_text(&q, 2);
941
+ const char * zName = db_column_text(&q, 3);
942
+ const int isLatest = db_column_int(&q, 4);
943
+ const char * zUuid = db_column_text(&q, 5);
944
+ if(!i++){
945
+ CX("[");
946
+ }else{
947
+ CX(",");
948
+ }
949
+ CX("{");
950
+ CX("\"uuid\": %!j, \"src\": %!j, \"target\": %!j, "
951
+ "\"filename\": %!j, \"mtime\": %!j, \"isLatest\": %s}",
952
+ zUuid, zSrc, zTarget,
953
+ zName, zTime, isLatest ? "true" : "false");
954
+ }
955
+ db_finalize(&q);
956
+ if(!i){
957
+ if(nullIfEmpty){
958
+ CX("null");
959
+ }else{
960
+ CX("[]");
961
+ }
962
+ }else{
963
+ CX("]");
964
+ }
965
+}
966
+
967
+/*
968
+** Proxy for wiki_ajax_emit_page_attachments() which attempts to load
969
+** the given wiki page artifact. Returns true if it can load the given
970
+** page, else false. If it returns false then it queues up a 404 ajax
971
+** error response.
972
+*/
973
+static int wiki_ajax_emit_page_attachments2(const char *zPageName,
974
+ int latestOnly,
975
+ int nullIfEmpty){
976
+ Manifest * pWiki = 0;
977
+ if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
978
+ ajax_route_error(404, "Wiki page could not be loaded: %s",
979
+ zPageName);
980
+ return 0;
981
+ }
982
+ wiki_ajax_emit_page_attachments(pWiki, latestOnly, nullIfEmpty);
983
+ manifest_destroy(pWiki);
984
+ return 1;
985
+}
986
+
898987
899988
/*
900989
** Loads the given wiki page, sets the response type to
901990
** application/json, and emits it as a JSON object. If zPageName is a
902991
** sandbox page then a "fake" object is emitted, as the wikiajax API
@@ -912,10 +1001,11 @@
9121001
** mimetype: "mimetype",
9131002
** version: UUID string or null for a sandbox page,
9141003
** parent: "parent uuid" or null if no parent,
9151004
** isDeleted: true if the page has no content (is "deleted")
9161005
** else not set (making it "falsy" in JS),
1006
+** attachments: see wiki_ajax_emit_page_attachments(),
9171007
** content: "page content" (only if includeContent is true)
9181008
** }
9191009
**
9201010
** If includeContent is false then the content member is elided.
9211011
*/
@@ -962,10 +1052,12 @@
9621052
CX(", \"isEmpty\": true");
9631053
}
9641054
if(includeContent){
9651055
CX(", \"content\": %!j", pWiki->zWiki);
9661056
}
1057
+ CX(", \"attachments\": ");
1058
+ wiki_ajax_emit_page_attachments(pWiki, 0, 1);
9671059
CX("}");
9681060
fossil_free(zUuid);
9691061
manifest_destroy(pWiki);
9701062
return 2;
9711063
}
@@ -1053,10 +1145,39 @@
10531145
return;
10541146
}
10551147
cgi_set_content_type("application/json");
10561148
wiki_ajax_emit_page_object(zPageName, 1);
10571149
}
1150
+
1151
+/*
1152
+** Ajax route handler for /wikiajax/attachments.
1153
+**
1154
+** URL params:
1155
+**
1156
+** page = the wiki page name
1157
+** latestOnly = if set, only latest version of each attachment
1158
+** is emitted.
1159
+**
1160
+** Responds with JSON: see wiki_ajax_emit_page_attachments()
1161
+**
1162
+** If there are no attachments it emits an empty array instead of null
1163
+** so that the output can be used as a top-level JSON response.
1164
+**
1165
+** On error, an object in the form documented by
1166
+** ajax_route_error(). On success, an object in the form documented
1167
+** for wiki_ajax_emit_page_attachments().
1168
+*/
1169
+static void wiki_ajax_route_attachments(void){
1170
+ const char * zPageName = P("page");
1171
+ const int fLatestOnly = P("latestOnly")!=0;
1172
+ if( zPageName==0 || zPageName[0]==0 ){
1173
+ ajax_route_error(400,"Missing page name.");
1174
+ return;
1175
+ }
1176
+ cgi_set_content_type("application/json");
1177
+ wiki_ajax_emit_page_attachments2(zPageName, fLatestOnly, 0);
1178
+}
10581179
10591180
/*
10601181
** Ajax route handler for /wikiajax/diff.
10611182
**
10621183
** URL params:
@@ -1210,10 +1331,11 @@
12101331
const char * zName = P("name");
12111332
AjaxRoute routeName = {0,0,0,0};
12121333
const AjaxRoute * pRoute = 0;
12131334
const AjaxRoute routes[] = {
12141335
/* Keep these sorted by zName (for bsearch()) */
1336
+ {"attachments", wiki_ajax_route_attachments, 0, 0},
12151337
{"diff", wiki_ajax_route_diff, 1, 1},
12161338
{"fetch", wiki_ajax_route_fetch, 0, 0},
12171339
{"list", wiki_ajax_route_list, 0, 0},
12181340
{"preview", wiki_ajax_route_preview, 0, 1},
12191341
{"save", wiki_ajax_route_save, 1, 1}
@@ -1436,13 +1558,17 @@
14361558
14371559
/****** The obligatory "Misc" tab ******/
14381560
{
14391561
CX("<div id='wikiedit-tab-misc' "
14401562
"data-tab-parent='wikiedit-tabs' "
1441
- "data-tab-label='Help' "
1563
+ "data-tab-label='Misc.' "
14421564
"class='hidden'"
14431565
">");
1566
+ CX("<fieldset id='attachment-wrapper'>");
1567
+ CX("<legend>Attachments</legend>");
1568
+ CX("<div>No attachments for the current page.</div>");
1569
+ CX("</fieldset>");
14441570
CX("<h2>Wiki formatting rules</h2>");
14451571
CX("<ul>");
14461572
CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>");
14471573
CX("<li><a href='%R/md_rules'>Markdown format</a></li>");
14481574
CX("<li>Plain-text pages use no special formatting.</li>");
@@ -1722,10 +1848,11 @@
17221848
void whistory_page(void){
17231849
Stmt q;
17241850
const char *zPageName;
17251851
double rNow;
17261852
int showRid;
1853
+ char zAuthor[64];
17271854
login_check_credentials();
17281855
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
17291856
zPageName = PD("name","");
17301857
style_set_current_feature("wiki");
17311858
style_header("History Of %s", zPageName);
@@ -1763,11 +1890,11 @@
17631890
@ <th>RID</th>
17641891
}
17651892
@ <th>&nbsp;</th>
17661893
@ </tr></thead><tbody>
17671894
rNow = db_double(0.0, "SELECT julianday('now')");
1768
- char zAuthor[64]; memset( zAuthor, 0, sizeof(zAuthor) );
1895
+ memset( zAuthor, 0, sizeof(zAuthor) );
17691896
while( db_step(&q)==SQLITE_ROW ){
17701897
double rMtime = db_column_double(&q, 0);
17711898
const char *zUuid = db_column_text(&q, 1);
17721899
const char *zUser = db_column_text(&q, 2);
17731900
int wrid = db_column_int(&q, 3);
17741901
--- src/wiki.c
+++ src/wiki.c
@@ -679,11 +679,11 @@
679 Manifest *pWiki = 0;
680 const char *zPageName;
681 const char *zMimetype = 0;
682 int isPopup = P("popup")!=0;
683 char *zBody = mprintf("%s","<i>Empty Page</i>");
684 int noSubmenu = P("nsm")!=0;
685
686 login_check_credentials();
687 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
688 zPageName = P("name");
689 if( zPageName==0 ){
@@ -717,11 +717,11 @@
717 zBody = pWiki->zWiki;
718 zMimetype = pWiki->zMimetype;
719 }
720 }
721 zMimetype = wiki_filter_mimetypes(zMimetype);
722 if( !g.isHome && !noSubmenu ){
723 if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
724 && wiki_special_permission(zPageName)
725 ){
726 style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
727 }else if( rid && g.perm.ApndWiki ){
@@ -893,10 +893,99 @@
893 }
894 }
895 ajax_route_error(403, "%s", zErr);
896 return 0;
897 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
898
899 /*
900 ** Loads the given wiki page, sets the response type to
901 ** application/json, and emits it as a JSON object. If zPageName is a
902 ** sandbox page then a "fake" object is emitted, as the wikiajax API
@@ -912,10 +1001,11 @@
912 ** mimetype: "mimetype",
913 ** version: UUID string or null for a sandbox page,
914 ** parent: "parent uuid" or null if no parent,
915 ** isDeleted: true if the page has no content (is "deleted")
916 ** else not set (making it "falsy" in JS),
 
917 ** content: "page content" (only if includeContent is true)
918 ** }
919 **
920 ** If includeContent is false then the content member is elided.
921 */
@@ -962,10 +1052,12 @@
962 CX(", \"isEmpty\": true");
963 }
964 if(includeContent){
965 CX(", \"content\": %!j", pWiki->zWiki);
966 }
 
 
967 CX("}");
968 fossil_free(zUuid);
969 manifest_destroy(pWiki);
970 return 2;
971 }
@@ -1053,10 +1145,39 @@
1053 return;
1054 }
1055 cgi_set_content_type("application/json");
1056 wiki_ajax_emit_page_object(zPageName, 1);
1057 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1058
1059 /*
1060 ** Ajax route handler for /wikiajax/diff.
1061 **
1062 ** URL params:
@@ -1210,10 +1331,11 @@
1210 const char * zName = P("name");
1211 AjaxRoute routeName = {0,0,0,0};
1212 const AjaxRoute * pRoute = 0;
1213 const AjaxRoute routes[] = {
1214 /* Keep these sorted by zName (for bsearch()) */
 
1215 {"diff", wiki_ajax_route_diff, 1, 1},
1216 {"fetch", wiki_ajax_route_fetch, 0, 0},
1217 {"list", wiki_ajax_route_list, 0, 0},
1218 {"preview", wiki_ajax_route_preview, 0, 1},
1219 {"save", wiki_ajax_route_save, 1, 1}
@@ -1436,13 +1558,17 @@
1436
1437 /****** The obligatory "Misc" tab ******/
1438 {
1439 CX("<div id='wikiedit-tab-misc' "
1440 "data-tab-parent='wikiedit-tabs' "
1441 "data-tab-label='Help' "
1442 "class='hidden'"
1443 ">");
 
 
 
 
1444 CX("<h2>Wiki formatting rules</h2>");
1445 CX("<ul>");
1446 CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>");
1447 CX("<li><a href='%R/md_rules'>Markdown format</a></li>");
1448 CX("<li>Plain-text pages use no special formatting.</li>");
@@ -1722,10 +1848,11 @@
1722 void whistory_page(void){
1723 Stmt q;
1724 const char *zPageName;
1725 double rNow;
1726 int showRid;
 
1727 login_check_credentials();
1728 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
1729 zPageName = PD("name","");
1730 style_set_current_feature("wiki");
1731 style_header("History Of %s", zPageName);
@@ -1763,11 +1890,11 @@
1763 @ <th>RID</th>
1764 }
1765 @ <th>&nbsp;</th>
1766 @ </tr></thead><tbody>
1767 rNow = db_double(0.0, "SELECT julianday('now')");
1768 char zAuthor[64]; memset( zAuthor, 0, sizeof(zAuthor) );
1769 while( db_step(&q)==SQLITE_ROW ){
1770 double rMtime = db_column_double(&q, 0);
1771 const char *zUuid = db_column_text(&q, 1);
1772 const char *zUser = db_column_text(&q, 2);
1773 int wrid = db_column_int(&q, 3);
1774
--- src/wiki.c
+++ src/wiki.c
@@ -679,11 +679,11 @@
679 Manifest *pWiki = 0;
680 const char *zPageName;
681 const char *zMimetype = 0;
682 int isPopup = P("popup")!=0;
683 char *zBody = mprintf("%s","<i>Empty Page</i>");
684 int noSubmenu = P("nsm")!=0 || g.isHome;
685
686 login_check_credentials();
687 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
688 zPageName = P("name");
689 if( zPageName==0 ){
@@ -717,11 +717,11 @@
717 zBody = pWiki->zWiki;
718 zMimetype = pWiki->zMimetype;
719 }
720 }
721 zMimetype = wiki_filter_mimetypes(zMimetype);
722 if( !noSubmenu ){
723 if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
724 && wiki_special_permission(zPageName)
725 ){
726 style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
727 }else if( rid && g.perm.ApndWiki ){
@@ -893,10 +893,99 @@
893 }
894 }
895 ajax_route_error(403, "%s", zErr);
896 return 0;
897 }
898
899
900 /*
901 ** Emits an array of attachment info records for the given wiki page
902 ** artifact.
903 **
904 ** Output format:
905 **
906 ** [{
907 ** "uuid": attachment artifact hash,
908 ** "src": hash of the attachment blob,
909 ** "target": wiki page name or ticket/event ID,
910 ** "filename": filename of attachment,
911 ** "mtime": ISO-8601 timestamp UTC,
912 ** "isLatest": true this is the latest version of this file
913 ** else false,
914 ** }, ...once per attachment]
915 **
916 ** If there are no matching attachments then it will emit a JSON
917 ** null (if nullIfEmpty) or an empty JSON array.
918 **
919 ** If latestOnly is true then only the most recent entry for a given
920 ** attachment is emitted, else all versions are emitted in descending
921 ** mtime order.
922 */
923 static void wiki_ajax_emit_page_attachments(Manifest * pWiki,
924 int latestOnly,
925 int nullIfEmpty){
926 int i = 0;
927 Stmt q = empty_Stmt;
928 db_prepare(&q,
929 "SELECT datetime(mtime), src, target, filename, isLatest,"
930 " (SELECT uuid FROM blob WHERE rid=attachid) uuid"
931 " FROM attachment"
932 " WHERE target=%Q"
933 " AND (isLatest OR %d)"
934 " ORDER BY target, isLatest DESC, mtime DESC",
935 pWiki->zWikiTitle, !latestOnly
936 );
937 while(SQLITE_ROW == db_step(&q)){
938 const char * zTime = db_column_text(&q, 0);
939 const char * zSrc = db_column_text(&q, 1);
940 const char * zTarget = db_column_text(&q, 2);
941 const char * zName = db_column_text(&q, 3);
942 const int isLatest = db_column_int(&q, 4);
943 const char * zUuid = db_column_text(&q, 5);
944 if(!i++){
945 CX("[");
946 }else{
947 CX(",");
948 }
949 CX("{");
950 CX("\"uuid\": %!j, \"src\": %!j, \"target\": %!j, "
951 "\"filename\": %!j, \"mtime\": %!j, \"isLatest\": %s}",
952 zUuid, zSrc, zTarget,
953 zName, zTime, isLatest ? "true" : "false");
954 }
955 db_finalize(&q);
956 if(!i){
957 if(nullIfEmpty){
958 CX("null");
959 }else{
960 CX("[]");
961 }
962 }else{
963 CX("]");
964 }
965 }
966
967 /*
968 ** Proxy for wiki_ajax_emit_page_attachments() which attempts to load
969 ** the given wiki page artifact. Returns true if it can load the given
970 ** page, else false. If it returns false then it queues up a 404 ajax
971 ** error response.
972 */
973 static int wiki_ajax_emit_page_attachments2(const char *zPageName,
974 int latestOnly,
975 int nullIfEmpty){
976 Manifest * pWiki = 0;
977 if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
978 ajax_route_error(404, "Wiki page could not be loaded: %s",
979 zPageName);
980 return 0;
981 }
982 wiki_ajax_emit_page_attachments(pWiki, latestOnly, nullIfEmpty);
983 manifest_destroy(pWiki);
984 return 1;
985 }
986
987
988 /*
989 ** Loads the given wiki page, sets the response type to
990 ** application/json, and emits it as a JSON object. If zPageName is a
991 ** sandbox page then a "fake" object is emitted, as the wikiajax API
@@ -912,10 +1001,11 @@
1001 ** mimetype: "mimetype",
1002 ** version: UUID string or null for a sandbox page,
1003 ** parent: "parent uuid" or null if no parent,
1004 ** isDeleted: true if the page has no content (is "deleted")
1005 ** else not set (making it "falsy" in JS),
1006 ** attachments: see wiki_ajax_emit_page_attachments(),
1007 ** content: "page content" (only if includeContent is true)
1008 ** }
1009 **
1010 ** If includeContent is false then the content member is elided.
1011 */
@@ -962,10 +1052,12 @@
1052 CX(", \"isEmpty\": true");
1053 }
1054 if(includeContent){
1055 CX(", \"content\": %!j", pWiki->zWiki);
1056 }
1057 CX(", \"attachments\": ");
1058 wiki_ajax_emit_page_attachments(pWiki, 0, 1);
1059 CX("}");
1060 fossil_free(zUuid);
1061 manifest_destroy(pWiki);
1062 return 2;
1063 }
@@ -1053,10 +1145,39 @@
1145 return;
1146 }
1147 cgi_set_content_type("application/json");
1148 wiki_ajax_emit_page_object(zPageName, 1);
1149 }
1150
1151 /*
1152 ** Ajax route handler for /wikiajax/attachments.
1153 **
1154 ** URL params:
1155 **
1156 ** page = the wiki page name
1157 ** latestOnly = if set, only latest version of each attachment
1158 ** is emitted.
1159 **
1160 ** Responds with JSON: see wiki_ajax_emit_page_attachments()
1161 **
1162 ** If there are no attachments it emits an empty array instead of null
1163 ** so that the output can be used as a top-level JSON response.
1164 **
1165 ** On error, an object in the form documented by
1166 ** ajax_route_error(). On success, an object in the form documented
1167 ** for wiki_ajax_emit_page_attachments().
1168 */
1169 static void wiki_ajax_route_attachments(void){
1170 const char * zPageName = P("page");
1171 const int fLatestOnly = P("latestOnly")!=0;
1172 if( zPageName==0 || zPageName[0]==0 ){
1173 ajax_route_error(400,"Missing page name.");
1174 return;
1175 }
1176 cgi_set_content_type("application/json");
1177 wiki_ajax_emit_page_attachments2(zPageName, fLatestOnly, 0);
1178 }
1179
1180 /*
1181 ** Ajax route handler for /wikiajax/diff.
1182 **
1183 ** URL params:
@@ -1210,10 +1331,11 @@
1331 const char * zName = P("name");
1332 AjaxRoute routeName = {0,0,0,0};
1333 const AjaxRoute * pRoute = 0;
1334 const AjaxRoute routes[] = {
1335 /* Keep these sorted by zName (for bsearch()) */
1336 {"attachments", wiki_ajax_route_attachments, 0, 0},
1337 {"diff", wiki_ajax_route_diff, 1, 1},
1338 {"fetch", wiki_ajax_route_fetch, 0, 0},
1339 {"list", wiki_ajax_route_list, 0, 0},
1340 {"preview", wiki_ajax_route_preview, 0, 1},
1341 {"save", wiki_ajax_route_save, 1, 1}
@@ -1436,13 +1558,17 @@
1558
1559 /****** The obligatory "Misc" tab ******/
1560 {
1561 CX("<div id='wikiedit-tab-misc' "
1562 "data-tab-parent='wikiedit-tabs' "
1563 "data-tab-label='Misc.' "
1564 "class='hidden'"
1565 ">");
1566 CX("<fieldset id='attachment-wrapper'>");
1567 CX("<legend>Attachments</legend>");
1568 CX("<div>No attachments for the current page.</div>");
1569 CX("</fieldset>");
1570 CX("<h2>Wiki formatting rules</h2>");
1571 CX("<ul>");
1572 CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>");
1573 CX("<li><a href='%R/md_rules'>Markdown format</a></li>");
1574 CX("<li>Plain-text pages use no special formatting.</li>");
@@ -1722,10 +1848,11 @@
1848 void whistory_page(void){
1849 Stmt q;
1850 const char *zPageName;
1851 double rNow;
1852 int showRid;
1853 char zAuthor[64];
1854 login_check_credentials();
1855 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
1856 zPageName = PD("name","");
1857 style_set_current_feature("wiki");
1858 style_header("History Of %s", zPageName);
@@ -1763,11 +1890,11 @@
1890 @ <th>RID</th>
1891 }
1892 @ <th>&nbsp;</th>
1893 @ </tr></thead><tbody>
1894 rNow = db_double(0.0, "SELECT julianday('now')");
1895 memset( zAuthor, 0, sizeof(zAuthor) );
1896 while( db_step(&q)==SQLITE_ROW ){
1897 double rMtime = db_column_double(&q, 0);
1898 const char *zUuid = db_column_text(&q, 1);
1899 const char *zUser = db_column_text(&q, 2);
1900 int wrid = db_column_int(&q, 3);
1901
+131 -4
--- src/wiki.c
+++ src/wiki.c
@@ -679,11 +679,11 @@
679679
Manifest *pWiki = 0;
680680
const char *zPageName;
681681
const char *zMimetype = 0;
682682
int isPopup = P("popup")!=0;
683683
char *zBody = mprintf("%s","<i>Empty Page</i>");
684
- int noSubmenu = P("nsm")!=0;
684
+ int noSubmenu = P("nsm")!=0 || g.isHome;
685685
686686
login_check_credentials();
687687
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
688688
zPageName = P("name");
689689
if( zPageName==0 ){
@@ -717,11 +717,11 @@
717717
zBody = pWiki->zWiki;
718718
zMimetype = pWiki->zMimetype;
719719
}
720720
}
721721
zMimetype = wiki_filter_mimetypes(zMimetype);
722
- if( !g.isHome && !noSubmenu ){
722
+ if( !noSubmenu ){
723723
if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
724724
&& wiki_special_permission(zPageName)
725725
){
726726
style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
727727
}else if( rid && g.perm.ApndWiki ){
@@ -893,10 +893,99 @@
893893
}
894894
}
895895
ajax_route_error(403, "%s", zErr);
896896
return 0;
897897
}
898
+
899
+
900
+/*
901
+** Emits an array of attachment info records for the given wiki page
902
+** artifact.
903
+**
904
+** Output format:
905
+**
906
+** [{
907
+** "uuid": attachment artifact hash,
908
+** "src": hash of the attachment blob,
909
+** "target": wiki page name or ticket/event ID,
910
+** "filename": filename of attachment,
911
+** "mtime": ISO-8601 timestamp UTC,
912
+** "isLatest": true this is the latest version of this file
913
+** else false,
914
+** }, ...once per attachment]
915
+**
916
+** If there are no matching attachments then it will emit a JSON
917
+** null (if nullIfEmpty) or an empty JSON array.
918
+**
919
+** If latestOnly is true then only the most recent entry for a given
920
+** attachment is emitted, else all versions are emitted in descending
921
+** mtime order.
922
+*/
923
+static void wiki_ajax_emit_page_attachments(Manifest * pWiki,
924
+ int latestOnly,
925
+ int nullIfEmpty){
926
+ int i = 0;
927
+ Stmt q = empty_Stmt;
928
+ db_prepare(&q,
929
+ "SELECT datetime(mtime), src, target, filename, isLatest,"
930
+ " (SELECT uuid FROM blob WHERE rid=attachid) uuid"
931
+ " FROM attachment"
932
+ " WHERE target=%Q"
933
+ " AND (isLatest OR %d)"
934
+ " ORDER BY target, isLatest DESC, mtime DESC",
935
+ pWiki->zWikiTitle, !latestOnly
936
+ );
937
+ while(SQLITE_ROW == db_step(&q)){
938
+ const char * zTime = db_column_text(&q, 0);
939
+ const char * zSrc = db_column_text(&q, 1);
940
+ const char * zTarget = db_column_text(&q, 2);
941
+ const char * zName = db_column_text(&q, 3);
942
+ const int isLatest = db_column_int(&q, 4);
943
+ const char * zUuid = db_column_text(&q, 5);
944
+ if(!i++){
945
+ CX("[");
946
+ }else{
947
+ CX(",");
948
+ }
949
+ CX("{");
950
+ CX("\"uuid\": %!j, \"src\": %!j, \"target\": %!j, "
951
+ "\"filename\": %!j, \"mtime\": %!j, \"isLatest\": %s}",
952
+ zUuid, zSrc, zTarget,
953
+ zName, zTime, isLatest ? "true" : "false");
954
+ }
955
+ db_finalize(&q);
956
+ if(!i){
957
+ if(nullIfEmpty){
958
+ CX("null");
959
+ }else{
960
+ CX("[]");
961
+ }
962
+ }else{
963
+ CX("]");
964
+ }
965
+}
966
+
967
+/*
968
+** Proxy for wiki_ajax_emit_page_attachments() which attempts to load
969
+** the given wiki page artifact. Returns true if it can load the given
970
+** page, else false. If it returns false then it queues up a 404 ajax
971
+** error response.
972
+*/
973
+static int wiki_ajax_emit_page_attachments2(const char *zPageName,
974
+ int latestOnly,
975
+ int nullIfEmpty){
976
+ Manifest * pWiki = 0;
977
+ if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
978
+ ajax_route_error(404, "Wiki page could not be loaded: %s",
979
+ zPageName);
980
+ return 0;
981
+ }
982
+ wiki_ajax_emit_page_attachments(pWiki, latestOnly, nullIfEmpty);
983
+ manifest_destroy(pWiki);
984
+ return 1;
985
+}
986
+
898987
899988
/*
900989
** Loads the given wiki page, sets the response type to
901990
** application/json, and emits it as a JSON object. If zPageName is a
902991
** sandbox page then a "fake" object is emitted, as the wikiajax API
@@ -912,10 +1001,11 @@
9121001
** mimetype: "mimetype",
9131002
** version: UUID string or null for a sandbox page,
9141003
** parent: "parent uuid" or null if no parent,
9151004
** isDeleted: true if the page has no content (is "deleted")
9161005
** else not set (making it "falsy" in JS),
1006
+** attachments: see wiki_ajax_emit_page_attachments(),
9171007
** content: "page content" (only if includeContent is true)
9181008
** }
9191009
**
9201010
** If includeContent is false then the content member is elided.
9211011
*/
@@ -962,10 +1052,12 @@
9621052
CX(", \"isEmpty\": true");
9631053
}
9641054
if(includeContent){
9651055
CX(", \"content\": %!j", pWiki->zWiki);
9661056
}
1057
+ CX(", \"attachments\": ");
1058
+ wiki_ajax_emit_page_attachments(pWiki, 0, 1);
9671059
CX("}");
9681060
fossil_free(zUuid);
9691061
manifest_destroy(pWiki);
9701062
return 2;
9711063
}
@@ -1053,10 +1145,39 @@
10531145
return;
10541146
}
10551147
cgi_set_content_type("application/json");
10561148
wiki_ajax_emit_page_object(zPageName, 1);
10571149
}
1150
+
1151
+/*
1152
+** Ajax route handler for /wikiajax/attachments.
1153
+**
1154
+** URL params:
1155
+**
1156
+** page = the wiki page name
1157
+** latestOnly = if set, only latest version of each attachment
1158
+** is emitted.
1159
+**
1160
+** Responds with JSON: see wiki_ajax_emit_page_attachments()
1161
+**
1162
+** If there are no attachments it emits an empty array instead of null
1163
+** so that the output can be used as a top-level JSON response.
1164
+**
1165
+** On error, an object in the form documented by
1166
+** ajax_route_error(). On success, an object in the form documented
1167
+** for wiki_ajax_emit_page_attachments().
1168
+*/
1169
+static void wiki_ajax_route_attachments(void){
1170
+ const char * zPageName = P("page");
1171
+ const int fLatestOnly = P("latestOnly")!=0;
1172
+ if( zPageName==0 || zPageName[0]==0 ){
1173
+ ajax_route_error(400,"Missing page name.");
1174
+ return;
1175
+ }
1176
+ cgi_set_content_type("application/json");
1177
+ wiki_ajax_emit_page_attachments2(zPageName, fLatestOnly, 0);
1178
+}
10581179
10591180
/*
10601181
** Ajax route handler for /wikiajax/diff.
10611182
**
10621183
** URL params:
@@ -1210,10 +1331,11 @@
12101331
const char * zName = P("name");
12111332
AjaxRoute routeName = {0,0,0,0};
12121333
const AjaxRoute * pRoute = 0;
12131334
const AjaxRoute routes[] = {
12141335
/* Keep these sorted by zName (for bsearch()) */
1336
+ {"attachments", wiki_ajax_route_attachments, 0, 0},
12151337
{"diff", wiki_ajax_route_diff, 1, 1},
12161338
{"fetch", wiki_ajax_route_fetch, 0, 0},
12171339
{"list", wiki_ajax_route_list, 0, 0},
12181340
{"preview", wiki_ajax_route_preview, 0, 1},
12191341
{"save", wiki_ajax_route_save, 1, 1}
@@ -1436,13 +1558,17 @@
14361558
14371559
/****** The obligatory "Misc" tab ******/
14381560
{
14391561
CX("<div id='wikiedit-tab-misc' "
14401562
"data-tab-parent='wikiedit-tabs' "
1441
- "data-tab-label='Help' "
1563
+ "data-tab-label='Misc.' "
14421564
"class='hidden'"
14431565
">");
1566
+ CX("<fieldset id='attachment-wrapper'>");
1567
+ CX("<legend>Attachments</legend>");
1568
+ CX("<div>No attachments for the current page.</div>");
1569
+ CX("</fieldset>");
14441570
CX("<h2>Wiki formatting rules</h2>");
14451571
CX("<ul>");
14461572
CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>");
14471573
CX("<li><a href='%R/md_rules'>Markdown format</a></li>");
14481574
CX("<li>Plain-text pages use no special formatting.</li>");
@@ -1722,10 +1848,11 @@
17221848
void whistory_page(void){
17231849
Stmt q;
17241850
const char *zPageName;
17251851
double rNow;
17261852
int showRid;
1853
+ char zAuthor[64];
17271854
login_check_credentials();
17281855
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
17291856
zPageName = PD("name","");
17301857
style_set_current_feature("wiki");
17311858
style_header("History Of %s", zPageName);
@@ -1763,11 +1890,11 @@
17631890
@ <th>RID</th>
17641891
}
17651892
@ <th>&nbsp;</th>
17661893
@ </tr></thead><tbody>
17671894
rNow = db_double(0.0, "SELECT julianday('now')");
1768
- char zAuthor[64]; memset( zAuthor, 0, sizeof(zAuthor) );
1895
+ memset( zAuthor, 0, sizeof(zAuthor) );
17691896
while( db_step(&q)==SQLITE_ROW ){
17701897
double rMtime = db_column_double(&q, 0);
17711898
const char *zUuid = db_column_text(&q, 1);
17721899
const char *zUser = db_column_text(&q, 2);
17731900
int wrid = db_column_int(&q, 3);
17741901
--- src/wiki.c
+++ src/wiki.c
@@ -679,11 +679,11 @@
679 Manifest *pWiki = 0;
680 const char *zPageName;
681 const char *zMimetype = 0;
682 int isPopup = P("popup")!=0;
683 char *zBody = mprintf("%s","<i>Empty Page</i>");
684 int noSubmenu = P("nsm")!=0;
685
686 login_check_credentials();
687 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
688 zPageName = P("name");
689 if( zPageName==0 ){
@@ -717,11 +717,11 @@
717 zBody = pWiki->zWiki;
718 zMimetype = pWiki->zMimetype;
719 }
720 }
721 zMimetype = wiki_filter_mimetypes(zMimetype);
722 if( !g.isHome && !noSubmenu ){
723 if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
724 && wiki_special_permission(zPageName)
725 ){
726 style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
727 }else if( rid && g.perm.ApndWiki ){
@@ -893,10 +893,99 @@
893 }
894 }
895 ajax_route_error(403, "%s", zErr);
896 return 0;
897 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
898
899 /*
900 ** Loads the given wiki page, sets the response type to
901 ** application/json, and emits it as a JSON object. If zPageName is a
902 ** sandbox page then a "fake" object is emitted, as the wikiajax API
@@ -912,10 +1001,11 @@
912 ** mimetype: "mimetype",
913 ** version: UUID string or null for a sandbox page,
914 ** parent: "parent uuid" or null if no parent,
915 ** isDeleted: true if the page has no content (is "deleted")
916 ** else not set (making it "falsy" in JS),
 
917 ** content: "page content" (only if includeContent is true)
918 ** }
919 **
920 ** If includeContent is false then the content member is elided.
921 */
@@ -962,10 +1052,12 @@
962 CX(", \"isEmpty\": true");
963 }
964 if(includeContent){
965 CX(", \"content\": %!j", pWiki->zWiki);
966 }
 
 
967 CX("}");
968 fossil_free(zUuid);
969 manifest_destroy(pWiki);
970 return 2;
971 }
@@ -1053,10 +1145,39 @@
1053 return;
1054 }
1055 cgi_set_content_type("application/json");
1056 wiki_ajax_emit_page_object(zPageName, 1);
1057 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1058
1059 /*
1060 ** Ajax route handler for /wikiajax/diff.
1061 **
1062 ** URL params:
@@ -1210,10 +1331,11 @@
1210 const char * zName = P("name");
1211 AjaxRoute routeName = {0,0,0,0};
1212 const AjaxRoute * pRoute = 0;
1213 const AjaxRoute routes[] = {
1214 /* Keep these sorted by zName (for bsearch()) */
 
1215 {"diff", wiki_ajax_route_diff, 1, 1},
1216 {"fetch", wiki_ajax_route_fetch, 0, 0},
1217 {"list", wiki_ajax_route_list, 0, 0},
1218 {"preview", wiki_ajax_route_preview, 0, 1},
1219 {"save", wiki_ajax_route_save, 1, 1}
@@ -1436,13 +1558,17 @@
1436
1437 /****** The obligatory "Misc" tab ******/
1438 {
1439 CX("<div id='wikiedit-tab-misc' "
1440 "data-tab-parent='wikiedit-tabs' "
1441 "data-tab-label='Help' "
1442 "class='hidden'"
1443 ">");
 
 
 
 
1444 CX("<h2>Wiki formatting rules</h2>");
1445 CX("<ul>");
1446 CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>");
1447 CX("<li><a href='%R/md_rules'>Markdown format</a></li>");
1448 CX("<li>Plain-text pages use no special formatting.</li>");
@@ -1722,10 +1848,11 @@
1722 void whistory_page(void){
1723 Stmt q;
1724 const char *zPageName;
1725 double rNow;
1726 int showRid;
 
1727 login_check_credentials();
1728 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
1729 zPageName = PD("name","");
1730 style_set_current_feature("wiki");
1731 style_header("History Of %s", zPageName);
@@ -1763,11 +1890,11 @@
1763 @ <th>RID</th>
1764 }
1765 @ <th>&nbsp;</th>
1766 @ </tr></thead><tbody>
1767 rNow = db_double(0.0, "SELECT julianday('now')");
1768 char zAuthor[64]; memset( zAuthor, 0, sizeof(zAuthor) );
1769 while( db_step(&q)==SQLITE_ROW ){
1770 double rMtime = db_column_double(&q, 0);
1771 const char *zUuid = db_column_text(&q, 1);
1772 const char *zUser = db_column_text(&q, 2);
1773 int wrid = db_column_int(&q, 3);
1774
--- src/wiki.c
+++ src/wiki.c
@@ -679,11 +679,11 @@
679 Manifest *pWiki = 0;
680 const char *zPageName;
681 const char *zMimetype = 0;
682 int isPopup = P("popup")!=0;
683 char *zBody = mprintf("%s","<i>Empty Page</i>");
684 int noSubmenu = P("nsm")!=0 || g.isHome;
685
686 login_check_credentials();
687 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
688 zPageName = P("name");
689 if( zPageName==0 ){
@@ -717,11 +717,11 @@
717 zBody = pWiki->zWiki;
718 zMimetype = pWiki->zMimetype;
719 }
720 }
721 zMimetype = wiki_filter_mimetypes(zMimetype);
722 if( !noSubmenu ){
723 if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
724 && wiki_special_permission(zPageName)
725 ){
726 style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
727 }else if( rid && g.perm.ApndWiki ){
@@ -893,10 +893,99 @@
893 }
894 }
895 ajax_route_error(403, "%s", zErr);
896 return 0;
897 }
898
899
900 /*
901 ** Emits an array of attachment info records for the given wiki page
902 ** artifact.
903 **
904 ** Output format:
905 **
906 ** [{
907 ** "uuid": attachment artifact hash,
908 ** "src": hash of the attachment blob,
909 ** "target": wiki page name or ticket/event ID,
910 ** "filename": filename of attachment,
911 ** "mtime": ISO-8601 timestamp UTC,
912 ** "isLatest": true this is the latest version of this file
913 ** else false,
914 ** }, ...once per attachment]
915 **
916 ** If there are no matching attachments then it will emit a JSON
917 ** null (if nullIfEmpty) or an empty JSON array.
918 **
919 ** If latestOnly is true then only the most recent entry for a given
920 ** attachment is emitted, else all versions are emitted in descending
921 ** mtime order.
922 */
923 static void wiki_ajax_emit_page_attachments(Manifest * pWiki,
924 int latestOnly,
925 int nullIfEmpty){
926 int i = 0;
927 Stmt q = empty_Stmt;
928 db_prepare(&q,
929 "SELECT datetime(mtime), src, target, filename, isLatest,"
930 " (SELECT uuid FROM blob WHERE rid=attachid) uuid"
931 " FROM attachment"
932 " WHERE target=%Q"
933 " AND (isLatest OR %d)"
934 " ORDER BY target, isLatest DESC, mtime DESC",
935 pWiki->zWikiTitle, !latestOnly
936 );
937 while(SQLITE_ROW == db_step(&q)){
938 const char * zTime = db_column_text(&q, 0);
939 const char * zSrc = db_column_text(&q, 1);
940 const char * zTarget = db_column_text(&q, 2);
941 const char * zName = db_column_text(&q, 3);
942 const int isLatest = db_column_int(&q, 4);
943 const char * zUuid = db_column_text(&q, 5);
944 if(!i++){
945 CX("[");
946 }else{
947 CX(",");
948 }
949 CX("{");
950 CX("\"uuid\": %!j, \"src\": %!j, \"target\": %!j, "
951 "\"filename\": %!j, \"mtime\": %!j, \"isLatest\": %s}",
952 zUuid, zSrc, zTarget,
953 zName, zTime, isLatest ? "true" : "false");
954 }
955 db_finalize(&q);
956 if(!i){
957 if(nullIfEmpty){
958 CX("null");
959 }else{
960 CX("[]");
961 }
962 }else{
963 CX("]");
964 }
965 }
966
967 /*
968 ** Proxy for wiki_ajax_emit_page_attachments() which attempts to load
969 ** the given wiki page artifact. Returns true if it can load the given
970 ** page, else false. If it returns false then it queues up a 404 ajax
971 ** error response.
972 */
973 static int wiki_ajax_emit_page_attachments2(const char *zPageName,
974 int latestOnly,
975 int nullIfEmpty){
976 Manifest * pWiki = 0;
977 if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){
978 ajax_route_error(404, "Wiki page could not be loaded: %s",
979 zPageName);
980 return 0;
981 }
982 wiki_ajax_emit_page_attachments(pWiki, latestOnly, nullIfEmpty);
983 manifest_destroy(pWiki);
984 return 1;
985 }
986
987
988 /*
989 ** Loads the given wiki page, sets the response type to
990 ** application/json, and emits it as a JSON object. If zPageName is a
991 ** sandbox page then a "fake" object is emitted, as the wikiajax API
@@ -912,10 +1001,11 @@
1001 ** mimetype: "mimetype",
1002 ** version: UUID string or null for a sandbox page,
1003 ** parent: "parent uuid" or null if no parent,
1004 ** isDeleted: true if the page has no content (is "deleted")
1005 ** else not set (making it "falsy" in JS),
1006 ** attachments: see wiki_ajax_emit_page_attachments(),
1007 ** content: "page content" (only if includeContent is true)
1008 ** }
1009 **
1010 ** If includeContent is false then the content member is elided.
1011 */
@@ -962,10 +1052,12 @@
1052 CX(", \"isEmpty\": true");
1053 }
1054 if(includeContent){
1055 CX(", \"content\": %!j", pWiki->zWiki);
1056 }
1057 CX(", \"attachments\": ");
1058 wiki_ajax_emit_page_attachments(pWiki, 0, 1);
1059 CX("}");
1060 fossil_free(zUuid);
1061 manifest_destroy(pWiki);
1062 return 2;
1063 }
@@ -1053,10 +1145,39 @@
1145 return;
1146 }
1147 cgi_set_content_type("application/json");
1148 wiki_ajax_emit_page_object(zPageName, 1);
1149 }
1150
1151 /*
1152 ** Ajax route handler for /wikiajax/attachments.
1153 **
1154 ** URL params:
1155 **
1156 ** page = the wiki page name
1157 ** latestOnly = if set, only latest version of each attachment
1158 ** is emitted.
1159 **
1160 ** Responds with JSON: see wiki_ajax_emit_page_attachments()
1161 **
1162 ** If there are no attachments it emits an empty array instead of null
1163 ** so that the output can be used as a top-level JSON response.
1164 **
1165 ** On error, an object in the form documented by
1166 ** ajax_route_error(). On success, an object in the form documented
1167 ** for wiki_ajax_emit_page_attachments().
1168 */
1169 static void wiki_ajax_route_attachments(void){
1170 const char * zPageName = P("page");
1171 const int fLatestOnly = P("latestOnly")!=0;
1172 if( zPageName==0 || zPageName[0]==0 ){
1173 ajax_route_error(400,"Missing page name.");
1174 return;
1175 }
1176 cgi_set_content_type("application/json");
1177 wiki_ajax_emit_page_attachments2(zPageName, fLatestOnly, 0);
1178 }
1179
1180 /*
1181 ** Ajax route handler for /wikiajax/diff.
1182 **
1183 ** URL params:
@@ -1210,10 +1331,11 @@
1331 const char * zName = P("name");
1332 AjaxRoute routeName = {0,0,0,0};
1333 const AjaxRoute * pRoute = 0;
1334 const AjaxRoute routes[] = {
1335 /* Keep these sorted by zName (for bsearch()) */
1336 {"attachments", wiki_ajax_route_attachments, 0, 0},
1337 {"diff", wiki_ajax_route_diff, 1, 1},
1338 {"fetch", wiki_ajax_route_fetch, 0, 0},
1339 {"list", wiki_ajax_route_list, 0, 0},
1340 {"preview", wiki_ajax_route_preview, 0, 1},
1341 {"save", wiki_ajax_route_save, 1, 1}
@@ -1436,13 +1558,17 @@
1558
1559 /****** The obligatory "Misc" tab ******/
1560 {
1561 CX("<div id='wikiedit-tab-misc' "
1562 "data-tab-parent='wikiedit-tabs' "
1563 "data-tab-label='Misc.' "
1564 "class='hidden'"
1565 ">");
1566 CX("<fieldset id='attachment-wrapper'>");
1567 CX("<legend>Attachments</legend>");
1568 CX("<div>No attachments for the current page.</div>");
1569 CX("</fieldset>");
1570 CX("<h2>Wiki formatting rules</h2>");
1571 CX("<ul>");
1572 CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>");
1573 CX("<li><a href='%R/md_rules'>Markdown format</a></li>");
1574 CX("<li>Plain-text pages use no special formatting.</li>");
@@ -1722,10 +1848,11 @@
1848 void whistory_page(void){
1849 Stmt q;
1850 const char *zPageName;
1851 double rNow;
1852 int showRid;
1853 char zAuthor[64];
1854 login_check_credentials();
1855 if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
1856 zPageName = PD("name","");
1857 style_set_current_feature("wiki");
1858 style_header("History Of %s", zPageName);
@@ -1763,11 +1890,11 @@
1890 @ <th>RID</th>
1891 }
1892 @ <th>&nbsp;</th>
1893 @ </tr></thead><tbody>
1894 rNow = db_double(0.0, "SELECT julianday('now')");
1895 memset( zAuthor, 0, sizeof(zAuthor) );
1896 while( db_step(&q)==SQLITE_ROW ){
1897 double rMtime = db_column_double(&q, 0);
1898 const char *zUuid = db_column_text(&q, 1);
1899 const char *zUser = db_column_text(&q, 2);
1900 int wrid = db_column_int(&q, 3);
1901
+1 -1
--- src/wiki.wiki
+++ src/wiki.wiki
@@ -85,6 +85,6 @@
8585
<tt>&lt;verbatim&nbsp;type="pikchr"&gt;...&lt;/verbatim&gt;</tt>
8686
is formatted using <a href="https://pikchr.org/home">Pikchr</a>.
8787
8888
8989
<a name="intermap"></a>
90
-<h2>Interwiki Tag Map</h2>
90
+<h2>Interwiki Tag [/intermap|Map]</h2>
9191
--- src/wiki.wiki
+++ src/wiki.wiki
@@ -85,6 +85,6 @@
85 <tt>&lt;verbatim&nbsp;type="pikchr"&gt;...&lt;/verbatim&gt;</tt>
86 is formatted using <a href="https://pikchr.org/home">Pikchr</a>.
87
88
89 <a name="intermap"></a>
90 <h2>Interwiki Tag Map</h2>
91
--- src/wiki.wiki
+++ src/wiki.wiki
@@ -85,6 +85,6 @@
85 <tt>&lt;verbatim&nbsp;type="pikchr"&gt;...&lt;/verbatim&gt;</tt>
86 is formatted using <a href="https://pikchr.org/home">Pikchr</a>.
87
88
89 <a name="intermap"></a>
90 <h2>Interwiki Tag [/intermap|Map]</h2>
91
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -2767,11 +2767,11 @@
27672767
**
27682768
** 1. Remove any elements that are not on the AllowedMarkup list.
27692769
** (ex: <script>, <form>, etc.)
27702770
**
27712771
** 2. Remove any attributes that are not on the AllowedMarkup list.
2772
-** (ex: onload=, id=, etc.)
2772
+** (ex: onload=, etc.)
27732773
**
27742774
** 3. Omit any surplus close-tags. This prevents the script from
27752775
** terminating an <div> or similar in the outer context.
27762776
**
27772777
** 4. Insert additional close-tags as necessary so that any
@@ -2778,11 +2778,11 @@
27782778
** tag in the input that needs a close-tag has one. This
27792779
** prevents tags in the embedded script from affecting the
27802780
** display of content that follows this script in the enclosing
27812781
** context.
27822782
**
2783
-** This modifications are intended to make the generated HTML safe
2783
+** These modifications are intended to make the generated HTML safe
27842784
** to be embedded in a larger HTML document, such that the embedded
27852785
** HTML has no influence on the formatting and operation of the
27862786
** larger document.
27872787
**
27882788
** If safe-html is disabled, then this routine is a no-op.
27892789
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -2767,11 +2767,11 @@
2767 **
2768 ** 1. Remove any elements that are not on the AllowedMarkup list.
2769 ** (ex: <script>, <form>, etc.)
2770 **
2771 ** 2. Remove any attributes that are not on the AllowedMarkup list.
2772 ** (ex: onload=, id=, etc.)
2773 **
2774 ** 3. Omit any surplus close-tags. This prevents the script from
2775 ** terminating an <div> or similar in the outer context.
2776 **
2777 ** 4. Insert additional close-tags as necessary so that any
@@ -2778,11 +2778,11 @@
2778 ** tag in the input that needs a close-tag has one. This
2779 ** prevents tags in the embedded script from affecting the
2780 ** display of content that follows this script in the enclosing
2781 ** context.
2782 **
2783 ** This modifications are intended to make the generated HTML safe
2784 ** to be embedded in a larger HTML document, such that the embedded
2785 ** HTML has no influence on the formatting and operation of the
2786 ** larger document.
2787 **
2788 ** If safe-html is disabled, then this routine is a no-op.
2789
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -2767,11 +2767,11 @@
2767 **
2768 ** 1. Remove any elements that are not on the AllowedMarkup list.
2769 ** (ex: <script>, <form>, etc.)
2770 **
2771 ** 2. Remove any attributes that are not on the AllowedMarkup list.
2772 ** (ex: onload=, etc.)
2773 **
2774 ** 3. Omit any surplus close-tags. This prevents the script from
2775 ** terminating an <div> or similar in the outer context.
2776 **
2777 ** 4. Insert additional close-tags as necessary so that any
@@ -2778,11 +2778,11 @@
2778 ** tag in the input that needs a close-tag has one. This
2779 ** prevents tags in the embedded script from affecting the
2780 ** display of content that follows this script in the enclosing
2781 ** context.
2782 **
2783 ** These modifications are intended to make the generated HTML safe
2784 ** to be embedded in a larger HTML document, such that the embedded
2785 ** HTML has no influence on the formatting and operation of the
2786 ** larger document.
2787 **
2788 ** If safe-html is disabled, then this routine is a no-op.
2789
+5 -5
--- src/winhttp.c
+++ src/winhttp.c
@@ -540,19 +540,19 @@
540540
if( PB("HTTPS") ){
541541
blob_appendf(&options, " --https");
542542
}
543543
if( zBaseUrl ){
544544
blob_appendf(&options, " --baseurl ");
545
- blob_append_escaped_arg(&options, zBaseUrl);
545
+ blob_append_escaped_arg(&options, zBaseUrl, 0);
546546
}
547547
if( zNotFound ){
548548
blob_appendf(&options, " --notfound ");
549
- blob_append_escaped_arg(&options, zNotFound);
549
+ blob_append_escaped_arg(&options, zNotFound, 1);
550550
}
551551
if( g.zCkoutAlias ){
552552
blob_appendf(&options, " --ckout-alias ");
553
- blob_append_escaped_arg(&options, g.zCkoutAlias);
553
+ blob_append_escaped_arg(&options, g.zCkoutAlias, 0);
554554
}
555555
if( zFileGlob ){
556556
blob_appendf(&options, " --files-urlenc %T", zFileGlob);
557557
}
558558
if( g.useLocalauth ){
@@ -564,19 +564,19 @@
564564
if( flags & HTTP_SERVER_REPOLIST ){
565565
blob_appendf(&options, " --repolist");
566566
}
567567
if( g.zExtRoot && g.zExtRoot[0] ){
568568
blob_appendf(&options, " --extroot");
569
- blob_append_escaped_arg(&options, g.zExtRoot);
569
+ blob_append_escaped_arg(&options, g.zExtRoot, 1);
570570
}
571571
zSkin = skin_in_use();
572572
if( zSkin ){
573573
blob_appendf(&options, " --skin %s", zSkin);
574574
}
575575
if( g.zMainMenuFile ){
576576
blob_appendf(&options, " --mainmenu ");
577
- blob_append_escaped_arg(&options, g.zMainMenuFile);
577
+ blob_append_escaped_arg(&options, g.zMainMenuFile, 1);
578578
}
579579
#if USE_SEE
580580
zSavedKey = db_get_saved_encryption_key();
581581
savedKeySize = db_get_saved_encryption_key_size();
582582
if( zSavedKey!=0 && savedKeySize>0 ){
583583
--- src/winhttp.c
+++ src/winhttp.c
@@ -540,19 +540,19 @@
540 if( PB("HTTPS") ){
541 blob_appendf(&options, " --https");
542 }
543 if( zBaseUrl ){
544 blob_appendf(&options, " --baseurl ");
545 blob_append_escaped_arg(&options, zBaseUrl);
546 }
547 if( zNotFound ){
548 blob_appendf(&options, " --notfound ");
549 blob_append_escaped_arg(&options, zNotFound);
550 }
551 if( g.zCkoutAlias ){
552 blob_appendf(&options, " --ckout-alias ");
553 blob_append_escaped_arg(&options, g.zCkoutAlias);
554 }
555 if( zFileGlob ){
556 blob_appendf(&options, " --files-urlenc %T", zFileGlob);
557 }
558 if( g.useLocalauth ){
@@ -564,19 +564,19 @@
564 if( flags & HTTP_SERVER_REPOLIST ){
565 blob_appendf(&options, " --repolist");
566 }
567 if( g.zExtRoot && g.zExtRoot[0] ){
568 blob_appendf(&options, " --extroot");
569 blob_append_escaped_arg(&options, g.zExtRoot);
570 }
571 zSkin = skin_in_use();
572 if( zSkin ){
573 blob_appendf(&options, " --skin %s", zSkin);
574 }
575 if( g.zMainMenuFile ){
576 blob_appendf(&options, " --mainmenu ");
577 blob_append_escaped_arg(&options, g.zMainMenuFile);
578 }
579 #if USE_SEE
580 zSavedKey = db_get_saved_encryption_key();
581 savedKeySize = db_get_saved_encryption_key_size();
582 if( zSavedKey!=0 && savedKeySize>0 ){
583
--- src/winhttp.c
+++ src/winhttp.c
@@ -540,19 +540,19 @@
540 if( PB("HTTPS") ){
541 blob_appendf(&options, " --https");
542 }
543 if( zBaseUrl ){
544 blob_appendf(&options, " --baseurl ");
545 blob_append_escaped_arg(&options, zBaseUrl, 0);
546 }
547 if( zNotFound ){
548 blob_appendf(&options, " --notfound ");
549 blob_append_escaped_arg(&options, zNotFound, 1);
550 }
551 if( g.zCkoutAlias ){
552 blob_appendf(&options, " --ckout-alias ");
553 blob_append_escaped_arg(&options, g.zCkoutAlias, 0);
554 }
555 if( zFileGlob ){
556 blob_appendf(&options, " --files-urlenc %T", zFileGlob);
557 }
558 if( g.useLocalauth ){
@@ -564,19 +564,19 @@
564 if( flags & HTTP_SERVER_REPOLIST ){
565 blob_appendf(&options, " --repolist");
566 }
567 if( g.zExtRoot && g.zExtRoot[0] ){
568 blob_appendf(&options, " --extroot");
569 blob_append_escaped_arg(&options, g.zExtRoot, 1);
570 }
571 zSkin = skin_in_use();
572 if( zSkin ){
573 blob_appendf(&options, " --skin %s", zSkin);
574 }
575 if( g.zMainMenuFile ){
576 blob_appendf(&options, " --mainmenu ");
577 blob_append_escaped_arg(&options, g.zMainMenuFile, 1);
578 }
579 #if USE_SEE
580 zSavedKey = db_get_saved_encryption_key();
581 savedKeySize = db_get_saved_encryption_key_size();
582 if( zSavedKey!=0 && savedKeySize>0 ){
583
+71 -40
--- src/xfer.c
+++ src/xfer.c
@@ -1061,29 +1061,27 @@
10611061
** If HASH is different from the unversioned content hash on this server,
10621062
** then send a bunch of uvigot cards, one for each entry unversioned file
10631063
** on this server.
10641064
*/
10651065
static void send_unversioned_catalog(Xfer *pXfer){
1066
+ int nUvIgot = 0;
1067
+ Stmt uvq;
10661068
unversioned_schema();
1067
- if( !blob_eq(&pXfer->aToken[2], unversioned_content_hash(0)) ){
1068
- int nUvIgot = 0;
1069
- Stmt uvq;
1070
- db_prepare(&uvq,
1071
- "SELECT name, mtime, hash, sz FROM unversioned"
1072
- );
1073
- while( db_step(&uvq)==SQLITE_ROW ){
1074
- const char *zName = db_column_text(&uvq,0);
1075
- sqlite3_int64 mtime = db_column_int64(&uvq,1);
1076
- const char *zHash = db_column_text(&uvq,2);
1077
- int sz = db_column_int(&uvq,3);
1078
- nUvIgot++;
1079
- if( zHash==0 ){ sz = 0; zHash = "-"; }
1080
- blob_appendf(pXfer->pOut, "uvigot %s %lld %s %d\n",
1081
- zName, mtime, zHash, sz);
1082
- }
1083
- db_finalize(&uvq);
1084
- }
1069
+ db_prepare(&uvq,
1070
+ "SELECT name, mtime, hash, sz FROM unversioned"
1071
+ );
1072
+ while( db_step(&uvq)==SQLITE_ROW ){
1073
+ const char *zName = db_column_text(&uvq,0);
1074
+ sqlite3_int64 mtime = db_column_int64(&uvq,1);
1075
+ const char *zHash = db_column_text(&uvq,2);
1076
+ int sz = db_column_int(&uvq,3);
1077
+ nUvIgot++;
1078
+ if( zHash==0 ){ sz = 0; zHash = "-"; }
1079
+ blob_appendf(pXfer->pOut, "uvigot %s %lld %s %d\n",
1080
+ zName, mtime, zHash, sz);
1081
+ }
1082
+ db_finalize(&uvq);
10851083
}
10861084
10871085
/*
10881086
** Called when there is an attempt to transfer private content to and
10891087
** from a server without authorization.
@@ -1616,18 +1614,20 @@
16161614
** "uvigot" cards.
16171615
*/
16181616
if( blob_eq(&xfer.aToken[1], "uv-hash")
16191617
&& blob_is_hname(&xfer.aToken[2])
16201618
){
1621
- if( !uvCatalogSent ){
1622
- if( g.perm.Read && g.perm.WrUnver ){
1619
+ if( !uvCatalogSent
1620
+ && g.perm.Read
1621
+ && !blob_eq_str(&xfer.aToken[2], unversioned_content_hash(0),-1)
1622
+ ){
1623
+ if( g.perm.WrUnver ){
16231624
@ pragma uv-push-ok
1624
- send_unversioned_catalog(&xfer);
16251625
}else if( g.perm.Read ){
16261626
@ pragma uv-pull-only
1627
- send_unversioned_catalog(&xfer);
16281627
}
1628
+ send_unversioned_catalog(&xfer);
16291629
}
16301630
uvCatalogSent = 1;
16311631
}
16321632
16331633
/* pragma ci-lock CHECKIN-HASH CLIENT-ID
@@ -1813,17 +1813,18 @@
18131813
#define SYNC_PULL 0x0002 /* pull content server to client */
18141814
#define SYNC_CLONE 0x0004 /* clone the repository */
18151815
#define SYNC_PRIVATE 0x0008 /* Also transfer private content */
18161816
#define SYNC_VERBOSE 0x0010 /* Extra diagnostics */
18171817
#define SYNC_RESYNC 0x0020 /* --verily */
1818
-#define SYNC_UNVERSIONED 0x0040 /* Sync unversioned content */
1819
-#define SYNC_UV_REVERT 0x0080 /* Copy server unversioned to client */
1820
-#define SYNC_FROMPARENT 0x0100 /* Pull from the parent project */
1821
-#define SYNC_UV_TRACE 0x0200 /* Describe UV activities */
1822
-#define SYNC_UV_DRYRUN 0x0400 /* Do not actually exchange files */
1823
-#define SYNC_IFABLE 0x0800 /* Inability to sync is not fatal */
1824
-#define SYNC_CKIN_LOCK 0x1000 /* Lock the current check-in */
1818
+#define SYNC_FROMPARENT 0x0040 /* Pull from the parent project */
1819
+#define SYNC_UNVERSIONED 0x0100 /* Sync unversioned content */
1820
+#define SYNC_UV_REVERT 0x0200 /* Copy server unversioned to client */
1821
+#define SYNC_UV_TRACE 0x0400 /* Describe UV activities */
1822
+#define SYNC_UV_DRYRUN 0x0800 /* Do not actually exchange files */
1823
+#define SYNC_IFABLE 0x1000 /* Inability to sync is not fatal */
1824
+#define SYNC_CKIN_LOCK 0x2000 /* Lock the current check-in */
1825
+#define SYNC_NOHTTPCOMPRESS 0x4000 /* Do not compression HTTP messages */
18251826
#endif
18261827
18271828
/*
18281829
** Floating-point absolute value
18291830
*/
@@ -1852,10 +1853,11 @@
18521853
int size; /* Size of a config value or uvfile */
18531854
int origConfigRcvMask; /* Original value of configRcvMask */
18541855
int nFileRecv; /* Number of files received */
18551856
int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
18561857
const char *zCookie; /* Server cookie */
1858
+ i64 nUncSent, nUncRcvd; /* Bytes sent and received (before compression) */
18571859
i64 nSent, nRcvd; /* Bytes sent and received (after compression) */
18581860
int cloneSeqno = 1; /* Sequence number for clones */
18591861
Blob send; /* Text we are sending to the server */
18601862
Blob recv; /* Reply we got back from the server */
18611863
Xfer xfer; /* Transfer data */
@@ -1870,10 +1872,11 @@
18701872
int nArtifactRcvd = 0; /* Total artifacts received */
18711873
const char *zOpType = 0;/* Push, Pull, Sync, Clone */
18721874
double rSkew = 0.0; /* Maximum time skew */
18731875
int uvHashSent = 0; /* The "pragma uv-hash" message has been sent */
18741876
int uvDoPush = 0; /* Generate uvfile messages to send to server */
1877
+ int uvPullOnly = 0; /* 1: pull-only. 2: pull-only warning issued */
18751878
int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
18761879
int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
18771880
sqlite3_int64 mtime; /* Modification time on a UV file */
18781881
int autopushFailed = 0; /* Autopush following commit failed if true */
18791882
const char *zCkinLock; /* Name of check-in to lock. NULL for none */
@@ -1912,10 +1915,11 @@
19121915
blob_zero(&send);
19131916
blob_zero(&recv);
19141917
blob_zero(&xfer.err);
19151918
blob_zero(&xfer.line);
19161919
origConfigRcvMask = 0;
1920
+ nUncSent = nUncRcvd = 0;
19171921
19181922
/* Send the send-private pragma if we are trying to sync private data */
19191923
if( syncFlags & SYNC_PRIVATE ){
19201924
blob_append(&send, "pragma send-private\n", -1);
19211925
}
@@ -2125,15 +2129,29 @@
21252129
/* Do not send a login card on the first round-trip of a clone */
21262130
mHttpFlags = 0;
21272131
}else{
21282132
mHttpFlags = HTTP_USE_LOGIN;
21292133
}
2134
+ if( syncFlags & SYNC_NOHTTPCOMPRESS ){
2135
+ mHttpFlags |= HTTP_NOCOMPRESS;
2136
+ }
2137
+
2138
+ /* Do the round-trip to the server */
21302139
if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
21312140
nErr++;
21322141
go = 2;
21332142
break;
21342143
}
2144
+
2145
+ /* Remember the URL of the sync target in the config file on the
2146
+ ** first successful round-trip */
2147
+ if( nCycle==0 && db_is_writeable("repository") ){
2148
+ db_unprotect(PROTECT_CONFIG);
2149
+ db_multi_exec("REPLACE INTO config(name,value,mtime)"
2150
+ "VALUES('syncwith:%q',1,now())", g.url.canonical);
2151
+ db_protect_pop();
2152
+ }
21352153
21362154
/* Output current stats */
21372155
if( syncFlags & SYNC_VERBOSE ){
21382156
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
21392157
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
@@ -2151,10 +2169,11 @@
21512169
xfer.nGimmeSent = 0;
21522170
xfer.nIGotSent = 0;
21532171
xfer.nPrivIGot = 0;
21542172
21552173
lastPctDone = -1;
2174
+ nUncSent += blob_size(&send);
21562175
blob_reset(&send);
21572176
blob_appendf(&send, "pragma client-version %d %d %d\n",
21582177
RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE,
21592178
MANIFEST_NUMERIC_TIME);
21602179
rArrivalTime = db_double(0.0, "SELECT julianday('now')");
@@ -2356,11 +2375,19 @@
23562375
db_multi_exec(
23572376
"UPDATE unversioned SET mtime=%lld WHERE name=%Q", mtime, zName
23582377
);
23592378
db_unset("uv-hash", 0);
23602379
}
2361
- if( iStatus<=3 ){
2380
+ if( iStatus>=4 && uvPullOnly==1 ){
2381
+ fossil_warning(
2382
+ "Warning: uv-pull-only \n"
2383
+ " Unable to push unversioned content because you lack\n"
2384
+ " sufficient permission on the server\n"
2385
+ );
2386
+ uvPullOnly = 2;
2387
+ }
2388
+ if( iStatus<=3 || uvPullOnly ){
23622389
db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName);
23632390
}else if( iStatus==4 ){
23642391
db_multi_exec("UPDATE uv_tosend SET mtimeOnly=1 WHERE name=%Q",zName);
23652392
}else if( iStatus==5 ){
23662393
db_multi_exec("REPLACE INTO uv_tosend(name,mtimeOnly) VALUES(%Q,0)",
@@ -2485,26 +2512,25 @@
24852512
xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
24862513
}
24872514
}
24882515
24892516
/* pragma uv-pull-only
2517
+ ** pragma uv-push-ok
24902518
**
24912519
** If the server is unwill to accept new unversioned content (because
24922520
** this client lacks the necessary permissions) then it sends a
24932521
** "uv-pull-only" pragma so that the client will know not to waste
24942522
** bandwidth trying to upload unversioned content. If the server
24952523
** does accept new unversioned content, it sends "uv-push-ok".
24962524
*/
2497
- if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){
2498
- fossil_print(
2499
- "Warning: uv-pull-only \n"
2500
- " Unable to push unversioned content because you lack\n"
2501
- " sufficient permission on the server\n"
2502
- );
2503
- if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1;
2504
- }else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){
2505
- uvDoPush = 1;
2525
+ if( syncFlags & SYNC_UNVERSIONED ){
2526
+ if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){
2527
+ uvPullOnly = 1;
2528
+ if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1;
2529
+ }else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){
2530
+ uvDoPush = 1;
2531
+ }
25062532
}
25072533
25082534
/* pragma ci-lock-fail USER-HOLDING-LOCK LOCK-TIME
25092535
**
25102536
** The server generates this message when a "pragma ci-lock"
@@ -2598,10 +2624,11 @@
25982624
xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
25992625
}else{
26002626
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
26012627
nRoundtrip, nArtifactSent, nArtifactRcvd);
26022628
}
2629
+ nUncRcvd += blob_size(&recv);
26032630
blob_reset(&recv);
26042631
nCycle++;
26052632
26062633
/* If we received one or more files on the previous exchange but
26072634
** there are still phantoms, then go another round.
@@ -2661,12 +2688,16 @@
26612688
g.clockSkewSeen = 1;
26622689
}
26632690
26642691
fossil_force_newline();
26652692
fossil_print(
2666
- "%s done, sent: %lld received: %lld ip: %s\n",
2693
+ "%s done, wire bytes sent: %lld received: %lld ip: %s\n",
26672694
zOpType, nSent, nRcvd, g.zIpAddr);
2695
+ if( syncFlags & SYNC_VERBOSE ){
2696
+ fossil_print(
2697
+ "Uncompressed payload sent: %lld received: %lld\n", nUncSent, nUncRcvd);
2698
+ }
26682699
transport_close(&g.url);
26692700
transport_global_shutdown(&g.url);
26702701
if( nErr && go==2 ){
26712702
db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");
26722703
manifest_crosslink_end(MC_PERMIT_HOOKS);
26732704
--- src/xfer.c
+++ src/xfer.c
@@ -1061,29 +1061,27 @@
1061 ** If HASH is different from the unversioned content hash on this server,
1062 ** then send a bunch of uvigot cards, one for each entry unversioned file
1063 ** on this server.
1064 */
1065 static void send_unversioned_catalog(Xfer *pXfer){
 
 
1066 unversioned_schema();
1067 if( !blob_eq(&pXfer->aToken[2], unversioned_content_hash(0)) ){
1068 int nUvIgot = 0;
1069 Stmt uvq;
1070 db_prepare(&uvq,
1071 "SELECT name, mtime, hash, sz FROM unversioned"
1072 );
1073 while( db_step(&uvq)==SQLITE_ROW ){
1074 const char *zName = db_column_text(&uvq,0);
1075 sqlite3_int64 mtime = db_column_int64(&uvq,1);
1076 const char *zHash = db_column_text(&uvq,2);
1077 int sz = db_column_int(&uvq,3);
1078 nUvIgot++;
1079 if( zHash==0 ){ sz = 0; zHash = "-"; }
1080 blob_appendf(pXfer->pOut, "uvigot %s %lld %s %d\n",
1081 zName, mtime, zHash, sz);
1082 }
1083 db_finalize(&uvq);
1084 }
1085 }
1086
1087 /*
1088 ** Called when there is an attempt to transfer private content to and
1089 ** from a server without authorization.
@@ -1616,18 +1614,20 @@
1616 ** "uvigot" cards.
1617 */
1618 if( blob_eq(&xfer.aToken[1], "uv-hash")
1619 && blob_is_hname(&xfer.aToken[2])
1620 ){
1621 if( !uvCatalogSent ){
1622 if( g.perm.Read && g.perm.WrUnver ){
 
 
 
1623 @ pragma uv-push-ok
1624 send_unversioned_catalog(&xfer);
1625 }else if( g.perm.Read ){
1626 @ pragma uv-pull-only
1627 send_unversioned_catalog(&xfer);
1628 }
 
1629 }
1630 uvCatalogSent = 1;
1631 }
1632
1633 /* pragma ci-lock CHECKIN-HASH CLIENT-ID
@@ -1813,17 +1813,18 @@
1813 #define SYNC_PULL 0x0002 /* pull content server to client */
1814 #define SYNC_CLONE 0x0004 /* clone the repository */
1815 #define SYNC_PRIVATE 0x0008 /* Also transfer private content */
1816 #define SYNC_VERBOSE 0x0010 /* Extra diagnostics */
1817 #define SYNC_RESYNC 0x0020 /* --verily */
1818 #define SYNC_UNVERSIONED 0x0040 /* Sync unversioned content */
1819 #define SYNC_UV_REVERT 0x0080 /* Copy server unversioned to client */
1820 #define SYNC_FROMPARENT 0x0100 /* Pull from the parent project */
1821 #define SYNC_UV_TRACE 0x0200 /* Describe UV activities */
1822 #define SYNC_UV_DRYRUN 0x0400 /* Do not actually exchange files */
1823 #define SYNC_IFABLE 0x0800 /* Inability to sync is not fatal */
1824 #define SYNC_CKIN_LOCK 0x1000 /* Lock the current check-in */
 
1825 #endif
1826
1827 /*
1828 ** Floating-point absolute value
1829 */
@@ -1852,10 +1853,11 @@
1852 int size; /* Size of a config value or uvfile */
1853 int origConfigRcvMask; /* Original value of configRcvMask */
1854 int nFileRecv; /* Number of files received */
1855 int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
1856 const char *zCookie; /* Server cookie */
 
1857 i64 nSent, nRcvd; /* Bytes sent and received (after compression) */
1858 int cloneSeqno = 1; /* Sequence number for clones */
1859 Blob send; /* Text we are sending to the server */
1860 Blob recv; /* Reply we got back from the server */
1861 Xfer xfer; /* Transfer data */
@@ -1870,10 +1872,11 @@
1870 int nArtifactRcvd = 0; /* Total artifacts received */
1871 const char *zOpType = 0;/* Push, Pull, Sync, Clone */
1872 double rSkew = 0.0; /* Maximum time skew */
1873 int uvHashSent = 0; /* The "pragma uv-hash" message has been sent */
1874 int uvDoPush = 0; /* Generate uvfile messages to send to server */
 
1875 int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
1876 int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1877 sqlite3_int64 mtime; /* Modification time on a UV file */
1878 int autopushFailed = 0; /* Autopush following commit failed if true */
1879 const char *zCkinLock; /* Name of check-in to lock. NULL for none */
@@ -1912,10 +1915,11 @@
1912 blob_zero(&send);
1913 blob_zero(&recv);
1914 blob_zero(&xfer.err);
1915 blob_zero(&xfer.line);
1916 origConfigRcvMask = 0;
 
1917
1918 /* Send the send-private pragma if we are trying to sync private data */
1919 if( syncFlags & SYNC_PRIVATE ){
1920 blob_append(&send, "pragma send-private\n", -1);
1921 }
@@ -2125,15 +2129,29 @@
2125 /* Do not send a login card on the first round-trip of a clone */
2126 mHttpFlags = 0;
2127 }else{
2128 mHttpFlags = HTTP_USE_LOGIN;
2129 }
 
 
 
 
 
2130 if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
2131 nErr++;
2132 go = 2;
2133 break;
2134 }
 
 
 
 
 
 
 
 
 
2135
2136 /* Output current stats */
2137 if( syncFlags & SYNC_VERBOSE ){
2138 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
2139 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
@@ -2151,10 +2169,11 @@
2151 xfer.nGimmeSent = 0;
2152 xfer.nIGotSent = 0;
2153 xfer.nPrivIGot = 0;
2154
2155 lastPctDone = -1;
 
2156 blob_reset(&send);
2157 blob_appendf(&send, "pragma client-version %d %d %d\n",
2158 RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE,
2159 MANIFEST_NUMERIC_TIME);
2160 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
@@ -2356,11 +2375,19 @@
2356 db_multi_exec(
2357 "UPDATE unversioned SET mtime=%lld WHERE name=%Q", mtime, zName
2358 );
2359 db_unset("uv-hash", 0);
2360 }
2361 if( iStatus<=3 ){
 
 
 
 
 
 
 
 
2362 db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName);
2363 }else if( iStatus==4 ){
2364 db_multi_exec("UPDATE uv_tosend SET mtimeOnly=1 WHERE name=%Q",zName);
2365 }else if( iStatus==5 ){
2366 db_multi_exec("REPLACE INTO uv_tosend(name,mtimeOnly) VALUES(%Q,0)",
@@ -2485,26 +2512,25 @@
2485 xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
2486 }
2487 }
2488
2489 /* pragma uv-pull-only
 
2490 **
2491 ** If the server is unwill to accept new unversioned content (because
2492 ** this client lacks the necessary permissions) then it sends a
2493 ** "uv-pull-only" pragma so that the client will know not to waste
2494 ** bandwidth trying to upload unversioned content. If the server
2495 ** does accept new unversioned content, it sends "uv-push-ok".
2496 */
2497 if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){
2498 fossil_print(
2499 "Warning: uv-pull-only \n"
2500 " Unable to push unversioned content because you lack\n"
2501 " sufficient permission on the server\n"
2502 );
2503 if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1;
2504 }else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){
2505 uvDoPush = 1;
2506 }
2507
2508 /* pragma ci-lock-fail USER-HOLDING-LOCK LOCK-TIME
2509 **
2510 ** The server generates this message when a "pragma ci-lock"
@@ -2598,10 +2624,11 @@
2598 xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
2599 }else{
2600 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2601 nRoundtrip, nArtifactSent, nArtifactRcvd);
2602 }
 
2603 blob_reset(&recv);
2604 nCycle++;
2605
2606 /* If we received one or more files on the previous exchange but
2607 ** there are still phantoms, then go another round.
@@ -2661,12 +2688,16 @@
2661 g.clockSkewSeen = 1;
2662 }
2663
2664 fossil_force_newline();
2665 fossil_print(
2666 "%s done, sent: %lld received: %lld ip: %s\n",
2667 zOpType, nSent, nRcvd, g.zIpAddr);
 
 
 
 
2668 transport_close(&g.url);
2669 transport_global_shutdown(&g.url);
2670 if( nErr && go==2 ){
2671 db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");
2672 manifest_crosslink_end(MC_PERMIT_HOOKS);
2673
--- src/xfer.c
+++ src/xfer.c
@@ -1061,29 +1061,27 @@
1061 ** If HASH is different from the unversioned content hash on this server,
1062 ** then send a bunch of uvigot cards, one for each entry unversioned file
1063 ** on this server.
1064 */
1065 static void send_unversioned_catalog(Xfer *pXfer){
1066 int nUvIgot = 0;
1067 Stmt uvq;
1068 unversioned_schema();
1069 db_prepare(&uvq,
1070 "SELECT name, mtime, hash, sz FROM unversioned"
1071 );
1072 while( db_step(&uvq)==SQLITE_ROW ){
1073 const char *zName = db_column_text(&uvq,0);
1074 sqlite3_int64 mtime = db_column_int64(&uvq,1);
1075 const char *zHash = db_column_text(&uvq,2);
1076 int sz = db_column_int(&uvq,3);
1077 nUvIgot++;
1078 if( zHash==0 ){ sz = 0; zHash = "-"; }
1079 blob_appendf(pXfer->pOut, "uvigot %s %lld %s %d\n",
1080 zName, mtime, zHash, sz);
1081 }
1082 db_finalize(&uvq);
 
 
 
 
1083 }
1084
1085 /*
1086 ** Called when there is an attempt to transfer private content to and
1087 ** from a server without authorization.
@@ -1616,18 +1614,20 @@
1614 ** "uvigot" cards.
1615 */
1616 if( blob_eq(&xfer.aToken[1], "uv-hash")
1617 && blob_is_hname(&xfer.aToken[2])
1618 ){
1619 if( !uvCatalogSent
1620 && g.perm.Read
1621 && !blob_eq_str(&xfer.aToken[2], unversioned_content_hash(0),-1)
1622 ){
1623 if( g.perm.WrUnver ){
1624 @ pragma uv-push-ok
 
1625 }else if( g.perm.Read ){
1626 @ pragma uv-pull-only
 
1627 }
1628 send_unversioned_catalog(&xfer);
1629 }
1630 uvCatalogSent = 1;
1631 }
1632
1633 /* pragma ci-lock CHECKIN-HASH CLIENT-ID
@@ -1813,17 +1813,18 @@
1813 #define SYNC_PULL 0x0002 /* pull content server to client */
1814 #define SYNC_CLONE 0x0004 /* clone the repository */
1815 #define SYNC_PRIVATE 0x0008 /* Also transfer private content */
1816 #define SYNC_VERBOSE 0x0010 /* Extra diagnostics */
1817 #define SYNC_RESYNC 0x0020 /* --verily */
1818 #define SYNC_FROMPARENT 0x0040 /* Pull from the parent project */
1819 #define SYNC_UNVERSIONED 0x0100 /* Sync unversioned content */
1820 #define SYNC_UV_REVERT 0x0200 /* Copy server unversioned to client */
1821 #define SYNC_UV_TRACE 0x0400 /* Describe UV activities */
1822 #define SYNC_UV_DRYRUN 0x0800 /* Do not actually exchange files */
1823 #define SYNC_IFABLE 0x1000 /* Inability to sync is not fatal */
1824 #define SYNC_CKIN_LOCK 0x2000 /* Lock the current check-in */
1825 #define SYNC_NOHTTPCOMPRESS 0x4000 /* Do not compression HTTP messages */
1826 #endif
1827
1828 /*
1829 ** Floating-point absolute value
1830 */
@@ -1852,10 +1853,11 @@
1853 int size; /* Size of a config value or uvfile */
1854 int origConfigRcvMask; /* Original value of configRcvMask */
1855 int nFileRecv; /* Number of files received */
1856 int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
1857 const char *zCookie; /* Server cookie */
1858 i64 nUncSent, nUncRcvd; /* Bytes sent and received (before compression) */
1859 i64 nSent, nRcvd; /* Bytes sent and received (after compression) */
1860 int cloneSeqno = 1; /* Sequence number for clones */
1861 Blob send; /* Text we are sending to the server */
1862 Blob recv; /* Reply we got back from the server */
1863 Xfer xfer; /* Transfer data */
@@ -1870,10 +1872,11 @@
1872 int nArtifactRcvd = 0; /* Total artifacts received */
1873 const char *zOpType = 0;/* Push, Pull, Sync, Clone */
1874 double rSkew = 0.0; /* Maximum time skew */
1875 int uvHashSent = 0; /* The "pragma uv-hash" message has been sent */
1876 int uvDoPush = 0; /* Generate uvfile messages to send to server */
1877 int uvPullOnly = 0; /* 1: pull-only. 2: pull-only warning issued */
1878 int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */
1879 int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1880 sqlite3_int64 mtime; /* Modification time on a UV file */
1881 int autopushFailed = 0; /* Autopush following commit failed if true */
1882 const char *zCkinLock; /* Name of check-in to lock. NULL for none */
@@ -1912,10 +1915,11 @@
1915 blob_zero(&send);
1916 blob_zero(&recv);
1917 blob_zero(&xfer.err);
1918 blob_zero(&xfer.line);
1919 origConfigRcvMask = 0;
1920 nUncSent = nUncRcvd = 0;
1921
1922 /* Send the send-private pragma if we are trying to sync private data */
1923 if( syncFlags & SYNC_PRIVATE ){
1924 blob_append(&send, "pragma send-private\n", -1);
1925 }
@@ -2125,15 +2129,29 @@
2129 /* Do not send a login card on the first round-trip of a clone */
2130 mHttpFlags = 0;
2131 }else{
2132 mHttpFlags = HTTP_USE_LOGIN;
2133 }
2134 if( syncFlags & SYNC_NOHTTPCOMPRESS ){
2135 mHttpFlags |= HTTP_NOCOMPRESS;
2136 }
2137
2138 /* Do the round-trip to the server */
2139 if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
2140 nErr++;
2141 go = 2;
2142 break;
2143 }
2144
2145 /* Remember the URL of the sync target in the config file on the
2146 ** first successful round-trip */
2147 if( nCycle==0 && db_is_writeable("repository") ){
2148 db_unprotect(PROTECT_CONFIG);
2149 db_multi_exec("REPLACE INTO config(name,value,mtime)"
2150 "VALUES('syncwith:%q',1,now())", g.url.canonical);
2151 db_protect_pop();
2152 }
2153
2154 /* Output current stats */
2155 if( syncFlags & SYNC_VERBOSE ){
2156 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
2157 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
@@ -2151,10 +2169,11 @@
2169 xfer.nGimmeSent = 0;
2170 xfer.nIGotSent = 0;
2171 xfer.nPrivIGot = 0;
2172
2173 lastPctDone = -1;
2174 nUncSent += blob_size(&send);
2175 blob_reset(&send);
2176 blob_appendf(&send, "pragma client-version %d %d %d\n",
2177 RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE,
2178 MANIFEST_NUMERIC_TIME);
2179 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
@@ -2356,11 +2375,19 @@
2375 db_multi_exec(
2376 "UPDATE unversioned SET mtime=%lld WHERE name=%Q", mtime, zName
2377 );
2378 db_unset("uv-hash", 0);
2379 }
2380 if( iStatus>=4 && uvPullOnly==1 ){
2381 fossil_warning(
2382 "Warning: uv-pull-only \n"
2383 " Unable to push unversioned content because you lack\n"
2384 " sufficient permission on the server\n"
2385 );
2386 uvPullOnly = 2;
2387 }
2388 if( iStatus<=3 || uvPullOnly ){
2389 db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName);
2390 }else if( iStatus==4 ){
2391 db_multi_exec("UPDATE uv_tosend SET mtimeOnly=1 WHERE name=%Q",zName);
2392 }else if( iStatus==5 ){
2393 db_multi_exec("REPLACE INTO uv_tosend(name,mtimeOnly) VALUES(%Q,0)",
@@ -2485,26 +2512,25 @@
2512 xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
2513 }
2514 }
2515
2516 /* pragma uv-pull-only
2517 ** pragma uv-push-ok
2518 **
2519 ** If the server is unwill to accept new unversioned content (because
2520 ** this client lacks the necessary permissions) then it sends a
2521 ** "uv-pull-only" pragma so that the client will know not to waste
2522 ** bandwidth trying to upload unversioned content. If the server
2523 ** does accept new unversioned content, it sends "uv-push-ok".
2524 */
2525 if( syncFlags & SYNC_UNVERSIONED ){
2526 if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){
2527 uvPullOnly = 1;
2528 if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1;
2529 }else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){
2530 uvDoPush = 1;
2531 }
 
 
2532 }
2533
2534 /* pragma ci-lock-fail USER-HOLDING-LOCK LOCK-TIME
2535 **
2536 ** The server generates this message when a "pragma ci-lock"
@@ -2598,10 +2624,11 @@
2624 xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
2625 }else{
2626 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2627 nRoundtrip, nArtifactSent, nArtifactRcvd);
2628 }
2629 nUncRcvd += blob_size(&recv);
2630 blob_reset(&recv);
2631 nCycle++;
2632
2633 /* If we received one or more files on the previous exchange but
2634 ** there are still phantoms, then go another round.
@@ -2661,12 +2688,16 @@
2688 g.clockSkewSeen = 1;
2689 }
2690
2691 fossil_force_newline();
2692 fossil_print(
2693 "%s done, wire bytes sent: %lld received: %lld ip: %s\n",
2694 zOpType, nSent, nRcvd, g.zIpAddr);
2695 if( syncFlags & SYNC_VERBOSE ){
2696 fossil_print(
2697 "Uncompressed payload sent: %lld received: %lld\n", nUncSent, nUncRcvd);
2698 }
2699 transport_close(&g.url);
2700 transport_global_shutdown(&g.url);
2701 if( nErr && go==2 ){
2702 db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");
2703 manifest_crosslink_end(MC_PERMIT_HOOKS);
2704
+2 -2
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -120,20 +120,20 @@
120120
}
121121
style_set_current_feature("xfersetup");
122122
style_header("Edit %s", zTitle);
123123
if( P("clear")!=0 ){
124124
login_verify_csrf_secret();
125
- db_unset(zDbField, 0);
125
+ db_unset(zDbField/*works-like:"x"*/, 0);
126126
if( xRebuild ) xRebuild();
127127
z = zDfltValue;
128128
}else if( isSubmit ){
129129
char *zErr = 0;
130130
login_verify_csrf_secret();
131131
if( xText && (zErr = xText(z))!=0 ){
132132
@ <p class="xfersetupError">ERROR: %h(zErr)</p>
133133
}else{
134
- db_set(zDbField, z, 0);
134
+ db_set(zDbField/*works-like:"x"*/, z, 0);
135135
if( xRebuild ) xRebuild();
136136
cgi_redirect("xfersetup");
137137
}
138138
}
139139
@ <form action="%R/%s(g.zPath)" method="post"><div>
140140
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -120,20 +120,20 @@
120 }
121 style_set_current_feature("xfersetup");
122 style_header("Edit %s", zTitle);
123 if( P("clear")!=0 ){
124 login_verify_csrf_secret();
125 db_unset(zDbField, 0);
126 if( xRebuild ) xRebuild();
127 z = zDfltValue;
128 }else if( isSubmit ){
129 char *zErr = 0;
130 login_verify_csrf_secret();
131 if( xText && (zErr = xText(z))!=0 ){
132 @ <p class="xfersetupError">ERROR: %h(zErr)</p>
133 }else{
134 db_set(zDbField, z, 0);
135 if( xRebuild ) xRebuild();
136 cgi_redirect("xfersetup");
137 }
138 }
139 @ <form action="%R/%s(g.zPath)" method="post"><div>
140
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -120,20 +120,20 @@
120 }
121 style_set_current_feature("xfersetup");
122 style_header("Edit %s", zTitle);
123 if( P("clear")!=0 ){
124 login_verify_csrf_secret();
125 db_unset(zDbField/*works-like:"x"*/, 0);
126 if( xRebuild ) xRebuild();
127 z = zDfltValue;
128 }else if( isSubmit ){
129 char *zErr = 0;
130 login_verify_csrf_secret();
131 if( xText && (zErr = xText(z))!=0 ){
132 @ <p class="xfersetupError">ERROR: %h(zErr)</p>
133 }else{
134 db_set(zDbField/*works-like:"x"*/, z, 0);
135 if( xRebuild ) xRebuild();
136 cgi_redirect("xfersetup");
137 }
138 }
139 @ <form action="%R/%s(g.zPath)" method="post"><div>
140
+3
--- src/zip.c
+++ src/zip.c
@@ -940,10 +940,13 @@
940940
nRid = strlen(zRid);
941941
zInclude = P("in");
942942
if( zInclude ) pInclude = glob_create(zInclude);
943943
zExclude = P("ex");
944944
if( zExclude ) pExclude = glob_create(zExclude);
945
+ if( zInclude==0 && zExclude==0 ){
946
+ etag_check_for_invariant_name(z);
947
+ }
945948
if( eType==ARCHIVE_ZIP
946949
&& nName>4
947950
&& fossil_strcmp(&zName[nName-4], ".zip")==0
948951
){
949952
/* Special case: Remove the ".zip" suffix. */
950953
--- src/zip.c
+++ src/zip.c
@@ -940,10 +940,13 @@
940 nRid = strlen(zRid);
941 zInclude = P("in");
942 if( zInclude ) pInclude = glob_create(zInclude);
943 zExclude = P("ex");
944 if( zExclude ) pExclude = glob_create(zExclude);
 
 
 
945 if( eType==ARCHIVE_ZIP
946 && nName>4
947 && fossil_strcmp(&zName[nName-4], ".zip")==0
948 ){
949 /* Special case: Remove the ".zip" suffix. */
950
--- src/zip.c
+++ src/zip.c
@@ -940,10 +940,13 @@
940 nRid = strlen(zRid);
941 zInclude = P("in");
942 if( zInclude ) pInclude = glob_create(zInclude);
943 zExclude = P("ex");
944 if( zExclude ) pExclude = glob_create(zExclude);
945 if( zInclude==0 && zExclude==0 ){
946 etag_check_for_invariant_name(z);
947 }
948 if( eType==ARCHIVE_ZIP
949 && nName>4
950 && fossil_strcmp(&zName[nName-4], ".zip")==0
951 ){
952 /* Special case: Remove the ".zip" suffix. */
953
--- test/tester.tcl
+++ test/tester.tcl
@@ -351,10 +351,11 @@
351351
ssl-ca-location \
352352
ssl-identity \
353353
tclsh \
354354
th1-setup \
355355
th1-uri-regexp \
356
+ ticket-default-report \
356357
user-color-map \
357358
uv-sync \
358359
web-browser]
359360
360361
fossil test-th-eval "hasfeature legacyMvRm"
361362
--- test/tester.tcl
+++ test/tester.tcl
@@ -351,10 +351,11 @@
351 ssl-ca-location \
352 ssl-identity \
353 tclsh \
354 th1-setup \
355 th1-uri-regexp \
 
356 user-color-map \
357 uv-sync \
358 web-browser]
359
360 fossil test-th-eval "hasfeature legacyMvRm"
361
--- test/tester.tcl
+++ test/tester.tcl
@@ -351,10 +351,11 @@
351 ssl-ca-location \
352 ssl-identity \
353 tclsh \
354 th1-setup \
355 th1-uri-regexp \
356 ticket-default-report \
357 user-color-map \
358 uv-sync \
359 web-browser]
360
361 fossil test-th-eval "hasfeature legacyMvRm"
362
+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_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_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 ajax_.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 chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.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 fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.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 pikchr_.c pikchrshow_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c ajax_.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 chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.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 fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.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 patch_.c path_.c piechart_.c pikchr_.c pikchrshow_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$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)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$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)\fileedit$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)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$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)\pikchr$O $(OBJDIR)\pikchrshow$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)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$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)\ajax$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)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$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)\fileedit$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)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$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)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchr$O $(OBJDIR)\pikchrshow$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)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$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 ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki 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 pikchr pikchrshow 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 wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki 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 patch path piechart pikchr pikchrshow 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 wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -661,10 +661,16 @@
661661
$(OBJDIR)\name$O : name_.c name.h
662662
$(TCC) -o$@ -c name_.c
663663
664664
name_.c : $(SRCDIR)\name.c
665665
+translate$E $** > $@
666
+
667
+$(OBJDIR)\patch$O : patch_.c patch.h
668
+ $(TCC) -o$@ -c patch_.c
669
+
670
+patch_.c : $(SRCDIR)\patch.c
671
+ +translate$E $** > $@
666672
667673
$(OBJDIR)\path$O : path_.c path.h
668674
$(TCC) -o$@ -c path_.c
669675
670676
path_.c : $(SRCDIR)\path.c
@@ -1005,7 +1011,7 @@
10051011
10061012
zip_.c : $(SRCDIR)\zip.c
10071013
+translate$E $** > $@
10081014
10091015
headers: makeheaders$E page_index.h builtin_data.h VERSION.h
1010
- +makeheaders$E add_.c:add.h ajax_.c:ajax.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 chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.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 fileedit_.c:fileedit.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 hook_.c:hook.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 interwiki_.c:interwiki.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 pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.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 wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.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
1016
+ +makeheaders$E add_.c:add.h ajax_.c:ajax.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 chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.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 fileedit_.c:fileedit.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 hook_.c:hook.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 interwiki_.c:interwiki.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 patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.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 wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.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
10111017
@copy /Y nul: headers
10121018
--- 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_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_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 ajax_.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 chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.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 fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.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 pikchr_.c pikchrshow_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$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)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$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)\fileedit$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)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$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)\pikchr$O $(OBJDIR)\pikchrshow$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)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$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 ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki 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 pikchr pikchrshow 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 wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -661,10 +661,16 @@
661 $(OBJDIR)\name$O : name_.c name.h
662 $(TCC) -o$@ -c name_.c
663
664 name_.c : $(SRCDIR)\name.c
665 +translate$E $** > $@
 
 
 
 
 
 
666
667 $(OBJDIR)\path$O : path_.c path.h
668 $(TCC) -o$@ -c path_.c
669
670 path_.c : $(SRCDIR)\path.c
@@ -1005,7 +1011,7 @@
1005
1006 zip_.c : $(SRCDIR)\zip.c
1007 +translate$E $** > $@
1008
1009 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
1010 +makeheaders$E add_.c:add.h ajax_.c:ajax.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 chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.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 fileedit_.c:fileedit.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 hook_.c:hook.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 interwiki_.c:interwiki.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 pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.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 wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.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
1011 @copy /Y nul: headers
1012
--- 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_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_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 ajax_.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 chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.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 fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.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 patch_.c path_.c piechart_.c pikchr_.c pikchrshow_.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 wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$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)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$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)\fileedit$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)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$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)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchr$O $(OBJDIR)\pikchrshow$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)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$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 ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki 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 patch path piechart pikchr pikchrshow 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 wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -661,10 +661,16 @@
661 $(OBJDIR)\name$O : name_.c name.h
662 $(TCC) -o$@ -c name_.c
663
664 name_.c : $(SRCDIR)\name.c
665 +translate$E $** > $@
666
667 $(OBJDIR)\patch$O : patch_.c patch.h
668 $(TCC) -o$@ -c patch_.c
669
670 patch_.c : $(SRCDIR)\patch.c
671 +translate$E $** > $@
672
673 $(OBJDIR)\path$O : path_.c path.h
674 $(TCC) -o$@ -c path_.c
675
676 path_.c : $(SRCDIR)\path.c
@@ -1005,7 +1011,7 @@
1011
1012 zip_.c : $(SRCDIR)\zip.c
1013 +translate$E $** > $@
1014
1015 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
1016 +makeheaders$E add_.c:add.h ajax_.c:ajax.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 chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.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 fileedit_.c:fileedit.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 hook_.c:hook.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 interwiki_.c:interwiki.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 patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.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 wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.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
1017 @copy /Y nul: headers
1018
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -513,10 +513,11 @@
513513
$(SRCDIR)/md5.c \
514514
$(SRCDIR)/merge.c \
515515
$(SRCDIR)/merge3.c \
516516
$(SRCDIR)/moderate.c \
517517
$(SRCDIR)/name.c \
518
+ $(SRCDIR)/patch.c \
518519
$(SRCDIR)/path.c \
519520
$(SRCDIR)/piechart.c \
520521
$(SRCDIR)/pikchr.c \
521522
$(SRCDIR)/pikchrshow.c \
522523
$(SRCDIR)/pivot.c \
@@ -770,10 +771,11 @@
770771
$(OBJDIR)/md5_.c \
771772
$(OBJDIR)/merge_.c \
772773
$(OBJDIR)/merge3_.c \
773774
$(OBJDIR)/moderate_.c \
774775
$(OBJDIR)/name_.c \
776
+ $(OBJDIR)/patch_.c \
775777
$(OBJDIR)/path_.c \
776778
$(OBJDIR)/piechart_.c \
777779
$(OBJDIR)/pikchr_.c \
778780
$(OBJDIR)/pikchrshow_.c \
779781
$(OBJDIR)/pivot_.c \
@@ -919,10 +921,11 @@
919921
$(OBJDIR)/md5.o \
920922
$(OBJDIR)/merge.o \
921923
$(OBJDIR)/merge3.o \
922924
$(OBJDIR)/moderate.o \
923925
$(OBJDIR)/name.o \
926
+ $(OBJDIR)/patch.o \
924927
$(OBJDIR)/path.o \
925928
$(OBJDIR)/piechart.o \
926929
$(OBJDIR)/pikchr.o \
927930
$(OBJDIR)/pikchrshow.o \
928931
$(OBJDIR)/pivot.o \
@@ -1283,10 +1286,11 @@
12831286
$(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
12841287
$(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
12851288
$(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
12861289
$(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
12871290
$(OBJDIR)/name_.c:$(OBJDIR)/name.h \
1291
+ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
12881292
$(OBJDIR)/path_.c:$(OBJDIR)/path.h \
12891293
$(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
12901294
$(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
12911295
$(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
12921296
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -2068,10 +2072,18 @@
20682072
20692073
$(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
20702074
$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
20712075
20722076
$(OBJDIR)/name.h: $(OBJDIR)/headers
2077
+
2078
+$(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(TRANSLATE)
2079
+ $(TRANSLATE) $(SRCDIR)/patch.c >$@
2080
+
2081
+$(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h
2082
+ $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c
2083
+
2084
+$(OBJDIR)/patch.h: $(OBJDIR)/headers
20732085
20742086
$(OBJDIR)/path_.c: $(SRCDIR)/path.c $(TRANSLATE)
20752087
$(TRANSLATE) $(SRCDIR)/path.c >$@
20762088
20772089
$(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
20782090
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -513,10 +513,11 @@
513 $(SRCDIR)/md5.c \
514 $(SRCDIR)/merge.c \
515 $(SRCDIR)/merge3.c \
516 $(SRCDIR)/moderate.c \
517 $(SRCDIR)/name.c \
 
518 $(SRCDIR)/path.c \
519 $(SRCDIR)/piechart.c \
520 $(SRCDIR)/pikchr.c \
521 $(SRCDIR)/pikchrshow.c \
522 $(SRCDIR)/pivot.c \
@@ -770,10 +771,11 @@
770 $(OBJDIR)/md5_.c \
771 $(OBJDIR)/merge_.c \
772 $(OBJDIR)/merge3_.c \
773 $(OBJDIR)/moderate_.c \
774 $(OBJDIR)/name_.c \
 
775 $(OBJDIR)/path_.c \
776 $(OBJDIR)/piechart_.c \
777 $(OBJDIR)/pikchr_.c \
778 $(OBJDIR)/pikchrshow_.c \
779 $(OBJDIR)/pivot_.c \
@@ -919,10 +921,11 @@
919 $(OBJDIR)/md5.o \
920 $(OBJDIR)/merge.o \
921 $(OBJDIR)/merge3.o \
922 $(OBJDIR)/moderate.o \
923 $(OBJDIR)/name.o \
 
924 $(OBJDIR)/path.o \
925 $(OBJDIR)/piechart.o \
926 $(OBJDIR)/pikchr.o \
927 $(OBJDIR)/pikchrshow.o \
928 $(OBJDIR)/pivot.o \
@@ -1283,10 +1286,11 @@
1283 $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
1284 $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
1285 $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
1286 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
1287 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
 
1288 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
1289 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
1290 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
1291 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
1292 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -2068,10 +2072,18 @@
2068
2069 $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
2070 $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
2071
2072 $(OBJDIR)/name.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
2073
2074 $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(TRANSLATE)
2075 $(TRANSLATE) $(SRCDIR)/path.c >$@
2076
2077 $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
2078
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -513,10 +513,11 @@
513 $(SRCDIR)/md5.c \
514 $(SRCDIR)/merge.c \
515 $(SRCDIR)/merge3.c \
516 $(SRCDIR)/moderate.c \
517 $(SRCDIR)/name.c \
518 $(SRCDIR)/patch.c \
519 $(SRCDIR)/path.c \
520 $(SRCDIR)/piechart.c \
521 $(SRCDIR)/pikchr.c \
522 $(SRCDIR)/pikchrshow.c \
523 $(SRCDIR)/pivot.c \
@@ -770,10 +771,11 @@
771 $(OBJDIR)/md5_.c \
772 $(OBJDIR)/merge_.c \
773 $(OBJDIR)/merge3_.c \
774 $(OBJDIR)/moderate_.c \
775 $(OBJDIR)/name_.c \
776 $(OBJDIR)/patch_.c \
777 $(OBJDIR)/path_.c \
778 $(OBJDIR)/piechart_.c \
779 $(OBJDIR)/pikchr_.c \
780 $(OBJDIR)/pikchrshow_.c \
781 $(OBJDIR)/pivot_.c \
@@ -919,10 +921,11 @@
921 $(OBJDIR)/md5.o \
922 $(OBJDIR)/merge.o \
923 $(OBJDIR)/merge3.o \
924 $(OBJDIR)/moderate.o \
925 $(OBJDIR)/name.o \
926 $(OBJDIR)/patch.o \
927 $(OBJDIR)/path.o \
928 $(OBJDIR)/piechart.o \
929 $(OBJDIR)/pikchr.o \
930 $(OBJDIR)/pikchrshow.o \
931 $(OBJDIR)/pivot.o \
@@ -1283,10 +1286,11 @@
1286 $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \
1287 $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \
1288 $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \
1289 $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \
1290 $(OBJDIR)/name_.c:$(OBJDIR)/name.h \
1291 $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \
1292 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
1293 $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \
1294 $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \
1295 $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \
1296 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
@@ -2068,10 +2072,18 @@
2072
2073 $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h
2074 $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
2075
2076 $(OBJDIR)/name.h: $(OBJDIR)/headers
2077
2078 $(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(TRANSLATE)
2079 $(TRANSLATE) $(SRCDIR)/patch.c >$@
2080
2081 $(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h
2082 $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c
2083
2084 $(OBJDIR)/patch.h: $(OBJDIR)/headers
2085
2086 $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(TRANSLATE)
2087 $(TRANSLATE) $(SRCDIR)/path.c >$@
2088
2089 $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h
2090
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -456,10 +456,11 @@
456456
"$(OX)\md5_.c" \
457457
"$(OX)\merge_.c" \
458458
"$(OX)\merge3_.c" \
459459
"$(OX)\moderate_.c" \
460460
"$(OX)\name_.c" \
461
+ "$(OX)\patch_.c" \
461462
"$(OX)\path_.c" \
462463
"$(OX)\piechart_.c" \
463464
"$(OX)\pikchr_.c" \
464465
"$(OX)\pikchrshow_.c" \
465466
"$(OX)\pivot_.c" \
@@ -712,10 +713,11 @@
712713
"$(OX)\md5$O" \
713714
"$(OX)\merge$O" \
714715
"$(OX)\merge3$O" \
715716
"$(OX)\moderate$O" \
716717
"$(OX)\name$O" \
718
+ "$(OX)\patch$O" \
717719
"$(OX)\path$O" \
718720
"$(OX)\piechart$O" \
719721
"$(OX)\pikchr$O" \
720722
"$(OX)\pikchrshow$O" \
721723
"$(OX)\pivot$O" \
@@ -942,10 +944,11 @@
942944
echo "$(OX)\md5.obj" >> $@
943945
echo "$(OX)\merge.obj" >> $@
944946
echo "$(OX)\merge3.obj" >> $@
945947
echo "$(OX)\moderate.obj" >> $@
946948
echo "$(OX)\name.obj" >> $@
949
+ echo "$(OX)\patch.obj" >> $@
947950
echo "$(OX)\path.obj" >> $@
948951
echo "$(OX)\piechart.obj" >> $@
949952
echo "$(OX)\pikchr.obj" >> $@
950953
echo "$(OX)\pikchrshow.obj" >> $@
951954
echo "$(OX)\pivot.obj" >> $@
@@ -1766,10 +1769,16 @@
17661769
"$(OX)\name$O" : "$(OX)\name_.c" "$(OX)\name.h"
17671770
$(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\name_.c"
17681771
17691772
"$(OX)\name_.c" : "$(SRCDIR)\name.c"
17701773
"$(OBJDIR)\translate$E" $** > $@
1774
+
1775
+"$(OX)\patch$O" : "$(OX)\patch_.c" "$(OX)\patch.h"
1776
+ $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\patch_.c"
1777
+
1778
+"$(OX)\patch_.c" : "$(SRCDIR)\patch.c"
1779
+ "$(OBJDIR)\translate$E" $** > $@
17711780
17721781
"$(OX)\path$O" : "$(OX)\path_.c" "$(OX)\path.h"
17731782
$(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\path_.c"
17741783
17751784
"$(OX)\path_.c" : "$(SRCDIR)\path.c"
@@ -2203,10 +2212,11 @@
22032212
"$(OX)\md5_.c":"$(OX)\md5.h" \
22042213
"$(OX)\merge_.c":"$(OX)\merge.h" \
22052214
"$(OX)\merge3_.c":"$(OX)\merge3.h" \
22062215
"$(OX)\moderate_.c":"$(OX)\moderate.h" \
22072216
"$(OX)\name_.c":"$(OX)\name.h" \
2217
+ "$(OX)\patch_.c":"$(OX)\patch.h" \
22082218
"$(OX)\path_.c":"$(OX)\path.h" \
22092219
"$(OX)\piechart_.c":"$(OX)\piechart.h" \
22102220
"$(OX)\pikchr_.c":"$(OX)\pikchr.h" \
22112221
"$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \
22122222
"$(OX)\pivot_.c":"$(OX)\pivot.h" \
22132223
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -456,10 +456,11 @@
456 "$(OX)\md5_.c" \
457 "$(OX)\merge_.c" \
458 "$(OX)\merge3_.c" \
459 "$(OX)\moderate_.c" \
460 "$(OX)\name_.c" \
 
461 "$(OX)\path_.c" \
462 "$(OX)\piechart_.c" \
463 "$(OX)\pikchr_.c" \
464 "$(OX)\pikchrshow_.c" \
465 "$(OX)\pivot_.c" \
@@ -712,10 +713,11 @@
712 "$(OX)\md5$O" \
713 "$(OX)\merge$O" \
714 "$(OX)\merge3$O" \
715 "$(OX)\moderate$O" \
716 "$(OX)\name$O" \
 
717 "$(OX)\path$O" \
718 "$(OX)\piechart$O" \
719 "$(OX)\pikchr$O" \
720 "$(OX)\pikchrshow$O" \
721 "$(OX)\pivot$O" \
@@ -942,10 +944,11 @@
942 echo "$(OX)\md5.obj" >> $@
943 echo "$(OX)\merge.obj" >> $@
944 echo "$(OX)\merge3.obj" >> $@
945 echo "$(OX)\moderate.obj" >> $@
946 echo "$(OX)\name.obj" >> $@
 
947 echo "$(OX)\path.obj" >> $@
948 echo "$(OX)\piechart.obj" >> $@
949 echo "$(OX)\pikchr.obj" >> $@
950 echo "$(OX)\pikchrshow.obj" >> $@
951 echo "$(OX)\pivot.obj" >> $@
@@ -1766,10 +1769,16 @@
1766 "$(OX)\name$O" : "$(OX)\name_.c" "$(OX)\name.h"
1767 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\name_.c"
1768
1769 "$(OX)\name_.c" : "$(SRCDIR)\name.c"
1770 "$(OBJDIR)\translate$E" $** > $@
 
 
 
 
 
 
1771
1772 "$(OX)\path$O" : "$(OX)\path_.c" "$(OX)\path.h"
1773 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\path_.c"
1774
1775 "$(OX)\path_.c" : "$(SRCDIR)\path.c"
@@ -2203,10 +2212,11 @@
2203 "$(OX)\md5_.c":"$(OX)\md5.h" \
2204 "$(OX)\merge_.c":"$(OX)\merge.h" \
2205 "$(OX)\merge3_.c":"$(OX)\merge3.h" \
2206 "$(OX)\moderate_.c":"$(OX)\moderate.h" \
2207 "$(OX)\name_.c":"$(OX)\name.h" \
 
2208 "$(OX)\path_.c":"$(OX)\path.h" \
2209 "$(OX)\piechart_.c":"$(OX)\piechart.h" \
2210 "$(OX)\pikchr_.c":"$(OX)\pikchr.h" \
2211 "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \
2212 "$(OX)\pivot_.c":"$(OX)\pivot.h" \
2213
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -456,10 +456,11 @@
456 "$(OX)\md5_.c" \
457 "$(OX)\merge_.c" \
458 "$(OX)\merge3_.c" \
459 "$(OX)\moderate_.c" \
460 "$(OX)\name_.c" \
461 "$(OX)\patch_.c" \
462 "$(OX)\path_.c" \
463 "$(OX)\piechart_.c" \
464 "$(OX)\pikchr_.c" \
465 "$(OX)\pikchrshow_.c" \
466 "$(OX)\pivot_.c" \
@@ -712,10 +713,11 @@
713 "$(OX)\md5$O" \
714 "$(OX)\merge$O" \
715 "$(OX)\merge3$O" \
716 "$(OX)\moderate$O" \
717 "$(OX)\name$O" \
718 "$(OX)\patch$O" \
719 "$(OX)\path$O" \
720 "$(OX)\piechart$O" \
721 "$(OX)\pikchr$O" \
722 "$(OX)\pikchrshow$O" \
723 "$(OX)\pivot$O" \
@@ -942,10 +944,11 @@
944 echo "$(OX)\md5.obj" >> $@
945 echo "$(OX)\merge.obj" >> $@
946 echo "$(OX)\merge3.obj" >> $@
947 echo "$(OX)\moderate.obj" >> $@
948 echo "$(OX)\name.obj" >> $@
949 echo "$(OX)\patch.obj" >> $@
950 echo "$(OX)\path.obj" >> $@
951 echo "$(OX)\piechart.obj" >> $@
952 echo "$(OX)\pikchr.obj" >> $@
953 echo "$(OX)\pikchrshow.obj" >> $@
954 echo "$(OX)\pivot.obj" >> $@
@@ -1766,10 +1769,16 @@
1769 "$(OX)\name$O" : "$(OX)\name_.c" "$(OX)\name.h"
1770 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\name_.c"
1771
1772 "$(OX)\name_.c" : "$(SRCDIR)\name.c"
1773 "$(OBJDIR)\translate$E" $** > $@
1774
1775 "$(OX)\patch$O" : "$(OX)\patch_.c" "$(OX)\patch.h"
1776 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\patch_.c"
1777
1778 "$(OX)\patch_.c" : "$(SRCDIR)\patch.c"
1779 "$(OBJDIR)\translate$E" $** > $@
1780
1781 "$(OX)\path$O" : "$(OX)\path_.c" "$(OX)\path.h"
1782 $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\path_.c"
1783
1784 "$(OX)\path_.c" : "$(SRCDIR)\path.c"
@@ -2203,10 +2212,11 @@
2212 "$(OX)\md5_.c":"$(OX)\md5.h" \
2213 "$(OX)\merge_.c":"$(OX)\merge.h" \
2214 "$(OX)\merge3_.c":"$(OX)\merge3.h" \
2215 "$(OX)\moderate_.c":"$(OX)\moderate.h" \
2216 "$(OX)\name_.c":"$(OX)\name.h" \
2217 "$(OX)\patch_.c":"$(OX)\patch.h" \
2218 "$(OX)\path_.c":"$(OX)\path.h" \
2219 "$(OX)\piechart_.c":"$(OX)\piechart.h" \
2220 "$(OX)\pikchr_.c":"$(OX)\pikchr.h" \
2221 "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \
2222 "$(OX)\pivot_.c":"$(OX)\pivot.h" \
2223
--- www/aboutdownload.wiki
+++ www/aboutdownload.wiki
@@ -11,10 +11,14 @@
1111
for a list of all unversioned files. Javascript in the
1212
[/uv/download.js?mimetype=text/plain|download.js] file (which is
1313
sourced by "download.html") then figures out which unversioned files are
1414
build products and paints appropriate icons on the displayed
1515
download page.
16
+
17
+Except, the "Source Tarball" download products are not stored as
18
+unversioned files. They are computed on-demand by the
19
+[/help?cmd=/tarball|/tarball web page].
1620
1721
When a new version is generated, the developers use the
1822
[/help?cmd=uv|fossil uv edit] command to make minor changes
1923
to the "[/uv/download.js?mimetype=text/plain|download.js]"
2024
file so that it knows about the
2125
--- www/aboutdownload.wiki
+++ www/aboutdownload.wiki
@@ -11,10 +11,14 @@
11 for a list of all unversioned files. Javascript in the
12 [/uv/download.js?mimetype=text/plain|download.js] file (which is
13 sourced by "download.html") then figures out which unversioned files are
14 build products and paints appropriate icons on the displayed
15 download page.
 
 
 
 
16
17 When a new version is generated, the developers use the
18 [/help?cmd=uv|fossil uv edit] command to make minor changes
19 to the "[/uv/download.js?mimetype=text/plain|download.js]"
20 file so that it knows about the
21
--- www/aboutdownload.wiki
+++ www/aboutdownload.wiki
@@ -11,10 +11,14 @@
11 for a list of all unversioned files. Javascript in the
12 [/uv/download.js?mimetype=text/plain|download.js] file (which is
13 sourced by "download.html") then figures out which unversioned files are
14 build products and paints appropriate icons on the displayed
15 download page.
16
17 Except, the "Source Tarball" download products are not stored as
18 unversioned files. They are computed on-demand by the
19 [/help?cmd=/tarball|/tarball web page].
20
21 When a new version is generated, the developers use the
22 [/help?cmd=uv|fossil uv edit] command to make minor changes
23 to the "[/uv/download.js?mimetype=text/plain|download.js]"
24 file so that it knows about the
25
+26 -11
--- www/build.wiki
+++ www/build.wiki
@@ -7,10 +7,14 @@
77
the appropriate executable for your platform
88
and put it on your $PATH.
99
To uninstall, simply delete the executable.
1010
To upgrade from an older release, just overwrite the older binary with
1111
the newer one.</p>
12
+
13
+<p>For details about how those binaries are built, see
14
+[/wiki?name=Release+Build+How-To | the Release Build How-To wiki page].</p>
15
+
1216
1317
<h2>0.1 Executive Summary</h2>
1418
1519
<p>Building and installing is very simple. Three steps:</p>
1620
@@ -131,30 +135,41 @@
131135
<li><p><i>Unix without running "configure"</i> → if you prefer to avoid
132136
running configure, you can also use: <b>make -f Makefile.classic</b>. You may
133137
want to make minor edits to Makefile.classic to configure the build for your
134138
system.
135139
136
-<li><p><i>MinGW 3.x (<u>not</u> 4.x) / MinGW-w64</i> → Use the MinGW makefile:
137
-"<b>make -f win/Makefile.mingw</b>". On a Windows box you will need either
138
-Cygwin or MSYS as build environment. On Cygwin, Linux or Darwin you may want
139
-to make minor edits to win/Makefile.mingw to configure the cross-compile
140
-environment.
140
+<li><p><i>MinGW / MinGW-w64</i> → The best-supported path is to build
141
+via the MinGW specific Makefile under a POSIX build of GNU make:
142
+"<b>make -f win/Makefile.mingw</b>".
143
+
144
+There is limited support for building under MinGW's native Windows port
145
+of GNU Make instead by defining the <tt>USE_WINDOWS=1</tt> variable, but
146
+it's better to build under MSYS, Cygwin, or WSL on Windows since this
147
+mode doesn't take care of cases such as the "openssl" target, which
148
+depends on <tt>sed</tt>. We've gone as far down this path as is
149
+practical short of breaking cross-compilation under Linux, macOS, and so
150
+forth, as we'd have to do to make everything work under
151
+<tt>cmd.exe</tt>.
152
+
153
+Unless you're building under MSYS where commands like "<tt>gcc</tt>"
154
+give MinGW's GCC and not some other version, you will need to make minor
155
+edits to win/Makefile.mingw to configure the cross-compilation
156
+environment. It should suffice to switch to one of the predefined
157
+<tt>PREFIX</tt> values, causing the build to be done using
158
+"<tt>x86_64-w64-mingw32-gcc</tt>" for example, yielding a 64-bit native
159
+Windows binary.
141160
142161
To enable the native [./th1.md#tclEval | Tcl integration feature], use a
143162
command line like the following (all on one line):
144163
145164
<b>make -f win/Makefile.mingw FOSSIL_ENABLE_TCL=1 FOSSIL_ENABLE_TCL_STUBS=1 FOSSIL_ENABLE_TCL_PRIVATE_STUBS=1</b>
146165
147
-Alternatively, <b>./configure</b> may now be used to create a Makefile
148
-suitable for use with MinGW; however, options passed to configure that are
166
+Alternatively, running <b>./configure</b> under MSYS should give a
167
+suitable top-level Makefile. However, options passed to configure that are
149168
not applicable on Windows may cause the configuration or compilation to fail
150169
(e.g. fusefs, internal-sqlite, etc).
151170
152
-<i>HINT</i>: Do <u>not</u> use MinGW-4.x, it may compile but the Fossil binary
153
-will not work correctly, see
154
-[https://fossil-scm.org/home/tktview/18cff45a4e210430e24c | ticket].
155
-
156171
<li><p><i>MSVC</i> → Use the MSVC makefile.
157172
158173
Run all of the following from a "x64 Native Tools Command Prompt".
159174
160175
First
161176
--- www/build.wiki
+++ www/build.wiki
@@ -7,10 +7,14 @@
7 the appropriate executable for your platform
8 and put it on your $PATH.
9 To uninstall, simply delete the executable.
10 To upgrade from an older release, just overwrite the older binary with
11 the newer one.</p>
 
 
 
 
12
13 <h2>0.1 Executive Summary</h2>
14
15 <p>Building and installing is very simple. Three steps:</p>
16
@@ -131,30 +135,41 @@
131 <li><p><i>Unix without running "configure"</i> → if you prefer to avoid
132 running configure, you can also use: <b>make -f Makefile.classic</b>. You may
133 want to make minor edits to Makefile.classic to configure the build for your
134 system.
135
136 <li><p><i>MinGW 3.x (<u>not</u> 4.x) / MinGW-w64</i> → Use the MinGW makefile:
137 "<b>make -f win/Makefile.mingw</b>". On a Windows box you will need either
138 Cygwin or MSYS as build environment. On Cygwin, Linux or Darwin you may want
139 to make minor edits to win/Makefile.mingw to configure the cross-compile
140 environment.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
142 To enable the native [./th1.md#tclEval | Tcl integration feature], use a
143 command line like the following (all on one line):
144
145 <b>make -f win/Makefile.mingw FOSSIL_ENABLE_TCL=1 FOSSIL_ENABLE_TCL_STUBS=1 FOSSIL_ENABLE_TCL_PRIVATE_STUBS=1</b>
146
147 Alternatively, <b>./configure</b> may now be used to create a Makefile
148 suitable for use with MinGW; however, options passed to configure that are
149 not applicable on Windows may cause the configuration or compilation to fail
150 (e.g. fusefs, internal-sqlite, etc).
151
152 <i>HINT</i>: Do <u>not</u> use MinGW-4.x, it may compile but the Fossil binary
153 will not work correctly, see
154 [https://fossil-scm.org/home/tktview/18cff45a4e210430e24c | ticket].
155
156 <li><p><i>MSVC</i> → Use the MSVC makefile.
157
158 Run all of the following from a "x64 Native Tools Command Prompt".
159
160 First
161
--- www/build.wiki
+++ www/build.wiki
@@ -7,10 +7,14 @@
7 the appropriate executable for your platform
8 and put it on your $PATH.
9 To uninstall, simply delete the executable.
10 To upgrade from an older release, just overwrite the older binary with
11 the newer one.</p>
12
13 <p>For details about how those binaries are built, see
14 [/wiki?name=Release+Build+How-To | the Release Build How-To wiki page].</p>
15
16
17 <h2>0.1 Executive Summary</h2>
18
19 <p>Building and installing is very simple. Three steps:</p>
20
@@ -131,30 +135,41 @@
135 <li><p><i>Unix without running "configure"</i> → if you prefer to avoid
136 running configure, you can also use: <b>make -f Makefile.classic</b>. You may
137 want to make minor edits to Makefile.classic to configure the build for your
138 system.
139
140 <li><p><i>MinGW / MinGW-w64</i> → The best-supported path is to build
141 via the MinGW specific Makefile under a POSIX build of GNU make:
142 "<b>make -f win/Makefile.mingw</b>".
143
144 There is limited support for building under MinGW's native Windows port
145 of GNU Make instead by defining the <tt>USE_WINDOWS=1</tt> variable, but
146 it's better to build under MSYS, Cygwin, or WSL on Windows since this
147 mode doesn't take care of cases such as the "openssl" target, which
148 depends on <tt>sed</tt>. We've gone as far down this path as is
149 practical short of breaking cross-compilation under Linux, macOS, and so
150 forth, as we'd have to do to make everything work under
151 <tt>cmd.exe</tt>.
152
153 Unless you're building under MSYS where commands like "<tt>gcc</tt>"
154 give MinGW's GCC and not some other version, you will need to make minor
155 edits to win/Makefile.mingw to configure the cross-compilation
156 environment. It should suffice to switch to one of the predefined
157 <tt>PREFIX</tt> values, causing the build to be done using
158 "<tt>x86_64-w64-mingw32-gcc</tt>" for example, yielding a 64-bit native
159 Windows binary.
160
161 To enable the native [./th1.md#tclEval | Tcl integration feature], use a
162 command line like the following (all on one line):
163
164 <b>make -f win/Makefile.mingw FOSSIL_ENABLE_TCL=1 FOSSIL_ENABLE_TCL_STUBS=1 FOSSIL_ENABLE_TCL_PRIVATE_STUBS=1</b>
165
166 Alternatively, running <b>./configure</b> under MSYS should give a
167 suitable top-level Makefile. However, options passed to configure that are
168 not applicable on Windows may cause the configuration or compilation to fail
169 (e.g. fusefs, internal-sqlite, etc).
170
 
 
 
 
171 <li><p><i>MSVC</i> → Use the MSVC makefile.
172
173 Run all of the following from a "x64 Native Tools Command Prompt".
174
175 First
176
--- www/caps/index.md
+++ www/caps/index.md
@@ -302,16 +302,11 @@
302302
* For `ssh://` URLs, Fossil pipes the HTTP conversation through a
303303
local SSH client to a remote instance of Fossil running the
304304
[`test-http`](/help?name=test-http) command to receive the tunneled
305305
HTTP connection. The reason Fossil’s user capability system is
306306
bypassed in this case is that [`test-http` gives full capabilities
307
- to its users][sxcap].
308
-
309
- The SSH client command defaults to “`ssh -e none -T`” on most
310
- platforms except Windows where it defaults to “`plink -ssh -T`”.
311
- You can override this with [the `ssh-command`
312
- setting](/help?name=ssh-command).
307
+ to its users][sxycap].
313308
314309
* For `file://` URLs — as opposed to plain local file paths —
315310
the “sending” Fossil instance writes its side of
316311
the HTTP conversation out to a temporary file in the same directory
317312
as the local repo clone and then calls itself on the “receiving”
@@ -321,11 +316,11 @@
321316
322317
Checks for capabilities like [**Read**][o] and [**Write**][i] within the
323318
HTTP conversation between two Fossil instances only have a useful effect
324319
when done over an `http[s]://` URL.
325320
326
-[sxcap]: /file?ci=8813ae91a699ac73&name=src/main.c&ln=2632-2637
321
+[sxycap]: /file?ci=ec5efceb8aac6cb4&name=src/main.c&ln=2748-2752
327322
328323
329324
## <a name="pubpg"></a>Public Pages
330325
331326
In Admin → Access, there is an option for giving a list of [globs][glob]
332327
--- www/caps/index.md
+++ www/caps/index.md
@@ -302,16 +302,11 @@
302 * For `ssh://` URLs, Fossil pipes the HTTP conversation through a
303 local SSH client to a remote instance of Fossil running the
304 [`test-http`](/help?name=test-http) command to receive the tunneled
305 HTTP connection. The reason Fossil’s user capability system is
306 bypassed in this case is that [`test-http` gives full capabilities
307 to its users][sxcap].
308
309 The SSH client command defaults to “`ssh -e none -T`” on most
310 platforms except Windows where it defaults to “`plink -ssh -T`”.
311 You can override this with [the `ssh-command`
312 setting](/help?name=ssh-command).
313
314 * For `file://` URLs — as opposed to plain local file paths —
315 the “sending” Fossil instance writes its side of
316 the HTTP conversation out to a temporary file in the same directory
317 as the local repo clone and then calls itself on the “receiving”
@@ -321,11 +316,11 @@
321
322 Checks for capabilities like [**Read**][o] and [**Write**][i] within the
323 HTTP conversation between two Fossil instances only have a useful effect
324 when done over an `http[s]://` URL.
325
326 [sxcap]: /file?ci=8813ae91a699ac73&name=src/main.c&ln=2632-2637
327
328
329 ## <a name="pubpg"></a>Public Pages
330
331 In Admin → Access, there is an option for giving a list of [globs][glob]
332
--- www/caps/index.md
+++ www/caps/index.md
@@ -302,16 +302,11 @@
302 * For `ssh://` URLs, Fossil pipes the HTTP conversation through a
303 local SSH client to a remote instance of Fossil running the
304 [`test-http`](/help?name=test-http) command to receive the tunneled
305 HTTP connection. The reason Fossil’s user capability system is
306 bypassed in this case is that [`test-http` gives full capabilities
307 to its users][sxycap].
 
 
 
 
 
308
309 * For `file://` URLs — as opposed to plain local file paths —
310 the “sending” Fossil instance writes its side of
311 the HTTP conversation out to a temporary file in the same directory
312 as the local repo clone and then calls itself on the “receiving”
@@ -321,11 +316,11 @@
316
317 Checks for capabilities like [**Read**][o] and [**Write**][i] within the
318 HTTP conversation between two Fossil instances only have a useful effect
319 when done over an `http[s]://` URL.
320
321 [sxycap]: /file?ci=ec5efceb8aac6cb4&name=src/main.c&ln=2748-2752
322
323
324 ## <a name="pubpg"></a>Public Pages
325
326 In Admin → Access, there is an option for giving a list of [globs][glob]
327
+60 -12
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,63 @@
11
<title>Change Log</title>
22
3
+<a name='v2_17'></a>
4
+<h2>Changes for version 2.17 (pending)</h2>
5
+ * The --branchcolor option on [/help?cmd=commit|fossil commit] and
6
+ [/help?cmd=amend|fossil amend] can now take the value "auto" to
7
+ force Fossil to use its built-in automatic color choosing algorithm.
8
+ * Fossil now [./concepts.wiki#workflow|autosyncs] prior to running
9
+ [/help?cmd=open|fossil open].
10
+ * Add the [/help?cmd=ticket-default-report|ticket-default-report setting],
11
+ which if set to the title of a ticket report causes that ticket report
12
+ to be displayed below the search box in the /ticket page.
13
+ * The "nc" query parameter to the [/help?cmd=/timeline|/timeline] page
14
+ causes all graph coloring to be omitted.
15
+ * Improvements and bug fixes to the new "fossil ui REMOTE" feature so
16
+ that it works better on a wider variety of platforms.
17
+ * In [/help?cmd=/wikiedit|/wikiedit], show the list of attachments for
18
+ the current page and list URLs suitable for pasting them into the page.
19
+ * Add the --no-http-compression option to [/help?cmd=sync|fossil sync]
20
+ and similar.
21
+ * Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
22
+ the --verbose option.
23
+ * Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
24
+ </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
25
+ * The [/mdrules|Markdown formatter] now interprets the content of
26
+ block HTML markup (such as &lt;table&gt;) in most cases. Only content
27
+ of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.
28
+ * [/wcontent|Listing] of the available wiki pages
29
+ [/timeline?r=wcontent-subsets|gained] the ability to
30
+ [./javascript.md#wcontent|interactively] adjust a subset of
31
+ wiki pages that are shown; this is based on the
32
+ classification of wiki page names according to the
33
+ [/help?cmd=wiki-classes|configurable] glob patterns.
34
+
335
<a name='v2_16'></a>
4
-<h2>Changes for Version 2.16 (pending)</h2>
36
+<h2>Changes for Version 2.16 (2021-07-02)</h2>
537
* <b>Security:</b> Fix the client-side TLS so that it verifies that the
6
- server hostname matches its certificate. <b>Upgrading to
7
- the patch is recommended.</b>
38
+ server hostname matches its certificate.
39
+ * The default "ssh" command on Windows is changed to "ssh" instead of the
40
+ legacy "plink", as ssh is now generally available on Windows systems.
41
+ Installations that still need to use the legacy "plink" can make that
42
+ happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
43
+ * Added the [./patchcmd.md|fossil patch] command.
44
+ * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
45
+ <li> The REPOSITORY argument can be the name of a check-out directory.
46
+ <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
47
+ then the ui is run on the remote machine and tunnelled back to the local
48
+ machine using ssh. (The latest version of fossil must be installed on
49
+ both the local and the remote for this to work correctly.)
50
+ <li> The new --nobrowser and --fossilcmd options is provided.
51
+ </ol>
852
* The [/brlist|/brlist web page] allows the user to
953
select multiple branches to be displayed together in a single
1054
timeline.
1155
* The [./forum.wiki|Forum] provides a hyperlink on the author of each
1256
post that goes to a timeline of recent posts by that same author.
57
+ * Added the "[/help?cmd=bisect|fossil bisect run]" command for improved
58
+ automation of bisects.
1359
* The [/help?cmd=merge|fossil merge] command now does a better job merging
1460
branches where files have been renamed between the current branch and the
1561
branch being merged.
1662
* The [/help?cmd=open|fossil open] command allows the repository file
1763
to be inside the working directory without requiring the --force flag.
@@ -19,22 +65,21 @@
1965
pages now default to markdown format.
2066
* The [/help?cmd=/login|/login] page now links to a user's forum post
2167
timeline if the repository has forum posts.
2268
* Tags may now be propagated for forum posts, wiki pages, and technotes.
2369
The [/help?cmd=tag|tag command] can now manipulate and list such tags.
24
- * [./caps/login-groups.md|Login-Groups] are now show on the repository
70
+ * [./caps/login-groups.md|Login-Groups] are now shown on the repository
2571
list of the "[/help?cmd=all|fossil all ui]" command.
26
- * Administrators can configure [./alerts|email alerts] to expire
72
+ * Administrators can configure [./alerts.md|email alerts] to expire
2773
a specific number of days (ex: 365) after the last user contact with
28
- the Fossil server. This can prevents alert emails being sent to
74
+ the Fossil server. This prevents alert emails being sent to
2975
abandoned email accounts forever.
30
- * [/wcontent|Listing] of the available wiki pages
31
- [/timeline?r=wcontent-subsets|gained] the ability to
32
- [./javascript.md#wcontent|interactively] adjust a subset of
33
- wiki pages that are shown; this is based on the
34
- classification of wiki page names according to the
35
- [/help?cmd=wiki-classes|configurable] glob patterns.
76
+ * SQL that defines [/tktsetup_tab|database objects for tickets] now
77
+ [/timeline?c=c717f1ef9a1a4c91|can DROP] a VIEW or an INDEX provided
78
+ that its name starts with '<code>ticket</code>' or '<code>fx_</code>'.
79
+ * Update the built-in SQLite to version 3.36.0.
80
+ * Numerous other minor enhancements.
3681
3782
<a name='v2_15'></a>
3883
<h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)
3984
and 2.15.2 on (2021-06-15)</h2>
4085
* <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the
@@ -293,10 +338,13 @@
293338
pages was removed. (Please let us know, via the site's Support menu,
294339
if that removal unduly impacts you.) This also changes the semantics
295340
of the wiki "Sandbox": that pseudo-page may be freely edited but
296341
no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
297342
can, though).
343
+ * The [/help?cmd=allow-symlinks|allow-symlinks setting] no longer
344
+ syncs. It must be activated individually on any clones which require
345
+ symlinks.
298346
* Countless documentation enhancements.
299347
300348
<a name='v2_11'></a>
301349
<h2>Changes for Version 2.11 (2020-05-25)</h2>
302350
303351
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,63 @@
1 <title>Change Log</title>
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3 <a name='v2_16'></a>
4 <h2>Changes for Version 2.16 (pending)</h2>
5 * <b>Security:</b> Fix the client-side TLS so that it verifies that the
6 server hostname matches its certificate. <b>Upgrading to
7 the patch is recommended.</b>
 
 
 
 
 
 
 
 
 
 
 
 
8 * The [/brlist|/brlist web page] allows the user to
9 select multiple branches to be displayed together in a single
10 timeline.
11 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
12 post that goes to a timeline of recent posts by that same author.
 
 
13 * The [/help?cmd=merge|fossil merge] command now does a better job merging
14 branches where files have been renamed between the current branch and the
15 branch being merged.
16 * The [/help?cmd=open|fossil open] command allows the repository file
17 to be inside the working directory without requiring the --force flag.
@@ -19,22 +65,21 @@
19 pages now default to markdown format.
20 * The [/help?cmd=/login|/login] page now links to a user's forum post
21 timeline if the repository has forum posts.
22 * Tags may now be propagated for forum posts, wiki pages, and technotes.
23 The [/help?cmd=tag|tag command] can now manipulate and list such tags.
24 * [./caps/login-groups.md|Login-Groups] are now show on the repository
25 list of the "[/help?cmd=all|fossil all ui]" command.
26 * Administrators can configure [./alerts|email alerts] to expire
27 a specific number of days (ex: 365) after the last user contact with
28 the Fossil server. This can prevents alert emails being sent to
29 abandoned email accounts forever.
30 * [/wcontent|Listing] of the available wiki pages
31 [/timeline?r=wcontent-subsets|gained] the ability to
32 [./javascript.md#wcontent|interactively] adjust a subset of
33 wiki pages that are shown; this is based on the
34 classification of wiki page names according to the
35 [/help?cmd=wiki-classes|configurable] glob patterns.
36
37 <a name='v2_15'></a>
38 <h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)
39 and 2.15.2 on (2021-06-15)</h2>
40 * <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the
@@ -293,10 +338,13 @@
293 pages was removed. (Please let us know, via the site's Support menu,
294 if that removal unduly impacts you.) This also changes the semantics
295 of the wiki "Sandbox": that pseudo-page may be freely edited but
296 no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
297 can, though).
 
 
 
298 * Countless documentation enhancements.
299
300 <a name='v2_11'></a>
301 <h2>Changes for Version 2.11 (2020-05-25)</h2>
302
303
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,63 @@
1 <title>Change Log</title>
2
3 <a name='v2_17'></a>
4 <h2>Changes for version 2.17 (pending)</h2>
5 * The --branchcolor option on [/help?cmd=commit|fossil commit] and
6 [/help?cmd=amend|fossil amend] can now take the value "auto" to
7 force Fossil to use its built-in automatic color choosing algorithm.
8 * Fossil now [./concepts.wiki#workflow|autosyncs] prior to running
9 [/help?cmd=open|fossil open].
10 * Add the [/help?cmd=ticket-default-report|ticket-default-report setting],
11 which if set to the title of a ticket report causes that ticket report
12 to be displayed below the search box in the /ticket page.
13 * The "nc" query parameter to the [/help?cmd=/timeline|/timeline] page
14 causes all graph coloring to be omitted.
15 * Improvements and bug fixes to the new "fossil ui REMOTE" feature so
16 that it works better on a wider variety of platforms.
17 * In [/help?cmd=/wikiedit|/wikiedit], show the list of attachments for
18 the current page and list URLs suitable for pasting them into the page.
19 * Add the --no-http-compression option to [/help?cmd=sync|fossil sync]
20 and similar.
21 * Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
22 the --verbose option.
23 * Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
24 </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
25 * The [/mdrules|Markdown formatter] now interprets the content of
26 block HTML markup (such as &lt;table&gt;) in most cases. Only content
27 of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.
28 * [/wcontent|Listing] of the available wiki pages
29 [/timeline?r=wcontent-subsets|gained] the ability to
30 [./javascript.md#wcontent|interactively] adjust a subset of
31 wiki pages that are shown; this is based on the
32 classification of wiki page names according to the
33 [/help?cmd=wiki-classes|configurable] glob patterns.
34
35 <a name='v2_16'></a>
36 <h2>Changes for Version 2.16 (2021-07-02)</h2>
37 * <b>Security:</b> Fix the client-side TLS so that it verifies that the
38 server hostname matches its certificate.
39 * The default "ssh" command on Windows is changed to "ssh" instead of the
40 legacy "plink", as ssh is now generally available on Windows systems.
41 Installations that still need to use the legacy "plink" can make that
42 happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
43 * Added the [./patchcmd.md|fossil patch] command.
44 * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
45 <li> The REPOSITORY argument can be the name of a check-out directory.
46 <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
47 then the ui is run on the remote machine and tunnelled back to the local
48 machine using ssh. (The latest version of fossil must be installed on
49 both the local and the remote for this to work correctly.)
50 <li> The new --nobrowser and --fossilcmd options is provided.
51 </ol>
52 * The [/brlist|/brlist web page] allows the user to
53 select multiple branches to be displayed together in a single
54 timeline.
55 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
56 post that goes to a timeline of recent posts by that same author.
57 * Added the "[/help?cmd=bisect|fossil bisect run]" command for improved
58 automation of bisects.
59 * The [/help?cmd=merge|fossil merge] command now does a better job merging
60 branches where files have been renamed between the current branch and the
61 branch being merged.
62 * The [/help?cmd=open|fossil open] command allows the repository file
63 to be inside the working directory without requiring the --force flag.
@@ -19,22 +65,21 @@
65 pages now default to markdown format.
66 * The [/help?cmd=/login|/login] page now links to a user's forum post
67 timeline if the repository has forum posts.
68 * Tags may now be propagated for forum posts, wiki pages, and technotes.
69 The [/help?cmd=tag|tag command] can now manipulate and list such tags.
70 * [./caps/login-groups.md|Login-Groups] are now shown on the repository
71 list of the "[/help?cmd=all|fossil all ui]" command.
72 * Administrators can configure [./alerts.md|email alerts] to expire
73 a specific number of days (ex: 365) after the last user contact with
74 the Fossil server. This prevents alert emails being sent to
75 abandoned email accounts forever.
76 * SQL that defines [/tktsetup_tab|database objects for tickets] now
77 [/timeline?c=c717f1ef9a1a4c91|can DROP] a VIEW or an INDEX provided
78 that its name starts with '<code>ticket</code>' or '<code>fx_</code>'.
79 * Update the built-in SQLite to version 3.36.0.
80 * Numerous other minor enhancements.
 
81
82 <a name='v2_15'></a>
83 <h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)
84 and 2.15.2 on (2021-06-15)</h2>
85 * <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the
@@ -293,10 +338,13 @@
338 pages was removed. (Please let us know, via the site's Support menu,
339 if that removal unduly impacts you.) This also changes the semantics
340 of the wiki "Sandbox": that pseudo-page may be freely edited but
341 no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
342 can, though).
343 * The [/help?cmd=allow-symlinks|allow-symlinks setting] no longer
344 syncs. It must be activated individually on any clones which require
345 symlinks.
346 * Countless documentation enhancements.
347
348 <a name='v2_11'></a>
349 <h2>Changes for Version 2.11 (2020-05-25)</h2>
350
351
+60 -12
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,63 @@
11
<title>Change Log</title>
22
3
+<a name='v2_17'></a>
4
+<h2>Changes for version 2.17 (pending)</h2>
5
+ * The --branchcolor option on [/help?cmd=commit|fossil commit] and
6
+ [/help?cmd=amend|fossil amend] can now take the value "auto" to
7
+ force Fossil to use its built-in automatic color choosing algorithm.
8
+ * Fossil now [./concepts.wiki#workflow|autosyncs] prior to running
9
+ [/help?cmd=open|fossil open].
10
+ * Add the [/help?cmd=ticket-default-report|ticket-default-report setting],
11
+ which if set to the title of a ticket report causes that ticket report
12
+ to be displayed below the search box in the /ticket page.
13
+ * The "nc" query parameter to the [/help?cmd=/timeline|/timeline] page
14
+ causes all graph coloring to be omitted.
15
+ * Improvements and bug fixes to the new "fossil ui REMOTE" feature so
16
+ that it works better on a wider variety of platforms.
17
+ * In [/help?cmd=/wikiedit|/wikiedit], show the list of attachments for
18
+ the current page and list URLs suitable for pasting them into the page.
19
+ * Add the --no-http-compression option to [/help?cmd=sync|fossil sync]
20
+ and similar.
21
+ * Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
22
+ the --verbose option.
23
+ * Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
24
+ </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
25
+ * The [/mdrules|Markdown formatter] now interprets the content of
26
+ block HTML markup (such as &lt;table&gt;) in most cases. Only content
27
+ of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.
28
+ * [/wcontent|Listing] of the available wiki pages
29
+ [/timeline?r=wcontent-subsets|gained] the ability to
30
+ [./javascript.md#wcontent|interactively] adjust a subset of
31
+ wiki pages that are shown; this is based on the
32
+ classification of wiki page names according to the
33
+ [/help?cmd=wiki-classes|configurable] glob patterns.
34
+
335
<a name='v2_16'></a>
4
-<h2>Changes for Version 2.16 (pending)</h2>
36
+<h2>Changes for Version 2.16 (2021-07-02)</h2>
537
* <b>Security:</b> Fix the client-side TLS so that it verifies that the
6
- server hostname matches its certificate. <b>Upgrading to
7
- the patch is recommended.</b>
38
+ server hostname matches its certificate.
39
+ * The default "ssh" command on Windows is changed to "ssh" instead of the
40
+ legacy "plink", as ssh is now generally available on Windows systems.
41
+ Installations that still need to use the legacy "plink" can make that
42
+ happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
43
+ * Added the [./patchcmd.md|fossil patch] command.
44
+ * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
45
+ <li> The REPOSITORY argument can be the name of a check-out directory.
46
+ <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
47
+ then the ui is run on the remote machine and tunnelled back to the local
48
+ machine using ssh. (The latest version of fossil must be installed on
49
+ both the local and the remote for this to work correctly.)
50
+ <li> The new --nobrowser and --fossilcmd options is provided.
51
+ </ol>
852
* The [/brlist|/brlist web page] allows the user to
953
select multiple branches to be displayed together in a single
1054
timeline.
1155
* The [./forum.wiki|Forum] provides a hyperlink on the author of each
1256
post that goes to a timeline of recent posts by that same author.
57
+ * Added the "[/help?cmd=bisect|fossil bisect run]" command for improved
58
+ automation of bisects.
1359
* The [/help?cmd=merge|fossil merge] command now does a better job merging
1460
branches where files have been renamed between the current branch and the
1561
branch being merged.
1662
* The [/help?cmd=open|fossil open] command allows the repository file
1763
to be inside the working directory without requiring the --force flag.
@@ -19,22 +65,21 @@
1965
pages now default to markdown format.
2066
* The [/help?cmd=/login|/login] page now links to a user's forum post
2167
timeline if the repository has forum posts.
2268
* Tags may now be propagated for forum posts, wiki pages, and technotes.
2369
The [/help?cmd=tag|tag command] can now manipulate and list such tags.
24
- * [./caps/login-groups.md|Login-Groups] are now show on the repository
70
+ * [./caps/login-groups.md|Login-Groups] are now shown on the repository
2571
list of the "[/help?cmd=all|fossil all ui]" command.
26
- * Administrators can configure [./alerts|email alerts] to expire
72
+ * Administrators can configure [./alerts.md|email alerts] to expire
2773
a specific number of days (ex: 365) after the last user contact with
28
- the Fossil server. This can prevents alert emails being sent to
74
+ the Fossil server. This prevents alert emails being sent to
2975
abandoned email accounts forever.
30
- * [/wcontent|Listing] of the available wiki pages
31
- [/timeline?r=wcontent-subsets|gained] the ability to
32
- [./javascript.md#wcontent|interactively] adjust a subset of
33
- wiki pages that are shown; this is based on the
34
- classification of wiki page names according to the
35
- [/help?cmd=wiki-classes|configurable] glob patterns.
76
+ * SQL that defines [/tktsetup_tab|database objects for tickets] now
77
+ [/timeline?c=c717f1ef9a1a4c91|can DROP] a VIEW or an INDEX provided
78
+ that its name starts with '<code>ticket</code>' or '<code>fx_</code>'.
79
+ * Update the built-in SQLite to version 3.36.0.
80
+ * Numerous other minor enhancements.
3681
3782
<a name='v2_15'></a>
3883
<h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)
3984
and 2.15.2 on (2021-06-15)</h2>
4085
* <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the
@@ -293,10 +338,13 @@
293338
pages was removed. (Please let us know, via the site's Support menu,
294339
if that removal unduly impacts you.) This also changes the semantics
295340
of the wiki "Sandbox": that pseudo-page may be freely edited but
296341
no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
297342
can, though).
343
+ * The [/help?cmd=allow-symlinks|allow-symlinks setting] no longer
344
+ syncs. It must be activated individually on any clones which require
345
+ symlinks.
298346
* Countless documentation enhancements.
299347
300348
<a name='v2_11'></a>
301349
<h2>Changes for Version 2.11 (2020-05-25)</h2>
302350
303351
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,63 @@
1 <title>Change Log</title>
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3 <a name='v2_16'></a>
4 <h2>Changes for Version 2.16 (pending)</h2>
5 * <b>Security:</b> Fix the client-side TLS so that it verifies that the
6 server hostname matches its certificate. <b>Upgrading to
7 the patch is recommended.</b>
 
 
 
 
 
 
 
 
 
 
 
 
8 * The [/brlist|/brlist web page] allows the user to
9 select multiple branches to be displayed together in a single
10 timeline.
11 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
12 post that goes to a timeline of recent posts by that same author.
 
 
13 * The [/help?cmd=merge|fossil merge] command now does a better job merging
14 branches where files have been renamed between the current branch and the
15 branch being merged.
16 * The [/help?cmd=open|fossil open] command allows the repository file
17 to be inside the working directory without requiring the --force flag.
@@ -19,22 +65,21 @@
19 pages now default to markdown format.
20 * The [/help?cmd=/login|/login] page now links to a user's forum post
21 timeline if the repository has forum posts.
22 * Tags may now be propagated for forum posts, wiki pages, and technotes.
23 The [/help?cmd=tag|tag command] can now manipulate and list such tags.
24 * [./caps/login-groups.md|Login-Groups] are now show on the repository
25 list of the "[/help?cmd=all|fossil all ui]" command.
26 * Administrators can configure [./alerts|email alerts] to expire
27 a specific number of days (ex: 365) after the last user contact with
28 the Fossil server. This can prevents alert emails being sent to
29 abandoned email accounts forever.
30 * [/wcontent|Listing] of the available wiki pages
31 [/timeline?r=wcontent-subsets|gained] the ability to
32 [./javascript.md#wcontent|interactively] adjust a subset of
33 wiki pages that are shown; this is based on the
34 classification of wiki page names according to the
35 [/help?cmd=wiki-classes|configurable] glob patterns.
36
37 <a name='v2_15'></a>
38 <h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)
39 and 2.15.2 on (2021-06-15)</h2>
40 * <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the
@@ -293,10 +338,13 @@
293 pages was removed. (Please let us know, via the site's Support menu,
294 if that removal unduly impacts you.) This also changes the semantics
295 of the wiki "Sandbox": that pseudo-page may be freely edited but
296 no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
297 can, though).
 
 
 
298 * Countless documentation enhancements.
299
300 <a name='v2_11'></a>
301 <h2>Changes for Version 2.11 (2020-05-25)</h2>
302
303
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,63 @@
1 <title>Change Log</title>
2
3 <a name='v2_17'></a>
4 <h2>Changes for version 2.17 (pending)</h2>
5 * The --branchcolor option on [/help?cmd=commit|fossil commit] and
6 [/help?cmd=amend|fossil amend] can now take the value "auto" to
7 force Fossil to use its built-in automatic color choosing algorithm.
8 * Fossil now [./concepts.wiki#workflow|autosyncs] prior to running
9 [/help?cmd=open|fossil open].
10 * Add the [/help?cmd=ticket-default-report|ticket-default-report setting],
11 which if set to the title of a ticket report causes that ticket report
12 to be displayed below the search box in the /ticket page.
13 * The "nc" query parameter to the [/help?cmd=/timeline|/timeline] page
14 causes all graph coloring to be omitted.
15 * Improvements and bug fixes to the new "fossil ui REMOTE" feature so
16 that it works better on a wider variety of platforms.
17 * In [/help?cmd=/wikiedit|/wikiedit], show the list of attachments for
18 the current page and list URLs suitable for pasting them into the page.
19 * Add the --no-http-compression option to [/help?cmd=sync|fossil sync]
20 and similar.
21 * Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
22 the --verbose option.
23 * Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
24 </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
25 * The [/mdrules|Markdown formatter] now interprets the content of
26 block HTML markup (such as &lt;table&gt;) in most cases. Only content
27 of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.
28 * [/wcontent|Listing] of the available wiki pages
29 [/timeline?r=wcontent-subsets|gained] the ability to
30 [./javascript.md#wcontent|interactively] adjust a subset of
31 wiki pages that are shown; this is based on the
32 classification of wiki page names according to the
33 [/help?cmd=wiki-classes|configurable] glob patterns.
34
35 <a name='v2_16'></a>
36 <h2>Changes for Version 2.16 (2021-07-02)</h2>
37 * <b>Security:</b> Fix the client-side TLS so that it verifies that the
38 server hostname matches its certificate.
39 * The default "ssh" command on Windows is changed to "ssh" instead of the
40 legacy "plink", as ssh is now generally available on Windows systems.
41 Installations that still need to use the legacy "plink" can make that
42 happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
43 * Added the [./patchcmd.md|fossil patch] command.
44 * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
45 <li> The REPOSITORY argument can be the name of a check-out directory.
46 <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
47 then the ui is run on the remote machine and tunnelled back to the local
48 machine using ssh. (The latest version of fossil must be installed on
49 both the local and the remote for this to work correctly.)
50 <li> The new --nobrowser and --fossilcmd options is provided.
51 </ol>
52 * The [/brlist|/brlist web page] allows the user to
53 select multiple branches to be displayed together in a single
54 timeline.
55 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
56 post that goes to a timeline of recent posts by that same author.
57 * Added the "[/help?cmd=bisect|fossil bisect run]" command for improved
58 automation of bisects.
59 * The [/help?cmd=merge|fossil merge] command now does a better job merging
60 branches where files have been renamed between the current branch and the
61 branch being merged.
62 * The [/help?cmd=open|fossil open] command allows the repository file
63 to be inside the working directory without requiring the --force flag.
@@ -19,22 +65,21 @@
65 pages now default to markdown format.
66 * The [/help?cmd=/login|/login] page now links to a user's forum post
67 timeline if the repository has forum posts.
68 * Tags may now be propagated for forum posts, wiki pages, and technotes.
69 The [/help?cmd=tag|tag command] can now manipulate and list such tags.
70 * [./caps/login-groups.md|Login-Groups] are now shown on the repository
71 list of the "[/help?cmd=all|fossil all ui]" command.
72 * Administrators can configure [./alerts.md|email alerts] to expire
73 a specific number of days (ex: 365) after the last user contact with
74 the Fossil server. This prevents alert emails being sent to
75 abandoned email accounts forever.
76 * SQL that defines [/tktsetup_tab|database objects for tickets] now
77 [/timeline?c=c717f1ef9a1a4c91|can DROP] a VIEW or an INDEX provided
78 that its name starts with '<code>ticket</code>' or '<code>fx_</code>'.
79 * Update the built-in SQLite to version 3.36.0.
80 * Numerous other minor enhancements.
 
81
82 <a name='v2_15'></a>
83 <h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)
84 and 2.15.2 on (2021-06-15)</h2>
85 * <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the
@@ -293,10 +338,13 @@
338 pages was removed. (Please let us know, via the site's Support menu,
339 if that removal unduly impacts you.) This also changes the semantics
340 of the wiki "Sandbox": that pseudo-page may be freely edited but
341 no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
342 can, though).
343 * The [/help?cmd=allow-symlinks|allow-symlinks setting] no longer
344 syncs. It must be activated individually on any clones which require
345 symlinks.
346 * Countless documentation enhancements.
347
348 <a name='v2_11'></a>
349 <h2>Changes for Version 2.11 (2020-05-25)</h2>
350
351
--- www/customskin.md
+++ www/customskin.md
@@ -238,11 +238,11 @@
238238
part of the overall web page.</dd>
239239
240240
<dt><b>js.txt</b></dt><dd>
241241
242242
<p>The js.txt file is optional. It is intended to be javascript.
243
-The complete text of this javascript is might be inserted into
243
+The complete text of this javascript might be inserted into
244244
the Content Footer, after being processed using TH1, using
245245
code like the following in the "footer.txt" file:
246246
247247
<blockquote><pre>
248248
&lt;script nonce="$nonce"&gt;
@@ -354,11 +354,11 @@
354354
355355
The menu bar of the default skin has an entry to open a drop-down menu with
356356
additional navigation links, represented by the ≡ button (hence the name
357357
"hamburger menu"). The Javascript logic to open and close the hamburger menu
358358
when the button is clicked is usually handled by a script named
359
-"hbmenu.js" that is one of the [built-in resource files](/test-builtin-list)
359
+"hbmenu.js" that is one of the [built-in resource files](/test-builtin-files)
360360
that are part of Fossil.
361361
362362
The ≡ button for the hamburger menu is added to the menu bar by the following
363363
TH1 commands in the `header.txt` file, right before the menu bar links:
364364
365365
--- www/customskin.md
+++ www/customskin.md
@@ -238,11 +238,11 @@
238 part of the overall web page.</dd>
239
240 <dt><b>js.txt</b></dt><dd>
241
242 <p>The js.txt file is optional. It is intended to be javascript.
243 The complete text of this javascript is might be inserted into
244 the Content Footer, after being processed using TH1, using
245 code like the following in the "footer.txt" file:
246
247 <blockquote><pre>
248 &lt;script nonce="$nonce"&gt;
@@ -354,11 +354,11 @@
354
355 The menu bar of the default skin has an entry to open a drop-down menu with
356 additional navigation links, represented by the ≡ button (hence the name
357 "hamburger menu"). The Javascript logic to open and close the hamburger menu
358 when the button is clicked is usually handled by a script named
359 "hbmenu.js" that is one of the [built-in resource files](/test-builtin-list)
360 that are part of Fossil.
361
362 The ≡ button for the hamburger menu is added to the menu bar by the following
363 TH1 commands in the `header.txt` file, right before the menu bar links:
364
365
--- www/customskin.md
+++ www/customskin.md
@@ -238,11 +238,11 @@
238 part of the overall web page.</dd>
239
240 <dt><b>js.txt</b></dt><dd>
241
242 <p>The js.txt file is optional. It is intended to be javascript.
243 The complete text of this javascript might be inserted into
244 the Content Footer, after being processed using TH1, using
245 code like the following in the "footer.txt" file:
246
247 <blockquote><pre>
248 &lt;script nonce="$nonce"&gt;
@@ -354,11 +354,11 @@
354
355 The menu bar of the default skin has an entry to open a drop-down menu with
356 additional navigation links, represented by the ≡ button (hence the name
357 "hamburger menu"). The Javascript logic to open and close the hamburger menu
358 when the button is clicked is usually handled by a script named
359 "hbmenu.js" that is one of the [built-in resource files](/test-builtin-files)
360 that are part of Fossil.
361
362 The ≡ button for the hamburger menu is added to the menu bar by the following
363 TH1 commands in the `header.txt` file, right before the menu bar links:
364
365
+2 -2
--- www/defcsp.md
+++ www/defcsp.md
@@ -1,19 +1,19 @@
11
# The Default Content Security Policy (CSP)
22
33
When Fossil’s web interface generates an HTML page, it normally includes
44
a [Content Security Policy][csp] (CSP) in the `<head>`. The CSP specifies
55
allowed sources for external resources such as images,
6
-CSS, javascript, and so froth.
6
+CSS, javascript, and so forth.
77
The purpose of CSP is to provide an extra layer of protection against
88
[cross-site scripting][xss] (XSS) and code injection
99
attacks. Compatible web browsers will not use external resources unless
1010
they are specifically allowed by the CSP, which dramatically reduces
1111
the attack surface of the application.
1212
1313
Fossil does not rely on CSP for security.
14
-A Fossil server should be secure from attack even with out CSP.
14
+A Fossil server should be secure from attack even without CSP.
1515
Fossil includes built-in server-side content filtering logic.
1616
For example, Fossil purposely breaks `<script>` tags when it finds
1717
them in Markdown and Fossil Wiki documents. And the Fossil build
1818
process scans the source code for potential injection vulnerabilities
1919
and refuses to compile if any problems are found.
2020
--- www/defcsp.md
+++ www/defcsp.md
@@ -1,19 +1,19 @@
1 # The Default Content Security Policy (CSP)
2
3 When Fossil’s web interface generates an HTML page, it normally includes
4 a [Content Security Policy][csp] (CSP) in the `<head>`. The CSP specifies
5 allowed sources for external resources such as images,
6 CSS, javascript, and so froth.
7 The purpose of CSP is to provide an extra layer of protection against
8 [cross-site scripting][xss] (XSS) and code injection
9 attacks. Compatible web browsers will not use external resources unless
10 they are specifically allowed by the CSP, which dramatically reduces
11 the attack surface of the application.
12
13 Fossil does not rely on CSP for security.
14 A Fossil server should be secure from attack even with out CSP.
15 Fossil includes built-in server-side content filtering logic.
16 For example, Fossil purposely breaks `<script>` tags when it finds
17 them in Markdown and Fossil Wiki documents. And the Fossil build
18 process scans the source code for potential injection vulnerabilities
19 and refuses to compile if any problems are found.
20
--- www/defcsp.md
+++ www/defcsp.md
@@ -1,19 +1,19 @@
1 # The Default Content Security Policy (CSP)
2
3 When Fossil’s web interface generates an HTML page, it normally includes
4 a [Content Security Policy][csp] (CSP) in the `<head>`. The CSP specifies
5 allowed sources for external resources such as images,
6 CSS, javascript, and so forth.
7 The purpose of CSP is to provide an extra layer of protection against
8 [cross-site scripting][xss] (XSS) and code injection
9 attacks. Compatible web browsers will not use external resources unless
10 they are specifically allowed by the CSP, which dramatically reduces
11 the attack surface of the application.
12
13 Fossil does not rely on CSP for security.
14 A Fossil server should be secure from attack even without CSP.
15 Fossil includes built-in server-side content filtering logic.
16 For example, Fossil purposely breaks `<script>` tags when it finds
17 them in Markdown and Fossil Wiki documents. And the Fossil build
18 process scans the source code for potential injection vulnerabilities
19 and refuses to compile if any problems are found.
20
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -185,11 +185,11 @@
185185
<tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
186186
configured it with the <tt>--with-th1-docs</tt> option, which is
187187
disabled by default.
188188
189189
Since TH1 is a full scripting language, this feature essential grants
190
-the ability to execute code on the server to any with check-in
190
+the ability to execute code on the server to anyone with check-in
191191
privilege for the project.
192192
This is a security risk that needs to be carefully managed.
193193
The feature is off by default.
194194
Administrators should understand and carefully assess the risks
195195
before enabling the use of TH1 within embedded documentation.
@@ -206,14 +206,14 @@
206206
[http://fossil-scm.org/home/doc/trunk/www/embeddeddoc.wiki].
207207
208208
The first part of this path, the "[http://fossil-scm.org/home]",
209209
is the base URL. You might have originally typed:
210210
[http://fossil-scm.org/]. The web server at the fossil-scm.org
211
-site automatically redirects such links by appending "fossil". The
212
-"fossil" file on fossil-scm.org is really a CGI script
211
+site automatically redirects such links by appending "home". The
212
+"home" file on fossil-scm.org is really a [./server/any/cgi.md|CGI script]
213213
which runs the fossil web service in CGI mode.
214
-The "fossil" CGI script looks like this:
214
+The "home" CGI script looks like this:
215215
216216
<blockquote><pre>
217217
#!/usr/bin/fossil
218218
repository: /fossil/fossil.fossil
219219
</pre></blockquote>
220220
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -185,11 +185,11 @@
185 <tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
186 configured it with the <tt>--with-th1-docs</tt> option, which is
187 disabled by default.
188
189 Since TH1 is a full scripting language, this feature essential grants
190 the ability to execute code on the server to any with check-in
191 privilege for the project.
192 This is a security risk that needs to be carefully managed.
193 The feature is off by default.
194 Administrators should understand and carefully assess the risks
195 before enabling the use of TH1 within embedded documentation.
@@ -206,14 +206,14 @@
206 [http://fossil-scm.org/home/doc/trunk/www/embeddeddoc.wiki].
207
208 The first part of this path, the "[http://fossil-scm.org/home]",
209 is the base URL. You might have originally typed:
210 [http://fossil-scm.org/]. The web server at the fossil-scm.org
211 site automatically redirects such links by appending "fossil". The
212 "fossil" file on fossil-scm.org is really a CGI script
213 which runs the fossil web service in CGI mode.
214 The "fossil" CGI script looks like this:
215
216 <blockquote><pre>
217 #!/usr/bin/fossil
218 repository: /fossil/fossil.fossil
219 </pre></blockquote>
220
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -185,11 +185,11 @@
185 <tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have
186 configured it with the <tt>--with-th1-docs</tt> option, which is
187 disabled by default.
188
189 Since TH1 is a full scripting language, this feature essential grants
190 the ability to execute code on the server to anyone with check-in
191 privilege for the project.
192 This is a security risk that needs to be carefully managed.
193 The feature is off by default.
194 Administrators should understand and carefully assess the risks
195 before enabling the use of TH1 within embedded documentation.
@@ -206,14 +206,14 @@
206 [http://fossil-scm.org/home/doc/trunk/www/embeddeddoc.wiki].
207
208 The first part of this path, the "[http://fossil-scm.org/home]",
209 is the base URL. You might have originally typed:
210 [http://fossil-scm.org/]. The web server at the fossil-scm.org
211 site automatically redirects such links by appending "home". The
212 "home" file on fossil-scm.org is really a [./server/any/cgi.md|CGI script]
213 which runs the fossil web service in CGI mode.
214 The "home" CGI script looks like this:
215
216 <blockquote><pre>
217 #!/usr/bin/fossil
218 repository: /fossil/fossil.fossil
219 </pre></blockquote>
220
+8 -7
--- www/index.wiki
+++ www/index.wiki
@@ -24,11 +24,12 @@
2424
2525
1. <b>Project Management</b> -
2626
In addition to doing [./concepts.wiki | distributed version control]
2727
like Git and Mercurial,
2828
Fossil also supports [./bugtheory.wiki | bug tracking],
29
- [./wikitheory.wiki | wiki], [./forum.wiki | forum], [./chat.md | chat], and
29
+ [./wikitheory.wiki | wiki], [./forum.wiki | forum],
30
+ [./alerts.md|email alerts], [./chat.md | chat], and
3031
[./event.wiki | technotes].
3132
3233
2. <b>Built-in Web Interface</b> -
3334
Fossil has a built-in, [/skins | themeable], [./serverext.wiki | extensible],
3435
and intuitive [./webui.wiki | web interface]
@@ -82,25 +83,25 @@
8283
the repository are consistent prior to each commit.
8384
8485
8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license].
8586
8687
<hr>
87
-<h3>Latest Release: 2.15.2 ([/timeline?c=version-2.15.2|2021-06-15])</h3>
88
+<h3>Latest Release: 2.16 ([/timeline?c=version-2.16|2021-07-02])</h3>
8889
8990
* [/uv/download.html|Download]
90
- * [./changes.wiki#v2_15|Change Summary]
91
- * [/timeline?p=version-2.15.2&bt=version-2.14&y=ci|Check-ins in version 2.15.2]
92
- * [/timeline?df=version-2.15&y=ci|Check-ins derived from the 2.15 release]
91
+ * [./changes.wiki#v2_16|Change Summary]
92
+ * [/timeline?p=version-2.16&bt=version-2.15&y=ci|Check-ins in version 2.16]
93
+ * [/timeline?df=version-2.16&y=ci|Check-ins derived from the 2.16 release]
9394
* [/timeline?t=release|Timeline of all past releases]
9495
9596
<hr>
9697
<h3>Quick Start</h3>
9798
9899
1. [/uv/download.html|Download] or install using a package manager or
99100
[./build.wiki|compile from sources].
100
- 2. <tt>fossil init</tt> <i>REPOSTORE-DIR/new-repository</i>
101
- 3. <tt>fossil open</tt> <i>REPOSTORE-DIR/new-repository</i>
101
+ 2. <tt>fossil init</tt> <i>REPOSITORY-DIR/new-repository</i>
102
+ 3. <tt>fossil open</tt> <i>REPOSITORY-DIR/new-repository</i>
102103
4. <tt>fossil add</tt> <i>files-or-directories</i>
103104
5. <tt>fossil commit -m</tt> "<i>commit message</i>"
104105
6. <tt>fossil ui</tt>
105106
7. Repeat steps 4, 5, and 6, in any order, as necessary.
106107
See the [./quickstart.wiki|Quick Start Guide] for more detail.
107108
--- www/index.wiki
+++ www/index.wiki
@@ -24,11 +24,12 @@
24
25 1. <b>Project Management</b> -
26 In addition to doing [./concepts.wiki | distributed version control]
27 like Git and Mercurial,
28 Fossil also supports [./bugtheory.wiki | bug tracking],
29 [./wikitheory.wiki | wiki], [./forum.wiki | forum], [./chat.md | chat], and
 
30 [./event.wiki | technotes].
31
32 2. <b>Built-in Web Interface</b> -
33 Fossil has a built-in, [/skins | themeable], [./serverext.wiki | extensible],
34 and intuitive [./webui.wiki | web interface]
@@ -82,25 +83,25 @@
82 the repository are consistent prior to each commit.
83
84 8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license].
85
86 <hr>
87 <h3>Latest Release: 2.15.2 ([/timeline?c=version-2.15.2|2021-06-15])</h3>
88
89 * [/uv/download.html|Download]
90 * [./changes.wiki#v2_15|Change Summary]
91 * [/timeline?p=version-2.15.2&bt=version-2.14&y=ci|Check-ins in version 2.15.2]
92 * [/timeline?df=version-2.15&y=ci|Check-ins derived from the 2.15 release]
93 * [/timeline?t=release|Timeline of all past releases]
94
95 <hr>
96 <h3>Quick Start</h3>
97
98 1. [/uv/download.html|Download] or install using a package manager or
99 [./build.wiki|compile from sources].
100 2. <tt>fossil init</tt> <i>REPOSTORE-DIR/new-repository</i>
101 3. <tt>fossil open</tt> <i>REPOSTORE-DIR/new-repository</i>
102 4. <tt>fossil add</tt> <i>files-or-directories</i>
103 5. <tt>fossil commit -m</tt> "<i>commit message</i>"
104 6. <tt>fossil ui</tt>
105 7. Repeat steps 4, 5, and 6, in any order, as necessary.
106 See the [./quickstart.wiki|Quick Start Guide] for more detail.
107
--- www/index.wiki
+++ www/index.wiki
@@ -24,11 +24,12 @@
24
25 1. <b>Project Management</b> -
26 In addition to doing [./concepts.wiki | distributed version control]
27 like Git and Mercurial,
28 Fossil also supports [./bugtheory.wiki | bug tracking],
29 [./wikitheory.wiki | wiki], [./forum.wiki | forum],
30 [./alerts.md|email alerts], [./chat.md | chat], and
31 [./event.wiki | technotes].
32
33 2. <b>Built-in Web Interface</b> -
34 Fossil has a built-in, [/skins | themeable], [./serverext.wiki | extensible],
35 and intuitive [./webui.wiki | web interface]
@@ -82,25 +83,25 @@
83 the repository are consistent prior to each commit.
84
85 8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license].
86
87 <hr>
88 <h3>Latest Release: 2.16 ([/timeline?c=version-2.16|2021-07-02])</h3>
89
90 * [/uv/download.html|Download]
91 * [./changes.wiki#v2_16|Change Summary]
92 * [/timeline?p=version-2.16&bt=version-2.15&y=ci|Check-ins in version 2.16]
93 * [/timeline?df=version-2.16&y=ci|Check-ins derived from the 2.16 release]
94 * [/timeline?t=release|Timeline of all past releases]
95
96 <hr>
97 <h3>Quick Start</h3>
98
99 1. [/uv/download.html|Download] or install using a package manager or
100 [./build.wiki|compile from sources].
101 2. <tt>fossil init</tt> <i>REPOSITORY-DIR/new-repository</i>
102 3. <tt>fossil open</tt> <i>REPOSITORY-DIR/new-repository</i>
103 4. <tt>fossil add</tt> <i>files-or-directories</i>
104 5. <tt>fossil commit -m</tt> "<i>commit message</i>"
105 6. <tt>fossil ui</tt>
106 7. Repeat steps 4, 5, and 6, in any order, as necessary.
107 See the [./quickstart.wiki|Quick Start Guide] for more detail.
108
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -83,10 +83,11 @@
8383
makefile.wiki {The Fossil Build Process}
8484
mirrorlimitations.md {Limitations On Git Mirrors}
8585
mirrortogithub.md {How To Mirror A Fossil Repository On GitHub}
8686
/md_rules {Markdown Formatting Rules}
8787
newrepo.wiki {How To Create A New Fossil Repository}
88
+ patchcmd.md {The "fossil patch" Command}
8889
password.wiki {Password Management And Authentication}
8990
pikchr.md {The Pikchr Diagram Language}
9091
pop.wiki {Principles Of Operation}
9192
private.wiki {Creating, Syncing, and Deleting Private Branches}
9293
qandc.wiki {Questions And Criticisms}
9394
9495
ADDED www/patchcmd.md
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -83,10 +83,11 @@
83 makefile.wiki {The Fossil Build Process}
84 mirrorlimitations.md {Limitations On Git Mirrors}
85 mirrortogithub.md {How To Mirror A Fossil Repository On GitHub}
86 /md_rules {Markdown Formatting Rules}
87 newrepo.wiki {How To Create A New Fossil Repository}
 
88 password.wiki {Password Management And Authentication}
89 pikchr.md {The Pikchr Diagram Language}
90 pop.wiki {Principles Of Operation}
91 private.wiki {Creating, Syncing, and Deleting Private Branches}
92 qandc.wiki {Questions And Criticisms}
93
94 DDED www/patchcmd.md
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -83,10 +83,11 @@
83 makefile.wiki {The Fossil Build Process}
84 mirrorlimitations.md {Limitations On Git Mirrors}
85 mirrortogithub.md {How To Mirror A Fossil Repository On GitHub}
86 /md_rules {Markdown Formatting Rules}
87 newrepo.wiki {How To Create A New Fossil Repository}
88 patchcmd.md {The "fossil patch" Command}
89 password.wiki {Password Management And Authentication}
90 pikchr.md {The Pikchr Diagram Language}
91 pop.wiki {Principles Of Operation}
92 private.wiki {Creating, Syncing, and Deleting Private Branches}
93 qandc.wiki {Questions And Criticisms}
94
95 DDED www/patchcmd.md
--- a/www/patchcmd.md
+++ b/www/patchcmd.md
@@ -0,0 +1,60 @@
1
+# The "fossil patch" command?cmd=
2
+The "[fossil patch](/help/patch)" command is designed to transfer
3
+uncommitted changes from one check-out to another, including transfering
4
+those changes to other machines.
5
+
6
+For example, if you are working on a Windows desktop and you want to
7
+test your changes on a Linux server before you commit, you can use the
8
+"fossil patch push" command to make a copy of all your changes on>the
9
+remote Linux server:
10
+
11
+ fossil patch push linuxserver:/path/to"linuxserver" is the name of the remote machine and
12
+"/path/to/checkout" is an existing checkout directory for the same project
13
+on the remote machine.
14
+
15
+The "fossil patch push" command works by first creating a patch file,
16
+then transfering that patch file to the remote machine using "ssh", then
17
+applying the patch. If you do not have ssh available, you can break these
18
+steps apart as follows:
19
+
20
+ 1. On the local machine: `fossil patch create mypatch.patch`
21
+ 2. Move "mypatch.patch" to the remote machine.
22
+ 3. On the remote machine: `fossil patch apply mypatch.patch`
23
+
24
+Step 2 can be accomplished by a variety of means including
25
+posting the mypatch.patch file on [chat](./chat.md) or sending
26
+it as an email attachment.
27
+
28
+## Setup
29
+
30
+The "fossil p pull" commands will only wnork if you have
31
+"ssh" available on the local machine and if "fossil" is on the default
32
+PATH on the remote machine.
33
+
34
+To check if Fossil is installed correctly on the remote, try a command
35
+like this:
36
+
37
+> `on"
38
+
39
+If the command abdatabase`on of Fossil, then you should be
40
+set to go. If you get "fossil not found", or if the version shown is too
41
+old, put a newer fossil executable on the default PATH. The default PATH
42
+can be shown using:
43
+
44
+ ssh -T remot> `cho $PATH'
45
+
46
+### Custom PAT`ems, the init script for the user's login shell
47
+(e.g. `~/.profile` or `~/.bash_profile`) may be configured to *not do
48
+anything* when runninCt do
49
+anything* when running under a non-interactive shell. Thus a fossil
50
+binary installed to a custom directory might not be found. To allow
51
+the patchdatabase fila directory
52
+which is normally ad> `emote 'echo $PATH'
53
+
54
+### Custom PA`
55
+
56
+Is equivalent to:
57
+
58
+>ch.patch`
59
+ 2. Move "- | Thus a fossil
60
+binary i`~/.bash_profile`) may be `
--- a/www/patchcmd.md
+++ b/www/patchcmd.md
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/patchcmd.md
+++ b/www/patchcmd.md
@@ -0,0 +1,60 @@
1 # The "fossil patch" command?cmd=
2 The "[fossil patch](/help/patch)" command is designed to transfer
3 uncommitted changes from one check-out to another, including transfering
4 those changes to other machines.
5
6 For example, if you are working on a Windows desktop and you want to
7 test your changes on a Linux server before you commit, you can use the
8 "fossil patch push" command to make a copy of all your changes on>the
9 remote Linux server:
10
11 fossil patch push linuxserver:/path/to"linuxserver" is the name of the remote machine and
12 "/path/to/checkout" is an existing checkout directory for the same project
13 on the remote machine.
14
15 The "fossil patch push" command works by first creating a patch file,
16 then transfering that patch file to the remote machine using "ssh", then
17 applying the patch. If you do not have ssh available, you can break these
18 steps apart as follows:
19
20 1. On the local machine: `fossil patch create mypatch.patch`
21 2. Move "mypatch.patch" to the remote machine.
22 3. On the remote machine: `fossil patch apply mypatch.patch`
23
24 Step 2 can be accomplished by a variety of means including
25 posting the mypatch.patch file on [chat](./chat.md) or sending
26 it as an email attachment.
27
28 ## Setup
29
30 The "fossil p pull" commands will only wnork if you have
31 "ssh" available on the local machine and if "fossil" is on the default
32 PATH on the remote machine.
33
34 To check if Fossil is installed correctly on the remote, try a command
35 like this:
36
37 > `on"
38
39 If the command abdatabase`on of Fossil, then you should be
40 set to go. If you get "fossil not found", or if the version shown is too
41 old, put a newer fossil executable on the default PATH. The default PATH
42 can be shown using:
43
44 ssh -T remot> `cho $PATH'
45
46 ### Custom PAT`ems, the init script for the user's login shell
47 (e.g. `~/.profile` or `~/.bash_profile`) may be configured to *not do
48 anything* when runninCt do
49 anything* when running under a non-interactive shell. Thus a fossil
50 binary installed to a custom directory might not be found. To allow
51 the patchdatabase fila directory
52 which is normally ad> `emote 'echo $PATH'
53
54 ### Custom PA`
55
56 Is equivalent to:
57
58 >ch.patch`
59 2. Move "- | Thus a fossil
60 binary i`~/.bash_profile`) may be `
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -106,10 +106,11 @@
106106
<li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li>
107107
<li><a href="../../../sitemap">Site Map</a></li>
108108
<li><a href="style.wiki">Source Code Style Guidelines</a></li>
109109
<li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li>
110110
<li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li>
111
+<li><a href="patchcmd.md">The "fossil patch" Command</a></li>
111112
<li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li>
112113
<li><a href="defcsp.md">The Default Content Security Policy</a></li>
113114
<li><a href="fileedit-page.md">The fileedit Page</a></li>
114115
<li><a href="makefile.wiki">The Fossil Build Process</a></li>
115116
<li><a href="sync.wiki">The Fossil Sync Protocol</a></li>
116117
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -106,10 +106,11 @@
106 <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li>
107 <li><a href="../../../sitemap">Site Map</a></li>
108 <li><a href="style.wiki">Source Code Style Guidelines</a></li>
109 <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li>
110 <li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li>
 
111 <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li>
112 <li><a href="defcsp.md">The Default Content Security Policy</a></li>
113 <li><a href="fileedit-page.md">The fileedit Page</a></li>
114 <li><a href="makefile.wiki">The Fossil Build Process</a></li>
115 <li><a href="sync.wiki">The Fossil Sync Protocol</a></li>
116
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -106,10 +106,11 @@
106 <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li>
107 <li><a href="../../../sitemap">Site Map</a></li>
108 <li><a href="style.wiki">Source Code Style Guidelines</a></li>
109 <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li>
110 <li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li>
111 <li><a href="patchcmd.md">The "fossil patch" Command</a></li>
112 <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li>
113 <li><a href="defcsp.md">The Default Content Security Policy</a></li>
114 <li><a href="fileedit-page.md">The fileedit Page</a></li>
115 <li><a href="makefile.wiki">The Fossil Build Process</a></li>
116 <li><a href="sync.wiki">The Fossil Sync Protocol</a></li>
117
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -60,14 +60,14 @@
6060
onto a $5/month "droplet" [https://en.wikipedia.org/wiki/Virtual_private_server|VPS]
6161
from [https://www.digitalocean.com|Digital Ocean]
6262
located in San Francisco.
6363
6464
Server (3) is synchronized with the canonical server (1) by running
65
-the following command via cron:
65
+a command similar to the following via cron:
6666
6767
<blockquote><pre>
68
-/home/hwaci/bin/fossil sync -R /home/hwaci/fossil/fossil.fossil
68
+/usr/local/bin/fossil all sync -u
6969
</pre></blockquote>
7070
7171
Server (2) is a
7272
<a href="http://www.linode.com/">Linode 4096</a> located in Newark, NJ
7373
and set up just like the canonical server (1) with the addition of a
7474
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -60,14 +60,14 @@
60 onto a $5/month "droplet" [https://en.wikipedia.org/wiki/Virtual_private_server|VPS]
61 from [https://www.digitalocean.com|Digital Ocean]
62 located in San Francisco.
63
64 Server (3) is synchronized with the canonical server (1) by running
65 the following command via cron:
66
67 <blockquote><pre>
68 /home/hwaci/bin/fossil sync -R /home/hwaci/fossil/fossil.fossil
69 </pre></blockquote>
70
71 Server (2) is a
72 <a href="http://www.linode.com/">Linode 4096</a> located in Newark, NJ
73 and set up just like the canonical server (1) with the addition of a
74
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -60,14 +60,14 @@
60 onto a $5/month "droplet" [https://en.wikipedia.org/wiki/Virtual_private_server|VPS]
61 from [https://www.digitalocean.com|Digital Ocean]
62 located in San Francisco.
63
64 Server (3) is synchronized with the canonical server (1) by running
65 a command similar to the following via cron:
66
67 <blockquote><pre>
68 /usr/local/bin/fossil all sync -u
69 </pre></blockquote>
70
71 Server (2) is a
72 <a href="http://www.linode.com/">Linode 4096</a> located in Newark, NJ
73 and set up just like the canonical server (1) with the addition of a
74
--- www/server/any/cgi.md
+++ www/server/any/cgi.md
@@ -35,11 +35,14 @@
3535
3636
* The repository file *and* the directory containing it must be
3737
writable by the same account which executes the Fossil binary.
3838
(This might differ from the user the web server normally runs
3939
under.) The directory holding the repository file(s) needs to be
40
- writable so that SQLite can write its journal files.
40
+ writable so that SQLite can write its journal files. When using
41
+ another access control system, such as AppArmor or SELinux, it may
42
+ be necessary to explicitly permit that account to read and write
43
+ the necessary files.
4144
4245
* Fossil must be able to create temporary files in a
4346
[directory that varies by host OS](../../env-opts.md#temp). When the
4447
CGI process is operating [within a chroot](../../chroot.md),
4548
ensure that this directory exists and is readable/writeable by the
4649
--- www/server/any/cgi.md
+++ www/server/any/cgi.md
@@ -35,11 +35,14 @@
35
36 * The repository file *and* the directory containing it must be
37 writable by the same account which executes the Fossil binary.
38 (This might differ from the user the web server normally runs
39 under.) The directory holding the repository file(s) needs to be
40 writable so that SQLite can write its journal files.
 
 
 
41
42 * Fossil must be able to create temporary files in a
43 [directory that varies by host OS](../../env-opts.md#temp). When the
44 CGI process is operating [within a chroot](../../chroot.md),
45 ensure that this directory exists and is readable/writeable by the
46
--- www/server/any/cgi.md
+++ www/server/any/cgi.md
@@ -35,11 +35,14 @@
35
36 * The repository file *and* the directory containing it must be
37 writable by the same account which executes the Fossil binary.
38 (This might differ from the user the web server normally runs
39 under.) The directory holding the repository file(s) needs to be
40 writable so that SQLite can write its journal files. When using
41 another access control system, such as AppArmor or SELinux, it may
42 be necessary to explicitly permit that account to read and write
43 the necessary files.
44
45 * Fossil must be able to create temporary files in a
46 [directory that varies by host OS](../../env-opts.md#temp). When the
47 CGI process is operating [within a chroot](../../chroot.md),
48 ensure that this directory exists and is readable/writeable by the
49
--- www/server/debian/service.md
+++ www/server/debian/service.md
@@ -29,20 +29,19 @@
2929
`~/.local/share/systemd/user/fossil.service`:
3030
3131
```dosini
3232
[Unit]
3333
Description=Fossil user server
34
- After=network.target
34
+ After=network-online.target
3535
3636
[Service]
3737
WorkingDirectory=/home/fossil/museum
3838
ExecStart=/home/fossil/bin/fossil server --port 9000 repo.fossil
3939
Restart=always
4040
RestartSec=3
4141
4242
[Install]
43
- WantedBy=sockets.target
4443
WantedBy=multi-user.target
4544
```
4645
4746
Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which
4847
user and group to run this service as, because we’ve installed it
@@ -64,11 +63,11 @@
6463
find online:
6564
6665
$ systemctl --user daemon-reload
6766
$ systemctl --user enable fossil
6867
$ systemctl --user start fossil
69
- $ systemctl --user status -l fossil
68
+ $ systemctl --user status fossil -l
7069
$ systemctl --user stop fossil
7170
7271
That is, we don’t need to talk to `systemd` with `sudo` privileges, but
7372
we do need to tell it to look at the user configuration rather than the
7473
system-level configuration.
@@ -89,14 +88,21 @@
8988
9089
9190
9291
### System Service Alternative
9392
94
-Another workaround for the problem with user services above is to
95
-install the service as a system service instead. This is a better path
96
-when you are proxying Fossil with a system-level service, such as
97
-[nginx](./nginx.md).
93
+There are a couple of common reasons that you’d have cause to install
94
+Fossil as a system-level service rather than the prior user-level one:
95
+
96
+* You need Fossil to listen on a TCP port under 1024, such as because
97
+ you’re running it on a private LAN, and the server has no other HTTP
98
+ service, so you want Fossil to handle the web traffic directly.
99
+
100
+* You’re proxying Fossil with a system-level service such as
101
+ [nginx](./nginx.md), so you need to put Fossil into the system-level
102
+ service dependency chain to make sure things start up and shut down
103
+ in the proper order.
98104
99105
There are just a small set of changes required:
100106
101107
1. Install the unit file to one of the persistent system-level unit
102108
file directories. Typically, these are:
@@ -146,19 +152,18 @@
146152
`[email protected]`:
147153
148154
```dosini
149155
[Unit]
150156
Description=Fossil socket server
151
- After=network.target
157
+ After=network-online.target
152158
153159
[Service]
154160
WorkingDirectory=/home/fossil/museum
155161
ExecStart=/home/fossil/bin/fossil http repo.fossil
156162
StandardInput=socket
157163
158164
[Install]
159
- WantedBy=sockets.target
160165
WantedBy=multi-user.target
161166
```
162167
163168
We’ll explain the “`@`” in the file name below.
164169
165170
--- www/server/debian/service.md
+++ www/server/debian/service.md
@@ -29,20 +29,19 @@
29 `~/.local/share/systemd/user/fossil.service`:
30
31 ```dosini
32 [Unit]
33 Description=Fossil user server
34 After=network.target
35
36 [Service]
37 WorkingDirectory=/home/fossil/museum
38 ExecStart=/home/fossil/bin/fossil server --port 9000 repo.fossil
39 Restart=always
40 RestartSec=3
41
42 [Install]
43 WantedBy=sockets.target
44 WantedBy=multi-user.target
45 ```
46
47 Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which
48 user and group to run this service as, because we’ve installed it
@@ -64,11 +63,11 @@
64 find online:
65
66 $ systemctl --user daemon-reload
67 $ systemctl --user enable fossil
68 $ systemctl --user start fossil
69 $ systemctl --user status -l fossil
70 $ systemctl --user stop fossil
71
72 That is, we don’t need to talk to `systemd` with `sudo` privileges, but
73 we do need to tell it to look at the user configuration rather than the
74 system-level configuration.
@@ -89,14 +88,21 @@
89
90
91
92 ### System Service Alternative
93
94 Another workaround for the problem with user services above is to
95 install the service as a system service instead. This is a better path
96 when you are proxying Fossil with a system-level service, such as
97 [nginx](./nginx.md).
 
 
 
 
 
 
 
98
99 There are just a small set of changes required:
100
101 1. Install the unit file to one of the persistent system-level unit
102 file directories. Typically, these are:
@@ -146,19 +152,18 @@
146 `[email protected]`:
147
148 ```dosini
149 [Unit]
150 Description=Fossil socket server
151 After=network.target
152
153 [Service]
154 WorkingDirectory=/home/fossil/museum
155 ExecStart=/home/fossil/bin/fossil http repo.fossil
156 StandardInput=socket
157
158 [Install]
159 WantedBy=sockets.target
160 WantedBy=multi-user.target
161 ```
162
163 We’ll explain the “`@`” in the file name below.
164
165
--- www/server/debian/service.md
+++ www/server/debian/service.md
@@ -29,20 +29,19 @@
29 `~/.local/share/systemd/user/fossil.service`:
30
31 ```dosini
32 [Unit]
33 Description=Fossil user server
34 After=network-online.target
35
36 [Service]
37 WorkingDirectory=/home/fossil/museum
38 ExecStart=/home/fossil/bin/fossil server --port 9000 repo.fossil
39 Restart=always
40 RestartSec=3
41
42 [Install]
 
43 WantedBy=multi-user.target
44 ```
45
46 Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which
47 user and group to run this service as, because we’ve installed it
@@ -64,11 +63,11 @@
63 find online:
64
65 $ systemctl --user daemon-reload
66 $ systemctl --user enable fossil
67 $ systemctl --user start fossil
68 $ systemctl --user status fossil -l
69 $ systemctl --user stop fossil
70
71 That is, we don’t need to talk to `systemd` with `sudo` privileges, but
72 we do need to tell it to look at the user configuration rather than the
73 system-level configuration.
@@ -89,14 +88,21 @@
88
89
90
91 ### System Service Alternative
92
93 There are a couple of common reasons that you’d have cause to install
94 Fossil as a system-level service rather than the prior user-level one:
95
96 * You need Fossil to listen on a TCP port under 1024, such as because
97 you’re running it on a private LAN, and the server has no other HTTP
98 service, so you want Fossil to handle the web traffic directly.
99
100 * You’re proxying Fossil with a system-level service such as
101 [nginx](./nginx.md), so you need to put Fossil into the system-level
102 service dependency chain to make sure things start up and shut down
103 in the proper order.
104
105 There are just a small set of changes required:
106
107 1. Install the unit file to one of the persistent system-level unit
108 file directories. Typically, these are:
@@ -146,19 +152,18 @@
152 `[email protected]`:
153
154 ```dosini
155 [Unit]
156 Description=Fossil socket server
157 After=network-online.target
158
159 [Service]
160 WorkingDirectory=/home/fossil/museum
161 ExecStart=/home/fossil/bin/fossil http repo.fossil
162 StandardInput=socket
163
164 [Install]
 
165 WantedBy=multi-user.target
166 ```
167
168 We’ll explain the “`@`” in the file name below.
169
170
--- www/serverext.wiki
+++ www/serverext.wiki
@@ -4,12 +4,12 @@
44
55
If you have a [./server/|Fossil server] for your project,
66
you can add [./aboutcgi.wiki|CGI]
77
extensions to that server. These extensions work like
88
any other CGI program, except that they also have access to the Fossil
9
-login information and can (optionally) leverage the "skins" of Fossil
10
-so that they appear to be more tightly integrated into the project.
9
+login information and can (optionally) leverage the "[./customskin.md|skins]"
10
+of Fossil so that they appear to be more tightly integrated into the project.
1111
1212
An example of where this is useful is the
1313
[https://sqlite.org/src/ext/checklist|checklist application] on
1414
the [https://sqlite.org/|SQLite] project. The checklist
1515
helps the SQLite developers track which release tests have passed,
@@ -25,11 +25,12 @@
2525
2626
<h2>2.0 How It Works</h2>
2727
2828
CGI Extensions are disabled by default.
2929
An administrator activates the CGI extension mechanism by specifying
30
-an "Extension Root Directory" or "extroot" as part of the server setup.
30
+an "Extension Root Directory" or "extroot" as part of the
31
+[./server/index.html|server setup].
3132
If the Fossil server is itself run as
3233
[./server/any/cgi.md|CGI], then add a line to the
3334
[./cgi.wiki#extroot|CGI script file] that says:
3435
3536
<blockquote><pre>
3637
--- www/serverext.wiki
+++ www/serverext.wiki
@@ -4,12 +4,12 @@
4
5 If you have a [./server/|Fossil server] for your project,
6 you can add [./aboutcgi.wiki|CGI]
7 extensions to that server. These extensions work like
8 any other CGI program, except that they also have access to the Fossil
9 login information and can (optionally) leverage the "skins" of Fossil
10 so that they appear to be more tightly integrated into the project.
11
12 An example of where this is useful is the
13 [https://sqlite.org/src/ext/checklist|checklist application] on
14 the [https://sqlite.org/|SQLite] project. The checklist
15 helps the SQLite developers track which release tests have passed,
@@ -25,11 +25,12 @@
25
26 <h2>2.0 How It Works</h2>
27
28 CGI Extensions are disabled by default.
29 An administrator activates the CGI extension mechanism by specifying
30 an "Extension Root Directory" or "extroot" as part of the server setup.
 
31 If the Fossil server is itself run as
32 [./server/any/cgi.md|CGI], then add a line to the
33 [./cgi.wiki#extroot|CGI script file] that says:
34
35 <blockquote><pre>
36
--- www/serverext.wiki
+++ www/serverext.wiki
@@ -4,12 +4,12 @@
4
5 If you have a [./server/|Fossil server] for your project,
6 you can add [./aboutcgi.wiki|CGI]
7 extensions to that server. These extensions work like
8 any other CGI program, except that they also have access to the Fossil
9 login information and can (optionally) leverage the "[./customskin.md|skins]"
10 of Fossil so that they appear to be more tightly integrated into the project.
11
12 An example of where this is useful is the
13 [https://sqlite.org/src/ext/checklist|checklist application] on
14 the [https://sqlite.org/|SQLite] project. The checklist
15 helps the SQLite developers track which release tests have passed,
@@ -25,11 +25,12 @@
25
26 <h2>2.0 How It Works</h2>
27
28 CGI Extensions are disabled by default.
29 An administrator activates the CGI extension mechanism by specifying
30 an "Extension Root Directory" or "extroot" as part of the
31 [./server/index.html|server setup].
32 If the Fossil server is itself run as
33 [./server/any/cgi.md|CGI], then add a line to the
34 [./cgi.wiki#extroot|CGI script file] that says:
35
36 <blockquote><pre>
37
+1 -1
--- www/ssl.wiki
+++ www/ssl.wiki
@@ -177,11 +177,11 @@
177177
for a different core reason: Windows does ship with a stock CA
178178
certificate set, but it's not in a format that OpenSSL understands how
179179
to use. Rather than try to find a way to convert the data format, you
180180
may find it acceptable to use the same Mozilla NSS cert set. I do not
181181
know of a way to easily get this from Mozilla themselves, but I did find
182
-a [https://curl.haxx.se/docs/caextract.html|third party source] for the
182
+a [https://curl.se/docs/caextract.html | third party source] for the
183183
<tt>cacert.pem</tt> file. I suggest placing the file into your Windows
184184
user home directory so that you can then point Fossil at it like so:
185185
186186
<pre>
187187
fossil set --global ssl-ca-location %userprofile%\cacert.pem
188188
--- www/ssl.wiki
+++ www/ssl.wiki
@@ -177,11 +177,11 @@
177 for a different core reason: Windows does ship with a stock CA
178 certificate set, but it's not in a format that OpenSSL understands how
179 to use. Rather than try to find a way to convert the data format, you
180 may find it acceptable to use the same Mozilla NSS cert set. I do not
181 know of a way to easily get this from Mozilla themselves, but I did find
182 a [https://curl.haxx.se/docs/caextract.html|third party source] for the
183 <tt>cacert.pem</tt> file. I suggest placing the file into your Windows
184 user home directory so that you can then point Fossil at it like so:
185
186 <pre>
187 fossil set --global ssl-ca-location %userprofile%\cacert.pem
188
--- www/ssl.wiki
+++ www/ssl.wiki
@@ -177,11 +177,11 @@
177 for a different core reason: Windows does ship with a stock CA
178 certificate set, but it's not in a format that OpenSSL understands how
179 to use. Rather than try to find a way to convert the data format, you
180 may find it acceptable to use the same Mozilla NSS cert set. I do not
181 know of a way to easily get this from Mozilla themselves, but I did find
182 a [https://curl.se/docs/caextract.html | third party source] for the
183 <tt>cacert.pem</tt> file. I suggest placing the file into your Windows
184 user home directory so that you can then point Fossil at it like so:
185
186 <pre>
187 fossil set --global ssl-ca-location %userprofile%\cacert.pem
188
+8 -6
--- www/th1.md
+++ www/th1.md
@@ -40,13 +40,14 @@
4040
is broken into space-separated tokens. The first token is the command
4141
name and subsequent tokens are the arguments. In this sense, TH1 syntax
4242
is similar to the familiar command-line shell syntax.
4343
4444
A token is any sequence of characters other than whitespace and semicolons.
45
-Or, all text without double-quotes is a single token even if it includes
46
-whitespace and semicolons. Or, all text within nested {...} pairs is a
47
-single token.
45
+Text inside double-quotes is a single token even if it includes
46
+whitespace and semicolons. Text within {...} pairs is also a
47
+single token, which is useful because curly braces are easier to “pair”
48
+and nest properly than double-quotes.
4849
4950
The nested {...} form of tokens is important because it allows TH1 commands
5051
to have an appearance similar to C/C++. It is important to remember, though,
5152
that a TH1 script is really just a list of text commands, not a context-free
5253
language with a grammar like C/C++. This can be confusing to long-time
@@ -64,11 +65,11 @@
6465
The example above is a single command. The first token, and the name
6566
of the command, is `if`.
6667
The second token is `$current eq "dev"` - an expression. (The outer {...}
6768
are removed from each token by the command parser.) The third token
6869
is the `puts "hello"`, with its whitespace and newlines. The fourth token
69
-is `else"` And the fifth and last token is `puts "world"`.
70
+is `else` and the fifth and last token is `puts "world"`.
7071
7172
The `if` command evaluates its first argument (the second token)
7273
as an expression, and if that expression is true, evaluates its
7374
second argument (the third token) as a TH1 script.
7475
If the expression is false and the third argument is `else`, then
@@ -110,11 +111,11 @@
110111
111112
112113
Summary of Core TH1 Commands
113114
----------------------------
114115
115
-The original Tcl language after when TH1 is modeled has a very rich
116
+The original Tcl language (after which TH1 is modeled) has a very rich
116117
repertoire of commands. TH1, as it is designed to be minimalist and
117118
embedded has a greatly reduced command set. The following bullets
118119
summarize the commands available in TH1:
119120
120121
* array exists VARNAME
@@ -284,11 +285,12 @@
284285
Added in Fossil 2.15.
285286
286287
* capexpr CAPABILITY-EXPR
287288
288289
The capability expression is a list. Each term of the list is a
289
-cluster of capability letters. The overall expression is true if any
290
+cluster of [capability letters](./caps/ref.html).
291
+The overall expression is true if any
290292
one term is true. A single term is true if all letters within that
291293
term are true. Or, if the term begins with "!", then the term is true
292294
if none of the terms or true. Or, if the term begins with "@" then
293295
the term is true if all of the capability letters in that term are
294296
available to the "anonymous" user. Or, if the term is "*" then it is
295297
--- www/th1.md
+++ www/th1.md
@@ -40,13 +40,14 @@
40 is broken into space-separated tokens. The first token is the command
41 name and subsequent tokens are the arguments. In this sense, TH1 syntax
42 is similar to the familiar command-line shell syntax.
43
44 A token is any sequence of characters other than whitespace and semicolons.
45 Or, all text without double-quotes is a single token even if it includes
46 whitespace and semicolons. Or, all text within nested {...} pairs is a
47 single token.
 
48
49 The nested {...} form of tokens is important because it allows TH1 commands
50 to have an appearance similar to C/C++. It is important to remember, though,
51 that a TH1 script is really just a list of text commands, not a context-free
52 language with a grammar like C/C++. This can be confusing to long-time
@@ -64,11 +65,11 @@
64 The example above is a single command. The first token, and the name
65 of the command, is `if`.
66 The second token is `$current eq "dev"` - an expression. (The outer {...}
67 are removed from each token by the command parser.) The third token
68 is the `puts "hello"`, with its whitespace and newlines. The fourth token
69 is `else"` And the fifth and last token is `puts "world"`.
70
71 The `if` command evaluates its first argument (the second token)
72 as an expression, and if that expression is true, evaluates its
73 second argument (the third token) as a TH1 script.
74 If the expression is false and the third argument is `else`, then
@@ -110,11 +111,11 @@
110
111
112 Summary of Core TH1 Commands
113 ----------------------------
114
115 The original Tcl language after when TH1 is modeled has a very rich
116 repertoire of commands. TH1, as it is designed to be minimalist and
117 embedded has a greatly reduced command set. The following bullets
118 summarize the commands available in TH1:
119
120 * array exists VARNAME
@@ -284,11 +285,12 @@
284 Added in Fossil 2.15.
285
286 * capexpr CAPABILITY-EXPR
287
288 The capability expression is a list. Each term of the list is a
289 cluster of capability letters. The overall expression is true if any
 
290 one term is true. A single term is true if all letters within that
291 term are true. Or, if the term begins with "!", then the term is true
292 if none of the terms or true. Or, if the term begins with "@" then
293 the term is true if all of the capability letters in that term are
294 available to the "anonymous" user. Or, if the term is "*" then it is
295
--- www/th1.md
+++ www/th1.md
@@ -40,13 +40,14 @@
40 is broken into space-separated tokens. The first token is the command
41 name and subsequent tokens are the arguments. In this sense, TH1 syntax
42 is similar to the familiar command-line shell syntax.
43
44 A token is any sequence of characters other than whitespace and semicolons.
45 Text inside double-quotes is a single token even if it includes
46 whitespace and semicolons. Text within {...} pairs is also a
47 single token, which is useful because curly braces are easier to “pair”
48 and nest properly than double-quotes.
49
50 The nested {...} form of tokens is important because it allows TH1 commands
51 to have an appearance similar to C/C++. It is important to remember, though,
52 that a TH1 script is really just a list of text commands, not a context-free
53 language with a grammar like C/C++. This can be confusing to long-time
@@ -64,11 +65,11 @@
65 The example above is a single command. The first token, and the name
66 of the command, is `if`.
67 The second token is `$current eq "dev"` - an expression. (The outer {...}
68 are removed from each token by the command parser.) The third token
69 is the `puts "hello"`, with its whitespace and newlines. The fourth token
70 is `else` and the fifth and last token is `puts "world"`.
71
72 The `if` command evaluates its first argument (the second token)
73 as an expression, and if that expression is true, evaluates its
74 second argument (the third token) as a TH1 script.
75 If the expression is false and the third argument is `else`, then
@@ -110,11 +111,11 @@
111
112
113 Summary of Core TH1 Commands
114 ----------------------------
115
116 The original Tcl language (after which TH1 is modeled) has a very rich
117 repertoire of commands. TH1, as it is designed to be minimalist and
118 embedded has a greatly reduced command set. The following bullets
119 summarize the commands available in TH1:
120
121 * array exists VARNAME
@@ -284,11 +285,12 @@
285 Added in Fossil 2.15.
286
287 * capexpr CAPABILITY-EXPR
288
289 The capability expression is a list. Each term of the list is a
290 cluster of [capability letters](./caps/ref.html).
291 The overall expression is true if any
292 one term is true. A single term is true if all letters within that
293 term are true. Or, if the term begins with "!", then the term is true
294 if none of the terms or true. Or, if the term begins with "@" then
295 the term is true if all of the capability letters in that term are
296 available to the "anonymous" user. Or, if the term is "*" then it is
297

Keyboard Shortcuts

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