Fossil SCM

Updating from trunk to get the latest trunk fixes.

viriketo 2012-04-04 16:20 annotate_links merge
Commit b7f3a32d4e67a900c0ac5e9b2bec23d412ef597c
--- ajax/i-test/rhino-test.js
+++ ajax/i-test/rhino-test.js
@@ -3,11 +3,11 @@
33
'http://localhost:8080'
44
//'http://fjson/cgi-bin/fossil-json.cgi'
55
//'http://192.168.1.62:8080'
66
//'http://fossil.wanderinghorse.net/repos/fossil-json-java/index.cgi'
77
,
8
- verbose:false,
8
+ verbose:true,
99
fossilBinary:'fossil',
1010
wiki:{}
1111
};
1212
(function bootstrap() {
1313
var srcdir = '../js/';
@@ -171,10 +171,26 @@
171171
print("Got first wiki page: "+WhAjaj.stringify(rs.payload));
172172
173173
}
174174
testAnonWiki.description = 'Fetch wiki list as anonymous user.';
175175
176
+function testFetchCheckinArtifact(){
177
+ var art = '18dd383e5e7684ece';
178
+ var rs;
179
+ TestApp.fossil.sendCommand('/json/artifact',{
180
+ 'name': art
181
+ },
182
+ {
183
+ onResponse:function(resp,req){
184
+ rs = resp;
185
+ }
186
+ });
187
+ assertResponseOK(rs);
188
+ assert(3 == rs.payload.artifact.parents.length, 'Got 3 parent artifacts.');
189
+}
190
+testFetchCheckinArtifact.description = '/json/artifact/CHECKIN';
191
+
176192
function testAnonLogout(){
177193
var rs;
178194
TestApp.fossil.logout({
179195
onResponse:function(resp,req){
180196
rs = resp;
@@ -239,10 +255,11 @@
239255
var testList = [
240256
testHAI,
241257
testIAmNobody,
242258
testAnonymousLogin,
243259
testAnonWiki,
260
+ testFetchCheckinArtifact,
244261
testAnonLogout,
245262
testExternalProcess,
246263
testExternalProcessHandler
247264
];
248265
var i, f;
249266
--- ajax/i-test/rhino-test.js
+++ ajax/i-test/rhino-test.js
@@ -3,11 +3,11 @@
3 'http://localhost:8080'
4 //'http://fjson/cgi-bin/fossil-json.cgi'
5 //'http://192.168.1.62:8080'
6 //'http://fossil.wanderinghorse.net/repos/fossil-json-java/index.cgi'
7 ,
8 verbose:false,
9 fossilBinary:'fossil',
10 wiki:{}
11 };
12 (function bootstrap() {
13 var srcdir = '../js/';
@@ -171,10 +171,26 @@
171 print("Got first wiki page: "+WhAjaj.stringify(rs.payload));
172
173 }
174 testAnonWiki.description = 'Fetch wiki list as anonymous user.';
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176 function testAnonLogout(){
177 var rs;
178 TestApp.fossil.logout({
179 onResponse:function(resp,req){
180 rs = resp;
@@ -239,10 +255,11 @@
239 var testList = [
240 testHAI,
241 testIAmNobody,
242 testAnonymousLogin,
243 testAnonWiki,
 
244 testAnonLogout,
245 testExternalProcess,
246 testExternalProcessHandler
247 ];
248 var i, f;
249
--- ajax/i-test/rhino-test.js
+++ ajax/i-test/rhino-test.js
@@ -3,11 +3,11 @@
3 'http://localhost:8080'
4 //'http://fjson/cgi-bin/fossil-json.cgi'
5 //'http://192.168.1.62:8080'
6 //'http://fossil.wanderinghorse.net/repos/fossil-json-java/index.cgi'
7 ,
8 verbose:true,
9 fossilBinary:'fossil',
10 wiki:{}
11 };
12 (function bootstrap() {
13 var srcdir = '../js/';
@@ -171,10 +171,26 @@
171 print("Got first wiki page: "+WhAjaj.stringify(rs.payload));
172
173 }
174 testAnonWiki.description = 'Fetch wiki list as anonymous user.';
175
176 function testFetchCheckinArtifact(){
177 var art = '18dd383e5e7684ece';
178 var rs;
179 TestApp.fossil.sendCommand('/json/artifact',{
180 'name': art
181 },
182 {
183 onResponse:function(resp,req){
184 rs = resp;
185 }
186 });
187 assertResponseOK(rs);
188 assert(3 == rs.payload.artifact.parents.length, 'Got 3 parent artifacts.');
189 }
190 testFetchCheckinArtifact.description = '/json/artifact/CHECKIN';
191
192 function testAnonLogout(){
193 var rs;
194 TestApp.fossil.logout({
195 onResponse:function(resp,req){
196 rs = resp;
@@ -239,10 +255,11 @@
255 var testList = [
256 testHAI,
257 testIAmNobody,
258 testAnonymousLogin,
259 testAnonWiki,
260 testFetchCheckinArtifact,
261 testAnonLogout,
262 testExternalProcess,
263 testExternalProcessHandler
264 ];
265 var i, f;
266
--- ajax/index.html
+++ ajax/index.html
@@ -233,14 +233,18 @@
233233
<input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
234234
<input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
235235
<input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
236236
<input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
237237
<input type='button' value='timeline/branch' onclick='TheApp.cgi.sendCommand("/json/timeline/branch")' />
238
+
239
+<br/>
240
+
238241
<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
239242
<input type='button' value='wiki/list verbose' onclick='TheApp.cgi.sendCommand("/json/wiki/list",{verbose:1})' />
240243
<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{name:"Fossil"})' />
241244
<input type='button' value='wiki/get/Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get/Fossil")' />
245
+<input type='button' value='wiki/diff' onclick='TheApp.cgi.sendCommand("/json/wiki/diff/e32ccdcda59e930c77c/e15992f475760cdf3a9")' />
242246
243247
<br/>
244248
245249
<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
246250
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
247251
--- ajax/index.html
+++ ajax/index.html
@@ -233,14 +233,18 @@
233 <input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
234 <input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
235 <input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
236 <input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
237 <input type='button' value='timeline/branch' onclick='TheApp.cgi.sendCommand("/json/timeline/branch")' />
 
 
 
238 <input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
239 <input type='button' value='wiki/list verbose' onclick='TheApp.cgi.sendCommand("/json/wiki/list",{verbose:1})' />
240 <input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{name:"Fossil"})' />
241 <input type='button' value='wiki/get/Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get/Fossil")' />
 
242
243 <br/>
244
245 <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
246 <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
247
--- ajax/index.html
+++ ajax/index.html
@@ -233,14 +233,18 @@
233 <input type='button' value='branch/list' onclick='TheApp.cgi.sendCommand("/json/branch/list")' />
234 <input type='button' value='timeline/ci' onclick='TheApp.cgi.sendCommand("/json/timeline/ci?files=true")' />
235 <input type='button' value='timeline/wiki' onclick='TheApp.cgi.sendCommand("/json/timeline/wiki")' />
236 <input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
237 <input type='button' value='timeline/branch' onclick='TheApp.cgi.sendCommand("/json/timeline/branch")' />
238
239 <br/>
240
241 <input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
242 <input type='button' value='wiki/list verbose' onclick='TheApp.cgi.sendCommand("/json/wiki/list",{verbose:1})' />
243 <input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{name:"Fossil"})' />
244 <input type='button' value='wiki/get/Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get/Fossil")' />
245 <input type='button' value='wiki/diff' onclick='TheApp.cgi.sendCommand("/json/wiki/diff/e32ccdcda59e930c77c/e15992f475760cdf3a9")' />
246
247 <br/>
248
249 <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
250 <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
251
+1 -1
--- src/add.c
+++ src/add.c
@@ -241,11 +241,11 @@
241241
for(i=2; i<g.argc; i++){
242242
char *zName;
243243
int isDir;
244244
Blob fullName;
245245
246
- file_canonical_name(g.argv[i], &fullName);
246
+ file_canonical_name(g.argv[i], &fullName, 0);
247247
zName = blob_str(&fullName);
248248
isDir = file_wd_isdir(zName);
249249
if( isDir==1 ){
250250
vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
251251
}else if( isDir==0 ){
252252
--- src/add.c
+++ src/add.c
@@ -241,11 +241,11 @@
241 for(i=2; i<g.argc; i++){
242 char *zName;
243 int isDir;
244 Blob fullName;
245
246 file_canonical_name(g.argv[i], &fullName);
247 zName = blob_str(&fullName);
248 isDir = file_wd_isdir(zName);
249 if( isDir==1 ){
250 vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
251 }else if( isDir==0 ){
252
--- src/add.c
+++ src/add.c
@@ -241,11 +241,11 @@
241 for(i=2; i<g.argc; i++){
242 char *zName;
243 int isDir;
244 Blob fullName;
245
246 file_canonical_name(g.argv[i], &fullName, 0);
247 zName = blob_str(&fullName);
248 isDir = file_wd_isdir(zName);
249 if( isDir==1 ){
250 vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
251 }else if( isDir==0 ){
252
+1 -1
--- src/allrepo.c
+++ src/allrepo.c
@@ -168,11 +168,11 @@
168168
}else if( !file_is_canonical(zFilename) ){
169169
Blob cname;
170170
char *zRepo = mprintf("repo:%s", zFilename);
171171
db_unset(zRepo, 1);
172172
free(zRepo);
173
- file_canonical_name(zFilename, &cname);
173
+ file_canonical_name(zFilename, &cname, 0);
174174
zRepo = mprintf("repo:%s", blob_str(&cname));
175175
db_set(zRepo, "1", 1);
176176
free(zRepo);
177177
}
178178
}
179179
--- src/allrepo.c
+++ src/allrepo.c
@@ -168,11 +168,11 @@
168 }else if( !file_is_canonical(zFilename) ){
169 Blob cname;
170 char *zRepo = mprintf("repo:%s", zFilename);
171 db_unset(zRepo, 1);
172 free(zRepo);
173 file_canonical_name(zFilename, &cname);
174 zRepo = mprintf("repo:%s", blob_str(&cname));
175 db_set(zRepo, "1", 1);
176 free(zRepo);
177 }
178 }
179
--- src/allrepo.c
+++ src/allrepo.c
@@ -168,11 +168,11 @@
168 }else if( !file_is_canonical(zFilename) ){
169 Blob cname;
170 char *zRepo = mprintf("repo:%s", zFilename);
171 db_unset(zRepo, 1);
172 free(zRepo);
173 file_canonical_name(zFilename, &cname, 0);
174 zRepo = mprintf("repo:%s", blob_str(&cname));
175 db_set(zRepo, "1", 1);
176 free(zRepo);
177 }
178 }
179
+4 -1
--- src/blob.c
+++ src/blob.c
@@ -90,10 +90,13 @@
9090
int fossil_isupper(char c){ return c>='A' && c<='Z'; }
9191
int fossil_isdigit(char c){ return c>='0' && c<='9'; }
9292
int fossil_tolower(char c){
9393
return fossil_isupper(c) ? c - 'A' + 'a' : c;
9494
}
95
+int fossil_toupper(char c){
96
+ return fossil_islower(c) ? c - 'a' + 'A' : c;
97
+}
9598
int fossil_isalpha(char c){
9699
return (c>='a' && c<='z') || (c>='A' && c<='Z');
97100
}
98101
int fossil_isalnum(char c){
99102
return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
@@ -791,11 +794,11 @@
791794
zName = mprintf("%s", zFilename);
792795
}else{
793796
zName = zBuf;
794797
memcpy(zName, zFilename, nName+1);
795798
}
796
- nName = file_simplify_name(zName, nName);
799
+ nName = file_simplify_name(zName, nName, 0);
797800
for(i=1; i<nName; i++){
798801
if( zName[i]=='/' ){
799802
zName[i] = 0;
800803
#if defined(_WIN32)
801804
/*
802805
--- src/blob.c
+++ src/blob.c
@@ -90,10 +90,13 @@
90 int fossil_isupper(char c){ return c>='A' && c<='Z'; }
91 int fossil_isdigit(char c){ return c>='0' && c<='9'; }
92 int fossil_tolower(char c){
93 return fossil_isupper(c) ? c - 'A' + 'a' : c;
94 }
 
 
 
95 int fossil_isalpha(char c){
96 return (c>='a' && c<='z') || (c>='A' && c<='Z');
97 }
98 int fossil_isalnum(char c){
99 return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
@@ -791,11 +794,11 @@
791 zName = mprintf("%s", zFilename);
792 }else{
793 zName = zBuf;
794 memcpy(zName, zFilename, nName+1);
795 }
796 nName = file_simplify_name(zName, nName);
797 for(i=1; i<nName; i++){
798 if( zName[i]=='/' ){
799 zName[i] = 0;
800 #if defined(_WIN32)
801 /*
802
--- src/blob.c
+++ src/blob.c
@@ -90,10 +90,13 @@
90 int fossil_isupper(char c){ return c>='A' && c<='Z'; }
91 int fossil_isdigit(char c){ return c>='0' && c<='9'; }
92 int fossil_tolower(char c){
93 return fossil_isupper(c) ? c - 'A' + 'a' : c;
94 }
95 int fossil_toupper(char c){
96 return fossil_islower(c) ? c - 'a' + 'A' : c;
97 }
98 int fossil_isalpha(char c){
99 return (c>='a' && c<='z') || (c>='A' && c<='Z');
100 }
101 int fossil_isalnum(char c){
102 return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
@@ -791,11 +794,11 @@
794 zName = mprintf("%s", zFilename);
795 }else{
796 zName = zBuf;
797 memcpy(zName, zFilename, nName+1);
798 }
799 nName = file_simplify_name(zName, nName, 0);
800 for(i=1; i<nName; i++){
801 if( zName[i]=='/' ){
802 zName[i] = 0;
803 #if defined(_WIN32)
804 /*
805
+1 -1
--- src/browse.c
+++ src/browse.c
@@ -34,11 +34,11 @@
3434
**
3535
** pathelement('abc/pqr/xyz', 4) -> '/pqr'
3636
** pathelement('abc/pqr', 4) -> 'pqr'
3737
** pathelement('abc/pqr/xyz', 0) -> '/abc'
3838
*/
39
-static void pathelementFunc(
39
+void pathelementFunc(
4040
sqlite3_context *context,
4141
int argc,
4242
sqlite3_value **argv
4343
){
4444
const unsigned char *z;
4545
--- src/browse.c
+++ src/browse.c
@@ -34,11 +34,11 @@
34 **
35 ** pathelement('abc/pqr/xyz', 4) -> '/pqr'
36 ** pathelement('abc/pqr', 4) -> 'pqr'
37 ** pathelement('abc/pqr/xyz', 0) -> '/abc'
38 */
39 static void pathelementFunc(
40 sqlite3_context *context,
41 int argc,
42 sqlite3_value **argv
43 ){
44 const unsigned char *z;
45
--- src/browse.c
+++ src/browse.c
@@ -34,11 +34,11 @@
34 **
35 ** pathelement('abc/pqr/xyz', 4) -> '/pqr'
36 ** pathelement('abc/pqr', 4) -> 'pqr'
37 ** pathelement('abc/pqr/xyz', 0) -> '/abc'
38 */
39 void pathelementFunc(
40 sqlite3_context *context,
41 int argc,
42 sqlite3_value **argv
43 ){
44 const unsigned char *z;
45
+17 -2
--- src/cgi.c
+++ src/cgi.c
@@ -738,16 +738,19 @@
738738
*/
739739
void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
740740
cson_value * jv = NULL;
741741
int rc;
742742
CgiPostReadState state;
743
+ cson_parse_opt popt = cson_parse_opt_empty;
744
+ cson_parse_info pinfo = cson_parse_info_empty;
745
+ popt.maxDepth = 15;
743746
state.fh = zIn;
744747
state.len = contentLen;
745748
state.pos = 0;
746749
rc = cson_parse( &jv,
747750
contentLen ? cson_data_source_FILE_n : cson_data_source_FILE,
748
- contentLen ? (void *)&state : (void *)zIn, NULL, NULL );
751
+ contentLen ? (void *)&state : (void *)zIn, &popt, &pinfo );
749752
if(rc){
750753
goto invalidRequest;
751754
}else{
752755
json_gc_add( "POST.JSON", jv );
753756
g.json.post.v = jv;
@@ -757,11 +760,23 @@
757760
}
758761
}
759762
return;
760763
invalidRequest:
761764
cgi_set_content_type(json_guess_content_type());
762
- json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
765
+ if(0 != pinfo.errorCode){ /* fancy error message */
766
+ char * msg = mprintf("JSON parse error at line %u, column %u, "
767
+ "byte offset %u: %s",
768
+ pinfo.line, pinfo.col, pinfo.length,
769
+ cson_rc_string(pinfo.errorCode));
770
+ json_err( FSL_JSON_E_INVALID_REQUEST, msg, 1 );
771
+ free(msg);
772
+ }else if(jv && !g.json.post.o){
773
+ json_err( FSL_JSON_E_INVALID_REQUEST,
774
+ "Request envelope must be a JSON Object (not array).", 1 );
775
+ }else{ /* generic error message */
776
+ json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
777
+ }
763778
fossil_exit( g.isHTTP ? 0 : 1);
764779
}
765780
#endif /* FOSSIL_ENABLE_JSON */
766781
767782
768783
--- src/cgi.c
+++ src/cgi.c
@@ -738,16 +738,19 @@
738 */
739 void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
740 cson_value * jv = NULL;
741 int rc;
742 CgiPostReadState state;
 
 
 
743 state.fh = zIn;
744 state.len = contentLen;
745 state.pos = 0;
746 rc = cson_parse( &jv,
747 contentLen ? cson_data_source_FILE_n : cson_data_source_FILE,
748 contentLen ? (void *)&state : (void *)zIn, NULL, NULL );
749 if(rc){
750 goto invalidRequest;
751 }else{
752 json_gc_add( "POST.JSON", jv );
753 g.json.post.v = jv;
@@ -757,11 +760,23 @@
757 }
758 }
759 return;
760 invalidRequest:
761 cgi_set_content_type(json_guess_content_type());
762 json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
 
 
 
 
 
 
 
 
 
 
 
 
763 fossil_exit( g.isHTTP ? 0 : 1);
764 }
765 #endif /* FOSSIL_ENABLE_JSON */
766
767
768
--- src/cgi.c
+++ src/cgi.c
@@ -738,16 +738,19 @@
738 */
739 void cgi_parse_POST_JSON( FILE * zIn, unsigned int contentLen ){
740 cson_value * jv = NULL;
741 int rc;
742 CgiPostReadState state;
743 cson_parse_opt popt = cson_parse_opt_empty;
744 cson_parse_info pinfo = cson_parse_info_empty;
745 popt.maxDepth = 15;
746 state.fh = zIn;
747 state.len = contentLen;
748 state.pos = 0;
749 rc = cson_parse( &jv,
750 contentLen ? cson_data_source_FILE_n : cson_data_source_FILE,
751 contentLen ? (void *)&state : (void *)zIn, &popt, &pinfo );
752 if(rc){
753 goto invalidRequest;
754 }else{
755 json_gc_add( "POST.JSON", jv );
756 g.json.post.v = jv;
@@ -757,11 +760,23 @@
760 }
761 }
762 return;
763 invalidRequest:
764 cgi_set_content_type(json_guess_content_type());
765 if(0 != pinfo.errorCode){ /* fancy error message */
766 char * msg = mprintf("JSON parse error at line %u, column %u, "
767 "byte offset %u: %s",
768 pinfo.line, pinfo.col, pinfo.length,
769 cson_rc_string(pinfo.errorCode));
770 json_err( FSL_JSON_E_INVALID_REQUEST, msg, 1 );
771 free(msg);
772 }else if(jv && !g.json.post.o){
773 json_err( FSL_JSON_E_INVALID_REQUEST,
774 "Request envelope must be a JSON Object (not array).", 1 );
775 }else{ /* generic error message */
776 json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 );
777 }
778 fossil_exit( g.isHTTP ? 0 : 1);
779 }
780 #endif /* FOSSIL_ENABLE_JSON */
781
782
783
+71 -24
--- src/checkin.c
+++ src/checkin.c
@@ -55,11 +55,11 @@
5555
int isChnged = db_column_int(&q,2);
5656
int isNew = db_column_int(&q,3)==0;
5757
int isRenamed = db_column_int(&q,4);
5858
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
5959
if( cwdRelative ){
60
- file_relative_name(zFullName, &rewrittenPathname);
60
+ file_relative_name(zFullName, &rewrittenPathname, 0);
6161
zDisplayName = blob_str(&rewrittenPathname);
6262
if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
6363
zDisplayName += 2; /* no unnecessary ./ prefix */
6464
}
6565
}
@@ -313,11 +313,11 @@
313313
blob_zero(&rewrittenPathname);
314314
while( db_step(&q)==SQLITE_ROW ){
315315
zDisplayName = zPathname = db_column_text(&q, 0);
316316
if( cwdRelative ) {
317317
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
318
- file_relative_name(zFullName, &rewrittenPathname);
318
+ file_relative_name(zFullName, &rewrittenPathname, 0);
319319
free(zFullName);
320320
zDisplayName = blob_str(&rewrittenPathname);
321321
if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
322322
zDisplayName += 2; /* no unnecessary ./ prefix */
323323
}
@@ -632,12 +632,13 @@
632632
int verifyDate, /* Verify that child is younger */
633633
Blob *pCksum, /* Repository checksum. May be 0 */
634634
const char *zDateOvrd, /* Date override. If 0 then use 'now' */
635635
const char *zUserOvrd, /* User override. If 0 then use g.zLogin */
636636
const char *zBranch, /* Branch name. May be 0 */
637
- const char *zBgColor, /* Background color. May be 0 */
638
- const char *zTag, /* Tag to apply to this check-in */
637
+ const char *zColor, /* One-time gackground color. May be 0 */
638
+ const char *zBrClr, /* Persistent branch color. May be 0 */
639
+ const char **azTag, /* Tags to apply to this check-in */
639640
int *pnFBcard /* Number of generated B- and F-cards */
640641
){
641642
char *zDate; /* Date of the check-in */
642643
char *zParentUuid; /* UUID of parent check-in */
643644
Blob filename; /* A single filename */
@@ -645,10 +646,11 @@
645646
Stmt q; /* Query of files changed */
646647
Stmt q2; /* Query of merge parents */
647648
Blob mcksum; /* Manifest checksum */
648649
ManifestFile *pFile; /* File from the baseline */
649650
int nFBcard = 0; /* Number of B-cards and F-cards */
651
+ int i; /* Loop counter */
650652
651653
assert( pBaseline==0 || pBaseline->zBaseline==0 );
652654
assert( pBaseline==0 || zBaselineUuid!=0 );
653655
blob_zero(pOut);
654656
zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
@@ -756,23 +758,31 @@
756758
757759
blob_appendf(pOut, "\n");
758760
if( pCksum ) blob_appendf(pOut, "R %b\n", pCksum);
759761
if( zBranch && zBranch[0] ){
760762
/* Set tags for the new branch */
761
- if( zBgColor && zBgColor[0] ){
762
- blob_appendf(pOut, "T *bgcolor * %F\n", zBgColor);
763
+ if( zBrClr && zBrClr[0] ){
764
+ zColor = 0;
765
+ blob_appendf(pOut, "T *bgcolor * %F\n", zBrClr);
763766
}
764767
blob_appendf(pOut, "T *branch * %F\n", zBranch);
765768
blob_appendf(pOut, "T *sym-%F *\n", zBranch);
766769
}
770
+ if( zColor && zColor[0] ){
771
+ /* One-time background color */
772
+ blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
773
+ }
767774
if( g.markPrivate ){
768775
/* If this manifest is private, mark it as such */
769776
blob_appendf(pOut, "T +private *\n");
770777
}
771
- if( zTag && zTag[0] ){
772
- /* Add a symbolic tag to this check-in */
773
- blob_appendf(pOut, "T +sym-%F *\n", zTag);
778
+ if( azTag ){
779
+ for(i=0; azTag[i]; i++){
780
+ /* Add a symbolic tag to this check-in. The tag names have already
781
+ ** been sorted and converted using the %F format */
782
+ blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
783
+ }
774784
}
775785
if( zBranch && zBranch[0] ){
776786
/* For a new branch, cancel all prior propagating tags */
777787
Stmt q;
778788
db_prepare(&q,
@@ -781,12 +791,12 @@
781791
" AND tagtype==2 AND tagname GLOB 'sym-*'"
782792
" AND tagname!='sym-'||%Q"
783793
" ORDER BY tagname",
784794
vid, zBranch);
785795
while( db_step(&q)==SQLITE_ROW ){
786
- const char *zTag = db_column_text(&q, 0);
787
- blob_appendf(pOut, "T -%F *\n", zTag);
796
+ const char *zBrTag = db_column_text(&q, 0);
797
+ blob_appendf(pOut, "T -%F *\n", zBrTag);
788798
}
789799
db_finalize(&q);
790800
}
791801
blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin);
792802
md5sum_blob(pOut, &mcksum);
@@ -826,11 +836,11 @@
826836
if( lastNl>1000 ) return; /* Binary if any line longer than 1000 */
827837
}
828838
}
829839
if( nCrNl ){
830840
char c;
831
- file_relative_name(zFilename, &fname);
841
+ file_relative_name(zFilename, &fname, 0);
832842
blob_zero(&ans);
833843
zMsg = mprintf(
834844
"%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
835845
blob_str(&fname));
836846
prompt_user(zMsg, &ans);
@@ -844,10 +854,19 @@
844854
}
845855
blob_reset(&ans);
846856
blob_reset(&fname);
847857
}
848858
}
859
+
860
+/*
861
+** qsort() comparison routine for an array of pointers to strings.
862
+*/
863
+static int tagCmp(const void *a, const void *b){
864
+ char **pA = (char**)a;
865
+ char **pB = (char**)b;
866
+ return fossil_strcmp(pA[0], pB[0]);
867
+}
849868
850869
/*
851870
** COMMAND: ci*
852871
** COMMAND: commit
853872
**
@@ -862,14 +881,23 @@
862881
** no editor is set.
863882
**
864883
** All files that have changed will be committed unless some subset of
865884
** files is specified on the command line.
866885
**
867
-** The --branch option followed by a branch name causes the new check-in
868
-** to be placed in the named branch. The --bgcolor option can be followed
869
-** by a color name (ex: '#ffc0c0') to specify the background color of
870
-** entries in the new branch when shown in the web timeline interface.
886
+** The --branch option followed by a branch name causes the new
887
+** check-in to be placed in a newly-created branch with the name
888
+** passed to the --branch option.
889
+**
890
+** Use the --branchcolor option followed by a color name (ex:
891
+** '#ffc0c0') to specify the background color of entries in the new
892
+** branch when shown in the web timeline interface. The use of
893
+** the --branchcolor option is not recommend. Instead, let Fossil
894
+** choose the branch color automatically.
895
+**
896
+** The --bgcolor option works like --branchcolor but only sets the
897
+** background color for a single check-in. Subsequent check-ins revert
898
+** to the default color.
871899
**
872900
** A check-in is not permitted to fork unless the --force or -f
873901
** option appears. A check-in is not allowed against a closed leaf.
874902
**
875903
** The --private option creates a private check-in that is never synced.
@@ -877,12 +905,13 @@
877905
**
878906
** the --tag option applies the symbolic tag name to the check-in.
879907
**
880908
** Options:
881909
** --baseline use a baseline manifest in the commit process
882
-** --bgcolor COLOR apply given COLOR to the branch
910
+** --bgcolor COLOR apply COLOR to this one check-in only
883911
** --branch NEW-BRANCH-NAME check in to this new branch
912
+** --branchcolor COLOR apply given COLOR to the branch
884913
** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment
885914
** --delta use a delta manifest in the commit process
886915
** --force|-f allow forking with this commit
887916
** --message-file|-M FILE read the commit comment from given file
888917
** --nosign do not attempt to sign this commit with gpg
@@ -908,15 +937,18 @@
908937
char *zManifestFile; /* Name of the manifest file */
909938
int useCksum; /* True if checksums should be computed and verified */
910939
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
911940
int testRun; /* True for a test run. Debugging only */
912941
const char *zBranch; /* Create a new branch with this name */
913
- const char *zBgColor; /* Set background color when branching */
942
+ const char *zBrClr; /* Set background color when branching */
943
+ const char *zColor; /* One-time check-in color */
914944
const char *zDateOvrd; /* Override date string */
915945
const char *zUserOvrd; /* Override user name */
916946
const char *zComFile; /* Read commit message from this file */
917
- const char *zTag; /* Symbolic tag to apply to this check-in */
947
+ int nTag = 0; /* Number of --tag arguments */
948
+ const char *zTag; /* A single --tag argument */
949
+ const char **azTag = 0;/* Array of all --tag arguments */
918950
Blob manifest; /* Manifest in baseline form */
919951
Blob muuid; /* Manifest uuid */
920952
Blob cksum1, cksum2; /* Before and after commit checksums */
921953
Blob cksum1b; /* Checksum recorded in the manifest */
922954
int szD; /* Size of the delta manifest */
@@ -931,26 +963,39 @@
931963
}
932964
testRun = find_option("test",0,0)!=0;
933965
zComment = find_option("comment","m",1);
934966
forceFlag = find_option("force", "f", 0)!=0;
935967
zBranch = find_option("branch","b",1);
936
- zBgColor = find_option("bgcolor",0,1);
937
- zTag = find_option("tag",0,1);
968
+ zColor = find_option("bgcolor",0,1);
969
+ zBrClr = find_option("branchcolor",0,1);
970
+ while( (zTag = find_option("tag",0,1))!=0 ){
971
+ if( zTag[0]==0 ) continue;
972
+ azTag = fossil_realloc(azTag, sizeof(char*)*(nTag+2));
973
+ azTag[nTag++] = zTag;
974
+ azTag[nTag] = 0;
975
+ }
938976
zComFile = find_option("message-file", "M", 1);
939977
if( find_option("private",0,0) ){
940978
g.markPrivate = 1;
941979
if( zBranch==0 ) zBranch = "private";
942
- if( zBgColor==0 ) zBgColor = "#fec084"; /* Orange */
980
+ if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
943981
}
944982
zDateOvrd = find_option("date-override",0,1);
945983
zUserOvrd = find_option("user-override",0,1);
946984
db_must_be_within_tree();
947985
noSign = db_get_boolean("omitsign", 0)|noSign;
948986
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
949987
useCksum = db_get_boolean("repo-cksum", 1);
950988
outputManifest = db_get_boolean("manifest", 0);
951989
verify_all_options();
990
+
991
+ /* Escape special characters in tags and put all tags in sorted order */
992
+ if( nTag ){
993
+ int i;
994
+ for(i=0; i<nTag; i++) azTag[i] = mprintf("%F", azTag[i]);
995
+ qsort((void*)azTag, nTag, sizeof(azTag[0]), tagCmp);
996
+ }
952997
953998
/* So that older versions of Fossil (that do not understand delta-
954999
** manifest) can continue to use this repository, do not create a new
9551000
** delta-manifest unless this repository already contains one or more
9561001
** delta-manifets, or unless the delta-manifest is explicitly requested
@@ -1126,11 +1171,12 @@
11261171
if( forceDelta ){
11271172
blob_zero(&manifest);
11281173
}else{
11291174
create_manifest(&manifest, 0, 0, &comment, vid,
11301175
!forceFlag, useCksum ? &cksum1 : 0,
1131
- zDateOvrd, zUserOvrd, zBranch, zBgColor, zTag, &szB);
1176
+ zDateOvrd, zUserOvrd, zBranch, zColor, zBrClr,
1177
+ azTag, &szB);
11321178
}
11331179
11341180
/* See if a delta-manifest would be more appropriate */
11351181
if( !forceBaseline ){
11361182
const char *zBaselineUuid;
@@ -1146,11 +1192,12 @@
11461192
}
11471193
if( pBaseline ){
11481194
Blob delta;
11491195
create_manifest(&delta, zBaselineUuid, pBaseline, &comment, vid,
11501196
!forceFlag, useCksum ? &cksum1 : 0,
1151
- zDateOvrd, zUserOvrd, zBranch, zBgColor, zTag, &szD);
1197
+ zDateOvrd, zUserOvrd, zBranch, zColor, zBrClr,
1198
+ azTag, &szD);
11521199
/*
11531200
** At this point, two manifests have been constructed, either of
11541201
** which would work for this checkin. The first manifest (held
11551202
** in the "manifest" variable) is a baseline manifest and the second
11561203
** (held in variable named "delta") is a delta manifest. The
11571204
--- src/checkin.c
+++ src/checkin.c
@@ -55,11 +55,11 @@
55 int isChnged = db_column_int(&q,2);
56 int isNew = db_column_int(&q,3)==0;
57 int isRenamed = db_column_int(&q,4);
58 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
59 if( cwdRelative ){
60 file_relative_name(zFullName, &rewrittenPathname);
61 zDisplayName = blob_str(&rewrittenPathname);
62 if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
63 zDisplayName += 2; /* no unnecessary ./ prefix */
64 }
65 }
@@ -313,11 +313,11 @@
313 blob_zero(&rewrittenPathname);
314 while( db_step(&q)==SQLITE_ROW ){
315 zDisplayName = zPathname = db_column_text(&q, 0);
316 if( cwdRelative ) {
317 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
318 file_relative_name(zFullName, &rewrittenPathname);
319 free(zFullName);
320 zDisplayName = blob_str(&rewrittenPathname);
321 if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
322 zDisplayName += 2; /* no unnecessary ./ prefix */
323 }
@@ -632,12 +632,13 @@
632 int verifyDate, /* Verify that child is younger */
633 Blob *pCksum, /* Repository checksum. May be 0 */
634 const char *zDateOvrd, /* Date override. If 0 then use 'now' */
635 const char *zUserOvrd, /* User override. If 0 then use g.zLogin */
636 const char *zBranch, /* Branch name. May be 0 */
637 const char *zBgColor, /* Background color. May be 0 */
638 const char *zTag, /* Tag to apply to this check-in */
 
639 int *pnFBcard /* Number of generated B- and F-cards */
640 ){
641 char *zDate; /* Date of the check-in */
642 char *zParentUuid; /* UUID of parent check-in */
643 Blob filename; /* A single filename */
@@ -645,10 +646,11 @@
645 Stmt q; /* Query of files changed */
646 Stmt q2; /* Query of merge parents */
647 Blob mcksum; /* Manifest checksum */
648 ManifestFile *pFile; /* File from the baseline */
649 int nFBcard = 0; /* Number of B-cards and F-cards */
 
650
651 assert( pBaseline==0 || pBaseline->zBaseline==0 );
652 assert( pBaseline==0 || zBaselineUuid!=0 );
653 blob_zero(pOut);
654 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
@@ -756,23 +758,31 @@
756
757 blob_appendf(pOut, "\n");
758 if( pCksum ) blob_appendf(pOut, "R %b\n", pCksum);
759 if( zBranch && zBranch[0] ){
760 /* Set tags for the new branch */
761 if( zBgColor && zBgColor[0] ){
762 blob_appendf(pOut, "T *bgcolor * %F\n", zBgColor);
 
763 }
764 blob_appendf(pOut, "T *branch * %F\n", zBranch);
765 blob_appendf(pOut, "T *sym-%F *\n", zBranch);
766 }
 
 
 
 
767 if( g.markPrivate ){
768 /* If this manifest is private, mark it as such */
769 blob_appendf(pOut, "T +private *\n");
770 }
771 if( zTag && zTag[0] ){
772 /* Add a symbolic tag to this check-in */
773 blob_appendf(pOut, "T +sym-%F *\n", zTag);
 
 
 
774 }
775 if( zBranch && zBranch[0] ){
776 /* For a new branch, cancel all prior propagating tags */
777 Stmt q;
778 db_prepare(&q,
@@ -781,12 +791,12 @@
781 " AND tagtype==2 AND tagname GLOB 'sym-*'"
782 " AND tagname!='sym-'||%Q"
783 " ORDER BY tagname",
784 vid, zBranch);
785 while( db_step(&q)==SQLITE_ROW ){
786 const char *zTag = db_column_text(&q, 0);
787 blob_appendf(pOut, "T -%F *\n", zTag);
788 }
789 db_finalize(&q);
790 }
791 blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin);
792 md5sum_blob(pOut, &mcksum);
@@ -826,11 +836,11 @@
826 if( lastNl>1000 ) return; /* Binary if any line longer than 1000 */
827 }
828 }
829 if( nCrNl ){
830 char c;
831 file_relative_name(zFilename, &fname);
832 blob_zero(&ans);
833 zMsg = mprintf(
834 "%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
835 blob_str(&fname));
836 prompt_user(zMsg, &ans);
@@ -844,10 +854,19 @@
844 }
845 blob_reset(&ans);
846 blob_reset(&fname);
847 }
848 }
 
 
 
 
 
 
 
 
 
849
850 /*
851 ** COMMAND: ci*
852 ** COMMAND: commit
853 **
@@ -862,14 +881,23 @@
862 ** no editor is set.
863 **
864 ** All files that have changed will be committed unless some subset of
865 ** files is specified on the command line.
866 **
867 ** The --branch option followed by a branch name causes the new check-in
868 ** to be placed in the named branch. The --bgcolor option can be followed
869 ** by a color name (ex: '#ffc0c0') to specify the background color of
870 ** entries in the new branch when shown in the web timeline interface.
 
 
 
 
 
 
 
 
 
871 **
872 ** A check-in is not permitted to fork unless the --force or -f
873 ** option appears. A check-in is not allowed against a closed leaf.
874 **
875 ** The --private option creates a private check-in that is never synced.
@@ -877,12 +905,13 @@
877 **
878 ** the --tag option applies the symbolic tag name to the check-in.
879 **
880 ** Options:
881 ** --baseline use a baseline manifest in the commit process
882 ** --bgcolor COLOR apply given COLOR to the branch
883 ** --branch NEW-BRANCH-NAME check in to this new branch
 
884 ** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment
885 ** --delta use a delta manifest in the commit process
886 ** --force|-f allow forking with this commit
887 ** --message-file|-M FILE read the commit comment from given file
888 ** --nosign do not attempt to sign this commit with gpg
@@ -908,15 +937,18 @@
908 char *zManifestFile; /* Name of the manifest file */
909 int useCksum; /* True if checksums should be computed and verified */
910 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
911 int testRun; /* True for a test run. Debugging only */
912 const char *zBranch; /* Create a new branch with this name */
913 const char *zBgColor; /* Set background color when branching */
 
914 const char *zDateOvrd; /* Override date string */
915 const char *zUserOvrd; /* Override user name */
916 const char *zComFile; /* Read commit message from this file */
917 const char *zTag; /* Symbolic tag to apply to this check-in */
 
 
918 Blob manifest; /* Manifest in baseline form */
919 Blob muuid; /* Manifest uuid */
920 Blob cksum1, cksum2; /* Before and after commit checksums */
921 Blob cksum1b; /* Checksum recorded in the manifest */
922 int szD; /* Size of the delta manifest */
@@ -931,26 +963,39 @@
931 }
932 testRun = find_option("test",0,0)!=0;
933 zComment = find_option("comment","m",1);
934 forceFlag = find_option("force", "f", 0)!=0;
935 zBranch = find_option("branch","b",1);
936 zBgColor = find_option("bgcolor",0,1);
937 zTag = find_option("tag",0,1);
 
 
 
 
 
 
938 zComFile = find_option("message-file", "M", 1);
939 if( find_option("private",0,0) ){
940 g.markPrivate = 1;
941 if( zBranch==0 ) zBranch = "private";
942 if( zBgColor==0 ) zBgColor = "#fec084"; /* Orange */
943 }
944 zDateOvrd = find_option("date-override",0,1);
945 zUserOvrd = find_option("user-override",0,1);
946 db_must_be_within_tree();
947 noSign = db_get_boolean("omitsign", 0)|noSign;
948 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
949 useCksum = db_get_boolean("repo-cksum", 1);
950 outputManifest = db_get_boolean("manifest", 0);
951 verify_all_options();
 
 
 
 
 
 
 
952
953 /* So that older versions of Fossil (that do not understand delta-
954 ** manifest) can continue to use this repository, do not create a new
955 ** delta-manifest unless this repository already contains one or more
956 ** delta-manifets, or unless the delta-manifest is explicitly requested
@@ -1126,11 +1171,12 @@
1126 if( forceDelta ){
1127 blob_zero(&manifest);
1128 }else{
1129 create_manifest(&manifest, 0, 0, &comment, vid,
1130 !forceFlag, useCksum ? &cksum1 : 0,
1131 zDateOvrd, zUserOvrd, zBranch, zBgColor, zTag, &szB);
 
1132 }
1133
1134 /* See if a delta-manifest would be more appropriate */
1135 if( !forceBaseline ){
1136 const char *zBaselineUuid;
@@ -1146,11 +1192,12 @@
1146 }
1147 if( pBaseline ){
1148 Blob delta;
1149 create_manifest(&delta, zBaselineUuid, pBaseline, &comment, vid,
1150 !forceFlag, useCksum ? &cksum1 : 0,
1151 zDateOvrd, zUserOvrd, zBranch, zBgColor, zTag, &szD);
 
1152 /*
1153 ** At this point, two manifests have been constructed, either of
1154 ** which would work for this checkin. The first manifest (held
1155 ** in the "manifest" variable) is a baseline manifest and the second
1156 ** (held in variable named "delta") is a delta manifest. The
1157
--- src/checkin.c
+++ src/checkin.c
@@ -55,11 +55,11 @@
55 int isChnged = db_column_int(&q,2);
56 int isNew = db_column_int(&q,3)==0;
57 int isRenamed = db_column_int(&q,4);
58 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
59 if( cwdRelative ){
60 file_relative_name(zFullName, &rewrittenPathname, 0);
61 zDisplayName = blob_str(&rewrittenPathname);
62 if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
63 zDisplayName += 2; /* no unnecessary ./ prefix */
64 }
65 }
@@ -313,11 +313,11 @@
313 blob_zero(&rewrittenPathname);
314 while( db_step(&q)==SQLITE_ROW ){
315 zDisplayName = zPathname = db_column_text(&q, 0);
316 if( cwdRelative ) {
317 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
318 file_relative_name(zFullName, &rewrittenPathname, 0);
319 free(zFullName);
320 zDisplayName = blob_str(&rewrittenPathname);
321 if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
322 zDisplayName += 2; /* no unnecessary ./ prefix */
323 }
@@ -632,12 +632,13 @@
632 int verifyDate, /* Verify that child is younger */
633 Blob *pCksum, /* Repository checksum. May be 0 */
634 const char *zDateOvrd, /* Date override. If 0 then use 'now' */
635 const char *zUserOvrd, /* User override. If 0 then use g.zLogin */
636 const char *zBranch, /* Branch name. May be 0 */
637 const char *zColor, /* One-time gackground color. May be 0 */
638 const char *zBrClr, /* Persistent branch color. May be 0 */
639 const char **azTag, /* Tags to apply to this check-in */
640 int *pnFBcard /* Number of generated B- and F-cards */
641 ){
642 char *zDate; /* Date of the check-in */
643 char *zParentUuid; /* UUID of parent check-in */
644 Blob filename; /* A single filename */
@@ -645,10 +646,11 @@
646 Stmt q; /* Query of files changed */
647 Stmt q2; /* Query of merge parents */
648 Blob mcksum; /* Manifest checksum */
649 ManifestFile *pFile; /* File from the baseline */
650 int nFBcard = 0; /* Number of B-cards and F-cards */
651 int i; /* Loop counter */
652
653 assert( pBaseline==0 || pBaseline->zBaseline==0 );
654 assert( pBaseline==0 || zBaselineUuid!=0 );
655 blob_zero(pOut);
656 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
@@ -756,23 +758,31 @@
758
759 blob_appendf(pOut, "\n");
760 if( pCksum ) blob_appendf(pOut, "R %b\n", pCksum);
761 if( zBranch && zBranch[0] ){
762 /* Set tags for the new branch */
763 if( zBrClr && zBrClr[0] ){
764 zColor = 0;
765 blob_appendf(pOut, "T *bgcolor * %F\n", zBrClr);
766 }
767 blob_appendf(pOut, "T *branch * %F\n", zBranch);
768 blob_appendf(pOut, "T *sym-%F *\n", zBranch);
769 }
770 if( zColor && zColor[0] ){
771 /* One-time background color */
772 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
773 }
774 if( g.markPrivate ){
775 /* If this manifest is private, mark it as such */
776 blob_appendf(pOut, "T +private *\n");
777 }
778 if( azTag ){
779 for(i=0; azTag[i]; i++){
780 /* Add a symbolic tag to this check-in. The tag names have already
781 ** been sorted and converted using the %F format */
782 blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
783 }
784 }
785 if( zBranch && zBranch[0] ){
786 /* For a new branch, cancel all prior propagating tags */
787 Stmt q;
788 db_prepare(&q,
@@ -781,12 +791,12 @@
791 " AND tagtype==2 AND tagname GLOB 'sym-*'"
792 " AND tagname!='sym-'||%Q"
793 " ORDER BY tagname",
794 vid, zBranch);
795 while( db_step(&q)==SQLITE_ROW ){
796 const char *zBrTag = db_column_text(&q, 0);
797 blob_appendf(pOut, "T -%F *\n", zBrTag);
798 }
799 db_finalize(&q);
800 }
801 blob_appendf(pOut, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin);
802 md5sum_blob(pOut, &mcksum);
@@ -826,11 +836,11 @@
836 if( lastNl>1000 ) return; /* Binary if any line longer than 1000 */
837 }
838 }
839 if( nCrNl ){
840 char c;
841 file_relative_name(zFilename, &fname, 0);
842 blob_zero(&ans);
843 zMsg = mprintf(
844 "%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
845 blob_str(&fname));
846 prompt_user(zMsg, &ans);
@@ -844,10 +854,19 @@
854 }
855 blob_reset(&ans);
856 blob_reset(&fname);
857 }
858 }
859
860 /*
861 ** qsort() comparison routine for an array of pointers to strings.
862 */
863 static int tagCmp(const void *a, const void *b){
864 char **pA = (char**)a;
865 char **pB = (char**)b;
866 return fossil_strcmp(pA[0], pB[0]);
867 }
868
869 /*
870 ** COMMAND: ci*
871 ** COMMAND: commit
872 **
@@ -862,14 +881,23 @@
881 ** no editor is set.
882 **
883 ** All files that have changed will be committed unless some subset of
884 ** files is specified on the command line.
885 **
886 ** The --branch option followed by a branch name causes the new
887 ** check-in to be placed in a newly-created branch with the name
888 ** passed to the --branch option.
889 **
890 ** Use the --branchcolor option followed by a color name (ex:
891 ** '#ffc0c0') to specify the background color of entries in the new
892 ** branch when shown in the web timeline interface. The use of
893 ** the --branchcolor option is not recommend. Instead, let Fossil
894 ** choose the branch color automatically.
895 **
896 ** The --bgcolor option works like --branchcolor but only sets the
897 ** background color for a single check-in. Subsequent check-ins revert
898 ** to the default color.
899 **
900 ** A check-in is not permitted to fork unless the --force or -f
901 ** option appears. A check-in is not allowed against a closed leaf.
902 **
903 ** The --private option creates a private check-in that is never synced.
@@ -877,12 +905,13 @@
905 **
906 ** the --tag option applies the symbolic tag name to the check-in.
907 **
908 ** Options:
909 ** --baseline use a baseline manifest in the commit process
910 ** --bgcolor COLOR apply COLOR to this one check-in only
911 ** --branch NEW-BRANCH-NAME check in to this new branch
912 ** --branchcolor COLOR apply given COLOR to the branch
913 ** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment
914 ** --delta use a delta manifest in the commit process
915 ** --force|-f allow forking with this commit
916 ** --message-file|-M FILE read the commit comment from given file
917 ** --nosign do not attempt to sign this commit with gpg
@@ -908,15 +937,18 @@
937 char *zManifestFile; /* Name of the manifest file */
938 int useCksum; /* True if checksums should be computed and verified */
939 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
940 int testRun; /* True for a test run. Debugging only */
941 const char *zBranch; /* Create a new branch with this name */
942 const char *zBrClr; /* Set background color when branching */
943 const char *zColor; /* One-time check-in color */
944 const char *zDateOvrd; /* Override date string */
945 const char *zUserOvrd; /* Override user name */
946 const char *zComFile; /* Read commit message from this file */
947 int nTag = 0; /* Number of --tag arguments */
948 const char *zTag; /* A single --tag argument */
949 const char **azTag = 0;/* Array of all --tag arguments */
950 Blob manifest; /* Manifest in baseline form */
951 Blob muuid; /* Manifest uuid */
952 Blob cksum1, cksum2; /* Before and after commit checksums */
953 Blob cksum1b; /* Checksum recorded in the manifest */
954 int szD; /* Size of the delta manifest */
@@ -931,26 +963,39 @@
963 }
964 testRun = find_option("test",0,0)!=0;
965 zComment = find_option("comment","m",1);
966 forceFlag = find_option("force", "f", 0)!=0;
967 zBranch = find_option("branch","b",1);
968 zColor = find_option("bgcolor",0,1);
969 zBrClr = find_option("branchcolor",0,1);
970 while( (zTag = find_option("tag",0,1))!=0 ){
971 if( zTag[0]==0 ) continue;
972 azTag = fossil_realloc(azTag, sizeof(char*)*(nTag+2));
973 azTag[nTag++] = zTag;
974 azTag[nTag] = 0;
975 }
976 zComFile = find_option("message-file", "M", 1);
977 if( find_option("private",0,0) ){
978 g.markPrivate = 1;
979 if( zBranch==0 ) zBranch = "private";
980 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
981 }
982 zDateOvrd = find_option("date-override",0,1);
983 zUserOvrd = find_option("user-override",0,1);
984 db_must_be_within_tree();
985 noSign = db_get_boolean("omitsign", 0)|noSign;
986 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
987 useCksum = db_get_boolean("repo-cksum", 1);
988 outputManifest = db_get_boolean("manifest", 0);
989 verify_all_options();
990
991 /* Escape special characters in tags and put all tags in sorted order */
992 if( nTag ){
993 int i;
994 for(i=0; i<nTag; i++) azTag[i] = mprintf("%F", azTag[i]);
995 qsort((void*)azTag, nTag, sizeof(azTag[0]), tagCmp);
996 }
997
998 /* So that older versions of Fossil (that do not understand delta-
999 ** manifest) can continue to use this repository, do not create a new
1000 ** delta-manifest unless this repository already contains one or more
1001 ** delta-manifets, or unless the delta-manifest is explicitly requested
@@ -1126,11 +1171,12 @@
1171 if( forceDelta ){
1172 blob_zero(&manifest);
1173 }else{
1174 create_manifest(&manifest, 0, 0, &comment, vid,
1175 !forceFlag, useCksum ? &cksum1 : 0,
1176 zDateOvrd, zUserOvrd, zBranch, zColor, zBrClr,
1177 azTag, &szB);
1178 }
1179
1180 /* See if a delta-manifest would be more appropriate */
1181 if( !forceBaseline ){
1182 const char *zBaselineUuid;
@@ -1146,11 +1192,12 @@
1192 }
1193 if( pBaseline ){
1194 Blob delta;
1195 create_manifest(&delta, zBaselineUuid, pBaseline, &comment, vid,
1196 !forceFlag, useCksum ? &cksum1 : 0,
1197 zDateOvrd, zUserOvrd, zBranch, zColor, zBrClr,
1198 azTag, &szD);
1199 /*
1200 ** At this point, two manifests have been constructed, either of
1201 ** which would work for this checkin. The first manifest (held
1202 ** in the "manifest" variable) is a baseline manifest and the second
1203 ** (held in variable named "delta") is a delta manifest. The
1204
+1 -1
--- src/clone.c
+++ src/clone.c
@@ -150,11 +150,11 @@
150150
db_set("last-sync-url", g.argv[2], 0);
151151
if( g.zSSLIdentity!=0 ){
152152
/* If the --ssl-identity option was specified, store it as a setting */
153153
Blob fn;
154154
blob_zero(&fn);
155
- file_canonical_name(g.zSSLIdentity, &fn);
155
+ file_canonical_name(g.zSSLIdentity, &fn, 0);
156156
db_set("ssl-identity", blob_str(&fn), 0);
157157
blob_reset(&fn);
158158
}
159159
db_multi_exec(
160160
"REPLACE INTO config(name,value,mtime)"
161161
--- src/clone.c
+++ src/clone.c
@@ -150,11 +150,11 @@
150 db_set("last-sync-url", g.argv[2], 0);
151 if( g.zSSLIdentity!=0 ){
152 /* If the --ssl-identity option was specified, store it as a setting */
153 Blob fn;
154 blob_zero(&fn);
155 file_canonical_name(g.zSSLIdentity, &fn);
156 db_set("ssl-identity", blob_str(&fn), 0);
157 blob_reset(&fn);
158 }
159 db_multi_exec(
160 "REPLACE INTO config(name,value,mtime)"
161
--- src/clone.c
+++ src/clone.c
@@ -150,11 +150,11 @@
150 db_set("last-sync-url", g.argv[2], 0);
151 if( g.zSSLIdentity!=0 ){
152 /* If the --ssl-identity option was specified, store it as a setting */
153 Blob fn;
154 blob_zero(&fn);
155 file_canonical_name(g.zSSLIdentity, &fn, 0);
156 db_set("ssl-identity", blob_str(&fn), 0);
157 blob_reset(&fn);
158 }
159 db_multi_exec(
160 "REPLACE INTO config(name,value,mtime)"
161
+15 -6
--- src/configure.c
+++ src/configure.c
@@ -78,23 +78,27 @@
7878
{ "css", CONFIGSET_SKIN },
7979
{ "header", CONFIGSET_SKIN },
8080
{ "footer", CONFIGSET_SKIN },
8181
{ "logo-mimetype", CONFIGSET_SKIN },
8282
{ "logo-image", CONFIGSET_SKIN },
83
+ { "background-mimetype", CONFIGSET_SKIN },
84
+ { "background-image", CONFIGSET_SKIN },
85
+ { "index-page", CONFIGSET_SKIN },
86
+ { "timeline-block-markup", CONFIGSET_SKIN },
87
+ { "timeline-max-comment", CONFIGSET_SKIN },
88
+#ifdef FOSSIL_ENABLE_TCL
89
+ { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
90
+#endif
91
+
8392
{ "project-name", CONFIGSET_PROJ },
8493
{ "project-description", CONFIGSET_PROJ },
8594
{ "manifest", CONFIGSET_PROJ },
8695
{ "ignore-glob", CONFIGSET_PROJ },
8796
{ "crnl-glob", CONFIGSET_PROJ },
8897
{ "empty-dirs", CONFIGSET_PROJ },
8998
{ "allow-symlinks", CONFIGSET_PROJ },
90
- { "index-page", CONFIGSET_SKIN },
91
-#ifdef FOSSIL_ENABLE_TCL
92
- { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
93
-#endif
94
- { "timeline-block-markup", CONFIGSET_SKIN },
95
- { "timeline-max-comment", CONFIGSET_SKIN },
99
+
96100
{ "ticket-table", CONFIGSET_TKT },
97101
{ "ticket-common", CONFIGSET_TKT },
98102
{ "ticket-change", CONFIGSET_TKT },
99103
{ "ticket-newpage", CONFIGSET_TKT },
100104
{ "ticket-viewpage", CONFIGSET_TKT },
@@ -103,15 +107,20 @@
103107
{ "ticket-report-template", CONFIGSET_TKT },
104108
{ "ticket-key-template", CONFIGSET_TKT },
105109
{ "ticket-title-expr", CONFIGSET_TKT },
106110
{ "ticket-closed-expr", CONFIGSET_TKT },
107111
{ "@reportfmt", CONFIGSET_TKT },
112
+
108113
{ "@user", CONFIGSET_USER },
114
+
109115
{ "@concealed", CONFIGSET_ADDR },
116
+
110117
{ "@shun", CONFIGSET_SHUN },
118
+
111119
{ "xfer-common-script", CONFIGSET_XFER },
112120
{ "xfer-push-script", CONFIGSET_XFER },
121
+
113122
};
114123
static int iConfig = 0;
115124
116125
/*
117126
** Return name of first configuration property matching the given mask.
118127
--- src/configure.c
+++ src/configure.c
@@ -78,23 +78,27 @@
78 { "css", CONFIGSET_SKIN },
79 { "header", CONFIGSET_SKIN },
80 { "footer", CONFIGSET_SKIN },
81 { "logo-mimetype", CONFIGSET_SKIN },
82 { "logo-image", CONFIGSET_SKIN },
 
 
 
 
 
 
 
 
 
83 { "project-name", CONFIGSET_PROJ },
84 { "project-description", CONFIGSET_PROJ },
85 { "manifest", CONFIGSET_PROJ },
86 { "ignore-glob", CONFIGSET_PROJ },
87 { "crnl-glob", CONFIGSET_PROJ },
88 { "empty-dirs", CONFIGSET_PROJ },
89 { "allow-symlinks", CONFIGSET_PROJ },
90 { "index-page", CONFIGSET_SKIN },
91 #ifdef FOSSIL_ENABLE_TCL
92 { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
93 #endif
94 { "timeline-block-markup", CONFIGSET_SKIN },
95 { "timeline-max-comment", CONFIGSET_SKIN },
96 { "ticket-table", CONFIGSET_TKT },
97 { "ticket-common", CONFIGSET_TKT },
98 { "ticket-change", CONFIGSET_TKT },
99 { "ticket-newpage", CONFIGSET_TKT },
100 { "ticket-viewpage", CONFIGSET_TKT },
@@ -103,15 +107,20 @@
103 { "ticket-report-template", CONFIGSET_TKT },
104 { "ticket-key-template", CONFIGSET_TKT },
105 { "ticket-title-expr", CONFIGSET_TKT },
106 { "ticket-closed-expr", CONFIGSET_TKT },
107 { "@reportfmt", CONFIGSET_TKT },
 
108 { "@user", CONFIGSET_USER },
 
109 { "@concealed", CONFIGSET_ADDR },
 
110 { "@shun", CONFIGSET_SHUN },
 
111 { "xfer-common-script", CONFIGSET_XFER },
112 { "xfer-push-script", CONFIGSET_XFER },
 
113 };
114 static int iConfig = 0;
115
116 /*
117 ** Return name of first configuration property matching the given mask.
118
--- src/configure.c
+++ src/configure.c
@@ -78,23 +78,27 @@
78 { "css", CONFIGSET_SKIN },
79 { "header", CONFIGSET_SKIN },
80 { "footer", CONFIGSET_SKIN },
81 { "logo-mimetype", CONFIGSET_SKIN },
82 { "logo-image", CONFIGSET_SKIN },
83 { "background-mimetype", CONFIGSET_SKIN },
84 { "background-image", CONFIGSET_SKIN },
85 { "index-page", CONFIGSET_SKIN },
86 { "timeline-block-markup", CONFIGSET_SKIN },
87 { "timeline-max-comment", CONFIGSET_SKIN },
88 #ifdef FOSSIL_ENABLE_TCL
89 { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
90 #endif
91
92 { "project-name", CONFIGSET_PROJ },
93 { "project-description", CONFIGSET_PROJ },
94 { "manifest", CONFIGSET_PROJ },
95 { "ignore-glob", CONFIGSET_PROJ },
96 { "crnl-glob", CONFIGSET_PROJ },
97 { "empty-dirs", CONFIGSET_PROJ },
98 { "allow-symlinks", CONFIGSET_PROJ },
99
 
 
 
 
 
100 { "ticket-table", CONFIGSET_TKT },
101 { "ticket-common", CONFIGSET_TKT },
102 { "ticket-change", CONFIGSET_TKT },
103 { "ticket-newpage", CONFIGSET_TKT },
104 { "ticket-viewpage", CONFIGSET_TKT },
@@ -103,15 +107,20 @@
107 { "ticket-report-template", CONFIGSET_TKT },
108 { "ticket-key-template", CONFIGSET_TKT },
109 { "ticket-title-expr", CONFIGSET_TKT },
110 { "ticket-closed-expr", CONFIGSET_TKT },
111 { "@reportfmt", CONFIGSET_TKT },
112
113 { "@user", CONFIGSET_USER },
114
115 { "@concealed", CONFIGSET_ADDR },
116
117 { "@shun", CONFIGSET_SHUN },
118
119 { "xfer-common-script", CONFIGSET_XFER },
120 { "xfer-push-script", CONFIGSET_XFER },
121
122 };
123 static int iConfig = 0;
124
125 /*
126 ** Return name of first configuration property matching the given mask.
127
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1427,11 +1427,11 @@
14271427
/**
14281428
Type IDs corresponding to JavaScript/JSON types.
14291429
*/
14301430
enum cson_type_id {
14311431
/**
1432
- The special "null" value constant.
1432
+ The special "undefined" value constant.
14331433
14341434
Its value must be 0 for internal reasons.
14351435
*/
14361436
CSON_TYPE_UNDEF = 0,
14371437
/**
@@ -1597,10 +1597,18 @@
15971597
static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 };
15981598
static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 };
15991599
static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 };
16001600
static const cson_value cson_value_object_empty = { &cson_value_api_object, NULL, 0 };
16011601
1602
+/**
1603
+ Strings are allocated as an instances of this class with N+1
1604
+ trailing bytes, where N is the length of the string being
1605
+ allocated. To convert a cson_string to c-string we simply increment
1606
+ the cson_string pointer. To do the opposite we use (cstr -
1607
+ sizeof(cson_string)). Zero-length strings are a special case
1608
+ handled by a couple of the cson_string functions.
1609
+*/
16021610
struct cson_string
16031611
{
16041612
unsigned int length;
16051613
};
16061614
#define cson_string_empty_m {0/*length*/}
@@ -1608,11 +1616,17 @@
16081616
16091617
16101618
16111619
#define CSON_CAST(T,V) ((T*)((V)->value))
16121620
#define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value)))
1613
-#define CSON_INT(V) ((cson_int_t*)(V)->value)
1621
+
1622
+#if CSON_VOID_PTR_IS_BIG
1623
+# define CSON_INT(V) ((cson_int_t*)(&((V)->value)))
1624
+#else
1625
+# define CSON_INT(V) ((cson_int_t*)(V)->value)
1626
+#endif
1627
+
16141628
#define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
16151629
#define CSON_STR(V) CSON_CAST(cson_string,(V))
16161630
#define CSON_OBJ(V) CSON_CAST(cson_object,(V))
16171631
#define CSON_ARRAY(V) CSON_CAST(cson_array,(V))
16181632
@@ -1668,11 +1682,11 @@
16681682
{ &cson_value_api_bool, &CSON_EMPTY_HOLDER.trueValue, 0 }, /* TRUE */
16691683
{ &cson_value_api_bool, NULL, 0 }, /* FALSE */
16701684
{ &cson_value_api_integer, NULL, 0 }, /* INT_0 */
16711685
{ &cson_value_api_double, NULL, 0 }, /* DBL_0 */
16721686
{ &cson_value_api_string, &CSON_EMPTY_HOLDER.stringValue, 0 }, /* STR_EMPTY */
1673
-{ 0, NULL, 0 }
1687
+{ NULL, NULL, 0 }
16741688
};
16751689
16761690
16771691
/**
16781692
Returns non-0 (true) if m is one of our special
@@ -1916,11 +1930,11 @@
19161930
19171931
cson_strings are supposed to be immutable, but this form provides
19181932
access to the immutable bits, which are v->length bytes long. A
19191933
length-0 string is returned as NULL from here, as opposed to
19201934
"". (This is a side-effect of the string allocation mechanism.)
1921
- Returns NULL if !v.
1935
+ Returns NULL if !v or if v is the internal empty-string singleton.
19221936
*/
19231937
static char * cson_string_str(cson_string *v)
19241938
{
19251939
/*
19261940
See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
@@ -1948,11 +1962,14 @@
19481962
See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
19491963
*/
19501964
#if 1
19511965
if( ! v ) return NULL;
19521966
else if( v == &CSON_EMPTY_HOLDER.stringValue ) return "";
1953
- else return (char *)((unsigned char *)(v+1));
1967
+ else {
1968
+ assert((0 < v->length) && "How do we have a non-singleton empty string?");
1969
+ return (char const *)((unsigned char const *)(v+1));
1970
+ }
19541971
#else
19551972
return (NULL == v)
19561973
? NULL
19571974
: (v->length
19581975
? (char const *) ((unsigned char const *)(v+1))
@@ -2028,10 +2045,13 @@
20282045
};
20292046
#define cson_kvp_empty_m {NULL,NULL}
20302047
static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
20312048
20322049
/** @def CSON_OBJECT_PROPS_SORT
2050
+
2051
+ Don't use this - it has not been updated to account for internal
2052
+ changes in cson_object.
20332053
20342054
If CSON_OBJECT_PROPS_SORT is set to a true value then
20352055
qsort() and bsearch() are used to sort (upon insertion)
20362056
and search cson_object::kvp property lists. This costs us
20372057
a re-sort on each insertion but searching is O(log n)
@@ -2210,11 +2230,12 @@
22102230
of the string to allocate + 1 byte (for the NUL).
22112231
22122232
The returned value->api member will be set appropriately and
22132233
val->value will be set to point to the memory allocated to hold the
22142234
native value type. Use the internal CSON_CAST() family of macros to
2215
- convert them.
2235
+ convert the cson_values to their corresponding native
2236
+ representation.
22162237
22172238
Returns NULL on allocation error.
22182239
22192240
@see cson_value_new_array()
22202241
@see cson_value_new_object()
@@ -2222,13 +2243,11 @@
22222243
@see cson_value_new_integer()
22232244
@see cson_value_new_double()
22242245
@see cson_value_new_bool()
22252246
@see cson_value_free()
22262247
*/
2227
-static cson_value * cson_value_new(cson_type_id t, size_t extra);
2228
-
2229
-cson_value * cson_value_new(cson_type_id t, size_t extra)
2248
+static cson_value * cson_value_new(cson_type_id t, size_t extra)
22302249
{
22312250
static const size_t vsz = sizeof(cson_value);
22322251
const size_t sz = vsz + extra;
22332252
size_t tx = 0;
22342253
cson_value def = cson_value_undef;
@@ -2248,17 +2267,14 @@
22482267
tx = sizeof(cson_double_t);
22492268
reason = "cson_value:double";
22502269
break;
22512270
case CSON_TYPE_INTEGER:
22522271
assert( 0 == extra );
2253
- /* FIXME: if sizeof(void*) >= sizeof(cson_int_t) then store
2254
- the int value directly in the void pointer (requires no
2255
- extra alloc). The current behaviour requires 32
2256
- bytes(!!!) on 64-bit builds.
2257
- */
22582272
def = cson_value_integer_empty;
2273
+#if !CSON_VOID_PTR_IS_BIG
22592274
tx = sizeof(cson_int_t);
2275
+#endif
22602276
reason = "cson_value:int";
22612277
break;
22622278
case CSON_TYPE_STRING:
22632279
assert( 0 != extra );
22642280
def = cson_value_string_empty;
@@ -2648,13 +2664,14 @@
26482664
}
26492665
case CSON_TYPE_STRING:
26502666
case CSON_TYPE_ARRAY:
26512667
case CSON_TYPE_OBJECT:
26522668
default:
2653
- break;
2669
+ rc = cson_rc.TypeError;
2670
+ break;
26542671
}
2655
- if(v) *v = i;
2672
+ if(!rc && v) *v = i;
26562673
return rc;
26572674
}
26582675
}
26592676
26602677
cson_int_t cson_value_get_integer( cson_value const * val )
@@ -2863,11 +2880,13 @@
28632880
{
28642881
if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
28652882
else
28662883
{
28672884
cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
2868
-
2885
+#if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG
2886
+ assert( sizeof(cson_int_t) <= sizeof(void *) );
2887
+#endif
28692888
if( c )
28702889
{
28712890
*CSON_INT(c) = v;
28722891
}
28732892
return c;
@@ -3142,11 +3161,11 @@
31423161
kvp->value = v;
31433162
}
31443163
return 0;
31453164
}
31463165
if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3147
- {
3166
+ { /* reserve space */
31483167
unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
31493168
if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
31503169
{
31513170
return cson_rc.AllocError;
31523171
}
@@ -3281,10 +3300,12 @@
32813300
{
32823301
cson_value_free(val);
32833302
return cson_rc.AllocError;
32843303
}
32853304
kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
3305
+ assert(0 == kvp->key->refcount);
3306
+ cson_refcount_incr(kvp->key);
32863307
p->ckey = NULL;
32873308
kvp->value = val;
32883309
cson_refcount_incr( val );
32893310
rc = cson_kvp_list_append( &obj->kvp, kvp );
32903311
if( 0 != rc )
@@ -3361,11 +3382,11 @@
33613382
? cson_value_new_array()
33623383
: cson_value_new_object();
33633384
if( ! obja )
33643385
{
33653386
p->errNo = cson_rc.AllocError;
3366
- return 0;
3387
+ break;
33673388
}
33683389
if( 0 != rc ) break;
33693390
if( ! p->root )
33703391
{
33713392
p->root = p->node = obja;
@@ -3384,12 +3405,16 @@
33843405
}
33853406
}
33863407
else
33873408
{
33883409
rc = cson_array_append( &p->stack, obja );
3389
- if( 0 == rc ) rc = cson_parser_push_value( p, obja );
3390
- if( 0 == rc ) p->node = obja;
3410
+ if(rc) cson_value_free( obja );
3411
+ else
3412
+ {
3413
+ rc = cson_parser_push_value( p, obja );
3414
+ if( 0 == rc ) p->node = obja;
3415
+ }
33913416
}
33923417
break;
33933418
}
33943419
case JSON_T_ARRAY_END:
33953420
case JSON_T_OBJECT_END: {
@@ -4578,10 +4603,39 @@
45784603
cson_value * v = NULL;
45794604
cson_object_fetch_sub2( obj, &v, path );
45804605
return v;
45814606
}
45824607
4608
+
4609
+/**
4610
+ If v is-a Object or Array then this function returns a deep
4611
+ clone, otherwise it returns v. In either case, the refcount
4612
+ of the returned value is increased by 1 by this call.
4613
+*/
4614
+static cson_value * cson_value_clone_ref( cson_value * v )
4615
+{
4616
+ cson_value * rc = NULL;
4617
+#define TRY_SHARING 1
4618
+#if TRY_SHARING
4619
+ if(!v ) return rc;
4620
+ else if( cson_value_is_object(v)
4621
+ || cson_value_is_array(v))
4622
+ {
4623
+ rc = cson_value_clone( v );
4624
+ }
4625
+ else
4626
+ {
4627
+ rc = v;
4628
+ }
4629
+#else
4630
+ rc = cson_value_clone(v);
4631
+#endif
4632
+#undef TRY_SHARING
4633
+ cson_value_add_reference(rc);
4634
+ return rc;
4635
+}
4636
+
45834637
static cson_value * cson_value_clone_array( cson_value const * orig )
45844638
{
45854639
unsigned int i = 0;
45864640
cson_array const * asrc = cson_value_get_array( orig );
45874641
unsigned int alen = cson_array_length_get( asrc );
@@ -4600,11 +4654,11 @@
46004654
for( ; i < alen; ++i )
46014655
{
46024656
cson_value * ch = cson_array_get( asrc, i );
46034657
if( NULL != ch )
46044658
{
4605
- cson_value * cl = cson_value_clone( ch );
4659
+ cson_value * cl = cson_value_clone_ref( ch );
46064660
if( NULL == cl )
46074661
{
46084662
cson_value_free( destV );
46094663
return NULL;
46104664
}
@@ -4612,15 +4666,16 @@
46124666
{
46134667
cson_value_free( cl );
46144668
cson_value_free( destV );
46154669
return NULL;
46164670
}
4671
+ cson_value_free(cl)/*remove our artificial reference */;
46174672
}
46184673
}
46194674
return destV;
46204675
}
4621
-
4676
+
46224677
static cson_value * cson_value_clone_object( cson_value const * orig )
46234678
{
46244679
cson_object const * src = cson_value_get_object( orig );
46254680
cson_value * destV = NULL;
46264681
cson_object * dest = NULL;
@@ -4639,32 +4694,33 @@
46394694
cson_value_free( destV );
46404695
return NULL;
46414696
}
46424697
while( (kvp = cson_object_iter_next( &iter )) )
46434698
{
4644
- /*
4645
- FIXME: refcount the keys! We first need a setter which takes
4646
- a cson_string or cson_value key type.
4647
- */
46484699
cson_value * key = NULL;
46494700
cson_value * val = NULL;
4650
- key = cson_value_clone(kvp->key);
4651
- val = key ? cson_value_clone( kvp->value ) : NULL;
4701
+ assert( kvp->key && (kvp->key->refcount>0) );
4702
+ key = cson_value_clone_ref(kvp->key);
4703
+ val = key ? cson_value_clone_ref(kvp->value) : NULL;
46524704
if( ! key || !val ){
4653
- cson_value_free(key);
4654
- cson_value_free(val);
4655
- cson_value_free(destV);
4656
- return NULL;
4705
+ goto error;
46574706
}
46584707
assert( CSON_STR(key) );
46594708
if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
46604709
{
4661
- cson_value_free(key);
4662
- cson_value_free(val);
4663
- cson_value_free(destV);
4664
- return NULL;
4710
+ goto error;
46654711
}
4712
+ /* remove our references */
4713
+ cson_value_free(key);
4714
+ cson_value_free(val);
4715
+ continue;
4716
+ error:
4717
+ cson_value_free(key);
4718
+ cson_value_free(val);
4719
+ cson_value_free(destV);
4720
+ destV = NULL;
4721
+ break;
46664722
}
46674723
return destV;
46684724
}
46694725
46704726
cson_value * cson_value_clone( cson_value const * orig )
@@ -4733,17 +4789,17 @@
47334789
void cson_free_array(cson_array *x)
47344790
{
47354791
if(x) cson_value_free(cson_array_value(x));
47364792
}
47374793
4738
-void cson_free_string(cson_string const *x)
4794
+void cson_free_string(cson_string *x)
47394795
{
47404796
if(x) cson_value_free(cson_string_value(x));
47414797
}
47424798
void cson_free_value(cson_value *x)
47434799
{
4744
- cson_value_free(x);
4800
+ if(x) cson_value_free(x);
47454801
}
47464802
47474803
47484804
#if 0
47494805
/* i'm not happy with this... */
@@ -4907,11 +4963,11 @@
49074963
assert( 0 && "Should have been caught by is-builtin check!" );
49084964
break;
49094965
default:
49104966
assert(0 && "Invalid typeID!");
49114967
return 0;
4912
-
4968
+#undef RCCHECK
49134969
}
49144970
return rc;
49154971
}
49164972
}
49174973
@@ -4954,27 +5010,29 @@
49545010
return 0;
49555011
}
49565012
49575013
static cson_value * cson_guess_arg_type(char const *arg){
49585014
char * end = NULL;
4959
- if(('0'<=*arg) && ('9'>=*arg)){
5015
+ if(!arg || !*arg) return cson_value_null();
5016
+ else if(('0'>*arg) || ('9'<*arg)){
49605017
goto do_string;
49615018
}
4962
- {
5019
+ else{ /* try numbers... */
49635020
long const val = strtol(arg, &end, 10);
49645021
if(!*end){
49655022
return cson_value_new_integer( (cson_int_t)val);
49665023
}
4967
- }
4968
- {
4969
- double const val = strtod(arg, &end);
4970
- if(!*end){
4971
- return cson_value_new_double(val);
5024
+ else if( '.' != *end ) {
5025
+ goto do_string;
5026
+ }
5027
+ else {
5028
+ double const val = strtod(arg, &end);
5029
+ if(!*end){
5030
+ return cson_value_new_double(val);
5031
+ }
49725032
}
49735033
}
4974
-
4975
-
49765034
do_string:
49775035
return cson_value_new_string(arg, strlen(arg));
49785036
}
49795037
49805038
@@ -5005,13 +5063,11 @@
50055063
if(!*pos){ /** --key */
50065064
v = cson_value_true();
50075065
}else{ /** --key=...*/
50085066
assert('=' == *pos);
50095067
++pos /*skip '='*/;
5010
- v = *pos
5011
- ? cson_guess_arg_type(pos)
5012
- : cson_value_null();
5068
+ v = cson_guess_arg_type(pos);
50135069
}
50145070
if(0 != (rc=cson_object_set_s(o, k, v))){
50155071
cson_free_string(k);
50165072
cson_value_free(v);
50175073
break;
@@ -5573,13 +5629,69 @@
55735629
rc = cson_sqlite3_stmt_to_json( st, tgt, fat );
55745630
sqlite3_finalize( st );
55755631
return rc;
55765632
}
55775633
}
5634
+
5635
+int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v )
5636
+{
5637
+ int rc = 0;
5638
+ char convertErr = 0;
5639
+ if(!st) return cson_rc.ArgError;
5640
+ else if( ndx < 1 ) {
5641
+ rc = cson_rc.RangeError;
5642
+ }
5643
+ else if( cson_value_is_array(v) ){
5644
+ cson_array * ar = cson_value_get_array(v);
5645
+ unsigned int len = cson_array_length_get(ar);
5646
+ unsigned int i;
5647
+ assert(NULL != ar);
5648
+ for( i = 0; !rc && (i < len); ++i ){
5649
+ rc = cson_sqlite3_bind_value( st, (int)i+ndx,
5650
+ cson_array_get(ar, i));
5651
+ }
5652
+ }
5653
+ else if(!v || cson_value_is_null(v)){
5654
+ rc = sqlite3_bind_null(st,ndx);
5655
+ convertErr = 1;
5656
+ }
5657
+ else if( cson_value_is_double(v) ){
5658
+ rc = sqlite3_bind_double( st, ndx, cson_value_get_double(v) );
5659
+ convertErr = 1;
5660
+ }
5661
+ else if( cson_value_is_bool(v) ){
5662
+ rc = sqlite3_bind_int( st, ndx, cson_value_get_bool(v) ? 1 : 0 );
5663
+ convertErr = 1;
5664
+ }
5665
+ else if( cson_value_is_integer(v) ){
5666
+ rc = sqlite3_bind_int64( st, ndx, cson_value_get_integer(v) );
5667
+ convertErr = 1;
5668
+ }
5669
+ else if( cson_value_is_string(v) ){
5670
+ cson_string const * s = cson_value_get_string(v);
5671
+ rc = sqlite3_bind_text( st, ndx,
5672
+ cson_string_cstr(s),
5673
+ cson_string_length_bytes(s),
5674
+ SQLITE_TRANSIENT);
5675
+ convertErr = 1;
5676
+ }
5677
+ else {
5678
+ rc = cson_rc.TypeError;
5679
+ }
5680
+ if(convertErr && rc) switch(rc){
5681
+ case SQLITE_TOOBIG:
5682
+ case SQLITE_RANGE: rc = cson_rc.RangeError; break;
5683
+ case SQLITE_NOMEM: rc = cson_rc.AllocError; break;
5684
+ case SQLITE_IOERR: rc = cson_rc.IOError; break;
5685
+ default: rc = cson_rc.UnknownError; break;
5686
+ };
5687
+ return rc;
5688
+}
5689
+
55785690
55795691
#if defined(__cplusplus)
55805692
} /*extern "C"*/
55815693
#endif
55825694
#undef MARKER
55835695
#endif /* CSON_ENABLE_SQLITE3 */
55845696
/* end file ./cson_sqlite3.c */
55855697
#endif /* FOSSIL_ENABLE_JSON */
55865698
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1427,11 +1427,11 @@
1427 /**
1428 Type IDs corresponding to JavaScript/JSON types.
1429 */
1430 enum cson_type_id {
1431 /**
1432 The special "null" value constant.
1433
1434 Its value must be 0 for internal reasons.
1435 */
1436 CSON_TYPE_UNDEF = 0,
1437 /**
@@ -1597,10 +1597,18 @@
1597 static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 };
1598 static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 };
1599 static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 };
1600 static const cson_value cson_value_object_empty = { &cson_value_api_object, NULL, 0 };
1601
 
 
 
 
 
 
 
 
1602 struct cson_string
1603 {
1604 unsigned int length;
1605 };
1606 #define cson_string_empty_m {0/*length*/}
@@ -1608,11 +1616,17 @@
1608
1609
1610
1611 #define CSON_CAST(T,V) ((T*)((V)->value))
1612 #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value)))
1613 #define CSON_INT(V) ((cson_int_t*)(V)->value)
 
 
 
 
 
 
1614 #define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
1615 #define CSON_STR(V) CSON_CAST(cson_string,(V))
1616 #define CSON_OBJ(V) CSON_CAST(cson_object,(V))
1617 #define CSON_ARRAY(V) CSON_CAST(cson_array,(V))
1618
@@ -1668,11 +1682,11 @@
1668 { &cson_value_api_bool, &CSON_EMPTY_HOLDER.trueValue, 0 }, /* TRUE */
1669 { &cson_value_api_bool, NULL, 0 }, /* FALSE */
1670 { &cson_value_api_integer, NULL, 0 }, /* INT_0 */
1671 { &cson_value_api_double, NULL, 0 }, /* DBL_0 */
1672 { &cson_value_api_string, &CSON_EMPTY_HOLDER.stringValue, 0 }, /* STR_EMPTY */
1673 { 0, NULL, 0 }
1674 };
1675
1676
1677 /**
1678 Returns non-0 (true) if m is one of our special
@@ -1916,11 +1930,11 @@
1916
1917 cson_strings are supposed to be immutable, but this form provides
1918 access to the immutable bits, which are v->length bytes long. A
1919 length-0 string is returned as NULL from here, as opposed to
1920 "". (This is a side-effect of the string allocation mechanism.)
1921 Returns NULL if !v.
1922 */
1923 static char * cson_string_str(cson_string *v)
1924 {
1925 /*
1926 See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
@@ -1948,11 +1962,14 @@
1948 See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
1949 */
1950 #if 1
1951 if( ! v ) return NULL;
1952 else if( v == &CSON_EMPTY_HOLDER.stringValue ) return "";
1953 else return (char *)((unsigned char *)(v+1));
 
 
 
1954 #else
1955 return (NULL == v)
1956 ? NULL
1957 : (v->length
1958 ? (char const *) ((unsigned char const *)(v+1))
@@ -2028,10 +2045,13 @@
2028 };
2029 #define cson_kvp_empty_m {NULL,NULL}
2030 static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
2031
2032 /** @def CSON_OBJECT_PROPS_SORT
 
 
 
2033
2034 If CSON_OBJECT_PROPS_SORT is set to a true value then
2035 qsort() and bsearch() are used to sort (upon insertion)
2036 and search cson_object::kvp property lists. This costs us
2037 a re-sort on each insertion but searching is O(log n)
@@ -2210,11 +2230,12 @@
2210 of the string to allocate + 1 byte (for the NUL).
2211
2212 The returned value->api member will be set appropriately and
2213 val->value will be set to point to the memory allocated to hold the
2214 native value type. Use the internal CSON_CAST() family of macros to
2215 convert them.
 
2216
2217 Returns NULL on allocation error.
2218
2219 @see cson_value_new_array()
2220 @see cson_value_new_object()
@@ -2222,13 +2243,11 @@
2222 @see cson_value_new_integer()
2223 @see cson_value_new_double()
2224 @see cson_value_new_bool()
2225 @see cson_value_free()
2226 */
2227 static cson_value * cson_value_new(cson_type_id t, size_t extra);
2228
2229 cson_value * cson_value_new(cson_type_id t, size_t extra)
2230 {
2231 static const size_t vsz = sizeof(cson_value);
2232 const size_t sz = vsz + extra;
2233 size_t tx = 0;
2234 cson_value def = cson_value_undef;
@@ -2248,17 +2267,14 @@
2248 tx = sizeof(cson_double_t);
2249 reason = "cson_value:double";
2250 break;
2251 case CSON_TYPE_INTEGER:
2252 assert( 0 == extra );
2253 /* FIXME: if sizeof(void*) >= sizeof(cson_int_t) then store
2254 the int value directly in the void pointer (requires no
2255 extra alloc). The current behaviour requires 32
2256 bytes(!!!) on 64-bit builds.
2257 */
2258 def = cson_value_integer_empty;
 
2259 tx = sizeof(cson_int_t);
 
2260 reason = "cson_value:int";
2261 break;
2262 case CSON_TYPE_STRING:
2263 assert( 0 != extra );
2264 def = cson_value_string_empty;
@@ -2648,13 +2664,14 @@
2648 }
2649 case CSON_TYPE_STRING:
2650 case CSON_TYPE_ARRAY:
2651 case CSON_TYPE_OBJECT:
2652 default:
2653 break;
 
2654 }
2655 if(v) *v = i;
2656 return rc;
2657 }
2658 }
2659
2660 cson_int_t cson_value_get_integer( cson_value const * val )
@@ -2863,11 +2880,13 @@
2863 {
2864 if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
2865 else
2866 {
2867 cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
2868
 
 
2869 if( c )
2870 {
2871 *CSON_INT(c) = v;
2872 }
2873 return c;
@@ -3142,11 +3161,11 @@
3142 kvp->value = v;
3143 }
3144 return 0;
3145 }
3146 if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3147 {
3148 unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
3149 if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3150 {
3151 return cson_rc.AllocError;
3152 }
@@ -3281,10 +3300,12 @@
3281 {
3282 cson_value_free(val);
3283 return cson_rc.AllocError;
3284 }
3285 kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
 
 
3286 p->ckey = NULL;
3287 kvp->value = val;
3288 cson_refcount_incr( val );
3289 rc = cson_kvp_list_append( &obj->kvp, kvp );
3290 if( 0 != rc )
@@ -3361,11 +3382,11 @@
3361 ? cson_value_new_array()
3362 : cson_value_new_object();
3363 if( ! obja )
3364 {
3365 p->errNo = cson_rc.AllocError;
3366 return 0;
3367 }
3368 if( 0 != rc ) break;
3369 if( ! p->root )
3370 {
3371 p->root = p->node = obja;
@@ -3384,12 +3405,16 @@
3384 }
3385 }
3386 else
3387 {
3388 rc = cson_array_append( &p->stack, obja );
3389 if( 0 == rc ) rc = cson_parser_push_value( p, obja );
3390 if( 0 == rc ) p->node = obja;
 
 
 
 
3391 }
3392 break;
3393 }
3394 case JSON_T_ARRAY_END:
3395 case JSON_T_OBJECT_END: {
@@ -4578,10 +4603,39 @@
4578 cson_value * v = NULL;
4579 cson_object_fetch_sub2( obj, &v, path );
4580 return v;
4581 }
4582
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4583 static cson_value * cson_value_clone_array( cson_value const * orig )
4584 {
4585 unsigned int i = 0;
4586 cson_array const * asrc = cson_value_get_array( orig );
4587 unsigned int alen = cson_array_length_get( asrc );
@@ -4600,11 +4654,11 @@
4600 for( ; i < alen; ++i )
4601 {
4602 cson_value * ch = cson_array_get( asrc, i );
4603 if( NULL != ch )
4604 {
4605 cson_value * cl = cson_value_clone( ch );
4606 if( NULL == cl )
4607 {
4608 cson_value_free( destV );
4609 return NULL;
4610 }
@@ -4612,15 +4666,16 @@
4612 {
4613 cson_value_free( cl );
4614 cson_value_free( destV );
4615 return NULL;
4616 }
 
4617 }
4618 }
4619 return destV;
4620 }
4621
4622 static cson_value * cson_value_clone_object( cson_value const * orig )
4623 {
4624 cson_object const * src = cson_value_get_object( orig );
4625 cson_value * destV = NULL;
4626 cson_object * dest = NULL;
@@ -4639,32 +4694,33 @@
4639 cson_value_free( destV );
4640 return NULL;
4641 }
4642 while( (kvp = cson_object_iter_next( &iter )) )
4643 {
4644 /*
4645 FIXME: refcount the keys! We first need a setter which takes
4646 a cson_string or cson_value key type.
4647 */
4648 cson_value * key = NULL;
4649 cson_value * val = NULL;
4650 key = cson_value_clone(kvp->key);
4651 val = key ? cson_value_clone( kvp->value ) : NULL;
 
4652 if( ! key || !val ){
4653 cson_value_free(key);
4654 cson_value_free(val);
4655 cson_value_free(destV);
4656 return NULL;
4657 }
4658 assert( CSON_STR(key) );
4659 if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
4660 {
4661 cson_value_free(key);
4662 cson_value_free(val);
4663 cson_value_free(destV);
4664 return NULL;
4665 }
 
 
 
 
 
 
 
 
 
 
4666 }
4667 return destV;
4668 }
4669
4670 cson_value * cson_value_clone( cson_value const * orig )
@@ -4733,17 +4789,17 @@
4733 void cson_free_array(cson_array *x)
4734 {
4735 if(x) cson_value_free(cson_array_value(x));
4736 }
4737
4738 void cson_free_string(cson_string const *x)
4739 {
4740 if(x) cson_value_free(cson_string_value(x));
4741 }
4742 void cson_free_value(cson_value *x)
4743 {
4744 cson_value_free(x);
4745 }
4746
4747
4748 #if 0
4749 /* i'm not happy with this... */
@@ -4907,11 +4963,11 @@
4907 assert( 0 && "Should have been caught by is-builtin check!" );
4908 break;
4909 default:
4910 assert(0 && "Invalid typeID!");
4911 return 0;
4912
4913 }
4914 return rc;
4915 }
4916 }
4917
@@ -4954,27 +5010,29 @@
4954 return 0;
4955 }
4956
4957 static cson_value * cson_guess_arg_type(char const *arg){
4958 char * end = NULL;
4959 if(('0'<=*arg) && ('9'>=*arg)){
 
4960 goto do_string;
4961 }
4962 {
4963 long const val = strtol(arg, &end, 10);
4964 if(!*end){
4965 return cson_value_new_integer( (cson_int_t)val);
4966 }
4967 }
4968 {
4969 double const val = strtod(arg, &end);
4970 if(!*end){
4971 return cson_value_new_double(val);
 
 
 
4972 }
4973 }
4974
4975
4976 do_string:
4977 return cson_value_new_string(arg, strlen(arg));
4978 }
4979
4980
@@ -5005,13 +5063,11 @@
5005 if(!*pos){ /** --key */
5006 v = cson_value_true();
5007 }else{ /** --key=...*/
5008 assert('=' == *pos);
5009 ++pos /*skip '='*/;
5010 v = *pos
5011 ? cson_guess_arg_type(pos)
5012 : cson_value_null();
5013 }
5014 if(0 != (rc=cson_object_set_s(o, k, v))){
5015 cson_free_string(k);
5016 cson_value_free(v);
5017 break;
@@ -5573,13 +5629,69 @@
5573 rc = cson_sqlite3_stmt_to_json( st, tgt, fat );
5574 sqlite3_finalize( st );
5575 return rc;
5576 }
5577 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5578
5579 #if defined(__cplusplus)
5580 } /*extern "C"*/
5581 #endif
5582 #undef MARKER
5583 #endif /* CSON_ENABLE_SQLITE3 */
5584 /* end file ./cson_sqlite3.c */
5585 #endif /* FOSSIL_ENABLE_JSON */
5586
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1427,11 +1427,11 @@
1427 /**
1428 Type IDs corresponding to JavaScript/JSON types.
1429 */
1430 enum cson_type_id {
1431 /**
1432 The special "undefined" value constant.
1433
1434 Its value must be 0 for internal reasons.
1435 */
1436 CSON_TYPE_UNDEF = 0,
1437 /**
@@ -1597,10 +1597,18 @@
1597 static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 };
1598 static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 };
1599 static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 };
1600 static const cson_value cson_value_object_empty = { &cson_value_api_object, NULL, 0 };
1601
1602 /**
1603 Strings are allocated as an instances of this class with N+1
1604 trailing bytes, where N is the length of the string being
1605 allocated. To convert a cson_string to c-string we simply increment
1606 the cson_string pointer. To do the opposite we use (cstr -
1607 sizeof(cson_string)). Zero-length strings are a special case
1608 handled by a couple of the cson_string functions.
1609 */
1610 struct cson_string
1611 {
1612 unsigned int length;
1613 };
1614 #define cson_string_empty_m {0/*length*/}
@@ -1608,11 +1616,17 @@
1616
1617
1618
1619 #define CSON_CAST(T,V) ((T*)((V)->value))
1620 #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value)))
1621
1622 #if CSON_VOID_PTR_IS_BIG
1623 # define CSON_INT(V) ((cson_int_t*)(&((V)->value)))
1624 #else
1625 # define CSON_INT(V) ((cson_int_t*)(V)->value)
1626 #endif
1627
1628 #define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
1629 #define CSON_STR(V) CSON_CAST(cson_string,(V))
1630 #define CSON_OBJ(V) CSON_CAST(cson_object,(V))
1631 #define CSON_ARRAY(V) CSON_CAST(cson_array,(V))
1632
@@ -1668,11 +1682,11 @@
1682 { &cson_value_api_bool, &CSON_EMPTY_HOLDER.trueValue, 0 }, /* TRUE */
1683 { &cson_value_api_bool, NULL, 0 }, /* FALSE */
1684 { &cson_value_api_integer, NULL, 0 }, /* INT_0 */
1685 { &cson_value_api_double, NULL, 0 }, /* DBL_0 */
1686 { &cson_value_api_string, &CSON_EMPTY_HOLDER.stringValue, 0 }, /* STR_EMPTY */
1687 { NULL, NULL, 0 }
1688 };
1689
1690
1691 /**
1692 Returns non-0 (true) if m is one of our special
@@ -1916,11 +1930,11 @@
1930
1931 cson_strings are supposed to be immutable, but this form provides
1932 access to the immutable bits, which are v->length bytes long. A
1933 length-0 string is returned as NULL from here, as opposed to
1934 "". (This is a side-effect of the string allocation mechanism.)
1935 Returns NULL if !v or if v is the internal empty-string singleton.
1936 */
1937 static char * cson_string_str(cson_string *v)
1938 {
1939 /*
1940 See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
@@ -1948,11 +1962,14 @@
1962 See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
1963 */
1964 #if 1
1965 if( ! v ) return NULL;
1966 else if( v == &CSON_EMPTY_HOLDER.stringValue ) return "";
1967 else {
1968 assert((0 < v->length) && "How do we have a non-singleton empty string?");
1969 return (char const *)((unsigned char const *)(v+1));
1970 }
1971 #else
1972 return (NULL == v)
1973 ? NULL
1974 : (v->length
1975 ? (char const *) ((unsigned char const *)(v+1))
@@ -2028,10 +2045,13 @@
2045 };
2046 #define cson_kvp_empty_m {NULL,NULL}
2047 static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
2048
2049 /** @def CSON_OBJECT_PROPS_SORT
2050
2051 Don't use this - it has not been updated to account for internal
2052 changes in cson_object.
2053
2054 If CSON_OBJECT_PROPS_SORT is set to a true value then
2055 qsort() and bsearch() are used to sort (upon insertion)
2056 and search cson_object::kvp property lists. This costs us
2057 a re-sort on each insertion but searching is O(log n)
@@ -2210,11 +2230,12 @@
2230 of the string to allocate + 1 byte (for the NUL).
2231
2232 The returned value->api member will be set appropriately and
2233 val->value will be set to point to the memory allocated to hold the
2234 native value type. Use the internal CSON_CAST() family of macros to
2235 convert the cson_values to their corresponding native
2236 representation.
2237
2238 Returns NULL on allocation error.
2239
2240 @see cson_value_new_array()
2241 @see cson_value_new_object()
@@ -2222,13 +2243,11 @@
2243 @see cson_value_new_integer()
2244 @see cson_value_new_double()
2245 @see cson_value_new_bool()
2246 @see cson_value_free()
2247 */
2248 static cson_value * cson_value_new(cson_type_id t, size_t extra)
 
 
2249 {
2250 static const size_t vsz = sizeof(cson_value);
2251 const size_t sz = vsz + extra;
2252 size_t tx = 0;
2253 cson_value def = cson_value_undef;
@@ -2248,17 +2267,14 @@
2267 tx = sizeof(cson_double_t);
2268 reason = "cson_value:double";
2269 break;
2270 case CSON_TYPE_INTEGER:
2271 assert( 0 == extra );
 
 
 
 
 
2272 def = cson_value_integer_empty;
2273 #if !CSON_VOID_PTR_IS_BIG
2274 tx = sizeof(cson_int_t);
2275 #endif
2276 reason = "cson_value:int";
2277 break;
2278 case CSON_TYPE_STRING:
2279 assert( 0 != extra );
2280 def = cson_value_string_empty;
@@ -2648,13 +2664,14 @@
2664 }
2665 case CSON_TYPE_STRING:
2666 case CSON_TYPE_ARRAY:
2667 case CSON_TYPE_OBJECT:
2668 default:
2669 rc = cson_rc.TypeError;
2670 break;
2671 }
2672 if(!rc && v) *v = i;
2673 return rc;
2674 }
2675 }
2676
2677 cson_int_t cson_value_get_integer( cson_value const * val )
@@ -2863,11 +2880,13 @@
2880 {
2881 if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
2882 else
2883 {
2884 cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
2885 #if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG
2886 assert( sizeof(cson_int_t) <= sizeof(void *) );
2887 #endif
2888 if( c )
2889 {
2890 *CSON_INT(c) = v;
2891 }
2892 return c;
@@ -3142,11 +3161,11 @@
3161 kvp->value = v;
3162 }
3163 return 0;
3164 }
3165 if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3166 { /* reserve space */
3167 unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
3168 if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3169 {
3170 return cson_rc.AllocError;
3171 }
@@ -3281,10 +3300,12 @@
3300 {
3301 cson_value_free(val);
3302 return cson_rc.AllocError;
3303 }
3304 kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
3305 assert(0 == kvp->key->refcount);
3306 cson_refcount_incr(kvp->key);
3307 p->ckey = NULL;
3308 kvp->value = val;
3309 cson_refcount_incr( val );
3310 rc = cson_kvp_list_append( &obj->kvp, kvp );
3311 if( 0 != rc )
@@ -3361,11 +3382,11 @@
3382 ? cson_value_new_array()
3383 : cson_value_new_object();
3384 if( ! obja )
3385 {
3386 p->errNo = cson_rc.AllocError;
3387 break;
3388 }
3389 if( 0 != rc ) break;
3390 if( ! p->root )
3391 {
3392 p->root = p->node = obja;
@@ -3384,12 +3405,16 @@
3405 }
3406 }
3407 else
3408 {
3409 rc = cson_array_append( &p->stack, obja );
3410 if(rc) cson_value_free( obja );
3411 else
3412 {
3413 rc = cson_parser_push_value( p, obja );
3414 if( 0 == rc ) p->node = obja;
3415 }
3416 }
3417 break;
3418 }
3419 case JSON_T_ARRAY_END:
3420 case JSON_T_OBJECT_END: {
@@ -4578,10 +4603,39 @@
4603 cson_value * v = NULL;
4604 cson_object_fetch_sub2( obj, &v, path );
4605 return v;
4606 }
4607
4608
4609 /**
4610 If v is-a Object or Array then this function returns a deep
4611 clone, otherwise it returns v. In either case, the refcount
4612 of the returned value is increased by 1 by this call.
4613 */
4614 static cson_value * cson_value_clone_ref( cson_value * v )
4615 {
4616 cson_value * rc = NULL;
4617 #define TRY_SHARING 1
4618 #if TRY_SHARING
4619 if(!v ) return rc;
4620 else if( cson_value_is_object(v)
4621 || cson_value_is_array(v))
4622 {
4623 rc = cson_value_clone( v );
4624 }
4625 else
4626 {
4627 rc = v;
4628 }
4629 #else
4630 rc = cson_value_clone(v);
4631 #endif
4632 #undef TRY_SHARING
4633 cson_value_add_reference(rc);
4634 return rc;
4635 }
4636
4637 static cson_value * cson_value_clone_array( cson_value const * orig )
4638 {
4639 unsigned int i = 0;
4640 cson_array const * asrc = cson_value_get_array( orig );
4641 unsigned int alen = cson_array_length_get( asrc );
@@ -4600,11 +4654,11 @@
4654 for( ; i < alen; ++i )
4655 {
4656 cson_value * ch = cson_array_get( asrc, i );
4657 if( NULL != ch )
4658 {
4659 cson_value * cl = cson_value_clone_ref( ch );
4660 if( NULL == cl )
4661 {
4662 cson_value_free( destV );
4663 return NULL;
4664 }
@@ -4612,15 +4666,16 @@
4666 {
4667 cson_value_free( cl );
4668 cson_value_free( destV );
4669 return NULL;
4670 }
4671 cson_value_free(cl)/*remove our artificial reference */;
4672 }
4673 }
4674 return destV;
4675 }
4676
4677 static cson_value * cson_value_clone_object( cson_value const * orig )
4678 {
4679 cson_object const * src = cson_value_get_object( orig );
4680 cson_value * destV = NULL;
4681 cson_object * dest = NULL;
@@ -4639,32 +4694,33 @@
4694 cson_value_free( destV );
4695 return NULL;
4696 }
4697 while( (kvp = cson_object_iter_next( &iter )) )
4698 {
 
 
 
 
4699 cson_value * key = NULL;
4700 cson_value * val = NULL;
4701 assert( kvp->key && (kvp->key->refcount>0) );
4702 key = cson_value_clone_ref(kvp->key);
4703 val = key ? cson_value_clone_ref(kvp->value) : NULL;
4704 if( ! key || !val ){
4705 goto error;
 
 
 
4706 }
4707 assert( CSON_STR(key) );
4708 if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
4709 {
4710 goto error;
 
 
 
4711 }
4712 /* remove our references */
4713 cson_value_free(key);
4714 cson_value_free(val);
4715 continue;
4716 error:
4717 cson_value_free(key);
4718 cson_value_free(val);
4719 cson_value_free(destV);
4720 destV = NULL;
4721 break;
4722 }
4723 return destV;
4724 }
4725
4726 cson_value * cson_value_clone( cson_value const * orig )
@@ -4733,17 +4789,17 @@
4789 void cson_free_array(cson_array *x)
4790 {
4791 if(x) cson_value_free(cson_array_value(x));
4792 }
4793
4794 void cson_free_string(cson_string *x)
4795 {
4796 if(x) cson_value_free(cson_string_value(x));
4797 }
4798 void cson_free_value(cson_value *x)
4799 {
4800 if(x) cson_value_free(x);
4801 }
4802
4803
4804 #if 0
4805 /* i'm not happy with this... */
@@ -4907,11 +4963,11 @@
4963 assert( 0 && "Should have been caught by is-builtin check!" );
4964 break;
4965 default:
4966 assert(0 && "Invalid typeID!");
4967 return 0;
4968 #undef RCCHECK
4969 }
4970 return rc;
4971 }
4972 }
4973
@@ -4954,27 +5010,29 @@
5010 return 0;
5011 }
5012
5013 static cson_value * cson_guess_arg_type(char const *arg){
5014 char * end = NULL;
5015 if(!arg || !*arg) return cson_value_null();
5016 else if(('0'>*arg) || ('9'<*arg)){
5017 goto do_string;
5018 }
5019 else{ /* try numbers... */
5020 long const val = strtol(arg, &end, 10);
5021 if(!*end){
5022 return cson_value_new_integer( (cson_int_t)val);
5023 }
5024 else if( '.' != *end ) {
5025 goto do_string;
5026 }
5027 else {
5028 double const val = strtod(arg, &end);
5029 if(!*end){
5030 return cson_value_new_double(val);
5031 }
5032 }
5033 }
 
 
5034 do_string:
5035 return cson_value_new_string(arg, strlen(arg));
5036 }
5037
5038
@@ -5005,13 +5063,11 @@
5063 if(!*pos){ /** --key */
5064 v = cson_value_true();
5065 }else{ /** --key=...*/
5066 assert('=' == *pos);
5067 ++pos /*skip '='*/;
5068 v = cson_guess_arg_type(pos);
 
 
5069 }
5070 if(0 != (rc=cson_object_set_s(o, k, v))){
5071 cson_free_string(k);
5072 cson_value_free(v);
5073 break;
@@ -5573,13 +5629,69 @@
5629 rc = cson_sqlite3_stmt_to_json( st, tgt, fat );
5630 sqlite3_finalize( st );
5631 return rc;
5632 }
5633 }
5634
5635 int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v )
5636 {
5637 int rc = 0;
5638 char convertErr = 0;
5639 if(!st) return cson_rc.ArgError;
5640 else if( ndx < 1 ) {
5641 rc = cson_rc.RangeError;
5642 }
5643 else if( cson_value_is_array(v) ){
5644 cson_array * ar = cson_value_get_array(v);
5645 unsigned int len = cson_array_length_get(ar);
5646 unsigned int i;
5647 assert(NULL != ar);
5648 for( i = 0; !rc && (i < len); ++i ){
5649 rc = cson_sqlite3_bind_value( st, (int)i+ndx,
5650 cson_array_get(ar, i));
5651 }
5652 }
5653 else if(!v || cson_value_is_null(v)){
5654 rc = sqlite3_bind_null(st,ndx);
5655 convertErr = 1;
5656 }
5657 else if( cson_value_is_double(v) ){
5658 rc = sqlite3_bind_double( st, ndx, cson_value_get_double(v) );
5659 convertErr = 1;
5660 }
5661 else if( cson_value_is_bool(v) ){
5662 rc = sqlite3_bind_int( st, ndx, cson_value_get_bool(v) ? 1 : 0 );
5663 convertErr = 1;
5664 }
5665 else if( cson_value_is_integer(v) ){
5666 rc = sqlite3_bind_int64( st, ndx, cson_value_get_integer(v) );
5667 convertErr = 1;
5668 }
5669 else if( cson_value_is_string(v) ){
5670 cson_string const * s = cson_value_get_string(v);
5671 rc = sqlite3_bind_text( st, ndx,
5672 cson_string_cstr(s),
5673 cson_string_length_bytes(s),
5674 SQLITE_TRANSIENT);
5675 convertErr = 1;
5676 }
5677 else {
5678 rc = cson_rc.TypeError;
5679 }
5680 if(convertErr && rc) switch(rc){
5681 case SQLITE_TOOBIG:
5682 case SQLITE_RANGE: rc = cson_rc.RangeError; break;
5683 case SQLITE_NOMEM: rc = cson_rc.AllocError; break;
5684 case SQLITE_IOERR: rc = cson_rc.IOError; break;
5685 default: rc = cson_rc.UnknownError; break;
5686 };
5687 return rc;
5688 }
5689
5690
5691 #if defined(__cplusplus)
5692 } /*extern "C"*/
5693 #endif
5694 #undef MARKER
5695 #endif /* CSON_ENABLE_SQLITE3 */
5696 /* end file ./cson_sqlite3.c */
5697 #endif /* FOSSIL_ENABLE_JSON */
5698
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -74,10 +74,46 @@
7474
#else
7575
typedef double cson_double_t;
7676
#define CSON_DOUBLE_T_SFMT "f"
7777
#define CSON_DOUBLE_T_PFMT "f"
7878
#endif
79
+
80
+/** @def CSON_VOID_PTR_IS_BIG
81
+
82
+ONLY define this to a true value if you know that
83
+
84
+(sizeof(cson_int_t) <= sizeof(void*))
85
+
86
+If that is the case, cson does not need to dynamically
87
+allocate integers. However, enabling this may cause
88
+compilation warnings in 32-bit builds even though the code
89
+being warned about cannot ever be called. To get around such
90
+warnings, when building on a 64-bit environment you can define
91
+this to 1 to get "big" integer support. HOWEVER, all clients must
92
+also use the same value for this macro. If i knew a halfway reliable
93
+way to determine this automatically at preprocessor-time, i would
94
+automate this. We might be able to do halfway reliably by looking
95
+for a large INT_MAX value?
96
+*/
97
+#if !defined(CSON_VOID_PTR_IS_BIG)
98
+
99
+/* Largely taken from http://predef.sourceforge.net/prearch.html
100
+
101
+See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
102
+*/
103
+# if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
104
+ || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
105
+ || defined(__x86_64__) || defined(__x86_64) \
106
+ || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
107
+ || defined(_M_IA64) \
108
+ || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
109
+ || defined(__64BIT__)
110
+# define CSON_VOID_PTR_IS_BIG 1
111
+# else
112
+# define CSON_VOID_PTR_IS_BIG 0
113
+# endif
114
+#endif
79115
80116
/** @def CSON_INT_T_SFMT
81117
82118
scanf()-compatible format token for cson_int_t.
83119
*/
@@ -928,11 +964,12 @@
928964
/**
929965
Returns a pointer to the NULL-terminated string bytes of str.
930966
The bytes are owned by string and will be invalided when it
931967
is cleaned up.
932968
933
- If str is NULL then NULL is returned.
969
+ If str is NULL then NULL is returned. If the string has a length
970
+ of 0 then "" is returned.
934971
935972
@see cson_string_length_bytes()
936973
@see cson_value_get_string()
937974
*/
938975
char const * cson_string_cstr( cson_string const * str );
@@ -1261,11 +1298,11 @@
12611298
void cson_free_array(cson_array *x);
12621299
12631300
/**
12641301
Equivalent to cson_value_free(cson_string_value(x)).
12651302
*/
1266
-void cson_free_string(cson_string const *x);
1303
+void cson_free_string(cson_string *x);
12671304
12681305
12691306
/**
12701307
Allocates a new "array" value and transfers ownership of it to the
12711308
caller. It must eventually be destroyed, by the caller or its
@@ -2037,14 +2074,14 @@
20372074
20382075
/**
20392076
Deeply copies a JSON value, be it an object/array or a "plain"
20402077
value (e.g. number/string/boolean). If cv is not NULL then this
20412078
function makes a deep clone of it and returns that clone. Ownership
2042
- of the clone is transfered to the caller, who must eventually free
2043
- the value using cson_value_free() or add it to a container
2044
- object/array to transfer ownership to the container. The returned
2045
- object will be of the same logical type as orig.
2079
+ of the clone is identical t transfered to the caller, who must
2080
+ eventually free the value using cson_value_free() or add it to a
2081
+ container object/array to transfer ownership to the container. The
2082
+ returned object will be of the same logical type as orig.
20462083
20472084
ACHTUNG: if orig contains any cyclic references at any depth level
20482085
this function will endlessly recurse. (Having _any_ cyclic
20492086
references violates this library's requirements.)
20502087
@@ -2051,10 +2088,36 @@
20512088
Returns NULL if orig is NULL or if cloning fails. Assuming that
20522089
orig is in a valid state, the only "likely" error case is that an
20532090
allocation fails while constructing the clone. In other words, if
20542091
cloning fails due to something other than an allocation error then
20552092
either orig is in an invalid state or there is a bug.
2093
+
2094
+ When this function clones Objects or Arrays it shares any immutable
2095
+ values (including object keys) between the parent and the
2096
+ clone. Mutable values (Objects and Arrays) are copied, however.
2097
+ For example, if we clone:
2098
+
2099
+ @code
2100
+ { a: 1, b: 2, c:["hi"] }
2101
+ @endcode
2102
+
2103
+ The cloned object and the array "c" would be a new Object/Array
2104
+ instances but the object keys (a,b,b) and the values of (a,b), as
2105
+ well as the string value within the "c" array, would be shared
2106
+ between the original and the clone. The "c" array itself would be
2107
+ deeply cloned, such that future changes to the clone are not
2108
+ visible to the parent, and vice versa, but immutable values within
2109
+ the array are shared (in this case the string "hi"). The
2110
+ justification for this heuristic is that immutable values can never
2111
+ be changed, so there is no harm in sharing them across
2112
+ clones. Additionally, such types can never contribute to cycles in
2113
+ a JSON tree, so they are safe to share this way. Objects and
2114
+ Arrays, on the other hand, can be modified later and can contribute
2115
+ to cycles, and thus the clone needs to be an independent instance.
2116
+ Note, however, that if this function directly passed a
2117
+ non-Object/Array, that value is deeply cloned. The sharing
2118
+ behaviour only applies when traversing Objects/Arrays.
20562119
*/
20572120
cson_value * cson_value_clone( cson_value const * orig );
20582121
20592122
/**
20602123
Returns the value handle associated with s. The handle itself owns
@@ -2062,11 +2125,12 @@
20622125
function. If the returned handle is part of a container, calling
20632126
cson_value_free() on the returned handle invoked undefined
20642127
behaviour (quite possibly downstream when the container tries to
20652128
use it).
20662129
2067
- This function only returns NULL if s. is NULL.
2130
+ This function only returns NULL if s is NULL. The length of the
2131
+ returned string is cson_string_length_bytes().
20682132
*/
20692133
cson_value * cson_string_value(cson_string const * s);
20702134
/**
20712135
The Object form of cson_string_value(). See that function
20722136
for full details.
@@ -2079,19 +2143,20 @@
20792143
*/
20802144
cson_value * cson_array_value(cson_array const * s);
20812145
20822146
20832147
/**
2084
- Calculates the in-memory-allocated size of v, recursively if it is
2085
- a container type, with the following caveats and limitations:
2086
-
2087
- If a given value is reference counted and multiple times within a
2088
- traversed container, each reference is counted at full cost. We
2089
- have no what of knowing if a given reference has been visited
2090
- already and whether it should or should not be counted, so we
2091
- pessimistically count them even though the _might_ not really count
2092
- for the given object tree (it depends on where the other open
2148
+ Calculates the approximate in-memory-allocated size of v,
2149
+ recursively if it is a container type, with the following caveats
2150
+ and limitations:
2151
+
2152
+ If a given value is reference counted then it is only and multiple
2153
+ times within a traversed container, each reference is counted at
2154
+ full cost. We have no way of knowing if a given reference has been
2155
+ visited already and whether it should or should not be counted, so
2156
+ we pessimistically count them even though the _might_ not really
2157
+ count for the given object tree (it depends on where the other open
20932158
references live).
20942159
20952160
This function returns 0 if any of the following are true:
20962161
20972162
- v is NULL
@@ -2429,13 +2494,32 @@
24292494
takes SQL instead of a sqlite3_stmt object. It has the same
24302495
return value and argument semantics as that function.
24312496
*/
24322497
int cson_sqlite3_sql_to_json( sqlite3 * db, cson_value ** tgt, char const * sql, char fat );
24332498
2499
+/**
2500
+ Binds a JSON value to a 1-based parameter index in a prepared SQL
2501
+ statement. v must be NULL or one of one of the types (null, string,
2502
+ integer, double, boolean, array). Booleans are bound as integer 0
2503
+ or 1. NULL or null are bound as SQL NULL. Integers are bound as
2504
+ 64-bit ints. Strings are bound using sqlite3_bind_text() (as
2505
+ opposed to text16), but we could/should arguably bind them as
2506
+ blobs.
2507
+
2508
+ If v is an Array then ndx is is used as a starting position
2509
+ (1-based) and each item in the array is bound to the next parameter
2510
+ position (starting and ndx, though the array uses 0-based offsets).
2511
+
2512
+ TODO: add Object support for named parameters.
2513
+
2514
+ Returns 0 on success, non-0 on error.
2515
+ */
2516
+int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v );
2517
+
24342518
#if defined(__cplusplus)
24352519
} /*extern "C"*/
24362520
#endif
24372521
24382522
#endif /* CSON_ENABLE_SQLITE3 */
24392523
#endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */
24402524
/* end file include/wh/cson/cson_sqlite3.h */
24412525
#endif /* FOSSIL_ENABLE_JSON */
24422526
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -74,10 +74,46 @@
74 #else
75 typedef double cson_double_t;
76 #define CSON_DOUBLE_T_SFMT "f"
77 #define CSON_DOUBLE_T_PFMT "f"
78 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
80 /** @def CSON_INT_T_SFMT
81
82 scanf()-compatible format token for cson_int_t.
83 */
@@ -928,11 +964,12 @@
928 /**
929 Returns a pointer to the NULL-terminated string bytes of str.
930 The bytes are owned by string and will be invalided when it
931 is cleaned up.
932
933 If str is NULL then NULL is returned.
 
934
935 @see cson_string_length_bytes()
936 @see cson_value_get_string()
937 */
938 char const * cson_string_cstr( cson_string const * str );
@@ -1261,11 +1298,11 @@
1261 void cson_free_array(cson_array *x);
1262
1263 /**
1264 Equivalent to cson_value_free(cson_string_value(x)).
1265 */
1266 void cson_free_string(cson_string const *x);
1267
1268
1269 /**
1270 Allocates a new "array" value and transfers ownership of it to the
1271 caller. It must eventually be destroyed, by the caller or its
@@ -2037,14 +2074,14 @@
2037
2038 /**
2039 Deeply copies a JSON value, be it an object/array or a "plain"
2040 value (e.g. number/string/boolean). If cv is not NULL then this
2041 function makes a deep clone of it and returns that clone. Ownership
2042 of the clone is transfered to the caller, who must eventually free
2043 the value using cson_value_free() or add it to a container
2044 object/array to transfer ownership to the container. The returned
2045 object will be of the same logical type as orig.
2046
2047 ACHTUNG: if orig contains any cyclic references at any depth level
2048 this function will endlessly recurse. (Having _any_ cyclic
2049 references violates this library's requirements.)
2050
@@ -2051,10 +2088,36 @@
2051 Returns NULL if orig is NULL or if cloning fails. Assuming that
2052 orig is in a valid state, the only "likely" error case is that an
2053 allocation fails while constructing the clone. In other words, if
2054 cloning fails due to something other than an allocation error then
2055 either orig is in an invalid state or there is a bug.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2056 */
2057 cson_value * cson_value_clone( cson_value const * orig );
2058
2059 /**
2060 Returns the value handle associated with s. The handle itself owns
@@ -2062,11 +2125,12 @@
2062 function. If the returned handle is part of a container, calling
2063 cson_value_free() on the returned handle invoked undefined
2064 behaviour (quite possibly downstream when the container tries to
2065 use it).
2066
2067 This function only returns NULL if s. is NULL.
 
2068 */
2069 cson_value * cson_string_value(cson_string const * s);
2070 /**
2071 The Object form of cson_string_value(). See that function
2072 for full details.
@@ -2079,19 +2143,20 @@
2079 */
2080 cson_value * cson_array_value(cson_array const * s);
2081
2082
2083 /**
2084 Calculates the in-memory-allocated size of v, recursively if it is
2085 a container type, with the following caveats and limitations:
2086
2087 If a given value is reference counted and multiple times within a
2088 traversed container, each reference is counted at full cost. We
2089 have no what of knowing if a given reference has been visited
2090 already and whether it should or should not be counted, so we
2091 pessimistically count them even though the _might_ not really count
2092 for the given object tree (it depends on where the other open
 
2093 references live).
2094
2095 This function returns 0 if any of the following are true:
2096
2097 - v is NULL
@@ -2429,13 +2494,32 @@
2429 takes SQL instead of a sqlite3_stmt object. It has the same
2430 return value and argument semantics as that function.
2431 */
2432 int cson_sqlite3_sql_to_json( sqlite3 * db, cson_value ** tgt, char const * sql, char fat );
2433
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2434 #if defined(__cplusplus)
2435 } /*extern "C"*/
2436 #endif
2437
2438 #endif /* CSON_ENABLE_SQLITE3 */
2439 #endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */
2440 /* end file include/wh/cson/cson_sqlite3.h */
2441 #endif /* FOSSIL_ENABLE_JSON */
2442
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -74,10 +74,46 @@
74 #else
75 typedef double cson_double_t;
76 #define CSON_DOUBLE_T_SFMT "f"
77 #define CSON_DOUBLE_T_PFMT "f"
78 #endif
79
80 /** @def CSON_VOID_PTR_IS_BIG
81
82 ONLY define this to a true value if you know that
83
84 (sizeof(cson_int_t) <= sizeof(void*))
85
86 If that is the case, cson does not need to dynamically
87 allocate integers. However, enabling this may cause
88 compilation warnings in 32-bit builds even though the code
89 being warned about cannot ever be called. To get around such
90 warnings, when building on a 64-bit environment you can define
91 this to 1 to get "big" integer support. HOWEVER, all clients must
92 also use the same value for this macro. If i knew a halfway reliable
93 way to determine this automatically at preprocessor-time, i would
94 automate this. We might be able to do halfway reliably by looking
95 for a large INT_MAX value?
96 */
97 #if !defined(CSON_VOID_PTR_IS_BIG)
98
99 /* Largely taken from http://predef.sourceforge.net/prearch.html
100
101 See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h
102 */
103 # if defined(_WIN64) || defined(__LP64__)/*gcc*/ \
104 || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \
105 || defined(__x86_64__) || defined(__x86_64) \
106 || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \
107 || defined(_M_IA64) \
108 || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \
109 || defined(__64BIT__)
110 # define CSON_VOID_PTR_IS_BIG 1
111 # else
112 # define CSON_VOID_PTR_IS_BIG 0
113 # endif
114 #endif
115
116 /** @def CSON_INT_T_SFMT
117
118 scanf()-compatible format token for cson_int_t.
119 */
@@ -928,11 +964,12 @@
964 /**
965 Returns a pointer to the NULL-terminated string bytes of str.
966 The bytes are owned by string and will be invalided when it
967 is cleaned up.
968
969 If str is NULL then NULL is returned. If the string has a length
970 of 0 then "" is returned.
971
972 @see cson_string_length_bytes()
973 @see cson_value_get_string()
974 */
975 char const * cson_string_cstr( cson_string const * str );
@@ -1261,11 +1298,11 @@
1298 void cson_free_array(cson_array *x);
1299
1300 /**
1301 Equivalent to cson_value_free(cson_string_value(x)).
1302 */
1303 void cson_free_string(cson_string *x);
1304
1305
1306 /**
1307 Allocates a new "array" value and transfers ownership of it to the
1308 caller. It must eventually be destroyed, by the caller or its
@@ -2037,14 +2074,14 @@
2074
2075 /**
2076 Deeply copies a JSON value, be it an object/array or a "plain"
2077 value (e.g. number/string/boolean). If cv is not NULL then this
2078 function makes a deep clone of it and returns that clone. Ownership
2079 of the clone is identical t transfered to the caller, who must
2080 eventually free the value using cson_value_free() or add it to a
2081 container object/array to transfer ownership to the container. The
2082 returned object will be of the same logical type as orig.
2083
2084 ACHTUNG: if orig contains any cyclic references at any depth level
2085 this function will endlessly recurse. (Having _any_ cyclic
2086 references violates this library's requirements.)
2087
@@ -2051,10 +2088,36 @@
2088 Returns NULL if orig is NULL or if cloning fails. Assuming that
2089 orig is in a valid state, the only "likely" error case is that an
2090 allocation fails while constructing the clone. In other words, if
2091 cloning fails due to something other than an allocation error then
2092 either orig is in an invalid state or there is a bug.
2093
2094 When this function clones Objects or Arrays it shares any immutable
2095 values (including object keys) between the parent and the
2096 clone. Mutable values (Objects and Arrays) are copied, however.
2097 For example, if we clone:
2098
2099 @code
2100 { a: 1, b: 2, c:["hi"] }
2101 @endcode
2102
2103 The cloned object and the array "c" would be a new Object/Array
2104 instances but the object keys (a,b,b) and the values of (a,b), as
2105 well as the string value within the "c" array, would be shared
2106 between the original and the clone. The "c" array itself would be
2107 deeply cloned, such that future changes to the clone are not
2108 visible to the parent, and vice versa, but immutable values within
2109 the array are shared (in this case the string "hi"). The
2110 justification for this heuristic is that immutable values can never
2111 be changed, so there is no harm in sharing them across
2112 clones. Additionally, such types can never contribute to cycles in
2113 a JSON tree, so they are safe to share this way. Objects and
2114 Arrays, on the other hand, can be modified later and can contribute
2115 to cycles, and thus the clone needs to be an independent instance.
2116 Note, however, that if this function directly passed a
2117 non-Object/Array, that value is deeply cloned. The sharing
2118 behaviour only applies when traversing Objects/Arrays.
2119 */
2120 cson_value * cson_value_clone( cson_value const * orig );
2121
2122 /**
2123 Returns the value handle associated with s. The handle itself owns
@@ -2062,11 +2125,12 @@
2125 function. If the returned handle is part of a container, calling
2126 cson_value_free() on the returned handle invoked undefined
2127 behaviour (quite possibly downstream when the container tries to
2128 use it).
2129
2130 This function only returns NULL if s is NULL. The length of the
2131 returned string is cson_string_length_bytes().
2132 */
2133 cson_value * cson_string_value(cson_string const * s);
2134 /**
2135 The Object form of cson_string_value(). See that function
2136 for full details.
@@ -2079,19 +2143,20 @@
2143 */
2144 cson_value * cson_array_value(cson_array const * s);
2145
2146
2147 /**
2148 Calculates the approximate in-memory-allocated size of v,
2149 recursively if it is a container type, with the following caveats
2150 and limitations:
2151
2152 If a given value is reference counted then it is only and multiple
2153 times within a traversed container, each reference is counted at
2154 full cost. We have no way of knowing if a given reference has been
2155 visited already and whether it should or should not be counted, so
2156 we pessimistically count them even though the _might_ not really
2157 count for the given object tree (it depends on where the other open
2158 references live).
2159
2160 This function returns 0 if any of the following are true:
2161
2162 - v is NULL
@@ -2429,13 +2494,32 @@
2494 takes SQL instead of a sqlite3_stmt object. It has the same
2495 return value and argument semantics as that function.
2496 */
2497 int cson_sqlite3_sql_to_json( sqlite3 * db, cson_value ** tgt, char const * sql, char fat );
2498
2499 /**
2500 Binds a JSON value to a 1-based parameter index in a prepared SQL
2501 statement. v must be NULL or one of one of the types (null, string,
2502 integer, double, boolean, array). Booleans are bound as integer 0
2503 or 1. NULL or null are bound as SQL NULL. Integers are bound as
2504 64-bit ints. Strings are bound using sqlite3_bind_text() (as
2505 opposed to text16), but we could/should arguably bind them as
2506 blobs.
2507
2508 If v is an Array then ndx is is used as a starting position
2509 (1-based) and each item in the array is bound to the next parameter
2510 position (starting and ndx, though the array uses 0-based offsets).
2511
2512 TODO: add Object support for named parameters.
2513
2514 Returns 0 on success, non-0 on error.
2515 */
2516 int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v );
2517
2518 #if defined(__cplusplus)
2519 } /*extern "C"*/
2520 #endif
2521
2522 #endif /* CSON_ENABLE_SQLITE3 */
2523 #endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */
2524 /* end file include/wh/cson/cson_sqlite3.h */
2525 #endif /* FOSSIL_ENABLE_JSON */
2526
+7 -4
--- src/db.c
+++ src/db.c
@@ -1035,11 +1035,11 @@
10351035
}
10361036
if( db_open_local()==0 ){
10371037
fossil_fatal("not in a local checkout");
10381038
return;
10391039
}
1040
- file_canonical_name(g.argv[2], &repo);
1040
+ file_canonical_name(g.argv[2], &repo, 0);
10411041
zRepo = blob_str(&repo);
10421042
if( file_access(zRepo, 0) ){
10431043
fossil_fatal("no such file: %s", zRepo);
10441044
}
10451045
db_open_or_attach(zRepo, "test_repo");
@@ -1698,23 +1698,26 @@
16981698
Blob full;
16991699
if( zName==0 ){
17001700
if( !g.localOpen ) return;
17011701
zName = db_repository_filename();
17021702
}
1703
- file_canonical_name(zName, &full);
1703
+ file_canonical_name(zName, &full, 0);
17041704
db_swap_connections();
17051705
db_multi_exec(
17061706
"INSERT OR IGNORE INTO global_config(name,value)"
17071707
"VALUES('repo:%q',1)",
17081708
blob_str(&full)
17091709
);
17101710
if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
1711
+ Blob localRoot;
1712
+ file_canonical_name(g.zLocalRoot, &localRoot, 1);
17111713
db_multi_exec(
17121714
"REPLACE INTO global_config(name, value)"
17131715
"VALUES('ckout:%q','%q');",
1714
- g.zLocalRoot, blob_str(&full)
1716
+ blob_str(&localRoot), blob_str(&full)
17151717
);
1718
+ blob_reset(&localRoot);
17161719
}
17171720
db_swap_connections();
17181721
blob_reset(&full);
17191722
}
17201723
@@ -1749,11 +1752,11 @@
17491752
usage("REPOSITORY-FILENAME ?VERSION?");
17501753
}
17511754
if( !allowNested && db_open_local() ){
17521755
fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
17531756
}
1754
- file_canonical_name(g.argv[2], &path);
1757
+ file_canonical_name(g.argv[2], &path, 0);
17551758
db_open_repository(blob_str(&path));
17561759
db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
17571760
db_delete_on_failure("./_FOSSIL_");
17581761
db_open_local();
17591762
db_lset("repository", g.argv[2]);
17601763
--- src/db.c
+++ src/db.c
@@ -1035,11 +1035,11 @@
1035 }
1036 if( db_open_local()==0 ){
1037 fossil_fatal("not in a local checkout");
1038 return;
1039 }
1040 file_canonical_name(g.argv[2], &repo);
1041 zRepo = blob_str(&repo);
1042 if( file_access(zRepo, 0) ){
1043 fossil_fatal("no such file: %s", zRepo);
1044 }
1045 db_open_or_attach(zRepo, "test_repo");
@@ -1698,23 +1698,26 @@
1698 Blob full;
1699 if( zName==0 ){
1700 if( !g.localOpen ) return;
1701 zName = db_repository_filename();
1702 }
1703 file_canonical_name(zName, &full);
1704 db_swap_connections();
1705 db_multi_exec(
1706 "INSERT OR IGNORE INTO global_config(name,value)"
1707 "VALUES('repo:%q',1)",
1708 blob_str(&full)
1709 );
1710 if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
 
 
1711 db_multi_exec(
1712 "REPLACE INTO global_config(name, value)"
1713 "VALUES('ckout:%q','%q');",
1714 g.zLocalRoot, blob_str(&full)
1715 );
 
1716 }
1717 db_swap_connections();
1718 blob_reset(&full);
1719 }
1720
@@ -1749,11 +1752,11 @@
1749 usage("REPOSITORY-FILENAME ?VERSION?");
1750 }
1751 if( !allowNested && db_open_local() ){
1752 fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
1753 }
1754 file_canonical_name(g.argv[2], &path);
1755 db_open_repository(blob_str(&path));
1756 db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
1757 db_delete_on_failure("./_FOSSIL_");
1758 db_open_local();
1759 db_lset("repository", g.argv[2]);
1760
--- src/db.c
+++ src/db.c
@@ -1035,11 +1035,11 @@
1035 }
1036 if( db_open_local()==0 ){
1037 fossil_fatal("not in a local checkout");
1038 return;
1039 }
1040 file_canonical_name(g.argv[2], &repo, 0);
1041 zRepo = blob_str(&repo);
1042 if( file_access(zRepo, 0) ){
1043 fossil_fatal("no such file: %s", zRepo);
1044 }
1045 db_open_or_attach(zRepo, "test_repo");
@@ -1698,23 +1698,26 @@
1698 Blob full;
1699 if( zName==0 ){
1700 if( !g.localOpen ) return;
1701 zName = db_repository_filename();
1702 }
1703 file_canonical_name(zName, &full, 0);
1704 db_swap_connections();
1705 db_multi_exec(
1706 "INSERT OR IGNORE INTO global_config(name,value)"
1707 "VALUES('repo:%q',1)",
1708 blob_str(&full)
1709 );
1710 if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
1711 Blob localRoot;
1712 file_canonical_name(g.zLocalRoot, &localRoot, 1);
1713 db_multi_exec(
1714 "REPLACE INTO global_config(name, value)"
1715 "VALUES('ckout:%q','%q');",
1716 blob_str(&localRoot), blob_str(&full)
1717 );
1718 blob_reset(&localRoot);
1719 }
1720 db_swap_connections();
1721 blob_reset(&full);
1722 }
1723
@@ -1749,11 +1752,11 @@
1752 usage("REPOSITORY-FILENAME ?VERSION?");
1753 }
1754 if( !allowNested && db_open_local() ){
1755 fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
1756 }
1757 file_canonical_name(g.argv[2], &path, 0);
1758 db_open_repository(blob_str(&path));
1759 db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
1760 db_delete_on_failure("./_FOSSIL_");
1761 db_open_local();
1762 db_lset("repository", g.argv[2]);
1763
+7 -4
--- src/db.c
+++ src/db.c
@@ -1035,11 +1035,11 @@
10351035
}
10361036
if( db_open_local()==0 ){
10371037
fossil_fatal("not in a local checkout");
10381038
return;
10391039
}
1040
- file_canonical_name(g.argv[2], &repo);
1040
+ file_canonical_name(g.argv[2], &repo, 0);
10411041
zRepo = blob_str(&repo);
10421042
if( file_access(zRepo, 0) ){
10431043
fossil_fatal("no such file: %s", zRepo);
10441044
}
10451045
db_open_or_attach(zRepo, "test_repo");
@@ -1698,23 +1698,26 @@
16981698
Blob full;
16991699
if( zName==0 ){
17001700
if( !g.localOpen ) return;
17011701
zName = db_repository_filename();
17021702
}
1703
- file_canonical_name(zName, &full);
1703
+ file_canonical_name(zName, &full, 0);
17041704
db_swap_connections();
17051705
db_multi_exec(
17061706
"INSERT OR IGNORE INTO global_config(name,value)"
17071707
"VALUES('repo:%q',1)",
17081708
blob_str(&full)
17091709
);
17101710
if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
1711
+ Blob localRoot;
1712
+ file_canonical_name(g.zLocalRoot, &localRoot, 1);
17111713
db_multi_exec(
17121714
"REPLACE INTO global_config(name, value)"
17131715
"VALUES('ckout:%q','%q');",
1714
- g.zLocalRoot, blob_str(&full)
1716
+ blob_str(&localRoot), blob_str(&full)
17151717
);
1718
+ blob_reset(&localRoot);
17161719
}
17171720
db_swap_connections();
17181721
blob_reset(&full);
17191722
}
17201723
@@ -1749,11 +1752,11 @@
17491752
usage("REPOSITORY-FILENAME ?VERSION?");
17501753
}
17511754
if( !allowNested && db_open_local() ){
17521755
fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
17531756
}
1754
- file_canonical_name(g.argv[2], &path);
1757
+ file_canonical_name(g.argv[2], &path, 0);
17551758
db_open_repository(blob_str(&path));
17561759
db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
17571760
db_delete_on_failure("./_FOSSIL_");
17581761
db_open_local();
17591762
db_lset("repository", g.argv[2]);
17601763
--- src/db.c
+++ src/db.c
@@ -1035,11 +1035,11 @@
1035 }
1036 if( db_open_local()==0 ){
1037 fossil_fatal("not in a local checkout");
1038 return;
1039 }
1040 file_canonical_name(g.argv[2], &repo);
1041 zRepo = blob_str(&repo);
1042 if( file_access(zRepo, 0) ){
1043 fossil_fatal("no such file: %s", zRepo);
1044 }
1045 db_open_or_attach(zRepo, "test_repo");
@@ -1698,23 +1698,26 @@
1698 Blob full;
1699 if( zName==0 ){
1700 if( !g.localOpen ) return;
1701 zName = db_repository_filename();
1702 }
1703 file_canonical_name(zName, &full);
1704 db_swap_connections();
1705 db_multi_exec(
1706 "INSERT OR IGNORE INTO global_config(name,value)"
1707 "VALUES('repo:%q',1)",
1708 blob_str(&full)
1709 );
1710 if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
 
 
1711 db_multi_exec(
1712 "REPLACE INTO global_config(name, value)"
1713 "VALUES('ckout:%q','%q');",
1714 g.zLocalRoot, blob_str(&full)
1715 );
 
1716 }
1717 db_swap_connections();
1718 blob_reset(&full);
1719 }
1720
@@ -1749,11 +1752,11 @@
1749 usage("REPOSITORY-FILENAME ?VERSION?");
1750 }
1751 if( !allowNested && db_open_local() ){
1752 fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
1753 }
1754 file_canonical_name(g.argv[2], &path);
1755 db_open_repository(blob_str(&path));
1756 db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
1757 db_delete_on_failure("./_FOSSIL_");
1758 db_open_local();
1759 db_lset("repository", g.argv[2]);
1760
--- src/db.c
+++ src/db.c
@@ -1035,11 +1035,11 @@
1035 }
1036 if( db_open_local()==0 ){
1037 fossil_fatal("not in a local checkout");
1038 return;
1039 }
1040 file_canonical_name(g.argv[2], &repo, 0);
1041 zRepo = blob_str(&repo);
1042 if( file_access(zRepo, 0) ){
1043 fossil_fatal("no such file: %s", zRepo);
1044 }
1045 db_open_or_attach(zRepo, "test_repo");
@@ -1698,23 +1698,26 @@
1698 Blob full;
1699 if( zName==0 ){
1700 if( !g.localOpen ) return;
1701 zName = db_repository_filename();
1702 }
1703 file_canonical_name(zName, &full, 0);
1704 db_swap_connections();
1705 db_multi_exec(
1706 "INSERT OR IGNORE INTO global_config(name,value)"
1707 "VALUES('repo:%q',1)",
1708 blob_str(&full)
1709 );
1710 if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
1711 Blob localRoot;
1712 file_canonical_name(g.zLocalRoot, &localRoot, 1);
1713 db_multi_exec(
1714 "REPLACE INTO global_config(name, value)"
1715 "VALUES('ckout:%q','%q');",
1716 blob_str(&localRoot), blob_str(&full)
1717 );
1718 blob_reset(&localRoot);
1719 }
1720 db_swap_connections();
1721 blob_reset(&full);
1722 }
1723
@@ -1749,11 +1752,11 @@
1752 usage("REPOSITORY-FILENAME ?VERSION?");
1753 }
1754 if( !allowNested && db_open_local() ){
1755 fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
1756 }
1757 file_canonical_name(g.argv[2], &path, 0);
1758 db_open_repository(blob_str(&path));
1759 db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
1760 db_delete_on_failure("./_FOSSIL_");
1761 db_open_local();
1762 db_lset("repository", g.argv[2]);
1763
+2
--- src/diff.c
+++ src/diff.c
@@ -727,10 +727,11 @@
727727
while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
728728
if( nA>250 ) nA = 250;
729729
if( nB>250 ) nB = 250;
730730
avg = (nA+nB)/2;
731731
if( avg==0 ) return 0;
732
+ if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
732733
memset(aFirst, 0, sizeof(aFirst));
733734
zA--; zB--; /* Make both zA[] and zB[] 1-indexed */
734735
for(i=nB; i>0; i--){
735736
c = (unsigned char)zB[i];
736737
aNext[i] = aFirst[c];
@@ -886,10 +887,11 @@
886887
int m, ma, mb;/* Number of lines to output */
887888
int skip; /* Number of lines to skip */
888889
int nChunk = 0; /* Number of chunks of diff output seen so far */
889890
SbsLine s; /* Output line buffer */
890891
892
+ memset(&s, 0, sizeof(s));
891893
s.zLine = fossil_malloc( 10*width + 200 );
892894
if( s.zLine==0 ) return;
893895
s.width = width;
894896
s.escHtml = escHtml;
895897
s.iStart = -1;
896898
--- src/diff.c
+++ src/diff.c
@@ -727,10 +727,11 @@
727 while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
728 if( nA>250 ) nA = 250;
729 if( nB>250 ) nB = 250;
730 avg = (nA+nB)/2;
731 if( avg==0 ) return 0;
 
732 memset(aFirst, 0, sizeof(aFirst));
733 zA--; zB--; /* Make both zA[] and zB[] 1-indexed */
734 for(i=nB; i>0; i--){
735 c = (unsigned char)zB[i];
736 aNext[i] = aFirst[c];
@@ -886,10 +887,11 @@
886 int m, ma, mb;/* Number of lines to output */
887 int skip; /* Number of lines to skip */
888 int nChunk = 0; /* Number of chunks of diff output seen so far */
889 SbsLine s; /* Output line buffer */
890
 
891 s.zLine = fossil_malloc( 10*width + 200 );
892 if( s.zLine==0 ) return;
893 s.width = width;
894 s.escHtml = escHtml;
895 s.iStart = -1;
896
--- src/diff.c
+++ src/diff.c
@@ -727,10 +727,11 @@
727 while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
728 if( nA>250 ) nA = 250;
729 if( nB>250 ) nB = 250;
730 avg = (nA+nB)/2;
731 if( avg==0 ) return 0;
732 if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
733 memset(aFirst, 0, sizeof(aFirst));
734 zA--; zB--; /* Make both zA[] and zB[] 1-indexed */
735 for(i=nB; i>0; i--){
736 c = (unsigned char)zB[i];
737 aNext[i] = aFirst[c];
@@ -886,10 +887,11 @@
887 int m, ma, mb;/* Number of lines to output */
888 int skip; /* Number of lines to skip */
889 int nChunk = 0; /* Number of chunks of diff output seen so far */
890 SbsLine s; /* Output line buffer */
891
892 memset(&s, 0, sizeof(s));
893 s.zLine = fossil_malloc( 10*width + 200 );
894 if( s.zLine==0 ) return;
895 s.width = width;
896 s.escHtml = escHtml;
897 s.iStart = -1;
898
+2
--- src/diff.c
+++ src/diff.c
@@ -727,10 +727,11 @@
727727
while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
728728
if( nA>250 ) nA = 250;
729729
if( nB>250 ) nB = 250;
730730
avg = (nA+nB)/2;
731731
if( avg==0 ) return 0;
732
+ if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
732733
memset(aFirst, 0, sizeof(aFirst));
733734
zA--; zB--; /* Make both zA[] and zB[] 1-indexed */
734735
for(i=nB; i>0; i--){
735736
c = (unsigned char)zB[i];
736737
aNext[i] = aFirst[c];
@@ -886,10 +887,11 @@
886887
int m, ma, mb;/* Number of lines to output */
887888
int skip; /* Number of lines to skip */
888889
int nChunk = 0; /* Number of chunks of diff output seen so far */
889890
SbsLine s; /* Output line buffer */
890891
892
+ memset(&s, 0, sizeof(s));
891893
s.zLine = fossil_malloc( 10*width + 200 );
892894
if( s.zLine==0 ) return;
893895
s.width = width;
894896
s.escHtml = escHtml;
895897
s.iStart = -1;
896898
--- src/diff.c
+++ src/diff.c
@@ -727,10 +727,11 @@
727 while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
728 if( nA>250 ) nA = 250;
729 if( nB>250 ) nB = 250;
730 avg = (nA+nB)/2;
731 if( avg==0 ) return 0;
 
732 memset(aFirst, 0, sizeof(aFirst));
733 zA--; zB--; /* Make both zA[] and zB[] 1-indexed */
734 for(i=nB; i>0; i--){
735 c = (unsigned char)zB[i];
736 aNext[i] = aFirst[c];
@@ -886,10 +887,11 @@
886 int m, ma, mb;/* Number of lines to output */
887 int skip; /* Number of lines to skip */
888 int nChunk = 0; /* Number of chunks of diff output seen so far */
889 SbsLine s; /* Output line buffer */
890
 
891 s.zLine = fossil_malloc( 10*width + 200 );
892 if( s.zLine==0 ) return;
893 s.width = width;
894 s.escHtml = escHtml;
895 s.iStart = -1;
896
--- src/diff.c
+++ src/diff.c
@@ -727,10 +727,11 @@
727 while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
728 if( nA>250 ) nA = 250;
729 if( nB>250 ) nB = 250;
730 avg = (nA+nB)/2;
731 if( avg==0 ) return 0;
732 if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
733 memset(aFirst, 0, sizeof(aFirst));
734 zA--; zB--; /* Make both zA[] and zB[] 1-indexed */
735 for(i=nB; i>0; i--){
736 c = (unsigned char)zB[i];
737 aNext[i] = aFirst[c];
@@ -886,10 +887,11 @@
887 int m, ma, mb;/* Number of lines to output */
888 int skip; /* Number of lines to skip */
889 int nChunk = 0; /* Number of chunks of diff output seen so far */
890 SbsLine s; /* Output line buffer */
891
892 memset(&s, 0, sizeof(s));
893 s.zLine = fossil_malloc( 10*width + 200 );
894 if( s.zLine==0 ) return;
895 s.width = width;
896 s.escHtml = escHtml;
897 s.iStart = -1;
898
+11 -2
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -19,10 +19,19 @@
1919
*/
2020
#include "config.h"
2121
#include "diffcmd.h"
2222
#include <assert.h>
2323
24
+/*
25
+** Use the right null device for the platform.
26
+*/
27
+#if defined(_WIN32)
28
+# define NULL_DEVICE "NUL"
29
+#else
30
+# define NULL_DEVICE "/dev/null"
31
+#endif
32
+
2433
/*
2534
** Print the "Index:" message that patches wants to see at the top of a diff.
2635
*/
2736
void diff_print_index(const char *zFile, int diffFlags){
2837
if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
@@ -83,11 +92,11 @@
8392
const char *zName2; /* Name of zFile2 for display */
8493
8594
/* Read content of zFile2 into memory */
8695
blob_zero(&file2);
8796
if( file_wd_size(zFile2)<0 ){
88
- zName2 = "/dev/null";
97
+ zName2 = NULL_DEVICE;
8998
}else{
9099
if( file_wd_islink(zFile2) ){
91100
blob_read_link(&file2, zFile2);
92101
}else{
93102
blob_read_from_file(&file2, zFile2);
@@ -290,11 +299,11 @@
290299
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
291300
char *zToFree = zFullName;
292301
int showDiff = 1;
293302
if( isDeleted ){
294303
fossil_print("DELETED %s\n", zPathname);
295
- if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
304
+ if( !asNewFile ){ showDiff = 0; zFullName = NULL_DEVICE; }
296305
}else if( file_access(zFullName, 0) ){
297306
fossil_print("MISSING %s\n", zPathname);
298307
if( !asNewFile ){ showDiff = 0; }
299308
}else if( isNew ){
300309
fossil_print("ADDED %s\n", zPathname);
301310
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -19,10 +19,19 @@
19 */
20 #include "config.h"
21 #include "diffcmd.h"
22 #include <assert.h>
23
 
 
 
 
 
 
 
 
 
24 /*
25 ** Print the "Index:" message that patches wants to see at the top of a diff.
26 */
27 void diff_print_index(const char *zFile, int diffFlags){
28 if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
@@ -83,11 +92,11 @@
83 const char *zName2; /* Name of zFile2 for display */
84
85 /* Read content of zFile2 into memory */
86 blob_zero(&file2);
87 if( file_wd_size(zFile2)<0 ){
88 zName2 = "/dev/null";
89 }else{
90 if( file_wd_islink(zFile2) ){
91 blob_read_link(&file2, zFile2);
92 }else{
93 blob_read_from_file(&file2, zFile2);
@@ -290,11 +299,11 @@
290 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
291 char *zToFree = zFullName;
292 int showDiff = 1;
293 if( isDeleted ){
294 fossil_print("DELETED %s\n", zPathname);
295 if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
296 }else if( file_access(zFullName, 0) ){
297 fossil_print("MISSING %s\n", zPathname);
298 if( !asNewFile ){ showDiff = 0; }
299 }else if( isNew ){
300 fossil_print("ADDED %s\n", zPathname);
301
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -19,10 +19,19 @@
19 */
20 #include "config.h"
21 #include "diffcmd.h"
22 #include <assert.h>
23
24 /*
25 ** Use the right null device for the platform.
26 */
27 #if defined(_WIN32)
28 # define NULL_DEVICE "NUL"
29 #else
30 # define NULL_DEVICE "/dev/null"
31 #endif
32
33 /*
34 ** Print the "Index:" message that patches wants to see at the top of a diff.
35 */
36 void diff_print_index(const char *zFile, int diffFlags){
37 if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
@@ -83,11 +92,11 @@
92 const char *zName2; /* Name of zFile2 for display */
93
94 /* Read content of zFile2 into memory */
95 blob_zero(&file2);
96 if( file_wd_size(zFile2)<0 ){
97 zName2 = NULL_DEVICE;
98 }else{
99 if( file_wd_islink(zFile2) ){
100 blob_read_link(&file2, zFile2);
101 }else{
102 blob_read_from_file(&file2, zFile2);
@@ -290,11 +299,11 @@
299 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
300 char *zToFree = zFullName;
301 int showDiff = 1;
302 if( isDeleted ){
303 fossil_print("DELETED %s\n", zPathname);
304 if( !asNewFile ){ showDiff = 0; zFullName = NULL_DEVICE; }
305 }else if( file_access(zFullName, 0) ){
306 fossil_print("MISSING %s\n", zPathname);
307 if( !asNewFile ){ showDiff = 0; }
308 }else if( isNew ){
309 fossil_print("ADDED %s\n", zPathname);
310
+11 -2
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -19,10 +19,19 @@
1919
*/
2020
#include "config.h"
2121
#include "diffcmd.h"
2222
#include <assert.h>
2323
24
+/*
25
+** Use the right null device for the platform.
26
+*/
27
+#if defined(_WIN32)
28
+# define NULL_DEVICE "NUL"
29
+#else
30
+# define NULL_DEVICE "/dev/null"
31
+#endif
32
+
2433
/*
2534
** Print the "Index:" message that patches wants to see at the top of a diff.
2635
*/
2736
void diff_print_index(const char *zFile, int diffFlags){
2837
if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
@@ -83,11 +92,11 @@
8392
const char *zName2; /* Name of zFile2 for display */
8493
8594
/* Read content of zFile2 into memory */
8695
blob_zero(&file2);
8796
if( file_wd_size(zFile2)<0 ){
88
- zName2 = "/dev/null";
97
+ zName2 = NULL_DEVICE;
8998
}else{
9099
if( file_wd_islink(zFile2) ){
91100
blob_read_link(&file2, zFile2);
92101
}else{
93102
blob_read_from_file(&file2, zFile2);
@@ -290,11 +299,11 @@
290299
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
291300
char *zToFree = zFullName;
292301
int showDiff = 1;
293302
if( isDeleted ){
294303
fossil_print("DELETED %s\n", zPathname);
295
- if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
304
+ if( !asNewFile ){ showDiff = 0; zFullName = NULL_DEVICE; }
296305
}else if( file_access(zFullName, 0) ){
297306
fossil_print("MISSING %s\n", zPathname);
298307
if( !asNewFile ){ showDiff = 0; }
299308
}else if( isNew ){
300309
fossil_print("ADDED %s\n", zPathname);
301310
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -19,10 +19,19 @@
19 */
20 #include "config.h"
21 #include "diffcmd.h"
22 #include <assert.h>
23
 
 
 
 
 
 
 
 
 
24 /*
25 ** Print the "Index:" message that patches wants to see at the top of a diff.
26 */
27 void diff_print_index(const char *zFile, int diffFlags){
28 if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
@@ -83,11 +92,11 @@
83 const char *zName2; /* Name of zFile2 for display */
84
85 /* Read content of zFile2 into memory */
86 blob_zero(&file2);
87 if( file_wd_size(zFile2)<0 ){
88 zName2 = "/dev/null";
89 }else{
90 if( file_wd_islink(zFile2) ){
91 blob_read_link(&file2, zFile2);
92 }else{
93 blob_read_from_file(&file2, zFile2);
@@ -290,11 +299,11 @@
290 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
291 char *zToFree = zFullName;
292 int showDiff = 1;
293 if( isDeleted ){
294 fossil_print("DELETED %s\n", zPathname);
295 if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
296 }else if( file_access(zFullName, 0) ){
297 fossil_print("MISSING %s\n", zPathname);
298 if( !asNewFile ){ showDiff = 0; }
299 }else if( isNew ){
300 fossil_print("ADDED %s\n", zPathname);
301
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -19,10 +19,19 @@
19 */
20 #include "config.h"
21 #include "diffcmd.h"
22 #include <assert.h>
23
24 /*
25 ** Use the right null device for the platform.
26 */
27 #if defined(_WIN32)
28 # define NULL_DEVICE "NUL"
29 #else
30 # define NULL_DEVICE "/dev/null"
31 #endif
32
33 /*
34 ** Print the "Index:" message that patches wants to see at the top of a diff.
35 */
36 void diff_print_index(const char *zFile, int diffFlags){
37 if( (diffFlags & (DIFF_SIDEBYSIDE|DIFF_BRIEF))==0 ){
@@ -83,11 +92,11 @@
92 const char *zName2; /* Name of zFile2 for display */
93
94 /* Read content of zFile2 into memory */
95 blob_zero(&file2);
96 if( file_wd_size(zFile2)<0 ){
97 zName2 = NULL_DEVICE;
98 }else{
99 if( file_wd_islink(zFile2) ){
100 blob_read_link(&file2, zFile2);
101 }else{
102 blob_read_from_file(&file2, zFile2);
@@ -290,11 +299,11 @@
299 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
300 char *zToFree = zFullName;
301 int showDiff = 1;
302 if( isDeleted ){
303 fossil_print("DELETED %s\n", zPathname);
304 if( !asNewFile ){ showDiff = 0; zFullName = NULL_DEVICE; }
305 }else if( file_access(zFullName, 0) ){
306 fossil_print("MISSING %s\n", zPathname);
307 if( !asNewFile ){ showDiff = 0; }
308 }else if( isNew ){
309 fossil_print("ADDED %s\n", zPathname);
310
+33
--- src/doc.c
+++ src/doc.c
@@ -604,5 +604,38 @@
604604
}
605605
cgi_set_content_type(zMime);
606606
cgi_set_content(&logo);
607607
g.isConst = 1;
608608
}
609
+
610
+/*
611
+** The default background image: a 16x16 white GIF
612
+*/
613
+static const unsigned char aBackground[] = {
614
+ 71, 73, 70, 56, 57, 97, 16, 0, 16, 0,
615
+ 240, 0, 0, 255, 255, 255, 0, 0, 0, 33,
616
+ 254, 4, 119, 105, 115, 104, 0, 44, 0, 0,
617
+ 0, 0, 16, 0, 16, 0, 0, 2, 14, 132,
618
+ 143, 169, 203, 237, 15, 163, 156, 180, 218, 139,
619
+ 179, 62, 5, 0, 59,
620
+};
621
+
622
+
623
+/*
624
+** WEBPAGE: background
625
+**
626
+** Return the background image.
627
+*/
628
+void background_page(void){
629
+ Blob bgimg;
630
+ char *zMime;
631
+
632
+ zMime = db_get("background-mimetype", "image/gif");
633
+ blob_zero(&bgimg);
634
+ db_blob(&bgimg, "SELECT value FROM config WHERE name='background-image'");
635
+ if( blob_size(&bgimg)==0 ){
636
+ blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
637
+ }
638
+ cgi_set_content_type(zMime);
639
+ cgi_set_content(&bgimg);
640
+ g.isConst = 1;
641
+}
609642
--- src/doc.c
+++ src/doc.c
@@ -604,5 +604,38 @@
604 }
605 cgi_set_content_type(zMime);
606 cgi_set_content(&logo);
607 g.isConst = 1;
608 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
609
--- src/doc.c
+++ src/doc.c
@@ -604,5 +604,38 @@
604 }
605 cgi_set_content_type(zMime);
606 cgi_set_content(&logo);
607 g.isConst = 1;
608 }
609
610 /*
611 ** The default background image: a 16x16 white GIF
612 */
613 static const unsigned char aBackground[] = {
614 71, 73, 70, 56, 57, 97, 16, 0, 16, 0,
615 240, 0, 0, 255, 255, 255, 0, 0, 0, 33,
616 254, 4, 119, 105, 115, 104, 0, 44, 0, 0,
617 0, 0, 16, 0, 16, 0, 0, 2, 14, 132,
618 143, 169, 203, 237, 15, 163, 156, 180, 218, 139,
619 179, 62, 5, 0, 59,
620 };
621
622
623 /*
624 ** WEBPAGE: background
625 **
626 ** Return the background image.
627 */
628 void background_page(void){
629 Blob bgimg;
630 char *zMime;
631
632 zMime = db_get("background-mimetype", "image/gif");
633 blob_zero(&bgimg);
634 db_blob(&bgimg, "SELECT value FROM config WHERE name='background-image'");
635 if( blob_size(&bgimg)==0 ){
636 blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
637 }
638 cgi_set_content_type(zMime);
639 cgi_set_content(&bgimg);
640 g.isConst = 1;
641 }
642
+90 -24
--- src/file.c
+++ src/file.c
@@ -28,10 +28,17 @@
2828
#include <unistd.h>
2929
#include <string.h>
3030
#include <errno.h>
3131
#include "file.h"
3232
33
+/*
34
+** On Windows, include the Platform SDK header file.
35
+*/
36
+#ifdef _WIN32
37
+# include <windows.h>
38
+#endif
39
+
3340
/*
3441
** The file status information from the most recent stat() call.
3542
**
3643
** Use _stati64 rather than stat on windows, in order to handle files
3744
** larger than 2GB.
@@ -168,11 +175,11 @@
168175
zName = mprintf("%s", zLinkFile);
169176
}else{
170177
zName = zBuf;
171178
memcpy(zName, zLinkFile, nName+1);
172179
}
173
- nName = file_simplify_name(zName, nName);
180
+ nName = file_simplify_name(zName, nName, 0);
174181
for(i=1; i<nName; i++){
175182
if( zName[i]=='/' ){
176183
zName[i] = 0;
177184
if( file_mkdir(zName, 1) ){
178185
fossil_fatal_recursive("unable to create directory %s", zName);
@@ -259,11 +266,11 @@
259266
int file_isdir(const char *zFilename){
260267
int rc;
261268
262269
if( zFilename ){
263270
char *zFN = mprintf("%s", zFilename);
264
- file_simplify_name(zFN, -1);
271
+ file_simplify_name(zFN, -1, 0);
265272
rc = getStat(zFN, 0);
266273
free(zFN);
267274
}else{
268275
rc = getStat(0, 0);
269276
}
@@ -276,11 +283,11 @@
276283
int file_wd_isdir(const char *zFilename){
277284
int rc;
278285
279286
if( zFilename ){
280287
char *zFN = mprintf("%s", zFilename);
281
- file_simplify_name(zFN, -1);
288
+ file_simplify_name(zFN, -1, 0);
282289
rc = getStat(zFN, 1);
283290
free(zFN);
284291
}else{
285292
rc = getStat(0, 1);
286293
}
@@ -314,11 +321,11 @@
314321
fossil_free(z);
315322
z = mprintf("%s-%s-%d", zBase, zSuffix, cnt++);
316323
}
317324
if( relFlag ){
318325
Blob x;
319
- file_relative_name(z, &x);
326
+ file_relative_name(z, &x, 0);
320327
fossil_free(z);
321328
z = blob_str(&x);
322329
}
323330
return z;
324331
}
@@ -473,12 +480,14 @@
473480
** * removing any trailing and duplicate /
474481
** * removing /./
475482
** * removing /A/../
476483
**
477484
** Changes are made in-place. Return the new name length.
485
+** If the slash parameter is non-zero, the trailing slash, if any,
486
+** is retained.
478487
*/
479
-int file_simplify_name(char *z, int n){
488
+int file_simplify_name(char *z, int n, int slash){
480489
int i, j;
481490
if( n<0 ) n = strlen(z);
482491
483492
/* On windows convert all \ characters to / */
484493
#if defined(_WIN32)
@@ -486,11 +495,13 @@
486495
if( z[i]=='\\' ) z[i] = '/';
487496
}
488497
#endif
489498
490499
/* Removing trailing "/" characters */
491
- while( n>1 && z[n-1]=='/' ){ n--; }
500
+ if ( !slash ){
501
+ while( n>1 && z[n-1]=='/' ){ n--; }
502
+ }
492503
493504
/* Remove duplicate '/' characters. Except, two // at the beginning
494505
** of a pathname is allowed since this is important on windows. */
495506
for(i=j=1; i<n; i++){
496507
z[j++] = z[i];
@@ -540,11 +551,11 @@
540551
int i;
541552
char *z;
542553
for(i=2; i<g.argc; i++){
543554
z = mprintf("%s", g.argv[i]);
544555
fossil_print("[%s] -> ", z);
545
- file_simplify_name(z, -1);
556
+ file_simplify_name(z, -1, 0);
546557
fossil_print("[%s]\n", z);
547558
fossil_free(z);
548559
}
549560
}
550561
@@ -606,22 +617,45 @@
606617
** Compute a canonical pathname for a file or directory.
607618
** Make the name absolute if it is relative.
608619
** Remove redundant / characters
609620
** Remove all /./ path elements.
610621
** Convert /A/../ to just /
622
+** If the slash parameter is non-zero, the trailing slash, if any,
623
+** is retained.
611624
*/
612
-void file_canonical_name(const char *zOrigName, Blob *pOut){
625
+void file_canonical_name(const char *zOrigName, Blob *pOut, int slash){
613626
if( file_is_absolute_path(zOrigName) ){
627
+#if defined(_WIN32)
628
+ char *zOut;
629
+#endif
614630
blob_set(pOut, zOrigName);
615631
blob_materialize(pOut);
632
+#if defined(_WIN32)
633
+ /*
634
+ ** On Windows, normalize the drive letter to upper case.
635
+ */
636
+ zOut = blob_str(pOut);
637
+ if( fossil_isalpha(zOut[0]) && zOut[1]==':' ){
638
+ zOut[0] = fossil_toupper(zOut[0]);
639
+ }
640
+#endif
616641
}else{
617642
char zPwd[2000];
618643
file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
644
+#if defined(_WIN32)
645
+ /*
646
+ ** On Windows, normalize the drive letter to upper case.
647
+ */
648
+ if( fossil_isalpha(zPwd[0]) && zPwd[1]==':' ){
649
+ zPwd[0] = fossil_toupper(zPwd[0]);
650
+ }
651
+#endif
619652
blob_zero(pOut);
620653
blob_appendf(pOut, "%//%/", zPwd, zOrigName);
621654
}
622
- blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
655
+ blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
656
+ blob_size(pOut), slash));
623657
}
624658
625659
/*
626660
** COMMAND: test-canonical-name
627661
** Usage: %fossil test-canonical-name FILENAME...
@@ -634,11 +668,11 @@
634668
Blob x;
635669
blob_zero(&x);
636670
for(i=2; i<g.argc; i++){
637671
char zBuf[100];
638672
const char *zName = g.argv[i];
639
- file_canonical_name(zName, &x);
673
+ file_canonical_name(zName, &x, 0);
640674
fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
641675
blob_reset(&x);
642676
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
643677
fossil_print(" file_size = %s\n", zBuf);
644678
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
@@ -688,16 +722,18 @@
688722
return zIn;
689723
}
690724
691725
/*
692726
** Compute a pathname for a file or directory that is relative
693
-** to the current directory.
727
+** to the current directory. If the slash parameter is non-zero,
728
+** the trailing slash, if any, is retained.
694729
*/
695
-void file_relative_name(const char *zOrigName, Blob *pOut){
730
+void file_relative_name(const char *zOrigName, Blob *pOut, int slash){
696731
char *zPath;
697732
blob_set(pOut, zOrigName);
698
- blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
733
+ blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
734
+ blob_size(pOut), slash));
699735
zPath = file_without_drive_letter(blob_buffer(pOut));
700736
if( zPath[0]=='/' ){
701737
int i, j;
702738
Blob tmp;
703739
char *zPwd;
@@ -753,11 +789,11 @@
753789
void cmd_test_relative_name(void){
754790
int i;
755791
Blob x;
756792
blob_zero(&x);
757793
for(i=2; i<g.argc; i++){
758
- file_relative_name(g.argv[i], &x);
794
+ file_relative_name(g.argv[i], &x, 0);
759795
fossil_print("%s\n", blob_buffer(&x));
760796
blob_reset(&x);
761797
}
762798
}
763799
@@ -768,37 +804,46 @@
768804
** false, then simply return 0.
769805
**
770806
** The root of the tree is defined by the g.zLocalRoot variable.
771807
*/
772808
int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
773
- int n;
809
+ Blob localRoot;
810
+ int nLocalRoot;
811
+ char *zLocalRoot;
774812
Blob full;
775813
int nFull;
776814
char *zFull;
777815
778816
blob_zero(pOut);
779817
db_must_be_within_tree();
780
- file_canonical_name(zOrigName, &full);
781
- n = strlen(g.zLocalRoot);
782
- assert( n>0 && g.zLocalRoot[n-1]=='/' );
818
+ file_canonical_name(g.zLocalRoot, &localRoot, 1);
819
+ nLocalRoot = blob_size(&localRoot);
820
+ zLocalRoot = blob_buffer(&localRoot);
821
+ assert( nLocalRoot>0 && zLocalRoot[nLocalRoot-1]=='/' );
822
+ file_canonical_name(zOrigName, &full, 0);
783823
nFull = blob_size(&full);
784824
zFull = blob_buffer(&full);
785825
786826
/* Special case. zOrigName refers to g.zLocalRoot directory. */
787
- if( nFull==n-1 && memcmp(g.zLocalRoot, zFull, nFull)==0 ){
827
+ if( nFull==nLocalRoot-1 && memcmp(zLocalRoot, zFull, nFull)==0 ){
788828
blob_append(pOut, ".", 1);
829
+ blob_reset(&localRoot);
830
+ blob_reset(&full);
789831
return 1;
790832
}
791833
792
- if( nFull<=n || memcmp(g.zLocalRoot, zFull, n) ){
834
+ if( nFull<=nLocalRoot || memcmp(zLocalRoot, zFull, nLocalRoot) ){
835
+ blob_reset(&localRoot);
793836
blob_reset(&full);
794837
if( errFatal ){
795838
fossil_fatal("file outside of checkout tree: %s", zOrigName);
796839
}
797840
return 0;
798841
}
799
- blob_append(pOut, &zFull[n], nFull-n);
842
+ blob_append(pOut, &zFull[nLocalRoot], nFull-nLocalRoot);
843
+ blob_reset(&localRoot);
844
+ blob_reset(&full);
800845
return 1;
801846
}
802847
803848
/*
804849
** COMMAND: test-tree-name
@@ -861,25 +906,44 @@
861906
/*
862907
** Construct a random temporary filename into zBuf[].
863908
*/
864909
void file_tempname(int nBuf, char *zBuf){
865910
static const char *azDirs[] = {
911
+#if defined(_WIN32)
912
+ 0, /* GetTempPath */
913
+ 0, /* TEMP */
914
+ 0, /* TMP */
915
+#else
866916
"/var/tmp",
867917
"/usr/tmp",
868918
"/tmp",
869919
"/temp",
920
+#endif
870921
".",
871922
};
872923
static const unsigned char zChars[] =
873924
"abcdefghijklmnopqrstuvwxyz"
874925
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
875926
"0123456789";
876927
unsigned int i, j;
877928
const char *zDir = ".";
878929
int cnt = 0;
930
+
931
+#if defined(_WIN32)
932
+ char zTmpPath[MAX_PATH];
933
+
934
+ if( GetTempPath(sizeof(zTmpPath), zTmpPath) ){
935
+ azDirs[0] = zTmpPath;
936
+ }
937
+
938
+ azDirs[1] = fossil_getenv("TEMP");
939
+ azDirs[2] = fossil_getenv("TMP");
940
+#endif
941
+
879942
880943
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
944
+ if( azDirs[i]==0 ) continue;
881945
if( !file_isdir(azDirs[i]) ) continue;
882946
zDir = azDirs[i];
883947
break;
884948
}
885949
@@ -898,10 +962,15 @@
898962
for(i=0; i<15; i++, j++){
899963
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
900964
}
901965
zBuf[j] = 0;
902966
}while( file_size(zBuf)>=0 );
967
+
968
+#if defined(_WIN32)
969
+ fossil_mbcs_free((char *)azDirs[1]);
970
+ fossil_mbcs_free((char *)azDirs[2]);
971
+#endif
903972
}
904973
905974
906975
/*
907976
** Return true if a file named zName exists and has identical content
@@ -930,13 +999,10 @@
930999
/**************************************************************************
9311000
** The following routines translate between MBCS and UTF8 on windows.
9321001
** Since everything is always UTF8 on unix, these routines are no-ops
9331002
** there.
9341003
*/
935
-#ifdef _WIN32
936
-# include <windows.h>
937
-#endif
9381004
9391005
/*
9401006
** Translate MBCS to UTF8. Return a pointer to the translated text.
9411007
** Call fossil_mbcs_free() to deallocate any memory used to store the
9421008
** returned pointer when done.
9431009
--- src/file.c
+++ src/file.c
@@ -28,10 +28,17 @@
28 #include <unistd.h>
29 #include <string.h>
30 #include <errno.h>
31 #include "file.h"
32
 
 
 
 
 
 
 
33 /*
34 ** The file status information from the most recent stat() call.
35 **
36 ** Use _stati64 rather than stat on windows, in order to handle files
37 ** larger than 2GB.
@@ -168,11 +175,11 @@
168 zName = mprintf("%s", zLinkFile);
169 }else{
170 zName = zBuf;
171 memcpy(zName, zLinkFile, nName+1);
172 }
173 nName = file_simplify_name(zName, nName);
174 for(i=1; i<nName; i++){
175 if( zName[i]=='/' ){
176 zName[i] = 0;
177 if( file_mkdir(zName, 1) ){
178 fossil_fatal_recursive("unable to create directory %s", zName);
@@ -259,11 +266,11 @@
259 int file_isdir(const char *zFilename){
260 int rc;
261
262 if( zFilename ){
263 char *zFN = mprintf("%s", zFilename);
264 file_simplify_name(zFN, -1);
265 rc = getStat(zFN, 0);
266 free(zFN);
267 }else{
268 rc = getStat(0, 0);
269 }
@@ -276,11 +283,11 @@
276 int file_wd_isdir(const char *zFilename){
277 int rc;
278
279 if( zFilename ){
280 char *zFN = mprintf("%s", zFilename);
281 file_simplify_name(zFN, -1);
282 rc = getStat(zFN, 1);
283 free(zFN);
284 }else{
285 rc = getStat(0, 1);
286 }
@@ -314,11 +321,11 @@
314 fossil_free(z);
315 z = mprintf("%s-%s-%d", zBase, zSuffix, cnt++);
316 }
317 if( relFlag ){
318 Blob x;
319 file_relative_name(z, &x);
320 fossil_free(z);
321 z = blob_str(&x);
322 }
323 return z;
324 }
@@ -473,12 +480,14 @@
473 ** * removing any trailing and duplicate /
474 ** * removing /./
475 ** * removing /A/../
476 **
477 ** Changes are made in-place. Return the new name length.
 
 
478 */
479 int file_simplify_name(char *z, int n){
480 int i, j;
481 if( n<0 ) n = strlen(z);
482
483 /* On windows convert all \ characters to / */
484 #if defined(_WIN32)
@@ -486,11 +495,13 @@
486 if( z[i]=='\\' ) z[i] = '/';
487 }
488 #endif
489
490 /* Removing trailing "/" characters */
491 while( n>1 && z[n-1]=='/' ){ n--; }
 
 
492
493 /* Remove duplicate '/' characters. Except, two // at the beginning
494 ** of a pathname is allowed since this is important on windows. */
495 for(i=j=1; i<n; i++){
496 z[j++] = z[i];
@@ -540,11 +551,11 @@
540 int i;
541 char *z;
542 for(i=2; i<g.argc; i++){
543 z = mprintf("%s", g.argv[i]);
544 fossil_print("[%s] -> ", z);
545 file_simplify_name(z, -1);
546 fossil_print("[%s]\n", z);
547 fossil_free(z);
548 }
549 }
550
@@ -606,22 +617,45 @@
606 ** Compute a canonical pathname for a file or directory.
607 ** Make the name absolute if it is relative.
608 ** Remove redundant / characters
609 ** Remove all /./ path elements.
610 ** Convert /A/../ to just /
 
 
611 */
612 void file_canonical_name(const char *zOrigName, Blob *pOut){
613 if( file_is_absolute_path(zOrigName) ){
 
 
 
614 blob_set(pOut, zOrigName);
615 blob_materialize(pOut);
 
 
 
 
 
 
 
 
 
616 }else{
617 char zPwd[2000];
618 file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
 
 
 
 
 
 
 
 
619 blob_zero(pOut);
620 blob_appendf(pOut, "%//%/", zPwd, zOrigName);
621 }
622 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
 
623 }
624
625 /*
626 ** COMMAND: test-canonical-name
627 ** Usage: %fossil test-canonical-name FILENAME...
@@ -634,11 +668,11 @@
634 Blob x;
635 blob_zero(&x);
636 for(i=2; i<g.argc; i++){
637 char zBuf[100];
638 const char *zName = g.argv[i];
639 file_canonical_name(zName, &x);
640 fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
641 blob_reset(&x);
642 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
643 fossil_print(" file_size = %s\n", zBuf);
644 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
@@ -688,16 +722,18 @@
688 return zIn;
689 }
690
691 /*
692 ** Compute a pathname for a file or directory that is relative
693 ** to the current directory.
 
694 */
695 void file_relative_name(const char *zOrigName, Blob *pOut){
696 char *zPath;
697 blob_set(pOut, zOrigName);
698 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
 
699 zPath = file_without_drive_letter(blob_buffer(pOut));
700 if( zPath[0]=='/' ){
701 int i, j;
702 Blob tmp;
703 char *zPwd;
@@ -753,11 +789,11 @@
753 void cmd_test_relative_name(void){
754 int i;
755 Blob x;
756 blob_zero(&x);
757 for(i=2; i<g.argc; i++){
758 file_relative_name(g.argv[i], &x);
759 fossil_print("%s\n", blob_buffer(&x));
760 blob_reset(&x);
761 }
762 }
763
@@ -768,37 +804,46 @@
768 ** false, then simply return 0.
769 **
770 ** The root of the tree is defined by the g.zLocalRoot variable.
771 */
772 int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
773 int n;
 
 
774 Blob full;
775 int nFull;
776 char *zFull;
777
778 blob_zero(pOut);
779 db_must_be_within_tree();
780 file_canonical_name(zOrigName, &full);
781 n = strlen(g.zLocalRoot);
782 assert( n>0 && g.zLocalRoot[n-1]=='/' );
 
 
783 nFull = blob_size(&full);
784 zFull = blob_buffer(&full);
785
786 /* Special case. zOrigName refers to g.zLocalRoot directory. */
787 if( nFull==n-1 && memcmp(g.zLocalRoot, zFull, nFull)==0 ){
788 blob_append(pOut, ".", 1);
 
 
789 return 1;
790 }
791
792 if( nFull<=n || memcmp(g.zLocalRoot, zFull, n) ){
 
793 blob_reset(&full);
794 if( errFatal ){
795 fossil_fatal("file outside of checkout tree: %s", zOrigName);
796 }
797 return 0;
798 }
799 blob_append(pOut, &zFull[n], nFull-n);
 
 
800 return 1;
801 }
802
803 /*
804 ** COMMAND: test-tree-name
@@ -861,25 +906,44 @@
861 /*
862 ** Construct a random temporary filename into zBuf[].
863 */
864 void file_tempname(int nBuf, char *zBuf){
865 static const char *azDirs[] = {
 
 
 
 
 
866 "/var/tmp",
867 "/usr/tmp",
868 "/tmp",
869 "/temp",
 
870 ".",
871 };
872 static const unsigned char zChars[] =
873 "abcdefghijklmnopqrstuvwxyz"
874 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
875 "0123456789";
876 unsigned int i, j;
877 const char *zDir = ".";
878 int cnt = 0;
 
 
 
 
 
 
 
 
 
 
 
 
879
880 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
 
881 if( !file_isdir(azDirs[i]) ) continue;
882 zDir = azDirs[i];
883 break;
884 }
885
@@ -898,10 +962,15 @@
898 for(i=0; i<15; i++, j++){
899 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
900 }
901 zBuf[j] = 0;
902 }while( file_size(zBuf)>=0 );
 
 
 
 
 
903 }
904
905
906 /*
907 ** Return true if a file named zName exists and has identical content
@@ -930,13 +999,10 @@
930 /**************************************************************************
931 ** The following routines translate between MBCS and UTF8 on windows.
932 ** Since everything is always UTF8 on unix, these routines are no-ops
933 ** there.
934 */
935 #ifdef _WIN32
936 # include <windows.h>
937 #endif
938
939 /*
940 ** Translate MBCS to UTF8. Return a pointer to the translated text.
941 ** Call fossil_mbcs_free() to deallocate any memory used to store the
942 ** returned pointer when done.
943
--- src/file.c
+++ src/file.c
@@ -28,10 +28,17 @@
28 #include <unistd.h>
29 #include <string.h>
30 #include <errno.h>
31 #include "file.h"
32
33 /*
34 ** On Windows, include the Platform SDK header file.
35 */
36 #ifdef _WIN32
37 # include <windows.h>
38 #endif
39
40 /*
41 ** The file status information from the most recent stat() call.
42 **
43 ** Use _stati64 rather than stat on windows, in order to handle files
44 ** larger than 2GB.
@@ -168,11 +175,11 @@
175 zName = mprintf("%s", zLinkFile);
176 }else{
177 zName = zBuf;
178 memcpy(zName, zLinkFile, nName+1);
179 }
180 nName = file_simplify_name(zName, nName, 0);
181 for(i=1; i<nName; i++){
182 if( zName[i]=='/' ){
183 zName[i] = 0;
184 if( file_mkdir(zName, 1) ){
185 fossil_fatal_recursive("unable to create directory %s", zName);
@@ -259,11 +266,11 @@
266 int file_isdir(const char *zFilename){
267 int rc;
268
269 if( zFilename ){
270 char *zFN = mprintf("%s", zFilename);
271 file_simplify_name(zFN, -1, 0);
272 rc = getStat(zFN, 0);
273 free(zFN);
274 }else{
275 rc = getStat(0, 0);
276 }
@@ -276,11 +283,11 @@
283 int file_wd_isdir(const char *zFilename){
284 int rc;
285
286 if( zFilename ){
287 char *zFN = mprintf("%s", zFilename);
288 file_simplify_name(zFN, -1, 0);
289 rc = getStat(zFN, 1);
290 free(zFN);
291 }else{
292 rc = getStat(0, 1);
293 }
@@ -314,11 +321,11 @@
321 fossil_free(z);
322 z = mprintf("%s-%s-%d", zBase, zSuffix, cnt++);
323 }
324 if( relFlag ){
325 Blob x;
326 file_relative_name(z, &x, 0);
327 fossil_free(z);
328 z = blob_str(&x);
329 }
330 return z;
331 }
@@ -473,12 +480,14 @@
480 ** * removing any trailing and duplicate /
481 ** * removing /./
482 ** * removing /A/../
483 **
484 ** Changes are made in-place. Return the new name length.
485 ** If the slash parameter is non-zero, the trailing slash, if any,
486 ** is retained.
487 */
488 int file_simplify_name(char *z, int n, int slash){
489 int i, j;
490 if( n<0 ) n = strlen(z);
491
492 /* On windows convert all \ characters to / */
493 #if defined(_WIN32)
@@ -486,11 +495,13 @@
495 if( z[i]=='\\' ) z[i] = '/';
496 }
497 #endif
498
499 /* Removing trailing "/" characters */
500 if ( !slash ){
501 while( n>1 && z[n-1]=='/' ){ n--; }
502 }
503
504 /* Remove duplicate '/' characters. Except, two // at the beginning
505 ** of a pathname is allowed since this is important on windows. */
506 for(i=j=1; i<n; i++){
507 z[j++] = z[i];
@@ -540,11 +551,11 @@
551 int i;
552 char *z;
553 for(i=2; i<g.argc; i++){
554 z = mprintf("%s", g.argv[i]);
555 fossil_print("[%s] -> ", z);
556 file_simplify_name(z, -1, 0);
557 fossil_print("[%s]\n", z);
558 fossil_free(z);
559 }
560 }
561
@@ -606,22 +617,45 @@
617 ** Compute a canonical pathname for a file or directory.
618 ** Make the name absolute if it is relative.
619 ** Remove redundant / characters
620 ** Remove all /./ path elements.
621 ** Convert /A/../ to just /
622 ** If the slash parameter is non-zero, the trailing slash, if any,
623 ** is retained.
624 */
625 void file_canonical_name(const char *zOrigName, Blob *pOut, int slash){
626 if( file_is_absolute_path(zOrigName) ){
627 #if defined(_WIN32)
628 char *zOut;
629 #endif
630 blob_set(pOut, zOrigName);
631 blob_materialize(pOut);
632 #if defined(_WIN32)
633 /*
634 ** On Windows, normalize the drive letter to upper case.
635 */
636 zOut = blob_str(pOut);
637 if( fossil_isalpha(zOut[0]) && zOut[1]==':' ){
638 zOut[0] = fossil_toupper(zOut[0]);
639 }
640 #endif
641 }else{
642 char zPwd[2000];
643 file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
644 #if defined(_WIN32)
645 /*
646 ** On Windows, normalize the drive letter to upper case.
647 */
648 if( fossil_isalpha(zPwd[0]) && zPwd[1]==':' ){
649 zPwd[0] = fossil_toupper(zPwd[0]);
650 }
651 #endif
652 blob_zero(pOut);
653 blob_appendf(pOut, "%//%/", zPwd, zOrigName);
654 }
655 blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
656 blob_size(pOut), slash));
657 }
658
659 /*
660 ** COMMAND: test-canonical-name
661 ** Usage: %fossil test-canonical-name FILENAME...
@@ -634,11 +668,11 @@
668 Blob x;
669 blob_zero(&x);
670 for(i=2; i<g.argc; i++){
671 char zBuf[100];
672 const char *zName = g.argv[i];
673 file_canonical_name(zName, &x, 0);
674 fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
675 blob_reset(&x);
676 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
677 fossil_print(" file_size = %s\n", zBuf);
678 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
@@ -688,16 +722,18 @@
722 return zIn;
723 }
724
725 /*
726 ** Compute a pathname for a file or directory that is relative
727 ** to the current directory. If the slash parameter is non-zero,
728 ** the trailing slash, if any, is retained.
729 */
730 void file_relative_name(const char *zOrigName, Blob *pOut, int slash){
731 char *zPath;
732 blob_set(pOut, zOrigName);
733 blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
734 blob_size(pOut), slash));
735 zPath = file_without_drive_letter(blob_buffer(pOut));
736 if( zPath[0]=='/' ){
737 int i, j;
738 Blob tmp;
739 char *zPwd;
@@ -753,11 +789,11 @@
789 void cmd_test_relative_name(void){
790 int i;
791 Blob x;
792 blob_zero(&x);
793 for(i=2; i<g.argc; i++){
794 file_relative_name(g.argv[i], &x, 0);
795 fossil_print("%s\n", blob_buffer(&x));
796 blob_reset(&x);
797 }
798 }
799
@@ -768,37 +804,46 @@
804 ** false, then simply return 0.
805 **
806 ** The root of the tree is defined by the g.zLocalRoot variable.
807 */
808 int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
809 Blob localRoot;
810 int nLocalRoot;
811 char *zLocalRoot;
812 Blob full;
813 int nFull;
814 char *zFull;
815
816 blob_zero(pOut);
817 db_must_be_within_tree();
818 file_canonical_name(g.zLocalRoot, &localRoot, 1);
819 nLocalRoot = blob_size(&localRoot);
820 zLocalRoot = blob_buffer(&localRoot);
821 assert( nLocalRoot>0 && zLocalRoot[nLocalRoot-1]=='/' );
822 file_canonical_name(zOrigName, &full, 0);
823 nFull = blob_size(&full);
824 zFull = blob_buffer(&full);
825
826 /* Special case. zOrigName refers to g.zLocalRoot directory. */
827 if( nFull==nLocalRoot-1 && memcmp(zLocalRoot, zFull, nFull)==0 ){
828 blob_append(pOut, ".", 1);
829 blob_reset(&localRoot);
830 blob_reset(&full);
831 return 1;
832 }
833
834 if( nFull<=nLocalRoot || memcmp(zLocalRoot, zFull, nLocalRoot) ){
835 blob_reset(&localRoot);
836 blob_reset(&full);
837 if( errFatal ){
838 fossil_fatal("file outside of checkout tree: %s", zOrigName);
839 }
840 return 0;
841 }
842 blob_append(pOut, &zFull[nLocalRoot], nFull-nLocalRoot);
843 blob_reset(&localRoot);
844 blob_reset(&full);
845 return 1;
846 }
847
848 /*
849 ** COMMAND: test-tree-name
@@ -861,25 +906,44 @@
906 /*
907 ** Construct a random temporary filename into zBuf[].
908 */
909 void file_tempname(int nBuf, char *zBuf){
910 static const char *azDirs[] = {
911 #if defined(_WIN32)
912 0, /* GetTempPath */
913 0, /* TEMP */
914 0, /* TMP */
915 #else
916 "/var/tmp",
917 "/usr/tmp",
918 "/tmp",
919 "/temp",
920 #endif
921 ".",
922 };
923 static const unsigned char zChars[] =
924 "abcdefghijklmnopqrstuvwxyz"
925 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
926 "0123456789";
927 unsigned int i, j;
928 const char *zDir = ".";
929 int cnt = 0;
930
931 #if defined(_WIN32)
932 char zTmpPath[MAX_PATH];
933
934 if( GetTempPath(sizeof(zTmpPath), zTmpPath) ){
935 azDirs[0] = zTmpPath;
936 }
937
938 azDirs[1] = fossil_getenv("TEMP");
939 azDirs[2] = fossil_getenv("TMP");
940 #endif
941
942
943 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
944 if( azDirs[i]==0 ) continue;
945 if( !file_isdir(azDirs[i]) ) continue;
946 zDir = azDirs[i];
947 break;
948 }
949
@@ -898,10 +962,15 @@
962 for(i=0; i<15; i++, j++){
963 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
964 }
965 zBuf[j] = 0;
966 }while( file_size(zBuf)>=0 );
967
968 #if defined(_WIN32)
969 fossil_mbcs_free((char *)azDirs[1]);
970 fossil_mbcs_free((char *)azDirs[2]);
971 #endif
972 }
973
974
975 /*
976 ** Return true if a file named zName exists and has identical content
@@ -930,13 +999,10 @@
999 /**************************************************************************
1000 ** The following routines translate between MBCS and UTF8 on windows.
1001 ** Since everything is always UTF8 on unix, these routines are no-ops
1002 ** there.
1003 */
 
 
 
1004
1005 /*
1006 ** Translate MBCS to UTF8. Return a pointer to the translated text.
1007 ** Call fossil_mbcs_free() to deallocate any memory used to store the
1008 ** returned pointer when done.
1009
+126 -106
--- src/json.c
+++ src/json.c
@@ -490,11 +490,11 @@
490490
491491
/*
492492
** Wrapper around json_getenv() which tries to evaluate a payload/env
493493
** value as a boolean. Uses mostly the same logic as
494494
** json_getenv_int(), with the addition that string values which
495
-** either start with a digit 1..9 or the letters [tT] are considered
495
+** either start with a digit 1..9 or the letters [tTyY] are considered
496496
** to be true. If this function cannot find a matching key/value then
497497
** dflt is returned. e.g. if it finds the key but the value is-a
498498
** Object then dftl is returned.
499499
**
500500
** If an entry is found, this function guarantees that it will return
@@ -512,12 +512,14 @@
512512
}else if( cson_value_is_string(v) ){
513513
char const * sv = cson_string_cstr(cson_value_get_string(v));
514514
if(!*sv || ('0'==*sv)){
515515
return 0;
516516
}else{
517
- return (('t'==*sv) || ('T'==*sv)
518
- || (('1'<=*sv) && ('9'>=*sv)))
517
+ return ((('1'<=*sv) && ('9'>=*sv))
518
+ || ('t'==*sv) || ('T'==*sv)
519
+ || ('y'==*sv) || ('Y'==*sv)
520
+ )
519521
? 1 : 0;
520522
}
521523
}else if( cson_value_is_bool(v) ){
522524
return cson_value_get_bool(v) ? 1 : 0;
523525
}else if( cson_value_is_null(v) ){
@@ -541,11 +543,11 @@
541543
/*
542544
** An extended form of find_option() which tries to look up a combo
543545
** GET/POST/CLI argument.
544546
**
545547
** zKey must be the GET/POST parameter key. zCLILong must be the "long
546
-** form" CLI flag (NULL means to use zKey). zCLIShort may be NULL or
548
+s** form" CLI flag (NULL means to use zKey). zCLIShort may be NULL or
547549
** the "short form" CLI flag (if NULL, no short form is used).
548550
**
549551
** If argPos is >=0 and no other match is found,
550552
** json_command_arg(argPos) is also checked.
551553
**
@@ -564,19 +566,22 @@
564566
rc = find_option(zCLILong ? zCLILong : zKey,
565567
zCLIShort, 1);
566568
}
567569
if(!rc && fossil_has_json()){
568570
rc = json_getenv_cstr(zKey);
571
+ if(!rc && zCLIShort){
572
+ rc = cson_value_get_cstr( cson_object_get( g.json.param.o, zCLIShort) );
573
+ }
569574
}
570575
if(!rc && (argPos>=0)){
571576
rc = json_command_arg((unsigned char)argPos);
572577
}
573578
return rc;
574579
}
575580
576581
/*
577
-** Short-hand form of json_find_option_cstr(zKey,zCLILong,zCLIShort,-1).
582
+** Short-hand form of json_find_option_cstr2(zKey,zCLILong,zCLIShort,-1).
578583
*/
579584
char const * json_find_option_cstr(char const * zKey,
580585
char const * zCLILong,
581586
char const * zCLIShort){
582587
return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1);
@@ -602,18 +607,18 @@
602607
}
603608
return (-1==rc) ? dflt : rc;
604609
}
605610
606611
/*
607
-** The integer equivalent of json_find_option_cstr().
612
+** The integer equivalent of json_find_option_cstr2().
608613
** If the option is not found, dftl is returned.
609614
*/
610615
int json_find_option_int(char const * zKey,
611616
char const * zCLILong,
612617
char const * zCLIShort,
613618
int dflt ){
614
- enum { Magic = -947 };
619
+ enum { Magic = -1947854832 };
615620
int rc = Magic;
616621
if(!g.isHTTP){
617622
/* FIXME: use strtol() for better error/dflt handling. */
618623
char const * opt = find_option(zCLILong ? zCLILong : zKey,
619624
zCLIShort, 1);
@@ -778,14 +783,15 @@
778783
}
779784
return g.json.authToken;
780785
}
781786
782787
/*
783
-** IFF json.reqPayload.o is not NULL then this returns
784
-** cson_object_get(json.reqPayload.o,pKey), else it returns NULL.
785
-**
786
-** The returned value is owned by (or shared with) json.reqPayload.v.
788
+** If g.json.reqPayload.o is NULL then NULL is returned, else the
789
+** given property is searched for in the request payload. If found it
790
+** is returned. The returned value is owned by (or shares ownership
791
+** with) g.json, and must NOT be cson_value_free()'d by the
792
+** caller.
787793
*/
788794
cson_value * json_req_payload_get(char const *pKey){
789795
return g.json.reqPayload.o
790796
? cson_object_get(g.json.reqPayload.o,pKey)
791797
: NULL;
@@ -979,11 +985,11 @@
979985
** parameters as this function, but returns the results as a JSON
980986
** Array (if splitting produced tokens) or NULL (if splitting failed
981987
** in any way or produced no tokens).
982988
**
983989
** The returned value is owned by the caller. If not NULL then it
984
-** _will_ have a JSON type of Array or Null.
990
+** _will_ have a JSON type of Array.
985991
*/
986992
cson_value * json_string_split2( char const * zStr,
987993
char separator,
988994
char doDeHttp ){
989995
cson_value * v = cson_value_new_array();
@@ -1166,10 +1172,17 @@
11661172
core, which we need before we call
11671173
login_check_credentials(). */;
11681174
login_check_credentials()/* populates g.perm */;
11691175
}
11701176
else{
1177
+ /* FIXME: we need an option which allows us to skip this. At least
1178
+ one known command (/json/version) does not need an opened
1179
+ repo. The problem here is we cannot know which functions need
1180
+ it from here (because command dispatching hasn't yet happened)
1181
+ and all other commands rely on the repo being opened before
1182
+ they are called. A textbook example of lack of foresight :/.
1183
+ */
11711184
db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
11721185
}
11731186
}
11741187
11751188
/*
@@ -1218,24 +1231,10 @@
12181231
}else{
12191232
ndx = g.json.cmd.offset + ndx;
12201233
return cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmd.offset + ndx )));
12211234
}
12221235
}
1223
-
1224
-/*
1225
-** If g.json.reqPayload.o is NULL then NULL is returned, else the
1226
-** given property is searched for in the request payload. If found it
1227
-** is returned. The returned value is owned by (or shares ownership
1228
-** with) g.json, and must NOT be cson_value_free()'d by the
1229
-** caller.
1230
-*/
1231
-cson_value * json_payload_property( char const * key ){
1232
- return g.json.reqPayload.o ?
1233
- cson_object_get( g.json.reqPayload.o, key )
1234
- : NULL;
1235
-}
1236
-
12371236
12381237
/* Returns the C-string form of json_auth_token(), or NULL
12391238
** if json_auth_token() returns NULL.
12401239
*/
12411240
char const * json_auth_token_cstr(){
@@ -1334,13 +1333,15 @@
13341333
unsigned int aLen = g.json.dispatchDepth+1; /*cson_array_length_get(g.json.cmd.a);*/
13351334
unsigned int i = 1;
13361335
for( ; i < aLen; ++i ){
13371336
char const * part = cson_string_cstr(cson_value_get_string(cson_array_get(g.json.cmd.a, i)));
13381337
if(!part){
1339
- fossil_warning("Iterating further than expected in %s.",
1338
+#if 1
1339
+ fossil_warning("Iterating further than expected in %s.",
13401340
__FILE__);
1341
- break;
1341
+#endif
1342
+ break;
13421343
}
13431344
blob_appendf(&path,"%s%s", (i>1 ? "/": ""), part);
13441345
}
13451346
rc = json_new_string((blob_size(&path)>0)
13461347
? blob_buffer(&path)
@@ -1475,13 +1476,13 @@
14751476
** json_err_cstr() is used to get the error string. The caller may
14761477
** provide his own or may use an empty string to suppress the
14771478
** resultText property.
14781479
**
14791480
*/
1480
-cson_value * json_create_response( int resultCode,
1481
- char const * pMsg,
1482
- cson_value * payload){
1481
+static cson_value * json_create_response( int resultCode,
1482
+ char const * pMsg,
1483
+ cson_value * payload){
14831484
cson_value * v = NULL;
14841485
cson_value * tmp = NULL;
14851486
cson_object * o = NULL;
14861487
int rc;
14871488
resultCode = json_dumbdown_rc(resultCode ? resultCode : g.json.resultCode);
@@ -1742,19 +1743,39 @@
17421743
cson_array_append(a, row);
17431744
}
17441745
return cson_array_value(a);
17451746
}
17461747
1748
+cson_value * json_stmt_to_array_of_values(Stmt *pStmt,
1749
+ int resultColumn,
1750
+ cson_array * pTgt){
1751
+ cson_array * a = pTgt;
1752
+ while( (SQLITE_ROW==db_step(pStmt)) ){
1753
+ cson_value * row = cson_sqlite3_column_to_value(pStmt->pStmt,
1754
+ resultColumn);
1755
+ if(row){
1756
+ if(!a){
1757
+ a = cson_new_array();
1758
+ assert(NULL!=a);
1759
+ }
1760
+ cson_array_append(a, row);
1761
+ }
1762
+ }
1763
+ return cson_array_value(a);
1764
+}
17471765
17481766
/*
17491767
** Executes the given SQL and runs it through
17501768
** json_stmt_to_array_of_obj(), returning the result of that
17511769
** function. If resetBlob is true then blob_reset(pSql) is called
17521770
** after preparing the query.
17531771
**
17541772
** pTgt has the same semantics as described for
17551773
** json_stmt_to_array_of_obj().
1774
+**
1775
+** FIXME: change this to take a (char const *) instead of a blob,
1776
+** to simplify the trivial use-cases (which don't need a Blob).
17561777
*/
17571778
cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
17581779
char resetBlob){
17591780
Stmt q = empty_Stmt;
17601781
cson_value * pay = NULL;
@@ -1774,10 +1795,13 @@
17741795
** function returns a JSON Array containing the tag names (owned by
17751796
** the caller), else it returns NULL.
17761797
**
17771798
** See info_tags_of_checkin() for more details (this is simply a JSON
17781799
** wrapper for that function).
1800
+**
1801
+** If there are no tags then this function returns NULL, not an empty
1802
+** Array.
17791803
*/
17801804
cson_value * json_tags_for_checkin_rid(int rid, char propagatingOnly){
17811805
cson_value * v = NULL;
17821806
char * tags = info_tags_of_checkin(rid, propagatingOnly);
17831807
if(tags){
@@ -1813,15 +1837,11 @@
18131837
cson_object * obj = NULL;
18141838
cson_string * kRC;
18151839
cson_string * kSymbol;
18161840
cson_string * kNumber;
18171841
cson_string * kDesc;
1818
- int rc = cson_array_reserve( list, 35 );
1819
- if(rc){
1820
- assert( 0 && "Allocation error.");
1821
- exit(1);
1822
- }
1842
+ cson_array_reserve( list, 35 );
18231843
kRC = cson_new_string("resultCode",10);
18241844
kSymbol = cson_new_string("cSymbol",7);
18251845
kNumber = cson_new_string("number",6);
18261846
kDesc = cson_new_string("description",11);
18271847
#define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
@@ -1888,15 +1908,16 @@
18881908
FSET(MANIFEST_UUID,"manifestUuid");
18891909
FSET(MANIFEST_VERSION,"manifestVersion");
18901910
FSET(MANIFEST_DATE,"manifestDate");
18911911
FSET(MANIFEST_YEAR,"manifestYear");
18921912
FSET(RELEASE_VERSION,"releaseVersion");
1893
-#undef FSET
18941913
cson_object_set( jobj, "releaseVersionNumber",
18951914
cson_value_new_integer(RELEASE_VERSION_NUMBER) );
18961915
cson_object_set( jobj, "resultCodeParanoiaLevel",
18971916
cson_value_new_integer(g.json.errorDetailParanoia) );
1917
+ /*FSET(FOSSIL_JSON_API_VERSION, "jsonApiVersion" );*/
1918
+#undef FSET
18981919
return jval;
18991920
}
19001921
19011922
19021923
/*
@@ -2113,22 +2134,43 @@
21132134
}
21142135
}
21152136
return i;
21162137
}
21172138
2139
+/*
2140
+** Creates an error message using zErrPrefix and the given array of
2141
+** JSON command definitions, and sets the g.json error state to
2142
+** reflect FSL_JSON_E_MISSING_ARGS. If zErrPrefix is NULL then
2143
+** some default is used (e.g. "Try one of: "). If it is "" then
2144
+** no prefix is used.
2145
+**
2146
+** The intention is to provide the user (via the response.resultText)
2147
+** a list of available commands/subcommands.
2148
+**
2149
+*/
2150
+void json_dispatch_missing_args_err( JsonPageDef const * pCommands,
2151
+ char const * zErrPrefix ){
2152
+ Blob cmdNames = empty_blob;
2153
+ blob_init(&cmdNames,NULL,0);
2154
+ if( !zErrPrefix ) {
2155
+ zErrPrefix = "Try one of: ";
2156
+ }
2157
+ blob_append( &cmdNames, zErrPrefix, strlen(zErrPrefix) );
2158
+ json_pagedefs_to_string(pCommands, &cmdNames);
2159
+ json_set_err(FSL_JSON_E_MISSING_ARGS, "%s",
2160
+ blob_str(&cmdNames));
2161
+ blob_reset(&cmdNames);
2162
+}
21182163
21192164
cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
21202165
JsonPageDef const * def;
21212166
char const * cmd = json_command_arg(1+g.json.dispatchDepth);
21222167
assert( NULL != pages );
21232168
if( ! cmd ){
2124
- Blob cmdNames = empty_blob;
2125
- json_pagedefs_to_string(pages, &cmdNames);
2126
- json_set_err(FSL_JSON_E_MISSING_ARGS,
2127
- "No subcommand specified. Try one of (%s).",
2128
- blob_str(&cmdNames));
2129
- blob_reset(&cmdNames);
2169
+ json_dispatch_missing_args_err(pages,
2170
+ "No subcommand specified. "
2171
+ "Try one of: ");
21302172
return NULL;
21312173
}
21322174
def = json_handler_for_name( cmd, pages );
21332175
if(!def){
21342176
json_set_err(FSL_JSON_E_UNKNOWN_COMMAND,
@@ -2186,10 +2228,12 @@
21862228
cson_value * json_page_artifact();
21872229
/* Impl in json_branch.c. */
21882230
cson_value * json_page_branch();
21892231
/* Impl in json_diff.c. */
21902232
cson_value * json_page_diff();
2233
+/* Impl in json_dir.c. */
2234
+cson_value * json_page_dir();
21912235
/* Impl in json_login.c. */
21922236
cson_value * json_page_login();
21932237
/* Impl in json_login.c. */
21942238
cson_value * json_page_logout();
21952239
/* Impl in json_query.c. */
@@ -2200,10 +2244,13 @@
22002244
cson_value * json_page_tag();
22012245
/* Impl in json_user.c. */
22022246
cson_value * json_page_user();
22032247
/* Impl in json_config.c. */
22042248
cson_value * json_page_config();
2249
+/* Impl in json_finfo.c. */
2250
+cson_value * json_page_finfo();
2251
+
22052252
/*
22062253
** Mapping of names to JSON pages/commands. Each name is a subpath of
22072254
** /json (in CGI mode) or a subcommand of the json command in CLI mode
22082255
*/
22092256
static const JsonPageDef JsonPageDefs[] = {
@@ -2212,11 +2259,12 @@
22122259
{"artifact", json_page_artifact, 0},
22132260
{"branch", json_page_branch,0},
22142261
{"cap", json_page_cap, 0},
22152262
{"config", json_page_config, 0 },
22162263
{"diff", json_page_diff, 0},
2217
-{"dir", json_page_nyi, 0},
2264
+{"dir", json_page_dir, 0},
2265
+{"finfo", json_page_finfo, 0},
22182266
{"g", json_page_g, 0},
22192267
{"HAI",json_page_version,0},
22202268
{"login",json_page_login,0},
22212269
{"logout",json_page_logout,0},
22222270
{"query",json_page_query,0},
@@ -2223,49 +2271,16 @@
22232271
{"rebuild",json_page_rebuild,0},
22242272
{"report", json_page_report, 0},
22252273
{"resultCodes", json_page_resultCodes,0},
22262274
{"stat",json_page_stat,0},
22272275
{"tag", json_page_tag,0},
2228
-{"ticket", json_page_nyi,0},
2276
+/*{"ticket", json_page_nyi,0},*/
22292277
{"timeline", json_page_timeline,0},
22302278
{"user",json_page_user,0},
22312279
{"version",json_page_version,0},
22322280
{"whoami",json_page_whoami,0},
22332281
{"wiki",json_page_wiki,0},
2234
-/* Last entry MUST have a NULL name. */
2235
-{NULL,NULL,0}
2236
-};
2237
-
2238
-
2239
-/*
2240
-** Mapping of /json/ticket/XXX commands/paths to callbacks.
2241
-*/
2242
-static const JsonPageDef JsonPageDefs_Ticket[] = {
2243
-{"get", json_page_nyi, 0},
2244
-{"list", json_page_nyi, 0},
2245
-{"save", json_page_nyi, 1},
2246
-{"create", json_page_nyi, 1},
2247
-/* Last entry MUST have a NULL name. */
2248
-{NULL,NULL,0}
2249
-};
2250
-
2251
-/*
2252
-** Mapping of /json/artifact/XXX commands/paths to callbacks.
2253
-*/
2254
-static const JsonPageDef JsonPageDefs_Artifact[] = {
2255
-{"vinfo", json_page_nyi, 0},
2256
-{"finfo", json_page_nyi, 0},
2257
-/* Last entry MUST have a NULL name. */
2258
-{NULL,NULL,0}
2259
-};
2260
-
2261
-/*
2262
-** Mapping of /json/tag/XXX commands/paths to callbacks.
2263
-*/
2264
-static const JsonPageDef JsonPageDefs_Tag[] = {
2265
-{"list", json_page_nyi, 0},
2266
-{"create", json_page_nyi, 1},
22672282
/* Last entry MUST have a NULL name. */
22682283
{NULL,NULL,0}
22692284
};
22702285
22712286
/*
@@ -2295,11 +2310,11 @@
22952310
else{
22962311
rc = 0;
22972312
g.json.dispatchDepth = 1;
22982313
payload = (*pageDef->func)();
22992314
}
2300
- payload = json_create_response(rc, rc ? g.zErrMsg : NULL, payload);
2315
+ payload = json_create_response(rc, NULL, payload);
23012316
json_send_response(payload);
23022317
cson_value_free(payload);
23032318
return rc;
23042319
}
23052320
@@ -2315,26 +2330,16 @@
23152330
char const * zCommand;
23162331
BEGIN_TIMER;
23172332
json_mode_bootstrap();
23182333
zCommand = json_command_arg(1);
23192334
if(!zCommand || !*zCommand){
2320
- goto usage;
2335
+ json_dispatch_missing_args_err( JsonPageDefs,
2336
+ "No command (sub-path) specified."
2337
+ " Try one of: ");
2338
+ return;
23212339
}
23222340
json_dispatch_root_command( zCommand );
2323
- return;
2324
- usage:
2325
- {
2326
- Blob cmdNames = empty_blob;
2327
- blob_init(&cmdNames,
2328
- "No command (sub-path) specified. Try one of: ",
2329
- -1);
2330
- json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames);
2331
- json_err(FSL_JSON_E_MISSING_ARGS,
2332
- blob_str(&cmdNames), 0);
2333
- blob_reset(&cmdNames);
2334
- }
2335
-
23362341
}
23372342
#endif /* FOSSIL_ENABLE_JSON for mkindex */
23382343
23392344
#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
23402345
/*
@@ -2341,27 +2346,42 @@
23412346
** This function dispatches json commands and is the CLI equivalent of
23422347
** json_page_top().
23432348
**
23442349
** COMMAND: json
23452350
**
2346
-** Usage: %fossil json SUBCOMMAND
2351
+** Usage: %fossil json SUBCOMMAND ?OPTIONS?
2352
+**
2353
+** In CLI mode, the -R REPO common option is supported. Due to limitations
2354
+** in the argument dispatching code, any -FLAGS must come after the final
2355
+** sub- (or subsub-) command.
23472356
**
23482357
** The commands include:
23492358
**
2359
+** anonymousPassord
2360
+** artifact
23502361
** branch
23512362
** cap
2363
+** diff
2364
+** g
2365
+** login
2366
+** logout
2367
+** query
2368
+** rebuild
2369
+** report
2370
+** resultCodes
23522371
** stat
2372
+** tag
23532373
** timeline
2374
+** user
23542375
** version (alias: HAI)
2376
+** whoami
23552377
** wiki
23562378
**
2357
-**
2358
-** TODOs:
2379
+** Run '%fossil json' without any subcommand to see the full list (but be
2380
+** aware that some listed might not yet be implemented).
23592381
**
2360
-** tag
2361
-** ticket
2362
-** ...
2382
+** PS: the notable TODO-commands include: config, dir, finfo, ticket
23632383
**
23642384
*/
23652385
void json_cmd_top(void){
23662386
char const * cmd = NULL;
23672387
int rc = 0;
@@ -2397,18 +2417,18 @@
23972417
fossil_exit(1);
23982418
}
23992419
return;
24002420
usage:
24012421
{
2402
- Blob cmdNames = empty_blob;
2403
- blob_init(&cmdNames,
2404
- "No subcommand specified. Try one of: ", -1);
2405
- json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames);
2406
- json_err(FSL_JSON_E_MISSING_ARGS,
2407
- blob_str(&cmdNames), 1);
2408
- blob_reset(&cmdNames);
2422
+ cson_value * payload;
2423
+ json_dispatch_missing_args_err( JsonPageDefs,
2424
+ "No subcommand specified."
2425
+ " Try one of: ");
2426
+ payload = json_create_response(0, NULL, NULL);
2427
+ json_send_response(payload);
2428
+ cson_value_free(payload);
24092429
fossil_exit(1);
24102430
}
24112431
}
24122432
#endif /* FOSSIL_ENABLE_JSON for mkindex */
24132433
24142434
#endif /* FOSSIL_ENABLE_JSON */
24152435
--- src/json.c
+++ src/json.c
@@ -490,11 +490,11 @@
490
491 /*
492 ** Wrapper around json_getenv() which tries to evaluate a payload/env
493 ** value as a boolean. Uses mostly the same logic as
494 ** json_getenv_int(), with the addition that string values which
495 ** either start with a digit 1..9 or the letters [tT] are considered
496 ** to be true. If this function cannot find a matching key/value then
497 ** dflt is returned. e.g. if it finds the key but the value is-a
498 ** Object then dftl is returned.
499 **
500 ** If an entry is found, this function guarantees that it will return
@@ -512,12 +512,14 @@
512 }else if( cson_value_is_string(v) ){
513 char const * sv = cson_string_cstr(cson_value_get_string(v));
514 if(!*sv || ('0'==*sv)){
515 return 0;
516 }else{
517 return (('t'==*sv) || ('T'==*sv)
518 || (('1'<=*sv) && ('9'>=*sv)))
 
 
519 ? 1 : 0;
520 }
521 }else if( cson_value_is_bool(v) ){
522 return cson_value_get_bool(v) ? 1 : 0;
523 }else if( cson_value_is_null(v) ){
@@ -541,11 +543,11 @@
541 /*
542 ** An extended form of find_option() which tries to look up a combo
543 ** GET/POST/CLI argument.
544 **
545 ** zKey must be the GET/POST parameter key. zCLILong must be the "long
546 ** form" CLI flag (NULL means to use zKey). zCLIShort may be NULL or
547 ** the "short form" CLI flag (if NULL, no short form is used).
548 **
549 ** If argPos is >=0 and no other match is found,
550 ** json_command_arg(argPos) is also checked.
551 **
@@ -564,19 +566,22 @@
564 rc = find_option(zCLILong ? zCLILong : zKey,
565 zCLIShort, 1);
566 }
567 if(!rc && fossil_has_json()){
568 rc = json_getenv_cstr(zKey);
 
 
 
569 }
570 if(!rc && (argPos>=0)){
571 rc = json_command_arg((unsigned char)argPos);
572 }
573 return rc;
574 }
575
576 /*
577 ** Short-hand form of json_find_option_cstr(zKey,zCLILong,zCLIShort,-1).
578 */
579 char const * json_find_option_cstr(char const * zKey,
580 char const * zCLILong,
581 char const * zCLIShort){
582 return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1);
@@ -602,18 +607,18 @@
602 }
603 return (-1==rc) ? dflt : rc;
604 }
605
606 /*
607 ** The integer equivalent of json_find_option_cstr().
608 ** If the option is not found, dftl is returned.
609 */
610 int json_find_option_int(char const * zKey,
611 char const * zCLILong,
612 char const * zCLIShort,
613 int dflt ){
614 enum { Magic = -947 };
615 int rc = Magic;
616 if(!g.isHTTP){
617 /* FIXME: use strtol() for better error/dflt handling. */
618 char const * opt = find_option(zCLILong ? zCLILong : zKey,
619 zCLIShort, 1);
@@ -778,14 +783,15 @@
778 }
779 return g.json.authToken;
780 }
781
782 /*
783 ** IFF json.reqPayload.o is not NULL then this returns
784 ** cson_object_get(json.reqPayload.o,pKey), else it returns NULL.
785 **
786 ** The returned value is owned by (or shared with) json.reqPayload.v.
 
787 */
788 cson_value * json_req_payload_get(char const *pKey){
789 return g.json.reqPayload.o
790 ? cson_object_get(g.json.reqPayload.o,pKey)
791 : NULL;
@@ -979,11 +985,11 @@
979 ** parameters as this function, but returns the results as a JSON
980 ** Array (if splitting produced tokens) or NULL (if splitting failed
981 ** in any way or produced no tokens).
982 **
983 ** The returned value is owned by the caller. If not NULL then it
984 ** _will_ have a JSON type of Array or Null.
985 */
986 cson_value * json_string_split2( char const * zStr,
987 char separator,
988 char doDeHttp ){
989 cson_value * v = cson_value_new_array();
@@ -1166,10 +1172,17 @@
1166 core, which we need before we call
1167 login_check_credentials(). */;
1168 login_check_credentials()/* populates g.perm */;
1169 }
1170 else{
 
 
 
 
 
 
 
1171 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
1172 }
1173 }
1174
1175 /*
@@ -1218,24 +1231,10 @@
1218 }else{
1219 ndx = g.json.cmd.offset + ndx;
1220 return cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmd.offset + ndx )));
1221 }
1222 }
1223
1224 /*
1225 ** If g.json.reqPayload.o is NULL then NULL is returned, else the
1226 ** given property is searched for in the request payload. If found it
1227 ** is returned. The returned value is owned by (or shares ownership
1228 ** with) g.json, and must NOT be cson_value_free()'d by the
1229 ** caller.
1230 */
1231 cson_value * json_payload_property( char const * key ){
1232 return g.json.reqPayload.o ?
1233 cson_object_get( g.json.reqPayload.o, key )
1234 : NULL;
1235 }
1236
1237
1238 /* Returns the C-string form of json_auth_token(), or NULL
1239 ** if json_auth_token() returns NULL.
1240 */
1241 char const * json_auth_token_cstr(){
@@ -1334,13 +1333,15 @@
1334 unsigned int aLen = g.json.dispatchDepth+1; /*cson_array_length_get(g.json.cmd.a);*/
1335 unsigned int i = 1;
1336 for( ; i < aLen; ++i ){
1337 char const * part = cson_string_cstr(cson_value_get_string(cson_array_get(g.json.cmd.a, i)));
1338 if(!part){
1339 fossil_warning("Iterating further than expected in %s.",
 
1340 __FILE__);
1341 break;
 
1342 }
1343 blob_appendf(&path,"%s%s", (i>1 ? "/": ""), part);
1344 }
1345 rc = json_new_string((blob_size(&path)>0)
1346 ? blob_buffer(&path)
@@ -1475,13 +1476,13 @@
1475 ** json_err_cstr() is used to get the error string. The caller may
1476 ** provide his own or may use an empty string to suppress the
1477 ** resultText property.
1478 **
1479 */
1480 cson_value * json_create_response( int resultCode,
1481 char const * pMsg,
1482 cson_value * payload){
1483 cson_value * v = NULL;
1484 cson_value * tmp = NULL;
1485 cson_object * o = NULL;
1486 int rc;
1487 resultCode = json_dumbdown_rc(resultCode ? resultCode : g.json.resultCode);
@@ -1742,19 +1743,39 @@
1742 cson_array_append(a, row);
1743 }
1744 return cson_array_value(a);
1745 }
1746
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1747
1748 /*
1749 ** Executes the given SQL and runs it through
1750 ** json_stmt_to_array_of_obj(), returning the result of that
1751 ** function. If resetBlob is true then blob_reset(pSql) is called
1752 ** after preparing the query.
1753 **
1754 ** pTgt has the same semantics as described for
1755 ** json_stmt_to_array_of_obj().
 
 
 
1756 */
1757 cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
1758 char resetBlob){
1759 Stmt q = empty_Stmt;
1760 cson_value * pay = NULL;
@@ -1774,10 +1795,13 @@
1774 ** function returns a JSON Array containing the tag names (owned by
1775 ** the caller), else it returns NULL.
1776 **
1777 ** See info_tags_of_checkin() for more details (this is simply a JSON
1778 ** wrapper for that function).
 
 
 
1779 */
1780 cson_value * json_tags_for_checkin_rid(int rid, char propagatingOnly){
1781 cson_value * v = NULL;
1782 char * tags = info_tags_of_checkin(rid, propagatingOnly);
1783 if(tags){
@@ -1813,15 +1837,11 @@
1813 cson_object * obj = NULL;
1814 cson_string * kRC;
1815 cson_string * kSymbol;
1816 cson_string * kNumber;
1817 cson_string * kDesc;
1818 int rc = cson_array_reserve( list, 35 );
1819 if(rc){
1820 assert( 0 && "Allocation error.");
1821 exit(1);
1822 }
1823 kRC = cson_new_string("resultCode",10);
1824 kSymbol = cson_new_string("cSymbol",7);
1825 kNumber = cson_new_string("number",6);
1826 kDesc = cson_new_string("description",11);
1827 #define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
@@ -1888,15 +1908,16 @@
1888 FSET(MANIFEST_UUID,"manifestUuid");
1889 FSET(MANIFEST_VERSION,"manifestVersion");
1890 FSET(MANIFEST_DATE,"manifestDate");
1891 FSET(MANIFEST_YEAR,"manifestYear");
1892 FSET(RELEASE_VERSION,"releaseVersion");
1893 #undef FSET
1894 cson_object_set( jobj, "releaseVersionNumber",
1895 cson_value_new_integer(RELEASE_VERSION_NUMBER) );
1896 cson_object_set( jobj, "resultCodeParanoiaLevel",
1897 cson_value_new_integer(g.json.errorDetailParanoia) );
 
 
1898 return jval;
1899 }
1900
1901
1902 /*
@@ -2113,22 +2134,43 @@
2113 }
2114 }
2115 return i;
2116 }
2117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2118
2119 cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
2120 JsonPageDef const * def;
2121 char const * cmd = json_command_arg(1+g.json.dispatchDepth);
2122 assert( NULL != pages );
2123 if( ! cmd ){
2124 Blob cmdNames = empty_blob;
2125 json_pagedefs_to_string(pages, &cmdNames);
2126 json_set_err(FSL_JSON_E_MISSING_ARGS,
2127 "No subcommand specified. Try one of (%s).",
2128 blob_str(&cmdNames));
2129 blob_reset(&cmdNames);
2130 return NULL;
2131 }
2132 def = json_handler_for_name( cmd, pages );
2133 if(!def){
2134 json_set_err(FSL_JSON_E_UNKNOWN_COMMAND,
@@ -2186,10 +2228,12 @@
2186 cson_value * json_page_artifact();
2187 /* Impl in json_branch.c. */
2188 cson_value * json_page_branch();
2189 /* Impl in json_diff.c. */
2190 cson_value * json_page_diff();
 
 
2191 /* Impl in json_login.c. */
2192 cson_value * json_page_login();
2193 /* Impl in json_login.c. */
2194 cson_value * json_page_logout();
2195 /* Impl in json_query.c. */
@@ -2200,10 +2244,13 @@
2200 cson_value * json_page_tag();
2201 /* Impl in json_user.c. */
2202 cson_value * json_page_user();
2203 /* Impl in json_config.c. */
2204 cson_value * json_page_config();
 
 
 
2205 /*
2206 ** Mapping of names to JSON pages/commands. Each name is a subpath of
2207 ** /json (in CGI mode) or a subcommand of the json command in CLI mode
2208 */
2209 static const JsonPageDef JsonPageDefs[] = {
@@ -2212,11 +2259,12 @@
2212 {"artifact", json_page_artifact, 0},
2213 {"branch", json_page_branch,0},
2214 {"cap", json_page_cap, 0},
2215 {"config", json_page_config, 0 },
2216 {"diff", json_page_diff, 0},
2217 {"dir", json_page_nyi, 0},
 
2218 {"g", json_page_g, 0},
2219 {"HAI",json_page_version,0},
2220 {"login",json_page_login,0},
2221 {"logout",json_page_logout,0},
2222 {"query",json_page_query,0},
@@ -2223,49 +2271,16 @@
2223 {"rebuild",json_page_rebuild,0},
2224 {"report", json_page_report, 0},
2225 {"resultCodes", json_page_resultCodes,0},
2226 {"stat",json_page_stat,0},
2227 {"tag", json_page_tag,0},
2228 {"ticket", json_page_nyi,0},
2229 {"timeline", json_page_timeline,0},
2230 {"user",json_page_user,0},
2231 {"version",json_page_version,0},
2232 {"whoami",json_page_whoami,0},
2233 {"wiki",json_page_wiki,0},
2234 /* Last entry MUST have a NULL name. */
2235 {NULL,NULL,0}
2236 };
2237
2238
2239 /*
2240 ** Mapping of /json/ticket/XXX commands/paths to callbacks.
2241 */
2242 static const JsonPageDef JsonPageDefs_Ticket[] = {
2243 {"get", json_page_nyi, 0},
2244 {"list", json_page_nyi, 0},
2245 {"save", json_page_nyi, 1},
2246 {"create", json_page_nyi, 1},
2247 /* Last entry MUST have a NULL name. */
2248 {NULL,NULL,0}
2249 };
2250
2251 /*
2252 ** Mapping of /json/artifact/XXX commands/paths to callbacks.
2253 */
2254 static const JsonPageDef JsonPageDefs_Artifact[] = {
2255 {"vinfo", json_page_nyi, 0},
2256 {"finfo", json_page_nyi, 0},
2257 /* Last entry MUST have a NULL name. */
2258 {NULL,NULL,0}
2259 };
2260
2261 /*
2262 ** Mapping of /json/tag/XXX commands/paths to callbacks.
2263 */
2264 static const JsonPageDef JsonPageDefs_Tag[] = {
2265 {"list", json_page_nyi, 0},
2266 {"create", json_page_nyi, 1},
2267 /* Last entry MUST have a NULL name. */
2268 {NULL,NULL,0}
2269 };
2270
2271 /*
@@ -2295,11 +2310,11 @@
2295 else{
2296 rc = 0;
2297 g.json.dispatchDepth = 1;
2298 payload = (*pageDef->func)();
2299 }
2300 payload = json_create_response(rc, rc ? g.zErrMsg : NULL, payload);
2301 json_send_response(payload);
2302 cson_value_free(payload);
2303 return rc;
2304 }
2305
@@ -2315,26 +2330,16 @@
2315 char const * zCommand;
2316 BEGIN_TIMER;
2317 json_mode_bootstrap();
2318 zCommand = json_command_arg(1);
2319 if(!zCommand || !*zCommand){
2320 goto usage;
 
 
 
2321 }
2322 json_dispatch_root_command( zCommand );
2323 return;
2324 usage:
2325 {
2326 Blob cmdNames = empty_blob;
2327 blob_init(&cmdNames,
2328 "No command (sub-path) specified. Try one of: ",
2329 -1);
2330 json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames);
2331 json_err(FSL_JSON_E_MISSING_ARGS,
2332 blob_str(&cmdNames), 0);
2333 blob_reset(&cmdNames);
2334 }
2335
2336 }
2337 #endif /* FOSSIL_ENABLE_JSON for mkindex */
2338
2339 #ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
2340 /*
@@ -2341,27 +2346,42 @@
2341 ** This function dispatches json commands and is the CLI equivalent of
2342 ** json_page_top().
2343 **
2344 ** COMMAND: json
2345 **
2346 ** Usage: %fossil json SUBCOMMAND
 
 
 
 
2347 **
2348 ** The commands include:
2349 **
 
 
2350 ** branch
2351 ** cap
 
 
 
 
 
 
 
 
2352 ** stat
 
2353 ** timeline
 
2354 ** version (alias: HAI)
 
2355 ** wiki
2356 **
2357 **
2358 ** TODOs:
2359 **
2360 ** tag
2361 ** ticket
2362 ** ...
2363 **
2364 */
2365 void json_cmd_top(void){
2366 char const * cmd = NULL;
2367 int rc = 0;
@@ -2397,18 +2417,18 @@
2397 fossil_exit(1);
2398 }
2399 return;
2400 usage:
2401 {
2402 Blob cmdNames = empty_blob;
2403 blob_init(&cmdNames,
2404 "No subcommand specified. Try one of: ", -1);
2405 json_pagedefs_to_string(&JsonPageDefs[0], &cmdNames);
2406 json_err(FSL_JSON_E_MISSING_ARGS,
2407 blob_str(&cmdNames), 1);
2408 blob_reset(&cmdNames);
2409 fossil_exit(1);
2410 }
2411 }
2412 #endif /* FOSSIL_ENABLE_JSON for mkindex */
2413
2414 #endif /* FOSSIL_ENABLE_JSON */
2415
--- src/json.c
+++ src/json.c
@@ -490,11 +490,11 @@
490
491 /*
492 ** Wrapper around json_getenv() which tries to evaluate a payload/env
493 ** value as a boolean. Uses mostly the same logic as
494 ** json_getenv_int(), with the addition that string values which
495 ** either start with a digit 1..9 or the letters [tTyY] are considered
496 ** to be true. If this function cannot find a matching key/value then
497 ** dflt is returned. e.g. if it finds the key but the value is-a
498 ** Object then dftl is returned.
499 **
500 ** If an entry is found, this function guarantees that it will return
@@ -512,12 +512,14 @@
512 }else if( cson_value_is_string(v) ){
513 char const * sv = cson_string_cstr(cson_value_get_string(v));
514 if(!*sv || ('0'==*sv)){
515 return 0;
516 }else{
517 return ((('1'<=*sv) && ('9'>=*sv))
518 || ('t'==*sv) || ('T'==*sv)
519 || ('y'==*sv) || ('Y'==*sv)
520 )
521 ? 1 : 0;
522 }
523 }else if( cson_value_is_bool(v) ){
524 return cson_value_get_bool(v) ? 1 : 0;
525 }else if( cson_value_is_null(v) ){
@@ -541,11 +543,11 @@
543 /*
544 ** An extended form of find_option() which tries to look up a combo
545 ** GET/POST/CLI argument.
546 **
547 ** zKey must be the GET/POST parameter key. zCLILong must be the "long
548 s** form" CLI flag (NULL means to use zKey). zCLIShort may be NULL or
549 ** the "short form" CLI flag (if NULL, no short form is used).
550 **
551 ** If argPos is >=0 and no other match is found,
552 ** json_command_arg(argPos) is also checked.
553 **
@@ -564,19 +566,22 @@
566 rc = find_option(zCLILong ? zCLILong : zKey,
567 zCLIShort, 1);
568 }
569 if(!rc && fossil_has_json()){
570 rc = json_getenv_cstr(zKey);
571 if(!rc && zCLIShort){
572 rc = cson_value_get_cstr( cson_object_get( g.json.param.o, zCLIShort) );
573 }
574 }
575 if(!rc && (argPos>=0)){
576 rc = json_command_arg((unsigned char)argPos);
577 }
578 return rc;
579 }
580
581 /*
582 ** Short-hand form of json_find_option_cstr2(zKey,zCLILong,zCLIShort,-1).
583 */
584 char const * json_find_option_cstr(char const * zKey,
585 char const * zCLILong,
586 char const * zCLIShort){
587 return json_find_option_cstr2(zKey, zCLILong, zCLIShort, -1);
@@ -602,18 +607,18 @@
607 }
608 return (-1==rc) ? dflt : rc;
609 }
610
611 /*
612 ** The integer equivalent of json_find_option_cstr2().
613 ** If the option is not found, dftl is returned.
614 */
615 int json_find_option_int(char const * zKey,
616 char const * zCLILong,
617 char const * zCLIShort,
618 int dflt ){
619 enum { Magic = -1947854832 };
620 int rc = Magic;
621 if(!g.isHTTP){
622 /* FIXME: use strtol() for better error/dflt handling. */
623 char const * opt = find_option(zCLILong ? zCLILong : zKey,
624 zCLIShort, 1);
@@ -778,14 +783,15 @@
783 }
784 return g.json.authToken;
785 }
786
787 /*
788 ** If g.json.reqPayload.o is NULL then NULL is returned, else the
789 ** given property is searched for in the request payload. If found it
790 ** is returned. The returned value is owned by (or shares ownership
791 ** with) g.json, and must NOT be cson_value_free()'d by the
792 ** caller.
793 */
794 cson_value * json_req_payload_get(char const *pKey){
795 return g.json.reqPayload.o
796 ? cson_object_get(g.json.reqPayload.o,pKey)
797 : NULL;
@@ -979,11 +985,11 @@
985 ** parameters as this function, but returns the results as a JSON
986 ** Array (if splitting produced tokens) or NULL (if splitting failed
987 ** in any way or produced no tokens).
988 **
989 ** The returned value is owned by the caller. If not NULL then it
990 ** _will_ have a JSON type of Array.
991 */
992 cson_value * json_string_split2( char const * zStr,
993 char separator,
994 char doDeHttp ){
995 cson_value * v = cson_value_new_array();
@@ -1166,10 +1172,17 @@
1172 core, which we need before we call
1173 login_check_credentials(). */;
1174 login_check_credentials()/* populates g.perm */;
1175 }
1176 else{
1177 /* FIXME: we need an option which allows us to skip this. At least
1178 one known command (/json/version) does not need an opened
1179 repo. The problem here is we cannot know which functions need
1180 it from here (because command dispatching hasn't yet happened)
1181 and all other commands rely on the repo being opened before
1182 they are called. A textbook example of lack of foresight :/.
1183 */
1184 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
1185 }
1186 }
1187
1188 /*
@@ -1218,24 +1231,10 @@
1231 }else{
1232 ndx = g.json.cmd.offset + ndx;
1233 return cson_string_cstr(cson_value_get_string(cson_array_get( ar, g.json.cmd.offset + ndx )));
1234 }
1235 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1236
1237 /* Returns the C-string form of json_auth_token(), or NULL
1238 ** if json_auth_token() returns NULL.
1239 */
1240 char const * json_auth_token_cstr(){
@@ -1334,13 +1333,15 @@
1333 unsigned int aLen = g.json.dispatchDepth+1; /*cson_array_length_get(g.json.cmd.a);*/
1334 unsigned int i = 1;
1335 for( ; i < aLen; ++i ){
1336 char const * part = cson_string_cstr(cson_value_get_string(cson_array_get(g.json.cmd.a, i)));
1337 if(!part){
1338 #if 1
1339 fossil_warning("Iterating further than expected in %s.",
1340 __FILE__);
1341 #endif
1342 break;
1343 }
1344 blob_appendf(&path,"%s%s", (i>1 ? "/": ""), part);
1345 }
1346 rc = json_new_string((blob_size(&path)>0)
1347 ? blob_buffer(&path)
@@ -1475,13 +1476,13 @@
1476 ** json_err_cstr() is used to get the error string. The caller may
1477 ** provide his own or may use an empty string to suppress the
1478 ** resultText property.
1479 **
1480 */
1481 static cson_value * json_create_response( int resultCode,
1482 char const * pMsg,
1483 cson_value * payload){
1484 cson_value * v = NULL;
1485 cson_value * tmp = NULL;
1486 cson_object * o = NULL;
1487 int rc;
1488 resultCode = json_dumbdown_rc(resultCode ? resultCode : g.json.resultCode);
@@ -1742,19 +1743,39 @@
1743 cson_array_append(a, row);
1744 }
1745 return cson_array_value(a);
1746 }
1747
1748 cson_value * json_stmt_to_array_of_values(Stmt *pStmt,
1749 int resultColumn,
1750 cson_array * pTgt){
1751 cson_array * a = pTgt;
1752 while( (SQLITE_ROW==db_step(pStmt)) ){
1753 cson_value * row = cson_sqlite3_column_to_value(pStmt->pStmt,
1754 resultColumn);
1755 if(row){
1756 if(!a){
1757 a = cson_new_array();
1758 assert(NULL!=a);
1759 }
1760 cson_array_append(a, row);
1761 }
1762 }
1763 return cson_array_value(a);
1764 }
1765
1766 /*
1767 ** Executes the given SQL and runs it through
1768 ** json_stmt_to_array_of_obj(), returning the result of that
1769 ** function. If resetBlob is true then blob_reset(pSql) is called
1770 ** after preparing the query.
1771 **
1772 ** pTgt has the same semantics as described for
1773 ** json_stmt_to_array_of_obj().
1774 **
1775 ** FIXME: change this to take a (char const *) instead of a blob,
1776 ** to simplify the trivial use-cases (which don't need a Blob).
1777 */
1778 cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
1779 char resetBlob){
1780 Stmt q = empty_Stmt;
1781 cson_value * pay = NULL;
@@ -1774,10 +1795,13 @@
1795 ** function returns a JSON Array containing the tag names (owned by
1796 ** the caller), else it returns NULL.
1797 **
1798 ** See info_tags_of_checkin() for more details (this is simply a JSON
1799 ** wrapper for that function).
1800 **
1801 ** If there are no tags then this function returns NULL, not an empty
1802 ** Array.
1803 */
1804 cson_value * json_tags_for_checkin_rid(int rid, char propagatingOnly){
1805 cson_value * v = NULL;
1806 char * tags = info_tags_of_checkin(rid, propagatingOnly);
1807 if(tags){
@@ -1813,15 +1837,11 @@
1837 cson_object * obj = NULL;
1838 cson_string * kRC;
1839 cson_string * kSymbol;
1840 cson_string * kNumber;
1841 cson_string * kDesc;
1842 cson_array_reserve( list, 35 );
 
 
 
 
1843 kRC = cson_new_string("resultCode",10);
1844 kSymbol = cson_new_string("cSymbol",7);
1845 kNumber = cson_new_string("number",6);
1846 kDesc = cson_new_string("description",11);
1847 #define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
@@ -1888,15 +1908,16 @@
1908 FSET(MANIFEST_UUID,"manifestUuid");
1909 FSET(MANIFEST_VERSION,"manifestVersion");
1910 FSET(MANIFEST_DATE,"manifestDate");
1911 FSET(MANIFEST_YEAR,"manifestYear");
1912 FSET(RELEASE_VERSION,"releaseVersion");
 
1913 cson_object_set( jobj, "releaseVersionNumber",
1914 cson_value_new_integer(RELEASE_VERSION_NUMBER) );
1915 cson_object_set( jobj, "resultCodeParanoiaLevel",
1916 cson_value_new_integer(g.json.errorDetailParanoia) );
1917 /*FSET(FOSSIL_JSON_API_VERSION, "jsonApiVersion" );*/
1918 #undef FSET
1919 return jval;
1920 }
1921
1922
1923 /*
@@ -2113,22 +2134,43 @@
2134 }
2135 }
2136 return i;
2137 }
2138
2139 /*
2140 ** Creates an error message using zErrPrefix and the given array of
2141 ** JSON command definitions, and sets the g.json error state to
2142 ** reflect FSL_JSON_E_MISSING_ARGS. If zErrPrefix is NULL then
2143 ** some default is used (e.g. "Try one of: "). If it is "" then
2144 ** no prefix is used.
2145 **
2146 ** The intention is to provide the user (via the response.resultText)
2147 ** a list of available commands/subcommands.
2148 **
2149 */
2150 void json_dispatch_missing_args_err( JsonPageDef const * pCommands,
2151 char const * zErrPrefix ){
2152 Blob cmdNames = empty_blob;
2153 blob_init(&cmdNames,NULL,0);
2154 if( !zErrPrefix ) {
2155 zErrPrefix = "Try one of: ";
2156 }
2157 blob_append( &cmdNames, zErrPrefix, strlen(zErrPrefix) );
2158 json_pagedefs_to_string(pCommands, &cmdNames);
2159 json_set_err(FSL_JSON_E_MISSING_ARGS, "%s",
2160 blob_str(&cmdNames));
2161 blob_reset(&cmdNames);
2162 }
2163
2164 cson_value * json_page_dispatch_helper(JsonPageDef const * pages){
2165 JsonPageDef const * def;
2166 char const * cmd = json_command_arg(1+g.json.dispatchDepth);
2167 assert( NULL != pages );
2168 if( ! cmd ){
2169 json_dispatch_missing_args_err(pages,
2170 "No subcommand specified. "
2171 "Try one of: ");
 
 
 
2172 return NULL;
2173 }
2174 def = json_handler_for_name( cmd, pages );
2175 if(!def){
2176 json_set_err(FSL_JSON_E_UNKNOWN_COMMAND,
@@ -2186,10 +2228,12 @@
2228 cson_value * json_page_artifact();
2229 /* Impl in json_branch.c. */
2230 cson_value * json_page_branch();
2231 /* Impl in json_diff.c. */
2232 cson_value * json_page_diff();
2233 /* Impl in json_dir.c. */
2234 cson_value * json_page_dir();
2235 /* Impl in json_login.c. */
2236 cson_value * json_page_login();
2237 /* Impl in json_login.c. */
2238 cson_value * json_page_logout();
2239 /* Impl in json_query.c. */
@@ -2200,10 +2244,13 @@
2244 cson_value * json_page_tag();
2245 /* Impl in json_user.c. */
2246 cson_value * json_page_user();
2247 /* Impl in json_config.c. */
2248 cson_value * json_page_config();
2249 /* Impl in json_finfo.c. */
2250 cson_value * json_page_finfo();
2251
2252 /*
2253 ** Mapping of names to JSON pages/commands. Each name is a subpath of
2254 ** /json (in CGI mode) or a subcommand of the json command in CLI mode
2255 */
2256 static const JsonPageDef JsonPageDefs[] = {
@@ -2212,11 +2259,12 @@
2259 {"artifact", json_page_artifact, 0},
2260 {"branch", json_page_branch,0},
2261 {"cap", json_page_cap, 0},
2262 {"config", json_page_config, 0 },
2263 {"diff", json_page_diff, 0},
2264 {"dir", json_page_dir, 0},
2265 {"finfo", json_page_finfo, 0},
2266 {"g", json_page_g, 0},
2267 {"HAI",json_page_version,0},
2268 {"login",json_page_login,0},
2269 {"logout",json_page_logout,0},
2270 {"query",json_page_query,0},
@@ -2223,49 +2271,16 @@
2271 {"rebuild",json_page_rebuild,0},
2272 {"report", json_page_report, 0},
2273 {"resultCodes", json_page_resultCodes,0},
2274 {"stat",json_page_stat,0},
2275 {"tag", json_page_tag,0},
2276 /*{"ticket", json_page_nyi,0},*/
2277 {"timeline", json_page_timeline,0},
2278 {"user",json_page_user,0},
2279 {"version",json_page_version,0},
2280 {"whoami",json_page_whoami,0},
2281 {"wiki",json_page_wiki,0},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2282 /* Last entry MUST have a NULL name. */
2283 {NULL,NULL,0}
2284 };
2285
2286 /*
@@ -2295,11 +2310,11 @@
2310 else{
2311 rc = 0;
2312 g.json.dispatchDepth = 1;
2313 payload = (*pageDef->func)();
2314 }
2315 payload = json_create_response(rc, NULL, payload);
2316 json_send_response(payload);
2317 cson_value_free(payload);
2318 return rc;
2319 }
2320
@@ -2315,26 +2330,16 @@
2330 char const * zCommand;
2331 BEGIN_TIMER;
2332 json_mode_bootstrap();
2333 zCommand = json_command_arg(1);
2334 if(!zCommand || !*zCommand){
2335 json_dispatch_missing_args_err( JsonPageDefs,
2336 "No command (sub-path) specified."
2337 " Try one of: ");
2338 return;
2339 }
2340 json_dispatch_root_command( zCommand );
 
 
 
 
 
 
 
 
 
 
 
 
 
2341 }
2342 #endif /* FOSSIL_ENABLE_JSON for mkindex */
2343
2344 #ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
2345 /*
@@ -2341,27 +2346,42 @@
2346 ** This function dispatches json commands and is the CLI equivalent of
2347 ** json_page_top().
2348 **
2349 ** COMMAND: json
2350 **
2351 ** Usage: %fossil json SUBCOMMAND ?OPTIONS?
2352 **
2353 ** In CLI mode, the -R REPO common option is supported. Due to limitations
2354 ** in the argument dispatching code, any -FLAGS must come after the final
2355 ** sub- (or subsub-) command.
2356 **
2357 ** The commands include:
2358 **
2359 ** anonymousPassord
2360 ** artifact
2361 ** branch
2362 ** cap
2363 ** diff
2364 ** g
2365 ** login
2366 ** logout
2367 ** query
2368 ** rebuild
2369 ** report
2370 ** resultCodes
2371 ** stat
2372 ** tag
2373 ** timeline
2374 ** user
2375 ** version (alias: HAI)
2376 ** whoami
2377 ** wiki
2378 **
2379 ** Run '%fossil json' without any subcommand to see the full list (but be
2380 ** aware that some listed might not yet be implemented).
2381 **
2382 ** PS: the notable TODO-commands include: config, dir, finfo, ticket
 
 
2383 **
2384 */
2385 void json_cmd_top(void){
2386 char const * cmd = NULL;
2387 int rc = 0;
@@ -2397,18 +2417,18 @@
2417 fossil_exit(1);
2418 }
2419 return;
2420 usage:
2421 {
2422 cson_value * payload;
2423 json_dispatch_missing_args_err( JsonPageDefs,
2424 "No subcommand specified."
2425 " Try one of: ");
2426 payload = json_create_response(0, NULL, NULL);
2427 json_send_response(payload);
2428 cson_value_free(payload);
2429 fossil_exit(1);
2430 }
2431 }
2432 #endif /* FOSSIL_ENABLE_JSON for mkindex */
2433
2434 #endif /* FOSSIL_ENABLE_JSON */
2435
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -81,47 +81,51 @@
8181
**
8282
** Returned value is NULL or an Object owned by the caller.
8383
*/
8484
cson_value * json_artifact_for_ci( int rid, char showFiles ){
8585
cson_value * v = NULL;
86
- Stmt q;
86
+ Stmt q = empty_Stmt;
8787
static cson_value * eventTypeLabel = NULL;
8888
if(!eventTypeLabel){
8989
eventTypeLabel = json_new_string("checkin");
9090
json_gc_add("$EVENT_TYPE_LABEL(commit)", eventTypeLabel);
9191
}
92
-
93
- db_prepare(&q,
94
- "SELECT uuid, "
95
- " cast(strftime('%%s',mtime) as int), "
96
- " user, "
97
- " comment,"
98
- " strftime('%%s',omtime)"
99
- " FROM blob, event"
100
- " WHERE blob.rid=%d"
101
- " AND event.objid=%d",
92
+
93
+ db_prepare(&q,
94
+ "SELECT b.uuid, "
95
+ " cast(strftime('%%s',e.mtime) as int), "
96
+ " strftime('%%s',e.omtime),"
97
+ " e.user, "
98
+ " e.comment"
99
+ " FROM blob b, event e"
100
+ " WHERE b.rid=%d"
101
+ " AND e.objid=%d",
102102
rid, rid
103103
);
104104
if( db_step(&q)==SQLITE_ROW ){
105105
cson_object * o;
106106
cson_value * tmpV = NULL;
107107
const char *zUuid = db_column_text(&q, 0);
108108
const char *zUser;
109109
const char *zComment;
110110
char * zEUser, * zEComment;
111
-#define ADD_PRIMARY_PARENT_UUID 0 /* temporary local macro */
112
-#if ADD_PRIMARY_PARENT_UUID
113
- char * zParent = NULL;
114
-#endif
115111
int mtime, omtime;
116112
v = cson_value_new_object();
117113
o = cson_value_get_object(v);
118114
#define SET(K,V) cson_object_set(o,(K), (V))
119115
SET("type", eventTypeLabel );
120116
SET("uuid",json_new_string(zUuid));
121117
SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));
122
- zUser = db_column_text(&q,2);
118
+
119
+ mtime = db_column_int(&q,1);
120
+ SET("timestamp",json_new_int(mtime));
121
+ omtime = db_column_int(&q,2);
122
+ if(omtime && (omtime!=mtime)){
123
+ SET("originTime",json_new_int(omtime));
124
+ }
125
+
126
+ zUser = db_column_text(&q,3);
123127
zEUser = db_text(0,
124128
"SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
125129
TAG_USER, rid);
126130
if(zEUser){
127131
SET("user", json_new_string(zEUser));
@@ -131,11 +135,11 @@
131135
free(zEUser);
132136
}else{
133137
SET("user",json_new_string(zUser));
134138
}
135139
136
- zComment = db_column_text(&q,3);
140
+ zComment = db_column_text(&q,4);
137141
zEComment = db_text(0,
138142
"SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
139143
TAG_COMMENT, rid);
140144
if(zEComment){
141145
SET("comment",json_new_string(zEComment));
@@ -145,31 +149,10 @@
145149
free(zEComment);
146150
}else{
147151
SET("comment",json_new_string(zComment));
148152
}
149153
150
- mtime = db_column_int(&q,1);
151
- SET("mtime",json_new_int(mtime));
152
- omtime = db_column_int(&q,4);
153
- if(omtime && (omtime!=mtime)){
154
- SET("originTime",json_new_int(omtime));
155
- }
156
-
157
-#if ADD_PRIMARY_PARENT_UUID
158
- zParent = db_text(0,
159
- "SELECT uuid FROM plink, blob"
160
- " WHERE plink.cid=%d AND blob.rid=plink.pid"
161
- " AND plink.isprim",
162
- rid
163
- );
164
- tmpV = zParent ? json_new_string(zParent) : cson_value_null();
165
- free(zParent);
166
- zParent = NULL;
167
- SET("parentUuid", tmpV );
168
-#endif
169
-#undef ADD_PRIMARY_PARENT_UUID
170
-
171154
tmpV = json_parent_uuids_for_ci(rid);
172155
if(tmpV){
173156
SET("parents", tmpV);
174157
}
175158
@@ -223,12 +206,12 @@
223206
224207
/*
225208
** Sub-impl of /json/artifact for checkins.
226209
*/
227210
static cson_value * json_artifact_ci( int rid ){
228
- if(! g.perm.Read ){
229
- g.json.resultCode = FSL_JSON_E_DENIED;
211
+ if(!g.perm.Read){
212
+ json_set_err( FSL_JSON_E_DENIED, "Viewing checkins requires 'o' privileges." );
230213
return NULL;
231214
}else{
232215
return json_artifact_for_ci(rid, 1);
233216
}
234217
}
@@ -258,18 +241,37 @@
258241
if( ! g.perm.RdWiki ){
259242
json_set_err(FSL_JSON_E_DENIED,
260243
"Requires 'j' privileges.");
261244
return NULL;
262245
}else{
263
- return json_get_wiki_page_by_rid(rid, 0);
246
+ char contentFormat = json_wiki_get_content_format_flag(-9);
247
+ if(-9 == contentFormat){
248
+ contentFormat = json_artifact_include_content_flag() ? -1 : 0;
249
+ }
250
+ return json_get_wiki_page_by_rid(rid, contentFormat);
264251
}
265252
}
253
+
254
+/*
255
+** Internal helper for routines which add a "status" flag to file
256
+** artifact data. isNew and isDel should be the "is this object new?"
257
+** and "is this object removed?" flags of the underlying query. This
258
+** function returns a static string from the set (added, removed,
259
+** modified), depending on the combination of the two args.
260
+**
261
+** Reminder to self: (mlink.pid==0) AS isNew, (mlink.fid==0) AS isDel
262
+*/
263
+char const * json_artifact_status_to_string( char isNew, char isDel ){
264
+ return isNew
265
+ ? "added"
266
+ : (isDel
267
+ ? "removed"
268
+ : "modified");
269
+}
266270
267271
cson_value * json_artifact_file(int rid){
268272
cson_object * pay = NULL;
269
- const char *zMime;
270
- Blob content = empty_blob;
271273
Stmt q = empty_Stmt;
272274
cson_array * checkin_arr = NULL;
273275
274276
if( ! g.perm.Read ){
275277
json_set_err(FSL_JSON_E_DENIED,
@@ -277,32 +279,39 @@
277279
return NULL;
278280
}
279281
280282
pay = cson_new_object();
281283
282
- content_get(rid, &content);
283
- cson_object_set(pay, "contentLength",
284
- json_new_int( blob_size(&content) )
285
- /* achtung: overflow potential on 32-bit builds! */);
286
- zMime = mimetype_from_content(&content);
287
-
288
- cson_object_set(pay, "contentType",
289
- json_new_string(zMime ? zMime : "text/plain"));
290
- if( json_artifact_include_content_flag() && !zMime ){
284
+ if( json_artifact_include_content_flag() ){
285
+ Blob content = empty_blob;
286
+ const char *zMime;
287
+ content_get(rid, &content);
288
+ zMime = mimetype_from_content(&content);
289
+ cson_object_set(pay, "contentType",
290
+ json_new_string(zMime ? zMime : "text/plain"));
291
+ cson_object_set(pay, "size", json_new_int( blob_size(&content)) );
292
+ if(!zMime){
291293
cson_object_set(pay, "content",
292294
cson_value_new_string(blob_str(&content),
293295
(unsigned int)blob_size(&content)));
296
+ }
297
+ blob_reset(&content);
294298
}
295
- blob_reset(&content);
296299
297300
db_prepare(&q,
298301
"SELECT filename.name AS name, "
299
- " cast(strftime('%%s',event.mtime) as int) AS mtime,"
300
- " coalesce(event.ecomment,event.comment) as comment,"
301
- " coalesce(event.euser,event.user) as user,"
302
- " b.uuid as uuid, mlink.mperm as mperm,"
303
- " coalesce((SELECT value FROM tagxref"
302
+ " (mlink.pid==0) AS isNew,"
303
+ " (mlink.fid==0) AS isDel,"
304
+ " cast(strftime('%%s',event.mtime) as int) AS timestamp,"
305
+ " coalesce(event.ecomment,event.comment) as comment,"
306
+ " coalesce(event.euser,event.user) as user,"
307
+ " a.size AS size,"
308
+ " b.uuid as uuid, "
309
+#if 0
310
+ " mlink.mperm as mperm,"
311
+#endif
312
+ " coalesce((SELECT value FROM tagxref"
304313
" WHERE tagid=%d AND tagtype>0 AND "
305314
" rid=mlink.mid),'trunk') as branch"
306315
" FROM mlink, filename, event, blob a, blob b"
307316
" WHERE filename.fnid=mlink.fnid"
308317
" AND event.objid=mlink.mid"
@@ -310,13 +319,25 @@
310319
" AND b.rid=mlink.mid"
311320
" AND mlink.fid=%d"
312321
" ORDER BY filename.name, event.mtime",
313322
TAG_BRANCH, rid
314323
);
324
+ /* TODO: add a "state" flag for the file in each checkin,
325
+ e.g. "modified", "new", "deleted".
326
+ */
315327
checkin_arr = cson_new_array();
316328
cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
317
- json_stmt_to_array_of_obj( &q, checkin_arr );
329
+ while( (SQLITE_ROW==db_step(&q) ) ){
330
+ cson_object * row = cson_value_get_object(cson_sqlite3_row_to_object(q.pStmt));
331
+ char const isNew = cson_value_get_bool(cson_object_get(row,"isNew"));
332
+ char const isDel = cson_value_get_bool(cson_object_get(row,"isDel"));
333
+ cson_object_set(row, "isNew", NULL);
334
+ cson_object_set(row, "isDel", NULL);
335
+ cson_object_set(row, "state",
336
+ json_new_string(json_artifact_status_to_string(isNew, isDel)));
337
+ cson_array_append( checkin_arr, cson_object_value(row) );
338
+ }
318339
db_finalize(&q);
319340
return cson_object_value(pay);
320341
}
321342
322343
/*
@@ -331,14 +352,14 @@
331352
cson_value * entry = NULL;
332353
Blob uuid = empty_blob;
333354
int rc;
334355
int rid = 0;
335356
ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
336
- zName = json_find_option_cstr2("uuid", NULL, NULL, 2);
357
+ zName = json_find_option_cstr2("name", NULL, NULL, g.json.dispatchDepth+1);
337358
if(!zName || !*zName) {
338359
json_set_err(FSL_JSON_E_MISSING_ARGS,
339
- "Missing 'uuid' argument.");
360
+ "Missing 'name' argument.");
340361
return NULL;
341362
}
342363
343364
if( validate16(zName, strlen(zName)) ){
344365
if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
@@ -406,11 +427,11 @@
406427
assert( NULL != zType );
407428
pay = cson_new_object();
408429
cson_object_set( pay, "type", json_new_string(zType) );
409430
/*cson_object_set( pay, "uuid", json_new_string(zUuid) );*/
410431
cson_object_set( pay, "name", json_new_string(zName ? zName : zUuid) );
411
- cson_object_set( pay, "rid", cson_value_new_integer(rid) );
432
+ /*cson_object_set( pay, "rid", cson_value_new_integer(rid) );*/
412433
if(entry){
413434
cson_object_set(pay, "artifact", entry);
414435
}
415436
}
416437
veryend:
417438
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -81,47 +81,51 @@
81 **
82 ** Returned value is NULL or an Object owned by the caller.
83 */
84 cson_value * json_artifact_for_ci( int rid, char showFiles ){
85 cson_value * v = NULL;
86 Stmt q;
87 static cson_value * eventTypeLabel = NULL;
88 if(!eventTypeLabel){
89 eventTypeLabel = json_new_string("checkin");
90 json_gc_add("$EVENT_TYPE_LABEL(commit)", eventTypeLabel);
91 }
92
93 db_prepare(&q,
94 "SELECT uuid, "
95 " cast(strftime('%%s',mtime) as int), "
96 " user, "
97 " comment,"
98 " strftime('%%s',omtime)"
99 " FROM blob, event"
100 " WHERE blob.rid=%d"
101 " AND event.objid=%d",
102 rid, rid
103 );
104 if( db_step(&q)==SQLITE_ROW ){
105 cson_object * o;
106 cson_value * tmpV = NULL;
107 const char *zUuid = db_column_text(&q, 0);
108 const char *zUser;
109 const char *zComment;
110 char * zEUser, * zEComment;
111 #define ADD_PRIMARY_PARENT_UUID 0 /* temporary local macro */
112 #if ADD_PRIMARY_PARENT_UUID
113 char * zParent = NULL;
114 #endif
115 int mtime, omtime;
116 v = cson_value_new_object();
117 o = cson_value_get_object(v);
118 #define SET(K,V) cson_object_set(o,(K), (V))
119 SET("type", eventTypeLabel );
120 SET("uuid",json_new_string(zUuid));
121 SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));
122 zUser = db_column_text(&q,2);
 
 
 
 
 
 
 
 
123 zEUser = db_text(0,
124 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
125 TAG_USER, rid);
126 if(zEUser){
127 SET("user", json_new_string(zEUser));
@@ -131,11 +135,11 @@
131 free(zEUser);
132 }else{
133 SET("user",json_new_string(zUser));
134 }
135
136 zComment = db_column_text(&q,3);
137 zEComment = db_text(0,
138 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
139 TAG_COMMENT, rid);
140 if(zEComment){
141 SET("comment",json_new_string(zEComment));
@@ -145,31 +149,10 @@
145 free(zEComment);
146 }else{
147 SET("comment",json_new_string(zComment));
148 }
149
150 mtime = db_column_int(&q,1);
151 SET("mtime",json_new_int(mtime));
152 omtime = db_column_int(&q,4);
153 if(omtime && (omtime!=mtime)){
154 SET("originTime",json_new_int(omtime));
155 }
156
157 #if ADD_PRIMARY_PARENT_UUID
158 zParent = db_text(0,
159 "SELECT uuid FROM plink, blob"
160 " WHERE plink.cid=%d AND blob.rid=plink.pid"
161 " AND plink.isprim",
162 rid
163 );
164 tmpV = zParent ? json_new_string(zParent) : cson_value_null();
165 free(zParent);
166 zParent = NULL;
167 SET("parentUuid", tmpV );
168 #endif
169 #undef ADD_PRIMARY_PARENT_UUID
170
171 tmpV = json_parent_uuids_for_ci(rid);
172 if(tmpV){
173 SET("parents", tmpV);
174 }
175
@@ -223,12 +206,12 @@
223
224 /*
225 ** Sub-impl of /json/artifact for checkins.
226 */
227 static cson_value * json_artifact_ci( int rid ){
228 if(! g.perm.Read ){
229 g.json.resultCode = FSL_JSON_E_DENIED;
230 return NULL;
231 }else{
232 return json_artifact_for_ci(rid, 1);
233 }
234 }
@@ -258,18 +241,37 @@
258 if( ! g.perm.RdWiki ){
259 json_set_err(FSL_JSON_E_DENIED,
260 "Requires 'j' privileges.");
261 return NULL;
262 }else{
263 return json_get_wiki_page_by_rid(rid, 0);
 
 
 
 
264 }
265 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
267 cson_value * json_artifact_file(int rid){
268 cson_object * pay = NULL;
269 const char *zMime;
270 Blob content = empty_blob;
271 Stmt q = empty_Stmt;
272 cson_array * checkin_arr = NULL;
273
274 if( ! g.perm.Read ){
275 json_set_err(FSL_JSON_E_DENIED,
@@ -277,32 +279,39 @@
277 return NULL;
278 }
279
280 pay = cson_new_object();
281
282 content_get(rid, &content);
283 cson_object_set(pay, "contentLength",
284 json_new_int( blob_size(&content) )
285 /* achtung: overflow potential on 32-bit builds! */);
286 zMime = mimetype_from_content(&content);
287
288 cson_object_set(pay, "contentType",
289 json_new_string(zMime ? zMime : "text/plain"));
290 if( json_artifact_include_content_flag() && !zMime ){
291 cson_object_set(pay, "content",
292 cson_value_new_string(blob_str(&content),
293 (unsigned int)blob_size(&content)));
 
 
294 }
295 blob_reset(&content);
296
297 db_prepare(&q,
298 "SELECT filename.name AS name, "
299 " cast(strftime('%%s',event.mtime) as int) AS mtime,"
300 " coalesce(event.ecomment,event.comment) as comment,"
301 " coalesce(event.euser,event.user) as user,"
302 " b.uuid as uuid, mlink.mperm as mperm,"
303 " coalesce((SELECT value FROM tagxref"
 
 
 
 
 
 
304 " WHERE tagid=%d AND tagtype>0 AND "
305 " rid=mlink.mid),'trunk') as branch"
306 " FROM mlink, filename, event, blob a, blob b"
307 " WHERE filename.fnid=mlink.fnid"
308 " AND event.objid=mlink.mid"
@@ -310,13 +319,25 @@
310 " AND b.rid=mlink.mid"
311 " AND mlink.fid=%d"
312 " ORDER BY filename.name, event.mtime",
313 TAG_BRANCH, rid
314 );
 
 
 
315 checkin_arr = cson_new_array();
316 cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
317 json_stmt_to_array_of_obj( &q, checkin_arr );
 
 
 
 
 
 
 
 
 
318 db_finalize(&q);
319 return cson_object_value(pay);
320 }
321
322 /*
@@ -331,14 +352,14 @@
331 cson_value * entry = NULL;
332 Blob uuid = empty_blob;
333 int rc;
334 int rid = 0;
335 ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
336 zName = json_find_option_cstr2("uuid", NULL, NULL, 2);
337 if(!zName || !*zName) {
338 json_set_err(FSL_JSON_E_MISSING_ARGS,
339 "Missing 'uuid' argument.");
340 return NULL;
341 }
342
343 if( validate16(zName, strlen(zName)) ){
344 if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
@@ -406,11 +427,11 @@
406 assert( NULL != zType );
407 pay = cson_new_object();
408 cson_object_set( pay, "type", json_new_string(zType) );
409 /*cson_object_set( pay, "uuid", json_new_string(zUuid) );*/
410 cson_object_set( pay, "name", json_new_string(zName ? zName : zUuid) );
411 cson_object_set( pay, "rid", cson_value_new_integer(rid) );
412 if(entry){
413 cson_object_set(pay, "artifact", entry);
414 }
415 }
416 veryend:
417
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -81,47 +81,51 @@
81 **
82 ** Returned value is NULL or an Object owned by the caller.
83 */
84 cson_value * json_artifact_for_ci( int rid, char showFiles ){
85 cson_value * v = NULL;
86 Stmt q = empty_Stmt;
87 static cson_value * eventTypeLabel = NULL;
88 if(!eventTypeLabel){
89 eventTypeLabel = json_new_string("checkin");
90 json_gc_add("$EVENT_TYPE_LABEL(commit)", eventTypeLabel);
91 }
92
93 db_prepare(&q,
94 "SELECT b.uuid, "
95 " cast(strftime('%%s',e.mtime) as int), "
96 " strftime('%%s',e.omtime),"
97 " e.user, "
98 " e.comment"
99 " FROM blob b, event e"
100 " WHERE b.rid=%d"
101 " AND e.objid=%d",
102 rid, rid
103 );
104 if( db_step(&q)==SQLITE_ROW ){
105 cson_object * o;
106 cson_value * tmpV = NULL;
107 const char *zUuid = db_column_text(&q, 0);
108 const char *zUser;
109 const char *zComment;
110 char * zEUser, * zEComment;
 
 
 
 
111 int mtime, omtime;
112 v = cson_value_new_object();
113 o = cson_value_get_object(v);
114 #define SET(K,V) cson_object_set(o,(K), (V))
115 SET("type", eventTypeLabel );
116 SET("uuid",json_new_string(zUuid));
117 SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));
118
119 mtime = db_column_int(&q,1);
120 SET("timestamp",json_new_int(mtime));
121 omtime = db_column_int(&q,2);
122 if(omtime && (omtime!=mtime)){
123 SET("originTime",json_new_int(omtime));
124 }
125
126 zUser = db_column_text(&q,3);
127 zEUser = db_text(0,
128 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
129 TAG_USER, rid);
130 if(zEUser){
131 SET("user", json_new_string(zEUser));
@@ -131,11 +135,11 @@
135 free(zEUser);
136 }else{
137 SET("user",json_new_string(zUser));
138 }
139
140 zComment = db_column_text(&q,4);
141 zEComment = db_text(0,
142 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
143 TAG_COMMENT, rid);
144 if(zEComment){
145 SET("comment",json_new_string(zEComment));
@@ -145,31 +149,10 @@
149 free(zEComment);
150 }else{
151 SET("comment",json_new_string(zComment));
152 }
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154 tmpV = json_parent_uuids_for_ci(rid);
155 if(tmpV){
156 SET("parents", tmpV);
157 }
158
@@ -223,12 +206,12 @@
206
207 /*
208 ** Sub-impl of /json/artifact for checkins.
209 */
210 static cson_value * json_artifact_ci( int rid ){
211 if(!g.perm.Read){
212 json_set_err( FSL_JSON_E_DENIED, "Viewing checkins requires 'o' privileges." );
213 return NULL;
214 }else{
215 return json_artifact_for_ci(rid, 1);
216 }
217 }
@@ -258,18 +241,37 @@
241 if( ! g.perm.RdWiki ){
242 json_set_err(FSL_JSON_E_DENIED,
243 "Requires 'j' privileges.");
244 return NULL;
245 }else{
246 char contentFormat = json_wiki_get_content_format_flag(-9);
247 if(-9 == contentFormat){
248 contentFormat = json_artifact_include_content_flag() ? -1 : 0;
249 }
250 return json_get_wiki_page_by_rid(rid, contentFormat);
251 }
252 }
253
254 /*
255 ** Internal helper for routines which add a "status" flag to file
256 ** artifact data. isNew and isDel should be the "is this object new?"
257 ** and "is this object removed?" flags of the underlying query. This
258 ** function returns a static string from the set (added, removed,
259 ** modified), depending on the combination of the two args.
260 **
261 ** Reminder to self: (mlink.pid==0) AS isNew, (mlink.fid==0) AS isDel
262 */
263 char const * json_artifact_status_to_string( char isNew, char isDel ){
264 return isNew
265 ? "added"
266 : (isDel
267 ? "removed"
268 : "modified");
269 }
270
271 cson_value * json_artifact_file(int rid){
272 cson_object * pay = NULL;
 
 
273 Stmt q = empty_Stmt;
274 cson_array * checkin_arr = NULL;
275
276 if( ! g.perm.Read ){
277 json_set_err(FSL_JSON_E_DENIED,
@@ -277,32 +279,39 @@
279 return NULL;
280 }
281
282 pay = cson_new_object();
283
284 if( json_artifact_include_content_flag() ){
285 Blob content = empty_blob;
286 const char *zMime;
287 content_get(rid, &content);
288 zMime = mimetype_from_content(&content);
289 cson_object_set(pay, "contentType",
290 json_new_string(zMime ? zMime : "text/plain"));
291 cson_object_set(pay, "size", json_new_int( blob_size(&content)) );
292 if(!zMime){
293 cson_object_set(pay, "content",
294 cson_value_new_string(blob_str(&content),
295 (unsigned int)blob_size(&content)));
296 }
297 blob_reset(&content);
298 }
 
299
300 db_prepare(&q,
301 "SELECT filename.name AS name, "
302 " (mlink.pid==0) AS isNew,"
303 " (mlink.fid==0) AS isDel,"
304 " cast(strftime('%%s',event.mtime) as int) AS timestamp,"
305 " coalesce(event.ecomment,event.comment) as comment,"
306 " coalesce(event.euser,event.user) as user,"
307 " a.size AS size,"
308 " b.uuid as uuid, "
309 #if 0
310 " mlink.mperm as mperm,"
311 #endif
312 " coalesce((SELECT value FROM tagxref"
313 " WHERE tagid=%d AND tagtype>0 AND "
314 " rid=mlink.mid),'trunk') as branch"
315 " FROM mlink, filename, event, blob a, blob b"
316 " WHERE filename.fnid=mlink.fnid"
317 " AND event.objid=mlink.mid"
@@ -310,13 +319,25 @@
319 " AND b.rid=mlink.mid"
320 " AND mlink.fid=%d"
321 " ORDER BY filename.name, event.mtime",
322 TAG_BRANCH, rid
323 );
324 /* TODO: add a "state" flag for the file in each checkin,
325 e.g. "modified", "new", "deleted".
326 */
327 checkin_arr = cson_new_array();
328 cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
329 while( (SQLITE_ROW==db_step(&q) ) ){
330 cson_object * row = cson_value_get_object(cson_sqlite3_row_to_object(q.pStmt));
331 char const isNew = cson_value_get_bool(cson_object_get(row,"isNew"));
332 char const isDel = cson_value_get_bool(cson_object_get(row,"isDel"));
333 cson_object_set(row, "isNew", NULL);
334 cson_object_set(row, "isDel", NULL);
335 cson_object_set(row, "state",
336 json_new_string(json_artifact_status_to_string(isNew, isDel)));
337 cson_array_append( checkin_arr, cson_object_value(row) );
338 }
339 db_finalize(&q);
340 return cson_object_value(pay);
341 }
342
343 /*
@@ -331,14 +352,14 @@
352 cson_value * entry = NULL;
353 Blob uuid = empty_blob;
354 int rc;
355 int rid = 0;
356 ArtifactDispatchEntry const * dispatcher = &ArtifactDispatchList[0];
357 zName = json_find_option_cstr2("name", NULL, NULL, g.json.dispatchDepth+1);
358 if(!zName || !*zName) {
359 json_set_err(FSL_JSON_E_MISSING_ARGS,
360 "Missing 'name' argument.");
361 return NULL;
362 }
363
364 if( validate16(zName, strlen(zName)) ){
365 if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
@@ -406,11 +427,11 @@
427 assert( NULL != zType );
428 pay = cson_new_object();
429 cson_object_set( pay, "type", json_new_string(zType) );
430 /*cson_object_set( pay, "uuid", json_new_string(zUuid) );*/
431 cson_object_set( pay, "name", json_new_string(zName ? zName : zUuid) );
432 /*cson_object_set( pay, "rid", cson_value_new_integer(rid) );*/
433 if(entry){
434 cson_object_set(pay, "artifact", entry);
435 }
436 }
437 veryend:
438
--- src/json_detail.h
+++ src/json_detail.h
@@ -17,10 +17,19 @@
1717
** http://www.hwaci.com/drh/
1818
**
1919
*/
2020
2121
#include "cson_amalgamation.h"
22
+
23
+/**
24
+ FOSSIL_JSON_API_VERSION holds the date (YYYYMMDD) of the latest
25
+ "significant" change to the JSON API (a change in an interface
26
+ or new functionality). It is sent as part of the /json/version
27
+ request. We could arguably add it to each response.
28
+*/
29
+#define FOSSIL_JSON_API_VERSION "20120409"
30
+
2231
/*
2332
** Impl details for the JSON API which need to be shared
2433
** across multiple C files.
2534
*/
2635
@@ -33,10 +42,14 @@
3342
** for warning codes.
3443
**
3544
** Numbers evenly dividable by 100 are "categories", and error codes
3645
** for a given category have their high bits set to the category
3746
** value.
47
+**
48
+** Maintenance reminder: when entries are added to this list, update
49
+** the code in json_page_resultCodes() and json_err_cstr() (both in
50
+** json.c)!
3851
**
3952
*/
4053
enum FossilJsonCodes {
4154
FSL_JSON_W_START = 0,
4255
FSL_JSON_W_UNKNOWN /*+1*/,
4356
--- src/json_detail.h
+++ src/json_detail.h
@@ -17,10 +17,19 @@
17 ** http://www.hwaci.com/drh/
18 **
19 */
20
21 #include "cson_amalgamation.h"
 
 
 
 
 
 
 
 
 
22 /*
23 ** Impl details for the JSON API which need to be shared
24 ** across multiple C files.
25 */
26
@@ -33,10 +42,14 @@
33 ** for warning codes.
34 **
35 ** Numbers evenly dividable by 100 are "categories", and error codes
36 ** for a given category have their high bits set to the category
37 ** value.
 
 
 
 
38 **
39 */
40 enum FossilJsonCodes {
41 FSL_JSON_W_START = 0,
42 FSL_JSON_W_UNKNOWN /*+1*/,
43
--- src/json_detail.h
+++ src/json_detail.h
@@ -17,10 +17,19 @@
17 ** http://www.hwaci.com/drh/
18 **
19 */
20
21 #include "cson_amalgamation.h"
22
23 /**
24 FOSSIL_JSON_API_VERSION holds the date (YYYYMMDD) of the latest
25 "significant" change to the JSON API (a change in an interface
26 or new functionality). It is sent as part of the /json/version
27 request. We could arguably add it to each response.
28 */
29 #define FOSSIL_JSON_API_VERSION "20120409"
30
31 /*
32 ** Impl details for the JSON API which need to be shared
33 ** across multiple C files.
34 */
35
@@ -33,10 +42,14 @@
42 ** for warning codes.
43 **
44 ** Numbers evenly dividable by 100 are "categories", and error codes
45 ** for a given category have their high bits set to the category
46 ** value.
47 **
48 ** Maintenance reminder: when entries are added to this list, update
49 ** the code in json_page_resultCodes() and json_err_cstr() (both in
50 ** json.c)!
51 **
52 */
53 enum FossilJsonCodes {
54 FSL_JSON_W_START = 0,
55 FSL_JSON_W_UNKNOWN /*+1*/,
56
+12 -5
--- src/json_diff.c
+++ src/json_diff.c
@@ -29,20 +29,24 @@
2929
** Generates a diff between two versions (zFrom and zTo), using nContext
3030
** content lines in the output. On success, returns a new JSON String
3131
** object. On error it sets g.json's error state and returns NULL.
3232
**
3333
** If fSbs is true (non-0) them side-by-side diffs are used.
34
+**
35
+** If fHtml is true then HTML markup is added to the diff.
3436
*/
3537
cson_value * json_generate_diff(const char *zFrom, const char *zTo,
36
- int nContext, char fSbs){
38
+ int nContext, char fSbs,
39
+ char fHtml){
3740
int fromid;
3841
int toid;
3942
int outLen;
4043
Blob from = empty_blob, to = empty_blob, out = empty_blob;
4144
cson_value * rc = NULL;
4245
int flags = (DIFF_CONTEXT_MASK & nContext)
43
- | (fSbs ? DIFF_SIDEBYSIDE : 0);
46
+ | (fSbs ? DIFF_SIDEBYSIDE : 0)
47
+ | (fHtml ? DIFF_HTML : 0);
4448
fromid = name_to_typed_rid(zFrom, "*");
4549
if(fromid<=0){
4650
json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
4751
"Could not resolve 'from' ID.");
4852
return NULL;
@@ -58,12 +62,13 @@
5862
blob_zero(&out);
5963
text_diff(&from, &to, &out, flags);
6064
blob_reset(&from);
6165
blob_reset(&to);
6266
outLen = blob_size(&out);
63
- if(outLen>0){
64
- rc = cson_value_new_string(blob_buffer(&out), blob_size(&out));
67
+ if(outLen>=0){
68
+ rc = cson_value_new_string(blob_buffer(&out),
69
+ (unsigned int)blob_size(&out));
6570
}
6671
blob_reset(&out);
6772
return rc;
6873
}
6974
@@ -84,10 +89,11 @@
8489
cson_value * v = NULL;
8590
char const * zFrom;
8691
char const * zTo;
8792
int nContext = 0;
8893
char doSBS;
94
+ char doHtml;
8995
if(!g.perm.Read){
9096
json_set_err(FSL_JSON_E_DENIED,
9197
"Requires 'o' permissions.");
9298
return NULL;
9399
}
@@ -109,11 +115,12 @@
109115
"Required 'v2' parameter is missing.");
110116
return NULL;
111117
}
112118
nContext = json_find_option_int("context",NULL,"c",5);
113119
doSBS = json_find_option_bool("sbs",NULL,"y",0);
114
- v = json_generate_diff(zFrom, zTo, nContext, doSBS);
120
+ doHtml = json_find_option_bool("html",NULL,"h",0);
121
+ v = json_generate_diff(zFrom, zTo, nContext, doSBS, doHtml);
115122
if(!v){
116123
if(!g.json.resultCode){
117124
json_set_err(FSL_JSON_E_UNKNOWN,
118125
"Generating diff failed for unknown reason.");
119126
}
120127
121128
ADDED src/json_dir.c
122129
ADDED src/json_finfo.c
--- src/json_diff.c
+++ src/json_diff.c
@@ -29,20 +29,24 @@
29 ** Generates a diff between two versions (zFrom and zTo), using nContext
30 ** content lines in the output. On success, returns a new JSON String
31 ** object. On error it sets g.json's error state and returns NULL.
32 **
33 ** If fSbs is true (non-0) them side-by-side diffs are used.
 
 
34 */
35 cson_value * json_generate_diff(const char *zFrom, const char *zTo,
36 int nContext, char fSbs){
 
37 int fromid;
38 int toid;
39 int outLen;
40 Blob from = empty_blob, to = empty_blob, out = empty_blob;
41 cson_value * rc = NULL;
42 int flags = (DIFF_CONTEXT_MASK & nContext)
43 | (fSbs ? DIFF_SIDEBYSIDE : 0);
 
44 fromid = name_to_typed_rid(zFrom, "*");
45 if(fromid<=0){
46 json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
47 "Could not resolve 'from' ID.");
48 return NULL;
@@ -58,12 +62,13 @@
58 blob_zero(&out);
59 text_diff(&from, &to, &out, flags);
60 blob_reset(&from);
61 blob_reset(&to);
62 outLen = blob_size(&out);
63 if(outLen>0){
64 rc = cson_value_new_string(blob_buffer(&out), blob_size(&out));
 
65 }
66 blob_reset(&out);
67 return rc;
68 }
69
@@ -84,10 +89,11 @@
84 cson_value * v = NULL;
85 char const * zFrom;
86 char const * zTo;
87 int nContext = 0;
88 char doSBS;
 
89 if(!g.perm.Read){
90 json_set_err(FSL_JSON_E_DENIED,
91 "Requires 'o' permissions.");
92 return NULL;
93 }
@@ -109,11 +115,12 @@
109 "Required 'v2' parameter is missing.");
110 return NULL;
111 }
112 nContext = json_find_option_int("context",NULL,"c",5);
113 doSBS = json_find_option_bool("sbs",NULL,"y",0);
114 v = json_generate_diff(zFrom, zTo, nContext, doSBS);
 
115 if(!v){
116 if(!g.json.resultCode){
117 json_set_err(FSL_JSON_E_UNKNOWN,
118 "Generating diff failed for unknown reason.");
119 }
120
121 DDED src/json_dir.c
122 DDED src/json_finfo.c
--- src/json_diff.c
+++ src/json_diff.c
@@ -29,20 +29,24 @@
29 ** Generates a diff between two versions (zFrom and zTo), using nContext
30 ** content lines in the output. On success, returns a new JSON String
31 ** object. On error it sets g.json's error state and returns NULL.
32 **
33 ** If fSbs is true (non-0) them side-by-side diffs are used.
34 **
35 ** If fHtml is true then HTML markup is added to the diff.
36 */
37 cson_value * json_generate_diff(const char *zFrom, const char *zTo,
38 int nContext, char fSbs,
39 char fHtml){
40 int fromid;
41 int toid;
42 int outLen;
43 Blob from = empty_blob, to = empty_blob, out = empty_blob;
44 cson_value * rc = NULL;
45 int flags = (DIFF_CONTEXT_MASK & nContext)
46 | (fSbs ? DIFF_SIDEBYSIDE : 0)
47 | (fHtml ? DIFF_HTML : 0);
48 fromid = name_to_typed_rid(zFrom, "*");
49 if(fromid<=0){
50 json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
51 "Could not resolve 'from' ID.");
52 return NULL;
@@ -58,12 +62,13 @@
62 blob_zero(&out);
63 text_diff(&from, &to, &out, flags);
64 blob_reset(&from);
65 blob_reset(&to);
66 outLen = blob_size(&out);
67 if(outLen>=0){
68 rc = cson_value_new_string(blob_buffer(&out),
69 (unsigned int)blob_size(&out));
70 }
71 blob_reset(&out);
72 return rc;
73 }
74
@@ -84,10 +89,11 @@
89 cson_value * v = NULL;
90 char const * zFrom;
91 char const * zTo;
92 int nContext = 0;
93 char doSBS;
94 char doHtml;
95 if(!g.perm.Read){
96 json_set_err(FSL_JSON_E_DENIED,
97 "Requires 'o' permissions.");
98 return NULL;
99 }
@@ -109,11 +115,12 @@
115 "Required 'v2' parameter is missing.");
116 return NULL;
117 }
118 nContext = json_find_option_int("context",NULL,"c",5);
119 doSBS = json_find_option_bool("sbs",NULL,"y",0);
120 doHtml = json_find_option_bool("html",NULL,"h",0);
121 v = json_generate_diff(zFrom, zTo, nContext, doSBS, doHtml);
122 if(!v){
123 if(!g.json.resultCode){
124 json_set_err(FSL_JSON_E_UNKNOWN,
125 "Generating diff failed for unknown reason.");
126 }
127
128 DDED src/json_dir.c
129 DDED src/json_finfo.c
--- a/src/json_dir.c
+++ b/src/json_dir.c
@@ -0,0 +1,49 @@
1
+#ifdef FOSSIL_E(c)LE_JSON
2
+/*
3
+** Copyright (c) 2011 D. Richard Hipp
4
+**
5
+** This program is free software; you can redistribute it and/or
6
+** modify it under the terms of the Simplified BSD License (also
7
+** known as the "2-Clause License" or "FreeBSD License".)
8
+**
9
+** This program is distributed in the hope that it will be useful,
10
+** but without any warranty; without even the implied warranty of
11
+** merchantability or fitness for a particular purpose.
12
+**
13
+** Author contact information:
14
+** [email protected]
15
+** http://www.hwaci.com/drh/
16
+**
17
+*/
18
+#include "VERSION.h"
19
+#include "config.h"
20
+#include "json_dir.h"
21
+
22
+#if INTERFACE
23
+#include "json_detail.h"
24
+#endif
25
+
26
+static cson_e json_page_dir_list(void);
27
+/*
28
+** Mapping of /json/wiki/XXX commastatic const JsonPageDef JsonPageDefs_Dir[] = {
29
+/* Last entry MUST have a NULLands/pathsTODO: Not used? */
30
+static char c){
31
+ static char const * zP = NULL;
32
+ if( !zP ){
33
+ zP = g.zExtra;
34
+ while(zP && *zP && ('/'==*zP)){
35
+ ++zP;
36
+ }
37
+ }
38
+ return zP;
39
+}
40
+#endif
41
+
42
+/*
43
+** Impl of /json/dir. 98% of it was taken directly
44
+** from browse.c::page_dir()
45
+*/
46
+static cson_value * json_page_dir_list(E_JSON
47
+/*
48
+** Copyright (c) 2011 D. Richard Hipp
49
+**3istory
--- a/src/json_dir.c
+++ b/src/json_dir.c
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/json_dir.c
+++ b/src/json_dir.c
@@ -0,0 +1,49 @@
1 #ifdef FOSSIL_E(c)LE_JSON
2 /*
3 ** Copyright (c) 2011 D. Richard Hipp
4 **
5 ** This program is free software; you can redistribute it and/or
6 ** modify it under the terms of the Simplified BSD License (also
7 ** known as the "2-Clause License" or "FreeBSD License".)
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but without any warranty; without even the implied warranty of
11 ** merchantability or fitness for a particular purpose.
12 **
13 ** Author contact information:
14 ** [email protected]
15 ** http://www.hwaci.com/drh/
16 **
17 */
18 #include "VERSION.h"
19 #include "config.h"
20 #include "json_dir.h"
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 static cson_e json_page_dir_list(void);
27 /*
28 ** Mapping of /json/wiki/XXX commastatic const JsonPageDef JsonPageDefs_Dir[] = {
29 /* Last entry MUST have a NULLands/pathsTODO: Not used? */
30 static char c){
31 static char const * zP = NULL;
32 if( !zP ){
33 zP = g.zExtra;
34 while(zP && *zP && ('/'==*zP)){
35 ++zP;
36 }
37 }
38 return zP;
39 }
40 #endif
41
42 /*
43 ** Impl of /json/dir. 98% of it was taken directly
44 ** from browse.c::page_dir()
45 */
46 static cson_value * json_page_dir_list(E_JSON
47 /*
48 ** Copyright (c) 2011 D. Richard Hipp
49 **3istory
--- a/src/json_finfo.c
+++ b/src/json_finfo.c
@@ -0,0 +1,9 @@
1
+#ifdef FOSSI#ifdef FOSSIL_ENABLE_JSON
2
+/*
3
+** Copyright (c) 2011 D. Richard Hipp
4
+**
5
+** This pr_ENABLE_JSON
6
+/*
7
+** Copyright (c) 2011 D. Richard Hipp
8
+**
9
+** This pr
--- a/src/json_finfo.c
+++ b/src/json_finfo.c
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
--- a/src/json_finfo.c
+++ b/src/json_finfo.c
@@ -0,0 +1,9 @@
1 #ifdef FOSSI#ifdef FOSSIL_ENABLE_JSON
2 /*
3 ** Copyright (c) 2011 D. Richard Hipp
4 **
5 ** This pr_ENABLE_JSON
6 /*
7 ** Copyright (c) 2011 D. Richard Hipp
8 **
9 ** This pr
--- src/json_login.c
+++ src/json_login.c
@@ -52,21 +52,21 @@
5252
then ONLY a GET param of "name" will match ("n"
5353
is not recognized). If we reverse the order of the
5454
checks then both forms work. Strangely enough, the
5555
"p"/"password" check is not affected by this.
5656
*/
57
- char const * name = cson_value_get_cstr(json_payload_property("name"));
57
+ char const * name = cson_value_get_cstr(json_req_payload_get("name"));
5858
char const * pw = NULL;
5959
char const * anonSeed = NULL;
6060
cson_value * payload = NULL;
6161
int uid = 0;
6262
/* reminder to self: Fossil internally (for the sake of /wiki)
6363
interprets paths in the form /foo/bar/baz such that P("name") ==
6464
"bar/baz". This collides with our name/password checking, and
6565
thus we do some rather elaborate name=... checking.
6666
*/
67
- pw = cson_value_get_cstr(json_payload_property("password"));
67
+ pw = cson_value_get_cstr(json_req_payload_get("password"));
6868
if( !pw ){
6969
pw = PD("p",NULL);
7070
if( !pw ){
7171
pw = PD("password",NULL);
7272
}
@@ -99,11 +99,11 @@
9999
};
100100
static char seedBuffer[SeedBufLen];
101101
cson_value const * jseed = json_getenv(FossilJsonKeys.anonymousSeed);
102102
seedBuffer[0] = 0;
103103
if( !jseed ){
104
- jseed = json_payload_property(FossilJsonKeys.anonymousSeed);
104
+ jseed = json_req_payload_get(FossilJsonKeys.anonymousSeed);
105105
if( !jseed ){
106106
jseed = json_getenv("cs") /* name used by HTML interface */;
107107
}
108108
}
109109
if(jseed){
110110
--- src/json_login.c
+++ src/json_login.c
@@ -52,21 +52,21 @@
52 then ONLY a GET param of "name" will match ("n"
53 is not recognized). If we reverse the order of the
54 checks then both forms work. Strangely enough, the
55 "p"/"password" check is not affected by this.
56 */
57 char const * name = cson_value_get_cstr(json_payload_property("name"));
58 char const * pw = NULL;
59 char const * anonSeed = NULL;
60 cson_value * payload = NULL;
61 int uid = 0;
62 /* reminder to self: Fossil internally (for the sake of /wiki)
63 interprets paths in the form /foo/bar/baz such that P("name") ==
64 "bar/baz". This collides with our name/password checking, and
65 thus we do some rather elaborate name=... checking.
66 */
67 pw = cson_value_get_cstr(json_payload_property("password"));
68 if( !pw ){
69 pw = PD("p",NULL);
70 if( !pw ){
71 pw = PD("password",NULL);
72 }
@@ -99,11 +99,11 @@
99 };
100 static char seedBuffer[SeedBufLen];
101 cson_value const * jseed = json_getenv(FossilJsonKeys.anonymousSeed);
102 seedBuffer[0] = 0;
103 if( !jseed ){
104 jseed = json_payload_property(FossilJsonKeys.anonymousSeed);
105 if( !jseed ){
106 jseed = json_getenv("cs") /* name used by HTML interface */;
107 }
108 }
109 if(jseed){
110
--- src/json_login.c
+++ src/json_login.c
@@ -52,21 +52,21 @@
52 then ONLY a GET param of "name" will match ("n"
53 is not recognized). If we reverse the order of the
54 checks then both forms work. Strangely enough, the
55 "p"/"password" check is not affected by this.
56 */
57 char const * name = cson_value_get_cstr(json_req_payload_get("name"));
58 char const * pw = NULL;
59 char const * anonSeed = NULL;
60 cson_value * payload = NULL;
61 int uid = 0;
62 /* reminder to self: Fossil internally (for the sake of /wiki)
63 interprets paths in the form /foo/bar/baz such that P("name") ==
64 "bar/baz". This collides with our name/password checking, and
65 thus we do some rather elaborate name=... checking.
66 */
67 pw = cson_value_get_cstr(json_req_payload_get("password"));
68 if( !pw ){
69 pw = PD("p",NULL);
70 if( !pw ){
71 pw = PD("password",NULL);
72 }
@@ -99,11 +99,11 @@
99 };
100 static char seedBuffer[SeedBufLen];
101 cson_value const * jseed = json_getenv(FossilJsonKeys.anonymousSeed);
102 seedBuffer[0] = 0;
103 if( !jseed ){
104 jseed = json_req_payload_get(FossilJsonKeys.anonymousSeed);
105 if( !jseed ){
106 jseed = json_getenv("cs") /* name used by HTML interface */;
107 }
108 }
109 if(jseed){
110
--- src/json_report.c
+++ src/json_report.c
@@ -101,11 +101,11 @@
101101
}
102102
103103
db_prepare(&q,"SELECT rn AS report,"
104104
" owner AS owner,"
105105
" title AS title,"
106
- " cast(strftime('%%s',mtime) as int) as mtime,"
106
+ " cast(strftime('%%s',mtime) as int) as timestamp,"
107107
" cols as columns,"
108108
" sqlcode as sqlCode"
109109
" FROM reportfmt"
110110
" WHERE rn=%d",
111111
nReport);
112112
--- src/json_report.c
+++ src/json_report.c
@@ -101,11 +101,11 @@
101 }
102
103 db_prepare(&q,"SELECT rn AS report,"
104 " owner AS owner,"
105 " title AS title,"
106 " cast(strftime('%%s',mtime) as int) as mtime,"
107 " cols as columns,"
108 " sqlcode as sqlCode"
109 " FROM reportfmt"
110 " WHERE rn=%d",
111 nReport);
112
--- src/json_report.c
+++ src/json_report.c
@@ -101,11 +101,11 @@
101 }
102
103 db_prepare(&q,"SELECT rn AS report,"
104 " owner AS owner,"
105 " title AS title,"
106 " cast(strftime('%%s',mtime) as int) as timestamp,"
107 " cols as columns,"
108 " sqlcode as sqlCode"
109 " FROM reportfmt"
110 " WHERE rn=%d",
111 nReport);
112
+1 -1
--- src/json_tag.c
+++ src/json_tag.c
@@ -276,11 +276,11 @@
276276
" SELECT"
277277
#if 0
278278
" blob.rid AS rid,"
279279
#endif
280280
" uuid AS uuid,"
281
- " cast(strftime('%s',event.mtime) as int) AS mtime,"
281
+ " cast(strftime('%s',event.mtime) as int) AS timestamp,"
282282
" coalesce(ecomment,comment) AS comment,"
283283
" coalesce(euser,user) AS user,"
284284
" CASE event.type"
285285
" WHEN 'ci' THEN 'checkin'"
286286
" WHEN 'w' THEN 'wiki'"
287287
--- src/json_tag.c
+++ src/json_tag.c
@@ -276,11 +276,11 @@
276 " SELECT"
277 #if 0
278 " blob.rid AS rid,"
279 #endif
280 " uuid AS uuid,"
281 " cast(strftime('%s',event.mtime) as int) AS mtime,"
282 " coalesce(ecomment,comment) AS comment,"
283 " coalesce(euser,user) AS user,"
284 " CASE event.type"
285 " WHEN 'ci' THEN 'checkin'"
286 " WHEN 'w' THEN 'wiki'"
287
--- src/json_tag.c
+++ src/json_tag.c
@@ -276,11 +276,11 @@
276 " SELECT"
277 #if 0
278 " blob.rid AS rid,"
279 #endif
280 " uuid AS uuid,"
281 " cast(strftime('%s',event.mtime) as int) AS timestamp,"
282 " coalesce(ecomment,comment) AS comment,"
283 " coalesce(euser,user) AS user,"
284 " CASE event.type"
285 " WHEN 'ci' THEN 'checkin'"
286 " WHEN 'w' THEN 'wiki'"
287
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -35,14 +35,11 @@
3535
that we end up with HTTP clients using 3 different names
3636
for the same requests.
3737
*/
3838
{"branch", json_timeline_branch, 0},
3939
{"checkin", json_timeline_ci, 0},
40
-{"ci", json_timeline_ci, -1},
41
-{"t", json_timeline_ticket, -1},
4240
{"ticket", json_timeline_ticket, 0},
43
-{"w", json_timeline_wiki, -1},
4441
{"wiki", json_timeline_wiki, 0},
4542
/* Last entry MUST have a NULL name. */
4643
{NULL,NULL,0}
4744
};
4845
@@ -100,11 +97,11 @@
10097
static const char zBaseSql[] =
10198
@ SELECT
10299
@ NULL,
103100
@ blob.rid,
104101
@ uuid,
105
- @ strftime('%%s',event.mtime),
102
+ @ CAST(strftime('%%s',event.mtime) AS INTEGER),
106103
@ datetime(event.mtime,'utc'),
107104
@ coalesce(ecomment, comment),
108105
@ coalesce(euser, user),
109106
@ blob.rid IN leaf,
110107
@ bgcolor,
@@ -135,11 +132,11 @@
135132
** to.
136133
**
137134
** Returns a positive value if it modifies pSql, 0 if it
138135
** does not. It returns a negative value if the tag
139136
** provided to the request was not found (pSql is not modified
140
-** in that case.
137
+** in that case).
141138
**
142139
** If payload is not NULL then on success its "tag" or "branch"
143140
** property is set to the tag/branch name found in the request.
144141
**
145142
** Only one of "tag" or "branch" modes will work at a time, and if
@@ -233,12 +230,11 @@
233230
** environment parameters. If it can it returns that value,
234231
** else it returns some statically defined default value.
235232
**
236233
** Never returns a negative value. 0 means no limit.
237234
*/
238
-static int json_timeline_limit(){
239
- static const int defaultLimit = 20;
235
+static int json_timeline_limit(int defaultLimit){
240236
int limit = -1;
241237
if(!g.isHTTP){/* CLI mode */
242238
char const * arg = find_option("limit","n",1);
243239
if(arg && *arg){
244240
limit = atoi(arg);
@@ -275,12 +271,12 @@
275271
blob_appendf(pSql, " AND event.type IN(%Q) ", zEventType);
276272
if( json_timeline_add_tag_branch_clause(pSql, pPayload) < 0 ){
277273
return FSL_JSON_E_INVALID_ARGS;
278274
}
279275
json_timeline_add_time_clause(pSql);
280
- limit = json_timeline_limit();
281
- if(limit>=0){
276
+ limit = json_timeline_limit(20);
277
+ if(limit>0){
282278
blob_appendf(pSql,"LIMIT %d ",limit);
283279
}
284280
if(pPayload){
285281
cson_object_set(pPayload, "limit", json_new_int(limit));
286282
}
@@ -295,29 +291,20 @@
295291
cson_value * json_get_changed_files(int rid){
296292
cson_value * rowsV = NULL;
297293
cson_array * rows = NULL;
298294
Stmt q = empty_Stmt;
299295
db_prepare(&q,
300
-#if 0
301
- "SELECT (mlink.pid==0) AS isNew,"
302
- " (mlink.fid==0) AS isDel,"
303
- " filename.name AS name"
304
- " FROM mlink, filename"
305
- " WHERE mid=%d"
306
- " AND pid!=fid"
307
- " AND filename.fnid=mlink.fnid"
308
- " ORDER BY 3 /*sort*/",
309
-#else
310296
"SELECT (pid==0) AS isnew,"
311297
" (fid==0) AS isdel,"
312298
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
313
- " (SELECT uuid FROM blob WHERE rid=fid) as uuid,"
314
- " (SELECT uuid FROM blob WHERE rid=pid) as prevUuid"
315
- " FROM mlink"
299
+ " blob.uuid as uuid,"
300
+ " (SELECT uuid FROM blob WHERE rid=pid) as parent,"
301
+ " blob.size as size"
302
+ " FROM mlink, blob"
316303
" WHERE mid=%d AND pid!=fid"
304
+ " AND blob.rid=fid "
317305
" ORDER BY name /*sort*/",
318
-#endif
319306
rid
320307
);
321308
while( (SQLITE_ROW == db_step(&q)) ){
322309
cson_value * rowV = cson_value_new_object();
323310
cson_object * row = cson_value_get_object(rowV);
@@ -330,18 +317,16 @@
330317
}
331318
cson_array_append( rows, rowV );
332319
cson_object_set(row, "name", json_new_string(db_column_text(&q,2)));
333320
cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
334321
if(!isNew){
335
- cson_object_set(row, "prevUuid", json_new_string(db_column_text(&q,4)));
322
+ cson_object_set(row, "parent", json_new_string(db_column_text(&q,4)));
336323
}
324
+ cson_object_set(row, "size", json_new_int(db_column_int(&q,5)));
325
+
337326
cson_object_set(row, "state",
338
- json_new_string(isNew
339
- ? "added"
340
- : (isDel
341
- ? "removed"
342
- : "modified")));
327
+ json_new_string(json_artifact_status_to_string(isNew,isDel)));
343328
zDownload = mprintf("/raw/%s?name=%s",
344329
/* reminder: g.zBaseURL is of course not set for CLI mode. */
345330
db_column_text(&q,2),
346331
db_column_text(&q,3));
347332
cson_object_set(row, "downloadPath", json_new_string(zDownload));
@@ -353,10 +338,11 @@
353338
354339
static cson_value * json_timeline_branch(){
355340
cson_value * pay = NULL;
356341
Blob sql = empty_blob;
357342
Stmt q = empty_Stmt;
343
+ int limit = 0;
358344
if(!g.perm.Read){
359345
json_set_err(FSL_JSON_E_DENIED,
360346
"Requires 'o' permissions.");
361347
return NULL;
362348
}
@@ -363,11 +349,11 @@
363349
json_timeline_temp_table();
364350
blob_append(&sql,
365351
"SELECT"
366352
" blob.rid AS rid,"
367353
" uuid AS uuid,"
368
- " datetime(event.mtime,'utc') as mtime,"
354
+ " CAST(strftime('%s',event.mtime) AS INTEGER) as timestamp,"
369355
" coalesce(ecomment, comment) as comment,"
370356
" coalesce(euser, user) as user,"
371357
" blob.rid IN leaf as isLeaf,"
372358
" bgcolor as bgColor"
373359
" FROM event JOIN blob"
@@ -378,42 +364,52 @@
378364
" AND event.type='ci'"
379365
" AND blob.rid IN (SELECT rid FROM tagxref"
380366
" WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
381367
" ORDER BY event.mtime DESC",
382368
TAG_BRANCH);
369
+ limit = json_timeline_limit(20);
370
+ if(limit>0){
371
+ blob_appendf(&sql," LIMIT %d ",limit);
372
+ }
383373
db_prepare(&q,"%s", blob_str(&sql));
384374
blob_reset(&sql);
385375
pay = json_stmt_to_array_of_obj(&q, NULL);
386376
db_finalize(&q);
387377
assert(NULL != pay);
388378
if(pay){
389379
/* get the array-form tags of each record. */
390380
cson_string * tags = cson_new_string("tags",4);
391381
cson_string * isLeaf = cson_new_string("isLeaf",6);
392
- cson_value_add_reference( cson_string_value(tags) );
393
- cson_value_add_reference( cson_string_value(isLeaf) );
394382
cson_array * ar = cson_value_get_array(pay);
383
+ cson_object * outer = NULL;
395384
unsigned int i = 0;
396385
unsigned int len = cson_array_length_get(ar);
386
+ cson_value_add_reference( cson_string_value(tags) );
387
+ cson_value_add_reference( cson_string_value(isLeaf) );
397388
for( ; i < len; ++i ){
398389
cson_object * row = cson_value_get_object(cson_array_get(ar,i));
399390
int rid = cson_value_get_integer(cson_object_get(row,"rid"));
400
- if(row>0) {
401
- cson_object_set_s(row, tags, json_tags_for_checkin_rid(rid,0));
402
- cson_object_set_s(row, isLeaf, json_value_to_bool(cson_object_get(row,"isLeaf")));
403
- }
391
+ assert( rid > 0 );
392
+ cson_object_set_s(row, tags, json_tags_for_checkin_rid(rid,0));
393
+ cson_object_set_s(row, isLeaf,
394
+ json_value_to_bool(cson_object_get(row,"isLeaf")));
395
+ cson_object_set(row, "rid", NULL)
396
+ /* remove rid - we don't really want it to be public */;
404397
}
405398
cson_value_free( cson_string_value(tags) );
406399
cson_value_free( cson_string_value(isLeaf) );
407
- }
408
-
409
- goto end;
410
-
411
- assert( 0 != g.json.resultCode );
412
- cson_value_free(pay);
413
-
414
- end:
400
+
401
+ /* now we wrap the payload in an outer shell, for consistency with
402
+ other /json/timeline/xyz APIs...
403
+ */
404
+ outer = cson_new_object();
405
+ if(limit>0){
406
+ cson_object_set( outer, "limit", json_new_int(limit) );
407
+ }
408
+ cson_object_set( outer, "timeline", pay );
409
+ pay = cson_object_value(outer);
410
+ }
415411
return pay;
416412
}
417413
418414
/*
419415
** Implementation of /json/timeline/ci.
@@ -430,15 +426,15 @@
430426
int check = 0;
431427
char showFiles = -1/*magic number*/;
432428
Stmt q = empty_Stmt;
433429
char warnRowToJsonFailed = 0;
434430
Blob sql = empty_blob;
435
- if( !g.perm.Read ){
436
- /* IMO this falls more under the category of g.perm.History, but
437
- i'm following the original timeline impl here.
431
+ if( !g.perm.History ){
432
+ /* Reminder to self: HTML impl requires 'o' (Read)
433
+ rights.
438434
*/
439
- json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
435
+ json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
440436
return NULL;
441437
}
442438
showFiles = json_find_option_bool("files",NULL,"f",0);
443439
payV = cson_value_new_object();
444440
pay = cson_value_get_object(payV);
@@ -461,27 +457,10 @@
461457
#endif
462458
db_multi_exec(blob_buffer(&sql));
463459
blob_reset(&sql);
464460
db_prepare(&q, "SELECT "
465461
" rid AS rid"
466
-#if 0
467
- " uuid AS uuid,"
468
- " mtime AS timestamp,"
469
-# if 0
470
- " timestampString AS timestampString,"
471
-# endif
472
- " comment AS comment, "
473
- " user AS user,"
474
- " isLeaf AS isLeaf," /*FIXME: convert to JSON bool */
475
- " bgColor AS bgColor," /* why always null? */
476
- " eventType AS eventType"
477
-# if 0
478
- " tags AS tags"
479
- /*tagId is always null?*/
480
- " tagId AS tagId"
481
-# endif
482
-#endif
483462
" FROM json_timeline"
484463
" ORDER BY rowid");
485464
listV = cson_value_new_array();
486465
list = cson_value_get_array(listV);
487466
tmp = listV;
@@ -518,11 +497,10 @@
518497
*/
519498
cson_value * json_timeline_wiki(){
520499
/* This code is 95% the same as json_timeline_ci(), by the way. */
521500
cson_value * payV = NULL;
522501
cson_object * pay = NULL;
523
- cson_value * tmp = NULL;
524502
cson_array * list = NULL;
525503
int check = 0;
526504
Stmt q = empty_Stmt;
527505
Blob sql = empty_blob;
528506
if( !g.perm.RdWiki && !g.perm.Read ){
@@ -535,24 +513,18 @@
535513
if(check){
536514
json_set_err(check, "Query initialization failed.");
537515
goto error;
538516
}
539517
540
-#define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
541
- json_set_err((cson_rc.AllocError==check) \
542
- ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN, \
543
- "Object property insertion failed."); \
544
- goto error;\
545
- } (void)0
546518
#if 0
547519
/* only for testing! */
548520
tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
549521
SET("timelineSql");
550522
#endif
551523
db_multi_exec(blob_buffer(&sql));
552524
blob_reset(&sql);
553
- db_prepare(&q, "SELECT rid AS rid,"
525
+ db_prepare(&q, "SELECT"
554526
" uuid AS uuid,"
555527
" mtime AS timestamp,"
556528
#if 0
557529
" timestampString AS timestampString,"
558530
#endif
@@ -567,14 +539,12 @@
567539
#endif
568540
" FROM json_timeline"
569541
" ORDER BY rowid",
570542
-1);
571543
list = cson_new_array();
572
- tmp = cson_array_value(list);
573
- SET("timeline");
574544
json_stmt_to_array_of_obj(&q, list);
575
-#undef SET
545
+ cson_object_set(pay, "timeline", cson_array_value(list));
576546
goto ok;
577547
error:
578548
assert( 0 != g.json.resultCode );
579549
cson_value_free(payV);
580550
payV = NULL;
@@ -650,26 +620,38 @@
650620
while( (SQLITE_ROW == db_step(&q) )){
651621
/* convert each row into a JSON object...*/
652622
int rc;
653623
int const rid = db_column_int(&q,0);
654624
Manifest * pMan = NULL;
655
- cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
656
- cson_object * row = cson_value_get_object(rowV);
625
+ cson_value * rowV;
626
+ cson_object * row;
627
+ /*printf("rid=%d\n",rid);*/
628
+ pMan = manifest_get(rid, CFTYPE_TICKET);
629
+ if(!pMan){
630
+ /* this might be an attachment? i'm seeing this with
631
+ rid 15380, uuid [1292fef05f2472108].
632
+
633
+ /json/artifact/1292fef05f2472108 returns not-found,
634
+ probably because we haven't added artifact/ticket
635
+ yet(?).
636
+ */
637
+ continue;
638
+ }
639
+
640
+ rowV = cson_sqlite3_row_to_object(q.pStmt);
641
+ row = cson_value_get_object(rowV);
657642
if(!row){
643
+ manifest_destroy(pMan);
658644
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
659645
"Could not convert at least one timeline result row to JSON." );
660646
continue;
661647
}
662
- pMan = manifest_get(rid, CFTYPE_TICKET);
663
- assert( pMan && "Manifest is NULL!?!" );
664
- if( pMan ){
665
- /* FIXME: certainly there's a more efficient way for use to get
666
- the ticket UUIDs?
667
- */
668
- cson_object_set(row,"ticketUuid",json_new_string(pMan->zTicketUuid));
669
- manifest_destroy(pMan);
670
- }
648
+ /* FIXME: certainly there's a more efficient way for use to get
649
+ the ticket UUIDs?
650
+ */
651
+ cson_object_set(row,"ticketUuid",json_new_string(pMan->zTicketUuid));
652
+ manifest_destroy(pMan);
671653
rc = cson_array_append( list, rowV );
672654
if( 0 != rc ){
673655
cson_value_free(rowV);
674656
g.json.resultCode = (cson_rc.AllocError==rc)
675657
? FSL_JSON_E_ALLOC
676658
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -35,14 +35,11 @@
35 that we end up with HTTP clients using 3 different names
36 for the same requests.
37 */
38 {"branch", json_timeline_branch, 0},
39 {"checkin", json_timeline_ci, 0},
40 {"ci", json_timeline_ci, -1},
41 {"t", json_timeline_ticket, -1},
42 {"ticket", json_timeline_ticket, 0},
43 {"w", json_timeline_wiki, -1},
44 {"wiki", json_timeline_wiki, 0},
45 /* Last entry MUST have a NULL name. */
46 {NULL,NULL,0}
47 };
48
@@ -100,11 +97,11 @@
100 static const char zBaseSql[] =
101 @ SELECT
102 @ NULL,
103 @ blob.rid,
104 @ uuid,
105 @ strftime('%%s',event.mtime),
106 @ datetime(event.mtime,'utc'),
107 @ coalesce(ecomment, comment),
108 @ coalesce(euser, user),
109 @ blob.rid IN leaf,
110 @ bgcolor,
@@ -135,11 +132,11 @@
135 ** to.
136 **
137 ** Returns a positive value if it modifies pSql, 0 if it
138 ** does not. It returns a negative value if the tag
139 ** provided to the request was not found (pSql is not modified
140 ** in that case.
141 **
142 ** If payload is not NULL then on success its "tag" or "branch"
143 ** property is set to the tag/branch name found in the request.
144 **
145 ** Only one of "tag" or "branch" modes will work at a time, and if
@@ -233,12 +230,11 @@
233 ** environment parameters. If it can it returns that value,
234 ** else it returns some statically defined default value.
235 **
236 ** Never returns a negative value. 0 means no limit.
237 */
238 static int json_timeline_limit(){
239 static const int defaultLimit = 20;
240 int limit = -1;
241 if(!g.isHTTP){/* CLI mode */
242 char const * arg = find_option("limit","n",1);
243 if(arg && *arg){
244 limit = atoi(arg);
@@ -275,12 +271,12 @@
275 blob_appendf(pSql, " AND event.type IN(%Q) ", zEventType);
276 if( json_timeline_add_tag_branch_clause(pSql, pPayload) < 0 ){
277 return FSL_JSON_E_INVALID_ARGS;
278 }
279 json_timeline_add_time_clause(pSql);
280 limit = json_timeline_limit();
281 if(limit>=0){
282 blob_appendf(pSql,"LIMIT %d ",limit);
283 }
284 if(pPayload){
285 cson_object_set(pPayload, "limit", json_new_int(limit));
286 }
@@ -295,29 +291,20 @@
295 cson_value * json_get_changed_files(int rid){
296 cson_value * rowsV = NULL;
297 cson_array * rows = NULL;
298 Stmt q = empty_Stmt;
299 db_prepare(&q,
300 #if 0
301 "SELECT (mlink.pid==0) AS isNew,"
302 " (mlink.fid==0) AS isDel,"
303 " filename.name AS name"
304 " FROM mlink, filename"
305 " WHERE mid=%d"
306 " AND pid!=fid"
307 " AND filename.fnid=mlink.fnid"
308 " ORDER BY 3 /*sort*/",
309 #else
310 "SELECT (pid==0) AS isnew,"
311 " (fid==0) AS isdel,"
312 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
313 " (SELECT uuid FROM blob WHERE rid=fid) as uuid,"
314 " (SELECT uuid FROM blob WHERE rid=pid) as prevUuid"
315 " FROM mlink"
 
316 " WHERE mid=%d AND pid!=fid"
 
317 " ORDER BY name /*sort*/",
318 #endif
319 rid
320 );
321 while( (SQLITE_ROW == db_step(&q)) ){
322 cson_value * rowV = cson_value_new_object();
323 cson_object * row = cson_value_get_object(rowV);
@@ -330,18 +317,16 @@
330 }
331 cson_array_append( rows, rowV );
332 cson_object_set(row, "name", json_new_string(db_column_text(&q,2)));
333 cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
334 if(!isNew){
335 cson_object_set(row, "prevUuid", json_new_string(db_column_text(&q,4)));
336 }
 
 
337 cson_object_set(row, "state",
338 json_new_string(isNew
339 ? "added"
340 : (isDel
341 ? "removed"
342 : "modified")));
343 zDownload = mprintf("/raw/%s?name=%s",
344 /* reminder: g.zBaseURL is of course not set for CLI mode. */
345 db_column_text(&q,2),
346 db_column_text(&q,3));
347 cson_object_set(row, "downloadPath", json_new_string(zDownload));
@@ -353,10 +338,11 @@
353
354 static cson_value * json_timeline_branch(){
355 cson_value * pay = NULL;
356 Blob sql = empty_blob;
357 Stmt q = empty_Stmt;
 
358 if(!g.perm.Read){
359 json_set_err(FSL_JSON_E_DENIED,
360 "Requires 'o' permissions.");
361 return NULL;
362 }
@@ -363,11 +349,11 @@
363 json_timeline_temp_table();
364 blob_append(&sql,
365 "SELECT"
366 " blob.rid AS rid,"
367 " uuid AS uuid,"
368 " datetime(event.mtime,'utc') as mtime,"
369 " coalesce(ecomment, comment) as comment,"
370 " coalesce(euser, user) as user,"
371 " blob.rid IN leaf as isLeaf,"
372 " bgcolor as bgColor"
373 " FROM event JOIN blob"
@@ -378,42 +364,52 @@
378 " AND event.type='ci'"
379 " AND blob.rid IN (SELECT rid FROM tagxref"
380 " WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
381 " ORDER BY event.mtime DESC",
382 TAG_BRANCH);
 
 
 
 
383 db_prepare(&q,"%s", blob_str(&sql));
384 blob_reset(&sql);
385 pay = json_stmt_to_array_of_obj(&q, NULL);
386 db_finalize(&q);
387 assert(NULL != pay);
388 if(pay){
389 /* get the array-form tags of each record. */
390 cson_string * tags = cson_new_string("tags",4);
391 cson_string * isLeaf = cson_new_string("isLeaf",6);
392 cson_value_add_reference( cson_string_value(tags) );
393 cson_value_add_reference( cson_string_value(isLeaf) );
394 cson_array * ar = cson_value_get_array(pay);
 
395 unsigned int i = 0;
396 unsigned int len = cson_array_length_get(ar);
 
 
397 for( ; i < len; ++i ){
398 cson_object * row = cson_value_get_object(cson_array_get(ar,i));
399 int rid = cson_value_get_integer(cson_object_get(row,"rid"));
400 if(row>0) {
401 cson_object_set_s(row, tags, json_tags_for_checkin_rid(rid,0));
402 cson_object_set_s(row, isLeaf, json_value_to_bool(cson_object_get(row,"isLeaf")));
403 }
 
 
404 }
405 cson_value_free( cson_string_value(tags) );
406 cson_value_free( cson_string_value(isLeaf) );
407 }
408
409 goto end;
410
411 assert( 0 != g.json.resultCode );
412 cson_value_free(pay);
413
414 end:
 
 
 
415 return pay;
416 }
417
418 /*
419 ** Implementation of /json/timeline/ci.
@@ -430,15 +426,15 @@
430 int check = 0;
431 char showFiles = -1/*magic number*/;
432 Stmt q = empty_Stmt;
433 char warnRowToJsonFailed = 0;
434 Blob sql = empty_blob;
435 if( !g.perm.Read ){
436 /* IMO this falls more under the category of g.perm.History, but
437 i'm following the original timeline impl here.
438 */
439 json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'o' access." );
440 return NULL;
441 }
442 showFiles = json_find_option_bool("files",NULL,"f",0);
443 payV = cson_value_new_object();
444 pay = cson_value_get_object(payV);
@@ -461,27 +457,10 @@
461 #endif
462 db_multi_exec(blob_buffer(&sql));
463 blob_reset(&sql);
464 db_prepare(&q, "SELECT "
465 " rid AS rid"
466 #if 0
467 " uuid AS uuid,"
468 " mtime AS timestamp,"
469 # if 0
470 " timestampString AS timestampString,"
471 # endif
472 " comment AS comment, "
473 " user AS user,"
474 " isLeaf AS isLeaf," /*FIXME: convert to JSON bool */
475 " bgColor AS bgColor," /* why always null? */
476 " eventType AS eventType"
477 # if 0
478 " tags AS tags"
479 /*tagId is always null?*/
480 " tagId AS tagId"
481 # endif
482 #endif
483 " FROM json_timeline"
484 " ORDER BY rowid");
485 listV = cson_value_new_array();
486 list = cson_value_get_array(listV);
487 tmp = listV;
@@ -518,11 +497,10 @@
518 */
519 cson_value * json_timeline_wiki(){
520 /* This code is 95% the same as json_timeline_ci(), by the way. */
521 cson_value * payV = NULL;
522 cson_object * pay = NULL;
523 cson_value * tmp = NULL;
524 cson_array * list = NULL;
525 int check = 0;
526 Stmt q = empty_Stmt;
527 Blob sql = empty_blob;
528 if( !g.perm.RdWiki && !g.perm.Read ){
@@ -535,24 +513,18 @@
535 if(check){
536 json_set_err(check, "Query initialization failed.");
537 goto error;
538 }
539
540 #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
541 json_set_err((cson_rc.AllocError==check) \
542 ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN, \
543 "Object property insertion failed."); \
544 goto error;\
545 } (void)0
546 #if 0
547 /* only for testing! */
548 tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
549 SET("timelineSql");
550 #endif
551 db_multi_exec(blob_buffer(&sql));
552 blob_reset(&sql);
553 db_prepare(&q, "SELECT rid AS rid,"
554 " uuid AS uuid,"
555 " mtime AS timestamp,"
556 #if 0
557 " timestampString AS timestampString,"
558 #endif
@@ -567,14 +539,12 @@
567 #endif
568 " FROM json_timeline"
569 " ORDER BY rowid",
570 -1);
571 list = cson_new_array();
572 tmp = cson_array_value(list);
573 SET("timeline");
574 json_stmt_to_array_of_obj(&q, list);
575 #undef SET
576 goto ok;
577 error:
578 assert( 0 != g.json.resultCode );
579 cson_value_free(payV);
580 payV = NULL;
@@ -650,26 +620,38 @@
650 while( (SQLITE_ROW == db_step(&q) )){
651 /* convert each row into a JSON object...*/
652 int rc;
653 int const rid = db_column_int(&q,0);
654 Manifest * pMan = NULL;
655 cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
656 cson_object * row = cson_value_get_object(rowV);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
657 if(!row){
 
658 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
659 "Could not convert at least one timeline result row to JSON." );
660 continue;
661 }
662 pMan = manifest_get(rid, CFTYPE_TICKET);
663 assert( pMan && "Manifest is NULL!?!" );
664 if( pMan ){
665 /* FIXME: certainly there's a more efficient way for use to get
666 the ticket UUIDs?
667 */
668 cson_object_set(row,"ticketUuid",json_new_string(pMan->zTicketUuid));
669 manifest_destroy(pMan);
670 }
671 rc = cson_array_append( list, rowV );
672 if( 0 != rc ){
673 cson_value_free(rowV);
674 g.json.resultCode = (cson_rc.AllocError==rc)
675 ? FSL_JSON_E_ALLOC
676
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -35,14 +35,11 @@
35 that we end up with HTTP clients using 3 different names
36 for the same requests.
37 */
38 {"branch", json_timeline_branch, 0},
39 {"checkin", json_timeline_ci, 0},
 
 
40 {"ticket", json_timeline_ticket, 0},
 
41 {"wiki", json_timeline_wiki, 0},
42 /* Last entry MUST have a NULL name. */
43 {NULL,NULL,0}
44 };
45
@@ -100,11 +97,11 @@
97 static const char zBaseSql[] =
98 @ SELECT
99 @ NULL,
100 @ blob.rid,
101 @ uuid,
102 @ CAST(strftime('%%s',event.mtime) AS INTEGER),
103 @ datetime(event.mtime,'utc'),
104 @ coalesce(ecomment, comment),
105 @ coalesce(euser, user),
106 @ blob.rid IN leaf,
107 @ bgcolor,
@@ -135,11 +132,11 @@
132 ** to.
133 **
134 ** Returns a positive value if it modifies pSql, 0 if it
135 ** does not. It returns a negative value if the tag
136 ** provided to the request was not found (pSql is not modified
137 ** in that case).
138 **
139 ** If payload is not NULL then on success its "tag" or "branch"
140 ** property is set to the tag/branch name found in the request.
141 **
142 ** Only one of "tag" or "branch" modes will work at a time, and if
@@ -233,12 +230,11 @@
230 ** environment parameters. If it can it returns that value,
231 ** else it returns some statically defined default value.
232 **
233 ** Never returns a negative value. 0 means no limit.
234 */
235 static int json_timeline_limit(int defaultLimit){
 
236 int limit = -1;
237 if(!g.isHTTP){/* CLI mode */
238 char const * arg = find_option("limit","n",1);
239 if(arg && *arg){
240 limit = atoi(arg);
@@ -275,12 +271,12 @@
271 blob_appendf(pSql, " AND event.type IN(%Q) ", zEventType);
272 if( json_timeline_add_tag_branch_clause(pSql, pPayload) < 0 ){
273 return FSL_JSON_E_INVALID_ARGS;
274 }
275 json_timeline_add_time_clause(pSql);
276 limit = json_timeline_limit(20);
277 if(limit>0){
278 blob_appendf(pSql,"LIMIT %d ",limit);
279 }
280 if(pPayload){
281 cson_object_set(pPayload, "limit", json_new_int(limit));
282 }
@@ -295,29 +291,20 @@
291 cson_value * json_get_changed_files(int rid){
292 cson_value * rowsV = NULL;
293 cson_array * rows = NULL;
294 Stmt q = empty_Stmt;
295 db_prepare(&q,
 
 
 
 
 
 
 
 
 
 
296 "SELECT (pid==0) AS isnew,"
297 " (fid==0) AS isdel,"
298 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
299 " blob.uuid as uuid,"
300 " (SELECT uuid FROM blob WHERE rid=pid) as parent,"
301 " blob.size as size"
302 " FROM mlink, blob"
303 " WHERE mid=%d AND pid!=fid"
304 " AND blob.rid=fid "
305 " ORDER BY name /*sort*/",
 
306 rid
307 );
308 while( (SQLITE_ROW == db_step(&q)) ){
309 cson_value * rowV = cson_value_new_object();
310 cson_object * row = cson_value_get_object(rowV);
@@ -330,18 +317,16 @@
317 }
318 cson_array_append( rows, rowV );
319 cson_object_set(row, "name", json_new_string(db_column_text(&q,2)));
320 cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
321 if(!isNew){
322 cson_object_set(row, "parent", json_new_string(db_column_text(&q,4)));
323 }
324 cson_object_set(row, "size", json_new_int(db_column_int(&q,5)));
325
326 cson_object_set(row, "state",
327 json_new_string(json_artifact_status_to_string(isNew,isDel)));
 
 
 
 
328 zDownload = mprintf("/raw/%s?name=%s",
329 /* reminder: g.zBaseURL is of course not set for CLI mode. */
330 db_column_text(&q,2),
331 db_column_text(&q,3));
332 cson_object_set(row, "downloadPath", json_new_string(zDownload));
@@ -353,10 +338,11 @@
338
339 static cson_value * json_timeline_branch(){
340 cson_value * pay = NULL;
341 Blob sql = empty_blob;
342 Stmt q = empty_Stmt;
343 int limit = 0;
344 if(!g.perm.Read){
345 json_set_err(FSL_JSON_E_DENIED,
346 "Requires 'o' permissions.");
347 return NULL;
348 }
@@ -363,11 +349,11 @@
349 json_timeline_temp_table();
350 blob_append(&sql,
351 "SELECT"
352 " blob.rid AS rid,"
353 " uuid AS uuid,"
354 " CAST(strftime('%s',event.mtime) AS INTEGER) as timestamp,"
355 " coalesce(ecomment, comment) as comment,"
356 " coalesce(euser, user) as user,"
357 " blob.rid IN leaf as isLeaf,"
358 " bgcolor as bgColor"
359 " FROM event JOIN blob"
@@ -378,42 +364,52 @@
364 " AND event.type='ci'"
365 " AND blob.rid IN (SELECT rid FROM tagxref"
366 " WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
367 " ORDER BY event.mtime DESC",
368 TAG_BRANCH);
369 limit = json_timeline_limit(20);
370 if(limit>0){
371 blob_appendf(&sql," LIMIT %d ",limit);
372 }
373 db_prepare(&q,"%s", blob_str(&sql));
374 blob_reset(&sql);
375 pay = json_stmt_to_array_of_obj(&q, NULL);
376 db_finalize(&q);
377 assert(NULL != pay);
378 if(pay){
379 /* get the array-form tags of each record. */
380 cson_string * tags = cson_new_string("tags",4);
381 cson_string * isLeaf = cson_new_string("isLeaf",6);
 
 
382 cson_array * ar = cson_value_get_array(pay);
383 cson_object * outer = NULL;
384 unsigned int i = 0;
385 unsigned int len = cson_array_length_get(ar);
386 cson_value_add_reference( cson_string_value(tags) );
387 cson_value_add_reference( cson_string_value(isLeaf) );
388 for( ; i < len; ++i ){
389 cson_object * row = cson_value_get_object(cson_array_get(ar,i));
390 int rid = cson_value_get_integer(cson_object_get(row,"rid"));
391 assert( rid > 0 );
392 cson_object_set_s(row, tags, json_tags_for_checkin_rid(rid,0));
393 cson_object_set_s(row, isLeaf,
394 json_value_to_bool(cson_object_get(row,"isLeaf")));
395 cson_object_set(row, "rid", NULL)
396 /* remove rid - we don't really want it to be public */;
397 }
398 cson_value_free( cson_string_value(tags) );
399 cson_value_free( cson_string_value(isLeaf) );
400
401 /* now we wrap the payload in an outer shell, for consistency with
402 other /json/timeline/xyz APIs...
403 */
404 outer = cson_new_object();
405 if(limit>0){
406 cson_object_set( outer, "limit", json_new_int(limit) );
407 }
408 cson_object_set( outer, "timeline", pay );
409 pay = cson_object_value(outer);
410 }
411 return pay;
412 }
413
414 /*
415 ** Implementation of /json/timeline/ci.
@@ -430,15 +426,15 @@
426 int check = 0;
427 char showFiles = -1/*magic number*/;
428 Stmt q = empty_Stmt;
429 char warnRowToJsonFailed = 0;
430 Blob sql = empty_blob;
431 if( !g.perm.History ){
432 /* Reminder to self: HTML impl requires 'o' (Read)
433 rights.
434 */
435 json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
436 return NULL;
437 }
438 showFiles = json_find_option_bool("files",NULL,"f",0);
439 payV = cson_value_new_object();
440 pay = cson_value_get_object(payV);
@@ -461,27 +457,10 @@
457 #endif
458 db_multi_exec(blob_buffer(&sql));
459 blob_reset(&sql);
460 db_prepare(&q, "SELECT "
461 " rid AS rid"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462 " FROM json_timeline"
463 " ORDER BY rowid");
464 listV = cson_value_new_array();
465 list = cson_value_get_array(listV);
466 tmp = listV;
@@ -518,11 +497,10 @@
497 */
498 cson_value * json_timeline_wiki(){
499 /* This code is 95% the same as json_timeline_ci(), by the way. */
500 cson_value * payV = NULL;
501 cson_object * pay = NULL;
 
502 cson_array * list = NULL;
503 int check = 0;
504 Stmt q = empty_Stmt;
505 Blob sql = empty_blob;
506 if( !g.perm.RdWiki && !g.perm.Read ){
@@ -535,24 +513,18 @@
513 if(check){
514 json_set_err(check, "Query initialization failed.");
515 goto error;
516 }
517
 
 
 
 
 
 
518 #if 0
519 /* only for testing! */
520 tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
521 SET("timelineSql");
522 #endif
523 db_multi_exec(blob_buffer(&sql));
524 blob_reset(&sql);
525 db_prepare(&q, "SELECT"
526 " uuid AS uuid,"
527 " mtime AS timestamp,"
528 #if 0
529 " timestampString AS timestampString,"
530 #endif
@@ -567,14 +539,12 @@
539 #endif
540 " FROM json_timeline"
541 " ORDER BY rowid",
542 -1);
543 list = cson_new_array();
 
 
544 json_stmt_to_array_of_obj(&q, list);
545 cson_object_set(pay, "timeline", cson_array_value(list));
546 goto ok;
547 error:
548 assert( 0 != g.json.resultCode );
549 cson_value_free(payV);
550 payV = NULL;
@@ -650,26 +620,38 @@
620 while( (SQLITE_ROW == db_step(&q) )){
621 /* convert each row into a JSON object...*/
622 int rc;
623 int const rid = db_column_int(&q,0);
624 Manifest * pMan = NULL;
625 cson_value * rowV;
626 cson_object * row;
627 /*printf("rid=%d\n",rid);*/
628 pMan = manifest_get(rid, CFTYPE_TICKET);
629 if(!pMan){
630 /* this might be an attachment? i'm seeing this with
631 rid 15380, uuid [1292fef05f2472108].
632
633 /json/artifact/1292fef05f2472108 returns not-found,
634 probably because we haven't added artifact/ticket
635 yet(?).
636 */
637 continue;
638 }
639
640 rowV = cson_sqlite3_row_to_object(q.pStmt);
641 row = cson_value_get_object(rowV);
642 if(!row){
643 manifest_destroy(pMan);
644 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
645 "Could not convert at least one timeline result row to JSON." );
646 continue;
647 }
648 /* FIXME: certainly there's a more efficient way for use to get
649 the ticket UUIDs?
650 */
651 cson_object_set(row,"ticketUuid",json_new_string(pMan->zTicketUuid));
652 manifest_destroy(pMan);
 
 
 
 
653 rc = cson_array_append( list, rowV );
654 if( 0 != rc ){
655 cson_value_free(rowV);
656 g.json.resultCode = (cson_rc.AllocError==rc)
657 ? FSL_JSON_E_ALLOC
658
+115 -69
--- src/json_user.c
+++ src/json_user.c
@@ -24,20 +24,15 @@
2424
#endif
2525
2626
static cson_value * json_user_get();
2727
static cson_value * json_user_list();
2828
static cson_value * json_user_save();
29
-#if 0
30
-static cson_value * json_user_create();
31
-
32
-#endif
3329
3430
/*
3531
** Mapping of /json/user/XXX commands/paths to callbacks.
3632
*/
3733
static const JsonPageDef JsonPageDefs_User[] = {
38
-{"create", json_page_nyi, 0},
3934
{"save", json_user_save, 0},
4035
{"get", json_user_get, 0},
4136
{"list", json_user_list, 0},
4237
/* Last entry MUST have a NULL name. */
4338
{NULL,NULL,0}
@@ -52,24 +47,25 @@
5247
return json_page_dispatch_helper(&JsonPageDefs_User[0]);
5348
}
5449
5550
5651
/*
57
-** Impl of /json/user/list. Requires admin rights.
52
+** Impl of /json/user/list. Requires admin/setup rights.
5853
*/
5954
static cson_value * json_user_list(){
6055
cson_value * payV = NULL;
6156
Stmt q;
62
- if(!g.perm.Admin){
63
- g.json.resultCode = FSL_JSON_E_DENIED;
57
+ if(!g.perm.Admin && !g.perm.Setup){
58
+ json_set_err(FSL_JSON_E_DENIED,
59
+ "Requires 'a' or 's' privileges.");
6460
return NULL;
6561
}
6662
db_prepare(&q,"SELECT uid AS uid,"
6763
" login AS name,"
6864
" cap AS capabilities,"
6965
" info AS info,"
70
- " mtime AS mtime"
66
+ " mtime AS timestamp"
7167
" FROM user ORDER BY login");
7268
payV = json_stmt_to_array_of_obj(&q, NULL);
7369
db_finalize(&q);
7470
if(NULL == payV){
7571
json_set_err(FSL_JSON_E_UNKNOWN,
@@ -89,11 +85,11 @@
8985
Stmt q;
9086
db_prepare(&q,"SELECT uid AS uid,"
9187
" login AS name,"
9288
" cap AS capabilities,"
9389
" info AS info,"
94
- " mtime AS mtime"
90
+ " mtime AS timestamp"
9591
" FROM user"
9692
" WHERE login=%Q",
9793
zName);
9894
if( (SQLITE_ROW == db_step(&q)) ){
9995
u = cson_sqlite3_row_to_object(q.pStmt);
@@ -101,21 +97,21 @@
10197
db_finalize(&q);
10298
return u;
10399
}
104100
105101
/*
106
-** Identical to _load_user_by_name(), but expects a user ID. Returns
102
+** Identical to json_load_user_by_name(), but expects a user ID. Returns
107103
** NULL if no user found with that ID.
108104
*/
109105
static cson_value * json_load_user_by_id(int uid){
110106
cson_value * u = NULL;
111107
Stmt q;
112108
db_prepare(&q,"SELECT uid AS uid,"
113109
" login AS name,"
114110
" cap AS capabilities,"
115111
" info AS info,"
116
- " mtime AS mtime"
112
+ " mtime AS timestamp"
117113
" FROM user"
118114
" WHERE uid=%d",
119115
uid);
120116
if( (SQLITE_ROW == db_step(&q)) ){
121117
u = cson_sqlite3_row_to_object(q.pStmt);
@@ -124,28 +120,21 @@
124120
return u;
125121
}
126122
127123
128124
/*
129
-** Impl of /json/user/get. Requires admin rights.
125
+** Impl of /json/user/get. Requires admin or setup rights.
130126
*/
131127
static cson_value * json_user_get(){
132128
cson_value * payV = NULL;
133129
char const * pUser = NULL;
134
- if(!g.perm.Admin){
130
+ if(!g.perm.Admin && !g.perm.Setup){
135131
json_set_err(FSL_JSON_E_DENIED,
136
- "Requires 'a' privileges.");
132
+ "Requires 'a' or 's' privileges.");
137133
return NULL;
138134
}
139
- pUser = json_command_arg(g.json.dispatchDepth+1);
140
- if( g.isHTTP && (!pUser || !*pUser) ){
141
- pUser = json_getenv_cstr("name")
142
- /* ACHTUNG: fossil apparently internally sets name=user/get/XYZ
143
- if we pass the name as part of the path, which is why we check
144
- with json_command_path() before trying to get("name").
145
- */;
146
- }
135
+ pUser = json_find_option_cstr2("name", NULL, NULL, g.json.dispatchDepth+1);
147136
if(!pUser || !*pUser){
148137
json_set_err(FSL_JSON_E_MISSING_ARGS,"Missing 'name' property.");
149138
return NULL;
150139
}
151140
payV = json_load_user_by_name(pUser);
@@ -164,16 +153,16 @@
164153
** are not included in pUser.
165154
**
166155
** If uid is specified then name may refer to a _new_ name
167156
** for a user, otherwise the name must refer to an existing user.
168157
** If uid=-1 then the name must be specified and a new user is
169
-** created (failes if one already exists).
158
+** created (fails if one already exists).
170159
**
171160
** If uid is not set, this function might modify pUser to contain the
172161
** db-found (or inserted) user ID.
173162
**
174
-** On error g.json's error state is set one of the FSL_JSON_E_xxx
163
+** On error g.json's error state is set and one of the FSL_JSON_E_xxx
175164
** values from FossilJsonCodes is returned.
176165
**
177166
** On success the db record for the given user is updated.
178167
**
179168
** Requires either Admin, Setup, or Password access. Non-admin/setup
@@ -197,16 +186,17 @@
197186
char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
198187
char tgtHadSetup = 0;
199188
Blob sql = empty_blob;
200189
Stmt q = empty_Stmt;
201190
191
+#if 0
202192
if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
203193
return json_set_err( FSL_JSON_E_DENIED,
204194
"Password change requires 'a', 's', "
205195
"or 'p' permissions.");
206196
}
207
-
197
+#endif
208198
if(uid<=0 && (!zName||!*zName)){
209199
return json_set_err(FSL_JSON_E_MISSING_ARGS,
210200
"One of 'uid' or 'name' is required.");
211201
}else if(uid>0){
212202
zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid);
@@ -216,18 +206,21 @@
216206
}
217207
zName = zNameFree;
218208
}else if(-1==uid){
219209
/* try to create a new user */
220210
if(!g.perm.Admin && !g.perm.Setup){
221
- return json_set_err(FSL_JSON_E_DENIED,
222
- "Requires 'a' or 's' privileges.");
211
+ json_set_err(FSL_JSON_E_DENIED,
212
+ "Requires 'a' or 's' privileges.");
213
+ goto error;
223214
}else if(!zName || !*zName){
224
- return json_set_err(FSL_JSON_E_MISSING_ARGS,
225
- "No name specified for new user.");
215
+ json_set_err(FSL_JSON_E_MISSING_ARGS,
216
+ "No name specified for new user.");
217
+ goto error;
226218
}else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
227
- return json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
228
- "User %s already exists.", zName);
219
+ json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
220
+ "User %s already exists.", zName);
221
+ goto error;
229222
}else{
230223
Stmt ins = empty_Stmt;
231224
db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
232225
db_step( &ins );
233226
db_finalize(&ins);
@@ -237,12 +230,13 @@
237230
cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
238231
}
239232
}else{
240233
uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
241234
if(uid<=0){
242
- return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
243
- "No login found for user [%s].", zName);
235
+ json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
236
+ "No login found for user [%s].", zName);
237
+ goto error;
244238
}
245239
cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
246240
}
247241
248242
/* Maintenance note: all error-returns from here on out should go
@@ -252,10 +246,11 @@
252246
if(uid != g.userUid){
253247
if(!g.perm.Admin && !g.perm.Setup){
254248
json_set_err(FSL_JSON_E_DENIED,
255249
"Changing another user's data requires "
256250
"'a' or 's' privileges.");
251
+ goto error;
257252
}
258253
}
259254
/* check if the target uid currently has setup rights. */
260255
tgtHadSetup = db_int(0,"SELECT 1 FROM user where uid=%d"
261256
" AND cap GLOB '*s*'", uid);
@@ -263,52 +258,76 @@
263258
if((tgtHasSetup || tgtHadSetup) && !g.perm.Setup){
264259
/*
265260
Do not allow a non-setup user to set or remove setup
266261
privileges. setup.c uses similar logic.
267262
*/
268
- return json_set_err(FSL_JSON_E_DENIED,
269
- "Modifying 's' users/privileges requires "
270
- "'s' privileges.");
263
+ json_set_err(FSL_JSON_E_DENIED,
264
+ "Modifying 's' users/privileges requires "
265
+ "'s' privileges.");
266
+ goto error;
271267
}
272268
/*
273269
Potential todo: do not allow a setup user to remove 's' from
274270
himself, to avoid locking himself out?
275271
*/
276272
277
- blob_append(&sql, "UPDATE USER SET",-1 );
273
+ blob_append(&sql, "UPDATE user SET",-1 );
278274
blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
279275
280276
if((uid>0) && zNameNew){
281277
/* Check for name change... */
282
- if( (!g.perm.Admin && !g.perm.Setup)
283
- && zNameNew && (zName != zNameNew)
284
- && (0!=strcmp(zNameNew,zName))){
285
- json_set_err( FSL_JSON_E_DENIED,
286
- "Modifying user names requires 'a' or 's' privileges.");
278
+ if(0!=strcmp(zName,zNameNew)){
279
+ if( (!g.perm.Admin && !g.perm.Setup)
280
+ && (zName != zNameNew)){
281
+ json_set_err( FSL_JSON_E_DENIED,
282
+ "Modifying user names requires 'a' or 's' privileges.");
283
+ goto error;
284
+ }
285
+ forceLogout = cson_value_true()
286
+ /* reminders: 1) does not allocate.
287
+ 2) we do this because changing a name
288
+ invalidates any login token because the old name
289
+ is part of the token hash.
290
+ */;
291
+ blob_appendf(&sql, ", login=%Q", zNameNew);
292
+ ++gotFields;
293
+ }
294
+ }
295
+
296
+ if( zCap && *zCap ){
297
+ if(!g.perm.Admin || !g.perm.Setup){
298
+ /* we "could" arguably silently ignore cap in this case. */
299
+ json_set_err(FSL_JSON_E_DENIED,
300
+ "Changing capabilities requires 'a' or 's' privileges.");
287301
goto error;
288302
}
289
- forceLogout = cson_value_true()
290
- /* reminders: 1) does not allocate.
291
- 2) we do this because changing a name
292
- invalidates any login token because the old name
293
- is part of the token hash.
294
- */;
295
- blob_appendf(&sql, ", login=%Q", zNameNew);
296
- ++gotFields;
297
- }
298
-
299
- if( zCap ){
300303
blob_appendf(&sql, ", cap=%Q", zCap);
301304
++gotFields;
302305
}
303306
304
- if( zPW ){
305
- char * zPWHash = NULL;
306
- ++gotFields;
307
- zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
308
- blob_appendf(&sql, ", pw=%Q", zPWHash);
309
- free(zPWHash);
307
+ if( zPW && *zPW ){
308
+ if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
309
+ json_set_err( FSL_JSON_E_DENIED,
310
+ "Password change requires 'a', 's', "
311
+ "or 'p' permissions.");
312
+ goto error;
313
+ }else{
314
+#define TRY_LOGIN_GROUP 0 /* login group support is not yet implemented. */
315
+#if !TRY_LOGIN_GROUP
316
+ char * zPWHash = NULL;
317
+ ++gotFields;
318
+ zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
319
+ blob_appendf(&sql, ", pw=%Q", zPWHash);
320
+ free(zPWHash);
321
+#else
322
+ ++gotFields;
323
+ blob_appendf(&sql, ", pw=coalesce(shared_secret(%Q,%Q,"
324
+ "(SELECT value FROM config WHERE name='project-code')))",
325
+ zPW, zNameNew ? zNameNew : zName);
326
+ /* shared_secret() func is undefined? */
327
+#endif
328
+ }
310329
}
311330
312331
if( zInfo ){
313332
blob_appendf(&sql, ", info=%Q", zInfo);
314333
++gotFields;
@@ -324,20 +343,48 @@
324343
json_set_err( FSL_JSON_E_MISSING_ARGS,
325344
"Required user data are missing.");
326345
goto error;
327346
}
328347
assert(uid>0);
348
+#if !TRY_LOGIN_GROUP
329349
blob_appendf(&sql, " WHERE uid=%d", uid);
330
- free( zNameFree );
350
+#else /* need name for login group support :/ */
351
+ blob_appendf(&sql, " WHERE login=%Q", zName);
352
+#endif
331353
#if 0
332354
puts(blob_str(&sql));
333355
cson_output_FILE( cson_object_value(pUser), stdout, NULL );
334356
#endif
335357
db_prepare(&q, "%s", blob_str(&sql));
336
- blob_reset(&sql);
337358
db_exec(&q);
338359
db_finalize(&q);
360
+#if TRY_LOGIN_GROUP
361
+ if( zPW || forceLogout ){
362
+ Blob groupSql = empty_blob;
363
+ char * zErr = NULL;
364
+ blob_appendf(&groupSql,
365
+ "INSERT INTO user(login)"
366
+ " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
367
+ zName, zName
368
+ );
369
+ blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
370
+ login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
371
+ blob_reset(&groupSql);
372
+ if( zErr ){
373
+ json_set_err( FSL_JSON_E_UNKNOWN,
374
+ "Repo-group update at least partially failed: %s",
375
+ zErr);
376
+ free(zErr);
377
+ goto error;
378
+ }
379
+ }
380
+#endif /* TRY_LOGIN_GROUP */
381
+
382
+#undef TRY_LOGIN_GROUP
383
+
384
+ free( zNameFree );
385
+ blob_reset(&sql);
339386
return 0;
340387
341388
error:
342389
assert(0 != g.json.resultCode);
343390
free(zNameFree);
@@ -356,24 +403,23 @@
356403
char const * str = NULL;
357404
char b = -1;
358405
int i = -1;
359406
int uid = -1;
360407
cson_value * payload = NULL;
361
-#define PROP(LK) str = json_find_option_cstr(LK,NULL,NULL); \
408
+#define PROP(LK,SK) str = json_find_option_cstr(LK,NULL,SK); \
362409
if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0
363
- PROP("name");
364
- PROP("password");
365
- PROP("info");
366
- PROP("capabilities");
410
+ PROP("name","n");
411
+ PROP("password","p");
412
+ PROP("info","i");
413
+ PROP("capabilities","c");
367414
#undef PROP
368
-
369415
#define PROP(LK,DFLT) b = json_find_option_bool(LK,NULL,NULL,DFLT); \
370416
if(DFLT!=b){ cson_object_set(u, LK, cson_value_new_bool(b)); } (void)0
371417
PROP("forceLogout",-1);
372418
#undef PROP
373419
374
-#define PROP(LK,DFLT) i = json_find_option_int(LK,NULL,NULL,DFLT); \
420
+#define PROP(LK,DFLT) i = json_find_option_int(LK,NULL,NULL,DFLT); \
375421
if(DFLT != i){ cson_object_set(u, LK, cson_value_new_integer(i)); } (void)0
376422
PROP("uid",-99);
377423
#undef PROP
378424
if( g.json.reqPayload.o ){
379425
cson_object_merge( u, g.json.reqPayload.o, CSON_MERGE_NO_RECURSE );
380426
--- src/json_user.c
+++ src/json_user.c
@@ -24,20 +24,15 @@
24 #endif
25
26 static cson_value * json_user_get();
27 static cson_value * json_user_list();
28 static cson_value * json_user_save();
29 #if 0
30 static cson_value * json_user_create();
31
32 #endif
33
34 /*
35 ** Mapping of /json/user/XXX commands/paths to callbacks.
36 */
37 static const JsonPageDef JsonPageDefs_User[] = {
38 {"create", json_page_nyi, 0},
39 {"save", json_user_save, 0},
40 {"get", json_user_get, 0},
41 {"list", json_user_list, 0},
42 /* Last entry MUST have a NULL name. */
43 {NULL,NULL,0}
@@ -52,24 +47,25 @@
52 return json_page_dispatch_helper(&JsonPageDefs_User[0]);
53 }
54
55
56 /*
57 ** Impl of /json/user/list. Requires admin rights.
58 */
59 static cson_value * json_user_list(){
60 cson_value * payV = NULL;
61 Stmt q;
62 if(!g.perm.Admin){
63 g.json.resultCode = FSL_JSON_E_DENIED;
 
64 return NULL;
65 }
66 db_prepare(&q,"SELECT uid AS uid,"
67 " login AS name,"
68 " cap AS capabilities,"
69 " info AS info,"
70 " mtime AS mtime"
71 " FROM user ORDER BY login");
72 payV = json_stmt_to_array_of_obj(&q, NULL);
73 db_finalize(&q);
74 if(NULL == payV){
75 json_set_err(FSL_JSON_E_UNKNOWN,
@@ -89,11 +85,11 @@
89 Stmt q;
90 db_prepare(&q,"SELECT uid AS uid,"
91 " login AS name,"
92 " cap AS capabilities,"
93 " info AS info,"
94 " mtime AS mtime"
95 " FROM user"
96 " WHERE login=%Q",
97 zName);
98 if( (SQLITE_ROW == db_step(&q)) ){
99 u = cson_sqlite3_row_to_object(q.pStmt);
@@ -101,21 +97,21 @@
101 db_finalize(&q);
102 return u;
103 }
104
105 /*
106 ** Identical to _load_user_by_name(), but expects a user ID. Returns
107 ** NULL if no user found with that ID.
108 */
109 static cson_value * json_load_user_by_id(int uid){
110 cson_value * u = NULL;
111 Stmt q;
112 db_prepare(&q,"SELECT uid AS uid,"
113 " login AS name,"
114 " cap AS capabilities,"
115 " info AS info,"
116 " mtime AS mtime"
117 " FROM user"
118 " WHERE uid=%d",
119 uid);
120 if( (SQLITE_ROW == db_step(&q)) ){
121 u = cson_sqlite3_row_to_object(q.pStmt);
@@ -124,28 +120,21 @@
124 return u;
125 }
126
127
128 /*
129 ** Impl of /json/user/get. Requires admin rights.
130 */
131 static cson_value * json_user_get(){
132 cson_value * payV = NULL;
133 char const * pUser = NULL;
134 if(!g.perm.Admin){
135 json_set_err(FSL_JSON_E_DENIED,
136 "Requires 'a' privileges.");
137 return NULL;
138 }
139 pUser = json_command_arg(g.json.dispatchDepth+1);
140 if( g.isHTTP && (!pUser || !*pUser) ){
141 pUser = json_getenv_cstr("name")
142 /* ACHTUNG: fossil apparently internally sets name=user/get/XYZ
143 if we pass the name as part of the path, which is why we check
144 with json_command_path() before trying to get("name").
145 */;
146 }
147 if(!pUser || !*pUser){
148 json_set_err(FSL_JSON_E_MISSING_ARGS,"Missing 'name' property.");
149 return NULL;
150 }
151 payV = json_load_user_by_name(pUser);
@@ -164,16 +153,16 @@
164 ** are not included in pUser.
165 **
166 ** If uid is specified then name may refer to a _new_ name
167 ** for a user, otherwise the name must refer to an existing user.
168 ** If uid=-1 then the name must be specified and a new user is
169 ** created (failes if one already exists).
170 **
171 ** If uid is not set, this function might modify pUser to contain the
172 ** db-found (or inserted) user ID.
173 **
174 ** On error g.json's error state is set one of the FSL_JSON_E_xxx
175 ** values from FossilJsonCodes is returned.
176 **
177 ** On success the db record for the given user is updated.
178 **
179 ** Requires either Admin, Setup, or Password access. Non-admin/setup
@@ -197,16 +186,17 @@
197 char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
198 char tgtHadSetup = 0;
199 Blob sql = empty_blob;
200 Stmt q = empty_Stmt;
201
 
202 if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
203 return json_set_err( FSL_JSON_E_DENIED,
204 "Password change requires 'a', 's', "
205 "or 'p' permissions.");
206 }
207
208 if(uid<=0 && (!zName||!*zName)){
209 return json_set_err(FSL_JSON_E_MISSING_ARGS,
210 "One of 'uid' or 'name' is required.");
211 }else if(uid>0){
212 zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid);
@@ -216,18 +206,21 @@
216 }
217 zName = zNameFree;
218 }else if(-1==uid){
219 /* try to create a new user */
220 if(!g.perm.Admin && !g.perm.Setup){
221 return json_set_err(FSL_JSON_E_DENIED,
222 "Requires 'a' or 's' privileges.");
 
223 }else if(!zName || !*zName){
224 return json_set_err(FSL_JSON_E_MISSING_ARGS,
225 "No name specified for new user.");
 
226 }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
227 return json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
228 "User %s already exists.", zName);
 
229 }else{
230 Stmt ins = empty_Stmt;
231 db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
232 db_step( &ins );
233 db_finalize(&ins);
@@ -237,12 +230,13 @@
237 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
238 }
239 }else{
240 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
241 if(uid<=0){
242 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
243 "No login found for user [%s].", zName);
 
244 }
245 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
246 }
247
248 /* Maintenance note: all error-returns from here on out should go
@@ -252,10 +246,11 @@
252 if(uid != g.userUid){
253 if(!g.perm.Admin && !g.perm.Setup){
254 json_set_err(FSL_JSON_E_DENIED,
255 "Changing another user's data requires "
256 "'a' or 's' privileges.");
 
257 }
258 }
259 /* check if the target uid currently has setup rights. */
260 tgtHadSetup = db_int(0,"SELECT 1 FROM user where uid=%d"
261 " AND cap GLOB '*s*'", uid);
@@ -263,52 +258,76 @@
263 if((tgtHasSetup || tgtHadSetup) && !g.perm.Setup){
264 /*
265 Do not allow a non-setup user to set or remove setup
266 privileges. setup.c uses similar logic.
267 */
268 return json_set_err(FSL_JSON_E_DENIED,
269 "Modifying 's' users/privileges requires "
270 "'s' privileges.");
 
271 }
272 /*
273 Potential todo: do not allow a setup user to remove 's' from
274 himself, to avoid locking himself out?
275 */
276
277 blob_append(&sql, "UPDATE USER SET",-1 );
278 blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
279
280 if((uid>0) && zNameNew){
281 /* Check for name change... */
282 if( (!g.perm.Admin && !g.perm.Setup)
283 && zNameNew && (zName != zNameNew)
284 && (0!=strcmp(zNameNew,zName))){
285 json_set_err( FSL_JSON_E_DENIED,
286 "Modifying user names requires 'a' or 's' privileges.");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287 goto error;
288 }
289 forceLogout = cson_value_true()
290 /* reminders: 1) does not allocate.
291 2) we do this because changing a name
292 invalidates any login token because the old name
293 is part of the token hash.
294 */;
295 blob_appendf(&sql, ", login=%Q", zNameNew);
296 ++gotFields;
297 }
298
299 if( zCap ){
300 blob_appendf(&sql, ", cap=%Q", zCap);
301 ++gotFields;
302 }
303
304 if( zPW ){
305 char * zPWHash = NULL;
306 ++gotFields;
307 zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
308 blob_appendf(&sql, ", pw=%Q", zPWHash);
309 free(zPWHash);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310 }
311
312 if( zInfo ){
313 blob_appendf(&sql, ", info=%Q", zInfo);
314 ++gotFields;
@@ -324,20 +343,48 @@
324 json_set_err( FSL_JSON_E_MISSING_ARGS,
325 "Required user data are missing.");
326 goto error;
327 }
328 assert(uid>0);
 
329 blob_appendf(&sql, " WHERE uid=%d", uid);
330 free( zNameFree );
 
 
331 #if 0
332 puts(blob_str(&sql));
333 cson_output_FILE( cson_object_value(pUser), stdout, NULL );
334 #endif
335 db_prepare(&q, "%s", blob_str(&sql));
336 blob_reset(&sql);
337 db_exec(&q);
338 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339 return 0;
340
341 error:
342 assert(0 != g.json.resultCode);
343 free(zNameFree);
@@ -356,24 +403,23 @@
356 char const * str = NULL;
357 char b = -1;
358 int i = -1;
359 int uid = -1;
360 cson_value * payload = NULL;
361 #define PROP(LK) str = json_find_option_cstr(LK,NULL,NULL); \
362 if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0
363 PROP("name");
364 PROP("password");
365 PROP("info");
366 PROP("capabilities");
367 #undef PROP
368
369 #define PROP(LK,DFLT) b = json_find_option_bool(LK,NULL,NULL,DFLT); \
370 if(DFLT!=b){ cson_object_set(u, LK, cson_value_new_bool(b)); } (void)0
371 PROP("forceLogout",-1);
372 #undef PROP
373
374 #define PROP(LK,DFLT) i = json_find_option_int(LK,NULL,NULL,DFLT); \
375 if(DFLT != i){ cson_object_set(u, LK, cson_value_new_integer(i)); } (void)0
376 PROP("uid",-99);
377 #undef PROP
378 if( g.json.reqPayload.o ){
379 cson_object_merge( u, g.json.reqPayload.o, CSON_MERGE_NO_RECURSE );
380
--- src/json_user.c
+++ src/json_user.c
@@ -24,20 +24,15 @@
24 #endif
25
26 static cson_value * json_user_get();
27 static cson_value * json_user_list();
28 static cson_value * json_user_save();
 
 
 
 
29
30 /*
31 ** Mapping of /json/user/XXX commands/paths to callbacks.
32 */
33 static const JsonPageDef JsonPageDefs_User[] = {
 
34 {"save", json_user_save, 0},
35 {"get", json_user_get, 0},
36 {"list", json_user_list, 0},
37 /* Last entry MUST have a NULL name. */
38 {NULL,NULL,0}
@@ -52,24 +47,25 @@
47 return json_page_dispatch_helper(&JsonPageDefs_User[0]);
48 }
49
50
51 /*
52 ** Impl of /json/user/list. Requires admin/setup rights.
53 */
54 static cson_value * json_user_list(){
55 cson_value * payV = NULL;
56 Stmt q;
57 if(!g.perm.Admin && !g.perm.Setup){
58 json_set_err(FSL_JSON_E_DENIED,
59 "Requires 'a' or 's' privileges.");
60 return NULL;
61 }
62 db_prepare(&q,"SELECT uid AS uid,"
63 " login AS name,"
64 " cap AS capabilities,"
65 " info AS info,"
66 " mtime AS timestamp"
67 " FROM user ORDER BY login");
68 payV = json_stmt_to_array_of_obj(&q, NULL);
69 db_finalize(&q);
70 if(NULL == payV){
71 json_set_err(FSL_JSON_E_UNKNOWN,
@@ -89,11 +85,11 @@
85 Stmt q;
86 db_prepare(&q,"SELECT uid AS uid,"
87 " login AS name,"
88 " cap AS capabilities,"
89 " info AS info,"
90 " mtime AS timestamp"
91 " FROM user"
92 " WHERE login=%Q",
93 zName);
94 if( (SQLITE_ROW == db_step(&q)) ){
95 u = cson_sqlite3_row_to_object(q.pStmt);
@@ -101,21 +97,21 @@
97 db_finalize(&q);
98 return u;
99 }
100
101 /*
102 ** Identical to json_load_user_by_name(), but expects a user ID. Returns
103 ** NULL if no user found with that ID.
104 */
105 static cson_value * json_load_user_by_id(int uid){
106 cson_value * u = NULL;
107 Stmt q;
108 db_prepare(&q,"SELECT uid AS uid,"
109 " login AS name,"
110 " cap AS capabilities,"
111 " info AS info,"
112 " mtime AS timestamp"
113 " FROM user"
114 " WHERE uid=%d",
115 uid);
116 if( (SQLITE_ROW == db_step(&q)) ){
117 u = cson_sqlite3_row_to_object(q.pStmt);
@@ -124,28 +120,21 @@
120 return u;
121 }
122
123
124 /*
125 ** Impl of /json/user/get. Requires admin or setup rights.
126 */
127 static cson_value * json_user_get(){
128 cson_value * payV = NULL;
129 char const * pUser = NULL;
130 if(!g.perm.Admin && !g.perm.Setup){
131 json_set_err(FSL_JSON_E_DENIED,
132 "Requires 'a' or 's' privileges.");
133 return NULL;
134 }
135 pUser = json_find_option_cstr2("name", NULL, NULL, g.json.dispatchDepth+1);
 
 
 
 
 
 
 
136 if(!pUser || !*pUser){
137 json_set_err(FSL_JSON_E_MISSING_ARGS,"Missing 'name' property.");
138 return NULL;
139 }
140 payV = json_load_user_by_name(pUser);
@@ -164,16 +153,16 @@
153 ** are not included in pUser.
154 **
155 ** If uid is specified then name may refer to a _new_ name
156 ** for a user, otherwise the name must refer to an existing user.
157 ** If uid=-1 then the name must be specified and a new user is
158 ** created (fails if one already exists).
159 **
160 ** If uid is not set, this function might modify pUser to contain the
161 ** db-found (or inserted) user ID.
162 **
163 ** On error g.json's error state is set and one of the FSL_JSON_E_xxx
164 ** values from FossilJsonCodes is returned.
165 **
166 ** On success the db record for the given user is updated.
167 **
168 ** Requires either Admin, Setup, or Password access. Non-admin/setup
@@ -197,16 +186,17 @@
186 char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
187 char tgtHadSetup = 0;
188 Blob sql = empty_blob;
189 Stmt q = empty_Stmt;
190
191 #if 0
192 if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
193 return json_set_err( FSL_JSON_E_DENIED,
194 "Password change requires 'a', 's', "
195 "or 'p' permissions.");
196 }
197 #endif
198 if(uid<=0 && (!zName||!*zName)){
199 return json_set_err(FSL_JSON_E_MISSING_ARGS,
200 "One of 'uid' or 'name' is required.");
201 }else if(uid>0){
202 zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid);
@@ -216,18 +206,21 @@
206 }
207 zName = zNameFree;
208 }else if(-1==uid){
209 /* try to create a new user */
210 if(!g.perm.Admin && !g.perm.Setup){
211 json_set_err(FSL_JSON_E_DENIED,
212 "Requires 'a' or 's' privileges.");
213 goto error;
214 }else if(!zName || !*zName){
215 json_set_err(FSL_JSON_E_MISSING_ARGS,
216 "No name specified for new user.");
217 goto error;
218 }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
219 json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
220 "User %s already exists.", zName);
221 goto error;
222 }else{
223 Stmt ins = empty_Stmt;
224 db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
225 db_step( &ins );
226 db_finalize(&ins);
@@ -237,12 +230,13 @@
230 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
231 }
232 }else{
233 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
234 if(uid<=0){
235 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
236 "No login found for user [%s].", zName);
237 goto error;
238 }
239 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
240 }
241
242 /* Maintenance note: all error-returns from here on out should go
@@ -252,10 +246,11 @@
246 if(uid != g.userUid){
247 if(!g.perm.Admin && !g.perm.Setup){
248 json_set_err(FSL_JSON_E_DENIED,
249 "Changing another user's data requires "
250 "'a' or 's' privileges.");
251 goto error;
252 }
253 }
254 /* check if the target uid currently has setup rights. */
255 tgtHadSetup = db_int(0,"SELECT 1 FROM user where uid=%d"
256 " AND cap GLOB '*s*'", uid);
@@ -263,52 +258,76 @@
258 if((tgtHasSetup || tgtHadSetup) && !g.perm.Setup){
259 /*
260 Do not allow a non-setup user to set or remove setup
261 privileges. setup.c uses similar logic.
262 */
263 json_set_err(FSL_JSON_E_DENIED,
264 "Modifying 's' users/privileges requires "
265 "'s' privileges.");
266 goto error;
267 }
268 /*
269 Potential todo: do not allow a setup user to remove 's' from
270 himself, to avoid locking himself out?
271 */
272
273 blob_append(&sql, "UPDATE user SET",-1 );
274 blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
275
276 if((uid>0) && zNameNew){
277 /* Check for name change... */
278 if(0!=strcmp(zName,zNameNew)){
279 if( (!g.perm.Admin && !g.perm.Setup)
280 && (zName != zNameNew)){
281 json_set_err( FSL_JSON_E_DENIED,
282 "Modifying user names requires 'a' or 's' privileges.");
283 goto error;
284 }
285 forceLogout = cson_value_true()
286 /* reminders: 1) does not allocate.
287 2) we do this because changing a name
288 invalidates any login token because the old name
289 is part of the token hash.
290 */;
291 blob_appendf(&sql, ", login=%Q", zNameNew);
292 ++gotFields;
293 }
294 }
295
296 if( zCap && *zCap ){
297 if(!g.perm.Admin || !g.perm.Setup){
298 /* we "could" arguably silently ignore cap in this case. */
299 json_set_err(FSL_JSON_E_DENIED,
300 "Changing capabilities requires 'a' or 's' privileges.");
301 goto error;
302 }
 
 
 
 
 
 
 
 
 
 
 
303 blob_appendf(&sql, ", cap=%Q", zCap);
304 ++gotFields;
305 }
306
307 if( zPW && *zPW ){
308 if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
309 json_set_err( FSL_JSON_E_DENIED,
310 "Password change requires 'a', 's', "
311 "or 'p' permissions.");
312 goto error;
313 }else{
314 #define TRY_LOGIN_GROUP 0 /* login group support is not yet implemented. */
315 #if !TRY_LOGIN_GROUP
316 char * zPWHash = NULL;
317 ++gotFields;
318 zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
319 blob_appendf(&sql, ", pw=%Q", zPWHash);
320 free(zPWHash);
321 #else
322 ++gotFields;
323 blob_appendf(&sql, ", pw=coalesce(shared_secret(%Q,%Q,"
324 "(SELECT value FROM config WHERE name='project-code')))",
325 zPW, zNameNew ? zNameNew : zName);
326 /* shared_secret() func is undefined? */
327 #endif
328 }
329 }
330
331 if( zInfo ){
332 blob_appendf(&sql, ", info=%Q", zInfo);
333 ++gotFields;
@@ -324,20 +343,48 @@
343 json_set_err( FSL_JSON_E_MISSING_ARGS,
344 "Required user data are missing.");
345 goto error;
346 }
347 assert(uid>0);
348 #if !TRY_LOGIN_GROUP
349 blob_appendf(&sql, " WHERE uid=%d", uid);
350 #else /* need name for login group support :/ */
351 blob_appendf(&sql, " WHERE login=%Q", zName);
352 #endif
353 #if 0
354 puts(blob_str(&sql));
355 cson_output_FILE( cson_object_value(pUser), stdout, NULL );
356 #endif
357 db_prepare(&q, "%s", blob_str(&sql));
 
358 db_exec(&q);
359 db_finalize(&q);
360 #if TRY_LOGIN_GROUP
361 if( zPW || forceLogout ){
362 Blob groupSql = empty_blob;
363 char * zErr = NULL;
364 blob_appendf(&groupSql,
365 "INSERT INTO user(login)"
366 " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
367 zName, zName
368 );
369 blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
370 login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
371 blob_reset(&groupSql);
372 if( zErr ){
373 json_set_err( FSL_JSON_E_UNKNOWN,
374 "Repo-group update at least partially failed: %s",
375 zErr);
376 free(zErr);
377 goto error;
378 }
379 }
380 #endif /* TRY_LOGIN_GROUP */
381
382 #undef TRY_LOGIN_GROUP
383
384 free( zNameFree );
385 blob_reset(&sql);
386 return 0;
387
388 error:
389 assert(0 != g.json.resultCode);
390 free(zNameFree);
@@ -356,24 +403,23 @@
403 char const * str = NULL;
404 char b = -1;
405 int i = -1;
406 int uid = -1;
407 cson_value * payload = NULL;
408 #define PROP(LK,SK) str = json_find_option_cstr(LK,NULL,SK); \
409 if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0
410 PROP("name","n");
411 PROP("password","p");
412 PROP("info","i");
413 PROP("capabilities","c");
414 #undef PROP
 
415 #define PROP(LK,DFLT) b = json_find_option_bool(LK,NULL,NULL,DFLT); \
416 if(DFLT!=b){ cson_object_set(u, LK, cson_value_new_bool(b)); } (void)0
417 PROP("forceLogout",-1);
418 #undef PROP
419
420 #define PROP(LK,DFLT) i = json_find_option_int(LK,NULL,NULL,DFLT); \
421 if(DFLT != i){ cson_object_set(u, LK, cson_value_new_integer(i)); } (void)0
422 PROP("uid",-99);
423 #undef PROP
424 if( g.json.reqPayload.o ){
425 cson_object_merge( u, g.json.reqPayload.o, CSON_MERGE_NO_RECURSE );
426
+304 -105
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -24,20 +24,23 @@
2424
#endif
2525
2626
static cson_value * json_wiki_create();
2727
static cson_value * json_wiki_get();
2828
static cson_value * json_wiki_list();
29
+static cson_value * json_wiki_preview();
2930
static cson_value * json_wiki_save();
30
-
31
+static cson_value * json_wiki_diff();
3132
/*
3233
** Mapping of /json/wiki/XXX commands/paths to callbacks.
3334
*/
3435
static const JsonPageDef JsonPageDefs_Wiki[] = {
35
-{"create", json_wiki_create, 1},
36
+{"create", json_wiki_create, 0},
37
+{"diff", json_wiki_diff, 0},
3638
{"get", json_wiki_get, 0},
3739
{"list", json_wiki_list, 0},
38
-{"save", json_wiki_save, 1},
40
+{"preview", json_wiki_preview, 0},
41
+{"save", json_wiki_save, 0},
3942
{"timeline", json_timeline_wiki,0},
4043
/* Last entry MUST have a NULL name. */
4144
{NULL,NULL,0}
4245
};
4346
@@ -48,166 +51,236 @@
4851
*/
4952
cson_value * json_page_wiki(){
5053
return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
5154
}
5255
56
+char * json_wiki_get_uuid_for_rid( int rid )
57
+{
58
+ return db_text(NULL,
59
+ "SELECT b.uuid FROM tag t, tagxref x, blob b"
60
+ " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
61
+ " AND b.rid=x.rid AND b.rid=%d"
62
+ " ORDER BY x.mtime DESC LIMIT 1",
63
+ rid
64
+ );
65
+}
5366
5467
/*
55
-** Loads the given wiki page and creates a JSON object representation
56
-** of it. If the page is not found then NULL is returned. If
57
-** contentFormat is positive true then the page content is HTML-ized
58
-** using fossil's conventional wiki format, if it is negative then no
59
-** parsing is performed, if it is 0 then the content is not returned
60
-** in the response. If contentFormat is 0 then the contentSize reflects
61
-** the number of bytes, not characters, stored in the page.
68
+** Tries to load a wiki page from the given rid creates a JSON object
69
+** representation of it. If the page is not found then NULL is
70
+** returned. If contentFormat is positive then the page content
71
+** is HTML-ized using fossil's conventional wiki format, if it is
72
+** negative then no parsing is performed, if it is 0 then the content
73
+** is not returned in the response. If contentFormat is 0 then the
74
+** contentSize reflects the number of bytes, not characters, stored in
75
+** the page.
6276
**
6377
** The returned value, if not NULL, is-a JSON Object owned by the
6478
** caller. If it returns NULL then it may set g.json's error state.
6579
*/
66
-cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){
67
- int rid;
68
- Manifest *pWiki = 0;
69
- char * zUuid = NULL;
70
- Stmt q;
71
- db_prepare(&q,
72
- "SELECT x.rid, b.uuid FROM tag t, tagxref x, blob b"
73
- " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
74
- " AND b.rid=x.rid"
75
- " ORDER BY x.mtime DESC LIMIT 1",
76
- zPageName
77
- );
78
- if( (SQLITE_ROW != db_step(&q)) ){
79
- db_finalize(&q);
80
- json_set_err( FSL_JSON_E_RESOURCE_NOT_FOUND, "Wiki page not found: %s",
81
- zPageName );
82
- return NULL;
83
- }
84
- rid = db_column_int(&q,0);
85
- zUuid = db_column_malloc(&q,1);
86
- db_finalize(&q);
80
+cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
81
+ Manifest * pWiki = NULL;
8782
if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
88
- free(zUuid);
8983
json_set_err( FSL_JSON_E_UNKNOWN,
90
- "Error reading wiki page from manifest (rid=%d, uuid=%s).",
91
- rid, zUuid );
84
+ "Error reading wiki page from manifest (rid=%d).",
85
+ rid );
9286
return NULL;
9387
}else{
94
- char const * zFormat = NULL;
88
+ /*char const * zFormat = NULL;*/
9589
unsigned int len = 0;
9690
cson_object * pay = cson_new_object();
9791
char const * zBody = pWiki->zWiki;
98
- cson_object_set(pay,"name",json_new_string(zPageName));
92
+ char const * zFormat = NULL;
93
+ char * zUuid = json_wiki_get_uuid_for_rid(rid);
94
+ cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
9995
cson_object_set(pay,"uuid",json_new_string(zUuid));
10096
free(zUuid);
10197
zUuid = NULL;
98
+ if( pWiki->nParent > 0 ){
99
+ cson_object_set( pay, "parent", json_new_string(pWiki->azParent[0]) )
100
+ /* Reminder: wiki pages do not branch and have only one parent
101
+ (except for the initial version, which has no parents). */;
102
+ }
102103
/*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/
103
- cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser));
104
+ cson_object_set(pay,"user",json_new_string(pWiki->zUser));
104105
cson_object_set(pay,FossilJsonKeys.timestamp,
105106
json_julian_to_timestamp(pWiki->rDate));
106
-
107
-
108107
if(0 == contentFormat){
109
- cson_object_set(pay,"contentLength",
108
+ cson_object_set(pay,"size",
110109
json_new_int((cson_int_t)(zBody?strlen(zBody):0)));
111110
}else{
112
- cson_object_set(pay,"contentFormat",json_new_string(zFormat));
113111
if( contentFormat>0 ){/*HTML-ize it*/
112
+ zFormat = "html";
114113
Blob content = empty_blob;
115114
Blob raw = empty_blob;
116115
if(zBody && *zBody){
117116
blob_append(&raw,zBody,-1);
118117
wiki_convert(&raw,&content,0);
119118
len = (unsigned int)blob_size(&content);
120119
}
121
- cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
120
+ cson_object_set(pay,"size",json_new_int((cson_int_t)len));
122121
cson_object_set(pay,"content",
123122
cson_value_new_string(blob_buffer(&content),len));
124123
blob_reset(&content);
125124
blob_reset(&raw);
126125
}else{/*raw format*/
126
+ zFormat = "raw";
127127
len = zBody ? strlen(zBody) : 0;
128
- cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
128
+ cson_object_set(pay,"size",json_new_int((cson_int_t)len));
129129
cson_object_set(pay,"content",cson_value_new_string(zBody,len));
130130
}
131
+ cson_object_set(pay,"contentFormat",json_new_string(zFormat));
132
+
131133
}
132134
/*TODO: add 'T' (tag) fields*/
133135
/*TODO: add the 'A' card (file attachment) entries?*/
134136
manifest_destroy(pWiki);
135137
return cson_object_value(pay);
136138
}
137
-
139
+}
140
+
141
+/*
142
+** Searches for the latest version of a wiki page with the given
143
+** name. If found it behaves like json_get_wiki_page_by_rid(theRid,
144
+** contentFormat), else it returns NULL.
145
+*/
146
+cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){
147
+ int rid;
148
+ rid = db_int(0,
149
+ "SELECT x.rid FROM tag t, tagxref x, blob b"
150
+ " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
151
+ " AND b.rid=x.rid"
152
+ " ORDER BY x.mtime DESC LIMIT 1",
153
+ zPageName
154
+ );
155
+ if( 0==rid ){
156
+ json_set_err( FSL_JSON_E_RESOURCE_NOT_FOUND, "Wiki page not found: %s",
157
+ zPageName );
158
+ return NULL;
159
+ }
160
+ return json_get_wiki_page_by_rid(rid, contentFormat);
138161
}
139162
163
+
164
+/*
165
+** Searches json_find_option_ctr("format",NULL,"f") for a flag.
166
+** If not found it returns defaultValue else it returns a value
167
+** depending on the first character of the format option:
168
+**
169
+** [h]tml = 1
170
+** [n]one = 0
171
+** [r]aw = -1
172
+**
173
+** The return value is intended for use with
174
+** json_get_wiki_page_by_rid() and friends.
175
+*/
176
+char json_wiki_get_content_format_flag( char defaultValue ){
177
+ char contentFormat = defaultValue;
178
+ char const * zFormat = json_find_option_cstr("format",NULL,"f");
179
+ if( !zFormat || !*zFormat ){
180
+ return contentFormat;
181
+ }
182
+ else if('r'==*zFormat){
183
+ contentFormat = -1;
184
+ }
185
+ else if('h'==*zFormat){
186
+ contentFormat = 1;
187
+ }
188
+ else if('n'==*zFormat){
189
+ contentFormat = 0;
190
+ }
191
+ return contentFormat;
192
+}
140193
141194
/*
142
-** Searches for a wiki page with the given rid. If found it behaves
143
-** like json_get_wiki_page_by_name(pageName, contentFormat), else it returns
144
-** NULL.
195
+** Helper for /json/wiki/get and /json/wiki/preview. At least one of
196
+** zPageName (wiki page name) or zSymname must be set to a
197
+** non-empty/non-NULL value. zSymname takes precedence. On success
198
+** the result of one of json_get_wiki_page_by_rid() or
199
+** json_get_wiki_page_by_name() will be returned (owned by the
200
+** caller). On error g.json's error state is set and NULL is returned.
145201
*/
146
-cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
147
- char * zPageName = NULL;
148
- cson_value * rc = NULL;
149
- zPageName = db_text(NULL,
150
- "SELECT substr(t.tagname,6) AS name "
151
- " FROM tag t, tagxref x, blob b "
152
- " WHERE b.rid=%d "
153
- " AND t.tagname GLOB 'wiki-*'"
154
- " AND x.tagid=t.tagid AND b.rid=x.rid ",
155
- rid);
156
- if( zPageName ){
157
- rc = json_get_wiki_page_by_name(zPageName, contentFormat);
158
- free(zPageName);
159
- }
160
- return rc;
202
+static cson_value * json_wiki_get_by_name_or_symname(char const * zPageName,
203
+ char const * zSymname,
204
+ char contentFormat ){
205
+ if(!zSymname || !*zSymname){
206
+ return json_get_wiki_page_by_name(zPageName, contentFormat);
207
+ }else{
208
+ int rid = symbolic_name_to_rid( zSymname ? zSymname : zPageName, "w" );
209
+ if(rid<0){
210
+ json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
211
+ "UUID [%s] is ambiguious.", zSymname);
212
+ return NULL;
213
+ }else if(rid==0){
214
+ json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
215
+ "UUID [%s] does not resolve to a wiki page.", zSymname);
216
+ return NULL;
217
+ }else{
218
+ return json_get_wiki_page_by_rid(rid, contentFormat);
219
+ }
220
+ }
161221
}
162222
163223
/*
164224
** Implementation of /json/wiki/get.
165225
**
166226
*/
167227
static cson_value * json_wiki_get(){
168228
char const * zPageName;
169
- char const * zFormat = NULL;
229
+ char const * zSymName = NULL;
170230
char contentFormat = -1;
171231
if( !g.perm.RdWiki && !g.perm.Read ){
172232
json_set_err(FSL_JSON_E_DENIED,
173233
"Requires 'o' or 'j' access.");
174234
return NULL;
175235
}
176
- zPageName = json_find_option_cstr("name",NULL,"n")
177
- /* Damn... fossil automatically sets name to the PATH
178
- part after /json, so we need a workaround down here....
179
- */
180
- ;
181
- if( zPageName && (NULL != strstr(zPageName, "/"))){
182
- /* Assume that we picked up a path remnant. */
183
- zPageName = NULL;
184
- }
185
- if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
186
- zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
187
- }
188
- if(!zPageName){
189
- zPageName = json_command_arg(g.json.dispatchDepth+1);
190
- }
191
- if(!zPageName||!*zPageName){
236
+ zPageName = json_find_option_cstr2("name",NULL,"n",g.json.dispatchDepth+1);
237
+
238
+ zSymName = json_find_option_cstr("uuid",NULL,"u");
239
+
240
+ if((!zPageName||!*zPageName) && (!zSymName || !*zSymName)){
241
+ json_set_err(FSL_JSON_E_MISSING_ARGS,
242
+ "At least one of the 'name' or 'uuid' arguments must be provided.");
243
+ return NULL;
244
+ }
245
+
246
+ /* TODO: see if we have a page named zPageName. If not, try to resolve
247
+ zPageName as a UUID.
248
+ */
249
+
250
+ contentFormat = json_wiki_get_content_format_flag(contentFormat);
251
+ return json_wiki_get_by_name_or_symname( zPageName, zSymName, contentFormat );
252
+}
253
+
254
+/*
255
+** Implementation of /json/wiki/preview.
256
+**
257
+*/
258
+static cson_value * json_wiki_preview(){
259
+ char const * zContent = NULL;
260
+ cson_value * pay = NULL;
261
+ Blob contentOrig = empty_blob;
262
+ Blob contentHtml = empty_blob;
263
+ if( !g.perm.WrWiki ){
264
+ json_set_err(FSL_JSON_E_DENIED,
265
+ "Requires 'k' access.");
266
+ return NULL;
267
+ }
268
+ zContent = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
269
+ if(!zContent) {
192270
json_set_err(FSL_JSON_E_MISSING_ARGS,
193
- "'name' argument is missing.");
194
- return NULL;
195
- }
196
-
197
- zFormat = json_find_option_cstr("format",NULL,"f");
198
- if(!zFormat || !*zFormat || ('r'==*zFormat)){
199
- contentFormat = -1;
200
- }
201
- else if('h'==*zFormat){
202
- contentFormat = 1;
203
- }
204
- else if('n'==*zFormat){
205
- contentFormat = 0;
206
- }
207
- return json_get_wiki_page_by_name(zPageName, contentFormat);
208
-}
271
+ "The 'payload' property must be a string containing the wiki code to preview.");
272
+ return NULL;
273
+ }
274
+ blob_append( &contentOrig, zContent, (int)cson_string_length_bytes(cson_value_get_string(g.json.reqPayload.v)) );
275
+ wiki_convert( &contentOrig, &contentHtml, 0 );
276
+ blob_reset( &contentOrig );
277
+ pay = cson_value_new_string( blob_str(&contentHtml), (unsigned int)blob_size(&contentHtml));
278
+ blob_reset( &contentHtml );
279
+ return pay;
280
+}
281
+
209282
210283
/*
211284
** Internal impl of /wiki/save and /wiki/create. If createMode is 0
212285
** and the page already exists then a
213286
** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered. If
@@ -219,15 +292,15 @@
219292
** here if it doesn't already exist. With that, save/create would
220293
** become one operation. That said, i expect there are people who
221294
** would categorize such behaviour as "being too clever" or "doing too
222295
** much automatically" (and i would likely agree with them).
223296
**
224
-** If allowCreateIfExists is true then this function will allow a new
297
+** If allowCreateIfNotExists is true then this function will allow a new
225298
** page to be created even if createMode is false.
226299
*/
227300
static cson_value * json_wiki_create_or_save(char createMode,
228
- char allowCreateIfExists){
301
+ char allowCreateIfNotExists){
229302
Blob content = empty_blob; /* wiki page content */
230303
cson_value * nameV; /* wiki page name */
231304
char const * zPageName; /* cstr form of page name */
232305
cson_value * contentV; /* passed-in content */
233306
cson_value * emptyContent = NULL; /* placeholder for empty content. */
@@ -247,10 +320,15 @@
247320
json_set_err( FSL_JSON_E_MISSING_ARGS,
248321
"'name' parameter is missing.");
249322
return NULL;
250323
}
251324
zPageName = cson_string_cstr(cson_value_get_string(nameV));
325
+ if(!zPageName || !*zPageName){
326
+ json_set_err(FSL_JSON_E_INVALID_ARGS,
327
+ "'name' parameter must be a non-empty string.");
328
+ return NULL;
329
+ }
252330
rid = db_int(0,
253331
"SELECT x.rid FROM tag t, tagxref x"
254332
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
255333
" ORDER BY x.mtime DESC LIMIT 1",
256334
zPageName
@@ -261,20 +339,20 @@
261339
json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
262340
"Wiki page '%s' already exists.",
263341
zPageName);
264342
goto error;
265343
}
266
- }else if(!allowCreateIfExists){
344
+ }else if(!createMode && !allowCreateIfNotExists){
267345
json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
268346
"Wiki page '%s' not found.",
269347
zPageName);
270348
goto error;
271349
}
272350
273351
contentV = json_req_payload_get("content");
274352
if( !contentV ){
275
- if( createMode || (!rid && allowCreateIfExists) ){
353
+ if( createMode || (!rid && allowCreateIfNotExists) ){
276354
contentV = emptyContent = cson_value_new_string("",0);
277355
}else{
278356
json_set_err(FSL_JSON_E_MISSING_ARGS,
279357
"'content' parameter is missing.");
280358
goto error;
@@ -281,11 +359,11 @@
281359
}
282360
}
283361
if( !cson_value_is_string(nameV)
284362
|| !cson_value_is_string(contentV)){
285363
json_set_err(FSL_JSON_E_INVALID_ARGS,
286
- "'name' and 'content' parameters must be strings.");
364
+ "'content' parameter must be a string.");
287365
goto error;
288366
}
289367
jstr = cson_value_get_string(contentV);
290368
contentLen = (int)cson_string_length_bytes(jstr);
291369
if(contentLen){
@@ -341,22 +419,40 @@
341419
** Implementation of /json/wiki/list.
342420
*/
343421
static cson_value * json_wiki_list(){
344422
cson_value * listV = NULL;
345423
cson_array * list = NULL;
346
- Stmt q;
424
+ char const * zGlob = NULL;
425
+ Stmt q = empty_Stmt;
426
+ Blob sql = empty_blob;
347427
char const verbose = json_find_option_bool("verbose",NULL,"v",0);
428
+ char fInvert = json_find_option_bool("invert",NULL,"i",0);;
348429
349430
if( !g.perm.RdWiki && !g.perm.Read ){
350431
json_set_err(FSL_JSON_E_DENIED,
351432
"Requires 'j' or 'o' permissions.");
352433
return NULL;
353434
}
354
- db_prepare(&q,"SELECT"
355
- " substr(tagname,6) as name"
356
- " FROM tag WHERE tagname GLOB 'wiki-*'"
357
- " ORDER BY lower(name)");
435
+ blob_append(&sql,"SELECT"
436
+ " substr(tagname,6) as name"
437
+ " FROM tag WHERE tagname GLOB 'wiki-*'",
438
+ -1);
439
+ zGlob = json_find_option_cstr("glob",NULL,"g");
440
+ if(zGlob && *zGlob){
441
+ blob_appendf(&sql," AND name %s GLOB %Q",
442
+ fInvert ? "NOT" : "", zGlob);
443
+ }else{
444
+ zGlob = json_find_option_cstr("like",NULL,"l");
445
+ if(zGlob && *zGlob){
446
+ blob_appendf(&sql," AND name %s LIKE %Q",
447
+ fInvert ? "NOT" : "",
448
+ zGlob);
449
+ }
450
+ }
451
+ blob_append(&sql," ORDER BY lower(name)", -1);
452
+ db_prepare(&q,"%s", blob_str(&sql));
453
+ blob_reset(&sql);
358454
listV = cson_value_new_array();
359455
list = cson_value_get_array(listV);
360456
while( SQLITE_ROW == db_step(&q) ){
361457
cson_value * v;
362458
if( verbose ){
@@ -384,6 +480,109 @@
384480
listV = NULL;
385481
end:
386482
db_finalize(&q);
387483
return listV;
388484
}
485
+
486
+static cson_value * json_wiki_diff(){
487
+ char const * zV1 = NULL;
488
+ char const * zV2 = NULL;
489
+ cson_object * pay = NULL;
490
+ int argPos = g.json.dispatchDepth;
491
+ int r1 = 0, r2 = 0;
492
+ Manifest * pW1 = NULL, *pW2 = NULL;
493
+ Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
494
+ char const * zErrTag = NULL;
495
+ int diffFlags;
496
+ char * zUuid = NULL;
497
+ if( !g.perm.History ){
498
+ json_set_err(FSL_JSON_E_DENIED,
499
+ "Requires 'h' permissions.");
500
+ return NULL;
501
+ }
502
+
503
+
504
+ zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );
505
+ zV2 = json_find_option_cstr2( "v2",NULL, NULL, ++argPos );
506
+ if(!zV1 || !*zV1 || !zV2 || !*zV2) {
507
+ json_set_err(FSL_JSON_E_INVALID_ARGS,
508
+ "Requires both 'v1' and 'v2' arguments.");
509
+ return NULL;
510
+ }
511
+
512
+ r1 = symbolic_name_to_rid( zV1, "w" );
513
+ zErrTag = zV1;
514
+ if(r1<0){
515
+ goto ambiguous;
516
+ }else if(0==r1){
517
+ goto invalid;
518
+ }
519
+
520
+ r2 = symbolic_name_to_rid( zV2, "w" );
521
+ zErrTag = zV2;
522
+ if(r2<0){
523
+ goto ambiguous;
524
+ }else if(0==r2){
525
+ goto invalid;
526
+ }
527
+
528
+ zErrTag = zV1;
529
+ pW1 = manifest_get(r1, CFTYPE_WIKI);
530
+ if( pW1==0 ) {
531
+ goto manifest;
532
+ }
533
+ zErrTag = zV2;
534
+ pW2 = manifest_get(r2, CFTYPE_WIKI);
535
+ if( pW2==0 ) {
536
+ goto manifest;
537
+ }
538
+
539
+ blob_init(&w1, pW1->zWiki, -1);
540
+ blob_zero(&w2);
541
+ blob_init(&w2, pW2->zWiki, -1);
542
+ blob_zero(&d);
543
+ diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
544
+ text_diff(&w2, &w1, &d, diffFlags);
545
+ blob_reset(&w1);
546
+ blob_reset(&w2);
547
+
548
+ pay = cson_new_object();
549
+
550
+ zUuid = json_wiki_get_uuid_for_rid( pW1->rid );
551
+ cson_object_set(pay, "v1", json_new_string(zUuid) );
552
+ free(zUuid);
553
+ zUuid = json_wiki_get_uuid_for_rid( pW2->rid );
554
+ cson_object_set(pay, "v2", json_new_string(zUuid) );
555
+ free(zUuid);
556
+ zUuid = NULL;
557
+
558
+ manifest_destroy(pW1);
559
+ manifest_destroy(pW2);
560
+
561
+ cson_object_set(pay, "diff",
562
+ cson_value_new_string( blob_str(&d),
563
+ (unsigned int)blob_size(&d)));
564
+
565
+ return cson_object_value(pay);
566
+
567
+ manifest:
568
+ json_set_err(FSL_JSON_E_UNKNOWN,
569
+ "Could not load wiki manifest for UUID [%s].",
570
+ zErrTag);
571
+ goto end;
572
+
573
+ ambiguous:
574
+ json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
575
+ "UUID [%s] is ambiguous.", zErrTag);
576
+ goto end;
577
+
578
+ invalid:
579
+ json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
580
+ "UUID [%s] not found.", zErrTag);
581
+ goto end;
582
+
583
+ end:
584
+ cson_free_object(pay);
585
+ return NULL;
586
+}
587
+
389588
#endif /* FOSSIL_ENABLE_JSON */
390589
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -24,20 +24,23 @@
24 #endif
25
26 static cson_value * json_wiki_create();
27 static cson_value * json_wiki_get();
28 static cson_value * json_wiki_list();
 
29 static cson_value * json_wiki_save();
30
31 /*
32 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
33 */
34 static const JsonPageDef JsonPageDefs_Wiki[] = {
35 {"create", json_wiki_create, 1},
 
36 {"get", json_wiki_get, 0},
37 {"list", json_wiki_list, 0},
38 {"save", json_wiki_save, 1},
 
39 {"timeline", json_timeline_wiki,0},
40 /* Last entry MUST have a NULL name. */
41 {NULL,NULL,0}
42 };
43
@@ -48,166 +51,236 @@
48 */
49 cson_value * json_page_wiki(){
50 return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
51 }
52
 
 
 
 
 
 
 
 
 
 
53
54 /*
55 ** Loads the given wiki page and creates a JSON object representation
56 ** of it. If the page is not found then NULL is returned. If
57 ** contentFormat is positive true then the page content is HTML-ized
58 ** using fossil's conventional wiki format, if it is negative then no
59 ** parsing is performed, if it is 0 then the content is not returned
60 ** in the response. If contentFormat is 0 then the contentSize reflects
61 ** the number of bytes, not characters, stored in the page.
 
62 **
63 ** The returned value, if not NULL, is-a JSON Object owned by the
64 ** caller. If it returns NULL then it may set g.json's error state.
65 */
66 cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){
67 int rid;
68 Manifest *pWiki = 0;
69 char * zUuid = NULL;
70 Stmt q;
71 db_prepare(&q,
72 "SELECT x.rid, b.uuid FROM tag t, tagxref x, blob b"
73 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
74 " AND b.rid=x.rid"
75 " ORDER BY x.mtime DESC LIMIT 1",
76 zPageName
77 );
78 if( (SQLITE_ROW != db_step(&q)) ){
79 db_finalize(&q);
80 json_set_err( FSL_JSON_E_RESOURCE_NOT_FOUND, "Wiki page not found: %s",
81 zPageName );
82 return NULL;
83 }
84 rid = db_column_int(&q,0);
85 zUuid = db_column_malloc(&q,1);
86 db_finalize(&q);
87 if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
88 free(zUuid);
89 json_set_err( FSL_JSON_E_UNKNOWN,
90 "Error reading wiki page from manifest (rid=%d, uuid=%s).",
91 rid, zUuid );
92 return NULL;
93 }else{
94 char const * zFormat = NULL;
95 unsigned int len = 0;
96 cson_object * pay = cson_new_object();
97 char const * zBody = pWiki->zWiki;
98 cson_object_set(pay,"name",json_new_string(zPageName));
 
 
99 cson_object_set(pay,"uuid",json_new_string(zUuid));
100 free(zUuid);
101 zUuid = NULL;
 
 
 
 
 
102 /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/
103 cson_object_set(pay,"lastSavedBy",json_new_string(pWiki->zUser));
104 cson_object_set(pay,FossilJsonKeys.timestamp,
105 json_julian_to_timestamp(pWiki->rDate));
106
107
108 if(0 == contentFormat){
109 cson_object_set(pay,"contentLength",
110 json_new_int((cson_int_t)(zBody?strlen(zBody):0)));
111 }else{
112 cson_object_set(pay,"contentFormat",json_new_string(zFormat));
113 if( contentFormat>0 ){/*HTML-ize it*/
 
114 Blob content = empty_blob;
115 Blob raw = empty_blob;
116 if(zBody && *zBody){
117 blob_append(&raw,zBody,-1);
118 wiki_convert(&raw,&content,0);
119 len = (unsigned int)blob_size(&content);
120 }
121 cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
122 cson_object_set(pay,"content",
123 cson_value_new_string(blob_buffer(&content),len));
124 blob_reset(&content);
125 blob_reset(&raw);
126 }else{/*raw format*/
 
127 len = zBody ? strlen(zBody) : 0;
128 cson_object_set(pay,"contentLength",json_new_int((cson_int_t)len));
129 cson_object_set(pay,"content",cson_value_new_string(zBody,len));
130 }
 
 
131 }
132 /*TODO: add 'T' (tag) fields*/
133 /*TODO: add the 'A' card (file attachment) entries?*/
134 manifest_destroy(pWiki);
135 return cson_object_value(pay);
136 }
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138 }
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
141 /*
142 ** Searches for a wiki page with the given rid. If found it behaves
143 ** like json_get_wiki_page_by_name(pageName, contentFormat), else it returns
144 ** NULL.
 
 
 
145 */
146 cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
147 char * zPageName = NULL;
148 cson_value * rc = NULL;
149 zPageName = db_text(NULL,
150 "SELECT substr(t.tagname,6) AS name "
151 " FROM tag t, tagxref x, blob b "
152 " WHERE b.rid=%d "
153 " AND t.tagname GLOB 'wiki-*'"
154 " AND x.tagid=t.tagid AND b.rid=x.rid ",
155 rid);
156 if( zPageName ){
157 rc = json_get_wiki_page_by_name(zPageName, contentFormat);
158 free(zPageName);
159 }
160 return rc;
 
 
 
 
161 }
162
163 /*
164 ** Implementation of /json/wiki/get.
165 **
166 */
167 static cson_value * json_wiki_get(){
168 char const * zPageName;
169 char const * zFormat = NULL;
170 char contentFormat = -1;
171 if( !g.perm.RdWiki && !g.perm.Read ){
172 json_set_err(FSL_JSON_E_DENIED,
173 "Requires 'o' or 'j' access.");
174 return NULL;
175 }
176 zPageName = json_find_option_cstr("name",NULL,"n")
177 /* Damn... fossil automatically sets name to the PATH
178 part after /json, so we need a workaround down here....
179 */
180 ;
181 if( zPageName && (NULL != strstr(zPageName, "/"))){
182 /* Assume that we picked up a path remnant. */
183 zPageName = NULL;
184 }
185 if( !zPageName && cson_value_is_string(g.json.reqPayload.v) ){
186 zPageName = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
187 }
188 if(!zPageName){
189 zPageName = json_command_arg(g.json.dispatchDepth+1);
190 }
191 if(!zPageName||!*zPageName){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192 json_set_err(FSL_JSON_E_MISSING_ARGS,
193 "'name' argument is missing.");
194 return NULL;
195 }
196
197 zFormat = json_find_option_cstr("format",NULL,"f");
198 if(!zFormat || !*zFormat || ('r'==*zFormat)){
199 contentFormat = -1;
200 }
201 else if('h'==*zFormat){
202 contentFormat = 1;
203 }
204 else if('n'==*zFormat){
205 contentFormat = 0;
206 }
207 return json_get_wiki_page_by_name(zPageName, contentFormat);
208 }
209
210 /*
211 ** Internal impl of /wiki/save and /wiki/create. If createMode is 0
212 ** and the page already exists then a
213 ** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered. If
@@ -219,15 +292,15 @@
219 ** here if it doesn't already exist. With that, save/create would
220 ** become one operation. That said, i expect there are people who
221 ** would categorize such behaviour as "being too clever" or "doing too
222 ** much automatically" (and i would likely agree with them).
223 **
224 ** If allowCreateIfExists is true then this function will allow a new
225 ** page to be created even if createMode is false.
226 */
227 static cson_value * json_wiki_create_or_save(char createMode,
228 char allowCreateIfExists){
229 Blob content = empty_blob; /* wiki page content */
230 cson_value * nameV; /* wiki page name */
231 char const * zPageName; /* cstr form of page name */
232 cson_value * contentV; /* passed-in content */
233 cson_value * emptyContent = NULL; /* placeholder for empty content. */
@@ -247,10 +320,15 @@
247 json_set_err( FSL_JSON_E_MISSING_ARGS,
248 "'name' parameter is missing.");
249 return NULL;
250 }
251 zPageName = cson_string_cstr(cson_value_get_string(nameV));
 
 
 
 
 
252 rid = db_int(0,
253 "SELECT x.rid FROM tag t, tagxref x"
254 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
255 " ORDER BY x.mtime DESC LIMIT 1",
256 zPageName
@@ -261,20 +339,20 @@
261 json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
262 "Wiki page '%s' already exists.",
263 zPageName);
264 goto error;
265 }
266 }else if(!allowCreateIfExists){
267 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
268 "Wiki page '%s' not found.",
269 zPageName);
270 goto error;
271 }
272
273 contentV = json_req_payload_get("content");
274 if( !contentV ){
275 if( createMode || (!rid && allowCreateIfExists) ){
276 contentV = emptyContent = cson_value_new_string("",0);
277 }else{
278 json_set_err(FSL_JSON_E_MISSING_ARGS,
279 "'content' parameter is missing.");
280 goto error;
@@ -281,11 +359,11 @@
281 }
282 }
283 if( !cson_value_is_string(nameV)
284 || !cson_value_is_string(contentV)){
285 json_set_err(FSL_JSON_E_INVALID_ARGS,
286 "'name' and 'content' parameters must be strings.");
287 goto error;
288 }
289 jstr = cson_value_get_string(contentV);
290 contentLen = (int)cson_string_length_bytes(jstr);
291 if(contentLen){
@@ -341,22 +419,40 @@
341 ** Implementation of /json/wiki/list.
342 */
343 static cson_value * json_wiki_list(){
344 cson_value * listV = NULL;
345 cson_array * list = NULL;
346 Stmt q;
 
 
347 char const verbose = json_find_option_bool("verbose",NULL,"v",0);
 
348
349 if( !g.perm.RdWiki && !g.perm.Read ){
350 json_set_err(FSL_JSON_E_DENIED,
351 "Requires 'j' or 'o' permissions.");
352 return NULL;
353 }
354 db_prepare(&q,"SELECT"
355 " substr(tagname,6) as name"
356 " FROM tag WHERE tagname GLOB 'wiki-*'"
357 " ORDER BY lower(name)");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358 listV = cson_value_new_array();
359 list = cson_value_get_array(listV);
360 while( SQLITE_ROW == db_step(&q) ){
361 cson_value * v;
362 if( verbose ){
@@ -384,6 +480,109 @@
384 listV = NULL;
385 end:
386 db_finalize(&q);
387 return listV;
388 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389 #endif /* FOSSIL_ENABLE_JSON */
390
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -24,20 +24,23 @@
24 #endif
25
26 static cson_value * json_wiki_create();
27 static cson_value * json_wiki_get();
28 static cson_value * json_wiki_list();
29 static cson_value * json_wiki_preview();
30 static cson_value * json_wiki_save();
31 static cson_value * json_wiki_diff();
32 /*
33 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
34 */
35 static const JsonPageDef JsonPageDefs_Wiki[] = {
36 {"create", json_wiki_create, 0},
37 {"diff", json_wiki_diff, 0},
38 {"get", json_wiki_get, 0},
39 {"list", json_wiki_list, 0},
40 {"preview", json_wiki_preview, 0},
41 {"save", json_wiki_save, 0},
42 {"timeline", json_timeline_wiki,0},
43 /* Last entry MUST have a NULL name. */
44 {NULL,NULL,0}
45 };
46
@@ -48,166 +51,236 @@
51 */
52 cson_value * json_page_wiki(){
53 return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
54 }
55
56 char * json_wiki_get_uuid_for_rid( int rid )
57 {
58 return db_text(NULL,
59 "SELECT b.uuid FROM tag t, tagxref x, blob b"
60 " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
61 " AND b.rid=x.rid AND b.rid=%d"
62 " ORDER BY x.mtime DESC LIMIT 1",
63 rid
64 );
65 }
66
67 /*
68 ** Tries to load a wiki page from the given rid creates a JSON object
69 ** representation of it. If the page is not found then NULL is
70 ** returned. If contentFormat is positive then the page content
71 ** is HTML-ized using fossil's conventional wiki format, if it is
72 ** negative then no parsing is performed, if it is 0 then the content
73 ** is not returned in the response. If contentFormat is 0 then the
74 ** contentSize reflects the number of bytes, not characters, stored in
75 ** the page.
76 **
77 ** The returned value, if not NULL, is-a JSON Object owned by the
78 ** caller. If it returns NULL then it may set g.json's error state.
79 */
80 cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
81 Manifest * pWiki = NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82 if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
 
83 json_set_err( FSL_JSON_E_UNKNOWN,
84 "Error reading wiki page from manifest (rid=%d).",
85 rid );
86 return NULL;
87 }else{
88 /*char const * zFormat = NULL;*/
89 unsigned int len = 0;
90 cson_object * pay = cson_new_object();
91 char const * zBody = pWiki->zWiki;
92 char const * zFormat = NULL;
93 char * zUuid = json_wiki_get_uuid_for_rid(rid);
94 cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
95 cson_object_set(pay,"uuid",json_new_string(zUuid));
96 free(zUuid);
97 zUuid = NULL;
98 if( pWiki->nParent > 0 ){
99 cson_object_set( pay, "parent", json_new_string(pWiki->azParent[0]) )
100 /* Reminder: wiki pages do not branch and have only one parent
101 (except for the initial version, which has no parents). */;
102 }
103 /*cson_object_set(pay,"rid",json_new_int((cson_int_t)rid));*/
104 cson_object_set(pay,"user",json_new_string(pWiki->zUser));
105 cson_object_set(pay,FossilJsonKeys.timestamp,
106 json_julian_to_timestamp(pWiki->rDate));
 
 
107 if(0 == contentFormat){
108 cson_object_set(pay,"size",
109 json_new_int((cson_int_t)(zBody?strlen(zBody):0)));
110 }else{
 
111 if( contentFormat>0 ){/*HTML-ize it*/
112 zFormat = "html";
113 Blob content = empty_blob;
114 Blob raw = empty_blob;
115 if(zBody && *zBody){
116 blob_append(&raw,zBody,-1);
117 wiki_convert(&raw,&content,0);
118 len = (unsigned int)blob_size(&content);
119 }
120 cson_object_set(pay,"size",json_new_int((cson_int_t)len));
121 cson_object_set(pay,"content",
122 cson_value_new_string(blob_buffer(&content),len));
123 blob_reset(&content);
124 blob_reset(&raw);
125 }else{/*raw format*/
126 zFormat = "raw";
127 len = zBody ? strlen(zBody) : 0;
128 cson_object_set(pay,"size",json_new_int((cson_int_t)len));
129 cson_object_set(pay,"content",cson_value_new_string(zBody,len));
130 }
131 cson_object_set(pay,"contentFormat",json_new_string(zFormat));
132
133 }
134 /*TODO: add 'T' (tag) fields*/
135 /*TODO: add the 'A' card (file attachment) entries?*/
136 manifest_destroy(pWiki);
137 return cson_object_value(pay);
138 }
139 }
140
141 /*
142 ** Searches for the latest version of a wiki page with the given
143 ** name. If found it behaves like json_get_wiki_page_by_rid(theRid,
144 ** contentFormat), else it returns NULL.
145 */
146 cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){
147 int rid;
148 rid = db_int(0,
149 "SELECT x.rid FROM tag t, tagxref x, blob b"
150 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
151 " AND b.rid=x.rid"
152 " ORDER BY x.mtime DESC LIMIT 1",
153 zPageName
154 );
155 if( 0==rid ){
156 json_set_err( FSL_JSON_E_RESOURCE_NOT_FOUND, "Wiki page not found: %s",
157 zPageName );
158 return NULL;
159 }
160 return json_get_wiki_page_by_rid(rid, contentFormat);
161 }
162
163
164 /*
165 ** Searches json_find_option_ctr("format",NULL,"f") for a flag.
166 ** If not found it returns defaultValue else it returns a value
167 ** depending on the first character of the format option:
168 **
169 ** [h]tml = 1
170 ** [n]one = 0
171 ** [r]aw = -1
172 **
173 ** The return value is intended for use with
174 ** json_get_wiki_page_by_rid() and friends.
175 */
176 char json_wiki_get_content_format_flag( char defaultValue ){
177 char contentFormat = defaultValue;
178 char const * zFormat = json_find_option_cstr("format",NULL,"f");
179 if( !zFormat || !*zFormat ){
180 return contentFormat;
181 }
182 else if('r'==*zFormat){
183 contentFormat = -1;
184 }
185 else if('h'==*zFormat){
186 contentFormat = 1;
187 }
188 else if('n'==*zFormat){
189 contentFormat = 0;
190 }
191 return contentFormat;
192 }
193
194 /*
195 ** Helper for /json/wiki/get and /json/wiki/preview. At least one of
196 ** zPageName (wiki page name) or zSymname must be set to a
197 ** non-empty/non-NULL value. zSymname takes precedence. On success
198 ** the result of one of json_get_wiki_page_by_rid() or
199 ** json_get_wiki_page_by_name() will be returned (owned by the
200 ** caller). On error g.json's error state is set and NULL is returned.
201 */
202 static cson_value * json_wiki_get_by_name_or_symname(char const * zPageName,
203 char const * zSymname,
204 char contentFormat ){
205 if(!zSymname || !*zSymname){
206 return json_get_wiki_page_by_name(zPageName, contentFormat);
207 }else{
208 int rid = symbolic_name_to_rid( zSymname ? zSymname : zPageName, "w" );
209 if(rid<0){
210 json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
211 "UUID [%s] is ambiguious.", zSymname);
212 return NULL;
213 }else if(rid==0){
214 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
215 "UUID [%s] does not resolve to a wiki page.", zSymname);
216 return NULL;
217 }else{
218 return json_get_wiki_page_by_rid(rid, contentFormat);
219 }
220 }
221 }
222
223 /*
224 ** Implementation of /json/wiki/get.
225 **
226 */
227 static cson_value * json_wiki_get(){
228 char const * zPageName;
229 char const * zSymName = NULL;
230 char contentFormat = -1;
231 if( !g.perm.RdWiki && !g.perm.Read ){
232 json_set_err(FSL_JSON_E_DENIED,
233 "Requires 'o' or 'j' access.");
234 return NULL;
235 }
236 zPageName = json_find_option_cstr2("name",NULL,"n",g.json.dispatchDepth+1);
237
238 zSymName = json_find_option_cstr("uuid",NULL,"u");
239
240 if((!zPageName||!*zPageName) && (!zSymName || !*zSymName)){
241 json_set_err(FSL_JSON_E_MISSING_ARGS,
242 "At least one of the 'name' or 'uuid' arguments must be provided.");
243 return NULL;
244 }
245
246 /* TODO: see if we have a page named zPageName. If not, try to resolve
247 zPageName as a UUID.
248 */
249
250 contentFormat = json_wiki_get_content_format_flag(contentFormat);
251 return json_wiki_get_by_name_or_symname( zPageName, zSymName, contentFormat );
252 }
253
254 /*
255 ** Implementation of /json/wiki/preview.
256 **
257 */
258 static cson_value * json_wiki_preview(){
259 char const * zContent = NULL;
260 cson_value * pay = NULL;
261 Blob contentOrig = empty_blob;
262 Blob contentHtml = empty_blob;
263 if( !g.perm.WrWiki ){
264 json_set_err(FSL_JSON_E_DENIED,
265 "Requires 'k' access.");
266 return NULL;
267 }
268 zContent = cson_string_cstr(cson_value_get_string(g.json.reqPayload.v));
269 if(!zContent) {
270 json_set_err(FSL_JSON_E_MISSING_ARGS,
271 "The 'payload' property must be a string containing the wiki code to preview.");
272 return NULL;
273 }
274 blob_append( &contentOrig, zContent, (int)cson_string_length_bytes(cson_value_get_string(g.json.reqPayload.v)) );
275 wiki_convert( &contentOrig, &contentHtml, 0 );
276 blob_reset( &contentOrig );
277 pay = cson_value_new_string( blob_str(&contentHtml), (unsigned int)blob_size(&contentHtml));
278 blob_reset( &contentHtml );
279 return pay;
280 }
281
 
 
 
 
 
282
283 /*
284 ** Internal impl of /wiki/save and /wiki/create. If createMode is 0
285 ** and the page already exists then a
286 ** FSL_JSON_E_RESOURCE_ALREADY_EXISTS error is triggered. If
@@ -219,15 +292,15 @@
292 ** here if it doesn't already exist. With that, save/create would
293 ** become one operation. That said, i expect there are people who
294 ** would categorize such behaviour as "being too clever" or "doing too
295 ** much automatically" (and i would likely agree with them).
296 **
297 ** If allowCreateIfNotExists is true then this function will allow a new
298 ** page to be created even if createMode is false.
299 */
300 static cson_value * json_wiki_create_or_save(char createMode,
301 char allowCreateIfNotExists){
302 Blob content = empty_blob; /* wiki page content */
303 cson_value * nameV; /* wiki page name */
304 char const * zPageName; /* cstr form of page name */
305 cson_value * contentV; /* passed-in content */
306 cson_value * emptyContent = NULL; /* placeholder for empty content. */
@@ -247,10 +320,15 @@
320 json_set_err( FSL_JSON_E_MISSING_ARGS,
321 "'name' parameter is missing.");
322 return NULL;
323 }
324 zPageName = cson_string_cstr(cson_value_get_string(nameV));
325 if(!zPageName || !*zPageName){
326 json_set_err(FSL_JSON_E_INVALID_ARGS,
327 "'name' parameter must be a non-empty string.");
328 return NULL;
329 }
330 rid = db_int(0,
331 "SELECT x.rid FROM tag t, tagxref x"
332 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
333 " ORDER BY x.mtime DESC LIMIT 1",
334 zPageName
@@ -261,20 +339,20 @@
339 json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
340 "Wiki page '%s' already exists.",
341 zPageName);
342 goto error;
343 }
344 }else if(!createMode && !allowCreateIfNotExists){
345 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
346 "Wiki page '%s' not found.",
347 zPageName);
348 goto error;
349 }
350
351 contentV = json_req_payload_get("content");
352 if( !contentV ){
353 if( createMode || (!rid && allowCreateIfNotExists) ){
354 contentV = emptyContent = cson_value_new_string("",0);
355 }else{
356 json_set_err(FSL_JSON_E_MISSING_ARGS,
357 "'content' parameter is missing.");
358 goto error;
@@ -281,11 +359,11 @@
359 }
360 }
361 if( !cson_value_is_string(nameV)
362 || !cson_value_is_string(contentV)){
363 json_set_err(FSL_JSON_E_INVALID_ARGS,
364 "'content' parameter must be a string.");
365 goto error;
366 }
367 jstr = cson_value_get_string(contentV);
368 contentLen = (int)cson_string_length_bytes(jstr);
369 if(contentLen){
@@ -341,22 +419,40 @@
419 ** Implementation of /json/wiki/list.
420 */
421 static cson_value * json_wiki_list(){
422 cson_value * listV = NULL;
423 cson_array * list = NULL;
424 char const * zGlob = NULL;
425 Stmt q = empty_Stmt;
426 Blob sql = empty_blob;
427 char const verbose = json_find_option_bool("verbose",NULL,"v",0);
428 char fInvert = json_find_option_bool("invert",NULL,"i",0);;
429
430 if( !g.perm.RdWiki && !g.perm.Read ){
431 json_set_err(FSL_JSON_E_DENIED,
432 "Requires 'j' or 'o' permissions.");
433 return NULL;
434 }
435 blob_append(&sql,"SELECT"
436 " substr(tagname,6) as name"
437 " FROM tag WHERE tagname GLOB 'wiki-*'",
438 -1);
439 zGlob = json_find_option_cstr("glob",NULL,"g");
440 if(zGlob && *zGlob){
441 blob_appendf(&sql," AND name %s GLOB %Q",
442 fInvert ? "NOT" : "", zGlob);
443 }else{
444 zGlob = json_find_option_cstr("like",NULL,"l");
445 if(zGlob && *zGlob){
446 blob_appendf(&sql," AND name %s LIKE %Q",
447 fInvert ? "NOT" : "",
448 zGlob);
449 }
450 }
451 blob_append(&sql," ORDER BY lower(name)", -1);
452 db_prepare(&q,"%s", blob_str(&sql));
453 blob_reset(&sql);
454 listV = cson_value_new_array();
455 list = cson_value_get_array(listV);
456 while( SQLITE_ROW == db_step(&q) ){
457 cson_value * v;
458 if( verbose ){
@@ -384,6 +480,109 @@
480 listV = NULL;
481 end:
482 db_finalize(&q);
483 return listV;
484 }
485
486 static cson_value * json_wiki_diff(){
487 char const * zV1 = NULL;
488 char const * zV2 = NULL;
489 cson_object * pay = NULL;
490 int argPos = g.json.dispatchDepth;
491 int r1 = 0, r2 = 0;
492 Manifest * pW1 = NULL, *pW2 = NULL;
493 Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
494 char const * zErrTag = NULL;
495 int diffFlags;
496 char * zUuid = NULL;
497 if( !g.perm.History ){
498 json_set_err(FSL_JSON_E_DENIED,
499 "Requires 'h' permissions.");
500 return NULL;
501 }
502
503
504 zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );
505 zV2 = json_find_option_cstr2( "v2",NULL, NULL, ++argPos );
506 if(!zV1 || !*zV1 || !zV2 || !*zV2) {
507 json_set_err(FSL_JSON_E_INVALID_ARGS,
508 "Requires both 'v1' and 'v2' arguments.");
509 return NULL;
510 }
511
512 r1 = symbolic_name_to_rid( zV1, "w" );
513 zErrTag = zV1;
514 if(r1<0){
515 goto ambiguous;
516 }else if(0==r1){
517 goto invalid;
518 }
519
520 r2 = symbolic_name_to_rid( zV2, "w" );
521 zErrTag = zV2;
522 if(r2<0){
523 goto ambiguous;
524 }else if(0==r2){
525 goto invalid;
526 }
527
528 zErrTag = zV1;
529 pW1 = manifest_get(r1, CFTYPE_WIKI);
530 if( pW1==0 ) {
531 goto manifest;
532 }
533 zErrTag = zV2;
534 pW2 = manifest_get(r2, CFTYPE_WIKI);
535 if( pW2==0 ) {
536 goto manifest;
537 }
538
539 blob_init(&w1, pW1->zWiki, -1);
540 blob_zero(&w2);
541 blob_init(&w2, pW2->zWiki, -1);
542 blob_zero(&d);
543 diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
544 text_diff(&w2, &w1, &d, diffFlags);
545 blob_reset(&w1);
546 blob_reset(&w2);
547
548 pay = cson_new_object();
549
550 zUuid = json_wiki_get_uuid_for_rid( pW1->rid );
551 cson_object_set(pay, "v1", json_new_string(zUuid) );
552 free(zUuid);
553 zUuid = json_wiki_get_uuid_for_rid( pW2->rid );
554 cson_object_set(pay, "v2", json_new_string(zUuid) );
555 free(zUuid);
556 zUuid = NULL;
557
558 manifest_destroy(pW1);
559 manifest_destroy(pW2);
560
561 cson_object_set(pay, "diff",
562 cson_value_new_string( blob_str(&d),
563 (unsigned int)blob_size(&d)));
564
565 return cson_object_value(pay);
566
567 manifest:
568 json_set_err(FSL_JSON_E_UNKNOWN,
569 "Could not load wiki manifest for UUID [%s].",
570 zErrTag);
571 goto end;
572
573 ambiguous:
574 json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
575 "UUID [%s] is ambiguous.", zErrTag);
576 goto end;
577
578 invalid:
579 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
580 "UUID [%s] not found.", zErrTag);
581 goto end;
582
583 end:
584 cson_free_object(pay);
585 return NULL;
586 }
587
588 #endif /* FOSSIL_ENABLE_JSON */
589
+19 -29
--- src/login.c
+++ src/login.c
@@ -261,14 +261,22 @@
261261
const char *zCookieName = login_cookie_name();
262262
const char *zExpire = db_get("cookie-expire","8766");
263263
int expires = atoi(zExpire)*3600;
264264
char *zHash;
265265
char *zCookie;
266
- char const * zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */
267
- char * zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
266
+ char const *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
267
+ char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
268
+
268269
assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
269
- zHash = db_text(0, "SELECT hex(randomblob(25))");
270
+ zHash = db_text(0,
271
+ "SELECT cookie FROM user"
272
+ " WHERE uid=%d"
273
+ " AND ipaddr=%Q"
274
+ " AND cexpire>julianday('now')"
275
+ " AND length(cookie)>30",
276
+ uid, zRemoteAddr);
277
+ if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
270278
zCookie = login_gen_user_cookie_value(zUsername, zHash);
271279
cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
272280
record_login_attempt(zUsername, zIpAddr, 1);
273281
db_multi_exec(
274282
"UPDATE user SET cookie=%Q, ipaddr=%Q, "
@@ -930,12 +938,11 @@
930938
931939
/*
932940
** Flags passed into the 2nd argument of login_set/replace_capabilities().
933941
*/
934942
#if INTERFACE
935
-#define LOGIN_IGNORE_U 0x01 /* Ignore "u" */
936
-#define LOGIN_IGNORE_V 0x01 /* Ignore "v" */
943
+#define LOGIN_IGNORE_UV 0x01 /* Ignore "u" and "v" */
937944
#endif
938945
939946
/*
940947
** Adds all capability flags in zCap to g.perm.
941948
*/
@@ -978,25 +985,25 @@
978985
case 'x': g.perm.Private = 1; break;
979986
980987
/* The "u" privileges is a little different. It recursively
981988
** inherits all privileges of the user named "reader" */
982989
case 'u': {
983
- if( (flags & LOGIN_IGNORE_U)==0 ){
990
+ if( (flags & LOGIN_IGNORE_UV)==0 ){
984991
const char *zUser;
985992
zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
986
- login_set_capabilities(zUser, flags | LOGIN_IGNORE_U);
993
+ login_set_capabilities(zUser, flags | LOGIN_IGNORE_UV);
987994
}
988995
break;
989996
}
990997
991998
/* The "v" privileges is a little different. It recursively
992999
** inherits all privileges of the user named "developer" */
9931000
case 'v': {
994
- if( (flags & LOGIN_IGNORE_V)==0 ){
1001
+ if( (flags & LOGIN_IGNORE_UV)==0 ){
9951002
const char *zDev;
9961003
zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
997
- login_set_capabilities(zDev, flags | LOGIN_IGNORE_V);
1004
+ login_set_capabilities(zDev, flags | LOGIN_IGNORE_UV);
9981005
}
9991006
break;
10001007
}
10011008
}
10021009
}
@@ -1207,37 +1214,20 @@
12071214
@ %s(zUsername) already exists.
12081215
@ </span></p>
12091216
}else{
12101217
char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
12111218
int uid;
1212
- char *zCookie;
1213
- const char *zCookieName;
1214
- const char *zExpire;
1215
- int expires;
1216
- const char *zIpAddr;
12171219
db_multi_exec(
12181220
"INSERT INTO user(login,pw,cap,info)"
12191221
"VALUES(%B,%Q,%B,%B)",
12201222
&login, zPw, &caps, &contact
12211223
);
12221224
free(zPw);
12231225
12241226
/* The user is registered, now just log him in. */
12251227
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername);
1226
- zCookieName = login_cookie_name();
1227
- zExpire = db_get("cookie-expire","8766");
1228
- expires = atoi(zExpire)*3600;
1229
- zIpAddr = PD("REMOTE_ADDR","nil");
1230
-
1231
- zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
1232
- cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
1233
- record_login_attempt(zUsername, zIpAddr, 1);
1234
- db_multi_exec(
1235
- "UPDATE user SET cookie=%Q, ipaddr=%Q, "
1236
- " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
1237
- zCookie, ipPrefix(zIpAddr), expires, uid
1238
- );
1228
+ login_set_user_cookie( zUsername, uid, NULL );
12391229
redirect_to_g();
12401230
12411231
}
12421232
}
12431233
}
@@ -1396,17 +1386,17 @@
13961386
13971387
*pzErrMsg = 0; /* Default to no errors */
13981388
zSelf = db_name("repository");
13991389
14001390
/* Get the full pathname of the other repository */
1401
- file_canonical_name(zRepo, &fullName);
1391
+ file_canonical_name(zRepo, &fullName, 0);
14021392
zRepo = mprintf(blob_str(&fullName));
14031393
blob_reset(&fullName);
14041394
14051395
/* Get the full pathname for our repository. Also the project code
14061396
** and project name for ourself. */
1407
- file_canonical_name(g.zRepositoryName, &fullName);
1397
+ file_canonical_name(g.zRepositoryName, &fullName, 0);
14081398
zSelfRepo = mprintf(blob_str(&fullName));
14091399
blob_reset(&fullName);
14101400
zSelfProjCode = db_get("project-code", "unknown");
14111401
zSelfLabel = db_get("project-name", 0);
14121402
if( zSelfLabel==0 ){
14131403
--- src/login.c
+++ src/login.c
@@ -261,14 +261,22 @@
261 const char *zCookieName = login_cookie_name();
262 const char *zExpire = db_get("cookie-expire","8766");
263 int expires = atoi(zExpire)*3600;
264 char *zHash;
265 char *zCookie;
266 char const * zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */
267 char * zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
 
268 assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
269 zHash = db_text(0, "SELECT hex(randomblob(25))");
 
 
 
 
 
 
 
270 zCookie = login_gen_user_cookie_value(zUsername, zHash);
271 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
272 record_login_attempt(zUsername, zIpAddr, 1);
273 db_multi_exec(
274 "UPDATE user SET cookie=%Q, ipaddr=%Q, "
@@ -930,12 +938,11 @@
930
931 /*
932 ** Flags passed into the 2nd argument of login_set/replace_capabilities().
933 */
934 #if INTERFACE
935 #define LOGIN_IGNORE_U 0x01 /* Ignore "u" */
936 #define LOGIN_IGNORE_V 0x01 /* Ignore "v" */
937 #endif
938
939 /*
940 ** Adds all capability flags in zCap to g.perm.
941 */
@@ -978,25 +985,25 @@
978 case 'x': g.perm.Private = 1; break;
979
980 /* The "u" privileges is a little different. It recursively
981 ** inherits all privileges of the user named "reader" */
982 case 'u': {
983 if( (flags & LOGIN_IGNORE_U)==0 ){
984 const char *zUser;
985 zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
986 login_set_capabilities(zUser, flags | LOGIN_IGNORE_U);
987 }
988 break;
989 }
990
991 /* The "v" privileges is a little different. It recursively
992 ** inherits all privileges of the user named "developer" */
993 case 'v': {
994 if( (flags & LOGIN_IGNORE_V)==0 ){
995 const char *zDev;
996 zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
997 login_set_capabilities(zDev, flags | LOGIN_IGNORE_V);
998 }
999 break;
1000 }
1001 }
1002 }
@@ -1207,37 +1214,20 @@
1207 @ %s(zUsername) already exists.
1208 @ </span></p>
1209 }else{
1210 char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
1211 int uid;
1212 char *zCookie;
1213 const char *zCookieName;
1214 const char *zExpire;
1215 int expires;
1216 const char *zIpAddr;
1217 db_multi_exec(
1218 "INSERT INTO user(login,pw,cap,info)"
1219 "VALUES(%B,%Q,%B,%B)",
1220 &login, zPw, &caps, &contact
1221 );
1222 free(zPw);
1223
1224 /* The user is registered, now just log him in. */
1225 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername);
1226 zCookieName = login_cookie_name();
1227 zExpire = db_get("cookie-expire","8766");
1228 expires = atoi(zExpire)*3600;
1229 zIpAddr = PD("REMOTE_ADDR","nil");
1230
1231 zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
1232 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
1233 record_login_attempt(zUsername, zIpAddr, 1);
1234 db_multi_exec(
1235 "UPDATE user SET cookie=%Q, ipaddr=%Q, "
1236 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
1237 zCookie, ipPrefix(zIpAddr), expires, uid
1238 );
1239 redirect_to_g();
1240
1241 }
1242 }
1243 }
@@ -1396,17 +1386,17 @@
1396
1397 *pzErrMsg = 0; /* Default to no errors */
1398 zSelf = db_name("repository");
1399
1400 /* Get the full pathname of the other repository */
1401 file_canonical_name(zRepo, &fullName);
1402 zRepo = mprintf(blob_str(&fullName));
1403 blob_reset(&fullName);
1404
1405 /* Get the full pathname for our repository. Also the project code
1406 ** and project name for ourself. */
1407 file_canonical_name(g.zRepositoryName, &fullName);
1408 zSelfRepo = mprintf(blob_str(&fullName));
1409 blob_reset(&fullName);
1410 zSelfProjCode = db_get("project-code", "unknown");
1411 zSelfLabel = db_get("project-name", 0);
1412 if( zSelfLabel==0 ){
1413
--- src/login.c
+++ src/login.c
@@ -261,14 +261,22 @@
261 const char *zCookieName = login_cookie_name();
262 const char *zExpire = db_get("cookie-expire","8766");
263 int expires = atoi(zExpire)*3600;
264 char *zHash;
265 char *zCookie;
266 char const *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
267 char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
268
269 assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
270 zHash = db_text(0,
271 "SELECT cookie FROM user"
272 " WHERE uid=%d"
273 " AND ipaddr=%Q"
274 " AND cexpire>julianday('now')"
275 " AND length(cookie)>30",
276 uid, zRemoteAddr);
277 if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
278 zCookie = login_gen_user_cookie_value(zUsername, zHash);
279 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
280 record_login_attempt(zUsername, zIpAddr, 1);
281 db_multi_exec(
282 "UPDATE user SET cookie=%Q, ipaddr=%Q, "
@@ -930,12 +938,11 @@
938
939 /*
940 ** Flags passed into the 2nd argument of login_set/replace_capabilities().
941 */
942 #if INTERFACE
943 #define LOGIN_IGNORE_UV 0x01 /* Ignore "u" and "v" */
 
944 #endif
945
946 /*
947 ** Adds all capability flags in zCap to g.perm.
948 */
@@ -978,25 +985,25 @@
985 case 'x': g.perm.Private = 1; break;
986
987 /* The "u" privileges is a little different. It recursively
988 ** inherits all privileges of the user named "reader" */
989 case 'u': {
990 if( (flags & LOGIN_IGNORE_UV)==0 ){
991 const char *zUser;
992 zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
993 login_set_capabilities(zUser, flags | LOGIN_IGNORE_UV);
994 }
995 break;
996 }
997
998 /* The "v" privileges is a little different. It recursively
999 ** inherits all privileges of the user named "developer" */
1000 case 'v': {
1001 if( (flags & LOGIN_IGNORE_UV)==0 ){
1002 const char *zDev;
1003 zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
1004 login_set_capabilities(zDev, flags | LOGIN_IGNORE_UV);
1005 }
1006 break;
1007 }
1008 }
1009 }
@@ -1207,37 +1214,20 @@
1214 @ %s(zUsername) already exists.
1215 @ </span></p>
1216 }else{
1217 char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
1218 int uid;
 
 
 
 
 
1219 db_multi_exec(
1220 "INSERT INTO user(login,pw,cap,info)"
1221 "VALUES(%B,%Q,%B,%B)",
1222 &login, zPw, &caps, &contact
1223 );
1224 free(zPw);
1225
1226 /* The user is registered, now just log him in. */
1227 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername);
1228 login_set_user_cookie( zUsername, uid, NULL );
 
 
 
 
 
 
 
 
 
 
 
 
1229 redirect_to_g();
1230
1231 }
1232 }
1233 }
@@ -1396,17 +1386,17 @@
1386
1387 *pzErrMsg = 0; /* Default to no errors */
1388 zSelf = db_name("repository");
1389
1390 /* Get the full pathname of the other repository */
1391 file_canonical_name(zRepo, &fullName, 0);
1392 zRepo = mprintf(blob_str(&fullName));
1393 blob_reset(&fullName);
1394
1395 /* Get the full pathname for our repository. Also the project code
1396 ** and project name for ourself. */
1397 file_canonical_name(g.zRepositoryName, &fullName, 0);
1398 zSelfRepo = mprintf(blob_str(&fullName));
1399 blob_reset(&fullName);
1400 zSelfProjCode = db_get("project-code", "unknown");
1401 zSelfLabel = db_get("project-name", 0);
1402 if( zSelfLabel==0 ){
1403
+31 -8
--- src/main.c
+++ src/main.c
@@ -446,13 +446,12 @@
446446
g.isHTTP = 1;
447447
}else if( argc<2 ){
448448
fossil_print(
449449
"Usage: %s COMMAND ...\n"
450450
" or: %s help -- for a list of common commands\n"
451
- " or: %s help COMMMAND -- for help with the named command\n"
452
- " or: %s commands -- for a list of all commands\n",
453
- argv[0], argv[0], argv[0], argv[0]);
451
+ " or: %s help COMMMAND -- for help with the named command\n",
452
+ argv[0], argv[0], argv[0]);
454453
fossil_exit(1);
455454
}else{
456455
g.isHTTP = 0;
457456
g.fQuiet = find_option("quiet", 0, 0)!=0;
458457
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
@@ -1113,11 +1112,11 @@
11131112
int i;
11141113
struct stat sStat;
11151114
Blob dir;
11161115
char *zDir;
11171116
1118
- file_canonical_name(zRepo, &dir);
1117
+ file_canonical_name(zRepo, &dir, 0);
11191118
zDir = blob_str(&dir);
11201119
if( file_isdir(zDir)==1 ){
11211120
if( chdir(zDir) || chroot(zDir) || chdir("/") ){
11221121
fossil_fatal("unable to chroot into %s", zDir);
11231122
}
@@ -1201,10 +1200,11 @@
12011200
}
12021201
zRepo[j] = '.';
12031202
}
12041203
12051204
if( szFile<1024 ){
1205
+ set_base_url();
12061206
if( zNotFound ){
12071207
cgi_redirect(zNotFound);
12081208
}else{
12091209
#ifdef FOSSIL_ENABLE_JSON
12101210
if(g.json.isJsonMode){
@@ -1288,11 +1288,11 @@
12881288
zUser = "nobody";
12891289
}
12901290
if( g.zLogin==0 ) zUser = "nobody";
12911291
if( zAltRepo[0]!='/' ){
12921292
zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
1293
- file_simplify_name(zAltRepo, -1);
1293
+ file_simplify_name(zAltRepo, -1, 0);
12941294
}
12951295
db_close(1);
12961296
db_open_repository(zAltRepo);
12971297
login_as_user(zUser);
12981298
g.perm.Password = 0;
@@ -1305,18 +1305,41 @@
13051305
}else{
13061306
g.zExtra = 0;
13071307
}
13081308
break;
13091309
}
1310
+#ifdef FOSSIL_ENABLE_JSON
1311
+ /*
1312
+ ** Workaround to allow us to customize some following behaviour for
1313
+ ** JSON mode. The problem is, we don't always know if we're in JSON
1314
+ ** mode at this point (namely, for GET mode we don't know but POST
1315
+ ** we do), so we snoop g.zPath and cheat a bit.
1316
+ */
1317
+ if( g.zPath && (0==strcmp("json",g.zPath)) ){
1318
+ g.json.isJsonMode = 1;
1319
+ }
1320
+#endif
13101321
if( g.zExtra ){
13111322
/* CGI parameters get this treatment elsewhere, but places like getfile
13121323
** will use g.zExtra directly.
13131324
** Reminder: the login mechanism uses 'name' differently, and may
13141325
** eventually have a problem/collision with this.
1326
+ **
1327
+ ** Disabled by stephan when running in JSON mode because this
1328
+ ** particular parameter name is very common and i have had no end
1329
+ ** of grief with this handling. The JSON API never relies on the
1330
+ ** handling below, and by disabling it in JSON mode i can remove
1331
+ ** lots of special-case handling in several JSON handlers.
13151332
*/
1316
- dehttpize(g.zExtra);
1317
- cgi_set_parameter_nocopy("name", g.zExtra);
1333
+#ifdef FOSSIL_ENABLE_JSON
1334
+ if(!g.json.isJsonMode){
1335
+#endif
1336
+ dehttpize(g.zExtra);
1337
+ cgi_set_parameter_nocopy("name", g.zExtra);
1338
+#ifdef FOSSIL_ENABLE_JSON
1339
+ }
1340
+#endif
13181341
}
13191342
13201343
/* Locate the method specified by the path and execute the function
13211344
** that implements that method.
13221345
*/
@@ -1527,11 +1550,11 @@
15271550
static void find_server_repository(int disallowDir){
15281551
if( g.argc<3 ){
15291552
db_must_be_within_tree();
15301553
}else if( !disallowDir && file_isdir(g.argv[2])==1 ){
15311554
g.zRepositoryName = mprintf("%s", g.argv[2]);
1532
- file_simplify_name(g.zRepositoryName, -1);
1555
+ file_simplify_name(g.zRepositoryName, -1, 0);
15331556
}else{
15341557
db_open_repository(g.argv[2]);
15351558
}
15361559
}
15371560
15381561
--- src/main.c
+++ src/main.c
@@ -446,13 +446,12 @@
446 g.isHTTP = 1;
447 }else if( argc<2 ){
448 fossil_print(
449 "Usage: %s COMMAND ...\n"
450 " or: %s help -- for a list of common commands\n"
451 " or: %s help COMMMAND -- for help with the named command\n"
452 " or: %s commands -- for a list of all commands\n",
453 argv[0], argv[0], argv[0], argv[0]);
454 fossil_exit(1);
455 }else{
456 g.isHTTP = 0;
457 g.fQuiet = find_option("quiet", 0, 0)!=0;
458 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
@@ -1113,11 +1112,11 @@
1113 int i;
1114 struct stat sStat;
1115 Blob dir;
1116 char *zDir;
1117
1118 file_canonical_name(zRepo, &dir);
1119 zDir = blob_str(&dir);
1120 if( file_isdir(zDir)==1 ){
1121 if( chdir(zDir) || chroot(zDir) || chdir("/") ){
1122 fossil_fatal("unable to chroot into %s", zDir);
1123 }
@@ -1201,10 +1200,11 @@
1201 }
1202 zRepo[j] = '.';
1203 }
1204
1205 if( szFile<1024 ){
 
1206 if( zNotFound ){
1207 cgi_redirect(zNotFound);
1208 }else{
1209 #ifdef FOSSIL_ENABLE_JSON
1210 if(g.json.isJsonMode){
@@ -1288,11 +1288,11 @@
1288 zUser = "nobody";
1289 }
1290 if( g.zLogin==0 ) zUser = "nobody";
1291 if( zAltRepo[0]!='/' ){
1292 zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
1293 file_simplify_name(zAltRepo, -1);
1294 }
1295 db_close(1);
1296 db_open_repository(zAltRepo);
1297 login_as_user(zUser);
1298 g.perm.Password = 0;
@@ -1305,18 +1305,41 @@
1305 }else{
1306 g.zExtra = 0;
1307 }
1308 break;
1309 }
 
 
 
 
 
 
 
 
 
 
 
1310 if( g.zExtra ){
1311 /* CGI parameters get this treatment elsewhere, but places like getfile
1312 ** will use g.zExtra directly.
1313 ** Reminder: the login mechanism uses 'name' differently, and may
1314 ** eventually have a problem/collision with this.
 
 
 
 
 
 
1315 */
1316 dehttpize(g.zExtra);
1317 cgi_set_parameter_nocopy("name", g.zExtra);
 
 
 
 
 
 
1318 }
1319
1320 /* Locate the method specified by the path and execute the function
1321 ** that implements that method.
1322 */
@@ -1527,11 +1550,11 @@
1527 static void find_server_repository(int disallowDir){
1528 if( g.argc<3 ){
1529 db_must_be_within_tree();
1530 }else if( !disallowDir && file_isdir(g.argv[2])==1 ){
1531 g.zRepositoryName = mprintf("%s", g.argv[2]);
1532 file_simplify_name(g.zRepositoryName, -1);
1533 }else{
1534 db_open_repository(g.argv[2]);
1535 }
1536 }
1537
1538
--- src/main.c
+++ src/main.c
@@ -446,13 +446,12 @@
446 g.isHTTP = 1;
447 }else if( argc<2 ){
448 fossil_print(
449 "Usage: %s COMMAND ...\n"
450 " or: %s help -- for a list of common commands\n"
451 " or: %s help COMMMAND -- for help with the named command\n",
452 argv[0], argv[0], argv[0]);
 
453 fossil_exit(1);
454 }else{
455 g.isHTTP = 0;
456 g.fQuiet = find_option("quiet", 0, 0)!=0;
457 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
@@ -1113,11 +1112,11 @@
1112 int i;
1113 struct stat sStat;
1114 Blob dir;
1115 char *zDir;
1116
1117 file_canonical_name(zRepo, &dir, 0);
1118 zDir = blob_str(&dir);
1119 if( file_isdir(zDir)==1 ){
1120 if( chdir(zDir) || chroot(zDir) || chdir("/") ){
1121 fossil_fatal("unable to chroot into %s", zDir);
1122 }
@@ -1201,10 +1200,11 @@
1200 }
1201 zRepo[j] = '.';
1202 }
1203
1204 if( szFile<1024 ){
1205 set_base_url();
1206 if( zNotFound ){
1207 cgi_redirect(zNotFound);
1208 }else{
1209 #ifdef FOSSIL_ENABLE_JSON
1210 if(g.json.isJsonMode){
@@ -1288,11 +1288,11 @@
1288 zUser = "nobody";
1289 }
1290 if( g.zLogin==0 ) zUser = "nobody";
1291 if( zAltRepo[0]!='/' ){
1292 zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
1293 file_simplify_name(zAltRepo, -1, 0);
1294 }
1295 db_close(1);
1296 db_open_repository(zAltRepo);
1297 login_as_user(zUser);
1298 g.perm.Password = 0;
@@ -1305,18 +1305,41 @@
1305 }else{
1306 g.zExtra = 0;
1307 }
1308 break;
1309 }
1310 #ifdef FOSSIL_ENABLE_JSON
1311 /*
1312 ** Workaround to allow us to customize some following behaviour for
1313 ** JSON mode. The problem is, we don't always know if we're in JSON
1314 ** mode at this point (namely, for GET mode we don't know but POST
1315 ** we do), so we snoop g.zPath and cheat a bit.
1316 */
1317 if( g.zPath && (0==strcmp("json",g.zPath)) ){
1318 g.json.isJsonMode = 1;
1319 }
1320 #endif
1321 if( g.zExtra ){
1322 /* CGI parameters get this treatment elsewhere, but places like getfile
1323 ** will use g.zExtra directly.
1324 ** Reminder: the login mechanism uses 'name' differently, and may
1325 ** eventually have a problem/collision with this.
1326 **
1327 ** Disabled by stephan when running in JSON mode because this
1328 ** particular parameter name is very common and i have had no end
1329 ** of grief with this handling. The JSON API never relies on the
1330 ** handling below, and by disabling it in JSON mode i can remove
1331 ** lots of special-case handling in several JSON handlers.
1332 */
1333 #ifdef FOSSIL_ENABLE_JSON
1334 if(!g.json.isJsonMode){
1335 #endif
1336 dehttpize(g.zExtra);
1337 cgi_set_parameter_nocopy("name", g.zExtra);
1338 #ifdef FOSSIL_ENABLE_JSON
1339 }
1340 #endif
1341 }
1342
1343 /* Locate the method specified by the path and execute the function
1344 ** that implements that method.
1345 */
@@ -1527,11 +1550,11 @@
1550 static void find_server_repository(int disallowDir){
1551 if( g.argc<3 ){
1552 db_must_be_within_tree();
1553 }else if( !disallowDir && file_isdir(g.argv[2])==1 ){
1554 g.zRepositoryName = mprintf("%s", g.argv[2]);
1555 file_simplify_name(g.zRepositoryName, -1, 0);
1556 }else{
1557 db_open_repository(g.argv[2]);
1558 }
1559 }
1560
1561
+22 -2
--- src/main.mk
+++ src/main.mk
@@ -55,10 +55,12 @@
5555
$(SRCDIR)/json.c \
5656
$(SRCDIR)/json_artifact.c \
5757
$(SRCDIR)/json_branch.c \
5858
$(SRCDIR)/json_config.c \
5959
$(SRCDIR)/json_diff.c \
60
+ $(SRCDIR)/json_dir.c \
61
+ $(SRCDIR)/json_finfo.c \
6062
$(SRCDIR)/json_login.c \
6163
$(SRCDIR)/json_query.c \
6264
$(SRCDIR)/json_report.c \
6365
$(SRCDIR)/json_tag.c \
6466
$(SRCDIR)/json_timeline.c \
@@ -152,10 +154,12 @@
152154
$(OBJDIR)/json_.c \
153155
$(OBJDIR)/json_artifact_.c \
154156
$(OBJDIR)/json_branch_.c \
155157
$(OBJDIR)/json_config_.c \
156158
$(OBJDIR)/json_diff_.c \
159
+ $(OBJDIR)/json_dir_.c \
160
+ $(OBJDIR)/json_finfo_.c \
157161
$(OBJDIR)/json_login_.c \
158162
$(OBJDIR)/json_query_.c \
159163
$(OBJDIR)/json_report_.c \
160164
$(OBJDIR)/json_tag_.c \
161165
$(OBJDIR)/json_timeline_.c \
@@ -249,10 +253,12 @@
249253
$(OBJDIR)/json.o \
250254
$(OBJDIR)/json_artifact.o \
251255
$(OBJDIR)/json_branch.o \
252256
$(OBJDIR)/json_config.o \
253257
$(OBJDIR)/json_diff.o \
258
+ $(OBJDIR)/json_dir.o \
259
+ $(OBJDIR)/json_finfo.o \
254260
$(OBJDIR)/json_login.o \
255261
$(OBJDIR)/json_query.o \
256262
$(OBJDIR)/json_report.o \
257263
$(OBJDIR)/json_tag.o \
258264
$(OBJDIR)/json_timeline.o \
@@ -368,14 +374,14 @@
368374
369375
370376
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
371377
$(OBJDIR)/mkindex $(TRANS_SRC) >$@
372378
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
373
- $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
379
+ $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
374380
touch $(OBJDIR)/headers
375381
$(OBJDIR)/headers: Makefile
376
-$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
382
+$(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_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
377383
Makefile:
378384
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
379385
$(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
380386
381387
$(OBJDIR)/add.o: $(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
@@ -674,10 +680,24 @@
674680
675681
$(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
676682
$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
677683
678684
$(OBJDIR)/json_diff.h: $(OBJDIR)/headers
685
+$(OBJDIR)/json_dir_.c: $(SRCDIR)/json_dir.c $(OBJDIR)/translate
686
+ $(OBJDIR)/translate $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c
687
+
688
+$(OBJDIR)/json_dir.o: $(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
689
+ $(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c
690
+
691
+$(OBJDIR)/json_dir.h: $(OBJDIR)/headers
692
+$(OBJDIR)/json_finfo_.c: $(SRCDIR)/json_finfo.c $(OBJDIR)/translate
693
+ $(OBJDIR)/translate $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c
694
+
695
+$(OBJDIR)/json_finfo.o: $(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
696
+ $(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c
697
+
698
+$(OBJDIR)/json_finfo.h: $(OBJDIR)/headers
679699
$(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
680700
$(OBJDIR)/translate $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
681701
682702
$(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
683703
$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
684704
--- src/main.mk
+++ src/main.mk
@@ -55,10 +55,12 @@
55 $(SRCDIR)/json.c \
56 $(SRCDIR)/json_artifact.c \
57 $(SRCDIR)/json_branch.c \
58 $(SRCDIR)/json_config.c \
59 $(SRCDIR)/json_diff.c \
 
 
60 $(SRCDIR)/json_login.c \
61 $(SRCDIR)/json_query.c \
62 $(SRCDIR)/json_report.c \
63 $(SRCDIR)/json_tag.c \
64 $(SRCDIR)/json_timeline.c \
@@ -152,10 +154,12 @@
152 $(OBJDIR)/json_.c \
153 $(OBJDIR)/json_artifact_.c \
154 $(OBJDIR)/json_branch_.c \
155 $(OBJDIR)/json_config_.c \
156 $(OBJDIR)/json_diff_.c \
 
 
157 $(OBJDIR)/json_login_.c \
158 $(OBJDIR)/json_query_.c \
159 $(OBJDIR)/json_report_.c \
160 $(OBJDIR)/json_tag_.c \
161 $(OBJDIR)/json_timeline_.c \
@@ -249,10 +253,12 @@
249 $(OBJDIR)/json.o \
250 $(OBJDIR)/json_artifact.o \
251 $(OBJDIR)/json_branch.o \
252 $(OBJDIR)/json_config.o \
253 $(OBJDIR)/json_diff.o \
 
 
254 $(OBJDIR)/json_login.o \
255 $(OBJDIR)/json_query.o \
256 $(OBJDIR)/json_report.o \
257 $(OBJDIR)/json_tag.o \
258 $(OBJDIR)/json_timeline.o \
@@ -368,14 +374,14 @@
368
369
370 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
371 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
372 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
373 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
374 touch $(OBJDIR)/headers
375 $(OBJDIR)/headers: Makefile
376 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
377 Makefile:
378 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
379 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
380
381 $(OBJDIR)/add.o: $(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
@@ -674,10 +680,24 @@
674
675 $(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
676 $(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
677
678 $(OBJDIR)/json_diff.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679 $(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
680 $(OBJDIR)/translate $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
681
682 $(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
683 $(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
684
--- src/main.mk
+++ src/main.mk
@@ -55,10 +55,12 @@
55 $(SRCDIR)/json.c \
56 $(SRCDIR)/json_artifact.c \
57 $(SRCDIR)/json_branch.c \
58 $(SRCDIR)/json_config.c \
59 $(SRCDIR)/json_diff.c \
60 $(SRCDIR)/json_dir.c \
61 $(SRCDIR)/json_finfo.c \
62 $(SRCDIR)/json_login.c \
63 $(SRCDIR)/json_query.c \
64 $(SRCDIR)/json_report.c \
65 $(SRCDIR)/json_tag.c \
66 $(SRCDIR)/json_timeline.c \
@@ -152,10 +154,12 @@
154 $(OBJDIR)/json_.c \
155 $(OBJDIR)/json_artifact_.c \
156 $(OBJDIR)/json_branch_.c \
157 $(OBJDIR)/json_config_.c \
158 $(OBJDIR)/json_diff_.c \
159 $(OBJDIR)/json_dir_.c \
160 $(OBJDIR)/json_finfo_.c \
161 $(OBJDIR)/json_login_.c \
162 $(OBJDIR)/json_query_.c \
163 $(OBJDIR)/json_report_.c \
164 $(OBJDIR)/json_tag_.c \
165 $(OBJDIR)/json_timeline_.c \
@@ -249,10 +253,12 @@
253 $(OBJDIR)/json.o \
254 $(OBJDIR)/json_artifact.o \
255 $(OBJDIR)/json_branch.o \
256 $(OBJDIR)/json_config.o \
257 $(OBJDIR)/json_diff.o \
258 $(OBJDIR)/json_dir.o \
259 $(OBJDIR)/json_finfo.o \
260 $(OBJDIR)/json_login.o \
261 $(OBJDIR)/json_query.o \
262 $(OBJDIR)/json_report.o \
263 $(OBJDIR)/json_tag.o \
264 $(OBJDIR)/json_timeline.o \
@@ -368,14 +374,14 @@
374
375
376 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
377 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
378 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
379 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
380 touch $(OBJDIR)/headers
381 $(OBJDIR)/headers: Makefile
382 $(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_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
383 Makefile:
384 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
385 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
386
387 $(OBJDIR)/add.o: $(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
@@ -674,10 +680,24 @@
680
681 $(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
682 $(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
683
684 $(OBJDIR)/json_diff.h: $(OBJDIR)/headers
685 $(OBJDIR)/json_dir_.c: $(SRCDIR)/json_dir.c $(OBJDIR)/translate
686 $(OBJDIR)/translate $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c
687
688 $(OBJDIR)/json_dir.o: $(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
689 $(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c
690
691 $(OBJDIR)/json_dir.h: $(OBJDIR)/headers
692 $(OBJDIR)/json_finfo_.c: $(SRCDIR)/json_finfo.c $(OBJDIR)/translate
693 $(OBJDIR)/translate $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c
694
695 $(OBJDIR)/json_finfo.o: $(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
696 $(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c
697
698 $(OBJDIR)/json_finfo.h: $(OBJDIR)/headers
699 $(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
700 $(OBJDIR)/translate $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
701
702 $(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
703 $(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
704
+10 -4
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -58,10 +58,12 @@
5858
json
5959
json_artifact
6060
json_branch
6161
json_config
6262
json_diff
63
+ json_dir
64
+ json_finfo
6365
json_login
6466
json_query
6567
json_report
6668
json_tag
6769
json_timeline
@@ -258,11 +260,11 @@
258260
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
259261
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
260262
writeln "\t\$(OBJDIR)/makeheaders $mhargs"
261263
writeln "\ttouch \$(OBJDIR)/headers"
262264
writeln "\$(OBJDIR)/headers: Makefile"
263
-writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
265
+writeln "\$(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_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
264266
writeln "Makefile:"
265267
set extra_h(main) \$(OBJDIR)/page_index.h
266268
267269
foreach s [lsort $src] {
268270
writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
@@ -467,11 +469,11 @@
467469
# or linking with it will not work (exact reason unknown).
468470
#
469471
ifdef FOSSIL_ENABLE_TCL
470472
LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
471473
else
472
-LIB += -lws2_32
474
+LIB += -lkernel32 -lws2_32
473475
endif
474476
475477
#### Tcl shell for use in running the fossil test suite. This is only
476478
# used for testing.
477479
#
@@ -610,11 +612,11 @@
610612
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
611613
612614
set opt {}
613615
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
614616
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
615
-writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
617
+writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
616618
617619
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
618620
set opt {-Dmain=sqlite3_shell}
619621
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
620622
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
@@ -667,11 +669,11 @@
667669
SSL =
668670
669671
CFLAGS = -o
670672
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
671673
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
672
-LIBS = $(DMDIR)\extra\lib\ zlib wsock32
674
+LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
673675
}
674676
writeln "SQLITE_OPTIONS = $SQLITE_OPTIONS\n"
675677
writeln -nonewline "SRC = "
676678
foreach s [lsort $src] {
677679
writeln -nonewline "${s}_.c "
@@ -754,10 +756,12 @@
754756
$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
755757
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
756758
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
757759
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
758760
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
761
+$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
762
+$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
759763
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
760764
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
761765
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
762766
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
763767
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -912,10 +916,12 @@
912916
$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
913917
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
914918
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
915919
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
916920
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
921
+$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
922
+$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
917923
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
918924
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
919925
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
920926
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
921927
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
922928
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -58,10 +58,12 @@
58 json
59 json_artifact
60 json_branch
61 json_config
62 json_diff
 
 
63 json_login
64 json_query
65 json_report
66 json_tag
67 json_timeline
@@ -258,11 +260,11 @@
258 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
259 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
260 writeln "\t\$(OBJDIR)/makeheaders $mhargs"
261 writeln "\ttouch \$(OBJDIR)/headers"
262 writeln "\$(OBJDIR)/headers: Makefile"
263 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
264 writeln "Makefile:"
265 set extra_h(main) \$(OBJDIR)/page_index.h
266
267 foreach s [lsort $src] {
268 writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
@@ -467,11 +469,11 @@
467 # or linking with it will not work (exact reason unknown).
468 #
469 ifdef FOSSIL_ENABLE_TCL
470 LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
471 else
472 LIB += -lws2_32
473 endif
474
475 #### Tcl shell for use in running the fossil test suite. This is only
476 # used for testing.
477 #
@@ -610,11 +612,11 @@
610 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
611
612 set opt {}
613 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
614 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
615 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
616
617 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
618 set opt {-Dmain=sqlite3_shell}
619 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
620 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
@@ -667,11 +669,11 @@
667 SSL =
668
669 CFLAGS = -o
670 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
671 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
672 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
673 }
674 writeln "SQLITE_OPTIONS = $SQLITE_OPTIONS\n"
675 writeln -nonewline "SRC = "
676 foreach s [lsort $src] {
677 writeln -nonewline "${s}_.c "
@@ -754,10 +756,12 @@
754 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
755 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
756 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
757 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
758 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
 
 
759 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
760 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
761 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
762 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
763 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -912,10 +916,12 @@
912 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
913 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
914 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
915 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
916 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
 
 
917 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
918 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
919 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
920 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
921 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
922
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -58,10 +58,12 @@
58 json
59 json_artifact
60 json_branch
61 json_config
62 json_diff
63 json_dir
64 json_finfo
65 json_login
66 json_query
67 json_report
68 json_tag
69 json_timeline
@@ -258,11 +260,11 @@
260 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
261 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
262 writeln "\t\$(OBJDIR)/makeheaders $mhargs"
263 writeln "\ttouch \$(OBJDIR)/headers"
264 writeln "\$(OBJDIR)/headers: Makefile"
265 writeln "\$(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_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
266 writeln "Makefile:"
267 set extra_h(main) \$(OBJDIR)/page_index.h
268
269 foreach s [lsort $src] {
270 writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
@@ -467,11 +469,11 @@
469 # or linking with it will not work (exact reason unknown).
470 #
471 ifdef FOSSIL_ENABLE_TCL
472 LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
473 else
474 LIB += -lkernel32 -lws2_32
475 endif
476
477 #### Tcl shell for use in running the fossil test suite. This is only
478 # used for testing.
479 #
@@ -610,11 +612,11 @@
612 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
613
614 set opt {}
615 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
616 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
617 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
618
619 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
620 set opt {-Dmain=sqlite3_shell}
621 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
622 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
@@ -667,11 +669,11 @@
669 SSL =
670
671 CFLAGS = -o
672 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
673 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
674 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
675 }
676 writeln "SQLITE_OPTIONS = $SQLITE_OPTIONS\n"
677 writeln -nonewline "SRC = "
678 foreach s [lsort $src] {
679 writeln -nonewline "${s}_.c "
@@ -754,10 +756,12 @@
756 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
757 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
758 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
759 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
760 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
761 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
762 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
763 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
764 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
765 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
766 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
767 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -912,10 +916,12 @@
916 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
917 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
918 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
919 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
920 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
921 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
922 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
923 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
924 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
925 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
926 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
927 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
928
--- src/merge3.c
+++ src/merge3.c
@@ -402,12 +402,10 @@
402402
char *zOther; /* Name of the merge file */
403403
404404
blob_read_from_file(&v1, zV1);
405405
rc = blob_merge(pPivot, &v1, pV2, pOut);
406406
if( rc!=0 ){
407
- const char *zGMerge; /* Name of the gmerge command */
408
-
409407
zPivot = file_newname(zV1, "baseline", 1);
410408
blob_write_to_file(pPivot, zPivot);
411409
zOrig = file_newname(zV1, "original", 1);
412410
blob_write_to_file(&v1, zOrig);
413411
zOther = file_newname(zV1, "merge", 1);
414412
--- src/merge3.c
+++ src/merge3.c
@@ -402,12 +402,10 @@
402 char *zOther; /* Name of the merge file */
403
404 blob_read_from_file(&v1, zV1);
405 rc = blob_merge(pPivot, &v1, pV2, pOut);
406 if( rc!=0 ){
407 const char *zGMerge; /* Name of the gmerge command */
408
409 zPivot = file_newname(zV1, "baseline", 1);
410 blob_write_to_file(pPivot, zPivot);
411 zOrig = file_newname(zV1, "original", 1);
412 blob_write_to_file(&v1, zOrig);
413 zOther = file_newname(zV1, "merge", 1);
414
--- src/merge3.c
+++ src/merge3.c
@@ -402,12 +402,10 @@
402 char *zOther; /* Name of the merge file */
403
404 blob_read_from_file(&v1, zV1);
405 rc = blob_merge(pPivot, &v1, pV2, pOut);
406 if( rc!=0 ){
 
 
407 zPivot = file_newname(zV1, "baseline", 1);
408 blob_write_to_file(pPivot, zPivot);
409 zOrig = file_newname(zV1, "original", 1);
410 blob_write_to_file(&v1, zOrig);
411 zOther = file_newname(zV1, "merge", 1);
412
+21 -1
--- src/name.c
+++ src/name.c
@@ -69,11 +69,11 @@
6969
** The zType parameter specifies the type of artifact: ci, t, w, e, g.
7070
** If zType is NULL or "" or "*" then any type of artifact will serve.
7171
** zType is "ci" in most use cases since we are usually searching for
7272
** a check-in.
7373
*/
74
-static int symbolic_name_to_rid(const char *zTag, const char *zType){
74
+int symbolic_name_to_rid(const char *zTag, const char *zType){
7575
int vid;
7676
int rid = 0;
7777
int nTag;
7878
int i;
7979
@@ -273,10 +273,30 @@
273273
blob_reset(pName);
274274
db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);
275275
return 0;
276276
}
277277
}
278
+
279
+/*
280
+** This routine is similar to name_to_uuid() except in the form it
281
+** takes its parameters and returns its value, and in that it does not
282
+** treat errors as fatal. zName must be a UUID, as described for
283
+** name_to_uuid(). zType is also as described for that function. If
284
+** zName does not resolve, 0 is returned. If it is ambiguous, a
285
+** negative value is returned. On success the rid is returned and
286
+** pUuid (if it is not NULL) is set to the a newly-allocated string,
287
+** the full UUID, which must eventually be free()d by the caller.
288
+*/
289
+int name_to_uuid2(char const *zName, const char *zType, char **pUuid){
290
+ int rid = symbolic_name_to_rid(zName, zType);
291
+ if((rid>0) && pUuid){
292
+ *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
293
+ }
294
+ return rid;
295
+}
296
+
297
+
278298
279299
/*
280300
** COMMAND: test-name-to-id
281301
**
282302
** Convert a name to a full artifact ID.
283303
--- src/name.c
+++ src/name.c
@@ -69,11 +69,11 @@
69 ** The zType parameter specifies the type of artifact: ci, t, w, e, g.
70 ** If zType is NULL or "" or "*" then any type of artifact will serve.
71 ** zType is "ci" in most use cases since we are usually searching for
72 ** a check-in.
73 */
74 static int symbolic_name_to_rid(const char *zTag, const char *zType){
75 int vid;
76 int rid = 0;
77 int nTag;
78 int i;
79
@@ -273,10 +273,30 @@
273 blob_reset(pName);
274 db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);
275 return 0;
276 }
277 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
279 /*
280 ** COMMAND: test-name-to-id
281 **
282 ** Convert a name to a full artifact ID.
283
--- src/name.c
+++ src/name.c
@@ -69,11 +69,11 @@
69 ** The zType parameter specifies the type of artifact: ci, t, w, e, g.
70 ** If zType is NULL or "" or "*" then any type of artifact will serve.
71 ** zType is "ci" in most use cases since we are usually searching for
72 ** a check-in.
73 */
74 int symbolic_name_to_rid(const char *zTag, const char *zType){
75 int vid;
76 int rid = 0;
77 int nTag;
78 int i;
79
@@ -273,10 +273,30 @@
273 blob_reset(pName);
274 db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);
275 return 0;
276 }
277 }
278
279 /*
280 ** This routine is similar to name_to_uuid() except in the form it
281 ** takes its parameters and returns its value, and in that it does not
282 ** treat errors as fatal. zName must be a UUID, as described for
283 ** name_to_uuid(). zType is also as described for that function. If
284 ** zName does not resolve, 0 is returned. If it is ambiguous, a
285 ** negative value is returned. On success the rid is returned and
286 ** pUuid (if it is not NULL) is set to the a newly-allocated string,
287 ** the full UUID, which must eventually be free()d by the caller.
288 */
289 int name_to_uuid2(char const *zName, const char *zType, char **pUuid){
290 int rid = symbolic_name_to_rid(zName, zType);
291 if((rid>0) && pUuid){
292 *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
293 }
294 return rid;
295 }
296
297
298
299 /*
300 ** COMMAND: test-name-to-id
301 **
302 ** Convert a name to a full artifact ID.
303
+21 -1
--- src/name.c
+++ src/name.c
@@ -69,11 +69,11 @@
6969
** The zType parameter specifies the type of artifact: ci, t, w, e, g.
7070
** If zType is NULL or "" or "*" then any type of artifact will serve.
7171
** zType is "ci" in most use cases since we are usually searching for
7272
** a check-in.
7373
*/
74
-static int symbolic_name_to_rid(const char *zTag, const char *zType){
74
+int symbolic_name_to_rid(const char *zTag, const char *zType){
7575
int vid;
7676
int rid = 0;
7777
int nTag;
7878
int i;
7979
@@ -273,10 +273,30 @@
273273
blob_reset(pName);
274274
db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);
275275
return 0;
276276
}
277277
}
278
+
279
+/*
280
+** This routine is similar to name_to_uuid() except in the form it
281
+** takes its parameters and returns its value, and in that it does not
282
+** treat errors as fatal. zName must be a UUID, as described for
283
+** name_to_uuid(). zType is also as described for that function. If
284
+** zName does not resolve, 0 is returned. If it is ambiguous, a
285
+** negative value is returned. On success the rid is returned and
286
+** pUuid (if it is not NULL) is set to the a newly-allocated string,
287
+** the full UUID, which must eventually be free()d by the caller.
288
+*/
289
+int name_to_uuid2(char const *zName, const char *zType, char **pUuid){
290
+ int rid = symbolic_name_to_rid(zName, zType);
291
+ if((rid>0) && pUuid){
292
+ *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
293
+ }
294
+ return rid;
295
+}
296
+
297
+
278298
279299
/*
280300
** COMMAND: test-name-to-id
281301
**
282302
** Convert a name to a full artifact ID.
283303
--- src/name.c
+++ src/name.c
@@ -69,11 +69,11 @@
69 ** The zType parameter specifies the type of artifact: ci, t, w, e, g.
70 ** If zType is NULL or "" or "*" then any type of artifact will serve.
71 ** zType is "ci" in most use cases since we are usually searching for
72 ** a check-in.
73 */
74 static int symbolic_name_to_rid(const char *zTag, const char *zType){
75 int vid;
76 int rid = 0;
77 int nTag;
78 int i;
79
@@ -273,10 +273,30 @@
273 blob_reset(pName);
274 db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);
275 return 0;
276 }
277 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
279 /*
280 ** COMMAND: test-name-to-id
281 **
282 ** Convert a name to a full artifact ID.
283
--- src/name.c
+++ src/name.c
@@ -69,11 +69,11 @@
69 ** The zType parameter specifies the type of artifact: ci, t, w, e, g.
70 ** If zType is NULL or "" or "*" then any type of artifact will serve.
71 ** zType is "ci" in most use cases since we are usually searching for
72 ** a check-in.
73 */
74 int symbolic_name_to_rid(const char *zTag, const char *zType){
75 int vid;
76 int rid = 0;
77 int nTag;
78 int i;
79
@@ -273,10 +273,30 @@
273 blob_reset(pName);
274 db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);
275 return 0;
276 }
277 }
278
279 /*
280 ** This routine is similar to name_to_uuid() except in the form it
281 ** takes its parameters and returns its value, and in that it does not
282 ** treat errors as fatal. zName must be a UUID, as described for
283 ** name_to_uuid(). zType is also as described for that function. If
284 ** zName does not resolve, 0 is returned. If it is ambiguous, a
285 ** negative value is returned. On success the rid is returned and
286 ** pUuid (if it is not NULL) is set to the a newly-allocated string,
287 ** the full UUID, which must eventually be free()d by the caller.
288 */
289 int name_to_uuid2(char const *zName, const char *zType, char **pUuid){
290 int rid = symbolic_name_to_rid(zName, zType);
291 if((rid>0) && pUuid){
292 *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
293 }
294 return rid;
295 }
296
297
298
299 /*
300 ** COMMAND: test-name-to-id
301 **
302 ** Convert a name to a full artifact ID.
303
+86 -31
--- src/setup.c
+++ src/setup.c
@@ -84,11 +84,11 @@
8484
setup_menu_entry("Header", "setup_header",
8585
"Edit HTML text inserted at the top of every page");
8686
setup_menu_entry("Footer", "setup_footer",
8787
"Edit HTML text inserted at the bottom of every page");
8888
setup_menu_entry("Logo", "setup_logo",
89
- "Change the logo image for the server");
89
+ "Change the logo and background images for the server");
9090
setup_menu_entry("Shunned", "shun",
9191
"Show artifacts that are shunned by this repository");
9292
setup_menu_entry("Log", "rcvfromlist",
9393
"A record of received artifacts and their sources");
9494
setup_menu_entry("User-Log", "access_log",
@@ -868,14 +868,15 @@
868868
@ login name of a valid user and no other login credentials are available,
869869
@ then the REMOTE_USER is accepted as an authenticated user.
870870
@ </p>
871871
@
872872
@ <hr />
873
- entry_attribute("IP address turns used in login cookie", 3, "ip-prefix-terms", "ipt",
874
- "2");
875
- @ <p>The number of octets of of the IP address used in the login cookie. Set to
876
- @ zero to omit the IP address from the login cookie. A value of 2 is recommended.
873
+ entry_attribute("IP address terms used in login cookie", 3,
874
+ "ip-prefix-terms", "ipt", "2");
875
+ @ <p>The number of octets of of the IP address used in the login cookie.
876
+ @ Set to zero to omit the IP address from the login cookie. A value of
877
+ @ 2 is recommended.
877878
@ </p>
878879
@
879880
@ <hr />
880881
entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766");
881882
@ <p>The number of hours for which a login is valid. This must be a
@@ -950,11 +951,11 @@
950951
951952
login_check_credentials();
952953
if( !g.perm.Setup ){
953954
login_needed();
954955
}
955
- file_canonical_name(g.zRepositoryName, &fullName);
956
+ file_canonical_name(g.zRepositoryName, &fullName, 0);
956957
zSelfRepo = mprintf(blob_str(&fullName));
957958
blob_reset(&fullName);
958959
if( P("join")!=0 ){
959960
login_group_join(zRepo, zLogin, zPw, zNewName, &zErrMsg);
960961
}else if( P("leave") ){
@@ -1318,69 +1319,123 @@
13181319
13191320
/*
13201321
** WEBPAGE: setup_logo
13211322
*/
13221323
void setup_logo(void){
1323
- const char *zMime = db_get("logo-mimetype","image/gif");
1324
- const char *aImg = P("im");
1325
- int szImg = atoi(PD("im:bytes","0"));
1326
- if( szImg>0 ){
1327
- zMime = PD("im:mimetype","image/gif");
1324
+ const char *zLogoMime = db_get("logo-mimetype","image/gif");
1325
+ const char *aLogoImg = P("logoim");
1326
+ int szLogoImg = atoi(PD("logoim:bytes","0"));
1327
+ const char *zBgMime = db_get("background-mimetype","image/gif");
1328
+ const char *aBgImg = P("bgim");
1329
+ int szBgImg = atoi(PD("bgim:bytes","0"));
1330
+ if( szLogoImg>0 ){
1331
+ zLogoMime = PD("logoim:mimetype","image/gif");
1332
+ }
1333
+ if( szBgImg>0 ){
1334
+ zBgMime = PD("bgim:mimetype","image/gif");
13281335
}
13291336
login_check_credentials();
13301337
if( !g.perm.Setup ){
13311338
login_needed();
13321339
}
13331340
db_begin_transaction();
1334
- if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
1341
+ if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
13351342
Blob img;
13361343
Stmt ins;
1337
- blob_init(&img, aImg, szImg);
1344
+ blob_init(&img, aLogoImg, szLogoImg);
13381345
db_prepare(&ins,
13391346
"REPLACE INTO config(name,value,mtime)"
13401347
" VALUES('logo-image',:bytes,now())"
13411348
);
13421349
db_bind_blob(&ins, ":bytes", &img);
13431350
db_step(&ins);
13441351
db_finalize(&ins);
13451352
db_multi_exec(
13461353
"REPLACE INTO config(name,value,mtime) VALUES('logo-mimetype',%Q,now())",
1347
- zMime
1354
+ zLogoMime
1355
+ );
1356
+ db_end_transaction(0);
1357
+ cgi_redirect("setup_logo");
1358
+ }else if( P("clrlogo")!=0 ){
1359
+ db_multi_exec(
1360
+ "DELETE FROM config WHERE name IN "
1361
+ "('logo-image','logo-mimetype')"
1362
+ );
1363
+ db_end_transaction(0);
1364
+ cgi_redirect("setup_logo");
1365
+ }else if( P("setbg")!=0 && zBgMime && zBgMime[0] && szBgImg>0 ){
1366
+ Blob img;
1367
+ Stmt ins;
1368
+ blob_init(&img, aBgImg, szBgImg);
1369
+ db_prepare(&ins,
1370
+ "REPLACE INTO config(name,value,mtime)"
1371
+ " VALUES('background-image',:bytes,now())"
1372
+ );
1373
+ db_bind_blob(&ins, ":bytes", &img);
1374
+ db_step(&ins);
1375
+ db_finalize(&ins);
1376
+ db_multi_exec(
1377
+ "REPLACE INTO config(name,value,mtime)"
1378
+ " VALUES('background-mimetype',%Q,now())",
1379
+ zBgMime
13481380
);
13491381
db_end_transaction(0);
13501382
cgi_redirect("setup_logo");
1351
- }else if( P("clr")!=0 ){
1383
+ }else if( P("clrbg")!=0 ){
13521384
db_multi_exec(
1353
- "DELETE FROM config WHERE name GLOB 'logo-*'"
1385
+ "DELETE FROM config WHERE name IN "
1386
+ "('background-image','background-mimetype')"
13541387
);
13551388
db_end_transaction(0);
13561389
cgi_redirect("setup_logo");
13571390
}
1358
- style_header("Edit Project Logo");
1359
- @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks
1360
- @ like this:</p>
1361
- @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" /></p></blockquote>
1391
+ style_header("Edit Project Logo And Background");
1392
+ @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b>
1393
+ @ and looks like this:</p>
1394
+ @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" border="1" />
1395
+ @ </p></blockquote>
13621396
@
1397
+ @ <form action="%s(g.zTop)/setup_logo" method="post"
1398
+ @ enctype="multipart/form-data"><div>
13631399
@ <p>The logo is accessible to all users at this URL:
13641400
@ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>.
13651401
@ The logo may or may not appear on each
13661402
@ page depending on the <a href="setup_editcss">CSS</a> and
1367
- @ <a href="setup_header">header setup</a>.</p>
1403
+ @ <a href="setup_header">header setup</a>.
1404
+ @ To change the logo image, use the following form:</p>
1405
+ login_insert_csrf_secret();
1406
+ @ Logo Image file:
1407
+ @ <input type="file" name="logoim" size="60" accept="image/*" />
1408
+ @ <p align="center">
1409
+ @ <input type="submit" name="setlogo" value="Change Logo" />
1410
+ @ <input type="submit" name="clrlogo" value="Revert To Default" /></p>
1411
+ @ </div></form>
1412
+ @ <hr />
1413
+ @
1414
+ @ <p>The current background image has a MIME-Type of <b>%h(zBgMime)</b>
1415
+ @ and looks like this:</p>
1416
+ @ <blockquote><p><img src="%s(g.zTop)/background" alt="background" border=1 />
1417
+ @ </p></blockquote>
13681418
@
13691419
@ <form action="%s(g.zTop)/setup_logo" method="post"
13701420
@ enctype="multipart/form-data"><div>
1371
- @ <p>To set a new logo image, select a file to use as the logo using
1372
- @ the entry box below and then press the "Change Logo" button.</p>
1421
+ @ <p>The background image is accessible to all users at this URL:
1422
+ @ <a href="%s(g.zBaseURL)/background">%s(g.zBaseURL)/background</a>.
1423
+ @ The background image may or may not appear on each
1424
+ @ page depending on the <a href="setup_editcss">CSS</a> and
1425
+ @ <a href="setup_header">header setup</a>.
1426
+ @ To change the background image, use the following form:</p>
13731427
login_insert_csrf_secret();
1374
- @ Logo Image file:
1375
- @ <input type="file" name="im" size="60" accept="image/*" /><br />
1376
- @ <input type="submit" name="set" value="Change Logo" />
1377
- @ <input type="submit" name="clr" value="Revert To Default" />
1428
+ @ Background image file:
1429
+ @ <input type="file" name="bgim" size="60" accept="image/*" />
1430
+ @ <p align="center">
1431
+ @ <input type="submit" name="setbg" value="Change Background" />
1432
+ @ <input type="submit" name="clrbg" value="Revert To Default" /></p>
13781433
@ </div></form>
1434
+ @ <hr />
13791435
@
1380
- @ <p><span class="note">Note:</span> Your browser has probably cached the
1381
- @ logo image, so you will probably need to press the Reload button on your
1382
- @ browser after changing the logo to provoke your browser to reload the new
1383
- @ logo image. </p>
1436
+ @ <p><span class="note">Note:</span> Your browser has probably cached these
1437
+ @ images, so you may need to press the Reload button before changes will
1438
+ @ take effect. </p>
13841439
style_footer();
13851440
db_end_transaction(0);
13861441
}
13871442
--- src/setup.c
+++ src/setup.c
@@ -84,11 +84,11 @@
84 setup_menu_entry("Header", "setup_header",
85 "Edit HTML text inserted at the top of every page");
86 setup_menu_entry("Footer", "setup_footer",
87 "Edit HTML text inserted at the bottom of every page");
88 setup_menu_entry("Logo", "setup_logo",
89 "Change the logo image for the server");
90 setup_menu_entry("Shunned", "shun",
91 "Show artifacts that are shunned by this repository");
92 setup_menu_entry("Log", "rcvfromlist",
93 "A record of received artifacts and their sources");
94 setup_menu_entry("User-Log", "access_log",
@@ -868,14 +868,15 @@
868 @ login name of a valid user and no other login credentials are available,
869 @ then the REMOTE_USER is accepted as an authenticated user.
870 @ </p>
871 @
872 @ <hr />
873 entry_attribute("IP address turns used in login cookie", 3, "ip-prefix-terms", "ipt",
874 "2");
875 @ <p>The number of octets of of the IP address used in the login cookie. Set to
876 @ zero to omit the IP address from the login cookie. A value of 2 is recommended.
 
877 @ </p>
878 @
879 @ <hr />
880 entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766");
881 @ <p>The number of hours for which a login is valid. This must be a
@@ -950,11 +951,11 @@
950
951 login_check_credentials();
952 if( !g.perm.Setup ){
953 login_needed();
954 }
955 file_canonical_name(g.zRepositoryName, &fullName);
956 zSelfRepo = mprintf(blob_str(&fullName));
957 blob_reset(&fullName);
958 if( P("join")!=0 ){
959 login_group_join(zRepo, zLogin, zPw, zNewName, &zErrMsg);
960 }else if( P("leave") ){
@@ -1318,69 +1319,123 @@
1318
1319 /*
1320 ** WEBPAGE: setup_logo
1321 */
1322 void setup_logo(void){
1323 const char *zMime = db_get("logo-mimetype","image/gif");
1324 const char *aImg = P("im");
1325 int szImg = atoi(PD("im:bytes","0"));
1326 if( szImg>0 ){
1327 zMime = PD("im:mimetype","image/gif");
 
 
 
 
 
 
1328 }
1329 login_check_credentials();
1330 if( !g.perm.Setup ){
1331 login_needed();
1332 }
1333 db_begin_transaction();
1334 if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
1335 Blob img;
1336 Stmt ins;
1337 blob_init(&img, aImg, szImg);
1338 db_prepare(&ins,
1339 "REPLACE INTO config(name,value,mtime)"
1340 " VALUES('logo-image',:bytes,now())"
1341 );
1342 db_bind_blob(&ins, ":bytes", &img);
1343 db_step(&ins);
1344 db_finalize(&ins);
1345 db_multi_exec(
1346 "REPLACE INTO config(name,value,mtime) VALUES('logo-mimetype',%Q,now())",
1347 zMime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1348 );
1349 db_end_transaction(0);
1350 cgi_redirect("setup_logo");
1351 }else if( P("clr")!=0 ){
1352 db_multi_exec(
1353 "DELETE FROM config WHERE name GLOB 'logo-*'"
 
1354 );
1355 db_end_transaction(0);
1356 cgi_redirect("setup_logo");
1357 }
1358 style_header("Edit Project Logo");
1359 @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks
1360 @ like this:</p>
1361 @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" /></p></blockquote>
 
1362 @
 
 
1363 @ <p>The logo is accessible to all users at this URL:
1364 @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>.
1365 @ The logo may or may not appear on each
1366 @ page depending on the <a href="setup_editcss">CSS</a> and
1367 @ <a href="setup_header">header setup</a>.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1368 @
1369 @ <form action="%s(g.zTop)/setup_logo" method="post"
1370 @ enctype="multipart/form-data"><div>
1371 @ <p>To set a new logo image, select a file to use as the logo using
1372 @ the entry box below and then press the "Change Logo" button.</p>
 
 
 
 
1373 login_insert_csrf_secret();
1374 @ Logo Image file:
1375 @ <input type="file" name="im" size="60" accept="image/*" /><br />
1376 @ <input type="submit" name="set" value="Change Logo" />
1377 @ <input type="submit" name="clr" value="Revert To Default" />
 
1378 @ </div></form>
 
1379 @
1380 @ <p><span class="note">Note:</span> Your browser has probably cached the
1381 @ logo image, so you will probably need to press the Reload button on your
1382 @ browser after changing the logo to provoke your browser to reload the new
1383 @ logo image. </p>
1384 style_footer();
1385 db_end_transaction(0);
1386 }
1387
--- src/setup.c
+++ src/setup.c
@@ -84,11 +84,11 @@
84 setup_menu_entry("Header", "setup_header",
85 "Edit HTML text inserted at the top of every page");
86 setup_menu_entry("Footer", "setup_footer",
87 "Edit HTML text inserted at the bottom of every page");
88 setup_menu_entry("Logo", "setup_logo",
89 "Change the logo and background images for the server");
90 setup_menu_entry("Shunned", "shun",
91 "Show artifacts that are shunned by this repository");
92 setup_menu_entry("Log", "rcvfromlist",
93 "A record of received artifacts and their sources");
94 setup_menu_entry("User-Log", "access_log",
@@ -868,14 +868,15 @@
868 @ login name of a valid user and no other login credentials are available,
869 @ then the REMOTE_USER is accepted as an authenticated user.
870 @ </p>
871 @
872 @ <hr />
873 entry_attribute("IP address terms used in login cookie", 3,
874 "ip-prefix-terms", "ipt", "2");
875 @ <p>The number of octets of of the IP address used in the login cookie.
876 @ Set to zero to omit the IP address from the login cookie. A value of
877 @ 2 is recommended.
878 @ </p>
879 @
880 @ <hr />
881 entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766");
882 @ <p>The number of hours for which a login is valid. This must be a
@@ -950,11 +951,11 @@
951
952 login_check_credentials();
953 if( !g.perm.Setup ){
954 login_needed();
955 }
956 file_canonical_name(g.zRepositoryName, &fullName, 0);
957 zSelfRepo = mprintf(blob_str(&fullName));
958 blob_reset(&fullName);
959 if( P("join")!=0 ){
960 login_group_join(zRepo, zLogin, zPw, zNewName, &zErrMsg);
961 }else if( P("leave") ){
@@ -1318,69 +1319,123 @@
1319
1320 /*
1321 ** WEBPAGE: setup_logo
1322 */
1323 void setup_logo(void){
1324 const char *zLogoMime = db_get("logo-mimetype","image/gif");
1325 const char *aLogoImg = P("logoim");
1326 int szLogoImg = atoi(PD("logoim:bytes","0"));
1327 const char *zBgMime = db_get("background-mimetype","image/gif");
1328 const char *aBgImg = P("bgim");
1329 int szBgImg = atoi(PD("bgim:bytes","0"));
1330 if( szLogoImg>0 ){
1331 zLogoMime = PD("logoim:mimetype","image/gif");
1332 }
1333 if( szBgImg>0 ){
1334 zBgMime = PD("bgim:mimetype","image/gif");
1335 }
1336 login_check_credentials();
1337 if( !g.perm.Setup ){
1338 login_needed();
1339 }
1340 db_begin_transaction();
1341 if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
1342 Blob img;
1343 Stmt ins;
1344 blob_init(&img, aLogoImg, szLogoImg);
1345 db_prepare(&ins,
1346 "REPLACE INTO config(name,value,mtime)"
1347 " VALUES('logo-image',:bytes,now())"
1348 );
1349 db_bind_blob(&ins, ":bytes", &img);
1350 db_step(&ins);
1351 db_finalize(&ins);
1352 db_multi_exec(
1353 "REPLACE INTO config(name,value,mtime) VALUES('logo-mimetype',%Q,now())",
1354 zLogoMime
1355 );
1356 db_end_transaction(0);
1357 cgi_redirect("setup_logo");
1358 }else if( P("clrlogo")!=0 ){
1359 db_multi_exec(
1360 "DELETE FROM config WHERE name IN "
1361 "('logo-image','logo-mimetype')"
1362 );
1363 db_end_transaction(0);
1364 cgi_redirect("setup_logo");
1365 }else if( P("setbg")!=0 && zBgMime && zBgMime[0] && szBgImg>0 ){
1366 Blob img;
1367 Stmt ins;
1368 blob_init(&img, aBgImg, szBgImg);
1369 db_prepare(&ins,
1370 "REPLACE INTO config(name,value,mtime)"
1371 " VALUES('background-image',:bytes,now())"
1372 );
1373 db_bind_blob(&ins, ":bytes", &img);
1374 db_step(&ins);
1375 db_finalize(&ins);
1376 db_multi_exec(
1377 "REPLACE INTO config(name,value,mtime)"
1378 " VALUES('background-mimetype',%Q,now())",
1379 zBgMime
1380 );
1381 db_end_transaction(0);
1382 cgi_redirect("setup_logo");
1383 }else if( P("clrbg")!=0 ){
1384 db_multi_exec(
1385 "DELETE FROM config WHERE name IN "
1386 "('background-image','background-mimetype')"
1387 );
1388 db_end_transaction(0);
1389 cgi_redirect("setup_logo");
1390 }
1391 style_header("Edit Project Logo And Background");
1392 @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b>
1393 @ and looks like this:</p>
1394 @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" border="1" />
1395 @ </p></blockquote>
1396 @
1397 @ <form action="%s(g.zTop)/setup_logo" method="post"
1398 @ enctype="multipart/form-data"><div>
1399 @ <p>The logo is accessible to all users at this URL:
1400 @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>.
1401 @ The logo may or may not appear on each
1402 @ page depending on the <a href="setup_editcss">CSS</a> and
1403 @ <a href="setup_header">header setup</a>.
1404 @ To change the logo image, use the following form:</p>
1405 login_insert_csrf_secret();
1406 @ Logo Image file:
1407 @ <input type="file" name="logoim" size="60" accept="image/*" />
1408 @ <p align="center">
1409 @ <input type="submit" name="setlogo" value="Change Logo" />
1410 @ <input type="submit" name="clrlogo" value="Revert To Default" /></p>
1411 @ </div></form>
1412 @ <hr />
1413 @
1414 @ <p>The current background image has a MIME-Type of <b>%h(zBgMime)</b>
1415 @ and looks like this:</p>
1416 @ <blockquote><p><img src="%s(g.zTop)/background" alt="background" border=1 />
1417 @ </p></blockquote>
1418 @
1419 @ <form action="%s(g.zTop)/setup_logo" method="post"
1420 @ enctype="multipart/form-data"><div>
1421 @ <p>The background image is accessible to all users at this URL:
1422 @ <a href="%s(g.zBaseURL)/background">%s(g.zBaseURL)/background</a>.
1423 @ The background image may or may not appear on each
1424 @ page depending on the <a href="setup_editcss">CSS</a> and
1425 @ <a href="setup_header">header setup</a>.
1426 @ To change the background image, use the following form:</p>
1427 login_insert_csrf_secret();
1428 @ Background image file:
1429 @ <input type="file" name="bgim" size="60" accept="image/*" />
1430 @ <p align="center">
1431 @ <input type="submit" name="setbg" value="Change Background" />
1432 @ <input type="submit" name="clrbg" value="Revert To Default" /></p>
1433 @ </div></form>
1434 @ <hr />
1435 @
1436 @ <p><span class="note">Note:</span> Your browser has probably cached these
1437 @ images, so you may need to press the Reload button before changes will
1438 @ take effect. </p>
 
1439 style_footer();
1440 db_end_transaction(0);
1441 }
1442
+22 -8
--- src/shell.c
+++ src/shell.c
@@ -66,10 +66,12 @@
6666
6767
#if defined(_WIN32) || defined(WIN32)
6868
# include <io.h>
6969
#define isatty(h) _isatty(h)
7070
#define access(f,m) _access((f),(m))
71
+#define popen(a,b) _popen((a),(b))
72
+#define pclose(x) _pclose(x)
7173
#else
7274
/* Make sure isatty() has a prototype.
7375
*/
7476
extern int isatty(int);
7577
#endif
@@ -1075,10 +1077,13 @@
10751077
fprintf(pArg->out, "Page cache hits: %d\n", iCur);
10761078
iHiwtr = iCur = -1;
10771079
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
10781080
fprintf(pArg->out, "Page cache misses: %d\n", iCur);
10791081
iHiwtr = iCur = -1;
1082
+ sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
1083
+ fprintf(pArg->out, "Page cache writes: %d\n", iCur);
1084
+ iHiwtr = iCur = -1;
10801085
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
10811086
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
10821087
iHiwtr = iCur = -1;
10831088
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
10841089
fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur);
@@ -1285,11 +1290,10 @@
12851290
sqlite3_stmt *pTableInfo = 0;
12861291
char *zSelect = 0;
12871292
char *zTableInfo = 0;
12881293
char *zTmp = 0;
12891294
int nRow = 0;
1290
- int kk;
12911295
12921296
zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
12931297
zTableInfo = appendText(zTableInfo, zTable, '"');
12941298
zTableInfo = appendText(zTableInfo, ");", 0);
12951299
@@ -1298,16 +1302,13 @@
12981302
if( rc!=SQLITE_OK || !pTableInfo ){
12991303
return 1;
13001304
}
13011305
13021306
zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
1303
- if( !isalpha(zTable[0]) ){
1304
- kk = 0;
1305
- }else{
1306
- for(kk=1; isalnum(zTable[kk]); kk++){}
1307
- }
1308
- zTmp = appendText(zTmp, zTable, zTable[kk] ? '"' : 0);
1307
+ /* Always quote the table name, even if it appears to be pure ascii,
1308
+ ** in case it is a keyword. Ex: INSERT INTO "table" ... */
1309
+ zTmp = appendText(zTmp, zTable, '"');
13091310
if( zTmp ){
13101311
zSelect = appendText(zSelect, zTmp, '\'');
13111312
}
13121313
zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
13131314
rc = sqlite3_step(pTableInfo);
@@ -1998,15 +1999,28 @@
19981999
"%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
19992000
}else
20002001
20012002
if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
20022003
if( p->out!=stdout ){
2003
- fclose(p->out);
2004
+ if( p->outfile[0]=='|' ){
2005
+ pclose(p->out);
2006
+ }else{
2007
+ fclose(p->out);
2008
+ }
20042009
}
20052010
if( strcmp(azArg[1],"stdout")==0 ){
20062011
p->out = stdout;
20072012
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout");
2013
+ }else if( azArg[1][0]=='|' ){
2014
+ p->out = popen(&azArg[1][1], "w");
2015
+ if( p->out==0 ){
2016
+ fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]);
2017
+ p->out = stdout;
2018
+ rc = 1;
2019
+ }else{
2020
+ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
2021
+ }
20082022
}else{
20092023
p->out = fopen(azArg[1], "wb");
20102024
if( p->out==0 ){
20112025
fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]);
20122026
p->out = stdout;
20132027
--- src/shell.c
+++ src/shell.c
@@ -66,10 +66,12 @@
66
67 #if defined(_WIN32) || defined(WIN32)
68 # include <io.h>
69 #define isatty(h) _isatty(h)
70 #define access(f,m) _access((f),(m))
 
 
71 #else
72 /* Make sure isatty() has a prototype.
73 */
74 extern int isatty(int);
75 #endif
@@ -1075,10 +1077,13 @@
1075 fprintf(pArg->out, "Page cache hits: %d\n", iCur);
1076 iHiwtr = iCur = -1;
1077 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
1078 fprintf(pArg->out, "Page cache misses: %d\n", iCur);
1079 iHiwtr = iCur = -1;
 
 
 
1080 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
1081 fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
1082 iHiwtr = iCur = -1;
1083 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
1084 fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur);
@@ -1285,11 +1290,10 @@
1285 sqlite3_stmt *pTableInfo = 0;
1286 char *zSelect = 0;
1287 char *zTableInfo = 0;
1288 char *zTmp = 0;
1289 int nRow = 0;
1290 int kk;
1291
1292 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
1293 zTableInfo = appendText(zTableInfo, zTable, '"');
1294 zTableInfo = appendText(zTableInfo, ");", 0);
1295
@@ -1298,16 +1302,13 @@
1298 if( rc!=SQLITE_OK || !pTableInfo ){
1299 return 1;
1300 }
1301
1302 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
1303 if( !isalpha(zTable[0]) ){
1304 kk = 0;
1305 }else{
1306 for(kk=1; isalnum(zTable[kk]); kk++){}
1307 }
1308 zTmp = appendText(zTmp, zTable, zTable[kk] ? '"' : 0);
1309 if( zTmp ){
1310 zSelect = appendText(zSelect, zTmp, '\'');
1311 }
1312 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
1313 rc = sqlite3_step(pTableInfo);
@@ -1998,15 +1999,28 @@
1998 "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
1999 }else
2000
2001 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
2002 if( p->out!=stdout ){
2003 fclose(p->out);
 
 
 
 
2004 }
2005 if( strcmp(azArg[1],"stdout")==0 ){
2006 p->out = stdout;
2007 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout");
 
 
 
 
 
 
 
 
 
2008 }else{
2009 p->out = fopen(azArg[1], "wb");
2010 if( p->out==0 ){
2011 fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]);
2012 p->out = stdout;
2013
--- src/shell.c
+++ src/shell.c
@@ -66,10 +66,12 @@
66
67 #if defined(_WIN32) || defined(WIN32)
68 # include <io.h>
69 #define isatty(h) _isatty(h)
70 #define access(f,m) _access((f),(m))
71 #define popen(a,b) _popen((a),(b))
72 #define pclose(x) _pclose(x)
73 #else
74 /* Make sure isatty() has a prototype.
75 */
76 extern int isatty(int);
77 #endif
@@ -1075,10 +1077,13 @@
1077 fprintf(pArg->out, "Page cache hits: %d\n", iCur);
1078 iHiwtr = iCur = -1;
1079 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
1080 fprintf(pArg->out, "Page cache misses: %d\n", iCur);
1081 iHiwtr = iCur = -1;
1082 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
1083 fprintf(pArg->out, "Page cache writes: %d\n", iCur);
1084 iHiwtr = iCur = -1;
1085 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
1086 fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
1087 iHiwtr = iCur = -1;
1088 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
1089 fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur);
@@ -1285,11 +1290,10 @@
1290 sqlite3_stmt *pTableInfo = 0;
1291 char *zSelect = 0;
1292 char *zTableInfo = 0;
1293 char *zTmp = 0;
1294 int nRow = 0;
 
1295
1296 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
1297 zTableInfo = appendText(zTableInfo, zTable, '"');
1298 zTableInfo = appendText(zTableInfo, ");", 0);
1299
@@ -1298,16 +1302,13 @@
1302 if( rc!=SQLITE_OK || !pTableInfo ){
1303 return 1;
1304 }
1305
1306 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
1307 /* Always quote the table name, even if it appears to be pure ascii,
1308 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
1309 zTmp = appendText(zTmp, zTable, '"');
 
 
 
1310 if( zTmp ){
1311 zSelect = appendText(zSelect, zTmp, '\'');
1312 }
1313 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
1314 rc = sqlite3_step(pTableInfo);
@@ -1998,15 +1999,28 @@
1999 "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
2000 }else
2001
2002 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
2003 if( p->out!=stdout ){
2004 if( p->outfile[0]=='|' ){
2005 pclose(p->out);
2006 }else{
2007 fclose(p->out);
2008 }
2009 }
2010 if( strcmp(azArg[1],"stdout")==0 ){
2011 p->out = stdout;
2012 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout");
2013 }else if( azArg[1][0]=='|' ){
2014 p->out = popen(&azArg[1][1], "w");
2015 if( p->out==0 ){
2016 fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]);
2017 p->out = stdout;
2018 rc = 1;
2019 }else{
2020 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
2021 }
2022 }else{
2023 p->out = fopen(azArg[1], "wb");
2024 if( p->out==0 ){
2025 fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]);
2026 p->out = stdout;
2027
+1 -1
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -75,11 +75,11 @@
7575
compress(&pOut[4], &nOut, pIn, nIn);
7676
sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
7777
}
7878
7979
/*
80
-** Implementation of the "uncontent(X)" SQL function. The argument X
80
+** Implementation of the "decompress(X)" SQL function. The argument X
8181
** is a blob which was obtained from compress(Y). The output will be
8282
** the value Y.
8383
*/
8484
static void sqlcmd_decompress(
8585
sqlite3_context *context,
8686
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -75,11 +75,11 @@
75 compress(&pOut[4], &nOut, pIn, nIn);
76 sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
77 }
78
79 /*
80 ** Implementation of the "uncontent(X)" SQL function. The argument X
81 ** is a blob which was obtained from compress(Y). The output will be
82 ** the value Y.
83 */
84 static void sqlcmd_decompress(
85 sqlite3_context *context,
86
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -75,11 +75,11 @@
75 compress(&pOut[4], &nOut, pIn, nIn);
76 sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
77 }
78
79 /*
80 ** Implementation of the "decompress(X)" SQL function. The argument X
81 ** is a blob which was obtained from compress(Y). The output will be
82 ** the value Y.
83 */
84 static void sqlcmd_decompress(
85 sqlite3_context *context,
86
+3886 -1399
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.7.11. By combining all the individual C code files into this
3
+** version 3.7.12. 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.
@@ -655,13 +655,13 @@
655655
**
656656
** See also: [sqlite3_libversion()],
657657
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
658658
** [sqlite_version()] and [sqlite_source_id()].
659659
*/
660
-#define SQLITE_VERSION "3.7.11"
661
-#define SQLITE_VERSION_NUMBER 3007011
662
-#define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130"
660
+#define SQLITE_VERSION "3.7.12"
661
+#define SQLITE_VERSION_NUMBER 3007012
662
+#define SQLITE_SOURCE_ID "2012-03-31 19:12:23 af602d87736b52802a4e760ffeeaa28112b99d9a"
663663
664664
/*
665665
** CAPI3REF: Run-Time Library Version Numbers
666666
** KEYWORDS: sqlite3_version, sqlite3_sourceid
667667
**
@@ -1009,10 +1009,11 @@
10091009
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
10101010
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
10111011
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
10121012
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
10131013
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
1014
+#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
10141015
10151016
/*
10161017
** CAPI3REF: Flags For File Open Operations
10171018
**
10181019
** These bit values are intended for use in the
@@ -1264,31 +1265,35 @@
12641265
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
12651266
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
12661267
** into an integer that the pArg argument points to. This capability
12671268
** is used during testing and only needs to be supported when SQLITE_TEST
12681269
** is defined.
1269
-**
1270
+** <ul>
1271
+** <li>[[SQLITE_FCNTL_SIZE_HINT]]
12701272
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
12711273
** layer a hint of how large the database file will grow to be during the
12721274
** current transaction. This hint is not guaranteed to be accurate but it
12731275
** is often close. The underlying VFS might choose to preallocate database
12741276
** file space based on this hint in order to help writes to the database
12751277
** file run faster.
12761278
**
1279
+** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
12771280
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
12781281
** extends and truncates the database file in chunks of a size specified
12791282
** by the user. The fourth argument to [sqlite3_file_control()] should
12801283
** point to an integer (type int) containing the new chunk-size to use
12811284
** for the nominated database. Allocating database file space in large
12821285
** chunks (say 1MB at a time), may reduce file-system fragmentation and
12831286
** improve performance on some systems.
12841287
**
1288
+** <li>[[SQLITE_FCNTL_FILE_POINTER]]
12851289
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
12861290
** to the [sqlite3_file] object associated with a particular database
12871291
** connection. See the [sqlite3_file_control()] documentation for
12881292
** additional information.
12891293
**
1294
+** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
12901295
** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
12911296
** SQLite and sent to all VFSes in place of a call to the xSync method
12921297
** when the database connection has [PRAGMA synchronous] set to OFF.)^
12931298
** Some specialized VFSes need this signal in order to operate correctly
12941299
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
@@ -1295,10 +1300,11 @@
12951300
** VFSes do not need this signal and should silently ignore this opcode.
12961301
** Applications should not call [sqlite3_file_control()] with this
12971302
** opcode as doing so may disrupt the operation of the specialized VFSes
12981303
** that do require it.
12991304
**
1305
+** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
13001306
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
13011307
** retry counts and intervals for certain disk I/O operations for the
13021308
** windows [VFS] in order to provide robustness in the presence of
13031309
** anti-virus programs. By default, the windows VFS will retry file read,
13041310
** file write, and file delete operations up to 10 times, with a delay
@@ -1311,10 +1317,11 @@
13111317
** integer is the delay. If either integer is negative, then the setting
13121318
** is not changed but instead the prior value of that setting is written
13131319
** into the array entry, allowing the current retry settings to be
13141320
** interrogated. The zDbName parameter is ignored.
13151321
**
1322
+** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
13161323
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
13171324
** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
13181325
** write ahead log and shared memory files used for transaction control
13191326
** are automatically deleted when the latest connection to the database
13201327
** closes. Setting persistent WAL mode causes those files to persist after
@@ -1325,24 +1332,27 @@
13251332
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
13261333
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
13271334
** WAL mode. If the integer is -1, then it is overwritten with the current
13281335
** WAL persistence setting.
13291336
**
1337
+** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
13301338
** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
13311339
** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
13321340
** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
13331341
** xDeviceCharacteristics methods. The fourth parameter to
13341342
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
13351343
** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
13361344
** mode. If the integer is -1, then it is overwritten with the current
13371345
** zero-damage mode setting.
13381346
**
1347
+** <li>[[SQLITE_FCNTL_OVERWRITE]]
13391348
** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
13401349
** a write transaction to indicate that, unless it is rolled back for some
13411350
** reason, the entire database file will be overwritten by the current
13421351
** transaction. This is used by VACUUM operations.
13431352
**
1353
+** <li>[[SQLITE_FCNTL_VFSNAME]]
13441354
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
13451355
** all [VFSes] in the VFS stack. The names are of all VFS shims and the
13461356
** final bottom-level VFS are written into memory obtained from
13471357
** [sqlite3_malloc()] and the result is stored in the char* variable
13481358
** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -1349,10 +1359,34 @@
13491359
** The caller is responsible for freeing the memory when done. As with
13501360
** all file-control actions, there is no guarantee that this will actually
13511361
** do anything. Callers should initialize the char* variable to a NULL
13521362
** pointer in case this file-control is not implemented. This file-control
13531363
** is intended for diagnostic use only.
1364
+**
1365
+** <li>[[SQLITE_FCNTL_PRAGMA]]
1366
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
1367
+** file control is sent to the open [sqlite3_file] object corresponding
1368
+** to the database file to which the pragma statement refers. ^The argument
1369
+** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
1370
+** pointers to strings (char**) in which the second element of the array
1371
+** is the name of the pragma and the third element is the argument to the
1372
+** pragma or NULL if the pragma has no argument. ^The handler for an
1373
+** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
1374
+** of the char** argument point to a string obtained from [sqlite3_mprintf()]
1375
+** or the equivalent and that string will become the result of the pragma or
1376
+** the error message if the pragma fails. ^If the
1377
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
1378
+** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
1379
+** file control returns [SQLITE_OK], then the parser assumes that the
1380
+** VFS has handled the PRAGMA itself and the parser generates a no-op
1381
+** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
1382
+** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
1383
+** that the VFS encountered an error while handling the [PRAGMA] and the
1384
+** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
1385
+** file control occurs at the beginning of pragma statement analysis and so
1386
+** it is able to override built-in [PRAGMA] statements.
1387
+** </ul>
13541388
*/
13551389
#define SQLITE_FCNTL_LOCKSTATE 1
13561390
#define SQLITE_GET_LOCKPROXYFILE 2
13571391
#define SQLITE_SET_LOCKPROXYFILE 3
13581392
#define SQLITE_LAST_ERRNO 4
@@ -1363,10 +1397,11 @@
13631397
#define SQLITE_FCNTL_WIN32_AV_RETRY 9
13641398
#define SQLITE_FCNTL_PERSIST_WAL 10
13651399
#define SQLITE_FCNTL_OVERWRITE 11
13661400
#define SQLITE_FCNTL_VFSNAME 12
13671401
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
1402
+#define SQLITE_FCNTL_PRAGMA 14
13681403
13691404
/*
13701405
** CAPI3REF: Mutex Handle
13711406
**
13721407
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -5012,10 +5047,19 @@
50125047
** will be an absolute pathname, even if the filename used
50135048
** to open the database originally was a URI or relative pathname.
50145049
*/
50155050
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
50165051
5052
+/*
5053
+** CAPI3REF: Determine if a database is read-only
5054
+**
5055
+** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
5056
+** of connection D is read-only, 0 if it is read/write, or -1 if N is not
5057
+** the name of a database on connection D.
5058
+*/
5059
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
5060
+
50175061
/*
50185062
** CAPI3REF: Find the next prepared statement
50195063
**
50205064
** ^This interface returns a pointer to the next [prepared statement] after
50215065
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -6510,10 +6554,21 @@
65106554
** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
65116555
** <dd>This parameter returns the number of pager cache misses that have
65126556
** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
65136557
** is always 0.
65146558
** </dd>
6559
+**
6560
+** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
6561
+** <dd>This parameter returns the number of dirty cache entries that have
6562
+** been written to disk. Specifically, the number of pages written to the
6563
+** wal file in wal mode databases, or the number of pages written to the
6564
+** database file in rollback mode databases. Any pages written as part of
6565
+** transaction rollback or database recovery operations are not included.
6566
+** If an IO or other error occurs while writing a page to disk, the effect
6567
+** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The
6568
+** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
6569
+** </dd>
65156570
** </dl>
65166571
*/
65176572
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
65186573
#define SQLITE_DBSTATUS_CACHE_USED 1
65196574
#define SQLITE_DBSTATUS_SCHEMA_USED 2
@@ -6521,11 +6576,12 @@
65216576
#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
65226577
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
65236578
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
65246579
#define SQLITE_DBSTATUS_CACHE_HIT 7
65256580
#define SQLITE_DBSTATUS_CACHE_MISS 8
6526
-#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */
6581
+#define SQLITE_DBSTATUS_CACHE_WRITE 9
6582
+#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
65276583
65286584
65296585
/*
65306586
** CAPI3REF: Prepared Statement Status
65316587
**
@@ -7137,15 +7193,16 @@
71377193
71387194
71397195
/*
71407196
** CAPI3REF: String Comparison
71417197
**
7142
-** ^The [sqlite3_strnicmp()] API allows applications and extensions to
7143
-** compare the contents of two buffers containing UTF-8 strings in a
7144
-** case-independent fashion, using the same definition of case independence
7145
-** that SQLite uses internally when comparing identifiers.
7198
+** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
7199
+** and extensions to compare the contents of two buffers containing UTF-8
7200
+** strings in a case-independent fashion, using the same definition of "case
7201
+** independence" that SQLite uses internally when comparing identifiers.
71467202
*/
7203
+SQLITE_API int sqlite3_stricmp(const char *, const char *);
71477204
SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
71487205
71497206
/*
71507207
** CAPI3REF: Error Logging Interface
71517208
**
@@ -8204,11 +8261,11 @@
82048261
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
82058262
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
82068263
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
82078264
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
82088265
SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
8209
-SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*);
8266
+SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int);
82108267
SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
82118268
SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
82128269
SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
82138270
SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
82148271
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
@@ -8944,10 +9001,13 @@
89449001
SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
89459002
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
89469003
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
89479004
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
89489005
SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
9006
+#ifdef SQLITE_ENABLE_ZIPVFS
9007
+SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
9008
+#endif
89499009
89509010
/* Functions used to query pager state and configuration. */
89519011
SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
89529012
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
89539013
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
@@ -9871,18 +9931,22 @@
98719931
void (*xDestroy)(void *);
98729932
void *pUserData;
98739933
};
98749934
98759935
/*
9876
-** Possible values for FuncDef.flags
9936
+** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF
9937
+** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
9938
+** are assert() statements in the code to verify this.
98779939
*/
98789940
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
98799941
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
98809942
#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
98819943
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
9882
-#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */
9883
-#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */
9944
+#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */
9945
+#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */
9946
+#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */
9947
+#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */
98849948
98859949
/*
98869950
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
98879951
** used to create the initializers for the FuncDef structures.
98889952
**
@@ -9906,11 +9970,14 @@
99069970
** available as the function user-data (sqlite3_user_data()). The
99079971
** FuncDef.flags variable is set to the value passed as the flags
99089972
** parameter.
99099973
*/
99109974
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
9911
- {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
9975
+ {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \
9976
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
9977
+#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
9978
+ {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
99129979
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
99139980
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
99149981
{nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
99159982
pArg, 0, xFunc, 0, 0, #zName, 0, 0}
99169983
#define LIKEFUNC(zName, nArg, arg, flags) \
@@ -10136,11 +10203,11 @@
1013610203
u8 tabFlags; /* Mask of TF_* values */
1013710204
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
1013810205
FKey *pFKey; /* Linked list of all foreign keys in this table */
1013910206
char *zColAff; /* String defining the affinity of each column */
1014010207
#ifndef SQLITE_OMIT_CHECK
10141
- Expr *pCheck; /* The AND of all CHECK constraints */
10208
+ ExprList *pCheck; /* All CHECK constraints */
1014210209
#endif
1014310210
#ifndef SQLITE_OMIT_ALTERTABLE
1014410211
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
1014510212
#endif
1014610213
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -10529,10 +10596,11 @@
1052910596
** TK_VARIABLE: variable number (always >= 1). */
1053010597
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
1053110598
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
1053210599
u8 flags2; /* Second set of flags. EP2_... */
1053310600
u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
10601
+ /* If TK_COLUMN, the value of p5 for OP_Column */
1053410602
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
1053510603
Table *pTab; /* Table for TK_COLUMN expressions. */
1053610604
#if SQLITE_MAX_EXPR_DEPTH>0
1053710605
int nHeight; /* Height of the tree headed by this node */
1053810606
#endif
@@ -10551,11 +10619,11 @@
1055110619
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
1055210620
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
1055310621
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
1055410622
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
1055510623
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
10556
-#define EP_Hint 0x1000 /* Optimizer hint. Not required for correctness */
10624
+#define EP_Hint 0x1000 /* Not used */
1055710625
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
1055810626
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
1055910627
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
1056010628
1056110629
/*
@@ -11070,10 +11138,11 @@
1107011138
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
1107111139
int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
1107211140
int regRowid; /* Register holding rowid of CREATE TABLE entry */
1107311141
int regRoot; /* Register holding root page number for new objects */
1107411142
int nMaxArg; /* Max args passed to user function by sub-program */
11143
+ Token constraintName;/* Name of the constraint currently being parsed */
1107511144
#ifndef SQLITE_OMIT_SHARED_CACHE
1107611145
int nTableLock; /* Number of locks in aTableLock */
1107711146
TableLock *aTableLock; /* Required table locks for shared-cache mode */
1107811147
#endif
1107911148
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
@@ -11138,18 +11207,20 @@
1113811207
const char *zAuthContext; /* Put saved Parse.zAuthContext here */
1113911208
Parse *pParse; /* The Parse structure */
1114011209
};
1114111210
1114211211
/*
11143
-** Bitfield flags for P5 value in OP_Insert and OP_Delete
11212
+** Bitfield flags for P5 value in various opcodes.
1114411213
*/
1114511214
#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
1114611215
#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
1114711216
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
1114811217
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
1114911218
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
1115011219
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
11220
+#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
11221
+#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
1115111222
1115211223
/*
1115311224
* Each trigger present in the database schema is stored as an instance of
1115411225
* struct Trigger.
1115511226
*
@@ -11415,11 +11486,11 @@
1141511486
#endif
1141611487
1141711488
/*
1141811489
** Internal function prototypes
1141911490
*/
11420
-SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
11491
+#define sqlite3StrICmp sqlite3_stricmp
1142111492
SQLITE_PRIVATE int sqlite3Strlen30(const char*);
1142211493
#define sqlite3StrNICmp sqlite3_strnicmp
1142311494
1142411495
SQLITE_PRIVATE int sqlite3MallocInit(void);
1142511496
SQLITE_PRIVATE void sqlite3MallocEnd(void);
@@ -11563,10 +11634,11 @@
1156311634
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
1156411635
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
1156511636
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
1156611637
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
1156711638
sqlite3_vfs**,char**,char **);
11639
+SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
1156811640
SQLITE_PRIVATE int sqlite3CodeOnce(Parse *);
1156911641
1157011642
SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
1157111643
SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
1157211644
SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
@@ -11628,11 +11700,11 @@
1162811700
#endif
1162911701
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
1163011702
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
1163111703
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
1163211704
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11633
-SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
11705
+SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
1163411706
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
1163511707
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
1163611708
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
1163711709
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
1163811710
SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
@@ -11662,11 +11734,11 @@
1166211734
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
1166311735
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
1166411736
SQLITE_PRIVATE void sqlite3PrngSaveState(void);
1166511737
SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
1166611738
SQLITE_PRIVATE void sqlite3PrngResetState(void);
11667
-SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*);
11739
+SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
1166811740
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
1166911741
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
1167011742
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
1167111743
SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
1167211744
SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
@@ -13460,14 +13532,16 @@
1346013532
** Set *pCurrent to the total cache hits or misses encountered by all
1346113533
** pagers the database handle is connected to. *pHighwater is always set
1346213534
** to zero.
1346313535
*/
1346413536
case SQLITE_DBSTATUS_CACHE_HIT:
13465
- case SQLITE_DBSTATUS_CACHE_MISS: {
13537
+ case SQLITE_DBSTATUS_CACHE_MISS:
13538
+ case SQLITE_DBSTATUS_CACHE_WRITE:{
1346613539
int i;
1346713540
int nRet = 0;
1346813541
assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
13542
+ assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
1346913543
1347013544
for(i=0; i<db->nDb; i++){
1347113545
if( db->aDb[i].pBt ){
1347213546
Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
1347313547
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
@@ -21210,17 +21284,17 @@
2121021284
2121121285
/*
2121221286
** Some systems have stricmp(). Others have strcasecmp(). Because
2121321287
** there is no consistency, we will define our own.
2121421288
**
21215
-** IMPLEMENTATION-OF: R-20522-24639 The sqlite3_strnicmp() API allows
21216
-** applications and extensions to compare the contents of two buffers
21217
-** containing UTF-8 strings in a case-independent fashion, using the same
21218
-** definition of case independence that SQLite uses internally when
21219
-** comparing identifiers.
21289
+** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
21290
+** sqlite3_strnicmp() APIs allow applications and extensions to compare
21291
+** the contents of two buffers containing UTF-8 strings in a
21292
+** case-independent fashion, using the same definition of "case
21293
+** independence" that SQLite uses internally when comparing identifiers.
2122021294
*/
21221
-SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){
21295
+SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
2122221296
register unsigned char *a, *b;
2122321297
a = (unsigned char *)zLeft;
2122421298
b = (unsigned char *)zRight;
2122521299
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
2122621300
return UpperToLower[*a] - UpperToLower[*b];
@@ -25494,11 +25568,11 @@
2549425568
** recover the hot journals.
2549525569
*/
2549625570
static int robust_open(const char *z, int f, mode_t m){
2549725571
int rc;
2549825572
mode_t m2;
25499
- mode_t origM;
25573
+ mode_t origM = 0;
2550025574
if( m==0 ){
2550125575
m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
2550225576
}else{
2550325577
m2 = m;
2550425578
origM = osUmask(0);
@@ -33678,10 +33752,13 @@
3367833752
}
3367933753
sqlite3_free(pFile->zDeleteOnClose);
3368033754
}
3368133755
#endif
3368233756
OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
33757
+ if( rc ){
33758
+ pFile->h = NULL;
33759
+ }
3368333760
OpenCounter(-1);
3368433761
return rc ? SQLITE_OK
3368533762
: winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
3368633763
"winClose", pFile->zPath);
3368733764
}
@@ -33695,22 +33772,33 @@
3369533772
sqlite3_file *id, /* File to read from */
3369633773
void *pBuf, /* Write content into this buffer */
3369733774
int amt, /* Number of bytes to read */
3369833775
sqlite3_int64 offset /* Begin reading at this offset */
3369933776
){
33777
+#if !SQLITE_OS_WINCE
33778
+ OVERLAPPED overlapped; /* The offset for ReadFile. */
33779
+#endif
3370033780
winFile *pFile = (winFile*)id; /* file handle */
3370133781
DWORD nRead; /* Number of bytes actually read from file */
3370233782
int nRetry = 0; /* Number of retrys */
3370333783
3370433784
assert( id!=0 );
3370533785
SimulateIOError(return SQLITE_IOERR_READ);
3370633786
OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
3370733787
33788
+#if SQLITE_OS_WINCE
3370833789
if( seekWinFile(pFile, offset) ){
3370933790
return SQLITE_FULL;
3371033791
}
3371133792
while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
33793
+#else
33794
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
33795
+ overlapped.Offset = (LONG)(offset & 0xffffffff);
33796
+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
33797
+ while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
33798
+ osGetLastError()!=ERROR_HANDLE_EOF ){
33799
+#endif
3371233800
DWORD lastErrno;
3371333801
if( retryIoerr(&nRetry, &lastErrno) ) continue;
3371433802
pFile->lastErrno = lastErrno;
3371533803
return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
3371633804
"winRead", pFile->zPath);
@@ -33733,11 +33821,11 @@
3373333821
sqlite3_file *id, /* File to write into */
3373433822
const void *pBuf, /* The bytes to be written */
3373533823
int amt, /* Number of bytes to write */
3373633824
sqlite3_int64 offset /* Offset into the file to begin writing at */
3373733825
){
33738
- int rc; /* True if error has occured, else false */
33826
+ int rc = 0; /* True if error has occured, else false */
3373933827
winFile *pFile = (winFile*)id; /* File handle */
3374033828
int nRetry = 0; /* Number of retries */
3374133829
3374233830
assert( amt>0 );
3374333831
assert( pFile );
@@ -33744,23 +33832,48 @@
3374433832
SimulateIOError(return SQLITE_IOERR_WRITE);
3374533833
SimulateDiskfullError(return SQLITE_FULL);
3374633834
3374733835
OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
3374833836
33837
+#if SQLITE_OS_WINCE
3374933838
rc = seekWinFile(pFile, offset);
3375033839
if( rc==0 ){
33840
+#else
33841
+ {
33842
+#endif
33843
+#if !SQLITE_OS_WINCE
33844
+ OVERLAPPED overlapped; /* The offset for WriteFile. */
33845
+#endif
3375133846
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
3375233847
int nRem = amt; /* Number of bytes yet to be written */
3375333848
DWORD nWrite; /* Bytes written by each WriteFile() call */
3375433849
DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
33850
+
33851
+#if !SQLITE_OS_WINCE
33852
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
33853
+ overlapped.Offset = (LONG)(offset & 0xffffffff);
33854
+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
33855
+#endif
3375533856
3375633857
while( nRem>0 ){
33858
+#if SQLITE_OS_WINCE
3375733859
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
33860
+#else
33861
+ if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
33862
+#endif
3375833863
if( retryIoerr(&nRetry, &lastErrno) ) continue;
3375933864
break;
3376033865
}
33761
- if( nWrite<=0 ) break;
33866
+ if( nWrite<=0 ){
33867
+ lastErrno = osGetLastError();
33868
+ break;
33869
+ }
33870
+#if !SQLITE_OS_WINCE
33871
+ offset += nWrite;
33872
+ overlapped.Offset = (LONG)(offset & 0xffffffff);
33873
+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
33874
+#endif
3376233875
aRem += nWrite;
3376333876
nRem -= nWrite;
3376433877
}
3376533878
if( nRem>0 ){
3376633879
pFile->lastErrno = lastErrno;
@@ -38302,10 +38415,11 @@
3830238415
# define sqlite3WalFrames(u,v,w,x,y,z) 0
3830338416
# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
3830438417
# define sqlite3WalCallback(z) 0
3830538418
# define sqlite3WalExclusiveMode(y,z) 0
3830638419
# define sqlite3WalHeapMemory(z) 0
38420
+# define sqlite3WalFramesize(z) 0
3830738421
#else
3830838422
3830938423
#define WAL_SAVEPOINT_NDATA 4
3831038424
3831138425
/* Connection to a write-ahead log (WAL) file.
@@ -38382,10 +38496,17 @@
3838238496
/* Return true if the argument is non-NULL and the WAL module is using
3838338497
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
3838438498
** WAL module is using shared-memory, return false.
3838538499
*/
3838638500
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
38501
+
38502
+#ifdef SQLITE_ENABLE_ZIPVFS
38503
+/* If the WAL file is not empty, return the number of bytes of content
38504
+** stored in each frame (i.e. the db page-size when the WAL was created).
38505
+*/
38506
+SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
38507
+#endif
3838738508
3838838509
#endif /* ifndef SQLITE_OMIT_WAL */
3838938510
#endif /* _WAL_H_ */
3839038511
3839138512
/************** End of wal.h *************************************************/
@@ -39037,13 +39158,13 @@
3903739158
i64 journalSizeLimit; /* Size limit for persistent journal files */
3903839159
char *zFilename; /* Name of the database file */
3903939160
char *zJournal; /* Name of the journal file */
3904039161
int (*xBusyHandler)(void*); /* Function to call when busy */
3904139162
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
39042
- int nHit, nMiss; /* Total cache hits and misses */
39163
+ int aStat[3]; /* Total cache hits, misses and writes */
3904339164
#ifdef SQLITE_TEST
39044
- int nRead, nWrite; /* Database pages read/written */
39165
+ int nRead; /* Database pages read */
3904539166
#endif
3904639167
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
3904739168
#ifdef SQLITE_HAS_CODEC
3904839169
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
3904939170
void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
@@ -39056,10 +39177,19 @@
3905639177
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
3905739178
char *zWal; /* File name for write-ahead log */
3905839179
#endif
3905939180
};
3906039181
39182
+/*
39183
+** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
39184
+** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
39185
+** or CACHE_WRITE to sqlite3_db_status().
39186
+*/
39187
+#define PAGER_STAT_HIT 0
39188
+#define PAGER_STAT_MISS 1
39189
+#define PAGER_STAT_WRITE 2
39190
+
3906139191
/*
3906239192
** The following global variables hold counters used for
3906339193
** testing purposes only. These variables do not exist in
3906439194
** a non-testing build. These variables are not thread-safe.
3906539195
*/
@@ -41338,10 +41468,11 @@
4133841468
PgHdr *pList, /* List of frames to log */
4133941469
Pgno nTruncate, /* Database size after this commit */
4134041470
int isCommit /* True if this is a commit */
4134141471
){
4134241472
int rc; /* Return code */
41473
+ int nList; /* Number of pages in pList */
4134341474
#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
4134441475
PgHdr *p; /* For looping over pages */
4134541476
#endif
4134641477
4134741478
assert( pPager->pWal );
@@ -41351,22 +41482,30 @@
4135141482
for(p=pList; p && p->pDirty; p=p->pDirty){
4135241483
assert( p->pgno < p->pDirty->pgno );
4135341484
}
4135441485
#endif
4135541486
41487
+ assert( pList->pDirty==0 || isCommit );
4135641488
if( isCommit ){
4135741489
/* If a WAL transaction is being committed, there is no point in writing
4135841490
** any pages with page numbers greater than nTruncate into the WAL file.
4135941491
** They will never be read by any client. So remove them from the pDirty
4136041492
** list here. */
4136141493
PgHdr *p;
4136241494
PgHdr **ppNext = &pList;
41495
+ nList = 0;
4136341496
for(p=pList; (*ppNext = p); p=p->pDirty){
41364
- if( p->pgno<=nTruncate ) ppNext = &p->pDirty;
41497
+ if( p->pgno<=nTruncate ){
41498
+ ppNext = &p->pDirty;
41499
+ nList++;
41500
+ }
4136541501
}
4136641502
assert( pList );
41503
+ }else{
41504
+ nList = 1;
4136741505
}
41506
+ pPager->aStat[PAGER_STAT_WRITE] += nList;
4136841507
4136941508
if( pList->pgno==1 ) pager_write_changecounter(pList);
4137041509
rc = sqlite3WalFrames(pPager->pWal,
4137141510
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
4137241511
);
@@ -42430,19 +42569,19 @@
4243042569
memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
4243142570
}
4243242571
if( pgno>pPager->dbFileSize ){
4243342572
pPager->dbFileSize = pgno;
4243442573
}
42574
+ pPager->aStat[PAGER_STAT_WRITE]++;
4243542575
4243642576
/* Update any backup objects copying the contents of this pager. */
4243742577
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
4243842578
4243942579
PAGERTRACE(("STORE %d page %d hash(%08x)\n",
4244042580
PAGERID(pPager), pgno, pager_pagehash(pList)));
4244142581
IOTRACE(("PGOUT %p %d\n", pPager, pgno));
4244242582
PAGER_INCR(sqlite3_pager_writedb_count);
42443
- PAGER_INCR(pPager->nWrite);
4244442583
}else{
4244542584
PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
4244642585
}
4244742586
pager_set_pagehash(pList);
4244842587
pList = pList->pDirty;
@@ -43396,11 +43535,11 @@
4339643535
4339743536
if( (*ppPage)->pPager && !noContent ){
4339843537
/* In this case the pcache already contains an initialized copy of
4339943538
** the page. Return without further ado. */
4340043539
assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
43401
- pPager->nHit++;
43540
+ pPager->aStat[PAGER_STAT_HIT]++;
4340243541
return SQLITE_OK;
4340343542
4340443543
}else{
4340543544
/* The pager cache has created a new page. Its content needs to
4340643545
** be initialized. */
@@ -43438,11 +43577,11 @@
4343843577
}
4343943578
memset(pPg->pData, 0, pPager->pageSize);
4344043579
IOTRACE(("ZERO %p %d\n", pPager, pgno));
4344143580
}else{
4344243581
assert( pPg->pPager==pPager );
43443
- pPager->nMiss++;
43582
+ pPager->aStat[PAGER_STAT_MISS]++;
4344443583
rc = readDbPage(pPg);
4344543584
if( rc!=SQLITE_OK ){
4344643585
goto pager_acquire_err;
4344743586
}
4344843587
}
@@ -44023,10 +44162,11 @@
4402344162
const void *zBuf;
4402444163
assert( pPager->dbFileSize>0 );
4402544164
CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
4402644165
if( rc==SQLITE_OK ){
4402744166
rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
44167
+ pPager->aStat[PAGER_STAT_WRITE]++;
4402844168
}
4402944169
if( rc==SQLITE_OK ){
4403044170
pPager->changeCountDone = 1;
4403144171
}
4403244172
}else{
@@ -44466,15 +44606,15 @@
4446644606
a[1] = sqlite3PcachePagecount(pPager->pPCache);
4446744607
a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
4446844608
a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
4446944609
a[4] = pPager->eState;
4447044610
a[5] = pPager->errCode;
44471
- a[6] = pPager->nHit;
44472
- a[7] = pPager->nMiss;
44611
+ a[6] = pPager->aStat[PAGER_STAT_HIT];
44612
+ a[7] = pPager->aStat[PAGER_STAT_MISS];
4447344613
a[8] = 0; /* Used to be pPager->nOvfl */
4447444614
a[9] = pPager->nRead;
44475
- a[10] = pPager->nWrite;
44615
+ a[10] = pPager->aStat[PAGER_STAT_WRITE];
4447644616
return a;
4447744617
}
4447844618
#endif
4447944619
4448044620
/*
@@ -44483,24 +44623,23 @@
4448344623
** current cache hit or miss count, according to the value of eStat. If the
4448444624
** reset parameter is non-zero, the cache hit or miss count is zeroed before
4448544625
** returning.
4448644626
*/
4448744627
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
44488
- int *piStat;
4448944628
4449044629
assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
4449144630
|| eStat==SQLITE_DBSTATUS_CACHE_MISS
44631
+ || eStat==SQLITE_DBSTATUS_CACHE_WRITE
4449244632
);
44493
- if( eStat==SQLITE_DBSTATUS_CACHE_HIT ){
44494
- piStat = &pPager->nHit;
44495
- }else{
44496
- piStat = &pPager->nMiss;
44497
- }
4449844633
44499
- *pnVal += *piStat;
44634
+ assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
44635
+ assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
44636
+ assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
44637
+
44638
+ *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
4450044639
if( reset ){
44501
- *piStat = 0;
44640
+ pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
4450244641
}
4450344642
}
4450444643
4450544644
/*
4450644645
** Return true if this is an in-memory pager.
@@ -45237,10 +45376,24 @@
4523745376
pPager->pWal = 0;
4523845377
}
4523945378
}
4524045379
return rc;
4524145380
}
45381
+
45382
+#ifdef SQLITE_ENABLE_ZIPVFS
45383
+/*
45384
+** A read-lock must be held on the pager when this function is called. If
45385
+** the pager is in WAL mode and the WAL file currently contains one or more
45386
+** frames, return the size in bytes of the page images stored within the
45387
+** WAL frames. Otherwise, if this is not a WAL database or the WAL file
45388
+** is empty, return 0.
45389
+*/
45390
+SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
45391
+ assert( pPager->eState==PAGER_READER );
45392
+ return sqlite3WalFramesize(pPager->pWal);
45393
+}
45394
+#endif
4524245395
4524345396
#ifdef SQLITE_HAS_CODEC
4524445397
/*
4524545398
** This function is called by the wal module when writing page content
4524645399
** into the log file.
@@ -47657,11 +47810,11 @@
4765747810
testcase( sz<=32768 );
4765847811
testcase( sz>=65536 );
4765947812
iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
4766047813
*pInWal = 1;
4766147814
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
47662
- return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
47815
+ return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
4766347816
}
4766447817
4766547818
*pInWal = 0;
4766647819
return SQLITE_OK;
4766747820
}
@@ -48327,10 +48480,22 @@
4832748480
** WAL module is using shared-memory, return false.
4832848481
*/
4832948482
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
4833048483
return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
4833148484
}
48485
+
48486
+#ifdef SQLITE_ENABLE_ZIPVFS
48487
+/*
48488
+** If the argument is not NULL, it points to a Wal object that holds a
48489
+** read-lock. This function returns the database page-size if it is known,
48490
+** or zero if it is not (or if pWal is NULL).
48491
+*/
48492
+SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
48493
+ assert( pWal==0 || pWal->readLock>=0 );
48494
+ return (pWal ? pWal->szPage : 0);
48495
+}
48496
+#endif
4833248497
4833348498
#endif /* #ifndef SQLITE_OMIT_WAL */
4833448499
4833548500
/************** End of wal.c *************************************************/
4833648501
/************** Begin file btmutex.c *****************************************/
@@ -51320,11 +51485,11 @@
5132051485
5132151486
/* Rollback any active transaction and free the handle structure.
5132251487
** The call to sqlite3BtreeRollback() drops any table-locks held by
5132351488
** this handle.
5132451489
*/
51325
- sqlite3BtreeRollback(p);
51490
+ sqlite3BtreeRollback(p, SQLITE_OK);
5132651491
sqlite3BtreeLeave(p);
5132751492
5132851493
/* If there are still other outstanding references to the shared-btree
5132951494
** structure, return now. The remainder of this procedure cleans
5133051495
** up the shared-btree.
@@ -52558,10 +52723,11 @@
5255852723
** save the state of the cursor. The cursor must be
5255952724
** invalidated.
5256052725
*/
5256152726
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
5256252727
BtCursor *p;
52728
+ if( pBtree==0 ) return;
5256352729
sqlite3BtreeEnter(pBtree);
5256452730
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
5256552731
int i;
5256652732
sqlite3BtreeClearCursor(p);
5256752733
p->eState = CURSOR_FAULT;
@@ -52581,29 +52747,24 @@
5258152747
** in an error.
5258252748
**
5258352749
** This will release the write lock on the database file. If there
5258452750
** are no active cursors, it also releases the read lock.
5258552751
*/
52586
-SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){
52752
+SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
5258752753
int rc;
5258852754
BtShared *pBt = p->pBt;
5258952755
MemPage *pPage1;
5259052756
5259152757
sqlite3BtreeEnter(p);
52592
- rc = saveAllCursors(pBt, 0, 0);
52593
-#ifndef SQLITE_OMIT_SHARED_CACHE
52594
- if( rc!=SQLITE_OK ){
52595
- /* This is a horrible situation. An IO or malloc() error occurred whilst
52596
- ** trying to save cursor positions. If this is an automatic rollback (as
52597
- ** the result of a constraint, malloc() failure or IO error) then
52598
- ** the cache may be internally inconsistent (not contain valid trees) so
52599
- ** we cannot simply return the error to the caller. Instead, abort
52600
- ** all queries that may be using any of the cursors that failed to save.
52601
- */
52602
- sqlite3BtreeTripAllCursors(p, rc);
52603
- }
52604
-#endif
52758
+ if( tripCode==SQLITE_OK ){
52759
+ rc = tripCode = saveAllCursors(pBt, 0, 0);
52760
+ }else{
52761
+ rc = SQLITE_OK;
52762
+ }
52763
+ if( tripCode ){
52764
+ sqlite3BtreeTripAllCursors(p, tripCode);
52765
+ }
5260552766
btreeIntegrity(p);
5260652767
5260752768
if( p->inTrans==TRANS_WRITE ){
5260852769
int rc2;
5260952770
@@ -56072,17 +56233,10 @@
5607256233
** keys with no associated data. If the cursor was opened expecting an
5607356234
** intkey table, the caller should be inserting integer keys with a
5607456235
** blob of associated data. */
5607556236
assert( (pKey==0)==(pCur->pKeyInfo==0) );
5607656237
56077
- /* If this is an insert into a table b-tree, invalidate any incrblob
56078
- ** cursors open on the row being replaced (assuming this is a replace
56079
- ** operation - if it is not, the following is a no-op). */
56080
- if( pCur->pKeyInfo==0 ){
56081
- invalidateIncrblobCursors(p, nKey, 0);
56082
- }
56083
-
5608456238
/* Save the positions of any other cursors open on this table.
5608556239
**
5608656240
** In some cases, the call to btreeMoveto() below is a no-op. For
5608756241
** example, when inserting data into a table with auto-generated integer
5608856242
** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
@@ -56092,10 +56246,18 @@
5609256246
** doing any work. To avoid thwarting these optimizations, it is important
5609356247
** not to clear the cursor here.
5609456248
*/
5609556249
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
5609656250
if( rc ) return rc;
56251
+
56252
+ /* If this is an insert into a table b-tree, invalidate any incrblob
56253
+ ** cursors open on the row being replaced (assuming this is a replace
56254
+ ** operation - if it is not, the following is a no-op). */
56255
+ if( pCur->pKeyInfo==0 ){
56256
+ invalidateIncrblobCursors(p, nKey, 0);
56257
+ }
56258
+
5609756259
if( !loc ){
5609856260
rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
5609956261
if( rc ) return rc;
5610056262
}
5610156263
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
@@ -56202,16 +56364,10 @@
5620256364
|| NEVER(pCur->eState!=CURSOR_VALID)
5620356365
){
5620456366
return SQLITE_ERROR; /* Something has gone awry. */
5620556367
}
5620656368
56207
- /* If this is a delete operation to remove a row from a table b-tree,
56208
- ** invalidate any incrblob cursors open on the row being deleted. */
56209
- if( pCur->pKeyInfo==0 ){
56210
- invalidateIncrblobCursors(p, pCur->info.nKey, 0);
56211
- }
56212
-
5621356369
iCellDepth = pCur->iPage;
5621456370
iCellIdx = pCur->aiIdx[iCellDepth];
5621556371
pPage = pCur->apPage[iCellDepth];
5621656372
pCell = findCell(pPage, iCellIdx);
5621756373
@@ -56233,10 +56389,17 @@
5623356389
** deleted writable. Then free any overflow pages associated with the
5623456390
** entry and finally remove the cell itself from within the page.
5623556391
*/
5623656392
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
5623756393
if( rc ) return rc;
56394
+
56395
+ /* If this is a delete operation to remove a row from a table b-tree,
56396
+ ** invalidate any incrblob cursors open on the row being deleted. */
56397
+ if( pCur->pKeyInfo==0 ){
56398
+ invalidateIncrblobCursors(p, pCur->info.nKey, 0);
56399
+ }
56400
+
5623856401
rc = sqlite3PagerWrite(pPage->pDbPage);
5623956402
if( rc ) return rc;
5624056403
rc = clearCell(pPage, pCell);
5624156404
dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc);
5624256405
if( rc ) return rc;
@@ -56514,17 +56677,17 @@
5651456677
int rc;
5651556678
BtShared *pBt = p->pBt;
5651656679
sqlite3BtreeEnter(p);
5651756680
assert( p->inTrans==TRANS_WRITE );
5651856681
56519
- /* Invalidate all incrblob cursors open on table iTable (assuming iTable
56520
- ** is the root of a table b-tree - if it is not, the following call is
56521
- ** a no-op). */
56522
- invalidateIncrblobCursors(p, 0, 1);
56523
-
5652456682
rc = saveAllCursors(pBt, (Pgno)iTable, 0);
56683
+
5652556684
if( SQLITE_OK==rc ){
56685
+ /* Invalidate all incrblob cursors open on table iTable (assuming iTable
56686
+ ** is the root of a table b-tree - if it is not, the following call is
56687
+ ** a no-op). */
56688
+ invalidateIncrblobCursors(p, 0, 1);
5652656689
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
5652756690
}
5652856691
sqlite3BtreeLeave(p);
5652956692
return rc;
5653056693
}
@@ -58121,11 +58284,11 @@
5812158284
}
5812258285
*pp = p->pNext;
5812358286
}
5812458287
5812558288
/* If a transaction is still open on the Btree, roll it back. */
58126
- sqlite3BtreeRollback(p->pDest);
58289
+ sqlite3BtreeRollback(p->pDest, SQLITE_OK);
5812758290
5812858291
/* Set the error code of the destination database handle. */
5812958292
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
5813058293
sqlite3Error(p->pDestDb, rc, 0);
5813158294
@@ -58332,14 +58495,14 @@
5833258495
5833358496
/*
5833458497
** Make sure pMem->z points to a writable allocation of at least
5833558498
** n bytes.
5833658499
**
58337
-** If the memory cell currently contains string or blob data
58338
-** and the third argument passed to this function is true, the
58339
-** current content of the cell is preserved. Otherwise, it may
58340
-** be discarded.
58500
+** If the third argument passed to this function is true, then memory
58501
+** cell pMem must contain a string or blob. In this case the content is
58502
+** preserved. Otherwise, if the third parameter to this function is false,
58503
+** any current string or blob value may be discarded.
5834158504
**
5834258505
** This function sets the MEM_Dyn flag and clears any xDel callback.
5834358506
** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
5834458507
** not set, Mem.n is zeroed.
5834558508
*/
@@ -58349,10 +58512,14 @@
5834958512
(((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
5835058513
((pMem->flags&MEM_Ephem) ? 1 : 0) +
5835158514
((pMem->flags&MEM_Static) ? 1 : 0)
5835258515
);
5835358516
assert( (pMem->flags&MEM_RowSet)==0 );
58517
+
58518
+ /* If the preserve flag is set to true, then the memory cell must already
58519
+ ** contain a valid string or blob value. */
58520
+ assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
5835458521
5835558522
if( n<32 ) n = 32;
5835658523
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
5835758524
if( preserve && pMem->z==pMem->zMalloc ){
5835858525
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
@@ -60668,11 +60835,11 @@
6066860835
int nByte = (nSub+1)*sizeof(SubProgram*);
6066960836
int j;
6067060837
for(j=0; j<nSub; j++){
6067160838
if( apSub[j]==pOp->p4.pProgram ) break;
6067260839
}
60673
- if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){
60840
+ if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){
6067460841
apSub = (SubProgram **)pSub->z;
6067560842
apSub[nSub++] = pOp->p4.pProgram;
6067660843
pSub->flags |= MEM_Blob;
6067760844
pSub->n = nSub*sizeof(SubProgram*);
6067860845
}
@@ -61431,36 +61598,10 @@
6143161598
}
6143261599
#else
6143361600
#define checkActiveVdbeCnt(x)
6143461601
#endif
6143561602
61436
-/*
61437
-** For every Btree that in database connection db which
61438
-** has been modified, "trip" or invalidate each cursor in
61439
-** that Btree might have been modified so that the cursor
61440
-** can never be used again. This happens when a rollback
61441
-*** occurs. We have to trip all the other cursors, even
61442
-** cursor from other VMs in different database connections,
61443
-** so that none of them try to use the data at which they
61444
-** were pointing and which now may have been changed due
61445
-** to the rollback.
61446
-**
61447
-** Remember that a rollback can delete tables complete and
61448
-** reorder rootpages. So it is not sufficient just to save
61449
-** the state of the cursor. We have to invalidate the cursor
61450
-** so that it is never used again.
61451
-*/
61452
-static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){
61453
- int i;
61454
- for(i=0; i<db->nDb; i++){
61455
- Btree *p = db->aDb[i].pBt;
61456
- if( p && sqlite3BtreeIsInTrans(p) ){
61457
- sqlite3BtreeTripAllCursors(p, SQLITE_ABORT);
61458
- }
61459
- }
61460
-}
61461
-
6146261603
/*
6146361604
** If the Vdbe passed as the first argument opened a statement-transaction,
6146461605
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
6146561606
** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
6146661607
** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
@@ -61621,12 +61762,11 @@
6162161762
eStatementOp = SAVEPOINT_ROLLBACK;
6162261763
}else{
6162361764
/* We are forced to roll back the active transaction. Before doing
6162461765
** so, abort any other statements this handle currently has active.
6162561766
*/
61626
- invalidateCursorsOnModifiedBtrees(db);
61627
- sqlite3RollbackAll(db);
61767
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
6162861768
sqlite3CloseSavepoints(db);
6162961769
db->autoCommit = 1;
6163061770
}
6163161771
}
6163261772
}
@@ -61664,27 +61804,26 @@
6166461804
if( rc==SQLITE_BUSY && p->readOnly ){
6166561805
sqlite3VdbeLeave(p);
6166661806
return SQLITE_BUSY;
6166761807
}else if( rc!=SQLITE_OK ){
6166861808
p->rc = rc;
61669
- sqlite3RollbackAll(db);
61809
+ sqlite3RollbackAll(db, SQLITE_OK);
6167061810
}else{
6167161811
db->nDeferredCons = 0;
6167261812
sqlite3CommitInternalChanges(db);
6167361813
}
6167461814
}else{
61675
- sqlite3RollbackAll(db);
61815
+ sqlite3RollbackAll(db, SQLITE_OK);
6167661816
}
6167761817
db->nStatement = 0;
6167861818
}else if( eStatementOp==0 ){
6167961819
if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
6168061820
eStatementOp = SAVEPOINT_RELEASE;
6168161821
}else if( p->errorAction==OE_Abort ){
6168261822
eStatementOp = SAVEPOINT_ROLLBACK;
6168361823
}else{
61684
- invalidateCursorsOnModifiedBtrees(db);
61685
- sqlite3RollbackAll(db);
61824
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
6168661825
sqlite3CloseSavepoints(db);
6168761826
db->autoCommit = 1;
6168861827
}
6168961828
}
6169061829
@@ -61700,12 +61839,11 @@
6170061839
if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
6170161840
p->rc = rc;
6170261841
sqlite3DbFree(db, p->zErrMsg);
6170361842
p->zErrMsg = 0;
6170461843
}
61705
- invalidateCursorsOnModifiedBtrees(db);
61706
- sqlite3RollbackAll(db);
61844
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
6170761845
sqlite3CloseSavepoints(db);
6170861846
db->autoCommit = 1;
6170961847
}
6171061848
}
6171161849
@@ -66946,10 +67084,15 @@
6694667084
**
6694767085
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
6694867086
** then the cache of the cursor is reset prior to extracting the column.
6694967087
** The first OP_Column against a pseudo-table after the value of the content
6695067088
** register has changed should have this bit set.
67089
+**
67090
+** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
67091
+** the result is guaranteed to only be used as the argument of a length()
67092
+** or typeof() function, respectively. The loading of large blobs can be
67093
+** skipped for length() and all content loading can be skipped for typeof().
6695167094
*/
6695267095
case OP_Column: {
6695367096
#if 0 /* local variables moved into u.an */
6695467097
u32 payloadSize; /* Number of bytes in the record */
6695567098
i64 payloadSize64; /* Number of bytes in the record */
@@ -67088,11 +67231,11 @@
6708867231
u.an.pC->aRow = (u8*)u.an.zData;
6708967232
}else{
6709067233
u.an.pC->aRow = 0;
6709167234
}
6709267235
}
67093
- /* The following assert is true in all cases accept when
67236
+ /* The following assert is true in all cases except when
6709467237
** the database file has been corrupted externally.
6709567238
** assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */
6709667239
u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset);
6709767240
6709867241
/* Make sure a corrupt database has not given us an oversize header.
@@ -67163,15 +67306,15 @@
6716367306
if( u.an.offset<u.an.szField ){ /* True if u.an.offset overflows */
6716467307
u.an.zIdx = &u.an.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
6716567308
break;
6716667309
}
6716767310
}else{
67168
- /* If u.an.i is less that u.an.nField, then there are less fields in this
67311
+ /* If u.an.i is less that u.an.nField, then there are fewer fields in this
6716967312
** record than SetNumColumns indicated there are columns in the
6717067313
** table. Set the u.an.offset for any extra columns not present in
67171
- ** the record to 0. This tells code below to store a NULL
67172
- ** instead of deserializing a value from the record.
67314
+ ** the record to 0. This tells code below to store the default value
67315
+ ** for the column instead of deserializing a value from the record.
6717367316
*/
6717467317
u.an.aOffset[u.an.i] = 0;
6717567318
}
6717667319
}
6717767320
sqlite3VdbeMemRelease(&u.an.sMem);
@@ -67197,21 +67340,36 @@
6719767340
** a pointer to a Mem object.
6719867341
*/
6719967342
if( u.an.aOffset[u.an.p2] ){
6720067343
assert( rc==SQLITE_OK );
6720167344
if( u.an.zRec ){
67345
+ /* This is the common case where the whole row fits on a single page */
6720267346
VdbeMemRelease(u.an.pDest);
6720367347
sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
6720467348
}else{
67205
- u.an.len = sqlite3VdbeSerialTypeLen(u.an.aType[u.an.p2]);
67206
- sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
67207
- rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex, &u.an.sMem);
67208
- if( rc!=SQLITE_OK ){
67209
- goto op_column_out;
67210
- }
67211
- u.an.zData = u.an.sMem.z;
67212
- sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.aType[u.an.p2], u.an.pDest);
67349
+ /* This branch happens only when the row overflows onto multiple pages */
67350
+ u.an.t = u.an.aType[u.an.p2];
67351
+ if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
67352
+ && ((u.an.t>=12 && (u.an.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
67353
+ ){
67354
+ /* Content is irrelevant for the typeof() function and for
67355
+ ** the length(X) function if X is a blob. So we might as well use
67356
+ ** bogus content rather than reading content from disk. NULL works
67357
+ ** for text and blob and whatever is in the u.an.payloadSize64 variable
67358
+ ** will work for everything else. */
67359
+ u.an.zData = u.an.t<12 ? (char*)&u.an.payloadSize64 : 0;
67360
+ }else{
67361
+ u.an.len = sqlite3VdbeSerialTypeLen(u.an.t);
67362
+ sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
67363
+ rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex,
67364
+ &u.an.sMem);
67365
+ if( rc!=SQLITE_OK ){
67366
+ goto op_column_out;
67367
+ }
67368
+ u.an.zData = u.an.sMem.z;
67369
+ }
67370
+ sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.t, u.an.pDest);
6721367371
}
6721467372
u.an.pDest->enc = encoding;
6721567373
}else{
6721667374
if( pOp->p4type==P4_MEM ){
6721767375
sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
@@ -67513,20 +67671,16 @@
6751367671
u.ar.iSavepoint++;
6751467672
}
6751567673
if( !u.ar.pSavepoint ){
6751667674
sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
6751767675
rc = SQLITE_ERROR;
67518
- }else if(
67519
- db->writeVdbeCnt>0 || (u.ar.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1)
67520
- ){
67676
+ }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){
6752167677
/* It is not possible to release (commit) a savepoint if there are
67522
- ** active write statements. It is not possible to rollback a savepoint
67523
- ** if there are any active statements at all.
67678
+ ** active write statements.
6752467679
*/
6752567680
sqlite3SetString(&p->zErrMsg, db,
67526
- "cannot %s savepoint - SQL statements in progress",
67527
- (u.ar.p1==SAVEPOINT_ROLLBACK ? "rollback": "release")
67681
+ "cannot release savepoint - SQL statements in progress"
6752867682
);
6752967683
rc = SQLITE_BUSY;
6753067684
}else{
6753167685
6753267686
/* Determine whether or not this is a transaction savepoint. If so,
@@ -67547,10 +67701,15 @@
6754767701
}
6754867702
db->isTransactionSavepoint = 0;
6754967703
rc = p->rc;
6755067704
}else{
6755167705
u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
67706
+ if( u.ar.p1==SAVEPOINT_ROLLBACK ){
67707
+ for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
67708
+ sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT);
67709
+ }
67710
+ }
6755267711
for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
6755367712
rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
6755467713
if( rc!=SQLITE_OK ){
6755567714
goto abort_due_to_error;
6755667715
}
@@ -67617,29 +67776,32 @@
6761767776
u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit;
6761867777
assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 );
6761967778
assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 );
6762067779
assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
6762167780
67781
+#if 0
6762267782
if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
6762367783
/* If this instruction implements a ROLLBACK and other VMs are
6762467784
** still running, and a transaction is active, return an error indicating
6762567785
** that the other VMs must complete first.
6762667786
*/
6762767787
sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
6762867788
"SQL statements in progress");
6762967789
rc = SQLITE_BUSY;
67630
- }else if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
67790
+ }else
67791
+#endif
67792
+ if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
6763167793
/* If this instruction implements a COMMIT and other VMs are writing
6763267794
** return an error indicating that the other VMs must complete first.
6763367795
*/
6763467796
sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
6763567797
"SQL statements in progress");
6763667798
rc = SQLITE_BUSY;
6763767799
}else if( u.as.desiredAutoCommit!=db->autoCommit ){
6763867800
if( u.as.iRollback ){
6763967801
assert( u.as.desiredAutoCommit==1 );
67640
- sqlite3RollbackAll(db);
67802
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
6764167803
db->autoCommit = 1;
6764267804
}else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
6764367805
goto vdbe_return;
6764467806
}else{
6764567807
db->autoCommit = (u8)u.as.desiredAutoCommit;
@@ -68701,11 +68863,11 @@
6870168863
u.bg.v = 1; /* IMP: R-61914-48074 */
6870268864
}else{
6870368865
assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) );
6870468866
rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v);
6870568867
assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
68706
- if( u.bg.v==MAX_ROWID ){
68868
+ if( u.bg.v>=MAX_ROWID ){
6870768869
u.bg.pC->useRandomRowid = 1;
6870868870
}else{
6870968871
u.bg.v++; /* IMP: R-29538-34987 */
6871068872
}
6871168873
}
@@ -74821,27 +74983,59 @@
7482174983
int op, /* Expression opcode */
7482274984
Expr *pLeft, /* Left operand */
7482374985
Expr *pRight, /* Right operand */
7482474986
const Token *pToken /* Argument token */
7482574987
){
74826
- Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
74827
- sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
74988
+ Expr *p;
74989
+ if( op==TK_AND && pLeft && pRight ){
74990
+ /* Take advantage of short-circuit false optimization for AND */
74991
+ p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
74992
+ }else{
74993
+ p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
74994
+ sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
74995
+ }
7482874996
if( p ) {
7482974997
sqlite3ExprCheckHeight(pParse, p->nHeight);
7483074998
}
7483174999
return p;
7483275000
}
75001
+
75002
+/*
75003
+** Return 1 if an expression must be FALSE in all cases and 0 if the
75004
+** expression might be true. This is an optimization. If is OK to
75005
+** return 0 here even if the expression really is always false (a
75006
+** false negative). But it is a bug to return 1 if the expression
75007
+** might be true in some rare circumstances (a false positive.)
75008
+**
75009
+** Note that if the expression is part of conditional for a
75010
+** LEFT JOIN, then we cannot determine at compile-time whether or not
75011
+** is it true or false, so always return 0.
75012
+*/
75013
+static int exprAlwaysFalse(Expr *p){
75014
+ int v = 0;
75015
+ if( ExprHasProperty(p, EP_FromJoin) ) return 0;
75016
+ if( !sqlite3ExprIsInteger(p, &v) ) return 0;
75017
+ return v==0;
75018
+}
7483375019
7483475020
/*
7483575021
** Join two expressions using an AND operator. If either expression is
7483675022
** NULL, then just return the other expression.
75023
+**
75024
+** If one side or the other of the AND is known to be false, then instead
75025
+** of returning an AND expression, just return a constant expression with
75026
+** a value of false.
7483775027
*/
7483875028
SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
7483975029
if( pLeft==0 ){
7484075030
return pRight;
7484175031
}else if( pRight==0 ){
7484275032
return pLeft;
75033
+ }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
75034
+ sqlite3ExprDelete(db, pLeft);
75035
+ sqlite3ExprDelete(db, pRight);
75036
+ return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
7484375037
}else{
7484475038
Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
7484575039
sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
7484675040
return pNew;
7484775041
}
@@ -76369,19 +76563,10 @@
7636976563
** Actually, the way the column cache is currently used, we are guaranteed
7637076564
** that the object will never already be in cache. Verify this guarantee.
7637176565
*/
7637276566
#ifndef NDEBUG
7637376567
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
76374
-#if 0 /* This code wold remove the entry from the cache if it existed */
76375
- if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
76376
- cacheEntryClear(pParse, p);
76377
- p->iLevel = pParse->iCacheLevel;
76378
- p->iReg = iReg;
76379
- p->lru = pParse->iCacheCnt++;
76380
- return;
76381
- }
76382
-#endif
7638376568
assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
7638476569
}
7638576570
#endif
7638676571
7638776572
/* Find an empty slot and replace it */
@@ -76512,11 +76697,12 @@
7651276697
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
7651376698
Parse *pParse, /* Parsing and code generating context */
7651476699
Table *pTab, /* Description of the table we are reading from */
7651576700
int iColumn, /* Index of the table column */
7651676701
int iTable, /* The cursor pointing to the table */
76517
- int iReg /* Store results here */
76702
+ int iReg, /* Store results here */
76703
+ u8 p5 /* P5 value for OP_Column */
7651876704
){
7651976705
Vdbe *v = pParse->pVdbe;
7652076706
int i;
7652176707
struct yColCache *p;
7652276708
@@ -76527,11 +76713,15 @@
7652776713
return p->iReg;
7652876714
}
7652976715
}
7653076716
assert( v!=0 );
7653176717
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
76532
- sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
76718
+ if( p5 ){
76719
+ sqlite3VdbeChangeP5(v, p5);
76720
+ }else{
76721
+ sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
76722
+ }
7653376723
return iReg;
7653476724
}
7653576725
7653676726
/*
7653776727
** Clear all column cache entries.
@@ -76655,11 +76845,12 @@
7665576845
/* This only happens when coding check constraints */
7665676846
assert( pParse->ckBase>0 );
7665776847
inReg = pExpr->iColumn + pParse->ckBase;
7665876848
}else{
7665976849
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
76660
- pExpr->iColumn, pExpr->iTable, target);
76850
+ pExpr->iColumn, pExpr->iTable, target,
76851
+ pExpr->op2);
7666176852
}
7666276853
break;
7666376854
}
7666476855
case TK_INTEGER: {
7666576856
codeInteger(pParse, pExpr, 0, target);
@@ -76932,10 +77123,29 @@
7693277123
}
7693377124
7693477125
7693577126
if( pFarg ){
7693677127
r1 = sqlite3GetTempRange(pParse, nFarg);
77128
+
77129
+ /* For length() and typeof() functions with a column argument,
77130
+ ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
77131
+ ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
77132
+ ** loading.
77133
+ */
77134
+ if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
77135
+ u8 exprOp;
77136
+ assert( nFarg==1 );
77137
+ assert( pFarg->a[0].pExpr!=0 );
77138
+ exprOp = pFarg->a[0].pExpr->op;
77139
+ if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
77140
+ assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
77141
+ assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
77142
+ testcase( pDef->flags==SQLITE_FUNC_LENGTH );
77143
+ pFarg->a[0].pExpr->op2 = pDef->flags;
77144
+ }
77145
+ }
77146
+
7693777147
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
7693877148
sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
7693977149
sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
7694077150
}else{
7694177151
r1 = 0;
@@ -80137,10 +80347,11 @@
8013780347
Index *pPrevIdx = 0; /* Previous index in the loop */
8013880348
int idx = 0; /* slot in pIdx->aSample[] for next sample */
8013980349
int eType; /* Datatype of a sample */
8014080350
IndexSample *pSample; /* A slot in pIdx->aSample[] */
8014180351
80352
+ assert( db->lookaside.bEnabled==0 );
8014280353
if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
8014380354
return SQLITE_OK;
8014480355
}
8014580356
8014680357
zSql = sqlite3MPrintf(db,
@@ -80163,11 +80374,11 @@
8016380374
nSample = sqlite3_column_int(pStmt, 1);
8016480375
pIdx = sqlite3FindIndex(db, zIndex, zDb);
8016580376
if( pIdx==0 ) continue;
8016680377
assert( pIdx->nSample==0 );
8016780378
pIdx->nSample = nSample;
80168
- pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) );
80379
+ pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
8016980380
pIdx->avgEq = pIdx->aiRowEst[1];
8017080381
if( pIdx->aSample==0 ){
8017180382
db->mallocFailed = 1;
8017280383
sqlite3_finalize(pStmt);
8017380384
return SQLITE_NOMEM;
@@ -80236,11 +80447,11 @@
8023680447
int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
8023780448
pSample->nByte = n;
8023880449
if( n < 1){
8023980450
pSample->u.z = 0;
8024080451
}else{
80241
- pSample->u.z = sqlite3Malloc(n);
80452
+ pSample->u.z = sqlite3DbMallocRaw(db, n);
8024280453
if( pSample->u.z==0 ){
8024380454
db->mallocFailed = 1;
8024480455
sqlite3_finalize(pStmt);
8024580456
return SQLITE_NOMEM;
8024680457
}
@@ -80312,11 +80523,14 @@
8031280523
8031380524
8031480525
/* Load the statistics from the sqlite_stat3 table. */
8031580526
#ifdef SQLITE_ENABLE_STAT3
8031680527
if( rc==SQLITE_OK ){
80528
+ int lookasideEnabled = db->lookaside.bEnabled;
80529
+ db->lookaside.bEnabled = 0;
8031780530
rc = loadStat3(db, sInfo.zDatabase);
80531
+ db->lookaside.bEnabled = lookasideEnabled;
8031880532
}
8031980533
#endif
8032080534
8032180535
if( rc==SQLITE_NOMEM ){
8032280536
db->mallocFailed = 1;
@@ -81675,11 +81889,11 @@
8167581889
sqliteDeleteColumnNames(db, pTable);
8167681890
sqlite3DbFree(db, pTable->zName);
8167781891
sqlite3DbFree(db, pTable->zColAff);
8167881892
sqlite3SelectDelete(db, pTable->pSelect);
8167981893
#ifndef SQLITE_OMIT_CHECK
81680
- sqlite3ExprDelete(db, pTable->pCheck);
81894
+ sqlite3ExprListDelete(db, pTable->pCheck);
8168181895
#endif
8168281896
#ifndef SQLITE_OMIT_VIRTUALTABLE
8168381897
sqlite3VtabClear(db, pTable);
8168481898
#endif
8168581899
sqlite3DbFree(db, pTable);
@@ -82338,19 +82552,21 @@
8233882552
*/
8233982553
SQLITE_PRIVATE void sqlite3AddCheckConstraint(
8234082554
Parse *pParse, /* Parsing context */
8234182555
Expr *pCheckExpr /* The check expression */
8234282556
){
82343
- sqlite3 *db = pParse->db;
8234482557
#ifndef SQLITE_OMIT_CHECK
8234582558
Table *pTab = pParse->pNewTable;
8234682559
if( pTab && !IN_DECLARE_VTAB ){
82347
- pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr);
82560
+ pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
82561
+ if( pParse->constraintName.n ){
82562
+ sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
82563
+ }
8234882564
}else
8234982565
#endif
8235082566
{
82351
- sqlite3ExprDelete(db, pCheckExpr);
82567
+ sqlite3ExprDelete(pParse->db, pCheckExpr);
8235282568
}
8235382569
}
8235482570
8235582571
/*
8235682572
** Set the collation function of the most recently parsed table column
@@ -82616,10 +82832,12 @@
8261682832
/* Resolve names in all CHECK constraint expressions.
8261782833
*/
8261882834
if( p->pCheck ){
8261982835
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
8262082836
NameContext sNC; /* Name context for pParse->pNewTable */
82837
+ ExprList *pList; /* List of all CHECK constraints */
82838
+ int i; /* Loop counter */
8262182839
8262282840
memset(&sNC, 0, sizeof(sNC));
8262382841
memset(&sSrc, 0, sizeof(sSrc));
8262482842
sSrc.nSrc = 1;
8262582843
sSrc.a[0].zName = p->zName;
@@ -82626,12 +82844,15 @@
8262682844
sSrc.a[0].pTab = p;
8262782845
sSrc.a[0].iCursor = -1;
8262882846
sNC.pParse = pParse;
8262982847
sNC.pSrcList = &sSrc;
8263082848
sNC.isCheck = 1;
82631
- if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
82632
- return;
82849
+ pList = p->pCheck;
82850
+ for(i=0; i<pList->nExpr; i++){
82851
+ if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
82852
+ return;
82853
+ }
8263382854
}
8263482855
}
8263582856
#endif /* !defined(SQLITE_OMIT_CHECK) */
8263682857
8263782858
/* If the db->init.busy is 1 it means we are reading the SQL off the
@@ -84178,23 +84399,25 @@
8417884399
exit_drop_index:
8417984400
sqlite3SrcListDelete(db, pName);
8418084401
}
8418184402
8418284403
/*
84183
-** pArray is a pointer to an array of objects. Each object in the
84184
-** array is szEntry bytes in size. This routine allocates a new
84185
-** object on the end of the array.
84186
-**
84187
-** *pnEntry is the number of entries already in use. *pnAlloc is
84188
-** the previously allocated size of the array. initSize is the
84189
-** suggested initial array size allocation.
84190
-**
84191
-** The index of the new entry is returned in *pIdx.
84192
-**
84193
-** This routine returns a pointer to the array of objects. This
84194
-** might be the same as the pArray parameter or it might be a different
84195
-** pointer if the array was resized.
84404
+** pArray is a pointer to an array of objects. Each object in the
84405
+** array is szEntry bytes in size. This routine uses sqlite3DbRealloc()
84406
+** to extend the array so that there is space for a new object at the end.
84407
+**
84408
+** When this function is called, *pnEntry contains the current size of
84409
+** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes
84410
+** in total).
84411
+**
84412
+** If the realloc() is successful (i.e. if no OOM condition occurs), the
84413
+** space allocated for the new object is zeroed, *pnEntry updated to
84414
+** reflect the new size of the array and a pointer to the new allocation
84415
+** returned. *pIdx is set to the index of the new array entry in this case.
84416
+**
84417
+** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains
84418
+** unchanged and a copy of pArray returned.
8419684419
*/
8419784420
SQLITE_PRIVATE void *sqlite3ArrayAllocate(
8419884421
sqlite3 *db, /* Connection to notify of malloc failures */
8419984422
void *pArray, /* Array of objects. Might be reallocated */
8420084423
int szEntry, /* Size of each object in the array */
@@ -85787,11 +86010,11 @@
8578786010
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
8578886011
pWInfo = sqlite3WhereBegin(
8578986012
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
8579086013
);
8579186014
if( pWInfo==0 ) goto delete_from_cleanup;
85792
- regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
86015
+ regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
8579386016
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
8579486017
if( db->flags & SQLITE_CountRows ){
8579586018
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
8579686019
}
8579786020
sqlite3WhereEnd(pWInfo);
@@ -87607,12 +87830,12 @@
8760787830
FUNCTION(min, 0, 0, 1, 0 ),
8760887831
AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
8760987832
FUNCTION(max, -1, 1, 1, minmaxFunc ),
8761087833
FUNCTION(max, 0, 1, 1, 0 ),
8761187834
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
87612
- FUNCTION(typeof, 1, 0, 0, typeofFunc ),
87613
- FUNCTION(length, 1, 0, 0, lengthFunc ),
87835
+ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
87836
+ FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
8761487837
FUNCTION(substr, 2, 0, 0, substrFunc ),
8761587838
FUNCTION(substr, 3, 0, 0, substrFunc ),
8761687839
FUNCTION(abs, 1, 0, 0, absFunc ),
8761787840
#ifndef SQLITE_OMIT_FLOATING_POINT
8761887841
FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -87620,15 +87843,13 @@
8762087843
#endif
8762187844
FUNCTION(upper, 1, 0, 0, upperFunc ),
8762287845
FUNCTION(lower, 1, 0, 0, lowerFunc ),
8762387846
FUNCTION(coalesce, 1, 0, 0, 0 ),
8762487847
FUNCTION(coalesce, 0, 0, 0, 0 ),
87625
-/* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */
87626
- {-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0},
87848
+ FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
8762787849
FUNCTION(hex, 1, 0, 0, hexFunc ),
87628
-/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
87629
- {2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0},
87850
+ FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
8763087851
FUNCTION(random, 0, 0, 0, randomFunc ),
8763187852
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
8763287853
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
8763387854
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
8763487855
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -90061,13 +90282,15 @@
9006190282
int j1; /* Addresss of jump instruction */
9006290283
int j2 = 0, j3; /* Addresses of jump instructions */
9006390284
int regData; /* Register containing first data column */
9006490285
int iCur; /* Table cursor number */
9006590286
Index *pIdx; /* Pointer to one of the indices */
90287
+ sqlite3 *db; /* Database connection */
9006690288
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
9006790289
int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
9006890290
90291
+ db = pParse->db;
9006990292
v = sqlite3GetVdbe(pParse);
9007090293
assert( v!=0 );
9007190294
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
9007290295
nCol = pTab->nCol;
9007390296
regData = regRowid + 1;
@@ -90096,11 +90319,11 @@
9009690319
case OE_Rollback:
9009790320
case OE_Fail: {
9009890321
char *zMsg;
9009990322
sqlite3VdbeAddOp3(v, OP_HaltIfNull,
9010090323
SQLITE_CONSTRAINT, onError, regData+i);
90101
- zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL",
90324
+ zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
9010290325
pTab->zName, pTab->aCol[i].zName);
9010390326
sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
9010490327
break;
9010590328
}
9010690329
case OE_Ignore: {
@@ -90118,22 +90341,31 @@
9011890341
}
9011990342
9012090343
/* Test all CHECK constraints
9012190344
*/
9012290345
#ifndef SQLITE_OMIT_CHECK
90123
- if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
90124
- int allOk = sqlite3VdbeMakeLabel(v);
90346
+ if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
90347
+ ExprList *pCheck = pTab->pCheck;
9012590348
pParse->ckBase = regData;
90126
- sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL);
9012790349
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
90128
- if( onError==OE_Ignore ){
90129
- sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
90130
- }else{
90131
- if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
90132
- sqlite3HaltConstraint(pParse, onError, 0, 0);
90350
+ for(i=0; i<pCheck->nExpr; i++){
90351
+ int allOk = sqlite3VdbeMakeLabel(v);
90352
+ sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
90353
+ if( onError==OE_Ignore ){
90354
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
90355
+ }else{
90356
+ char *zConsName = pCheck->a[i].zName;
90357
+ if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
90358
+ if( zConsName ){
90359
+ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
90360
+ }else{
90361
+ zConsName = 0;
90362
+ }
90363
+ sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
90364
+ }
90365
+ sqlite3VdbeResolveLabel(v, allOk);
9013390366
}
90134
- sqlite3VdbeResolveLabel(v, allOk);
9013590367
}
9013690368
#endif /* !defined(SQLITE_OMIT_CHECK) */
9013790369
9013890370
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
9013990371
** of the new record does not previously exist. Except, if this
@@ -90185,11 +90417,11 @@
9018590417
**
9018690418
** to run without a statement journal if there are no indexes on the
9018790419
** table.
9018890420
*/
9018990421
Trigger *pTrigger = 0;
90190
- if( pParse->db->flags&SQLITE_RecTriggers ){
90422
+ if( db->flags&SQLITE_RecTriggers ){
9019190423
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
9019290424
}
9019390425
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
9019490426
sqlite3MultiWrite(pParse);
9019590427
sqlite3GenerateRowDelete(
@@ -90274,11 +90506,11 @@
9027490506
StrAccum errMsg;
9027590507
const char *zSep;
9027690508
char *zErr;
9027790509
9027890510
sqlite3StrAccumInit(&errMsg, 0, 0, 200);
90279
- errMsg.db = pParse->db;
90511
+ errMsg.db = db;
9028090512
zSep = pIdx->nColumn>1 ? "columns " : "column ";
9028190513
for(j=0; j<pIdx->nColumn; j++){
9028290514
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
9028390515
sqlite3StrAccumAppend(&errMsg, zSep, -1);
9028490516
zSep = ", ";
@@ -90298,11 +90530,11 @@
9029890530
}
9029990531
default: {
9030090532
Trigger *pTrigger = 0;
9030190533
assert( onError==OE_Replace );
9030290534
sqlite3MultiWrite(pParse);
90303
- if( pParse->db->flags&SQLITE_RecTriggers ){
90535
+ if( db->flags&SQLITE_RecTriggers ){
9030490536
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
9030590537
}
9030690538
sqlite3GenerateRowDelete(
9030790539
pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
9030890540
);
@@ -90628,11 +90860,11 @@
9062890860
if( pSrcIdx==0 ){
9062990861
return 0; /* pDestIdx has no corresponding index in pSrc */
9063090862
}
9063190863
}
9063290864
#ifndef SQLITE_OMIT_CHECK
90633
- if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
90865
+ if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
9063490866
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
9063590867
}
9063690868
#endif
9063790869
#ifndef SQLITE_OMIT_FOREIGN_KEY
9063890870
/* Disallow the transfer optimization if the destination table constains
@@ -92317,13 +92549,16 @@
9231792549
char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */
9231892550
char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */
9231992551
const char *zDb = 0; /* The database name */
9232092552
Token *pId; /* Pointer to <id> token */
9232192553
int iDb; /* Database index for <database> */
92322
- sqlite3 *db = pParse->db;
92323
- Db *pDb;
92324
- Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
92554
+ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
92555
+ int rc; /* return value form SQLITE_FCNTL_PRAGMA */
92556
+ sqlite3 *db = pParse->db; /* The database connection */
92557
+ Db *pDb; /* The specific database being pragmaed */
92558
+ Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */
92559
+
9232592560
if( v==0 ) return;
9232692561
sqlite3VdbeRunOnlyOnce(v);
9232792562
pParse->nMem = 2;
9232892563
9232992564
/* Interpret the [database.] part of the pragma statement. iDb is the
@@ -92350,10 +92585,38 @@
9235092585
assert( pId2 );
9235192586
zDb = pId2->n>0 ? pDb->zName : 0;
9235292587
if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
9235392588
goto pragma_out;
9235492589
}
92590
+
92591
+ /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
92592
+ ** connection. If it returns SQLITE_OK, then assume that the VFS
92593
+ ** handled the pragma and generate a no-op prepared statement.
92594
+ */
92595
+ aFcntl[0] = 0;
92596
+ aFcntl[1] = zLeft;
92597
+ aFcntl[2] = zRight;
92598
+ aFcntl[3] = 0;
92599
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
92600
+ if( rc==SQLITE_OK ){
92601
+ if( aFcntl[0] ){
92602
+ int mem = ++pParse->nMem;
92603
+ sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
92604
+ sqlite3VdbeSetNumCols(v, 1);
92605
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
92606
+ sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
92607
+ sqlite3_free(aFcntl[0]);
92608
+ }
92609
+ }else if( rc!=SQLITE_NOTFOUND ){
92610
+ if( aFcntl[0] ){
92611
+ sqlite3ErrorMsg(pParse, "%s", aFcntl[0]);
92612
+ sqlite3_free(aFcntl[0]);
92613
+ }
92614
+ pParse->nErr++;
92615
+ pParse->rc = rc;
92616
+ }else
92617
+
9235592618
9235692619
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
9235792620
/*
9235892621
** PRAGMA [database.]default_cache_size
9235992622
** PRAGMA [database.]default_cache_size=N
@@ -92637,11 +92900,11 @@
9263792900
/* Call SetAutoVacuum() to set initialize the internal auto and
9263892901
** incr-vacuum flags. This is required in case this connection
9263992902
** creates the database file. It is important that it is created
9264092903
** as an auto-vacuum capable db.
9264192904
*/
92642
- int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
92905
+ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
9264392906
if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
9264492907
/* When setting the auto_vacuum mode to either "full" or
9264592908
** "incremental", write the value of meta[6] in the database
9264692909
** file. Before writing to meta[6], check that meta[3] indicates
9264792910
** that this really is an auto-vacuum capable database.
@@ -92755,11 +93018,10 @@
9275593018
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
9275693019
}
9275793020
}else{
9275893021
#ifndef SQLITE_OMIT_WSD
9275993022
if( zRight[0] ){
92760
- int rc;
9276193023
int res;
9276293024
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
9276393025
if( rc!=SQLITE_OK || res==0 ){
9276493026
sqlite3ErrorMsg(pParse, "not a writable directory");
9276593027
goto pragma_out;
@@ -95671,13 +95933,21 @@
9567195933
int nCol; /* Number of columns in the result set */
9567295934
Expr *p; /* Expression for a single result column */
9567395935
char *zName; /* Column name */
9567495936
int nName; /* Size of name in zName[] */
9567595937
95676
- *pnCol = nCol = pEList->nExpr;
95677
- aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
95678
- if( aCol==0 ) return SQLITE_NOMEM;
95938
+ if( pEList ){
95939
+ nCol = pEList->nExpr;
95940
+ aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
95941
+ testcase( aCol==0 );
95942
+ }else{
95943
+ nCol = 0;
95944
+ aCol = 0;
95945
+ }
95946
+ *pnCol = nCol;
95947
+ *paCol = aCol;
95948
+
9567995949
for(i=0, pCol=aCol; i<nCol; i++, pCol++){
9568095950
/* Get an appropriate name for the column
9568195951
*/
9568295952
p = pEList->a[i].pExpr;
9568395953
assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
@@ -98641,11 +98911,11 @@
9864198911
if( pCol->iSorterColumn>=j ){
9864298912
int r1 = j + regBase;
9864398913
int r2;
9864498914
9864598915
r2 = sqlite3ExprCodeGetColumn(pParse,
98646
- pCol->pTab, pCol->iColumn, pCol->iTable, r1);
98916
+ pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
9864798917
if( r1!=r2 ){
9864898918
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
9864998919
}
9865098920
j++;
9865198921
}
@@ -101201,10 +101471,22 @@
101201101471
char *zKey;
101202101472
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
101203101473
if( nKey ) db->nextPagesize = 0;
101204101474
}
101205101475
#endif
101476
+
101477
+ rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
101478
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
101479
+
101480
+ /* Begin a transaction and take an exclusive lock on the main database
101481
+ ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
101482
+ ** to ensure that we do not try to change the page-size on a WAL database.
101483
+ */
101484
+ rc = execSql(db, pzErrMsg, "BEGIN;");
101485
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
101486
+ rc = sqlite3BtreeBeginTrans(pMain, 2);
101487
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
101206101488
101207101489
/* Do not attempt to change the page size for a WAL database */
101208101490
if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
101209101491
==PAGER_JOURNALMODE_WAL ){
101210101492
db->nextPagesize = 0;
@@ -101215,24 +101497,16 @@
101215101497
|| NEVER(db->mallocFailed)
101216101498
){
101217101499
rc = SQLITE_NOMEM;
101218101500
goto end_of_vacuum;
101219101501
}
101220
- rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
101221
- if( rc!=SQLITE_OK ){
101222
- goto end_of_vacuum;
101223
- }
101224101502
101225101503
#ifndef SQLITE_OMIT_AUTOVACUUM
101226101504
sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac :
101227101505
sqlite3BtreeGetAutoVacuum(pMain));
101228101506
#endif
101229101507
101230
- /* Begin a transaction */
101231
- rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;");
101232
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
101233
-
101234101508
/* Query the schema of the main database. Create a mirror schema
101235101509
** in the temporary database.
101236101510
*/
101237101511
rc = execExecSql(db, pzErrMsg,
101238101512
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
@@ -103126,11 +103400,14 @@
103126103400
#ifdef SQLITE_EBCDIC
103127103401
if( *pnoCase ) return 0;
103128103402
#endif
103129103403
pList = pExpr->x.pList;
103130103404
pLeft = pList->a[1].pExpr;
103131
- if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ){
103405
+ if( pLeft->op!=TK_COLUMN
103406
+ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
103407
+ || IsVirtual(pLeft->pTab)
103408
+ ){
103132103409
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
103133103410
** be the name of an indexed column with TEXT affinity. */
103134103411
return 0;
103135103412
}
103136103413
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
@@ -105543,11 +105820,13 @@
105543105820
}
105544105821
105545105822
/* If there is a DISTINCT qualifier and this index will scan rows in
105546105823
** order of the DISTINCT expressions, clear bDist and set the appropriate
105547105824
** flags in wsFlags. */
105548
- if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
105825
+ if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq)
105826
+ && (wsFlags & WHERE_COLUMN_IN)==0
105827
+ ){
105549105828
bDist = 0;
105550105829
wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
105551105830
}
105552105831
105553105832
/* If currently calculating the cost of using an index (not the IPK
@@ -106240,12 +106519,11 @@
106240106519
*/
106241106520
static Bitmask codeOneLoopStart(
106242106521
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
106243106522
int iLevel, /* Which level of pWInfo->a[] should be coded */
106244106523
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
106245
- Bitmask notReady, /* Which tables are currently available */
106246
- Expr *pWhere /* Complete WHERE clause */
106524
+ Bitmask notReady /* Which tables are currently available */
106247106525
){
106248106526
int j, k; /* Loop counters */
106249106527
int iCur; /* The VDBE cursor for the table */
106250106528
int addrNxt; /* Where to jump to continue with the next IN case */
106251106529
int omitTable; /* True if we use the index only */
@@ -106780,14 +107058,29 @@
106780107058
106781107059
/* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
106782107060
** Then for every term xN, evaluate as the subexpression: xN AND z
106783107061
** That way, terms in y that are factored into the disjunction will
106784107062
** be picked up by the recursive calls to sqlite3WhereBegin() below.
107063
+ **
107064
+ ** Actually, each subexpression is converted to "xN AND w" where w is
107065
+ ** the "interesting" terms of z - terms that did not originate in the
107066
+ ** ON or USING clause of a LEFT JOIN, and terms that are usable as
107067
+ ** indices.
106785107068
*/
106786107069
if( pWC->nTerm>1 ){
106787
- pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0);
106788
- pAndExpr->pRight = pWhere;
107070
+ int iTerm;
107071
+ for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
107072
+ Expr *pExpr = pWC->a[iTerm].pExpr;
107073
+ if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
107074
+ if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
107075
+ if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
107076
+ pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
107077
+ pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
107078
+ }
107079
+ if( pAndExpr ){
107080
+ pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
107081
+ }
106789107082
}
106790107083
106791107084
for(ii=0; ii<pOrWc->nTerm; ii++){
106792107085
WhereTerm *pOrTerm = &pOrWc->a[ii];
106793107086
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
@@ -106807,11 +107100,11 @@
106807107100
);
106808107101
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
106809107102
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
106810107103
int r;
106811107104
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
106812
- regRowid);
107105
+ regRowid, 0);
106813107106
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
106814107107
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
106815107108
}
106816107109
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
106817107110
@@ -106825,11 +107118,14 @@
106825107118
/* Finish the loop through table entries that match term pOrTerm. */
106826107119
sqlite3WhereEnd(pSubWInfo);
106827107120
}
106828107121
}
106829107122
}
106830
- sqlite3DbFree(pParse->db, pAndExpr);
107123
+ if( pAndExpr ){
107124
+ pAndExpr->pLeft = 0;
107125
+ sqlite3ExprDelete(pParse->db, pAndExpr);
107126
+ }
106831107127
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
106832107128
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
106833107129
sqlite3VdbeResolveLabel(v, iLoopBody);
106834107130
106835107131
if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
@@ -107481,11 +107777,11 @@
107481107777
*/
107482107778
notReady = ~(Bitmask)0;
107483107779
for(i=0; i<nTabList; i++){
107484107780
pLevel = &pWInfo->a[i];
107485107781
explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
107486
- notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere);
107782
+ notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
107487107783
pWInfo->iContinue = pLevel->addrCont;
107488107784
}
107489107785
107490107786
#ifdef SQLITE_TEST /* For testing and debugging use only */
107491107787
/* Record in the query plan information about the current table
@@ -107717,11 +108013,11 @@
107717108013
** An instance of this structure is used to store the LIKE,
107718108014
** GLOB, NOT LIKE, and NOT GLOB operators.
107719108015
*/
107720108016
struct LikeOp {
107721108017
Token eOperator; /* "like" or "glob" or "regexp" */
107722
- int not; /* True if the NOT keyword is present */
108018
+ int bNot; /* True if the NOT keyword is present */
107723108019
};
107724108020
107725108021
/*
107726108022
** An instance of the following structure describes the event of a
107727108023
** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
@@ -107896,12 +108192,12 @@
107896108192
#endif
107897108193
#define sqlite3ParserARG_SDECL Parse *pParse;
107898108194
#define sqlite3ParserARG_PDECL ,Parse *pParse
107899108195
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
107900108196
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
107901
-#define YYNSTATE 629
107902
-#define YYNRULE 327
108197
+#define YYNSTATE 627
108198
+#define YYNRULE 325
107903108199
#define YYFALLBACK 1
107904108200
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
107905108201
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
107906108202
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
107907108203
@@ -107967,480 +108263,478 @@
107967108263
** shifting terminals.
107968108264
** yy_reduce_ofst[] For each state, the offset into yy_action for
107969108265
** shifting non-terminals after a reduce.
107970108266
** yy_default[] Default action for each state.
107971108267
*/
107972
-#define YY_ACTTAB_COUNT (1580)
108268
+#define YY_ACTTAB_COUNT (1561)
107973108269
static const YYACTIONTYPE yy_action[] = {
107974
- /* 0 */ 310, 328, 574, 573, 15, 172, 187, 596, 56, 56,
108270
+ /* 0 */ 310, 328, 573, 572, 15, 171, 185, 595, 56, 56,
107975108271
/* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52,
107976
- /* 20 */ 52, 52, 51, 234, 622, 621, 626, 622, 621, 299,
107977
- /* 30 */ 589, 583, 56, 56, 56, 56, 236, 54, 54, 54,
107978
- /* 40 */ 54, 53, 53, 52, 52, 52, 51, 234, 351, 57,
107979
- /* 50 */ 58, 48, 581, 580, 582, 582, 55, 55, 56, 56,
107980
- /* 60 */ 56, 56, 570, 54, 54, 54, 54, 53, 53, 52,
107981
- /* 70 */ 52, 52, 51, 234, 310, 596, 326, 607, 233, 232,
108272
+ /* 20 */ 52, 52, 51, 233, 52, 52, 52, 51, 233, 624,
108273
+ /* 30 */ 588, 582, 56, 56, 56, 56, 314, 54, 54, 54,
108274
+ /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 299, 57,
108275
+ /* 50 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108276
+ /* 60 */ 56, 56, 569, 54, 54, 54, 54, 53, 53, 52,
108277
+ /* 70 */ 52, 52, 51, 233, 310, 595, 326, 575, 663, 65,
107982108278
/* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52,
107983
- /* 90 */ 51, 234, 619, 618, 326, 619, 618, 166, 605, 492,
107984
- /* 100 */ 381, 378, 377, 235, 589, 583, 554, 495, 1, 59,
107985
- /* 110 */ 19, 376, 622, 621, 53, 53, 52, 52, 52, 51,
107986
- /* 120 */ 234, 571, 571, 57, 58, 48, 581, 580, 582, 582,
107987
- /* 130 */ 55, 55, 56, 56, 56, 56, 215, 54, 54, 54,
107988
- /* 140 */ 54, 53, 53, 52, 52, 52, 51, 234, 310, 224,
107989
- /* 150 */ 50, 47, 147, 177, 139, 281, 384, 276, 383, 169,
107990
- /* 160 */ 408, 553, 578, 578, 622, 621, 272, 224, 439, 550,
107991
- /* 170 */ 552, 410, 139, 281, 384, 276, 383, 169, 589, 583,
107992
- /* 180 */ 619, 618, 280, 620, 272, 195, 413, 309, 440, 441,
107993
- /* 190 */ 567, 491, 214, 279, 560, 600, 92, 57, 58, 48,
107994
- /* 200 */ 581, 580, 582, 582, 55, 55, 56, 56, 56, 56,
107995
- /* 210 */ 559, 54, 54, 54, 54, 53, 53, 52, 52, 52,
107996
- /* 220 */ 51, 234, 310, 464, 233, 232, 558, 133, 519, 50,
107997
- /* 230 */ 47, 147, 619, 618, 565, 436, 397, 515, 514, 518,
107998
- /* 240 */ 410, 387, 438, 389, 437, 622, 621, 442, 570, 433,
107999
- /* 250 */ 203, 390, 589, 583, 6, 413, 166, 670, 250, 381,
108000
- /* 260 */ 378, 377, 525, 190, 600, 92, 594, 571, 571, 465,
108001
- /* 270 */ 376, 57, 58, 48, 581, 580, 582, 582, 55, 55,
108002
- /* 280 */ 56, 56, 56, 56, 599, 54, 54, 54, 54, 53,
108003
- /* 290 */ 53, 52, 52, 52, 51, 234, 310, 592, 592, 592,
108004
- /* 300 */ 490, 182, 247, 548, 249, 397, 273, 410, 7, 439,
108005
- /* 310 */ 398, 606, 67, 619, 618, 620, 472, 256, 347, 255,
108006
- /* 320 */ 473, 620, 413, 576, 620, 65, 589, 583, 236, 440,
108007
- /* 330 */ 336, 600, 92, 68, 364, 192, 481, 622, 621, 547,
108008
- /* 340 */ 622, 621, 560, 323, 207, 57, 58, 48, 581, 580,
108009
- /* 350 */ 582, 582, 55, 55, 56, 56, 56, 56, 559, 54,
108010
- /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
108011
- /* 370 */ 310, 410, 397, 146, 558, 531, 401, 348, 599, 166,
108012
- /* 380 */ 248, 204, 381, 378, 377, 541, 413, 171, 337, 570,
108013
- /* 390 */ 622, 621, 40, 376, 38, 600, 74, 465, 548, 490,
108014
- /* 400 */ 589, 583, 532, 350, 579, 619, 618, 297, 619, 618,
108015
- /* 410 */ 480, 67, 470, 39, 620, 599, 406, 574, 573, 57,
108016
- /* 420 */ 58, 48, 581, 580, 582, 582, 55, 55, 56, 56,
108017
- /* 430 */ 56, 56, 577, 54, 54, 54, 54, 53, 53, 52,
108018
- /* 440 */ 52, 52, 51, 234, 310, 256, 347, 255, 530, 52,
108019
- /* 450 */ 52, 52, 51, 234, 345, 564, 236, 386, 619, 618,
108020
- /* 460 */ 957, 185, 418, 2, 408, 410, 578, 578, 198, 197,
108021
- /* 470 */ 196, 499, 183, 167, 589, 583, 671, 570, 505, 506,
108022
- /* 480 */ 413, 267, 601, 672, 546, 208, 602, 36, 601, 600,
108023
- /* 490 */ 91, 468, 602, 57, 58, 48, 581, 580, 582, 582,
108024
- /* 500 */ 55, 55, 56, 56, 56, 56, 202, 54, 54, 54,
108025
- /* 510 */ 54, 53, 53, 52, 52, 52, 51, 234, 310, 599,
108026
- /* 520 */ 157, 408, 527, 578, 578, 263, 490, 265, 410, 873,
108027
- /* 530 */ 410, 474, 474, 366, 373, 410, 504, 428, 67, 290,
108028
- /* 540 */ 599, 620, 352, 413, 408, 413, 578, 578, 589, 583,
108029
- /* 550 */ 413, 382, 600, 92, 600, 16, 543, 62, 503, 600,
108030
- /* 560 */ 92, 408, 346, 578, 578, 168, 45, 57, 58, 48,
108031
- /* 570 */ 581, 580, 582, 582, 55, 55, 56, 56, 56, 56,
108032
- /* 580 */ 200, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108033
- /* 590 */ 51, 234, 310, 393, 395, 534, 510, 617, 616, 615,
108034
- /* 600 */ 318, 314, 172, 66, 596, 410, 338, 596, 324, 571,
108035
- /* 610 */ 571, 50, 47, 147, 599, 629, 627, 330, 539, 315,
108036
- /* 620 */ 413, 30, 589, 583, 272, 236, 199, 144, 176, 600,
108037
- /* 630 */ 73, 420, 947, 620, 947, 420, 946, 351, 946, 175,
108038
- /* 640 */ 596, 57, 58, 48, 581, 580, 582, 582, 55, 55,
108039
- /* 650 */ 56, 56, 56, 56, 410, 54, 54, 54, 54, 53,
108040
- /* 660 */ 53, 52, 52, 52, 51, 234, 310, 261, 410, 413,
108041
- /* 670 */ 269, 208, 596, 363, 410, 596, 424, 360, 600, 69,
108042
- /* 680 */ 424, 327, 620, 413, 50, 47, 147, 410, 358, 413,
108043
- /* 690 */ 575, 553, 600, 94, 483, 509, 589, 583, 600, 97,
108044
- /* 700 */ 552, 484, 413, 620, 188, 599, 551, 563, 596, 566,
108045
- /* 710 */ 334, 600, 95, 205, 201, 57, 58, 48, 581, 580,
108046
- /* 720 */ 582, 582, 55, 55, 56, 56, 56, 56, 352, 54,
108047
- /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
108048
- /* 740 */ 310, 410, 261, 410, 167, 22, 356, 599, 359, 623,
108049
- /* 750 */ 50, 47, 147, 548, 357, 562, 413, 620, 413, 332,
108050
- /* 760 */ 523, 270, 410, 167, 620, 600, 104, 600, 103, 603,
108051
- /* 770 */ 589, 583, 339, 539, 304, 423, 222, 413, 174, 304,
108052
- /* 780 */ 422, 561, 567, 405, 214, 260, 600, 106, 620, 57,
108053
- /* 790 */ 58, 48, 581, 580, 582, 582, 55, 55, 56, 56,
108054
- /* 800 */ 56, 56, 410, 54, 54, 54, 54, 53, 53, 52,
108055
- /* 810 */ 52, 52, 51, 234, 310, 410, 557, 413, 410, 421,
108056
- /* 820 */ 273, 35, 512, 146, 421, 12, 600, 107, 213, 144,
108057
- /* 830 */ 413, 410, 32, 413, 410, 620, 365, 353, 358, 600,
108058
- /* 840 */ 134, 11, 600, 135, 589, 583, 413, 21, 548, 413,
108059
- /* 850 */ 316, 148, 620, 620, 170, 600, 98, 223, 600, 102,
108060
- /* 860 */ 374, 168, 167, 57, 58, 48, 581, 580, 582, 582,
108061
- /* 870 */ 55, 55, 56, 56, 56, 56, 410, 54, 54, 54,
108062
- /* 880 */ 54, 53, 53, 52, 52, 52, 51, 234, 310, 410,
108063
- /* 890 */ 273, 413, 410, 273, 212, 469, 410, 167, 628, 2,
108064
- /* 900 */ 600, 101, 545, 221, 413, 620, 130, 413, 620, 410,
108065
- /* 910 */ 539, 413, 537, 600, 93, 315, 600, 100, 589, 583,
108066
- /* 920 */ 600, 77, 425, 305, 413, 620, 254, 322, 599, 458,
108067
- /* 930 */ 320, 171, 543, 600, 96, 521, 520, 57, 58, 48,
108068
- /* 940 */ 581, 580, 582, 582, 55, 55, 56, 56, 56, 56,
108069
- /* 950 */ 410, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108070
- /* 960 */ 51, 234, 310, 410, 273, 413, 410, 457, 358, 35,
108071
- /* 970 */ 426, 230, 306, 319, 600, 138, 467, 520, 413, 620,
108072
- /* 980 */ 143, 413, 410, 620, 410, 353, 529, 600, 137, 142,
108073
- /* 990 */ 600, 136, 589, 583, 604, 261, 528, 413, 229, 413,
108074
- /* 1000 */ 620, 321, 495, 28, 543, 543, 600, 76, 600, 90,
108075
- /* 1010 */ 620, 57, 46, 48, 581, 580, 582, 582, 55, 55,
108076
- /* 1020 */ 56, 56, 56, 56, 410, 54, 54, 54, 54, 53,
108077
- /* 1030 */ 53, 52, 52, 52, 51, 234, 310, 261, 451, 413,
108078
- /* 1040 */ 410, 211, 611, 285, 283, 610, 609, 502, 600, 89,
108079
- /* 1050 */ 380, 217, 620, 128, 140, 413, 220, 620, 410, 409,
108080
- /* 1060 */ 620, 620, 588, 587, 600, 75, 589, 583, 271, 620,
108081
- /* 1070 */ 51, 234, 127, 413, 620, 599, 627, 330, 27, 375,
108082
- /* 1080 */ 449, 279, 600, 88, 585, 584, 58, 48, 581, 580,
108083
- /* 1090 */ 582, 582, 55, 55, 56, 56, 56, 56, 410, 54,
108084
- /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
108085
- /* 1110 */ 310, 586, 410, 413, 410, 261, 593, 165, 399, 556,
108086
- /* 1120 */ 126, 371, 600, 87, 478, 186, 123, 413, 367, 413,
108087
- /* 1130 */ 620, 620, 410, 620, 620, 410, 600, 99, 600, 86,
108088
- /* 1140 */ 589, 583, 475, 122, 258, 171, 471, 413, 160, 121,
108089
- /* 1150 */ 413, 14, 159, 463, 25, 24, 600, 17, 448, 600,
108090
- /* 1160 */ 85, 48, 581, 580, 582, 582, 55, 55, 56, 56,
108091
- /* 1170 */ 56, 56, 158, 54, 54, 54, 54, 53, 53, 52,
108092
- /* 1180 */ 52, 52, 51, 234, 44, 404, 261, 3, 544, 261,
108093
- /* 1190 */ 540, 414, 621, 460, 119, 118, 538, 275, 10, 349,
108094
- /* 1200 */ 4, 620, 407, 620, 620, 620, 116, 44, 404, 410,
108095
- /* 1210 */ 3, 620, 620, 410, 414, 621, 456, 454, 252, 450,
108096
- /* 1220 */ 508, 402, 111, 109, 413, 407, 155, 444, 413, 447,
108097
- /* 1230 */ 435, 565, 219, 600, 84, 620, 108, 600, 83, 64,
108098
- /* 1240 */ 434, 417, 625, 150, 402, 333, 410, 237, 238, 124,
108099
- /* 1250 */ 274, 41, 42, 533, 565, 206, 189, 261, 43, 412,
108100
- /* 1260 */ 411, 413, 261, 594, 488, 620, 329, 149, 419, 268,
108101
- /* 1270 */ 600, 72, 620, 266, 41, 42, 181, 620, 410, 620,
108102
- /* 1280 */ 105, 43, 412, 411, 620, 624, 594, 614, 620, 599,
108103
- /* 1290 */ 228, 125, 313, 413, 592, 592, 592, 591, 590, 13,
108104
- /* 1300 */ 218, 410, 600, 71, 236, 244, 44, 404, 264, 3,
108105
- /* 1310 */ 312, 613, 340, 414, 621, 180, 413, 592, 592, 592,
108106
- /* 1320 */ 591, 590, 13, 620, 407, 600, 82, 410, 416, 34,
108107
- /* 1330 */ 404, 410, 3, 410, 262, 410, 414, 621, 612, 331,
108108
- /* 1340 */ 178, 415, 413, 402, 8, 236, 413, 407, 413, 620,
108109
- /* 1350 */ 413, 600, 81, 565, 257, 600, 80, 600, 70, 600,
108110
- /* 1360 */ 18, 598, 361, 462, 461, 30, 402, 294, 31, 620,
108111
- /* 1370 */ 293, 354, 251, 41, 42, 410, 565, 620, 620, 620,
108112
- /* 1380 */ 43, 412, 411, 453, 396, 594, 620, 620, 394, 61,
108113
- /* 1390 */ 413, 292, 443, 622, 621, 243, 41, 42, 620, 600,
108114
- /* 1400 */ 79, 597, 291, 43, 412, 411, 60, 620, 594, 240,
108115
- /* 1410 */ 620, 410, 231, 37, 555, 173, 592, 592, 592, 591,
108116
- /* 1420 */ 590, 13, 216, 239, 620, 184, 413, 302, 301, 300,
108117
- /* 1430 */ 179, 298, 388, 565, 452, 600, 78, 286, 620, 592,
108118
- /* 1440 */ 592, 592, 591, 590, 13, 429, 29, 413, 151, 289,
108119
- /* 1450 */ 242, 145, 392, 194, 193, 288, 600, 9, 542, 241,
108120
- /* 1460 */ 620, 525, 391, 284, 620, 594, 620, 620, 522, 536,
108121
- /* 1470 */ 620, 535, 153, 385, 465, 516, 282, 325, 154, 517,
108122
- /* 1480 */ 277, 152, 512, 511, 513, 129, 226, 308, 487, 486,
108123
- /* 1490 */ 485, 164, 372, 493, 307, 227, 592, 592, 592, 225,
108124
- /* 1500 */ 479, 163, 368, 370, 162, 476, 210, 477, 26, 259,
108125
- /* 1510 */ 161, 466, 362, 141, 132, 120, 117, 455, 156, 115,
108126
- /* 1520 */ 344, 343, 256, 342, 245, 114, 113, 446, 311, 112,
108127
- /* 1530 */ 23, 317, 432, 236, 131, 431, 110, 430, 20, 427,
108128
- /* 1540 */ 608, 595, 295, 63, 379, 287, 509, 191, 278, 403,
108129
- /* 1550 */ 572, 569, 497, 498, 496, 494, 335, 459, 445, 303,
108130
- /* 1560 */ 296, 246, 341, 355, 5, 568, 369, 507, 253, 549,
108131
- /* 1570 */ 526, 209, 400, 501, 500, 524, 234, 958, 489, 482,
108279
+ /* 90 */ 51, 233, 53, 53, 52, 52, 52, 51, 233, 489,
108280
+ /* 100 */ 663, 440, 663, 235, 588, 582, 553, 297, 363, 59,
108281
+ /* 110 */ 481, 67, 360, 1, 618, 351, 618, 620, 619, 207,
108282
+ /* 120 */ 6, 441, 442, 57, 58, 48, 580, 579, 581, 581,
108283
+ /* 130 */ 55, 55, 56, 56, 56, 56, 605, 54, 54, 54,
108284
+ /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 223,
108285
+ /* 150 */ 50, 47, 146, 598, 138, 281, 385, 276, 384, 168,
108286
+ /* 160 */ 489, 552, 620, 619, 620, 619, 272, 214, 440, 411,
108287
+ /* 170 */ 551, 604, 67, 165, 7, 618, 352, 353, 588, 582,
108288
+ /* 180 */ 443, 569, 192, 618, 414, 617, 616, 668, 441, 336,
108289
+ /* 190 */ 669, 62, 618, 599, 92, 382, 346, 57, 58, 48,
108290
+ /* 200 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
108291
+ /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108292
+ /* 220 */ 51, 233, 310, 465, 232, 231, 373, 132, 514, 513,
108293
+ /* 230 */ 617, 616, 617, 616, 398, 437, 411, 66, 280, 388,
108294
+ /* 240 */ 411, 595, 439, 220, 438, 620, 619, 337, 569, 279,
108295
+ /* 250 */ 201, 414, 588, 582, 166, 414, 546, 167, 68, 234,
108296
+ /* 260 */ 599, 92, 620, 619, 599, 92, 19, 570, 570, 466,
108297
+ /* 270 */ 564, 57, 58, 48, 580, 579, 581, 581, 55, 55,
108298
+ /* 280 */ 56, 56, 56, 56, 598, 54, 54, 54, 54, 53,
108299
+ /* 290 */ 53, 52, 52, 52, 51, 233, 310, 411, 524, 232,
108300
+ /* 300 */ 231, 398, 593, 547, 559, 398, 348, 202, 175, 595,
108301
+ /* 310 */ 399, 315, 414, 617, 616, 387, 272, 255, 347, 254,
108302
+ /* 320 */ 558, 599, 74, 620, 619, 45, 588, 582, 235, 466,
108303
+ /* 330 */ 617, 616, 511, 591, 591, 591, 557, 578, 402, 545,
108304
+ /* 340 */ 600, 598, 570, 570, 601, 57, 58, 48, 580, 579,
108305
+ /* 350 */ 581, 581, 55, 55, 56, 56, 56, 56, 550, 54,
108306
+ /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
108307
+ /* 370 */ 310, 309, 411, 145, 566, 490, 213, 255, 347, 254,
108308
+ /* 380 */ 196, 195, 194, 587, 586, 531, 600, 414, 235, 174,
108309
+ /* 390 */ 601, 617, 616, 411, 620, 619, 599, 91, 547, 574,
108310
+ /* 400 */ 588, 582, 50, 47, 146, 584, 583, 471, 414, 249,
108311
+ /* 410 */ 565, 542, 186, 39, 304, 424, 562, 599, 16, 57,
108312
+ /* 420 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108313
+ /* 430 */ 56, 56, 585, 54, 54, 54, 54, 53, 53, 52,
108314
+ /* 440 */ 52, 52, 51, 233, 310, 559, 290, 530, 529, 345,
108315
+ /* 450 */ 533, 576, 540, 246, 170, 248, 411, 396, 411, 422,
108316
+ /* 460 */ 199, 558, 617, 616, 165, 563, 50, 47, 146, 181,
108317
+ /* 470 */ 498, 414, 166, 414, 588, 582, 269, 557, 166, 518,
108318
+ /* 480 */ 599, 92, 599, 92, 561, 595, 469, 36, 173, 409,
108319
+ /* 490 */ 517, 577, 577, 57, 58, 48, 580, 579, 581, 581,
108320
+ /* 500 */ 55, 55, 56, 56, 56, 56, 338, 54, 54, 54,
108321
+ /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 304,
108322
+ /* 520 */ 423, 394, 526, 318, 869, 235, 167, 180, 473, 547,
108323
+ /* 530 */ 503, 247, 474, 381, 378, 377, 409, 351, 577, 577,
108324
+ /* 540 */ 409, 560, 577, 577, 376, 383, 364, 603, 588, 582,
108325
+ /* 550 */ 620, 619, 502, 595, 409, 494, 577, 577, 409, 266,
108326
+ /* 560 */ 577, 577, 421, 943, 422, 943, 198, 57, 58, 48,
108327
+ /* 570 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
108328
+ /* 580 */ 315, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108329
+ /* 590 */ 51, 233, 310, 390, 421, 942, 509, 942, 556, 145,
108330
+ /* 600 */ 598, 391, 324, 262, 549, 264, 411, 425, 407, 573,
108331
+ /* 610 */ 572, 12, 197, 143, 489, 50, 47, 146, 617, 616,
108332
+ /* 620 */ 206, 414, 588, 582, 547, 429, 67, 212, 143, 618,
108333
+ /* 630 */ 599, 73, 504, 505, 207, 434, 475, 475, 366, 425,
108334
+ /* 640 */ 35, 57, 58, 48, 580, 579, 581, 581, 55, 55,
108335
+ /* 650 */ 56, 56, 56, 56, 598, 54, 54, 54, 54, 53,
108336
+ /* 660 */ 53, 52, 52, 52, 51, 233, 310, 260, 598, 569,
108337
+ /* 670 */ 268, 615, 614, 613, 171, 411, 595, 11, 411, 350,
108338
+ /* 680 */ 411, 32, 618, 953, 183, 419, 2, 627, 625, 330,
108339
+ /* 690 */ 414, 352, 552, 414, 538, 414, 588, 582, 188, 599,
108340
+ /* 700 */ 69, 551, 599, 94, 599, 97, 374, 544, 166, 618,
108341
+ /* 710 */ 334, 359, 50, 47, 146, 57, 58, 48, 580, 579,
108342
+ /* 720 */ 581, 581, 55, 55, 56, 56, 56, 56, 411, 54,
108343
+ /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
108344
+ /* 740 */ 310, 411, 129, 414, 595, 22, 273, 156, 411, 566,
108345
+ /* 750 */ 406, 213, 599, 95, 570, 570, 414, 327, 169, 332,
108346
+ /* 760 */ 411, 618, 536, 414, 358, 599, 104, 483, 508, 356,
108347
+ /* 770 */ 588, 582, 599, 103, 484, 414, 470, 357, 166, 618,
108348
+ /* 780 */ 626, 2, 204, 323, 599, 105, 40, 528, 38, 57,
108349
+ /* 790 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108350
+ /* 800 */ 56, 56, 411, 54, 54, 54, 54, 53, 53, 52,
108351
+ /* 810 */ 52, 52, 51, 233, 310, 411, 598, 414, 411, 260,
108352
+ /* 820 */ 273, 273, 273, 273, 426, 305, 599, 106, 520, 519,
108353
+ /* 830 */ 414, 411, 142, 414, 618, 618, 618, 618, 618, 599,
108354
+ /* 840 */ 133, 339, 599, 134, 588, 582, 414, 21, 30, 316,
108355
+ /* 850 */ 147, 459, 221, 170, 527, 599, 98, 222, 322, 321,
108356
+ /* 860 */ 320, 141, 259, 57, 58, 48, 580, 579, 581, 581,
108357
+ /* 870 */ 55, 55, 56, 56, 56, 56, 411, 54, 54, 54,
108358
+ /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 411,
108359
+ /* 890 */ 260, 414, 411, 458, 200, 35, 411, 358, 211, 228,
108360
+ /* 900 */ 599, 102, 468, 519, 414, 618, 28, 414, 538, 501,
108361
+ /* 910 */ 411, 414, 618, 599, 101, 358, 599, 93, 588, 582,
108362
+ /* 920 */ 599, 100, 522, 618, 427, 414, 306, 271, 598, 380,
108363
+ /* 930 */ 618, 602, 598, 452, 599, 77, 210, 57, 58, 48,
108364
+ /* 940 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
108365
+ /* 950 */ 411, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108366
+ /* 960 */ 51, 233, 310, 411, 621, 414, 411, 127, 609, 270,
108367
+ /* 970 */ 598, 365, 51, 233, 599, 96, 625, 330, 414, 618,
108368
+ /* 980 */ 126, 414, 411, 618, 411, 253, 608, 599, 137, 27,
108369
+ /* 990 */ 599, 136, 588, 582, 375, 260, 125, 414, 164, 414,
108370
+ /* 1000 */ 371, 618, 279, 219, 542, 542, 599, 135, 599, 76,
108371
+ /* 1010 */ 618, 57, 46, 48, 580, 579, 581, 581, 55, 55,
108372
+ /* 1020 */ 56, 56, 56, 56, 411, 54, 54, 54, 54, 53,
108373
+ /* 1030 */ 53, 52, 52, 52, 51, 233, 310, 411, 450, 414,
108374
+ /* 1040 */ 411, 260, 542, 229, 285, 607, 479, 184, 599, 90,
108375
+ /* 1050 */ 367, 122, 414, 476, 121, 414, 618, 170, 411, 353,
108376
+ /* 1060 */ 618, 599, 89, 410, 599, 75, 588, 582, 472, 257,
108377
+ /* 1070 */ 538, 120, 159, 414, 618, 14, 464, 158, 618, 157,
108378
+ /* 1080 */ 461, 283, 599, 88, 449, 618, 58, 48, 580, 579,
108379
+ /* 1090 */ 581, 581, 55, 55, 56, 56, 56, 56, 411, 54,
108380
+ /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
108381
+ /* 1110 */ 310, 411, 260, 414, 411, 592, 260, 118, 25, 400,
108382
+ /* 1120 */ 10, 24, 599, 87, 117, 216, 414, 618, 349, 414,
108383
+ /* 1130 */ 618, 618, 411, 319, 618, 599, 99, 555, 599, 86,
108384
+ /* 1140 */ 588, 582, 4, 260, 457, 455, 115, 414, 251, 154,
108385
+ /* 1150 */ 451, 108, 618, 110, 436, 448, 599, 17, 618, 218,
108386
+ /* 1160 */ 107, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108387
+ /* 1170 */ 56, 56, 435, 54, 54, 54, 54, 53, 53, 52,
108388
+ /* 1180 */ 52, 52, 51, 233, 44, 405, 217, 3, 411, 260,
108389
+ /* 1190 */ 543, 415, 619, 445, 64, 149, 539, 237, 333, 329,
108390
+ /* 1200 */ 203, 187, 408, 414, 618, 618, 420, 44, 405, 411,
108391
+ /* 1210 */ 3, 618, 599, 85, 415, 619, 148, 227, 622, 179,
108392
+ /* 1220 */ 313, 403, 312, 612, 414, 408, 611, 124, 417, 178,
108393
+ /* 1230 */ 610, 564, 243, 599, 84, 537, 8, 176, 235, 416,
108394
+ /* 1240 */ 294, 418, 623, 30, 403, 597, 411, 236, 293, 123,
108395
+ /* 1250 */ 618, 41, 42, 532, 564, 205, 292, 275, 43, 413,
108396
+ /* 1260 */ 412, 414, 395, 593, 507, 274, 31, 397, 291, 37,
108397
+ /* 1270 */ 599, 83, 618, 491, 41, 42, 267, 411, 265, 618,
108398
+ /* 1280 */ 618, 43, 413, 412, 596, 263, 593, 60, 618, 598,
108399
+ /* 1290 */ 261, 618, 414, 618, 591, 591, 591, 590, 589, 13,
108400
+ /* 1300 */ 618, 599, 72, 554, 235, 618, 44, 405, 256, 3,
108401
+ /* 1310 */ 361, 172, 340, 415, 619, 230, 411, 591, 591, 591,
108402
+ /* 1320 */ 590, 589, 13, 618, 408, 618, 182, 411, 286, 34,
108403
+ /* 1330 */ 405, 414, 3, 411, 463, 411, 415, 619, 29, 331,
108404
+ /* 1340 */ 599, 71, 414, 403, 392, 386, 284, 408, 414, 618,
108405
+ /* 1350 */ 414, 599, 82, 564, 411, 462, 354, 599, 81, 599,
108406
+ /* 1360 */ 80, 541, 250, 535, 282, 521, 403, 534, 516, 414,
108407
+ /* 1370 */ 618, 618, 454, 41, 42, 411, 564, 618, 599, 70,
108408
+ /* 1380 */ 43, 413, 412, 444, 515, 593, 242, 618, 325, 61,
108409
+ /* 1390 */ 414, 277, 239, 620, 619, 238, 41, 42, 618, 599,
108410
+ /* 1400 */ 18, 618, 512, 43, 413, 412, 511, 618, 593, 430,
108411
+ /* 1410 */ 618, 411, 128, 510, 308, 226, 591, 591, 591, 590,
108412
+ /* 1420 */ 589, 13, 215, 289, 618, 225, 414, 302, 301, 300,
108413
+ /* 1430 */ 177, 298, 411, 564, 453, 599, 79, 224, 618, 591,
108414
+ /* 1440 */ 591, 591, 590, 589, 13, 389, 492, 414, 150, 144,
108415
+ /* 1450 */ 241, 393, 288, 191, 190, 193, 599, 78, 165, 240,
108416
+ /* 1460 */ 414, 524, 487, 307, 618, 593, 618, 618, 486, 599,
108417
+ /* 1470 */ 9, 163, 152, 485, 466, 372, 480, 162, 153, 370,
108418
+ /* 1480 */ 161, 151, 209, 478, 258, 368, 477, 26, 160, 467,
108419
+ /* 1490 */ 140, 362, 131, 119, 116, 456, 591, 591, 591, 155,
108420
+ /* 1500 */ 114, 344, 343, 113, 112, 111, 447, 109, 130, 23,
108421
+ /* 1510 */ 317, 433, 20, 432, 431, 428, 606, 594, 63, 189,
108422
+ /* 1520 */ 404, 571, 255, 342, 244, 295, 287, 278, 311, 508,
108423
+ /* 1530 */ 496, 497, 495, 235, 493, 568, 379, 355, 460, 245,
108424
+ /* 1540 */ 341, 446, 303, 567, 5, 252, 548, 208, 139, 506,
108425
+ /* 1550 */ 369, 401, 500, 499, 296, 525, 335, 488, 482, 523,
108426
+ /* 1560 */ 233,
108132108427
};
108133108428
static const YYCODETYPE yy_lookahead[] = {
108134108429
/* 0 */ 19, 169, 170, 171, 22, 24, 24, 26, 77, 78,
108135108430
/* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
108136
- /* 20 */ 89, 90, 91, 92, 26, 27, 1, 26, 27, 15,
108137
- /* 30 */ 49, 50, 77, 78, 79, 80, 116, 82, 83, 84,
108138
- /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 128, 68,
108431
+ /* 20 */ 89, 90, 91, 92, 88, 89, 90, 91, 92, 1,
108432
+ /* 30 */ 49, 50, 77, 78, 79, 80, 155, 82, 83, 84,
108433
+ /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 15, 68,
108139108434
/* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108140108435
/* 60 */ 79, 80, 230, 82, 83, 84, 85, 86, 87, 88,
108141
- /* 70 */ 89, 90, 91, 92, 19, 94, 19, 23, 86, 87,
108436
+ /* 70 */ 89, 90, 91, 92, 19, 94, 19, 23, 1, 25,
108142108437
/* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108143
- /* 90 */ 91, 92, 94, 95, 19, 94, 95, 96, 172, 173,
108144
- /* 100 */ 99, 100, 101, 197, 49, 50, 177, 181, 22, 54,
108145
- /* 110 */ 204, 110, 26, 27, 86, 87, 88, 89, 90, 91,
108146
- /* 120 */ 92, 129, 130, 68, 69, 70, 71, 72, 73, 74,
108147
- /* 130 */ 75, 76, 77, 78, 79, 80, 22, 82, 83, 84,
108438
+ /* 90 */ 91, 92, 86, 87, 88, 89, 90, 91, 92, 150,
108439
+ /* 100 */ 23, 150, 25, 116, 49, 50, 177, 158, 227, 54,
108440
+ /* 110 */ 161, 162, 231, 22, 165, 128, 165, 26, 27, 160,
108441
+ /* 120 */ 22, 170, 171, 68, 69, 70, 71, 72, 73, 74,
108442
+ /* 130 */ 75, 76, 77, 78, 79, 80, 23, 82, 83, 84,
108148108443
/* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92,
108149
- /* 150 */ 221, 222, 223, 96, 97, 98, 99, 100, 101, 102,
108150
- /* 160 */ 112, 32, 114, 115, 26, 27, 109, 92, 150, 25,
108151
- /* 170 */ 41, 150, 97, 98, 99, 100, 101, 102, 49, 50,
108152
- /* 180 */ 94, 95, 98, 165, 109, 25, 165, 163, 170, 171,
108153
- /* 190 */ 166, 167, 168, 109, 12, 174, 175, 68, 69, 70,
108444
+ /* 150 */ 221, 222, 223, 194, 97, 98, 99, 100, 101, 102,
108445
+ /* 160 */ 150, 32, 26, 27, 26, 27, 109, 22, 150, 150,
108446
+ /* 170 */ 41, 161, 162, 96, 76, 165, 217, 150, 49, 50,
108447
+ /* 180 */ 229, 230, 172, 165, 165, 94, 95, 118, 170, 171,
108448
+ /* 190 */ 118, 232, 165, 174, 175, 185, 237, 68, 69, 70,
108154108449
/* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108155
- /* 210 */ 28, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108156
- /* 220 */ 91, 92, 19, 11, 86, 87, 44, 24, 46, 221,
108157
- /* 230 */ 222, 223, 94, 95, 66, 97, 215, 7, 8, 57,
108158
- /* 240 */ 150, 220, 104, 19, 106, 26, 27, 229, 230, 241,
108159
- /* 250 */ 160, 27, 49, 50, 22, 165, 96, 118, 16, 99,
108160
- /* 260 */ 100, 101, 94, 119, 174, 175, 98, 129, 130, 57,
108161
- /* 270 */ 110, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108450
+ /* 210 */ 118, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108451
+ /* 220 */ 91, 92, 19, 11, 86, 87, 19, 24, 7, 8,
108452
+ /* 230 */ 94, 95, 94, 95, 215, 97, 150, 22, 98, 220,
108453
+ /* 240 */ 150, 26, 104, 216, 106, 26, 27, 229, 230, 109,
108454
+ /* 250 */ 160, 165, 49, 50, 25, 165, 120, 50, 22, 197,
108455
+ /* 260 */ 174, 175, 26, 27, 174, 175, 204, 129, 130, 57,
108456
+ /* 270 */ 66, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108162108457
/* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
108163
- /* 290 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 131,
108164
- /* 300 */ 150, 23, 60, 25, 62, 215, 150, 150, 76, 150,
108165
- /* 310 */ 220, 161, 162, 94, 95, 165, 30, 105, 106, 107,
108166
- /* 320 */ 34, 165, 165, 23, 165, 25, 49, 50, 116, 170,
108167
- /* 330 */ 171, 174, 175, 22, 48, 185, 186, 26, 27, 120,
108168
- /* 340 */ 26, 27, 12, 187, 160, 68, 69, 70, 71, 72,
108169
- /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 28, 82,
108458
+ /* 290 */ 87, 88, 89, 90, 91, 92, 19, 150, 94, 86,
108459
+ /* 300 */ 87, 215, 98, 25, 12, 215, 220, 160, 118, 94,
108460
+ /* 310 */ 220, 104, 165, 94, 95, 88, 109, 105, 106, 107,
108461
+ /* 320 */ 28, 174, 175, 26, 27, 22, 49, 50, 116, 57,
108462
+ /* 330 */ 94, 95, 103, 129, 130, 131, 44, 113, 46, 120,
108463
+ /* 340 */ 113, 194, 129, 130, 117, 68, 69, 70, 71, 72,
108464
+ /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 177, 82,
108170108465
/* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108171
- /* 370 */ 19, 150, 215, 95, 44, 23, 46, 220, 194, 96,
108172
- /* 380 */ 138, 160, 99, 100, 101, 23, 165, 25, 229, 230,
108173
- /* 390 */ 26, 27, 135, 110, 137, 174, 175, 57, 120, 150,
108174
- /* 400 */ 49, 50, 88, 219, 113, 94, 95, 158, 94, 95,
108175
- /* 410 */ 161, 162, 21, 136, 165, 194, 169, 170, 171, 68,
108466
+ /* 370 */ 19, 163, 150, 95, 166, 167, 168, 105, 106, 107,
108467
+ /* 380 */ 105, 106, 107, 49, 50, 88, 113, 165, 116, 118,
108468
+ /* 390 */ 117, 94, 95, 150, 26, 27, 174, 175, 120, 23,
108469
+ /* 400 */ 49, 50, 221, 222, 223, 71, 72, 21, 165, 16,
108470
+ /* 410 */ 23, 166, 22, 136, 22, 23, 11, 174, 175, 68,
108176108471
/* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108177
- /* 430 */ 79, 80, 23, 82, 83, 84, 85, 86, 87, 88,
108178
- /* 440 */ 89, 90, 91, 92, 19, 105, 106, 107, 23, 88,
108179
- /* 450 */ 89, 90, 91, 92, 63, 23, 116, 88, 94, 95,
108180
- /* 460 */ 142, 143, 144, 145, 112, 150, 114, 115, 105, 106,
108181
- /* 470 */ 107, 23, 23, 25, 49, 50, 118, 230, 97, 98,
108182
- /* 480 */ 165, 16, 113, 118, 120, 160, 117, 136, 113, 174,
108183
- /* 490 */ 175, 100, 117, 68, 69, 70, 71, 72, 73, 74,
108184
- /* 500 */ 75, 76, 77, 78, 79, 80, 160, 82, 83, 84,
108185
- /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 194,
108186
- /* 520 */ 25, 112, 23, 114, 115, 60, 150, 62, 150, 138,
108187
- /* 530 */ 150, 105, 106, 107, 19, 150, 36, 161, 162, 224,
108188
- /* 540 */ 194, 165, 217, 165, 112, 165, 114, 115, 49, 50,
108189
- /* 550 */ 165, 51, 174, 175, 174, 175, 166, 232, 58, 174,
108190
- /* 560 */ 175, 112, 237, 114, 115, 50, 22, 68, 69, 70,
108472
+ /* 430 */ 79, 80, 98, 82, 83, 84, 85, 86, 87, 88,
108473
+ /* 440 */ 89, 90, 91, 92, 19, 12, 224, 23, 23, 63,
108474
+ /* 450 */ 205, 23, 23, 60, 25, 62, 150, 214, 150, 67,
108475
+ /* 460 */ 22, 28, 94, 95, 96, 23, 221, 222, 223, 23,
108476
+ /* 470 */ 23, 165, 25, 165, 49, 50, 23, 44, 25, 46,
108477
+ /* 480 */ 174, 175, 174, 175, 23, 26, 100, 136, 25, 112,
108478
+ /* 490 */ 57, 114, 115, 68, 69, 70, 71, 72, 73, 74,
108479
+ /* 500 */ 75, 76, 77, 78, 79, 80, 97, 82, 83, 84,
108480
+ /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 22,
108481
+ /* 520 */ 23, 215, 23, 215, 138, 116, 50, 23, 30, 25,
108482
+ /* 530 */ 36, 138, 34, 99, 100, 101, 112, 128, 114, 115,
108483
+ /* 540 */ 112, 23, 114, 115, 110, 51, 48, 173, 49, 50,
108484
+ /* 550 */ 26, 27, 58, 94, 112, 181, 114, 115, 112, 16,
108485
+ /* 560 */ 114, 115, 22, 23, 67, 25, 160, 68, 69, 70,
108191108486
/* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108192
- /* 580 */ 160, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108193
- /* 590 */ 91, 92, 19, 215, 214, 205, 23, 7, 8, 9,
108194
- /* 600 */ 215, 155, 24, 22, 26, 150, 97, 26, 108, 129,
108195
- /* 610 */ 130, 221, 222, 223, 194, 0, 1, 2, 150, 104,
108196
- /* 620 */ 165, 126, 49, 50, 109, 116, 206, 207, 118, 174,
108197
- /* 630 */ 175, 22, 23, 165, 25, 22, 23, 128, 25, 118,
108198
- /* 640 */ 26, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108199
- /* 650 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
108200
- /* 660 */ 87, 88, 89, 90, 91, 92, 19, 150, 150, 165,
108201
- /* 670 */ 23, 160, 94, 227, 150, 94, 67, 231, 174, 175,
108202
- /* 680 */ 67, 213, 165, 165, 221, 222, 223, 150, 150, 165,
108203
- /* 690 */ 23, 32, 174, 175, 181, 182, 49, 50, 174, 175,
108204
- /* 700 */ 41, 188, 165, 165, 22, 194, 177, 11, 94, 23,
108205
- /* 710 */ 193, 174, 175, 160, 22, 68, 69, 70, 71, 72,
108206
- /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 217, 82,
108487
+ /* 580 */ 104, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108488
+ /* 590 */ 91, 92, 19, 19, 22, 23, 23, 25, 23, 95,
108489
+ /* 600 */ 194, 27, 108, 60, 25, 62, 150, 67, 169, 170,
108490
+ /* 610 */ 171, 35, 206, 207, 150, 221, 222, 223, 94, 95,
108491
+ /* 620 */ 160, 165, 49, 50, 120, 161, 162, 206, 207, 165,
108492
+ /* 630 */ 174, 175, 97, 98, 160, 241, 105, 106, 107, 67,
108493
+ /* 640 */ 25, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108494
+ /* 650 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
108495
+ /* 660 */ 87, 88, 89, 90, 91, 92, 19, 150, 194, 230,
108496
+ /* 670 */ 23, 7, 8, 9, 24, 150, 26, 35, 150, 219,
108497
+ /* 680 */ 150, 25, 165, 142, 143, 144, 145, 0, 1, 2,
108498
+ /* 690 */ 165, 217, 32, 165, 150, 165, 49, 50, 119, 174,
108499
+ /* 700 */ 175, 41, 174, 175, 174, 175, 23, 120, 25, 165,
108500
+ /* 710 */ 193, 237, 221, 222, 223, 68, 69, 70, 71, 72,
108501
+ /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
108207108502
/* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108208
- /* 740 */ 19, 150, 150, 150, 25, 24, 19, 194, 237, 150,
108209
- /* 750 */ 221, 222, 223, 25, 27, 23, 165, 165, 165, 242,
108210
- /* 760 */ 165, 23, 150, 25, 165, 174, 175, 174, 175, 174,
108211
- /* 770 */ 49, 50, 219, 150, 22, 23, 238, 165, 25, 22,
108212
- /* 780 */ 23, 23, 166, 167, 168, 193, 174, 175, 165, 68,
108503
+ /* 740 */ 19, 150, 22, 165, 94, 24, 150, 25, 150, 166,
108504
+ /* 750 */ 167, 168, 174, 175, 129, 130, 165, 213, 35, 242,
108505
+ /* 760 */ 150, 165, 27, 165, 150, 174, 175, 181, 182, 19,
108506
+ /* 770 */ 49, 50, 174, 175, 188, 165, 23, 27, 25, 165,
108507
+ /* 780 */ 144, 145, 160, 187, 174, 175, 135, 23, 137, 68,
108213108508
/* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108214108509
/* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88,
108215
- /* 810 */ 89, 90, 91, 92, 19, 150, 23, 165, 150, 67,
108216
- /* 820 */ 150, 25, 103, 95, 67, 35, 174, 175, 206, 207,
108217
- /* 830 */ 165, 150, 25, 165, 150, 165, 213, 150, 150, 174,
108218
- /* 840 */ 175, 35, 174, 175, 49, 50, 165, 52, 120, 165,
108219
- /* 850 */ 245, 246, 165, 165, 35, 174, 175, 187, 174, 175,
108220
- /* 860 */ 23, 50, 25, 68, 69, 70, 71, 72, 73, 74,
108510
+ /* 810 */ 89, 90, 91, 92, 19, 150, 194, 165, 150, 150,
108511
+ /* 820 */ 150, 150, 150, 150, 247, 248, 174, 175, 190, 191,
108512
+ /* 830 */ 165, 150, 118, 165, 165, 165, 165, 165, 165, 174,
108513
+ /* 840 */ 175, 219, 174, 175, 49, 50, 165, 52, 126, 245,
108514
+ /* 850 */ 246, 23, 238, 25, 23, 174, 175, 187, 187, 187,
108515
+ /* 860 */ 187, 39, 193, 68, 69, 70, 71, 72, 73, 74,
108221108516
/* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84,
108222108517
/* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150,
108223
- /* 890 */ 150, 165, 150, 150, 160, 23, 150, 25, 144, 145,
108224
- /* 900 */ 174, 175, 120, 216, 165, 165, 22, 165, 165, 150,
108225
- /* 910 */ 150, 165, 27, 174, 175, 104, 174, 175, 49, 50,
108226
- /* 920 */ 174, 175, 247, 248, 165, 165, 238, 187, 194, 23,
108227
- /* 930 */ 187, 25, 166, 174, 175, 190, 191, 68, 69, 70,
108518
+ /* 890 */ 150, 165, 150, 23, 160, 25, 150, 150, 160, 52,
108519
+ /* 900 */ 174, 175, 190, 191, 165, 165, 22, 165, 150, 29,
108520
+ /* 910 */ 150, 165, 165, 174, 175, 150, 174, 175, 49, 50,
108521
+ /* 920 */ 174, 175, 165, 165, 23, 165, 25, 25, 194, 52,
108522
+ /* 930 */ 165, 174, 194, 193, 174, 175, 160, 68, 69, 70,
108228108523
/* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108229108524
/* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108230
- /* 960 */ 91, 92, 19, 150, 150, 165, 150, 23, 150, 25,
108231
- /* 970 */ 23, 205, 25, 213, 174, 175, 190, 191, 165, 165,
108232
- /* 980 */ 118, 165, 150, 165, 150, 150, 23, 174, 175, 39,
108233
- /* 990 */ 174, 175, 49, 50, 173, 150, 23, 165, 52, 165,
108234
- /* 1000 */ 165, 187, 181, 22, 166, 166, 174, 175, 174, 175,
108525
+ /* 960 */ 91, 92, 19, 150, 150, 165, 150, 22, 150, 23,
108526
+ /* 970 */ 194, 213, 91, 92, 174, 175, 1, 2, 165, 165,
108527
+ /* 980 */ 22, 165, 150, 165, 150, 238, 150, 174, 175, 22,
108528
+ /* 990 */ 174, 175, 49, 50, 52, 150, 22, 165, 102, 165,
108529
+ /* 1000 */ 19, 165, 109, 238, 166, 166, 174, 175, 174, 175,
108235108530
/* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108236108531
/* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
108237108532
/* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165,
108238
- /* 1040 */ 150, 160, 150, 205, 205, 150, 150, 29, 174, 175,
108239
- /* 1050 */ 52, 216, 165, 22, 150, 165, 238, 165, 150, 150,
108240
- /* 1060 */ 165, 165, 49, 50, 174, 175, 49, 50, 23, 165,
108241
- /* 1070 */ 91, 92, 22, 165, 165, 194, 1, 2, 22, 52,
108242
- /* 1080 */ 193, 109, 174, 175, 71, 72, 69, 70, 71, 72,
108533
+ /* 1040 */ 150, 150, 166, 205, 205, 150, 20, 24, 174, 175,
108534
+ /* 1050 */ 43, 104, 165, 59, 53, 165, 165, 25, 150, 150,
108535
+ /* 1060 */ 165, 174, 175, 150, 174, 175, 49, 50, 53, 138,
108536
+ /* 1070 */ 150, 22, 104, 165, 165, 5, 1, 118, 165, 35,
108537
+ /* 1080 */ 27, 205, 174, 175, 193, 165, 69, 70, 71, 72,
108243108538
/* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
108244108539
/* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108245
- /* 1110 */ 19, 98, 150, 165, 150, 150, 150, 102, 150, 150,
108246
- /* 1120 */ 22, 19, 174, 175, 20, 24, 104, 165, 43, 165,
108247
- /* 1130 */ 165, 165, 150, 165, 165, 150, 174, 175, 174, 175,
108248
- /* 1140 */ 49, 50, 59, 53, 138, 25, 53, 165, 104, 22,
108249
- /* 1150 */ 165, 5, 118, 1, 76, 76, 174, 175, 193, 174,
108250
- /* 1160 */ 175, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108251
- /* 1170 */ 79, 80, 35, 82, 83, 84, 85, 86, 87, 88,
108252
- /* 1180 */ 89, 90, 91, 92, 19, 20, 150, 22, 150, 150,
108253
- /* 1190 */ 150, 26, 27, 27, 108, 127, 150, 150, 22, 25,
108254
- /* 1200 */ 22, 165, 37, 165, 165, 165, 119, 19, 20, 150,
108255
- /* 1210 */ 22, 165, 165, 150, 26, 27, 23, 1, 16, 20,
108256
- /* 1220 */ 150, 56, 119, 108, 165, 37, 121, 128, 165, 193,
108257
- /* 1230 */ 23, 66, 193, 174, 175, 165, 127, 174, 175, 16,
108258
- /* 1240 */ 23, 146, 147, 15, 56, 65, 150, 152, 140, 154,
108259
- /* 1250 */ 150, 86, 87, 88, 66, 160, 22, 150, 93, 94,
108260
- /* 1260 */ 95, 165, 150, 98, 150, 165, 3, 246, 4, 150,
108261
- /* 1270 */ 174, 175, 165, 150, 86, 87, 6, 165, 150, 165,
108262
- /* 1280 */ 164, 93, 94, 95, 165, 149, 98, 149, 165, 194,
108263
- /* 1290 */ 180, 180, 249, 165, 129, 130, 131, 132, 133, 134,
108264
- /* 1300 */ 193, 150, 174, 175, 116, 193, 19, 20, 150, 22,
108265
- /* 1310 */ 249, 149, 217, 26, 27, 151, 165, 129, 130, 131,
108266
- /* 1320 */ 132, 133, 134, 165, 37, 174, 175, 150, 149, 19,
108267
- /* 1330 */ 20, 150, 22, 150, 150, 150, 26, 27, 13, 244,
108268
- /* 1340 */ 151, 159, 165, 56, 25, 116, 165, 37, 165, 165,
108269
- /* 1350 */ 165, 174, 175, 66, 150, 174, 175, 174, 175, 174,
108270
- /* 1360 */ 175, 194, 150, 150, 150, 126, 56, 199, 124, 165,
108271
- /* 1370 */ 200, 150, 150, 86, 87, 150, 66, 165, 165, 165,
108272
- /* 1380 */ 93, 94, 95, 150, 122, 98, 165, 165, 123, 22,
108273
- /* 1390 */ 165, 201, 150, 26, 27, 150, 86, 87, 165, 174,
108274
- /* 1400 */ 175, 203, 202, 93, 94, 95, 125, 165, 98, 150,
108275
- /* 1410 */ 165, 150, 225, 135, 157, 118, 129, 130, 131, 132,
108276
- /* 1420 */ 133, 134, 5, 150, 165, 157, 165, 10, 11, 12,
108277
- /* 1430 */ 13, 14, 150, 66, 17, 174, 175, 210, 165, 129,
108278
- /* 1440 */ 130, 131, 132, 133, 134, 150, 104, 165, 31, 150,
108279
- /* 1450 */ 33, 150, 150, 86, 87, 150, 174, 175, 211, 42,
108280
- /* 1460 */ 165, 94, 121, 210, 165, 98, 165, 165, 176, 211,
108281
- /* 1470 */ 165, 211, 55, 104, 57, 184, 210, 47, 61, 176,
108282
- /* 1480 */ 176, 64, 103, 176, 178, 22, 92, 179, 176, 176,
108283
- /* 1490 */ 176, 156, 18, 184, 179, 228, 129, 130, 131, 228,
108284
- /* 1500 */ 157, 156, 45, 157, 156, 236, 157, 157, 135, 235,
108285
- /* 1510 */ 156, 189, 157, 68, 218, 189, 22, 199, 156, 192,
108286
- /* 1520 */ 157, 18, 105, 106, 107, 192, 192, 199, 111, 192,
108287
- /* 1530 */ 240, 157, 40, 116, 218, 157, 189, 157, 240, 38,
108288
- /* 1540 */ 153, 166, 198, 243, 178, 209, 182, 196, 177, 226,
108289
- /* 1550 */ 230, 230, 166, 177, 177, 166, 139, 199, 199, 148,
108290
- /* 1560 */ 195, 209, 209, 239, 196, 166, 234, 183, 239, 208,
108291
- /* 1570 */ 174, 233, 191, 183, 183, 174, 92, 250, 186, 186,
108540
+ /* 1110 */ 19, 150, 150, 165, 150, 150, 150, 108, 76, 150,
108541
+ /* 1120 */ 22, 76, 174, 175, 127, 216, 165, 165, 25, 165,
108542
+ /* 1130 */ 165, 165, 150, 213, 165, 174, 175, 150, 174, 175,
108543
+ /* 1140 */ 49, 50, 22, 150, 23, 1, 119, 165, 16, 121,
108544
+ /* 1150 */ 20, 108, 165, 119, 23, 193, 174, 175, 165, 193,
108545
+ /* 1160 */ 127, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108546
+ /* 1170 */ 79, 80, 23, 82, 83, 84, 85, 86, 87, 88,
108547
+ /* 1180 */ 89, 90, 91, 92, 19, 20, 193, 22, 150, 150,
108548
+ /* 1190 */ 150, 26, 27, 128, 16, 15, 150, 140, 65, 3,
108549
+ /* 1200 */ 164, 22, 37, 165, 165, 165, 4, 19, 20, 150,
108550
+ /* 1210 */ 22, 165, 174, 175, 26, 27, 246, 180, 149, 6,
108551
+ /* 1220 */ 249, 56, 249, 149, 165, 37, 149, 180, 149, 151,
108552
+ /* 1230 */ 13, 66, 193, 174, 175, 150, 25, 151, 116, 159,
108553
+ /* 1240 */ 199, 146, 147, 126, 56, 194, 150, 152, 200, 154,
108554
+ /* 1250 */ 165, 86, 87, 88, 66, 160, 201, 150, 93, 94,
108555
+ /* 1260 */ 95, 165, 123, 98, 150, 150, 124, 122, 202, 135,
108556
+ /* 1270 */ 174, 175, 165, 150, 86, 87, 150, 150, 150, 165,
108557
+ /* 1280 */ 165, 93, 94, 95, 203, 150, 98, 125, 165, 194,
108558
+ /* 1290 */ 150, 165, 165, 165, 129, 130, 131, 132, 133, 134,
108559
+ /* 1300 */ 165, 174, 175, 157, 116, 165, 19, 20, 150, 22,
108560
+ /* 1310 */ 150, 118, 217, 26, 27, 225, 150, 129, 130, 131,
108561
+ /* 1320 */ 132, 133, 134, 165, 37, 165, 157, 150, 210, 19,
108562
+ /* 1330 */ 20, 165, 22, 150, 150, 150, 26, 27, 104, 244,
108563
+ /* 1340 */ 174, 175, 165, 56, 121, 104, 210, 37, 165, 165,
108564
+ /* 1350 */ 165, 174, 175, 66, 150, 150, 150, 174, 175, 174,
108565
+ /* 1360 */ 175, 211, 150, 211, 210, 176, 56, 211, 176, 165,
108566
+ /* 1370 */ 165, 165, 150, 86, 87, 150, 66, 165, 174, 175,
108567
+ /* 1380 */ 93, 94, 95, 150, 184, 98, 150, 165, 47, 22,
108568
+ /* 1390 */ 165, 176, 150, 26, 27, 150, 86, 87, 165, 174,
108569
+ /* 1400 */ 175, 165, 178, 93, 94, 95, 103, 165, 98, 150,
108570
+ /* 1410 */ 165, 150, 22, 176, 179, 228, 129, 130, 131, 132,
108571
+ /* 1420 */ 133, 134, 5, 150, 165, 92, 165, 10, 11, 12,
108572
+ /* 1430 */ 13, 14, 150, 66, 17, 174, 175, 228, 165, 129,
108573
+ /* 1440 */ 130, 131, 132, 133, 134, 150, 184, 165, 31, 150,
108574
+ /* 1450 */ 33, 150, 150, 86, 87, 172, 174, 175, 96, 42,
108575
+ /* 1460 */ 165, 94, 176, 179, 165, 98, 165, 165, 176, 174,
108576
+ /* 1470 */ 175, 156, 55, 176, 57, 18, 157, 156, 61, 157,
108577
+ /* 1480 */ 156, 64, 157, 157, 235, 45, 236, 135, 156, 189,
108578
+ /* 1490 */ 68, 157, 218, 189, 22, 199, 129, 130, 131, 156,
108579
+ /* 1500 */ 192, 157, 18, 192, 192, 192, 199, 189, 218, 240,
108580
+ /* 1510 */ 157, 40, 240, 157, 157, 38, 153, 166, 243, 196,
108581
+ /* 1520 */ 226, 230, 105, 106, 107, 198, 209, 177, 111, 182,
108582
+ /* 1530 */ 166, 177, 177, 116, 166, 230, 178, 239, 199, 209,
108583
+ /* 1540 */ 209, 199, 148, 166, 196, 239, 208, 233, 172, 183,
108584
+ /* 1550 */ 234, 191, 183, 183, 195, 174, 139, 186, 186, 174,
108585
+ /* 1560 */ 92,
108292108586
};
108293
-#define YY_SHIFT_USE_DFLT (-81)
108294
-#define YY_SHIFT_COUNT (417)
108295
-#define YY_SHIFT_MIN (-80)
108296
-#define YY_SHIFT_MAX (1503)
108587
+#define YY_SHIFT_USE_DFLT (-70)
108588
+#define YY_SHIFT_COUNT (418)
108589
+#define YY_SHIFT_MIN (-69)
108590
+#define YY_SHIFT_MAX (1484)
108297108591
static const short yy_shift_ofst[] = {
108298
- /* 0 */ 1075, 1188, 1417, 1188, 1287, 1287, 138, 138, 1, -19,
108299
- /* 10 */ 1287, 1287, 1287, 1287, 340, -2, 129, 129, 795, 1165,
108592
+ /* 0 */ 975, 1188, 1417, 1188, 1287, 1287, 138, 138, 368, -19,
108593
+ /* 10 */ 1287, 1287, 1287, 1287, 272, 524, 129, 129, 795, 1165,
108300108594
/* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108301108595
/* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108302108596
/* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
108303108597
/* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108304
- /* 60 */ 1287, 1287, 212, -2, -2, -8, -8, 614, 1229, 55,
108598
+ /* 60 */ 1287, 1287, 212, 524, 524, 213, 213, 459, 1122, 55,
108305108599
/* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869,
108306108600
/* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
108307108601
/* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45,
108308
- /* 100 */ -45, -45, -45, -45, -1, 57, 28, 361, -2, -2,
108309
- /* 110 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108310
- /* 120 */ -2, -2, -2, -2, 391, 515, -2, -2, -2, -2,
108311
- /* 130 */ -2, 509, -80, 614, 979, 1484, -81, -81, -81, 1367,
108312
- /* 140 */ 75, 182, 182, 314, 311, 364, 219, 86, 613, 609,
108313
- /* 150 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108314
- /* 160 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108315
- /* 170 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108316
- /* 180 */ -2, -2, 578, 578, 578, 615, 1229, 1229, 1229, -81,
108317
- /* 190 */ -81, -81, 160, 168, 168, 283, 500, 500, 500, 278,
108318
- /* 200 */ 449, 330, 432, 409, 352, 48, 48, 48, 48, 426,
108319
- /* 210 */ 286, 48, 48, 728, 581, 369, 590, 495, 224, 224,
108320
- /* 220 */ 727, 495, 727, 719, 614, 659, 614, 659, 811, 659,
108321
- /* 230 */ 224, 257, 480, 480, 614, 144, 375, -18, 1501, 1297,
108322
- /* 240 */ 1297, 1492, 1492, 1297, 1494, 1445, 1239, 1503, 1503, 1503,
108323
- /* 250 */ 1503, 1297, 1474, 1239, 1494, 1445, 1445, 1297, 1474, 1373,
108324
- /* 260 */ 1457, 1297, 1297, 1474, 1297, 1474, 1297, 1474, 1463, 1369,
108325
- /* 270 */ 1369, 1369, 1430, 1394, 1394, 1463, 1369, 1379, 1369, 1430,
108326
- /* 280 */ 1369, 1369, 1341, 1342, 1341, 1342, 1341, 1342, 1297, 1297,
108327
- /* 290 */ 1278, 1281, 1262, 1244, 1265, 1239, 1229, 1319, 1325, 1325,
108328
- /* 300 */ 1270, 1270, 1270, 1270, -81, -81, -81, -81, -81, -81,
108329
- /* 310 */ 1013, 242, 757, 752, 465, 363, 947, 232, 944, 906,
108330
- /* 320 */ 872, 837, 738, 448, 381, 230, 84, 362, 300, 1264,
108331
- /* 330 */ 1263, 1234, 1108, 1228, 1180, 1223, 1217, 1207, 1099, 1174,
108332
- /* 340 */ 1109, 1115, 1103, 1199, 1105, 1202, 1216, 1087, 1193, 1178,
108333
- /* 350 */ 1174, 1176, 1068, 1079, 1078, 1086, 1166, 1137, 1034, 1152,
108334
- /* 360 */ 1146, 1127, 1044, 1006, 1093, 1120, 1090, 1083, 1085, 1022,
108335
- /* 370 */ 1101, 1104, 1102, 972, 1015, 1098, 1027, 1056, 1050, 1045,
108336
- /* 380 */ 1031, 998, 1018, 981, 946, 950, 973, 963, 862, 885,
108337
- /* 390 */ 819, 884, 782, 796, 806, 807, 790, 796, 793, 758,
108338
- /* 400 */ 753, 732, 692, 696, 682, 686, 667, 544, 291, 521,
108339
- /* 410 */ 510, 365, 358, 139, 114, 54, 14, 25,
108602
+ /* 100 */ -45, -45, -45, -45, -1, 6, -64, 524, 524, 524,
108603
+ /* 110 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108604
+ /* 120 */ 524, 524, 524, 386, 207, 524, 524, 524, 524, 524,
108605
+ /* 130 */ 409, -13, 459, 881, 1468, -70, -70, -70, 1367, 57,
108606
+ /* 140 */ 433, 433, 297, 236, 219, 136, 91, 572, 540, 524,
108607
+ /* 150 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108608
+ /* 160 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108609
+ /* 170 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108610
+ /* 180 */ 650, 650, 650, 687, 1122, 1122, 1122, -70, -70, -70,
108611
+ /* 190 */ 204, 204, 434, 434, 494, 494, 494, 504, 446, 292,
108612
+ /* 200 */ 442, 428, 424, 77, 377, 377, 377, 377, 531, 498,
108613
+ /* 210 */ 377, 377, 278, 215, 227, 664, 722, 574, 574, 750,
108614
+ /* 220 */ 722, 750, 229, 459, 660, 459, 660, 476, 660, 574,
108615
+ /* 230 */ 651, 625, 625, 459, 579, 273, -18, 1477, 1193, 1193,
108616
+ /* 240 */ 1471, 1471, 1193, 1472, 1422, 1117, 1484, 1484, 1484, 1484,
108617
+ /* 250 */ 1193, 1457, 1117, 1472, 1422, 1422, 1193, 1457, 1352, 1440,
108618
+ /* 260 */ 1193, 1193, 1457, 1193, 1457, 1193, 1457, 1390, 1241, 1241,
108619
+ /* 270 */ 1241, 1362, 1341, 1333, 1333, 1390, 1241, 1303, 1241, 1341,
108620
+ /* 280 */ 1241, 1241, 1223, 1234, 1223, 1234, 1223, 1234, 1193, 1193,
108621
+ /* 290 */ 1134, 1162, 1145, 1142, 1139, 1117, 1122, 1211, 1217, 1217,
108622
+ /* 300 */ 1213, 1213, 1213, 1213, -70, -70, -70, -70, -70, -70,
108623
+ /* 310 */ 334, 393, 497, 392, 543, 275, 901, 98, 870, 828,
108624
+ /* 320 */ 753, 683, 453, 447, 535, 221, 140, 429, 54, 1202,
108625
+ /* 330 */ 1196, 1179, 1057, 1180, 1133, 1178, 1149, 1131, 1065, 1103,
108626
+ /* 340 */ 1033, 1043, 1034, 1130, 1028, 1132, 1144, 1027, 1121, 1120,
108627
+ /* 350 */ 1103, 1098, 997, 1045, 1042, 1009, 1053, 1044, 959, 1075,
108628
+ /* 360 */ 1070, 1049, 968, 931, 1015, 1032, 1001, 994, 1007, 947,
108629
+ /* 370 */ 1023, 1026, 981, 893, 896, 974, 942, 967, 958, 946,
108630
+ /* 380 */ 945, 877, 902, 880, 884, 847, 822, 831, 764, 714,
108631
+ /* 390 */ 735, 723, 720, 587, 615, 642, 656, 576, 615, 575,
108632
+ /* 400 */ 518, 463, 461, 438, 405, 390, 387, 376, 303, 224,
108633
+ /* 410 */ 271, 190, 92, 72, 69, 145, 113, 33, 28,
108340108634
};
108341108635
#define YY_REDUCE_USE_DFLT (-169)
108342108636
#define YY_REDUCE_COUNT (309)
108343108637
#define YY_REDUCE_MIN (-168)
108344
-#define YY_REDUCE_MAX (1411)
108638
+#define YY_REDUCE_MAX (1394)
108345108639
static const short yy_reduce_ofst[] = {
108346
- /* 0 */ 318, 90, 1095, 221, 157, 21, 159, 18, 150, 390,
108347
- /* 10 */ 385, 378, 380, 315, 325, 249, 529, -71, 8, 1282,
108348
- /* 20 */ 1261, 1225, 1185, 1183, 1181, 1177, 1151, 1128, 1096, 1063,
108349
- /* 30 */ 1059, 985, 982, 964, 962, 948, 908, 890, 874, 834,
108350
- /* 40 */ 832, 816, 813, 800, 759, 746, 742, 739, 726, 684,
108351
- /* 50 */ 681, 668, 665, 652, 612, 593, 591, 537, 524, 518,
108352
- /* 60 */ 504, 455, 511, 376, 517, 247, -168, 24, 420, 463,
108353
- /* 70 */ 463, 463, 463, 463, 463, 463, 463, 463, 463, 463,
108354
- /* 80 */ 463, 463, 463, 463, 463, 463, 463, 463, 463, 463,
108355
- /* 90 */ 463, 463, 463, 463, 463, 463, 463, 463, 463, 463,
108356
- /* 100 */ 463, 463, 463, 463, 463, -74, 463, 463, 1112, 835,
108357
- /* 110 */ 1107, 1039, 1036, 965, 887, 845, 818, 760, 688, 687,
108358
- /* 120 */ 538, 743, 623, 592, 446, 513, 814, 740, 670, 156,
108359
- /* 130 */ 468, 553, 184, 616, 463, 463, 463, 463, 463, 595,
108360
- /* 140 */ 821, 786, 745, 909, 1305, 1302, 1301, 1299, 675, 675,
108361
- /* 150 */ 1295, 1273, 1259, 1245, 1242, 1233, 1222, 1221, 1214, 1213,
108362
- /* 160 */ 1212, 1204, 1184, 1158, 1123, 1119, 1114, 1100, 1070, 1047,
108363
- /* 170 */ 1046, 1040, 1038, 969, 968, 966, 909, 904, 896, 895,
108364
- /* 180 */ 892, 599, 839, 838, 766, 754, 881, 734, 346, 605,
108365
- /* 190 */ 622, -94, 1393, 1401, 1396, 1392, 1391, 1390, 1384, 1361,
108366
- /* 200 */ 1365, 1381, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1332,
108367
- /* 210 */ 1338, 1365, 1365, 1361, 1399, 1368, 1411, 1359, 1353, 1352,
108368
- /* 220 */ 1329, 1358, 1324, 1366, 1389, 1377, 1386, 1376, 1364, 1371,
108369
- /* 230 */ 1336, 1323, 1321, 1320, 1375, 1344, 1351, 1387, 1300, 1380,
108370
- /* 240 */ 1378, 1298, 1290, 1374, 1316, 1347, 1328, 1337, 1334, 1333,
108371
- /* 250 */ 1327, 1363, 1362, 1318, 1296, 1326, 1322, 1355, 1354, 1269,
108372
- /* 260 */ 1274, 1350, 1349, 1348, 1346, 1345, 1343, 1335, 1315, 1314,
108373
- /* 270 */ 1313, 1312, 1309, 1271, 1267, 1308, 1307, 1306, 1304, 1291,
108374
- /* 280 */ 1303, 1292, 1260, 1266, 1258, 1253, 1247, 1227, 1268, 1257,
108375
- /* 290 */ 1187, 1198, 1200, 1190, 1170, 1168, 1167, 1182, 1189, 1164,
108376
- /* 300 */ 1179, 1162, 1138, 1136, 1061, 1043, 1021, 1111, 1110, 1116,
108640
+ /* 0 */ 541, 90, 1095, 147, 86, 19, 18, -49, 10, 245,
108641
+ /* 10 */ 308, 306, 243, 222, -41, -51, 181, -71, 394, 1295,
108642
+ /* 20 */ 1282, 1261, 1225, 1204, 1185, 1183, 1177, 1166, 1127, 1096,
108643
+ /* 30 */ 1059, 1038, 982, 964, 961, 948, 908, 890, 887, 874,
108644
+ /* 40 */ 834, 832, 816, 813, 800, 760, 746, 742, 739, 726,
108645
+ /* 50 */ 681, 668, 665, 652, 610, 598, 591, 578, 530, 528,
108646
+ /* 60 */ 525, 456, 474, 464, 517, 439, -168, 208, 406, 491,
108647
+ /* 70 */ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
108648
+ /* 80 */ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
108649
+ /* 90 */ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
108650
+ /* 100 */ 491, 491, 491, 491, 491, 491, 491, 1039, 909, 993,
108651
+ /* 110 */ 966, 962, 891, 845, 740, 765, 920, 747, 27, 614,
108652
+ /* 120 */ 673, 758, 669, -119, 586, 672, 671, 670, 596, 544,
108653
+ /* 130 */ 622, 460, 583, 491, 491, 491, 491, 491, 757, 374,
108654
+ /* 140 */ 712, 638, 913, 1302, 1301, 1299, 1273, 577, 577, 1259,
108655
+ /* 150 */ 1245, 1242, 1236, 1233, 1222, 1212, 1206, 1205, 1184, 1160,
108656
+ /* 160 */ 1158, 1140, 1135, 1128, 1126, 1123, 1115, 1114, 1107, 1085,
108657
+ /* 170 */ 1046, 1040, 987, 969, 965, 913, 895, 836, 818, 814,
108658
+ /* 180 */ 876, 839, 838, 636, 776, 738, 734, 604, 421, 62,
108659
+ /* 190 */ 1385, 1381, 1372, 1371, 1370, 1369, 1366, 1338, 1359, 1360,
108660
+ /* 200 */ 1359, 1359, 1359, 1376, 1359, 1359, 1359, 1359, 1316, 1314,
108661
+ /* 210 */ 1359, 1359, 1338, 1377, 1348, 1394, 1342, 1331, 1330, 1306,
108662
+ /* 220 */ 1339, 1298, 1358, 1368, 1355, 1364, 1354, 1347, 1350, 1317,
108663
+ /* 230 */ 1294, 1305, 1291, 1351, 1327, 1323, 1363, 1275, 1357, 1356,
108664
+ /* 240 */ 1272, 1269, 1353, 1290, 1318, 1307, 1313, 1312, 1311, 1308,
108665
+ /* 250 */ 1344, 1343, 1296, 1274, 1304, 1300, 1334, 1332, 1250, 1249,
108666
+ /* 260 */ 1326, 1325, 1324, 1322, 1321, 1319, 1315, 1284, 1297, 1292,
108667
+ /* 270 */ 1286, 1283, 1262, 1209, 1187, 1235, 1237, 1224, 1215, 1200,
108668
+ /* 280 */ 1192, 1189, 1156, 1154, 1152, 1136, 1150, 1118, 1169, 1146,
108669
+ /* 290 */ 1090, 1081, 1066, 1055, 1048, 1041, 1051, 1080, 1086, 1078,
108670
+ /* 300 */ 1079, 1077, 1074, 1069, 973, 971, 970, 1047, 1037, 1036,
108377108671
};
108378108672
static const YYACTIONTYPE yy_default[] = {
108379
- /* 0 */ 634, 868, 956, 956, 868, 868, 956, 956, 956, 758,
108380
- /* 10 */ 956, 956, 956, 866, 956, 956, 786, 786, 930, 956,
108381
- /* 20 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108382
- /* 30 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108383
- /* 40 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108384
- /* 50 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108385
- /* 60 */ 956, 956, 956, 956, 956, 956, 956, 673, 762, 792,
108386
- /* 70 */ 956, 956, 956, 956, 956, 956, 956, 956, 929, 931,
108387
- /* 80 */ 800, 799, 909, 773, 797, 790, 794, 869, 862, 863,
108388
- /* 90 */ 861, 865, 870, 956, 793, 829, 846, 828, 840, 845,
108389
- /* 100 */ 852, 844, 841, 831, 830, 665, 832, 833, 956, 956,
108390
- /* 110 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108391
- /* 120 */ 956, 956, 956, 956, 660, 727, 956, 956, 956, 956,
108392
- /* 130 */ 956, 956, 956, 956, 834, 835, 849, 848, 847, 956,
108393
- /* 140 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108394
- /* 150 */ 956, 936, 934, 956, 881, 956, 956, 956, 956, 956,
108395
- /* 160 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108396
- /* 170 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108397
- /* 180 */ 956, 640, 758, 758, 758, 634, 956, 956, 956, 948,
108398
- /* 190 */ 762, 752, 718, 956, 956, 956, 956, 956, 956, 956,
108399
- /* 200 */ 956, 956, 956, 956, 956, 802, 741, 919, 921, 956,
108400
- /* 210 */ 902, 739, 662, 760, 675, 750, 642, 796, 775, 775,
108401
- /* 220 */ 914, 796, 914, 699, 956, 786, 956, 786, 696, 786,
108402
- /* 230 */ 775, 864, 956, 956, 956, 759, 750, 956, 941, 766,
108403
- /* 240 */ 766, 933, 933, 766, 808, 731, 796, 738, 738, 738,
108404
- /* 250 */ 738, 766, 657, 796, 808, 731, 731, 766, 657, 908,
108405
- /* 260 */ 906, 766, 766, 657, 766, 657, 766, 657, 874, 729,
108406
- /* 270 */ 729, 729, 714, 878, 878, 874, 729, 699, 729, 714,
108407
- /* 280 */ 729, 729, 779, 774, 779, 774, 779, 774, 766, 766,
108408
- /* 290 */ 956, 791, 780, 789, 787, 796, 956, 717, 650, 650,
108409
- /* 300 */ 639, 639, 639, 639, 953, 953, 948, 701, 701, 683,
108410
- /* 310 */ 956, 956, 956, 956, 956, 956, 956, 883, 956, 956,
108411
- /* 320 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108412
- /* 330 */ 635, 943, 956, 956, 940, 956, 956, 956, 956, 801,
108413
- /* 340 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108414
- /* 350 */ 918, 956, 956, 956, 956, 956, 956, 956, 912, 956,
108415
- /* 360 */ 956, 956, 956, 956, 956, 905, 904, 956, 956, 956,
108416
- /* 370 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108417
- /* 380 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108418
- /* 390 */ 956, 956, 956, 788, 956, 781, 956, 867, 956, 956,
108419
- /* 400 */ 956, 956, 956, 956, 956, 956, 956, 956, 744, 817,
108420
- /* 410 */ 956, 816, 820, 815, 667, 956, 648, 956, 631, 636,
108421
- /* 420 */ 952, 955, 954, 951, 950, 949, 944, 942, 939, 938,
108422
- /* 430 */ 937, 935, 932, 928, 887, 885, 892, 891, 890, 889,
108423
- /* 440 */ 888, 886, 884, 882, 803, 798, 795, 927, 880, 740,
108424
- /* 450 */ 737, 736, 656, 945, 911, 920, 807, 806, 809, 917,
108425
- /* 460 */ 916, 915, 913, 910, 897, 805, 804, 732, 872, 871,
108426
- /* 470 */ 659, 901, 900, 899, 903, 907, 898, 768, 658, 655,
108427
- /* 480 */ 664, 721, 720, 728, 726, 725, 724, 723, 722, 719,
108428
- /* 490 */ 666, 674, 685, 713, 698, 697, 877, 879, 876, 875,
108429
- /* 500 */ 706, 705, 711, 710, 709, 708, 707, 704, 703, 702,
108430
- /* 510 */ 695, 694, 700, 693, 716, 715, 712, 692, 735, 734,
108431
- /* 520 */ 733, 730, 691, 690, 689, 820, 688, 687, 826, 825,
108432
- /* 530 */ 813, 856, 755, 754, 753, 765, 764, 777, 776, 811,
108433
- /* 540 */ 810, 778, 763, 757, 756, 772, 771, 770, 769, 761,
108434
- /* 550 */ 751, 783, 785, 784, 782, 858, 767, 855, 926, 925,
108435
- /* 560 */ 924, 923, 922, 860, 859, 827, 824, 678, 679, 895,
108436
- /* 570 */ 894, 896, 893, 681, 680, 677, 676, 857, 746, 745,
108437
- /* 580 */ 853, 850, 842, 838, 854, 851, 843, 839, 837, 836,
108438
- /* 590 */ 822, 821, 819, 818, 814, 823, 669, 747, 743, 742,
108439
- /* 600 */ 812, 749, 748, 686, 684, 682, 663, 661, 654, 652,
108440
- /* 610 */ 651, 653, 649, 647, 646, 645, 644, 643, 672, 671,
108441
- /* 620 */ 670, 668, 667, 641, 638, 637, 633, 632, 630,
108673
+ /* 0 */ 632, 864, 952, 952, 864, 864, 952, 952, 683, 754,
108674
+ /* 10 */ 952, 952, 952, 862, 952, 952, 782, 782, 926, 952,
108675
+ /* 20 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108676
+ /* 30 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108677
+ /* 40 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108678
+ /* 50 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108679
+ /* 60 */ 952, 952, 952, 952, 952, 952, 952, 671, 758, 788,
108680
+ /* 70 */ 952, 952, 952, 952, 952, 952, 952, 952, 925, 927,
108681
+ /* 80 */ 796, 795, 905, 769, 793, 786, 790, 865, 858, 859,
108682
+ /* 90 */ 857, 861, 866, 952, 789, 825, 842, 824, 836, 841,
108683
+ /* 100 */ 848, 840, 837, 827, 826, 828, 829, 952, 952, 952,
108684
+ /* 110 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108685
+ /* 120 */ 952, 952, 952, 658, 723, 952, 952, 952, 952, 952,
108686
+ /* 130 */ 952, 952, 952, 830, 831, 845, 844, 843, 952, 952,
108687
+ /* 140 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108688
+ /* 150 */ 932, 930, 952, 877, 952, 952, 952, 952, 952, 952,
108689
+ /* 160 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108690
+ /* 170 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 638,
108691
+ /* 180 */ 754, 754, 754, 632, 952, 952, 952, 944, 758, 748,
108692
+ /* 190 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108693
+ /* 200 */ 952, 952, 952, 683, 798, 737, 915, 917, 952, 898,
108694
+ /* 210 */ 735, 660, 756, 673, 746, 640, 792, 771, 771, 910,
108695
+ /* 220 */ 792, 910, 697, 952, 782, 952, 782, 694, 782, 771,
108696
+ /* 230 */ 860, 952, 952, 952, 755, 746, 952, 937, 762, 762,
108697
+ /* 240 */ 929, 929, 762, 804, 727, 792, 734, 734, 734, 734,
108698
+ /* 250 */ 762, 655, 792, 804, 727, 727, 762, 655, 904, 902,
108699
+ /* 260 */ 762, 762, 655, 762, 655, 762, 655, 870, 725, 725,
108700
+ /* 270 */ 725, 683, 712, 874, 874, 870, 725, 697, 725, 712,
108701
+ /* 280 */ 725, 725, 775, 770, 775, 770, 775, 770, 762, 762,
108702
+ /* 290 */ 952, 787, 776, 785, 783, 792, 952, 715, 648, 648,
108703
+ /* 300 */ 637, 637, 637, 637, 949, 949, 944, 699, 699, 681,
108704
+ /* 310 */ 952, 952, 952, 952, 952, 952, 952, 879, 952, 952,
108705
+ /* 320 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108706
+ /* 330 */ 633, 939, 952, 952, 936, 952, 952, 952, 952, 797,
108707
+ /* 340 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108708
+ /* 350 */ 914, 952, 952, 952, 952, 952, 952, 952, 908, 952,
108709
+ /* 360 */ 952, 952, 952, 952, 952, 901, 900, 952, 952, 952,
108710
+ /* 370 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108711
+ /* 380 */ 952, 952, 716, 952, 952, 952, 952, 952, 952, 952,
108712
+ /* 390 */ 952, 952, 952, 952, 784, 952, 777, 952, 863, 952,
108713
+ /* 400 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 740,
108714
+ /* 410 */ 813, 952, 812, 816, 811, 665, 952, 646, 952, 629,
108715
+ /* 420 */ 634, 948, 951, 950, 947, 946, 945, 940, 938, 935,
108716
+ /* 430 */ 934, 933, 931, 928, 924, 883, 881, 888, 887, 886,
108717
+ /* 440 */ 885, 884, 882, 880, 878, 799, 794, 791, 923, 876,
108718
+ /* 450 */ 736, 733, 732, 654, 941, 907, 916, 803, 802, 805,
108719
+ /* 460 */ 913, 912, 911, 909, 906, 893, 801, 800, 728, 868,
108720
+ /* 470 */ 867, 657, 897, 896, 895, 899, 903, 894, 764, 656,
108721
+ /* 480 */ 653, 662, 718, 724, 722, 721, 720, 719, 717, 664,
108722
+ /* 490 */ 672, 682, 711, 696, 695, 873, 875, 872, 871, 704,
108723
+ /* 500 */ 703, 709, 708, 707, 706, 705, 702, 701, 700, 693,
108724
+ /* 510 */ 692, 698, 691, 714, 713, 710, 690, 731, 730, 729,
108725
+ /* 520 */ 726, 689, 688, 687, 816, 686, 685, 822, 821, 809,
108726
+ /* 530 */ 852, 751, 750, 749, 761, 760, 773, 772, 807, 806,
108727
+ /* 540 */ 774, 759, 753, 752, 768, 767, 766, 765, 757, 747,
108728
+ /* 550 */ 779, 781, 780, 778, 854, 763, 851, 922, 921, 920,
108729
+ /* 560 */ 919, 918, 856, 855, 823, 820, 676, 677, 891, 890,
108730
+ /* 570 */ 892, 889, 679, 678, 675, 674, 853, 742, 741, 849,
108731
+ /* 580 */ 846, 838, 834, 850, 847, 839, 835, 833, 832, 818,
108732
+ /* 590 */ 817, 815, 814, 810, 819, 667, 743, 739, 738, 808,
108733
+ /* 600 */ 745, 744, 684, 680, 661, 659, 652, 650, 649, 651,
108734
+ /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666,
108735
+ /* 620 */ 665, 639, 636, 635, 631, 630, 628,
108442108736
};
108443108737
108444108738
/* The next table maps tokens into fallback tokens. If a construct
108445108739
** like the following:
108446108740
**
@@ -108639,11 +108933,11 @@
108639108933
"create_table", "create_table_args", "createkw", "temp",
108640108934
"ifnotexists", "dbnm", "columnlist", "conslist_opt",
108641108935
"select", "column", "columnid", "type",
108642108936
"carglist", "id", "ids", "typetoken",
108643108937
"typename", "signed", "plus_num", "minus_num",
108644
- "carg", "ccons", "term", "expr",
108938
+ "cname", "ccons", "term", "expr",
108645108939
"onconf", "sortorder", "autoinc", "idxlist_opt",
108646108940
"refargs", "defer_subclause", "refarg", "refact",
108647108941
"init_deferred_pred_opt", "conslist", "tcons", "idxlist",
108648108942
"defer_subclause_opt", "orconf", "resolvetype", "raisetype",
108649108943
"ifexists", "fullname", "oneselect", "multiselect_op",
@@ -108719,14 +109013,14 @@
108719109013
/* 48 */ "typetoken ::= typename LP signed COMMA signed RP",
108720109014
/* 49 */ "typename ::= ids",
108721109015
/* 50 */ "typename ::= typename ids",
108722109016
/* 51 */ "signed ::= plus_num",
108723109017
/* 52 */ "signed ::= minus_num",
108724
- /* 53 */ "carglist ::= carglist carg",
109018
+ /* 53 */ "carglist ::= carglist cname ccons",
108725109019
/* 54 */ "carglist ::=",
108726
- /* 55 */ "carg ::= CONSTRAINT nm ccons",
108727
- /* 56 */ "carg ::= ccons",
109020
+ /* 55 */ "cname ::= CONSTRAINT nm",
109021
+ /* 56 */ "cname ::=",
108728109022
/* 57 */ "ccons ::= DEFAULT term",
108729109023
/* 58 */ "ccons ::= DEFAULT LP expr RP",
108730109024
/* 59 */ "ccons ::= DEFAULT PLUS term",
108731109025
/* 60 */ "ccons ::= DEFAULT MINUS term",
108732109026
/* 61 */ "ccons ::= DEFAULT id",
@@ -108756,247 +109050,245 @@
108756109050
/* 85 */ "init_deferred_pred_opt ::=",
108757109051
/* 86 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
108758109052
/* 87 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
108759109053
/* 88 */ "conslist_opt ::=",
108760109054
/* 89 */ "conslist_opt ::= COMMA conslist",
108761
- /* 90 */ "conslist ::= conslist COMMA tcons",
108762
- /* 91 */ "conslist ::= conslist tcons",
108763
- /* 92 */ "conslist ::= tcons",
108764
- /* 93 */ "tcons ::= CONSTRAINT nm",
108765
- /* 94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
108766
- /* 95 */ "tcons ::= UNIQUE LP idxlist RP onconf",
108767
- /* 96 */ "tcons ::= CHECK LP expr RP onconf",
108768
- /* 97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
108769
- /* 98 */ "defer_subclause_opt ::=",
108770
- /* 99 */ "defer_subclause_opt ::= defer_subclause",
108771
- /* 100 */ "onconf ::=",
108772
- /* 101 */ "onconf ::= ON CONFLICT resolvetype",
108773
- /* 102 */ "orconf ::=",
108774
- /* 103 */ "orconf ::= OR resolvetype",
108775
- /* 104 */ "resolvetype ::= raisetype",
108776
- /* 105 */ "resolvetype ::= IGNORE",
108777
- /* 106 */ "resolvetype ::= REPLACE",
108778
- /* 107 */ "cmd ::= DROP TABLE ifexists fullname",
108779
- /* 108 */ "ifexists ::= IF EXISTS",
108780
- /* 109 */ "ifexists ::=",
108781
- /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
108782
- /* 111 */ "cmd ::= DROP VIEW ifexists fullname",
108783
- /* 112 */ "cmd ::= select",
108784
- /* 113 */ "select ::= oneselect",
108785
- /* 114 */ "select ::= select multiselect_op oneselect",
108786
- /* 115 */ "multiselect_op ::= UNION",
108787
- /* 116 */ "multiselect_op ::= UNION ALL",
108788
- /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT",
108789
- /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
108790
- /* 119 */ "distinct ::= DISTINCT",
108791
- /* 120 */ "distinct ::= ALL",
108792
- /* 121 */ "distinct ::=",
108793
- /* 122 */ "sclp ::= selcollist COMMA",
108794
- /* 123 */ "sclp ::=",
108795
- /* 124 */ "selcollist ::= sclp expr as",
108796
- /* 125 */ "selcollist ::= sclp STAR",
108797
- /* 126 */ "selcollist ::= sclp nm DOT STAR",
108798
- /* 127 */ "as ::= AS nm",
108799
- /* 128 */ "as ::= ids",
108800
- /* 129 */ "as ::=",
108801
- /* 130 */ "from ::=",
108802
- /* 131 */ "from ::= FROM seltablist",
108803
- /* 132 */ "stl_prefix ::= seltablist joinop",
108804
- /* 133 */ "stl_prefix ::=",
108805
- /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
108806
- /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
108807
- /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
108808
- /* 137 */ "dbnm ::=",
108809
- /* 138 */ "dbnm ::= DOT nm",
108810
- /* 139 */ "fullname ::= nm dbnm",
108811
- /* 140 */ "joinop ::= COMMA|JOIN",
108812
- /* 141 */ "joinop ::= JOIN_KW JOIN",
108813
- /* 142 */ "joinop ::= JOIN_KW nm JOIN",
108814
- /* 143 */ "joinop ::= JOIN_KW nm nm JOIN",
108815
- /* 144 */ "on_opt ::= ON expr",
108816
- /* 145 */ "on_opt ::=",
108817
- /* 146 */ "indexed_opt ::=",
108818
- /* 147 */ "indexed_opt ::= INDEXED BY nm",
108819
- /* 148 */ "indexed_opt ::= NOT INDEXED",
108820
- /* 149 */ "using_opt ::= USING LP inscollist RP",
108821
- /* 150 */ "using_opt ::=",
108822
- /* 151 */ "orderby_opt ::=",
108823
- /* 152 */ "orderby_opt ::= ORDER BY sortlist",
108824
- /* 153 */ "sortlist ::= sortlist COMMA expr sortorder",
108825
- /* 154 */ "sortlist ::= expr sortorder",
108826
- /* 155 */ "sortorder ::= ASC",
108827
- /* 156 */ "sortorder ::= DESC",
108828
- /* 157 */ "sortorder ::=",
108829
- /* 158 */ "groupby_opt ::=",
108830
- /* 159 */ "groupby_opt ::= GROUP BY nexprlist",
108831
- /* 160 */ "having_opt ::=",
108832
- /* 161 */ "having_opt ::= HAVING expr",
108833
- /* 162 */ "limit_opt ::=",
108834
- /* 163 */ "limit_opt ::= LIMIT expr",
108835
- /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr",
108836
- /* 165 */ "limit_opt ::= LIMIT expr COMMA expr",
108837
- /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
108838
- /* 167 */ "where_opt ::=",
108839
- /* 168 */ "where_opt ::= WHERE expr",
108840
- /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
108841
- /* 170 */ "setlist ::= setlist COMMA nm EQ expr",
108842
- /* 171 */ "setlist ::= nm EQ expr",
108843
- /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
108844
- /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
108845
- /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
108846
- /* 175 */ "insert_cmd ::= INSERT orconf",
108847
- /* 176 */ "insert_cmd ::= REPLACE",
108848
- /* 177 */ "valuelist ::= VALUES LP nexprlist RP",
108849
- /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP",
108850
- /* 179 */ "inscollist_opt ::=",
108851
- /* 180 */ "inscollist_opt ::= LP inscollist RP",
108852
- /* 181 */ "inscollist ::= inscollist COMMA nm",
108853
- /* 182 */ "inscollist ::= nm",
108854
- /* 183 */ "expr ::= term",
108855
- /* 184 */ "expr ::= LP expr RP",
108856
- /* 185 */ "term ::= NULL",
108857
- /* 186 */ "expr ::= id",
108858
- /* 187 */ "expr ::= JOIN_KW",
108859
- /* 188 */ "expr ::= nm DOT nm",
108860
- /* 189 */ "expr ::= nm DOT nm DOT nm",
108861
- /* 190 */ "term ::= INTEGER|FLOAT|BLOB",
108862
- /* 191 */ "term ::= STRING",
108863
- /* 192 */ "expr ::= REGISTER",
108864
- /* 193 */ "expr ::= VARIABLE",
108865
- /* 194 */ "expr ::= expr COLLATE ids",
108866
- /* 195 */ "expr ::= CAST LP expr AS typetoken RP",
108867
- /* 196 */ "expr ::= ID LP distinct exprlist RP",
108868
- /* 197 */ "expr ::= ID LP STAR RP",
108869
- /* 198 */ "term ::= CTIME_KW",
108870
- /* 199 */ "expr ::= expr AND expr",
108871
- /* 200 */ "expr ::= expr OR expr",
108872
- /* 201 */ "expr ::= expr LT|GT|GE|LE expr",
108873
- /* 202 */ "expr ::= expr EQ|NE expr",
108874
- /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
108875
- /* 204 */ "expr ::= expr PLUS|MINUS expr",
108876
- /* 205 */ "expr ::= expr STAR|SLASH|REM expr",
108877
- /* 206 */ "expr ::= expr CONCAT expr",
108878
- /* 207 */ "likeop ::= LIKE_KW",
108879
- /* 208 */ "likeop ::= NOT LIKE_KW",
108880
- /* 209 */ "likeop ::= MATCH",
108881
- /* 210 */ "likeop ::= NOT MATCH",
108882
- /* 211 */ "expr ::= expr likeop expr",
108883
- /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
108884
- /* 213 */ "expr ::= expr ISNULL|NOTNULL",
108885
- /* 214 */ "expr ::= expr NOT NULL",
108886
- /* 215 */ "expr ::= expr IS expr",
108887
- /* 216 */ "expr ::= expr IS NOT expr",
108888
- /* 217 */ "expr ::= NOT expr",
108889
- /* 218 */ "expr ::= BITNOT expr",
108890
- /* 219 */ "expr ::= MINUS expr",
108891
- /* 220 */ "expr ::= PLUS expr",
108892
- /* 221 */ "between_op ::= BETWEEN",
108893
- /* 222 */ "between_op ::= NOT BETWEEN",
108894
- /* 223 */ "expr ::= expr between_op expr AND expr",
108895
- /* 224 */ "in_op ::= IN",
108896
- /* 225 */ "in_op ::= NOT IN",
108897
- /* 226 */ "expr ::= expr in_op LP exprlist RP",
108898
- /* 227 */ "expr ::= LP select RP",
108899
- /* 228 */ "expr ::= expr in_op LP select RP",
108900
- /* 229 */ "expr ::= expr in_op nm dbnm",
108901
- /* 230 */ "expr ::= EXISTS LP select RP",
108902
- /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END",
108903
- /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
108904
- /* 233 */ "case_exprlist ::= WHEN expr THEN expr",
108905
- /* 234 */ "case_else ::= ELSE expr",
108906
- /* 235 */ "case_else ::=",
108907
- /* 236 */ "case_operand ::= expr",
108908
- /* 237 */ "case_operand ::=",
108909
- /* 238 */ "exprlist ::= nexprlist",
108910
- /* 239 */ "exprlist ::=",
108911
- /* 240 */ "nexprlist ::= nexprlist COMMA expr",
108912
- /* 241 */ "nexprlist ::= expr",
108913
- /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
108914
- /* 243 */ "uniqueflag ::= UNIQUE",
108915
- /* 244 */ "uniqueflag ::=",
108916
- /* 245 */ "idxlist_opt ::=",
108917
- /* 246 */ "idxlist_opt ::= LP idxlist RP",
108918
- /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder",
108919
- /* 248 */ "idxlist ::= nm collate sortorder",
108920
- /* 249 */ "collate ::=",
108921
- /* 250 */ "collate ::= COLLATE ids",
108922
- /* 251 */ "cmd ::= DROP INDEX ifexists fullname",
108923
- /* 252 */ "cmd ::= VACUUM",
108924
- /* 253 */ "cmd ::= VACUUM nm",
108925
- /* 254 */ "cmd ::= PRAGMA nm dbnm",
108926
- /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
108927
- /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
108928
- /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
108929
- /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
108930
- /* 259 */ "nmnum ::= plus_num",
108931
- /* 260 */ "nmnum ::= nm",
108932
- /* 261 */ "nmnum ::= ON",
108933
- /* 262 */ "nmnum ::= DELETE",
108934
- /* 263 */ "nmnum ::= DEFAULT",
108935
- /* 264 */ "plus_num ::= PLUS number",
108936
- /* 265 */ "plus_num ::= number",
108937
- /* 266 */ "minus_num ::= MINUS number",
108938
- /* 267 */ "number ::= INTEGER|FLOAT",
108939
- /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
108940
- /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
108941
- /* 270 */ "trigger_time ::= BEFORE",
108942
- /* 271 */ "trigger_time ::= AFTER",
108943
- /* 272 */ "trigger_time ::= INSTEAD OF",
108944
- /* 273 */ "trigger_time ::=",
108945
- /* 274 */ "trigger_event ::= DELETE|INSERT",
108946
- /* 275 */ "trigger_event ::= UPDATE",
108947
- /* 276 */ "trigger_event ::= UPDATE OF inscollist",
108948
- /* 277 */ "foreach_clause ::=",
108949
- /* 278 */ "foreach_clause ::= FOR EACH ROW",
108950
- /* 279 */ "when_clause ::=",
108951
- /* 280 */ "when_clause ::= WHEN expr",
108952
- /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
108953
- /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI",
108954
- /* 283 */ "trnm ::= nm",
108955
- /* 284 */ "trnm ::= nm DOT nm",
108956
- /* 285 */ "tridxby ::=",
108957
- /* 286 */ "tridxby ::= INDEXED BY nm",
108958
- /* 287 */ "tridxby ::= NOT INDEXED",
108959
- /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
108960
- /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
108961
- /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
108962
- /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
108963
- /* 292 */ "trigger_cmd ::= select",
108964
- /* 293 */ "expr ::= RAISE LP IGNORE RP",
108965
- /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP",
108966
- /* 295 */ "raisetype ::= ROLLBACK",
108967
- /* 296 */ "raisetype ::= ABORT",
108968
- /* 297 */ "raisetype ::= FAIL",
108969
- /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname",
108970
- /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
108971
- /* 300 */ "cmd ::= DETACH database_kw_opt expr",
108972
- /* 301 */ "key_opt ::=",
108973
- /* 302 */ "key_opt ::= KEY expr",
108974
- /* 303 */ "database_kw_opt ::= DATABASE",
108975
- /* 304 */ "database_kw_opt ::=",
108976
- /* 305 */ "cmd ::= REINDEX",
108977
- /* 306 */ "cmd ::= REINDEX nm dbnm",
108978
- /* 307 */ "cmd ::= ANALYZE",
108979
- /* 308 */ "cmd ::= ANALYZE nm dbnm",
108980
- /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
108981
- /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
108982
- /* 311 */ "add_column_fullname ::= fullname",
108983
- /* 312 */ "kwcolumn_opt ::=",
108984
- /* 313 */ "kwcolumn_opt ::= COLUMNKW",
108985
- /* 314 */ "cmd ::= create_vtab",
108986
- /* 315 */ "cmd ::= create_vtab LP vtabarglist RP",
108987
- /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
108988
- /* 317 */ "vtabarglist ::= vtabarg",
108989
- /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
108990
- /* 319 */ "vtabarg ::=",
108991
- /* 320 */ "vtabarg ::= vtabarg vtabargtoken",
108992
- /* 321 */ "vtabargtoken ::= ANY",
108993
- /* 322 */ "vtabargtoken ::= lp anylist RP",
108994
- /* 323 */ "lp ::= LP",
108995
- /* 324 */ "anylist ::=",
108996
- /* 325 */ "anylist ::= anylist LP anylist RP",
108997
- /* 326 */ "anylist ::= anylist ANY",
109055
+ /* 90 */ "conslist ::= conslist COMMA cname tcons",
109056
+ /* 91 */ "conslist ::= cname tcons",
109057
+ /* 92 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
109058
+ /* 93 */ "tcons ::= UNIQUE LP idxlist RP onconf",
109059
+ /* 94 */ "tcons ::= CHECK LP expr RP onconf",
109060
+ /* 95 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
109061
+ /* 96 */ "defer_subclause_opt ::=",
109062
+ /* 97 */ "defer_subclause_opt ::= defer_subclause",
109063
+ /* 98 */ "onconf ::=",
109064
+ /* 99 */ "onconf ::= ON CONFLICT resolvetype",
109065
+ /* 100 */ "orconf ::=",
109066
+ /* 101 */ "orconf ::= OR resolvetype",
109067
+ /* 102 */ "resolvetype ::= raisetype",
109068
+ /* 103 */ "resolvetype ::= IGNORE",
109069
+ /* 104 */ "resolvetype ::= REPLACE",
109070
+ /* 105 */ "cmd ::= DROP TABLE ifexists fullname",
109071
+ /* 106 */ "ifexists ::= IF EXISTS",
109072
+ /* 107 */ "ifexists ::=",
109073
+ /* 108 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
109074
+ /* 109 */ "cmd ::= DROP VIEW ifexists fullname",
109075
+ /* 110 */ "cmd ::= select",
109076
+ /* 111 */ "select ::= oneselect",
109077
+ /* 112 */ "select ::= select multiselect_op oneselect",
109078
+ /* 113 */ "multiselect_op ::= UNION",
109079
+ /* 114 */ "multiselect_op ::= UNION ALL",
109080
+ /* 115 */ "multiselect_op ::= EXCEPT|INTERSECT",
109081
+ /* 116 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
109082
+ /* 117 */ "distinct ::= DISTINCT",
109083
+ /* 118 */ "distinct ::= ALL",
109084
+ /* 119 */ "distinct ::=",
109085
+ /* 120 */ "sclp ::= selcollist COMMA",
109086
+ /* 121 */ "sclp ::=",
109087
+ /* 122 */ "selcollist ::= sclp expr as",
109088
+ /* 123 */ "selcollist ::= sclp STAR",
109089
+ /* 124 */ "selcollist ::= sclp nm DOT STAR",
109090
+ /* 125 */ "as ::= AS nm",
109091
+ /* 126 */ "as ::= ids",
109092
+ /* 127 */ "as ::=",
109093
+ /* 128 */ "from ::=",
109094
+ /* 129 */ "from ::= FROM seltablist",
109095
+ /* 130 */ "stl_prefix ::= seltablist joinop",
109096
+ /* 131 */ "stl_prefix ::=",
109097
+ /* 132 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
109098
+ /* 133 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
109099
+ /* 134 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
109100
+ /* 135 */ "dbnm ::=",
109101
+ /* 136 */ "dbnm ::= DOT nm",
109102
+ /* 137 */ "fullname ::= nm dbnm",
109103
+ /* 138 */ "joinop ::= COMMA|JOIN",
109104
+ /* 139 */ "joinop ::= JOIN_KW JOIN",
109105
+ /* 140 */ "joinop ::= JOIN_KW nm JOIN",
109106
+ /* 141 */ "joinop ::= JOIN_KW nm nm JOIN",
109107
+ /* 142 */ "on_opt ::= ON expr",
109108
+ /* 143 */ "on_opt ::=",
109109
+ /* 144 */ "indexed_opt ::=",
109110
+ /* 145 */ "indexed_opt ::= INDEXED BY nm",
109111
+ /* 146 */ "indexed_opt ::= NOT INDEXED",
109112
+ /* 147 */ "using_opt ::= USING LP inscollist RP",
109113
+ /* 148 */ "using_opt ::=",
109114
+ /* 149 */ "orderby_opt ::=",
109115
+ /* 150 */ "orderby_opt ::= ORDER BY sortlist",
109116
+ /* 151 */ "sortlist ::= sortlist COMMA expr sortorder",
109117
+ /* 152 */ "sortlist ::= expr sortorder",
109118
+ /* 153 */ "sortorder ::= ASC",
109119
+ /* 154 */ "sortorder ::= DESC",
109120
+ /* 155 */ "sortorder ::=",
109121
+ /* 156 */ "groupby_opt ::=",
109122
+ /* 157 */ "groupby_opt ::= GROUP BY nexprlist",
109123
+ /* 158 */ "having_opt ::=",
109124
+ /* 159 */ "having_opt ::= HAVING expr",
109125
+ /* 160 */ "limit_opt ::=",
109126
+ /* 161 */ "limit_opt ::= LIMIT expr",
109127
+ /* 162 */ "limit_opt ::= LIMIT expr OFFSET expr",
109128
+ /* 163 */ "limit_opt ::= LIMIT expr COMMA expr",
109129
+ /* 164 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
109130
+ /* 165 */ "where_opt ::=",
109131
+ /* 166 */ "where_opt ::= WHERE expr",
109132
+ /* 167 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
109133
+ /* 168 */ "setlist ::= setlist COMMA nm EQ expr",
109134
+ /* 169 */ "setlist ::= nm EQ expr",
109135
+ /* 170 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
109136
+ /* 171 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
109137
+ /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
109138
+ /* 173 */ "insert_cmd ::= INSERT orconf",
109139
+ /* 174 */ "insert_cmd ::= REPLACE",
109140
+ /* 175 */ "valuelist ::= VALUES LP nexprlist RP",
109141
+ /* 176 */ "valuelist ::= valuelist COMMA LP exprlist RP",
109142
+ /* 177 */ "inscollist_opt ::=",
109143
+ /* 178 */ "inscollist_opt ::= LP inscollist RP",
109144
+ /* 179 */ "inscollist ::= inscollist COMMA nm",
109145
+ /* 180 */ "inscollist ::= nm",
109146
+ /* 181 */ "expr ::= term",
109147
+ /* 182 */ "expr ::= LP expr RP",
109148
+ /* 183 */ "term ::= NULL",
109149
+ /* 184 */ "expr ::= id",
109150
+ /* 185 */ "expr ::= JOIN_KW",
109151
+ /* 186 */ "expr ::= nm DOT nm",
109152
+ /* 187 */ "expr ::= nm DOT nm DOT nm",
109153
+ /* 188 */ "term ::= INTEGER|FLOAT|BLOB",
109154
+ /* 189 */ "term ::= STRING",
109155
+ /* 190 */ "expr ::= REGISTER",
109156
+ /* 191 */ "expr ::= VARIABLE",
109157
+ /* 192 */ "expr ::= expr COLLATE ids",
109158
+ /* 193 */ "expr ::= CAST LP expr AS typetoken RP",
109159
+ /* 194 */ "expr ::= ID LP distinct exprlist RP",
109160
+ /* 195 */ "expr ::= ID LP STAR RP",
109161
+ /* 196 */ "term ::= CTIME_KW",
109162
+ /* 197 */ "expr ::= expr AND expr",
109163
+ /* 198 */ "expr ::= expr OR expr",
109164
+ /* 199 */ "expr ::= expr LT|GT|GE|LE expr",
109165
+ /* 200 */ "expr ::= expr EQ|NE expr",
109166
+ /* 201 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
109167
+ /* 202 */ "expr ::= expr PLUS|MINUS expr",
109168
+ /* 203 */ "expr ::= expr STAR|SLASH|REM expr",
109169
+ /* 204 */ "expr ::= expr CONCAT expr",
109170
+ /* 205 */ "likeop ::= LIKE_KW",
109171
+ /* 206 */ "likeop ::= NOT LIKE_KW",
109172
+ /* 207 */ "likeop ::= MATCH",
109173
+ /* 208 */ "likeop ::= NOT MATCH",
109174
+ /* 209 */ "expr ::= expr likeop expr",
109175
+ /* 210 */ "expr ::= expr likeop expr ESCAPE expr",
109176
+ /* 211 */ "expr ::= expr ISNULL|NOTNULL",
109177
+ /* 212 */ "expr ::= expr NOT NULL",
109178
+ /* 213 */ "expr ::= expr IS expr",
109179
+ /* 214 */ "expr ::= expr IS NOT expr",
109180
+ /* 215 */ "expr ::= NOT expr",
109181
+ /* 216 */ "expr ::= BITNOT expr",
109182
+ /* 217 */ "expr ::= MINUS expr",
109183
+ /* 218 */ "expr ::= PLUS expr",
109184
+ /* 219 */ "between_op ::= BETWEEN",
109185
+ /* 220 */ "between_op ::= NOT BETWEEN",
109186
+ /* 221 */ "expr ::= expr between_op expr AND expr",
109187
+ /* 222 */ "in_op ::= IN",
109188
+ /* 223 */ "in_op ::= NOT IN",
109189
+ /* 224 */ "expr ::= expr in_op LP exprlist RP",
109190
+ /* 225 */ "expr ::= LP select RP",
109191
+ /* 226 */ "expr ::= expr in_op LP select RP",
109192
+ /* 227 */ "expr ::= expr in_op nm dbnm",
109193
+ /* 228 */ "expr ::= EXISTS LP select RP",
109194
+ /* 229 */ "expr ::= CASE case_operand case_exprlist case_else END",
109195
+ /* 230 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
109196
+ /* 231 */ "case_exprlist ::= WHEN expr THEN expr",
109197
+ /* 232 */ "case_else ::= ELSE expr",
109198
+ /* 233 */ "case_else ::=",
109199
+ /* 234 */ "case_operand ::= expr",
109200
+ /* 235 */ "case_operand ::=",
109201
+ /* 236 */ "exprlist ::= nexprlist",
109202
+ /* 237 */ "exprlist ::=",
109203
+ /* 238 */ "nexprlist ::= nexprlist COMMA expr",
109204
+ /* 239 */ "nexprlist ::= expr",
109205
+ /* 240 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
109206
+ /* 241 */ "uniqueflag ::= UNIQUE",
109207
+ /* 242 */ "uniqueflag ::=",
109208
+ /* 243 */ "idxlist_opt ::=",
109209
+ /* 244 */ "idxlist_opt ::= LP idxlist RP",
109210
+ /* 245 */ "idxlist ::= idxlist COMMA nm collate sortorder",
109211
+ /* 246 */ "idxlist ::= nm collate sortorder",
109212
+ /* 247 */ "collate ::=",
109213
+ /* 248 */ "collate ::= COLLATE ids",
109214
+ /* 249 */ "cmd ::= DROP INDEX ifexists fullname",
109215
+ /* 250 */ "cmd ::= VACUUM",
109216
+ /* 251 */ "cmd ::= VACUUM nm",
109217
+ /* 252 */ "cmd ::= PRAGMA nm dbnm",
109218
+ /* 253 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
109219
+ /* 254 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
109220
+ /* 255 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
109221
+ /* 256 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
109222
+ /* 257 */ "nmnum ::= plus_num",
109223
+ /* 258 */ "nmnum ::= nm",
109224
+ /* 259 */ "nmnum ::= ON",
109225
+ /* 260 */ "nmnum ::= DELETE",
109226
+ /* 261 */ "nmnum ::= DEFAULT",
109227
+ /* 262 */ "plus_num ::= PLUS number",
109228
+ /* 263 */ "plus_num ::= number",
109229
+ /* 264 */ "minus_num ::= MINUS number",
109230
+ /* 265 */ "number ::= INTEGER|FLOAT",
109231
+ /* 266 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
109232
+ /* 267 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
109233
+ /* 268 */ "trigger_time ::= BEFORE",
109234
+ /* 269 */ "trigger_time ::= AFTER",
109235
+ /* 270 */ "trigger_time ::= INSTEAD OF",
109236
+ /* 271 */ "trigger_time ::=",
109237
+ /* 272 */ "trigger_event ::= DELETE|INSERT",
109238
+ /* 273 */ "trigger_event ::= UPDATE",
109239
+ /* 274 */ "trigger_event ::= UPDATE OF inscollist",
109240
+ /* 275 */ "foreach_clause ::=",
109241
+ /* 276 */ "foreach_clause ::= FOR EACH ROW",
109242
+ /* 277 */ "when_clause ::=",
109243
+ /* 278 */ "when_clause ::= WHEN expr",
109244
+ /* 279 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
109245
+ /* 280 */ "trigger_cmd_list ::= trigger_cmd SEMI",
109246
+ /* 281 */ "trnm ::= nm",
109247
+ /* 282 */ "trnm ::= nm DOT nm",
109248
+ /* 283 */ "tridxby ::=",
109249
+ /* 284 */ "tridxby ::= INDEXED BY nm",
109250
+ /* 285 */ "tridxby ::= NOT INDEXED",
109251
+ /* 286 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
109252
+ /* 287 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
109253
+ /* 288 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
109254
+ /* 289 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
109255
+ /* 290 */ "trigger_cmd ::= select",
109256
+ /* 291 */ "expr ::= RAISE LP IGNORE RP",
109257
+ /* 292 */ "expr ::= RAISE LP raisetype COMMA nm RP",
109258
+ /* 293 */ "raisetype ::= ROLLBACK",
109259
+ /* 294 */ "raisetype ::= ABORT",
109260
+ /* 295 */ "raisetype ::= FAIL",
109261
+ /* 296 */ "cmd ::= DROP TRIGGER ifexists fullname",
109262
+ /* 297 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
109263
+ /* 298 */ "cmd ::= DETACH database_kw_opt expr",
109264
+ /* 299 */ "key_opt ::=",
109265
+ /* 300 */ "key_opt ::= KEY expr",
109266
+ /* 301 */ "database_kw_opt ::= DATABASE",
109267
+ /* 302 */ "database_kw_opt ::=",
109268
+ /* 303 */ "cmd ::= REINDEX",
109269
+ /* 304 */ "cmd ::= REINDEX nm dbnm",
109270
+ /* 305 */ "cmd ::= ANALYZE",
109271
+ /* 306 */ "cmd ::= ANALYZE nm dbnm",
109272
+ /* 307 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
109273
+ /* 308 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
109274
+ /* 309 */ "add_column_fullname ::= fullname",
109275
+ /* 310 */ "kwcolumn_opt ::=",
109276
+ /* 311 */ "kwcolumn_opt ::= COLUMNKW",
109277
+ /* 312 */ "cmd ::= create_vtab",
109278
+ /* 313 */ "cmd ::= create_vtab LP vtabarglist RP",
109279
+ /* 314 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
109280
+ /* 315 */ "vtabarglist ::= vtabarg",
109281
+ /* 316 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
109282
+ /* 317 */ "vtabarg ::=",
109283
+ /* 318 */ "vtabarg ::= vtabarg vtabargtoken",
109284
+ /* 319 */ "vtabargtoken ::= ANY",
109285
+ /* 320 */ "vtabargtoken ::= lp anylist RP",
109286
+ /* 321 */ "lp ::= LP",
109287
+ /* 322 */ "anylist ::=",
109288
+ /* 323 */ "anylist ::= anylist LP anylist RP",
109289
+ /* 324 */ "anylist ::= anylist ANY",
108998109290
};
108999109291
#endif /* NDEBUG */
109000109292
109001109293
109002109294
#if YYSTACKDEPTH<=0
@@ -109438,14 +109730,14 @@
109438109730
{ 167, 6 },
109439109731
{ 168, 1 },
109440109732
{ 168, 2 },
109441109733
{ 169, 1 },
109442109734
{ 169, 1 },
109443
- { 164, 2 },
109735
+ { 164, 3 },
109444109736
{ 164, 0 },
109445
- { 172, 3 },
109446
- { 172, 1 },
109737
+ { 172, 2 },
109738
+ { 172, 0 },
109447109739
{ 173, 2 },
109448109740
{ 173, 4 },
109449109741
{ 173, 3 },
109450109742
{ 173, 3 },
109451109743
{ 173, 2 },
@@ -109475,14 +109767,12 @@
109475109767
{ 184, 0 },
109476109768
{ 184, 2 },
109477109769
{ 184, 2 },
109478109770
{ 159, 0 },
109479109771
{ 159, 2 },
109480
- { 185, 3 },
109772
+ { 185, 4 },
109481109773
{ 185, 2 },
109482
- { 185, 1 },
109483
- { 186, 2 },
109484109774
{ 186, 7 },
109485109775
{ 186, 5 },
109486109776
{ 186, 5 },
109487109777
{ 186, 10 },
109488109778
{ 188, 0 },
@@ -109787,12 +110077,12 @@
109787110077
{yygotominor.yy392 = TK_DEFERRED;}
109788110078
break;
109789110079
case 14: /* transtype ::= DEFERRED */
109790110080
case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
109791110081
case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
109792
- case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
109793
- case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
110082
+ case 113: /* multiselect_op ::= UNION */ yytestcase(yyruleno==113);
110083
+ case 115: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==115);
109794110084
{yygotominor.yy392 = yymsp[0].major;}
109795110085
break;
109796110086
case 17: /* cmd ::= COMMIT trans_opt */
109797110087
case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
109798110088
{sqlite3CommitTransaction(pParse);}
@@ -109830,26 +110120,26 @@
109830110120
case 31: /* temp ::= */ yytestcase(yyruleno==31);
109831110121
case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
109832110122
case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
109833110123
case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
109834110124
case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
109835
- case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
109836
- case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
109837
- case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
109838
- case 121: /* distinct ::= */ yytestcase(yyruleno==121);
109839
- case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
109840
- case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
110125
+ case 96: /* defer_subclause_opt ::= */ yytestcase(yyruleno==96);
110126
+ case 107: /* ifexists ::= */ yytestcase(yyruleno==107);
110127
+ case 118: /* distinct ::= ALL */ yytestcase(yyruleno==118);
110128
+ case 119: /* distinct ::= */ yytestcase(yyruleno==119);
110129
+ case 219: /* between_op ::= BETWEEN */ yytestcase(yyruleno==219);
110130
+ case 222: /* in_op ::= IN */ yytestcase(yyruleno==222);
109841110131
{yygotominor.yy392 = 0;}
109842110132
break;
109843110133
case 29: /* ifnotexists ::= IF NOT EXISTS */
109844110134
case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
109845110135
case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
109846110136
case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
109847
- case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
109848
- case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
109849
- case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
109850
- case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
110137
+ case 106: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==106);
110138
+ case 117: /* distinct ::= DISTINCT */ yytestcase(yyruleno==117);
110139
+ case 220: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==220);
110140
+ case 223: /* in_op ::= NOT IN */ yytestcase(yyruleno==223);
109851110141
{yygotominor.yy392 = 1;}
109852110142
break;
109853110143
case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
109854110144
{
109855110145
sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
@@ -109879,25 +110169,25 @@
109879110169
case 41: /* nm ::= id */ yytestcase(yyruleno==41);
109880110170
case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
109881110171
case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
109882110172
case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
109883110173
case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
109884
- case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
109885
- case 128: /* as ::= ids */ yytestcase(yyruleno==128);
109886
- case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
109887
- case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
109888
- case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250);
109889
- case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259);
109890
- case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260);
109891
- case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261);
109892
- case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262);
109893
- case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263);
109894
- case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264);
109895
- case 265: /* plus_num ::= number */ yytestcase(yyruleno==265);
109896
- case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
109897
- case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
109898
- case 283: /* trnm ::= nm */ yytestcase(yyruleno==283);
110174
+ case 125: /* as ::= AS nm */ yytestcase(yyruleno==125);
110175
+ case 126: /* as ::= ids */ yytestcase(yyruleno==126);
110176
+ case 136: /* dbnm ::= DOT nm */ yytestcase(yyruleno==136);
110177
+ case 145: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==145);
110178
+ case 248: /* collate ::= COLLATE ids */ yytestcase(yyruleno==248);
110179
+ case 257: /* nmnum ::= plus_num */ yytestcase(yyruleno==257);
110180
+ case 258: /* nmnum ::= nm */ yytestcase(yyruleno==258);
110181
+ case 259: /* nmnum ::= ON */ yytestcase(yyruleno==259);
110182
+ case 260: /* nmnum ::= DELETE */ yytestcase(yyruleno==260);
110183
+ case 261: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==261);
110184
+ case 262: /* plus_num ::= PLUS number */ yytestcase(yyruleno==262);
110185
+ case 263: /* plus_num ::= number */ yytestcase(yyruleno==263);
110186
+ case 264: /* minus_num ::= MINUS number */ yytestcase(yyruleno==264);
110187
+ case 265: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==265);
110188
+ case 281: /* trnm ::= nm */ yytestcase(yyruleno==281);
109899110189
{yygotominor.yy0 = yymsp[0].minor.yy0;}
109900110190
break;
109901110191
case 45: /* type ::= typetoken */
109902110192
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
109903110193
break;
@@ -109913,10 +110203,16 @@
109913110203
yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
109914110204
}
109915110205
break;
109916110206
case 50: /* typename ::= typename ids */
109917110207
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
110208
+ break;
110209
+ case 55: /* cname ::= CONSTRAINT nm */
110210
+{pParse->constraintName = yymsp[0].minor.yy0;}
110211
+ break;
110212
+ case 56: /* cname ::= */
110213
+{pParse->constraintName.n = 0;}
109918110214
break;
109919110215
case 57: /* ccons ::= DEFAULT term */
109920110216
case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
109921110217
{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
109922110218
break;
@@ -109990,80 +110286,80 @@
109990110286
break;
109991110287
case 82: /* refact ::= NO ACTION */
109992110288
{ yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */}
109993110289
break;
109994110290
case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
109995
- case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
109996
- case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
109997
- case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
110291
+ case 97: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==97);
110292
+ case 99: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==99);
110293
+ case 102: /* resolvetype ::= raisetype */ yytestcase(yyruleno==102);
109998110294
{yygotominor.yy392 = yymsp[0].minor.yy392;}
109999110295
break;
110000110296
case 88: /* conslist_opt ::= */
110001110297
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
110002110298
break;
110003110299
case 89: /* conslist_opt ::= COMMA conslist */
110004110300
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
110005110301
break;
110006
- case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
110302
+ case 92: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
110007110303
{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
110008110304
break;
110009
- case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
110305
+ case 93: /* tcons ::= UNIQUE LP idxlist RP onconf */
110010110306
{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
110011110307
break;
110012
- case 96: /* tcons ::= CHECK LP expr RP onconf */
110308
+ case 94: /* tcons ::= CHECK LP expr RP onconf */
110013110309
{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
110014110310
break;
110015
- case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
110311
+ case 95: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
110016110312
{
110017110313
sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
110018110314
sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
110019110315
}
110020110316
break;
110021
- case 100: /* onconf ::= */
110317
+ case 98: /* onconf ::= */
110022110318
{yygotominor.yy392 = OE_Default;}
110023110319
break;
110024
- case 102: /* orconf ::= */
110320
+ case 100: /* orconf ::= */
110025110321
{yygotominor.yy258 = OE_Default;}
110026110322
break;
110027
- case 103: /* orconf ::= OR resolvetype */
110323
+ case 101: /* orconf ::= OR resolvetype */
110028110324
{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
110029110325
break;
110030
- case 105: /* resolvetype ::= IGNORE */
110326
+ case 103: /* resolvetype ::= IGNORE */
110031110327
{yygotominor.yy392 = OE_Ignore;}
110032110328
break;
110033
- case 106: /* resolvetype ::= REPLACE */
110329
+ case 104: /* resolvetype ::= REPLACE */
110034110330
{yygotominor.yy392 = OE_Replace;}
110035110331
break;
110036
- case 107: /* cmd ::= DROP TABLE ifexists fullname */
110332
+ case 105: /* cmd ::= DROP TABLE ifexists fullname */
110037110333
{
110038110334
sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
110039110335
}
110040110336
break;
110041
- case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
110337
+ case 108: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
110042110338
{
110043110339
sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
110044110340
}
110045110341
break;
110046
- case 111: /* cmd ::= DROP VIEW ifexists fullname */
110342
+ case 109: /* cmd ::= DROP VIEW ifexists fullname */
110047110343
{
110048110344
sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
110049110345
}
110050110346
break;
110051
- case 112: /* cmd ::= select */
110347
+ case 110: /* cmd ::= select */
110052110348
{
110053110349
SelectDest dest = {SRT_Output, 0, 0, 0, 0};
110054110350
sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
110055110351
sqlite3ExplainBegin(pParse->pVdbe);
110056110352
sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
110057110353
sqlite3ExplainFinish(pParse->pVdbe);
110058110354
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
110059110355
}
110060110356
break;
110061
- case 113: /* select ::= oneselect */
110357
+ case 111: /* select ::= oneselect */
110062110358
{yygotominor.yy159 = yymsp[0].minor.yy159;}
110063110359
break;
110064
- case 114: /* select ::= select multiselect_op oneselect */
110360
+ case 112: /* select ::= select multiselect_op oneselect */
110065110361
{
110066110362
if( yymsp[0].minor.yy159 ){
110067110363
yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
110068110364
yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
110069110365
}else{
@@ -110070,83 +110366,83 @@
110070110366
sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
110071110367
}
110072110368
yygotominor.yy159 = yymsp[0].minor.yy159;
110073110369
}
110074110370
break;
110075
- case 116: /* multiselect_op ::= UNION ALL */
110371
+ case 114: /* multiselect_op ::= UNION ALL */
110076110372
{yygotominor.yy392 = TK_ALL;}
110077110373
break;
110078
- case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110374
+ case 116: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110079110375
{
110080110376
yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
110081110377
}
110082110378
break;
110083
- case 122: /* sclp ::= selcollist COMMA */
110084
- case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
110379
+ case 120: /* sclp ::= selcollist COMMA */
110380
+ case 244: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==244);
110085110381
{yygotominor.yy442 = yymsp[-1].minor.yy442;}
110086110382
break;
110087
- case 123: /* sclp ::= */
110088
- case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
110089
- case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
110090
- case 239: /* exprlist ::= */ yytestcase(yyruleno==239);
110091
- case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245);
110383
+ case 121: /* sclp ::= */
110384
+ case 149: /* orderby_opt ::= */ yytestcase(yyruleno==149);
110385
+ case 156: /* groupby_opt ::= */ yytestcase(yyruleno==156);
110386
+ case 237: /* exprlist ::= */ yytestcase(yyruleno==237);
110387
+ case 243: /* idxlist_opt ::= */ yytestcase(yyruleno==243);
110092110388
{yygotominor.yy442 = 0;}
110093110389
break;
110094
- case 124: /* selcollist ::= sclp expr as */
110390
+ case 122: /* selcollist ::= sclp expr as */
110095110391
{
110096110392
yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
110097110393
if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
110098110394
sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
110099110395
}
110100110396
break;
110101
- case 125: /* selcollist ::= sclp STAR */
110397
+ case 123: /* selcollist ::= sclp STAR */
110102110398
{
110103110399
Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
110104110400
yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
110105110401
}
110106110402
break;
110107
- case 126: /* selcollist ::= sclp nm DOT STAR */
110403
+ case 124: /* selcollist ::= sclp nm DOT STAR */
110108110404
{
110109110405
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
110110110406
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110111110407
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
110112110408
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
110113110409
}
110114110410
break;
110115
- case 129: /* as ::= */
110411
+ case 127: /* as ::= */
110116110412
{yygotominor.yy0.n = 0;}
110117110413
break;
110118
- case 130: /* from ::= */
110414
+ case 128: /* from ::= */
110119110415
{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
110120110416
break;
110121
- case 131: /* from ::= FROM seltablist */
110417
+ case 129: /* from ::= FROM seltablist */
110122110418
{
110123110419
yygotominor.yy347 = yymsp[0].minor.yy347;
110124110420
sqlite3SrcListShiftJoinType(yygotominor.yy347);
110125110421
}
110126110422
break;
110127
- case 132: /* stl_prefix ::= seltablist joinop */
110423
+ case 130: /* stl_prefix ::= seltablist joinop */
110128110424
{
110129110425
yygotominor.yy347 = yymsp[-1].minor.yy347;
110130110426
if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
110131110427
}
110132110428
break;
110133
- case 133: /* stl_prefix ::= */
110429
+ case 131: /* stl_prefix ::= */
110134110430
{yygotominor.yy347 = 0;}
110135110431
break;
110136
- case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
110432
+ case 132: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
110137110433
{
110138110434
yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110139110435
sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
110140110436
}
110141110437
break;
110142
- case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
110438
+ case 133: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
110143110439
{
110144110440
yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110145110441
}
110146110442
break;
110147
- case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110443
+ case 134: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110148110444
{
110149110445
if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
110150110446
yygotominor.yy347 = yymsp[-4].minor.yy347;
110151110447
}else{
110152110448
Select *pSubquery;
@@ -110154,137 +110450,137 @@
110154110450
pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
110155110451
yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110156110452
}
110157110453
}
110158110454
break;
110159
- case 137: /* dbnm ::= */
110160
- case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
110455
+ case 135: /* dbnm ::= */
110456
+ case 144: /* indexed_opt ::= */ yytestcase(yyruleno==144);
110161110457
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
110162110458
break;
110163
- case 139: /* fullname ::= nm dbnm */
110459
+ case 137: /* fullname ::= nm dbnm */
110164110460
{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
110165110461
break;
110166
- case 140: /* joinop ::= COMMA|JOIN */
110462
+ case 138: /* joinop ::= COMMA|JOIN */
110167110463
{ yygotominor.yy392 = JT_INNER; }
110168110464
break;
110169
- case 141: /* joinop ::= JOIN_KW JOIN */
110465
+ case 139: /* joinop ::= JOIN_KW JOIN */
110170110466
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
110171110467
break;
110172
- case 142: /* joinop ::= JOIN_KW nm JOIN */
110468
+ case 140: /* joinop ::= JOIN_KW nm JOIN */
110173110469
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
110174110470
break;
110175
- case 143: /* joinop ::= JOIN_KW nm nm JOIN */
110471
+ case 141: /* joinop ::= JOIN_KW nm nm JOIN */
110176110472
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
110177110473
break;
110178
- case 144: /* on_opt ::= ON expr */
110179
- case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
110180
- case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
110181
- case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234);
110182
- case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236);
110474
+ case 142: /* on_opt ::= ON expr */
110475
+ case 159: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==159);
110476
+ case 166: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==166);
110477
+ case 232: /* case_else ::= ELSE expr */ yytestcase(yyruleno==232);
110478
+ case 234: /* case_operand ::= expr */ yytestcase(yyruleno==234);
110183110479
{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
110184110480
break;
110185
- case 145: /* on_opt ::= */
110186
- case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
110187
- case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
110188
- case 235: /* case_else ::= */ yytestcase(yyruleno==235);
110189
- case 237: /* case_operand ::= */ yytestcase(yyruleno==237);
110481
+ case 143: /* on_opt ::= */
110482
+ case 158: /* having_opt ::= */ yytestcase(yyruleno==158);
110483
+ case 165: /* where_opt ::= */ yytestcase(yyruleno==165);
110484
+ case 233: /* case_else ::= */ yytestcase(yyruleno==233);
110485
+ case 235: /* case_operand ::= */ yytestcase(yyruleno==235);
110190110486
{yygotominor.yy122 = 0;}
110191110487
break;
110192
- case 148: /* indexed_opt ::= NOT INDEXED */
110488
+ case 146: /* indexed_opt ::= NOT INDEXED */
110193110489
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
110194110490
break;
110195
- case 149: /* using_opt ::= USING LP inscollist RP */
110196
- case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
110491
+ case 147: /* using_opt ::= USING LP inscollist RP */
110492
+ case 178: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==178);
110197110493
{yygotominor.yy180 = yymsp[-1].minor.yy180;}
110198110494
break;
110199
- case 150: /* using_opt ::= */
110200
- case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
110495
+ case 148: /* using_opt ::= */
110496
+ case 177: /* inscollist_opt ::= */ yytestcase(yyruleno==177);
110201110497
{yygotominor.yy180 = 0;}
110202110498
break;
110203
- case 152: /* orderby_opt ::= ORDER BY sortlist */
110204
- case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
110205
- case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238);
110499
+ case 150: /* orderby_opt ::= ORDER BY sortlist */
110500
+ case 157: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==157);
110501
+ case 236: /* exprlist ::= nexprlist */ yytestcase(yyruleno==236);
110206110502
{yygotominor.yy442 = yymsp[0].minor.yy442;}
110207110503
break;
110208
- case 153: /* sortlist ::= sortlist COMMA expr sortorder */
110504
+ case 151: /* sortlist ::= sortlist COMMA expr sortorder */
110209110505
{
110210110506
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
110211110507
if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110212110508
}
110213110509
break;
110214
- case 154: /* sortlist ::= expr sortorder */
110510
+ case 152: /* sortlist ::= expr sortorder */
110215110511
{
110216110512
yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
110217110513
if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
110218110514
}
110219110515
break;
110220
- case 155: /* sortorder ::= ASC */
110221
- case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
110516
+ case 153: /* sortorder ::= ASC */
110517
+ case 155: /* sortorder ::= */ yytestcase(yyruleno==155);
110222110518
{yygotominor.yy392 = SQLITE_SO_ASC;}
110223110519
break;
110224
- case 156: /* sortorder ::= DESC */
110520
+ case 154: /* sortorder ::= DESC */
110225110521
{yygotominor.yy392 = SQLITE_SO_DESC;}
110226110522
break;
110227
- case 162: /* limit_opt ::= */
110523
+ case 160: /* limit_opt ::= */
110228110524
{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
110229110525
break;
110230
- case 163: /* limit_opt ::= LIMIT expr */
110526
+ case 161: /* limit_opt ::= LIMIT expr */
110231110527
{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
110232110528
break;
110233
- case 164: /* limit_opt ::= LIMIT expr OFFSET expr */
110529
+ case 162: /* limit_opt ::= LIMIT expr OFFSET expr */
110234110530
{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
110235110531
break;
110236
- case 165: /* limit_opt ::= LIMIT expr COMMA expr */
110532
+ case 163: /* limit_opt ::= LIMIT expr COMMA expr */
110237110533
{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
110238110534
break;
110239
- case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
110535
+ case 164: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
110240110536
{
110241110537
sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
110242110538
sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
110243110539
}
110244110540
break;
110245
- case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
110541
+ case 167: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
110246110542
{
110247110543
sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
110248110544
sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
110249110545
sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
110250110546
}
110251110547
break;
110252
- case 170: /* setlist ::= setlist COMMA nm EQ expr */
110548
+ case 168: /* setlist ::= setlist COMMA nm EQ expr */
110253110549
{
110254110550
yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
110255110551
sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110256110552
}
110257110553
break;
110258
- case 171: /* setlist ::= nm EQ expr */
110554
+ case 169: /* setlist ::= nm EQ expr */
110259110555
{
110260110556
yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
110261110557
sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110262110558
}
110263110559
break;
110264
- case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
110560
+ case 170: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
110265110561
{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
110266110562
break;
110267
- case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
110563
+ case 171: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
110268110564
{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
110269110565
break;
110270
- case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
110566
+ case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
110271110567
{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
110272110568
break;
110273
- case 175: /* insert_cmd ::= INSERT orconf */
110569
+ case 173: /* insert_cmd ::= INSERT orconf */
110274110570
{yygotominor.yy258 = yymsp[0].minor.yy258;}
110275110571
break;
110276
- case 176: /* insert_cmd ::= REPLACE */
110572
+ case 174: /* insert_cmd ::= REPLACE */
110277110573
{yygotominor.yy258 = OE_Replace;}
110278110574
break;
110279
- case 177: /* valuelist ::= VALUES LP nexprlist RP */
110575
+ case 175: /* valuelist ::= VALUES LP nexprlist RP */
110280110576
{
110281110577
yygotominor.yy487.pList = yymsp[-1].minor.yy442;
110282110578
yygotominor.yy487.pSelect = 0;
110283110579
}
110284110580
break;
110285
- case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */
110581
+ case 176: /* valuelist ::= valuelist COMMA LP exprlist RP */
110286110582
{
110287110583
Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
110288110584
if( yymsp[-4].minor.yy487.pList ){
110289110585
yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
110290110586
yymsp[-4].minor.yy487.pList = 0;
@@ -110301,50 +110597,50 @@
110301110597
pRight->pPrior->selFlags |= SF_Values;
110302110598
yygotominor.yy487.pSelect = pRight;
110303110599
}
110304110600
}
110305110601
break;
110306
- case 181: /* inscollist ::= inscollist COMMA nm */
110602
+ case 179: /* inscollist ::= inscollist COMMA nm */
110307110603
{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
110308110604
break;
110309
- case 182: /* inscollist ::= nm */
110605
+ case 180: /* inscollist ::= nm */
110310110606
{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
110311110607
break;
110312
- case 183: /* expr ::= term */
110608
+ case 181: /* expr ::= term */
110313110609
{yygotominor.yy342 = yymsp[0].minor.yy342;}
110314110610
break;
110315
- case 184: /* expr ::= LP expr RP */
110611
+ case 182: /* expr ::= LP expr RP */
110316110612
{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
110317110613
break;
110318
- case 185: /* term ::= NULL */
110319
- case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
110320
- case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
110614
+ case 183: /* term ::= NULL */
110615
+ case 188: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==188);
110616
+ case 189: /* term ::= STRING */ yytestcase(yyruleno==189);
110321110617
{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
110322110618
break;
110323
- case 186: /* expr ::= id */
110324
- case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
110619
+ case 184: /* expr ::= id */
110620
+ case 185: /* expr ::= JOIN_KW */ yytestcase(yyruleno==185);
110325110621
{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
110326110622
break;
110327
- case 188: /* expr ::= nm DOT nm */
110623
+ case 186: /* expr ::= nm DOT nm */
110328110624
{
110329110625
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110330110626
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
110331110627
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
110332110628
spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
110333110629
}
110334110630
break;
110335
- case 189: /* expr ::= nm DOT nm DOT nm */
110631
+ case 187: /* expr ::= nm DOT nm DOT nm */
110336110632
{
110337110633
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
110338110634
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110339110635
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
110340110636
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
110341110637
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
110342110638
spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
110343110639
}
110344110640
break;
110345
- case 192: /* expr ::= REGISTER */
110641
+ case 190: /* expr ::= REGISTER */
110346110642
{
110347110643
/* When doing a nested parse, one can include terms in an expression
110348110644
** that look like this: #1 #2 ... These terms refer to registers
110349110645
** in the virtual machine. #N is the N-th register. */
110350110646
if( pParse->nested==0 ){
@@ -110355,31 +110651,31 @@
110355110651
if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
110356110652
}
110357110653
spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110358110654
}
110359110655
break;
110360
- case 193: /* expr ::= VARIABLE */
110656
+ case 191: /* expr ::= VARIABLE */
110361110657
{
110362110658
spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
110363110659
sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
110364110660
spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110365110661
}
110366110662
break;
110367
- case 194: /* expr ::= expr COLLATE ids */
110663
+ case 192: /* expr ::= expr COLLATE ids */
110368110664
{
110369110665
yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110370110666
yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110371110667
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110372110668
}
110373110669
break;
110374
- case 195: /* expr ::= CAST LP expr AS typetoken RP */
110670
+ case 193: /* expr ::= CAST LP expr AS typetoken RP */
110375110671
{
110376110672
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
110377110673
spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
110378110674
}
110379110675
break;
110380
- case 196: /* expr ::= ID LP distinct exprlist RP */
110676
+ case 194: /* expr ::= ID LP distinct exprlist RP */
110381110677
{
110382110678
if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
110383110679
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
110384110680
}
110385110681
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
@@ -110387,17 +110683,17 @@
110387110683
if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
110388110684
yygotominor.yy342.pExpr->flags |= EP_Distinct;
110389110685
}
110390110686
}
110391110687
break;
110392
- case 197: /* expr ::= ID LP STAR RP */
110688
+ case 195: /* expr ::= ID LP STAR RP */
110393110689
{
110394110690
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
110395110691
spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
110396110692
}
110397110693
break;
110398
- case 198: /* term ::= CTIME_KW */
110694
+ case 196: /* term ::= CTIME_KW */
110399110695
{
110400110696
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
110401110697
** treated as functions that return constants */
110402110698
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
110403110699
if( yygotominor.yy342.pExpr ){
@@ -110404,82 +110700,82 @@
110404110700
yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
110405110701
}
110406110702
spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110407110703
}
110408110704
break;
110409
- case 199: /* expr ::= expr AND expr */
110410
- case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
110411
- case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
110412
- case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
110413
- case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
110414
- case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
110415
- case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
110416
- case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
110705
+ case 197: /* expr ::= expr AND expr */
110706
+ case 198: /* expr ::= expr OR expr */ yytestcase(yyruleno==198);
110707
+ case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199);
110708
+ case 200: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==200);
110709
+ case 201: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==201);
110710
+ case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202);
110711
+ case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203);
110712
+ case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204);
110417110713
{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
110418110714
break;
110419
- case 207: /* likeop ::= LIKE_KW */
110420
- case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
110421
-{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.not = 0;}
110422
- break;
110423
- case 208: /* likeop ::= NOT LIKE_KW */
110424
- case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
110425
-{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.not = 1;}
110426
- break;
110427
- case 211: /* expr ::= expr likeop expr */
110715
+ case 205: /* likeop ::= LIKE_KW */
110716
+ case 207: /* likeop ::= MATCH */ yytestcase(yyruleno==207);
110717
+{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;}
110718
+ break;
110719
+ case 206: /* likeop ::= NOT LIKE_KW */
110720
+ case 208: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==208);
110721
+{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;}
110722
+ break;
110723
+ case 209: /* expr ::= expr likeop expr */
110428110724
{
110429110725
ExprList *pList;
110430110726
pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
110431110727
pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
110432110728
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
110433
- if( yymsp[-1].minor.yy318.not ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110729
+ if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110434110730
yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110435110731
yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110436110732
if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
110437110733
}
110438110734
break;
110439
- case 212: /* expr ::= expr likeop expr ESCAPE expr */
110735
+ case 210: /* expr ::= expr likeop expr ESCAPE expr */
110440110736
{
110441110737
ExprList *pList;
110442110738
pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110443110739
pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
110444110740
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
110445110741
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
110446
- if( yymsp[-3].minor.yy318.not ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110742
+ if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110447110743
yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110448110744
yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110449110745
if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
110450110746
}
110451110747
break;
110452
- case 213: /* expr ::= expr ISNULL|NOTNULL */
110748
+ case 211: /* expr ::= expr ISNULL|NOTNULL */
110453110749
{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
110454110750
break;
110455
- case 214: /* expr ::= expr NOT NULL */
110751
+ case 212: /* expr ::= expr NOT NULL */
110456110752
{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
110457110753
break;
110458
- case 215: /* expr ::= expr IS expr */
110754
+ case 213: /* expr ::= expr IS expr */
110459110755
{
110460110756
spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
110461110757
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
110462110758
}
110463110759
break;
110464
- case 216: /* expr ::= expr IS NOT expr */
110760
+ case 214: /* expr ::= expr IS NOT expr */
110465110761
{
110466110762
spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
110467110763
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
110468110764
}
110469110765
break;
110470
- case 217: /* expr ::= NOT expr */
110471
- case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218);
110766
+ case 215: /* expr ::= NOT expr */
110767
+ case 216: /* expr ::= BITNOT expr */ yytestcase(yyruleno==216);
110472110768
{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110473110769
break;
110474
- case 219: /* expr ::= MINUS expr */
110770
+ case 217: /* expr ::= MINUS expr */
110475110771
{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110476110772
break;
110477
- case 220: /* expr ::= PLUS expr */
110773
+ case 218: /* expr ::= PLUS expr */
110478110774
{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110479110775
break;
110480
- case 223: /* expr ::= expr between_op expr AND expr */
110776
+ case 221: /* expr ::= expr between_op expr AND expr */
110481110777
{
110482110778
ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110483110779
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
110484110780
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
110485110781
if( yygotominor.yy342.pExpr ){
@@ -110490,11 +110786,11 @@
110490110786
if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110491110787
yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110492110788
yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110493110789
}
110494110790
break;
110495
- case 226: /* expr ::= expr in_op LP exprlist RP */
110791
+ case 224: /* expr ::= expr in_op LP exprlist RP */
110496110792
{
110497110793
if( yymsp[-1].minor.yy442==0 ){
110498110794
/* Expressions of the form
110499110795
**
110500110796
** expr1 IN ()
@@ -110517,11 +110813,11 @@
110517110813
}
110518110814
yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110519110815
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110520110816
}
110521110817
break;
110522
- case 227: /* expr ::= LP select RP */
110818
+ case 225: /* expr ::= LP select RP */
110523110819
{
110524110820
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
110525110821
if( yygotominor.yy342.pExpr ){
110526110822
yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
110527110823
ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
@@ -110531,11 +110827,11 @@
110531110827
}
110532110828
yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
110533110829
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110534110830
}
110535110831
break;
110536
- case 228: /* expr ::= expr in_op LP select RP */
110832
+ case 226: /* expr ::= expr in_op LP select RP */
110537110833
{
110538110834
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
110539110835
if( yygotominor.yy342.pExpr ){
110540110836
yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
110541110837
ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
@@ -110546,11 +110842,11 @@
110546110842
if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110547110843
yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110548110844
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110549110845
}
110550110846
break;
110551
- case 229: /* expr ::= expr in_op nm dbnm */
110847
+ case 227: /* expr ::= expr in_op nm dbnm */
110552110848
{
110553110849
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
110554110850
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
110555110851
if( yygotominor.yy342.pExpr ){
110556110852
yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
@@ -110562,11 +110858,11 @@
110562110858
if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110563110859
yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
110564110860
yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
110565110861
}
110566110862
break;
110567
- case 230: /* expr ::= EXISTS LP select RP */
110863
+ case 228: /* expr ::= EXISTS LP select RP */
110568110864
{
110569110865
Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
110570110866
if( p ){
110571110867
p->x.pSelect = yymsp[-1].minor.yy159;
110572110868
ExprSetProperty(p, EP_xIsSelect);
@@ -110576,11 +110872,11 @@
110576110872
}
110577110873
yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
110578110874
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110579110875
}
110580110876
break;
110581
- case 231: /* expr ::= CASE case_operand case_exprlist case_else END */
110877
+ case 229: /* expr ::= CASE case_operand case_exprlist case_else END */
110582110878
{
110583110879
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
110584110880
if( yygotominor.yy342.pExpr ){
110585110881
yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
110586110882
sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
@@ -110589,43 +110885,43 @@
110589110885
}
110590110886
yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
110591110887
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110592110888
}
110593110889
break;
110594
- case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
110890
+ case 230: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
110595110891
{
110596110892
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
110597110893
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
110598110894
}
110599110895
break;
110600
- case 233: /* case_exprlist ::= WHEN expr THEN expr */
110896
+ case 231: /* case_exprlist ::= WHEN expr THEN expr */
110601110897
{
110602110898
yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110603110899
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
110604110900
}
110605110901
break;
110606
- case 240: /* nexprlist ::= nexprlist COMMA expr */
110902
+ case 238: /* nexprlist ::= nexprlist COMMA expr */
110607110903
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
110608110904
break;
110609
- case 241: /* nexprlist ::= expr */
110905
+ case 239: /* nexprlist ::= expr */
110610110906
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
110611110907
break;
110612
- case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
110908
+ case 240: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
110613110909
{
110614110910
sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
110615110911
sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
110616110912
&yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
110617110913
}
110618110914
break;
110619
- case 243: /* uniqueflag ::= UNIQUE */
110620
- case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296);
110915
+ case 241: /* uniqueflag ::= UNIQUE */
110916
+ case 294: /* raisetype ::= ABORT */ yytestcase(yyruleno==294);
110621110917
{yygotominor.yy392 = OE_Abort;}
110622110918
break;
110623
- case 244: /* uniqueflag ::= */
110919
+ case 242: /* uniqueflag ::= */
110624110920
{yygotominor.yy392 = OE_None;}
110625110921
break;
110626
- case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
110922
+ case 245: /* idxlist ::= idxlist COMMA nm collate sortorder */
110627110923
{
110628110924
Expr *p = 0;
110629110925
if( yymsp[-1].minor.yy0.n>0 ){
110630110926
p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
110631110927
sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
@@ -110634,11 +110930,11 @@
110634110930
sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
110635110931
sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110636110932
if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110637110933
}
110638110934
break;
110639
- case 248: /* idxlist ::= nm collate sortorder */
110935
+ case 246: /* idxlist ::= nm collate sortorder */
110640110936
{
110641110937
Expr *p = 0;
110642110938
if( yymsp[-1].minor.yy0.n>0 ){
110643110939
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
110644110940
sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
@@ -110647,212 +110943,212 @@
110647110943
sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110648110944
sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110649110945
if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110650110946
}
110651110947
break;
110652
- case 249: /* collate ::= */
110948
+ case 247: /* collate ::= */
110653110949
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
110654110950
break;
110655
- case 251: /* cmd ::= DROP INDEX ifexists fullname */
110951
+ case 249: /* cmd ::= DROP INDEX ifexists fullname */
110656110952
{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
110657110953
break;
110658
- case 252: /* cmd ::= VACUUM */
110659
- case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253);
110954
+ case 250: /* cmd ::= VACUUM */
110955
+ case 251: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==251);
110660110956
{sqlite3Vacuum(pParse);}
110661110957
break;
110662
- case 254: /* cmd ::= PRAGMA nm dbnm */
110958
+ case 252: /* cmd ::= PRAGMA nm dbnm */
110663110959
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
110664110960
break;
110665
- case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
110961
+ case 253: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
110666110962
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
110667110963
break;
110668
- case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
110964
+ case 254: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
110669110965
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
110670110966
break;
110671
- case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
110967
+ case 255: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
110672110968
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
110673110969
break;
110674
- case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
110970
+ case 256: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
110675110971
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
110676110972
break;
110677
- case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
110973
+ case 266: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
110678110974
{
110679110975
Token all;
110680110976
all.z = yymsp[-3].minor.yy0.z;
110681110977
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
110682110978
sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
110683110979
}
110684110980
break;
110685
- case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
110981
+ case 267: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
110686110982
{
110687110983
sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
110688110984
yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
110689110985
}
110690110986
break;
110691
- case 270: /* trigger_time ::= BEFORE */
110692
- case 273: /* trigger_time ::= */ yytestcase(yyruleno==273);
110987
+ case 268: /* trigger_time ::= BEFORE */
110988
+ case 271: /* trigger_time ::= */ yytestcase(yyruleno==271);
110693110989
{ yygotominor.yy392 = TK_BEFORE; }
110694110990
break;
110695
- case 271: /* trigger_time ::= AFTER */
110991
+ case 269: /* trigger_time ::= AFTER */
110696110992
{ yygotominor.yy392 = TK_AFTER; }
110697110993
break;
110698
- case 272: /* trigger_time ::= INSTEAD OF */
110994
+ case 270: /* trigger_time ::= INSTEAD OF */
110699110995
{ yygotominor.yy392 = TK_INSTEAD;}
110700110996
break;
110701
- case 274: /* trigger_event ::= DELETE|INSERT */
110702
- case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275);
110997
+ case 272: /* trigger_event ::= DELETE|INSERT */
110998
+ case 273: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==273);
110703110999
{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
110704111000
break;
110705
- case 276: /* trigger_event ::= UPDATE OF inscollist */
111001
+ case 274: /* trigger_event ::= UPDATE OF inscollist */
110706111002
{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
110707111003
break;
110708
- case 279: /* when_clause ::= */
110709
- case 301: /* key_opt ::= */ yytestcase(yyruleno==301);
111004
+ case 277: /* when_clause ::= */
111005
+ case 299: /* key_opt ::= */ yytestcase(yyruleno==299);
110710111006
{ yygotominor.yy122 = 0; }
110711111007
break;
110712
- case 280: /* when_clause ::= WHEN expr */
110713
- case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302);
111008
+ case 278: /* when_clause ::= WHEN expr */
111009
+ case 300: /* key_opt ::= KEY expr */ yytestcase(yyruleno==300);
110714111010
{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
110715111011
break;
110716
- case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
111012
+ case 279: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
110717111013
{
110718111014
assert( yymsp[-2].minor.yy327!=0 );
110719111015
yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
110720111016
yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
110721111017
yygotominor.yy327 = yymsp[-2].minor.yy327;
110722111018
}
110723111019
break;
110724
- case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
111020
+ case 280: /* trigger_cmd_list ::= trigger_cmd SEMI */
110725111021
{
110726111022
assert( yymsp[-1].minor.yy327!=0 );
110727111023
yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
110728111024
yygotominor.yy327 = yymsp[-1].minor.yy327;
110729111025
}
110730111026
break;
110731
- case 284: /* trnm ::= nm DOT nm */
111027
+ case 282: /* trnm ::= nm DOT nm */
110732111028
{
110733111029
yygotominor.yy0 = yymsp[0].minor.yy0;
110734111030
sqlite3ErrorMsg(pParse,
110735111031
"qualified table names are not allowed on INSERT, UPDATE, and DELETE "
110736111032
"statements within triggers");
110737111033
}
110738111034
break;
110739
- case 286: /* tridxby ::= INDEXED BY nm */
111035
+ case 284: /* tridxby ::= INDEXED BY nm */
110740111036
{
110741111037
sqlite3ErrorMsg(pParse,
110742111038
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
110743111039
"within triggers");
110744111040
}
110745111041
break;
110746
- case 287: /* tridxby ::= NOT INDEXED */
111042
+ case 285: /* tridxby ::= NOT INDEXED */
110747111043
{
110748111044
sqlite3ErrorMsg(pParse,
110749111045
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
110750111046
"within triggers");
110751111047
}
110752111048
break;
110753
- case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
111049
+ case 286: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
110754111050
{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
110755111051
break;
110756
- case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
111052
+ case 287: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
110757111053
{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
110758111054
break;
110759
- case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
111055
+ case 288: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
110760111056
{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
110761111057
break;
110762
- case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
111058
+ case 289: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
110763111059
{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
110764111060
break;
110765
- case 292: /* trigger_cmd ::= select */
111061
+ case 290: /* trigger_cmd ::= select */
110766111062
{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
110767111063
break;
110768
- case 293: /* expr ::= RAISE LP IGNORE RP */
111064
+ case 291: /* expr ::= RAISE LP IGNORE RP */
110769111065
{
110770111066
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
110771111067
if( yygotominor.yy342.pExpr ){
110772111068
yygotominor.yy342.pExpr->affinity = OE_Ignore;
110773111069
}
110774111070
yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
110775111071
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110776111072
}
110777111073
break;
110778
- case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
111074
+ case 292: /* expr ::= RAISE LP raisetype COMMA nm RP */
110779111075
{
110780111076
yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
110781111077
if( yygotominor.yy342.pExpr ) {
110782111078
yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
110783111079
}
110784111080
yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
110785111081
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110786111082
}
110787111083
break;
110788
- case 295: /* raisetype ::= ROLLBACK */
111084
+ case 293: /* raisetype ::= ROLLBACK */
110789111085
{yygotominor.yy392 = OE_Rollback;}
110790111086
break;
110791
- case 297: /* raisetype ::= FAIL */
111087
+ case 295: /* raisetype ::= FAIL */
110792111088
{yygotominor.yy392 = OE_Fail;}
110793111089
break;
110794
- case 298: /* cmd ::= DROP TRIGGER ifexists fullname */
111090
+ case 296: /* cmd ::= DROP TRIGGER ifexists fullname */
110795111091
{
110796111092
sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
110797111093
}
110798111094
break;
110799
- case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
111095
+ case 297: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
110800111096
{
110801111097
sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
110802111098
}
110803111099
break;
110804
- case 300: /* cmd ::= DETACH database_kw_opt expr */
111100
+ case 298: /* cmd ::= DETACH database_kw_opt expr */
110805111101
{
110806111102
sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
110807111103
}
110808111104
break;
110809
- case 305: /* cmd ::= REINDEX */
111105
+ case 303: /* cmd ::= REINDEX */
110810111106
{sqlite3Reindex(pParse, 0, 0);}
110811111107
break;
110812
- case 306: /* cmd ::= REINDEX nm dbnm */
111108
+ case 304: /* cmd ::= REINDEX nm dbnm */
110813111109
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
110814111110
break;
110815
- case 307: /* cmd ::= ANALYZE */
111111
+ case 305: /* cmd ::= ANALYZE */
110816111112
{sqlite3Analyze(pParse, 0, 0);}
110817111113
break;
110818
- case 308: /* cmd ::= ANALYZE nm dbnm */
111114
+ case 306: /* cmd ::= ANALYZE nm dbnm */
110819111115
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
110820111116
break;
110821
- case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
111117
+ case 307: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
110822111118
{
110823111119
sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
110824111120
}
110825111121
break;
110826
- case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
111122
+ case 308: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
110827111123
{
110828111124
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
110829111125
}
110830111126
break;
110831
- case 311: /* add_column_fullname ::= fullname */
111127
+ case 309: /* add_column_fullname ::= fullname */
110832111128
{
110833111129
pParse->db->lookaside.bEnabled = 0;
110834111130
sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
110835111131
}
110836111132
break;
110837
- case 314: /* cmd ::= create_vtab */
111133
+ case 312: /* cmd ::= create_vtab */
110838111134
{sqlite3VtabFinishParse(pParse,0);}
110839111135
break;
110840
- case 315: /* cmd ::= create_vtab LP vtabarglist RP */
111136
+ case 313: /* cmd ::= create_vtab LP vtabarglist RP */
110841111137
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
110842111138
break;
110843
- case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
111139
+ case 314: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
110844111140
{
110845111141
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
110846111142
}
110847111143
break;
110848
- case 319: /* vtabarg ::= */
111144
+ case 317: /* vtabarg ::= */
110849111145
{sqlite3VtabArgInit(pParse);}
110850111146
break;
110851
- case 321: /* vtabargtoken ::= ANY */
110852
- case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322);
110853
- case 323: /* lp ::= LP */ yytestcase(yyruleno==323);
111147
+ case 319: /* vtabargtoken ::= ANY */
111148
+ case 320: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==320);
111149
+ case 321: /* lp ::= LP */ yytestcase(yyruleno==321);
110854111150
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
110855111151
break;
110856111152
default:
110857111153
/* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
110858111154
/* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
@@ -110868,32 +111164,28 @@
110868111164
/* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
110869111165
/* (35) columnlist ::= column */ yytestcase(yyruleno==35);
110870111166
/* (44) type ::= */ yytestcase(yyruleno==44);
110871111167
/* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
110872111168
/* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
110873
- /* (53) carglist ::= carglist carg */ yytestcase(yyruleno==53);
111169
+ /* (53) carglist ::= carglist cname ccons */ yytestcase(yyruleno==53);
110874111170
/* (54) carglist ::= */ yytestcase(yyruleno==54);
110875
- /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55);
110876
- /* (56) carg ::= ccons */ yytestcase(yyruleno==56);
110877111171
/* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
110878
- /* (90) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==90);
110879
- /* (91) conslist ::= conslist tcons */ yytestcase(yyruleno==91);
110880
- /* (92) conslist ::= tcons */ yytestcase(yyruleno==92);
110881
- /* (93) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
110882
- /* (277) foreach_clause ::= */ yytestcase(yyruleno==277);
110883
- /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278);
110884
- /* (285) tridxby ::= */ yytestcase(yyruleno==285);
110885
- /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303);
110886
- /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304);
110887
- /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312);
110888
- /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313);
110889
- /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317);
110890
- /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
110891
- /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
110892
- /* (324) anylist ::= */ yytestcase(yyruleno==324);
110893
- /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
110894
- /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
111172
+ /* (90) conslist ::= conslist COMMA cname tcons */ yytestcase(yyruleno==90);
111173
+ /* (91) conslist ::= cname tcons */ yytestcase(yyruleno==91);
111174
+ /* (275) foreach_clause ::= */ yytestcase(yyruleno==275);
111175
+ /* (276) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==276);
111176
+ /* (283) tridxby ::= */ yytestcase(yyruleno==283);
111177
+ /* (301) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==301);
111178
+ /* (302) database_kw_opt ::= */ yytestcase(yyruleno==302);
111179
+ /* (310) kwcolumn_opt ::= */ yytestcase(yyruleno==310);
111180
+ /* (311) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==311);
111181
+ /* (315) vtabarglist ::= vtabarg */ yytestcase(yyruleno==315);
111182
+ /* (316) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==316);
111183
+ /* (318) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==318);
111184
+ /* (322) anylist ::= */ yytestcase(yyruleno==322);
111185
+ /* (323) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==323);
111186
+ /* (324) anylist ::= anylist ANY */ yytestcase(yyruleno==324);
110895111187
break;
110896111188
};
110897111189
yygoto = yyRuleInfo[yyruleno].lhs;
110898111190
yysize = yyRuleInfo[yyruleno].nrhs;
110899111191
yypParser->yyidx -= yysize;
@@ -113174,23 +113466,27 @@
113174113466
sqlite3_free(db);
113175113467
return SQLITE_OK;
113176113468
}
113177113469
113178113470
/*
113179
-** Rollback all database files.
113471
+** Rollback all database files. If tripCode is not SQLITE_OK, then
113472
+** any open cursors are invalidated ("tripped" - as in "tripping a circuit
113473
+** breaker") and made to return tripCode if there are any further
113474
+** attempts to use that cursor.
113180113475
*/
113181
-SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){
113476
+SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
113182113477
int i;
113183113478
int inTrans = 0;
113184113479
assert( sqlite3_mutex_held(db->mutex) );
113185113480
sqlite3BeginBenignMalloc();
113186113481
for(i=0; i<db->nDb; i++){
113187
- if( db->aDb[i].pBt ){
113188
- if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
113482
+ Btree *p = db->aDb[i].pBt;
113483
+ if( p ){
113484
+ if( sqlite3BtreeIsInTrans(p) ){
113189113485
inTrans = 1;
113190113486
}
113191
- sqlite3BtreeRollback(db->aDb[i].pBt);
113487
+ sqlite3BtreeRollback(p, tripCode);
113192113488
db->aDb[i].inTrans = 0;
113193113489
}
113194113490
}
113195113491
sqlite3VtabRollback(db);
113196113492
sqlite3EndBenignMalloc();
@@ -113241,16 +113537,25 @@
113241113537
/* SQLITE_AUTH */ "authorization denied",
113242113538
/* SQLITE_FORMAT */ "auxiliary database format error",
113243113539
/* SQLITE_RANGE */ "bind or column index out of range",
113244113540
/* SQLITE_NOTADB */ "file is encrypted or is not a database",
113245113541
};
113246
- rc &= 0xff;
113247
- if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
113248
- return aMsg[rc];
113249
- }else{
113250
- return "unknown error";
113542
+ const char *zErr = "unknown error";
113543
+ switch( rc ){
113544
+ case SQLITE_ABORT_ROLLBACK: {
113545
+ zErr = "abort due to ROLLBACK";
113546
+ break;
113547
+ }
113548
+ default: {
113549
+ rc &= 0xff;
113550
+ if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){
113551
+ zErr = aMsg[rc];
113552
+ }
113553
+ break;
113554
+ }
113251113555
}
113556
+ return zErr;
113252113557
}
113253113558
113254113559
/*
113255113560
** This routine implements a busy callback that sleeps and tries
113256113561
** again until a timeout value is reached. The timeout value is
@@ -113624,13 +113929,12 @@
113624113929
sqlite3_mutex_leave(db->mutex);
113625113930
return pOld;
113626113931
}
113627113932
#endif /* SQLITE_OMIT_TRACE */
113628113933
113629
-/*** EXPERIMENTAL ***
113630
-**
113631
-** Register a function to be invoked when a transaction comments.
113934
+/*
113935
+** Register a function to be invoked when a transaction commits.
113632113936
** If the invoked function returns non-zero, then the commit becomes a
113633113937
** rollback.
113634113938
*/
113635113939
SQLITE_API void *sqlite3_commit_hook(
113636113940
sqlite3 *db, /* Attach the hook to this database */
@@ -115017,39 +115321,31 @@
115017115321
/*
115018115322
** Invoke the xFileControl method on a particular database.
115019115323
*/
115020115324
SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
115021115325
int rc = SQLITE_ERROR;
115022
- int iDb;
115326
+ Btree *pBtree;
115327
+
115023115328
sqlite3_mutex_enter(db->mutex);
115024
- if( zDbName==0 ){
115025
- iDb = 0;
115026
- }else{
115027
- for(iDb=0; iDb<db->nDb; iDb++){
115028
- if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break;
115029
- }
115030
- }
115031
- if( iDb<db->nDb ){
115032
- Btree *pBtree = db->aDb[iDb].pBt;
115033
- if( pBtree ){
115034
- Pager *pPager;
115035
- sqlite3_file *fd;
115036
- sqlite3BtreeEnter(pBtree);
115037
- pPager = sqlite3BtreePager(pBtree);
115038
- assert( pPager!=0 );
115039
- fd = sqlite3PagerFile(pPager);
115040
- assert( fd!=0 );
115041
- if( op==SQLITE_FCNTL_FILE_POINTER ){
115042
- *(sqlite3_file**)pArg = fd;
115043
- rc = SQLITE_OK;
115044
- }else if( fd->pMethods ){
115045
- rc = sqlite3OsFileControl(fd, op, pArg);
115046
- }else{
115047
- rc = SQLITE_NOTFOUND;
115048
- }
115049
- sqlite3BtreeLeave(pBtree);
115050
- }
115329
+ pBtree = sqlite3DbNameToBtree(db, zDbName);
115330
+ if( pBtree ){
115331
+ Pager *pPager;
115332
+ sqlite3_file *fd;
115333
+ sqlite3BtreeEnter(pBtree);
115334
+ pPager = sqlite3BtreePager(pBtree);
115335
+ assert( pPager!=0 );
115336
+ fd = sqlite3PagerFile(pPager);
115337
+ assert( fd!=0 );
115338
+ if( op==SQLITE_FCNTL_FILE_POINTER ){
115339
+ *(sqlite3_file**)pArg = fd;
115340
+ rc = SQLITE_OK;
115341
+ }else if( fd->pMethods ){
115342
+ rc = sqlite3OsFileControl(fd, op, pArg);
115343
+ }else{
115344
+ rc = SQLITE_NOTFOUND;
115345
+ }
115346
+ sqlite3BtreeLeave(pBtree);
115051115347
}
115052115348
sqlite3_mutex_leave(db->mutex);
115053115349
return rc;
115054115350
}
115055115351
@@ -115339,23 +115635,42 @@
115339115635
if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
115340115636
bDflt = v;
115341115637
}
115342115638
return bDflt;
115343115639
}
115640
+
115641
+/*
115642
+** Return the Btree pointer identified by zDbName. Return NULL if not found.
115643
+*/
115644
+SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
115645
+ int i;
115646
+ for(i=0; i<db->nDb; i++){
115647
+ if( db->aDb[i].pBt
115648
+ && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0)
115649
+ ){
115650
+ return db->aDb[i].pBt;
115651
+ }
115652
+ }
115653
+ return 0;
115654
+}
115344115655
115345115656
/*
115346115657
** Return the filename of the database associated with a database
115347115658
** connection.
115348115659
*/
115349115660
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
115350
- int i;
115351
- for(i=0; i<db->nDb; i++){
115352
- if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){
115353
- return sqlite3BtreeGetFilename(db->aDb[i].pBt);
115354
- }
115355
- }
115356
- return 0;
115661
+ Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
115662
+ return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
115663
+}
115664
+
115665
+/*
115666
+** Return 1 if database is read-only or 0 if read/write. Return -1 if
115667
+** no such database exists.
115668
+*/
115669
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
115670
+ Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
115671
+ return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
115357115672
}
115358115673
115359115674
/************** End of main.c ************************************************/
115360115675
/************** Begin file notify.c ******************************************/
115361115676
/*
@@ -115761,11 +116076,11 @@
115761116076
** option. But that functionality is no longer supported.
115762116077
**
115763116078
** A doclist is stored like this:
115764116079
**
115765116080
** array {
115766
-** varint docid;
116081
+** varint docid; (delta from previous doclist)
115767116082
** array { (position list for column 0)
115768116083
** varint position; (2 more than the delta from previous position)
115769116084
** }
115770116085
** array {
115771116086
** varint POS_COLUMN; (marks start of position list for new column)
@@ -115792,12 +116107,12 @@
115792116107
** The 123 value is the first docid. For column zero in this document
115793116108
** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
115794116109
** at D signals the start of a new column; the 1 at E indicates that the
115795116110
** new column is column number 1. There are two positions at 12 and 45
115796116111
** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
115797
-** 234 at I is the next docid. It has one position 72 (72-2) and then
115798
-** terminates with the 0 at K.
116112
+** 234 at I is the delta to next docid (357). It has one position 70
116113
+** (72-2) and then terminates with the 0 at K.
115799116114
**
115800116115
** A "position-list" is the list of positions for multiple columns for
115801116116
** a single docid. A "column-list" is the set of positions for a single
115802116117
** column. Hence, a position-list consists of one or more column-lists,
115803116118
** a document record consists of a docid followed by a position-list and
@@ -115977,14 +116292,10 @@
115977116292
** we simply write the new doclist. Segment merges overwrite older
115978116293
** data for a particular docid with newer data, so deletes or updates
115979116294
** will eventually overtake the earlier data and knock it out. The
115980116295
** query logic likewise merges doclists so that newer data knocks out
115981116296
** older data.
115982
-**
115983
-** TODO(shess) Provide a VACUUM type operation to clear out all
115984
-** deletions and duplications. This would basically be a forced merge
115985
-** into a single segment.
115986116297
*/
115987116298
115988116299
/************** Include fts3Int.h in the middle of fts3.c ********************/
115989116300
/************** Begin file fts3Int.h *****************************************/
115990116301
/*
@@ -116076,11 +116387,11 @@
116076116387
typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
116077116388
116078116389
struct sqlite3_tokenizer_module {
116079116390
116080116391
/*
116081
- ** Structure version. Should always be set to 0.
116392
+ ** Structure version. Should always be set to 0 or 1.
116082116393
*/
116083116394
int iVersion;
116084116395
116085116396
/*
116086116397
** Create a new tokenizer. The values in the argv[] array are the
@@ -116157,10 +116468,19 @@
116157116468
const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
116158116469
int *piStartOffset, /* OUT: Byte offset of token in input buffer */
116159116470
int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
116160116471
int *piPosition /* OUT: Number of tokens returned before this one */
116161116472
);
116473
+
116474
+ /***********************************************************************
116475
+ ** Methods below this point are only available if iVersion>=1.
116476
+ */
116477
+
116478
+ /*
116479
+ ** Configure the language id of a tokenizer cursor.
116480
+ */
116481
+ int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
116162116482
};
116163116483
116164116484
struct sqlite3_tokenizer {
116165116485
const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
116166116486
/* Tokenizer implementations will typically add additional fields */
@@ -116323,10 +116643,13 @@
116323116643
116324116644
116325116645
#ifndef MIN
116326116646
# define MIN(x,y) ((x)<(y)?(x):(y))
116327116647
#endif
116648
+#ifndef MAX
116649
+# define MAX(x,y) ((x)>(y)?(x):(y))
116650
+#endif
116328116651
116329116652
/*
116330116653
** Maximum length of a varint encoded integer. The varint format is different
116331116654
** from that used by SQLite, so the maximum length is 10, not 9.
116332116655
*/
@@ -116377,20 +116700,21 @@
116377116700
#ifdef SQLITE_COVERAGE_TEST
116378116701
# define ALWAYS(x) (1)
116379116702
# define NEVER(X) (0)
116380116703
#else
116381116704
# define ALWAYS(x) (x)
116382
-# define NEVER(X) (x)
116705
+# define NEVER(x) (x)
116383116706
#endif
116384116707
116385116708
/*
116386116709
** Internal types used by SQLite.
116387116710
*/
116388116711
typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
116389116712
typedef short int i16; /* 2-byte (or larger) signed integer */
116390116713
typedef unsigned int u32; /* 4-byte unsigned integer */
116391116714
typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
116715
+typedef sqlite3_int64 i64; /* 8-byte signed integer */
116392116716
116393116717
/*
116394116718
** Macro used to suppress compiler warnings for unused parameters.
116395116719
*/
116396116720
#define UNUSED_PARAMETER(x) (void)(x)
@@ -116448,55 +116772,64 @@
116448116772
const char *zName; /* virtual table name */
116449116773
int nColumn; /* number of named columns in virtual table */
116450116774
char **azColumn; /* column names. malloced */
116451116775
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
116452116776
char *zContentTbl; /* content=xxx option, or NULL */
116777
+ char *zLanguageid; /* languageid=xxx option, or NULL */
116778
+ u8 bAutoincrmerge; /* True if automerge=1 */
116779
+ u32 nLeafAdd; /* Number of leaf blocks added this trans */
116453116780
116454116781
/* Precompiled statements used by the implementation. Each of these
116455116782
** statements is run and reset within a single virtual table API call.
116456116783
*/
116457
- sqlite3_stmt *aStmt[27];
116784
+ sqlite3_stmt *aStmt[37];
116458116785
116459116786
char *zReadExprlist;
116460116787
char *zWriteExprlist;
116461116788
116462116789
int nNodeSize; /* Soft limit for node size */
116790
+ u8 bFts4; /* True for FTS4, false for FTS3 */
116463116791
u8 bHasStat; /* True if %_stat table exists */
116464116792
u8 bHasDocsize; /* True if %_docsize table exists */
116465116793
u8 bDescIdx; /* True if doclists are in reverse order */
116794
+ u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */
116466116795
int nPgsz; /* Page size for host database */
116467116796
char *zSegmentsTbl; /* Name of %_segments table */
116468116797
sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
116469116798
116470
- /* TODO: Fix the first paragraph of this comment.
116471
- **
116472
- ** The following hash table is used to buffer pending index updates during
116473
- ** transactions. Variable nPendingData estimates the memory size of the
116474
- ** pending data, including hash table overhead, but not malloc overhead.
116475
- ** When nPendingData exceeds nMaxPendingData, the buffer is flushed
116476
- ** automatically. Variable iPrevDocid is the docid of the most recently
116477
- ** inserted record.
116799
+ /*
116800
+ ** The following array of hash tables is used to buffer pending index
116801
+ ** updates during transactions. All pending updates buffered at any one
116802
+ ** time must share a common language-id (see the FTS4 langid= feature).
116803
+ ** The current language id is stored in variable iPrevLangid.
116478116804
**
116479116805
** A single FTS4 table may have multiple full-text indexes. For each index
116480116806
** there is an entry in the aIndex[] array. Index 0 is an index of all the
116481116807
** terms that appear in the document set. Each subsequent index in aIndex[]
116482116808
** is an index of prefixes of a specific length.
116809
+ **
116810
+ ** Variable nPendingData contains an estimate the memory consumed by the
116811
+ ** pending data structures, including hash table overhead, but not including
116812
+ ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash
116813
+ ** tables are flushed to disk. Variable iPrevDocid is the docid of the most
116814
+ ** recently inserted record.
116483116815
*/
116484116816
int nIndex; /* Size of aIndex[] */
116485116817
struct Fts3Index {
116486116818
int nPrefix; /* Prefix length (0 for main terms index) */
116487116819
Fts3Hash hPending; /* Pending terms table for this index */
116488116820
} *aIndex;
116489116821
int nMaxPendingData; /* Max pending data before flush to disk */
116490116822
int nPendingData; /* Current bytes of pending data */
116491116823
sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
116824
+ int iPrevLangid; /* Langid of recently inserted document */
116492116825
116493116826
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
116494116827
/* State variables used for validating that the transaction control
116495116828
** methods of the virtual table are called at appropriate times. These
116496
- ** values do not contribution to the FTS computation; they are used for
116497
- ** verifying the SQLite core.
116829
+ ** values do not contribute to FTS functionality; they are used for
116830
+ ** verifying the operation of the SQLite core.
116498116831
*/
116499116832
int inTransaction; /* True after xBegin but before xCommit/xRollback */
116500116833
int mxSavepoint; /* Largest valid xSavepoint integer */
116501116834
#endif
116502116835
};
@@ -116511,10 +116844,11 @@
116511116844
i16 eSearch; /* Search strategy (see below) */
116512116845
u8 isEof; /* True if at End Of Results */
116513116846
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
116514116847
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
116515116848
Fts3Expr *pExpr; /* Parsed MATCH query string */
116849
+ int iLangid; /* Language being queried for */
116516116850
int nPhrase; /* Number of matchable phrases in query */
116517116851
Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
116518116852
sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
116519116853
char *pNextId; /* Pointer into the body of aDoclist */
116520116854
char *aDoclist; /* List of docids for full-text queries */
@@ -116662,11 +116996,11 @@
116662116996
SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
116663116997
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
116664116998
SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
116665116999
Fts3Table*,int,const char*,int,int,Fts3SegReader**);
116666117000
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
116667
-SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
117001
+SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
116668117002
SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
116669117003
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
116670117004
116671117005
SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
116672117006
SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
@@ -116674,21 +117008,22 @@
116674117008
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
116675117009
SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
116676117010
SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
116677117011
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
116678117012
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
117013
+SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *);
116679117014
116680117015
/* Special values interpreted by sqlite3SegReaderCursor() */
116681117016
#define FTS3_SEGCURSOR_PENDING -1
116682117017
#define FTS3_SEGCURSOR_ALL -2
116683117018
116684117019
SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
116685117020
SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
116686117021
SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
116687117022
116688
-SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
116689
- Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *);
117023
+SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *,
117024
+ int, int, int, const char *, int, int, int, Fts3MultiSegReader *);
116690117025
116691117026
/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
116692117027
#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
116693117028
#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
116694117029
#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
@@ -116725,19 +117060,22 @@
116725117060
int nTerm; /* Size of zTerm in bytes */
116726117061
char *aDoclist; /* Pointer to doclist buffer */
116727117062
int nDoclist; /* Size of aDoclist[] in bytes */
116728117063
};
116729117064
117065
+SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
117066
+
116730117067
/* fts3.c */
116731117068
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
116732117069
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
116733117070
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
116734117071
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
116735117072
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
116736117073
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
116737117074
SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
116738117075
SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
117076
+SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
116739117077
116740117078
/* fts3_tokenizer.c */
116741117079
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
116742117080
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
116743117081
SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -116751,18 +117089,22 @@
116751117089
const char *, const char *, int, int
116752117090
);
116753117091
SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
116754117092
116755117093
/* fts3_expr.c */
116756
-SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
117094
+SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
116757117095
char **, int, int, int, const char *, int, Fts3Expr **
116758117096
);
116759117097
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
116760117098
#ifdef SQLITE_TEST
116761117099
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
116762117100
SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
116763117101
#endif
117102
+
117103
+SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
117104
+ sqlite3_tokenizer_cursor **
117105
+);
116764117106
116765117107
/* fts3_aux.c */
116766117108
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
116767117109
116768117110
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
@@ -116954,10 +117296,11 @@
116954117296
}
116955117297
sqlite3_free(p->zSegmentsTbl);
116956117298
sqlite3_free(p->zReadExprlist);
116957117299
sqlite3_free(p->zWriteExprlist);
116958117300
sqlite3_free(p->zContentTbl);
117301
+ sqlite3_free(p->zLanguageid);
116959117302
116960117303
/* Invoke the tokenizer destructor to free the tokenizer. */
116961117304
p->pTokenizer->pModule->xDestroy(p->pTokenizer);
116962117305
116963117306
sqlite3_free(p);
@@ -117030,11 +117373,13 @@
117030117373
if( *pRc==SQLITE_OK ){
117031117374
int i; /* Iterator variable */
117032117375
int rc; /* Return code */
117033117376
char *zSql; /* SQL statement passed to declare_vtab() */
117034117377
char *zCols; /* List of user defined columns */
117378
+ const char *zLanguageid;
117035117379
117380
+ zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid");
117036117381
sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
117037117382
117038117383
/* Create a list of user columns for the virtual table */
117039117384
zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
117040117385
for(i=1; zCols && i<p->nColumn; i++){
@@ -117041,11 +117386,12 @@
117041117386
zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
117042117387
}
117043117388
117044117389
/* Create the whole "CREATE TABLE" statement to pass to SQLite */
117045117390
zSql = sqlite3_mprintf(
117046
- "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName
117391
+ "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
117392
+ zCols, p->zName, zLanguageid
117047117393
);
117048117394
if( !zCols || !zSql ){
117049117395
rc = SQLITE_NOMEM;
117050117396
}else{
117051117397
rc = sqlite3_declare_vtab(p->db, zSql);
@@ -117054,10 +117400,22 @@
117054117400
sqlite3_free(zSql);
117055117401
sqlite3_free(zCols);
117056117402
*pRc = rc;
117057117403
}
117058117404
}
117405
+
117406
+/*
117407
+** Create the %_stat table if it does not already exist.
117408
+*/
117409
+SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){
117410
+ fts3DbExec(pRc, p->db,
117411
+ "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'"
117412
+ "(id INTEGER PRIMARY KEY, value BLOB);",
117413
+ p->zDb, p->zName
117414
+ );
117415
+ if( (*pRc)==SQLITE_OK ) p->bHasStat = 1;
117416
+}
117059117417
117060117418
/*
117061117419
** Create the backing store tables (%_content, %_segments and %_segdir)
117062117420
** required by the FTS3 table passed as the only argument. This is done
117063117421
** as part of the vtab xCreate() method.
@@ -117070,18 +117428,22 @@
117070117428
int rc = SQLITE_OK; /* Return code */
117071117429
int i; /* Iterator variable */
117072117430
sqlite3 *db = p->db; /* The database connection */
117073117431
117074117432
if( p->zContentTbl==0 ){
117433
+ const char *zLanguageid = p->zLanguageid;
117075117434
char *zContentCols; /* Columns of %_content table */
117076117435
117077117436
/* Create a list of user columns for the content table */
117078117437
zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
117079117438
for(i=0; zContentCols && i<p->nColumn; i++){
117080117439
char *z = p->azColumn[i];
117081117440
zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
117082117441
}
117442
+ if( zLanguageid && zContentCols ){
117443
+ zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);
117444
+ }
117083117445
if( zContentCols==0 ) rc = SQLITE_NOMEM;
117084117446
117085117447
/* Create the content table */
117086117448
fts3DbExec(&rc, db,
117087117449
"CREATE TABLE %Q.'%q_content'(%s)",
@@ -117111,15 +117473,13 @@
117111117473
fts3DbExec(&rc, db,
117112117474
"CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
117113117475
p->zDb, p->zName
117114117476
);
117115117477
}
117478
+ assert( p->bHasStat==p->bFts4 );
117116117479
if( p->bHasStat ){
117117
- fts3DbExec(&rc, db,
117118
- "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);",
117119
- p->zDb, p->zName
117120
- );
117480
+ sqlite3Fts3CreateStatTable(&rc, p);
117121117481
}
117122117482
return rc;
117123117483
}
117124117484
117125117485
/*
@@ -117222,11 +117582,11 @@
117222117582
** memory.
117223117583
*/
117224117584
static char *fts3QuoteId(char const *zInput){
117225117585
int nRet;
117226117586
char *zRet;
117227
- nRet = 2 + strlen(zInput)*2 + 1;
117587
+ nRet = 2 + (int)strlen(zInput)*2 + 1;
117228117588
zRet = sqlite3_malloc(nRet);
117229117589
if( zRet ){
117230117590
int i;
117231117591
char *z = zRet;
117232117592
*(z++) = '"';
@@ -117277,18 +117637,24 @@
117277117637
}
117278117638
fts3Appendf(pRc, &zRet, "docid");
117279117639
for(i=0; i<p->nColumn; i++){
117280117640
fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
117281117641
}
117642
+ if( p->zLanguageid ){
117643
+ fts3Appendf(pRc, &zRet, ", x.%Q", "langid");
117644
+ }
117282117645
sqlite3_free(zFree);
117283117646
}else{
117284117647
fts3Appendf(pRc, &zRet, "rowid");
117285117648
for(i=0; i<p->nColumn; i++){
117286117649
fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]);
117287117650
}
117651
+ if( p->zLanguageid ){
117652
+ fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid);
117653
+ }
117288117654
}
117289
- fts3Appendf(pRc, &zRet, "FROM '%q'.'%q%s' AS x",
117655
+ fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
117290117656
p->zDb,
117291117657
(p->zContentTbl ? p->zContentTbl : p->zName),
117292117658
(p->zContentTbl ? "" : "_content")
117293117659
);
117294117660
return zRet;
@@ -117327,10 +117693,13 @@
117327117693
}
117328117694
fts3Appendf(pRc, &zRet, "?");
117329117695
for(i=0; i<p->nColumn; i++){
117330117696
fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
117331117697
}
117698
+ if( p->zLanguageid ){
117699
+ fts3Appendf(pRc, &zRet, ", ?");
117700
+ }
117332117701
sqlite3_free(zFree);
117333117702
return zRet;
117334117703
}
117335117704
117336117705
/*
@@ -117469,11 +117838,11 @@
117469117838
** space required to store a copy of each column name, including the
117470117839
** nul-terminator byte. */
117471117840
nCol = sqlite3_column_count(pStmt);
117472117841
for(i=0; i<nCol; i++){
117473117842
const char *zCol = sqlite3_column_name(pStmt, i);
117474
- nStr += strlen(zCol) + 1;
117843
+ nStr += (int)strlen(zCol) + 1;
117475117844
}
117476117845
117477117846
/* Allocate and populate the array to return. */
117478117847
azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
117479117848
if( azCol==0 ){
@@ -117480,11 +117849,11 @@
117480117849
rc = SQLITE_NOMEM;
117481117850
}else{
117482117851
char *p = (char *)&azCol[nCol];
117483117852
for(i=0; i<nCol; i++){
117484117853
const char *zCol = sqlite3_column_name(pStmt, i);
117485
- int n = strlen(zCol)+1;
117854
+ int n = (int)strlen(zCol)+1;
117486117855
memcpy(p, zCol, n);
117487117856
azCol[i] = p;
117488117857
p += n;
117489117858
}
117490117859
}
@@ -117542,10 +117911,11 @@
117542117911
int bDescIdx = 0; /* True to store descending indexes */
117543117912
char *zPrefix = 0; /* Prefix parameter value (or NULL) */
117544117913
char *zCompress = 0; /* compress=? parameter (or NULL) */
117545117914
char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
117546117915
char *zContent = 0; /* content=? parameter (or NULL) */
117916
+ char *zLanguageid = 0; /* languageid=? parameter (or NULL) */
117547117917
117548117918
assert( strlen(argv[0])==4 );
117549117919
assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
117550117920
|| (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
117551117921
);
@@ -117591,11 +117961,12 @@
117591117961
{ "matchinfo", 9 }, /* 0 -> MATCHINFO */
117592117962
{ "prefix", 6 }, /* 1 -> PREFIX */
117593117963
{ "compress", 8 }, /* 2 -> COMPRESS */
117594117964
{ "uncompress", 10 }, /* 3 -> UNCOMPRESS */
117595117965
{ "order", 5 }, /* 4 -> ORDER */
117596
- { "content", 7 } /* 5 -> CONTENT */
117966
+ { "content", 7 }, /* 5 -> CONTENT */
117967
+ { "languageid", 10 } /* 6 -> LANGUAGEID */
117597117968
};
117598117969
117599117970
int iOpt;
117600117971
if( !zVal ){
117601117972
rc = SQLITE_NOMEM;
@@ -117645,16 +118016,22 @@
117645118016
rc = SQLITE_ERROR;
117646118017
}
117647118018
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
117648118019
break;
117649118020
117650
- default: /* CONTENT */
117651
- assert( iOpt==5 );
117652
- sqlite3_free(zUncompress);
118021
+ case 5: /* CONTENT */
118022
+ sqlite3_free(zContent);
117653118023
zContent = zVal;
117654118024
zVal = 0;
117655118025
break;
118026
+
118027
+ case 6: /* LANGUAGEID */
118028
+ assert( iOpt==6 );
118029
+ sqlite3_free(zLanguageid);
118030
+ zLanguageid = zVal;
118031
+ zVal = 0;
118032
+ break;
117656118033
}
117657118034
}
117658118035
sqlite3_free(zVal);
117659118036
}
117660118037
}
@@ -117680,12 +118057,25 @@
117680118057
zUncompress = 0;
117681118058
if( nCol==0 ){
117682118059
sqlite3_free((void*)aCol);
117683118060
aCol = 0;
117684118061
rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
118062
+
118063
+ /* If a languageid= option was specified, remove the language id
118064
+ ** column from the aCol[] array. */
118065
+ if( rc==SQLITE_OK && zLanguageid ){
118066
+ int j;
118067
+ for(j=0; j<nCol; j++){
118068
+ if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){
118069
+ int k;
118070
+ for(k=j; k<nCol; k++) aCol[k] = aCol[k+1];
118071
+ nCol--;
118072
+ break;
118073
+ }
118074
+ }
118075
+ }
117685118076
}
117686
- assert( rc!=SQLITE_OK || nCol>0 );
117687118077
}
117688118078
if( rc!=SQLITE_OK ) goto fts3_init_out;
117689118079
117690118080
if( nCol==0 ){
117691118081
assert( nString==0 );
@@ -117726,13 +118116,17 @@
117726118116
p->azColumn = (char **)&p[1];
117727118117
p->pTokenizer = pTokenizer;
117728118118
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
117729118119
p->bHasDocsize = (isFts4 && bNoDocsize==0);
117730118120
p->bHasStat = isFts4;
118121
+ p->bFts4 = isFts4;
117731118122
p->bDescIdx = bDescIdx;
118123
+ p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */
117732118124
p->zContentTbl = zContent;
118125
+ p->zLanguageid = zLanguageid;
117733118126
zContent = 0;
118127
+ zLanguageid = 0;
117734118128
TESTONLY( p->inTransaction = -1 );
117735118129
TESTONLY( p->mxSavepoint = -1 );
117736118130
117737118131
p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
117738118132
memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
@@ -117776,10 +118170,20 @@
117776118170
** database. TODO: For xConnect(), it could verify that said tables exist.
117777118171
*/
117778118172
if( isCreate ){
117779118173
rc = fts3CreateTables(p);
117780118174
}
118175
+
118176
+ /* Check to see if a legacy fts3 table has been "upgraded" by the
118177
+ ** addition of a %_stat table so that it can use incremental merge.
118178
+ */
118179
+ if( !isFts4 && !isCreate ){
118180
+ int rc2 = SQLITE_OK;
118181
+ fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
118182
+ p->zDb, p->zName);
118183
+ if( rc2==SQLITE_OK ) p->bHasStat = 1;
118184
+ }
117781118185
117782118186
/* Figure out the page-size for the database. This is required in order to
117783118187
** estimate the cost of loading large doclists from the database. */
117784118188
fts3DatabasePageSize(&rc, p);
117785118189
p->nNodeSize = p->nPgsz-35;
@@ -117791,10 +118195,11 @@
117791118195
sqlite3_free(zPrefix);
117792118196
sqlite3_free(aIndex);
117793118197
sqlite3_free(zCompress);
117794118198
sqlite3_free(zUncompress);
117795118199
sqlite3_free(zContent);
118200
+ sqlite3_free(zLanguageid);
117796118201
sqlite3_free((void *)aCol);
117797118202
if( rc!=SQLITE_OK ){
117798118203
if( p ){
117799118204
fts3DisconnectMethod((sqlite3_vtab *)p);
117800118205
}else if( pTokenizer ){
@@ -117842,10 +118247,11 @@
117842118247
*/
117843118248
static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
117844118249
Fts3Table *p = (Fts3Table *)pVTab;
117845118250
int i; /* Iterator variable */
117846118251
int iCons = -1; /* Index of constraint to use */
118252
+ int iLangidCons = -1; /* Index of langid=x constraint, if present */
117847118253
117848118254
/* By default use a full table scan. This is an expensive option,
117849118255
** so search through the constraints to see if a more efficient
117850118256
** strategy is possible.
117851118257
*/
@@ -117854,11 +118260,12 @@
117854118260
for(i=0; i<pInfo->nConstraint; i++){
117855118261
struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
117856118262
if( pCons->usable==0 ) continue;
117857118263
117858118264
/* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
117859
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
118265
+ if( iCons<0
118266
+ && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
117860118267
&& (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
117861118268
){
117862118269
pInfo->idxNum = FTS3_DOCID_SEARCH;
117863118270
pInfo->estimatedCost = 1.0;
117864118271
iCons = i;
@@ -117877,18 +118284,27 @@
117877118284
&& pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
117878118285
){
117879118286
pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
117880118287
pInfo->estimatedCost = 2.0;
117881118288
iCons = i;
117882
- break;
118289
+ }
118290
+
118291
+ /* Equality constraint on the langid column */
118292
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
118293
+ && pCons->iColumn==p->nColumn + 2
118294
+ ){
118295
+ iLangidCons = i;
117883118296
}
117884118297
}
117885118298
117886118299
if( iCons>=0 ){
117887118300
pInfo->aConstraintUsage[iCons].argvIndex = 1;
117888118301
pInfo->aConstraintUsage[iCons].omit = 1;
117889118302
}
118303
+ if( iLangidCons>=0 ){
118304
+ pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
118305
+ }
117890118306
117891118307
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
117892118308
** docid) order. Both ascending and descending are possible.
117893118309
*/
117894118310
if( pInfo->nOrderBy==1 ){
@@ -118768,11 +119184,11 @@
118768119184
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
118769119185
}
118770119186
}
118771119187
118772119188
*paOut = aOut;
118773
- *pnOut = (p-aOut);
119189
+ *pnOut = (int)(p-aOut);
118774119190
assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
118775119191
return SQLITE_OK;
118776119192
}
118777119193
118778119194
/*
@@ -118832,11 +119248,11 @@
118832119248
fts3PoslistCopy(0, &p2);
118833119249
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
118834119250
}
118835119251
}
118836119252
118837
- *pnRight = p - aOut;
119253
+ *pnRight = (int)(p - aOut);
118838119254
}
118839119255
118840119256
/*
118841119257
** Argument pList points to a position list nList bytes in size. This
118842119258
** function checks to see if the position list contains any entries for
@@ -119034,10 +119450,11 @@
119034119450
** This function returns SQLITE_OK if successful, or an SQLite error code
119035119451
** otherwise.
119036119452
*/
119037119453
static int fts3SegReaderCursor(
119038119454
Fts3Table *p, /* FTS3 table handle */
119455
+ int iLangid, /* Language id */
119039119456
int iIndex, /* Index to search (from 0 to p->nIndex-1) */
119040119457
int iLevel, /* Level of segments to scan */
119041119458
const char *zTerm, /* Term to query for */
119042119459
int nTerm, /* Size of zTerm in bytes */
119043119460
int isPrefix, /* True for a prefix search */
@@ -119062,11 +119479,11 @@
119062119479
}
119063119480
}
119064119481
119065119482
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
119066119483
if( rc==SQLITE_OK ){
119067
- rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt);
119484
+ rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt);
119068119485
}
119069119486
119070119487
while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
119071119488
Fts3SegReader *pSeg = 0;
119072119489
@@ -119107,10 +119524,11 @@
119107119524
** Set up a cursor object for iterating through a full-text index or a
119108119525
** single level therein.
119109119526
*/
119110119527
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
119111119528
Fts3Table *p, /* FTS3 table handle */
119529
+ int iLangid, /* Language-id to search */
119112119530
int iIndex, /* Index to search (from 0 to p->nIndex-1) */
119113119531
int iLevel, /* Level of segments to scan */
119114119532
const char *zTerm, /* Term to query for */
119115119533
int nTerm, /* Size of zTerm in bytes */
119116119534
int isPrefix, /* True for a prefix search */
@@ -119124,18 +119542,13 @@
119124119542
);
119125119543
assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
119126119544
assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
119127119545
assert( isPrefix==0 || isScan==0 );
119128119546
119129
- /* "isScan" is only set to true by the ft4aux module, an ordinary
119130
- ** full-text tables. */
119131
- assert( isScan==0 || p->aIndex==0 );
119132
-
119133119547
memset(pCsr, 0, sizeof(Fts3MultiSegReader));
119134
-
119135119548
return fts3SegReaderCursor(
119136
- p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
119549
+ p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
119137119550
);
119138119551
}
119139119552
119140119553
/*
119141119554
** In addition to its current configuration, have the Fts3MultiSegReader
@@ -119143,15 +119556,18 @@
119143119556
**
119144119557
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
119145119558
*/
119146119559
static int fts3SegReaderCursorAddZero(
119147119560
Fts3Table *p, /* FTS virtual table handle */
119561
+ int iLangid,
119148119562
const char *zTerm, /* Term to scan doclist of */
119149119563
int nTerm, /* Number of bytes in zTerm */
119150119564
Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
119151119565
){
119152
- return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
119566
+ return fts3SegReaderCursor(p,
119567
+ iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
119568
+ );
119153119569
}
119154119570
119155119571
/*
119156119572
** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
119157119573
** if isPrefix is true, to scan the doclist for all terms for which
@@ -119183,32 +119599,35 @@
119183119599
119184119600
if( isPrefix ){
119185119601
for(i=1; bFound==0 && i<p->nIndex; i++){
119186119602
if( p->aIndex[i].nPrefix==nTerm ){
119187119603
bFound = 1;
119188
- rc = sqlite3Fts3SegReaderCursor(
119189
- p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr);
119604
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
119605
+ i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
119606
+ );
119190119607
pSegcsr->bLookup = 1;
119191119608
}
119192119609
}
119193119610
119194119611
for(i=1; bFound==0 && i<p->nIndex; i++){
119195119612
if( p->aIndex[i].nPrefix==nTerm+1 ){
119196119613
bFound = 1;
119197
- rc = sqlite3Fts3SegReaderCursor(
119198
- p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
119614
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
119615
+ i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
119199119616
);
119200119617
if( rc==SQLITE_OK ){
119201
- rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr);
119618
+ rc = fts3SegReaderCursorAddZero(
119619
+ p, pCsr->iLangid, zTerm, nTerm, pSegcsr
119620
+ );
119202119621
}
119203119622
}
119204119623
}
119205119624
}
119206119625
119207119626
if( bFound==0 ){
119208
- rc = sqlite3Fts3SegReaderCursor(
119209
- p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
119627
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
119628
+ 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
119210119629
);
119211119630
pSegcsr->bLookup = !isPrefix;
119212119631
}
119213119632
}
119214119633
@@ -119359,11 +119778,11 @@
119359119778
119360119779
UNUSED_PARAMETER(idxStr);
119361119780
UNUSED_PARAMETER(nVal);
119362119781
119363119782
assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
119364
- assert( nVal==0 || nVal==1 );
119783
+ assert( nVal==0 || nVal==1 || nVal==2 );
119365119784
assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
119366119785
assert( p->pSegments==0 );
119367119786
119368119787
/* In case the cursor has been used before, clear it now. */
119369119788
sqlite3_finalize(pCsr->pStmt);
@@ -119384,12 +119803,15 @@
119384119803
119385119804
if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
119386119805
return SQLITE_NOMEM;
119387119806
}
119388119807
119389
- rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->bHasStat,
119390
- p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
119808
+ pCsr->iLangid = 0;
119809
+ if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
119810
+
119811
+ rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
119812
+ p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
119391119813
);
119392119814
if( rc!=SQLITE_OK ){
119393119815
if( rc==SQLITE_ERROR ){
119394119816
static const char *zErr = "malformed MATCH expression: [%s]";
119395119817
p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
@@ -119456,37 +119878,56 @@
119456119878
}
119457119879
119458119880
/*
119459119881
** This is the xColumn method, called by SQLite to request a value from
119460119882
** the row that the supplied cursor currently points to.
119883
+**
119884
+** If:
119885
+**
119886
+** (iCol < p->nColumn) -> The value of the iCol'th user column.
119887
+** (iCol == p->nColumn) -> Magic column with the same name as the table.
119888
+** (iCol == p->nColumn+1) -> Docid column
119889
+** (iCol == p->nColumn+2) -> Langid column
119461119890
*/
119462119891
static int fts3ColumnMethod(
119463119892
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
119464
- sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
119893
+ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
119465119894
int iCol /* Index of column to read value from */
119466119895
){
119467119896
int rc = SQLITE_OK; /* Return Code */
119468119897
Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
119469119898
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
119470119899
119471119900
/* The column value supplied by SQLite must be in range. */
119472
- assert( iCol>=0 && iCol<=p->nColumn+1 );
119901
+ assert( iCol>=0 && iCol<=p->nColumn+2 );
119473119902
119474119903
if( iCol==p->nColumn+1 ){
119475119904
/* This call is a request for the "docid" column. Since "docid" is an
119476119905
** alias for "rowid", use the xRowid() method to obtain the value.
119477119906
*/
119478
- sqlite3_result_int64(pContext, pCsr->iPrevId);
119907
+ sqlite3_result_int64(pCtx, pCsr->iPrevId);
119479119908
}else if( iCol==p->nColumn ){
119480119909
/* The extra column whose name is the same as the table.
119481
- ** Return a blob which is a pointer to the cursor.
119482
- */
119483
- sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
119910
+ ** Return a blob which is a pointer to the cursor. */
119911
+ sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
119912
+ }else if( iCol==p->nColumn+2 && pCsr->pExpr ){
119913
+ sqlite3_result_int64(pCtx, pCsr->iLangid);
119484119914
}else{
119915
+ /* The requested column is either a user column (one that contains
119916
+ ** indexed data), or the language-id column. */
119485119917
rc = fts3CursorSeek(0, pCsr);
119486
- if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
119487
- sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
119918
+
119919
+ if( rc==SQLITE_OK ){
119920
+ if( iCol==p->nColumn+2 ){
119921
+ int iLangid = 0;
119922
+ if( p->zLanguageid ){
119923
+ iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
119924
+ }
119925
+ sqlite3_result_int(pCtx, iLangid);
119926
+ }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
119927
+ sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
119928
+ }
119488119929
}
119489119930
}
119490119931
119491119932
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
119492119933
return rc;
@@ -119509,26 +119950,61 @@
119509119950
/*
119510119951
** Implementation of xSync() method. Flush the contents of the pending-terms
119511119952
** hash-table to the database.
119512119953
*/
119513119954
static int fts3SyncMethod(sqlite3_vtab *pVtab){
119514
- int rc = sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab);
119515
- sqlite3Fts3SegmentsClose((Fts3Table *)pVtab);
119955
+
119956
+ /* Following an incremental-merge operation, assuming that the input
119957
+ ** segments are not completely consumed (the usual case), they are updated
119958
+ ** in place to remove the entries that have already been merged. This
119959
+ ** involves updating the leaf block that contains the smallest unmerged
119960
+ ** entry and each block (if any) between the leaf and the root node. So
119961
+ ** if the height of the input segment b-trees is N, and input segments
119962
+ ** are merged eight at a time, updating the input segments at the end
119963
+ ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually
119964
+ ** small - often between 0 and 2. So the overhead of the incremental
119965
+ ** merge is somewhere between 8 and 24 blocks. To avoid this overhead
119966
+ ** dwarfing the actual productive work accomplished, the incremental merge
119967
+ ** is only attempted if it will write at least 64 leaf blocks. Hence
119968
+ ** nMinMerge.
119969
+ **
119970
+ ** Of course, updating the input segments also involves deleting a bunch
119971
+ ** of blocks from the segments table. But this is not considered overhead
119972
+ ** as it would also be required by a crisis-merge that used the same input
119973
+ ** segments.
119974
+ */
119975
+ const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
119976
+
119977
+ Fts3Table *p = (Fts3Table*)pVtab;
119978
+ int rc = sqlite3Fts3PendingTermsFlush(p);
119979
+
119980
+ if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
119981
+ int mxLevel = 0; /* Maximum relative level value in db */
119982
+ int A; /* Incr-merge parameter A */
119983
+
119984
+ rc = sqlite3Fts3MaxLevel(p, &mxLevel);
119985
+ assert( rc==SQLITE_OK || mxLevel==0 );
119986
+ A = p->nLeafAdd * mxLevel;
119987
+ A += (A/2);
119988
+ if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
119989
+ }
119990
+ sqlite3Fts3SegmentsClose(p);
119516119991
return rc;
119517119992
}
119518119993
119519119994
/*
119520119995
** Implementation of xBegin() method. This is a no-op.
119521119996
*/
119522119997
static int fts3BeginMethod(sqlite3_vtab *pVtab){
119523
- TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
119998
+ Fts3Table *p = (Fts3Table*)pVtab;
119524119999
UNUSED_PARAMETER(pVtab);
119525120000
assert( p->pSegments==0 );
119526120001
assert( p->nPendingData==0 );
119527120002
assert( p->inTransaction!=1 );
119528120003
TESTONLY( p->inTransaction = 1 );
119529120004
TESTONLY( p->mxSavepoint = -1; );
120005
+ p->nLeafAdd = 0;
119530120006
return SQLITE_OK;
119531120007
}
119532120008
119533120009
/*
119534120010
** Implementation of xCommit() method. This is a no-op. The contents of
@@ -119819,15 +120295,19 @@
119819120295
** The xSavepoint() method.
119820120296
**
119821120297
** Flush the contents of the pending-terms table to disk.
119822120298
*/
119823120299
static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
120300
+ int rc = SQLITE_OK;
119824120301
UNUSED_PARAMETER(iSavepoint);
119825120302
assert( ((Fts3Table *)pVtab)->inTransaction );
119826120303
assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
119827120304
TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
119828
- return fts3SyncMethod(pVtab);
120305
+ if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){
120306
+ rc = fts3SyncMethod(pVtab);
120307
+ }
120308
+ return rc;
119829120309
}
119830120310
119831120311
/*
119832120312
** The xRelease() method.
119833120313
**
@@ -120183,11 +120663,11 @@
120183120663
120184120664
assert( iPrev>=0 );
120185120665
fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
120186120666
sqlite3_free(aPoslist);
120187120667
aPoslist = pList;
120188
- nPoslist = aOut - aPoslist;
120668
+ nPoslist = (int)(aOut - aPoslist);
120189120669
if( nPoslist==0 ){
120190120670
sqlite3_free(aPoslist);
120191120671
pPhrase->doclist.pList = 0;
120192120672
pPhrase->doclist.nList = 0;
120193120673
return SQLITE_OK;
@@ -120227,11 +120707,11 @@
120227120707
}
120228120708
120229120709
pPhrase->doclist.pList = aOut;
120230120710
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
120231120711
pPhrase->doclist.bFreeList = 1;
120232
- pPhrase->doclist.nList = (aOut - pPhrase->doclist.pList);
120712
+ pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
120233120713
}else{
120234120714
sqlite3_free(aOut);
120235120715
pPhrase->doclist.pList = 0;
120236120716
pPhrase->doclist.nList = 0;
120237120717
}
@@ -120323,11 +120803,11 @@
120323120803
fts3PoslistCopy(0, &pDocid);
120324120804
while( pDocid<pEnd && *pDocid==0 ) pDocid++;
120325120805
iMul = (bDescIdx ? -1 : 1);
120326120806
}
120327120807
120328
- *pnList = pEnd - pNext;
120808
+ *pnList = (int)(pEnd - pNext);
120329120809
*ppIter = pNext;
120330120810
*piDocid = iDocid;
120331120811
}else{
120332120812
int iMul = (bDescIdx ? -1 : 1);
120333120813
sqlite3_int64 iDelta;
@@ -120337,11 +120817,11 @@
120337120817
if( p==aDoclist ){
120338120818
*pbEof = 1;
120339120819
}else{
120340120820
char *pSave = p;
120341120821
fts3ReversePoslist(aDoclist, &p);
120342
- *pnList = (pSave - p);
120822
+ *pnList = (int)(pSave - p);
120343120823
}
120344120824
*ppIter = p;
120345120825
}
120346120826
}
120347120827
@@ -120397,11 +120877,11 @@
120397120877
}else{
120398120878
pDL->iDocid -= iDelta;
120399120879
}
120400120880
pDL->pList = pIter;
120401120881
fts3PoslistCopy(0, &pIter);
120402
- pDL->nList = (pIter - pDL->pList);
120882
+ pDL->nList = (int)(pIter - pDL->pList);
120403120883
120404120884
/* pIter now points just past the 0x00 that terminates the position-
120405120885
** list for document pDL->iDocid. However, if this position-list was
120406120886
** edited in place by fts3EvalNearTrim(), then pIter may not actually
120407120887
** point to the start of the next docid value. The following line deals
@@ -120738,11 +121218,11 @@
120738121218
120739121219
/* Allocate a MultiSegReader for each token in the expression. */
120740121220
fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
120741121221
120742121222
/* Determine which, if any, tokens in the expression should be deferred. */
120743
- if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
121223
+ if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
120744121224
Fts3TokenAndCost *aTC;
120745121225
Fts3Expr **apOr;
120746121226
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
120747121227
sizeof(Fts3TokenAndCost) * nToken
120748121228
+ sizeof(Fts3Expr *) * nOr * 2
@@ -120755,12 +121235,12 @@
120755121235
int ii;
120756121236
Fts3TokenAndCost *pTC = aTC;
120757121237
Fts3Expr **ppOr = apOr;
120758121238
120759121239
fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
120760
- nToken = pTC-aTC;
120761
- nOr = ppOr-apOr;
121240
+ nToken = (int)(pTC-aTC);
121241
+ nOr = (int)(ppOr-apOr);
120762121242
120763121243
if( rc==SQLITE_OK ){
120764121244
rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
120765121245
for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
120766121246
rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
@@ -120828,11 +121308,11 @@
120828121308
p2 = pOut = pPhrase->doclist.pList;
120829121309
res = fts3PoslistNearMerge(
120830121310
&pOut, aTmp, nParam1, nParam2, paPoslist, &p2
120831121311
);
120832121312
if( res ){
120833
- nNew = (pOut - pPhrase->doclist.pList) - 1;
121313
+ nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
120834121314
assert( pPhrase->doclist.pList[nNew]=='\0' );
120835121315
assert( nNew<=pPhrase->doclist.nList && nNew>0 );
120836121316
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
120837121317
pPhrase->doclist.nList = nNew;
120838121318
*paPoslist = pPhrase->doclist.pList;
@@ -121553,10 +122033,11 @@
121553122033
fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
121554122034
pPhrase->aToken[i].pSegcsr = 0;
121555122035
}
121556122036
}
121557122037
}
122038
+
121558122039
121559122040
/*
121560122041
** Return SQLITE_CORRUPT_VTAB.
121561122042
*/
121562122043
#ifdef SQLITE_DEBUG
@@ -121661,13 +122142,13 @@
121661122142
);
121662122143
return SQLITE_ERROR;
121663122144
}
121664122145
121665122146
zDb = argv[1];
121666
- nDb = strlen(zDb);
122147
+ nDb = (int)strlen(zDb);
121667122148
zFts3 = argv[3];
121668
- nFts3 = strlen(zFts3);
122149
+ nFts3 = (int)strlen(zFts3);
121669122150
121670122151
rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
121671122152
if( rc!=SQLITE_OK ) return rc;
121672122153
121673122154
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
@@ -121958,11 +122439,11 @@
121958122439
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
121959122440
pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
121960122441
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
121961122442
}
121962122443
121963
- rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL,
122444
+ rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
121964122445
pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
121965122446
);
121966122447
if( rc==SQLITE_OK ){
121967122448
rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
121968122449
}
@@ -122150,10 +122631,11 @@
122150122631
** zero.
122151122632
*/
122152122633
typedef struct ParseContext ParseContext;
122153122634
struct ParseContext {
122154122635
sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
122636
+ int iLangid; /* Language id used with tokenizer */
122155122637
const char **azCol; /* Array of column names for fts3 table */
122156122638
int bFts4; /* True to allow FTS4-only syntax */
122157122639
int nCol; /* Number of entries in azCol[] */
122158122640
int iDefaultCol; /* Default column to query */
122159122641
int isNot; /* True if getNextNode() sees a unary - */
@@ -122185,10 +122667,37 @@
122185122667
void *pRet = sqlite3_malloc(nByte);
122186122668
if( pRet ) memset(pRet, 0, nByte);
122187122669
return pRet;
122188122670
}
122189122671
122672
+SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
122673
+ sqlite3_tokenizer *pTokenizer,
122674
+ int iLangid,
122675
+ const char *z,
122676
+ int n,
122677
+ sqlite3_tokenizer_cursor **ppCsr
122678
+){
122679
+ sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
122680
+ sqlite3_tokenizer_cursor *pCsr = 0;
122681
+ int rc;
122682
+
122683
+ rc = pModule->xOpen(pTokenizer, z, n, &pCsr);
122684
+ assert( rc==SQLITE_OK || pCsr==0 );
122685
+ if( rc==SQLITE_OK ){
122686
+ pCsr->pTokenizer = pTokenizer;
122687
+ if( pModule->iVersion>=1 ){
122688
+ rc = pModule->xLanguageid(pCsr, iLangid);
122689
+ if( rc!=SQLITE_OK ){
122690
+ pModule->xClose(pCsr);
122691
+ pCsr = 0;
122692
+ }
122693
+ }
122694
+ }
122695
+ *ppCsr = pCsr;
122696
+ return rc;
122697
+}
122698
+
122190122699
122191122700
/*
122192122701
** Extract the next token from buffer z (length n) using the tokenizer
122193122702
** and other information (column names etc.) in pParse. Create an Fts3Expr
122194122703
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -122212,19 +122721,17 @@
122212122721
int rc;
122213122722
sqlite3_tokenizer_cursor *pCursor;
122214122723
Fts3Expr *pRet = 0;
122215122724
int nConsumed = 0;
122216122725
122217
- rc = pModule->xOpen(pTokenizer, z, n, &pCursor);
122726
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
122218122727
if( rc==SQLITE_OK ){
122219122728
const char *zToken;
122220122729
int nToken, iStart, iEnd, iPosition;
122221122730
int nByte; /* total space to allocate */
122222122731
122223
- pCursor->pTokenizer = pTokenizer;
122224122732
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
122225
-
122226122733
if( rc==SQLITE_OK ){
122227122734
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
122228122735
pRet = (Fts3Expr *)fts3MallocZero(nByte);
122229122736
if( !pRet ){
122230122737
rc = SQLITE_NOMEM;
@@ -122326,14 +122833,14 @@
122326122833
**
122327122834
** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
122328122835
** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
122329122836
** structures.
122330122837
*/
122331
- rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor);
122838
+ rc = sqlite3Fts3OpenTokenizer(
122839
+ pTokenizer, pParse->iLangid, zInput, nInput, &pCursor);
122332122840
if( rc==SQLITE_OK ){
122333122841
int ii;
122334
- pCursor->pTokenizer = pTokenizer;
122335122842
for(ii=0; rc==SQLITE_OK; ii++){
122336122843
const char *zByte;
122337122844
int nByte, iBegin, iEnd, iPos;
122338122845
rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
122339122846
if( rc==SQLITE_OK ){
@@ -122803,10 +123310,11 @@
122803123310
** specified as part of the query string), or -1 if tokens may by default
122804123311
** match any table column.
122805123312
*/
122806123313
SQLITE_PRIVATE int sqlite3Fts3ExprParse(
122807123314
sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
123315
+ int iLangid, /* Language id for tokenizer */
122808123316
char **azCol, /* Array of column names for fts3 table */
122809123317
int bFts4, /* True to allow FTS4-only syntax */
122810123318
int nCol, /* Number of entries in azCol[] */
122811123319
int iDefaultCol, /* Default column to query */
122812123320
const char *z, int n, /* Text of MATCH query */
@@ -122813,15 +123321,17 @@
122813123321
Fts3Expr **ppExpr /* OUT: Parsed query structure */
122814123322
){
122815123323
int nParsed;
122816123324
int rc;
122817123325
ParseContext sParse;
123326
+
123327
+ memset(&sParse, 0, sizeof(ParseContext));
122818123328
sParse.pTokenizer = pTokenizer;
123329
+ sParse.iLangid = iLangid;
122819123330
sParse.azCol = (const char **)azCol;
122820123331
sParse.nCol = nCol;
122821123332
sParse.iDefaultCol = iDefaultCol;
122822
- sParse.nNest = 0;
122823123333
sParse.bFts4 = bFts4;
122824123334
if( z==0 ){
122825123335
*ppExpr = 0;
122826123336
return SQLITE_OK;
122827123337
}
@@ -123008,11 +123518,11 @@
123008123518
for(ii=0; ii<nCol; ii++){
123009123519
azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
123010123520
}
123011123521
123012123522
rc = sqlite3Fts3ExprParse(
123013
- pTokenizer, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
123523
+ pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
123014123524
);
123015123525
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
123016123526
sqlite3_result_error(context, "Error parsing expression", -1);
123017123527
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
123018123528
sqlite3_result_error_nomem(context);
@@ -124057,10 +124567,11 @@
124057124567
porterCreate,
124058124568
porterDestroy,
124059124569
porterOpen,
124060124570
porterClose,
124061124571
porterNext,
124572
+ 0
124062124573
};
124063124574
124064124575
/*
124065124576
** Allocate a new porter tokenizer. Return a pointer to the new
124066124577
** tokenizer in *ppModule
@@ -124362,15 +124873,14 @@
124362124873
if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
124363124874
zErr = "error in xCreate()";
124364124875
goto finish;
124365124876
}
124366124877
pTokenizer->pModule = p;
124367
- if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){
124878
+ if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){
124368124879
zErr = "error in xOpen()";
124369124880
goto finish;
124370124881
}
124371
- pCsr->pTokenizer = pTokenizer;
124372124882
124373124883
while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
124374124884
Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
124375124885
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
124376124886
zToken = &zInput[iStart];
@@ -124782,10 +125292,11 @@
124782125292
simpleCreate,
124783125293
simpleDestroy,
124784125294
simpleOpen,
124785125295
simpleClose,
124786125296
simpleNext,
125297
+ 0,
124787125298
};
124788125299
124789125300
/*
124790125301
** Allocate a new simple tokenizer. Return a pointer to the new
124791125302
** tokenizer in *ppModule
@@ -124823,10 +125334,13 @@
124823125334
124824125335
/* #include <string.h> */
124825125336
/* #include <assert.h> */
124826125337
/* #include <stdlib.h> */
124827125338
125339
+
125340
+#define FTS_MAX_APPENDABLE_HEIGHT 16
125341
+
124828125342
/*
124829125343
** When full-text index nodes are loaded from disk, the buffer that they
124830125344
** are loaded into has the following number of bytes of padding at the end
124831125345
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
124832125346
** of 920 bytes is allocated for it.
@@ -124861,10 +125375,33 @@
124861125375
# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
124862125376
#else
124863125377
# define FTS3_NODE_CHUNKSIZE (4*1024)
124864125378
# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
124865125379
#endif
125380
+
125381
+/*
125382
+** The two values that may be meaningfully bound to the :1 parameter in
125383
+** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
125384
+*/
125385
+#define FTS_STAT_DOCTOTAL 0
125386
+#define FTS_STAT_INCRMERGEHINT 1
125387
+#define FTS_STAT_AUTOINCRMERGE 2
125388
+
125389
+/*
125390
+** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
125391
+** and incremental merge operation that takes place. This is used for
125392
+** debugging FTS only, it should not usually be turned on in production
125393
+** systems.
125394
+*/
125395
+#ifdef FTS3_LOG_MERGES
125396
+static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){
125397
+ sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel);
125398
+}
125399
+#else
125400
+#define fts3LogMerge(x, y)
125401
+#endif
125402
+
124866125403
124867125404
typedef struct PendingList PendingList;
124868125405
typedef struct SegmentNode SegmentNode;
124869125406
typedef struct SegmentWriter SegmentWriter;
124870125407
@@ -125023,17 +125560,26 @@
125023125560
#define SQL_DELETE_SEGMENTS_RANGE 17
125024125561
#define SQL_CONTENT_INSERT 18
125025125562
#define SQL_DELETE_DOCSIZE 19
125026125563
#define SQL_REPLACE_DOCSIZE 20
125027125564
#define SQL_SELECT_DOCSIZE 21
125028
-#define SQL_SELECT_DOCTOTAL 22
125029
-#define SQL_REPLACE_DOCTOTAL 23
125565
+#define SQL_SELECT_STAT 22
125566
+#define SQL_REPLACE_STAT 23
125030125567
125031125568
#define SQL_SELECT_ALL_PREFIX_LEVEL 24
125032125569
#define SQL_DELETE_ALL_TERMS_SEGDIR 25
125033
-
125034125570
#define SQL_DELETE_SEGDIR_RANGE 26
125571
+#define SQL_SELECT_ALL_LANGID 27
125572
+#define SQL_FIND_MERGE_LEVEL 28
125573
+#define SQL_MAX_LEAF_NODE_ESTIMATE 29
125574
+#define SQL_DELETE_SEGDIR_ENTRY 30
125575
+#define SQL_SHIFT_SEGDIR_ENTRY 31
125576
+#define SQL_SELECT_SEGDIR 32
125577
+#define SQL_CHOMP_SEGDIR 33
125578
+#define SQL_SEGMENT_IS_APPENDABLE 34
125579
+#define SQL_SELECT_INDEXES 35
125580
+#define SQL_SELECT_MXLEVEL 36
125035125581
125036125582
/*
125037125583
** This function is used to obtain an SQLite prepared statement handle
125038125584
** for the statement identified by the second argument. If successful,
125039125585
** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -125058,13 +125604,13 @@
125058125604
/* 4 */ "DELETE FROM %Q.'%q_segdir'",
125059125605
/* 5 */ "DELETE FROM %Q.'%q_docsize'",
125060125606
/* 6 */ "DELETE FROM %Q.'%q_stat'",
125061125607
/* 7 */ "SELECT %s WHERE rowid=?",
125062125608
/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
125063
-/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
125609
+/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
125064125610
/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
125065
-/* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
125611
+/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
125066125612
125067125613
/* Return segments in order from oldest to newest.*/
125068125614
/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
125069125615
"FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
125070125616
/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
@@ -125078,17 +125624,65 @@
125078125624
/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
125079125625
/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
125080125626
/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
125081125627
/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
125082125628
/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
125083
-/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
125084
-/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
125629
+/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?",
125630
+/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)",
125085125631
/* 24 */ "",
125086125632
/* 25 */ "",
125087125633
125088125634
/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
125635
+/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
125089125636
125637
+/* This statement is used to determine which level to read the input from
125638
+** when performing an incremental merge. It returns the absolute level number
125639
+** of the oldest level in the db that contains at least ? segments. Or,
125640
+** if no level in the FTS index contains more than ? segments, the statement
125641
+** returns zero rows. */
125642
+/* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?"
125643
+ " ORDER BY (level %% 1024) ASC LIMIT 1",
125644
+
125645
+/* Estimate the upper limit on the number of leaf nodes in a new segment
125646
+** created by merging the oldest :2 segments from absolute level :1. See
125647
+** function sqlite3Fts3Incrmerge() for details. */
125648
+/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
125649
+ " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
125650
+
125651
+/* SQL_DELETE_SEGDIR_ENTRY
125652
+** Delete the %_segdir entry on absolute level :1 with index :2. */
125653
+/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
125654
+
125655
+/* SQL_SHIFT_SEGDIR_ENTRY
125656
+** Modify the idx value for the segment with idx=:3 on absolute level :2
125657
+** to :1. */
125658
+/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?",
125659
+
125660
+/* SQL_SELECT_SEGDIR
125661
+** Read a single entry from the %_segdir table. The entry from absolute
125662
+** level :1 with index value :2. */
125663
+/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
125664
+ "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
125665
+
125666
+/* SQL_CHOMP_SEGDIR
125667
+** Update the start_block (:1) and root (:2) fields of the %_segdir
125668
+** entry located on absolute level :3 with index :4. */
125669
+/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?"
125670
+ "WHERE level = ? AND idx = ?",
125671
+
125672
+/* SQL_SEGMENT_IS_APPENDABLE
125673
+** Return a single row if the segment with end_block=? is appendable. Or
125674
+** no rows otherwise. */
125675
+/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL",
125676
+
125677
+/* SQL_SELECT_INDEXES
125678
+** Return the list of valid segment indexes for absolute level ? */
125679
+/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC",
125680
+
125681
+/* SQL_SELECT_MXLEVEL
125682
+** Return the largest relative level in the FTS index or indexes. */
125683
+/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
125090125684
};
125091125685
int rc = SQLITE_OK;
125092125686
sqlite3_stmt *pStmt;
125093125687
125094125688
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
@@ -125121,27 +125715,23 @@
125121125715
}
125122125716
}
125123125717
*pp = pStmt;
125124125718
return rc;
125125125719
}
125720
+
125126125721
125127125722
static int fts3SelectDocsize(
125128125723
Fts3Table *pTab, /* FTS3 table handle */
125129
- int eStmt, /* Either SQL_SELECT_DOCSIZE or DOCTOTAL */
125130125724
sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */
125131125725
sqlite3_stmt **ppStmt /* OUT: Statement handle */
125132125726
){
125133125727
sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */
125134125728
int rc; /* Return code */
125135125729
125136
- assert( eStmt==SQL_SELECT_DOCSIZE || eStmt==SQL_SELECT_DOCTOTAL );
125137
-
125138
- rc = fts3SqlStmt(pTab, eStmt, &pStmt, 0);
125730
+ rc = fts3SqlStmt(pTab, SQL_SELECT_DOCSIZE, &pStmt, 0);
125139125731
if( rc==SQLITE_OK ){
125140
- if( eStmt==SQL_SELECT_DOCSIZE ){
125141
- sqlite3_bind_int64(pStmt, 1, iDocid);
125142
- }
125732
+ sqlite3_bind_int64(pStmt, 1, iDocid);
125143125733
rc = sqlite3_step(pStmt);
125144125734
if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
125145125735
rc = sqlite3_reset(pStmt);
125146125736
if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
125147125737
pStmt = 0;
@@ -125156,19 +125746,33 @@
125156125746
125157125747
SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(
125158125748
Fts3Table *pTab, /* Fts3 table handle */
125159125749
sqlite3_stmt **ppStmt /* OUT: Statement handle */
125160125750
){
125161
- return fts3SelectDocsize(pTab, SQL_SELECT_DOCTOTAL, 0, ppStmt);
125751
+ sqlite3_stmt *pStmt = 0;
125752
+ int rc;
125753
+ rc = fts3SqlStmt(pTab, SQL_SELECT_STAT, &pStmt, 0);
125754
+ if( rc==SQLITE_OK ){
125755
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
125756
+ if( sqlite3_step(pStmt)!=SQLITE_ROW
125757
+ || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB
125758
+ ){
125759
+ rc = sqlite3_reset(pStmt);
125760
+ if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
125761
+ pStmt = 0;
125762
+ }
125763
+ }
125764
+ *ppStmt = pStmt;
125765
+ return rc;
125162125766
}
125163125767
125164125768
SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(
125165125769
Fts3Table *pTab, /* Fts3 table handle */
125166125770
sqlite3_int64 iDocid, /* Docid to read size data for */
125167125771
sqlite3_stmt **ppStmt /* OUT: Statement handle */
125168125772
){
125169
- return fts3SelectDocsize(pTab, SQL_SELECT_DOCSIZE, iDocid, ppStmt);
125773
+ return fts3SelectDocsize(pTab, iDocid, ppStmt);
125170125774
}
125171125775
125172125776
/*
125173125777
** Similar to fts3SqlStmt(). Except, after binding the parameters in
125174125778
** array apVal[] to the SQL statement identified by eStmt, the statement
@@ -125229,10 +125833,48 @@
125229125833
rc = SQLITE_OK;
125230125834
}
125231125835
125232125836
return rc;
125233125837
}
125838
+
125839
+/*
125840
+** FTS maintains a separate indexes for each language-id (a 32-bit integer).
125841
+** Within each language id, a separate index is maintained to store the
125842
+** document terms, and each configured prefix size (configured the FTS
125843
+** "prefix=" option). And each index consists of multiple levels ("relative
125844
+** levels").
125845
+**
125846
+** All three of these values (the language id, the specific index and the
125847
+** level within the index) are encoded in 64-bit integer values stored
125848
+** in the %_segdir table on disk. This function is used to convert three
125849
+** separate component values into the single 64-bit integer value that
125850
+** can be used to query the %_segdir table.
125851
+**
125852
+** Specifically, each language-id/index combination is allocated 1024
125853
+** 64-bit integer level values ("absolute levels"). The main terms index
125854
+** for language-id 0 is allocate values 0-1023. The first prefix index
125855
+** (if any) for language-id 0 is allocated values 1024-2047. And so on.
125856
+** Language 1 indexes are allocated immediately following language 0.
125857
+**
125858
+** So, for a system with nPrefix prefix indexes configured, the block of
125859
+** absolute levels that corresponds to language-id iLangid and index
125860
+** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024).
125861
+*/
125862
+static sqlite3_int64 getAbsoluteLevel(
125863
+ Fts3Table *p, /* FTS3 table handle */
125864
+ int iLangid, /* Language id */
125865
+ int iIndex, /* Index in p->aIndex[] */
125866
+ int iLevel /* Level of segments */
125867
+){
125868
+ sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
125869
+ assert( iLangid>=0 );
125870
+ assert( p->nIndex>0 );
125871
+ assert( iIndex>=0 && iIndex<p->nIndex );
125872
+
125873
+ iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL;
125874
+ return iBase + iLevel;
125875
+}
125234125876
125235125877
/*
125236125878
** Set *ppStmt to a statement handle that may be used to iterate through
125237125879
** all rows in the %_segdir table, from oldest to newest. If successful,
125238125880
** return SQLITE_OK. If an error occurs while preparing the statement,
@@ -125249,12 +125891,13 @@
125249125891
** 3: end_block
125250125892
** 4: root
125251125893
*/
125252125894
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
125253125895
Fts3Table *p, /* FTS3 table */
125896
+ int iLangid, /* Language being queried */
125254125897
int iIndex, /* Index for p->aIndex[] */
125255
- int iLevel, /* Level to select */
125898
+ int iLevel, /* Level to select (relative level) */
125256125899
sqlite3_stmt **ppStmt /* OUT: Compiled statement */
125257125900
){
125258125901
int rc;
125259125902
sqlite3_stmt *pStmt = 0;
125260125903
@@ -125264,18 +125907,20 @@
125264125907
125265125908
if( iLevel<0 ){
125266125909
/* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
125267125910
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
125268125911
if( rc==SQLITE_OK ){
125269
- sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
125270
- sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1);
125912
+ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
125913
+ sqlite3_bind_int64(pStmt, 2,
125914
+ getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
125915
+ );
125271125916
}
125272125917
}else{
125273125918
/* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
125274125919
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
125275125920
if( rc==SQLITE_OK ){
125276
- sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL);
125921
+ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel));
125277125922
}
125278125923
}
125279125924
*ppStmt = pStmt;
125280125925
return rc;
125281125926
}
@@ -125437,10 +126082,11 @@
125437126082
**
125438126083
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
125439126084
*/
125440126085
static int fts3PendingTermsAdd(
125441126086
Fts3Table *p, /* Table into which text will be inserted */
126087
+ int iLangid, /* Language id to use */
125442126088
const char *zText, /* Text of document to be inserted */
125443126089
int iCol, /* Column into which text is being inserted */
125444126090
u32 *pnWord /* OUT: Number of tokens inserted */
125445126091
){
125446126092
int rc;
@@ -125466,15 +126112,14 @@
125466126112
if( zText==0 ){
125467126113
*pnWord = 0;
125468126114
return SQLITE_OK;
125469126115
}
125470126116
125471
- rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
126117
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr);
125472126118
if( rc!=SQLITE_OK ){
125473126119
return rc;
125474126120
}
125475
- pCsr->pTokenizer = pTokenizer;
125476126121
125477126122
xNext = pModule->xNext;
125478126123
while( SQLITE_OK==rc
125479126124
&& SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
125480126125
){
@@ -125513,22 +126158,32 @@
125513126158
/*
125514126159
** Calling this function indicates that subsequent calls to
125515126160
** fts3PendingTermsAdd() are to add term/position-list pairs for the
125516126161
** contents of the document with docid iDocid.
125517126162
*/
125518
-static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){
126163
+static int fts3PendingTermsDocid(
126164
+ Fts3Table *p, /* Full-text table handle */
126165
+ int iLangid, /* Language id of row being written */
126166
+ sqlite_int64 iDocid /* Docid of row being written */
126167
+){
126168
+ assert( iLangid>=0 );
126169
+
125519126170
/* TODO(shess) Explore whether partially flushing the buffer on
125520126171
** forced-flush would provide better performance. I suspect that if
125521126172
** we ordered the doclists by size and flushed the largest until the
125522126173
** buffer was half empty, that would let the less frequent terms
125523126174
** generate longer doclists.
125524126175
*/
125525
- if( iDocid<=p->iPrevDocid || p->nPendingData>p->nMaxPendingData ){
126176
+ if( iDocid<=p->iPrevDocid
126177
+ || p->iPrevLangid!=iLangid
126178
+ || p->nPendingData>p->nMaxPendingData
126179
+ ){
125526126180
int rc = sqlite3Fts3PendingTermsFlush(p);
125527126181
if( rc!=SQLITE_OK ) return rc;
125528126182
}
125529126183
p->iPrevDocid = iDocid;
126184
+ p->iPrevLangid = iLangid;
125530126185
return SQLITE_OK;
125531126186
}
125532126187
125533126188
/*
125534126189
** Discard the contents of the pending-terms hash tables.
@@ -125553,15 +126208,20 @@
125553126208
** pendingTerms hash table.
125554126209
**
125555126210
** Argument apVal is the same as the similarly named argument passed to
125556126211
** fts3InsertData(). Parameter iDocid is the docid of the new row.
125557126212
*/
125558
-static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
126213
+static int fts3InsertTerms(
126214
+ Fts3Table *p,
126215
+ int iLangid,
126216
+ sqlite3_value **apVal,
126217
+ u32 *aSz
126218
+){
125559126219
int i; /* Iterator variable */
125560126220
for(i=2; i<p->nColumn+2; i++){
125561126221
const char *zText = (const char *)sqlite3_value_text(apVal[i]);
125562
- int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
126222
+ int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
125563126223
if( rc!=SQLITE_OK ){
125564126224
return rc;
125565126225
}
125566126226
aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
125567126227
}
@@ -125578,10 +126238,11 @@
125578126238
** apVal[2] Left-most user-defined column
125579126239
** ...
125580126240
** apVal[p->nColumn+1] Right-most user-defined column
125581126241
** apVal[p->nColumn+2] Hidden column with same name as table
125582126242
** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid)
126243
+** apVal[p->nColumn+4] Hidden languageid column
125583126244
*/
125584126245
static int fts3InsertData(
125585126246
Fts3Table *p, /* Full-text table */
125586126247
sqlite3_value **apVal, /* Array of values to insert */
125587126248
sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */
@@ -125608,13 +126269,17 @@
125608126269
**
125609126270
** The statement features N '?' variables, where N is the number of user
125610126271
** defined columns in the FTS3 table, plus one for the docid field.
125611126272
*/
125612126273
rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
125613
- if( rc!=SQLITE_OK ){
125614
- return rc;
126274
+ if( rc==SQLITE_OK && p->zLanguageid ){
126275
+ rc = sqlite3_bind_int(
126276
+ pContentInsert, p->nColumn+2,
126277
+ sqlite3_value_int(apVal[p->nColumn+4])
126278
+ );
125615126279
}
126280
+ if( rc!=SQLITE_OK ) return rc;
125616126281
125617126282
/* There is a quirk here. The users INSERT statement may have specified
125618126283
** a value for the "rowid" field, for the "docid" field, or for both.
125619126284
** Which is a problem, since "rowid" and "docid" are aliases for the
125620126285
** same value. For example:
@@ -125669,10 +126334,19 @@
125669126334
if( p->bHasStat ){
125670126335
fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
125671126336
}
125672126337
return rc;
125673126338
}
126339
+
126340
+/*
126341
+**
126342
+*/
126343
+static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){
126344
+ int iLangid = 0;
126345
+ if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1);
126346
+ return iLangid;
126347
+}
125674126348
125675126349
/*
125676126350
** The first element in the apVal[] array is assumed to contain the docid
125677126351
** (an integer) of a row about to be deleted. Remove all terms from the
125678126352
** full-text index.
@@ -125689,19 +126363,21 @@
125689126363
if( *pRC ) return;
125690126364
rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
125691126365
if( rc==SQLITE_OK ){
125692126366
if( SQLITE_ROW==sqlite3_step(pSelect) ){
125693126367
int i;
125694
- for(i=1; i<=p->nColumn; i++){
126368
+ int iLangid = langidFromSelect(p, pSelect);
126369
+ rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
126370
+ for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
125695126371
const char *zText = (const char *)sqlite3_column_text(pSelect, i);
125696
- rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]);
125697
- if( rc!=SQLITE_OK ){
125698
- sqlite3_reset(pSelect);
125699
- *pRC = rc;
125700
- return;
125701
- }
126372
+ rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
125702126373
aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
126374
+ }
126375
+ if( rc!=SQLITE_OK ){
126376
+ sqlite3_reset(pSelect);
126377
+ *pRC = rc;
126378
+ return;
125703126379
}
125704126380
}
125705126381
rc = sqlite3_reset(pSelect);
125706126382
}else{
125707126383
sqlite3_reset(pSelect);
@@ -125711,11 +126387,11 @@
125711126387
125712126388
/*
125713126389
** Forward declaration to account for the circular dependency between
125714126390
** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
125715126391
*/
125716
-static int fts3SegmentMerge(Fts3Table *, int, int);
126392
+static int fts3SegmentMerge(Fts3Table *, int, int, int);
125717126393
125718126394
/*
125719126395
** This function allocates a new level iLevel index in the segdir table.
125720126396
** Usually, indexes are allocated within a level sequentially starting
125721126397
** with 0, so the allocated index is one greater than the value returned
@@ -125730,22 +126406,28 @@
125730126406
** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
125731126407
** returned. Otherwise, an SQLite error code is returned.
125732126408
*/
125733126409
static int fts3AllocateSegdirIdx(
125734126410
Fts3Table *p,
126411
+ int iLangid, /* Language id */
125735126412
int iIndex, /* Index for p->aIndex */
125736126413
int iLevel,
125737126414
int *piIdx
125738126415
){
125739126416
int rc; /* Return Code */
125740126417
sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
125741126418
int iNext = 0; /* Result of query pNextIdx */
125742126419
126420
+ assert( iLangid>=0 );
126421
+ assert( p->nIndex>=1 );
126422
+
125743126423
/* Set variable iNext to the next available segdir index at level iLevel. */
125744126424
rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
125745126425
if( rc==SQLITE_OK ){
125746
- sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
126426
+ sqlite3_bind_int64(
126427
+ pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
126428
+ );
125747126429
if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
125748126430
iNext = sqlite3_column_int(pNextIdx, 0);
125749126431
}
125750126432
rc = sqlite3_reset(pNextIdx);
125751126433
}
@@ -125755,11 +126437,12 @@
125755126437
** full, merge all segments in level iLevel into a single iLevel+1
125756126438
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
125757126439
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
125758126440
*/
125759126441
if( iNext>=FTS3_MERGE_COUNT ){
125760
- rc = fts3SegmentMerge(p, iIndex, iLevel);
126442
+ fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
126443
+ rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
125761126444
*piIdx = 0;
125762126445
}else{
125763126446
*piIdx = iNext;
125764126447
}
125765126448
}
@@ -125802,11 +126485,11 @@
125802126485
int *pnLoad /* OUT: Bytes actually loaded */
125803126486
){
125804126487
int rc; /* Return code */
125805126488
125806126489
/* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
125807
- assert( pnBlob);
126490
+ assert( pnBlob );
125808126491
125809126492
if( p->pSegments ){
125810126493
rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
125811126494
}else{
125812126495
if( 0==p->zSegmentsTbl ){
@@ -126143,11 +126826,11 @@
126143126826
int nOvfl = 0;
126144126827
int ii;
126145126828
int rc = SQLITE_OK;
126146126829
int pgsz = p->nPgsz;
126147126830
126148
- assert( p->bHasStat );
126831
+ assert( p->bFts4 );
126149126832
assert( pgsz>0 );
126150126833
126151126834
for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
126152126835
Fts3SegReader *pReader = pMsr->apSegment[ii];
126153126836
if( !fts3SegReaderIsPending(pReader)
@@ -126500,17 +127183,38 @@
126500127183
sqlite3_step(pStmt);
126501127184
rc = sqlite3_reset(pStmt);
126502127185
}
126503127186
return rc;
126504127187
}
127188
+
127189
+/*
127190
+** Find the largest relative level number in the table. If successful, set
127191
+** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs,
127192
+** set *pnMax to zero and return an SQLite error code.
127193
+*/
127194
+SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){
127195
+ int rc;
127196
+ int mxLevel = 0;
127197
+ sqlite3_stmt *pStmt = 0;
127198
+
127199
+ rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0);
127200
+ if( rc==SQLITE_OK ){
127201
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
127202
+ mxLevel = sqlite3_column_int(pStmt, 0);
127203
+ }
127204
+ rc = sqlite3_reset(pStmt);
127205
+ }
127206
+ *pnMax = mxLevel;
127207
+ return rc;
127208
+}
126505127209
126506127210
/*
126507127211
** Insert a record into the %_segdir table.
126508127212
*/
126509127213
static int fts3WriteSegdir(
126510127214
Fts3Table *p, /* Virtual table handle */
126511
- int iLevel, /* Value for "level" field */
127215
+ sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */
126512127216
int iIdx, /* Value for "idx" field */
126513127217
sqlite3_int64 iStartBlock, /* Value for "start_block" field */
126514127218
sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
126515127219
sqlite3_int64 iEndBlock, /* Value for "end_block" field */
126516127220
char *zRoot, /* Blob value for "root" field */
@@ -126517,11 +127221,11 @@
126517127221
int nRoot /* Number of bytes in buffer zRoot */
126518127222
){
126519127223
sqlite3_stmt *pStmt;
126520127224
int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0);
126521127225
if( rc==SQLITE_OK ){
126522
- sqlite3_bind_int(pStmt, 1, iLevel);
127226
+ sqlite3_bind_int64(pStmt, 1, iLevel);
126523127227
sqlite3_bind_int(pStmt, 2, iIdx);
126524127228
sqlite3_bind_int64(pStmt, 3, iStartBlock);
126525127229
sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
126526127230
sqlite3_bind_int64(pStmt, 5, iEndBlock);
126527127231
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
@@ -126817,10 +127521,11 @@
126817127521
int rc;
126818127522
126819127523
/* The current leaf node is full. Write it out to the database. */
126820127524
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
126821127525
if( rc!=SQLITE_OK ) return rc;
127526
+ p->nLeafAdd++;
126822127527
126823127528
/* Add the current term to the interior node tree. The term added to
126824127529
** the interior tree must:
126825127530
**
126826127531
** a) be greater than the largest term on the leaf node just written
@@ -126900,11 +127605,11 @@
126900127605
** returned. Otherwise, an SQLite error code.
126901127606
*/
126902127607
static int fts3SegWriterFlush(
126903127608
Fts3Table *p, /* Virtual table handle */
126904127609
SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
126905
- int iLevel, /* Value for 'level' column of %_segdir */
127610
+ sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */
126906127611
int iIdx /* Value for 'idx' column of %_segdir */
126907127612
){
126908127613
int rc; /* Return code */
126909127614
if( pWriter->pTree ){
126910127615
sqlite3_int64 iLast = 0; /* Largest block id written to database */
@@ -126925,10 +127630,11 @@
126925127630
}else{
126926127631
/* The entire tree fits on the root node. Write it to the segdir table. */
126927127632
rc = fts3WriteSegdir(
126928127633
p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
126929127634
}
127635
+ p->nLeafAdd++;
126930127636
return rc;
126931127637
}
126932127638
126933127639
/*
126934127640
** Release all memory held by the SegmentWriter object passed as the
@@ -126978,11 +127684,16 @@
126978127684
**
126979127685
** Segment levels are stored in the 'level' column of the %_segdir table.
126980127686
**
126981127687
** Return SQLITE_OK if successful, or an SQLite error code if not.
126982127688
*/
126983
-static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){
127689
+static int fts3SegmentMaxLevel(
127690
+ Fts3Table *p,
127691
+ int iLangid,
127692
+ int iIndex,
127693
+ sqlite3_int64 *pnMax
127694
+){
126984127695
sqlite3_stmt *pStmt;
126985127696
int rc;
126986127697
assert( iIndex>=0 && iIndex<p->nIndex );
126987127698
126988127699
/* Set pStmt to the compiled version of:
@@ -126991,17 +127702,42 @@
126991127702
**
126992127703
** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
126993127704
*/
126994127705
rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
126995127706
if( rc!=SQLITE_OK ) return rc;
126996
- sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
126997
- sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1);
127707
+ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
127708
+ sqlite3_bind_int64(pStmt, 2,
127709
+ getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
127710
+ );
126998127711
if( SQLITE_ROW==sqlite3_step(pStmt) ){
126999
- *pnMax = sqlite3_column_int(pStmt, 0);
127712
+ *pnMax = sqlite3_column_int64(pStmt, 0);
127000127713
}
127001127714
return sqlite3_reset(pStmt);
127002127715
}
127716
+
127717
+/*
127718
+** Delete all entries in the %_segments table associated with the segment
127719
+** opened with seg-reader pSeg. This function does not affect the contents
127720
+** of the %_segdir table.
127721
+*/
127722
+static int fts3DeleteSegment(
127723
+ Fts3Table *p, /* FTS table handle */
127724
+ Fts3SegReader *pSeg /* Segment to delete */
127725
+){
127726
+ int rc = SQLITE_OK; /* Return code */
127727
+ if( pSeg->iStartBlock ){
127728
+ sqlite3_stmt *pDelete; /* SQL statement to delete rows */
127729
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
127730
+ if( rc==SQLITE_OK ){
127731
+ sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock);
127732
+ sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock);
127733
+ sqlite3_step(pDelete);
127734
+ rc = sqlite3_reset(pDelete);
127735
+ }
127736
+ }
127737
+ return rc;
127738
+}
127003127739
127004127740
/*
127005127741
** This function is used after merging multiple segments into a single large
127006127742
** segment to delete the old, now redundant, segment b-trees. Specifically,
127007127743
** it:
@@ -127015,44 +127751,42 @@
127015127751
**
127016127752
** SQLITE_OK is returned if successful, otherwise an SQLite error code.
127017127753
*/
127018127754
static int fts3DeleteSegdir(
127019127755
Fts3Table *p, /* Virtual table handle */
127756
+ int iLangid, /* Language id */
127020127757
int iIndex, /* Index for p->aIndex */
127021127758
int iLevel, /* Level of %_segdir entries to delete */
127022127759
Fts3SegReader **apSegment, /* Array of SegReader objects */
127023127760
int nReader /* Size of array apSegment */
127024127761
){
127025
- int rc; /* Return Code */
127762
+ int rc = SQLITE_OK; /* Return Code */
127026127763
int i; /* Iterator variable */
127027
- sqlite3_stmt *pDelete; /* SQL statement to delete rows */
127764
+ sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */
127028127765
127029
- rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
127030127766
for(i=0; rc==SQLITE_OK && i<nReader; i++){
127031
- Fts3SegReader *pSegment = apSegment[i];
127032
- if( pSegment->iStartBlock ){
127033
- sqlite3_bind_int64(pDelete, 1, pSegment->iStartBlock);
127034
- sqlite3_bind_int64(pDelete, 2, pSegment->iEndBlock);
127035
- sqlite3_step(pDelete);
127036
- rc = sqlite3_reset(pDelete);
127037
- }
127767
+ rc = fts3DeleteSegment(p, apSegment[i]);
127038127768
}
127039127769
if( rc!=SQLITE_OK ){
127040127770
return rc;
127041127771
}
127042127772
127043127773
assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
127044127774
if( iLevel==FTS3_SEGCURSOR_ALL ){
127045127775
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
127046127776
if( rc==SQLITE_OK ){
127047
- sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
127048
- sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1);
127777
+ sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
127778
+ sqlite3_bind_int64(pDelete, 2,
127779
+ getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
127780
+ );
127049127781
}
127050127782
}else{
127051127783
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
127052127784
if( rc==SQLITE_OK ){
127053
- sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
127785
+ sqlite3_bind_int64(
127786
+ pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
127787
+ );
127054127788
}
127055127789
}
127056127790
127057127791
if( rc==SQLITE_OK ){
127058127792
sqlite3_step(pDelete);
@@ -127517,27 +128251,32 @@
127517128251
** If this function is called with iLevel<0, but there is only one
127518128252
** segment in the database, SQLITE_DONE is returned immediately.
127519128253
** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
127520128254
** an SQLite error code is returned.
127521128255
*/
127522
-static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){
128256
+static int fts3SegmentMerge(
128257
+ Fts3Table *p,
128258
+ int iLangid, /* Language id to merge */
128259
+ int iIndex, /* Index in p->aIndex[] to merge */
128260
+ int iLevel /* Level to merge */
128261
+){
127523128262
int rc; /* Return code */
127524128263
int iIdx = 0; /* Index of new segment */
127525
- int iNewLevel = 0; /* Level/index to create new segment at */
128264
+ sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */
127526128265
SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
127527128266
Fts3SegFilter filter; /* Segment term filter condition */
127528
- Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
128267
+ Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
127529128268
int bIgnoreEmpty = 0; /* True to ignore empty segments */
127530128269
127531128270
assert( iLevel==FTS3_SEGCURSOR_ALL
127532128271
|| iLevel==FTS3_SEGCURSOR_PENDING
127533128272
|| iLevel>=0
127534128273
);
127535128274
assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
127536128275
assert( iIndex>=0 && iIndex<p->nIndex );
127537128276
127538
- rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr);
128277
+ rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
127539128278
if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
127540128279
127541128280
if( iLevel==FTS3_SEGCURSOR_ALL ){
127542128281
/* This call is to merge all segments in the database to a single
127543128282
** segment. The level of the new segment is equal to the the numerically
@@ -127545,28 +128284,28 @@
127545128284
** index. The idx of the new segment is always 0. */
127546128285
if( csr.nSegment==1 ){
127547128286
rc = SQLITE_DONE;
127548128287
goto finished;
127549128288
}
127550
- rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel);
128289
+ rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
127551128290
bIgnoreEmpty = 1;
127552128291
127553128292
}else if( iLevel==FTS3_SEGCURSOR_PENDING ){
127554
- iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL;
127555
- rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx);
128293
+ iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
128294
+ rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
127556128295
}else{
127557128296
/* This call is to merge all segments at level iLevel. find the next
127558128297
** available segment index at level iLevel+1. The call to
127559128298
** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
127560128299
** a single iLevel+2 segment if necessary. */
127561
- rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx);
127562
- iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1;
128300
+ rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
128301
+ iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
127563128302
}
127564128303
if( rc!=SQLITE_OK ) goto finished;
127565128304
assert( csr.nSegment>0 );
127566
- assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) );
127567
- assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) );
128305
+ assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
128306
+ assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
127568128307
127569128308
memset(&filter, 0, sizeof(Fts3SegFilter));
127570128309
filter.flags = FTS3_SEGMENT_REQUIRE_POS;
127571128310
filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
127572128311
@@ -127579,11 +128318,13 @@
127579128318
}
127580128319
if( rc!=SQLITE_OK ) goto finished;
127581128320
assert( pWriter );
127582128321
127583128322
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
127584
- rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment);
128323
+ rc = fts3DeleteSegdir(
128324
+ p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment
128325
+ );
127585128326
if( rc!=SQLITE_OK ) goto finished;
127586128327
}
127587128328
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
127588128329
127589128330
finished:
@@ -127597,15 +128338,32 @@
127597128338
** Flush the contents of pendingTerms to level 0 segments.
127598128339
*/
127599128340
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
127600128341
int rc = SQLITE_OK;
127601128342
int i;
128343
+
127602128344
for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
127603
- rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING);
128345
+ rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
127604128346
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
127605128347
}
127606128348
sqlite3Fts3PendingTermsClear(p);
128349
+
128350
+ /* Determine the auto-incr-merge setting if unknown. If enabled,
128351
+ ** estimate the number of leaf blocks of content to be written
128352
+ */
128353
+ if( rc==SQLITE_OK && p->bHasStat
128354
+ && p->bAutoincrmerge==0xff && p->nLeafAdd>0
128355
+ ){
128356
+ sqlite3_stmt *pStmt = 0;
128357
+ rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
128358
+ if( rc==SQLITE_OK ){
128359
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
128360
+ rc = sqlite3_step(pStmt);
128361
+ p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
128362
+ rc = sqlite3_reset(pStmt);
128363
+ }
128364
+ }
127607128365
return rc;
127608128366
}
127609128367
127610128368
/*
127611128369
** Encode N integers as varints into a blob.
@@ -127712,16 +128470,17 @@
127712128470
if( a==0 ){
127713128471
*pRC = SQLITE_NOMEM;
127714128472
return;
127715128473
}
127716128474
pBlob = (char*)&a[nStat];
127717
- rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
128475
+ rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
127718128476
if( rc ){
127719128477
sqlite3_free(a);
127720128478
*pRC = rc;
127721128479
return;
127722128480
}
128481
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
127723128482
if( sqlite3_step(pStmt)==SQLITE_ROW ){
127724128483
fts3DecodeIntArray(nStat, a,
127725128484
sqlite3_column_blob(pStmt, 0),
127726128485
sqlite3_column_bytes(pStmt, 0));
127727128486
}else{
@@ -127741,33 +128500,51 @@
127741128500
x = x + aSzIns[i] - aSzDel[i];
127742128501
}
127743128502
a[i+1] = x;
127744128503
}
127745128504
fts3EncodeIntArray(nStat, a, pBlob, &nBlob);
127746
- rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0);
128505
+ rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
127747128506
if( rc ){
127748128507
sqlite3_free(a);
127749128508
*pRC = rc;
127750128509
return;
127751128510
}
127752
- sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
128511
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
128512
+ sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
127753128513
sqlite3_step(pStmt);
127754128514
*pRC = sqlite3_reset(pStmt);
127755128515
sqlite3_free(a);
127756128516
}
127757128517
128518
+/*
128519
+** Merge the entire database so that there is one segment for each
128520
+** iIndex/iLangid combination.
128521
+*/
127758128522
static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
127759
- int i;
127760128523
int bSeenDone = 0;
127761
- int rc = SQLITE_OK;
127762
- for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
127763
- rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL);
127764
- if( rc==SQLITE_DONE ){
127765
- bSeenDone = 1;
127766
- rc = SQLITE_OK;
127767
- }
127768
- }
128524
+ int rc;
128525
+ sqlite3_stmt *pAllLangid = 0;
128526
+
128527
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
128528
+ if( rc==SQLITE_OK ){
128529
+ int rc2;
128530
+ sqlite3_bind_int(pAllLangid, 1, p->nIndex);
128531
+ while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
128532
+ int i;
128533
+ int iLangid = sqlite3_column_int(pAllLangid, 0);
128534
+ for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
128535
+ rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
128536
+ if( rc==SQLITE_DONE ){
128537
+ bSeenDone = 1;
128538
+ rc = SQLITE_OK;
128539
+ }
128540
+ }
128541
+ }
128542
+ rc2 = sqlite3_reset(pAllLangid);
128543
+ if( rc==SQLITE_OK ) rc = rc2;
128544
+ }
128545
+
127769128546
sqlite3Fts3SegmentsClose(p);
127770128547
sqlite3Fts3PendingTermsClear(p);
127771128548
127772128549
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
127773128550
}
@@ -127814,15 +128591,16 @@
127814128591
}
127815128592
}
127816128593
127817128594
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
127818128595
int iCol;
127819
- rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0));
128596
+ int iLangid = langidFromSelect(p, pStmt);
128597
+ rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
127820128598
aSz[p->nColumn] = 0;
127821128599
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
127822128600
const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
127823
- rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]);
128601
+ rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
127824128602
aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
127825128603
}
127826128604
if( p->bHasDocsize ){
127827128605
fts3InsertDocsize(&rc, p, aSz);
127828128606
}
@@ -127834,11 +128612,11 @@
127834128612
for(iCol=0; iCol<=p->nColumn; iCol++){
127835128613
aSzIns[iCol] += aSz[iCol];
127836128614
}
127837128615
}
127838128616
}
127839
- if( p->bHasStat ){
128617
+ if( p->bFts4 ){
127840128618
fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
127841128619
}
127842128620
sqlite3_free(aSz);
127843128621
127844128622
if( pStmt ){
@@ -127850,10 +128628,1692 @@
127850128628
}
127851128629
127852128630
return rc;
127853128631
}
127854128632
128633
+
128634
+/*
128635
+** This function opens a cursor used to read the input data for an
128636
+** incremental merge operation. Specifically, it opens a cursor to scan
128637
+** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
128638
+** level iAbsLevel.
128639
+*/
128640
+static int fts3IncrmergeCsr(
128641
+ Fts3Table *p, /* FTS3 table handle */
128642
+ sqlite3_int64 iAbsLevel, /* Absolute level to open */
128643
+ int nSeg, /* Number of segments to merge */
128644
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
128645
+){
128646
+ int rc; /* Return Code */
128647
+ sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
128648
+ int nByte; /* Bytes allocated at pCsr->apSegment[] */
128649
+
128650
+ /* Allocate space for the Fts3MultiSegReader.aCsr[] array */
128651
+ memset(pCsr, 0, sizeof(*pCsr));
128652
+ nByte = sizeof(Fts3SegReader *) * nSeg;
128653
+ pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
128654
+
128655
+ if( pCsr->apSegment==0 ){
128656
+ rc = SQLITE_NOMEM;
128657
+ }else{
128658
+ memset(pCsr->apSegment, 0, nByte);
128659
+ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
128660
+ }
128661
+ if( rc==SQLITE_OK ){
128662
+ int i;
128663
+ int rc2;
128664
+ sqlite3_bind_int64(pStmt, 1, iAbsLevel);
128665
+ assert( pCsr->nSegment==0 );
128666
+ for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && i<nSeg; i++){
128667
+ rc = sqlite3Fts3SegReaderNew(i, 0,
128668
+ sqlite3_column_int64(pStmt, 1), /* segdir.start_block */
128669
+ sqlite3_column_int64(pStmt, 2), /* segdir.leaves_end_block */
128670
+ sqlite3_column_int64(pStmt, 3), /* segdir.end_block */
128671
+ sqlite3_column_blob(pStmt, 4), /* segdir.root */
128672
+ sqlite3_column_bytes(pStmt, 4), /* segdir.root */
128673
+ &pCsr->apSegment[i]
128674
+ );
128675
+ pCsr->nSegment++;
128676
+ }
128677
+ rc2 = sqlite3_reset(pStmt);
128678
+ if( rc==SQLITE_OK ) rc = rc2;
128679
+ }
128680
+
128681
+ return rc;
128682
+}
128683
+
128684
+typedef struct IncrmergeWriter IncrmergeWriter;
128685
+typedef struct NodeWriter NodeWriter;
128686
+typedef struct Blob Blob;
128687
+typedef struct NodeReader NodeReader;
128688
+
128689
+/*
128690
+** An instance of the following structure is used as a dynamic buffer
128691
+** to build up nodes or other blobs of data in.
128692
+**
128693
+** The function blobGrowBuffer() is used to extend the allocation.
128694
+*/
128695
+struct Blob {
128696
+ char *a; /* Pointer to allocation */
128697
+ int n; /* Number of valid bytes of data in a[] */
128698
+ int nAlloc; /* Allocated size of a[] (nAlloc>=n) */
128699
+};
128700
+
128701
+/*
128702
+** This structure is used to build up buffers containing segment b-tree
128703
+** nodes (blocks).
128704
+*/
128705
+struct NodeWriter {
128706
+ sqlite3_int64 iBlock; /* Current block id */
128707
+ Blob key; /* Last key written to the current block */
128708
+ Blob block; /* Current block image */
128709
+};
128710
+
128711
+/*
128712
+** An object of this type contains the state required to create or append
128713
+** to an appendable b-tree segment.
128714
+*/
128715
+struct IncrmergeWriter {
128716
+ int nLeafEst; /* Space allocated for leaf blocks */
128717
+ int nWork; /* Number of leaf pages flushed */
128718
+ sqlite3_int64 iAbsLevel; /* Absolute level of input segments */
128719
+ int iIdx; /* Index of *output* segment in iAbsLevel+1 */
128720
+ sqlite3_int64 iStart; /* Block number of first allocated block */
128721
+ sqlite3_int64 iEnd; /* Block number of last allocated block */
128722
+ NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
128723
+};
128724
+
128725
+/*
128726
+** An object of the following type is used to read data from a single
128727
+** FTS segment node. See the following functions:
128728
+**
128729
+** nodeReaderInit()
128730
+** nodeReaderNext()
128731
+** nodeReaderRelease()
128732
+*/
128733
+struct NodeReader {
128734
+ const char *aNode;
128735
+ int nNode;
128736
+ int iOff; /* Current offset within aNode[] */
128737
+
128738
+ /* Output variables. Containing the current node entry. */
128739
+ sqlite3_int64 iChild; /* Pointer to child node */
128740
+ Blob term; /* Current term */
128741
+ const char *aDoclist; /* Pointer to doclist */
128742
+ int nDoclist; /* Size of doclist in bytes */
128743
+};
128744
+
128745
+/*
128746
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
128747
+** Otherwise, if the allocation at pBlob->a is not already at least nMin
128748
+** bytes in size, extend (realloc) it to be so.
128749
+**
128750
+** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a
128751
+** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc
128752
+** to reflect the new size of the pBlob->a[] buffer.
128753
+*/
128754
+static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
128755
+ if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
128756
+ int nAlloc = nMin;
128757
+ char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
128758
+ if( a ){
128759
+ pBlob->nAlloc = nAlloc;
128760
+ pBlob->a = a;
128761
+ }else{
128762
+ *pRc = SQLITE_NOMEM;
128763
+ }
128764
+ }
128765
+}
128766
+
128767
+/*
128768
+** Attempt to advance the node-reader object passed as the first argument to
128769
+** the next entry on the node.
128770
+**
128771
+** Return an error code if an error occurs (SQLITE_NOMEM is possible).
128772
+** Otherwise return SQLITE_OK. If there is no next entry on the node
128773
+** (e.g. because the current entry is the last) set NodeReader->aNode to
128774
+** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
128775
+** variables for the new entry.
128776
+*/
128777
+static int nodeReaderNext(NodeReader *p){
128778
+ int bFirst = (p->term.n==0); /* True for first term on the node */
128779
+ int nPrefix = 0; /* Bytes to copy from previous term */
128780
+ int nSuffix = 0; /* Bytes to append to the prefix */
128781
+ int rc = SQLITE_OK; /* Return code */
128782
+
128783
+ assert( p->aNode );
128784
+ if( p->iChild && bFirst==0 ) p->iChild++;
128785
+ if( p->iOff>=p->nNode ){
128786
+ /* EOF */
128787
+ p->aNode = 0;
128788
+ }else{
128789
+ if( bFirst==0 ){
128790
+ p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
128791
+ }
128792
+ p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
128793
+
128794
+ blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
128795
+ if( rc==SQLITE_OK ){
128796
+ memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
128797
+ p->term.n = nPrefix+nSuffix;
128798
+ p->iOff += nSuffix;
128799
+ if( p->iChild==0 ){
128800
+ p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
128801
+ p->aDoclist = &p->aNode[p->iOff];
128802
+ p->iOff += p->nDoclist;
128803
+ }
128804
+ }
128805
+ }
128806
+
128807
+ assert( p->iOff<=p->nNode );
128808
+
128809
+ return rc;
128810
+}
128811
+
128812
+/*
128813
+** Release all dynamic resources held by node-reader object *p.
128814
+*/
128815
+static void nodeReaderRelease(NodeReader *p){
128816
+ sqlite3_free(p->term.a);
128817
+}
128818
+
128819
+/*
128820
+** Initialize a node-reader object to read the node in buffer aNode/nNode.
128821
+**
128822
+** If successful, SQLITE_OK is returned and the NodeReader object set to
128823
+** point to the first entry on the node (if any). Otherwise, an SQLite
128824
+** error code is returned.
128825
+*/
128826
+static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
128827
+ memset(p, 0, sizeof(NodeReader));
128828
+ p->aNode = aNode;
128829
+ p->nNode = nNode;
128830
+
128831
+ /* Figure out if this is a leaf or an internal node. */
128832
+ if( p->aNode[0] ){
128833
+ /* An internal node. */
128834
+ p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
128835
+ }else{
128836
+ p->iOff = 1;
128837
+ }
128838
+
128839
+ return nodeReaderNext(p);
128840
+}
128841
+
128842
+/*
128843
+** This function is called while writing an FTS segment each time a leaf o
128844
+** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed
128845
+** to be greater than the largest key on the node just written, but smaller
128846
+** than or equal to the first key that will be written to the next leaf
128847
+** node.
128848
+**
128849
+** The block id of the leaf node just written to disk may be found in
128850
+** (pWriter->aNodeWriter[0].iBlock) when this function is called.
128851
+*/
128852
+static int fts3IncrmergePush(
128853
+ Fts3Table *p, /* Fts3 table handle */
128854
+ IncrmergeWriter *pWriter, /* Writer object */
128855
+ const char *zTerm, /* Term to write to internal node */
128856
+ int nTerm /* Bytes at zTerm */
128857
+){
128858
+ sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock;
128859
+ int iLayer;
128860
+
128861
+ assert( nTerm>0 );
128862
+ for(iLayer=1; ALWAYS(iLayer<FTS_MAX_APPENDABLE_HEIGHT); iLayer++){
128863
+ sqlite3_int64 iNextPtr = 0;
128864
+ NodeWriter *pNode = &pWriter->aNodeWriter[iLayer];
128865
+ int rc = SQLITE_OK;
128866
+ int nPrefix;
128867
+ int nSuffix;
128868
+ int nSpace;
128869
+
128870
+ /* Figure out how much space the key will consume if it is written to
128871
+ ** the current node of layer iLayer. Due to the prefix compression,
128872
+ ** the space required changes depending on which node the key is to
128873
+ ** be added to. */
128874
+ nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
128875
+ nSuffix = nTerm - nPrefix;
128876
+ nSpace = sqlite3Fts3VarintLen(nPrefix);
128877
+ nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
128878
+
128879
+ if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
128880
+ /* If the current node of layer iLayer contains zero keys, or if adding
128881
+ ** the key to it will not cause it to grow to larger than nNodeSize
128882
+ ** bytes in size, write the key here. */
128883
+
128884
+ Blob *pBlk = &pNode->block;
128885
+ if( pBlk->n==0 ){
128886
+ blobGrowBuffer(pBlk, p->nNodeSize, &rc);
128887
+ if( rc==SQLITE_OK ){
128888
+ pBlk->a[0] = (char)iLayer;
128889
+ pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr);
128890
+ }
128891
+ }
128892
+ blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc);
128893
+ blobGrowBuffer(&pNode->key, nTerm, &rc);
128894
+
128895
+ if( rc==SQLITE_OK ){
128896
+ if( pNode->key.n ){
128897
+ pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
128898
+ }
128899
+ pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
128900
+ memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
128901
+ pBlk->n += nSuffix;
128902
+
128903
+ memcpy(pNode->key.a, zTerm, nTerm);
128904
+ pNode->key.n = nTerm;
128905
+ }
128906
+ }else{
128907
+ /* Otherwise, flush the the current node of layer iLayer to disk.
128908
+ ** Then allocate a new, empty sibling node. The key will be written
128909
+ ** into the parent of this node. */
128910
+ rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
128911
+
128912
+ assert( pNode->block.nAlloc>=p->nNodeSize );
128913
+ pNode->block.a[0] = (char)iLayer;
128914
+ pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1);
128915
+
128916
+ iNextPtr = pNode->iBlock;
128917
+ pNode->iBlock++;
128918
+ pNode->key.n = 0;
128919
+ }
128920
+
128921
+ if( rc!=SQLITE_OK || iNextPtr==0 ) return rc;
128922
+ iPtr = iNextPtr;
128923
+ }
128924
+
128925
+ assert( 0 );
128926
+ return 0;
128927
+}
128928
+
128929
+/*
128930
+** Append a term and (optionally) doclist to the FTS segment node currently
128931
+** stored in blob *pNode. The node need not contain any terms, but the
128932
+** header must be written before this function is called.
128933
+**
128934
+** A node header is a single 0x00 byte for a leaf node, or a height varint
128935
+** followed by the left-hand-child varint for an internal node.
128936
+**
128937
+** The term to be appended is passed via arguments zTerm/nTerm. For a
128938
+** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal
128939
+** node, both aDoclist and nDoclist must be passed 0.
128940
+**
128941
+** If the size of the value in blob pPrev is zero, then this is the first
128942
+** term written to the node. Otherwise, pPrev contains a copy of the
128943
+** previous term. Before this function returns, it is updated to contain a
128944
+** copy of zTerm/nTerm.
128945
+**
128946
+** It is assumed that the buffer associated with pNode is already large
128947
+** enough to accommodate the new entry. The buffer associated with pPrev
128948
+** is extended by this function if requrired.
128949
+**
128950
+** If an error (i.e. OOM condition) occurs, an SQLite error code is
128951
+** returned. Otherwise, SQLITE_OK.
128952
+*/
128953
+static int fts3AppendToNode(
128954
+ Blob *pNode, /* Current node image to append to */
128955
+ Blob *pPrev, /* Buffer containing previous term written */
128956
+ const char *zTerm, /* New term to write */
128957
+ int nTerm, /* Size of zTerm in bytes */
128958
+ const char *aDoclist, /* Doclist (or NULL) to write */
128959
+ int nDoclist /* Size of aDoclist in bytes */
128960
+){
128961
+ int rc = SQLITE_OK; /* Return code */
128962
+ int bFirst = (pPrev->n==0); /* True if this is the first term written */
128963
+ int nPrefix; /* Size of term prefix in bytes */
128964
+ int nSuffix; /* Size of term suffix in bytes */
128965
+
128966
+ /* Node must have already been started. There must be a doclist for a
128967
+ ** leaf node, and there must not be a doclist for an internal node. */
128968
+ assert( pNode->n>0 );
128969
+ assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
128970
+
128971
+ blobGrowBuffer(pPrev, nTerm, &rc);
128972
+ if( rc!=SQLITE_OK ) return rc;
128973
+
128974
+ nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
128975
+ nSuffix = nTerm - nPrefix;
128976
+ memcpy(pPrev->a, zTerm, nTerm);
128977
+ pPrev->n = nTerm;
128978
+
128979
+ if( bFirst==0 ){
128980
+ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix);
128981
+ }
128982
+ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix);
128983
+ memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix);
128984
+ pNode->n += nSuffix;
128985
+
128986
+ if( aDoclist ){
128987
+ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist);
128988
+ memcpy(&pNode->a[pNode->n], aDoclist, nDoclist);
128989
+ pNode->n += nDoclist;
128990
+ }
128991
+
128992
+ assert( pNode->n<=pNode->nAlloc );
128993
+
128994
+ return SQLITE_OK;
128995
+}
128996
+
128997
+/*
128998
+** Append the current term and doclist pointed to by cursor pCsr to the
128999
+** appendable b-tree segment opened for writing by pWriter.
129000
+**
129001
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
129002
+*/
129003
+static int fts3IncrmergeAppend(
129004
+ Fts3Table *p, /* Fts3 table handle */
129005
+ IncrmergeWriter *pWriter, /* Writer object */
129006
+ Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */
129007
+){
129008
+ const char *zTerm = pCsr->zTerm;
129009
+ int nTerm = pCsr->nTerm;
129010
+ const char *aDoclist = pCsr->aDoclist;
129011
+ int nDoclist = pCsr->nDoclist;
129012
+ int rc = SQLITE_OK; /* Return code */
129013
+ int nSpace; /* Total space in bytes required on leaf */
129014
+ int nPrefix; /* Size of prefix shared with previous term */
129015
+ int nSuffix; /* Size of suffix (nTerm - nPrefix) */
129016
+ NodeWriter *pLeaf; /* Object used to write leaf nodes */
129017
+
129018
+ pLeaf = &pWriter->aNodeWriter[0];
129019
+ nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
129020
+ nSuffix = nTerm - nPrefix;
129021
+
129022
+ nSpace = sqlite3Fts3VarintLen(nPrefix);
129023
+ nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
129024
+ nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
129025
+
129026
+ /* If the current block is not empty, and if adding this term/doclist
129027
+ ** to the current block would make it larger than Fts3Table.nNodeSize
129028
+ ** bytes, write this block out to the database. */
129029
+ if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){
129030
+ rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
129031
+ pWriter->nWork++;
129032
+
129033
+ /* Add the current term to the parent node. The term added to the
129034
+ ** parent must:
129035
+ **
129036
+ ** a) be greater than the largest term on the leaf node just written
129037
+ ** to the database (still available in pLeaf->key), and
129038
+ **
129039
+ ** b) be less than or equal to the term about to be added to the new
129040
+ ** leaf node (zTerm/nTerm).
129041
+ **
129042
+ ** In other words, it must be the prefix of zTerm 1 byte longer than
129043
+ ** the common prefix (if any) of zTerm and pWriter->zTerm.
129044
+ */
129045
+ if( rc==SQLITE_OK ){
129046
+ rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1);
129047
+ }
129048
+
129049
+ /* Advance to the next output block */
129050
+ pLeaf->iBlock++;
129051
+ pLeaf->key.n = 0;
129052
+ pLeaf->block.n = 0;
129053
+
129054
+ nPrefix = 0;
129055
+ nSuffix = nTerm;
129056
+ nSpace = 1;
129057
+ nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
129058
+ nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
129059
+ }
129060
+
129061
+ blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
129062
+
129063
+ if( rc==SQLITE_OK ){
129064
+ if( pLeaf->block.n==0 ){
129065
+ pLeaf->block.n = 1;
129066
+ pLeaf->block.a[0] = '\0';
129067
+ }
129068
+ rc = fts3AppendToNode(
129069
+ &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist
129070
+ );
129071
+ }
129072
+
129073
+ return rc;
129074
+}
129075
+
129076
+/*
129077
+** This function is called to release all dynamic resources held by the
129078
+** merge-writer object pWriter, and if no error has occurred, to flush
129079
+** all outstanding node buffers held by pWriter to disk.
129080
+**
129081
+** If *pRc is not SQLITE_OK when this function is called, then no attempt
129082
+** is made to write any data to disk. Instead, this function serves only
129083
+** to release outstanding resources.
129084
+**
129085
+** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while
129086
+** flushing buffers to disk, *pRc is set to an SQLite error code before
129087
+** returning.
129088
+*/
129089
+static void fts3IncrmergeRelease(
129090
+ Fts3Table *p, /* FTS3 table handle */
129091
+ IncrmergeWriter *pWriter, /* Merge-writer object */
129092
+ int *pRc /* IN/OUT: Error code */
129093
+){
129094
+ int i; /* Used to iterate through non-root layers */
129095
+ int iRoot; /* Index of root in pWriter->aNodeWriter */
129096
+ NodeWriter *pRoot; /* NodeWriter for root node */
129097
+ int rc = *pRc; /* Error code */
129098
+
129099
+ /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
129100
+ ** root node. If the segment fits entirely on a single leaf node, iRoot
129101
+ ** will be set to 0. If the root node is the parent of the leaves, iRoot
129102
+ ** will be 1. And so on. */
129103
+ for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){
129104
+ NodeWriter *pNode = &pWriter->aNodeWriter[iRoot];
129105
+ if( pNode->block.n>0 ) break;
129106
+ assert( *pRc || pNode->block.nAlloc==0 );
129107
+ assert( *pRc || pNode->key.nAlloc==0 );
129108
+ sqlite3_free(pNode->block.a);
129109
+ sqlite3_free(pNode->key.a);
129110
+ }
129111
+
129112
+ /* Empty output segment. This is a no-op. */
129113
+ if( iRoot<0 ) return;
129114
+
129115
+ /* The entire output segment fits on a single node. Normally, this means
129116
+ ** the node would be stored as a blob in the "root" column of the %_segdir
129117
+ ** table. However, this is not permitted in this case. The problem is that
129118
+ ** space has already been reserved in the %_segments table, and so the
129119
+ ** start_block and end_block fields of the %_segdir table must be populated.
129120
+ ** And, by design or by accident, released versions of FTS cannot handle
129121
+ ** segments that fit entirely on the root node with start_block!=0.
129122
+ **
129123
+ ** Instead, create a synthetic root node that contains nothing but a
129124
+ ** pointer to the single content node. So that the segment consists of a
129125
+ ** single leaf and a single interior (root) node.
129126
+ **
129127
+ ** Todo: Better might be to defer allocating space in the %_segments
129128
+ ** table until we are sure it is needed.
129129
+ */
129130
+ if( iRoot==0 ){
129131
+ Blob *pBlock = &pWriter->aNodeWriter[1].block;
129132
+ blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc);
129133
+ if( rc==SQLITE_OK ){
129134
+ pBlock->a[0] = 0x01;
129135
+ pBlock->n = 1 + sqlite3Fts3PutVarint(
129136
+ &pBlock->a[1], pWriter->aNodeWriter[0].iBlock
129137
+ );
129138
+ }
129139
+ iRoot = 1;
129140
+ }
129141
+ pRoot = &pWriter->aNodeWriter[iRoot];
129142
+
129143
+ /* Flush all currently outstanding nodes to disk. */
129144
+ for(i=0; i<iRoot; i++){
129145
+ NodeWriter *pNode = &pWriter->aNodeWriter[i];
129146
+ if( pNode->block.n>0 && rc==SQLITE_OK ){
129147
+ rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
129148
+ }
129149
+ sqlite3_free(pNode->block.a);
129150
+ sqlite3_free(pNode->key.a);
129151
+ }
129152
+
129153
+ /* Write the %_segdir record. */
129154
+ if( rc==SQLITE_OK ){
129155
+ rc = fts3WriteSegdir(p,
129156
+ pWriter->iAbsLevel+1, /* level */
129157
+ pWriter->iIdx, /* idx */
129158
+ pWriter->iStart, /* start_block */
129159
+ pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
129160
+ pWriter->iEnd, /* end_block */
129161
+ pRoot->block.a, pRoot->block.n /* root */
129162
+ );
129163
+ }
129164
+ sqlite3_free(pRoot->block.a);
129165
+ sqlite3_free(pRoot->key.a);
129166
+
129167
+ *pRc = rc;
129168
+}
129169
+
129170
+/*
129171
+** Compare the term in buffer zLhs (size in bytes nLhs) with that in
129172
+** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of
129173
+** the other, it is considered to be smaller than the other.
129174
+**
129175
+** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve
129176
+** if it is greater.
129177
+*/
129178
+static int fts3TermCmp(
129179
+ const char *zLhs, int nLhs, /* LHS of comparison */
129180
+ const char *zRhs, int nRhs /* RHS of comparison */
129181
+){
129182
+ int nCmp = MIN(nLhs, nRhs);
129183
+ int res;
129184
+
129185
+ res = memcmp(zLhs, zRhs, nCmp);
129186
+ if( res==0 ) res = nLhs - nRhs;
129187
+
129188
+ return res;
129189
+}
129190
+
129191
+
129192
+/*
129193
+** Query to see if the entry in the %_segments table with blockid iEnd is
129194
+** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before
129195
+** returning. Otherwise, set *pbRes to 0.
129196
+**
129197
+** Or, if an error occurs while querying the database, return an SQLite
129198
+** error code. The final value of *pbRes is undefined in this case.
129199
+**
129200
+** This is used to test if a segment is an "appendable" segment. If it
129201
+** is, then a NULL entry has been inserted into the %_segments table
129202
+** with blockid %_segdir.end_block.
129203
+*/
129204
+static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){
129205
+ int bRes = 0; /* Result to set *pbRes to */
129206
+ sqlite3_stmt *pCheck = 0; /* Statement to query database with */
129207
+ int rc; /* Return code */
129208
+
129209
+ rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0);
129210
+ if( rc==SQLITE_OK ){
129211
+ sqlite3_bind_int64(pCheck, 1, iEnd);
129212
+ if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1;
129213
+ rc = sqlite3_reset(pCheck);
129214
+ }
129215
+
129216
+ *pbRes = bRes;
129217
+ return rc;
129218
+}
129219
+
129220
+/*
129221
+** This function is called when initializing an incremental-merge operation.
129222
+** It checks if the existing segment with index value iIdx at absolute level
129223
+** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the
129224
+** merge-writer object *pWriter is initialized to write to it.
129225
+**
129226
+** An existing segment can be appended to by an incremental merge if:
129227
+**
129228
+** * It was initially created as an appendable segment (with all required
129229
+** space pre-allocated), and
129230
+**
129231
+** * The first key read from the input (arguments zKey and nKey) is
129232
+** greater than the largest key currently stored in the potential
129233
+** output segment.
129234
+*/
129235
+static int fts3IncrmergeLoad(
129236
+ Fts3Table *p, /* Fts3 table handle */
129237
+ sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
129238
+ int iIdx, /* Index of candidate output segment */
129239
+ const char *zKey, /* First key to write */
129240
+ int nKey, /* Number of bytes in nKey */
129241
+ IncrmergeWriter *pWriter /* Populate this object */
129242
+){
129243
+ int rc; /* Return code */
129244
+ sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */
129245
+
129246
+ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0);
129247
+ if( rc==SQLITE_OK ){
129248
+ sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */
129249
+ sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */
129250
+ sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */
129251
+ const char *aRoot = 0; /* Pointer to %_segdir.root buffer */
129252
+ int nRoot = 0; /* Size of aRoot[] in bytes */
129253
+ int rc2; /* Return code from sqlite3_reset() */
129254
+ int bAppendable = 0; /* Set to true if segment is appendable */
129255
+
129256
+ /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */
129257
+ sqlite3_bind_int64(pSelect, 1, iAbsLevel+1);
129258
+ sqlite3_bind_int(pSelect, 2, iIdx);
129259
+ if( sqlite3_step(pSelect)==SQLITE_ROW ){
129260
+ iStart = sqlite3_column_int64(pSelect, 1);
129261
+ iLeafEnd = sqlite3_column_int64(pSelect, 2);
129262
+ iEnd = sqlite3_column_int64(pSelect, 3);
129263
+ nRoot = sqlite3_column_bytes(pSelect, 4);
129264
+ aRoot = sqlite3_column_blob(pSelect, 4);
129265
+ }else{
129266
+ return sqlite3_reset(pSelect);
129267
+ }
129268
+
129269
+ /* Check for the zero-length marker in the %_segments table */
129270
+ rc = fts3IsAppendable(p, iEnd, &bAppendable);
129271
+
129272
+ /* Check that zKey/nKey is larger than the largest key the candidate */
129273
+ if( rc==SQLITE_OK && bAppendable ){
129274
+ char *aLeaf = 0;
129275
+ int nLeaf = 0;
129276
+
129277
+ rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0);
129278
+ if( rc==SQLITE_OK ){
129279
+ NodeReader reader;
129280
+ for(rc = nodeReaderInit(&reader, aLeaf, nLeaf);
129281
+ rc==SQLITE_OK && reader.aNode;
129282
+ rc = nodeReaderNext(&reader)
129283
+ ){
129284
+ assert( reader.aNode );
129285
+ }
129286
+ if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){
129287
+ bAppendable = 0;
129288
+ }
129289
+ nodeReaderRelease(&reader);
129290
+ }
129291
+ sqlite3_free(aLeaf);
129292
+ }
129293
+
129294
+ if( rc==SQLITE_OK && bAppendable ){
129295
+ /* It is possible to append to this segment. Set up the IncrmergeWriter
129296
+ ** object to do so. */
129297
+ int i;
129298
+ int nHeight = (int)aRoot[0];
129299
+ NodeWriter *pNode;
129300
+
129301
+ pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
129302
+ pWriter->iStart = iStart;
129303
+ pWriter->iEnd = iEnd;
129304
+ pWriter->iAbsLevel = iAbsLevel;
129305
+ pWriter->iIdx = iIdx;
129306
+
129307
+ for(i=nHeight+1; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
129308
+ pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
129309
+ }
129310
+
129311
+ pNode = &pWriter->aNodeWriter[nHeight];
129312
+ pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
129313
+ blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
129314
+ if( rc==SQLITE_OK ){
129315
+ memcpy(pNode->block.a, aRoot, nRoot);
129316
+ pNode->block.n = nRoot;
129317
+ }
129318
+
129319
+ for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
129320
+ NodeReader reader;
129321
+ pNode = &pWriter->aNodeWriter[i];
129322
+
129323
+ rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
129324
+ while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
129325
+ blobGrowBuffer(&pNode->key, reader.term.n, &rc);
129326
+ if( rc==SQLITE_OK ){
129327
+ memcpy(pNode->key.a, reader.term.a, reader.term.n);
129328
+ pNode->key.n = reader.term.n;
129329
+ if( i>0 ){
129330
+ char *aBlock = 0;
129331
+ int nBlock = 0;
129332
+ pNode = &pWriter->aNodeWriter[i-1];
129333
+ pNode->iBlock = reader.iChild;
129334
+ rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
129335
+ blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
129336
+ if( rc==SQLITE_OK ){
129337
+ memcpy(pNode->block.a, aBlock, nBlock);
129338
+ pNode->block.n = nBlock;
129339
+ }
129340
+ sqlite3_free(aBlock);
129341
+ }
129342
+ }
129343
+ nodeReaderRelease(&reader);
129344
+ }
129345
+ }
129346
+
129347
+ rc2 = sqlite3_reset(pSelect);
129348
+ if( rc==SQLITE_OK ) rc = rc2;
129349
+ }
129350
+
129351
+ return rc;
129352
+}
129353
+
129354
+/*
129355
+** Determine the largest segment index value that exists within absolute
129356
+** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus
129357
+** one before returning SQLITE_OK. Or, if there are no segments at all
129358
+** within level iAbsLevel, set *piIdx to zero.
129359
+**
129360
+** If an error occurs, return an SQLite error code. The final value of
129361
+** *piIdx is undefined in this case.
129362
+*/
129363
+static int fts3IncrmergeOutputIdx(
129364
+ Fts3Table *p, /* FTS Table handle */
129365
+ sqlite3_int64 iAbsLevel, /* Absolute index of input segments */
129366
+ int *piIdx /* OUT: Next free index at iAbsLevel+1 */
129367
+){
129368
+ int rc;
129369
+ sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */
129370
+
129371
+ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0);
129372
+ if( rc==SQLITE_OK ){
129373
+ sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1);
129374
+ sqlite3_step(pOutputIdx);
129375
+ *piIdx = sqlite3_column_int(pOutputIdx, 0);
129376
+ rc = sqlite3_reset(pOutputIdx);
129377
+ }
129378
+
129379
+ return rc;
129380
+}
129381
+
129382
+/*
129383
+** Allocate an appendable output segment on absolute level iAbsLevel+1
129384
+** with idx value iIdx.
129385
+**
129386
+** In the %_segdir table, a segment is defined by the values in three
129387
+** columns:
129388
+**
129389
+** start_block
129390
+** leaves_end_block
129391
+** end_block
129392
+**
129393
+** When an appendable segment is allocated, it is estimated that the
129394
+** maximum number of leaf blocks that may be required is the sum of the
129395
+** number of leaf blocks consumed by the input segments, plus the number
129396
+** of input segments, multiplied by two. This value is stored in stack
129397
+** variable nLeafEst.
129398
+**
129399
+** A total of 16*nLeafEst blocks are allocated when an appendable segment
129400
+** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous
129401
+** array of leaf nodes starts at the first block allocated. The array
129402
+** of interior nodes that are parents of the leaf nodes start at block
129403
+** (start_block + (1 + end_block - start_block) / 16). And so on.
129404
+**
129405
+** In the actual code below, the value "16" is replaced with the
129406
+** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT.
129407
+*/
129408
+static int fts3IncrmergeWriter(
129409
+ Fts3Table *p, /* Fts3 table handle */
129410
+ sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
129411
+ int iIdx, /* Index of new output segment */
129412
+ Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */
129413
+ IncrmergeWriter *pWriter /* Populate this object */
129414
+){
129415
+ int rc; /* Return Code */
129416
+ int i; /* Iterator variable */
129417
+ int nLeafEst = 0; /* Blocks allocated for leaf nodes */
129418
+ sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */
129419
+ sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */
129420
+
129421
+ /* Calculate nLeafEst. */
129422
+ rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0);
129423
+ if( rc==SQLITE_OK ){
129424
+ sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
129425
+ sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
129426
+ if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
129427
+ nLeafEst = sqlite3_column_int(pLeafEst, 0);
129428
+ }
129429
+ rc = sqlite3_reset(pLeafEst);
129430
+ }
129431
+ if( rc!=SQLITE_OK ) return rc;
129432
+
129433
+ /* Calculate the first block to use in the output segment */
129434
+ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0);
129435
+ if( rc==SQLITE_OK ){
129436
+ if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){
129437
+ pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0);
129438
+ pWriter->iEnd = pWriter->iStart - 1;
129439
+ pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT;
129440
+ }
129441
+ rc = sqlite3_reset(pFirstBlock);
129442
+ }
129443
+ if( rc!=SQLITE_OK ) return rc;
129444
+
129445
+ /* Insert the marker in the %_segments table to make sure nobody tries
129446
+ ** to steal the space just allocated. This is also used to identify
129447
+ ** appendable segments. */
129448
+ rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0);
129449
+ if( rc!=SQLITE_OK ) return rc;
129450
+
129451
+ pWriter->iAbsLevel = iAbsLevel;
129452
+ pWriter->nLeafEst = nLeafEst;
129453
+ pWriter->iIdx = iIdx;
129454
+
129455
+ /* Set up the array of NodeWriter objects */
129456
+ for(i=0; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
129457
+ pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
129458
+ }
129459
+ return SQLITE_OK;
129460
+}
129461
+
129462
+/*
129463
+** Remove an entry from the %_segdir table. This involves running the
129464
+** following two statements:
129465
+**
129466
+** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx
129467
+** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx
129468
+**
129469
+** The DELETE statement removes the specific %_segdir level. The UPDATE
129470
+** statement ensures that the remaining segments have contiguously allocated
129471
+** idx values.
129472
+*/
129473
+static int fts3RemoveSegdirEntry(
129474
+ Fts3Table *p, /* FTS3 table handle */
129475
+ sqlite3_int64 iAbsLevel, /* Absolute level to delete from */
129476
+ int iIdx /* Index of %_segdir entry to delete */
129477
+){
129478
+ int rc; /* Return code */
129479
+ sqlite3_stmt *pDelete = 0; /* DELETE statement */
129480
+
129481
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0);
129482
+ if( rc==SQLITE_OK ){
129483
+ sqlite3_bind_int64(pDelete, 1, iAbsLevel);
129484
+ sqlite3_bind_int(pDelete, 2, iIdx);
129485
+ sqlite3_step(pDelete);
129486
+ rc = sqlite3_reset(pDelete);
129487
+ }
129488
+
129489
+ return rc;
129490
+}
129491
+
129492
+/*
129493
+** One or more segments have just been removed from absolute level iAbsLevel.
129494
+** Update the 'idx' values of the remaining segments in the level so that
129495
+** the idx values are a contiguous sequence starting from 0.
129496
+*/
129497
+static int fts3RepackSegdirLevel(
129498
+ Fts3Table *p, /* FTS3 table handle */
129499
+ sqlite3_int64 iAbsLevel /* Absolute level to repack */
129500
+){
129501
+ int rc; /* Return code */
129502
+ int *aIdx = 0; /* Array of remaining idx values */
129503
+ int nIdx = 0; /* Valid entries in aIdx[] */
129504
+ int nAlloc = 0; /* Allocated size of aIdx[] */
129505
+ int i; /* Iterator variable */
129506
+ sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */
129507
+ sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */
129508
+
129509
+ rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0);
129510
+ if( rc==SQLITE_OK ){
129511
+ int rc2;
129512
+ sqlite3_bind_int64(pSelect, 1, iAbsLevel);
129513
+ while( SQLITE_ROW==sqlite3_step(pSelect) ){
129514
+ if( nIdx>=nAlloc ){
129515
+ int *aNew;
129516
+ nAlloc += 16;
129517
+ aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
129518
+ if( !aNew ){
129519
+ rc = SQLITE_NOMEM;
129520
+ break;
129521
+ }
129522
+ aIdx = aNew;
129523
+ }
129524
+ aIdx[nIdx++] = sqlite3_column_int(pSelect, 0);
129525
+ }
129526
+ rc2 = sqlite3_reset(pSelect);
129527
+ if( rc==SQLITE_OK ) rc = rc2;
129528
+ }
129529
+
129530
+ if( rc==SQLITE_OK ){
129531
+ rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0);
129532
+ }
129533
+ if( rc==SQLITE_OK ){
129534
+ sqlite3_bind_int64(pUpdate, 2, iAbsLevel);
129535
+ }
129536
+
129537
+ assert( p->bIgnoreSavepoint==0 );
129538
+ p->bIgnoreSavepoint = 1;
129539
+ for(i=0; rc==SQLITE_OK && i<nIdx; i++){
129540
+ if( aIdx[i]!=i ){
129541
+ sqlite3_bind_int(pUpdate, 3, aIdx[i]);
129542
+ sqlite3_bind_int(pUpdate, 1, i);
129543
+ sqlite3_step(pUpdate);
129544
+ rc = sqlite3_reset(pUpdate);
129545
+ }
129546
+ }
129547
+ p->bIgnoreSavepoint = 0;
129548
+
129549
+ sqlite3_free(aIdx);
129550
+ return rc;
129551
+}
129552
+
129553
+static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){
129554
+ pNode->a[0] = (char)iHeight;
129555
+ if( iChild ){
129556
+ assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) );
129557
+ pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild);
129558
+ }else{
129559
+ assert( pNode->nAlloc>=1 );
129560
+ pNode->n = 1;
129561
+ }
129562
+}
129563
+
129564
+/*
129565
+** The first two arguments are a pointer to and the size of a segment b-tree
129566
+** node. The node may be a leaf or an internal node.
129567
+**
129568
+** This function creates a new node image in blob object *pNew by copying
129569
+** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes)
129570
+** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode.
129571
+*/
129572
+static int fts3TruncateNode(
129573
+ const char *aNode, /* Current node image */
129574
+ int nNode, /* Size of aNode in bytes */
129575
+ Blob *pNew, /* OUT: Write new node image here */
129576
+ const char *zTerm, /* Omit all terms smaller than this */
129577
+ int nTerm, /* Size of zTerm in bytes */
129578
+ sqlite3_int64 *piBlock /* OUT: Block number in next layer down */
129579
+){
129580
+ NodeReader reader; /* Reader object */
129581
+ Blob prev = {0, 0, 0}; /* Previous term written to new node */
129582
+ int rc = SQLITE_OK; /* Return code */
129583
+ int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
129584
+
129585
+ /* Allocate required output space */
129586
+ blobGrowBuffer(pNew, nNode, &rc);
129587
+ if( rc!=SQLITE_OK ) return rc;
129588
+ pNew->n = 0;
129589
+
129590
+ /* Populate new node buffer */
129591
+ for(rc = nodeReaderInit(&reader, aNode, nNode);
129592
+ rc==SQLITE_OK && reader.aNode;
129593
+ rc = nodeReaderNext(&reader)
129594
+ ){
129595
+ if( pNew->n==0 ){
129596
+ int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm);
129597
+ if( res<0 || (bLeaf==0 && res==0) ) continue;
129598
+ fts3StartNode(pNew, (int)aNode[0], reader.iChild);
129599
+ *piBlock = reader.iChild;
129600
+ }
129601
+ rc = fts3AppendToNode(
129602
+ pNew, &prev, reader.term.a, reader.term.n,
129603
+ reader.aDoclist, reader.nDoclist
129604
+ );
129605
+ if( rc!=SQLITE_OK ) break;
129606
+ }
129607
+ if( pNew->n==0 ){
129608
+ fts3StartNode(pNew, (int)aNode[0], reader.iChild);
129609
+ *piBlock = reader.iChild;
129610
+ }
129611
+ assert( pNew->n<=pNew->nAlloc );
129612
+
129613
+ nodeReaderRelease(&reader);
129614
+ sqlite3_free(prev.a);
129615
+ return rc;
129616
+}
129617
+
129618
+/*
129619
+** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
129620
+** level iAbsLevel. This may involve deleting entries from the %_segments
129621
+** table, and modifying existing entries in both the %_segments and %_segdir
129622
+** tables.
129623
+**
129624
+** SQLITE_OK is returned if the segment is updated successfully. Or an
129625
+** SQLite error code otherwise.
129626
+*/
129627
+static int fts3TruncateSegment(
129628
+ Fts3Table *p, /* FTS3 table handle */
129629
+ sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */
129630
+ int iIdx, /* Index within level of segment to modify */
129631
+ const char *zTerm, /* Remove terms smaller than this */
129632
+ int nTerm /* Number of bytes in buffer zTerm */
129633
+){
129634
+ int rc = SQLITE_OK; /* Return code */
129635
+ Blob root = {0,0,0}; /* New root page image */
129636
+ Blob block = {0,0,0}; /* Buffer used for any other block */
129637
+ sqlite3_int64 iBlock = 0; /* Block id */
129638
+ sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */
129639
+ sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */
129640
+ sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */
129641
+
129642
+ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0);
129643
+ if( rc==SQLITE_OK ){
129644
+ int rc2; /* sqlite3_reset() return code */
129645
+ sqlite3_bind_int64(pFetch, 1, iAbsLevel);
129646
+ sqlite3_bind_int(pFetch, 2, iIdx);
129647
+ if( SQLITE_ROW==sqlite3_step(pFetch) ){
129648
+ const char *aRoot = sqlite3_column_blob(pFetch, 4);
129649
+ int nRoot = sqlite3_column_bytes(pFetch, 4);
129650
+ iOldStart = sqlite3_column_int64(pFetch, 1);
129651
+ rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock);
129652
+ }
129653
+ rc2 = sqlite3_reset(pFetch);
129654
+ if( rc==SQLITE_OK ) rc = rc2;
129655
+ }
129656
+
129657
+ while( rc==SQLITE_OK && iBlock ){
129658
+ char *aBlock = 0;
129659
+ int nBlock = 0;
129660
+ iNewStart = iBlock;
129661
+
129662
+ rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0);
129663
+ if( rc==SQLITE_OK ){
129664
+ rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock);
129665
+ }
129666
+ if( rc==SQLITE_OK ){
129667
+ rc = fts3WriteSegment(p, iNewStart, block.a, block.n);
129668
+ }
129669
+ sqlite3_free(aBlock);
129670
+ }
129671
+
129672
+ /* Variable iNewStart now contains the first valid leaf node. */
129673
+ if( rc==SQLITE_OK && iNewStart ){
129674
+ sqlite3_stmt *pDel = 0;
129675
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0);
129676
+ if( rc==SQLITE_OK ){
129677
+ sqlite3_bind_int64(pDel, 1, iOldStart);
129678
+ sqlite3_bind_int64(pDel, 2, iNewStart-1);
129679
+ sqlite3_step(pDel);
129680
+ rc = sqlite3_reset(pDel);
129681
+ }
129682
+ }
129683
+
129684
+ if( rc==SQLITE_OK ){
129685
+ sqlite3_stmt *pChomp = 0;
129686
+ rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0);
129687
+ if( rc==SQLITE_OK ){
129688
+ sqlite3_bind_int64(pChomp, 1, iNewStart);
129689
+ sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC);
129690
+ sqlite3_bind_int64(pChomp, 3, iAbsLevel);
129691
+ sqlite3_bind_int(pChomp, 4, iIdx);
129692
+ sqlite3_step(pChomp);
129693
+ rc = sqlite3_reset(pChomp);
129694
+ }
129695
+ }
129696
+
129697
+ sqlite3_free(root.a);
129698
+ sqlite3_free(block.a);
129699
+ return rc;
129700
+}
129701
+
129702
+/*
129703
+** This function is called after an incrmental-merge operation has run to
129704
+** merge (or partially merge) two or more segments from absolute level
129705
+** iAbsLevel.
129706
+**
129707
+** Each input segment is either removed from the db completely (if all of
129708
+** its data was copied to the output segment by the incrmerge operation)
129709
+** or modified in place so that it no longer contains those entries that
129710
+** have been duplicated in the output segment.
129711
+*/
129712
+static int fts3IncrmergeChomp(
129713
+ Fts3Table *p, /* FTS table handle */
129714
+ sqlite3_int64 iAbsLevel, /* Absolute level containing segments */
129715
+ Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */
129716
+ int *pnRem /* Number of segments not deleted */
129717
+){
129718
+ int i;
129719
+ int nRem = 0;
129720
+ int rc = SQLITE_OK;
129721
+
129722
+ for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){
129723
+ Fts3SegReader *pSeg = 0;
129724
+ int j;
129725
+
129726
+ /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding
129727
+ ** somewhere in the pCsr->apSegment[] array. */
129728
+ for(j=0; ALWAYS(j<pCsr->nSegment); j++){
129729
+ pSeg = pCsr->apSegment[j];
129730
+ if( pSeg->iIdx==i ) break;
129731
+ }
129732
+ assert( j<pCsr->nSegment && pSeg->iIdx==i );
129733
+
129734
+ if( pSeg->aNode==0 ){
129735
+ /* Seg-reader is at EOF. Remove the entire input segment. */
129736
+ rc = fts3DeleteSegment(p, pSeg);
129737
+ if( rc==SQLITE_OK ){
129738
+ rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx);
129739
+ }
129740
+ *pnRem = 0;
129741
+ }else{
129742
+ /* The incremental merge did not copy all the data from this
129743
+ ** segment to the upper level. The segment is modified in place
129744
+ ** so that it contains no keys smaller than zTerm/nTerm. */
129745
+ const char *zTerm = pSeg->zTerm;
129746
+ int nTerm = pSeg->nTerm;
129747
+ rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
129748
+ nRem++;
129749
+ }
129750
+ }
129751
+
129752
+ if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){
129753
+ rc = fts3RepackSegdirLevel(p, iAbsLevel);
129754
+ }
129755
+
129756
+ *pnRem = nRem;
129757
+ return rc;
129758
+}
129759
+
129760
+/*
129761
+** Store an incr-merge hint in the database.
129762
+*/
129763
+static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
129764
+ sqlite3_stmt *pReplace = 0;
129765
+ int rc; /* Return code */
129766
+
129767
+ rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0);
129768
+ if( rc==SQLITE_OK ){
129769
+ sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT);
129770
+ sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
129771
+ sqlite3_step(pReplace);
129772
+ rc = sqlite3_reset(pReplace);
129773
+ }
129774
+
129775
+ return rc;
129776
+}
129777
+
129778
+/*
129779
+** Load an incr-merge hint from the database. The incr-merge hint, if one
129780
+** exists, is stored in the rowid==1 row of the %_stat table.
129781
+**
129782
+** If successful, populate blob *pHint with the value read from the %_stat
129783
+** table and return SQLITE_OK. Otherwise, if an error occurs, return an
129784
+** SQLite error code.
129785
+*/
129786
+static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
129787
+ sqlite3_stmt *pSelect = 0;
129788
+ int rc;
129789
+
129790
+ pHint->n = 0;
129791
+ rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0);
129792
+ if( rc==SQLITE_OK ){
129793
+ int rc2;
129794
+ sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
129795
+ if( SQLITE_ROW==sqlite3_step(pSelect) ){
129796
+ const char *aHint = sqlite3_column_blob(pSelect, 0);
129797
+ int nHint = sqlite3_column_bytes(pSelect, 0);
129798
+ if( aHint ){
129799
+ blobGrowBuffer(pHint, nHint, &rc);
129800
+ if( rc==SQLITE_OK ){
129801
+ memcpy(pHint->a, aHint, nHint);
129802
+ pHint->n = nHint;
129803
+ }
129804
+ }
129805
+ }
129806
+ rc2 = sqlite3_reset(pSelect);
129807
+ if( rc==SQLITE_OK ) rc = rc2;
129808
+ }
129809
+
129810
+ return rc;
129811
+}
129812
+
129813
+/*
129814
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
129815
+** Otherwise, append an entry to the hint stored in blob *pHint. Each entry
129816
+** consists of two varints, the absolute level number of the input segments
129817
+** and the number of input segments.
129818
+**
129819
+** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
129820
+** set *pRc to an SQLite error code before returning.
129821
+*/
129822
+static void fts3IncrmergeHintPush(
129823
+ Blob *pHint, /* Hint blob to append to */
129824
+ i64 iAbsLevel, /* First varint to store in hint */
129825
+ int nInput, /* Second varint to store in hint */
129826
+ int *pRc /* IN/OUT: Error code */
129827
+){
129828
+ blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc);
129829
+ if( *pRc==SQLITE_OK ){
129830
+ pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel);
129831
+ pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput);
129832
+ }
129833
+}
129834
+
129835
+/*
129836
+** Read the last entry (most recently pushed) from the hint blob *pHint
129837
+** and then remove the entry. Write the two values read to *piAbsLevel and
129838
+** *pnInput before returning.
129839
+**
129840
+** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
129841
+** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB.
129842
+*/
129843
+static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
129844
+ const int nHint = pHint->n;
129845
+ int i;
129846
+
129847
+ i = pHint->n-2;
129848
+ while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
129849
+ while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
129850
+
129851
+ pHint->n = i;
129852
+ i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
129853
+ i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput);
129854
+ if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
129855
+
129856
+ return SQLITE_OK;
129857
+}
129858
+
129859
+
129860
+/*
129861
+** Attempt an incremental merge that writes nMerge leaf blocks.
129862
+**
129863
+** Incremental merges happen nMin segments at a time. The two
129864
+** segments to be merged are the nMin oldest segments (the ones with
129865
+** the smallest indexes) in the highest level that contains at least
129866
+** nMin segments. Multiple merges might occur in an attempt to write the
129867
+** quota of nMerge leaf blocks.
129868
+*/
129869
+SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
129870
+ int rc; /* Return code */
129871
+ int nRem = nMerge; /* Number of leaf pages yet to be written */
129872
+ Fts3MultiSegReader *pCsr; /* Cursor used to read input data */
129873
+ Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */
129874
+ IncrmergeWriter *pWriter; /* Writer object */
129875
+ int nSeg = 0; /* Number of input segments */
129876
+ sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */
129877
+ Blob hint = {0, 0, 0}; /* Hint read from %_stat table */
129878
+ int bDirtyHint = 0; /* True if blob 'hint' has been modified */
129879
+
129880
+ /* Allocate space for the cursor, filter and writer objects */
129881
+ const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
129882
+ pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
129883
+ if( !pWriter ) return SQLITE_NOMEM;
129884
+ pFilter = (Fts3SegFilter *)&pWriter[1];
129885
+ pCsr = (Fts3MultiSegReader *)&pFilter[1];
129886
+
129887
+ rc = fts3IncrmergeHintLoad(p, &hint);
129888
+ while( rc==SQLITE_OK && nRem>0 ){
129889
+ const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
129890
+ sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
129891
+ int bUseHint = 0; /* True if attempting to append */
129892
+
129893
+ /* Search the %_segdir table for the absolute level with the smallest
129894
+ ** relative level number that contains at least nMin segments, if any.
129895
+ ** If one is found, set iAbsLevel to the absolute level number and
129896
+ ** nSeg to nMin. If no level with at least nMin segments can be found,
129897
+ ** set nSeg to -1.
129898
+ */
129899
+ rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
129900
+ sqlite3_bind_int(pFindLevel, 1, nMin);
129901
+ if( sqlite3_step(pFindLevel)==SQLITE_ROW ){
129902
+ iAbsLevel = sqlite3_column_int64(pFindLevel, 0);
129903
+ nSeg = nMin;
129904
+ }else{
129905
+ nSeg = -1;
129906
+ }
129907
+ rc = sqlite3_reset(pFindLevel);
129908
+
129909
+ /* If the hint read from the %_stat table is not empty, check if the
129910
+ ** last entry in it specifies a relative level smaller than or equal
129911
+ ** to the level identified by the block above (if any). If so, this
129912
+ ** iteration of the loop will work on merging at the hinted level.
129913
+ */
129914
+ if( rc==SQLITE_OK && hint.n ){
129915
+ int nHint = hint.n;
129916
+ sqlite3_int64 iHintAbsLevel = 0; /* Hint level */
129917
+ int nHintSeg = 0; /* Hint number of segments */
129918
+
129919
+ rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
129920
+ if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
129921
+ iAbsLevel = iHintAbsLevel;
129922
+ nSeg = nHintSeg;
129923
+ bUseHint = 1;
129924
+ bDirtyHint = 1;
129925
+ }else{
129926
+ /* This undoes the effect of the HintPop() above - so that no entry
129927
+ ** is removed from the hint blob. */
129928
+ hint.n = nHint;
129929
+ }
129930
+ }
129931
+
129932
+ /* If nSeg is less that zero, then there is no level with at least
129933
+ ** nMin segments and no hint in the %_stat table. No work to do.
129934
+ ** Exit early in this case. */
129935
+ if( nSeg<0 ) break;
129936
+
129937
+ /* Open a cursor to iterate through the contents of the oldest nSeg
129938
+ ** indexes of absolute level iAbsLevel. If this cursor is opened using
129939
+ ** the 'hint' parameters, it is possible that there are less than nSeg
129940
+ ** segments available in level iAbsLevel. In this case, no work is
129941
+ ** done on iAbsLevel - fall through to the next iteration of the loop
129942
+ ** to start work on some other level. */
129943
+ memset(pWriter, 0, nAlloc);
129944
+ pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
129945
+ if( rc==SQLITE_OK ){
129946
+ rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
129947
+ }
129948
+ if( SQLITE_OK==rc && pCsr->nSegment==nSeg
129949
+ && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
129950
+ && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
129951
+ ){
129952
+ int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
129953
+ rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
129954
+ if( rc==SQLITE_OK ){
129955
+ if( bUseHint && iIdx>0 ){
129956
+ const char *zKey = pCsr->zTerm;
129957
+ int nKey = pCsr->nTerm;
129958
+ rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
129959
+ }else{
129960
+ rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
129961
+ }
129962
+ }
129963
+
129964
+ if( rc==SQLITE_OK && pWriter->nLeafEst ){
129965
+ fts3LogMerge(nSeg, iAbsLevel);
129966
+ do {
129967
+ rc = fts3IncrmergeAppend(p, pWriter, pCsr);
129968
+ if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
129969
+ if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
129970
+ }while( rc==SQLITE_ROW );
129971
+
129972
+ /* Update or delete the input segments */
129973
+ if( rc==SQLITE_OK ){
129974
+ nRem -= (1 + pWriter->nWork);
129975
+ rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg);
129976
+ if( nSeg!=0 ){
129977
+ bDirtyHint = 1;
129978
+ fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc);
129979
+ }
129980
+ }
129981
+ }
129982
+
129983
+ fts3IncrmergeRelease(p, pWriter, &rc);
129984
+ }
129985
+
129986
+ sqlite3Fts3SegReaderFinish(pCsr);
129987
+ }
129988
+
129989
+ /* Write the hint values into the %_stat table for the next incr-merger */
129990
+ if( bDirtyHint && rc==SQLITE_OK ){
129991
+ rc = fts3IncrmergeHintStore(p, &hint);
129992
+ }
129993
+
129994
+ sqlite3_free(pWriter);
129995
+ sqlite3_free(hint.a);
129996
+ return rc;
129997
+}
129998
+
129999
+/*
130000
+** Convert the text beginning at *pz into an integer and return
130001
+** its value. Advance *pz to point to the first character past
130002
+** the integer.
130003
+*/
130004
+static int fts3Getint(const char **pz){
130005
+ const char *z = *pz;
130006
+ int i = 0;
130007
+ while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
130008
+ *pz = z;
130009
+ return i;
130010
+}
130011
+
130012
+/*
130013
+** Process statements of the form:
130014
+**
130015
+** INSERT INTO table(table) VALUES('merge=A,B');
130016
+**
130017
+** A and B are integers that decode to be the number of leaf pages
130018
+** written for the merge, and the minimum number of segments on a level
130019
+** before it will be selected for a merge, respectively.
130020
+*/
130021
+static int fts3DoIncrmerge(
130022
+ Fts3Table *p, /* FTS3 table handle */
130023
+ const char *zParam /* Nul-terminated string containing "A,B" */
130024
+){
130025
+ int rc;
130026
+ int nMin = (FTS3_MERGE_COUNT / 2);
130027
+ int nMerge = 0;
130028
+ const char *z = zParam;
130029
+
130030
+ /* Read the first integer value */
130031
+ nMerge = fts3Getint(&z);
130032
+
130033
+ /* If the first integer value is followed by a ',', read the second
130034
+ ** integer value. */
130035
+ if( z[0]==',' && z[1]!='\0' ){
130036
+ z++;
130037
+ nMin = fts3Getint(&z);
130038
+ }
130039
+
130040
+ if( z[0]!='\0' || nMin<2 ){
130041
+ rc = SQLITE_ERROR;
130042
+ }else{
130043
+ rc = SQLITE_OK;
130044
+ if( !p->bHasStat ){
130045
+ assert( p->bFts4==0 );
130046
+ sqlite3Fts3CreateStatTable(&rc, p);
130047
+ }
130048
+ if( rc==SQLITE_OK ){
130049
+ rc = sqlite3Fts3Incrmerge(p, nMerge, nMin);
130050
+ }
130051
+ sqlite3Fts3SegmentsClose(p);
130052
+ }
130053
+ return rc;
130054
+}
130055
+
130056
+/*
130057
+** Process statements of the form:
130058
+**
130059
+** INSERT INTO table(table) VALUES('automerge=X');
130060
+**
130061
+** where X is an integer. X==0 means to turn automerge off. X!=0 means
130062
+** turn it on. The setting is persistent.
130063
+*/
130064
+static int fts3DoAutoincrmerge(
130065
+ Fts3Table *p, /* FTS3 table handle */
130066
+ const char *zParam /* Nul-terminated string containing boolean */
130067
+){
130068
+ int rc = SQLITE_OK;
130069
+ sqlite3_stmt *pStmt = 0;
130070
+ p->bAutoincrmerge = fts3Getint(&zParam)!=0;
130071
+ if( !p->bHasStat ){
130072
+ assert( p->bFts4==0 );
130073
+ sqlite3Fts3CreateStatTable(&rc, p);
130074
+ if( rc ) return rc;
130075
+ }
130076
+ rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
130077
+ if( rc ) return rc;;
130078
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
130079
+ sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
130080
+ sqlite3_step(pStmt);
130081
+ rc = sqlite3_reset(pStmt);
130082
+ return rc;
130083
+}
130084
+
130085
+/*
130086
+** Return a 64-bit checksum for the FTS index entry specified by the
130087
+** arguments to this function.
130088
+*/
130089
+static u64 fts3ChecksumEntry(
130090
+ const char *zTerm, /* Pointer to buffer containing term */
130091
+ int nTerm, /* Size of zTerm in bytes */
130092
+ int iLangid, /* Language id for current row */
130093
+ int iIndex, /* Index (0..Fts3Table.nIndex-1) */
130094
+ i64 iDocid, /* Docid for current row. */
130095
+ int iCol, /* Column number */
130096
+ int iPos /* Position */
130097
+){
130098
+ int i;
130099
+ u64 ret = (u64)iDocid;
130100
+
130101
+ ret += (ret<<3) + iLangid;
130102
+ ret += (ret<<3) + iIndex;
130103
+ ret += (ret<<3) + iCol;
130104
+ ret += (ret<<3) + iPos;
130105
+ for(i=0; i<nTerm; i++) ret += (ret<<3) + zTerm[i];
130106
+
130107
+ return ret;
130108
+}
130109
+
130110
+/*
130111
+** Return a checksum of all entries in the FTS index that correspond to
130112
+** language id iLangid. The checksum is calculated by XORing the checksums
130113
+** of each individual entry (see fts3ChecksumEntry()) together.
130114
+**
130115
+** If successful, the checksum value is returned and *pRc set to SQLITE_OK.
130116
+** Otherwise, if an error occurs, *pRc is set to an SQLite error code. The
130117
+** return value is undefined in this case.
130118
+*/
130119
+static u64 fts3ChecksumIndex(
130120
+ Fts3Table *p, /* FTS3 table handle */
130121
+ int iLangid, /* Language id to return cksum for */
130122
+ int iIndex, /* Index to cksum (0..p->nIndex-1) */
130123
+ int *pRc /* OUT: Return code */
130124
+){
130125
+ Fts3SegFilter filter;
130126
+ Fts3MultiSegReader csr;
130127
+ int rc;
130128
+ u64 cksum = 0;
130129
+
130130
+ assert( *pRc==SQLITE_OK );
130131
+
130132
+ memset(&filter, 0, sizeof(filter));
130133
+ memset(&csr, 0, sizeof(csr));
130134
+ filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
130135
+ filter.flags |= FTS3_SEGMENT_SCAN;
130136
+
130137
+ rc = sqlite3Fts3SegReaderCursor(
130138
+ p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr
130139
+ );
130140
+ if( rc==SQLITE_OK ){
130141
+ rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
130142
+ }
130143
+
130144
+ if( rc==SQLITE_OK ){
130145
+ while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){
130146
+ char *pCsr = csr.aDoclist;
130147
+ char *pEnd = &pCsr[csr.nDoclist];
130148
+
130149
+ i64 iDocid = 0;
130150
+ i64 iCol = 0;
130151
+ i64 iPos = 0;
130152
+
130153
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
130154
+ while( pCsr<pEnd ){
130155
+ i64 iVal = 0;
130156
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
130157
+ if( pCsr<pEnd ){
130158
+ if( iVal==0 || iVal==1 ){
130159
+ iCol = 0;
130160
+ iPos = 0;
130161
+ if( iVal ){
130162
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
130163
+ }else{
130164
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
130165
+ iDocid += iVal;
130166
+ }
130167
+ }else{
130168
+ iPos += (iVal - 2);
130169
+ cksum = cksum ^ fts3ChecksumEntry(
130170
+ csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid,
130171
+ (int)iCol, (int)iPos
130172
+ );
130173
+ }
130174
+ }
130175
+ }
130176
+ }
130177
+ }
130178
+ sqlite3Fts3SegReaderFinish(&csr);
130179
+
130180
+ *pRc = rc;
130181
+ return cksum;
130182
+}
130183
+
130184
+/*
130185
+** Check if the contents of the FTS index match the current contents of the
130186
+** content table. If no error occurs and the contents do match, set *pbOk
130187
+** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
130188
+** to false before returning.
130189
+**
130190
+** If an error occurs (e.g. an OOM or IO error), return an SQLite error
130191
+** code. The final value of *pbOk is undefined in this case.
130192
+*/
130193
+static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
130194
+ int rc = SQLITE_OK; /* Return code */
130195
+ u64 cksum1 = 0; /* Checksum based on FTS index contents */
130196
+ u64 cksum2 = 0; /* Checksum based on %_content contents */
130197
+ sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */
130198
+
130199
+ /* This block calculates the checksum according to the FTS index. */
130200
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
130201
+ if( rc==SQLITE_OK ){
130202
+ int rc2;
130203
+ sqlite3_bind_int(pAllLangid, 1, p->nIndex);
130204
+ while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
130205
+ int iLangid = sqlite3_column_int(pAllLangid, 0);
130206
+ int i;
130207
+ for(i=0; i<p->nIndex; i++){
130208
+ cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
130209
+ }
130210
+ }
130211
+ rc2 = sqlite3_reset(pAllLangid);
130212
+ if( rc==SQLITE_OK ) rc = rc2;
130213
+ }
130214
+
130215
+ /* This block calculates the checksum according to the %_content table */
130216
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
130217
+ if( rc==SQLITE_OK ){
130218
+ sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
130219
+ sqlite3_stmt *pStmt = 0;
130220
+ char *zSql;
130221
+
130222
+ zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
130223
+ if( !zSql ){
130224
+ rc = SQLITE_NOMEM;
130225
+ }else{
130226
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
130227
+ sqlite3_free(zSql);
130228
+ }
130229
+
130230
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
130231
+ i64 iDocid = sqlite3_column_int64(pStmt, 0);
130232
+ int iLang = langidFromSelect(p, pStmt);
130233
+ int iCol;
130234
+
130235
+ for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
130236
+ const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
130237
+ int nText = sqlite3_column_bytes(pStmt, iCol+1);
130238
+ sqlite3_tokenizer_cursor *pT = 0;
130239
+
130240
+ rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
130241
+ while( rc==SQLITE_OK ){
130242
+ char const *zToken; /* Buffer containing token */
130243
+ int nToken; /* Number of bytes in token */
130244
+ int iDum1, iDum2; /* Dummy variables */
130245
+ int iPos; /* Position of token in zText */
130246
+
130247
+ rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
130248
+ if( rc==SQLITE_OK ){
130249
+ int i;
130250
+ cksum2 = cksum2 ^ fts3ChecksumEntry(
130251
+ zToken, nToken, iLang, 0, iDocid, iCol, iPos
130252
+ );
130253
+ for(i=1; i<p->nIndex; i++){
130254
+ if( p->aIndex[i].nPrefix<=nToken ){
130255
+ cksum2 = cksum2 ^ fts3ChecksumEntry(
130256
+ zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
130257
+ );
130258
+ }
130259
+ }
130260
+ }
130261
+ }
130262
+ if( pT ) pModule->xClose(pT);
130263
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
130264
+ }
130265
+ }
130266
+
130267
+ sqlite3_finalize(pStmt);
130268
+ }
130269
+
130270
+ *pbOk = (cksum1==cksum2);
130271
+ return rc;
130272
+}
130273
+
130274
+/*
130275
+** Run the integrity-check. If no error occurs and the current contents of
130276
+** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
130277
+** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
130278
+**
130279
+** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
130280
+** error code.
130281
+**
130282
+** The integrity-check works as follows. For each token and indexed token
130283
+** prefix in the document set, a 64-bit checksum is calculated (by code
130284
+** in fts3ChecksumEntry()) based on the following:
130285
+**
130286
+** + The index number (0 for the main index, 1 for the first prefix
130287
+** index etc.),
130288
+** + The token (or token prefix) text itself,
130289
+** + The language-id of the row it appears in,
130290
+** + The docid of the row it appears in,
130291
+** + The column it appears in, and
130292
+** + The tokens position within that column.
130293
+**
130294
+** The checksums for all entries in the index are XORed together to create
130295
+** a single checksum for the entire index.
130296
+**
130297
+** The integrity-check code calculates the same checksum in two ways:
130298
+**
130299
+** 1. By scanning the contents of the FTS index, and
130300
+** 2. By scanning and tokenizing the content table.
130301
+**
130302
+** If the two checksums are identical, the integrity-check is deemed to have
130303
+** passed.
130304
+*/
130305
+static int fts3DoIntegrityCheck(
130306
+ Fts3Table *p /* FTS3 table handle */
130307
+){
130308
+ int rc;
130309
+ int bOk = 0;
130310
+ rc = fts3IntegrityCheck(p, &bOk);
130311
+ if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
130312
+ return rc;
130313
+}
130314
+
127855130315
/*
127856130316
** Handle a 'special' INSERT of the form:
127857130317
**
127858130318
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
127859130319
**
@@ -127869,10 +130329,16 @@
127869130329
return SQLITE_NOMEM;
127870130330
}else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
127871130331
rc = fts3DoOptimize(p, 0);
127872130332
}else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
127873130333
rc = fts3DoRebuild(p);
130334
+ }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){
130335
+ rc = fts3DoIntegrityCheck(p);
130336
+ }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){
130337
+ rc = fts3DoIncrmerge(p, &zVal[6]);
130338
+ }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
130339
+ rc = fts3DoAutoincrmerge(p, &zVal[10]);
127874130340
#ifdef SQLITE_TEST
127875130341
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
127876130342
p->nNodeSize = atoi(&zVal[9]);
127877130343
rc = SQLITE_OK;
127878130344
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
@@ -127937,18 +130403,17 @@
127937130403
127938130404
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
127939130405
const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
127940130406
sqlite3_tokenizer_cursor *pTC = 0;
127941130407
127942
- rc = pModule->xOpen(pT, zText, -1, &pTC);
130408
+ rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
127943130409
while( rc==SQLITE_OK ){
127944130410
char const *zToken; /* Buffer containing token */
127945130411
int nToken; /* Number of bytes in token */
127946130412
int iDum1, iDum2; /* Dummy variables */
127947130413
int iPos; /* Position of token in zText */
127948130414
127949
- pTC->pTokenizer = pT;
127950130415
rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
127951130416
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
127952130417
Fts3PhraseToken *pPT = pDef->pToken;
127953130418
if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
127954130419
&& (pPT->bFirst==0 || iPos==0)
@@ -128044,12 +130509,10 @@
128044130509
** delete the contents of all three tables and throw away any
128045130510
** data in the pendingTerms hash table. */
128046130511
rc = fts3DeleteAll(p, 1);
128047130512
*pnDoc = *pnDoc - 1;
128048130513
}else{
128049
- sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
128050
- rc = fts3PendingTermsDocid(p, iRemove);
128051130514
fts3DeleteTerms(&rc, p, pRowid, aSzDel);
128052130515
if( p->zContentTbl==0 ){
128053130516
fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
128054130517
if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
128055130518
}else{
@@ -128064,11 +130527,20 @@
128064130527
return rc;
128065130528
}
128066130529
128067130530
/*
128068130531
** This function does the work for the xUpdate method of FTS3 virtual
128069
-** tables.
130532
+** tables. The schema of the virtual table being:
130533
+**
130534
+** CREATE TABLE <table name>(
130535
+** <user columns>,
130536
+** <table name> HIDDEN,
130537
+** docid HIDDEN,
130538
+** <langid> HIDDEN
130539
+** );
130540
+**
130541
+**
128070130542
*/
128071130543
SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
128072130544
sqlite3_vtab *pVtab, /* FTS3 vtab object */
128073130545
int nArg, /* Size of argument array */
128074130546
sqlite3_value **apVal, /* Array of arguments */
@@ -128081,10 +130553,14 @@
128081130553
u32 *aSzDel; /* Sizes of deleted documents */
128082130554
int nChng = 0; /* Net change in number of documents */
128083130555
int bInsertDone = 0;
128084130556
128085130557
assert( p->pSegments==0 );
130558
+ assert(
130559
+ nArg==1 /* DELETE operations */
130560
+ || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */
130561
+ );
128086130562
128087130563
/* Check for a "special" INSERT operation. One of the form:
128088130564
**
128089130565
** INSERT INTO xyz(xyz) VALUES('command');
128090130566
*/
@@ -128093,10 +130569,15 @@
128093130569
&& sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
128094130570
){
128095130571
rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
128096130572
goto update_out;
128097130573
}
130574
+
130575
+ if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){
130576
+ rc = SQLITE_CONSTRAINT;
130577
+ goto update_out;
130578
+ }
128098130579
128099130580
/* Allocate space to hold the change in document sizes */
128100130581
aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
128101130582
if( aSzIns==0 ){
128102130583
rc = SQLITE_NOMEM;
@@ -128161,30 +130642,31 @@
128161130642
isRemove = 1;
128162130643
}
128163130644
128164130645
/* If this is an INSERT or UPDATE operation, insert the new record. */
128165130646
if( nArg>1 && rc==SQLITE_OK ){
130647
+ int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]);
128166130648
if( bInsertDone==0 ){
128167130649
rc = fts3InsertData(p, apVal, pRowid);
128168130650
if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
128169130651
rc = FTS_CORRUPT_VTAB;
128170130652
}
128171130653
}
128172130654
if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
128173
- rc = fts3PendingTermsDocid(p, *pRowid);
130655
+ rc = fts3PendingTermsDocid(p, iLangid, *pRowid);
128174130656
}
128175130657
if( rc==SQLITE_OK ){
128176130658
assert( p->iPrevDocid==*pRowid );
128177
- rc = fts3InsertTerms(p, apVal, aSzIns);
130659
+ rc = fts3InsertTerms(p, iLangid, apVal, aSzIns);
128178130660
}
128179130661
if( p->bHasDocsize ){
128180130662
fts3InsertDocsize(&rc, p, aSzIns);
128181130663
}
128182130664
nChng++;
128183130665
}
128184130666
128185
- if( p->bHasStat ){
130667
+ if( p->bFts4 ){
128186130668
fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
128187130669
}
128188130670
128189130671
update_out:
128190130672
sqlite3_free(aSzIns);
@@ -128749,10 +131231,11 @@
128749131231
** is no way for fts3BestSnippet() to know whether or not the document
128750131232
** actually contains terms that follow the final highlighted term.
128751131233
*/
128752131234
static int fts3SnippetShift(
128753131235
Fts3Table *pTab, /* FTS3 table snippet comes from */
131236
+ int iLangid, /* Language id to use in tokenizing */
128754131237
int nSnippet, /* Number of tokens desired for snippet */
128755131238
const char *zDoc, /* Document text to extract snippet from */
128756131239
int nDoc, /* Size of buffer zDoc in bytes */
128757131240
int *piPos, /* IN/OUT: First token of snippet */
128758131241
u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
@@ -128784,15 +131267,14 @@
128784131267
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
128785131268
128786131269
/* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
128787131270
** or more tokens in zDoc/nDoc.
128788131271
*/
128789
- rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
131272
+ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC);
128790131273
if( rc!=SQLITE_OK ){
128791131274
return rc;
128792131275
}
128793
- pC->pTokenizer = pTab->pTokenizer;
128794131276
while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
128795131277
const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
128796131278
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
128797131279
}
128798131280
pMod->xClose(pC);
@@ -128848,15 +131330,14 @@
128848131330
}
128849131331
nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
128850131332
128851131333
/* Open a token cursor on the document. */
128852131334
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
128853
- rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
131335
+ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC);
128854131336
if( rc!=SQLITE_OK ){
128855131337
return rc;
128856131338
}
128857
- pC->pTokenizer = pTab->pTokenizer;
128858131339
128859131340
while( rc==SQLITE_OK ){
128860131341
int iBegin; /* Offset in zDoc of start of token */
128861131342
int iFin; /* Offset in zDoc of end of token */
128862131343
int isHighlight; /* True for highlighted terms */
@@ -128874,11 +131355,13 @@
128874131355
}
128875131356
if( iCurrent<iPos ){ continue; }
128876131357
128877131358
if( !isShiftDone ){
128878131359
int n = nDoc - iBegin;
128879
- rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask);
131360
+ rc = fts3SnippetShift(
131361
+ pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask
131362
+ );
128880131363
isShiftDone = 1;
128881131364
128882131365
/* Now that the shift has been done, check if the initial "..." are
128883131366
** required. They are required if (a) this is not the first fragment,
128884131367
** or (b) this fragment does not begin at position 0 of its column.
@@ -129010,12 +131493,12 @@
129010131493
char cArg,
129011131494
char **pzErr
129012131495
){
129013131496
if( (cArg==FTS3_MATCHINFO_NPHRASE)
129014131497
|| (cArg==FTS3_MATCHINFO_NCOL)
129015
- || (cArg==FTS3_MATCHINFO_NDOC && pTab->bHasStat)
129016
- || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bHasStat)
131498
+ || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4)
131499
+ || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4)
129017131500
|| (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
129018131501
|| (cArg==FTS3_MATCHINFO_LCS)
129019131502
|| (cArg==FTS3_MATCHINFO_HITS)
129020131503
){
129021131504
return SQLITE_OK;
@@ -129607,13 +132090,14 @@
129607132090
rc = SQLITE_NOMEM;
129608132091
goto offsets_out;
129609132092
}
129610132093
129611132094
/* Initialize a tokenizer iterator to iterate through column iCol. */
129612
- rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
132095
+ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid,
132096
+ zDoc, nDoc, &pC
132097
+ );
129613132098
if( rc!=SQLITE_OK ) goto offsets_out;
129614
- pC->pTokenizer = pTab->pTokenizer;
129615132099
129616132100
rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
129617132101
while( rc==SQLITE_OK ){
129618132102
int i; /* Used to loop through terms */
129619132103
int iMinPos = 0x7FFFFFFF; /* Position of next token */
@@ -132774,12 +135258,12 @@
132774135258
}
132775135259
132776135260
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
132777135261
132778135262
/* Allocate the sqlite3_vtab structure */
132779
- nDb = strlen(argv[1]);
132780
- nName = strlen(argv[2]);
135263
+ nDb = (int)strlen(argv[1]);
135264
+ nName = (int)strlen(argv[2]);
132781135265
pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
132782135266
if( !pRtree ){
132783135267
return SQLITE_NOMEM;
132784135268
}
132785135269
memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
@@ -132870,14 +135354,14 @@
132870135354
RtreeCell cell;
132871135355
int jj;
132872135356
132873135357
nodeGetCell(&tree, &node, ii, &cell);
132874135358
sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
132875
- nCell = strlen(zCell);
135359
+ nCell = (int)strlen(zCell);
132876135360
for(jj=0; jj<tree.nDim*2; jj++){
132877135361
sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);
132878
- nCell = strlen(zCell);
135362
+ nCell = (int)strlen(zCell);
132879135363
}
132880135364
132881135365
if( zText ){
132882135366
char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
132883135367
sqlite3_free(zText);
@@ -133616,11 +136100,14 @@
133616136100
int iInput = 0;
133617136101
int iOut = 0;
133618136102
133619136103
*ppCursor = 0;
133620136104
133621
- if( nInput<0 ){
136105
+ if( zInput==0 ){
136106
+ nInput = 0;
136107
+ zInput = "";
136108
+ }else if( nInput<0 ){
133622136109
nInput = strlen(zInput);
133623136110
}
133624136111
nChar = nInput+1;
133625136112
pCsr = (IcuCursor *)sqlite3_malloc(
133626136113
sizeof(IcuCursor) + /* IcuCursor */
133627136114
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.11. 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.
@@ -655,13 +655,13 @@
655 **
656 ** See also: [sqlite3_libversion()],
657 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
658 ** [sqlite_version()] and [sqlite_source_id()].
659 */
660 #define SQLITE_VERSION "3.7.11"
661 #define SQLITE_VERSION_NUMBER 3007011
662 #define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130"
663
664 /*
665 ** CAPI3REF: Run-Time Library Version Numbers
666 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
667 **
@@ -1009,10 +1009,11 @@
1009 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1010 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1011 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1012 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
1013 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
 
1014
1015 /*
1016 ** CAPI3REF: Flags For File Open Operations
1017 **
1018 ** These bit values are intended for use in the
@@ -1264,31 +1265,35 @@
1264 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
1265 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
1266 ** into an integer that the pArg argument points to. This capability
1267 ** is used during testing and only needs to be supported when SQLITE_TEST
1268 ** is defined.
1269 **
 
1270 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
1271 ** layer a hint of how large the database file will grow to be during the
1272 ** current transaction. This hint is not guaranteed to be accurate but it
1273 ** is often close. The underlying VFS might choose to preallocate database
1274 ** file space based on this hint in order to help writes to the database
1275 ** file run faster.
1276 **
 
1277 ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
1278 ** extends and truncates the database file in chunks of a size specified
1279 ** by the user. The fourth argument to [sqlite3_file_control()] should
1280 ** point to an integer (type int) containing the new chunk-size to use
1281 ** for the nominated database. Allocating database file space in large
1282 ** chunks (say 1MB at a time), may reduce file-system fragmentation and
1283 ** improve performance on some systems.
1284 **
 
1285 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
1286 ** to the [sqlite3_file] object associated with a particular database
1287 ** connection. See the [sqlite3_file_control()] documentation for
1288 ** additional information.
1289 **
 
1290 ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
1291 ** SQLite and sent to all VFSes in place of a call to the xSync method
1292 ** when the database connection has [PRAGMA synchronous] set to OFF.)^
1293 ** Some specialized VFSes need this signal in order to operate correctly
1294 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
@@ -1295,10 +1300,11 @@
1295 ** VFSes do not need this signal and should silently ignore this opcode.
1296 ** Applications should not call [sqlite3_file_control()] with this
1297 ** opcode as doing so may disrupt the operation of the specialized VFSes
1298 ** that do require it.
1299 **
 
1300 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
1301 ** retry counts and intervals for certain disk I/O operations for the
1302 ** windows [VFS] in order to provide robustness in the presence of
1303 ** anti-virus programs. By default, the windows VFS will retry file read,
1304 ** file write, and file delete operations up to 10 times, with a delay
@@ -1311,10 +1317,11 @@
1311 ** integer is the delay. If either integer is negative, then the setting
1312 ** is not changed but instead the prior value of that setting is written
1313 ** into the array entry, allowing the current retry settings to be
1314 ** interrogated. The zDbName parameter is ignored.
1315 **
 
1316 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
1317 ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
1318 ** write ahead log and shared memory files used for transaction control
1319 ** are automatically deleted when the latest connection to the database
1320 ** closes. Setting persistent WAL mode causes those files to persist after
@@ -1325,24 +1332,27 @@
1325 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
1326 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
1327 ** WAL mode. If the integer is -1, then it is overwritten with the current
1328 ** WAL persistence setting.
1329 **
 
1330 ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
1331 ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
1332 ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
1333 ** xDeviceCharacteristics methods. The fourth parameter to
1334 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
1335 ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
1336 ** mode. If the integer is -1, then it is overwritten with the current
1337 ** zero-damage mode setting.
1338 **
 
1339 ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
1340 ** a write transaction to indicate that, unless it is rolled back for some
1341 ** reason, the entire database file will be overwritten by the current
1342 ** transaction. This is used by VACUUM operations.
1343 **
 
1344 ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
1345 ** all [VFSes] in the VFS stack. The names are of all VFS shims and the
1346 ** final bottom-level VFS are written into memory obtained from
1347 ** [sqlite3_malloc()] and the result is stored in the char* variable
1348 ** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -1349,10 +1359,34 @@
1349 ** The caller is responsible for freeing the memory when done. As with
1350 ** all file-control actions, there is no guarantee that this will actually
1351 ** do anything. Callers should initialize the char* variable to a NULL
1352 ** pointer in case this file-control is not implemented. This file-control
1353 ** is intended for diagnostic use only.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1354 */
1355 #define SQLITE_FCNTL_LOCKSTATE 1
1356 #define SQLITE_GET_LOCKPROXYFILE 2
1357 #define SQLITE_SET_LOCKPROXYFILE 3
1358 #define SQLITE_LAST_ERRNO 4
@@ -1363,10 +1397,11 @@
1363 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
1364 #define SQLITE_FCNTL_PERSIST_WAL 10
1365 #define SQLITE_FCNTL_OVERWRITE 11
1366 #define SQLITE_FCNTL_VFSNAME 12
1367 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
 
1368
1369 /*
1370 ** CAPI3REF: Mutex Handle
1371 **
1372 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -5012,10 +5047,19 @@
5012 ** will be an absolute pathname, even if the filename used
5013 ** to open the database originally was a URI or relative pathname.
5014 */
5015 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
5016
 
 
 
 
 
 
 
 
 
5017 /*
5018 ** CAPI3REF: Find the next prepared statement
5019 **
5020 ** ^This interface returns a pointer to the next [prepared statement] after
5021 ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -6510,10 +6554,21 @@
6510 ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
6511 ** <dd>This parameter returns the number of pager cache misses that have
6512 ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
6513 ** is always 0.
6514 ** </dd>
 
 
 
 
 
 
 
 
 
 
 
6515 ** </dl>
6516 */
6517 #define SQLITE_DBSTATUS_LOOKASIDE_USED 0
6518 #define SQLITE_DBSTATUS_CACHE_USED 1
6519 #define SQLITE_DBSTATUS_SCHEMA_USED 2
@@ -6521,11 +6576,12 @@
6521 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
6522 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
6523 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
6524 #define SQLITE_DBSTATUS_CACHE_HIT 7
6525 #define SQLITE_DBSTATUS_CACHE_MISS 8
6526 #define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */
 
6527
6528
6529 /*
6530 ** CAPI3REF: Prepared Statement Status
6531 **
@@ -7137,15 +7193,16 @@
7137
7138
7139 /*
7140 ** CAPI3REF: String Comparison
7141 **
7142 ** ^The [sqlite3_strnicmp()] API allows applications and extensions to
7143 ** compare the contents of two buffers containing UTF-8 strings in a
7144 ** case-independent fashion, using the same definition of case independence
7145 ** that SQLite uses internally when comparing identifiers.
7146 */
 
7147 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
7148
7149 /*
7150 ** CAPI3REF: Error Logging Interface
7151 **
@@ -8204,11 +8261,11 @@
8204 SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
8205 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
8206 SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
8207 SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
8208 SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
8209 SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*);
8210 SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
8211 SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
8212 SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
8213 SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
8214 SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
@@ -8944,10 +9001,13 @@
8944 SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
8945 SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
8946 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
8947 SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
8948 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
 
 
 
8949
8950 /* Functions used to query pager state and configuration. */
8951 SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
8952 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
8953 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
@@ -9871,18 +9931,22 @@
9871 void (*xDestroy)(void *);
9872 void *pUserData;
9873 };
9874
9875 /*
9876 ** Possible values for FuncDef.flags
 
 
9877 */
9878 #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
9879 #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
9880 #define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
9881 #define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
9882 #define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */
9883 #define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */
 
 
9884
9885 /*
9886 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
9887 ** used to create the initializers for the FuncDef structures.
9888 **
@@ -9906,11 +9970,14 @@
9906 ** available as the function user-data (sqlite3_user_data()). The
9907 ** FuncDef.flags variable is set to the value passed as the flags
9908 ** parameter.
9909 */
9910 #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
9911 {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
 
 
 
9912 SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
9913 #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
9914 {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
9915 pArg, 0, xFunc, 0, 0, #zName, 0, 0}
9916 #define LIKEFUNC(zName, nArg, arg, flags) \
@@ -10136,11 +10203,11 @@
10136 u8 tabFlags; /* Mask of TF_* values */
10137 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10138 FKey *pFKey; /* Linked list of all foreign keys in this table */
10139 char *zColAff; /* String defining the affinity of each column */
10140 #ifndef SQLITE_OMIT_CHECK
10141 Expr *pCheck; /* The AND of all CHECK constraints */
10142 #endif
10143 #ifndef SQLITE_OMIT_ALTERTABLE
10144 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10145 #endif
10146 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -10529,10 +10596,11 @@
10529 ** TK_VARIABLE: variable number (always >= 1). */
10530 i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
10531 i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
10532 u8 flags2; /* Second set of flags. EP2_... */
10533 u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
 
10534 AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
10535 Table *pTab; /* Table for TK_COLUMN expressions. */
10536 #if SQLITE_MAX_EXPR_DEPTH>0
10537 int nHeight; /* Height of the tree headed by this node */
10538 #endif
@@ -10551,11 +10619,11 @@
10551 #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
10552 #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
10553 #define EP_FixedDest 0x0200 /* Result needed in a specific register */
10554 #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
10555 #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
10556 #define EP_Hint 0x1000 /* Optimizer hint. Not required for correctness */
10557 #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
10558 #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
10559 #define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
10560
10561 /*
@@ -11070,10 +11138,11 @@
11070 int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
11071 int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
11072 int regRowid; /* Register holding rowid of CREATE TABLE entry */
11073 int regRoot; /* Register holding root page number for new objects */
11074 int nMaxArg; /* Max args passed to user function by sub-program */
 
11075 #ifndef SQLITE_OMIT_SHARED_CACHE
11076 int nTableLock; /* Number of locks in aTableLock */
11077 TableLock *aTableLock; /* Required table locks for shared-cache mode */
11078 #endif
11079 AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
@@ -11138,18 +11207,20 @@
11138 const char *zAuthContext; /* Put saved Parse.zAuthContext here */
11139 Parse *pParse; /* The Parse structure */
11140 };
11141
11142 /*
11143 ** Bitfield flags for P5 value in OP_Insert and OP_Delete
11144 */
11145 #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
11146 #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
11147 #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
11148 #define OPFLAG_APPEND 0x08 /* This is likely to be an append */
11149 #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
11150 #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
 
 
11151
11152 /*
11153 * Each trigger present in the database schema is stored as an instance of
11154 * struct Trigger.
11155 *
@@ -11415,11 +11486,11 @@
11415 #endif
11416
11417 /*
11418 ** Internal function prototypes
11419 */
11420 SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
11421 SQLITE_PRIVATE int sqlite3Strlen30(const char*);
11422 #define sqlite3StrNICmp sqlite3_strnicmp
11423
11424 SQLITE_PRIVATE int sqlite3MallocInit(void);
11425 SQLITE_PRIVATE void sqlite3MallocEnd(void);
@@ -11563,10 +11634,11 @@
11563 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
11564 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
11565 SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
11566 SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
11567 sqlite3_vfs**,char**,char **);
 
11568 SQLITE_PRIVATE int sqlite3CodeOnce(Parse *);
11569
11570 SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
11571 SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
11572 SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
@@ -11628,11 +11700,11 @@
11628 #endif
11629 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
11630 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11631 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
11632 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11633 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
11634 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
11635 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
11636 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
11637 SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
11638 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
@@ -11662,11 +11734,11 @@
11662 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
11663 SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
11664 SQLITE_PRIVATE void sqlite3PrngSaveState(void);
11665 SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
11666 SQLITE_PRIVATE void sqlite3PrngResetState(void);
11667 SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*);
11668 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
11669 SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
11670 SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
11671 SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
11672 SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
@@ -13460,14 +13532,16 @@
13460 ** Set *pCurrent to the total cache hits or misses encountered by all
13461 ** pagers the database handle is connected to. *pHighwater is always set
13462 ** to zero.
13463 */
13464 case SQLITE_DBSTATUS_CACHE_HIT:
13465 case SQLITE_DBSTATUS_CACHE_MISS: {
 
13466 int i;
13467 int nRet = 0;
13468 assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
 
13469
13470 for(i=0; i<db->nDb; i++){
13471 if( db->aDb[i].pBt ){
13472 Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
13473 sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
@@ -21210,17 +21284,17 @@
21210
21211 /*
21212 ** Some systems have stricmp(). Others have strcasecmp(). Because
21213 ** there is no consistency, we will define our own.
21214 **
21215 ** IMPLEMENTATION-OF: R-20522-24639 The sqlite3_strnicmp() API allows
21216 ** applications and extensions to compare the contents of two buffers
21217 ** containing UTF-8 strings in a case-independent fashion, using the same
21218 ** definition of case independence that SQLite uses internally when
21219 ** comparing identifiers.
21220 */
21221 SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){
21222 register unsigned char *a, *b;
21223 a = (unsigned char *)zLeft;
21224 b = (unsigned char *)zRight;
21225 while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
21226 return UpperToLower[*a] - UpperToLower[*b];
@@ -25494,11 +25568,11 @@
25494 ** recover the hot journals.
25495 */
25496 static int robust_open(const char *z, int f, mode_t m){
25497 int rc;
25498 mode_t m2;
25499 mode_t origM;
25500 if( m==0 ){
25501 m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
25502 }else{
25503 m2 = m;
25504 origM = osUmask(0);
@@ -33678,10 +33752,13 @@
33678 }
33679 sqlite3_free(pFile->zDeleteOnClose);
33680 }
33681 #endif
33682 OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
 
 
 
33683 OpenCounter(-1);
33684 return rc ? SQLITE_OK
33685 : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
33686 "winClose", pFile->zPath);
33687 }
@@ -33695,22 +33772,33 @@
33695 sqlite3_file *id, /* File to read from */
33696 void *pBuf, /* Write content into this buffer */
33697 int amt, /* Number of bytes to read */
33698 sqlite3_int64 offset /* Begin reading at this offset */
33699 ){
 
 
 
33700 winFile *pFile = (winFile*)id; /* file handle */
33701 DWORD nRead; /* Number of bytes actually read from file */
33702 int nRetry = 0; /* Number of retrys */
33703
33704 assert( id!=0 );
33705 SimulateIOError(return SQLITE_IOERR_READ);
33706 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
33707
 
33708 if( seekWinFile(pFile, offset) ){
33709 return SQLITE_FULL;
33710 }
33711 while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
 
 
 
 
 
 
 
33712 DWORD lastErrno;
33713 if( retryIoerr(&nRetry, &lastErrno) ) continue;
33714 pFile->lastErrno = lastErrno;
33715 return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
33716 "winRead", pFile->zPath);
@@ -33733,11 +33821,11 @@
33733 sqlite3_file *id, /* File to write into */
33734 const void *pBuf, /* The bytes to be written */
33735 int amt, /* Number of bytes to write */
33736 sqlite3_int64 offset /* Offset into the file to begin writing at */
33737 ){
33738 int rc; /* True if error has occured, else false */
33739 winFile *pFile = (winFile*)id; /* File handle */
33740 int nRetry = 0; /* Number of retries */
33741
33742 assert( amt>0 );
33743 assert( pFile );
@@ -33744,23 +33832,48 @@
33744 SimulateIOError(return SQLITE_IOERR_WRITE);
33745 SimulateDiskfullError(return SQLITE_FULL);
33746
33747 OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
33748
 
33749 rc = seekWinFile(pFile, offset);
33750 if( rc==0 ){
 
 
 
 
 
 
33751 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
33752 int nRem = amt; /* Number of bytes yet to be written */
33753 DWORD nWrite; /* Bytes written by each WriteFile() call */
33754 DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
 
 
 
 
 
 
33755
33756 while( nRem>0 ){
 
33757 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
 
 
 
33758 if( retryIoerr(&nRetry, &lastErrno) ) continue;
33759 break;
33760 }
33761 if( nWrite<=0 ) break;
 
 
 
 
 
 
 
 
33762 aRem += nWrite;
33763 nRem -= nWrite;
33764 }
33765 if( nRem>0 ){
33766 pFile->lastErrno = lastErrno;
@@ -38302,10 +38415,11 @@
38302 # define sqlite3WalFrames(u,v,w,x,y,z) 0
38303 # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
38304 # define sqlite3WalCallback(z) 0
38305 # define sqlite3WalExclusiveMode(y,z) 0
38306 # define sqlite3WalHeapMemory(z) 0
 
38307 #else
38308
38309 #define WAL_SAVEPOINT_NDATA 4
38310
38311 /* Connection to a write-ahead log (WAL) file.
@@ -38382,10 +38496,17 @@
38382 /* Return true if the argument is non-NULL and the WAL module is using
38383 ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
38384 ** WAL module is using shared-memory, return false.
38385 */
38386 SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
 
 
 
 
 
 
 
38387
38388 #endif /* ifndef SQLITE_OMIT_WAL */
38389 #endif /* _WAL_H_ */
38390
38391 /************** End of wal.h *************************************************/
@@ -39037,13 +39158,13 @@
39037 i64 journalSizeLimit; /* Size limit for persistent journal files */
39038 char *zFilename; /* Name of the database file */
39039 char *zJournal; /* Name of the journal file */
39040 int (*xBusyHandler)(void*); /* Function to call when busy */
39041 void *pBusyHandlerArg; /* Context argument for xBusyHandler */
39042 int nHit, nMiss; /* Total cache hits and misses */
39043 #ifdef SQLITE_TEST
39044 int nRead, nWrite; /* Database pages read/written */
39045 #endif
39046 void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
39047 #ifdef SQLITE_HAS_CODEC
39048 void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
39049 void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
@@ -39056,10 +39177,19 @@
39056 Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
39057 char *zWal; /* File name for write-ahead log */
39058 #endif
39059 };
39060
 
 
 
 
 
 
 
 
 
39061 /*
39062 ** The following global variables hold counters used for
39063 ** testing purposes only. These variables do not exist in
39064 ** a non-testing build. These variables are not thread-safe.
39065 */
@@ -41338,10 +41468,11 @@
41338 PgHdr *pList, /* List of frames to log */
41339 Pgno nTruncate, /* Database size after this commit */
41340 int isCommit /* True if this is a commit */
41341 ){
41342 int rc; /* Return code */
 
41343 #if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
41344 PgHdr *p; /* For looping over pages */
41345 #endif
41346
41347 assert( pPager->pWal );
@@ -41351,22 +41482,30 @@
41351 for(p=pList; p && p->pDirty; p=p->pDirty){
41352 assert( p->pgno < p->pDirty->pgno );
41353 }
41354 #endif
41355
 
41356 if( isCommit ){
41357 /* If a WAL transaction is being committed, there is no point in writing
41358 ** any pages with page numbers greater than nTruncate into the WAL file.
41359 ** They will never be read by any client. So remove them from the pDirty
41360 ** list here. */
41361 PgHdr *p;
41362 PgHdr **ppNext = &pList;
 
41363 for(p=pList; (*ppNext = p); p=p->pDirty){
41364 if( p->pgno<=nTruncate ) ppNext = &p->pDirty;
 
 
 
41365 }
41366 assert( pList );
 
 
41367 }
 
41368
41369 if( pList->pgno==1 ) pager_write_changecounter(pList);
41370 rc = sqlite3WalFrames(pPager->pWal,
41371 pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
41372 );
@@ -42430,19 +42569,19 @@
42430 memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
42431 }
42432 if( pgno>pPager->dbFileSize ){
42433 pPager->dbFileSize = pgno;
42434 }
 
42435
42436 /* Update any backup objects copying the contents of this pager. */
42437 sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
42438
42439 PAGERTRACE(("STORE %d page %d hash(%08x)\n",
42440 PAGERID(pPager), pgno, pager_pagehash(pList)));
42441 IOTRACE(("PGOUT %p %d\n", pPager, pgno));
42442 PAGER_INCR(sqlite3_pager_writedb_count);
42443 PAGER_INCR(pPager->nWrite);
42444 }else{
42445 PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
42446 }
42447 pager_set_pagehash(pList);
42448 pList = pList->pDirty;
@@ -43396,11 +43535,11 @@
43396
43397 if( (*ppPage)->pPager && !noContent ){
43398 /* In this case the pcache already contains an initialized copy of
43399 ** the page. Return without further ado. */
43400 assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
43401 pPager->nHit++;
43402 return SQLITE_OK;
43403
43404 }else{
43405 /* The pager cache has created a new page. Its content needs to
43406 ** be initialized. */
@@ -43438,11 +43577,11 @@
43438 }
43439 memset(pPg->pData, 0, pPager->pageSize);
43440 IOTRACE(("ZERO %p %d\n", pPager, pgno));
43441 }else{
43442 assert( pPg->pPager==pPager );
43443 pPager->nMiss++;
43444 rc = readDbPage(pPg);
43445 if( rc!=SQLITE_OK ){
43446 goto pager_acquire_err;
43447 }
43448 }
@@ -44023,10 +44162,11 @@
44023 const void *zBuf;
44024 assert( pPager->dbFileSize>0 );
44025 CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
44026 if( rc==SQLITE_OK ){
44027 rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
 
44028 }
44029 if( rc==SQLITE_OK ){
44030 pPager->changeCountDone = 1;
44031 }
44032 }else{
@@ -44466,15 +44606,15 @@
44466 a[1] = sqlite3PcachePagecount(pPager->pPCache);
44467 a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
44468 a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
44469 a[4] = pPager->eState;
44470 a[5] = pPager->errCode;
44471 a[6] = pPager->nHit;
44472 a[7] = pPager->nMiss;
44473 a[8] = 0; /* Used to be pPager->nOvfl */
44474 a[9] = pPager->nRead;
44475 a[10] = pPager->nWrite;
44476 return a;
44477 }
44478 #endif
44479
44480 /*
@@ -44483,24 +44623,23 @@
44483 ** current cache hit or miss count, according to the value of eStat. If the
44484 ** reset parameter is non-zero, the cache hit or miss count is zeroed before
44485 ** returning.
44486 */
44487 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
44488 int *piStat;
44489
44490 assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
44491 || eStat==SQLITE_DBSTATUS_CACHE_MISS
 
44492 );
44493 if( eStat==SQLITE_DBSTATUS_CACHE_HIT ){
44494 piStat = &pPager->nHit;
44495 }else{
44496 piStat = &pPager->nMiss;
44497 }
44498
44499 *pnVal += *piStat;
 
 
 
 
44500 if( reset ){
44501 *piStat = 0;
44502 }
44503 }
44504
44505 /*
44506 ** Return true if this is an in-memory pager.
@@ -45237,10 +45376,24 @@
45237 pPager->pWal = 0;
45238 }
45239 }
45240 return rc;
45241 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45242
45243 #ifdef SQLITE_HAS_CODEC
45244 /*
45245 ** This function is called by the wal module when writing page content
45246 ** into the log file.
@@ -47657,11 +47810,11 @@
47657 testcase( sz<=32768 );
47658 testcase( sz>=65536 );
47659 iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
47660 *pInWal = 1;
47661 /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
47662 return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
47663 }
47664
47665 *pInWal = 0;
47666 return SQLITE_OK;
47667 }
@@ -48327,10 +48480,22 @@
48327 ** WAL module is using shared-memory, return false.
48328 */
48329 SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
48330 return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
48331 }
 
 
 
 
 
 
 
 
 
 
 
 
48332
48333 #endif /* #ifndef SQLITE_OMIT_WAL */
48334
48335 /************** End of wal.c *************************************************/
48336 /************** Begin file btmutex.c *****************************************/
@@ -51320,11 +51485,11 @@
51320
51321 /* Rollback any active transaction and free the handle structure.
51322 ** The call to sqlite3BtreeRollback() drops any table-locks held by
51323 ** this handle.
51324 */
51325 sqlite3BtreeRollback(p);
51326 sqlite3BtreeLeave(p);
51327
51328 /* If there are still other outstanding references to the shared-btree
51329 ** structure, return now. The remainder of this procedure cleans
51330 ** up the shared-btree.
@@ -52558,10 +52723,11 @@
52558 ** save the state of the cursor. The cursor must be
52559 ** invalidated.
52560 */
52561 SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
52562 BtCursor *p;
 
52563 sqlite3BtreeEnter(pBtree);
52564 for(p=pBtree->pBt->pCursor; p; p=p->pNext){
52565 int i;
52566 sqlite3BtreeClearCursor(p);
52567 p->eState = CURSOR_FAULT;
@@ -52581,29 +52747,24 @@
52581 ** in an error.
52582 **
52583 ** This will release the write lock on the database file. If there
52584 ** are no active cursors, it also releases the read lock.
52585 */
52586 SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){
52587 int rc;
52588 BtShared *pBt = p->pBt;
52589 MemPage *pPage1;
52590
52591 sqlite3BtreeEnter(p);
52592 rc = saveAllCursors(pBt, 0, 0);
52593 #ifndef SQLITE_OMIT_SHARED_CACHE
52594 if( rc!=SQLITE_OK ){
52595 /* This is a horrible situation. An IO or malloc() error occurred whilst
52596 ** trying to save cursor positions. If this is an automatic rollback (as
52597 ** the result of a constraint, malloc() failure or IO error) then
52598 ** the cache may be internally inconsistent (not contain valid trees) so
52599 ** we cannot simply return the error to the caller. Instead, abort
52600 ** all queries that may be using any of the cursors that failed to save.
52601 */
52602 sqlite3BtreeTripAllCursors(p, rc);
52603 }
52604 #endif
52605 btreeIntegrity(p);
52606
52607 if( p->inTrans==TRANS_WRITE ){
52608 int rc2;
52609
@@ -56072,17 +56233,10 @@
56072 ** keys with no associated data. If the cursor was opened expecting an
56073 ** intkey table, the caller should be inserting integer keys with a
56074 ** blob of associated data. */
56075 assert( (pKey==0)==(pCur->pKeyInfo==0) );
56076
56077 /* If this is an insert into a table b-tree, invalidate any incrblob
56078 ** cursors open on the row being replaced (assuming this is a replace
56079 ** operation - if it is not, the following is a no-op). */
56080 if( pCur->pKeyInfo==0 ){
56081 invalidateIncrblobCursors(p, nKey, 0);
56082 }
56083
56084 /* Save the positions of any other cursors open on this table.
56085 **
56086 ** In some cases, the call to btreeMoveto() below is a no-op. For
56087 ** example, when inserting data into a table with auto-generated integer
56088 ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
@@ -56092,10 +56246,18 @@
56092 ** doing any work. To avoid thwarting these optimizations, it is important
56093 ** not to clear the cursor here.
56094 */
56095 rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
56096 if( rc ) return rc;
 
 
 
 
 
 
 
 
56097 if( !loc ){
56098 rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
56099 if( rc ) return rc;
56100 }
56101 assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
@@ -56202,16 +56364,10 @@
56202 || NEVER(pCur->eState!=CURSOR_VALID)
56203 ){
56204 return SQLITE_ERROR; /* Something has gone awry. */
56205 }
56206
56207 /* If this is a delete operation to remove a row from a table b-tree,
56208 ** invalidate any incrblob cursors open on the row being deleted. */
56209 if( pCur->pKeyInfo==0 ){
56210 invalidateIncrblobCursors(p, pCur->info.nKey, 0);
56211 }
56212
56213 iCellDepth = pCur->iPage;
56214 iCellIdx = pCur->aiIdx[iCellDepth];
56215 pPage = pCur->apPage[iCellDepth];
56216 pCell = findCell(pPage, iCellIdx);
56217
@@ -56233,10 +56389,17 @@
56233 ** deleted writable. Then free any overflow pages associated with the
56234 ** entry and finally remove the cell itself from within the page.
56235 */
56236 rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
56237 if( rc ) return rc;
 
 
 
 
 
 
 
56238 rc = sqlite3PagerWrite(pPage->pDbPage);
56239 if( rc ) return rc;
56240 rc = clearCell(pPage, pCell);
56241 dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc);
56242 if( rc ) return rc;
@@ -56514,17 +56677,17 @@
56514 int rc;
56515 BtShared *pBt = p->pBt;
56516 sqlite3BtreeEnter(p);
56517 assert( p->inTrans==TRANS_WRITE );
56518
56519 /* Invalidate all incrblob cursors open on table iTable (assuming iTable
56520 ** is the root of a table b-tree - if it is not, the following call is
56521 ** a no-op). */
56522 invalidateIncrblobCursors(p, 0, 1);
56523
56524 rc = saveAllCursors(pBt, (Pgno)iTable, 0);
 
56525 if( SQLITE_OK==rc ){
 
 
 
 
56526 rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
56527 }
56528 sqlite3BtreeLeave(p);
56529 return rc;
56530 }
@@ -58121,11 +58284,11 @@
58121 }
58122 *pp = p->pNext;
58123 }
58124
58125 /* If a transaction is still open on the Btree, roll it back. */
58126 sqlite3BtreeRollback(p->pDest);
58127
58128 /* Set the error code of the destination database handle. */
58129 rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
58130 sqlite3Error(p->pDestDb, rc, 0);
58131
@@ -58332,14 +58495,14 @@
58332
58333 /*
58334 ** Make sure pMem->z points to a writable allocation of at least
58335 ** n bytes.
58336 **
58337 ** If the memory cell currently contains string or blob data
58338 ** and the third argument passed to this function is true, the
58339 ** current content of the cell is preserved. Otherwise, it may
58340 ** be discarded.
58341 **
58342 ** This function sets the MEM_Dyn flag and clears any xDel callback.
58343 ** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
58344 ** not set, Mem.n is zeroed.
58345 */
@@ -58349,10 +58512,14 @@
58349 (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
58350 ((pMem->flags&MEM_Ephem) ? 1 : 0) +
58351 ((pMem->flags&MEM_Static) ? 1 : 0)
58352 );
58353 assert( (pMem->flags&MEM_RowSet)==0 );
 
 
 
 
58354
58355 if( n<32 ) n = 32;
58356 if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
58357 if( preserve && pMem->z==pMem->zMalloc ){
58358 pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
@@ -60668,11 +60835,11 @@
60668 int nByte = (nSub+1)*sizeof(SubProgram*);
60669 int j;
60670 for(j=0; j<nSub; j++){
60671 if( apSub[j]==pOp->p4.pProgram ) break;
60672 }
60673 if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){
60674 apSub = (SubProgram **)pSub->z;
60675 apSub[nSub++] = pOp->p4.pProgram;
60676 pSub->flags |= MEM_Blob;
60677 pSub->n = nSub*sizeof(SubProgram*);
60678 }
@@ -61431,36 +61598,10 @@
61431 }
61432 #else
61433 #define checkActiveVdbeCnt(x)
61434 #endif
61435
61436 /*
61437 ** For every Btree that in database connection db which
61438 ** has been modified, "trip" or invalidate each cursor in
61439 ** that Btree might have been modified so that the cursor
61440 ** can never be used again. This happens when a rollback
61441 *** occurs. We have to trip all the other cursors, even
61442 ** cursor from other VMs in different database connections,
61443 ** so that none of them try to use the data at which they
61444 ** were pointing and which now may have been changed due
61445 ** to the rollback.
61446 **
61447 ** Remember that a rollback can delete tables complete and
61448 ** reorder rootpages. So it is not sufficient just to save
61449 ** the state of the cursor. We have to invalidate the cursor
61450 ** so that it is never used again.
61451 */
61452 static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){
61453 int i;
61454 for(i=0; i<db->nDb; i++){
61455 Btree *p = db->aDb[i].pBt;
61456 if( p && sqlite3BtreeIsInTrans(p) ){
61457 sqlite3BtreeTripAllCursors(p, SQLITE_ABORT);
61458 }
61459 }
61460 }
61461
61462 /*
61463 ** If the Vdbe passed as the first argument opened a statement-transaction,
61464 ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
61465 ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
61466 ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
@@ -61621,12 +61762,11 @@
61621 eStatementOp = SAVEPOINT_ROLLBACK;
61622 }else{
61623 /* We are forced to roll back the active transaction. Before doing
61624 ** so, abort any other statements this handle currently has active.
61625 */
61626 invalidateCursorsOnModifiedBtrees(db);
61627 sqlite3RollbackAll(db);
61628 sqlite3CloseSavepoints(db);
61629 db->autoCommit = 1;
61630 }
61631 }
61632 }
@@ -61664,27 +61804,26 @@
61664 if( rc==SQLITE_BUSY && p->readOnly ){
61665 sqlite3VdbeLeave(p);
61666 return SQLITE_BUSY;
61667 }else if( rc!=SQLITE_OK ){
61668 p->rc = rc;
61669 sqlite3RollbackAll(db);
61670 }else{
61671 db->nDeferredCons = 0;
61672 sqlite3CommitInternalChanges(db);
61673 }
61674 }else{
61675 sqlite3RollbackAll(db);
61676 }
61677 db->nStatement = 0;
61678 }else if( eStatementOp==0 ){
61679 if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
61680 eStatementOp = SAVEPOINT_RELEASE;
61681 }else if( p->errorAction==OE_Abort ){
61682 eStatementOp = SAVEPOINT_ROLLBACK;
61683 }else{
61684 invalidateCursorsOnModifiedBtrees(db);
61685 sqlite3RollbackAll(db);
61686 sqlite3CloseSavepoints(db);
61687 db->autoCommit = 1;
61688 }
61689 }
61690
@@ -61700,12 +61839,11 @@
61700 if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
61701 p->rc = rc;
61702 sqlite3DbFree(db, p->zErrMsg);
61703 p->zErrMsg = 0;
61704 }
61705 invalidateCursorsOnModifiedBtrees(db);
61706 sqlite3RollbackAll(db);
61707 sqlite3CloseSavepoints(db);
61708 db->autoCommit = 1;
61709 }
61710 }
61711
@@ -66946,10 +67084,15 @@
66946 **
66947 ** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
66948 ** then the cache of the cursor is reset prior to extracting the column.
66949 ** The first OP_Column against a pseudo-table after the value of the content
66950 ** register has changed should have this bit set.
 
 
 
 
 
66951 */
66952 case OP_Column: {
66953 #if 0 /* local variables moved into u.an */
66954 u32 payloadSize; /* Number of bytes in the record */
66955 i64 payloadSize64; /* Number of bytes in the record */
@@ -67088,11 +67231,11 @@
67088 u.an.pC->aRow = (u8*)u.an.zData;
67089 }else{
67090 u.an.pC->aRow = 0;
67091 }
67092 }
67093 /* The following assert is true in all cases accept when
67094 ** the database file has been corrupted externally.
67095 ** assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */
67096 u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset);
67097
67098 /* Make sure a corrupt database has not given us an oversize header.
@@ -67163,15 +67306,15 @@
67163 if( u.an.offset<u.an.szField ){ /* True if u.an.offset overflows */
67164 u.an.zIdx = &u.an.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
67165 break;
67166 }
67167 }else{
67168 /* If u.an.i is less that u.an.nField, then there are less fields in this
67169 ** record than SetNumColumns indicated there are columns in the
67170 ** table. Set the u.an.offset for any extra columns not present in
67171 ** the record to 0. This tells code below to store a NULL
67172 ** instead of deserializing a value from the record.
67173 */
67174 u.an.aOffset[u.an.i] = 0;
67175 }
67176 }
67177 sqlite3VdbeMemRelease(&u.an.sMem);
@@ -67197,21 +67340,36 @@
67197 ** a pointer to a Mem object.
67198 */
67199 if( u.an.aOffset[u.an.p2] ){
67200 assert( rc==SQLITE_OK );
67201 if( u.an.zRec ){
 
67202 VdbeMemRelease(u.an.pDest);
67203 sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
67204 }else{
67205 u.an.len = sqlite3VdbeSerialTypeLen(u.an.aType[u.an.p2]);
67206 sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
67207 rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex, &u.an.sMem);
67208 if( rc!=SQLITE_OK ){
67209 goto op_column_out;
67210 }
67211 u.an.zData = u.an.sMem.z;
67212 sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.aType[u.an.p2], u.an.pDest);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67213 }
67214 u.an.pDest->enc = encoding;
67215 }else{
67216 if( pOp->p4type==P4_MEM ){
67217 sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
@@ -67513,20 +67671,16 @@
67513 u.ar.iSavepoint++;
67514 }
67515 if( !u.ar.pSavepoint ){
67516 sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
67517 rc = SQLITE_ERROR;
67518 }else if(
67519 db->writeVdbeCnt>0 || (u.ar.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1)
67520 ){
67521 /* It is not possible to release (commit) a savepoint if there are
67522 ** active write statements. It is not possible to rollback a savepoint
67523 ** if there are any active statements at all.
67524 */
67525 sqlite3SetString(&p->zErrMsg, db,
67526 "cannot %s savepoint - SQL statements in progress",
67527 (u.ar.p1==SAVEPOINT_ROLLBACK ? "rollback": "release")
67528 );
67529 rc = SQLITE_BUSY;
67530 }else{
67531
67532 /* Determine whether or not this is a transaction savepoint. If so,
@@ -67547,10 +67701,15 @@
67547 }
67548 db->isTransactionSavepoint = 0;
67549 rc = p->rc;
67550 }else{
67551 u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
 
 
 
 
 
67552 for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
67553 rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
67554 if( rc!=SQLITE_OK ){
67555 goto abort_due_to_error;
67556 }
@@ -67617,29 +67776,32 @@
67617 u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit;
67618 assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 );
67619 assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 );
67620 assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
67621
 
67622 if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
67623 /* If this instruction implements a ROLLBACK and other VMs are
67624 ** still running, and a transaction is active, return an error indicating
67625 ** that the other VMs must complete first.
67626 */
67627 sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
67628 "SQL statements in progress");
67629 rc = SQLITE_BUSY;
67630 }else if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
 
 
67631 /* If this instruction implements a COMMIT and other VMs are writing
67632 ** return an error indicating that the other VMs must complete first.
67633 */
67634 sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
67635 "SQL statements in progress");
67636 rc = SQLITE_BUSY;
67637 }else if( u.as.desiredAutoCommit!=db->autoCommit ){
67638 if( u.as.iRollback ){
67639 assert( u.as.desiredAutoCommit==1 );
67640 sqlite3RollbackAll(db);
67641 db->autoCommit = 1;
67642 }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
67643 goto vdbe_return;
67644 }else{
67645 db->autoCommit = (u8)u.as.desiredAutoCommit;
@@ -68701,11 +68863,11 @@
68701 u.bg.v = 1; /* IMP: R-61914-48074 */
68702 }else{
68703 assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) );
68704 rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v);
68705 assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
68706 if( u.bg.v==MAX_ROWID ){
68707 u.bg.pC->useRandomRowid = 1;
68708 }else{
68709 u.bg.v++; /* IMP: R-29538-34987 */
68710 }
68711 }
@@ -74821,27 +74983,59 @@
74821 int op, /* Expression opcode */
74822 Expr *pLeft, /* Left operand */
74823 Expr *pRight, /* Right operand */
74824 const Token *pToken /* Argument token */
74825 ){
74826 Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
74827 sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
 
 
 
 
 
 
74828 if( p ) {
74829 sqlite3ExprCheckHeight(pParse, p->nHeight);
74830 }
74831 return p;
74832 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74833
74834 /*
74835 ** Join two expressions using an AND operator. If either expression is
74836 ** NULL, then just return the other expression.
 
 
 
 
74837 */
74838 SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
74839 if( pLeft==0 ){
74840 return pRight;
74841 }else if( pRight==0 ){
74842 return pLeft;
 
 
 
 
74843 }else{
74844 Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
74845 sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
74846 return pNew;
74847 }
@@ -76369,19 +76563,10 @@
76369 ** Actually, the way the column cache is currently used, we are guaranteed
76370 ** that the object will never already be in cache. Verify this guarantee.
76371 */
76372 #ifndef NDEBUG
76373 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
76374 #if 0 /* This code wold remove the entry from the cache if it existed */
76375 if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
76376 cacheEntryClear(pParse, p);
76377 p->iLevel = pParse->iCacheLevel;
76378 p->iReg = iReg;
76379 p->lru = pParse->iCacheCnt++;
76380 return;
76381 }
76382 #endif
76383 assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
76384 }
76385 #endif
76386
76387 /* Find an empty slot and replace it */
@@ -76512,11 +76697,12 @@
76512 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
76513 Parse *pParse, /* Parsing and code generating context */
76514 Table *pTab, /* Description of the table we are reading from */
76515 int iColumn, /* Index of the table column */
76516 int iTable, /* The cursor pointing to the table */
76517 int iReg /* Store results here */
 
76518 ){
76519 Vdbe *v = pParse->pVdbe;
76520 int i;
76521 struct yColCache *p;
76522
@@ -76527,11 +76713,15 @@
76527 return p->iReg;
76528 }
76529 }
76530 assert( v!=0 );
76531 sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
76532 sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
 
 
 
 
76533 return iReg;
76534 }
76535
76536 /*
76537 ** Clear all column cache entries.
@@ -76655,11 +76845,12 @@
76655 /* This only happens when coding check constraints */
76656 assert( pParse->ckBase>0 );
76657 inReg = pExpr->iColumn + pParse->ckBase;
76658 }else{
76659 inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
76660 pExpr->iColumn, pExpr->iTable, target);
 
76661 }
76662 break;
76663 }
76664 case TK_INTEGER: {
76665 codeInteger(pParse, pExpr, 0, target);
@@ -76932,10 +77123,29 @@
76932 }
76933
76934
76935 if( pFarg ){
76936 r1 = sqlite3GetTempRange(pParse, nFarg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76937 sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
76938 sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
76939 sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
76940 }else{
76941 r1 = 0;
@@ -80137,10 +80347,11 @@
80137 Index *pPrevIdx = 0; /* Previous index in the loop */
80138 int idx = 0; /* slot in pIdx->aSample[] for next sample */
80139 int eType; /* Datatype of a sample */
80140 IndexSample *pSample; /* A slot in pIdx->aSample[] */
80141
 
80142 if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
80143 return SQLITE_OK;
80144 }
80145
80146 zSql = sqlite3MPrintf(db,
@@ -80163,11 +80374,11 @@
80163 nSample = sqlite3_column_int(pStmt, 1);
80164 pIdx = sqlite3FindIndex(db, zIndex, zDb);
80165 if( pIdx==0 ) continue;
80166 assert( pIdx->nSample==0 );
80167 pIdx->nSample = nSample;
80168 pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) );
80169 pIdx->avgEq = pIdx->aiRowEst[1];
80170 if( pIdx->aSample==0 ){
80171 db->mallocFailed = 1;
80172 sqlite3_finalize(pStmt);
80173 return SQLITE_NOMEM;
@@ -80236,11 +80447,11 @@
80236 int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
80237 pSample->nByte = n;
80238 if( n < 1){
80239 pSample->u.z = 0;
80240 }else{
80241 pSample->u.z = sqlite3Malloc(n);
80242 if( pSample->u.z==0 ){
80243 db->mallocFailed = 1;
80244 sqlite3_finalize(pStmt);
80245 return SQLITE_NOMEM;
80246 }
@@ -80312,11 +80523,14 @@
80312
80313
80314 /* Load the statistics from the sqlite_stat3 table. */
80315 #ifdef SQLITE_ENABLE_STAT3
80316 if( rc==SQLITE_OK ){
 
 
80317 rc = loadStat3(db, sInfo.zDatabase);
 
80318 }
80319 #endif
80320
80321 if( rc==SQLITE_NOMEM ){
80322 db->mallocFailed = 1;
@@ -81675,11 +81889,11 @@
81675 sqliteDeleteColumnNames(db, pTable);
81676 sqlite3DbFree(db, pTable->zName);
81677 sqlite3DbFree(db, pTable->zColAff);
81678 sqlite3SelectDelete(db, pTable->pSelect);
81679 #ifndef SQLITE_OMIT_CHECK
81680 sqlite3ExprDelete(db, pTable->pCheck);
81681 #endif
81682 #ifndef SQLITE_OMIT_VIRTUALTABLE
81683 sqlite3VtabClear(db, pTable);
81684 #endif
81685 sqlite3DbFree(db, pTable);
@@ -82338,19 +82552,21 @@
82338 */
82339 SQLITE_PRIVATE void sqlite3AddCheckConstraint(
82340 Parse *pParse, /* Parsing context */
82341 Expr *pCheckExpr /* The check expression */
82342 ){
82343 sqlite3 *db = pParse->db;
82344 #ifndef SQLITE_OMIT_CHECK
82345 Table *pTab = pParse->pNewTable;
82346 if( pTab && !IN_DECLARE_VTAB ){
82347 pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr);
 
 
 
82348 }else
82349 #endif
82350 {
82351 sqlite3ExprDelete(db, pCheckExpr);
82352 }
82353 }
82354
82355 /*
82356 ** Set the collation function of the most recently parsed table column
@@ -82616,10 +82832,12 @@
82616 /* Resolve names in all CHECK constraint expressions.
82617 */
82618 if( p->pCheck ){
82619 SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
82620 NameContext sNC; /* Name context for pParse->pNewTable */
 
 
82621
82622 memset(&sNC, 0, sizeof(sNC));
82623 memset(&sSrc, 0, sizeof(sSrc));
82624 sSrc.nSrc = 1;
82625 sSrc.a[0].zName = p->zName;
@@ -82626,12 +82844,15 @@
82626 sSrc.a[0].pTab = p;
82627 sSrc.a[0].iCursor = -1;
82628 sNC.pParse = pParse;
82629 sNC.pSrcList = &sSrc;
82630 sNC.isCheck = 1;
82631 if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
82632 return;
 
 
 
82633 }
82634 }
82635 #endif /* !defined(SQLITE_OMIT_CHECK) */
82636
82637 /* If the db->init.busy is 1 it means we are reading the SQL off the
@@ -84178,23 +84399,25 @@
84178 exit_drop_index:
84179 sqlite3SrcListDelete(db, pName);
84180 }
84181
84182 /*
84183 ** pArray is a pointer to an array of objects. Each object in the
84184 ** array is szEntry bytes in size. This routine allocates a new
84185 ** object on the end of the array.
84186 **
84187 ** *pnEntry is the number of entries already in use. *pnAlloc is
84188 ** the previously allocated size of the array. initSize is the
84189 ** suggested initial array size allocation.
84190 **
84191 ** The index of the new entry is returned in *pIdx.
84192 **
84193 ** This routine returns a pointer to the array of objects. This
84194 ** might be the same as the pArray parameter or it might be a different
84195 ** pointer if the array was resized.
 
 
84196 */
84197 SQLITE_PRIVATE void *sqlite3ArrayAllocate(
84198 sqlite3 *db, /* Connection to notify of malloc failures */
84199 void *pArray, /* Array of objects. Might be reallocated */
84200 int szEntry, /* Size of each object in the array */
@@ -85787,11 +86010,11 @@
85787 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
85788 pWInfo = sqlite3WhereBegin(
85789 pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
85790 );
85791 if( pWInfo==0 ) goto delete_from_cleanup;
85792 regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
85793 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
85794 if( db->flags & SQLITE_CountRows ){
85795 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
85796 }
85797 sqlite3WhereEnd(pWInfo);
@@ -87607,12 +87830,12 @@
87607 FUNCTION(min, 0, 0, 1, 0 ),
87608 AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
87609 FUNCTION(max, -1, 1, 1, minmaxFunc ),
87610 FUNCTION(max, 0, 1, 1, 0 ),
87611 AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
87612 FUNCTION(typeof, 1, 0, 0, typeofFunc ),
87613 FUNCTION(length, 1, 0, 0, lengthFunc ),
87614 FUNCTION(substr, 2, 0, 0, substrFunc ),
87615 FUNCTION(substr, 3, 0, 0, substrFunc ),
87616 FUNCTION(abs, 1, 0, 0, absFunc ),
87617 #ifndef SQLITE_OMIT_FLOATING_POINT
87618 FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -87620,15 +87843,13 @@
87620 #endif
87621 FUNCTION(upper, 1, 0, 0, upperFunc ),
87622 FUNCTION(lower, 1, 0, 0, lowerFunc ),
87623 FUNCTION(coalesce, 1, 0, 0, 0 ),
87624 FUNCTION(coalesce, 0, 0, 0, 0 ),
87625 /* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */
87626 {-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0},
87627 FUNCTION(hex, 1, 0, 0, hexFunc ),
87628 /* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
87629 {2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0},
87630 FUNCTION(random, 0, 0, 0, randomFunc ),
87631 FUNCTION(randomblob, 1, 0, 0, randomBlob ),
87632 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
87633 FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
87634 FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -90061,13 +90282,15 @@
90061 int j1; /* Addresss of jump instruction */
90062 int j2 = 0, j3; /* Addresses of jump instructions */
90063 int regData; /* Register containing first data column */
90064 int iCur; /* Table cursor number */
90065 Index *pIdx; /* Pointer to one of the indices */
 
90066 int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
90067 int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
90068
 
90069 v = sqlite3GetVdbe(pParse);
90070 assert( v!=0 );
90071 assert( pTab->pSelect==0 ); /* This table is not a VIEW */
90072 nCol = pTab->nCol;
90073 regData = regRowid + 1;
@@ -90096,11 +90319,11 @@
90096 case OE_Rollback:
90097 case OE_Fail: {
90098 char *zMsg;
90099 sqlite3VdbeAddOp3(v, OP_HaltIfNull,
90100 SQLITE_CONSTRAINT, onError, regData+i);
90101 zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL",
90102 pTab->zName, pTab->aCol[i].zName);
90103 sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
90104 break;
90105 }
90106 case OE_Ignore: {
@@ -90118,22 +90341,31 @@
90118 }
90119
90120 /* Test all CHECK constraints
90121 */
90122 #ifndef SQLITE_OMIT_CHECK
90123 if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
90124 int allOk = sqlite3VdbeMakeLabel(v);
90125 pParse->ckBase = regData;
90126 sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL);
90127 onError = overrideError!=OE_Default ? overrideError : OE_Abort;
90128 if( onError==OE_Ignore ){
90129 sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
90130 }else{
90131 if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
90132 sqlite3HaltConstraint(pParse, onError, 0, 0);
 
 
 
 
 
 
 
 
 
 
 
90133 }
90134 sqlite3VdbeResolveLabel(v, allOk);
90135 }
90136 #endif /* !defined(SQLITE_OMIT_CHECK) */
90137
90138 /* If we have an INTEGER PRIMARY KEY, make sure the primary key
90139 ** of the new record does not previously exist. Except, if this
@@ -90185,11 +90417,11 @@
90185 **
90186 ** to run without a statement journal if there are no indexes on the
90187 ** table.
90188 */
90189 Trigger *pTrigger = 0;
90190 if( pParse->db->flags&SQLITE_RecTriggers ){
90191 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
90192 }
90193 if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
90194 sqlite3MultiWrite(pParse);
90195 sqlite3GenerateRowDelete(
@@ -90274,11 +90506,11 @@
90274 StrAccum errMsg;
90275 const char *zSep;
90276 char *zErr;
90277
90278 sqlite3StrAccumInit(&errMsg, 0, 0, 200);
90279 errMsg.db = pParse->db;
90280 zSep = pIdx->nColumn>1 ? "columns " : "column ";
90281 for(j=0; j<pIdx->nColumn; j++){
90282 char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
90283 sqlite3StrAccumAppend(&errMsg, zSep, -1);
90284 zSep = ", ";
@@ -90298,11 +90530,11 @@
90298 }
90299 default: {
90300 Trigger *pTrigger = 0;
90301 assert( onError==OE_Replace );
90302 sqlite3MultiWrite(pParse);
90303 if( pParse->db->flags&SQLITE_RecTriggers ){
90304 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
90305 }
90306 sqlite3GenerateRowDelete(
90307 pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
90308 );
@@ -90628,11 +90860,11 @@
90628 if( pSrcIdx==0 ){
90629 return 0; /* pDestIdx has no corresponding index in pSrc */
90630 }
90631 }
90632 #ifndef SQLITE_OMIT_CHECK
90633 if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
90634 return 0; /* Tables have different CHECK constraints. Ticket #2252 */
90635 }
90636 #endif
90637 #ifndef SQLITE_OMIT_FOREIGN_KEY
90638 /* Disallow the transfer optimization if the destination table constains
@@ -92317,13 +92549,16 @@
92317 char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */
92318 char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */
92319 const char *zDb = 0; /* The database name */
92320 Token *pId; /* Pointer to <id> token */
92321 int iDb; /* Database index for <database> */
92322 sqlite3 *db = pParse->db;
92323 Db *pDb;
92324 Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
 
 
 
92325 if( v==0 ) return;
92326 sqlite3VdbeRunOnlyOnce(v);
92327 pParse->nMem = 2;
92328
92329 /* Interpret the [database.] part of the pragma statement. iDb is the
@@ -92350,10 +92585,38 @@
92350 assert( pId2 );
92351 zDb = pId2->n>0 ? pDb->zName : 0;
92352 if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
92353 goto pragma_out;
92354 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92355
92356 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
92357 /*
92358 ** PRAGMA [database.]default_cache_size
92359 ** PRAGMA [database.]default_cache_size=N
@@ -92637,11 +92900,11 @@
92637 /* Call SetAutoVacuum() to set initialize the internal auto and
92638 ** incr-vacuum flags. This is required in case this connection
92639 ** creates the database file. It is important that it is created
92640 ** as an auto-vacuum capable db.
92641 */
92642 int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
92643 if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
92644 /* When setting the auto_vacuum mode to either "full" or
92645 ** "incremental", write the value of meta[6] in the database
92646 ** file. Before writing to meta[6], check that meta[3] indicates
92647 ** that this really is an auto-vacuum capable database.
@@ -92755,11 +93018,10 @@
92755 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
92756 }
92757 }else{
92758 #ifndef SQLITE_OMIT_WSD
92759 if( zRight[0] ){
92760 int rc;
92761 int res;
92762 rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
92763 if( rc!=SQLITE_OK || res==0 ){
92764 sqlite3ErrorMsg(pParse, "not a writable directory");
92765 goto pragma_out;
@@ -95671,13 +95933,21 @@
95671 int nCol; /* Number of columns in the result set */
95672 Expr *p; /* Expression for a single result column */
95673 char *zName; /* Column name */
95674 int nName; /* Size of name in zName[] */
95675
95676 *pnCol = nCol = pEList->nExpr;
95677 aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
95678 if( aCol==0 ) return SQLITE_NOMEM;
 
 
 
 
 
 
 
 
95679 for(i=0, pCol=aCol; i<nCol; i++, pCol++){
95680 /* Get an appropriate name for the column
95681 */
95682 p = pEList->a[i].pExpr;
95683 assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
@@ -98641,11 +98911,11 @@
98641 if( pCol->iSorterColumn>=j ){
98642 int r1 = j + regBase;
98643 int r2;
98644
98645 r2 = sqlite3ExprCodeGetColumn(pParse,
98646 pCol->pTab, pCol->iColumn, pCol->iTable, r1);
98647 if( r1!=r2 ){
98648 sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
98649 }
98650 j++;
98651 }
@@ -101201,10 +101471,22 @@
101201 char *zKey;
101202 sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
101203 if( nKey ) db->nextPagesize = 0;
101204 }
101205 #endif
 
 
 
 
 
 
 
 
 
 
 
 
101206
101207 /* Do not attempt to change the page size for a WAL database */
101208 if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
101209 ==PAGER_JOURNALMODE_WAL ){
101210 db->nextPagesize = 0;
@@ -101215,24 +101497,16 @@
101215 || NEVER(db->mallocFailed)
101216 ){
101217 rc = SQLITE_NOMEM;
101218 goto end_of_vacuum;
101219 }
101220 rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
101221 if( rc!=SQLITE_OK ){
101222 goto end_of_vacuum;
101223 }
101224
101225 #ifndef SQLITE_OMIT_AUTOVACUUM
101226 sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac :
101227 sqlite3BtreeGetAutoVacuum(pMain));
101228 #endif
101229
101230 /* Begin a transaction */
101231 rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;");
101232 if( rc!=SQLITE_OK ) goto end_of_vacuum;
101233
101234 /* Query the schema of the main database. Create a mirror schema
101235 ** in the temporary database.
101236 */
101237 rc = execExecSql(db, pzErrMsg,
101238 "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
@@ -103126,11 +103400,14 @@
103126 #ifdef SQLITE_EBCDIC
103127 if( *pnoCase ) return 0;
103128 #endif
103129 pList = pExpr->x.pList;
103130 pLeft = pList->a[1].pExpr;
103131 if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ){
 
 
 
103132 /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
103133 ** be the name of an indexed column with TEXT affinity. */
103134 return 0;
103135 }
103136 assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
@@ -105543,11 +105820,13 @@
105543 }
105544
105545 /* If there is a DISTINCT qualifier and this index will scan rows in
105546 ** order of the DISTINCT expressions, clear bDist and set the appropriate
105547 ** flags in wsFlags. */
105548 if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){
 
 
105549 bDist = 0;
105550 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
105551 }
105552
105553 /* If currently calculating the cost of using an index (not the IPK
@@ -106240,12 +106519,11 @@
106240 */
106241 static Bitmask codeOneLoopStart(
106242 WhereInfo *pWInfo, /* Complete information about the WHERE clause */
106243 int iLevel, /* Which level of pWInfo->a[] should be coded */
106244 u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
106245 Bitmask notReady, /* Which tables are currently available */
106246 Expr *pWhere /* Complete WHERE clause */
106247 ){
106248 int j, k; /* Loop counters */
106249 int iCur; /* The VDBE cursor for the table */
106250 int addrNxt; /* Where to jump to continue with the next IN case */
106251 int omitTable; /* True if we use the index only */
@@ -106780,14 +107058,29 @@
106780
106781 /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
106782 ** Then for every term xN, evaluate as the subexpression: xN AND z
106783 ** That way, terms in y that are factored into the disjunction will
106784 ** be picked up by the recursive calls to sqlite3WhereBegin() below.
 
 
 
 
 
106785 */
106786 if( pWC->nTerm>1 ){
106787 pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0);
106788 pAndExpr->pRight = pWhere;
 
 
 
 
 
 
 
 
 
 
106789 }
106790
106791 for(ii=0; ii<pOrWc->nTerm; ii++){
106792 WhereTerm *pOrTerm = &pOrWc->a[ii];
106793 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
@@ -106807,11 +107100,11 @@
106807 );
106808 if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
106809 int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
106810 int r;
106811 r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
106812 regRowid);
106813 sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
106814 sqlite3VdbeCurrentAddr(v)+2, r, iSet);
106815 }
106816 sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
106817
@@ -106825,11 +107118,14 @@
106825 /* Finish the loop through table entries that match term pOrTerm. */
106826 sqlite3WhereEnd(pSubWInfo);
106827 }
106828 }
106829 }
106830 sqlite3DbFree(pParse->db, pAndExpr);
 
 
 
106831 sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
106832 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
106833 sqlite3VdbeResolveLabel(v, iLoopBody);
106834
106835 if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
@@ -107481,11 +107777,11 @@
107481 */
107482 notReady = ~(Bitmask)0;
107483 for(i=0; i<nTabList; i++){
107484 pLevel = &pWInfo->a[i];
107485 explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
107486 notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere);
107487 pWInfo->iContinue = pLevel->addrCont;
107488 }
107489
107490 #ifdef SQLITE_TEST /* For testing and debugging use only */
107491 /* Record in the query plan information about the current table
@@ -107717,11 +108013,11 @@
107717 ** An instance of this structure is used to store the LIKE,
107718 ** GLOB, NOT LIKE, and NOT GLOB operators.
107719 */
107720 struct LikeOp {
107721 Token eOperator; /* "like" or "glob" or "regexp" */
107722 int not; /* True if the NOT keyword is present */
107723 };
107724
107725 /*
107726 ** An instance of the following structure describes the event of a
107727 ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
@@ -107896,12 +108192,12 @@
107896 #endif
107897 #define sqlite3ParserARG_SDECL Parse *pParse;
107898 #define sqlite3ParserARG_PDECL ,Parse *pParse
107899 #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
107900 #define sqlite3ParserARG_STORE yypParser->pParse = pParse
107901 #define YYNSTATE 629
107902 #define YYNRULE 327
107903 #define YYFALLBACK 1
107904 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
107905 #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
107906 #define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
107907
@@ -107967,480 +108263,478 @@
107967 ** shifting terminals.
107968 ** yy_reduce_ofst[] For each state, the offset into yy_action for
107969 ** shifting non-terminals after a reduce.
107970 ** yy_default[] Default action for each state.
107971 */
107972 #define YY_ACTTAB_COUNT (1580)
107973 static const YYACTIONTYPE yy_action[] = {
107974 /* 0 */ 310, 328, 574, 573, 15, 172, 187, 596, 56, 56,
107975 /* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52,
107976 /* 20 */ 52, 52, 51, 234, 622, 621, 626, 622, 621, 299,
107977 /* 30 */ 589, 583, 56, 56, 56, 56, 236, 54, 54, 54,
107978 /* 40 */ 54, 53, 53, 52, 52, 52, 51, 234, 351, 57,
107979 /* 50 */ 58, 48, 581, 580, 582, 582, 55, 55, 56, 56,
107980 /* 60 */ 56, 56, 570, 54, 54, 54, 54, 53, 53, 52,
107981 /* 70 */ 52, 52, 51, 234, 310, 596, 326, 607, 233, 232,
107982 /* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52,
107983 /* 90 */ 51, 234, 619, 618, 326, 619, 618, 166, 605, 492,
107984 /* 100 */ 381, 378, 377, 235, 589, 583, 554, 495, 1, 59,
107985 /* 110 */ 19, 376, 622, 621, 53, 53, 52, 52, 52, 51,
107986 /* 120 */ 234, 571, 571, 57, 58, 48, 581, 580, 582, 582,
107987 /* 130 */ 55, 55, 56, 56, 56, 56, 215, 54, 54, 54,
107988 /* 140 */ 54, 53, 53, 52, 52, 52, 51, 234, 310, 224,
107989 /* 150 */ 50, 47, 147, 177, 139, 281, 384, 276, 383, 169,
107990 /* 160 */ 408, 553, 578, 578, 622, 621, 272, 224, 439, 550,
107991 /* 170 */ 552, 410, 139, 281, 384, 276, 383, 169, 589, 583,
107992 /* 180 */ 619, 618, 280, 620, 272, 195, 413, 309, 440, 441,
107993 /* 190 */ 567, 491, 214, 279, 560, 600, 92, 57, 58, 48,
107994 /* 200 */ 581, 580, 582, 582, 55, 55, 56, 56, 56, 56,
107995 /* 210 */ 559, 54, 54, 54, 54, 53, 53, 52, 52, 52,
107996 /* 220 */ 51, 234, 310, 464, 233, 232, 558, 133, 519, 50,
107997 /* 230 */ 47, 147, 619, 618, 565, 436, 397, 515, 514, 518,
107998 /* 240 */ 410, 387, 438, 389, 437, 622, 621, 442, 570, 433,
107999 /* 250 */ 203, 390, 589, 583, 6, 413, 166, 670, 250, 381,
108000 /* 260 */ 378, 377, 525, 190, 600, 92, 594, 571, 571, 465,
108001 /* 270 */ 376, 57, 58, 48, 581, 580, 582, 582, 55, 55,
108002 /* 280 */ 56, 56, 56, 56, 599, 54, 54, 54, 54, 53,
108003 /* 290 */ 53, 52, 52, 52, 51, 234, 310, 592, 592, 592,
108004 /* 300 */ 490, 182, 247, 548, 249, 397, 273, 410, 7, 439,
108005 /* 310 */ 398, 606, 67, 619, 618, 620, 472, 256, 347, 255,
108006 /* 320 */ 473, 620, 413, 576, 620, 65, 589, 583, 236, 440,
108007 /* 330 */ 336, 600, 92, 68, 364, 192, 481, 622, 621, 547,
108008 /* 340 */ 622, 621, 560, 323, 207, 57, 58, 48, 581, 580,
108009 /* 350 */ 582, 582, 55, 55, 56, 56, 56, 56, 559, 54,
108010 /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
108011 /* 370 */ 310, 410, 397, 146, 558, 531, 401, 348, 599, 166,
108012 /* 380 */ 248, 204, 381, 378, 377, 541, 413, 171, 337, 570,
108013 /* 390 */ 622, 621, 40, 376, 38, 600, 74, 465, 548, 490,
108014 /* 400 */ 589, 583, 532, 350, 579, 619, 618, 297, 619, 618,
108015 /* 410 */ 480, 67, 470, 39, 620, 599, 406, 574, 573, 57,
108016 /* 420 */ 58, 48, 581, 580, 582, 582, 55, 55, 56, 56,
108017 /* 430 */ 56, 56, 577, 54, 54, 54, 54, 53, 53, 52,
108018 /* 440 */ 52, 52, 51, 234, 310, 256, 347, 255, 530, 52,
108019 /* 450 */ 52, 52, 51, 234, 345, 564, 236, 386, 619, 618,
108020 /* 460 */ 957, 185, 418, 2, 408, 410, 578, 578, 198, 197,
108021 /* 470 */ 196, 499, 183, 167, 589, 583, 671, 570, 505, 506,
108022 /* 480 */ 413, 267, 601, 672, 546, 208, 602, 36, 601, 600,
108023 /* 490 */ 91, 468, 602, 57, 58, 48, 581, 580, 582, 582,
108024 /* 500 */ 55, 55, 56, 56, 56, 56, 202, 54, 54, 54,
108025 /* 510 */ 54, 53, 53, 52, 52, 52, 51, 234, 310, 599,
108026 /* 520 */ 157, 408, 527, 578, 578, 263, 490, 265, 410, 873,
108027 /* 530 */ 410, 474, 474, 366, 373, 410, 504, 428, 67, 290,
108028 /* 540 */ 599, 620, 352, 413, 408, 413, 578, 578, 589, 583,
108029 /* 550 */ 413, 382, 600, 92, 600, 16, 543, 62, 503, 600,
108030 /* 560 */ 92, 408, 346, 578, 578, 168, 45, 57, 58, 48,
108031 /* 570 */ 581, 580, 582, 582, 55, 55, 56, 56, 56, 56,
108032 /* 580 */ 200, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108033 /* 590 */ 51, 234, 310, 393, 395, 534, 510, 617, 616, 615,
108034 /* 600 */ 318, 314, 172, 66, 596, 410, 338, 596, 324, 571,
108035 /* 610 */ 571, 50, 47, 147, 599, 629, 627, 330, 539, 315,
108036 /* 620 */ 413, 30, 589, 583, 272, 236, 199, 144, 176, 600,
108037 /* 630 */ 73, 420, 947, 620, 947, 420, 946, 351, 946, 175,
108038 /* 640 */ 596, 57, 58, 48, 581, 580, 582, 582, 55, 55,
108039 /* 650 */ 56, 56, 56, 56, 410, 54, 54, 54, 54, 53,
108040 /* 660 */ 53, 52, 52, 52, 51, 234, 310, 261, 410, 413,
108041 /* 670 */ 269, 208, 596, 363, 410, 596, 424, 360, 600, 69,
108042 /* 680 */ 424, 327, 620, 413, 50, 47, 147, 410, 358, 413,
108043 /* 690 */ 575, 553, 600, 94, 483, 509, 589, 583, 600, 97,
108044 /* 700 */ 552, 484, 413, 620, 188, 599, 551, 563, 596, 566,
108045 /* 710 */ 334, 600, 95, 205, 201, 57, 58, 48, 581, 580,
108046 /* 720 */ 582, 582, 55, 55, 56, 56, 56, 56, 352, 54,
108047 /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
108048 /* 740 */ 310, 410, 261, 410, 167, 22, 356, 599, 359, 623,
108049 /* 750 */ 50, 47, 147, 548, 357, 562, 413, 620, 413, 332,
108050 /* 760 */ 523, 270, 410, 167, 620, 600, 104, 600, 103, 603,
108051 /* 770 */ 589, 583, 339, 539, 304, 423, 222, 413, 174, 304,
108052 /* 780 */ 422, 561, 567, 405, 214, 260, 600, 106, 620, 57,
108053 /* 790 */ 58, 48, 581, 580, 582, 582, 55, 55, 56, 56,
108054 /* 800 */ 56, 56, 410, 54, 54, 54, 54, 53, 53, 52,
108055 /* 810 */ 52, 52, 51, 234, 310, 410, 557, 413, 410, 421,
108056 /* 820 */ 273, 35, 512, 146, 421, 12, 600, 107, 213, 144,
108057 /* 830 */ 413, 410, 32, 413, 410, 620, 365, 353, 358, 600,
108058 /* 840 */ 134, 11, 600, 135, 589, 583, 413, 21, 548, 413,
108059 /* 850 */ 316, 148, 620, 620, 170, 600, 98, 223, 600, 102,
108060 /* 860 */ 374, 168, 167, 57, 58, 48, 581, 580, 582, 582,
108061 /* 870 */ 55, 55, 56, 56, 56, 56, 410, 54, 54, 54,
108062 /* 880 */ 54, 53, 53, 52, 52, 52, 51, 234, 310, 410,
108063 /* 890 */ 273, 413, 410, 273, 212, 469, 410, 167, 628, 2,
108064 /* 900 */ 600, 101, 545, 221, 413, 620, 130, 413, 620, 410,
108065 /* 910 */ 539, 413, 537, 600, 93, 315, 600, 100, 589, 583,
108066 /* 920 */ 600, 77, 425, 305, 413, 620, 254, 322, 599, 458,
108067 /* 930 */ 320, 171, 543, 600, 96, 521, 520, 57, 58, 48,
108068 /* 940 */ 581, 580, 582, 582, 55, 55, 56, 56, 56, 56,
108069 /* 950 */ 410, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108070 /* 960 */ 51, 234, 310, 410, 273, 413, 410, 457, 358, 35,
108071 /* 970 */ 426, 230, 306, 319, 600, 138, 467, 520, 413, 620,
108072 /* 980 */ 143, 413, 410, 620, 410, 353, 529, 600, 137, 142,
108073 /* 990 */ 600, 136, 589, 583, 604, 261, 528, 413, 229, 413,
108074 /* 1000 */ 620, 321, 495, 28, 543, 543, 600, 76, 600, 90,
108075 /* 1010 */ 620, 57, 46, 48, 581, 580, 582, 582, 55, 55,
108076 /* 1020 */ 56, 56, 56, 56, 410, 54, 54, 54, 54, 53,
108077 /* 1030 */ 53, 52, 52, 52, 51, 234, 310, 261, 451, 413,
108078 /* 1040 */ 410, 211, 611, 285, 283, 610, 609, 502, 600, 89,
108079 /* 1050 */ 380, 217, 620, 128, 140, 413, 220, 620, 410, 409,
108080 /* 1060 */ 620, 620, 588, 587, 600, 75, 589, 583, 271, 620,
108081 /* 1070 */ 51, 234, 127, 413, 620, 599, 627, 330, 27, 375,
108082 /* 1080 */ 449, 279, 600, 88, 585, 584, 58, 48, 581, 580,
108083 /* 1090 */ 582, 582, 55, 55, 56, 56, 56, 56, 410, 54,
108084 /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
108085 /* 1110 */ 310, 586, 410, 413, 410, 261, 593, 165, 399, 556,
108086 /* 1120 */ 126, 371, 600, 87, 478, 186, 123, 413, 367, 413,
108087 /* 1130 */ 620, 620, 410, 620, 620, 410, 600, 99, 600, 86,
108088 /* 1140 */ 589, 583, 475, 122, 258, 171, 471, 413, 160, 121,
108089 /* 1150 */ 413, 14, 159, 463, 25, 24, 600, 17, 448, 600,
108090 /* 1160 */ 85, 48, 581, 580, 582, 582, 55, 55, 56, 56,
108091 /* 1170 */ 56, 56, 158, 54, 54, 54, 54, 53, 53, 52,
108092 /* 1180 */ 52, 52, 51, 234, 44, 404, 261, 3, 544, 261,
108093 /* 1190 */ 540, 414, 621, 460, 119, 118, 538, 275, 10, 349,
108094 /* 1200 */ 4, 620, 407, 620, 620, 620, 116, 44, 404, 410,
108095 /* 1210 */ 3, 620, 620, 410, 414, 621, 456, 454, 252, 450,
108096 /* 1220 */ 508, 402, 111, 109, 413, 407, 155, 444, 413, 447,
108097 /* 1230 */ 435, 565, 219, 600, 84, 620, 108, 600, 83, 64,
108098 /* 1240 */ 434, 417, 625, 150, 402, 333, 410, 237, 238, 124,
108099 /* 1250 */ 274, 41, 42, 533, 565, 206, 189, 261, 43, 412,
108100 /* 1260 */ 411, 413, 261, 594, 488, 620, 329, 149, 419, 268,
108101 /* 1270 */ 600, 72, 620, 266, 41, 42, 181, 620, 410, 620,
108102 /* 1280 */ 105, 43, 412, 411, 620, 624, 594, 614, 620, 599,
108103 /* 1290 */ 228, 125, 313, 413, 592, 592, 592, 591, 590, 13,
108104 /* 1300 */ 218, 410, 600, 71, 236, 244, 44, 404, 264, 3,
108105 /* 1310 */ 312, 613, 340, 414, 621, 180, 413, 592, 592, 592,
108106 /* 1320 */ 591, 590, 13, 620, 407, 600, 82, 410, 416, 34,
108107 /* 1330 */ 404, 410, 3, 410, 262, 410, 414, 621, 612, 331,
108108 /* 1340 */ 178, 415, 413, 402, 8, 236, 413, 407, 413, 620,
108109 /* 1350 */ 413, 600, 81, 565, 257, 600, 80, 600, 70, 600,
108110 /* 1360 */ 18, 598, 361, 462, 461, 30, 402, 294, 31, 620,
108111 /* 1370 */ 293, 354, 251, 41, 42, 410, 565, 620, 620, 620,
108112 /* 1380 */ 43, 412, 411, 453, 396, 594, 620, 620, 394, 61,
108113 /* 1390 */ 413, 292, 443, 622, 621, 243, 41, 42, 620, 600,
108114 /* 1400 */ 79, 597, 291, 43, 412, 411, 60, 620, 594, 240,
108115 /* 1410 */ 620, 410, 231, 37, 555, 173, 592, 592, 592, 591,
108116 /* 1420 */ 590, 13, 216, 239, 620, 184, 413, 302, 301, 300,
108117 /* 1430 */ 179, 298, 388, 565, 452, 600, 78, 286, 620, 592,
108118 /* 1440 */ 592, 592, 591, 590, 13, 429, 29, 413, 151, 289,
108119 /* 1450 */ 242, 145, 392, 194, 193, 288, 600, 9, 542, 241,
108120 /* 1460 */ 620, 525, 391, 284, 620, 594, 620, 620, 522, 536,
108121 /* 1470 */ 620, 535, 153, 385, 465, 516, 282, 325, 154, 517,
108122 /* 1480 */ 277, 152, 512, 511, 513, 129, 226, 308, 487, 486,
108123 /* 1490 */ 485, 164, 372, 493, 307, 227, 592, 592, 592, 225,
108124 /* 1500 */ 479, 163, 368, 370, 162, 476, 210, 477, 26, 259,
108125 /* 1510 */ 161, 466, 362, 141, 132, 120, 117, 455, 156, 115,
108126 /* 1520 */ 344, 343, 256, 342, 245, 114, 113, 446, 311, 112,
108127 /* 1530 */ 23, 317, 432, 236, 131, 431, 110, 430, 20, 427,
108128 /* 1540 */ 608, 595, 295, 63, 379, 287, 509, 191, 278, 403,
108129 /* 1550 */ 572, 569, 497, 498, 496, 494, 335, 459, 445, 303,
108130 /* 1560 */ 296, 246, 341, 355, 5, 568, 369, 507, 253, 549,
108131 /* 1570 */ 526, 209, 400, 501, 500, 524, 234, 958, 489, 482,
108132 };
108133 static const YYCODETYPE yy_lookahead[] = {
108134 /* 0 */ 19, 169, 170, 171, 22, 24, 24, 26, 77, 78,
108135 /* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
108136 /* 20 */ 89, 90, 91, 92, 26, 27, 1, 26, 27, 15,
108137 /* 30 */ 49, 50, 77, 78, 79, 80, 116, 82, 83, 84,
108138 /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 128, 68,
108139 /* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108140 /* 60 */ 79, 80, 230, 82, 83, 84, 85, 86, 87, 88,
108141 /* 70 */ 89, 90, 91, 92, 19, 94, 19, 23, 86, 87,
108142 /* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108143 /* 90 */ 91, 92, 94, 95, 19, 94, 95, 96, 172, 173,
108144 /* 100 */ 99, 100, 101, 197, 49, 50, 177, 181, 22, 54,
108145 /* 110 */ 204, 110, 26, 27, 86, 87, 88, 89, 90, 91,
108146 /* 120 */ 92, 129, 130, 68, 69, 70, 71, 72, 73, 74,
108147 /* 130 */ 75, 76, 77, 78, 79, 80, 22, 82, 83, 84,
108148 /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92,
108149 /* 150 */ 221, 222, 223, 96, 97, 98, 99, 100, 101, 102,
108150 /* 160 */ 112, 32, 114, 115, 26, 27, 109, 92, 150, 25,
108151 /* 170 */ 41, 150, 97, 98, 99, 100, 101, 102, 49, 50,
108152 /* 180 */ 94, 95, 98, 165, 109, 25, 165, 163, 170, 171,
108153 /* 190 */ 166, 167, 168, 109, 12, 174, 175, 68, 69, 70,
108154 /* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108155 /* 210 */ 28, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108156 /* 220 */ 91, 92, 19, 11, 86, 87, 44, 24, 46, 221,
108157 /* 230 */ 222, 223, 94, 95, 66, 97, 215, 7, 8, 57,
108158 /* 240 */ 150, 220, 104, 19, 106, 26, 27, 229, 230, 241,
108159 /* 250 */ 160, 27, 49, 50, 22, 165, 96, 118, 16, 99,
108160 /* 260 */ 100, 101, 94, 119, 174, 175, 98, 129, 130, 57,
108161 /* 270 */ 110, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108162 /* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
108163 /* 290 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 131,
108164 /* 300 */ 150, 23, 60, 25, 62, 215, 150, 150, 76, 150,
108165 /* 310 */ 220, 161, 162, 94, 95, 165, 30, 105, 106, 107,
108166 /* 320 */ 34, 165, 165, 23, 165, 25, 49, 50, 116, 170,
108167 /* 330 */ 171, 174, 175, 22, 48, 185, 186, 26, 27, 120,
108168 /* 340 */ 26, 27, 12, 187, 160, 68, 69, 70, 71, 72,
108169 /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 28, 82,
108170 /* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108171 /* 370 */ 19, 150, 215, 95, 44, 23, 46, 220, 194, 96,
108172 /* 380 */ 138, 160, 99, 100, 101, 23, 165, 25, 229, 230,
108173 /* 390 */ 26, 27, 135, 110, 137, 174, 175, 57, 120, 150,
108174 /* 400 */ 49, 50, 88, 219, 113, 94, 95, 158, 94, 95,
108175 /* 410 */ 161, 162, 21, 136, 165, 194, 169, 170, 171, 68,
108176 /* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108177 /* 430 */ 79, 80, 23, 82, 83, 84, 85, 86, 87, 88,
108178 /* 440 */ 89, 90, 91, 92, 19, 105, 106, 107, 23, 88,
108179 /* 450 */ 89, 90, 91, 92, 63, 23, 116, 88, 94, 95,
108180 /* 460 */ 142, 143, 144, 145, 112, 150, 114, 115, 105, 106,
108181 /* 470 */ 107, 23, 23, 25, 49, 50, 118, 230, 97, 98,
108182 /* 480 */ 165, 16, 113, 118, 120, 160, 117, 136, 113, 174,
108183 /* 490 */ 175, 100, 117, 68, 69, 70, 71, 72, 73, 74,
108184 /* 500 */ 75, 76, 77, 78, 79, 80, 160, 82, 83, 84,
108185 /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 194,
108186 /* 520 */ 25, 112, 23, 114, 115, 60, 150, 62, 150, 138,
108187 /* 530 */ 150, 105, 106, 107, 19, 150, 36, 161, 162, 224,
108188 /* 540 */ 194, 165, 217, 165, 112, 165, 114, 115, 49, 50,
108189 /* 550 */ 165, 51, 174, 175, 174, 175, 166, 232, 58, 174,
108190 /* 560 */ 175, 112, 237, 114, 115, 50, 22, 68, 69, 70,
108191 /* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108192 /* 580 */ 160, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108193 /* 590 */ 91, 92, 19, 215, 214, 205, 23, 7, 8, 9,
108194 /* 600 */ 215, 155, 24, 22, 26, 150, 97, 26, 108, 129,
108195 /* 610 */ 130, 221, 222, 223, 194, 0, 1, 2, 150, 104,
108196 /* 620 */ 165, 126, 49, 50, 109, 116, 206, 207, 118, 174,
108197 /* 630 */ 175, 22, 23, 165, 25, 22, 23, 128, 25, 118,
108198 /* 640 */ 26, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108199 /* 650 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
108200 /* 660 */ 87, 88, 89, 90, 91, 92, 19, 150, 150, 165,
108201 /* 670 */ 23, 160, 94, 227, 150, 94, 67, 231, 174, 175,
108202 /* 680 */ 67, 213, 165, 165, 221, 222, 223, 150, 150, 165,
108203 /* 690 */ 23, 32, 174, 175, 181, 182, 49, 50, 174, 175,
108204 /* 700 */ 41, 188, 165, 165, 22, 194, 177, 11, 94, 23,
108205 /* 710 */ 193, 174, 175, 160, 22, 68, 69, 70, 71, 72,
108206 /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 217, 82,
108207 /* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108208 /* 740 */ 19, 150, 150, 150, 25, 24, 19, 194, 237, 150,
108209 /* 750 */ 221, 222, 223, 25, 27, 23, 165, 165, 165, 242,
108210 /* 760 */ 165, 23, 150, 25, 165, 174, 175, 174, 175, 174,
108211 /* 770 */ 49, 50, 219, 150, 22, 23, 238, 165, 25, 22,
108212 /* 780 */ 23, 23, 166, 167, 168, 193, 174, 175, 165, 68,
108213 /* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108214 /* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88,
108215 /* 810 */ 89, 90, 91, 92, 19, 150, 23, 165, 150, 67,
108216 /* 820 */ 150, 25, 103, 95, 67, 35, 174, 175, 206, 207,
108217 /* 830 */ 165, 150, 25, 165, 150, 165, 213, 150, 150, 174,
108218 /* 840 */ 175, 35, 174, 175, 49, 50, 165, 52, 120, 165,
108219 /* 850 */ 245, 246, 165, 165, 35, 174, 175, 187, 174, 175,
108220 /* 860 */ 23, 50, 25, 68, 69, 70, 71, 72, 73, 74,
108221 /* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84,
108222 /* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150,
108223 /* 890 */ 150, 165, 150, 150, 160, 23, 150, 25, 144, 145,
108224 /* 900 */ 174, 175, 120, 216, 165, 165, 22, 165, 165, 150,
108225 /* 910 */ 150, 165, 27, 174, 175, 104, 174, 175, 49, 50,
108226 /* 920 */ 174, 175, 247, 248, 165, 165, 238, 187, 194, 23,
108227 /* 930 */ 187, 25, 166, 174, 175, 190, 191, 68, 69, 70,
108228 /* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108229 /* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108230 /* 960 */ 91, 92, 19, 150, 150, 165, 150, 23, 150, 25,
108231 /* 970 */ 23, 205, 25, 213, 174, 175, 190, 191, 165, 165,
108232 /* 980 */ 118, 165, 150, 165, 150, 150, 23, 174, 175, 39,
108233 /* 990 */ 174, 175, 49, 50, 173, 150, 23, 165, 52, 165,
108234 /* 1000 */ 165, 187, 181, 22, 166, 166, 174, 175, 174, 175,
108235 /* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108236 /* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
108237 /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165,
108238 /* 1040 */ 150, 160, 150, 205, 205, 150, 150, 29, 174, 175,
108239 /* 1050 */ 52, 216, 165, 22, 150, 165, 238, 165, 150, 150,
108240 /* 1060 */ 165, 165, 49, 50, 174, 175, 49, 50, 23, 165,
108241 /* 1070 */ 91, 92, 22, 165, 165, 194, 1, 2, 22, 52,
108242 /* 1080 */ 193, 109, 174, 175, 71, 72, 69, 70, 71, 72,
108243 /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
108244 /* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108245 /* 1110 */ 19, 98, 150, 165, 150, 150, 150, 102, 150, 150,
108246 /* 1120 */ 22, 19, 174, 175, 20, 24, 104, 165, 43, 165,
108247 /* 1130 */ 165, 165, 150, 165, 165, 150, 174, 175, 174, 175,
108248 /* 1140 */ 49, 50, 59, 53, 138, 25, 53, 165, 104, 22,
108249 /* 1150 */ 165, 5, 118, 1, 76, 76, 174, 175, 193, 174,
108250 /* 1160 */ 175, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108251 /* 1170 */ 79, 80, 35, 82, 83, 84, 85, 86, 87, 88,
108252 /* 1180 */ 89, 90, 91, 92, 19, 20, 150, 22, 150, 150,
108253 /* 1190 */ 150, 26, 27, 27, 108, 127, 150, 150, 22, 25,
108254 /* 1200 */ 22, 165, 37, 165, 165, 165, 119, 19, 20, 150,
108255 /* 1210 */ 22, 165, 165, 150, 26, 27, 23, 1, 16, 20,
108256 /* 1220 */ 150, 56, 119, 108, 165, 37, 121, 128, 165, 193,
108257 /* 1230 */ 23, 66, 193, 174, 175, 165, 127, 174, 175, 16,
108258 /* 1240 */ 23, 146, 147, 15, 56, 65, 150, 152, 140, 154,
108259 /* 1250 */ 150, 86, 87, 88, 66, 160, 22, 150, 93, 94,
108260 /* 1260 */ 95, 165, 150, 98, 150, 165, 3, 246, 4, 150,
108261 /* 1270 */ 174, 175, 165, 150, 86, 87, 6, 165, 150, 165,
108262 /* 1280 */ 164, 93, 94, 95, 165, 149, 98, 149, 165, 194,
108263 /* 1290 */ 180, 180, 249, 165, 129, 130, 131, 132, 133, 134,
108264 /* 1300 */ 193, 150, 174, 175, 116, 193, 19, 20, 150, 22,
108265 /* 1310 */ 249, 149, 217, 26, 27, 151, 165, 129, 130, 131,
108266 /* 1320 */ 132, 133, 134, 165, 37, 174, 175, 150, 149, 19,
108267 /* 1330 */ 20, 150, 22, 150, 150, 150, 26, 27, 13, 244,
108268 /* 1340 */ 151, 159, 165, 56, 25, 116, 165, 37, 165, 165,
108269 /* 1350 */ 165, 174, 175, 66, 150, 174, 175, 174, 175, 174,
108270 /* 1360 */ 175, 194, 150, 150, 150, 126, 56, 199, 124, 165,
108271 /* 1370 */ 200, 150, 150, 86, 87, 150, 66, 165, 165, 165,
108272 /* 1380 */ 93, 94, 95, 150, 122, 98, 165, 165, 123, 22,
108273 /* 1390 */ 165, 201, 150, 26, 27, 150, 86, 87, 165, 174,
108274 /* 1400 */ 175, 203, 202, 93, 94, 95, 125, 165, 98, 150,
108275 /* 1410 */ 165, 150, 225, 135, 157, 118, 129, 130, 131, 132,
108276 /* 1420 */ 133, 134, 5, 150, 165, 157, 165, 10, 11, 12,
108277 /* 1430 */ 13, 14, 150, 66, 17, 174, 175, 210, 165, 129,
108278 /* 1440 */ 130, 131, 132, 133, 134, 150, 104, 165, 31, 150,
108279 /* 1450 */ 33, 150, 150, 86, 87, 150, 174, 175, 211, 42,
108280 /* 1460 */ 165, 94, 121, 210, 165, 98, 165, 165, 176, 211,
108281 /* 1470 */ 165, 211, 55, 104, 57, 184, 210, 47, 61, 176,
108282 /* 1480 */ 176, 64, 103, 176, 178, 22, 92, 179, 176, 176,
108283 /* 1490 */ 176, 156, 18, 184, 179, 228, 129, 130, 131, 228,
108284 /* 1500 */ 157, 156, 45, 157, 156, 236, 157, 157, 135, 235,
108285 /* 1510 */ 156, 189, 157, 68, 218, 189, 22, 199, 156, 192,
108286 /* 1520 */ 157, 18, 105, 106, 107, 192, 192, 199, 111, 192,
108287 /* 1530 */ 240, 157, 40, 116, 218, 157, 189, 157, 240, 38,
108288 /* 1540 */ 153, 166, 198, 243, 178, 209, 182, 196, 177, 226,
108289 /* 1550 */ 230, 230, 166, 177, 177, 166, 139, 199, 199, 148,
108290 /* 1560 */ 195, 209, 209, 239, 196, 166, 234, 183, 239, 208,
108291 /* 1570 */ 174, 233, 191, 183, 183, 174, 92, 250, 186, 186,
108292 };
108293 #define YY_SHIFT_USE_DFLT (-81)
108294 #define YY_SHIFT_COUNT (417)
108295 #define YY_SHIFT_MIN (-80)
108296 #define YY_SHIFT_MAX (1503)
108297 static const short yy_shift_ofst[] = {
108298 /* 0 */ 1075, 1188, 1417, 1188, 1287, 1287, 138, 138, 1, -19,
108299 /* 10 */ 1287, 1287, 1287, 1287, 340, -2, 129, 129, 795, 1165,
108300 /* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108301 /* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108302 /* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
108303 /* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108304 /* 60 */ 1287, 1287, 212, -2, -2, -8, -8, 614, 1229, 55,
108305 /* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869,
108306 /* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
108307 /* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45,
108308 /* 100 */ -45, -45, -45, -45, -1, 57, 28, 361, -2, -2,
108309 /* 110 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108310 /* 120 */ -2, -2, -2, -2, 391, 515, -2, -2, -2, -2,
108311 /* 130 */ -2, 509, -80, 614, 979, 1484, -81, -81, -81, 1367,
108312 /* 140 */ 75, 182, 182, 314, 311, 364, 219, 86, 613, 609,
108313 /* 150 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108314 /* 160 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108315 /* 170 */ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
108316 /* 180 */ -2, -2, 578, 578, 578, 615, 1229, 1229, 1229, -81,
108317 /* 190 */ -81, -81, 160, 168, 168, 283, 500, 500, 500, 278,
108318 /* 200 */ 449, 330, 432, 409, 352, 48, 48, 48, 48, 426,
108319 /* 210 */ 286, 48, 48, 728, 581, 369, 590, 495, 224, 224,
108320 /* 220 */ 727, 495, 727, 719, 614, 659, 614, 659, 811, 659,
108321 /* 230 */ 224, 257, 480, 480, 614, 144, 375, -18, 1501, 1297,
108322 /* 240 */ 1297, 1492, 1492, 1297, 1494, 1445, 1239, 1503, 1503, 1503,
108323 /* 250 */ 1503, 1297, 1474, 1239, 1494, 1445, 1445, 1297, 1474, 1373,
108324 /* 260 */ 1457, 1297, 1297, 1474, 1297, 1474, 1297, 1474, 1463, 1369,
108325 /* 270 */ 1369, 1369, 1430, 1394, 1394, 1463, 1369, 1379, 1369, 1430,
108326 /* 280 */ 1369, 1369, 1341, 1342, 1341, 1342, 1341, 1342, 1297, 1297,
108327 /* 290 */ 1278, 1281, 1262, 1244, 1265, 1239, 1229, 1319, 1325, 1325,
108328 /* 300 */ 1270, 1270, 1270, 1270, -81, -81, -81, -81, -81, -81,
108329 /* 310 */ 1013, 242, 757, 752, 465, 363, 947, 232, 944, 906,
108330 /* 320 */ 872, 837, 738, 448, 381, 230, 84, 362, 300, 1264,
108331 /* 330 */ 1263, 1234, 1108, 1228, 1180, 1223, 1217, 1207, 1099, 1174,
108332 /* 340 */ 1109, 1115, 1103, 1199, 1105, 1202, 1216, 1087, 1193, 1178,
108333 /* 350 */ 1174, 1176, 1068, 1079, 1078, 1086, 1166, 1137, 1034, 1152,
108334 /* 360 */ 1146, 1127, 1044, 1006, 1093, 1120, 1090, 1083, 1085, 1022,
108335 /* 370 */ 1101, 1104, 1102, 972, 1015, 1098, 1027, 1056, 1050, 1045,
108336 /* 380 */ 1031, 998, 1018, 981, 946, 950, 973, 963, 862, 885,
108337 /* 390 */ 819, 884, 782, 796, 806, 807, 790, 796, 793, 758,
108338 /* 400 */ 753, 732, 692, 696, 682, 686, 667, 544, 291, 521,
108339 /* 410 */ 510, 365, 358, 139, 114, 54, 14, 25,
108340 };
108341 #define YY_REDUCE_USE_DFLT (-169)
108342 #define YY_REDUCE_COUNT (309)
108343 #define YY_REDUCE_MIN (-168)
108344 #define YY_REDUCE_MAX (1411)
108345 static const short yy_reduce_ofst[] = {
108346 /* 0 */ 318, 90, 1095, 221, 157, 21, 159, 18, 150, 390,
108347 /* 10 */ 385, 378, 380, 315, 325, 249, 529, -71, 8, 1282,
108348 /* 20 */ 1261, 1225, 1185, 1183, 1181, 1177, 1151, 1128, 1096, 1063,
108349 /* 30 */ 1059, 985, 982, 964, 962, 948, 908, 890, 874, 834,
108350 /* 40 */ 832, 816, 813, 800, 759, 746, 742, 739, 726, 684,
108351 /* 50 */ 681, 668, 665, 652, 612, 593, 591, 537, 524, 518,
108352 /* 60 */ 504, 455, 511, 376, 517, 247, -168, 24, 420, 463,
108353 /* 70 */ 463, 463, 463, 463, 463, 463, 463, 463, 463, 463,
108354 /* 80 */ 463, 463, 463, 463, 463, 463, 463, 463, 463, 463,
108355 /* 90 */ 463, 463, 463, 463, 463, 463, 463, 463, 463, 463,
108356 /* 100 */ 463, 463, 463, 463, 463, -74, 463, 463, 1112, 835,
108357 /* 110 */ 1107, 1039, 1036, 965, 887, 845, 818, 760, 688, 687,
108358 /* 120 */ 538, 743, 623, 592, 446, 513, 814, 740, 670, 156,
108359 /* 130 */ 468, 553, 184, 616, 463, 463, 463, 463, 463, 595,
108360 /* 140 */ 821, 786, 745, 909, 1305, 1302, 1301, 1299, 675, 675,
108361 /* 150 */ 1295, 1273, 1259, 1245, 1242, 1233, 1222, 1221, 1214, 1213,
108362 /* 160 */ 1212, 1204, 1184, 1158, 1123, 1119, 1114, 1100, 1070, 1047,
108363 /* 170 */ 1046, 1040, 1038, 969, 968, 966, 909, 904, 896, 895,
108364 /* 180 */ 892, 599, 839, 838, 766, 754, 881, 734, 346, 605,
108365 /* 190 */ 622, -94, 1393, 1401, 1396, 1392, 1391, 1390, 1384, 1361,
108366 /* 200 */ 1365, 1381, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1332,
108367 /* 210 */ 1338, 1365, 1365, 1361, 1399, 1368, 1411, 1359, 1353, 1352,
108368 /* 220 */ 1329, 1358, 1324, 1366, 1389, 1377, 1386, 1376, 1364, 1371,
108369 /* 230 */ 1336, 1323, 1321, 1320, 1375, 1344, 1351, 1387, 1300, 1380,
108370 /* 240 */ 1378, 1298, 1290, 1374, 1316, 1347, 1328, 1337, 1334, 1333,
108371 /* 250 */ 1327, 1363, 1362, 1318, 1296, 1326, 1322, 1355, 1354, 1269,
108372 /* 260 */ 1274, 1350, 1349, 1348, 1346, 1345, 1343, 1335, 1315, 1314,
108373 /* 270 */ 1313, 1312, 1309, 1271, 1267, 1308, 1307, 1306, 1304, 1291,
108374 /* 280 */ 1303, 1292, 1260, 1266, 1258, 1253, 1247, 1227, 1268, 1257,
108375 /* 290 */ 1187, 1198, 1200, 1190, 1170, 1168, 1167, 1182, 1189, 1164,
108376 /* 300 */ 1179, 1162, 1138, 1136, 1061, 1043, 1021, 1111, 1110, 1116,
108377 };
108378 static const YYACTIONTYPE yy_default[] = {
108379 /* 0 */ 634, 868, 956, 956, 868, 868, 956, 956, 956, 758,
108380 /* 10 */ 956, 956, 956, 866, 956, 956, 786, 786, 930, 956,
108381 /* 20 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108382 /* 30 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108383 /* 40 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108384 /* 50 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108385 /* 60 */ 956, 956, 956, 956, 956, 956, 956, 673, 762, 792,
108386 /* 70 */ 956, 956, 956, 956, 956, 956, 956, 956, 929, 931,
108387 /* 80 */ 800, 799, 909, 773, 797, 790, 794, 869, 862, 863,
108388 /* 90 */ 861, 865, 870, 956, 793, 829, 846, 828, 840, 845,
108389 /* 100 */ 852, 844, 841, 831, 830, 665, 832, 833, 956, 956,
108390 /* 110 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108391 /* 120 */ 956, 956, 956, 956, 660, 727, 956, 956, 956, 956,
108392 /* 130 */ 956, 956, 956, 956, 834, 835, 849, 848, 847, 956,
108393 /* 140 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108394 /* 150 */ 956, 936, 934, 956, 881, 956, 956, 956, 956, 956,
108395 /* 160 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108396 /* 170 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108397 /* 180 */ 956, 640, 758, 758, 758, 634, 956, 956, 956, 948,
108398 /* 190 */ 762, 752, 718, 956, 956, 956, 956, 956, 956, 956,
108399 /* 200 */ 956, 956, 956, 956, 956, 802, 741, 919, 921, 956,
108400 /* 210 */ 902, 739, 662, 760, 675, 750, 642, 796, 775, 775,
108401 /* 220 */ 914, 796, 914, 699, 956, 786, 956, 786, 696, 786,
108402 /* 230 */ 775, 864, 956, 956, 956, 759, 750, 956, 941, 766,
108403 /* 240 */ 766, 933, 933, 766, 808, 731, 796, 738, 738, 738,
108404 /* 250 */ 738, 766, 657, 796, 808, 731, 731, 766, 657, 908,
108405 /* 260 */ 906, 766, 766, 657, 766, 657, 766, 657, 874, 729,
108406 /* 270 */ 729, 729, 714, 878, 878, 874, 729, 699, 729, 714,
108407 /* 280 */ 729, 729, 779, 774, 779, 774, 779, 774, 766, 766,
108408 /* 290 */ 956, 791, 780, 789, 787, 796, 956, 717, 650, 650,
108409 /* 300 */ 639, 639, 639, 639, 953, 953, 948, 701, 701, 683,
108410 /* 310 */ 956, 956, 956, 956, 956, 956, 956, 883, 956, 956,
108411 /* 320 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108412 /* 330 */ 635, 943, 956, 956, 940, 956, 956, 956, 956, 801,
108413 /* 340 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108414 /* 350 */ 918, 956, 956, 956, 956, 956, 956, 956, 912, 956,
108415 /* 360 */ 956, 956, 956, 956, 956, 905, 904, 956, 956, 956,
108416 /* 370 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108417 /* 380 */ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
108418 /* 390 */ 956, 956, 956, 788, 956, 781, 956, 867, 956, 956,
108419 /* 400 */ 956, 956, 956, 956, 956, 956, 956, 956, 744, 817,
108420 /* 410 */ 956, 816, 820, 815, 667, 956, 648, 956, 631, 636,
108421 /* 420 */ 952, 955, 954, 951, 950, 949, 944, 942, 939, 938,
108422 /* 430 */ 937, 935, 932, 928, 887, 885, 892, 891, 890, 889,
108423 /* 440 */ 888, 886, 884, 882, 803, 798, 795, 927, 880, 740,
108424 /* 450 */ 737, 736, 656, 945, 911, 920, 807, 806, 809, 917,
108425 /* 460 */ 916, 915, 913, 910, 897, 805, 804, 732, 872, 871,
108426 /* 470 */ 659, 901, 900, 899, 903, 907, 898, 768, 658, 655,
108427 /* 480 */ 664, 721, 720, 728, 726, 725, 724, 723, 722, 719,
108428 /* 490 */ 666, 674, 685, 713, 698, 697, 877, 879, 876, 875,
108429 /* 500 */ 706, 705, 711, 710, 709, 708, 707, 704, 703, 702,
108430 /* 510 */ 695, 694, 700, 693, 716, 715, 712, 692, 735, 734,
108431 /* 520 */ 733, 730, 691, 690, 689, 820, 688, 687, 826, 825,
108432 /* 530 */ 813, 856, 755, 754, 753, 765, 764, 777, 776, 811,
108433 /* 540 */ 810, 778, 763, 757, 756, 772, 771, 770, 769, 761,
108434 /* 550 */ 751, 783, 785, 784, 782, 858, 767, 855, 926, 925,
108435 /* 560 */ 924, 923, 922, 860, 859, 827, 824, 678, 679, 895,
108436 /* 570 */ 894, 896, 893, 681, 680, 677, 676, 857, 746, 745,
108437 /* 580 */ 853, 850, 842, 838, 854, 851, 843, 839, 837, 836,
108438 /* 590 */ 822, 821, 819, 818, 814, 823, 669, 747, 743, 742,
108439 /* 600 */ 812, 749, 748, 686, 684, 682, 663, 661, 654, 652,
108440 /* 610 */ 651, 653, 649, 647, 646, 645, 644, 643, 672, 671,
108441 /* 620 */ 670, 668, 667, 641, 638, 637, 633, 632, 630,
108442 };
108443
108444 /* The next table maps tokens into fallback tokens. If a construct
108445 ** like the following:
108446 **
@@ -108639,11 +108933,11 @@
108639 "create_table", "create_table_args", "createkw", "temp",
108640 "ifnotexists", "dbnm", "columnlist", "conslist_opt",
108641 "select", "column", "columnid", "type",
108642 "carglist", "id", "ids", "typetoken",
108643 "typename", "signed", "plus_num", "minus_num",
108644 "carg", "ccons", "term", "expr",
108645 "onconf", "sortorder", "autoinc", "idxlist_opt",
108646 "refargs", "defer_subclause", "refarg", "refact",
108647 "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
108648 "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
108649 "ifexists", "fullname", "oneselect", "multiselect_op",
@@ -108719,14 +109013,14 @@
108719 /* 48 */ "typetoken ::= typename LP signed COMMA signed RP",
108720 /* 49 */ "typename ::= ids",
108721 /* 50 */ "typename ::= typename ids",
108722 /* 51 */ "signed ::= plus_num",
108723 /* 52 */ "signed ::= minus_num",
108724 /* 53 */ "carglist ::= carglist carg",
108725 /* 54 */ "carglist ::=",
108726 /* 55 */ "carg ::= CONSTRAINT nm ccons",
108727 /* 56 */ "carg ::= ccons",
108728 /* 57 */ "ccons ::= DEFAULT term",
108729 /* 58 */ "ccons ::= DEFAULT LP expr RP",
108730 /* 59 */ "ccons ::= DEFAULT PLUS term",
108731 /* 60 */ "ccons ::= DEFAULT MINUS term",
108732 /* 61 */ "ccons ::= DEFAULT id",
@@ -108756,247 +109050,245 @@
108756 /* 85 */ "init_deferred_pred_opt ::=",
108757 /* 86 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
108758 /* 87 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
108759 /* 88 */ "conslist_opt ::=",
108760 /* 89 */ "conslist_opt ::= COMMA conslist",
108761 /* 90 */ "conslist ::= conslist COMMA tcons",
108762 /* 91 */ "conslist ::= conslist tcons",
108763 /* 92 */ "conslist ::= tcons",
108764 /* 93 */ "tcons ::= CONSTRAINT nm",
108765 /* 94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
108766 /* 95 */ "tcons ::= UNIQUE LP idxlist RP onconf",
108767 /* 96 */ "tcons ::= CHECK LP expr RP onconf",
108768 /* 97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
108769 /* 98 */ "defer_subclause_opt ::=",
108770 /* 99 */ "defer_subclause_opt ::= defer_subclause",
108771 /* 100 */ "onconf ::=",
108772 /* 101 */ "onconf ::= ON CONFLICT resolvetype",
108773 /* 102 */ "orconf ::=",
108774 /* 103 */ "orconf ::= OR resolvetype",
108775 /* 104 */ "resolvetype ::= raisetype",
108776 /* 105 */ "resolvetype ::= IGNORE",
108777 /* 106 */ "resolvetype ::= REPLACE",
108778 /* 107 */ "cmd ::= DROP TABLE ifexists fullname",
108779 /* 108 */ "ifexists ::= IF EXISTS",
108780 /* 109 */ "ifexists ::=",
108781 /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
108782 /* 111 */ "cmd ::= DROP VIEW ifexists fullname",
108783 /* 112 */ "cmd ::= select",
108784 /* 113 */ "select ::= oneselect",
108785 /* 114 */ "select ::= select multiselect_op oneselect",
108786 /* 115 */ "multiselect_op ::= UNION",
108787 /* 116 */ "multiselect_op ::= UNION ALL",
108788 /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT",
108789 /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
108790 /* 119 */ "distinct ::= DISTINCT",
108791 /* 120 */ "distinct ::= ALL",
108792 /* 121 */ "distinct ::=",
108793 /* 122 */ "sclp ::= selcollist COMMA",
108794 /* 123 */ "sclp ::=",
108795 /* 124 */ "selcollist ::= sclp expr as",
108796 /* 125 */ "selcollist ::= sclp STAR",
108797 /* 126 */ "selcollist ::= sclp nm DOT STAR",
108798 /* 127 */ "as ::= AS nm",
108799 /* 128 */ "as ::= ids",
108800 /* 129 */ "as ::=",
108801 /* 130 */ "from ::=",
108802 /* 131 */ "from ::= FROM seltablist",
108803 /* 132 */ "stl_prefix ::= seltablist joinop",
108804 /* 133 */ "stl_prefix ::=",
108805 /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
108806 /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
108807 /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
108808 /* 137 */ "dbnm ::=",
108809 /* 138 */ "dbnm ::= DOT nm",
108810 /* 139 */ "fullname ::= nm dbnm",
108811 /* 140 */ "joinop ::= COMMA|JOIN",
108812 /* 141 */ "joinop ::= JOIN_KW JOIN",
108813 /* 142 */ "joinop ::= JOIN_KW nm JOIN",
108814 /* 143 */ "joinop ::= JOIN_KW nm nm JOIN",
108815 /* 144 */ "on_opt ::= ON expr",
108816 /* 145 */ "on_opt ::=",
108817 /* 146 */ "indexed_opt ::=",
108818 /* 147 */ "indexed_opt ::= INDEXED BY nm",
108819 /* 148 */ "indexed_opt ::= NOT INDEXED",
108820 /* 149 */ "using_opt ::= USING LP inscollist RP",
108821 /* 150 */ "using_opt ::=",
108822 /* 151 */ "orderby_opt ::=",
108823 /* 152 */ "orderby_opt ::= ORDER BY sortlist",
108824 /* 153 */ "sortlist ::= sortlist COMMA expr sortorder",
108825 /* 154 */ "sortlist ::= expr sortorder",
108826 /* 155 */ "sortorder ::= ASC",
108827 /* 156 */ "sortorder ::= DESC",
108828 /* 157 */ "sortorder ::=",
108829 /* 158 */ "groupby_opt ::=",
108830 /* 159 */ "groupby_opt ::= GROUP BY nexprlist",
108831 /* 160 */ "having_opt ::=",
108832 /* 161 */ "having_opt ::= HAVING expr",
108833 /* 162 */ "limit_opt ::=",
108834 /* 163 */ "limit_opt ::= LIMIT expr",
108835 /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr",
108836 /* 165 */ "limit_opt ::= LIMIT expr COMMA expr",
108837 /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
108838 /* 167 */ "where_opt ::=",
108839 /* 168 */ "where_opt ::= WHERE expr",
108840 /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
108841 /* 170 */ "setlist ::= setlist COMMA nm EQ expr",
108842 /* 171 */ "setlist ::= nm EQ expr",
108843 /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
108844 /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
108845 /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
108846 /* 175 */ "insert_cmd ::= INSERT orconf",
108847 /* 176 */ "insert_cmd ::= REPLACE",
108848 /* 177 */ "valuelist ::= VALUES LP nexprlist RP",
108849 /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP",
108850 /* 179 */ "inscollist_opt ::=",
108851 /* 180 */ "inscollist_opt ::= LP inscollist RP",
108852 /* 181 */ "inscollist ::= inscollist COMMA nm",
108853 /* 182 */ "inscollist ::= nm",
108854 /* 183 */ "expr ::= term",
108855 /* 184 */ "expr ::= LP expr RP",
108856 /* 185 */ "term ::= NULL",
108857 /* 186 */ "expr ::= id",
108858 /* 187 */ "expr ::= JOIN_KW",
108859 /* 188 */ "expr ::= nm DOT nm",
108860 /* 189 */ "expr ::= nm DOT nm DOT nm",
108861 /* 190 */ "term ::= INTEGER|FLOAT|BLOB",
108862 /* 191 */ "term ::= STRING",
108863 /* 192 */ "expr ::= REGISTER",
108864 /* 193 */ "expr ::= VARIABLE",
108865 /* 194 */ "expr ::= expr COLLATE ids",
108866 /* 195 */ "expr ::= CAST LP expr AS typetoken RP",
108867 /* 196 */ "expr ::= ID LP distinct exprlist RP",
108868 /* 197 */ "expr ::= ID LP STAR RP",
108869 /* 198 */ "term ::= CTIME_KW",
108870 /* 199 */ "expr ::= expr AND expr",
108871 /* 200 */ "expr ::= expr OR expr",
108872 /* 201 */ "expr ::= expr LT|GT|GE|LE expr",
108873 /* 202 */ "expr ::= expr EQ|NE expr",
108874 /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
108875 /* 204 */ "expr ::= expr PLUS|MINUS expr",
108876 /* 205 */ "expr ::= expr STAR|SLASH|REM expr",
108877 /* 206 */ "expr ::= expr CONCAT expr",
108878 /* 207 */ "likeop ::= LIKE_KW",
108879 /* 208 */ "likeop ::= NOT LIKE_KW",
108880 /* 209 */ "likeop ::= MATCH",
108881 /* 210 */ "likeop ::= NOT MATCH",
108882 /* 211 */ "expr ::= expr likeop expr",
108883 /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
108884 /* 213 */ "expr ::= expr ISNULL|NOTNULL",
108885 /* 214 */ "expr ::= expr NOT NULL",
108886 /* 215 */ "expr ::= expr IS expr",
108887 /* 216 */ "expr ::= expr IS NOT expr",
108888 /* 217 */ "expr ::= NOT expr",
108889 /* 218 */ "expr ::= BITNOT expr",
108890 /* 219 */ "expr ::= MINUS expr",
108891 /* 220 */ "expr ::= PLUS expr",
108892 /* 221 */ "between_op ::= BETWEEN",
108893 /* 222 */ "between_op ::= NOT BETWEEN",
108894 /* 223 */ "expr ::= expr between_op expr AND expr",
108895 /* 224 */ "in_op ::= IN",
108896 /* 225 */ "in_op ::= NOT IN",
108897 /* 226 */ "expr ::= expr in_op LP exprlist RP",
108898 /* 227 */ "expr ::= LP select RP",
108899 /* 228 */ "expr ::= expr in_op LP select RP",
108900 /* 229 */ "expr ::= expr in_op nm dbnm",
108901 /* 230 */ "expr ::= EXISTS LP select RP",
108902 /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END",
108903 /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
108904 /* 233 */ "case_exprlist ::= WHEN expr THEN expr",
108905 /* 234 */ "case_else ::= ELSE expr",
108906 /* 235 */ "case_else ::=",
108907 /* 236 */ "case_operand ::= expr",
108908 /* 237 */ "case_operand ::=",
108909 /* 238 */ "exprlist ::= nexprlist",
108910 /* 239 */ "exprlist ::=",
108911 /* 240 */ "nexprlist ::= nexprlist COMMA expr",
108912 /* 241 */ "nexprlist ::= expr",
108913 /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
108914 /* 243 */ "uniqueflag ::= UNIQUE",
108915 /* 244 */ "uniqueflag ::=",
108916 /* 245 */ "idxlist_opt ::=",
108917 /* 246 */ "idxlist_opt ::= LP idxlist RP",
108918 /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder",
108919 /* 248 */ "idxlist ::= nm collate sortorder",
108920 /* 249 */ "collate ::=",
108921 /* 250 */ "collate ::= COLLATE ids",
108922 /* 251 */ "cmd ::= DROP INDEX ifexists fullname",
108923 /* 252 */ "cmd ::= VACUUM",
108924 /* 253 */ "cmd ::= VACUUM nm",
108925 /* 254 */ "cmd ::= PRAGMA nm dbnm",
108926 /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
108927 /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
108928 /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
108929 /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
108930 /* 259 */ "nmnum ::= plus_num",
108931 /* 260 */ "nmnum ::= nm",
108932 /* 261 */ "nmnum ::= ON",
108933 /* 262 */ "nmnum ::= DELETE",
108934 /* 263 */ "nmnum ::= DEFAULT",
108935 /* 264 */ "plus_num ::= PLUS number",
108936 /* 265 */ "plus_num ::= number",
108937 /* 266 */ "minus_num ::= MINUS number",
108938 /* 267 */ "number ::= INTEGER|FLOAT",
108939 /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
108940 /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
108941 /* 270 */ "trigger_time ::= BEFORE",
108942 /* 271 */ "trigger_time ::= AFTER",
108943 /* 272 */ "trigger_time ::= INSTEAD OF",
108944 /* 273 */ "trigger_time ::=",
108945 /* 274 */ "trigger_event ::= DELETE|INSERT",
108946 /* 275 */ "trigger_event ::= UPDATE",
108947 /* 276 */ "trigger_event ::= UPDATE OF inscollist",
108948 /* 277 */ "foreach_clause ::=",
108949 /* 278 */ "foreach_clause ::= FOR EACH ROW",
108950 /* 279 */ "when_clause ::=",
108951 /* 280 */ "when_clause ::= WHEN expr",
108952 /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
108953 /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI",
108954 /* 283 */ "trnm ::= nm",
108955 /* 284 */ "trnm ::= nm DOT nm",
108956 /* 285 */ "tridxby ::=",
108957 /* 286 */ "tridxby ::= INDEXED BY nm",
108958 /* 287 */ "tridxby ::= NOT INDEXED",
108959 /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
108960 /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
108961 /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
108962 /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
108963 /* 292 */ "trigger_cmd ::= select",
108964 /* 293 */ "expr ::= RAISE LP IGNORE RP",
108965 /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP",
108966 /* 295 */ "raisetype ::= ROLLBACK",
108967 /* 296 */ "raisetype ::= ABORT",
108968 /* 297 */ "raisetype ::= FAIL",
108969 /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname",
108970 /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
108971 /* 300 */ "cmd ::= DETACH database_kw_opt expr",
108972 /* 301 */ "key_opt ::=",
108973 /* 302 */ "key_opt ::= KEY expr",
108974 /* 303 */ "database_kw_opt ::= DATABASE",
108975 /* 304 */ "database_kw_opt ::=",
108976 /* 305 */ "cmd ::= REINDEX",
108977 /* 306 */ "cmd ::= REINDEX nm dbnm",
108978 /* 307 */ "cmd ::= ANALYZE",
108979 /* 308 */ "cmd ::= ANALYZE nm dbnm",
108980 /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
108981 /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
108982 /* 311 */ "add_column_fullname ::= fullname",
108983 /* 312 */ "kwcolumn_opt ::=",
108984 /* 313 */ "kwcolumn_opt ::= COLUMNKW",
108985 /* 314 */ "cmd ::= create_vtab",
108986 /* 315 */ "cmd ::= create_vtab LP vtabarglist RP",
108987 /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
108988 /* 317 */ "vtabarglist ::= vtabarg",
108989 /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
108990 /* 319 */ "vtabarg ::=",
108991 /* 320 */ "vtabarg ::= vtabarg vtabargtoken",
108992 /* 321 */ "vtabargtoken ::= ANY",
108993 /* 322 */ "vtabargtoken ::= lp anylist RP",
108994 /* 323 */ "lp ::= LP",
108995 /* 324 */ "anylist ::=",
108996 /* 325 */ "anylist ::= anylist LP anylist RP",
108997 /* 326 */ "anylist ::= anylist ANY",
108998 };
108999 #endif /* NDEBUG */
109000
109001
109002 #if YYSTACKDEPTH<=0
@@ -109438,14 +109730,14 @@
109438 { 167, 6 },
109439 { 168, 1 },
109440 { 168, 2 },
109441 { 169, 1 },
109442 { 169, 1 },
109443 { 164, 2 },
109444 { 164, 0 },
109445 { 172, 3 },
109446 { 172, 1 },
109447 { 173, 2 },
109448 { 173, 4 },
109449 { 173, 3 },
109450 { 173, 3 },
109451 { 173, 2 },
@@ -109475,14 +109767,12 @@
109475 { 184, 0 },
109476 { 184, 2 },
109477 { 184, 2 },
109478 { 159, 0 },
109479 { 159, 2 },
109480 { 185, 3 },
109481 { 185, 2 },
109482 { 185, 1 },
109483 { 186, 2 },
109484 { 186, 7 },
109485 { 186, 5 },
109486 { 186, 5 },
109487 { 186, 10 },
109488 { 188, 0 },
@@ -109787,12 +110077,12 @@
109787 {yygotominor.yy392 = TK_DEFERRED;}
109788 break;
109789 case 14: /* transtype ::= DEFERRED */
109790 case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
109791 case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
109792 case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
109793 case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
109794 {yygotominor.yy392 = yymsp[0].major;}
109795 break;
109796 case 17: /* cmd ::= COMMIT trans_opt */
109797 case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
109798 {sqlite3CommitTransaction(pParse);}
@@ -109830,26 +110120,26 @@
109830 case 31: /* temp ::= */ yytestcase(yyruleno==31);
109831 case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
109832 case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
109833 case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
109834 case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
109835 case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
109836 case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
109837 case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
109838 case 121: /* distinct ::= */ yytestcase(yyruleno==121);
109839 case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
109840 case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
109841 {yygotominor.yy392 = 0;}
109842 break;
109843 case 29: /* ifnotexists ::= IF NOT EXISTS */
109844 case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
109845 case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
109846 case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
109847 case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
109848 case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
109849 case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
109850 case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
109851 {yygotominor.yy392 = 1;}
109852 break;
109853 case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
109854 {
109855 sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
@@ -109879,25 +110169,25 @@
109879 case 41: /* nm ::= id */ yytestcase(yyruleno==41);
109880 case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
109881 case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
109882 case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
109883 case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
109884 case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
109885 case 128: /* as ::= ids */ yytestcase(yyruleno==128);
109886 case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
109887 case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
109888 case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250);
109889 case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259);
109890 case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260);
109891 case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261);
109892 case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262);
109893 case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263);
109894 case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264);
109895 case 265: /* plus_num ::= number */ yytestcase(yyruleno==265);
109896 case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
109897 case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
109898 case 283: /* trnm ::= nm */ yytestcase(yyruleno==283);
109899 {yygotominor.yy0 = yymsp[0].minor.yy0;}
109900 break;
109901 case 45: /* type ::= typetoken */
109902 {sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
109903 break;
@@ -109913,10 +110203,16 @@
109913 yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
109914 }
109915 break;
109916 case 50: /* typename ::= typename ids */
109917 {yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
 
 
 
 
 
 
109918 break;
109919 case 57: /* ccons ::= DEFAULT term */
109920 case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
109921 {sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
109922 break;
@@ -109990,80 +110286,80 @@
109990 break;
109991 case 82: /* refact ::= NO ACTION */
109992 { yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */}
109993 break;
109994 case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
109995 case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
109996 case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
109997 case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
109998 {yygotominor.yy392 = yymsp[0].minor.yy392;}
109999 break;
110000 case 88: /* conslist_opt ::= */
110001 {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
110002 break;
110003 case 89: /* conslist_opt ::= COMMA conslist */
110004 {yygotominor.yy0 = yymsp[-1].minor.yy0;}
110005 break;
110006 case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
110007 {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
110008 break;
110009 case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
110010 {sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
110011 break;
110012 case 96: /* tcons ::= CHECK LP expr RP onconf */
110013 {sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
110014 break;
110015 case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
110016 {
110017 sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
110018 sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
110019 }
110020 break;
110021 case 100: /* onconf ::= */
110022 {yygotominor.yy392 = OE_Default;}
110023 break;
110024 case 102: /* orconf ::= */
110025 {yygotominor.yy258 = OE_Default;}
110026 break;
110027 case 103: /* orconf ::= OR resolvetype */
110028 {yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
110029 break;
110030 case 105: /* resolvetype ::= IGNORE */
110031 {yygotominor.yy392 = OE_Ignore;}
110032 break;
110033 case 106: /* resolvetype ::= REPLACE */
110034 {yygotominor.yy392 = OE_Replace;}
110035 break;
110036 case 107: /* cmd ::= DROP TABLE ifexists fullname */
110037 {
110038 sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
110039 }
110040 break;
110041 case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
110042 {
110043 sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
110044 }
110045 break;
110046 case 111: /* cmd ::= DROP VIEW ifexists fullname */
110047 {
110048 sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
110049 }
110050 break;
110051 case 112: /* cmd ::= select */
110052 {
110053 SelectDest dest = {SRT_Output, 0, 0, 0, 0};
110054 sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
110055 sqlite3ExplainBegin(pParse->pVdbe);
110056 sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
110057 sqlite3ExplainFinish(pParse->pVdbe);
110058 sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
110059 }
110060 break;
110061 case 113: /* select ::= oneselect */
110062 {yygotominor.yy159 = yymsp[0].minor.yy159;}
110063 break;
110064 case 114: /* select ::= select multiselect_op oneselect */
110065 {
110066 if( yymsp[0].minor.yy159 ){
110067 yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
110068 yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
110069 }else{
@@ -110070,83 +110366,83 @@
110070 sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
110071 }
110072 yygotominor.yy159 = yymsp[0].minor.yy159;
110073 }
110074 break;
110075 case 116: /* multiselect_op ::= UNION ALL */
110076 {yygotominor.yy392 = TK_ALL;}
110077 break;
110078 case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110079 {
110080 yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
110081 }
110082 break;
110083 case 122: /* sclp ::= selcollist COMMA */
110084 case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
110085 {yygotominor.yy442 = yymsp[-1].minor.yy442;}
110086 break;
110087 case 123: /* sclp ::= */
110088 case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
110089 case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
110090 case 239: /* exprlist ::= */ yytestcase(yyruleno==239);
110091 case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245);
110092 {yygotominor.yy442 = 0;}
110093 break;
110094 case 124: /* selcollist ::= sclp expr as */
110095 {
110096 yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
110097 if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
110098 sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
110099 }
110100 break;
110101 case 125: /* selcollist ::= sclp STAR */
110102 {
110103 Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
110104 yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
110105 }
110106 break;
110107 case 126: /* selcollist ::= sclp nm DOT STAR */
110108 {
110109 Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
110110 Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110111 Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
110112 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
110113 }
110114 break;
110115 case 129: /* as ::= */
110116 {yygotominor.yy0.n = 0;}
110117 break;
110118 case 130: /* from ::= */
110119 {yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
110120 break;
110121 case 131: /* from ::= FROM seltablist */
110122 {
110123 yygotominor.yy347 = yymsp[0].minor.yy347;
110124 sqlite3SrcListShiftJoinType(yygotominor.yy347);
110125 }
110126 break;
110127 case 132: /* stl_prefix ::= seltablist joinop */
110128 {
110129 yygotominor.yy347 = yymsp[-1].minor.yy347;
110130 if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
110131 }
110132 break;
110133 case 133: /* stl_prefix ::= */
110134 {yygotominor.yy347 = 0;}
110135 break;
110136 case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
110137 {
110138 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110139 sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
110140 }
110141 break;
110142 case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
110143 {
110144 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110145 }
110146 break;
110147 case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110148 {
110149 if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
110150 yygotominor.yy347 = yymsp[-4].minor.yy347;
110151 }else{
110152 Select *pSubquery;
@@ -110154,137 +110450,137 @@
110154 pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
110155 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110156 }
110157 }
110158 break;
110159 case 137: /* dbnm ::= */
110160 case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
110161 {yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
110162 break;
110163 case 139: /* fullname ::= nm dbnm */
110164 {yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
110165 break;
110166 case 140: /* joinop ::= COMMA|JOIN */
110167 { yygotominor.yy392 = JT_INNER; }
110168 break;
110169 case 141: /* joinop ::= JOIN_KW JOIN */
110170 { yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
110171 break;
110172 case 142: /* joinop ::= JOIN_KW nm JOIN */
110173 { yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
110174 break;
110175 case 143: /* joinop ::= JOIN_KW nm nm JOIN */
110176 { yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
110177 break;
110178 case 144: /* on_opt ::= ON expr */
110179 case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
110180 case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
110181 case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234);
110182 case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236);
110183 {yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
110184 break;
110185 case 145: /* on_opt ::= */
110186 case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
110187 case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
110188 case 235: /* case_else ::= */ yytestcase(yyruleno==235);
110189 case 237: /* case_operand ::= */ yytestcase(yyruleno==237);
110190 {yygotominor.yy122 = 0;}
110191 break;
110192 case 148: /* indexed_opt ::= NOT INDEXED */
110193 {yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
110194 break;
110195 case 149: /* using_opt ::= USING LP inscollist RP */
110196 case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
110197 {yygotominor.yy180 = yymsp[-1].minor.yy180;}
110198 break;
110199 case 150: /* using_opt ::= */
110200 case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
110201 {yygotominor.yy180 = 0;}
110202 break;
110203 case 152: /* orderby_opt ::= ORDER BY sortlist */
110204 case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
110205 case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238);
110206 {yygotominor.yy442 = yymsp[0].minor.yy442;}
110207 break;
110208 case 153: /* sortlist ::= sortlist COMMA expr sortorder */
110209 {
110210 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
110211 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110212 }
110213 break;
110214 case 154: /* sortlist ::= expr sortorder */
110215 {
110216 yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
110217 if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
110218 }
110219 break;
110220 case 155: /* sortorder ::= ASC */
110221 case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
110222 {yygotominor.yy392 = SQLITE_SO_ASC;}
110223 break;
110224 case 156: /* sortorder ::= DESC */
110225 {yygotominor.yy392 = SQLITE_SO_DESC;}
110226 break;
110227 case 162: /* limit_opt ::= */
110228 {yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
110229 break;
110230 case 163: /* limit_opt ::= LIMIT expr */
110231 {yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
110232 break;
110233 case 164: /* limit_opt ::= LIMIT expr OFFSET expr */
110234 {yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
110235 break;
110236 case 165: /* limit_opt ::= LIMIT expr COMMA expr */
110237 {yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
110238 break;
110239 case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
110240 {
110241 sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
110242 sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
110243 }
110244 break;
110245 case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
110246 {
110247 sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
110248 sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
110249 sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
110250 }
110251 break;
110252 case 170: /* setlist ::= setlist COMMA nm EQ expr */
110253 {
110254 yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
110255 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110256 }
110257 break;
110258 case 171: /* setlist ::= nm EQ expr */
110259 {
110260 yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
110261 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110262 }
110263 break;
110264 case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
110265 {sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
110266 break;
110267 case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
110268 {sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
110269 break;
110270 case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
110271 {sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
110272 break;
110273 case 175: /* insert_cmd ::= INSERT orconf */
110274 {yygotominor.yy258 = yymsp[0].minor.yy258;}
110275 break;
110276 case 176: /* insert_cmd ::= REPLACE */
110277 {yygotominor.yy258 = OE_Replace;}
110278 break;
110279 case 177: /* valuelist ::= VALUES LP nexprlist RP */
110280 {
110281 yygotominor.yy487.pList = yymsp[-1].minor.yy442;
110282 yygotominor.yy487.pSelect = 0;
110283 }
110284 break;
110285 case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */
110286 {
110287 Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
110288 if( yymsp[-4].minor.yy487.pList ){
110289 yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
110290 yymsp[-4].minor.yy487.pList = 0;
@@ -110301,50 +110597,50 @@
110301 pRight->pPrior->selFlags |= SF_Values;
110302 yygotominor.yy487.pSelect = pRight;
110303 }
110304 }
110305 break;
110306 case 181: /* inscollist ::= inscollist COMMA nm */
110307 {yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
110308 break;
110309 case 182: /* inscollist ::= nm */
110310 {yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
110311 break;
110312 case 183: /* expr ::= term */
110313 {yygotominor.yy342 = yymsp[0].minor.yy342;}
110314 break;
110315 case 184: /* expr ::= LP expr RP */
110316 {yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
110317 break;
110318 case 185: /* term ::= NULL */
110319 case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
110320 case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
110321 {spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
110322 break;
110323 case 186: /* expr ::= id */
110324 case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
110325 {spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
110326 break;
110327 case 188: /* expr ::= nm DOT nm */
110328 {
110329 Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110330 Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
110331 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
110332 spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
110333 }
110334 break;
110335 case 189: /* expr ::= nm DOT nm DOT nm */
110336 {
110337 Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
110338 Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110339 Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
110340 Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
110341 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
110342 spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
110343 }
110344 break;
110345 case 192: /* expr ::= REGISTER */
110346 {
110347 /* When doing a nested parse, one can include terms in an expression
110348 ** that look like this: #1 #2 ... These terms refer to registers
110349 ** in the virtual machine. #N is the N-th register. */
110350 if( pParse->nested==0 ){
@@ -110355,31 +110651,31 @@
110355 if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
110356 }
110357 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110358 }
110359 break;
110360 case 193: /* expr ::= VARIABLE */
110361 {
110362 spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
110363 sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
110364 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110365 }
110366 break;
110367 case 194: /* expr ::= expr COLLATE ids */
110368 {
110369 yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110370 yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110371 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110372 }
110373 break;
110374 case 195: /* expr ::= CAST LP expr AS typetoken RP */
110375 {
110376 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
110377 spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
110378 }
110379 break;
110380 case 196: /* expr ::= ID LP distinct exprlist RP */
110381 {
110382 if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
110383 sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
110384 }
110385 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
@@ -110387,17 +110683,17 @@
110387 if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
110388 yygotominor.yy342.pExpr->flags |= EP_Distinct;
110389 }
110390 }
110391 break;
110392 case 197: /* expr ::= ID LP STAR RP */
110393 {
110394 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
110395 spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
110396 }
110397 break;
110398 case 198: /* term ::= CTIME_KW */
110399 {
110400 /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
110401 ** treated as functions that return constants */
110402 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
110403 if( yygotominor.yy342.pExpr ){
@@ -110404,82 +110700,82 @@
110404 yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
110405 }
110406 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110407 }
110408 break;
110409 case 199: /* expr ::= expr AND expr */
110410 case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
110411 case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
110412 case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
110413 case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
110414 case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
110415 case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
110416 case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
110417 {spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
110418 break;
110419 case 207: /* likeop ::= LIKE_KW */
110420 case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
110421 {yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.not = 0;}
110422 break;
110423 case 208: /* likeop ::= NOT LIKE_KW */
110424 case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
110425 {yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.not = 1;}
110426 break;
110427 case 211: /* expr ::= expr likeop expr */
110428 {
110429 ExprList *pList;
110430 pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
110431 pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
110432 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
110433 if( yymsp[-1].minor.yy318.not ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110434 yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110435 yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110436 if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
110437 }
110438 break;
110439 case 212: /* expr ::= expr likeop expr ESCAPE expr */
110440 {
110441 ExprList *pList;
110442 pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110443 pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
110444 pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
110445 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
110446 if( yymsp[-3].minor.yy318.not ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110447 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110448 yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110449 if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
110450 }
110451 break;
110452 case 213: /* expr ::= expr ISNULL|NOTNULL */
110453 {spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
110454 break;
110455 case 214: /* expr ::= expr NOT NULL */
110456 {spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
110457 break;
110458 case 215: /* expr ::= expr IS expr */
110459 {
110460 spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
110461 binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
110462 }
110463 break;
110464 case 216: /* expr ::= expr IS NOT expr */
110465 {
110466 spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
110467 binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
110468 }
110469 break;
110470 case 217: /* expr ::= NOT expr */
110471 case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218);
110472 {spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110473 break;
110474 case 219: /* expr ::= MINUS expr */
110475 {spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110476 break;
110477 case 220: /* expr ::= PLUS expr */
110478 {spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110479 break;
110480 case 223: /* expr ::= expr between_op expr AND expr */
110481 {
110482 ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110483 pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
110484 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
110485 if( yygotominor.yy342.pExpr ){
@@ -110490,11 +110786,11 @@
110490 if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110491 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110492 yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110493 }
110494 break;
110495 case 226: /* expr ::= expr in_op LP exprlist RP */
110496 {
110497 if( yymsp[-1].minor.yy442==0 ){
110498 /* Expressions of the form
110499 **
110500 ** expr1 IN ()
@@ -110517,11 +110813,11 @@
110517 }
110518 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110519 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110520 }
110521 break;
110522 case 227: /* expr ::= LP select RP */
110523 {
110524 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
110525 if( yygotominor.yy342.pExpr ){
110526 yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
110527 ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
@@ -110531,11 +110827,11 @@
110531 }
110532 yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
110533 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110534 }
110535 break;
110536 case 228: /* expr ::= expr in_op LP select RP */
110537 {
110538 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
110539 if( yygotominor.yy342.pExpr ){
110540 yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
110541 ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
@@ -110546,11 +110842,11 @@
110546 if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110547 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110548 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110549 }
110550 break;
110551 case 229: /* expr ::= expr in_op nm dbnm */
110552 {
110553 SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
110554 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
110555 if( yygotominor.yy342.pExpr ){
110556 yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
@@ -110562,11 +110858,11 @@
110562 if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110563 yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
110564 yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
110565 }
110566 break;
110567 case 230: /* expr ::= EXISTS LP select RP */
110568 {
110569 Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
110570 if( p ){
110571 p->x.pSelect = yymsp[-1].minor.yy159;
110572 ExprSetProperty(p, EP_xIsSelect);
@@ -110576,11 +110872,11 @@
110576 }
110577 yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
110578 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110579 }
110580 break;
110581 case 231: /* expr ::= CASE case_operand case_exprlist case_else END */
110582 {
110583 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
110584 if( yygotominor.yy342.pExpr ){
110585 yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
110586 sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
@@ -110589,43 +110885,43 @@
110589 }
110590 yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
110591 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110592 }
110593 break;
110594 case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
110595 {
110596 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
110597 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
110598 }
110599 break;
110600 case 233: /* case_exprlist ::= WHEN expr THEN expr */
110601 {
110602 yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110603 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
110604 }
110605 break;
110606 case 240: /* nexprlist ::= nexprlist COMMA expr */
110607 {yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
110608 break;
110609 case 241: /* nexprlist ::= expr */
110610 {yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
110611 break;
110612 case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
110613 {
110614 sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
110615 sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
110616 &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
110617 }
110618 break;
110619 case 243: /* uniqueflag ::= UNIQUE */
110620 case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296);
110621 {yygotominor.yy392 = OE_Abort;}
110622 break;
110623 case 244: /* uniqueflag ::= */
110624 {yygotominor.yy392 = OE_None;}
110625 break;
110626 case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
110627 {
110628 Expr *p = 0;
110629 if( yymsp[-1].minor.yy0.n>0 ){
110630 p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
110631 sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
@@ -110634,11 +110930,11 @@
110634 sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
110635 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110636 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110637 }
110638 break;
110639 case 248: /* idxlist ::= nm collate sortorder */
110640 {
110641 Expr *p = 0;
110642 if( yymsp[-1].minor.yy0.n>0 ){
110643 p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
110644 sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
@@ -110647,212 +110943,212 @@
110647 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110648 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110649 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110650 }
110651 break;
110652 case 249: /* collate ::= */
110653 {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
110654 break;
110655 case 251: /* cmd ::= DROP INDEX ifexists fullname */
110656 {sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
110657 break;
110658 case 252: /* cmd ::= VACUUM */
110659 case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253);
110660 {sqlite3Vacuum(pParse);}
110661 break;
110662 case 254: /* cmd ::= PRAGMA nm dbnm */
110663 {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
110664 break;
110665 case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
110666 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
110667 break;
110668 case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
110669 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
110670 break;
110671 case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
110672 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
110673 break;
110674 case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
110675 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
110676 break;
110677 case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
110678 {
110679 Token all;
110680 all.z = yymsp[-3].minor.yy0.z;
110681 all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
110682 sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
110683 }
110684 break;
110685 case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
110686 {
110687 sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
110688 yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
110689 }
110690 break;
110691 case 270: /* trigger_time ::= BEFORE */
110692 case 273: /* trigger_time ::= */ yytestcase(yyruleno==273);
110693 { yygotominor.yy392 = TK_BEFORE; }
110694 break;
110695 case 271: /* trigger_time ::= AFTER */
110696 { yygotominor.yy392 = TK_AFTER; }
110697 break;
110698 case 272: /* trigger_time ::= INSTEAD OF */
110699 { yygotominor.yy392 = TK_INSTEAD;}
110700 break;
110701 case 274: /* trigger_event ::= DELETE|INSERT */
110702 case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275);
110703 {yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
110704 break;
110705 case 276: /* trigger_event ::= UPDATE OF inscollist */
110706 {yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
110707 break;
110708 case 279: /* when_clause ::= */
110709 case 301: /* key_opt ::= */ yytestcase(yyruleno==301);
110710 { yygotominor.yy122 = 0; }
110711 break;
110712 case 280: /* when_clause ::= WHEN expr */
110713 case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302);
110714 { yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
110715 break;
110716 case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
110717 {
110718 assert( yymsp[-2].minor.yy327!=0 );
110719 yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
110720 yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
110721 yygotominor.yy327 = yymsp[-2].minor.yy327;
110722 }
110723 break;
110724 case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
110725 {
110726 assert( yymsp[-1].minor.yy327!=0 );
110727 yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
110728 yygotominor.yy327 = yymsp[-1].minor.yy327;
110729 }
110730 break;
110731 case 284: /* trnm ::= nm DOT nm */
110732 {
110733 yygotominor.yy0 = yymsp[0].minor.yy0;
110734 sqlite3ErrorMsg(pParse,
110735 "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
110736 "statements within triggers");
110737 }
110738 break;
110739 case 286: /* tridxby ::= INDEXED BY nm */
110740 {
110741 sqlite3ErrorMsg(pParse,
110742 "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
110743 "within triggers");
110744 }
110745 break;
110746 case 287: /* tridxby ::= NOT INDEXED */
110747 {
110748 sqlite3ErrorMsg(pParse,
110749 "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
110750 "within triggers");
110751 }
110752 break;
110753 case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
110754 { yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
110755 break;
110756 case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
110757 {yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
110758 break;
110759 case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
110760 {yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
110761 break;
110762 case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
110763 {yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
110764 break;
110765 case 292: /* trigger_cmd ::= select */
110766 {yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
110767 break;
110768 case 293: /* expr ::= RAISE LP IGNORE RP */
110769 {
110770 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
110771 if( yygotominor.yy342.pExpr ){
110772 yygotominor.yy342.pExpr->affinity = OE_Ignore;
110773 }
110774 yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
110775 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110776 }
110777 break;
110778 case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
110779 {
110780 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
110781 if( yygotominor.yy342.pExpr ) {
110782 yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
110783 }
110784 yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
110785 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110786 }
110787 break;
110788 case 295: /* raisetype ::= ROLLBACK */
110789 {yygotominor.yy392 = OE_Rollback;}
110790 break;
110791 case 297: /* raisetype ::= FAIL */
110792 {yygotominor.yy392 = OE_Fail;}
110793 break;
110794 case 298: /* cmd ::= DROP TRIGGER ifexists fullname */
110795 {
110796 sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
110797 }
110798 break;
110799 case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
110800 {
110801 sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
110802 }
110803 break;
110804 case 300: /* cmd ::= DETACH database_kw_opt expr */
110805 {
110806 sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
110807 }
110808 break;
110809 case 305: /* cmd ::= REINDEX */
110810 {sqlite3Reindex(pParse, 0, 0);}
110811 break;
110812 case 306: /* cmd ::= REINDEX nm dbnm */
110813 {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
110814 break;
110815 case 307: /* cmd ::= ANALYZE */
110816 {sqlite3Analyze(pParse, 0, 0);}
110817 break;
110818 case 308: /* cmd ::= ANALYZE nm dbnm */
110819 {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
110820 break;
110821 case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
110822 {
110823 sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
110824 }
110825 break;
110826 case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
110827 {
110828 sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
110829 }
110830 break;
110831 case 311: /* add_column_fullname ::= fullname */
110832 {
110833 pParse->db->lookaside.bEnabled = 0;
110834 sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
110835 }
110836 break;
110837 case 314: /* cmd ::= create_vtab */
110838 {sqlite3VtabFinishParse(pParse,0);}
110839 break;
110840 case 315: /* cmd ::= create_vtab LP vtabarglist RP */
110841 {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
110842 break;
110843 case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
110844 {
110845 sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
110846 }
110847 break;
110848 case 319: /* vtabarg ::= */
110849 {sqlite3VtabArgInit(pParse);}
110850 break;
110851 case 321: /* vtabargtoken ::= ANY */
110852 case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322);
110853 case 323: /* lp ::= LP */ yytestcase(yyruleno==323);
110854 {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
110855 break;
110856 default:
110857 /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
110858 /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
@@ -110868,32 +111164,28 @@
110868 /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
110869 /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
110870 /* (44) type ::= */ yytestcase(yyruleno==44);
110871 /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
110872 /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
110873 /* (53) carglist ::= carglist carg */ yytestcase(yyruleno==53);
110874 /* (54) carglist ::= */ yytestcase(yyruleno==54);
110875 /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55);
110876 /* (56) carg ::= ccons */ yytestcase(yyruleno==56);
110877 /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
110878 /* (90) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==90);
110879 /* (91) conslist ::= conslist tcons */ yytestcase(yyruleno==91);
110880 /* (92) conslist ::= tcons */ yytestcase(yyruleno==92);
110881 /* (93) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
110882 /* (277) foreach_clause ::= */ yytestcase(yyruleno==277);
110883 /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278);
110884 /* (285) tridxby ::= */ yytestcase(yyruleno==285);
110885 /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303);
110886 /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304);
110887 /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312);
110888 /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313);
110889 /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317);
110890 /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
110891 /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
110892 /* (324) anylist ::= */ yytestcase(yyruleno==324);
110893 /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
110894 /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
110895 break;
110896 };
110897 yygoto = yyRuleInfo[yyruleno].lhs;
110898 yysize = yyRuleInfo[yyruleno].nrhs;
110899 yypParser->yyidx -= yysize;
@@ -113174,23 +113466,27 @@
113174 sqlite3_free(db);
113175 return SQLITE_OK;
113176 }
113177
113178 /*
113179 ** Rollback all database files.
 
 
 
113180 */
113181 SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){
113182 int i;
113183 int inTrans = 0;
113184 assert( sqlite3_mutex_held(db->mutex) );
113185 sqlite3BeginBenignMalloc();
113186 for(i=0; i<db->nDb; i++){
113187 if( db->aDb[i].pBt ){
113188 if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
 
113189 inTrans = 1;
113190 }
113191 sqlite3BtreeRollback(db->aDb[i].pBt);
113192 db->aDb[i].inTrans = 0;
113193 }
113194 }
113195 sqlite3VtabRollback(db);
113196 sqlite3EndBenignMalloc();
@@ -113241,16 +113537,25 @@
113241 /* SQLITE_AUTH */ "authorization denied",
113242 /* SQLITE_FORMAT */ "auxiliary database format error",
113243 /* SQLITE_RANGE */ "bind or column index out of range",
113244 /* SQLITE_NOTADB */ "file is encrypted or is not a database",
113245 };
113246 rc &= 0xff;
113247 if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
113248 return aMsg[rc];
113249 }else{
113250 return "unknown error";
 
 
 
 
 
 
 
 
113251 }
 
113252 }
113253
113254 /*
113255 ** This routine implements a busy callback that sleeps and tries
113256 ** again until a timeout value is reached. The timeout value is
@@ -113624,13 +113929,12 @@
113624 sqlite3_mutex_leave(db->mutex);
113625 return pOld;
113626 }
113627 #endif /* SQLITE_OMIT_TRACE */
113628
113629 /*** EXPERIMENTAL ***
113630 **
113631 ** Register a function to be invoked when a transaction comments.
113632 ** If the invoked function returns non-zero, then the commit becomes a
113633 ** rollback.
113634 */
113635 SQLITE_API void *sqlite3_commit_hook(
113636 sqlite3 *db, /* Attach the hook to this database */
@@ -115017,39 +115321,31 @@
115017 /*
115018 ** Invoke the xFileControl method on a particular database.
115019 */
115020 SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
115021 int rc = SQLITE_ERROR;
115022 int iDb;
 
115023 sqlite3_mutex_enter(db->mutex);
115024 if( zDbName==0 ){
115025 iDb = 0;
115026 }else{
115027 for(iDb=0; iDb<db->nDb; iDb++){
115028 if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break;
115029 }
115030 }
115031 if( iDb<db->nDb ){
115032 Btree *pBtree = db->aDb[iDb].pBt;
115033 if( pBtree ){
115034 Pager *pPager;
115035 sqlite3_file *fd;
115036 sqlite3BtreeEnter(pBtree);
115037 pPager = sqlite3BtreePager(pBtree);
115038 assert( pPager!=0 );
115039 fd = sqlite3PagerFile(pPager);
115040 assert( fd!=0 );
115041 if( op==SQLITE_FCNTL_FILE_POINTER ){
115042 *(sqlite3_file**)pArg = fd;
115043 rc = SQLITE_OK;
115044 }else if( fd->pMethods ){
115045 rc = sqlite3OsFileControl(fd, op, pArg);
115046 }else{
115047 rc = SQLITE_NOTFOUND;
115048 }
115049 sqlite3BtreeLeave(pBtree);
115050 }
115051 }
115052 sqlite3_mutex_leave(db->mutex);
115053 return rc;
115054 }
115055
@@ -115339,23 +115635,42 @@
115339 if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
115340 bDflt = v;
115341 }
115342 return bDflt;
115343 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115344
115345 /*
115346 ** Return the filename of the database associated with a database
115347 ** connection.
115348 */
115349 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
115350 int i;
115351 for(i=0; i<db->nDb; i++){
115352 if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){
115353 return sqlite3BtreeGetFilename(db->aDb[i].pBt);
115354 }
115355 }
115356 return 0;
 
 
 
 
115357 }
115358
115359 /************** End of main.c ************************************************/
115360 /************** Begin file notify.c ******************************************/
115361 /*
@@ -115761,11 +116076,11 @@
115761 ** option. But that functionality is no longer supported.
115762 **
115763 ** A doclist is stored like this:
115764 **
115765 ** array {
115766 ** varint docid;
115767 ** array { (position list for column 0)
115768 ** varint position; (2 more than the delta from previous position)
115769 ** }
115770 ** array {
115771 ** varint POS_COLUMN; (marks start of position list for new column)
@@ -115792,12 +116107,12 @@
115792 ** The 123 value is the first docid. For column zero in this document
115793 ** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
115794 ** at D signals the start of a new column; the 1 at E indicates that the
115795 ** new column is column number 1. There are two positions at 12 and 45
115796 ** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
115797 ** 234 at I is the next docid. It has one position 72 (72-2) and then
115798 ** terminates with the 0 at K.
115799 **
115800 ** A "position-list" is the list of positions for multiple columns for
115801 ** a single docid. A "column-list" is the set of positions for a single
115802 ** column. Hence, a position-list consists of one or more column-lists,
115803 ** a document record consists of a docid followed by a position-list and
@@ -115977,14 +116292,10 @@
115977 ** we simply write the new doclist. Segment merges overwrite older
115978 ** data for a particular docid with newer data, so deletes or updates
115979 ** will eventually overtake the earlier data and knock it out. The
115980 ** query logic likewise merges doclists so that newer data knocks out
115981 ** older data.
115982 **
115983 ** TODO(shess) Provide a VACUUM type operation to clear out all
115984 ** deletions and duplications. This would basically be a forced merge
115985 ** into a single segment.
115986 */
115987
115988 /************** Include fts3Int.h in the middle of fts3.c ********************/
115989 /************** Begin file fts3Int.h *****************************************/
115990 /*
@@ -116076,11 +116387,11 @@
116076 typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
116077
116078 struct sqlite3_tokenizer_module {
116079
116080 /*
116081 ** Structure version. Should always be set to 0.
116082 */
116083 int iVersion;
116084
116085 /*
116086 ** Create a new tokenizer. The values in the argv[] array are the
@@ -116157,10 +116468,19 @@
116157 const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
116158 int *piStartOffset, /* OUT: Byte offset of token in input buffer */
116159 int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
116160 int *piPosition /* OUT: Number of tokens returned before this one */
116161 );
 
 
 
 
 
 
 
 
 
116162 };
116163
116164 struct sqlite3_tokenizer {
116165 const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
116166 /* Tokenizer implementations will typically add additional fields */
@@ -116323,10 +116643,13 @@
116323
116324
116325 #ifndef MIN
116326 # define MIN(x,y) ((x)<(y)?(x):(y))
116327 #endif
 
 
 
116328
116329 /*
116330 ** Maximum length of a varint encoded integer. The varint format is different
116331 ** from that used by SQLite, so the maximum length is 10, not 9.
116332 */
@@ -116377,20 +116700,21 @@
116377 #ifdef SQLITE_COVERAGE_TEST
116378 # define ALWAYS(x) (1)
116379 # define NEVER(X) (0)
116380 #else
116381 # define ALWAYS(x) (x)
116382 # define NEVER(X) (x)
116383 #endif
116384
116385 /*
116386 ** Internal types used by SQLite.
116387 */
116388 typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
116389 typedef short int i16; /* 2-byte (or larger) signed integer */
116390 typedef unsigned int u32; /* 4-byte unsigned integer */
116391 typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
 
116392
116393 /*
116394 ** Macro used to suppress compiler warnings for unused parameters.
116395 */
116396 #define UNUSED_PARAMETER(x) (void)(x)
@@ -116448,55 +116772,64 @@
116448 const char *zName; /* virtual table name */
116449 int nColumn; /* number of named columns in virtual table */
116450 char **azColumn; /* column names. malloced */
116451 sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
116452 char *zContentTbl; /* content=xxx option, or NULL */
 
 
 
116453
116454 /* Precompiled statements used by the implementation. Each of these
116455 ** statements is run and reset within a single virtual table API call.
116456 */
116457 sqlite3_stmt *aStmt[27];
116458
116459 char *zReadExprlist;
116460 char *zWriteExprlist;
116461
116462 int nNodeSize; /* Soft limit for node size */
 
116463 u8 bHasStat; /* True if %_stat table exists */
116464 u8 bHasDocsize; /* True if %_docsize table exists */
116465 u8 bDescIdx; /* True if doclists are in reverse order */
 
116466 int nPgsz; /* Page size for host database */
116467 char *zSegmentsTbl; /* Name of %_segments table */
116468 sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
116469
116470 /* TODO: Fix the first paragraph of this comment.
116471 **
116472 ** The following hash table is used to buffer pending index updates during
116473 ** transactions. Variable nPendingData estimates the memory size of the
116474 ** pending data, including hash table overhead, but not malloc overhead.
116475 ** When nPendingData exceeds nMaxPendingData, the buffer is flushed
116476 ** automatically. Variable iPrevDocid is the docid of the most recently
116477 ** inserted record.
116478 **
116479 ** A single FTS4 table may have multiple full-text indexes. For each index
116480 ** there is an entry in the aIndex[] array. Index 0 is an index of all the
116481 ** terms that appear in the document set. Each subsequent index in aIndex[]
116482 ** is an index of prefixes of a specific length.
 
 
 
 
 
 
116483 */
116484 int nIndex; /* Size of aIndex[] */
116485 struct Fts3Index {
116486 int nPrefix; /* Prefix length (0 for main terms index) */
116487 Fts3Hash hPending; /* Pending terms table for this index */
116488 } *aIndex;
116489 int nMaxPendingData; /* Max pending data before flush to disk */
116490 int nPendingData; /* Current bytes of pending data */
116491 sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
 
116492
116493 #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
116494 /* State variables used for validating that the transaction control
116495 ** methods of the virtual table are called at appropriate times. These
116496 ** values do not contribution to the FTS computation; they are used for
116497 ** verifying the SQLite core.
116498 */
116499 int inTransaction; /* True after xBegin but before xCommit/xRollback */
116500 int mxSavepoint; /* Largest valid xSavepoint integer */
116501 #endif
116502 };
@@ -116511,10 +116844,11 @@
116511 i16 eSearch; /* Search strategy (see below) */
116512 u8 isEof; /* True if at End Of Results */
116513 u8 isRequireSeek; /* True if must seek pStmt to %_content row */
116514 sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
116515 Fts3Expr *pExpr; /* Parsed MATCH query string */
 
116516 int nPhrase; /* Number of matchable phrases in query */
116517 Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
116518 sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
116519 char *pNextId; /* Pointer into the body of aDoclist */
116520 char *aDoclist; /* List of docids for full-text queries */
@@ -116662,11 +116996,11 @@
116662 SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
116663 sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
116664 SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
116665 Fts3Table*,int,const char*,int,int,Fts3SegReader**);
116666 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
116667 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
116668 SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
116669 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
116670
116671 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
116672 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
@@ -116674,21 +117008,22 @@
116674 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
116675 SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
116676 SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
116677 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
116678 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
 
116679
116680 /* Special values interpreted by sqlite3SegReaderCursor() */
116681 #define FTS3_SEGCURSOR_PENDING -1
116682 #define FTS3_SEGCURSOR_ALL -2
116683
116684 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
116685 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
116686 SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
116687
116688 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
116689 Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *);
116690
116691 /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
116692 #define FTS3_SEGMENT_REQUIRE_POS 0x00000001
116693 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
116694 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
@@ -116725,19 +117060,22 @@
116725 int nTerm; /* Size of zTerm in bytes */
116726 char *aDoclist; /* Pointer to doclist buffer */
116727 int nDoclist; /* Size of aDoclist[] in bytes */
116728 };
116729
 
 
116730 /* fts3.c */
116731 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
116732 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
116733 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
116734 SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
116735 SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
116736 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
116737 SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
116738 SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
 
116739
116740 /* fts3_tokenizer.c */
116741 SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
116742 SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
116743 SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -116751,18 +117089,22 @@
116751 const char *, const char *, int, int
116752 );
116753 SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
116754
116755 /* fts3_expr.c */
116756 SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
116757 char **, int, int, int, const char *, int, Fts3Expr **
116758 );
116759 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
116760 #ifdef SQLITE_TEST
116761 SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
116762 SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
116763 #endif
 
 
 
 
116764
116765 /* fts3_aux.c */
116766 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
116767
116768 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
@@ -116954,10 +117296,11 @@
116954 }
116955 sqlite3_free(p->zSegmentsTbl);
116956 sqlite3_free(p->zReadExprlist);
116957 sqlite3_free(p->zWriteExprlist);
116958 sqlite3_free(p->zContentTbl);
 
116959
116960 /* Invoke the tokenizer destructor to free the tokenizer. */
116961 p->pTokenizer->pModule->xDestroy(p->pTokenizer);
116962
116963 sqlite3_free(p);
@@ -117030,11 +117373,13 @@
117030 if( *pRc==SQLITE_OK ){
117031 int i; /* Iterator variable */
117032 int rc; /* Return code */
117033 char *zSql; /* SQL statement passed to declare_vtab() */
117034 char *zCols; /* List of user defined columns */
 
117035
 
117036 sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
117037
117038 /* Create a list of user columns for the virtual table */
117039 zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
117040 for(i=1; zCols && i<p->nColumn; i++){
@@ -117041,11 +117386,12 @@
117041 zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
117042 }
117043
117044 /* Create the whole "CREATE TABLE" statement to pass to SQLite */
117045 zSql = sqlite3_mprintf(
117046 "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName
 
117047 );
117048 if( !zCols || !zSql ){
117049 rc = SQLITE_NOMEM;
117050 }else{
117051 rc = sqlite3_declare_vtab(p->db, zSql);
@@ -117054,10 +117400,22 @@
117054 sqlite3_free(zSql);
117055 sqlite3_free(zCols);
117056 *pRc = rc;
117057 }
117058 }
 
 
 
 
 
 
 
 
 
 
 
 
117059
117060 /*
117061 ** Create the backing store tables (%_content, %_segments and %_segdir)
117062 ** required by the FTS3 table passed as the only argument. This is done
117063 ** as part of the vtab xCreate() method.
@@ -117070,18 +117428,22 @@
117070 int rc = SQLITE_OK; /* Return code */
117071 int i; /* Iterator variable */
117072 sqlite3 *db = p->db; /* The database connection */
117073
117074 if( p->zContentTbl==0 ){
 
117075 char *zContentCols; /* Columns of %_content table */
117076
117077 /* Create a list of user columns for the content table */
117078 zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
117079 for(i=0; zContentCols && i<p->nColumn; i++){
117080 char *z = p->azColumn[i];
117081 zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
117082 }
 
 
 
117083 if( zContentCols==0 ) rc = SQLITE_NOMEM;
117084
117085 /* Create the content table */
117086 fts3DbExec(&rc, db,
117087 "CREATE TABLE %Q.'%q_content'(%s)",
@@ -117111,15 +117473,13 @@
117111 fts3DbExec(&rc, db,
117112 "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
117113 p->zDb, p->zName
117114 );
117115 }
 
117116 if( p->bHasStat ){
117117 fts3DbExec(&rc, db,
117118 "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);",
117119 p->zDb, p->zName
117120 );
117121 }
117122 return rc;
117123 }
117124
117125 /*
@@ -117222,11 +117582,11 @@
117222 ** memory.
117223 */
117224 static char *fts3QuoteId(char const *zInput){
117225 int nRet;
117226 char *zRet;
117227 nRet = 2 + strlen(zInput)*2 + 1;
117228 zRet = sqlite3_malloc(nRet);
117229 if( zRet ){
117230 int i;
117231 char *z = zRet;
117232 *(z++) = '"';
@@ -117277,18 +117637,24 @@
117277 }
117278 fts3Appendf(pRc, &zRet, "docid");
117279 for(i=0; i<p->nColumn; i++){
117280 fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
117281 }
 
 
 
117282 sqlite3_free(zFree);
117283 }else{
117284 fts3Appendf(pRc, &zRet, "rowid");
117285 for(i=0; i<p->nColumn; i++){
117286 fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]);
117287 }
 
 
 
117288 }
117289 fts3Appendf(pRc, &zRet, "FROM '%q'.'%q%s' AS x",
117290 p->zDb,
117291 (p->zContentTbl ? p->zContentTbl : p->zName),
117292 (p->zContentTbl ? "" : "_content")
117293 );
117294 return zRet;
@@ -117327,10 +117693,13 @@
117327 }
117328 fts3Appendf(pRc, &zRet, "?");
117329 for(i=0; i<p->nColumn; i++){
117330 fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
117331 }
 
 
 
117332 sqlite3_free(zFree);
117333 return zRet;
117334 }
117335
117336 /*
@@ -117469,11 +117838,11 @@
117469 ** space required to store a copy of each column name, including the
117470 ** nul-terminator byte. */
117471 nCol = sqlite3_column_count(pStmt);
117472 for(i=0; i<nCol; i++){
117473 const char *zCol = sqlite3_column_name(pStmt, i);
117474 nStr += strlen(zCol) + 1;
117475 }
117476
117477 /* Allocate and populate the array to return. */
117478 azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
117479 if( azCol==0 ){
@@ -117480,11 +117849,11 @@
117480 rc = SQLITE_NOMEM;
117481 }else{
117482 char *p = (char *)&azCol[nCol];
117483 for(i=0; i<nCol; i++){
117484 const char *zCol = sqlite3_column_name(pStmt, i);
117485 int n = strlen(zCol)+1;
117486 memcpy(p, zCol, n);
117487 azCol[i] = p;
117488 p += n;
117489 }
117490 }
@@ -117542,10 +117911,11 @@
117542 int bDescIdx = 0; /* True to store descending indexes */
117543 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
117544 char *zCompress = 0; /* compress=? parameter (or NULL) */
117545 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
117546 char *zContent = 0; /* content=? parameter (or NULL) */
 
117547
117548 assert( strlen(argv[0])==4 );
117549 assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
117550 || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
117551 );
@@ -117591,11 +117961,12 @@
117591 { "matchinfo", 9 }, /* 0 -> MATCHINFO */
117592 { "prefix", 6 }, /* 1 -> PREFIX */
117593 { "compress", 8 }, /* 2 -> COMPRESS */
117594 { "uncompress", 10 }, /* 3 -> UNCOMPRESS */
117595 { "order", 5 }, /* 4 -> ORDER */
117596 { "content", 7 } /* 5 -> CONTENT */
 
117597 };
117598
117599 int iOpt;
117600 if( !zVal ){
117601 rc = SQLITE_NOMEM;
@@ -117645,16 +118016,22 @@
117645 rc = SQLITE_ERROR;
117646 }
117647 bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
117648 break;
117649
117650 default: /* CONTENT */
117651 assert( iOpt==5 );
117652 sqlite3_free(zUncompress);
117653 zContent = zVal;
117654 zVal = 0;
117655 break;
 
 
 
 
 
 
 
117656 }
117657 }
117658 sqlite3_free(zVal);
117659 }
117660 }
@@ -117680,12 +118057,25 @@
117680 zUncompress = 0;
117681 if( nCol==0 ){
117682 sqlite3_free((void*)aCol);
117683 aCol = 0;
117684 rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117685 }
117686 assert( rc!=SQLITE_OK || nCol>0 );
117687 }
117688 if( rc!=SQLITE_OK ) goto fts3_init_out;
117689
117690 if( nCol==0 ){
117691 assert( nString==0 );
@@ -117726,13 +118116,17 @@
117726 p->azColumn = (char **)&p[1];
117727 p->pTokenizer = pTokenizer;
117728 p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
117729 p->bHasDocsize = (isFts4 && bNoDocsize==0);
117730 p->bHasStat = isFts4;
 
117731 p->bDescIdx = bDescIdx;
 
117732 p->zContentTbl = zContent;
 
117733 zContent = 0;
 
117734 TESTONLY( p->inTransaction = -1 );
117735 TESTONLY( p->mxSavepoint = -1 );
117736
117737 p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
117738 memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
@@ -117776,10 +118170,20 @@
117776 ** database. TODO: For xConnect(), it could verify that said tables exist.
117777 */
117778 if( isCreate ){
117779 rc = fts3CreateTables(p);
117780 }
 
 
 
 
 
 
 
 
 
 
117781
117782 /* Figure out the page-size for the database. This is required in order to
117783 ** estimate the cost of loading large doclists from the database. */
117784 fts3DatabasePageSize(&rc, p);
117785 p->nNodeSize = p->nPgsz-35;
@@ -117791,10 +118195,11 @@
117791 sqlite3_free(zPrefix);
117792 sqlite3_free(aIndex);
117793 sqlite3_free(zCompress);
117794 sqlite3_free(zUncompress);
117795 sqlite3_free(zContent);
 
117796 sqlite3_free((void *)aCol);
117797 if( rc!=SQLITE_OK ){
117798 if( p ){
117799 fts3DisconnectMethod((sqlite3_vtab *)p);
117800 }else if( pTokenizer ){
@@ -117842,10 +118247,11 @@
117842 */
117843 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
117844 Fts3Table *p = (Fts3Table *)pVTab;
117845 int i; /* Iterator variable */
117846 int iCons = -1; /* Index of constraint to use */
 
117847
117848 /* By default use a full table scan. This is an expensive option,
117849 ** so search through the constraints to see if a more efficient
117850 ** strategy is possible.
117851 */
@@ -117854,11 +118260,12 @@
117854 for(i=0; i<pInfo->nConstraint; i++){
117855 struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
117856 if( pCons->usable==0 ) continue;
117857
117858 /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
117859 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
 
117860 && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
117861 ){
117862 pInfo->idxNum = FTS3_DOCID_SEARCH;
117863 pInfo->estimatedCost = 1.0;
117864 iCons = i;
@@ -117877,18 +118284,27 @@
117877 && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
117878 ){
117879 pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
117880 pInfo->estimatedCost = 2.0;
117881 iCons = i;
117882 break;
 
 
 
 
 
 
117883 }
117884 }
117885
117886 if( iCons>=0 ){
117887 pInfo->aConstraintUsage[iCons].argvIndex = 1;
117888 pInfo->aConstraintUsage[iCons].omit = 1;
117889 }
 
 
 
117890
117891 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
117892 ** docid) order. Both ascending and descending are possible.
117893 */
117894 if( pInfo->nOrderBy==1 ){
@@ -118768,11 +119184,11 @@
118768 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
118769 }
118770 }
118771
118772 *paOut = aOut;
118773 *pnOut = (p-aOut);
118774 assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
118775 return SQLITE_OK;
118776 }
118777
118778 /*
@@ -118832,11 +119248,11 @@
118832 fts3PoslistCopy(0, &p2);
118833 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
118834 }
118835 }
118836
118837 *pnRight = p - aOut;
118838 }
118839
118840 /*
118841 ** Argument pList points to a position list nList bytes in size. This
118842 ** function checks to see if the position list contains any entries for
@@ -119034,10 +119450,11 @@
119034 ** This function returns SQLITE_OK if successful, or an SQLite error code
119035 ** otherwise.
119036 */
119037 static int fts3SegReaderCursor(
119038 Fts3Table *p, /* FTS3 table handle */
 
119039 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
119040 int iLevel, /* Level of segments to scan */
119041 const char *zTerm, /* Term to query for */
119042 int nTerm, /* Size of zTerm in bytes */
119043 int isPrefix, /* True for a prefix search */
@@ -119062,11 +119479,11 @@
119062 }
119063 }
119064
119065 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
119066 if( rc==SQLITE_OK ){
119067 rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt);
119068 }
119069
119070 while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
119071 Fts3SegReader *pSeg = 0;
119072
@@ -119107,10 +119524,11 @@
119107 ** Set up a cursor object for iterating through a full-text index or a
119108 ** single level therein.
119109 */
119110 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
119111 Fts3Table *p, /* FTS3 table handle */
 
119112 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
119113 int iLevel, /* Level of segments to scan */
119114 const char *zTerm, /* Term to query for */
119115 int nTerm, /* Size of zTerm in bytes */
119116 int isPrefix, /* True for a prefix search */
@@ -119124,18 +119542,13 @@
119124 );
119125 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
119126 assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
119127 assert( isPrefix==0 || isScan==0 );
119128
119129 /* "isScan" is only set to true by the ft4aux module, an ordinary
119130 ** full-text tables. */
119131 assert( isScan==0 || p->aIndex==0 );
119132
119133 memset(pCsr, 0, sizeof(Fts3MultiSegReader));
119134
119135 return fts3SegReaderCursor(
119136 p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
119137 );
119138 }
119139
119140 /*
119141 ** In addition to its current configuration, have the Fts3MultiSegReader
@@ -119143,15 +119556,18 @@
119143 **
119144 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
119145 */
119146 static int fts3SegReaderCursorAddZero(
119147 Fts3Table *p, /* FTS virtual table handle */
 
119148 const char *zTerm, /* Term to scan doclist of */
119149 int nTerm, /* Number of bytes in zTerm */
119150 Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
119151 ){
119152 return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr);
 
 
119153 }
119154
119155 /*
119156 ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
119157 ** if isPrefix is true, to scan the doclist for all terms for which
@@ -119183,32 +119599,35 @@
119183
119184 if( isPrefix ){
119185 for(i=1; bFound==0 && i<p->nIndex; i++){
119186 if( p->aIndex[i].nPrefix==nTerm ){
119187 bFound = 1;
119188 rc = sqlite3Fts3SegReaderCursor(
119189 p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr);
 
119190 pSegcsr->bLookup = 1;
119191 }
119192 }
119193
119194 for(i=1; bFound==0 && i<p->nIndex; i++){
119195 if( p->aIndex[i].nPrefix==nTerm+1 ){
119196 bFound = 1;
119197 rc = sqlite3Fts3SegReaderCursor(
119198 p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
119199 );
119200 if( rc==SQLITE_OK ){
119201 rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr);
 
 
119202 }
119203 }
119204 }
119205 }
119206
119207 if( bFound==0 ){
119208 rc = sqlite3Fts3SegReaderCursor(
119209 p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
119210 );
119211 pSegcsr->bLookup = !isPrefix;
119212 }
119213 }
119214
@@ -119359,11 +119778,11 @@
119359
119360 UNUSED_PARAMETER(idxStr);
119361 UNUSED_PARAMETER(nVal);
119362
119363 assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
119364 assert( nVal==0 || nVal==1 );
119365 assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
119366 assert( p->pSegments==0 );
119367
119368 /* In case the cursor has been used before, clear it now. */
119369 sqlite3_finalize(pCsr->pStmt);
@@ -119384,12 +119803,15 @@
119384
119385 if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
119386 return SQLITE_NOMEM;
119387 }
119388
119389 rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->bHasStat,
119390 p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
 
 
 
119391 );
119392 if( rc!=SQLITE_OK ){
119393 if( rc==SQLITE_ERROR ){
119394 static const char *zErr = "malformed MATCH expression: [%s]";
119395 p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
@@ -119456,37 +119878,56 @@
119456 }
119457
119458 /*
119459 ** This is the xColumn method, called by SQLite to request a value from
119460 ** the row that the supplied cursor currently points to.
 
 
 
 
 
 
 
119461 */
119462 static int fts3ColumnMethod(
119463 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
119464 sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
119465 int iCol /* Index of column to read value from */
119466 ){
119467 int rc = SQLITE_OK; /* Return Code */
119468 Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
119469 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
119470
119471 /* The column value supplied by SQLite must be in range. */
119472 assert( iCol>=0 && iCol<=p->nColumn+1 );
119473
119474 if( iCol==p->nColumn+1 ){
119475 /* This call is a request for the "docid" column. Since "docid" is an
119476 ** alias for "rowid", use the xRowid() method to obtain the value.
119477 */
119478 sqlite3_result_int64(pContext, pCsr->iPrevId);
119479 }else if( iCol==p->nColumn ){
119480 /* The extra column whose name is the same as the table.
119481 ** Return a blob which is a pointer to the cursor.
119482 */
119483 sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
 
119484 }else{
 
 
119485 rc = fts3CursorSeek(0, pCsr);
119486 if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
119487 sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
 
 
 
 
 
 
 
 
 
119488 }
119489 }
119490
119491 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
119492 return rc;
@@ -119509,26 +119950,61 @@
119509 /*
119510 ** Implementation of xSync() method. Flush the contents of the pending-terms
119511 ** hash-table to the database.
119512 */
119513 static int fts3SyncMethod(sqlite3_vtab *pVtab){
119514 int rc = sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab);
119515 sqlite3Fts3SegmentsClose((Fts3Table *)pVtab);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119516 return rc;
119517 }
119518
119519 /*
119520 ** Implementation of xBegin() method. This is a no-op.
119521 */
119522 static int fts3BeginMethod(sqlite3_vtab *pVtab){
119523 TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
119524 UNUSED_PARAMETER(pVtab);
119525 assert( p->pSegments==0 );
119526 assert( p->nPendingData==0 );
119527 assert( p->inTransaction!=1 );
119528 TESTONLY( p->inTransaction = 1 );
119529 TESTONLY( p->mxSavepoint = -1; );
 
119530 return SQLITE_OK;
119531 }
119532
119533 /*
119534 ** Implementation of xCommit() method. This is a no-op. The contents of
@@ -119819,15 +120295,19 @@
119819 ** The xSavepoint() method.
119820 **
119821 ** Flush the contents of the pending-terms table to disk.
119822 */
119823 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
 
119824 UNUSED_PARAMETER(iSavepoint);
119825 assert( ((Fts3Table *)pVtab)->inTransaction );
119826 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
119827 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
119828 return fts3SyncMethod(pVtab);
 
 
 
119829 }
119830
119831 /*
119832 ** The xRelease() method.
119833 **
@@ -120183,11 +120663,11 @@
120183
120184 assert( iPrev>=0 );
120185 fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
120186 sqlite3_free(aPoslist);
120187 aPoslist = pList;
120188 nPoslist = aOut - aPoslist;
120189 if( nPoslist==0 ){
120190 sqlite3_free(aPoslist);
120191 pPhrase->doclist.pList = 0;
120192 pPhrase->doclist.nList = 0;
120193 return SQLITE_OK;
@@ -120227,11 +120707,11 @@
120227 }
120228
120229 pPhrase->doclist.pList = aOut;
120230 if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
120231 pPhrase->doclist.bFreeList = 1;
120232 pPhrase->doclist.nList = (aOut - pPhrase->doclist.pList);
120233 }else{
120234 sqlite3_free(aOut);
120235 pPhrase->doclist.pList = 0;
120236 pPhrase->doclist.nList = 0;
120237 }
@@ -120323,11 +120803,11 @@
120323 fts3PoslistCopy(0, &pDocid);
120324 while( pDocid<pEnd && *pDocid==0 ) pDocid++;
120325 iMul = (bDescIdx ? -1 : 1);
120326 }
120327
120328 *pnList = pEnd - pNext;
120329 *ppIter = pNext;
120330 *piDocid = iDocid;
120331 }else{
120332 int iMul = (bDescIdx ? -1 : 1);
120333 sqlite3_int64 iDelta;
@@ -120337,11 +120817,11 @@
120337 if( p==aDoclist ){
120338 *pbEof = 1;
120339 }else{
120340 char *pSave = p;
120341 fts3ReversePoslist(aDoclist, &p);
120342 *pnList = (pSave - p);
120343 }
120344 *ppIter = p;
120345 }
120346 }
120347
@@ -120397,11 +120877,11 @@
120397 }else{
120398 pDL->iDocid -= iDelta;
120399 }
120400 pDL->pList = pIter;
120401 fts3PoslistCopy(0, &pIter);
120402 pDL->nList = (pIter - pDL->pList);
120403
120404 /* pIter now points just past the 0x00 that terminates the position-
120405 ** list for document pDL->iDocid. However, if this position-list was
120406 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
120407 ** point to the start of the next docid value. The following line deals
@@ -120738,11 +121218,11 @@
120738
120739 /* Allocate a MultiSegReader for each token in the expression. */
120740 fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
120741
120742 /* Determine which, if any, tokens in the expression should be deferred. */
120743 if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){
120744 Fts3TokenAndCost *aTC;
120745 Fts3Expr **apOr;
120746 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
120747 sizeof(Fts3TokenAndCost) * nToken
120748 + sizeof(Fts3Expr *) * nOr * 2
@@ -120755,12 +121235,12 @@
120755 int ii;
120756 Fts3TokenAndCost *pTC = aTC;
120757 Fts3Expr **ppOr = apOr;
120758
120759 fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
120760 nToken = pTC-aTC;
120761 nOr = ppOr-apOr;
120762
120763 if( rc==SQLITE_OK ){
120764 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
120765 for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
120766 rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
@@ -120828,11 +121308,11 @@
120828 p2 = pOut = pPhrase->doclist.pList;
120829 res = fts3PoslistNearMerge(
120830 &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
120831 );
120832 if( res ){
120833 nNew = (pOut - pPhrase->doclist.pList) - 1;
120834 assert( pPhrase->doclist.pList[nNew]=='\0' );
120835 assert( nNew<=pPhrase->doclist.nList && nNew>0 );
120836 memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
120837 pPhrase->doclist.nList = nNew;
120838 *paPoslist = pPhrase->doclist.pList;
@@ -121553,10 +122033,11 @@
121553 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
121554 pPhrase->aToken[i].pSegcsr = 0;
121555 }
121556 }
121557 }
 
121558
121559 /*
121560 ** Return SQLITE_CORRUPT_VTAB.
121561 */
121562 #ifdef SQLITE_DEBUG
@@ -121661,13 +122142,13 @@
121661 );
121662 return SQLITE_ERROR;
121663 }
121664
121665 zDb = argv[1];
121666 nDb = strlen(zDb);
121667 zFts3 = argv[3];
121668 nFts3 = strlen(zFts3);
121669
121670 rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
121671 if( rc!=SQLITE_OK ) return rc;
121672
121673 nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
@@ -121958,11 +122439,11 @@
121958 pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
121959 pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
121960 if( pCsr->zStop==0 ) return SQLITE_NOMEM;
121961 }
121962
121963 rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL,
121964 pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
121965 );
121966 if( rc==SQLITE_OK ){
121967 rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
121968 }
@@ -122150,10 +122631,11 @@
122150 ** zero.
122151 */
122152 typedef struct ParseContext ParseContext;
122153 struct ParseContext {
122154 sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
 
122155 const char **azCol; /* Array of column names for fts3 table */
122156 int bFts4; /* True to allow FTS4-only syntax */
122157 int nCol; /* Number of entries in azCol[] */
122158 int iDefaultCol; /* Default column to query */
122159 int isNot; /* True if getNextNode() sees a unary - */
@@ -122185,10 +122667,37 @@
122185 void *pRet = sqlite3_malloc(nByte);
122186 if( pRet ) memset(pRet, 0, nByte);
122187 return pRet;
122188 }
122189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122190
122191 /*
122192 ** Extract the next token from buffer z (length n) using the tokenizer
122193 ** and other information (column names etc.) in pParse. Create an Fts3Expr
122194 ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -122212,19 +122721,17 @@
122212 int rc;
122213 sqlite3_tokenizer_cursor *pCursor;
122214 Fts3Expr *pRet = 0;
122215 int nConsumed = 0;
122216
122217 rc = pModule->xOpen(pTokenizer, z, n, &pCursor);
122218 if( rc==SQLITE_OK ){
122219 const char *zToken;
122220 int nToken, iStart, iEnd, iPosition;
122221 int nByte; /* total space to allocate */
122222
122223 pCursor->pTokenizer = pTokenizer;
122224 rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
122225
122226 if( rc==SQLITE_OK ){
122227 nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
122228 pRet = (Fts3Expr *)fts3MallocZero(nByte);
122229 if( !pRet ){
122230 rc = SQLITE_NOMEM;
@@ -122326,14 +122833,14 @@
122326 **
122327 ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
122328 ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
122329 ** structures.
122330 */
122331 rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor);
 
122332 if( rc==SQLITE_OK ){
122333 int ii;
122334 pCursor->pTokenizer = pTokenizer;
122335 for(ii=0; rc==SQLITE_OK; ii++){
122336 const char *zByte;
122337 int nByte, iBegin, iEnd, iPos;
122338 rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
122339 if( rc==SQLITE_OK ){
@@ -122803,10 +123310,11 @@
122803 ** specified as part of the query string), or -1 if tokens may by default
122804 ** match any table column.
122805 */
122806 SQLITE_PRIVATE int sqlite3Fts3ExprParse(
122807 sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
 
122808 char **azCol, /* Array of column names for fts3 table */
122809 int bFts4, /* True to allow FTS4-only syntax */
122810 int nCol, /* Number of entries in azCol[] */
122811 int iDefaultCol, /* Default column to query */
122812 const char *z, int n, /* Text of MATCH query */
@@ -122813,15 +123321,17 @@
122813 Fts3Expr **ppExpr /* OUT: Parsed query structure */
122814 ){
122815 int nParsed;
122816 int rc;
122817 ParseContext sParse;
 
 
122818 sParse.pTokenizer = pTokenizer;
 
122819 sParse.azCol = (const char **)azCol;
122820 sParse.nCol = nCol;
122821 sParse.iDefaultCol = iDefaultCol;
122822 sParse.nNest = 0;
122823 sParse.bFts4 = bFts4;
122824 if( z==0 ){
122825 *ppExpr = 0;
122826 return SQLITE_OK;
122827 }
@@ -123008,11 +123518,11 @@
123008 for(ii=0; ii<nCol; ii++){
123009 azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
123010 }
123011
123012 rc = sqlite3Fts3ExprParse(
123013 pTokenizer, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
123014 );
123015 if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
123016 sqlite3_result_error(context, "Error parsing expression", -1);
123017 }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
123018 sqlite3_result_error_nomem(context);
@@ -124057,10 +124567,11 @@
124057 porterCreate,
124058 porterDestroy,
124059 porterOpen,
124060 porterClose,
124061 porterNext,
 
124062 };
124063
124064 /*
124065 ** Allocate a new porter tokenizer. Return a pointer to the new
124066 ** tokenizer in *ppModule
@@ -124362,15 +124873,14 @@
124362 if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
124363 zErr = "error in xCreate()";
124364 goto finish;
124365 }
124366 pTokenizer->pModule = p;
124367 if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){
124368 zErr = "error in xOpen()";
124369 goto finish;
124370 }
124371 pCsr->pTokenizer = pTokenizer;
124372
124373 while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
124374 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
124375 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
124376 zToken = &zInput[iStart];
@@ -124782,10 +125292,11 @@
124782 simpleCreate,
124783 simpleDestroy,
124784 simpleOpen,
124785 simpleClose,
124786 simpleNext,
 
124787 };
124788
124789 /*
124790 ** Allocate a new simple tokenizer. Return a pointer to the new
124791 ** tokenizer in *ppModule
@@ -124823,10 +125334,13 @@
124823
124824 /* #include <string.h> */
124825 /* #include <assert.h> */
124826 /* #include <stdlib.h> */
124827
 
 
 
124828 /*
124829 ** When full-text index nodes are loaded from disk, the buffer that they
124830 ** are loaded into has the following number of bytes of padding at the end
124831 ** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
124832 ** of 920 bytes is allocated for it.
@@ -124861,10 +125375,33 @@
124861 # define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
124862 #else
124863 # define FTS3_NODE_CHUNKSIZE (4*1024)
124864 # define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
124865 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124866
124867 typedef struct PendingList PendingList;
124868 typedef struct SegmentNode SegmentNode;
124869 typedef struct SegmentWriter SegmentWriter;
124870
@@ -125023,17 +125560,26 @@
125023 #define SQL_DELETE_SEGMENTS_RANGE 17
125024 #define SQL_CONTENT_INSERT 18
125025 #define SQL_DELETE_DOCSIZE 19
125026 #define SQL_REPLACE_DOCSIZE 20
125027 #define SQL_SELECT_DOCSIZE 21
125028 #define SQL_SELECT_DOCTOTAL 22
125029 #define SQL_REPLACE_DOCTOTAL 23
125030
125031 #define SQL_SELECT_ALL_PREFIX_LEVEL 24
125032 #define SQL_DELETE_ALL_TERMS_SEGDIR 25
125033
125034 #define SQL_DELETE_SEGDIR_RANGE 26
 
 
 
 
 
 
 
 
 
 
125035
125036 /*
125037 ** This function is used to obtain an SQLite prepared statement handle
125038 ** for the statement identified by the second argument. If successful,
125039 ** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -125058,13 +125604,13 @@
125058 /* 4 */ "DELETE FROM %Q.'%q_segdir'",
125059 /* 5 */ "DELETE FROM %Q.'%q_docsize'",
125060 /* 6 */ "DELETE FROM %Q.'%q_stat'",
125061 /* 7 */ "SELECT %s WHERE rowid=?",
125062 /* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
125063 /* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
125064 /* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
125065 /* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
125066
125067 /* Return segments in order from oldest to newest.*/
125068 /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
125069 "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
125070 /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
@@ -125078,17 +125624,65 @@
125078 /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
125079 /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
125080 /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
125081 /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
125082 /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
125083 /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
125084 /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
125085 /* 24 */ "",
125086 /* 25 */ "",
125087
125088 /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
 
125089
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125090 };
125091 int rc = SQLITE_OK;
125092 sqlite3_stmt *pStmt;
125093
125094 assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
@@ -125121,27 +125715,23 @@
125121 }
125122 }
125123 *pp = pStmt;
125124 return rc;
125125 }
 
125126
125127 static int fts3SelectDocsize(
125128 Fts3Table *pTab, /* FTS3 table handle */
125129 int eStmt, /* Either SQL_SELECT_DOCSIZE or DOCTOTAL */
125130 sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */
125131 sqlite3_stmt **ppStmt /* OUT: Statement handle */
125132 ){
125133 sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */
125134 int rc; /* Return code */
125135
125136 assert( eStmt==SQL_SELECT_DOCSIZE || eStmt==SQL_SELECT_DOCTOTAL );
125137
125138 rc = fts3SqlStmt(pTab, eStmt, &pStmt, 0);
125139 if( rc==SQLITE_OK ){
125140 if( eStmt==SQL_SELECT_DOCSIZE ){
125141 sqlite3_bind_int64(pStmt, 1, iDocid);
125142 }
125143 rc = sqlite3_step(pStmt);
125144 if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
125145 rc = sqlite3_reset(pStmt);
125146 if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
125147 pStmt = 0;
@@ -125156,19 +125746,33 @@
125156
125157 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(
125158 Fts3Table *pTab, /* Fts3 table handle */
125159 sqlite3_stmt **ppStmt /* OUT: Statement handle */
125160 ){
125161 return fts3SelectDocsize(pTab, SQL_SELECT_DOCTOTAL, 0, ppStmt);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125162 }
125163
125164 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(
125165 Fts3Table *pTab, /* Fts3 table handle */
125166 sqlite3_int64 iDocid, /* Docid to read size data for */
125167 sqlite3_stmt **ppStmt /* OUT: Statement handle */
125168 ){
125169 return fts3SelectDocsize(pTab, SQL_SELECT_DOCSIZE, iDocid, ppStmt);
125170 }
125171
125172 /*
125173 ** Similar to fts3SqlStmt(). Except, after binding the parameters in
125174 ** array apVal[] to the SQL statement identified by eStmt, the statement
@@ -125229,10 +125833,48 @@
125229 rc = SQLITE_OK;
125230 }
125231
125232 return rc;
125233 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125234
125235 /*
125236 ** Set *ppStmt to a statement handle that may be used to iterate through
125237 ** all rows in the %_segdir table, from oldest to newest. If successful,
125238 ** return SQLITE_OK. If an error occurs while preparing the statement,
@@ -125249,12 +125891,13 @@
125249 ** 3: end_block
125250 ** 4: root
125251 */
125252 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
125253 Fts3Table *p, /* FTS3 table */
 
125254 int iIndex, /* Index for p->aIndex[] */
125255 int iLevel, /* Level to select */
125256 sqlite3_stmt **ppStmt /* OUT: Compiled statement */
125257 ){
125258 int rc;
125259 sqlite3_stmt *pStmt = 0;
125260
@@ -125264,18 +125907,20 @@
125264
125265 if( iLevel<0 ){
125266 /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
125267 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
125268 if( rc==SQLITE_OK ){
125269 sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
125270 sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1);
 
 
125271 }
125272 }else{
125273 /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
125274 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
125275 if( rc==SQLITE_OK ){
125276 sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL);
125277 }
125278 }
125279 *ppStmt = pStmt;
125280 return rc;
125281 }
@@ -125437,10 +126082,11 @@
125437 **
125438 ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
125439 */
125440 static int fts3PendingTermsAdd(
125441 Fts3Table *p, /* Table into which text will be inserted */
 
125442 const char *zText, /* Text of document to be inserted */
125443 int iCol, /* Column into which text is being inserted */
125444 u32 *pnWord /* OUT: Number of tokens inserted */
125445 ){
125446 int rc;
@@ -125466,15 +126112,14 @@
125466 if( zText==0 ){
125467 *pnWord = 0;
125468 return SQLITE_OK;
125469 }
125470
125471 rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
125472 if( rc!=SQLITE_OK ){
125473 return rc;
125474 }
125475 pCsr->pTokenizer = pTokenizer;
125476
125477 xNext = pModule->xNext;
125478 while( SQLITE_OK==rc
125479 && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
125480 ){
@@ -125513,22 +126158,32 @@
125513 /*
125514 ** Calling this function indicates that subsequent calls to
125515 ** fts3PendingTermsAdd() are to add term/position-list pairs for the
125516 ** contents of the document with docid iDocid.
125517 */
125518 static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){
 
 
 
 
 
 
125519 /* TODO(shess) Explore whether partially flushing the buffer on
125520 ** forced-flush would provide better performance. I suspect that if
125521 ** we ordered the doclists by size and flushed the largest until the
125522 ** buffer was half empty, that would let the less frequent terms
125523 ** generate longer doclists.
125524 */
125525 if( iDocid<=p->iPrevDocid || p->nPendingData>p->nMaxPendingData ){
 
 
 
125526 int rc = sqlite3Fts3PendingTermsFlush(p);
125527 if( rc!=SQLITE_OK ) return rc;
125528 }
125529 p->iPrevDocid = iDocid;
 
125530 return SQLITE_OK;
125531 }
125532
125533 /*
125534 ** Discard the contents of the pending-terms hash tables.
@@ -125553,15 +126208,20 @@
125553 ** pendingTerms hash table.
125554 **
125555 ** Argument apVal is the same as the similarly named argument passed to
125556 ** fts3InsertData(). Parameter iDocid is the docid of the new row.
125557 */
125558 static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
 
 
 
 
 
125559 int i; /* Iterator variable */
125560 for(i=2; i<p->nColumn+2; i++){
125561 const char *zText = (const char *)sqlite3_value_text(apVal[i]);
125562 int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
125563 if( rc!=SQLITE_OK ){
125564 return rc;
125565 }
125566 aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
125567 }
@@ -125578,10 +126238,11 @@
125578 ** apVal[2] Left-most user-defined column
125579 ** ...
125580 ** apVal[p->nColumn+1] Right-most user-defined column
125581 ** apVal[p->nColumn+2] Hidden column with same name as table
125582 ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid)
 
125583 */
125584 static int fts3InsertData(
125585 Fts3Table *p, /* Full-text table */
125586 sqlite3_value **apVal, /* Array of values to insert */
125587 sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */
@@ -125608,13 +126269,17 @@
125608 **
125609 ** The statement features N '?' variables, where N is the number of user
125610 ** defined columns in the FTS3 table, plus one for the docid field.
125611 */
125612 rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
125613 if( rc!=SQLITE_OK ){
125614 return rc;
 
 
 
125615 }
 
125616
125617 /* There is a quirk here. The users INSERT statement may have specified
125618 ** a value for the "rowid" field, for the "docid" field, or for both.
125619 ** Which is a problem, since "rowid" and "docid" are aliases for the
125620 ** same value. For example:
@@ -125669,10 +126334,19 @@
125669 if( p->bHasStat ){
125670 fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
125671 }
125672 return rc;
125673 }
 
 
 
 
 
 
 
 
 
125674
125675 /*
125676 ** The first element in the apVal[] array is assumed to contain the docid
125677 ** (an integer) of a row about to be deleted. Remove all terms from the
125678 ** full-text index.
@@ -125689,19 +126363,21 @@
125689 if( *pRC ) return;
125690 rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
125691 if( rc==SQLITE_OK ){
125692 if( SQLITE_ROW==sqlite3_step(pSelect) ){
125693 int i;
125694 for(i=1; i<=p->nColumn; i++){
 
 
125695 const char *zText = (const char *)sqlite3_column_text(pSelect, i);
125696 rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]);
125697 if( rc!=SQLITE_OK ){
125698 sqlite3_reset(pSelect);
125699 *pRC = rc;
125700 return;
125701 }
125702 aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
 
 
 
 
 
125703 }
125704 }
125705 rc = sqlite3_reset(pSelect);
125706 }else{
125707 sqlite3_reset(pSelect);
@@ -125711,11 +126387,11 @@
125711
125712 /*
125713 ** Forward declaration to account for the circular dependency between
125714 ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
125715 */
125716 static int fts3SegmentMerge(Fts3Table *, int, int);
125717
125718 /*
125719 ** This function allocates a new level iLevel index in the segdir table.
125720 ** Usually, indexes are allocated within a level sequentially starting
125721 ** with 0, so the allocated index is one greater than the value returned
@@ -125730,22 +126406,28 @@
125730 ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
125731 ** returned. Otherwise, an SQLite error code is returned.
125732 */
125733 static int fts3AllocateSegdirIdx(
125734 Fts3Table *p,
 
125735 int iIndex, /* Index for p->aIndex */
125736 int iLevel,
125737 int *piIdx
125738 ){
125739 int rc; /* Return Code */
125740 sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
125741 int iNext = 0; /* Result of query pNextIdx */
125742
 
 
 
125743 /* Set variable iNext to the next available segdir index at level iLevel. */
125744 rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
125745 if( rc==SQLITE_OK ){
125746 sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
 
 
125747 if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
125748 iNext = sqlite3_column_int(pNextIdx, 0);
125749 }
125750 rc = sqlite3_reset(pNextIdx);
125751 }
@@ -125755,11 +126437,12 @@
125755 ** full, merge all segments in level iLevel into a single iLevel+1
125756 ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
125757 ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
125758 */
125759 if( iNext>=FTS3_MERGE_COUNT ){
125760 rc = fts3SegmentMerge(p, iIndex, iLevel);
 
125761 *piIdx = 0;
125762 }else{
125763 *piIdx = iNext;
125764 }
125765 }
@@ -125802,11 +126485,11 @@
125802 int *pnLoad /* OUT: Bytes actually loaded */
125803 ){
125804 int rc; /* Return code */
125805
125806 /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
125807 assert( pnBlob);
125808
125809 if( p->pSegments ){
125810 rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
125811 }else{
125812 if( 0==p->zSegmentsTbl ){
@@ -126143,11 +126826,11 @@
126143 int nOvfl = 0;
126144 int ii;
126145 int rc = SQLITE_OK;
126146 int pgsz = p->nPgsz;
126147
126148 assert( p->bHasStat );
126149 assert( pgsz>0 );
126150
126151 for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
126152 Fts3SegReader *pReader = pMsr->apSegment[ii];
126153 if( !fts3SegReaderIsPending(pReader)
@@ -126500,17 +127183,38 @@
126500 sqlite3_step(pStmt);
126501 rc = sqlite3_reset(pStmt);
126502 }
126503 return rc;
126504 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126505
126506 /*
126507 ** Insert a record into the %_segdir table.
126508 */
126509 static int fts3WriteSegdir(
126510 Fts3Table *p, /* Virtual table handle */
126511 int iLevel, /* Value for "level" field */
126512 int iIdx, /* Value for "idx" field */
126513 sqlite3_int64 iStartBlock, /* Value for "start_block" field */
126514 sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
126515 sqlite3_int64 iEndBlock, /* Value for "end_block" field */
126516 char *zRoot, /* Blob value for "root" field */
@@ -126517,11 +127221,11 @@
126517 int nRoot /* Number of bytes in buffer zRoot */
126518 ){
126519 sqlite3_stmt *pStmt;
126520 int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0);
126521 if( rc==SQLITE_OK ){
126522 sqlite3_bind_int(pStmt, 1, iLevel);
126523 sqlite3_bind_int(pStmt, 2, iIdx);
126524 sqlite3_bind_int64(pStmt, 3, iStartBlock);
126525 sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
126526 sqlite3_bind_int64(pStmt, 5, iEndBlock);
126527 sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
@@ -126817,10 +127521,11 @@
126817 int rc;
126818
126819 /* The current leaf node is full. Write it out to the database. */
126820 rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
126821 if( rc!=SQLITE_OK ) return rc;
 
126822
126823 /* Add the current term to the interior node tree. The term added to
126824 ** the interior tree must:
126825 **
126826 ** a) be greater than the largest term on the leaf node just written
@@ -126900,11 +127605,11 @@
126900 ** returned. Otherwise, an SQLite error code.
126901 */
126902 static int fts3SegWriterFlush(
126903 Fts3Table *p, /* Virtual table handle */
126904 SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
126905 int iLevel, /* Value for 'level' column of %_segdir */
126906 int iIdx /* Value for 'idx' column of %_segdir */
126907 ){
126908 int rc; /* Return code */
126909 if( pWriter->pTree ){
126910 sqlite3_int64 iLast = 0; /* Largest block id written to database */
@@ -126925,10 +127630,11 @@
126925 }else{
126926 /* The entire tree fits on the root node. Write it to the segdir table. */
126927 rc = fts3WriteSegdir(
126928 p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
126929 }
 
126930 return rc;
126931 }
126932
126933 /*
126934 ** Release all memory held by the SegmentWriter object passed as the
@@ -126978,11 +127684,16 @@
126978 **
126979 ** Segment levels are stored in the 'level' column of the %_segdir table.
126980 **
126981 ** Return SQLITE_OK if successful, or an SQLite error code if not.
126982 */
126983 static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){
 
 
 
 
 
126984 sqlite3_stmt *pStmt;
126985 int rc;
126986 assert( iIndex>=0 && iIndex<p->nIndex );
126987
126988 /* Set pStmt to the compiled version of:
@@ -126991,17 +127702,42 @@
126991 **
126992 ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
126993 */
126994 rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
126995 if( rc!=SQLITE_OK ) return rc;
126996 sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
126997 sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1);
 
 
126998 if( SQLITE_ROW==sqlite3_step(pStmt) ){
126999 *pnMax = sqlite3_column_int(pStmt, 0);
127000 }
127001 return sqlite3_reset(pStmt);
127002 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127003
127004 /*
127005 ** This function is used after merging multiple segments into a single large
127006 ** segment to delete the old, now redundant, segment b-trees. Specifically,
127007 ** it:
@@ -127015,44 +127751,42 @@
127015 **
127016 ** SQLITE_OK is returned if successful, otherwise an SQLite error code.
127017 */
127018 static int fts3DeleteSegdir(
127019 Fts3Table *p, /* Virtual table handle */
 
127020 int iIndex, /* Index for p->aIndex */
127021 int iLevel, /* Level of %_segdir entries to delete */
127022 Fts3SegReader **apSegment, /* Array of SegReader objects */
127023 int nReader /* Size of array apSegment */
127024 ){
127025 int rc; /* Return Code */
127026 int i; /* Iterator variable */
127027 sqlite3_stmt *pDelete; /* SQL statement to delete rows */
127028
127029 rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
127030 for(i=0; rc==SQLITE_OK && i<nReader; i++){
127031 Fts3SegReader *pSegment = apSegment[i];
127032 if( pSegment->iStartBlock ){
127033 sqlite3_bind_int64(pDelete, 1, pSegment->iStartBlock);
127034 sqlite3_bind_int64(pDelete, 2, pSegment->iEndBlock);
127035 sqlite3_step(pDelete);
127036 rc = sqlite3_reset(pDelete);
127037 }
127038 }
127039 if( rc!=SQLITE_OK ){
127040 return rc;
127041 }
127042
127043 assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
127044 if( iLevel==FTS3_SEGCURSOR_ALL ){
127045 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
127046 if( rc==SQLITE_OK ){
127047 sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL);
127048 sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1);
 
 
127049 }
127050 }else{
127051 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
127052 if( rc==SQLITE_OK ){
127053 sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel);
 
 
127054 }
127055 }
127056
127057 if( rc==SQLITE_OK ){
127058 sqlite3_step(pDelete);
@@ -127517,27 +128251,32 @@
127517 ** If this function is called with iLevel<0, but there is only one
127518 ** segment in the database, SQLITE_DONE is returned immediately.
127519 ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
127520 ** an SQLite error code is returned.
127521 */
127522 static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){
 
 
 
 
 
127523 int rc; /* Return code */
127524 int iIdx = 0; /* Index of new segment */
127525 int iNewLevel = 0; /* Level/index to create new segment at */
127526 SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
127527 Fts3SegFilter filter; /* Segment term filter condition */
127528 Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
127529 int bIgnoreEmpty = 0; /* True to ignore empty segments */
127530
127531 assert( iLevel==FTS3_SEGCURSOR_ALL
127532 || iLevel==FTS3_SEGCURSOR_PENDING
127533 || iLevel>=0
127534 );
127535 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
127536 assert( iIndex>=0 && iIndex<p->nIndex );
127537
127538 rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr);
127539 if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
127540
127541 if( iLevel==FTS3_SEGCURSOR_ALL ){
127542 /* This call is to merge all segments in the database to a single
127543 ** segment. The level of the new segment is equal to the the numerically
@@ -127545,28 +128284,28 @@
127545 ** index. The idx of the new segment is always 0. */
127546 if( csr.nSegment==1 ){
127547 rc = SQLITE_DONE;
127548 goto finished;
127549 }
127550 rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel);
127551 bIgnoreEmpty = 1;
127552
127553 }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
127554 iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL;
127555 rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx);
127556 }else{
127557 /* This call is to merge all segments at level iLevel. find the next
127558 ** available segment index at level iLevel+1. The call to
127559 ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
127560 ** a single iLevel+2 segment if necessary. */
127561 rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx);
127562 iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1;
127563 }
127564 if( rc!=SQLITE_OK ) goto finished;
127565 assert( csr.nSegment>0 );
127566 assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) );
127567 assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) );
127568
127569 memset(&filter, 0, sizeof(Fts3SegFilter));
127570 filter.flags = FTS3_SEGMENT_REQUIRE_POS;
127571 filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
127572
@@ -127579,11 +128318,13 @@
127579 }
127580 if( rc!=SQLITE_OK ) goto finished;
127581 assert( pWriter );
127582
127583 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
127584 rc = fts3DeleteSegdir(p, iIndex, iLevel, csr.apSegment, csr.nSegment);
 
 
127585 if( rc!=SQLITE_OK ) goto finished;
127586 }
127587 rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
127588
127589 finished:
@@ -127597,15 +128338,32 @@
127597 ** Flush the contents of pendingTerms to level 0 segments.
127598 */
127599 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
127600 int rc = SQLITE_OK;
127601 int i;
 
127602 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
127603 rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING);
127604 if( rc==SQLITE_DONE ) rc = SQLITE_OK;
127605 }
127606 sqlite3Fts3PendingTermsClear(p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127607 return rc;
127608 }
127609
127610 /*
127611 ** Encode N integers as varints into a blob.
@@ -127712,16 +128470,17 @@
127712 if( a==0 ){
127713 *pRC = SQLITE_NOMEM;
127714 return;
127715 }
127716 pBlob = (char*)&a[nStat];
127717 rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
127718 if( rc ){
127719 sqlite3_free(a);
127720 *pRC = rc;
127721 return;
127722 }
 
127723 if( sqlite3_step(pStmt)==SQLITE_ROW ){
127724 fts3DecodeIntArray(nStat, a,
127725 sqlite3_column_blob(pStmt, 0),
127726 sqlite3_column_bytes(pStmt, 0));
127727 }else{
@@ -127741,33 +128500,51 @@
127741 x = x + aSzIns[i] - aSzDel[i];
127742 }
127743 a[i+1] = x;
127744 }
127745 fts3EncodeIntArray(nStat, a, pBlob, &nBlob);
127746 rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0);
127747 if( rc ){
127748 sqlite3_free(a);
127749 *pRC = rc;
127750 return;
127751 }
127752 sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
 
127753 sqlite3_step(pStmt);
127754 *pRC = sqlite3_reset(pStmt);
127755 sqlite3_free(a);
127756 }
127757
 
 
 
 
127758 static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
127759 int i;
127760 int bSeenDone = 0;
127761 int rc = SQLITE_OK;
127762 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
127763 rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL);
127764 if( rc==SQLITE_DONE ){
127765 bSeenDone = 1;
127766 rc = SQLITE_OK;
127767 }
127768 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127769 sqlite3Fts3SegmentsClose(p);
127770 sqlite3Fts3PendingTermsClear(p);
127771
127772 return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
127773 }
@@ -127814,15 +128591,16 @@
127814 }
127815 }
127816
127817 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
127818 int iCol;
127819 rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0));
 
127820 aSz[p->nColumn] = 0;
127821 for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
127822 const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
127823 rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]);
127824 aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
127825 }
127826 if( p->bHasDocsize ){
127827 fts3InsertDocsize(&rc, p, aSz);
127828 }
@@ -127834,11 +128612,11 @@
127834 for(iCol=0; iCol<=p->nColumn; iCol++){
127835 aSzIns[iCol] += aSz[iCol];
127836 }
127837 }
127838 }
127839 if( p->bHasStat ){
127840 fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
127841 }
127842 sqlite3_free(aSz);
127843
127844 if( pStmt ){
@@ -127850,10 +128628,1692 @@
127850 }
127851
127852 return rc;
127853 }
127854
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127855 /*
127856 ** Handle a 'special' INSERT of the form:
127857 **
127858 ** "INSERT INTO tbl(tbl) VALUES(<expr>)"
127859 **
@@ -127869,10 +130329,16 @@
127869 return SQLITE_NOMEM;
127870 }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
127871 rc = fts3DoOptimize(p, 0);
127872 }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
127873 rc = fts3DoRebuild(p);
 
 
 
 
 
 
127874 #ifdef SQLITE_TEST
127875 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
127876 p->nNodeSize = atoi(&zVal[9]);
127877 rc = SQLITE_OK;
127878 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
@@ -127937,18 +130403,17 @@
127937
127938 for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
127939 const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
127940 sqlite3_tokenizer_cursor *pTC = 0;
127941
127942 rc = pModule->xOpen(pT, zText, -1, &pTC);
127943 while( rc==SQLITE_OK ){
127944 char const *zToken; /* Buffer containing token */
127945 int nToken; /* Number of bytes in token */
127946 int iDum1, iDum2; /* Dummy variables */
127947 int iPos; /* Position of token in zText */
127948
127949 pTC->pTokenizer = pT;
127950 rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
127951 for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
127952 Fts3PhraseToken *pPT = pDef->pToken;
127953 if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
127954 && (pPT->bFirst==0 || iPos==0)
@@ -128044,12 +130509,10 @@
128044 ** delete the contents of all three tables and throw away any
128045 ** data in the pendingTerms hash table. */
128046 rc = fts3DeleteAll(p, 1);
128047 *pnDoc = *pnDoc - 1;
128048 }else{
128049 sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
128050 rc = fts3PendingTermsDocid(p, iRemove);
128051 fts3DeleteTerms(&rc, p, pRowid, aSzDel);
128052 if( p->zContentTbl==0 ){
128053 fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
128054 if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
128055 }else{
@@ -128064,11 +130527,20 @@
128064 return rc;
128065 }
128066
128067 /*
128068 ** This function does the work for the xUpdate method of FTS3 virtual
128069 ** tables.
 
 
 
 
 
 
 
 
 
128070 */
128071 SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
128072 sqlite3_vtab *pVtab, /* FTS3 vtab object */
128073 int nArg, /* Size of argument array */
128074 sqlite3_value **apVal, /* Array of arguments */
@@ -128081,10 +130553,14 @@
128081 u32 *aSzDel; /* Sizes of deleted documents */
128082 int nChng = 0; /* Net change in number of documents */
128083 int bInsertDone = 0;
128084
128085 assert( p->pSegments==0 );
 
 
 
 
128086
128087 /* Check for a "special" INSERT operation. One of the form:
128088 **
128089 ** INSERT INTO xyz(xyz) VALUES('command');
128090 */
@@ -128093,10 +130569,15 @@
128093 && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
128094 ){
128095 rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
128096 goto update_out;
128097 }
 
 
 
 
 
128098
128099 /* Allocate space to hold the change in document sizes */
128100 aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
128101 if( aSzIns==0 ){
128102 rc = SQLITE_NOMEM;
@@ -128161,30 +130642,31 @@
128161 isRemove = 1;
128162 }
128163
128164 /* If this is an INSERT or UPDATE operation, insert the new record. */
128165 if( nArg>1 && rc==SQLITE_OK ){
 
128166 if( bInsertDone==0 ){
128167 rc = fts3InsertData(p, apVal, pRowid);
128168 if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
128169 rc = FTS_CORRUPT_VTAB;
128170 }
128171 }
128172 if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
128173 rc = fts3PendingTermsDocid(p, *pRowid);
128174 }
128175 if( rc==SQLITE_OK ){
128176 assert( p->iPrevDocid==*pRowid );
128177 rc = fts3InsertTerms(p, apVal, aSzIns);
128178 }
128179 if( p->bHasDocsize ){
128180 fts3InsertDocsize(&rc, p, aSzIns);
128181 }
128182 nChng++;
128183 }
128184
128185 if( p->bHasStat ){
128186 fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
128187 }
128188
128189 update_out:
128190 sqlite3_free(aSzIns);
@@ -128749,10 +131231,11 @@
128749 ** is no way for fts3BestSnippet() to know whether or not the document
128750 ** actually contains terms that follow the final highlighted term.
128751 */
128752 static int fts3SnippetShift(
128753 Fts3Table *pTab, /* FTS3 table snippet comes from */
 
128754 int nSnippet, /* Number of tokens desired for snippet */
128755 const char *zDoc, /* Document text to extract snippet from */
128756 int nDoc, /* Size of buffer zDoc in bytes */
128757 int *piPos, /* IN/OUT: First token of snippet */
128758 u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
@@ -128784,15 +131267,14 @@
128784 pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
128785
128786 /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
128787 ** or more tokens in zDoc/nDoc.
128788 */
128789 rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
128790 if( rc!=SQLITE_OK ){
128791 return rc;
128792 }
128793 pC->pTokenizer = pTab->pTokenizer;
128794 while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
128795 const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
128796 rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
128797 }
128798 pMod->xClose(pC);
@@ -128848,15 +131330,14 @@
128848 }
128849 nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
128850
128851 /* Open a token cursor on the document. */
128852 pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
128853 rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
128854 if( rc!=SQLITE_OK ){
128855 return rc;
128856 }
128857 pC->pTokenizer = pTab->pTokenizer;
128858
128859 while( rc==SQLITE_OK ){
128860 int iBegin; /* Offset in zDoc of start of token */
128861 int iFin; /* Offset in zDoc of end of token */
128862 int isHighlight; /* True for highlighted terms */
@@ -128874,11 +131355,13 @@
128874 }
128875 if( iCurrent<iPos ){ continue; }
128876
128877 if( !isShiftDone ){
128878 int n = nDoc - iBegin;
128879 rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask);
 
 
128880 isShiftDone = 1;
128881
128882 /* Now that the shift has been done, check if the initial "..." are
128883 ** required. They are required if (a) this is not the first fragment,
128884 ** or (b) this fragment does not begin at position 0 of its column.
@@ -129010,12 +131493,12 @@
129010 char cArg,
129011 char **pzErr
129012 ){
129013 if( (cArg==FTS3_MATCHINFO_NPHRASE)
129014 || (cArg==FTS3_MATCHINFO_NCOL)
129015 || (cArg==FTS3_MATCHINFO_NDOC && pTab->bHasStat)
129016 || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bHasStat)
129017 || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
129018 || (cArg==FTS3_MATCHINFO_LCS)
129019 || (cArg==FTS3_MATCHINFO_HITS)
129020 ){
129021 return SQLITE_OK;
@@ -129607,13 +132090,14 @@
129607 rc = SQLITE_NOMEM;
129608 goto offsets_out;
129609 }
129610
129611 /* Initialize a tokenizer iterator to iterate through column iCol. */
129612 rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
 
 
129613 if( rc!=SQLITE_OK ) goto offsets_out;
129614 pC->pTokenizer = pTab->pTokenizer;
129615
129616 rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
129617 while( rc==SQLITE_OK ){
129618 int i; /* Used to loop through terms */
129619 int iMinPos = 0x7FFFFFFF; /* Position of next token */
@@ -132774,12 +135258,12 @@
132774 }
132775
132776 sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
132777
132778 /* Allocate the sqlite3_vtab structure */
132779 nDb = strlen(argv[1]);
132780 nName = strlen(argv[2]);
132781 pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
132782 if( !pRtree ){
132783 return SQLITE_NOMEM;
132784 }
132785 memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
@@ -132870,14 +135354,14 @@
132870 RtreeCell cell;
132871 int jj;
132872
132873 nodeGetCell(&tree, &node, ii, &cell);
132874 sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
132875 nCell = strlen(zCell);
132876 for(jj=0; jj<tree.nDim*2; jj++){
132877 sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);
132878 nCell = strlen(zCell);
132879 }
132880
132881 if( zText ){
132882 char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
132883 sqlite3_free(zText);
@@ -133616,11 +136100,14 @@
133616 int iInput = 0;
133617 int iOut = 0;
133618
133619 *ppCursor = 0;
133620
133621 if( nInput<0 ){
 
 
 
133622 nInput = strlen(zInput);
133623 }
133624 nChar = nInput+1;
133625 pCsr = (IcuCursor *)sqlite3_malloc(
133626 sizeof(IcuCursor) + /* IcuCursor */
133627
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.12. 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.
@@ -655,13 +655,13 @@
655 **
656 ** See also: [sqlite3_libversion()],
657 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
658 ** [sqlite_version()] and [sqlite_source_id()].
659 */
660 #define SQLITE_VERSION "3.7.12"
661 #define SQLITE_VERSION_NUMBER 3007012
662 #define SQLITE_SOURCE_ID "2012-03-31 19:12:23 af602d87736b52802a4e760ffeeaa28112b99d9a"
663
664 /*
665 ** CAPI3REF: Run-Time Library Version Numbers
666 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
667 **
@@ -1009,10 +1009,11 @@
1009 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1010 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1011 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1012 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
1013 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
1014 #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
1015
1016 /*
1017 ** CAPI3REF: Flags For File Open Operations
1018 **
1019 ** These bit values are intended for use in the
@@ -1264,31 +1265,35 @@
1265 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
1266 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
1267 ** into an integer that the pArg argument points to. This capability
1268 ** is used during testing and only needs to be supported when SQLITE_TEST
1269 ** is defined.
1270 ** <ul>
1271 ** <li>[[SQLITE_FCNTL_SIZE_HINT]]
1272 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
1273 ** layer a hint of how large the database file will grow to be during the
1274 ** current transaction. This hint is not guaranteed to be accurate but it
1275 ** is often close. The underlying VFS might choose to preallocate database
1276 ** file space based on this hint in order to help writes to the database
1277 ** file run faster.
1278 **
1279 ** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
1280 ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
1281 ** extends and truncates the database file in chunks of a size specified
1282 ** by the user. The fourth argument to [sqlite3_file_control()] should
1283 ** point to an integer (type int) containing the new chunk-size to use
1284 ** for the nominated database. Allocating database file space in large
1285 ** chunks (say 1MB at a time), may reduce file-system fragmentation and
1286 ** improve performance on some systems.
1287 **
1288 ** <li>[[SQLITE_FCNTL_FILE_POINTER]]
1289 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
1290 ** to the [sqlite3_file] object associated with a particular database
1291 ** connection. See the [sqlite3_file_control()] documentation for
1292 ** additional information.
1293 **
1294 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
1295 ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
1296 ** SQLite and sent to all VFSes in place of a call to the xSync method
1297 ** when the database connection has [PRAGMA synchronous] set to OFF.)^
1298 ** Some specialized VFSes need this signal in order to operate correctly
1299 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
@@ -1295,10 +1300,11 @@
1300 ** VFSes do not need this signal and should silently ignore this opcode.
1301 ** Applications should not call [sqlite3_file_control()] with this
1302 ** opcode as doing so may disrupt the operation of the specialized VFSes
1303 ** that do require it.
1304 **
1305 ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
1306 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
1307 ** retry counts and intervals for certain disk I/O operations for the
1308 ** windows [VFS] in order to provide robustness in the presence of
1309 ** anti-virus programs. By default, the windows VFS will retry file read,
1310 ** file write, and file delete operations up to 10 times, with a delay
@@ -1311,10 +1317,11 @@
1317 ** integer is the delay. If either integer is negative, then the setting
1318 ** is not changed but instead the prior value of that setting is written
1319 ** into the array entry, allowing the current retry settings to be
1320 ** interrogated. The zDbName parameter is ignored.
1321 **
1322 ** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
1323 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
1324 ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
1325 ** write ahead log and shared memory files used for transaction control
1326 ** are automatically deleted when the latest connection to the database
1327 ** closes. Setting persistent WAL mode causes those files to persist after
@@ -1325,24 +1332,27 @@
1332 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
1333 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
1334 ** WAL mode. If the integer is -1, then it is overwritten with the current
1335 ** WAL persistence setting.
1336 **
1337 ** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
1338 ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
1339 ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
1340 ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
1341 ** xDeviceCharacteristics methods. The fourth parameter to
1342 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
1343 ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
1344 ** mode. If the integer is -1, then it is overwritten with the current
1345 ** zero-damage mode setting.
1346 **
1347 ** <li>[[SQLITE_FCNTL_OVERWRITE]]
1348 ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
1349 ** a write transaction to indicate that, unless it is rolled back for some
1350 ** reason, the entire database file will be overwritten by the current
1351 ** transaction. This is used by VACUUM operations.
1352 **
1353 ** <li>[[SQLITE_FCNTL_VFSNAME]]
1354 ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
1355 ** all [VFSes] in the VFS stack. The names are of all VFS shims and the
1356 ** final bottom-level VFS are written into memory obtained from
1357 ** [sqlite3_malloc()] and the result is stored in the char* variable
1358 ** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -1349,10 +1359,34 @@
1359 ** The caller is responsible for freeing the memory when done. As with
1360 ** all file-control actions, there is no guarantee that this will actually
1361 ** do anything. Callers should initialize the char* variable to a NULL
1362 ** pointer in case this file-control is not implemented. This file-control
1363 ** is intended for diagnostic use only.
1364 **
1365 ** <li>[[SQLITE_FCNTL_PRAGMA]]
1366 ** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
1367 ** file control is sent to the open [sqlite3_file] object corresponding
1368 ** to the database file to which the pragma statement refers. ^The argument
1369 ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
1370 ** pointers to strings (char**) in which the second element of the array
1371 ** is the name of the pragma and the third element is the argument to the
1372 ** pragma or NULL if the pragma has no argument. ^The handler for an
1373 ** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
1374 ** of the char** argument point to a string obtained from [sqlite3_mprintf()]
1375 ** or the equivalent and that string will become the result of the pragma or
1376 ** the error message if the pragma fails. ^If the
1377 ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
1378 ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
1379 ** file control returns [SQLITE_OK], then the parser assumes that the
1380 ** VFS has handled the PRAGMA itself and the parser generates a no-op
1381 ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
1382 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
1383 ** that the VFS encountered an error while handling the [PRAGMA] and the
1384 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
1385 ** file control occurs at the beginning of pragma statement analysis and so
1386 ** it is able to override built-in [PRAGMA] statements.
1387 ** </ul>
1388 */
1389 #define SQLITE_FCNTL_LOCKSTATE 1
1390 #define SQLITE_GET_LOCKPROXYFILE 2
1391 #define SQLITE_SET_LOCKPROXYFILE 3
1392 #define SQLITE_LAST_ERRNO 4
@@ -1363,10 +1397,11 @@
1397 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
1398 #define SQLITE_FCNTL_PERSIST_WAL 10
1399 #define SQLITE_FCNTL_OVERWRITE 11
1400 #define SQLITE_FCNTL_VFSNAME 12
1401 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
1402 #define SQLITE_FCNTL_PRAGMA 14
1403
1404 /*
1405 ** CAPI3REF: Mutex Handle
1406 **
1407 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -5012,10 +5047,19 @@
5047 ** will be an absolute pathname, even if the filename used
5048 ** to open the database originally was a URI or relative pathname.
5049 */
5050 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
5051
5052 /*
5053 ** CAPI3REF: Determine if a database is read-only
5054 **
5055 ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
5056 ** of connection D is read-only, 0 if it is read/write, or -1 if N is not
5057 ** the name of a database on connection D.
5058 */
5059 SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
5060
5061 /*
5062 ** CAPI3REF: Find the next prepared statement
5063 **
5064 ** ^This interface returns a pointer to the next [prepared statement] after
5065 ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -6510,10 +6554,21 @@
6554 ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
6555 ** <dd>This parameter returns the number of pager cache misses that have
6556 ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
6557 ** is always 0.
6558 ** </dd>
6559 **
6560 ** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
6561 ** <dd>This parameter returns the number of dirty cache entries that have
6562 ** been written to disk. Specifically, the number of pages written to the
6563 ** wal file in wal mode databases, or the number of pages written to the
6564 ** database file in rollback mode databases. Any pages written as part of
6565 ** transaction rollback or database recovery operations are not included.
6566 ** If an IO or other error occurs while writing a page to disk, the effect
6567 ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The
6568 ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
6569 ** </dd>
6570 ** </dl>
6571 */
6572 #define SQLITE_DBSTATUS_LOOKASIDE_USED 0
6573 #define SQLITE_DBSTATUS_CACHE_USED 1
6574 #define SQLITE_DBSTATUS_SCHEMA_USED 2
@@ -6521,11 +6576,12 @@
6576 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
6577 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
6578 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
6579 #define SQLITE_DBSTATUS_CACHE_HIT 7
6580 #define SQLITE_DBSTATUS_CACHE_MISS 8
6581 #define SQLITE_DBSTATUS_CACHE_WRITE 9
6582 #define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
6583
6584
6585 /*
6586 ** CAPI3REF: Prepared Statement Status
6587 **
@@ -7137,15 +7193,16 @@
7193
7194
7195 /*
7196 ** CAPI3REF: String Comparison
7197 **
7198 ** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
7199 ** and extensions to compare the contents of two buffers containing UTF-8
7200 ** strings in a case-independent fashion, using the same definition of "case
7201 ** independence" that SQLite uses internally when comparing identifiers.
7202 */
7203 SQLITE_API int sqlite3_stricmp(const char *, const char *);
7204 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
7205
7206 /*
7207 ** CAPI3REF: Error Logging Interface
7208 **
@@ -8204,11 +8261,11 @@
8261 SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
8262 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
8263 SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
8264 SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
8265 SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
8266 SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int);
8267 SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
8268 SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
8269 SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
8270 SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
8271 SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
@@ -8944,10 +9001,13 @@
9001 SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
9002 SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
9003 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
9004 SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
9005 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
9006 #ifdef SQLITE_ENABLE_ZIPVFS
9007 SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
9008 #endif
9009
9010 /* Functions used to query pager state and configuration. */
9011 SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
9012 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
9013 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
@@ -9871,18 +9931,22 @@
9931 void (*xDestroy)(void *);
9932 void *pUserData;
9933 };
9934
9935 /*
9936 ** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF
9937 ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
9938 ** are assert() statements in the code to verify this.
9939 */
9940 #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
9941 #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
9942 #define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
9943 #define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
9944 #define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */
9945 #define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */
9946 #define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */
9947 #define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */
9948
9949 /*
9950 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
9951 ** used to create the initializers for the FuncDef structures.
9952 **
@@ -9906,11 +9970,14 @@
9970 ** available as the function user-data (sqlite3_user_data()). The
9971 ** FuncDef.flags variable is set to the value passed as the flags
9972 ** parameter.
9973 */
9974 #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
9975 {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \
9976 SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
9977 #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
9978 {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
9979 SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
9980 #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
9981 {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
9982 pArg, 0, xFunc, 0, 0, #zName, 0, 0}
9983 #define LIKEFUNC(zName, nArg, arg, flags) \
@@ -10136,11 +10203,11 @@
10203 u8 tabFlags; /* Mask of TF_* values */
10204 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10205 FKey *pFKey; /* Linked list of all foreign keys in this table */
10206 char *zColAff; /* String defining the affinity of each column */
10207 #ifndef SQLITE_OMIT_CHECK
10208 ExprList *pCheck; /* All CHECK constraints */
10209 #endif
10210 #ifndef SQLITE_OMIT_ALTERTABLE
10211 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10212 #endif
10213 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -10529,10 +10596,11 @@
10596 ** TK_VARIABLE: variable number (always >= 1). */
10597 i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
10598 i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
10599 u8 flags2; /* Second set of flags. EP2_... */
10600 u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
10601 /* If TK_COLUMN, the value of p5 for OP_Column */
10602 AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
10603 Table *pTab; /* Table for TK_COLUMN expressions. */
10604 #if SQLITE_MAX_EXPR_DEPTH>0
10605 int nHeight; /* Height of the tree headed by this node */
10606 #endif
@@ -10551,11 +10619,11 @@
10619 #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
10620 #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
10621 #define EP_FixedDest 0x0200 /* Result needed in a specific register */
10622 #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
10623 #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
10624 #define EP_Hint 0x1000 /* Not used */
10625 #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
10626 #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
10627 #define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
10628
10629 /*
@@ -11070,10 +11138,11 @@
11138 int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
11139 int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
11140 int regRowid; /* Register holding rowid of CREATE TABLE entry */
11141 int regRoot; /* Register holding root page number for new objects */
11142 int nMaxArg; /* Max args passed to user function by sub-program */
11143 Token constraintName;/* Name of the constraint currently being parsed */
11144 #ifndef SQLITE_OMIT_SHARED_CACHE
11145 int nTableLock; /* Number of locks in aTableLock */
11146 TableLock *aTableLock; /* Required table locks for shared-cache mode */
11147 #endif
11148 AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
@@ -11138,18 +11207,20 @@
11207 const char *zAuthContext; /* Put saved Parse.zAuthContext here */
11208 Parse *pParse; /* The Parse structure */
11209 };
11210
11211 /*
11212 ** Bitfield flags for P5 value in various opcodes.
11213 */
11214 #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
11215 #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
11216 #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
11217 #define OPFLAG_APPEND 0x08 /* This is likely to be an append */
11218 #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
11219 #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
11220 #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
11221 #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
11222
11223 /*
11224 * Each trigger present in the database schema is stored as an instance of
11225 * struct Trigger.
11226 *
@@ -11415,11 +11486,11 @@
11486 #endif
11487
11488 /*
11489 ** Internal function prototypes
11490 */
11491 #define sqlite3StrICmp sqlite3_stricmp
11492 SQLITE_PRIVATE int sqlite3Strlen30(const char*);
11493 #define sqlite3StrNICmp sqlite3_strnicmp
11494
11495 SQLITE_PRIVATE int sqlite3MallocInit(void);
11496 SQLITE_PRIVATE void sqlite3MallocEnd(void);
@@ -11563,10 +11634,11 @@
11634 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
11635 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
11636 SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
11637 SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
11638 sqlite3_vfs**,char**,char **);
11639 SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
11640 SQLITE_PRIVATE int sqlite3CodeOnce(Parse *);
11641
11642 SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
11643 SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
11644 SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
@@ -11628,11 +11700,11 @@
11700 #endif
11701 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
11702 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
11703 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
11704 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
11705 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
11706 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
11707 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
11708 SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
11709 SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
11710 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
@@ -11662,11 +11734,11 @@
11734 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
11735 SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
11736 SQLITE_PRIVATE void sqlite3PrngSaveState(void);
11737 SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
11738 SQLITE_PRIVATE void sqlite3PrngResetState(void);
11739 SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
11740 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
11741 SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
11742 SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
11743 SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
11744 SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
@@ -13460,14 +13532,16 @@
13532 ** Set *pCurrent to the total cache hits or misses encountered by all
13533 ** pagers the database handle is connected to. *pHighwater is always set
13534 ** to zero.
13535 */
13536 case SQLITE_DBSTATUS_CACHE_HIT:
13537 case SQLITE_DBSTATUS_CACHE_MISS:
13538 case SQLITE_DBSTATUS_CACHE_WRITE:{
13539 int i;
13540 int nRet = 0;
13541 assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
13542 assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
13543
13544 for(i=0; i<db->nDb; i++){
13545 if( db->aDb[i].pBt ){
13546 Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
13547 sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
@@ -21210,17 +21284,17 @@
21284
21285 /*
21286 ** Some systems have stricmp(). Others have strcasecmp(). Because
21287 ** there is no consistency, we will define our own.
21288 **
21289 ** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
21290 ** sqlite3_strnicmp() APIs allow applications and extensions to compare
21291 ** the contents of two buffers containing UTF-8 strings in a
21292 ** case-independent fashion, using the same definition of "case
21293 ** independence" that SQLite uses internally when comparing identifiers.
21294 */
21295 SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
21296 register unsigned char *a, *b;
21297 a = (unsigned char *)zLeft;
21298 b = (unsigned char *)zRight;
21299 while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
21300 return UpperToLower[*a] - UpperToLower[*b];
@@ -25494,11 +25568,11 @@
25568 ** recover the hot journals.
25569 */
25570 static int robust_open(const char *z, int f, mode_t m){
25571 int rc;
25572 mode_t m2;
25573 mode_t origM = 0;
25574 if( m==0 ){
25575 m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
25576 }else{
25577 m2 = m;
25578 origM = osUmask(0);
@@ -33678,10 +33752,13 @@
33752 }
33753 sqlite3_free(pFile->zDeleteOnClose);
33754 }
33755 #endif
33756 OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
33757 if( rc ){
33758 pFile->h = NULL;
33759 }
33760 OpenCounter(-1);
33761 return rc ? SQLITE_OK
33762 : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
33763 "winClose", pFile->zPath);
33764 }
@@ -33695,22 +33772,33 @@
33772 sqlite3_file *id, /* File to read from */
33773 void *pBuf, /* Write content into this buffer */
33774 int amt, /* Number of bytes to read */
33775 sqlite3_int64 offset /* Begin reading at this offset */
33776 ){
33777 #if !SQLITE_OS_WINCE
33778 OVERLAPPED overlapped; /* The offset for ReadFile. */
33779 #endif
33780 winFile *pFile = (winFile*)id; /* file handle */
33781 DWORD nRead; /* Number of bytes actually read from file */
33782 int nRetry = 0; /* Number of retrys */
33783
33784 assert( id!=0 );
33785 SimulateIOError(return SQLITE_IOERR_READ);
33786 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
33787
33788 #if SQLITE_OS_WINCE
33789 if( seekWinFile(pFile, offset) ){
33790 return SQLITE_FULL;
33791 }
33792 while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
33793 #else
33794 memset(&overlapped, 0, sizeof(OVERLAPPED));
33795 overlapped.Offset = (LONG)(offset & 0xffffffff);
33796 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
33797 while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
33798 osGetLastError()!=ERROR_HANDLE_EOF ){
33799 #endif
33800 DWORD lastErrno;
33801 if( retryIoerr(&nRetry, &lastErrno) ) continue;
33802 pFile->lastErrno = lastErrno;
33803 return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
33804 "winRead", pFile->zPath);
@@ -33733,11 +33821,11 @@
33821 sqlite3_file *id, /* File to write into */
33822 const void *pBuf, /* The bytes to be written */
33823 int amt, /* Number of bytes to write */
33824 sqlite3_int64 offset /* Offset into the file to begin writing at */
33825 ){
33826 int rc = 0; /* True if error has occured, else false */
33827 winFile *pFile = (winFile*)id; /* File handle */
33828 int nRetry = 0; /* Number of retries */
33829
33830 assert( amt>0 );
33831 assert( pFile );
@@ -33744,23 +33832,48 @@
33832 SimulateIOError(return SQLITE_IOERR_WRITE);
33833 SimulateDiskfullError(return SQLITE_FULL);
33834
33835 OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
33836
33837 #if SQLITE_OS_WINCE
33838 rc = seekWinFile(pFile, offset);
33839 if( rc==0 ){
33840 #else
33841 {
33842 #endif
33843 #if !SQLITE_OS_WINCE
33844 OVERLAPPED overlapped; /* The offset for WriteFile. */
33845 #endif
33846 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
33847 int nRem = amt; /* Number of bytes yet to be written */
33848 DWORD nWrite; /* Bytes written by each WriteFile() call */
33849 DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
33850
33851 #if !SQLITE_OS_WINCE
33852 memset(&overlapped, 0, sizeof(OVERLAPPED));
33853 overlapped.Offset = (LONG)(offset & 0xffffffff);
33854 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
33855 #endif
33856
33857 while( nRem>0 ){
33858 #if SQLITE_OS_WINCE
33859 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
33860 #else
33861 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
33862 #endif
33863 if( retryIoerr(&nRetry, &lastErrno) ) continue;
33864 break;
33865 }
33866 if( nWrite<=0 ){
33867 lastErrno = osGetLastError();
33868 break;
33869 }
33870 #if !SQLITE_OS_WINCE
33871 offset += nWrite;
33872 overlapped.Offset = (LONG)(offset & 0xffffffff);
33873 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
33874 #endif
33875 aRem += nWrite;
33876 nRem -= nWrite;
33877 }
33878 if( nRem>0 ){
33879 pFile->lastErrno = lastErrno;
@@ -38302,10 +38415,11 @@
38415 # define sqlite3WalFrames(u,v,w,x,y,z) 0
38416 # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
38417 # define sqlite3WalCallback(z) 0
38418 # define sqlite3WalExclusiveMode(y,z) 0
38419 # define sqlite3WalHeapMemory(z) 0
38420 # define sqlite3WalFramesize(z) 0
38421 #else
38422
38423 #define WAL_SAVEPOINT_NDATA 4
38424
38425 /* Connection to a write-ahead log (WAL) file.
@@ -38382,10 +38496,17 @@
38496 /* Return true if the argument is non-NULL and the WAL module is using
38497 ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
38498 ** WAL module is using shared-memory, return false.
38499 */
38500 SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
38501
38502 #ifdef SQLITE_ENABLE_ZIPVFS
38503 /* If the WAL file is not empty, return the number of bytes of content
38504 ** stored in each frame (i.e. the db page-size when the WAL was created).
38505 */
38506 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
38507 #endif
38508
38509 #endif /* ifndef SQLITE_OMIT_WAL */
38510 #endif /* _WAL_H_ */
38511
38512 /************** End of wal.h *************************************************/
@@ -39037,13 +39158,13 @@
39158 i64 journalSizeLimit; /* Size limit for persistent journal files */
39159 char *zFilename; /* Name of the database file */
39160 char *zJournal; /* Name of the journal file */
39161 int (*xBusyHandler)(void*); /* Function to call when busy */
39162 void *pBusyHandlerArg; /* Context argument for xBusyHandler */
39163 int aStat[3]; /* Total cache hits, misses and writes */
39164 #ifdef SQLITE_TEST
39165 int nRead; /* Database pages read */
39166 #endif
39167 void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
39168 #ifdef SQLITE_HAS_CODEC
39169 void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
39170 void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
@@ -39056,10 +39177,19 @@
39177 Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
39178 char *zWal; /* File name for write-ahead log */
39179 #endif
39180 };
39181
39182 /*
39183 ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
39184 ** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
39185 ** or CACHE_WRITE to sqlite3_db_status().
39186 */
39187 #define PAGER_STAT_HIT 0
39188 #define PAGER_STAT_MISS 1
39189 #define PAGER_STAT_WRITE 2
39190
39191 /*
39192 ** The following global variables hold counters used for
39193 ** testing purposes only. These variables do not exist in
39194 ** a non-testing build. These variables are not thread-safe.
39195 */
@@ -41338,10 +41468,11 @@
41468 PgHdr *pList, /* List of frames to log */
41469 Pgno nTruncate, /* Database size after this commit */
41470 int isCommit /* True if this is a commit */
41471 ){
41472 int rc; /* Return code */
41473 int nList; /* Number of pages in pList */
41474 #if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
41475 PgHdr *p; /* For looping over pages */
41476 #endif
41477
41478 assert( pPager->pWal );
@@ -41351,22 +41482,30 @@
41482 for(p=pList; p && p->pDirty; p=p->pDirty){
41483 assert( p->pgno < p->pDirty->pgno );
41484 }
41485 #endif
41486
41487 assert( pList->pDirty==0 || isCommit );
41488 if( isCommit ){
41489 /* If a WAL transaction is being committed, there is no point in writing
41490 ** any pages with page numbers greater than nTruncate into the WAL file.
41491 ** They will never be read by any client. So remove them from the pDirty
41492 ** list here. */
41493 PgHdr *p;
41494 PgHdr **ppNext = &pList;
41495 nList = 0;
41496 for(p=pList; (*ppNext = p); p=p->pDirty){
41497 if( p->pgno<=nTruncate ){
41498 ppNext = &p->pDirty;
41499 nList++;
41500 }
41501 }
41502 assert( pList );
41503 }else{
41504 nList = 1;
41505 }
41506 pPager->aStat[PAGER_STAT_WRITE] += nList;
41507
41508 if( pList->pgno==1 ) pager_write_changecounter(pList);
41509 rc = sqlite3WalFrames(pPager->pWal,
41510 pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
41511 );
@@ -42430,19 +42569,19 @@
42569 memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
42570 }
42571 if( pgno>pPager->dbFileSize ){
42572 pPager->dbFileSize = pgno;
42573 }
42574 pPager->aStat[PAGER_STAT_WRITE]++;
42575
42576 /* Update any backup objects copying the contents of this pager. */
42577 sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
42578
42579 PAGERTRACE(("STORE %d page %d hash(%08x)\n",
42580 PAGERID(pPager), pgno, pager_pagehash(pList)));
42581 IOTRACE(("PGOUT %p %d\n", pPager, pgno));
42582 PAGER_INCR(sqlite3_pager_writedb_count);
 
42583 }else{
42584 PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
42585 }
42586 pager_set_pagehash(pList);
42587 pList = pList->pDirty;
@@ -43396,11 +43535,11 @@
43535
43536 if( (*ppPage)->pPager && !noContent ){
43537 /* In this case the pcache already contains an initialized copy of
43538 ** the page. Return without further ado. */
43539 assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
43540 pPager->aStat[PAGER_STAT_HIT]++;
43541 return SQLITE_OK;
43542
43543 }else{
43544 /* The pager cache has created a new page. Its content needs to
43545 ** be initialized. */
@@ -43438,11 +43577,11 @@
43577 }
43578 memset(pPg->pData, 0, pPager->pageSize);
43579 IOTRACE(("ZERO %p %d\n", pPager, pgno));
43580 }else{
43581 assert( pPg->pPager==pPager );
43582 pPager->aStat[PAGER_STAT_MISS]++;
43583 rc = readDbPage(pPg);
43584 if( rc!=SQLITE_OK ){
43585 goto pager_acquire_err;
43586 }
43587 }
@@ -44023,10 +44162,11 @@
44162 const void *zBuf;
44163 assert( pPager->dbFileSize>0 );
44164 CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
44165 if( rc==SQLITE_OK ){
44166 rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
44167 pPager->aStat[PAGER_STAT_WRITE]++;
44168 }
44169 if( rc==SQLITE_OK ){
44170 pPager->changeCountDone = 1;
44171 }
44172 }else{
@@ -44466,15 +44606,15 @@
44606 a[1] = sqlite3PcachePagecount(pPager->pPCache);
44607 a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
44608 a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
44609 a[4] = pPager->eState;
44610 a[5] = pPager->errCode;
44611 a[6] = pPager->aStat[PAGER_STAT_HIT];
44612 a[7] = pPager->aStat[PAGER_STAT_MISS];
44613 a[8] = 0; /* Used to be pPager->nOvfl */
44614 a[9] = pPager->nRead;
44615 a[10] = pPager->aStat[PAGER_STAT_WRITE];
44616 return a;
44617 }
44618 #endif
44619
44620 /*
@@ -44483,24 +44623,23 @@
44623 ** current cache hit or miss count, according to the value of eStat. If the
44624 ** reset parameter is non-zero, the cache hit or miss count is zeroed before
44625 ** returning.
44626 */
44627 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
 
44628
44629 assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
44630 || eStat==SQLITE_DBSTATUS_CACHE_MISS
44631 || eStat==SQLITE_DBSTATUS_CACHE_WRITE
44632 );
 
 
 
 
 
44633
44634 assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
44635 assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
44636 assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
44637
44638 *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
44639 if( reset ){
44640 pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
44641 }
44642 }
44643
44644 /*
44645 ** Return true if this is an in-memory pager.
@@ -45237,10 +45376,24 @@
45376 pPager->pWal = 0;
45377 }
45378 }
45379 return rc;
45380 }
45381
45382 #ifdef SQLITE_ENABLE_ZIPVFS
45383 /*
45384 ** A read-lock must be held on the pager when this function is called. If
45385 ** the pager is in WAL mode and the WAL file currently contains one or more
45386 ** frames, return the size in bytes of the page images stored within the
45387 ** WAL frames. Otherwise, if this is not a WAL database or the WAL file
45388 ** is empty, return 0.
45389 */
45390 SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
45391 assert( pPager->eState==PAGER_READER );
45392 return sqlite3WalFramesize(pPager->pWal);
45393 }
45394 #endif
45395
45396 #ifdef SQLITE_HAS_CODEC
45397 /*
45398 ** This function is called by the wal module when writing page content
45399 ** into the log file.
@@ -47657,11 +47810,11 @@
47810 testcase( sz<=32768 );
47811 testcase( sz>=65536 );
47812 iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
47813 *pInWal = 1;
47814 /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
47815 return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
47816 }
47817
47818 *pInWal = 0;
47819 return SQLITE_OK;
47820 }
@@ -48327,10 +48480,22 @@
48480 ** WAL module is using shared-memory, return false.
48481 */
48482 SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
48483 return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
48484 }
48485
48486 #ifdef SQLITE_ENABLE_ZIPVFS
48487 /*
48488 ** If the argument is not NULL, it points to a Wal object that holds a
48489 ** read-lock. This function returns the database page-size if it is known,
48490 ** or zero if it is not (or if pWal is NULL).
48491 */
48492 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
48493 assert( pWal==0 || pWal->readLock>=0 );
48494 return (pWal ? pWal->szPage : 0);
48495 }
48496 #endif
48497
48498 #endif /* #ifndef SQLITE_OMIT_WAL */
48499
48500 /************** End of wal.c *************************************************/
48501 /************** Begin file btmutex.c *****************************************/
@@ -51320,11 +51485,11 @@
51485
51486 /* Rollback any active transaction and free the handle structure.
51487 ** The call to sqlite3BtreeRollback() drops any table-locks held by
51488 ** this handle.
51489 */
51490 sqlite3BtreeRollback(p, SQLITE_OK);
51491 sqlite3BtreeLeave(p);
51492
51493 /* If there are still other outstanding references to the shared-btree
51494 ** structure, return now. The remainder of this procedure cleans
51495 ** up the shared-btree.
@@ -52558,10 +52723,11 @@
52723 ** save the state of the cursor. The cursor must be
52724 ** invalidated.
52725 */
52726 SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
52727 BtCursor *p;
52728 if( pBtree==0 ) return;
52729 sqlite3BtreeEnter(pBtree);
52730 for(p=pBtree->pBt->pCursor; p; p=p->pNext){
52731 int i;
52732 sqlite3BtreeClearCursor(p);
52733 p->eState = CURSOR_FAULT;
@@ -52581,29 +52747,24 @@
52747 ** in an error.
52748 **
52749 ** This will release the write lock on the database file. If there
52750 ** are no active cursors, it also releases the read lock.
52751 */
52752 SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
52753 int rc;
52754 BtShared *pBt = p->pBt;
52755 MemPage *pPage1;
52756
52757 sqlite3BtreeEnter(p);
52758 if( tripCode==SQLITE_OK ){
52759 rc = tripCode = saveAllCursors(pBt, 0, 0);
52760 }else{
52761 rc = SQLITE_OK;
52762 }
52763 if( tripCode ){
52764 sqlite3BtreeTripAllCursors(p, tripCode);
52765 }
 
 
 
 
 
52766 btreeIntegrity(p);
52767
52768 if( p->inTrans==TRANS_WRITE ){
52769 int rc2;
52770
@@ -56072,17 +56233,10 @@
56233 ** keys with no associated data. If the cursor was opened expecting an
56234 ** intkey table, the caller should be inserting integer keys with a
56235 ** blob of associated data. */
56236 assert( (pKey==0)==(pCur->pKeyInfo==0) );
56237
 
 
 
 
 
 
 
56238 /* Save the positions of any other cursors open on this table.
56239 **
56240 ** In some cases, the call to btreeMoveto() below is a no-op. For
56241 ** example, when inserting data into a table with auto-generated integer
56242 ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
@@ -56092,10 +56246,18 @@
56246 ** doing any work. To avoid thwarting these optimizations, it is important
56247 ** not to clear the cursor here.
56248 */
56249 rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
56250 if( rc ) return rc;
56251
56252 /* If this is an insert into a table b-tree, invalidate any incrblob
56253 ** cursors open on the row being replaced (assuming this is a replace
56254 ** operation - if it is not, the following is a no-op). */
56255 if( pCur->pKeyInfo==0 ){
56256 invalidateIncrblobCursors(p, nKey, 0);
56257 }
56258
56259 if( !loc ){
56260 rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
56261 if( rc ) return rc;
56262 }
56263 assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
@@ -56202,16 +56364,10 @@
56364 || NEVER(pCur->eState!=CURSOR_VALID)
56365 ){
56366 return SQLITE_ERROR; /* Something has gone awry. */
56367 }
56368
 
 
 
 
 
 
56369 iCellDepth = pCur->iPage;
56370 iCellIdx = pCur->aiIdx[iCellDepth];
56371 pPage = pCur->apPage[iCellDepth];
56372 pCell = findCell(pPage, iCellIdx);
56373
@@ -56233,10 +56389,17 @@
56389 ** deleted writable. Then free any overflow pages associated with the
56390 ** entry and finally remove the cell itself from within the page.
56391 */
56392 rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
56393 if( rc ) return rc;
56394
56395 /* If this is a delete operation to remove a row from a table b-tree,
56396 ** invalidate any incrblob cursors open on the row being deleted. */
56397 if( pCur->pKeyInfo==0 ){
56398 invalidateIncrblobCursors(p, pCur->info.nKey, 0);
56399 }
56400
56401 rc = sqlite3PagerWrite(pPage->pDbPage);
56402 if( rc ) return rc;
56403 rc = clearCell(pPage, pCell);
56404 dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc);
56405 if( rc ) return rc;
@@ -56514,17 +56677,17 @@
56677 int rc;
56678 BtShared *pBt = p->pBt;
56679 sqlite3BtreeEnter(p);
56680 assert( p->inTrans==TRANS_WRITE );
56681
 
 
 
 
 
56682 rc = saveAllCursors(pBt, (Pgno)iTable, 0);
56683
56684 if( SQLITE_OK==rc ){
56685 /* Invalidate all incrblob cursors open on table iTable (assuming iTable
56686 ** is the root of a table b-tree - if it is not, the following call is
56687 ** a no-op). */
56688 invalidateIncrblobCursors(p, 0, 1);
56689 rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
56690 }
56691 sqlite3BtreeLeave(p);
56692 return rc;
56693 }
@@ -58121,11 +58284,11 @@
58284 }
58285 *pp = p->pNext;
58286 }
58287
58288 /* If a transaction is still open on the Btree, roll it back. */
58289 sqlite3BtreeRollback(p->pDest, SQLITE_OK);
58290
58291 /* Set the error code of the destination database handle. */
58292 rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
58293 sqlite3Error(p->pDestDb, rc, 0);
58294
@@ -58332,14 +58495,14 @@
58495
58496 /*
58497 ** Make sure pMem->z points to a writable allocation of at least
58498 ** n bytes.
58499 **
58500 ** If the third argument passed to this function is true, then memory
58501 ** cell pMem must contain a string or blob. In this case the content is
58502 ** preserved. Otherwise, if the third parameter to this function is false,
58503 ** any current string or blob value may be discarded.
58504 **
58505 ** This function sets the MEM_Dyn flag and clears any xDel callback.
58506 ** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
58507 ** not set, Mem.n is zeroed.
58508 */
@@ -58349,10 +58512,14 @@
58512 (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
58513 ((pMem->flags&MEM_Ephem) ? 1 : 0) +
58514 ((pMem->flags&MEM_Static) ? 1 : 0)
58515 );
58516 assert( (pMem->flags&MEM_RowSet)==0 );
58517
58518 /* If the preserve flag is set to true, then the memory cell must already
58519 ** contain a valid string or blob value. */
58520 assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
58521
58522 if( n<32 ) n = 32;
58523 if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
58524 if( preserve && pMem->z==pMem->zMalloc ){
58525 pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
@@ -60668,11 +60835,11 @@
60835 int nByte = (nSub+1)*sizeof(SubProgram*);
60836 int j;
60837 for(j=0; j<nSub; j++){
60838 if( apSub[j]==pOp->p4.pProgram ) break;
60839 }
60840 if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){
60841 apSub = (SubProgram **)pSub->z;
60842 apSub[nSub++] = pOp->p4.pProgram;
60843 pSub->flags |= MEM_Blob;
60844 pSub->n = nSub*sizeof(SubProgram*);
60845 }
@@ -61431,36 +61598,10 @@
61598 }
61599 #else
61600 #define checkActiveVdbeCnt(x)
61601 #endif
61602
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61603 /*
61604 ** If the Vdbe passed as the first argument opened a statement-transaction,
61605 ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
61606 ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
61607 ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
@@ -61621,12 +61762,11 @@
61762 eStatementOp = SAVEPOINT_ROLLBACK;
61763 }else{
61764 /* We are forced to roll back the active transaction. Before doing
61765 ** so, abort any other statements this handle currently has active.
61766 */
61767 sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
 
61768 sqlite3CloseSavepoints(db);
61769 db->autoCommit = 1;
61770 }
61771 }
61772 }
@@ -61664,27 +61804,26 @@
61804 if( rc==SQLITE_BUSY && p->readOnly ){
61805 sqlite3VdbeLeave(p);
61806 return SQLITE_BUSY;
61807 }else if( rc!=SQLITE_OK ){
61808 p->rc = rc;
61809 sqlite3RollbackAll(db, SQLITE_OK);
61810 }else{
61811 db->nDeferredCons = 0;
61812 sqlite3CommitInternalChanges(db);
61813 }
61814 }else{
61815 sqlite3RollbackAll(db, SQLITE_OK);
61816 }
61817 db->nStatement = 0;
61818 }else if( eStatementOp==0 ){
61819 if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
61820 eStatementOp = SAVEPOINT_RELEASE;
61821 }else if( p->errorAction==OE_Abort ){
61822 eStatementOp = SAVEPOINT_ROLLBACK;
61823 }else{
61824 sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
 
61825 sqlite3CloseSavepoints(db);
61826 db->autoCommit = 1;
61827 }
61828 }
61829
@@ -61700,12 +61839,11 @@
61839 if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
61840 p->rc = rc;
61841 sqlite3DbFree(db, p->zErrMsg);
61842 p->zErrMsg = 0;
61843 }
61844 sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
 
61845 sqlite3CloseSavepoints(db);
61846 db->autoCommit = 1;
61847 }
61848 }
61849
@@ -66946,10 +67084,15 @@
67084 **
67085 ** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
67086 ** then the cache of the cursor is reset prior to extracting the column.
67087 ** The first OP_Column against a pseudo-table after the value of the content
67088 ** register has changed should have this bit set.
67089 **
67090 ** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
67091 ** the result is guaranteed to only be used as the argument of a length()
67092 ** or typeof() function, respectively. The loading of large blobs can be
67093 ** skipped for length() and all content loading can be skipped for typeof().
67094 */
67095 case OP_Column: {
67096 #if 0 /* local variables moved into u.an */
67097 u32 payloadSize; /* Number of bytes in the record */
67098 i64 payloadSize64; /* Number of bytes in the record */
@@ -67088,11 +67231,11 @@
67231 u.an.pC->aRow = (u8*)u.an.zData;
67232 }else{
67233 u.an.pC->aRow = 0;
67234 }
67235 }
67236 /* The following assert is true in all cases except when
67237 ** the database file has been corrupted externally.
67238 ** assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */
67239 u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset);
67240
67241 /* Make sure a corrupt database has not given us an oversize header.
@@ -67163,15 +67306,15 @@
67306 if( u.an.offset<u.an.szField ){ /* True if u.an.offset overflows */
67307 u.an.zIdx = &u.an.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
67308 break;
67309 }
67310 }else{
67311 /* If u.an.i is less that u.an.nField, then there are fewer fields in this
67312 ** record than SetNumColumns indicated there are columns in the
67313 ** table. Set the u.an.offset for any extra columns not present in
67314 ** the record to 0. This tells code below to store the default value
67315 ** for the column instead of deserializing a value from the record.
67316 */
67317 u.an.aOffset[u.an.i] = 0;
67318 }
67319 }
67320 sqlite3VdbeMemRelease(&u.an.sMem);
@@ -67197,21 +67340,36 @@
67340 ** a pointer to a Mem object.
67341 */
67342 if( u.an.aOffset[u.an.p2] ){
67343 assert( rc==SQLITE_OK );
67344 if( u.an.zRec ){
67345 /* This is the common case where the whole row fits on a single page */
67346 VdbeMemRelease(u.an.pDest);
67347 sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
67348 }else{
67349 /* This branch happens only when the row overflows onto multiple pages */
67350 u.an.t = u.an.aType[u.an.p2];
67351 if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
67352 && ((u.an.t>=12 && (u.an.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
67353 ){
67354 /* Content is irrelevant for the typeof() function and for
67355 ** the length(X) function if X is a blob. So we might as well use
67356 ** bogus content rather than reading content from disk. NULL works
67357 ** for text and blob and whatever is in the u.an.payloadSize64 variable
67358 ** will work for everything else. */
67359 u.an.zData = u.an.t<12 ? (char*)&u.an.payloadSize64 : 0;
67360 }else{
67361 u.an.len = sqlite3VdbeSerialTypeLen(u.an.t);
67362 sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
67363 rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex,
67364 &u.an.sMem);
67365 if( rc!=SQLITE_OK ){
67366 goto op_column_out;
67367 }
67368 u.an.zData = u.an.sMem.z;
67369 }
67370 sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.t, u.an.pDest);
67371 }
67372 u.an.pDest->enc = encoding;
67373 }else{
67374 if( pOp->p4type==P4_MEM ){
67375 sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
@@ -67513,20 +67671,16 @@
67671 u.ar.iSavepoint++;
67672 }
67673 if( !u.ar.pSavepoint ){
67674 sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
67675 rc = SQLITE_ERROR;
67676 }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){
 
 
67677 /* It is not possible to release (commit) a savepoint if there are
67678 ** active write statements.
 
67679 */
67680 sqlite3SetString(&p->zErrMsg, db,
67681 "cannot release savepoint - SQL statements in progress"
 
67682 );
67683 rc = SQLITE_BUSY;
67684 }else{
67685
67686 /* Determine whether or not this is a transaction savepoint. If so,
@@ -67547,10 +67701,15 @@
67701 }
67702 db->isTransactionSavepoint = 0;
67703 rc = p->rc;
67704 }else{
67705 u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
67706 if( u.ar.p1==SAVEPOINT_ROLLBACK ){
67707 for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
67708 sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT);
67709 }
67710 }
67711 for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
67712 rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
67713 if( rc!=SQLITE_OK ){
67714 goto abort_due_to_error;
67715 }
@@ -67617,29 +67776,32 @@
67776 u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit;
67777 assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 );
67778 assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 );
67779 assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
67780
67781 #if 0
67782 if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
67783 /* If this instruction implements a ROLLBACK and other VMs are
67784 ** still running, and a transaction is active, return an error indicating
67785 ** that the other VMs must complete first.
67786 */
67787 sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
67788 "SQL statements in progress");
67789 rc = SQLITE_BUSY;
67790 }else
67791 #endif
67792 if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
67793 /* If this instruction implements a COMMIT and other VMs are writing
67794 ** return an error indicating that the other VMs must complete first.
67795 */
67796 sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
67797 "SQL statements in progress");
67798 rc = SQLITE_BUSY;
67799 }else if( u.as.desiredAutoCommit!=db->autoCommit ){
67800 if( u.as.iRollback ){
67801 assert( u.as.desiredAutoCommit==1 );
67802 sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
67803 db->autoCommit = 1;
67804 }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
67805 goto vdbe_return;
67806 }else{
67807 db->autoCommit = (u8)u.as.desiredAutoCommit;
@@ -68701,11 +68863,11 @@
68863 u.bg.v = 1; /* IMP: R-61914-48074 */
68864 }else{
68865 assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) );
68866 rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v);
68867 assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
68868 if( u.bg.v>=MAX_ROWID ){
68869 u.bg.pC->useRandomRowid = 1;
68870 }else{
68871 u.bg.v++; /* IMP: R-29538-34987 */
68872 }
68873 }
@@ -74821,27 +74983,59 @@
74983 int op, /* Expression opcode */
74984 Expr *pLeft, /* Left operand */
74985 Expr *pRight, /* Right operand */
74986 const Token *pToken /* Argument token */
74987 ){
74988 Expr *p;
74989 if( op==TK_AND && pLeft && pRight ){
74990 /* Take advantage of short-circuit false optimization for AND */
74991 p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
74992 }else{
74993 p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
74994 sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
74995 }
74996 if( p ) {
74997 sqlite3ExprCheckHeight(pParse, p->nHeight);
74998 }
74999 return p;
75000 }
75001
75002 /*
75003 ** Return 1 if an expression must be FALSE in all cases and 0 if the
75004 ** expression might be true. This is an optimization. If is OK to
75005 ** return 0 here even if the expression really is always false (a
75006 ** false negative). But it is a bug to return 1 if the expression
75007 ** might be true in some rare circumstances (a false positive.)
75008 **
75009 ** Note that if the expression is part of conditional for a
75010 ** LEFT JOIN, then we cannot determine at compile-time whether or not
75011 ** is it true or false, so always return 0.
75012 */
75013 static int exprAlwaysFalse(Expr *p){
75014 int v = 0;
75015 if( ExprHasProperty(p, EP_FromJoin) ) return 0;
75016 if( !sqlite3ExprIsInteger(p, &v) ) return 0;
75017 return v==0;
75018 }
75019
75020 /*
75021 ** Join two expressions using an AND operator. If either expression is
75022 ** NULL, then just return the other expression.
75023 **
75024 ** If one side or the other of the AND is known to be false, then instead
75025 ** of returning an AND expression, just return a constant expression with
75026 ** a value of false.
75027 */
75028 SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
75029 if( pLeft==0 ){
75030 return pRight;
75031 }else if( pRight==0 ){
75032 return pLeft;
75033 }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
75034 sqlite3ExprDelete(db, pLeft);
75035 sqlite3ExprDelete(db, pRight);
75036 return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
75037 }else{
75038 Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
75039 sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
75040 return pNew;
75041 }
@@ -76369,19 +76563,10 @@
76563 ** Actually, the way the column cache is currently used, we are guaranteed
76564 ** that the object will never already be in cache. Verify this guarantee.
76565 */
76566 #ifndef NDEBUG
76567 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
 
 
 
 
 
 
 
 
 
76568 assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
76569 }
76570 #endif
76571
76572 /* Find an empty slot and replace it */
@@ -76512,11 +76697,12 @@
76697 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
76698 Parse *pParse, /* Parsing and code generating context */
76699 Table *pTab, /* Description of the table we are reading from */
76700 int iColumn, /* Index of the table column */
76701 int iTable, /* The cursor pointing to the table */
76702 int iReg, /* Store results here */
76703 u8 p5 /* P5 value for OP_Column */
76704 ){
76705 Vdbe *v = pParse->pVdbe;
76706 int i;
76707 struct yColCache *p;
76708
@@ -76527,11 +76713,15 @@
76713 return p->iReg;
76714 }
76715 }
76716 assert( v!=0 );
76717 sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
76718 if( p5 ){
76719 sqlite3VdbeChangeP5(v, p5);
76720 }else{
76721 sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
76722 }
76723 return iReg;
76724 }
76725
76726 /*
76727 ** Clear all column cache entries.
@@ -76655,11 +76845,12 @@
76845 /* This only happens when coding check constraints */
76846 assert( pParse->ckBase>0 );
76847 inReg = pExpr->iColumn + pParse->ckBase;
76848 }else{
76849 inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
76850 pExpr->iColumn, pExpr->iTable, target,
76851 pExpr->op2);
76852 }
76853 break;
76854 }
76855 case TK_INTEGER: {
76856 codeInteger(pParse, pExpr, 0, target);
@@ -76932,10 +77123,29 @@
77123 }
77124
77125
77126 if( pFarg ){
77127 r1 = sqlite3GetTempRange(pParse, nFarg);
77128
77129 /* For length() and typeof() functions with a column argument,
77130 ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
77131 ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
77132 ** loading.
77133 */
77134 if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
77135 u8 exprOp;
77136 assert( nFarg==1 );
77137 assert( pFarg->a[0].pExpr!=0 );
77138 exprOp = pFarg->a[0].pExpr->op;
77139 if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
77140 assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
77141 assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
77142 testcase( pDef->flags==SQLITE_FUNC_LENGTH );
77143 pFarg->a[0].pExpr->op2 = pDef->flags;
77144 }
77145 }
77146
77147 sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
77148 sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
77149 sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
77150 }else{
77151 r1 = 0;
@@ -80137,10 +80347,11 @@
80347 Index *pPrevIdx = 0; /* Previous index in the loop */
80348 int idx = 0; /* slot in pIdx->aSample[] for next sample */
80349 int eType; /* Datatype of a sample */
80350 IndexSample *pSample; /* A slot in pIdx->aSample[] */
80351
80352 assert( db->lookaside.bEnabled==0 );
80353 if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
80354 return SQLITE_OK;
80355 }
80356
80357 zSql = sqlite3MPrintf(db,
@@ -80163,11 +80374,11 @@
80374 nSample = sqlite3_column_int(pStmt, 1);
80375 pIdx = sqlite3FindIndex(db, zIndex, zDb);
80376 if( pIdx==0 ) continue;
80377 assert( pIdx->nSample==0 );
80378 pIdx->nSample = nSample;
80379 pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
80380 pIdx->avgEq = pIdx->aiRowEst[1];
80381 if( pIdx->aSample==0 ){
80382 db->mallocFailed = 1;
80383 sqlite3_finalize(pStmt);
80384 return SQLITE_NOMEM;
@@ -80236,11 +80447,11 @@
80447 int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
80448 pSample->nByte = n;
80449 if( n < 1){
80450 pSample->u.z = 0;
80451 }else{
80452 pSample->u.z = sqlite3DbMallocRaw(db, n);
80453 if( pSample->u.z==0 ){
80454 db->mallocFailed = 1;
80455 sqlite3_finalize(pStmt);
80456 return SQLITE_NOMEM;
80457 }
@@ -80312,11 +80523,14 @@
80523
80524
80525 /* Load the statistics from the sqlite_stat3 table. */
80526 #ifdef SQLITE_ENABLE_STAT3
80527 if( rc==SQLITE_OK ){
80528 int lookasideEnabled = db->lookaside.bEnabled;
80529 db->lookaside.bEnabled = 0;
80530 rc = loadStat3(db, sInfo.zDatabase);
80531 db->lookaside.bEnabled = lookasideEnabled;
80532 }
80533 #endif
80534
80535 if( rc==SQLITE_NOMEM ){
80536 db->mallocFailed = 1;
@@ -81675,11 +81889,11 @@
81889 sqliteDeleteColumnNames(db, pTable);
81890 sqlite3DbFree(db, pTable->zName);
81891 sqlite3DbFree(db, pTable->zColAff);
81892 sqlite3SelectDelete(db, pTable->pSelect);
81893 #ifndef SQLITE_OMIT_CHECK
81894 sqlite3ExprListDelete(db, pTable->pCheck);
81895 #endif
81896 #ifndef SQLITE_OMIT_VIRTUALTABLE
81897 sqlite3VtabClear(db, pTable);
81898 #endif
81899 sqlite3DbFree(db, pTable);
@@ -82338,19 +82552,21 @@
82552 */
82553 SQLITE_PRIVATE void sqlite3AddCheckConstraint(
82554 Parse *pParse, /* Parsing context */
82555 Expr *pCheckExpr /* The check expression */
82556 ){
 
82557 #ifndef SQLITE_OMIT_CHECK
82558 Table *pTab = pParse->pNewTable;
82559 if( pTab && !IN_DECLARE_VTAB ){
82560 pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
82561 if( pParse->constraintName.n ){
82562 sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
82563 }
82564 }else
82565 #endif
82566 {
82567 sqlite3ExprDelete(pParse->db, pCheckExpr);
82568 }
82569 }
82570
82571 /*
82572 ** Set the collation function of the most recently parsed table column
@@ -82616,10 +82832,12 @@
82832 /* Resolve names in all CHECK constraint expressions.
82833 */
82834 if( p->pCheck ){
82835 SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
82836 NameContext sNC; /* Name context for pParse->pNewTable */
82837 ExprList *pList; /* List of all CHECK constraints */
82838 int i; /* Loop counter */
82839
82840 memset(&sNC, 0, sizeof(sNC));
82841 memset(&sSrc, 0, sizeof(sSrc));
82842 sSrc.nSrc = 1;
82843 sSrc.a[0].zName = p->zName;
@@ -82626,12 +82844,15 @@
82844 sSrc.a[0].pTab = p;
82845 sSrc.a[0].iCursor = -1;
82846 sNC.pParse = pParse;
82847 sNC.pSrcList = &sSrc;
82848 sNC.isCheck = 1;
82849 pList = p->pCheck;
82850 for(i=0; i<pList->nExpr; i++){
82851 if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
82852 return;
82853 }
82854 }
82855 }
82856 #endif /* !defined(SQLITE_OMIT_CHECK) */
82857
82858 /* If the db->init.busy is 1 it means we are reading the SQL off the
@@ -84178,23 +84399,25 @@
84399 exit_drop_index:
84400 sqlite3SrcListDelete(db, pName);
84401 }
84402
84403 /*
84404 ** pArray is a pointer to an array of objects. Each object in the
84405 ** array is szEntry bytes in size. This routine uses sqlite3DbRealloc()
84406 ** to extend the array so that there is space for a new object at the end.
84407 **
84408 ** When this function is called, *pnEntry contains the current size of
84409 ** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes
84410 ** in total).
84411 **
84412 ** If the realloc() is successful (i.e. if no OOM condition occurs), the
84413 ** space allocated for the new object is zeroed, *pnEntry updated to
84414 ** reflect the new size of the array and a pointer to the new allocation
84415 ** returned. *pIdx is set to the index of the new array entry in this case.
84416 **
84417 ** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains
84418 ** unchanged and a copy of pArray returned.
84419 */
84420 SQLITE_PRIVATE void *sqlite3ArrayAllocate(
84421 sqlite3 *db, /* Connection to notify of malloc failures */
84422 void *pArray, /* Array of objects. Might be reallocated */
84423 int szEntry, /* Size of each object in the array */
@@ -85787,11 +86010,11 @@
86010 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
86011 pWInfo = sqlite3WhereBegin(
86012 pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
86013 );
86014 if( pWInfo==0 ) goto delete_from_cleanup;
86015 regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
86016 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
86017 if( db->flags & SQLITE_CountRows ){
86018 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
86019 }
86020 sqlite3WhereEnd(pWInfo);
@@ -87607,12 +87830,12 @@
87830 FUNCTION(min, 0, 0, 1, 0 ),
87831 AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
87832 FUNCTION(max, -1, 1, 1, minmaxFunc ),
87833 FUNCTION(max, 0, 1, 1, 0 ),
87834 AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
87835 FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
87836 FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
87837 FUNCTION(substr, 2, 0, 0, substrFunc ),
87838 FUNCTION(substr, 3, 0, 0, substrFunc ),
87839 FUNCTION(abs, 1, 0, 0, absFunc ),
87840 #ifndef SQLITE_OMIT_FLOATING_POINT
87841 FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -87620,15 +87843,13 @@
87843 #endif
87844 FUNCTION(upper, 1, 0, 0, upperFunc ),
87845 FUNCTION(lower, 1, 0, 0, lowerFunc ),
87846 FUNCTION(coalesce, 1, 0, 0, 0 ),
87847 FUNCTION(coalesce, 0, 0, 0, 0 ),
87848 FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
 
87849 FUNCTION(hex, 1, 0, 0, hexFunc ),
87850 FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
 
87851 FUNCTION(random, 0, 0, 0, randomFunc ),
87852 FUNCTION(randomblob, 1, 0, 0, randomBlob ),
87853 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
87854 FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
87855 FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -90061,13 +90282,15 @@
90282 int j1; /* Addresss of jump instruction */
90283 int j2 = 0, j3; /* Addresses of jump instructions */
90284 int regData; /* Register containing first data column */
90285 int iCur; /* Table cursor number */
90286 Index *pIdx; /* Pointer to one of the indices */
90287 sqlite3 *db; /* Database connection */
90288 int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
90289 int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
90290
90291 db = pParse->db;
90292 v = sqlite3GetVdbe(pParse);
90293 assert( v!=0 );
90294 assert( pTab->pSelect==0 ); /* This table is not a VIEW */
90295 nCol = pTab->nCol;
90296 regData = regRowid + 1;
@@ -90096,11 +90319,11 @@
90319 case OE_Rollback:
90320 case OE_Fail: {
90321 char *zMsg;
90322 sqlite3VdbeAddOp3(v, OP_HaltIfNull,
90323 SQLITE_CONSTRAINT, onError, regData+i);
90324 zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
90325 pTab->zName, pTab->aCol[i].zName);
90326 sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
90327 break;
90328 }
90329 case OE_Ignore: {
@@ -90118,22 +90341,31 @@
90341 }
90342
90343 /* Test all CHECK constraints
90344 */
90345 #ifndef SQLITE_OMIT_CHECK
90346 if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
90347 ExprList *pCheck = pTab->pCheck;
90348 pParse->ckBase = regData;
 
90349 onError = overrideError!=OE_Default ? overrideError : OE_Abort;
90350 for(i=0; i<pCheck->nExpr; i++){
90351 int allOk = sqlite3VdbeMakeLabel(v);
90352 sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
90353 if( onError==OE_Ignore ){
90354 sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
90355 }else{
90356 char *zConsName = pCheck->a[i].zName;
90357 if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
90358 if( zConsName ){
90359 zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
90360 }else{
90361 zConsName = 0;
90362 }
90363 sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
90364 }
90365 sqlite3VdbeResolveLabel(v, allOk);
90366 }
 
90367 }
90368 #endif /* !defined(SQLITE_OMIT_CHECK) */
90369
90370 /* If we have an INTEGER PRIMARY KEY, make sure the primary key
90371 ** of the new record does not previously exist. Except, if this
@@ -90185,11 +90417,11 @@
90417 **
90418 ** to run without a statement journal if there are no indexes on the
90419 ** table.
90420 */
90421 Trigger *pTrigger = 0;
90422 if( db->flags&SQLITE_RecTriggers ){
90423 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
90424 }
90425 if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
90426 sqlite3MultiWrite(pParse);
90427 sqlite3GenerateRowDelete(
@@ -90274,11 +90506,11 @@
90506 StrAccum errMsg;
90507 const char *zSep;
90508 char *zErr;
90509
90510 sqlite3StrAccumInit(&errMsg, 0, 0, 200);
90511 errMsg.db = db;
90512 zSep = pIdx->nColumn>1 ? "columns " : "column ";
90513 for(j=0; j<pIdx->nColumn; j++){
90514 char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
90515 sqlite3StrAccumAppend(&errMsg, zSep, -1);
90516 zSep = ", ";
@@ -90298,11 +90530,11 @@
90530 }
90531 default: {
90532 Trigger *pTrigger = 0;
90533 assert( onError==OE_Replace );
90534 sqlite3MultiWrite(pParse);
90535 if( db->flags&SQLITE_RecTriggers ){
90536 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
90537 }
90538 sqlite3GenerateRowDelete(
90539 pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
90540 );
@@ -90628,11 +90860,11 @@
90860 if( pSrcIdx==0 ){
90861 return 0; /* pDestIdx has no corresponding index in pSrc */
90862 }
90863 }
90864 #ifndef SQLITE_OMIT_CHECK
90865 if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
90866 return 0; /* Tables have different CHECK constraints. Ticket #2252 */
90867 }
90868 #endif
90869 #ifndef SQLITE_OMIT_FOREIGN_KEY
90870 /* Disallow the transfer optimization if the destination table constains
@@ -92317,13 +92549,16 @@
92549 char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */
92550 char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */
92551 const char *zDb = 0; /* The database name */
92552 Token *pId; /* Pointer to <id> token */
92553 int iDb; /* Database index for <database> */
92554 char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
92555 int rc; /* return value form SQLITE_FCNTL_PRAGMA */
92556 sqlite3 *db = pParse->db; /* The database connection */
92557 Db *pDb; /* The specific database being pragmaed */
92558 Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */
92559
92560 if( v==0 ) return;
92561 sqlite3VdbeRunOnlyOnce(v);
92562 pParse->nMem = 2;
92563
92564 /* Interpret the [database.] part of the pragma statement. iDb is the
@@ -92350,10 +92585,38 @@
92585 assert( pId2 );
92586 zDb = pId2->n>0 ? pDb->zName : 0;
92587 if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
92588 goto pragma_out;
92589 }
92590
92591 /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
92592 ** connection. If it returns SQLITE_OK, then assume that the VFS
92593 ** handled the pragma and generate a no-op prepared statement.
92594 */
92595 aFcntl[0] = 0;
92596 aFcntl[1] = zLeft;
92597 aFcntl[2] = zRight;
92598 aFcntl[3] = 0;
92599 rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
92600 if( rc==SQLITE_OK ){
92601 if( aFcntl[0] ){
92602 int mem = ++pParse->nMem;
92603 sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
92604 sqlite3VdbeSetNumCols(v, 1);
92605 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
92606 sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
92607 sqlite3_free(aFcntl[0]);
92608 }
92609 }else if( rc!=SQLITE_NOTFOUND ){
92610 if( aFcntl[0] ){
92611 sqlite3ErrorMsg(pParse, "%s", aFcntl[0]);
92612 sqlite3_free(aFcntl[0]);
92613 }
92614 pParse->nErr++;
92615 pParse->rc = rc;
92616 }else
92617
92618
92619 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
92620 /*
92621 ** PRAGMA [database.]default_cache_size
92622 ** PRAGMA [database.]default_cache_size=N
@@ -92637,11 +92900,11 @@
92900 /* Call SetAutoVacuum() to set initialize the internal auto and
92901 ** incr-vacuum flags. This is required in case this connection
92902 ** creates the database file. It is important that it is created
92903 ** as an auto-vacuum capable db.
92904 */
92905 rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
92906 if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
92907 /* When setting the auto_vacuum mode to either "full" or
92908 ** "incremental", write the value of meta[6] in the database
92909 ** file. Before writing to meta[6], check that meta[3] indicates
92910 ** that this really is an auto-vacuum capable database.
@@ -92755,11 +93018,10 @@
93018 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
93019 }
93020 }else{
93021 #ifndef SQLITE_OMIT_WSD
93022 if( zRight[0] ){
 
93023 int res;
93024 rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
93025 if( rc!=SQLITE_OK || res==0 ){
93026 sqlite3ErrorMsg(pParse, "not a writable directory");
93027 goto pragma_out;
@@ -95671,13 +95933,21 @@
95933 int nCol; /* Number of columns in the result set */
95934 Expr *p; /* Expression for a single result column */
95935 char *zName; /* Column name */
95936 int nName; /* Size of name in zName[] */
95937
95938 if( pEList ){
95939 nCol = pEList->nExpr;
95940 aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
95941 testcase( aCol==0 );
95942 }else{
95943 nCol = 0;
95944 aCol = 0;
95945 }
95946 *pnCol = nCol;
95947 *paCol = aCol;
95948
95949 for(i=0, pCol=aCol; i<nCol; i++, pCol++){
95950 /* Get an appropriate name for the column
95951 */
95952 p = pEList->a[i].pExpr;
95953 assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
@@ -98641,11 +98911,11 @@
98911 if( pCol->iSorterColumn>=j ){
98912 int r1 = j + regBase;
98913 int r2;
98914
98915 r2 = sqlite3ExprCodeGetColumn(pParse,
98916 pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
98917 if( r1!=r2 ){
98918 sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
98919 }
98920 j++;
98921 }
@@ -101201,10 +101471,22 @@
101471 char *zKey;
101472 sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
101473 if( nKey ) db->nextPagesize = 0;
101474 }
101475 #endif
101476
101477 rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
101478 if( rc!=SQLITE_OK ) goto end_of_vacuum;
101479
101480 /* Begin a transaction and take an exclusive lock on the main database
101481 ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
101482 ** to ensure that we do not try to change the page-size on a WAL database.
101483 */
101484 rc = execSql(db, pzErrMsg, "BEGIN;");
101485 if( rc!=SQLITE_OK ) goto end_of_vacuum;
101486 rc = sqlite3BtreeBeginTrans(pMain, 2);
101487 if( rc!=SQLITE_OK ) goto end_of_vacuum;
101488
101489 /* Do not attempt to change the page size for a WAL database */
101490 if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
101491 ==PAGER_JOURNALMODE_WAL ){
101492 db->nextPagesize = 0;
@@ -101215,24 +101497,16 @@
101497 || NEVER(db->mallocFailed)
101498 ){
101499 rc = SQLITE_NOMEM;
101500 goto end_of_vacuum;
101501 }
 
 
 
 
101502
101503 #ifndef SQLITE_OMIT_AUTOVACUUM
101504 sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac :
101505 sqlite3BtreeGetAutoVacuum(pMain));
101506 #endif
101507
 
 
 
 
101508 /* Query the schema of the main database. Create a mirror schema
101509 ** in the temporary database.
101510 */
101511 rc = execExecSql(db, pzErrMsg,
101512 "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
@@ -103126,11 +103400,14 @@
103400 #ifdef SQLITE_EBCDIC
103401 if( *pnoCase ) return 0;
103402 #endif
103403 pList = pExpr->x.pList;
103404 pLeft = pList->a[1].pExpr;
103405 if( pLeft->op!=TK_COLUMN
103406 || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
103407 || IsVirtual(pLeft->pTab)
103408 ){
103409 /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
103410 ** be the name of an indexed column with TEXT affinity. */
103411 return 0;
103412 }
103413 assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
@@ -105543,11 +105820,13 @@
105820 }
105821
105822 /* If there is a DISTINCT qualifier and this index will scan rows in
105823 ** order of the DISTINCT expressions, clear bDist and set the appropriate
105824 ** flags in wsFlags. */
105825 if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq)
105826 && (wsFlags & WHERE_COLUMN_IN)==0
105827 ){
105828 bDist = 0;
105829 wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
105830 }
105831
105832 /* If currently calculating the cost of using an index (not the IPK
@@ -106240,12 +106519,11 @@
106519 */
106520 static Bitmask codeOneLoopStart(
106521 WhereInfo *pWInfo, /* Complete information about the WHERE clause */
106522 int iLevel, /* Which level of pWInfo->a[] should be coded */
106523 u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
106524 Bitmask notReady /* Which tables are currently available */
 
106525 ){
106526 int j, k; /* Loop counters */
106527 int iCur; /* The VDBE cursor for the table */
106528 int addrNxt; /* Where to jump to continue with the next IN case */
106529 int omitTable; /* True if we use the index only */
@@ -106780,14 +107058,29 @@
107058
107059 /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
107060 ** Then for every term xN, evaluate as the subexpression: xN AND z
107061 ** That way, terms in y that are factored into the disjunction will
107062 ** be picked up by the recursive calls to sqlite3WhereBegin() below.
107063 **
107064 ** Actually, each subexpression is converted to "xN AND w" where w is
107065 ** the "interesting" terms of z - terms that did not originate in the
107066 ** ON or USING clause of a LEFT JOIN, and terms that are usable as
107067 ** indices.
107068 */
107069 if( pWC->nTerm>1 ){
107070 int iTerm;
107071 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
107072 Expr *pExpr = pWC->a[iTerm].pExpr;
107073 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
107074 if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
107075 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
107076 pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
107077 pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
107078 }
107079 if( pAndExpr ){
107080 pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
107081 }
107082 }
107083
107084 for(ii=0; ii<pOrWc->nTerm; ii++){
107085 WhereTerm *pOrTerm = &pOrWc->a[ii];
107086 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
@@ -106807,11 +107100,11 @@
107100 );
107101 if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
107102 int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
107103 int r;
107104 r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
107105 regRowid, 0);
107106 sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
107107 sqlite3VdbeCurrentAddr(v)+2, r, iSet);
107108 }
107109 sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
107110
@@ -106825,11 +107118,14 @@
107118 /* Finish the loop through table entries that match term pOrTerm. */
107119 sqlite3WhereEnd(pSubWInfo);
107120 }
107121 }
107122 }
107123 if( pAndExpr ){
107124 pAndExpr->pLeft = 0;
107125 sqlite3ExprDelete(pParse->db, pAndExpr);
107126 }
107127 sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
107128 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
107129 sqlite3VdbeResolveLabel(v, iLoopBody);
107130
107131 if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
@@ -107481,11 +107777,11 @@
107777 */
107778 notReady = ~(Bitmask)0;
107779 for(i=0; i<nTabList; i++){
107780 pLevel = &pWInfo->a[i];
107781 explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
107782 notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
107783 pWInfo->iContinue = pLevel->addrCont;
107784 }
107785
107786 #ifdef SQLITE_TEST /* For testing and debugging use only */
107787 /* Record in the query plan information about the current table
@@ -107717,11 +108013,11 @@
108013 ** An instance of this structure is used to store the LIKE,
108014 ** GLOB, NOT LIKE, and NOT GLOB operators.
108015 */
108016 struct LikeOp {
108017 Token eOperator; /* "like" or "glob" or "regexp" */
108018 int bNot; /* True if the NOT keyword is present */
108019 };
108020
108021 /*
108022 ** An instance of the following structure describes the event of a
108023 ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
@@ -107896,12 +108192,12 @@
108192 #endif
108193 #define sqlite3ParserARG_SDECL Parse *pParse;
108194 #define sqlite3ParserARG_PDECL ,Parse *pParse
108195 #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
108196 #define sqlite3ParserARG_STORE yypParser->pParse = pParse
108197 #define YYNSTATE 627
108198 #define YYNRULE 325
108199 #define YYFALLBACK 1
108200 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
108201 #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
108202 #define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
108203
@@ -107967,480 +108263,478 @@
108263 ** shifting terminals.
108264 ** yy_reduce_ofst[] For each state, the offset into yy_action for
108265 ** shifting non-terminals after a reduce.
108266 ** yy_default[] Default action for each state.
108267 */
108268 #define YY_ACTTAB_COUNT (1561)
108269 static const YYACTIONTYPE yy_action[] = {
108270 /* 0 */ 310, 328, 573, 572, 15, 171, 185, 595, 56, 56,
108271 /* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52,
108272 /* 20 */ 52, 52, 51, 233, 52, 52, 52, 51, 233, 624,
108273 /* 30 */ 588, 582, 56, 56, 56, 56, 314, 54, 54, 54,
108274 /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 299, 57,
108275 /* 50 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108276 /* 60 */ 56, 56, 569, 54, 54, 54, 54, 53, 53, 52,
108277 /* 70 */ 52, 52, 51, 233, 310, 595, 326, 575, 663, 65,
108278 /* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108279 /* 90 */ 51, 233, 53, 53, 52, 52, 52, 51, 233, 489,
108280 /* 100 */ 663, 440, 663, 235, 588, 582, 553, 297, 363, 59,
108281 /* 110 */ 481, 67, 360, 1, 618, 351, 618, 620, 619, 207,
108282 /* 120 */ 6, 441, 442, 57, 58, 48, 580, 579, 581, 581,
108283 /* 130 */ 55, 55, 56, 56, 56, 56, 605, 54, 54, 54,
108284 /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 223,
108285 /* 150 */ 50, 47, 146, 598, 138, 281, 385, 276, 384, 168,
108286 /* 160 */ 489, 552, 620, 619, 620, 619, 272, 214, 440, 411,
108287 /* 170 */ 551, 604, 67, 165, 7, 618, 352, 353, 588, 582,
108288 /* 180 */ 443, 569, 192, 618, 414, 617, 616, 668, 441, 336,
108289 /* 190 */ 669, 62, 618, 599, 92, 382, 346, 57, 58, 48,
108290 /* 200 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
108291 /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108292 /* 220 */ 51, 233, 310, 465, 232, 231, 373, 132, 514, 513,
108293 /* 230 */ 617, 616, 617, 616, 398, 437, 411, 66, 280, 388,
108294 /* 240 */ 411, 595, 439, 220, 438, 620, 619, 337, 569, 279,
108295 /* 250 */ 201, 414, 588, 582, 166, 414, 546, 167, 68, 234,
108296 /* 260 */ 599, 92, 620, 619, 599, 92, 19, 570, 570, 466,
108297 /* 270 */ 564, 57, 58, 48, 580, 579, 581, 581, 55, 55,
108298 /* 280 */ 56, 56, 56, 56, 598, 54, 54, 54, 54, 53,
108299 /* 290 */ 53, 52, 52, 52, 51, 233, 310, 411, 524, 232,
108300 /* 300 */ 231, 398, 593, 547, 559, 398, 348, 202, 175, 595,
108301 /* 310 */ 399, 315, 414, 617, 616, 387, 272, 255, 347, 254,
108302 /* 320 */ 558, 599, 74, 620, 619, 45, 588, 582, 235, 466,
108303 /* 330 */ 617, 616, 511, 591, 591, 591, 557, 578, 402, 545,
108304 /* 340 */ 600, 598, 570, 570, 601, 57, 58, 48, 580, 579,
108305 /* 350 */ 581, 581, 55, 55, 56, 56, 56, 56, 550, 54,
108306 /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
108307 /* 370 */ 310, 309, 411, 145, 566, 490, 213, 255, 347, 254,
108308 /* 380 */ 196, 195, 194, 587, 586, 531, 600, 414, 235, 174,
108309 /* 390 */ 601, 617, 616, 411, 620, 619, 599, 91, 547, 574,
108310 /* 400 */ 588, 582, 50, 47, 146, 584, 583, 471, 414, 249,
108311 /* 410 */ 565, 542, 186, 39, 304, 424, 562, 599, 16, 57,
108312 /* 420 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108313 /* 430 */ 56, 56, 585, 54, 54, 54, 54, 53, 53, 52,
108314 /* 440 */ 52, 52, 51, 233, 310, 559, 290, 530, 529, 345,
108315 /* 450 */ 533, 576, 540, 246, 170, 248, 411, 396, 411, 422,
108316 /* 460 */ 199, 558, 617, 616, 165, 563, 50, 47, 146, 181,
108317 /* 470 */ 498, 414, 166, 414, 588, 582, 269, 557, 166, 518,
108318 /* 480 */ 599, 92, 599, 92, 561, 595, 469, 36, 173, 409,
108319 /* 490 */ 517, 577, 577, 57, 58, 48, 580, 579, 581, 581,
108320 /* 500 */ 55, 55, 56, 56, 56, 56, 338, 54, 54, 54,
108321 /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 304,
108322 /* 520 */ 423, 394, 526, 318, 869, 235, 167, 180, 473, 547,
108323 /* 530 */ 503, 247, 474, 381, 378, 377, 409, 351, 577, 577,
108324 /* 540 */ 409, 560, 577, 577, 376, 383, 364, 603, 588, 582,
108325 /* 550 */ 620, 619, 502, 595, 409, 494, 577, 577, 409, 266,
108326 /* 560 */ 577, 577, 421, 943, 422, 943, 198, 57, 58, 48,
108327 /* 570 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
108328 /* 580 */ 315, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108329 /* 590 */ 51, 233, 310, 390, 421, 942, 509, 942, 556, 145,
108330 /* 600 */ 598, 391, 324, 262, 549, 264, 411, 425, 407, 573,
108331 /* 610 */ 572, 12, 197, 143, 489, 50, 47, 146, 617, 616,
108332 /* 620 */ 206, 414, 588, 582, 547, 429, 67, 212, 143, 618,
108333 /* 630 */ 599, 73, 504, 505, 207, 434, 475, 475, 366, 425,
108334 /* 640 */ 35, 57, 58, 48, 580, 579, 581, 581, 55, 55,
108335 /* 650 */ 56, 56, 56, 56, 598, 54, 54, 54, 54, 53,
108336 /* 660 */ 53, 52, 52, 52, 51, 233, 310, 260, 598, 569,
108337 /* 670 */ 268, 615, 614, 613, 171, 411, 595, 11, 411, 350,
108338 /* 680 */ 411, 32, 618, 953, 183, 419, 2, 627, 625, 330,
108339 /* 690 */ 414, 352, 552, 414, 538, 414, 588, 582, 188, 599,
108340 /* 700 */ 69, 551, 599, 94, 599, 97, 374, 544, 166, 618,
108341 /* 710 */ 334, 359, 50, 47, 146, 57, 58, 48, 580, 579,
108342 /* 720 */ 581, 581, 55, 55, 56, 56, 56, 56, 411, 54,
108343 /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
108344 /* 740 */ 310, 411, 129, 414, 595, 22, 273, 156, 411, 566,
108345 /* 750 */ 406, 213, 599, 95, 570, 570, 414, 327, 169, 332,
108346 /* 760 */ 411, 618, 536, 414, 358, 599, 104, 483, 508, 356,
108347 /* 770 */ 588, 582, 599, 103, 484, 414, 470, 357, 166, 618,
108348 /* 780 */ 626, 2, 204, 323, 599, 105, 40, 528, 38, 57,
108349 /* 790 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108350 /* 800 */ 56, 56, 411, 54, 54, 54, 54, 53, 53, 52,
108351 /* 810 */ 52, 52, 51, 233, 310, 411, 598, 414, 411, 260,
108352 /* 820 */ 273, 273, 273, 273, 426, 305, 599, 106, 520, 519,
108353 /* 830 */ 414, 411, 142, 414, 618, 618, 618, 618, 618, 599,
108354 /* 840 */ 133, 339, 599, 134, 588, 582, 414, 21, 30, 316,
108355 /* 850 */ 147, 459, 221, 170, 527, 599, 98, 222, 322, 321,
108356 /* 860 */ 320, 141, 259, 57, 58, 48, 580, 579, 581, 581,
108357 /* 870 */ 55, 55, 56, 56, 56, 56, 411, 54, 54, 54,
108358 /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 411,
108359 /* 890 */ 260, 414, 411, 458, 200, 35, 411, 358, 211, 228,
108360 /* 900 */ 599, 102, 468, 519, 414, 618, 28, 414, 538, 501,
108361 /* 910 */ 411, 414, 618, 599, 101, 358, 599, 93, 588, 582,
108362 /* 920 */ 599, 100, 522, 618, 427, 414, 306, 271, 598, 380,
108363 /* 930 */ 618, 602, 598, 452, 599, 77, 210, 57, 58, 48,
108364 /* 940 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
108365 /* 950 */ 411, 54, 54, 54, 54, 53, 53, 52, 52, 52,
108366 /* 960 */ 51, 233, 310, 411, 621, 414, 411, 127, 609, 270,
108367 /* 970 */ 598, 365, 51, 233, 599, 96, 625, 330, 414, 618,
108368 /* 980 */ 126, 414, 411, 618, 411, 253, 608, 599, 137, 27,
108369 /* 990 */ 599, 136, 588, 582, 375, 260, 125, 414, 164, 414,
108370 /* 1000 */ 371, 618, 279, 219, 542, 542, 599, 135, 599, 76,
108371 /* 1010 */ 618, 57, 46, 48, 580, 579, 581, 581, 55, 55,
108372 /* 1020 */ 56, 56, 56, 56, 411, 54, 54, 54, 54, 53,
108373 /* 1030 */ 53, 52, 52, 52, 51, 233, 310, 411, 450, 414,
108374 /* 1040 */ 411, 260, 542, 229, 285, 607, 479, 184, 599, 90,
108375 /* 1050 */ 367, 122, 414, 476, 121, 414, 618, 170, 411, 353,
108376 /* 1060 */ 618, 599, 89, 410, 599, 75, 588, 582, 472, 257,
108377 /* 1070 */ 538, 120, 159, 414, 618, 14, 464, 158, 618, 157,
108378 /* 1080 */ 461, 283, 599, 88, 449, 618, 58, 48, 580, 579,
108379 /* 1090 */ 581, 581, 55, 55, 56, 56, 56, 56, 411, 54,
108380 /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
108381 /* 1110 */ 310, 411, 260, 414, 411, 592, 260, 118, 25, 400,
108382 /* 1120 */ 10, 24, 599, 87, 117, 216, 414, 618, 349, 414,
108383 /* 1130 */ 618, 618, 411, 319, 618, 599, 99, 555, 599, 86,
108384 /* 1140 */ 588, 582, 4, 260, 457, 455, 115, 414, 251, 154,
108385 /* 1150 */ 451, 108, 618, 110, 436, 448, 599, 17, 618, 218,
108386 /* 1160 */ 107, 48, 580, 579, 581, 581, 55, 55, 56, 56,
108387 /* 1170 */ 56, 56, 435, 54, 54, 54, 54, 53, 53, 52,
108388 /* 1180 */ 52, 52, 51, 233, 44, 405, 217, 3, 411, 260,
108389 /* 1190 */ 543, 415, 619, 445, 64, 149, 539, 237, 333, 329,
108390 /* 1200 */ 203, 187, 408, 414, 618, 618, 420, 44, 405, 411,
108391 /* 1210 */ 3, 618, 599, 85, 415, 619, 148, 227, 622, 179,
108392 /* 1220 */ 313, 403, 312, 612, 414, 408, 611, 124, 417, 178,
108393 /* 1230 */ 610, 564, 243, 599, 84, 537, 8, 176, 235, 416,
108394 /* 1240 */ 294, 418, 623, 30, 403, 597, 411, 236, 293, 123,
108395 /* 1250 */ 618, 41, 42, 532, 564, 205, 292, 275, 43, 413,
108396 /* 1260 */ 412, 414, 395, 593, 507, 274, 31, 397, 291, 37,
108397 /* 1270 */ 599, 83, 618, 491, 41, 42, 267, 411, 265, 618,
108398 /* 1280 */ 618, 43, 413, 412, 596, 263, 593, 60, 618, 598,
108399 /* 1290 */ 261, 618, 414, 618, 591, 591, 591, 590, 589, 13,
108400 /* 1300 */ 618, 599, 72, 554, 235, 618, 44, 405, 256, 3,
108401 /* 1310 */ 361, 172, 340, 415, 619, 230, 411, 591, 591, 591,
108402 /* 1320 */ 590, 589, 13, 618, 408, 618, 182, 411, 286, 34,
108403 /* 1330 */ 405, 414, 3, 411, 463, 411, 415, 619, 29, 331,
108404 /* 1340 */ 599, 71, 414, 403, 392, 386, 284, 408, 414, 618,
108405 /* 1350 */ 414, 599, 82, 564, 411, 462, 354, 599, 81, 599,
108406 /* 1360 */ 80, 541, 250, 535, 282, 521, 403, 534, 516, 414,
108407 /* 1370 */ 618, 618, 454, 41, 42, 411, 564, 618, 599, 70,
108408 /* 1380 */ 43, 413, 412, 444, 515, 593, 242, 618, 325, 61,
108409 /* 1390 */ 414, 277, 239, 620, 619, 238, 41, 42, 618, 599,
108410 /* 1400 */ 18, 618, 512, 43, 413, 412, 511, 618, 593, 430,
108411 /* 1410 */ 618, 411, 128, 510, 308, 226, 591, 591, 591, 590,
108412 /* 1420 */ 589, 13, 215, 289, 618, 225, 414, 302, 301, 300,
108413 /* 1430 */ 177, 298, 411, 564, 453, 599, 79, 224, 618, 591,
108414 /* 1440 */ 591, 591, 590, 589, 13, 389, 492, 414, 150, 144,
108415 /* 1450 */ 241, 393, 288, 191, 190, 193, 599, 78, 165, 240,
108416 /* 1460 */ 414, 524, 487, 307, 618, 593, 618, 618, 486, 599,
108417 /* 1470 */ 9, 163, 152, 485, 466, 372, 480, 162, 153, 370,
108418 /* 1480 */ 161, 151, 209, 478, 258, 368, 477, 26, 160, 467,
108419 /* 1490 */ 140, 362, 131, 119, 116, 456, 591, 591, 591, 155,
108420 /* 1500 */ 114, 344, 343, 113, 112, 111, 447, 109, 130, 23,
108421 /* 1510 */ 317, 433, 20, 432, 431, 428, 606, 594, 63, 189,
108422 /* 1520 */ 404, 571, 255, 342, 244, 295, 287, 278, 311, 508,
108423 /* 1530 */ 496, 497, 495, 235, 493, 568, 379, 355, 460, 245,
108424 /* 1540 */ 341, 446, 303, 567, 5, 252, 548, 208, 139, 506,
108425 /* 1550 */ 369, 401, 500, 499, 296, 525, 335, 488, 482, 523,
108426 /* 1560 */ 233,
 
108427 };
108428 static const YYCODETYPE yy_lookahead[] = {
108429 /* 0 */ 19, 169, 170, 171, 22, 24, 24, 26, 77, 78,
108430 /* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
108431 /* 20 */ 89, 90, 91, 92, 88, 89, 90, 91, 92, 1,
108432 /* 30 */ 49, 50, 77, 78, 79, 80, 155, 82, 83, 84,
108433 /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 15, 68,
108434 /* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108435 /* 60 */ 79, 80, 230, 82, 83, 84, 85, 86, 87, 88,
108436 /* 70 */ 89, 90, 91, 92, 19, 94, 19, 23, 1, 25,
108437 /* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108438 /* 90 */ 91, 92, 86, 87, 88, 89, 90, 91, 92, 150,
108439 /* 100 */ 23, 150, 25, 116, 49, 50, 177, 158, 227, 54,
108440 /* 110 */ 161, 162, 231, 22, 165, 128, 165, 26, 27, 160,
108441 /* 120 */ 22, 170, 171, 68, 69, 70, 71, 72, 73, 74,
108442 /* 130 */ 75, 76, 77, 78, 79, 80, 23, 82, 83, 84,
108443 /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92,
108444 /* 150 */ 221, 222, 223, 194, 97, 98, 99, 100, 101, 102,
108445 /* 160 */ 150, 32, 26, 27, 26, 27, 109, 22, 150, 150,
108446 /* 170 */ 41, 161, 162, 96, 76, 165, 217, 150, 49, 50,
108447 /* 180 */ 229, 230, 172, 165, 165, 94, 95, 118, 170, 171,
108448 /* 190 */ 118, 232, 165, 174, 175, 185, 237, 68, 69, 70,
108449 /* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108450 /* 210 */ 118, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108451 /* 220 */ 91, 92, 19, 11, 86, 87, 19, 24, 7, 8,
108452 /* 230 */ 94, 95, 94, 95, 215, 97, 150, 22, 98, 220,
108453 /* 240 */ 150, 26, 104, 216, 106, 26, 27, 229, 230, 109,
108454 /* 250 */ 160, 165, 49, 50, 25, 165, 120, 50, 22, 197,
108455 /* 260 */ 174, 175, 26, 27, 174, 175, 204, 129, 130, 57,
108456 /* 270 */ 66, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108457 /* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
108458 /* 290 */ 87, 88, 89, 90, 91, 92, 19, 150, 94, 86,
108459 /* 300 */ 87, 215, 98, 25, 12, 215, 220, 160, 118, 94,
108460 /* 310 */ 220, 104, 165, 94, 95, 88, 109, 105, 106, 107,
108461 /* 320 */ 28, 174, 175, 26, 27, 22, 49, 50, 116, 57,
108462 /* 330 */ 94, 95, 103, 129, 130, 131, 44, 113, 46, 120,
108463 /* 340 */ 113, 194, 129, 130, 117, 68, 69, 70, 71, 72,
108464 /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 177, 82,
108465 /* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108466 /* 370 */ 19, 163, 150, 95, 166, 167, 168, 105, 106, 107,
108467 /* 380 */ 105, 106, 107, 49, 50, 88, 113, 165, 116, 118,
108468 /* 390 */ 117, 94, 95, 150, 26, 27, 174, 175, 120, 23,
108469 /* 400 */ 49, 50, 221, 222, 223, 71, 72, 21, 165, 16,
108470 /* 410 */ 23, 166, 22, 136, 22, 23, 11, 174, 175, 68,
108471 /* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108472 /* 430 */ 79, 80, 98, 82, 83, 84, 85, 86, 87, 88,
108473 /* 440 */ 89, 90, 91, 92, 19, 12, 224, 23, 23, 63,
108474 /* 450 */ 205, 23, 23, 60, 25, 62, 150, 214, 150, 67,
108475 /* 460 */ 22, 28, 94, 95, 96, 23, 221, 222, 223, 23,
108476 /* 470 */ 23, 165, 25, 165, 49, 50, 23, 44, 25, 46,
108477 /* 480 */ 174, 175, 174, 175, 23, 26, 100, 136, 25, 112,
108478 /* 490 */ 57, 114, 115, 68, 69, 70, 71, 72, 73, 74,
108479 /* 500 */ 75, 76, 77, 78, 79, 80, 97, 82, 83, 84,
108480 /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 22,
108481 /* 520 */ 23, 215, 23, 215, 138, 116, 50, 23, 30, 25,
108482 /* 530 */ 36, 138, 34, 99, 100, 101, 112, 128, 114, 115,
108483 /* 540 */ 112, 23, 114, 115, 110, 51, 48, 173, 49, 50,
108484 /* 550 */ 26, 27, 58, 94, 112, 181, 114, 115, 112, 16,
108485 /* 560 */ 114, 115, 22, 23, 67, 25, 160, 68, 69, 70,
108486 /* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108487 /* 580 */ 104, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108488 /* 590 */ 91, 92, 19, 19, 22, 23, 23, 25, 23, 95,
108489 /* 600 */ 194, 27, 108, 60, 25, 62, 150, 67, 169, 170,
108490 /* 610 */ 171, 35, 206, 207, 150, 221, 222, 223, 94, 95,
108491 /* 620 */ 160, 165, 49, 50, 120, 161, 162, 206, 207, 165,
108492 /* 630 */ 174, 175, 97, 98, 160, 241, 105, 106, 107, 67,
108493 /* 640 */ 25, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108494 /* 650 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
108495 /* 660 */ 87, 88, 89, 90, 91, 92, 19, 150, 194, 230,
108496 /* 670 */ 23, 7, 8, 9, 24, 150, 26, 35, 150, 219,
108497 /* 680 */ 150, 25, 165, 142, 143, 144, 145, 0, 1, 2,
108498 /* 690 */ 165, 217, 32, 165, 150, 165, 49, 50, 119, 174,
108499 /* 700 */ 175, 41, 174, 175, 174, 175, 23, 120, 25, 165,
108500 /* 710 */ 193, 237, 221, 222, 223, 68, 69, 70, 71, 72,
108501 /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
108502 /* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108503 /* 740 */ 19, 150, 22, 165, 94, 24, 150, 25, 150, 166,
108504 /* 750 */ 167, 168, 174, 175, 129, 130, 165, 213, 35, 242,
108505 /* 760 */ 150, 165, 27, 165, 150, 174, 175, 181, 182, 19,
108506 /* 770 */ 49, 50, 174, 175, 188, 165, 23, 27, 25, 165,
108507 /* 780 */ 144, 145, 160, 187, 174, 175, 135, 23, 137, 68,
108508 /* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108509 /* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88,
108510 /* 810 */ 89, 90, 91, 92, 19, 150, 194, 165, 150, 150,
108511 /* 820 */ 150, 150, 150, 150, 247, 248, 174, 175, 190, 191,
108512 /* 830 */ 165, 150, 118, 165, 165, 165, 165, 165, 165, 174,
108513 /* 840 */ 175, 219, 174, 175, 49, 50, 165, 52, 126, 245,
108514 /* 850 */ 246, 23, 238, 25, 23, 174, 175, 187, 187, 187,
108515 /* 860 */ 187, 39, 193, 68, 69, 70, 71, 72, 73, 74,
108516 /* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84,
108517 /* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150,
108518 /* 890 */ 150, 165, 150, 23, 160, 25, 150, 150, 160, 52,
108519 /* 900 */ 174, 175, 190, 191, 165, 165, 22, 165, 150, 29,
108520 /* 910 */ 150, 165, 165, 174, 175, 150, 174, 175, 49, 50,
108521 /* 920 */ 174, 175, 165, 165, 23, 165, 25, 25, 194, 52,
108522 /* 930 */ 165, 174, 194, 193, 174, 175, 160, 68, 69, 70,
108523 /* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
108524 /* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90,
108525 /* 960 */ 91, 92, 19, 150, 150, 165, 150, 22, 150, 23,
108526 /* 970 */ 194, 213, 91, 92, 174, 175, 1, 2, 165, 165,
108527 /* 980 */ 22, 165, 150, 165, 150, 238, 150, 174, 175, 22,
108528 /* 990 */ 174, 175, 49, 50, 52, 150, 22, 165, 102, 165,
108529 /* 1000 */ 19, 165, 109, 238, 166, 166, 174, 175, 174, 175,
108530 /* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76,
108531 /* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
108532 /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165,
108533 /* 1040 */ 150, 150, 166, 205, 205, 150, 20, 24, 174, 175,
108534 /* 1050 */ 43, 104, 165, 59, 53, 165, 165, 25, 150, 150,
108535 /* 1060 */ 165, 174, 175, 150, 174, 175, 49, 50, 53, 138,
108536 /* 1070 */ 150, 22, 104, 165, 165, 5, 1, 118, 165, 35,
108537 /* 1080 */ 27, 205, 174, 175, 193, 165, 69, 70, 71, 72,
108538 /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
108539 /* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
108540 /* 1110 */ 19, 150, 150, 165, 150, 150, 150, 108, 76, 150,
108541 /* 1120 */ 22, 76, 174, 175, 127, 216, 165, 165, 25, 165,
108542 /* 1130 */ 165, 165, 150, 213, 165, 174, 175, 150, 174, 175,
108543 /* 1140 */ 49, 50, 22, 150, 23, 1, 119, 165, 16, 121,
108544 /* 1150 */ 20, 108, 165, 119, 23, 193, 174, 175, 165, 193,
108545 /* 1160 */ 127, 70, 71, 72, 73, 74, 75, 76, 77, 78,
108546 /* 1170 */ 79, 80, 23, 82, 83, 84, 85, 86, 87, 88,
108547 /* 1180 */ 89, 90, 91, 92, 19, 20, 193, 22, 150, 150,
108548 /* 1190 */ 150, 26, 27, 128, 16, 15, 150, 140, 65, 3,
108549 /* 1200 */ 164, 22, 37, 165, 165, 165, 4, 19, 20, 150,
108550 /* 1210 */ 22, 165, 174, 175, 26, 27, 246, 180, 149, 6,
108551 /* 1220 */ 249, 56, 249, 149, 165, 37, 149, 180, 149, 151,
108552 /* 1230 */ 13, 66, 193, 174, 175, 150, 25, 151, 116, 159,
108553 /* 1240 */ 199, 146, 147, 126, 56, 194, 150, 152, 200, 154,
108554 /* 1250 */ 165, 86, 87, 88, 66, 160, 201, 150, 93, 94,
108555 /* 1260 */ 95, 165, 123, 98, 150, 150, 124, 122, 202, 135,
108556 /* 1270 */ 174, 175, 165, 150, 86, 87, 150, 150, 150, 165,
108557 /* 1280 */ 165, 93, 94, 95, 203, 150, 98, 125, 165, 194,
108558 /* 1290 */ 150, 165, 165, 165, 129, 130, 131, 132, 133, 134,
108559 /* 1300 */ 165, 174, 175, 157, 116, 165, 19, 20, 150, 22,
108560 /* 1310 */ 150, 118, 217, 26, 27, 225, 150, 129, 130, 131,
108561 /* 1320 */ 132, 133, 134, 165, 37, 165, 157, 150, 210, 19,
108562 /* 1330 */ 20, 165, 22, 150, 150, 150, 26, 27, 104, 244,
108563 /* 1340 */ 174, 175, 165, 56, 121, 104, 210, 37, 165, 165,
108564 /* 1350 */ 165, 174, 175, 66, 150, 150, 150, 174, 175, 174,
108565 /* 1360 */ 175, 211, 150, 211, 210, 176, 56, 211, 176, 165,
108566 /* 1370 */ 165, 165, 150, 86, 87, 150, 66, 165, 174, 175,
108567 /* 1380 */ 93, 94, 95, 150, 184, 98, 150, 165, 47, 22,
108568 /* 1390 */ 165, 176, 150, 26, 27, 150, 86, 87, 165, 174,
108569 /* 1400 */ 175, 165, 178, 93, 94, 95, 103, 165, 98, 150,
108570 /* 1410 */ 165, 150, 22, 176, 179, 228, 129, 130, 131, 132,
108571 /* 1420 */ 133, 134, 5, 150, 165, 92, 165, 10, 11, 12,
108572 /* 1430 */ 13, 14, 150, 66, 17, 174, 175, 228, 165, 129,
108573 /* 1440 */ 130, 131, 132, 133, 134, 150, 184, 165, 31, 150,
108574 /* 1450 */ 33, 150, 150, 86, 87, 172, 174, 175, 96, 42,
108575 /* 1460 */ 165, 94, 176, 179, 165, 98, 165, 165, 176, 174,
108576 /* 1470 */ 175, 156, 55, 176, 57, 18, 157, 156, 61, 157,
108577 /* 1480 */ 156, 64, 157, 157, 235, 45, 236, 135, 156, 189,
108578 /* 1490 */ 68, 157, 218, 189, 22, 199, 129, 130, 131, 156,
108579 /* 1500 */ 192, 157, 18, 192, 192, 192, 199, 189, 218, 240,
108580 /* 1510 */ 157, 40, 240, 157, 157, 38, 153, 166, 243, 196,
108581 /* 1520 */ 226, 230, 105, 106, 107, 198, 209, 177, 111, 182,
108582 /* 1530 */ 166, 177, 177, 116, 166, 230, 178, 239, 199, 209,
108583 /* 1540 */ 209, 199, 148, 166, 196, 239, 208, 233, 172, 183,
108584 /* 1550 */ 234, 191, 183, 183, 195, 174, 139, 186, 186, 174,
108585 /* 1560 */ 92,
 
108586 };
108587 #define YY_SHIFT_USE_DFLT (-70)
108588 #define YY_SHIFT_COUNT (418)
108589 #define YY_SHIFT_MIN (-69)
108590 #define YY_SHIFT_MAX (1484)
108591 static const short yy_shift_ofst[] = {
108592 /* 0 */ 975, 1188, 1417, 1188, 1287, 1287, 138, 138, 368, -19,
108593 /* 10 */ 1287, 1287, 1287, 1287, 272, 524, 129, 129, 795, 1165,
108594 /* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108595 /* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108596 /* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
108597 /* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
108598 /* 60 */ 1287, 1287, 212, 524, 524, 213, 213, 459, 1122, 55,
108599 /* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869,
108600 /* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
108601 /* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45,
108602 /* 100 */ -45, -45, -45, -45, -1, 6, -64, 524, 524, 524,
108603 /* 110 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108604 /* 120 */ 524, 524, 524, 386, 207, 524, 524, 524, 524, 524,
108605 /* 130 */ 409, -13, 459, 881, 1468, -70, -70, -70, 1367, 57,
108606 /* 140 */ 433, 433, 297, 236, 219, 136, 91, 572, 540, 524,
108607 /* 150 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108608 /* 160 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108609 /* 170 */ 524, 524, 524, 524, 524, 524, 524, 524, 524, 524,
108610 /* 180 */ 650, 650, 650, 687, 1122, 1122, 1122, -70, -70, -70,
108611 /* 190 */ 204, 204, 434, 434, 494, 494, 494, 504, 446, 292,
108612 /* 200 */ 442, 428, 424, 77, 377, 377, 377, 377, 531, 498,
108613 /* 210 */ 377, 377, 278, 215, 227, 664, 722, 574, 574, 750,
108614 /* 220 */ 722, 750, 229, 459, 660, 459, 660, 476, 660, 574,
108615 /* 230 */ 651, 625, 625, 459, 579, 273, -18, 1477, 1193, 1193,
108616 /* 240 */ 1471, 1471, 1193, 1472, 1422, 1117, 1484, 1484, 1484, 1484,
108617 /* 250 */ 1193, 1457, 1117, 1472, 1422, 1422, 1193, 1457, 1352, 1440,
108618 /* 260 */ 1193, 1193, 1457, 1193, 1457, 1193, 1457, 1390, 1241, 1241,
108619 /* 270 */ 1241, 1362, 1341, 1333, 1333, 1390, 1241, 1303, 1241, 1341,
108620 /* 280 */ 1241, 1241, 1223, 1234, 1223, 1234, 1223, 1234, 1193, 1193,
108621 /* 290 */ 1134, 1162, 1145, 1142, 1139, 1117, 1122, 1211, 1217, 1217,
108622 /* 300 */ 1213, 1213, 1213, 1213, -70, -70, -70, -70, -70, -70,
108623 /* 310 */ 334, 393, 497, 392, 543, 275, 901, 98, 870, 828,
108624 /* 320 */ 753, 683, 453, 447, 535, 221, 140, 429, 54, 1202,
108625 /* 330 */ 1196, 1179, 1057, 1180, 1133, 1178, 1149, 1131, 1065, 1103,
108626 /* 340 */ 1033, 1043, 1034, 1130, 1028, 1132, 1144, 1027, 1121, 1120,
108627 /* 350 */ 1103, 1098, 997, 1045, 1042, 1009, 1053, 1044, 959, 1075,
108628 /* 360 */ 1070, 1049, 968, 931, 1015, 1032, 1001, 994, 1007, 947,
108629 /* 370 */ 1023, 1026, 981, 893, 896, 974, 942, 967, 958, 946,
108630 /* 380 */ 945, 877, 902, 880, 884, 847, 822, 831, 764, 714,
108631 /* 390 */ 735, 723, 720, 587, 615, 642, 656, 576, 615, 575,
108632 /* 400 */ 518, 463, 461, 438, 405, 390, 387, 376, 303, 224,
108633 /* 410 */ 271, 190, 92, 72, 69, 145, 113, 33, 28,
108634 };
108635 #define YY_REDUCE_USE_DFLT (-169)
108636 #define YY_REDUCE_COUNT (309)
108637 #define YY_REDUCE_MIN (-168)
108638 #define YY_REDUCE_MAX (1394)
108639 static const short yy_reduce_ofst[] = {
108640 /* 0 */ 541, 90, 1095, 147, 86, 19, 18, -49, 10, 245,
108641 /* 10 */ 308, 306, 243, 222, -41, -51, 181, -71, 394, 1295,
108642 /* 20 */ 1282, 1261, 1225, 1204, 1185, 1183, 1177, 1166, 1127, 1096,
108643 /* 30 */ 1059, 1038, 982, 964, 961, 948, 908, 890, 887, 874,
108644 /* 40 */ 834, 832, 816, 813, 800, 760, 746, 742, 739, 726,
108645 /* 50 */ 681, 668, 665, 652, 610, 598, 591, 578, 530, 528,
108646 /* 60 */ 525, 456, 474, 464, 517, 439, -168, 208, 406, 491,
108647 /* 70 */ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
108648 /* 80 */ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
108649 /* 90 */ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
108650 /* 100 */ 491, 491, 491, 491, 491, 491, 491, 1039, 909, 993,
108651 /* 110 */ 966, 962, 891, 845, 740, 765, 920, 747, 27, 614,
108652 /* 120 */ 673, 758, 669, -119, 586, 672, 671, 670, 596, 544,
108653 /* 130 */ 622, 460, 583, 491, 491, 491, 491, 491, 757, 374,
108654 /* 140 */ 712, 638, 913, 1302, 1301, 1299, 1273, 577, 577, 1259,
108655 /* 150 */ 1245, 1242, 1236, 1233, 1222, 1212, 1206, 1205, 1184, 1160,
108656 /* 160 */ 1158, 1140, 1135, 1128, 1126, 1123, 1115, 1114, 1107, 1085,
108657 /* 170 */ 1046, 1040, 987, 969, 965, 913, 895, 836, 818, 814,
108658 /* 180 */ 876, 839, 838, 636, 776, 738, 734, 604, 421, 62,
108659 /* 190 */ 1385, 1381, 1372, 1371, 1370, 1369, 1366, 1338, 1359, 1360,
108660 /* 200 */ 1359, 1359, 1359, 1376, 1359, 1359, 1359, 1359, 1316, 1314,
108661 /* 210 */ 1359, 1359, 1338, 1377, 1348, 1394, 1342, 1331, 1330, 1306,
108662 /* 220 */ 1339, 1298, 1358, 1368, 1355, 1364, 1354, 1347, 1350, 1317,
108663 /* 230 */ 1294, 1305, 1291, 1351, 1327, 1323, 1363, 1275, 1357, 1356,
108664 /* 240 */ 1272, 1269, 1353, 1290, 1318, 1307, 1313, 1312, 1311, 1308,
108665 /* 250 */ 1344, 1343, 1296, 1274, 1304, 1300, 1334, 1332, 1250, 1249,
108666 /* 260 */ 1326, 1325, 1324, 1322, 1321, 1319, 1315, 1284, 1297, 1292,
108667 /* 270 */ 1286, 1283, 1262, 1209, 1187, 1235, 1237, 1224, 1215, 1200,
108668 /* 280 */ 1192, 1189, 1156, 1154, 1152, 1136, 1150, 1118, 1169, 1146,
108669 /* 290 */ 1090, 1081, 1066, 1055, 1048, 1041, 1051, 1080, 1086, 1078,
108670 /* 300 */ 1079, 1077, 1074, 1069, 973, 971, 970, 1047, 1037, 1036,
108671 };
108672 static const YYACTIONTYPE yy_default[] = {
108673 /* 0 */ 632, 864, 952, 952, 864, 864, 952, 952, 683, 754,
108674 /* 10 */ 952, 952, 952, 862, 952, 952, 782, 782, 926, 952,
108675 /* 20 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108676 /* 30 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108677 /* 40 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108678 /* 50 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108679 /* 60 */ 952, 952, 952, 952, 952, 952, 952, 671, 758, 788,
108680 /* 70 */ 952, 952, 952, 952, 952, 952, 952, 952, 925, 927,
108681 /* 80 */ 796, 795, 905, 769, 793, 786, 790, 865, 858, 859,
108682 /* 90 */ 857, 861, 866, 952, 789, 825, 842, 824, 836, 841,
108683 /* 100 */ 848, 840, 837, 827, 826, 828, 829, 952, 952, 952,
108684 /* 110 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108685 /* 120 */ 952, 952, 952, 658, 723, 952, 952, 952, 952, 952,
108686 /* 130 */ 952, 952, 952, 830, 831, 845, 844, 843, 952, 952,
108687 /* 140 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108688 /* 150 */ 932, 930, 952, 877, 952, 952, 952, 952, 952, 952,
108689 /* 160 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108690 /* 170 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 638,
108691 /* 180 */ 754, 754, 754, 632, 952, 952, 952, 944, 758, 748,
108692 /* 190 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108693 /* 200 */ 952, 952, 952, 683, 798, 737, 915, 917, 952, 898,
108694 /* 210 */ 735, 660, 756, 673, 746, 640, 792, 771, 771, 910,
108695 /* 220 */ 792, 910, 697, 952, 782, 952, 782, 694, 782, 771,
108696 /* 230 */ 860, 952, 952, 952, 755, 746, 952, 937, 762, 762,
108697 /* 240 */ 929, 929, 762, 804, 727, 792, 734, 734, 734, 734,
108698 /* 250 */ 762, 655, 792, 804, 727, 727, 762, 655, 904, 902,
108699 /* 260 */ 762, 762, 655, 762, 655, 762, 655, 870, 725, 725,
108700 /* 270 */ 725, 683, 712, 874, 874, 870, 725, 697, 725, 712,
108701 /* 280 */ 725, 725, 775, 770, 775, 770, 775, 770, 762, 762,
108702 /* 290 */ 952, 787, 776, 785, 783, 792, 952, 715, 648, 648,
108703 /* 300 */ 637, 637, 637, 637, 949, 949, 944, 699, 699, 681,
108704 /* 310 */ 952, 952, 952, 952, 952, 952, 952, 879, 952, 952,
108705 /* 320 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108706 /* 330 */ 633, 939, 952, 952, 936, 952, 952, 952, 952, 797,
108707 /* 340 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108708 /* 350 */ 914, 952, 952, 952, 952, 952, 952, 952, 908, 952,
108709 /* 360 */ 952, 952, 952, 952, 952, 901, 900, 952, 952, 952,
108710 /* 370 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 952,
108711 /* 380 */ 952, 952, 716, 952, 952, 952, 952, 952, 952, 952,
108712 /* 390 */ 952, 952, 952, 952, 784, 952, 777, 952, 863, 952,
108713 /* 400 */ 952, 952, 952, 952, 952, 952, 952, 952, 952, 740,
108714 /* 410 */ 813, 952, 812, 816, 811, 665, 952, 646, 952, 629,
108715 /* 420 */ 634, 948, 951, 950, 947, 946, 945, 940, 938, 935,
108716 /* 430 */ 934, 933, 931, 928, 924, 883, 881, 888, 887, 886,
108717 /* 440 */ 885, 884, 882, 880, 878, 799, 794, 791, 923, 876,
108718 /* 450 */ 736, 733, 732, 654, 941, 907, 916, 803, 802, 805,
108719 /* 460 */ 913, 912, 911, 909, 906, 893, 801, 800, 728, 868,
108720 /* 470 */ 867, 657, 897, 896, 895, 899, 903, 894, 764, 656,
108721 /* 480 */ 653, 662, 718, 724, 722, 721, 720, 719, 717, 664,
108722 /* 490 */ 672, 682, 711, 696, 695, 873, 875, 872, 871, 704,
108723 /* 500 */ 703, 709, 708, 707, 706, 705, 702, 701, 700, 693,
108724 /* 510 */ 692, 698, 691, 714, 713, 710, 690, 731, 730, 729,
108725 /* 520 */ 726, 689, 688, 687, 816, 686, 685, 822, 821, 809,
108726 /* 530 */ 852, 751, 750, 749, 761, 760, 773, 772, 807, 806,
108727 /* 540 */ 774, 759, 753, 752, 768, 767, 766, 765, 757, 747,
108728 /* 550 */ 779, 781, 780, 778, 854, 763, 851, 922, 921, 920,
108729 /* 560 */ 919, 918, 856, 855, 823, 820, 676, 677, 891, 890,
108730 /* 570 */ 892, 889, 679, 678, 675, 674, 853, 742, 741, 849,
108731 /* 580 */ 846, 838, 834, 850, 847, 839, 835, 833, 832, 818,
108732 /* 590 */ 817, 815, 814, 810, 819, 667, 743, 739, 738, 808,
108733 /* 600 */ 745, 744, 684, 680, 661, 659, 652, 650, 649, 651,
108734 /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666,
108735 /* 620 */ 665, 639, 636, 635, 631, 630, 628,
108736 };
108737
108738 /* The next table maps tokens into fallback tokens. If a construct
108739 ** like the following:
108740 **
@@ -108639,11 +108933,11 @@
108933 "create_table", "create_table_args", "createkw", "temp",
108934 "ifnotexists", "dbnm", "columnlist", "conslist_opt",
108935 "select", "column", "columnid", "type",
108936 "carglist", "id", "ids", "typetoken",
108937 "typename", "signed", "plus_num", "minus_num",
108938 "cname", "ccons", "term", "expr",
108939 "onconf", "sortorder", "autoinc", "idxlist_opt",
108940 "refargs", "defer_subclause", "refarg", "refact",
108941 "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
108942 "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
108943 "ifexists", "fullname", "oneselect", "multiselect_op",
@@ -108719,14 +109013,14 @@
109013 /* 48 */ "typetoken ::= typename LP signed COMMA signed RP",
109014 /* 49 */ "typename ::= ids",
109015 /* 50 */ "typename ::= typename ids",
109016 /* 51 */ "signed ::= plus_num",
109017 /* 52 */ "signed ::= minus_num",
109018 /* 53 */ "carglist ::= carglist cname ccons",
109019 /* 54 */ "carglist ::=",
109020 /* 55 */ "cname ::= CONSTRAINT nm",
109021 /* 56 */ "cname ::=",
109022 /* 57 */ "ccons ::= DEFAULT term",
109023 /* 58 */ "ccons ::= DEFAULT LP expr RP",
109024 /* 59 */ "ccons ::= DEFAULT PLUS term",
109025 /* 60 */ "ccons ::= DEFAULT MINUS term",
109026 /* 61 */ "ccons ::= DEFAULT id",
@@ -108756,247 +109050,245 @@
109050 /* 85 */ "init_deferred_pred_opt ::=",
109051 /* 86 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
109052 /* 87 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
109053 /* 88 */ "conslist_opt ::=",
109054 /* 89 */ "conslist_opt ::= COMMA conslist",
109055 /* 90 */ "conslist ::= conslist COMMA cname tcons",
109056 /* 91 */ "conslist ::= cname tcons",
109057 /* 92 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
109058 /* 93 */ "tcons ::= UNIQUE LP idxlist RP onconf",
109059 /* 94 */ "tcons ::= CHECK LP expr RP onconf",
109060 /* 95 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
109061 /* 96 */ "defer_subclause_opt ::=",
109062 /* 97 */ "defer_subclause_opt ::= defer_subclause",
109063 /* 98 */ "onconf ::=",
109064 /* 99 */ "onconf ::= ON CONFLICT resolvetype",
109065 /* 100 */ "orconf ::=",
109066 /* 101 */ "orconf ::= OR resolvetype",
109067 /* 102 */ "resolvetype ::= raisetype",
109068 /* 103 */ "resolvetype ::= IGNORE",
109069 /* 104 */ "resolvetype ::= REPLACE",
109070 /* 105 */ "cmd ::= DROP TABLE ifexists fullname",
109071 /* 106 */ "ifexists ::= IF EXISTS",
109072 /* 107 */ "ifexists ::=",
109073 /* 108 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
109074 /* 109 */ "cmd ::= DROP VIEW ifexists fullname",
109075 /* 110 */ "cmd ::= select",
109076 /* 111 */ "select ::= oneselect",
109077 /* 112 */ "select ::= select multiselect_op oneselect",
109078 /* 113 */ "multiselect_op ::= UNION",
109079 /* 114 */ "multiselect_op ::= UNION ALL",
109080 /* 115 */ "multiselect_op ::= EXCEPT|INTERSECT",
109081 /* 116 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
109082 /* 117 */ "distinct ::= DISTINCT",
109083 /* 118 */ "distinct ::= ALL",
109084 /* 119 */ "distinct ::=",
109085 /* 120 */ "sclp ::= selcollist COMMA",
109086 /* 121 */ "sclp ::=",
109087 /* 122 */ "selcollist ::= sclp expr as",
109088 /* 123 */ "selcollist ::= sclp STAR",
109089 /* 124 */ "selcollist ::= sclp nm DOT STAR",
109090 /* 125 */ "as ::= AS nm",
109091 /* 126 */ "as ::= ids",
109092 /* 127 */ "as ::=",
109093 /* 128 */ "from ::=",
109094 /* 129 */ "from ::= FROM seltablist",
109095 /* 130 */ "stl_prefix ::= seltablist joinop",
109096 /* 131 */ "stl_prefix ::=",
109097 /* 132 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
109098 /* 133 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
109099 /* 134 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
109100 /* 135 */ "dbnm ::=",
109101 /* 136 */ "dbnm ::= DOT nm",
109102 /* 137 */ "fullname ::= nm dbnm",
109103 /* 138 */ "joinop ::= COMMA|JOIN",
109104 /* 139 */ "joinop ::= JOIN_KW JOIN",
109105 /* 140 */ "joinop ::= JOIN_KW nm JOIN",
109106 /* 141 */ "joinop ::= JOIN_KW nm nm JOIN",
109107 /* 142 */ "on_opt ::= ON expr",
109108 /* 143 */ "on_opt ::=",
109109 /* 144 */ "indexed_opt ::=",
109110 /* 145 */ "indexed_opt ::= INDEXED BY nm",
109111 /* 146 */ "indexed_opt ::= NOT INDEXED",
109112 /* 147 */ "using_opt ::= USING LP inscollist RP",
109113 /* 148 */ "using_opt ::=",
109114 /* 149 */ "orderby_opt ::=",
109115 /* 150 */ "orderby_opt ::= ORDER BY sortlist",
109116 /* 151 */ "sortlist ::= sortlist COMMA expr sortorder",
109117 /* 152 */ "sortlist ::= expr sortorder",
109118 /* 153 */ "sortorder ::= ASC",
109119 /* 154 */ "sortorder ::= DESC",
109120 /* 155 */ "sortorder ::=",
109121 /* 156 */ "groupby_opt ::=",
109122 /* 157 */ "groupby_opt ::= GROUP BY nexprlist",
109123 /* 158 */ "having_opt ::=",
109124 /* 159 */ "having_opt ::= HAVING expr",
109125 /* 160 */ "limit_opt ::=",
109126 /* 161 */ "limit_opt ::= LIMIT expr",
109127 /* 162 */ "limit_opt ::= LIMIT expr OFFSET expr",
109128 /* 163 */ "limit_opt ::= LIMIT expr COMMA expr",
109129 /* 164 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
109130 /* 165 */ "where_opt ::=",
109131 /* 166 */ "where_opt ::= WHERE expr",
109132 /* 167 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
109133 /* 168 */ "setlist ::= setlist COMMA nm EQ expr",
109134 /* 169 */ "setlist ::= nm EQ expr",
109135 /* 170 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
109136 /* 171 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
109137 /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
109138 /* 173 */ "insert_cmd ::= INSERT orconf",
109139 /* 174 */ "insert_cmd ::= REPLACE",
109140 /* 175 */ "valuelist ::= VALUES LP nexprlist RP",
109141 /* 176 */ "valuelist ::= valuelist COMMA LP exprlist RP",
109142 /* 177 */ "inscollist_opt ::=",
109143 /* 178 */ "inscollist_opt ::= LP inscollist RP",
109144 /* 179 */ "inscollist ::= inscollist COMMA nm",
109145 /* 180 */ "inscollist ::= nm",
109146 /* 181 */ "expr ::= term",
109147 /* 182 */ "expr ::= LP expr RP",
109148 /* 183 */ "term ::= NULL",
109149 /* 184 */ "expr ::= id",
109150 /* 185 */ "expr ::= JOIN_KW",
109151 /* 186 */ "expr ::= nm DOT nm",
109152 /* 187 */ "expr ::= nm DOT nm DOT nm",
109153 /* 188 */ "term ::= INTEGER|FLOAT|BLOB",
109154 /* 189 */ "term ::= STRING",
109155 /* 190 */ "expr ::= REGISTER",
109156 /* 191 */ "expr ::= VARIABLE",
109157 /* 192 */ "expr ::= expr COLLATE ids",
109158 /* 193 */ "expr ::= CAST LP expr AS typetoken RP",
109159 /* 194 */ "expr ::= ID LP distinct exprlist RP",
109160 /* 195 */ "expr ::= ID LP STAR RP",
109161 /* 196 */ "term ::= CTIME_KW",
109162 /* 197 */ "expr ::= expr AND expr",
109163 /* 198 */ "expr ::= expr OR expr",
109164 /* 199 */ "expr ::= expr LT|GT|GE|LE expr",
109165 /* 200 */ "expr ::= expr EQ|NE expr",
109166 /* 201 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
109167 /* 202 */ "expr ::= expr PLUS|MINUS expr",
109168 /* 203 */ "expr ::= expr STAR|SLASH|REM expr",
109169 /* 204 */ "expr ::= expr CONCAT expr",
109170 /* 205 */ "likeop ::= LIKE_KW",
109171 /* 206 */ "likeop ::= NOT LIKE_KW",
109172 /* 207 */ "likeop ::= MATCH",
109173 /* 208 */ "likeop ::= NOT MATCH",
109174 /* 209 */ "expr ::= expr likeop expr",
109175 /* 210 */ "expr ::= expr likeop expr ESCAPE expr",
109176 /* 211 */ "expr ::= expr ISNULL|NOTNULL",
109177 /* 212 */ "expr ::= expr NOT NULL",
109178 /* 213 */ "expr ::= expr IS expr",
109179 /* 214 */ "expr ::= expr IS NOT expr",
109180 /* 215 */ "expr ::= NOT expr",
109181 /* 216 */ "expr ::= BITNOT expr",
109182 /* 217 */ "expr ::= MINUS expr",
109183 /* 218 */ "expr ::= PLUS expr",
109184 /* 219 */ "between_op ::= BETWEEN",
109185 /* 220 */ "between_op ::= NOT BETWEEN",
109186 /* 221 */ "expr ::= expr between_op expr AND expr",
109187 /* 222 */ "in_op ::= IN",
109188 /* 223 */ "in_op ::= NOT IN",
109189 /* 224 */ "expr ::= expr in_op LP exprlist RP",
109190 /* 225 */ "expr ::= LP select RP",
109191 /* 226 */ "expr ::= expr in_op LP select RP",
109192 /* 227 */ "expr ::= expr in_op nm dbnm",
109193 /* 228 */ "expr ::= EXISTS LP select RP",
109194 /* 229 */ "expr ::= CASE case_operand case_exprlist case_else END",
109195 /* 230 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
109196 /* 231 */ "case_exprlist ::= WHEN expr THEN expr",
109197 /* 232 */ "case_else ::= ELSE expr",
109198 /* 233 */ "case_else ::=",
109199 /* 234 */ "case_operand ::= expr",
109200 /* 235 */ "case_operand ::=",
109201 /* 236 */ "exprlist ::= nexprlist",
109202 /* 237 */ "exprlist ::=",
109203 /* 238 */ "nexprlist ::= nexprlist COMMA expr",
109204 /* 239 */ "nexprlist ::= expr",
109205 /* 240 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
109206 /* 241 */ "uniqueflag ::= UNIQUE",
109207 /* 242 */ "uniqueflag ::=",
109208 /* 243 */ "idxlist_opt ::=",
109209 /* 244 */ "idxlist_opt ::= LP idxlist RP",
109210 /* 245 */ "idxlist ::= idxlist COMMA nm collate sortorder",
109211 /* 246 */ "idxlist ::= nm collate sortorder",
109212 /* 247 */ "collate ::=",
109213 /* 248 */ "collate ::= COLLATE ids",
109214 /* 249 */ "cmd ::= DROP INDEX ifexists fullname",
109215 /* 250 */ "cmd ::= VACUUM",
109216 /* 251 */ "cmd ::= VACUUM nm",
109217 /* 252 */ "cmd ::= PRAGMA nm dbnm",
109218 /* 253 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
109219 /* 254 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
109220 /* 255 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
109221 /* 256 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
109222 /* 257 */ "nmnum ::= plus_num",
109223 /* 258 */ "nmnum ::= nm",
109224 /* 259 */ "nmnum ::= ON",
109225 /* 260 */ "nmnum ::= DELETE",
109226 /* 261 */ "nmnum ::= DEFAULT",
109227 /* 262 */ "plus_num ::= PLUS number",
109228 /* 263 */ "plus_num ::= number",
109229 /* 264 */ "minus_num ::= MINUS number",
109230 /* 265 */ "number ::= INTEGER|FLOAT",
109231 /* 266 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
109232 /* 267 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
109233 /* 268 */ "trigger_time ::= BEFORE",
109234 /* 269 */ "trigger_time ::= AFTER",
109235 /* 270 */ "trigger_time ::= INSTEAD OF",
109236 /* 271 */ "trigger_time ::=",
109237 /* 272 */ "trigger_event ::= DELETE|INSERT",
109238 /* 273 */ "trigger_event ::= UPDATE",
109239 /* 274 */ "trigger_event ::= UPDATE OF inscollist",
109240 /* 275 */ "foreach_clause ::=",
109241 /* 276 */ "foreach_clause ::= FOR EACH ROW",
109242 /* 277 */ "when_clause ::=",
109243 /* 278 */ "when_clause ::= WHEN expr",
109244 /* 279 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
109245 /* 280 */ "trigger_cmd_list ::= trigger_cmd SEMI",
109246 /* 281 */ "trnm ::= nm",
109247 /* 282 */ "trnm ::= nm DOT nm",
109248 /* 283 */ "tridxby ::=",
109249 /* 284 */ "tridxby ::= INDEXED BY nm",
109250 /* 285 */ "tridxby ::= NOT INDEXED",
109251 /* 286 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
109252 /* 287 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
109253 /* 288 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
109254 /* 289 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
109255 /* 290 */ "trigger_cmd ::= select",
109256 /* 291 */ "expr ::= RAISE LP IGNORE RP",
109257 /* 292 */ "expr ::= RAISE LP raisetype COMMA nm RP",
109258 /* 293 */ "raisetype ::= ROLLBACK",
109259 /* 294 */ "raisetype ::= ABORT",
109260 /* 295 */ "raisetype ::= FAIL",
109261 /* 296 */ "cmd ::= DROP TRIGGER ifexists fullname",
109262 /* 297 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
109263 /* 298 */ "cmd ::= DETACH database_kw_opt expr",
109264 /* 299 */ "key_opt ::=",
109265 /* 300 */ "key_opt ::= KEY expr",
109266 /* 301 */ "database_kw_opt ::= DATABASE",
109267 /* 302 */ "database_kw_opt ::=",
109268 /* 303 */ "cmd ::= REINDEX",
109269 /* 304 */ "cmd ::= REINDEX nm dbnm",
109270 /* 305 */ "cmd ::= ANALYZE",
109271 /* 306 */ "cmd ::= ANALYZE nm dbnm",
109272 /* 307 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
109273 /* 308 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
109274 /* 309 */ "add_column_fullname ::= fullname",
109275 /* 310 */ "kwcolumn_opt ::=",
109276 /* 311 */ "kwcolumn_opt ::= COLUMNKW",
109277 /* 312 */ "cmd ::= create_vtab",
109278 /* 313 */ "cmd ::= create_vtab LP vtabarglist RP",
109279 /* 314 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
109280 /* 315 */ "vtabarglist ::= vtabarg",
109281 /* 316 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
109282 /* 317 */ "vtabarg ::=",
109283 /* 318 */ "vtabarg ::= vtabarg vtabargtoken",
109284 /* 319 */ "vtabargtoken ::= ANY",
109285 /* 320 */ "vtabargtoken ::= lp anylist RP",
109286 /* 321 */ "lp ::= LP",
109287 /* 322 */ "anylist ::=",
109288 /* 323 */ "anylist ::= anylist LP anylist RP",
109289 /* 324 */ "anylist ::= anylist ANY",
 
 
109290 };
109291 #endif /* NDEBUG */
109292
109293
109294 #if YYSTACKDEPTH<=0
@@ -109438,14 +109730,14 @@
109730 { 167, 6 },
109731 { 168, 1 },
109732 { 168, 2 },
109733 { 169, 1 },
109734 { 169, 1 },
109735 { 164, 3 },
109736 { 164, 0 },
109737 { 172, 2 },
109738 { 172, 0 },
109739 { 173, 2 },
109740 { 173, 4 },
109741 { 173, 3 },
109742 { 173, 3 },
109743 { 173, 2 },
@@ -109475,14 +109767,12 @@
109767 { 184, 0 },
109768 { 184, 2 },
109769 { 184, 2 },
109770 { 159, 0 },
109771 { 159, 2 },
109772 { 185, 4 },
109773 { 185, 2 },
 
 
109774 { 186, 7 },
109775 { 186, 5 },
109776 { 186, 5 },
109777 { 186, 10 },
109778 { 188, 0 },
@@ -109787,12 +110077,12 @@
110077 {yygotominor.yy392 = TK_DEFERRED;}
110078 break;
110079 case 14: /* transtype ::= DEFERRED */
110080 case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
110081 case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
110082 case 113: /* multiselect_op ::= UNION */ yytestcase(yyruleno==113);
110083 case 115: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==115);
110084 {yygotominor.yy392 = yymsp[0].major;}
110085 break;
110086 case 17: /* cmd ::= COMMIT trans_opt */
110087 case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
110088 {sqlite3CommitTransaction(pParse);}
@@ -109830,26 +110120,26 @@
110120 case 31: /* temp ::= */ yytestcase(yyruleno==31);
110121 case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
110122 case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
110123 case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
110124 case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
110125 case 96: /* defer_subclause_opt ::= */ yytestcase(yyruleno==96);
110126 case 107: /* ifexists ::= */ yytestcase(yyruleno==107);
110127 case 118: /* distinct ::= ALL */ yytestcase(yyruleno==118);
110128 case 119: /* distinct ::= */ yytestcase(yyruleno==119);
110129 case 219: /* between_op ::= BETWEEN */ yytestcase(yyruleno==219);
110130 case 222: /* in_op ::= IN */ yytestcase(yyruleno==222);
110131 {yygotominor.yy392 = 0;}
110132 break;
110133 case 29: /* ifnotexists ::= IF NOT EXISTS */
110134 case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
110135 case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
110136 case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
110137 case 106: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==106);
110138 case 117: /* distinct ::= DISTINCT */ yytestcase(yyruleno==117);
110139 case 220: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==220);
110140 case 223: /* in_op ::= NOT IN */ yytestcase(yyruleno==223);
110141 {yygotominor.yy392 = 1;}
110142 break;
110143 case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
110144 {
110145 sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
@@ -109879,25 +110169,25 @@
110169 case 41: /* nm ::= id */ yytestcase(yyruleno==41);
110170 case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
110171 case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
110172 case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
110173 case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
110174 case 125: /* as ::= AS nm */ yytestcase(yyruleno==125);
110175 case 126: /* as ::= ids */ yytestcase(yyruleno==126);
110176 case 136: /* dbnm ::= DOT nm */ yytestcase(yyruleno==136);
110177 case 145: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==145);
110178 case 248: /* collate ::= COLLATE ids */ yytestcase(yyruleno==248);
110179 case 257: /* nmnum ::= plus_num */ yytestcase(yyruleno==257);
110180 case 258: /* nmnum ::= nm */ yytestcase(yyruleno==258);
110181 case 259: /* nmnum ::= ON */ yytestcase(yyruleno==259);
110182 case 260: /* nmnum ::= DELETE */ yytestcase(yyruleno==260);
110183 case 261: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==261);
110184 case 262: /* plus_num ::= PLUS number */ yytestcase(yyruleno==262);
110185 case 263: /* plus_num ::= number */ yytestcase(yyruleno==263);
110186 case 264: /* minus_num ::= MINUS number */ yytestcase(yyruleno==264);
110187 case 265: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==265);
110188 case 281: /* trnm ::= nm */ yytestcase(yyruleno==281);
110189 {yygotominor.yy0 = yymsp[0].minor.yy0;}
110190 break;
110191 case 45: /* type ::= typetoken */
110192 {sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
110193 break;
@@ -109913,10 +110203,16 @@
110203 yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
110204 }
110205 break;
110206 case 50: /* typename ::= typename ids */
110207 {yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
110208 break;
110209 case 55: /* cname ::= CONSTRAINT nm */
110210 {pParse->constraintName = yymsp[0].minor.yy0;}
110211 break;
110212 case 56: /* cname ::= */
110213 {pParse->constraintName.n = 0;}
110214 break;
110215 case 57: /* ccons ::= DEFAULT term */
110216 case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
110217 {sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
110218 break;
@@ -109990,80 +110286,80 @@
110286 break;
110287 case 82: /* refact ::= NO ACTION */
110288 { yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */}
110289 break;
110290 case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
110291 case 97: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==97);
110292 case 99: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==99);
110293 case 102: /* resolvetype ::= raisetype */ yytestcase(yyruleno==102);
110294 {yygotominor.yy392 = yymsp[0].minor.yy392;}
110295 break;
110296 case 88: /* conslist_opt ::= */
110297 {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
110298 break;
110299 case 89: /* conslist_opt ::= COMMA conslist */
110300 {yygotominor.yy0 = yymsp[-1].minor.yy0;}
110301 break;
110302 case 92: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
110303 {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
110304 break;
110305 case 93: /* tcons ::= UNIQUE LP idxlist RP onconf */
110306 {sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
110307 break;
110308 case 94: /* tcons ::= CHECK LP expr RP onconf */
110309 {sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
110310 break;
110311 case 95: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
110312 {
110313 sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
110314 sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
110315 }
110316 break;
110317 case 98: /* onconf ::= */
110318 {yygotominor.yy392 = OE_Default;}
110319 break;
110320 case 100: /* orconf ::= */
110321 {yygotominor.yy258 = OE_Default;}
110322 break;
110323 case 101: /* orconf ::= OR resolvetype */
110324 {yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
110325 break;
110326 case 103: /* resolvetype ::= IGNORE */
110327 {yygotominor.yy392 = OE_Ignore;}
110328 break;
110329 case 104: /* resolvetype ::= REPLACE */
110330 {yygotominor.yy392 = OE_Replace;}
110331 break;
110332 case 105: /* cmd ::= DROP TABLE ifexists fullname */
110333 {
110334 sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
110335 }
110336 break;
110337 case 108: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
110338 {
110339 sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
110340 }
110341 break;
110342 case 109: /* cmd ::= DROP VIEW ifexists fullname */
110343 {
110344 sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
110345 }
110346 break;
110347 case 110: /* cmd ::= select */
110348 {
110349 SelectDest dest = {SRT_Output, 0, 0, 0, 0};
110350 sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
110351 sqlite3ExplainBegin(pParse->pVdbe);
110352 sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
110353 sqlite3ExplainFinish(pParse->pVdbe);
110354 sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
110355 }
110356 break;
110357 case 111: /* select ::= oneselect */
110358 {yygotominor.yy159 = yymsp[0].minor.yy159;}
110359 break;
110360 case 112: /* select ::= select multiselect_op oneselect */
110361 {
110362 if( yymsp[0].minor.yy159 ){
110363 yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
110364 yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
110365 }else{
@@ -110070,83 +110366,83 @@
110366 sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
110367 }
110368 yygotominor.yy159 = yymsp[0].minor.yy159;
110369 }
110370 break;
110371 case 114: /* multiselect_op ::= UNION ALL */
110372 {yygotominor.yy392 = TK_ALL;}
110373 break;
110374 case 116: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
110375 {
110376 yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
110377 }
110378 break;
110379 case 120: /* sclp ::= selcollist COMMA */
110380 case 244: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==244);
110381 {yygotominor.yy442 = yymsp[-1].minor.yy442;}
110382 break;
110383 case 121: /* sclp ::= */
110384 case 149: /* orderby_opt ::= */ yytestcase(yyruleno==149);
110385 case 156: /* groupby_opt ::= */ yytestcase(yyruleno==156);
110386 case 237: /* exprlist ::= */ yytestcase(yyruleno==237);
110387 case 243: /* idxlist_opt ::= */ yytestcase(yyruleno==243);
110388 {yygotominor.yy442 = 0;}
110389 break;
110390 case 122: /* selcollist ::= sclp expr as */
110391 {
110392 yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
110393 if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
110394 sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
110395 }
110396 break;
110397 case 123: /* selcollist ::= sclp STAR */
110398 {
110399 Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
110400 yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
110401 }
110402 break;
110403 case 124: /* selcollist ::= sclp nm DOT STAR */
110404 {
110405 Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
110406 Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110407 Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
110408 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
110409 }
110410 break;
110411 case 127: /* as ::= */
110412 {yygotominor.yy0.n = 0;}
110413 break;
110414 case 128: /* from ::= */
110415 {yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
110416 break;
110417 case 129: /* from ::= FROM seltablist */
110418 {
110419 yygotominor.yy347 = yymsp[0].minor.yy347;
110420 sqlite3SrcListShiftJoinType(yygotominor.yy347);
110421 }
110422 break;
110423 case 130: /* stl_prefix ::= seltablist joinop */
110424 {
110425 yygotominor.yy347 = yymsp[-1].minor.yy347;
110426 if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
110427 }
110428 break;
110429 case 131: /* stl_prefix ::= */
110430 {yygotominor.yy347 = 0;}
110431 break;
110432 case 132: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
110433 {
110434 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110435 sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
110436 }
110437 break;
110438 case 133: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
110439 {
110440 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110441 }
110442 break;
110443 case 134: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
110444 {
110445 if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
110446 yygotominor.yy347 = yymsp[-4].minor.yy347;
110447 }else{
110448 Select *pSubquery;
@@ -110154,137 +110450,137 @@
110450 pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
110451 yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
110452 }
110453 }
110454 break;
110455 case 135: /* dbnm ::= */
110456 case 144: /* indexed_opt ::= */ yytestcase(yyruleno==144);
110457 {yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
110458 break;
110459 case 137: /* fullname ::= nm dbnm */
110460 {yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
110461 break;
110462 case 138: /* joinop ::= COMMA|JOIN */
110463 { yygotominor.yy392 = JT_INNER; }
110464 break;
110465 case 139: /* joinop ::= JOIN_KW JOIN */
110466 { yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
110467 break;
110468 case 140: /* joinop ::= JOIN_KW nm JOIN */
110469 { yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
110470 break;
110471 case 141: /* joinop ::= JOIN_KW nm nm JOIN */
110472 { yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
110473 break;
110474 case 142: /* on_opt ::= ON expr */
110475 case 159: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==159);
110476 case 166: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==166);
110477 case 232: /* case_else ::= ELSE expr */ yytestcase(yyruleno==232);
110478 case 234: /* case_operand ::= expr */ yytestcase(yyruleno==234);
110479 {yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
110480 break;
110481 case 143: /* on_opt ::= */
110482 case 158: /* having_opt ::= */ yytestcase(yyruleno==158);
110483 case 165: /* where_opt ::= */ yytestcase(yyruleno==165);
110484 case 233: /* case_else ::= */ yytestcase(yyruleno==233);
110485 case 235: /* case_operand ::= */ yytestcase(yyruleno==235);
110486 {yygotominor.yy122 = 0;}
110487 break;
110488 case 146: /* indexed_opt ::= NOT INDEXED */
110489 {yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
110490 break;
110491 case 147: /* using_opt ::= USING LP inscollist RP */
110492 case 178: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==178);
110493 {yygotominor.yy180 = yymsp[-1].minor.yy180;}
110494 break;
110495 case 148: /* using_opt ::= */
110496 case 177: /* inscollist_opt ::= */ yytestcase(yyruleno==177);
110497 {yygotominor.yy180 = 0;}
110498 break;
110499 case 150: /* orderby_opt ::= ORDER BY sortlist */
110500 case 157: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==157);
110501 case 236: /* exprlist ::= nexprlist */ yytestcase(yyruleno==236);
110502 {yygotominor.yy442 = yymsp[0].minor.yy442;}
110503 break;
110504 case 151: /* sortlist ::= sortlist COMMA expr sortorder */
110505 {
110506 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
110507 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110508 }
110509 break;
110510 case 152: /* sortlist ::= expr sortorder */
110511 {
110512 yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
110513 if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
110514 }
110515 break;
110516 case 153: /* sortorder ::= ASC */
110517 case 155: /* sortorder ::= */ yytestcase(yyruleno==155);
110518 {yygotominor.yy392 = SQLITE_SO_ASC;}
110519 break;
110520 case 154: /* sortorder ::= DESC */
110521 {yygotominor.yy392 = SQLITE_SO_DESC;}
110522 break;
110523 case 160: /* limit_opt ::= */
110524 {yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
110525 break;
110526 case 161: /* limit_opt ::= LIMIT expr */
110527 {yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
110528 break;
110529 case 162: /* limit_opt ::= LIMIT expr OFFSET expr */
110530 {yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
110531 break;
110532 case 163: /* limit_opt ::= LIMIT expr COMMA expr */
110533 {yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
110534 break;
110535 case 164: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
110536 {
110537 sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
110538 sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
110539 }
110540 break;
110541 case 167: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
110542 {
110543 sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
110544 sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
110545 sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
110546 }
110547 break;
110548 case 168: /* setlist ::= setlist COMMA nm EQ expr */
110549 {
110550 yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
110551 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110552 }
110553 break;
110554 case 169: /* setlist ::= nm EQ expr */
110555 {
110556 yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
110557 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110558 }
110559 break;
110560 case 170: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
110561 {sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
110562 break;
110563 case 171: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
110564 {sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
110565 break;
110566 case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
110567 {sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
110568 break;
110569 case 173: /* insert_cmd ::= INSERT orconf */
110570 {yygotominor.yy258 = yymsp[0].minor.yy258;}
110571 break;
110572 case 174: /* insert_cmd ::= REPLACE */
110573 {yygotominor.yy258 = OE_Replace;}
110574 break;
110575 case 175: /* valuelist ::= VALUES LP nexprlist RP */
110576 {
110577 yygotominor.yy487.pList = yymsp[-1].minor.yy442;
110578 yygotominor.yy487.pSelect = 0;
110579 }
110580 break;
110581 case 176: /* valuelist ::= valuelist COMMA LP exprlist RP */
110582 {
110583 Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
110584 if( yymsp[-4].minor.yy487.pList ){
110585 yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
110586 yymsp[-4].minor.yy487.pList = 0;
@@ -110301,50 +110597,50 @@
110597 pRight->pPrior->selFlags |= SF_Values;
110598 yygotominor.yy487.pSelect = pRight;
110599 }
110600 }
110601 break;
110602 case 179: /* inscollist ::= inscollist COMMA nm */
110603 {yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
110604 break;
110605 case 180: /* inscollist ::= nm */
110606 {yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
110607 break;
110608 case 181: /* expr ::= term */
110609 {yygotominor.yy342 = yymsp[0].minor.yy342;}
110610 break;
110611 case 182: /* expr ::= LP expr RP */
110612 {yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
110613 break;
110614 case 183: /* term ::= NULL */
110615 case 188: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==188);
110616 case 189: /* term ::= STRING */ yytestcase(yyruleno==189);
110617 {spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
110618 break;
110619 case 184: /* expr ::= id */
110620 case 185: /* expr ::= JOIN_KW */ yytestcase(yyruleno==185);
110621 {spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
110622 break;
110623 case 186: /* expr ::= nm DOT nm */
110624 {
110625 Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110626 Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
110627 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
110628 spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
110629 }
110630 break;
110631 case 187: /* expr ::= nm DOT nm DOT nm */
110632 {
110633 Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
110634 Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
110635 Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
110636 Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
110637 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
110638 spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
110639 }
110640 break;
110641 case 190: /* expr ::= REGISTER */
110642 {
110643 /* When doing a nested parse, one can include terms in an expression
110644 ** that look like this: #1 #2 ... These terms refer to registers
110645 ** in the virtual machine. #N is the N-th register. */
110646 if( pParse->nested==0 ){
@@ -110355,31 +110651,31 @@
110651 if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
110652 }
110653 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110654 }
110655 break;
110656 case 191: /* expr ::= VARIABLE */
110657 {
110658 spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
110659 sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
110660 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110661 }
110662 break;
110663 case 192: /* expr ::= expr COLLATE ids */
110664 {
110665 yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
110666 yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110667 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110668 }
110669 break;
110670 case 193: /* expr ::= CAST LP expr AS typetoken RP */
110671 {
110672 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
110673 spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
110674 }
110675 break;
110676 case 194: /* expr ::= ID LP distinct exprlist RP */
110677 {
110678 if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
110679 sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
110680 }
110681 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
@@ -110387,17 +110683,17 @@
110683 if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
110684 yygotominor.yy342.pExpr->flags |= EP_Distinct;
110685 }
110686 }
110687 break;
110688 case 195: /* expr ::= ID LP STAR RP */
110689 {
110690 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
110691 spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
110692 }
110693 break;
110694 case 196: /* term ::= CTIME_KW */
110695 {
110696 /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
110697 ** treated as functions that return constants */
110698 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
110699 if( yygotominor.yy342.pExpr ){
@@ -110404,82 +110700,82 @@
110700 yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
110701 }
110702 spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
110703 }
110704 break;
110705 case 197: /* expr ::= expr AND expr */
110706 case 198: /* expr ::= expr OR expr */ yytestcase(yyruleno==198);
110707 case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199);
110708 case 200: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==200);
110709 case 201: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==201);
110710 case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202);
110711 case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203);
110712 case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204);
110713 {spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
110714 break;
110715 case 205: /* likeop ::= LIKE_KW */
110716 case 207: /* likeop ::= MATCH */ yytestcase(yyruleno==207);
110717 {yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;}
110718 break;
110719 case 206: /* likeop ::= NOT LIKE_KW */
110720 case 208: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==208);
110721 {yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;}
110722 break;
110723 case 209: /* expr ::= expr likeop expr */
110724 {
110725 ExprList *pList;
110726 pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
110727 pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
110728 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
110729 if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110730 yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
110731 yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110732 if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
110733 }
110734 break;
110735 case 210: /* expr ::= expr likeop expr ESCAPE expr */
110736 {
110737 ExprList *pList;
110738 pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110739 pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
110740 pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
110741 yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
110742 if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110743 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110744 yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110745 if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
110746 }
110747 break;
110748 case 211: /* expr ::= expr ISNULL|NOTNULL */
110749 {spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
110750 break;
110751 case 212: /* expr ::= expr NOT NULL */
110752 {spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
110753 break;
110754 case 213: /* expr ::= expr IS expr */
110755 {
110756 spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
110757 binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
110758 }
110759 break;
110760 case 214: /* expr ::= expr IS NOT expr */
110761 {
110762 spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
110763 binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
110764 }
110765 break;
110766 case 215: /* expr ::= NOT expr */
110767 case 216: /* expr ::= BITNOT expr */ yytestcase(yyruleno==216);
110768 {spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110769 break;
110770 case 217: /* expr ::= MINUS expr */
110771 {spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110772 break;
110773 case 218: /* expr ::= PLUS expr */
110774 {spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
110775 break;
110776 case 221: /* expr ::= expr between_op expr AND expr */
110777 {
110778 ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110779 pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
110780 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
110781 if( yygotominor.yy342.pExpr ){
@@ -110490,11 +110786,11 @@
110786 if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110787 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110788 yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
110789 }
110790 break;
110791 case 224: /* expr ::= expr in_op LP exprlist RP */
110792 {
110793 if( yymsp[-1].minor.yy442==0 ){
110794 /* Expressions of the form
110795 **
110796 ** expr1 IN ()
@@ -110517,11 +110813,11 @@
110813 }
110814 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110815 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110816 }
110817 break;
110818 case 225: /* expr ::= LP select RP */
110819 {
110820 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
110821 if( yygotominor.yy342.pExpr ){
110822 yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
110823 ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
@@ -110531,11 +110827,11 @@
110827 }
110828 yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
110829 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110830 }
110831 break;
110832 case 226: /* expr ::= expr in_op LP select RP */
110833 {
110834 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
110835 if( yygotominor.yy342.pExpr ){
110836 yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
110837 ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
@@ -110546,11 +110842,11 @@
110842 if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110843 yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
110844 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110845 }
110846 break;
110847 case 227: /* expr ::= expr in_op nm dbnm */
110848 {
110849 SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
110850 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
110851 if( yygotominor.yy342.pExpr ){
110852 yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
@@ -110562,11 +110858,11 @@
110858 if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
110859 yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
110860 yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
110861 }
110862 break;
110863 case 228: /* expr ::= EXISTS LP select RP */
110864 {
110865 Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
110866 if( p ){
110867 p->x.pSelect = yymsp[-1].minor.yy159;
110868 ExprSetProperty(p, EP_xIsSelect);
@@ -110576,11 +110872,11 @@
110872 }
110873 yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
110874 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110875 }
110876 break;
110877 case 229: /* expr ::= CASE case_operand case_exprlist case_else END */
110878 {
110879 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
110880 if( yygotominor.yy342.pExpr ){
110881 yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
110882 sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
@@ -110589,43 +110885,43 @@
110885 }
110886 yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
110887 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
110888 }
110889 break;
110890 case 230: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
110891 {
110892 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
110893 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
110894 }
110895 break;
110896 case 231: /* case_exprlist ::= WHEN expr THEN expr */
110897 {
110898 yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
110899 yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
110900 }
110901 break;
110902 case 238: /* nexprlist ::= nexprlist COMMA expr */
110903 {yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
110904 break;
110905 case 239: /* nexprlist ::= expr */
110906 {yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
110907 break;
110908 case 240: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
110909 {
110910 sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
110911 sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
110912 &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
110913 }
110914 break;
110915 case 241: /* uniqueflag ::= UNIQUE */
110916 case 294: /* raisetype ::= ABORT */ yytestcase(yyruleno==294);
110917 {yygotominor.yy392 = OE_Abort;}
110918 break;
110919 case 242: /* uniqueflag ::= */
110920 {yygotominor.yy392 = OE_None;}
110921 break;
110922 case 245: /* idxlist ::= idxlist COMMA nm collate sortorder */
110923 {
110924 Expr *p = 0;
110925 if( yymsp[-1].minor.yy0.n>0 ){
110926 p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
110927 sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
@@ -110634,11 +110930,11 @@
110930 sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
110931 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110932 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110933 }
110934 break;
110935 case 246: /* idxlist ::= nm collate sortorder */
110936 {
110937 Expr *p = 0;
110938 if( yymsp[-1].minor.yy0.n>0 ){
110939 p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
110940 sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
@@ -110647,212 +110943,212 @@
110943 sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
110944 sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
110945 if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
110946 }
110947 break;
110948 case 247: /* collate ::= */
110949 {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
110950 break;
110951 case 249: /* cmd ::= DROP INDEX ifexists fullname */
110952 {sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
110953 break;
110954 case 250: /* cmd ::= VACUUM */
110955 case 251: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==251);
110956 {sqlite3Vacuum(pParse);}
110957 break;
110958 case 252: /* cmd ::= PRAGMA nm dbnm */
110959 {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
110960 break;
110961 case 253: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
110962 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
110963 break;
110964 case 254: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
110965 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
110966 break;
110967 case 255: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
110968 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
110969 break;
110970 case 256: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
110971 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
110972 break;
110973 case 266: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
110974 {
110975 Token all;
110976 all.z = yymsp[-3].minor.yy0.z;
110977 all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
110978 sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
110979 }
110980 break;
110981 case 267: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
110982 {
110983 sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
110984 yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
110985 }
110986 break;
110987 case 268: /* trigger_time ::= BEFORE */
110988 case 271: /* trigger_time ::= */ yytestcase(yyruleno==271);
110989 { yygotominor.yy392 = TK_BEFORE; }
110990 break;
110991 case 269: /* trigger_time ::= AFTER */
110992 { yygotominor.yy392 = TK_AFTER; }
110993 break;
110994 case 270: /* trigger_time ::= INSTEAD OF */
110995 { yygotominor.yy392 = TK_INSTEAD;}
110996 break;
110997 case 272: /* trigger_event ::= DELETE|INSERT */
110998 case 273: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==273);
110999 {yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
111000 break;
111001 case 274: /* trigger_event ::= UPDATE OF inscollist */
111002 {yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
111003 break;
111004 case 277: /* when_clause ::= */
111005 case 299: /* key_opt ::= */ yytestcase(yyruleno==299);
111006 { yygotominor.yy122 = 0; }
111007 break;
111008 case 278: /* when_clause ::= WHEN expr */
111009 case 300: /* key_opt ::= KEY expr */ yytestcase(yyruleno==300);
111010 { yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
111011 break;
111012 case 279: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
111013 {
111014 assert( yymsp[-2].minor.yy327!=0 );
111015 yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
111016 yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
111017 yygotominor.yy327 = yymsp[-2].minor.yy327;
111018 }
111019 break;
111020 case 280: /* trigger_cmd_list ::= trigger_cmd SEMI */
111021 {
111022 assert( yymsp[-1].minor.yy327!=0 );
111023 yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
111024 yygotominor.yy327 = yymsp[-1].minor.yy327;
111025 }
111026 break;
111027 case 282: /* trnm ::= nm DOT nm */
111028 {
111029 yygotominor.yy0 = yymsp[0].minor.yy0;
111030 sqlite3ErrorMsg(pParse,
111031 "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
111032 "statements within triggers");
111033 }
111034 break;
111035 case 284: /* tridxby ::= INDEXED BY nm */
111036 {
111037 sqlite3ErrorMsg(pParse,
111038 "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
111039 "within triggers");
111040 }
111041 break;
111042 case 285: /* tridxby ::= NOT INDEXED */
111043 {
111044 sqlite3ErrorMsg(pParse,
111045 "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
111046 "within triggers");
111047 }
111048 break;
111049 case 286: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
111050 { yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
111051 break;
111052 case 287: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
111053 {yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
111054 break;
111055 case 288: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
111056 {yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
111057 break;
111058 case 289: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
111059 {yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
111060 break;
111061 case 290: /* trigger_cmd ::= select */
111062 {yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
111063 break;
111064 case 291: /* expr ::= RAISE LP IGNORE RP */
111065 {
111066 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
111067 if( yygotominor.yy342.pExpr ){
111068 yygotominor.yy342.pExpr->affinity = OE_Ignore;
111069 }
111070 yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
111071 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
111072 }
111073 break;
111074 case 292: /* expr ::= RAISE LP raisetype COMMA nm RP */
111075 {
111076 yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
111077 if( yygotominor.yy342.pExpr ) {
111078 yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
111079 }
111080 yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
111081 yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
111082 }
111083 break;
111084 case 293: /* raisetype ::= ROLLBACK */
111085 {yygotominor.yy392 = OE_Rollback;}
111086 break;
111087 case 295: /* raisetype ::= FAIL */
111088 {yygotominor.yy392 = OE_Fail;}
111089 break;
111090 case 296: /* cmd ::= DROP TRIGGER ifexists fullname */
111091 {
111092 sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
111093 }
111094 break;
111095 case 297: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
111096 {
111097 sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
111098 }
111099 break;
111100 case 298: /* cmd ::= DETACH database_kw_opt expr */
111101 {
111102 sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
111103 }
111104 break;
111105 case 303: /* cmd ::= REINDEX */
111106 {sqlite3Reindex(pParse, 0, 0);}
111107 break;
111108 case 304: /* cmd ::= REINDEX nm dbnm */
111109 {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
111110 break;
111111 case 305: /* cmd ::= ANALYZE */
111112 {sqlite3Analyze(pParse, 0, 0);}
111113 break;
111114 case 306: /* cmd ::= ANALYZE nm dbnm */
111115 {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
111116 break;
111117 case 307: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
111118 {
111119 sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
111120 }
111121 break;
111122 case 308: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
111123 {
111124 sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
111125 }
111126 break;
111127 case 309: /* add_column_fullname ::= fullname */
111128 {
111129 pParse->db->lookaside.bEnabled = 0;
111130 sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
111131 }
111132 break;
111133 case 312: /* cmd ::= create_vtab */
111134 {sqlite3VtabFinishParse(pParse,0);}
111135 break;
111136 case 313: /* cmd ::= create_vtab LP vtabarglist RP */
111137 {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
111138 break;
111139 case 314: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
111140 {
111141 sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
111142 }
111143 break;
111144 case 317: /* vtabarg ::= */
111145 {sqlite3VtabArgInit(pParse);}
111146 break;
111147 case 319: /* vtabargtoken ::= ANY */
111148 case 320: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==320);
111149 case 321: /* lp ::= LP */ yytestcase(yyruleno==321);
111150 {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
111151 break;
111152 default:
111153 /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
111154 /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
@@ -110868,32 +111164,28 @@
111164 /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
111165 /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
111166 /* (44) type ::= */ yytestcase(yyruleno==44);
111167 /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
111168 /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
111169 /* (53) carglist ::= carglist cname ccons */ yytestcase(yyruleno==53);
111170 /* (54) carglist ::= */ yytestcase(yyruleno==54);
 
 
111171 /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
111172 /* (90) conslist ::= conslist COMMA cname tcons */ yytestcase(yyruleno==90);
111173 /* (91) conslist ::= cname tcons */ yytestcase(yyruleno==91);
111174 /* (275) foreach_clause ::= */ yytestcase(yyruleno==275);
111175 /* (276) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==276);
111176 /* (283) tridxby ::= */ yytestcase(yyruleno==283);
111177 /* (301) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==301);
111178 /* (302) database_kw_opt ::= */ yytestcase(yyruleno==302);
111179 /* (310) kwcolumn_opt ::= */ yytestcase(yyruleno==310);
111180 /* (311) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==311);
111181 /* (315) vtabarglist ::= vtabarg */ yytestcase(yyruleno==315);
111182 /* (316) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==316);
111183 /* (318) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==318);
111184 /* (322) anylist ::= */ yytestcase(yyruleno==322);
111185 /* (323) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==323);
111186 /* (324) anylist ::= anylist ANY */ yytestcase(yyruleno==324);
 
 
111187 break;
111188 };
111189 yygoto = yyRuleInfo[yyruleno].lhs;
111190 yysize = yyRuleInfo[yyruleno].nrhs;
111191 yypParser->yyidx -= yysize;
@@ -113174,23 +113466,27 @@
113466 sqlite3_free(db);
113467 return SQLITE_OK;
113468 }
113469
113470 /*
113471 ** Rollback all database files. If tripCode is not SQLITE_OK, then
113472 ** any open cursors are invalidated ("tripped" - as in "tripping a circuit
113473 ** breaker") and made to return tripCode if there are any further
113474 ** attempts to use that cursor.
113475 */
113476 SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
113477 int i;
113478 int inTrans = 0;
113479 assert( sqlite3_mutex_held(db->mutex) );
113480 sqlite3BeginBenignMalloc();
113481 for(i=0; i<db->nDb; i++){
113482 Btree *p = db->aDb[i].pBt;
113483 if( p ){
113484 if( sqlite3BtreeIsInTrans(p) ){
113485 inTrans = 1;
113486 }
113487 sqlite3BtreeRollback(p, tripCode);
113488 db->aDb[i].inTrans = 0;
113489 }
113490 }
113491 sqlite3VtabRollback(db);
113492 sqlite3EndBenignMalloc();
@@ -113241,16 +113537,25 @@
113537 /* SQLITE_AUTH */ "authorization denied",
113538 /* SQLITE_FORMAT */ "auxiliary database format error",
113539 /* SQLITE_RANGE */ "bind or column index out of range",
113540 /* SQLITE_NOTADB */ "file is encrypted or is not a database",
113541 };
113542 const char *zErr = "unknown error";
113543 switch( rc ){
113544 case SQLITE_ABORT_ROLLBACK: {
113545 zErr = "abort due to ROLLBACK";
113546 break;
113547 }
113548 default: {
113549 rc &= 0xff;
113550 if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){
113551 zErr = aMsg[rc];
113552 }
113553 break;
113554 }
113555 }
113556 return zErr;
113557 }
113558
113559 /*
113560 ** This routine implements a busy callback that sleeps and tries
113561 ** again until a timeout value is reached. The timeout value is
@@ -113624,13 +113929,12 @@
113929 sqlite3_mutex_leave(db->mutex);
113930 return pOld;
113931 }
113932 #endif /* SQLITE_OMIT_TRACE */
113933
113934 /*
113935 ** Register a function to be invoked when a transaction commits.
 
113936 ** If the invoked function returns non-zero, then the commit becomes a
113937 ** rollback.
113938 */
113939 SQLITE_API void *sqlite3_commit_hook(
113940 sqlite3 *db, /* Attach the hook to this database */
@@ -115017,39 +115321,31 @@
115321 /*
115322 ** Invoke the xFileControl method on a particular database.
115323 */
115324 SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
115325 int rc = SQLITE_ERROR;
115326 Btree *pBtree;
115327
115328 sqlite3_mutex_enter(db->mutex);
115329 pBtree = sqlite3DbNameToBtree(db, zDbName);
115330 if( pBtree ){
115331 Pager *pPager;
115332 sqlite3_file *fd;
115333 sqlite3BtreeEnter(pBtree);
115334 pPager = sqlite3BtreePager(pBtree);
115335 assert( pPager!=0 );
115336 fd = sqlite3PagerFile(pPager);
115337 assert( fd!=0 );
115338 if( op==SQLITE_FCNTL_FILE_POINTER ){
115339 *(sqlite3_file**)pArg = fd;
115340 rc = SQLITE_OK;
115341 }else if( fd->pMethods ){
115342 rc = sqlite3OsFileControl(fd, op, pArg);
115343 }else{
115344 rc = SQLITE_NOTFOUND;
115345 }
115346 sqlite3BtreeLeave(pBtree);
 
 
 
 
 
 
 
 
 
115347 }
115348 sqlite3_mutex_leave(db->mutex);
115349 return rc;
115350 }
115351
@@ -115339,23 +115635,42 @@
115635 if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
115636 bDflt = v;
115637 }
115638 return bDflt;
115639 }
115640
115641 /*
115642 ** Return the Btree pointer identified by zDbName. Return NULL if not found.
115643 */
115644 SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
115645 int i;
115646 for(i=0; i<db->nDb; i++){
115647 if( db->aDb[i].pBt
115648 && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0)
115649 ){
115650 return db->aDb[i].pBt;
115651 }
115652 }
115653 return 0;
115654 }
115655
115656 /*
115657 ** Return the filename of the database associated with a database
115658 ** connection.
115659 */
115660 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
115661 Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
115662 return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
115663 }
115664
115665 /*
115666 ** Return 1 if database is read-only or 0 if read/write. Return -1 if
115667 ** no such database exists.
115668 */
115669 SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
115670 Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
115671 return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
115672 }
115673
115674 /************** End of main.c ************************************************/
115675 /************** Begin file notify.c ******************************************/
115676 /*
@@ -115761,11 +116076,11 @@
116076 ** option. But that functionality is no longer supported.
116077 **
116078 ** A doclist is stored like this:
116079 **
116080 ** array {
116081 ** varint docid; (delta from previous doclist)
116082 ** array { (position list for column 0)
116083 ** varint position; (2 more than the delta from previous position)
116084 ** }
116085 ** array {
116086 ** varint POS_COLUMN; (marks start of position list for new column)
@@ -115792,12 +116107,12 @@
116107 ** The 123 value is the first docid. For column zero in this document
116108 ** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
116109 ** at D signals the start of a new column; the 1 at E indicates that the
116110 ** new column is column number 1. There are two positions at 12 and 45
116111 ** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
116112 ** 234 at I is the delta to next docid (357). It has one position 70
116113 ** (72-2) and then terminates with the 0 at K.
116114 **
116115 ** A "position-list" is the list of positions for multiple columns for
116116 ** a single docid. A "column-list" is the set of positions for a single
116117 ** column. Hence, a position-list consists of one or more column-lists,
116118 ** a document record consists of a docid followed by a position-list and
@@ -115977,14 +116292,10 @@
116292 ** we simply write the new doclist. Segment merges overwrite older
116293 ** data for a particular docid with newer data, so deletes or updates
116294 ** will eventually overtake the earlier data and knock it out. The
116295 ** query logic likewise merges doclists so that newer data knocks out
116296 ** older data.
 
 
 
 
116297 */
116298
116299 /************** Include fts3Int.h in the middle of fts3.c ********************/
116300 /************** Begin file fts3Int.h *****************************************/
116301 /*
@@ -116076,11 +116387,11 @@
116387 typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
116388
116389 struct sqlite3_tokenizer_module {
116390
116391 /*
116392 ** Structure version. Should always be set to 0 or 1.
116393 */
116394 int iVersion;
116395
116396 /*
116397 ** Create a new tokenizer. The values in the argv[] array are the
@@ -116157,10 +116468,19 @@
116468 const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
116469 int *piStartOffset, /* OUT: Byte offset of token in input buffer */
116470 int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
116471 int *piPosition /* OUT: Number of tokens returned before this one */
116472 );
116473
116474 /***********************************************************************
116475 ** Methods below this point are only available if iVersion>=1.
116476 */
116477
116478 /*
116479 ** Configure the language id of a tokenizer cursor.
116480 */
116481 int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
116482 };
116483
116484 struct sqlite3_tokenizer {
116485 const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
116486 /* Tokenizer implementations will typically add additional fields */
@@ -116323,10 +116643,13 @@
116643
116644
116645 #ifndef MIN
116646 # define MIN(x,y) ((x)<(y)?(x):(y))
116647 #endif
116648 #ifndef MAX
116649 # define MAX(x,y) ((x)>(y)?(x):(y))
116650 #endif
116651
116652 /*
116653 ** Maximum length of a varint encoded integer. The varint format is different
116654 ** from that used by SQLite, so the maximum length is 10, not 9.
116655 */
@@ -116377,20 +116700,21 @@
116700 #ifdef SQLITE_COVERAGE_TEST
116701 # define ALWAYS(x) (1)
116702 # define NEVER(X) (0)
116703 #else
116704 # define ALWAYS(x) (x)
116705 # define NEVER(x) (x)
116706 #endif
116707
116708 /*
116709 ** Internal types used by SQLite.
116710 */
116711 typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
116712 typedef short int i16; /* 2-byte (or larger) signed integer */
116713 typedef unsigned int u32; /* 4-byte unsigned integer */
116714 typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
116715 typedef sqlite3_int64 i64; /* 8-byte signed integer */
116716
116717 /*
116718 ** Macro used to suppress compiler warnings for unused parameters.
116719 */
116720 #define UNUSED_PARAMETER(x) (void)(x)
@@ -116448,55 +116772,64 @@
116772 const char *zName; /* virtual table name */
116773 int nColumn; /* number of named columns in virtual table */
116774 char **azColumn; /* column names. malloced */
116775 sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
116776 char *zContentTbl; /* content=xxx option, or NULL */
116777 char *zLanguageid; /* languageid=xxx option, or NULL */
116778 u8 bAutoincrmerge; /* True if automerge=1 */
116779 u32 nLeafAdd; /* Number of leaf blocks added this trans */
116780
116781 /* Precompiled statements used by the implementation. Each of these
116782 ** statements is run and reset within a single virtual table API call.
116783 */
116784 sqlite3_stmt *aStmt[37];
116785
116786 char *zReadExprlist;
116787 char *zWriteExprlist;
116788
116789 int nNodeSize; /* Soft limit for node size */
116790 u8 bFts4; /* True for FTS4, false for FTS3 */
116791 u8 bHasStat; /* True if %_stat table exists */
116792 u8 bHasDocsize; /* True if %_docsize table exists */
116793 u8 bDescIdx; /* True if doclists are in reverse order */
116794 u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */
116795 int nPgsz; /* Page size for host database */
116796 char *zSegmentsTbl; /* Name of %_segments table */
116797 sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
116798
116799 /*
116800 ** The following array of hash tables is used to buffer pending index
116801 ** updates during transactions. All pending updates buffered at any one
116802 ** time must share a common language-id (see the FTS4 langid= feature).
116803 ** The current language id is stored in variable iPrevLangid.
 
 
 
116804 **
116805 ** A single FTS4 table may have multiple full-text indexes. For each index
116806 ** there is an entry in the aIndex[] array. Index 0 is an index of all the
116807 ** terms that appear in the document set. Each subsequent index in aIndex[]
116808 ** is an index of prefixes of a specific length.
116809 **
116810 ** Variable nPendingData contains an estimate the memory consumed by the
116811 ** pending data structures, including hash table overhead, but not including
116812 ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash
116813 ** tables are flushed to disk. Variable iPrevDocid is the docid of the most
116814 ** recently inserted record.
116815 */
116816 int nIndex; /* Size of aIndex[] */
116817 struct Fts3Index {
116818 int nPrefix; /* Prefix length (0 for main terms index) */
116819 Fts3Hash hPending; /* Pending terms table for this index */
116820 } *aIndex;
116821 int nMaxPendingData; /* Max pending data before flush to disk */
116822 int nPendingData; /* Current bytes of pending data */
116823 sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
116824 int iPrevLangid; /* Langid of recently inserted document */
116825
116826 #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
116827 /* State variables used for validating that the transaction control
116828 ** methods of the virtual table are called at appropriate times. These
116829 ** values do not contribute to FTS functionality; they are used for
116830 ** verifying the operation of the SQLite core.
116831 */
116832 int inTransaction; /* True after xBegin but before xCommit/xRollback */
116833 int mxSavepoint; /* Largest valid xSavepoint integer */
116834 #endif
116835 };
@@ -116511,10 +116844,11 @@
116844 i16 eSearch; /* Search strategy (see below) */
116845 u8 isEof; /* True if at End Of Results */
116846 u8 isRequireSeek; /* True if must seek pStmt to %_content row */
116847 sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
116848 Fts3Expr *pExpr; /* Parsed MATCH query string */
116849 int iLangid; /* Language being queried for */
116850 int nPhrase; /* Number of matchable phrases in query */
116851 Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
116852 sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
116853 char *pNextId; /* Pointer into the body of aDoclist */
116854 char *aDoclist; /* List of docids for full-text queries */
@@ -116662,11 +116996,11 @@
116996 SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
116997 sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
116998 SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
116999 Fts3Table*,int,const char*,int,int,Fts3SegReader**);
117000 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
117001 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
117002 SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
117003 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
117004
117005 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
117006 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
@@ -116674,21 +117008,22 @@
117008 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
117009 SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
117010 SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
117011 SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
117012 SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
117013 SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *);
117014
117015 /* Special values interpreted by sqlite3SegReaderCursor() */
117016 #define FTS3_SEGCURSOR_PENDING -1
117017 #define FTS3_SEGCURSOR_ALL -2
117018
117019 SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
117020 SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
117021 SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
117022
117023 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *,
117024 int, int, int, const char *, int, int, int, Fts3MultiSegReader *);
117025
117026 /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
117027 #define FTS3_SEGMENT_REQUIRE_POS 0x00000001
117028 #define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
117029 #define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
@@ -116725,19 +117060,22 @@
117060 int nTerm; /* Size of zTerm in bytes */
117061 char *aDoclist; /* Pointer to doclist buffer */
117062 int nDoclist; /* Size of aDoclist[] in bytes */
117063 };
117064
117065 SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
117066
117067 /* fts3.c */
117068 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
117069 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
117070 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
117071 SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
117072 SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
117073 SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
117074 SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
117075 SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
117076 SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
117077
117078 /* fts3_tokenizer.c */
117079 SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
117080 SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
117081 SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
@@ -116751,18 +117089,22 @@
117089 const char *, const char *, int, int
117090 );
117091 SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
117092
117093 /* fts3_expr.c */
117094 SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
117095 char **, int, int, int, const char *, int, Fts3Expr **
117096 );
117097 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
117098 #ifdef SQLITE_TEST
117099 SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
117100 SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
117101 #endif
117102
117103 SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
117104 sqlite3_tokenizer_cursor **
117105 );
117106
117107 /* fts3_aux.c */
117108 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
117109
117110 SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
@@ -116954,10 +117296,11 @@
117296 }
117297 sqlite3_free(p->zSegmentsTbl);
117298 sqlite3_free(p->zReadExprlist);
117299 sqlite3_free(p->zWriteExprlist);
117300 sqlite3_free(p->zContentTbl);
117301 sqlite3_free(p->zLanguageid);
117302
117303 /* Invoke the tokenizer destructor to free the tokenizer. */
117304 p->pTokenizer->pModule->xDestroy(p->pTokenizer);
117305
117306 sqlite3_free(p);
@@ -117030,11 +117373,13 @@
117373 if( *pRc==SQLITE_OK ){
117374 int i; /* Iterator variable */
117375 int rc; /* Return code */
117376 char *zSql; /* SQL statement passed to declare_vtab() */
117377 char *zCols; /* List of user defined columns */
117378 const char *zLanguageid;
117379
117380 zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid");
117381 sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
117382
117383 /* Create a list of user columns for the virtual table */
117384 zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
117385 for(i=1; zCols && i<p->nColumn; i++){
@@ -117041,11 +117386,12 @@
117386 zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
117387 }
117388
117389 /* Create the whole "CREATE TABLE" statement to pass to SQLite */
117390 zSql = sqlite3_mprintf(
117391 "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
117392 zCols, p->zName, zLanguageid
117393 );
117394 if( !zCols || !zSql ){
117395 rc = SQLITE_NOMEM;
117396 }else{
117397 rc = sqlite3_declare_vtab(p->db, zSql);
@@ -117054,10 +117400,22 @@
117400 sqlite3_free(zSql);
117401 sqlite3_free(zCols);
117402 *pRc = rc;
117403 }
117404 }
117405
117406 /*
117407 ** Create the %_stat table if it does not already exist.
117408 */
117409 SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){
117410 fts3DbExec(pRc, p->db,
117411 "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'"
117412 "(id INTEGER PRIMARY KEY, value BLOB);",
117413 p->zDb, p->zName
117414 );
117415 if( (*pRc)==SQLITE_OK ) p->bHasStat = 1;
117416 }
117417
117418 /*
117419 ** Create the backing store tables (%_content, %_segments and %_segdir)
117420 ** required by the FTS3 table passed as the only argument. This is done
117421 ** as part of the vtab xCreate() method.
@@ -117070,18 +117428,22 @@
117428 int rc = SQLITE_OK; /* Return code */
117429 int i; /* Iterator variable */
117430 sqlite3 *db = p->db; /* The database connection */
117431
117432 if( p->zContentTbl==0 ){
117433 const char *zLanguageid = p->zLanguageid;
117434 char *zContentCols; /* Columns of %_content table */
117435
117436 /* Create a list of user columns for the content table */
117437 zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
117438 for(i=0; zContentCols && i<p->nColumn; i++){
117439 char *z = p->azColumn[i];
117440 zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
117441 }
117442 if( zLanguageid && zContentCols ){
117443 zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);
117444 }
117445 if( zContentCols==0 ) rc = SQLITE_NOMEM;
117446
117447 /* Create the content table */
117448 fts3DbExec(&rc, db,
117449 "CREATE TABLE %Q.'%q_content'(%s)",
@@ -117111,15 +117473,13 @@
117473 fts3DbExec(&rc, db,
117474 "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
117475 p->zDb, p->zName
117476 );
117477 }
117478 assert( p->bHasStat==p->bFts4 );
117479 if( p->bHasStat ){
117480 sqlite3Fts3CreateStatTable(&rc, p);
 
 
 
117481 }
117482 return rc;
117483 }
117484
117485 /*
@@ -117222,11 +117582,11 @@
117582 ** memory.
117583 */
117584 static char *fts3QuoteId(char const *zInput){
117585 int nRet;
117586 char *zRet;
117587 nRet = 2 + (int)strlen(zInput)*2 + 1;
117588 zRet = sqlite3_malloc(nRet);
117589 if( zRet ){
117590 int i;
117591 char *z = zRet;
117592 *(z++) = '"';
@@ -117277,18 +117637,24 @@
117637 }
117638 fts3Appendf(pRc, &zRet, "docid");
117639 for(i=0; i<p->nColumn; i++){
117640 fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
117641 }
117642 if( p->zLanguageid ){
117643 fts3Appendf(pRc, &zRet, ", x.%Q", "langid");
117644 }
117645 sqlite3_free(zFree);
117646 }else{
117647 fts3Appendf(pRc, &zRet, "rowid");
117648 for(i=0; i<p->nColumn; i++){
117649 fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]);
117650 }
117651 if( p->zLanguageid ){
117652 fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid);
117653 }
117654 }
117655 fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
117656 p->zDb,
117657 (p->zContentTbl ? p->zContentTbl : p->zName),
117658 (p->zContentTbl ? "" : "_content")
117659 );
117660 return zRet;
@@ -117327,10 +117693,13 @@
117693 }
117694 fts3Appendf(pRc, &zRet, "?");
117695 for(i=0; i<p->nColumn; i++){
117696 fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
117697 }
117698 if( p->zLanguageid ){
117699 fts3Appendf(pRc, &zRet, ", ?");
117700 }
117701 sqlite3_free(zFree);
117702 return zRet;
117703 }
117704
117705 /*
@@ -117469,11 +117838,11 @@
117838 ** space required to store a copy of each column name, including the
117839 ** nul-terminator byte. */
117840 nCol = sqlite3_column_count(pStmt);
117841 for(i=0; i<nCol; i++){
117842 const char *zCol = sqlite3_column_name(pStmt, i);
117843 nStr += (int)strlen(zCol) + 1;
117844 }
117845
117846 /* Allocate and populate the array to return. */
117847 azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
117848 if( azCol==0 ){
@@ -117480,11 +117849,11 @@
117849 rc = SQLITE_NOMEM;
117850 }else{
117851 char *p = (char *)&azCol[nCol];
117852 for(i=0; i<nCol; i++){
117853 const char *zCol = sqlite3_column_name(pStmt, i);
117854 int n = (int)strlen(zCol)+1;
117855 memcpy(p, zCol, n);
117856 azCol[i] = p;
117857 p += n;
117858 }
117859 }
@@ -117542,10 +117911,11 @@
117911 int bDescIdx = 0; /* True to store descending indexes */
117912 char *zPrefix = 0; /* Prefix parameter value (or NULL) */
117913 char *zCompress = 0; /* compress=? parameter (or NULL) */
117914 char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
117915 char *zContent = 0; /* content=? parameter (or NULL) */
117916 char *zLanguageid = 0; /* languageid=? parameter (or NULL) */
117917
117918 assert( strlen(argv[0])==4 );
117919 assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
117920 || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
117921 );
@@ -117591,11 +117961,12 @@
117961 { "matchinfo", 9 }, /* 0 -> MATCHINFO */
117962 { "prefix", 6 }, /* 1 -> PREFIX */
117963 { "compress", 8 }, /* 2 -> COMPRESS */
117964 { "uncompress", 10 }, /* 3 -> UNCOMPRESS */
117965 { "order", 5 }, /* 4 -> ORDER */
117966 { "content", 7 }, /* 5 -> CONTENT */
117967 { "languageid", 10 } /* 6 -> LANGUAGEID */
117968 };
117969
117970 int iOpt;
117971 if( !zVal ){
117972 rc = SQLITE_NOMEM;
@@ -117645,16 +118016,22 @@
118016 rc = SQLITE_ERROR;
118017 }
118018 bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
118019 break;
118020
118021 case 5: /* CONTENT */
118022 sqlite3_free(zContent);
 
118023 zContent = zVal;
118024 zVal = 0;
118025 break;
118026
118027 case 6: /* LANGUAGEID */
118028 assert( iOpt==6 );
118029 sqlite3_free(zLanguageid);
118030 zLanguageid = zVal;
118031 zVal = 0;
118032 break;
118033 }
118034 }
118035 sqlite3_free(zVal);
118036 }
118037 }
@@ -117680,12 +118057,25 @@
118057 zUncompress = 0;
118058 if( nCol==0 ){
118059 sqlite3_free((void*)aCol);
118060 aCol = 0;
118061 rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
118062
118063 /* If a languageid= option was specified, remove the language id
118064 ** column from the aCol[] array. */
118065 if( rc==SQLITE_OK && zLanguageid ){
118066 int j;
118067 for(j=0; j<nCol; j++){
118068 if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){
118069 int k;
118070 for(k=j; k<nCol; k++) aCol[k] = aCol[k+1];
118071 nCol--;
118072 break;
118073 }
118074 }
118075 }
118076 }
 
118077 }
118078 if( rc!=SQLITE_OK ) goto fts3_init_out;
118079
118080 if( nCol==0 ){
118081 assert( nString==0 );
@@ -117726,13 +118116,17 @@
118116 p->azColumn = (char **)&p[1];
118117 p->pTokenizer = pTokenizer;
118118 p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
118119 p->bHasDocsize = (isFts4 && bNoDocsize==0);
118120 p->bHasStat = isFts4;
118121 p->bFts4 = isFts4;
118122 p->bDescIdx = bDescIdx;
118123 p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */
118124 p->zContentTbl = zContent;
118125 p->zLanguageid = zLanguageid;
118126 zContent = 0;
118127 zLanguageid = 0;
118128 TESTONLY( p->inTransaction = -1 );
118129 TESTONLY( p->mxSavepoint = -1 );
118130
118131 p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
118132 memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
@@ -117776,10 +118170,20 @@
118170 ** database. TODO: For xConnect(), it could verify that said tables exist.
118171 */
118172 if( isCreate ){
118173 rc = fts3CreateTables(p);
118174 }
118175
118176 /* Check to see if a legacy fts3 table has been "upgraded" by the
118177 ** addition of a %_stat table so that it can use incremental merge.
118178 */
118179 if( !isFts4 && !isCreate ){
118180 int rc2 = SQLITE_OK;
118181 fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
118182 p->zDb, p->zName);
118183 if( rc2==SQLITE_OK ) p->bHasStat = 1;
118184 }
118185
118186 /* Figure out the page-size for the database. This is required in order to
118187 ** estimate the cost of loading large doclists from the database. */
118188 fts3DatabasePageSize(&rc, p);
118189 p->nNodeSize = p->nPgsz-35;
@@ -117791,10 +118195,11 @@
118195 sqlite3_free(zPrefix);
118196 sqlite3_free(aIndex);
118197 sqlite3_free(zCompress);
118198 sqlite3_free(zUncompress);
118199 sqlite3_free(zContent);
118200 sqlite3_free(zLanguageid);
118201 sqlite3_free((void *)aCol);
118202 if( rc!=SQLITE_OK ){
118203 if( p ){
118204 fts3DisconnectMethod((sqlite3_vtab *)p);
118205 }else if( pTokenizer ){
@@ -117842,10 +118247,11 @@
118247 */
118248 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
118249 Fts3Table *p = (Fts3Table *)pVTab;
118250 int i; /* Iterator variable */
118251 int iCons = -1; /* Index of constraint to use */
118252 int iLangidCons = -1; /* Index of langid=x constraint, if present */
118253
118254 /* By default use a full table scan. This is an expensive option,
118255 ** so search through the constraints to see if a more efficient
118256 ** strategy is possible.
118257 */
@@ -117854,11 +118260,12 @@
118260 for(i=0; i<pInfo->nConstraint; i++){
118261 struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
118262 if( pCons->usable==0 ) continue;
118263
118264 /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
118265 if( iCons<0
118266 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
118267 && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
118268 ){
118269 pInfo->idxNum = FTS3_DOCID_SEARCH;
118270 pInfo->estimatedCost = 1.0;
118271 iCons = i;
@@ -117877,18 +118284,27 @@
118284 && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
118285 ){
118286 pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
118287 pInfo->estimatedCost = 2.0;
118288 iCons = i;
118289 }
118290
118291 /* Equality constraint on the langid column */
118292 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
118293 && pCons->iColumn==p->nColumn + 2
118294 ){
118295 iLangidCons = i;
118296 }
118297 }
118298
118299 if( iCons>=0 ){
118300 pInfo->aConstraintUsage[iCons].argvIndex = 1;
118301 pInfo->aConstraintUsage[iCons].omit = 1;
118302 }
118303 if( iLangidCons>=0 ){
118304 pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
118305 }
118306
118307 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
118308 ** docid) order. Both ascending and descending are possible.
118309 */
118310 if( pInfo->nOrderBy==1 ){
@@ -118768,11 +119184,11 @@
119184 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
119185 }
119186 }
119187
119188 *paOut = aOut;
119189 *pnOut = (int)(p-aOut);
119190 assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
119191 return SQLITE_OK;
119192 }
119193
119194 /*
@@ -118832,11 +119248,11 @@
119248 fts3PoslistCopy(0, &p2);
119249 fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
119250 }
119251 }
119252
119253 *pnRight = (int)(p - aOut);
119254 }
119255
119256 /*
119257 ** Argument pList points to a position list nList bytes in size. This
119258 ** function checks to see if the position list contains any entries for
@@ -119034,10 +119450,11 @@
119450 ** This function returns SQLITE_OK if successful, or an SQLite error code
119451 ** otherwise.
119452 */
119453 static int fts3SegReaderCursor(
119454 Fts3Table *p, /* FTS3 table handle */
119455 int iLangid, /* Language id */
119456 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
119457 int iLevel, /* Level of segments to scan */
119458 const char *zTerm, /* Term to query for */
119459 int nTerm, /* Size of zTerm in bytes */
119460 int isPrefix, /* True for a prefix search */
@@ -119062,11 +119479,11 @@
119479 }
119480 }
119481
119482 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
119483 if( rc==SQLITE_OK ){
119484 rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt);
119485 }
119486
119487 while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
119488 Fts3SegReader *pSeg = 0;
119489
@@ -119107,10 +119524,11 @@
119524 ** Set up a cursor object for iterating through a full-text index or a
119525 ** single level therein.
119526 */
119527 SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
119528 Fts3Table *p, /* FTS3 table handle */
119529 int iLangid, /* Language-id to search */
119530 int iIndex, /* Index to search (from 0 to p->nIndex-1) */
119531 int iLevel, /* Level of segments to scan */
119532 const char *zTerm, /* Term to query for */
119533 int nTerm, /* Size of zTerm in bytes */
119534 int isPrefix, /* True for a prefix search */
@@ -119124,18 +119542,13 @@
119542 );
119543 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
119544 assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
119545 assert( isPrefix==0 || isScan==0 );
119546
 
 
 
 
119547 memset(pCsr, 0, sizeof(Fts3MultiSegReader));
 
119548 return fts3SegReaderCursor(
119549 p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
119550 );
119551 }
119552
119553 /*
119554 ** In addition to its current configuration, have the Fts3MultiSegReader
@@ -119143,15 +119556,18 @@
119556 **
119557 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
119558 */
119559 static int fts3SegReaderCursorAddZero(
119560 Fts3Table *p, /* FTS virtual table handle */
119561 int iLangid,
119562 const char *zTerm, /* Term to scan doclist of */
119563 int nTerm, /* Number of bytes in zTerm */
119564 Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
119565 ){
119566 return fts3SegReaderCursor(p,
119567 iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
119568 );
119569 }
119570
119571 /*
119572 ** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
119573 ** if isPrefix is true, to scan the doclist for all terms for which
@@ -119183,32 +119599,35 @@
119599
119600 if( isPrefix ){
119601 for(i=1; bFound==0 && i<p->nIndex; i++){
119602 if( p->aIndex[i].nPrefix==nTerm ){
119603 bFound = 1;
119604 rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
119605 i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
119606 );
119607 pSegcsr->bLookup = 1;
119608 }
119609 }
119610
119611 for(i=1; bFound==0 && i<p->nIndex; i++){
119612 if( p->aIndex[i].nPrefix==nTerm+1 ){
119613 bFound = 1;
119614 rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
119615 i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
119616 );
119617 if( rc==SQLITE_OK ){
119618 rc = fts3SegReaderCursorAddZero(
119619 p, pCsr->iLangid, zTerm, nTerm, pSegcsr
119620 );
119621 }
119622 }
119623 }
119624 }
119625
119626 if( bFound==0 ){
119627 rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
119628 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
119629 );
119630 pSegcsr->bLookup = !isPrefix;
119631 }
119632 }
119633
@@ -119359,11 +119778,11 @@
119778
119779 UNUSED_PARAMETER(idxStr);
119780 UNUSED_PARAMETER(nVal);
119781
119782 assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
119783 assert( nVal==0 || nVal==1 || nVal==2 );
119784 assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
119785 assert( p->pSegments==0 );
119786
119787 /* In case the cursor has been used before, clear it now. */
119788 sqlite3_finalize(pCsr->pStmt);
@@ -119384,12 +119803,15 @@
119803
119804 if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
119805 return SQLITE_NOMEM;
119806 }
119807
119808 pCsr->iLangid = 0;
119809 if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
119810
119811 rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
119812 p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
119813 );
119814 if( rc!=SQLITE_OK ){
119815 if( rc==SQLITE_ERROR ){
119816 static const char *zErr = "malformed MATCH expression: [%s]";
119817 p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
@@ -119456,37 +119878,56 @@
119878 }
119879
119880 /*
119881 ** This is the xColumn method, called by SQLite to request a value from
119882 ** the row that the supplied cursor currently points to.
119883 **
119884 ** If:
119885 **
119886 ** (iCol < p->nColumn) -> The value of the iCol'th user column.
119887 ** (iCol == p->nColumn) -> Magic column with the same name as the table.
119888 ** (iCol == p->nColumn+1) -> Docid column
119889 ** (iCol == p->nColumn+2) -> Langid column
119890 */
119891 static int fts3ColumnMethod(
119892 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
119893 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
119894 int iCol /* Index of column to read value from */
119895 ){
119896 int rc = SQLITE_OK; /* Return Code */
119897 Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
119898 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
119899
119900 /* The column value supplied by SQLite must be in range. */
119901 assert( iCol>=0 && iCol<=p->nColumn+2 );
119902
119903 if( iCol==p->nColumn+1 ){
119904 /* This call is a request for the "docid" column. Since "docid" is an
119905 ** alias for "rowid", use the xRowid() method to obtain the value.
119906 */
119907 sqlite3_result_int64(pCtx, pCsr->iPrevId);
119908 }else if( iCol==p->nColumn ){
119909 /* The extra column whose name is the same as the table.
119910 ** Return a blob which is a pointer to the cursor. */
119911 sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
119912 }else if( iCol==p->nColumn+2 && pCsr->pExpr ){
119913 sqlite3_result_int64(pCtx, pCsr->iLangid);
119914 }else{
119915 /* The requested column is either a user column (one that contains
119916 ** indexed data), or the language-id column. */
119917 rc = fts3CursorSeek(0, pCsr);
119918
119919 if( rc==SQLITE_OK ){
119920 if( iCol==p->nColumn+2 ){
119921 int iLangid = 0;
119922 if( p->zLanguageid ){
119923 iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
119924 }
119925 sqlite3_result_int(pCtx, iLangid);
119926 }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
119927 sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
119928 }
119929 }
119930 }
119931
119932 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
119933 return rc;
@@ -119509,26 +119950,61 @@
119950 /*
119951 ** Implementation of xSync() method. Flush the contents of the pending-terms
119952 ** hash-table to the database.
119953 */
119954 static int fts3SyncMethod(sqlite3_vtab *pVtab){
119955
119956 /* Following an incremental-merge operation, assuming that the input
119957 ** segments are not completely consumed (the usual case), they are updated
119958 ** in place to remove the entries that have already been merged. This
119959 ** involves updating the leaf block that contains the smallest unmerged
119960 ** entry and each block (if any) between the leaf and the root node. So
119961 ** if the height of the input segment b-trees is N, and input segments
119962 ** are merged eight at a time, updating the input segments at the end
119963 ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually
119964 ** small - often between 0 and 2. So the overhead of the incremental
119965 ** merge is somewhere between 8 and 24 blocks. To avoid this overhead
119966 ** dwarfing the actual productive work accomplished, the incremental merge
119967 ** is only attempted if it will write at least 64 leaf blocks. Hence
119968 ** nMinMerge.
119969 **
119970 ** Of course, updating the input segments also involves deleting a bunch
119971 ** of blocks from the segments table. But this is not considered overhead
119972 ** as it would also be required by a crisis-merge that used the same input
119973 ** segments.
119974 */
119975 const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
119976
119977 Fts3Table *p = (Fts3Table*)pVtab;
119978 int rc = sqlite3Fts3PendingTermsFlush(p);
119979
119980 if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
119981 int mxLevel = 0; /* Maximum relative level value in db */
119982 int A; /* Incr-merge parameter A */
119983
119984 rc = sqlite3Fts3MaxLevel(p, &mxLevel);
119985 assert( rc==SQLITE_OK || mxLevel==0 );
119986 A = p->nLeafAdd * mxLevel;
119987 A += (A/2);
119988 if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
119989 }
119990 sqlite3Fts3SegmentsClose(p);
119991 return rc;
119992 }
119993
119994 /*
119995 ** Implementation of xBegin() method. This is a no-op.
119996 */
119997 static int fts3BeginMethod(sqlite3_vtab *pVtab){
119998 Fts3Table *p = (Fts3Table*)pVtab;
119999 UNUSED_PARAMETER(pVtab);
120000 assert( p->pSegments==0 );
120001 assert( p->nPendingData==0 );
120002 assert( p->inTransaction!=1 );
120003 TESTONLY( p->inTransaction = 1 );
120004 TESTONLY( p->mxSavepoint = -1; );
120005 p->nLeafAdd = 0;
120006 return SQLITE_OK;
120007 }
120008
120009 /*
120010 ** Implementation of xCommit() method. This is a no-op. The contents of
@@ -119819,15 +120295,19 @@
120295 ** The xSavepoint() method.
120296 **
120297 ** Flush the contents of the pending-terms table to disk.
120298 */
120299 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
120300 int rc = SQLITE_OK;
120301 UNUSED_PARAMETER(iSavepoint);
120302 assert( ((Fts3Table *)pVtab)->inTransaction );
120303 assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
120304 TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
120305 if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){
120306 rc = fts3SyncMethod(pVtab);
120307 }
120308 return rc;
120309 }
120310
120311 /*
120312 ** The xRelease() method.
120313 **
@@ -120183,11 +120663,11 @@
120663
120664 assert( iPrev>=0 );
120665 fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
120666 sqlite3_free(aPoslist);
120667 aPoslist = pList;
120668 nPoslist = (int)(aOut - aPoslist);
120669 if( nPoslist==0 ){
120670 sqlite3_free(aPoslist);
120671 pPhrase->doclist.pList = 0;
120672 pPhrase->doclist.nList = 0;
120673 return SQLITE_OK;
@@ -120227,11 +120707,11 @@
120707 }
120708
120709 pPhrase->doclist.pList = aOut;
120710 if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
120711 pPhrase->doclist.bFreeList = 1;
120712 pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
120713 }else{
120714 sqlite3_free(aOut);
120715 pPhrase->doclist.pList = 0;
120716 pPhrase->doclist.nList = 0;
120717 }
@@ -120323,11 +120803,11 @@
120803 fts3PoslistCopy(0, &pDocid);
120804 while( pDocid<pEnd && *pDocid==0 ) pDocid++;
120805 iMul = (bDescIdx ? -1 : 1);
120806 }
120807
120808 *pnList = (int)(pEnd - pNext);
120809 *ppIter = pNext;
120810 *piDocid = iDocid;
120811 }else{
120812 int iMul = (bDescIdx ? -1 : 1);
120813 sqlite3_int64 iDelta;
@@ -120337,11 +120817,11 @@
120817 if( p==aDoclist ){
120818 *pbEof = 1;
120819 }else{
120820 char *pSave = p;
120821 fts3ReversePoslist(aDoclist, &p);
120822 *pnList = (int)(pSave - p);
120823 }
120824 *ppIter = p;
120825 }
120826 }
120827
@@ -120397,11 +120877,11 @@
120877 }else{
120878 pDL->iDocid -= iDelta;
120879 }
120880 pDL->pList = pIter;
120881 fts3PoslistCopy(0, &pIter);
120882 pDL->nList = (int)(pIter - pDL->pList);
120883
120884 /* pIter now points just past the 0x00 that terminates the position-
120885 ** list for document pDL->iDocid. However, if this position-list was
120886 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
120887 ** point to the start of the next docid value. The following line deals
@@ -120738,11 +121218,11 @@
121218
121219 /* Allocate a MultiSegReader for each token in the expression. */
121220 fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
121221
121222 /* Determine which, if any, tokens in the expression should be deferred. */
121223 if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
121224 Fts3TokenAndCost *aTC;
121225 Fts3Expr **apOr;
121226 aTC = (Fts3TokenAndCost *)sqlite3_malloc(
121227 sizeof(Fts3TokenAndCost) * nToken
121228 + sizeof(Fts3Expr *) * nOr * 2
@@ -120755,12 +121235,12 @@
121235 int ii;
121236 Fts3TokenAndCost *pTC = aTC;
121237 Fts3Expr **ppOr = apOr;
121238
121239 fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
121240 nToken = (int)(pTC-aTC);
121241 nOr = (int)(ppOr-apOr);
121242
121243 if( rc==SQLITE_OK ){
121244 rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
121245 for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
121246 rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
@@ -120828,11 +121308,11 @@
121308 p2 = pOut = pPhrase->doclist.pList;
121309 res = fts3PoslistNearMerge(
121310 &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
121311 );
121312 if( res ){
121313 nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
121314 assert( pPhrase->doclist.pList[nNew]=='\0' );
121315 assert( nNew<=pPhrase->doclist.nList && nNew>0 );
121316 memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
121317 pPhrase->doclist.nList = nNew;
121318 *paPoslist = pPhrase->doclist.pList;
@@ -121553,10 +122033,11 @@
122033 fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
122034 pPhrase->aToken[i].pSegcsr = 0;
122035 }
122036 }
122037 }
122038
122039
122040 /*
122041 ** Return SQLITE_CORRUPT_VTAB.
122042 */
122043 #ifdef SQLITE_DEBUG
@@ -121661,13 +122142,13 @@
122142 );
122143 return SQLITE_ERROR;
122144 }
122145
122146 zDb = argv[1];
122147 nDb = (int)strlen(zDb);
122148 zFts3 = argv[3];
122149 nFts3 = (int)strlen(zFts3);
122150
122151 rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
122152 if( rc!=SQLITE_OK ) return rc;
122153
122154 nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
@@ -121958,11 +122439,11 @@
122439 pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
122440 pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
122441 if( pCsr->zStop==0 ) return SQLITE_NOMEM;
122442 }
122443
122444 rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
122445 pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
122446 );
122447 if( rc==SQLITE_OK ){
122448 rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
122449 }
@@ -122150,10 +122631,11 @@
122631 ** zero.
122632 */
122633 typedef struct ParseContext ParseContext;
122634 struct ParseContext {
122635 sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
122636 int iLangid; /* Language id used with tokenizer */
122637 const char **azCol; /* Array of column names for fts3 table */
122638 int bFts4; /* True to allow FTS4-only syntax */
122639 int nCol; /* Number of entries in azCol[] */
122640 int iDefaultCol; /* Default column to query */
122641 int isNot; /* True if getNextNode() sees a unary - */
@@ -122185,10 +122667,37 @@
122667 void *pRet = sqlite3_malloc(nByte);
122668 if( pRet ) memset(pRet, 0, nByte);
122669 return pRet;
122670 }
122671
122672 SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
122673 sqlite3_tokenizer *pTokenizer,
122674 int iLangid,
122675 const char *z,
122676 int n,
122677 sqlite3_tokenizer_cursor **ppCsr
122678 ){
122679 sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
122680 sqlite3_tokenizer_cursor *pCsr = 0;
122681 int rc;
122682
122683 rc = pModule->xOpen(pTokenizer, z, n, &pCsr);
122684 assert( rc==SQLITE_OK || pCsr==0 );
122685 if( rc==SQLITE_OK ){
122686 pCsr->pTokenizer = pTokenizer;
122687 if( pModule->iVersion>=1 ){
122688 rc = pModule->xLanguageid(pCsr, iLangid);
122689 if( rc!=SQLITE_OK ){
122690 pModule->xClose(pCsr);
122691 pCsr = 0;
122692 }
122693 }
122694 }
122695 *ppCsr = pCsr;
122696 return rc;
122697 }
122698
122699
122700 /*
122701 ** Extract the next token from buffer z (length n) using the tokenizer
122702 ** and other information (column names etc.) in pParse. Create an Fts3Expr
122703 ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -122212,19 +122721,17 @@
122721 int rc;
122722 sqlite3_tokenizer_cursor *pCursor;
122723 Fts3Expr *pRet = 0;
122724 int nConsumed = 0;
122725
122726 rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
122727 if( rc==SQLITE_OK ){
122728 const char *zToken;
122729 int nToken, iStart, iEnd, iPosition;
122730 int nByte; /* total space to allocate */
122731
 
122732 rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
 
122733 if( rc==SQLITE_OK ){
122734 nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
122735 pRet = (Fts3Expr *)fts3MallocZero(nByte);
122736 if( !pRet ){
122737 rc = SQLITE_NOMEM;
@@ -122326,14 +122833,14 @@
122833 **
122834 ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
122835 ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
122836 ** structures.
122837 */
122838 rc = sqlite3Fts3OpenTokenizer(
122839 pTokenizer, pParse->iLangid, zInput, nInput, &pCursor);
122840 if( rc==SQLITE_OK ){
122841 int ii;
 
122842 for(ii=0; rc==SQLITE_OK; ii++){
122843 const char *zByte;
122844 int nByte, iBegin, iEnd, iPos;
122845 rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
122846 if( rc==SQLITE_OK ){
@@ -122803,10 +123310,11 @@
123310 ** specified as part of the query string), or -1 if tokens may by default
123311 ** match any table column.
123312 */
123313 SQLITE_PRIVATE int sqlite3Fts3ExprParse(
123314 sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
123315 int iLangid, /* Language id for tokenizer */
123316 char **azCol, /* Array of column names for fts3 table */
123317 int bFts4, /* True to allow FTS4-only syntax */
123318 int nCol, /* Number of entries in azCol[] */
123319 int iDefaultCol, /* Default column to query */
123320 const char *z, int n, /* Text of MATCH query */
@@ -122813,15 +123321,17 @@
123321 Fts3Expr **ppExpr /* OUT: Parsed query structure */
123322 ){
123323 int nParsed;
123324 int rc;
123325 ParseContext sParse;
123326
123327 memset(&sParse, 0, sizeof(ParseContext));
123328 sParse.pTokenizer = pTokenizer;
123329 sParse.iLangid = iLangid;
123330 sParse.azCol = (const char **)azCol;
123331 sParse.nCol = nCol;
123332 sParse.iDefaultCol = iDefaultCol;
 
123333 sParse.bFts4 = bFts4;
123334 if( z==0 ){
123335 *ppExpr = 0;
123336 return SQLITE_OK;
123337 }
@@ -123008,11 +123518,11 @@
123518 for(ii=0; ii<nCol; ii++){
123519 azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
123520 }
123521
123522 rc = sqlite3Fts3ExprParse(
123523 pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
123524 );
123525 if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
123526 sqlite3_result_error(context, "Error parsing expression", -1);
123527 }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
123528 sqlite3_result_error_nomem(context);
@@ -124057,10 +124567,11 @@
124567 porterCreate,
124568 porterDestroy,
124569 porterOpen,
124570 porterClose,
124571 porterNext,
124572 0
124573 };
124574
124575 /*
124576 ** Allocate a new porter tokenizer. Return a pointer to the new
124577 ** tokenizer in *ppModule
@@ -124362,15 +124873,14 @@
124873 if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
124874 zErr = "error in xCreate()";
124875 goto finish;
124876 }
124877 pTokenizer->pModule = p;
124878 if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){
124879 zErr = "error in xOpen()";
124880 goto finish;
124881 }
 
124882
124883 while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
124884 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
124885 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
124886 zToken = &zInput[iStart];
@@ -124782,10 +125292,11 @@
125292 simpleCreate,
125293 simpleDestroy,
125294 simpleOpen,
125295 simpleClose,
125296 simpleNext,
125297 0,
125298 };
125299
125300 /*
125301 ** Allocate a new simple tokenizer. Return a pointer to the new
125302 ** tokenizer in *ppModule
@@ -124823,10 +125334,13 @@
125334
125335 /* #include <string.h> */
125336 /* #include <assert.h> */
125337 /* #include <stdlib.h> */
125338
125339
125340 #define FTS_MAX_APPENDABLE_HEIGHT 16
125341
125342 /*
125343 ** When full-text index nodes are loaded from disk, the buffer that they
125344 ** are loaded into has the following number of bytes of padding at the end
125345 ** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
125346 ** of 920 bytes is allocated for it.
@@ -124861,10 +125375,33 @@
125375 # define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
125376 #else
125377 # define FTS3_NODE_CHUNKSIZE (4*1024)
125378 # define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
125379 #endif
125380
125381 /*
125382 ** The two values that may be meaningfully bound to the :1 parameter in
125383 ** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
125384 */
125385 #define FTS_STAT_DOCTOTAL 0
125386 #define FTS_STAT_INCRMERGEHINT 1
125387 #define FTS_STAT_AUTOINCRMERGE 2
125388
125389 /*
125390 ** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
125391 ** and incremental merge operation that takes place. This is used for
125392 ** debugging FTS only, it should not usually be turned on in production
125393 ** systems.
125394 */
125395 #ifdef FTS3_LOG_MERGES
125396 static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){
125397 sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel);
125398 }
125399 #else
125400 #define fts3LogMerge(x, y)
125401 #endif
125402
125403
125404 typedef struct PendingList PendingList;
125405 typedef struct SegmentNode SegmentNode;
125406 typedef struct SegmentWriter SegmentWriter;
125407
@@ -125023,17 +125560,26 @@
125560 #define SQL_DELETE_SEGMENTS_RANGE 17
125561 #define SQL_CONTENT_INSERT 18
125562 #define SQL_DELETE_DOCSIZE 19
125563 #define SQL_REPLACE_DOCSIZE 20
125564 #define SQL_SELECT_DOCSIZE 21
125565 #define SQL_SELECT_STAT 22
125566 #define SQL_REPLACE_STAT 23
125567
125568 #define SQL_SELECT_ALL_PREFIX_LEVEL 24
125569 #define SQL_DELETE_ALL_TERMS_SEGDIR 25
 
125570 #define SQL_DELETE_SEGDIR_RANGE 26
125571 #define SQL_SELECT_ALL_LANGID 27
125572 #define SQL_FIND_MERGE_LEVEL 28
125573 #define SQL_MAX_LEAF_NODE_ESTIMATE 29
125574 #define SQL_DELETE_SEGDIR_ENTRY 30
125575 #define SQL_SHIFT_SEGDIR_ENTRY 31
125576 #define SQL_SELECT_SEGDIR 32
125577 #define SQL_CHOMP_SEGDIR 33
125578 #define SQL_SEGMENT_IS_APPENDABLE 34
125579 #define SQL_SELECT_INDEXES 35
125580 #define SQL_SELECT_MXLEVEL 36
125581
125582 /*
125583 ** This function is used to obtain an SQLite prepared statement handle
125584 ** for the statement identified by the second argument. If successful,
125585 ** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -125058,13 +125604,13 @@
125604 /* 4 */ "DELETE FROM %Q.'%q_segdir'",
125605 /* 5 */ "DELETE FROM %Q.'%q_docsize'",
125606 /* 6 */ "DELETE FROM %Q.'%q_stat'",
125607 /* 7 */ "SELECT %s WHERE rowid=?",
125608 /* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
125609 /* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
125610 /* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
125611 /* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
125612
125613 /* Return segments in order from oldest to newest.*/
125614 /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
125615 "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
125616 /* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
@@ -125078,17 +125624,65 @@
125624 /* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
125625 /* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
125626 /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
125627 /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
125628 /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
125629 /* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?",
125630 /* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)",
125631 /* 24 */ "",
125632 /* 25 */ "",
125633
125634 /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
125635 /* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
125636
125637 /* This statement is used to determine which level to read the input from
125638 ** when performing an incremental merge. It returns the absolute level number
125639 ** of the oldest level in the db that contains at least ? segments. Or,
125640 ** if no level in the FTS index contains more than ? segments, the statement
125641 ** returns zero rows. */
125642 /* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?"
125643 " ORDER BY (level %% 1024) ASC LIMIT 1",
125644
125645 /* Estimate the upper limit on the number of leaf nodes in a new segment
125646 ** created by merging the oldest :2 segments from absolute level :1. See
125647 ** function sqlite3Fts3Incrmerge() for details. */
125648 /* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
125649 " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
125650
125651 /* SQL_DELETE_SEGDIR_ENTRY
125652 ** Delete the %_segdir entry on absolute level :1 with index :2. */
125653 /* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
125654
125655 /* SQL_SHIFT_SEGDIR_ENTRY
125656 ** Modify the idx value for the segment with idx=:3 on absolute level :2
125657 ** to :1. */
125658 /* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?",
125659
125660 /* SQL_SELECT_SEGDIR
125661 ** Read a single entry from the %_segdir table. The entry from absolute
125662 ** level :1 with index value :2. */
125663 /* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
125664 "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
125665
125666 /* SQL_CHOMP_SEGDIR
125667 ** Update the start_block (:1) and root (:2) fields of the %_segdir
125668 ** entry located on absolute level :3 with index :4. */
125669 /* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?"
125670 "WHERE level = ? AND idx = ?",
125671
125672 /* SQL_SEGMENT_IS_APPENDABLE
125673 ** Return a single row if the segment with end_block=? is appendable. Or
125674 ** no rows otherwise. */
125675 /* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL",
125676
125677 /* SQL_SELECT_INDEXES
125678 ** Return the list of valid segment indexes for absolute level ? */
125679 /* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC",
125680
125681 /* SQL_SELECT_MXLEVEL
125682 ** Return the largest relative level in the FTS index or indexes. */
125683 /* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
125684 };
125685 int rc = SQLITE_OK;
125686 sqlite3_stmt *pStmt;
125687
125688 assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
@@ -125121,27 +125715,23 @@
125715 }
125716 }
125717 *pp = pStmt;
125718 return rc;
125719 }
125720
125721
125722 static int fts3SelectDocsize(
125723 Fts3Table *pTab, /* FTS3 table handle */
 
125724 sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */
125725 sqlite3_stmt **ppStmt /* OUT: Statement handle */
125726 ){
125727 sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */
125728 int rc; /* Return code */
125729
125730 rc = fts3SqlStmt(pTab, SQL_SELECT_DOCSIZE, &pStmt, 0);
 
 
125731 if( rc==SQLITE_OK ){
125732 sqlite3_bind_int64(pStmt, 1, iDocid);
 
 
125733 rc = sqlite3_step(pStmt);
125734 if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
125735 rc = sqlite3_reset(pStmt);
125736 if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
125737 pStmt = 0;
@@ -125156,19 +125746,33 @@
125746
125747 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(
125748 Fts3Table *pTab, /* Fts3 table handle */
125749 sqlite3_stmt **ppStmt /* OUT: Statement handle */
125750 ){
125751 sqlite3_stmt *pStmt = 0;
125752 int rc;
125753 rc = fts3SqlStmt(pTab, SQL_SELECT_STAT, &pStmt, 0);
125754 if( rc==SQLITE_OK ){
125755 sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
125756 if( sqlite3_step(pStmt)!=SQLITE_ROW
125757 || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB
125758 ){
125759 rc = sqlite3_reset(pStmt);
125760 if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
125761 pStmt = 0;
125762 }
125763 }
125764 *ppStmt = pStmt;
125765 return rc;
125766 }
125767
125768 SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(
125769 Fts3Table *pTab, /* Fts3 table handle */
125770 sqlite3_int64 iDocid, /* Docid to read size data for */
125771 sqlite3_stmt **ppStmt /* OUT: Statement handle */
125772 ){
125773 return fts3SelectDocsize(pTab, iDocid, ppStmt);
125774 }
125775
125776 /*
125777 ** Similar to fts3SqlStmt(). Except, after binding the parameters in
125778 ** array apVal[] to the SQL statement identified by eStmt, the statement
@@ -125229,10 +125833,48 @@
125833 rc = SQLITE_OK;
125834 }
125835
125836 return rc;
125837 }
125838
125839 /*
125840 ** FTS maintains a separate indexes for each language-id (a 32-bit integer).
125841 ** Within each language id, a separate index is maintained to store the
125842 ** document terms, and each configured prefix size (configured the FTS
125843 ** "prefix=" option). And each index consists of multiple levels ("relative
125844 ** levels").
125845 **
125846 ** All three of these values (the language id, the specific index and the
125847 ** level within the index) are encoded in 64-bit integer values stored
125848 ** in the %_segdir table on disk. This function is used to convert three
125849 ** separate component values into the single 64-bit integer value that
125850 ** can be used to query the %_segdir table.
125851 **
125852 ** Specifically, each language-id/index combination is allocated 1024
125853 ** 64-bit integer level values ("absolute levels"). The main terms index
125854 ** for language-id 0 is allocate values 0-1023. The first prefix index
125855 ** (if any) for language-id 0 is allocated values 1024-2047. And so on.
125856 ** Language 1 indexes are allocated immediately following language 0.
125857 **
125858 ** So, for a system with nPrefix prefix indexes configured, the block of
125859 ** absolute levels that corresponds to language-id iLangid and index
125860 ** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024).
125861 */
125862 static sqlite3_int64 getAbsoluteLevel(
125863 Fts3Table *p, /* FTS3 table handle */
125864 int iLangid, /* Language id */
125865 int iIndex, /* Index in p->aIndex[] */
125866 int iLevel /* Level of segments */
125867 ){
125868 sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
125869 assert( iLangid>=0 );
125870 assert( p->nIndex>0 );
125871 assert( iIndex>=0 && iIndex<p->nIndex );
125872
125873 iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL;
125874 return iBase + iLevel;
125875 }
125876
125877 /*
125878 ** Set *ppStmt to a statement handle that may be used to iterate through
125879 ** all rows in the %_segdir table, from oldest to newest. If successful,
125880 ** return SQLITE_OK. If an error occurs while preparing the statement,
@@ -125249,12 +125891,13 @@
125891 ** 3: end_block
125892 ** 4: root
125893 */
125894 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
125895 Fts3Table *p, /* FTS3 table */
125896 int iLangid, /* Language being queried */
125897 int iIndex, /* Index for p->aIndex[] */
125898 int iLevel, /* Level to select (relative level) */
125899 sqlite3_stmt **ppStmt /* OUT: Compiled statement */
125900 ){
125901 int rc;
125902 sqlite3_stmt *pStmt = 0;
125903
@@ -125264,18 +125907,20 @@
125907
125908 if( iLevel<0 ){
125909 /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
125910 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
125911 if( rc==SQLITE_OK ){
125912 sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
125913 sqlite3_bind_int64(pStmt, 2,
125914 getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
125915 );
125916 }
125917 }else{
125918 /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
125919 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
125920 if( rc==SQLITE_OK ){
125921 sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel));
125922 }
125923 }
125924 *ppStmt = pStmt;
125925 return rc;
125926 }
@@ -125437,10 +126082,11 @@
126082 **
126083 ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
126084 */
126085 static int fts3PendingTermsAdd(
126086 Fts3Table *p, /* Table into which text will be inserted */
126087 int iLangid, /* Language id to use */
126088 const char *zText, /* Text of document to be inserted */
126089 int iCol, /* Column into which text is being inserted */
126090 u32 *pnWord /* OUT: Number of tokens inserted */
126091 ){
126092 int rc;
@@ -125466,15 +126112,14 @@
126112 if( zText==0 ){
126113 *pnWord = 0;
126114 return SQLITE_OK;
126115 }
126116
126117 rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr);
126118 if( rc!=SQLITE_OK ){
126119 return rc;
126120 }
 
126121
126122 xNext = pModule->xNext;
126123 while( SQLITE_OK==rc
126124 && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
126125 ){
@@ -125513,22 +126158,32 @@
126158 /*
126159 ** Calling this function indicates that subsequent calls to
126160 ** fts3PendingTermsAdd() are to add term/position-list pairs for the
126161 ** contents of the document with docid iDocid.
126162 */
126163 static int fts3PendingTermsDocid(
126164 Fts3Table *p, /* Full-text table handle */
126165 int iLangid, /* Language id of row being written */
126166 sqlite_int64 iDocid /* Docid of row being written */
126167 ){
126168 assert( iLangid>=0 );
126169
126170 /* TODO(shess) Explore whether partially flushing the buffer on
126171 ** forced-flush would provide better performance. I suspect that if
126172 ** we ordered the doclists by size and flushed the largest until the
126173 ** buffer was half empty, that would let the less frequent terms
126174 ** generate longer doclists.
126175 */
126176 if( iDocid<=p->iPrevDocid
126177 || p->iPrevLangid!=iLangid
126178 || p->nPendingData>p->nMaxPendingData
126179 ){
126180 int rc = sqlite3Fts3PendingTermsFlush(p);
126181 if( rc!=SQLITE_OK ) return rc;
126182 }
126183 p->iPrevDocid = iDocid;
126184 p->iPrevLangid = iLangid;
126185 return SQLITE_OK;
126186 }
126187
126188 /*
126189 ** Discard the contents of the pending-terms hash tables.
@@ -125553,15 +126208,20 @@
126208 ** pendingTerms hash table.
126209 **
126210 ** Argument apVal is the same as the similarly named argument passed to
126211 ** fts3InsertData(). Parameter iDocid is the docid of the new row.
126212 */
126213 static int fts3InsertTerms(
126214 Fts3Table *p,
126215 int iLangid,
126216 sqlite3_value **apVal,
126217 u32 *aSz
126218 ){
126219 int i; /* Iterator variable */
126220 for(i=2; i<p->nColumn+2; i++){
126221 const char *zText = (const char *)sqlite3_value_text(apVal[i]);
126222 int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
126223 if( rc!=SQLITE_OK ){
126224 return rc;
126225 }
126226 aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
126227 }
@@ -125578,10 +126238,11 @@
126238 ** apVal[2] Left-most user-defined column
126239 ** ...
126240 ** apVal[p->nColumn+1] Right-most user-defined column
126241 ** apVal[p->nColumn+2] Hidden column with same name as table
126242 ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid)
126243 ** apVal[p->nColumn+4] Hidden languageid column
126244 */
126245 static int fts3InsertData(
126246 Fts3Table *p, /* Full-text table */
126247 sqlite3_value **apVal, /* Array of values to insert */
126248 sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */
@@ -125608,13 +126269,17 @@
126269 **
126270 ** The statement features N '?' variables, where N is the number of user
126271 ** defined columns in the FTS3 table, plus one for the docid field.
126272 */
126273 rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
126274 if( rc==SQLITE_OK && p->zLanguageid ){
126275 rc = sqlite3_bind_int(
126276 pContentInsert, p->nColumn+2,
126277 sqlite3_value_int(apVal[p->nColumn+4])
126278 );
126279 }
126280 if( rc!=SQLITE_OK ) return rc;
126281
126282 /* There is a quirk here. The users INSERT statement may have specified
126283 ** a value for the "rowid" field, for the "docid" field, or for both.
126284 ** Which is a problem, since "rowid" and "docid" are aliases for the
126285 ** same value. For example:
@@ -125669,10 +126334,19 @@
126334 if( p->bHasStat ){
126335 fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
126336 }
126337 return rc;
126338 }
126339
126340 /*
126341 **
126342 */
126343 static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){
126344 int iLangid = 0;
126345 if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1);
126346 return iLangid;
126347 }
126348
126349 /*
126350 ** The first element in the apVal[] array is assumed to contain the docid
126351 ** (an integer) of a row about to be deleted. Remove all terms from the
126352 ** full-text index.
@@ -125689,19 +126363,21 @@
126363 if( *pRC ) return;
126364 rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
126365 if( rc==SQLITE_OK ){
126366 if( SQLITE_ROW==sqlite3_step(pSelect) ){
126367 int i;
126368 int iLangid = langidFromSelect(p, pSelect);
126369 rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
126370 for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
126371 const char *zText = (const char *)sqlite3_column_text(pSelect, i);
126372 rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
 
 
 
 
 
126373 aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
126374 }
126375 if( rc!=SQLITE_OK ){
126376 sqlite3_reset(pSelect);
126377 *pRC = rc;
126378 return;
126379 }
126380 }
126381 rc = sqlite3_reset(pSelect);
126382 }else{
126383 sqlite3_reset(pSelect);
@@ -125711,11 +126387,11 @@
126387
126388 /*
126389 ** Forward declaration to account for the circular dependency between
126390 ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
126391 */
126392 static int fts3SegmentMerge(Fts3Table *, int, int, int);
126393
126394 /*
126395 ** This function allocates a new level iLevel index in the segdir table.
126396 ** Usually, indexes are allocated within a level sequentially starting
126397 ** with 0, so the allocated index is one greater than the value returned
@@ -125730,22 +126406,28 @@
126406 ** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
126407 ** returned. Otherwise, an SQLite error code is returned.
126408 */
126409 static int fts3AllocateSegdirIdx(
126410 Fts3Table *p,
126411 int iLangid, /* Language id */
126412 int iIndex, /* Index for p->aIndex */
126413 int iLevel,
126414 int *piIdx
126415 ){
126416 int rc; /* Return Code */
126417 sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
126418 int iNext = 0; /* Result of query pNextIdx */
126419
126420 assert( iLangid>=0 );
126421 assert( p->nIndex>=1 );
126422
126423 /* Set variable iNext to the next available segdir index at level iLevel. */
126424 rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
126425 if( rc==SQLITE_OK ){
126426 sqlite3_bind_int64(
126427 pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
126428 );
126429 if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
126430 iNext = sqlite3_column_int(pNextIdx, 0);
126431 }
126432 rc = sqlite3_reset(pNextIdx);
126433 }
@@ -125755,11 +126437,12 @@
126437 ** full, merge all segments in level iLevel into a single iLevel+1
126438 ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
126439 ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
126440 */
126441 if( iNext>=FTS3_MERGE_COUNT ){
126442 fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
126443 rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
126444 *piIdx = 0;
126445 }else{
126446 *piIdx = iNext;
126447 }
126448 }
@@ -125802,11 +126485,11 @@
126485 int *pnLoad /* OUT: Bytes actually loaded */
126486 ){
126487 int rc; /* Return code */
126488
126489 /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
126490 assert( pnBlob );
126491
126492 if( p->pSegments ){
126493 rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
126494 }else{
126495 if( 0==p->zSegmentsTbl ){
@@ -126143,11 +126826,11 @@
126826 int nOvfl = 0;
126827 int ii;
126828 int rc = SQLITE_OK;
126829 int pgsz = p->nPgsz;
126830
126831 assert( p->bFts4 );
126832 assert( pgsz>0 );
126833
126834 for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
126835 Fts3SegReader *pReader = pMsr->apSegment[ii];
126836 if( !fts3SegReaderIsPending(pReader)
@@ -126500,17 +127183,38 @@
127183 sqlite3_step(pStmt);
127184 rc = sqlite3_reset(pStmt);
127185 }
127186 return rc;
127187 }
127188
127189 /*
127190 ** Find the largest relative level number in the table. If successful, set
127191 ** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs,
127192 ** set *pnMax to zero and return an SQLite error code.
127193 */
127194 SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){
127195 int rc;
127196 int mxLevel = 0;
127197 sqlite3_stmt *pStmt = 0;
127198
127199 rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0);
127200 if( rc==SQLITE_OK ){
127201 if( SQLITE_ROW==sqlite3_step(pStmt) ){
127202 mxLevel = sqlite3_column_int(pStmt, 0);
127203 }
127204 rc = sqlite3_reset(pStmt);
127205 }
127206 *pnMax = mxLevel;
127207 return rc;
127208 }
127209
127210 /*
127211 ** Insert a record into the %_segdir table.
127212 */
127213 static int fts3WriteSegdir(
127214 Fts3Table *p, /* Virtual table handle */
127215 sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */
127216 int iIdx, /* Value for "idx" field */
127217 sqlite3_int64 iStartBlock, /* Value for "start_block" field */
127218 sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
127219 sqlite3_int64 iEndBlock, /* Value for "end_block" field */
127220 char *zRoot, /* Blob value for "root" field */
@@ -126517,11 +127221,11 @@
127221 int nRoot /* Number of bytes in buffer zRoot */
127222 ){
127223 sqlite3_stmt *pStmt;
127224 int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0);
127225 if( rc==SQLITE_OK ){
127226 sqlite3_bind_int64(pStmt, 1, iLevel);
127227 sqlite3_bind_int(pStmt, 2, iIdx);
127228 sqlite3_bind_int64(pStmt, 3, iStartBlock);
127229 sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
127230 sqlite3_bind_int64(pStmt, 5, iEndBlock);
127231 sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
@@ -126817,10 +127521,11 @@
127521 int rc;
127522
127523 /* The current leaf node is full. Write it out to the database. */
127524 rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
127525 if( rc!=SQLITE_OK ) return rc;
127526 p->nLeafAdd++;
127527
127528 /* Add the current term to the interior node tree. The term added to
127529 ** the interior tree must:
127530 **
127531 ** a) be greater than the largest term on the leaf node just written
@@ -126900,11 +127605,11 @@
127605 ** returned. Otherwise, an SQLite error code.
127606 */
127607 static int fts3SegWriterFlush(
127608 Fts3Table *p, /* Virtual table handle */
127609 SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
127610 sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */
127611 int iIdx /* Value for 'idx' column of %_segdir */
127612 ){
127613 int rc; /* Return code */
127614 if( pWriter->pTree ){
127615 sqlite3_int64 iLast = 0; /* Largest block id written to database */
@@ -126925,10 +127630,11 @@
127630 }else{
127631 /* The entire tree fits on the root node. Write it to the segdir table. */
127632 rc = fts3WriteSegdir(
127633 p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
127634 }
127635 p->nLeafAdd++;
127636 return rc;
127637 }
127638
127639 /*
127640 ** Release all memory held by the SegmentWriter object passed as the
@@ -126978,11 +127684,16 @@
127684 **
127685 ** Segment levels are stored in the 'level' column of the %_segdir table.
127686 **
127687 ** Return SQLITE_OK if successful, or an SQLite error code if not.
127688 */
127689 static int fts3SegmentMaxLevel(
127690 Fts3Table *p,
127691 int iLangid,
127692 int iIndex,
127693 sqlite3_int64 *pnMax
127694 ){
127695 sqlite3_stmt *pStmt;
127696 int rc;
127697 assert( iIndex>=0 && iIndex<p->nIndex );
127698
127699 /* Set pStmt to the compiled version of:
@@ -126991,17 +127702,42 @@
127702 **
127703 ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
127704 */
127705 rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
127706 if( rc!=SQLITE_OK ) return rc;
127707 sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
127708 sqlite3_bind_int64(pStmt, 2,
127709 getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
127710 );
127711 if( SQLITE_ROW==sqlite3_step(pStmt) ){
127712 *pnMax = sqlite3_column_int64(pStmt, 0);
127713 }
127714 return sqlite3_reset(pStmt);
127715 }
127716
127717 /*
127718 ** Delete all entries in the %_segments table associated with the segment
127719 ** opened with seg-reader pSeg. This function does not affect the contents
127720 ** of the %_segdir table.
127721 */
127722 static int fts3DeleteSegment(
127723 Fts3Table *p, /* FTS table handle */
127724 Fts3SegReader *pSeg /* Segment to delete */
127725 ){
127726 int rc = SQLITE_OK; /* Return code */
127727 if( pSeg->iStartBlock ){
127728 sqlite3_stmt *pDelete; /* SQL statement to delete rows */
127729 rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
127730 if( rc==SQLITE_OK ){
127731 sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock);
127732 sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock);
127733 sqlite3_step(pDelete);
127734 rc = sqlite3_reset(pDelete);
127735 }
127736 }
127737 return rc;
127738 }
127739
127740 /*
127741 ** This function is used after merging multiple segments into a single large
127742 ** segment to delete the old, now redundant, segment b-trees. Specifically,
127743 ** it:
@@ -127015,44 +127751,42 @@
127751 **
127752 ** SQLITE_OK is returned if successful, otherwise an SQLite error code.
127753 */
127754 static int fts3DeleteSegdir(
127755 Fts3Table *p, /* Virtual table handle */
127756 int iLangid, /* Language id */
127757 int iIndex, /* Index for p->aIndex */
127758 int iLevel, /* Level of %_segdir entries to delete */
127759 Fts3SegReader **apSegment, /* Array of SegReader objects */
127760 int nReader /* Size of array apSegment */
127761 ){
127762 int rc = SQLITE_OK; /* Return Code */
127763 int i; /* Iterator variable */
127764 sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */
127765
 
127766 for(i=0; rc==SQLITE_OK && i<nReader; i++){
127767 rc = fts3DeleteSegment(p, apSegment[i]);
 
 
 
 
 
 
127768 }
127769 if( rc!=SQLITE_OK ){
127770 return rc;
127771 }
127772
127773 assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
127774 if( iLevel==FTS3_SEGCURSOR_ALL ){
127775 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
127776 if( rc==SQLITE_OK ){
127777 sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
127778 sqlite3_bind_int64(pDelete, 2,
127779 getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
127780 );
127781 }
127782 }else{
127783 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
127784 if( rc==SQLITE_OK ){
127785 sqlite3_bind_int64(
127786 pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
127787 );
127788 }
127789 }
127790
127791 if( rc==SQLITE_OK ){
127792 sqlite3_step(pDelete);
@@ -127517,27 +128251,32 @@
128251 ** If this function is called with iLevel<0, but there is only one
128252 ** segment in the database, SQLITE_DONE is returned immediately.
128253 ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
128254 ** an SQLite error code is returned.
128255 */
128256 static int fts3SegmentMerge(
128257 Fts3Table *p,
128258 int iLangid, /* Language id to merge */
128259 int iIndex, /* Index in p->aIndex[] to merge */
128260 int iLevel /* Level to merge */
128261 ){
128262 int rc; /* Return code */
128263 int iIdx = 0; /* Index of new segment */
128264 sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */
128265 SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
128266 Fts3SegFilter filter; /* Segment term filter condition */
128267 Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
128268 int bIgnoreEmpty = 0; /* True to ignore empty segments */
128269
128270 assert( iLevel==FTS3_SEGCURSOR_ALL
128271 || iLevel==FTS3_SEGCURSOR_PENDING
128272 || iLevel>=0
128273 );
128274 assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
128275 assert( iIndex>=0 && iIndex<p->nIndex );
128276
128277 rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
128278 if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
128279
128280 if( iLevel==FTS3_SEGCURSOR_ALL ){
128281 /* This call is to merge all segments in the database to a single
128282 ** segment. The level of the new segment is equal to the the numerically
@@ -127545,28 +128284,28 @@
128284 ** index. The idx of the new segment is always 0. */
128285 if( csr.nSegment==1 ){
128286 rc = SQLITE_DONE;
128287 goto finished;
128288 }
128289 rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
128290 bIgnoreEmpty = 1;
128291
128292 }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
128293 iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
128294 rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
128295 }else{
128296 /* This call is to merge all segments at level iLevel. find the next
128297 ** available segment index at level iLevel+1. The call to
128298 ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
128299 ** a single iLevel+2 segment if necessary. */
128300 rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
128301 iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
128302 }
128303 if( rc!=SQLITE_OK ) goto finished;
128304 assert( csr.nSegment>0 );
128305 assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
128306 assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
128307
128308 memset(&filter, 0, sizeof(Fts3SegFilter));
128309 filter.flags = FTS3_SEGMENT_REQUIRE_POS;
128310 filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
128311
@@ -127579,11 +128318,13 @@
128318 }
128319 if( rc!=SQLITE_OK ) goto finished;
128320 assert( pWriter );
128321
128322 if( iLevel!=FTS3_SEGCURSOR_PENDING ){
128323 rc = fts3DeleteSegdir(
128324 p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment
128325 );
128326 if( rc!=SQLITE_OK ) goto finished;
128327 }
128328 rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
128329
128330 finished:
@@ -127597,15 +128338,32 @@
128338 ** Flush the contents of pendingTerms to level 0 segments.
128339 */
128340 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
128341 int rc = SQLITE_OK;
128342 int i;
128343
128344 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
128345 rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
128346 if( rc==SQLITE_DONE ) rc = SQLITE_OK;
128347 }
128348 sqlite3Fts3PendingTermsClear(p);
128349
128350 /* Determine the auto-incr-merge setting if unknown. If enabled,
128351 ** estimate the number of leaf blocks of content to be written
128352 */
128353 if( rc==SQLITE_OK && p->bHasStat
128354 && p->bAutoincrmerge==0xff && p->nLeafAdd>0
128355 ){
128356 sqlite3_stmt *pStmt = 0;
128357 rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
128358 if( rc==SQLITE_OK ){
128359 sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
128360 rc = sqlite3_step(pStmt);
128361 p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
128362 rc = sqlite3_reset(pStmt);
128363 }
128364 }
128365 return rc;
128366 }
128367
128368 /*
128369 ** Encode N integers as varints into a blob.
@@ -127712,16 +128470,17 @@
128470 if( a==0 ){
128471 *pRC = SQLITE_NOMEM;
128472 return;
128473 }
128474 pBlob = (char*)&a[nStat];
128475 rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
128476 if( rc ){
128477 sqlite3_free(a);
128478 *pRC = rc;
128479 return;
128480 }
128481 sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
128482 if( sqlite3_step(pStmt)==SQLITE_ROW ){
128483 fts3DecodeIntArray(nStat, a,
128484 sqlite3_column_blob(pStmt, 0),
128485 sqlite3_column_bytes(pStmt, 0));
128486 }else{
@@ -127741,33 +128500,51 @@
128500 x = x + aSzIns[i] - aSzDel[i];
128501 }
128502 a[i+1] = x;
128503 }
128504 fts3EncodeIntArray(nStat, a, pBlob, &nBlob);
128505 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
128506 if( rc ){
128507 sqlite3_free(a);
128508 *pRC = rc;
128509 return;
128510 }
128511 sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
128512 sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
128513 sqlite3_step(pStmt);
128514 *pRC = sqlite3_reset(pStmt);
128515 sqlite3_free(a);
128516 }
128517
128518 /*
128519 ** Merge the entire database so that there is one segment for each
128520 ** iIndex/iLangid combination.
128521 */
128522 static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
 
128523 int bSeenDone = 0;
128524 int rc;
128525 sqlite3_stmt *pAllLangid = 0;
128526
128527 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
128528 if( rc==SQLITE_OK ){
128529 int rc2;
128530 sqlite3_bind_int(pAllLangid, 1, p->nIndex);
128531 while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
128532 int i;
128533 int iLangid = sqlite3_column_int(pAllLangid, 0);
128534 for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
128535 rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
128536 if( rc==SQLITE_DONE ){
128537 bSeenDone = 1;
128538 rc = SQLITE_OK;
128539 }
128540 }
128541 }
128542 rc2 = sqlite3_reset(pAllLangid);
128543 if( rc==SQLITE_OK ) rc = rc2;
128544 }
128545
128546 sqlite3Fts3SegmentsClose(p);
128547 sqlite3Fts3PendingTermsClear(p);
128548
128549 return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
128550 }
@@ -127814,15 +128591,16 @@
128591 }
128592 }
128593
128594 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
128595 int iCol;
128596 int iLangid = langidFromSelect(p, pStmt);
128597 rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
128598 aSz[p->nColumn] = 0;
128599 for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
128600 const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
128601 rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
128602 aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
128603 }
128604 if( p->bHasDocsize ){
128605 fts3InsertDocsize(&rc, p, aSz);
128606 }
@@ -127834,11 +128612,11 @@
128612 for(iCol=0; iCol<=p->nColumn; iCol++){
128613 aSzIns[iCol] += aSz[iCol];
128614 }
128615 }
128616 }
128617 if( p->bFts4 ){
128618 fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
128619 }
128620 sqlite3_free(aSz);
128621
128622 if( pStmt ){
@@ -127850,10 +128628,1692 @@
128628 }
128629
128630 return rc;
128631 }
128632
128633
128634 /*
128635 ** This function opens a cursor used to read the input data for an
128636 ** incremental merge operation. Specifically, it opens a cursor to scan
128637 ** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
128638 ** level iAbsLevel.
128639 */
128640 static int fts3IncrmergeCsr(
128641 Fts3Table *p, /* FTS3 table handle */
128642 sqlite3_int64 iAbsLevel, /* Absolute level to open */
128643 int nSeg, /* Number of segments to merge */
128644 Fts3MultiSegReader *pCsr /* Cursor object to populate */
128645 ){
128646 int rc; /* Return Code */
128647 sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
128648 int nByte; /* Bytes allocated at pCsr->apSegment[] */
128649
128650 /* Allocate space for the Fts3MultiSegReader.aCsr[] array */
128651 memset(pCsr, 0, sizeof(*pCsr));
128652 nByte = sizeof(Fts3SegReader *) * nSeg;
128653 pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
128654
128655 if( pCsr->apSegment==0 ){
128656 rc = SQLITE_NOMEM;
128657 }else{
128658 memset(pCsr->apSegment, 0, nByte);
128659 rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
128660 }
128661 if( rc==SQLITE_OK ){
128662 int i;
128663 int rc2;
128664 sqlite3_bind_int64(pStmt, 1, iAbsLevel);
128665 assert( pCsr->nSegment==0 );
128666 for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && i<nSeg; i++){
128667 rc = sqlite3Fts3SegReaderNew(i, 0,
128668 sqlite3_column_int64(pStmt, 1), /* segdir.start_block */
128669 sqlite3_column_int64(pStmt, 2), /* segdir.leaves_end_block */
128670 sqlite3_column_int64(pStmt, 3), /* segdir.end_block */
128671 sqlite3_column_blob(pStmt, 4), /* segdir.root */
128672 sqlite3_column_bytes(pStmt, 4), /* segdir.root */
128673 &pCsr->apSegment[i]
128674 );
128675 pCsr->nSegment++;
128676 }
128677 rc2 = sqlite3_reset(pStmt);
128678 if( rc==SQLITE_OK ) rc = rc2;
128679 }
128680
128681 return rc;
128682 }
128683
128684 typedef struct IncrmergeWriter IncrmergeWriter;
128685 typedef struct NodeWriter NodeWriter;
128686 typedef struct Blob Blob;
128687 typedef struct NodeReader NodeReader;
128688
128689 /*
128690 ** An instance of the following structure is used as a dynamic buffer
128691 ** to build up nodes or other blobs of data in.
128692 **
128693 ** The function blobGrowBuffer() is used to extend the allocation.
128694 */
128695 struct Blob {
128696 char *a; /* Pointer to allocation */
128697 int n; /* Number of valid bytes of data in a[] */
128698 int nAlloc; /* Allocated size of a[] (nAlloc>=n) */
128699 };
128700
128701 /*
128702 ** This structure is used to build up buffers containing segment b-tree
128703 ** nodes (blocks).
128704 */
128705 struct NodeWriter {
128706 sqlite3_int64 iBlock; /* Current block id */
128707 Blob key; /* Last key written to the current block */
128708 Blob block; /* Current block image */
128709 };
128710
128711 /*
128712 ** An object of this type contains the state required to create or append
128713 ** to an appendable b-tree segment.
128714 */
128715 struct IncrmergeWriter {
128716 int nLeafEst; /* Space allocated for leaf blocks */
128717 int nWork; /* Number of leaf pages flushed */
128718 sqlite3_int64 iAbsLevel; /* Absolute level of input segments */
128719 int iIdx; /* Index of *output* segment in iAbsLevel+1 */
128720 sqlite3_int64 iStart; /* Block number of first allocated block */
128721 sqlite3_int64 iEnd; /* Block number of last allocated block */
128722 NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
128723 };
128724
128725 /*
128726 ** An object of the following type is used to read data from a single
128727 ** FTS segment node. See the following functions:
128728 **
128729 ** nodeReaderInit()
128730 ** nodeReaderNext()
128731 ** nodeReaderRelease()
128732 */
128733 struct NodeReader {
128734 const char *aNode;
128735 int nNode;
128736 int iOff; /* Current offset within aNode[] */
128737
128738 /* Output variables. Containing the current node entry. */
128739 sqlite3_int64 iChild; /* Pointer to child node */
128740 Blob term; /* Current term */
128741 const char *aDoclist; /* Pointer to doclist */
128742 int nDoclist; /* Size of doclist in bytes */
128743 };
128744
128745 /*
128746 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
128747 ** Otherwise, if the allocation at pBlob->a is not already at least nMin
128748 ** bytes in size, extend (realloc) it to be so.
128749 **
128750 ** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a
128751 ** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc
128752 ** to reflect the new size of the pBlob->a[] buffer.
128753 */
128754 static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
128755 if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
128756 int nAlloc = nMin;
128757 char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
128758 if( a ){
128759 pBlob->nAlloc = nAlloc;
128760 pBlob->a = a;
128761 }else{
128762 *pRc = SQLITE_NOMEM;
128763 }
128764 }
128765 }
128766
128767 /*
128768 ** Attempt to advance the node-reader object passed as the first argument to
128769 ** the next entry on the node.
128770 **
128771 ** Return an error code if an error occurs (SQLITE_NOMEM is possible).
128772 ** Otherwise return SQLITE_OK. If there is no next entry on the node
128773 ** (e.g. because the current entry is the last) set NodeReader->aNode to
128774 ** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
128775 ** variables for the new entry.
128776 */
128777 static int nodeReaderNext(NodeReader *p){
128778 int bFirst = (p->term.n==0); /* True for first term on the node */
128779 int nPrefix = 0; /* Bytes to copy from previous term */
128780 int nSuffix = 0; /* Bytes to append to the prefix */
128781 int rc = SQLITE_OK; /* Return code */
128782
128783 assert( p->aNode );
128784 if( p->iChild && bFirst==0 ) p->iChild++;
128785 if( p->iOff>=p->nNode ){
128786 /* EOF */
128787 p->aNode = 0;
128788 }else{
128789 if( bFirst==0 ){
128790 p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
128791 }
128792 p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
128793
128794 blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
128795 if( rc==SQLITE_OK ){
128796 memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
128797 p->term.n = nPrefix+nSuffix;
128798 p->iOff += nSuffix;
128799 if( p->iChild==0 ){
128800 p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
128801 p->aDoclist = &p->aNode[p->iOff];
128802 p->iOff += p->nDoclist;
128803 }
128804 }
128805 }
128806
128807 assert( p->iOff<=p->nNode );
128808
128809 return rc;
128810 }
128811
128812 /*
128813 ** Release all dynamic resources held by node-reader object *p.
128814 */
128815 static void nodeReaderRelease(NodeReader *p){
128816 sqlite3_free(p->term.a);
128817 }
128818
128819 /*
128820 ** Initialize a node-reader object to read the node in buffer aNode/nNode.
128821 **
128822 ** If successful, SQLITE_OK is returned and the NodeReader object set to
128823 ** point to the first entry on the node (if any). Otherwise, an SQLite
128824 ** error code is returned.
128825 */
128826 static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
128827 memset(p, 0, sizeof(NodeReader));
128828 p->aNode = aNode;
128829 p->nNode = nNode;
128830
128831 /* Figure out if this is a leaf or an internal node. */
128832 if( p->aNode[0] ){
128833 /* An internal node. */
128834 p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
128835 }else{
128836 p->iOff = 1;
128837 }
128838
128839 return nodeReaderNext(p);
128840 }
128841
128842 /*
128843 ** This function is called while writing an FTS segment each time a leaf o
128844 ** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed
128845 ** to be greater than the largest key on the node just written, but smaller
128846 ** than or equal to the first key that will be written to the next leaf
128847 ** node.
128848 **
128849 ** The block id of the leaf node just written to disk may be found in
128850 ** (pWriter->aNodeWriter[0].iBlock) when this function is called.
128851 */
128852 static int fts3IncrmergePush(
128853 Fts3Table *p, /* Fts3 table handle */
128854 IncrmergeWriter *pWriter, /* Writer object */
128855 const char *zTerm, /* Term to write to internal node */
128856 int nTerm /* Bytes at zTerm */
128857 ){
128858 sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock;
128859 int iLayer;
128860
128861 assert( nTerm>0 );
128862 for(iLayer=1; ALWAYS(iLayer<FTS_MAX_APPENDABLE_HEIGHT); iLayer++){
128863 sqlite3_int64 iNextPtr = 0;
128864 NodeWriter *pNode = &pWriter->aNodeWriter[iLayer];
128865 int rc = SQLITE_OK;
128866 int nPrefix;
128867 int nSuffix;
128868 int nSpace;
128869
128870 /* Figure out how much space the key will consume if it is written to
128871 ** the current node of layer iLayer. Due to the prefix compression,
128872 ** the space required changes depending on which node the key is to
128873 ** be added to. */
128874 nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
128875 nSuffix = nTerm - nPrefix;
128876 nSpace = sqlite3Fts3VarintLen(nPrefix);
128877 nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
128878
128879 if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
128880 /* If the current node of layer iLayer contains zero keys, or if adding
128881 ** the key to it will not cause it to grow to larger than nNodeSize
128882 ** bytes in size, write the key here. */
128883
128884 Blob *pBlk = &pNode->block;
128885 if( pBlk->n==0 ){
128886 blobGrowBuffer(pBlk, p->nNodeSize, &rc);
128887 if( rc==SQLITE_OK ){
128888 pBlk->a[0] = (char)iLayer;
128889 pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr);
128890 }
128891 }
128892 blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc);
128893 blobGrowBuffer(&pNode->key, nTerm, &rc);
128894
128895 if( rc==SQLITE_OK ){
128896 if( pNode->key.n ){
128897 pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
128898 }
128899 pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
128900 memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
128901 pBlk->n += nSuffix;
128902
128903 memcpy(pNode->key.a, zTerm, nTerm);
128904 pNode->key.n = nTerm;
128905 }
128906 }else{
128907 /* Otherwise, flush the the current node of layer iLayer to disk.
128908 ** Then allocate a new, empty sibling node. The key will be written
128909 ** into the parent of this node. */
128910 rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
128911
128912 assert( pNode->block.nAlloc>=p->nNodeSize );
128913 pNode->block.a[0] = (char)iLayer;
128914 pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1);
128915
128916 iNextPtr = pNode->iBlock;
128917 pNode->iBlock++;
128918 pNode->key.n = 0;
128919 }
128920
128921 if( rc!=SQLITE_OK || iNextPtr==0 ) return rc;
128922 iPtr = iNextPtr;
128923 }
128924
128925 assert( 0 );
128926 return 0;
128927 }
128928
128929 /*
128930 ** Append a term and (optionally) doclist to the FTS segment node currently
128931 ** stored in blob *pNode. The node need not contain any terms, but the
128932 ** header must be written before this function is called.
128933 **
128934 ** A node header is a single 0x00 byte for a leaf node, or a height varint
128935 ** followed by the left-hand-child varint for an internal node.
128936 **
128937 ** The term to be appended is passed via arguments zTerm/nTerm. For a
128938 ** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal
128939 ** node, both aDoclist and nDoclist must be passed 0.
128940 **
128941 ** If the size of the value in blob pPrev is zero, then this is the first
128942 ** term written to the node. Otherwise, pPrev contains a copy of the
128943 ** previous term. Before this function returns, it is updated to contain a
128944 ** copy of zTerm/nTerm.
128945 **
128946 ** It is assumed that the buffer associated with pNode is already large
128947 ** enough to accommodate the new entry. The buffer associated with pPrev
128948 ** is extended by this function if requrired.
128949 **
128950 ** If an error (i.e. OOM condition) occurs, an SQLite error code is
128951 ** returned. Otherwise, SQLITE_OK.
128952 */
128953 static int fts3AppendToNode(
128954 Blob *pNode, /* Current node image to append to */
128955 Blob *pPrev, /* Buffer containing previous term written */
128956 const char *zTerm, /* New term to write */
128957 int nTerm, /* Size of zTerm in bytes */
128958 const char *aDoclist, /* Doclist (or NULL) to write */
128959 int nDoclist /* Size of aDoclist in bytes */
128960 ){
128961 int rc = SQLITE_OK; /* Return code */
128962 int bFirst = (pPrev->n==0); /* True if this is the first term written */
128963 int nPrefix; /* Size of term prefix in bytes */
128964 int nSuffix; /* Size of term suffix in bytes */
128965
128966 /* Node must have already been started. There must be a doclist for a
128967 ** leaf node, and there must not be a doclist for an internal node. */
128968 assert( pNode->n>0 );
128969 assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
128970
128971 blobGrowBuffer(pPrev, nTerm, &rc);
128972 if( rc!=SQLITE_OK ) return rc;
128973
128974 nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
128975 nSuffix = nTerm - nPrefix;
128976 memcpy(pPrev->a, zTerm, nTerm);
128977 pPrev->n = nTerm;
128978
128979 if( bFirst==0 ){
128980 pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix);
128981 }
128982 pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix);
128983 memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix);
128984 pNode->n += nSuffix;
128985
128986 if( aDoclist ){
128987 pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist);
128988 memcpy(&pNode->a[pNode->n], aDoclist, nDoclist);
128989 pNode->n += nDoclist;
128990 }
128991
128992 assert( pNode->n<=pNode->nAlloc );
128993
128994 return SQLITE_OK;
128995 }
128996
128997 /*
128998 ** Append the current term and doclist pointed to by cursor pCsr to the
128999 ** appendable b-tree segment opened for writing by pWriter.
129000 **
129001 ** Return SQLITE_OK if successful, or an SQLite error code otherwise.
129002 */
129003 static int fts3IncrmergeAppend(
129004 Fts3Table *p, /* Fts3 table handle */
129005 IncrmergeWriter *pWriter, /* Writer object */
129006 Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */
129007 ){
129008 const char *zTerm = pCsr->zTerm;
129009 int nTerm = pCsr->nTerm;
129010 const char *aDoclist = pCsr->aDoclist;
129011 int nDoclist = pCsr->nDoclist;
129012 int rc = SQLITE_OK; /* Return code */
129013 int nSpace; /* Total space in bytes required on leaf */
129014 int nPrefix; /* Size of prefix shared with previous term */
129015 int nSuffix; /* Size of suffix (nTerm - nPrefix) */
129016 NodeWriter *pLeaf; /* Object used to write leaf nodes */
129017
129018 pLeaf = &pWriter->aNodeWriter[0];
129019 nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
129020 nSuffix = nTerm - nPrefix;
129021
129022 nSpace = sqlite3Fts3VarintLen(nPrefix);
129023 nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
129024 nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
129025
129026 /* If the current block is not empty, and if adding this term/doclist
129027 ** to the current block would make it larger than Fts3Table.nNodeSize
129028 ** bytes, write this block out to the database. */
129029 if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){
129030 rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
129031 pWriter->nWork++;
129032
129033 /* Add the current term to the parent node. The term added to the
129034 ** parent must:
129035 **
129036 ** a) be greater than the largest term on the leaf node just written
129037 ** to the database (still available in pLeaf->key), and
129038 **
129039 ** b) be less than or equal to the term about to be added to the new
129040 ** leaf node (zTerm/nTerm).
129041 **
129042 ** In other words, it must be the prefix of zTerm 1 byte longer than
129043 ** the common prefix (if any) of zTerm and pWriter->zTerm.
129044 */
129045 if( rc==SQLITE_OK ){
129046 rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1);
129047 }
129048
129049 /* Advance to the next output block */
129050 pLeaf->iBlock++;
129051 pLeaf->key.n = 0;
129052 pLeaf->block.n = 0;
129053
129054 nPrefix = 0;
129055 nSuffix = nTerm;
129056 nSpace = 1;
129057 nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
129058 nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
129059 }
129060
129061 blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
129062
129063 if( rc==SQLITE_OK ){
129064 if( pLeaf->block.n==0 ){
129065 pLeaf->block.n = 1;
129066 pLeaf->block.a[0] = '\0';
129067 }
129068 rc = fts3AppendToNode(
129069 &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist
129070 );
129071 }
129072
129073 return rc;
129074 }
129075
129076 /*
129077 ** This function is called to release all dynamic resources held by the
129078 ** merge-writer object pWriter, and if no error has occurred, to flush
129079 ** all outstanding node buffers held by pWriter to disk.
129080 **
129081 ** If *pRc is not SQLITE_OK when this function is called, then no attempt
129082 ** is made to write any data to disk. Instead, this function serves only
129083 ** to release outstanding resources.
129084 **
129085 ** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while
129086 ** flushing buffers to disk, *pRc is set to an SQLite error code before
129087 ** returning.
129088 */
129089 static void fts3IncrmergeRelease(
129090 Fts3Table *p, /* FTS3 table handle */
129091 IncrmergeWriter *pWriter, /* Merge-writer object */
129092 int *pRc /* IN/OUT: Error code */
129093 ){
129094 int i; /* Used to iterate through non-root layers */
129095 int iRoot; /* Index of root in pWriter->aNodeWriter */
129096 NodeWriter *pRoot; /* NodeWriter for root node */
129097 int rc = *pRc; /* Error code */
129098
129099 /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
129100 ** root node. If the segment fits entirely on a single leaf node, iRoot
129101 ** will be set to 0. If the root node is the parent of the leaves, iRoot
129102 ** will be 1. And so on. */
129103 for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){
129104 NodeWriter *pNode = &pWriter->aNodeWriter[iRoot];
129105 if( pNode->block.n>0 ) break;
129106 assert( *pRc || pNode->block.nAlloc==0 );
129107 assert( *pRc || pNode->key.nAlloc==0 );
129108 sqlite3_free(pNode->block.a);
129109 sqlite3_free(pNode->key.a);
129110 }
129111
129112 /* Empty output segment. This is a no-op. */
129113 if( iRoot<0 ) return;
129114
129115 /* The entire output segment fits on a single node. Normally, this means
129116 ** the node would be stored as a blob in the "root" column of the %_segdir
129117 ** table. However, this is not permitted in this case. The problem is that
129118 ** space has already been reserved in the %_segments table, and so the
129119 ** start_block and end_block fields of the %_segdir table must be populated.
129120 ** And, by design or by accident, released versions of FTS cannot handle
129121 ** segments that fit entirely on the root node with start_block!=0.
129122 **
129123 ** Instead, create a synthetic root node that contains nothing but a
129124 ** pointer to the single content node. So that the segment consists of a
129125 ** single leaf and a single interior (root) node.
129126 **
129127 ** Todo: Better might be to defer allocating space in the %_segments
129128 ** table until we are sure it is needed.
129129 */
129130 if( iRoot==0 ){
129131 Blob *pBlock = &pWriter->aNodeWriter[1].block;
129132 blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc);
129133 if( rc==SQLITE_OK ){
129134 pBlock->a[0] = 0x01;
129135 pBlock->n = 1 + sqlite3Fts3PutVarint(
129136 &pBlock->a[1], pWriter->aNodeWriter[0].iBlock
129137 );
129138 }
129139 iRoot = 1;
129140 }
129141 pRoot = &pWriter->aNodeWriter[iRoot];
129142
129143 /* Flush all currently outstanding nodes to disk. */
129144 for(i=0; i<iRoot; i++){
129145 NodeWriter *pNode = &pWriter->aNodeWriter[i];
129146 if( pNode->block.n>0 && rc==SQLITE_OK ){
129147 rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
129148 }
129149 sqlite3_free(pNode->block.a);
129150 sqlite3_free(pNode->key.a);
129151 }
129152
129153 /* Write the %_segdir record. */
129154 if( rc==SQLITE_OK ){
129155 rc = fts3WriteSegdir(p,
129156 pWriter->iAbsLevel+1, /* level */
129157 pWriter->iIdx, /* idx */
129158 pWriter->iStart, /* start_block */
129159 pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
129160 pWriter->iEnd, /* end_block */
129161 pRoot->block.a, pRoot->block.n /* root */
129162 );
129163 }
129164 sqlite3_free(pRoot->block.a);
129165 sqlite3_free(pRoot->key.a);
129166
129167 *pRc = rc;
129168 }
129169
129170 /*
129171 ** Compare the term in buffer zLhs (size in bytes nLhs) with that in
129172 ** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of
129173 ** the other, it is considered to be smaller than the other.
129174 **
129175 ** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve
129176 ** if it is greater.
129177 */
129178 static int fts3TermCmp(
129179 const char *zLhs, int nLhs, /* LHS of comparison */
129180 const char *zRhs, int nRhs /* RHS of comparison */
129181 ){
129182 int nCmp = MIN(nLhs, nRhs);
129183 int res;
129184
129185 res = memcmp(zLhs, zRhs, nCmp);
129186 if( res==0 ) res = nLhs - nRhs;
129187
129188 return res;
129189 }
129190
129191
129192 /*
129193 ** Query to see if the entry in the %_segments table with blockid iEnd is
129194 ** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before
129195 ** returning. Otherwise, set *pbRes to 0.
129196 **
129197 ** Or, if an error occurs while querying the database, return an SQLite
129198 ** error code. The final value of *pbRes is undefined in this case.
129199 **
129200 ** This is used to test if a segment is an "appendable" segment. If it
129201 ** is, then a NULL entry has been inserted into the %_segments table
129202 ** with blockid %_segdir.end_block.
129203 */
129204 static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){
129205 int bRes = 0; /* Result to set *pbRes to */
129206 sqlite3_stmt *pCheck = 0; /* Statement to query database with */
129207 int rc; /* Return code */
129208
129209 rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0);
129210 if( rc==SQLITE_OK ){
129211 sqlite3_bind_int64(pCheck, 1, iEnd);
129212 if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1;
129213 rc = sqlite3_reset(pCheck);
129214 }
129215
129216 *pbRes = bRes;
129217 return rc;
129218 }
129219
129220 /*
129221 ** This function is called when initializing an incremental-merge operation.
129222 ** It checks if the existing segment with index value iIdx at absolute level
129223 ** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the
129224 ** merge-writer object *pWriter is initialized to write to it.
129225 **
129226 ** An existing segment can be appended to by an incremental merge if:
129227 **
129228 ** * It was initially created as an appendable segment (with all required
129229 ** space pre-allocated), and
129230 **
129231 ** * The first key read from the input (arguments zKey and nKey) is
129232 ** greater than the largest key currently stored in the potential
129233 ** output segment.
129234 */
129235 static int fts3IncrmergeLoad(
129236 Fts3Table *p, /* Fts3 table handle */
129237 sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
129238 int iIdx, /* Index of candidate output segment */
129239 const char *zKey, /* First key to write */
129240 int nKey, /* Number of bytes in nKey */
129241 IncrmergeWriter *pWriter /* Populate this object */
129242 ){
129243 int rc; /* Return code */
129244 sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */
129245
129246 rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0);
129247 if( rc==SQLITE_OK ){
129248 sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */
129249 sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */
129250 sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */
129251 const char *aRoot = 0; /* Pointer to %_segdir.root buffer */
129252 int nRoot = 0; /* Size of aRoot[] in bytes */
129253 int rc2; /* Return code from sqlite3_reset() */
129254 int bAppendable = 0; /* Set to true if segment is appendable */
129255
129256 /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */
129257 sqlite3_bind_int64(pSelect, 1, iAbsLevel+1);
129258 sqlite3_bind_int(pSelect, 2, iIdx);
129259 if( sqlite3_step(pSelect)==SQLITE_ROW ){
129260 iStart = sqlite3_column_int64(pSelect, 1);
129261 iLeafEnd = sqlite3_column_int64(pSelect, 2);
129262 iEnd = sqlite3_column_int64(pSelect, 3);
129263 nRoot = sqlite3_column_bytes(pSelect, 4);
129264 aRoot = sqlite3_column_blob(pSelect, 4);
129265 }else{
129266 return sqlite3_reset(pSelect);
129267 }
129268
129269 /* Check for the zero-length marker in the %_segments table */
129270 rc = fts3IsAppendable(p, iEnd, &bAppendable);
129271
129272 /* Check that zKey/nKey is larger than the largest key the candidate */
129273 if( rc==SQLITE_OK && bAppendable ){
129274 char *aLeaf = 0;
129275 int nLeaf = 0;
129276
129277 rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0);
129278 if( rc==SQLITE_OK ){
129279 NodeReader reader;
129280 for(rc = nodeReaderInit(&reader, aLeaf, nLeaf);
129281 rc==SQLITE_OK && reader.aNode;
129282 rc = nodeReaderNext(&reader)
129283 ){
129284 assert( reader.aNode );
129285 }
129286 if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){
129287 bAppendable = 0;
129288 }
129289 nodeReaderRelease(&reader);
129290 }
129291 sqlite3_free(aLeaf);
129292 }
129293
129294 if( rc==SQLITE_OK && bAppendable ){
129295 /* It is possible to append to this segment. Set up the IncrmergeWriter
129296 ** object to do so. */
129297 int i;
129298 int nHeight = (int)aRoot[0];
129299 NodeWriter *pNode;
129300
129301 pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
129302 pWriter->iStart = iStart;
129303 pWriter->iEnd = iEnd;
129304 pWriter->iAbsLevel = iAbsLevel;
129305 pWriter->iIdx = iIdx;
129306
129307 for(i=nHeight+1; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
129308 pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
129309 }
129310
129311 pNode = &pWriter->aNodeWriter[nHeight];
129312 pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
129313 blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
129314 if( rc==SQLITE_OK ){
129315 memcpy(pNode->block.a, aRoot, nRoot);
129316 pNode->block.n = nRoot;
129317 }
129318
129319 for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
129320 NodeReader reader;
129321 pNode = &pWriter->aNodeWriter[i];
129322
129323 rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
129324 while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
129325 blobGrowBuffer(&pNode->key, reader.term.n, &rc);
129326 if( rc==SQLITE_OK ){
129327 memcpy(pNode->key.a, reader.term.a, reader.term.n);
129328 pNode->key.n = reader.term.n;
129329 if( i>0 ){
129330 char *aBlock = 0;
129331 int nBlock = 0;
129332 pNode = &pWriter->aNodeWriter[i-1];
129333 pNode->iBlock = reader.iChild;
129334 rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
129335 blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
129336 if( rc==SQLITE_OK ){
129337 memcpy(pNode->block.a, aBlock, nBlock);
129338 pNode->block.n = nBlock;
129339 }
129340 sqlite3_free(aBlock);
129341 }
129342 }
129343 nodeReaderRelease(&reader);
129344 }
129345 }
129346
129347 rc2 = sqlite3_reset(pSelect);
129348 if( rc==SQLITE_OK ) rc = rc2;
129349 }
129350
129351 return rc;
129352 }
129353
129354 /*
129355 ** Determine the largest segment index value that exists within absolute
129356 ** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus
129357 ** one before returning SQLITE_OK. Or, if there are no segments at all
129358 ** within level iAbsLevel, set *piIdx to zero.
129359 **
129360 ** If an error occurs, return an SQLite error code. The final value of
129361 ** *piIdx is undefined in this case.
129362 */
129363 static int fts3IncrmergeOutputIdx(
129364 Fts3Table *p, /* FTS Table handle */
129365 sqlite3_int64 iAbsLevel, /* Absolute index of input segments */
129366 int *piIdx /* OUT: Next free index at iAbsLevel+1 */
129367 ){
129368 int rc;
129369 sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */
129370
129371 rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0);
129372 if( rc==SQLITE_OK ){
129373 sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1);
129374 sqlite3_step(pOutputIdx);
129375 *piIdx = sqlite3_column_int(pOutputIdx, 0);
129376 rc = sqlite3_reset(pOutputIdx);
129377 }
129378
129379 return rc;
129380 }
129381
129382 /*
129383 ** Allocate an appendable output segment on absolute level iAbsLevel+1
129384 ** with idx value iIdx.
129385 **
129386 ** In the %_segdir table, a segment is defined by the values in three
129387 ** columns:
129388 **
129389 ** start_block
129390 ** leaves_end_block
129391 ** end_block
129392 **
129393 ** When an appendable segment is allocated, it is estimated that the
129394 ** maximum number of leaf blocks that may be required is the sum of the
129395 ** number of leaf blocks consumed by the input segments, plus the number
129396 ** of input segments, multiplied by two. This value is stored in stack
129397 ** variable nLeafEst.
129398 **
129399 ** A total of 16*nLeafEst blocks are allocated when an appendable segment
129400 ** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous
129401 ** array of leaf nodes starts at the first block allocated. The array
129402 ** of interior nodes that are parents of the leaf nodes start at block
129403 ** (start_block + (1 + end_block - start_block) / 16). And so on.
129404 **
129405 ** In the actual code below, the value "16" is replaced with the
129406 ** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT.
129407 */
129408 static int fts3IncrmergeWriter(
129409 Fts3Table *p, /* Fts3 table handle */
129410 sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
129411 int iIdx, /* Index of new output segment */
129412 Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */
129413 IncrmergeWriter *pWriter /* Populate this object */
129414 ){
129415 int rc; /* Return Code */
129416 int i; /* Iterator variable */
129417 int nLeafEst = 0; /* Blocks allocated for leaf nodes */
129418 sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */
129419 sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */
129420
129421 /* Calculate nLeafEst. */
129422 rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0);
129423 if( rc==SQLITE_OK ){
129424 sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
129425 sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
129426 if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
129427 nLeafEst = sqlite3_column_int(pLeafEst, 0);
129428 }
129429 rc = sqlite3_reset(pLeafEst);
129430 }
129431 if( rc!=SQLITE_OK ) return rc;
129432
129433 /* Calculate the first block to use in the output segment */
129434 rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0);
129435 if( rc==SQLITE_OK ){
129436 if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){
129437 pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0);
129438 pWriter->iEnd = pWriter->iStart - 1;
129439 pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT;
129440 }
129441 rc = sqlite3_reset(pFirstBlock);
129442 }
129443 if( rc!=SQLITE_OK ) return rc;
129444
129445 /* Insert the marker in the %_segments table to make sure nobody tries
129446 ** to steal the space just allocated. This is also used to identify
129447 ** appendable segments. */
129448 rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0);
129449 if( rc!=SQLITE_OK ) return rc;
129450
129451 pWriter->iAbsLevel = iAbsLevel;
129452 pWriter->nLeafEst = nLeafEst;
129453 pWriter->iIdx = iIdx;
129454
129455 /* Set up the array of NodeWriter objects */
129456 for(i=0; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
129457 pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
129458 }
129459 return SQLITE_OK;
129460 }
129461
129462 /*
129463 ** Remove an entry from the %_segdir table. This involves running the
129464 ** following two statements:
129465 **
129466 ** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx
129467 ** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx
129468 **
129469 ** The DELETE statement removes the specific %_segdir level. The UPDATE
129470 ** statement ensures that the remaining segments have contiguously allocated
129471 ** idx values.
129472 */
129473 static int fts3RemoveSegdirEntry(
129474 Fts3Table *p, /* FTS3 table handle */
129475 sqlite3_int64 iAbsLevel, /* Absolute level to delete from */
129476 int iIdx /* Index of %_segdir entry to delete */
129477 ){
129478 int rc; /* Return code */
129479 sqlite3_stmt *pDelete = 0; /* DELETE statement */
129480
129481 rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0);
129482 if( rc==SQLITE_OK ){
129483 sqlite3_bind_int64(pDelete, 1, iAbsLevel);
129484 sqlite3_bind_int(pDelete, 2, iIdx);
129485 sqlite3_step(pDelete);
129486 rc = sqlite3_reset(pDelete);
129487 }
129488
129489 return rc;
129490 }
129491
129492 /*
129493 ** One or more segments have just been removed from absolute level iAbsLevel.
129494 ** Update the 'idx' values of the remaining segments in the level so that
129495 ** the idx values are a contiguous sequence starting from 0.
129496 */
129497 static int fts3RepackSegdirLevel(
129498 Fts3Table *p, /* FTS3 table handle */
129499 sqlite3_int64 iAbsLevel /* Absolute level to repack */
129500 ){
129501 int rc; /* Return code */
129502 int *aIdx = 0; /* Array of remaining idx values */
129503 int nIdx = 0; /* Valid entries in aIdx[] */
129504 int nAlloc = 0; /* Allocated size of aIdx[] */
129505 int i; /* Iterator variable */
129506 sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */
129507 sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */
129508
129509 rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0);
129510 if( rc==SQLITE_OK ){
129511 int rc2;
129512 sqlite3_bind_int64(pSelect, 1, iAbsLevel);
129513 while( SQLITE_ROW==sqlite3_step(pSelect) ){
129514 if( nIdx>=nAlloc ){
129515 int *aNew;
129516 nAlloc += 16;
129517 aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
129518 if( !aNew ){
129519 rc = SQLITE_NOMEM;
129520 break;
129521 }
129522 aIdx = aNew;
129523 }
129524 aIdx[nIdx++] = sqlite3_column_int(pSelect, 0);
129525 }
129526 rc2 = sqlite3_reset(pSelect);
129527 if( rc==SQLITE_OK ) rc = rc2;
129528 }
129529
129530 if( rc==SQLITE_OK ){
129531 rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0);
129532 }
129533 if( rc==SQLITE_OK ){
129534 sqlite3_bind_int64(pUpdate, 2, iAbsLevel);
129535 }
129536
129537 assert( p->bIgnoreSavepoint==0 );
129538 p->bIgnoreSavepoint = 1;
129539 for(i=0; rc==SQLITE_OK && i<nIdx; i++){
129540 if( aIdx[i]!=i ){
129541 sqlite3_bind_int(pUpdate, 3, aIdx[i]);
129542 sqlite3_bind_int(pUpdate, 1, i);
129543 sqlite3_step(pUpdate);
129544 rc = sqlite3_reset(pUpdate);
129545 }
129546 }
129547 p->bIgnoreSavepoint = 0;
129548
129549 sqlite3_free(aIdx);
129550 return rc;
129551 }
129552
129553 static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){
129554 pNode->a[0] = (char)iHeight;
129555 if( iChild ){
129556 assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) );
129557 pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild);
129558 }else{
129559 assert( pNode->nAlloc>=1 );
129560 pNode->n = 1;
129561 }
129562 }
129563
129564 /*
129565 ** The first two arguments are a pointer to and the size of a segment b-tree
129566 ** node. The node may be a leaf or an internal node.
129567 **
129568 ** This function creates a new node image in blob object *pNew by copying
129569 ** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes)
129570 ** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode.
129571 */
129572 static int fts3TruncateNode(
129573 const char *aNode, /* Current node image */
129574 int nNode, /* Size of aNode in bytes */
129575 Blob *pNew, /* OUT: Write new node image here */
129576 const char *zTerm, /* Omit all terms smaller than this */
129577 int nTerm, /* Size of zTerm in bytes */
129578 sqlite3_int64 *piBlock /* OUT: Block number in next layer down */
129579 ){
129580 NodeReader reader; /* Reader object */
129581 Blob prev = {0, 0, 0}; /* Previous term written to new node */
129582 int rc = SQLITE_OK; /* Return code */
129583 int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
129584
129585 /* Allocate required output space */
129586 blobGrowBuffer(pNew, nNode, &rc);
129587 if( rc!=SQLITE_OK ) return rc;
129588 pNew->n = 0;
129589
129590 /* Populate new node buffer */
129591 for(rc = nodeReaderInit(&reader, aNode, nNode);
129592 rc==SQLITE_OK && reader.aNode;
129593 rc = nodeReaderNext(&reader)
129594 ){
129595 if( pNew->n==0 ){
129596 int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm);
129597 if( res<0 || (bLeaf==0 && res==0) ) continue;
129598 fts3StartNode(pNew, (int)aNode[0], reader.iChild);
129599 *piBlock = reader.iChild;
129600 }
129601 rc = fts3AppendToNode(
129602 pNew, &prev, reader.term.a, reader.term.n,
129603 reader.aDoclist, reader.nDoclist
129604 );
129605 if( rc!=SQLITE_OK ) break;
129606 }
129607 if( pNew->n==0 ){
129608 fts3StartNode(pNew, (int)aNode[0], reader.iChild);
129609 *piBlock = reader.iChild;
129610 }
129611 assert( pNew->n<=pNew->nAlloc );
129612
129613 nodeReaderRelease(&reader);
129614 sqlite3_free(prev.a);
129615 return rc;
129616 }
129617
129618 /*
129619 ** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
129620 ** level iAbsLevel. This may involve deleting entries from the %_segments
129621 ** table, and modifying existing entries in both the %_segments and %_segdir
129622 ** tables.
129623 **
129624 ** SQLITE_OK is returned if the segment is updated successfully. Or an
129625 ** SQLite error code otherwise.
129626 */
129627 static int fts3TruncateSegment(
129628 Fts3Table *p, /* FTS3 table handle */
129629 sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */
129630 int iIdx, /* Index within level of segment to modify */
129631 const char *zTerm, /* Remove terms smaller than this */
129632 int nTerm /* Number of bytes in buffer zTerm */
129633 ){
129634 int rc = SQLITE_OK; /* Return code */
129635 Blob root = {0,0,0}; /* New root page image */
129636 Blob block = {0,0,0}; /* Buffer used for any other block */
129637 sqlite3_int64 iBlock = 0; /* Block id */
129638 sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */
129639 sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */
129640 sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */
129641
129642 rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0);
129643 if( rc==SQLITE_OK ){
129644 int rc2; /* sqlite3_reset() return code */
129645 sqlite3_bind_int64(pFetch, 1, iAbsLevel);
129646 sqlite3_bind_int(pFetch, 2, iIdx);
129647 if( SQLITE_ROW==sqlite3_step(pFetch) ){
129648 const char *aRoot = sqlite3_column_blob(pFetch, 4);
129649 int nRoot = sqlite3_column_bytes(pFetch, 4);
129650 iOldStart = sqlite3_column_int64(pFetch, 1);
129651 rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock);
129652 }
129653 rc2 = sqlite3_reset(pFetch);
129654 if( rc==SQLITE_OK ) rc = rc2;
129655 }
129656
129657 while( rc==SQLITE_OK && iBlock ){
129658 char *aBlock = 0;
129659 int nBlock = 0;
129660 iNewStart = iBlock;
129661
129662 rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0);
129663 if( rc==SQLITE_OK ){
129664 rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock);
129665 }
129666 if( rc==SQLITE_OK ){
129667 rc = fts3WriteSegment(p, iNewStart, block.a, block.n);
129668 }
129669 sqlite3_free(aBlock);
129670 }
129671
129672 /* Variable iNewStart now contains the first valid leaf node. */
129673 if( rc==SQLITE_OK && iNewStart ){
129674 sqlite3_stmt *pDel = 0;
129675 rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0);
129676 if( rc==SQLITE_OK ){
129677 sqlite3_bind_int64(pDel, 1, iOldStart);
129678 sqlite3_bind_int64(pDel, 2, iNewStart-1);
129679 sqlite3_step(pDel);
129680 rc = sqlite3_reset(pDel);
129681 }
129682 }
129683
129684 if( rc==SQLITE_OK ){
129685 sqlite3_stmt *pChomp = 0;
129686 rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0);
129687 if( rc==SQLITE_OK ){
129688 sqlite3_bind_int64(pChomp, 1, iNewStart);
129689 sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC);
129690 sqlite3_bind_int64(pChomp, 3, iAbsLevel);
129691 sqlite3_bind_int(pChomp, 4, iIdx);
129692 sqlite3_step(pChomp);
129693 rc = sqlite3_reset(pChomp);
129694 }
129695 }
129696
129697 sqlite3_free(root.a);
129698 sqlite3_free(block.a);
129699 return rc;
129700 }
129701
129702 /*
129703 ** This function is called after an incrmental-merge operation has run to
129704 ** merge (or partially merge) two or more segments from absolute level
129705 ** iAbsLevel.
129706 **
129707 ** Each input segment is either removed from the db completely (if all of
129708 ** its data was copied to the output segment by the incrmerge operation)
129709 ** or modified in place so that it no longer contains those entries that
129710 ** have been duplicated in the output segment.
129711 */
129712 static int fts3IncrmergeChomp(
129713 Fts3Table *p, /* FTS table handle */
129714 sqlite3_int64 iAbsLevel, /* Absolute level containing segments */
129715 Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */
129716 int *pnRem /* Number of segments not deleted */
129717 ){
129718 int i;
129719 int nRem = 0;
129720 int rc = SQLITE_OK;
129721
129722 for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){
129723 Fts3SegReader *pSeg = 0;
129724 int j;
129725
129726 /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding
129727 ** somewhere in the pCsr->apSegment[] array. */
129728 for(j=0; ALWAYS(j<pCsr->nSegment); j++){
129729 pSeg = pCsr->apSegment[j];
129730 if( pSeg->iIdx==i ) break;
129731 }
129732 assert( j<pCsr->nSegment && pSeg->iIdx==i );
129733
129734 if( pSeg->aNode==0 ){
129735 /* Seg-reader is at EOF. Remove the entire input segment. */
129736 rc = fts3DeleteSegment(p, pSeg);
129737 if( rc==SQLITE_OK ){
129738 rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx);
129739 }
129740 *pnRem = 0;
129741 }else{
129742 /* The incremental merge did not copy all the data from this
129743 ** segment to the upper level. The segment is modified in place
129744 ** so that it contains no keys smaller than zTerm/nTerm. */
129745 const char *zTerm = pSeg->zTerm;
129746 int nTerm = pSeg->nTerm;
129747 rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
129748 nRem++;
129749 }
129750 }
129751
129752 if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){
129753 rc = fts3RepackSegdirLevel(p, iAbsLevel);
129754 }
129755
129756 *pnRem = nRem;
129757 return rc;
129758 }
129759
129760 /*
129761 ** Store an incr-merge hint in the database.
129762 */
129763 static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
129764 sqlite3_stmt *pReplace = 0;
129765 int rc; /* Return code */
129766
129767 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0);
129768 if( rc==SQLITE_OK ){
129769 sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT);
129770 sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
129771 sqlite3_step(pReplace);
129772 rc = sqlite3_reset(pReplace);
129773 }
129774
129775 return rc;
129776 }
129777
129778 /*
129779 ** Load an incr-merge hint from the database. The incr-merge hint, if one
129780 ** exists, is stored in the rowid==1 row of the %_stat table.
129781 **
129782 ** If successful, populate blob *pHint with the value read from the %_stat
129783 ** table and return SQLITE_OK. Otherwise, if an error occurs, return an
129784 ** SQLite error code.
129785 */
129786 static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
129787 sqlite3_stmt *pSelect = 0;
129788 int rc;
129789
129790 pHint->n = 0;
129791 rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0);
129792 if( rc==SQLITE_OK ){
129793 int rc2;
129794 sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
129795 if( SQLITE_ROW==sqlite3_step(pSelect) ){
129796 const char *aHint = sqlite3_column_blob(pSelect, 0);
129797 int nHint = sqlite3_column_bytes(pSelect, 0);
129798 if( aHint ){
129799 blobGrowBuffer(pHint, nHint, &rc);
129800 if( rc==SQLITE_OK ){
129801 memcpy(pHint->a, aHint, nHint);
129802 pHint->n = nHint;
129803 }
129804 }
129805 }
129806 rc2 = sqlite3_reset(pSelect);
129807 if( rc==SQLITE_OK ) rc = rc2;
129808 }
129809
129810 return rc;
129811 }
129812
129813 /*
129814 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
129815 ** Otherwise, append an entry to the hint stored in blob *pHint. Each entry
129816 ** consists of two varints, the absolute level number of the input segments
129817 ** and the number of input segments.
129818 **
129819 ** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
129820 ** set *pRc to an SQLite error code before returning.
129821 */
129822 static void fts3IncrmergeHintPush(
129823 Blob *pHint, /* Hint blob to append to */
129824 i64 iAbsLevel, /* First varint to store in hint */
129825 int nInput, /* Second varint to store in hint */
129826 int *pRc /* IN/OUT: Error code */
129827 ){
129828 blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc);
129829 if( *pRc==SQLITE_OK ){
129830 pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel);
129831 pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput);
129832 }
129833 }
129834
129835 /*
129836 ** Read the last entry (most recently pushed) from the hint blob *pHint
129837 ** and then remove the entry. Write the two values read to *piAbsLevel and
129838 ** *pnInput before returning.
129839 **
129840 ** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
129841 ** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB.
129842 */
129843 static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
129844 const int nHint = pHint->n;
129845 int i;
129846
129847 i = pHint->n-2;
129848 while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
129849 while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
129850
129851 pHint->n = i;
129852 i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
129853 i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput);
129854 if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
129855
129856 return SQLITE_OK;
129857 }
129858
129859
129860 /*
129861 ** Attempt an incremental merge that writes nMerge leaf blocks.
129862 **
129863 ** Incremental merges happen nMin segments at a time. The two
129864 ** segments to be merged are the nMin oldest segments (the ones with
129865 ** the smallest indexes) in the highest level that contains at least
129866 ** nMin segments. Multiple merges might occur in an attempt to write the
129867 ** quota of nMerge leaf blocks.
129868 */
129869 SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
129870 int rc; /* Return code */
129871 int nRem = nMerge; /* Number of leaf pages yet to be written */
129872 Fts3MultiSegReader *pCsr; /* Cursor used to read input data */
129873 Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */
129874 IncrmergeWriter *pWriter; /* Writer object */
129875 int nSeg = 0; /* Number of input segments */
129876 sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */
129877 Blob hint = {0, 0, 0}; /* Hint read from %_stat table */
129878 int bDirtyHint = 0; /* True if blob 'hint' has been modified */
129879
129880 /* Allocate space for the cursor, filter and writer objects */
129881 const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
129882 pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
129883 if( !pWriter ) return SQLITE_NOMEM;
129884 pFilter = (Fts3SegFilter *)&pWriter[1];
129885 pCsr = (Fts3MultiSegReader *)&pFilter[1];
129886
129887 rc = fts3IncrmergeHintLoad(p, &hint);
129888 while( rc==SQLITE_OK && nRem>0 ){
129889 const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
129890 sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
129891 int bUseHint = 0; /* True if attempting to append */
129892
129893 /* Search the %_segdir table for the absolute level with the smallest
129894 ** relative level number that contains at least nMin segments, if any.
129895 ** If one is found, set iAbsLevel to the absolute level number and
129896 ** nSeg to nMin. If no level with at least nMin segments can be found,
129897 ** set nSeg to -1.
129898 */
129899 rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
129900 sqlite3_bind_int(pFindLevel, 1, nMin);
129901 if( sqlite3_step(pFindLevel)==SQLITE_ROW ){
129902 iAbsLevel = sqlite3_column_int64(pFindLevel, 0);
129903 nSeg = nMin;
129904 }else{
129905 nSeg = -1;
129906 }
129907 rc = sqlite3_reset(pFindLevel);
129908
129909 /* If the hint read from the %_stat table is not empty, check if the
129910 ** last entry in it specifies a relative level smaller than or equal
129911 ** to the level identified by the block above (if any). If so, this
129912 ** iteration of the loop will work on merging at the hinted level.
129913 */
129914 if( rc==SQLITE_OK && hint.n ){
129915 int nHint = hint.n;
129916 sqlite3_int64 iHintAbsLevel = 0; /* Hint level */
129917 int nHintSeg = 0; /* Hint number of segments */
129918
129919 rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
129920 if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
129921 iAbsLevel = iHintAbsLevel;
129922 nSeg = nHintSeg;
129923 bUseHint = 1;
129924 bDirtyHint = 1;
129925 }else{
129926 /* This undoes the effect of the HintPop() above - so that no entry
129927 ** is removed from the hint blob. */
129928 hint.n = nHint;
129929 }
129930 }
129931
129932 /* If nSeg is less that zero, then there is no level with at least
129933 ** nMin segments and no hint in the %_stat table. No work to do.
129934 ** Exit early in this case. */
129935 if( nSeg<0 ) break;
129936
129937 /* Open a cursor to iterate through the contents of the oldest nSeg
129938 ** indexes of absolute level iAbsLevel. If this cursor is opened using
129939 ** the 'hint' parameters, it is possible that there are less than nSeg
129940 ** segments available in level iAbsLevel. In this case, no work is
129941 ** done on iAbsLevel - fall through to the next iteration of the loop
129942 ** to start work on some other level. */
129943 memset(pWriter, 0, nAlloc);
129944 pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
129945 if( rc==SQLITE_OK ){
129946 rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
129947 }
129948 if( SQLITE_OK==rc && pCsr->nSegment==nSeg
129949 && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
129950 && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
129951 ){
129952 int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
129953 rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
129954 if( rc==SQLITE_OK ){
129955 if( bUseHint && iIdx>0 ){
129956 const char *zKey = pCsr->zTerm;
129957 int nKey = pCsr->nTerm;
129958 rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
129959 }else{
129960 rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
129961 }
129962 }
129963
129964 if( rc==SQLITE_OK && pWriter->nLeafEst ){
129965 fts3LogMerge(nSeg, iAbsLevel);
129966 do {
129967 rc = fts3IncrmergeAppend(p, pWriter, pCsr);
129968 if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
129969 if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
129970 }while( rc==SQLITE_ROW );
129971
129972 /* Update or delete the input segments */
129973 if( rc==SQLITE_OK ){
129974 nRem -= (1 + pWriter->nWork);
129975 rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg);
129976 if( nSeg!=0 ){
129977 bDirtyHint = 1;
129978 fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc);
129979 }
129980 }
129981 }
129982
129983 fts3IncrmergeRelease(p, pWriter, &rc);
129984 }
129985
129986 sqlite3Fts3SegReaderFinish(pCsr);
129987 }
129988
129989 /* Write the hint values into the %_stat table for the next incr-merger */
129990 if( bDirtyHint && rc==SQLITE_OK ){
129991 rc = fts3IncrmergeHintStore(p, &hint);
129992 }
129993
129994 sqlite3_free(pWriter);
129995 sqlite3_free(hint.a);
129996 return rc;
129997 }
129998
129999 /*
130000 ** Convert the text beginning at *pz into an integer and return
130001 ** its value. Advance *pz to point to the first character past
130002 ** the integer.
130003 */
130004 static int fts3Getint(const char **pz){
130005 const char *z = *pz;
130006 int i = 0;
130007 while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
130008 *pz = z;
130009 return i;
130010 }
130011
130012 /*
130013 ** Process statements of the form:
130014 **
130015 ** INSERT INTO table(table) VALUES('merge=A,B');
130016 **
130017 ** A and B are integers that decode to be the number of leaf pages
130018 ** written for the merge, and the minimum number of segments on a level
130019 ** before it will be selected for a merge, respectively.
130020 */
130021 static int fts3DoIncrmerge(
130022 Fts3Table *p, /* FTS3 table handle */
130023 const char *zParam /* Nul-terminated string containing "A,B" */
130024 ){
130025 int rc;
130026 int nMin = (FTS3_MERGE_COUNT / 2);
130027 int nMerge = 0;
130028 const char *z = zParam;
130029
130030 /* Read the first integer value */
130031 nMerge = fts3Getint(&z);
130032
130033 /* If the first integer value is followed by a ',', read the second
130034 ** integer value. */
130035 if( z[0]==',' && z[1]!='\0' ){
130036 z++;
130037 nMin = fts3Getint(&z);
130038 }
130039
130040 if( z[0]!='\0' || nMin<2 ){
130041 rc = SQLITE_ERROR;
130042 }else{
130043 rc = SQLITE_OK;
130044 if( !p->bHasStat ){
130045 assert( p->bFts4==0 );
130046 sqlite3Fts3CreateStatTable(&rc, p);
130047 }
130048 if( rc==SQLITE_OK ){
130049 rc = sqlite3Fts3Incrmerge(p, nMerge, nMin);
130050 }
130051 sqlite3Fts3SegmentsClose(p);
130052 }
130053 return rc;
130054 }
130055
130056 /*
130057 ** Process statements of the form:
130058 **
130059 ** INSERT INTO table(table) VALUES('automerge=X');
130060 **
130061 ** where X is an integer. X==0 means to turn automerge off. X!=0 means
130062 ** turn it on. The setting is persistent.
130063 */
130064 static int fts3DoAutoincrmerge(
130065 Fts3Table *p, /* FTS3 table handle */
130066 const char *zParam /* Nul-terminated string containing boolean */
130067 ){
130068 int rc = SQLITE_OK;
130069 sqlite3_stmt *pStmt = 0;
130070 p->bAutoincrmerge = fts3Getint(&zParam)!=0;
130071 if( !p->bHasStat ){
130072 assert( p->bFts4==0 );
130073 sqlite3Fts3CreateStatTable(&rc, p);
130074 if( rc ) return rc;
130075 }
130076 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
130077 if( rc ) return rc;;
130078 sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
130079 sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
130080 sqlite3_step(pStmt);
130081 rc = sqlite3_reset(pStmt);
130082 return rc;
130083 }
130084
130085 /*
130086 ** Return a 64-bit checksum for the FTS index entry specified by the
130087 ** arguments to this function.
130088 */
130089 static u64 fts3ChecksumEntry(
130090 const char *zTerm, /* Pointer to buffer containing term */
130091 int nTerm, /* Size of zTerm in bytes */
130092 int iLangid, /* Language id for current row */
130093 int iIndex, /* Index (0..Fts3Table.nIndex-1) */
130094 i64 iDocid, /* Docid for current row. */
130095 int iCol, /* Column number */
130096 int iPos /* Position */
130097 ){
130098 int i;
130099 u64 ret = (u64)iDocid;
130100
130101 ret += (ret<<3) + iLangid;
130102 ret += (ret<<3) + iIndex;
130103 ret += (ret<<3) + iCol;
130104 ret += (ret<<3) + iPos;
130105 for(i=0; i<nTerm; i++) ret += (ret<<3) + zTerm[i];
130106
130107 return ret;
130108 }
130109
130110 /*
130111 ** Return a checksum of all entries in the FTS index that correspond to
130112 ** language id iLangid. The checksum is calculated by XORing the checksums
130113 ** of each individual entry (see fts3ChecksumEntry()) together.
130114 **
130115 ** If successful, the checksum value is returned and *pRc set to SQLITE_OK.
130116 ** Otherwise, if an error occurs, *pRc is set to an SQLite error code. The
130117 ** return value is undefined in this case.
130118 */
130119 static u64 fts3ChecksumIndex(
130120 Fts3Table *p, /* FTS3 table handle */
130121 int iLangid, /* Language id to return cksum for */
130122 int iIndex, /* Index to cksum (0..p->nIndex-1) */
130123 int *pRc /* OUT: Return code */
130124 ){
130125 Fts3SegFilter filter;
130126 Fts3MultiSegReader csr;
130127 int rc;
130128 u64 cksum = 0;
130129
130130 assert( *pRc==SQLITE_OK );
130131
130132 memset(&filter, 0, sizeof(filter));
130133 memset(&csr, 0, sizeof(csr));
130134 filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
130135 filter.flags |= FTS3_SEGMENT_SCAN;
130136
130137 rc = sqlite3Fts3SegReaderCursor(
130138 p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr
130139 );
130140 if( rc==SQLITE_OK ){
130141 rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
130142 }
130143
130144 if( rc==SQLITE_OK ){
130145 while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){
130146 char *pCsr = csr.aDoclist;
130147 char *pEnd = &pCsr[csr.nDoclist];
130148
130149 i64 iDocid = 0;
130150 i64 iCol = 0;
130151 i64 iPos = 0;
130152
130153 pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
130154 while( pCsr<pEnd ){
130155 i64 iVal = 0;
130156 pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
130157 if( pCsr<pEnd ){
130158 if( iVal==0 || iVal==1 ){
130159 iCol = 0;
130160 iPos = 0;
130161 if( iVal ){
130162 pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
130163 }else{
130164 pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
130165 iDocid += iVal;
130166 }
130167 }else{
130168 iPos += (iVal - 2);
130169 cksum = cksum ^ fts3ChecksumEntry(
130170 csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid,
130171 (int)iCol, (int)iPos
130172 );
130173 }
130174 }
130175 }
130176 }
130177 }
130178 sqlite3Fts3SegReaderFinish(&csr);
130179
130180 *pRc = rc;
130181 return cksum;
130182 }
130183
130184 /*
130185 ** Check if the contents of the FTS index match the current contents of the
130186 ** content table. If no error occurs and the contents do match, set *pbOk
130187 ** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
130188 ** to false before returning.
130189 **
130190 ** If an error occurs (e.g. an OOM or IO error), return an SQLite error
130191 ** code. The final value of *pbOk is undefined in this case.
130192 */
130193 static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
130194 int rc = SQLITE_OK; /* Return code */
130195 u64 cksum1 = 0; /* Checksum based on FTS index contents */
130196 u64 cksum2 = 0; /* Checksum based on %_content contents */
130197 sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */
130198
130199 /* This block calculates the checksum according to the FTS index. */
130200 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
130201 if( rc==SQLITE_OK ){
130202 int rc2;
130203 sqlite3_bind_int(pAllLangid, 1, p->nIndex);
130204 while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
130205 int iLangid = sqlite3_column_int(pAllLangid, 0);
130206 int i;
130207 for(i=0; i<p->nIndex; i++){
130208 cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
130209 }
130210 }
130211 rc2 = sqlite3_reset(pAllLangid);
130212 if( rc==SQLITE_OK ) rc = rc2;
130213 }
130214
130215 /* This block calculates the checksum according to the %_content table */
130216 rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
130217 if( rc==SQLITE_OK ){
130218 sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
130219 sqlite3_stmt *pStmt = 0;
130220 char *zSql;
130221
130222 zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
130223 if( !zSql ){
130224 rc = SQLITE_NOMEM;
130225 }else{
130226 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
130227 sqlite3_free(zSql);
130228 }
130229
130230 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
130231 i64 iDocid = sqlite3_column_int64(pStmt, 0);
130232 int iLang = langidFromSelect(p, pStmt);
130233 int iCol;
130234
130235 for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
130236 const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
130237 int nText = sqlite3_column_bytes(pStmt, iCol+1);
130238 sqlite3_tokenizer_cursor *pT = 0;
130239
130240 rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
130241 while( rc==SQLITE_OK ){
130242 char const *zToken; /* Buffer containing token */
130243 int nToken; /* Number of bytes in token */
130244 int iDum1, iDum2; /* Dummy variables */
130245 int iPos; /* Position of token in zText */
130246
130247 rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
130248 if( rc==SQLITE_OK ){
130249 int i;
130250 cksum2 = cksum2 ^ fts3ChecksumEntry(
130251 zToken, nToken, iLang, 0, iDocid, iCol, iPos
130252 );
130253 for(i=1; i<p->nIndex; i++){
130254 if( p->aIndex[i].nPrefix<=nToken ){
130255 cksum2 = cksum2 ^ fts3ChecksumEntry(
130256 zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
130257 );
130258 }
130259 }
130260 }
130261 }
130262 if( pT ) pModule->xClose(pT);
130263 if( rc==SQLITE_DONE ) rc = SQLITE_OK;
130264 }
130265 }
130266
130267 sqlite3_finalize(pStmt);
130268 }
130269
130270 *pbOk = (cksum1==cksum2);
130271 return rc;
130272 }
130273
130274 /*
130275 ** Run the integrity-check. If no error occurs and the current contents of
130276 ** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
130277 ** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
130278 **
130279 ** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
130280 ** error code.
130281 **
130282 ** The integrity-check works as follows. For each token and indexed token
130283 ** prefix in the document set, a 64-bit checksum is calculated (by code
130284 ** in fts3ChecksumEntry()) based on the following:
130285 **
130286 ** + The index number (0 for the main index, 1 for the first prefix
130287 ** index etc.),
130288 ** + The token (or token prefix) text itself,
130289 ** + The language-id of the row it appears in,
130290 ** + The docid of the row it appears in,
130291 ** + The column it appears in, and
130292 ** + The tokens position within that column.
130293 **
130294 ** The checksums for all entries in the index are XORed together to create
130295 ** a single checksum for the entire index.
130296 **
130297 ** The integrity-check code calculates the same checksum in two ways:
130298 **
130299 ** 1. By scanning the contents of the FTS index, and
130300 ** 2. By scanning and tokenizing the content table.
130301 **
130302 ** If the two checksums are identical, the integrity-check is deemed to have
130303 ** passed.
130304 */
130305 static int fts3DoIntegrityCheck(
130306 Fts3Table *p /* FTS3 table handle */
130307 ){
130308 int rc;
130309 int bOk = 0;
130310 rc = fts3IntegrityCheck(p, &bOk);
130311 if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
130312 return rc;
130313 }
130314
130315 /*
130316 ** Handle a 'special' INSERT of the form:
130317 **
130318 ** "INSERT INTO tbl(tbl) VALUES(<expr>)"
130319 **
@@ -127869,10 +130329,16 @@
130329 return SQLITE_NOMEM;
130330 }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
130331 rc = fts3DoOptimize(p, 0);
130332 }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
130333 rc = fts3DoRebuild(p);
130334 }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){
130335 rc = fts3DoIntegrityCheck(p);
130336 }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){
130337 rc = fts3DoIncrmerge(p, &zVal[6]);
130338 }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
130339 rc = fts3DoAutoincrmerge(p, &zVal[10]);
130340 #ifdef SQLITE_TEST
130341 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
130342 p->nNodeSize = atoi(&zVal[9]);
130343 rc = SQLITE_OK;
130344 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
@@ -127937,18 +130403,17 @@
130403
130404 for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
130405 const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
130406 sqlite3_tokenizer_cursor *pTC = 0;
130407
130408 rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
130409 while( rc==SQLITE_OK ){
130410 char const *zToken; /* Buffer containing token */
130411 int nToken; /* Number of bytes in token */
130412 int iDum1, iDum2; /* Dummy variables */
130413 int iPos; /* Position of token in zText */
130414
 
130415 rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
130416 for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
130417 Fts3PhraseToken *pPT = pDef->pToken;
130418 if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
130419 && (pPT->bFirst==0 || iPos==0)
@@ -128044,12 +130509,10 @@
130509 ** delete the contents of all three tables and throw away any
130510 ** data in the pendingTerms hash table. */
130511 rc = fts3DeleteAll(p, 1);
130512 *pnDoc = *pnDoc - 1;
130513 }else{
 
 
130514 fts3DeleteTerms(&rc, p, pRowid, aSzDel);
130515 if( p->zContentTbl==0 ){
130516 fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
130517 if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
130518 }else{
@@ -128064,11 +130527,20 @@
130527 return rc;
130528 }
130529
130530 /*
130531 ** This function does the work for the xUpdate method of FTS3 virtual
130532 ** tables. The schema of the virtual table being:
130533 **
130534 ** CREATE TABLE <table name>(
130535 ** <user columns>,
130536 ** <table name> HIDDEN,
130537 ** docid HIDDEN,
130538 ** <langid> HIDDEN
130539 ** );
130540 **
130541 **
130542 */
130543 SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
130544 sqlite3_vtab *pVtab, /* FTS3 vtab object */
130545 int nArg, /* Size of argument array */
130546 sqlite3_value **apVal, /* Array of arguments */
@@ -128081,10 +130553,14 @@
130553 u32 *aSzDel; /* Sizes of deleted documents */
130554 int nChng = 0; /* Net change in number of documents */
130555 int bInsertDone = 0;
130556
130557 assert( p->pSegments==0 );
130558 assert(
130559 nArg==1 /* DELETE operations */
130560 || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */
130561 );
130562
130563 /* Check for a "special" INSERT operation. One of the form:
130564 **
130565 ** INSERT INTO xyz(xyz) VALUES('command');
130566 */
@@ -128093,10 +130569,15 @@
130569 && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
130570 ){
130571 rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
130572 goto update_out;
130573 }
130574
130575 if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){
130576 rc = SQLITE_CONSTRAINT;
130577 goto update_out;
130578 }
130579
130580 /* Allocate space to hold the change in document sizes */
130581 aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
130582 if( aSzIns==0 ){
130583 rc = SQLITE_NOMEM;
@@ -128161,30 +130642,31 @@
130642 isRemove = 1;
130643 }
130644
130645 /* If this is an INSERT or UPDATE operation, insert the new record. */
130646 if( nArg>1 && rc==SQLITE_OK ){
130647 int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]);
130648 if( bInsertDone==0 ){
130649 rc = fts3InsertData(p, apVal, pRowid);
130650 if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
130651 rc = FTS_CORRUPT_VTAB;
130652 }
130653 }
130654 if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
130655 rc = fts3PendingTermsDocid(p, iLangid, *pRowid);
130656 }
130657 if( rc==SQLITE_OK ){
130658 assert( p->iPrevDocid==*pRowid );
130659 rc = fts3InsertTerms(p, iLangid, apVal, aSzIns);
130660 }
130661 if( p->bHasDocsize ){
130662 fts3InsertDocsize(&rc, p, aSzIns);
130663 }
130664 nChng++;
130665 }
130666
130667 if( p->bFts4 ){
130668 fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
130669 }
130670
130671 update_out:
130672 sqlite3_free(aSzIns);
@@ -128749,10 +131231,11 @@
131231 ** is no way for fts3BestSnippet() to know whether or not the document
131232 ** actually contains terms that follow the final highlighted term.
131233 */
131234 static int fts3SnippetShift(
131235 Fts3Table *pTab, /* FTS3 table snippet comes from */
131236 int iLangid, /* Language id to use in tokenizing */
131237 int nSnippet, /* Number of tokens desired for snippet */
131238 const char *zDoc, /* Document text to extract snippet from */
131239 int nDoc, /* Size of buffer zDoc in bytes */
131240 int *piPos, /* IN/OUT: First token of snippet */
131241 u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
@@ -128784,15 +131267,14 @@
131267 pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
131268
131269 /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
131270 ** or more tokens in zDoc/nDoc.
131271 */
131272 rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC);
131273 if( rc!=SQLITE_OK ){
131274 return rc;
131275 }
 
131276 while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
131277 const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
131278 rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
131279 }
131280 pMod->xClose(pC);
@@ -128848,15 +131330,14 @@
131330 }
131331 nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
131332
131333 /* Open a token cursor on the document. */
131334 pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
131335 rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC);
131336 if( rc!=SQLITE_OK ){
131337 return rc;
131338 }
 
131339
131340 while( rc==SQLITE_OK ){
131341 int iBegin; /* Offset in zDoc of start of token */
131342 int iFin; /* Offset in zDoc of end of token */
131343 int isHighlight; /* True for highlighted terms */
@@ -128874,11 +131355,13 @@
131355 }
131356 if( iCurrent<iPos ){ continue; }
131357
131358 if( !isShiftDone ){
131359 int n = nDoc - iBegin;
131360 rc = fts3SnippetShift(
131361 pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask
131362 );
131363 isShiftDone = 1;
131364
131365 /* Now that the shift has been done, check if the initial "..." are
131366 ** required. They are required if (a) this is not the first fragment,
131367 ** or (b) this fragment does not begin at position 0 of its column.
@@ -129010,12 +131493,12 @@
131493 char cArg,
131494 char **pzErr
131495 ){
131496 if( (cArg==FTS3_MATCHINFO_NPHRASE)
131497 || (cArg==FTS3_MATCHINFO_NCOL)
131498 || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4)
131499 || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4)
131500 || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
131501 || (cArg==FTS3_MATCHINFO_LCS)
131502 || (cArg==FTS3_MATCHINFO_HITS)
131503 ){
131504 return SQLITE_OK;
@@ -129607,13 +132090,14 @@
132090 rc = SQLITE_NOMEM;
132091 goto offsets_out;
132092 }
132093
132094 /* Initialize a tokenizer iterator to iterate through column iCol. */
132095 rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid,
132096 zDoc, nDoc, &pC
132097 );
132098 if( rc!=SQLITE_OK ) goto offsets_out;
 
132099
132100 rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
132101 while( rc==SQLITE_OK ){
132102 int i; /* Used to loop through terms */
132103 int iMinPos = 0x7FFFFFFF; /* Position of next token */
@@ -132774,12 +135258,12 @@
135258 }
135259
135260 sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
135261
135262 /* Allocate the sqlite3_vtab structure */
135263 nDb = (int)strlen(argv[1]);
135264 nName = (int)strlen(argv[2]);
135265 pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
135266 if( !pRtree ){
135267 return SQLITE_NOMEM;
135268 }
135269 memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
@@ -132870,14 +135354,14 @@
135354 RtreeCell cell;
135355 int jj;
135356
135357 nodeGetCell(&tree, &node, ii, &cell);
135358 sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
135359 nCell = (int)strlen(zCell);
135360 for(jj=0; jj<tree.nDim*2; jj++){
135361 sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);
135362 nCell = (int)strlen(zCell);
135363 }
135364
135365 if( zText ){
135366 char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
135367 sqlite3_free(zText);
@@ -133616,11 +136100,14 @@
136100 int iInput = 0;
136101 int iOut = 0;
136102
136103 *ppCursor = 0;
136104
136105 if( zInput==0 ){
136106 nInput = 0;
136107 zInput = "";
136108 }else if( nInput<0 ){
136109 nInput = strlen(zInput);
136110 }
136111 nChar = nInput+1;
136112 pCsr = (IcuCursor *)sqlite3_malloc(
136113 sizeof(IcuCursor) + /* IcuCursor */
136114
+66 -9
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.7.11"
111
-#define SQLITE_VERSION_NUMBER 3007011
112
-#define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130"
110
+#define SQLITE_VERSION "3.7.12"
111
+#define SQLITE_VERSION_NUMBER 3007012
112
+#define SQLITE_SOURCE_ID "2012-03-31 19:12:23 af602d87736b52802a4e760ffeeaa28112b99d9a"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -459,10 +459,11 @@
459459
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
460460
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
461461
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
462462
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
463463
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
464
+#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
464465
465466
/*
466467
** CAPI3REF: Flags For File Open Operations
467468
**
468469
** These bit values are intended for use in the
@@ -714,31 +715,35 @@
714715
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
715716
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
716717
** into an integer that the pArg argument points to. This capability
717718
** is used during testing and only needs to be supported when SQLITE_TEST
718719
** is defined.
719
-**
720
+** <ul>
721
+** <li>[[SQLITE_FCNTL_SIZE_HINT]]
720722
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
721723
** layer a hint of how large the database file will grow to be during the
722724
** current transaction. This hint is not guaranteed to be accurate but it
723725
** is often close. The underlying VFS might choose to preallocate database
724726
** file space based on this hint in order to help writes to the database
725727
** file run faster.
726728
**
729
+** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
727730
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
728731
** extends and truncates the database file in chunks of a size specified
729732
** by the user. The fourth argument to [sqlite3_file_control()] should
730733
** point to an integer (type int) containing the new chunk-size to use
731734
** for the nominated database. Allocating database file space in large
732735
** chunks (say 1MB at a time), may reduce file-system fragmentation and
733736
** improve performance on some systems.
734737
**
738
+** <li>[[SQLITE_FCNTL_FILE_POINTER]]
735739
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
736740
** to the [sqlite3_file] object associated with a particular database
737741
** connection. See the [sqlite3_file_control()] documentation for
738742
** additional information.
739743
**
744
+** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
740745
** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
741746
** SQLite and sent to all VFSes in place of a call to the xSync method
742747
** when the database connection has [PRAGMA synchronous] set to OFF.)^
743748
** Some specialized VFSes need this signal in order to operate correctly
744749
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
@@ -745,10 +750,11 @@
745750
** VFSes do not need this signal and should silently ignore this opcode.
746751
** Applications should not call [sqlite3_file_control()] with this
747752
** opcode as doing so may disrupt the operation of the specialized VFSes
748753
** that do require it.
749754
**
755
+** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
750756
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
751757
** retry counts and intervals for certain disk I/O operations for the
752758
** windows [VFS] in order to provide robustness in the presence of
753759
** anti-virus programs. By default, the windows VFS will retry file read,
754760
** file write, and file delete operations up to 10 times, with a delay
@@ -761,10 +767,11 @@
761767
** integer is the delay. If either integer is negative, then the setting
762768
** is not changed but instead the prior value of that setting is written
763769
** into the array entry, allowing the current retry settings to be
764770
** interrogated. The zDbName parameter is ignored.
765771
**
772
+** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
766773
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
767774
** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
768775
** write ahead log and shared memory files used for transaction control
769776
** are automatically deleted when the latest connection to the database
770777
** closes. Setting persistent WAL mode causes those files to persist after
@@ -775,24 +782,27 @@
775782
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
776783
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
777784
** WAL mode. If the integer is -1, then it is overwritten with the current
778785
** WAL persistence setting.
779786
**
787
+** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
780788
** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
781789
** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
782790
** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
783791
** xDeviceCharacteristics methods. The fourth parameter to
784792
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
785793
** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
786794
** mode. If the integer is -1, then it is overwritten with the current
787795
** zero-damage mode setting.
788796
**
797
+** <li>[[SQLITE_FCNTL_OVERWRITE]]
789798
** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
790799
** a write transaction to indicate that, unless it is rolled back for some
791800
** reason, the entire database file will be overwritten by the current
792801
** transaction. This is used by VACUUM operations.
793802
**
803
+** <li>[[SQLITE_FCNTL_VFSNAME]]
794804
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
795805
** all [VFSes] in the VFS stack. The names are of all VFS shims and the
796806
** final bottom-level VFS are written into memory obtained from
797807
** [sqlite3_malloc()] and the result is stored in the char* variable
798808
** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -799,10 +809,34 @@
799809
** The caller is responsible for freeing the memory when done. As with
800810
** all file-control actions, there is no guarantee that this will actually
801811
** do anything. Callers should initialize the char* variable to a NULL
802812
** pointer in case this file-control is not implemented. This file-control
803813
** is intended for diagnostic use only.
814
+**
815
+** <li>[[SQLITE_FCNTL_PRAGMA]]
816
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
817
+** file control is sent to the open [sqlite3_file] object corresponding
818
+** to the database file to which the pragma statement refers. ^The argument
819
+** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
820
+** pointers to strings (char**) in which the second element of the array
821
+** is the name of the pragma and the third element is the argument to the
822
+** pragma or NULL if the pragma has no argument. ^The handler for an
823
+** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
824
+** of the char** argument point to a string obtained from [sqlite3_mprintf()]
825
+** or the equivalent and that string will become the result of the pragma or
826
+** the error message if the pragma fails. ^If the
827
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
828
+** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
829
+** file control returns [SQLITE_OK], then the parser assumes that the
830
+** VFS has handled the PRAGMA itself and the parser generates a no-op
831
+** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
832
+** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
833
+** that the VFS encountered an error while handling the [PRAGMA] and the
834
+** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
835
+** file control occurs at the beginning of pragma statement analysis and so
836
+** it is able to override built-in [PRAGMA] statements.
837
+** </ul>
804838
*/
805839
#define SQLITE_FCNTL_LOCKSTATE 1
806840
#define SQLITE_GET_LOCKPROXYFILE 2
807841
#define SQLITE_SET_LOCKPROXYFILE 3
808842
#define SQLITE_LAST_ERRNO 4
@@ -813,10 +847,11 @@
813847
#define SQLITE_FCNTL_WIN32_AV_RETRY 9
814848
#define SQLITE_FCNTL_PERSIST_WAL 10
815849
#define SQLITE_FCNTL_OVERWRITE 11
816850
#define SQLITE_FCNTL_VFSNAME 12
817851
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
852
+#define SQLITE_FCNTL_PRAGMA 14
818853
819854
/*
820855
** CAPI3REF: Mutex Handle
821856
**
822857
** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -4462,10 +4497,19 @@
44624497
** will be an absolute pathname, even if the filename used
44634498
** to open the database originally was a URI or relative pathname.
44644499
*/
44654500
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
44664501
4502
+/*
4503
+** CAPI3REF: Determine if a database is read-only
4504
+**
4505
+** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
4506
+** of connection D is read-only, 0 if it is read/write, or -1 if N is not
4507
+** the name of a database on connection D.
4508
+*/
4509
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
4510
+
44674511
/*
44684512
** CAPI3REF: Find the next prepared statement
44694513
**
44704514
** ^This interface returns a pointer to the next [prepared statement] after
44714515
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -5960,10 +6004,21 @@
59606004
** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
59616005
** <dd>This parameter returns the number of pager cache misses that have
59626006
** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
59636007
** is always 0.
59646008
** </dd>
6009
+**
6010
+** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
6011
+** <dd>This parameter returns the number of dirty cache entries that have
6012
+** been written to disk. Specifically, the number of pages written to the
6013
+** wal file in wal mode databases, or the number of pages written to the
6014
+** database file in rollback mode databases. Any pages written as part of
6015
+** transaction rollback or database recovery operations are not included.
6016
+** If an IO or other error occurs while writing a page to disk, the effect
6017
+** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The
6018
+** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
6019
+** </dd>
59656020
** </dl>
59666021
*/
59676022
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
59686023
#define SQLITE_DBSTATUS_CACHE_USED 1
59696024
#define SQLITE_DBSTATUS_SCHEMA_USED 2
@@ -5971,11 +6026,12 @@
59716026
#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
59726027
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
59736028
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
59746029
#define SQLITE_DBSTATUS_CACHE_HIT 7
59756030
#define SQLITE_DBSTATUS_CACHE_MISS 8
5976
-#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */
6031
+#define SQLITE_DBSTATUS_CACHE_WRITE 9
6032
+#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
59776033
59786034
59796035
/*
59806036
** CAPI3REF: Prepared Statement Status
59816037
**
@@ -6587,15 +6643,16 @@
65876643
65886644
65896645
/*
65906646
** CAPI3REF: String Comparison
65916647
**
6592
-** ^The [sqlite3_strnicmp()] API allows applications and extensions to
6593
-** compare the contents of two buffers containing UTF-8 strings in a
6594
-** case-independent fashion, using the same definition of case independence
6595
-** that SQLite uses internally when comparing identifiers.
6648
+** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
6649
+** and extensions to compare the contents of two buffers containing UTF-8
6650
+** strings in a case-independent fashion, using the same definition of "case
6651
+** independence" that SQLite uses internally when comparing identifiers.
65966652
*/
6653
+SQLITE_API int sqlite3_stricmp(const char *, const char *);
65976654
SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
65986655
65996656
/*
66006657
** CAPI3REF: Error Logging Interface
66016658
**
66026659
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.11"
111 #define SQLITE_VERSION_NUMBER 3007011
112 #define SQLITE_SOURCE_ID "2012-02-13 20:16:37 84b324606adc8437338c086404eb157f30f04130"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -459,10 +459,11 @@
459 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
460 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
461 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
462 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
463 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
 
464
465 /*
466 ** CAPI3REF: Flags For File Open Operations
467 **
468 ** These bit values are intended for use in the
@@ -714,31 +715,35 @@
714 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
715 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
716 ** into an integer that the pArg argument points to. This capability
717 ** is used during testing and only needs to be supported when SQLITE_TEST
718 ** is defined.
719 **
 
720 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
721 ** layer a hint of how large the database file will grow to be during the
722 ** current transaction. This hint is not guaranteed to be accurate but it
723 ** is often close. The underlying VFS might choose to preallocate database
724 ** file space based on this hint in order to help writes to the database
725 ** file run faster.
726 **
 
727 ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
728 ** extends and truncates the database file in chunks of a size specified
729 ** by the user. The fourth argument to [sqlite3_file_control()] should
730 ** point to an integer (type int) containing the new chunk-size to use
731 ** for the nominated database. Allocating database file space in large
732 ** chunks (say 1MB at a time), may reduce file-system fragmentation and
733 ** improve performance on some systems.
734 **
 
735 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
736 ** to the [sqlite3_file] object associated with a particular database
737 ** connection. See the [sqlite3_file_control()] documentation for
738 ** additional information.
739 **
 
740 ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
741 ** SQLite and sent to all VFSes in place of a call to the xSync method
742 ** when the database connection has [PRAGMA synchronous] set to OFF.)^
743 ** Some specialized VFSes need this signal in order to operate correctly
744 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
@@ -745,10 +750,11 @@
745 ** VFSes do not need this signal and should silently ignore this opcode.
746 ** Applications should not call [sqlite3_file_control()] with this
747 ** opcode as doing so may disrupt the operation of the specialized VFSes
748 ** that do require it.
749 **
 
750 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
751 ** retry counts and intervals for certain disk I/O operations for the
752 ** windows [VFS] in order to provide robustness in the presence of
753 ** anti-virus programs. By default, the windows VFS will retry file read,
754 ** file write, and file delete operations up to 10 times, with a delay
@@ -761,10 +767,11 @@
761 ** integer is the delay. If either integer is negative, then the setting
762 ** is not changed but instead the prior value of that setting is written
763 ** into the array entry, allowing the current retry settings to be
764 ** interrogated. The zDbName parameter is ignored.
765 **
 
766 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
767 ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
768 ** write ahead log and shared memory files used for transaction control
769 ** are automatically deleted when the latest connection to the database
770 ** closes. Setting persistent WAL mode causes those files to persist after
@@ -775,24 +782,27 @@
775 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
776 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
777 ** WAL mode. If the integer is -1, then it is overwritten with the current
778 ** WAL persistence setting.
779 **
 
780 ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
781 ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
782 ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
783 ** xDeviceCharacteristics methods. The fourth parameter to
784 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
785 ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
786 ** mode. If the integer is -1, then it is overwritten with the current
787 ** zero-damage mode setting.
788 **
 
789 ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
790 ** a write transaction to indicate that, unless it is rolled back for some
791 ** reason, the entire database file will be overwritten by the current
792 ** transaction. This is used by VACUUM operations.
793 **
 
794 ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
795 ** all [VFSes] in the VFS stack. The names are of all VFS shims and the
796 ** final bottom-level VFS are written into memory obtained from
797 ** [sqlite3_malloc()] and the result is stored in the char* variable
798 ** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -799,10 +809,34 @@
799 ** The caller is responsible for freeing the memory when done. As with
800 ** all file-control actions, there is no guarantee that this will actually
801 ** do anything. Callers should initialize the char* variable to a NULL
802 ** pointer in case this file-control is not implemented. This file-control
803 ** is intended for diagnostic use only.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
804 */
805 #define SQLITE_FCNTL_LOCKSTATE 1
806 #define SQLITE_GET_LOCKPROXYFILE 2
807 #define SQLITE_SET_LOCKPROXYFILE 3
808 #define SQLITE_LAST_ERRNO 4
@@ -813,10 +847,11 @@
813 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
814 #define SQLITE_FCNTL_PERSIST_WAL 10
815 #define SQLITE_FCNTL_OVERWRITE 11
816 #define SQLITE_FCNTL_VFSNAME 12
817 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
 
818
819 /*
820 ** CAPI3REF: Mutex Handle
821 **
822 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -4462,10 +4497,19 @@
4462 ** will be an absolute pathname, even if the filename used
4463 ** to open the database originally was a URI or relative pathname.
4464 */
4465 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
4466
 
 
 
 
 
 
 
 
 
4467 /*
4468 ** CAPI3REF: Find the next prepared statement
4469 **
4470 ** ^This interface returns a pointer to the next [prepared statement] after
4471 ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -5960,10 +6004,21 @@
5960 ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
5961 ** <dd>This parameter returns the number of pager cache misses that have
5962 ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
5963 ** is always 0.
5964 ** </dd>
 
 
 
 
 
 
 
 
 
 
 
5965 ** </dl>
5966 */
5967 #define SQLITE_DBSTATUS_LOOKASIDE_USED 0
5968 #define SQLITE_DBSTATUS_CACHE_USED 1
5969 #define SQLITE_DBSTATUS_SCHEMA_USED 2
@@ -5971,11 +6026,12 @@
5971 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
5972 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
5973 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
5974 #define SQLITE_DBSTATUS_CACHE_HIT 7
5975 #define SQLITE_DBSTATUS_CACHE_MISS 8
5976 #define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */
 
5977
5978
5979 /*
5980 ** CAPI3REF: Prepared Statement Status
5981 **
@@ -6587,15 +6643,16 @@
6587
6588
6589 /*
6590 ** CAPI3REF: String Comparison
6591 **
6592 ** ^The [sqlite3_strnicmp()] API allows applications and extensions to
6593 ** compare the contents of two buffers containing UTF-8 strings in a
6594 ** case-independent fashion, using the same definition of case independence
6595 ** that SQLite uses internally when comparing identifiers.
6596 */
 
6597 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
6598
6599 /*
6600 ** CAPI3REF: Error Logging Interface
6601 **
6602
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.12"
111 #define SQLITE_VERSION_NUMBER 3007012
112 #define SQLITE_SOURCE_ID "2012-03-31 19:12:23 af602d87736b52802a4e760ffeeaa28112b99d9a"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -459,10 +459,11 @@
459 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
460 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
461 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
462 #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
463 #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
464 #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
465
466 /*
467 ** CAPI3REF: Flags For File Open Operations
468 **
469 ** These bit values are intended for use in the
@@ -714,31 +715,35 @@
715 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
716 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
717 ** into an integer that the pArg argument points to. This capability
718 ** is used during testing and only needs to be supported when SQLITE_TEST
719 ** is defined.
720 ** <ul>
721 ** <li>[[SQLITE_FCNTL_SIZE_HINT]]
722 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
723 ** layer a hint of how large the database file will grow to be during the
724 ** current transaction. This hint is not guaranteed to be accurate but it
725 ** is often close. The underlying VFS might choose to preallocate database
726 ** file space based on this hint in order to help writes to the database
727 ** file run faster.
728 **
729 ** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
730 ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
731 ** extends and truncates the database file in chunks of a size specified
732 ** by the user. The fourth argument to [sqlite3_file_control()] should
733 ** point to an integer (type int) containing the new chunk-size to use
734 ** for the nominated database. Allocating database file space in large
735 ** chunks (say 1MB at a time), may reduce file-system fragmentation and
736 ** improve performance on some systems.
737 **
738 ** <li>[[SQLITE_FCNTL_FILE_POINTER]]
739 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
740 ** to the [sqlite3_file] object associated with a particular database
741 ** connection. See the [sqlite3_file_control()] documentation for
742 ** additional information.
743 **
744 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
745 ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
746 ** SQLite and sent to all VFSes in place of a call to the xSync method
747 ** when the database connection has [PRAGMA synchronous] set to OFF.)^
748 ** Some specialized VFSes need this signal in order to operate correctly
749 ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
@@ -745,10 +750,11 @@
750 ** VFSes do not need this signal and should silently ignore this opcode.
751 ** Applications should not call [sqlite3_file_control()] with this
752 ** opcode as doing so may disrupt the operation of the specialized VFSes
753 ** that do require it.
754 **
755 ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
756 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
757 ** retry counts and intervals for certain disk I/O operations for the
758 ** windows [VFS] in order to provide robustness in the presence of
759 ** anti-virus programs. By default, the windows VFS will retry file read,
760 ** file write, and file delete operations up to 10 times, with a delay
@@ -761,10 +767,11 @@
767 ** integer is the delay. If either integer is negative, then the setting
768 ** is not changed but instead the prior value of that setting is written
769 ** into the array entry, allowing the current retry settings to be
770 ** interrogated. The zDbName parameter is ignored.
771 **
772 ** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
773 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
774 ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary
775 ** write ahead log and shared memory files used for transaction control
776 ** are automatically deleted when the latest connection to the database
777 ** closes. Setting persistent WAL mode causes those files to persist after
@@ -775,24 +782,27 @@
782 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
783 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
784 ** WAL mode. If the integer is -1, then it is overwritten with the current
785 ** WAL persistence setting.
786 **
787 ** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
788 ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
789 ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
790 ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
791 ** xDeviceCharacteristics methods. The fourth parameter to
792 ** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
793 ** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
794 ** mode. If the integer is -1, then it is overwritten with the current
795 ** zero-damage mode setting.
796 **
797 ** <li>[[SQLITE_FCNTL_OVERWRITE]]
798 ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
799 ** a write transaction to indicate that, unless it is rolled back for some
800 ** reason, the entire database file will be overwritten by the current
801 ** transaction. This is used by VACUUM operations.
802 **
803 ** <li>[[SQLITE_FCNTL_VFSNAME]]
804 ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
805 ** all [VFSes] in the VFS stack. The names are of all VFS shims and the
806 ** final bottom-level VFS are written into memory obtained from
807 ** [sqlite3_malloc()] and the result is stored in the char* variable
808 ** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -799,10 +809,34 @@
809 ** The caller is responsible for freeing the memory when done. As with
810 ** all file-control actions, there is no guarantee that this will actually
811 ** do anything. Callers should initialize the char* variable to a NULL
812 ** pointer in case this file-control is not implemented. This file-control
813 ** is intended for diagnostic use only.
814 **
815 ** <li>[[SQLITE_FCNTL_PRAGMA]]
816 ** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
817 ** file control is sent to the open [sqlite3_file] object corresponding
818 ** to the database file to which the pragma statement refers. ^The argument
819 ** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
820 ** pointers to strings (char**) in which the second element of the array
821 ** is the name of the pragma and the third element is the argument to the
822 ** pragma or NULL if the pragma has no argument. ^The handler for an
823 ** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
824 ** of the char** argument point to a string obtained from [sqlite3_mprintf()]
825 ** or the equivalent and that string will become the result of the pragma or
826 ** the error message if the pragma fails. ^If the
827 ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
828 ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
829 ** file control returns [SQLITE_OK], then the parser assumes that the
830 ** VFS has handled the PRAGMA itself and the parser generates a no-op
831 ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
832 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
833 ** that the VFS encountered an error while handling the [PRAGMA] and the
834 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
835 ** file control occurs at the beginning of pragma statement analysis and so
836 ** it is able to override built-in [PRAGMA] statements.
837 ** </ul>
838 */
839 #define SQLITE_FCNTL_LOCKSTATE 1
840 #define SQLITE_GET_LOCKPROXYFILE 2
841 #define SQLITE_SET_LOCKPROXYFILE 3
842 #define SQLITE_LAST_ERRNO 4
@@ -813,10 +847,11 @@
847 #define SQLITE_FCNTL_WIN32_AV_RETRY 9
848 #define SQLITE_FCNTL_PERSIST_WAL 10
849 #define SQLITE_FCNTL_OVERWRITE 11
850 #define SQLITE_FCNTL_VFSNAME 12
851 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
852 #define SQLITE_FCNTL_PRAGMA 14
853
854 /*
855 ** CAPI3REF: Mutex Handle
856 **
857 ** The mutex module within SQLite defines [sqlite3_mutex] to be an
@@ -4462,10 +4497,19 @@
4497 ** will be an absolute pathname, even if the filename used
4498 ** to open the database originally was a URI or relative pathname.
4499 */
4500 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
4501
4502 /*
4503 ** CAPI3REF: Determine if a database is read-only
4504 **
4505 ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
4506 ** of connection D is read-only, 0 if it is read/write, or -1 if N is not
4507 ** the name of a database on connection D.
4508 */
4509 SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
4510
4511 /*
4512 ** CAPI3REF: Find the next prepared statement
4513 **
4514 ** ^This interface returns a pointer to the next [prepared statement] after
4515 ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -5960,10 +6004,21 @@
6004 ** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
6005 ** <dd>This parameter returns the number of pager cache misses that have
6006 ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
6007 ** is always 0.
6008 ** </dd>
6009 **
6010 ** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
6011 ** <dd>This parameter returns the number of dirty cache entries that have
6012 ** been written to disk. Specifically, the number of pages written to the
6013 ** wal file in wal mode databases, or the number of pages written to the
6014 ** database file in rollback mode databases. Any pages written as part of
6015 ** transaction rollback or database recovery operations are not included.
6016 ** If an IO or other error occurs while writing a page to disk, the effect
6017 ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The
6018 ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
6019 ** </dd>
6020 ** </dl>
6021 */
6022 #define SQLITE_DBSTATUS_LOOKASIDE_USED 0
6023 #define SQLITE_DBSTATUS_CACHE_USED 1
6024 #define SQLITE_DBSTATUS_SCHEMA_USED 2
@@ -5971,11 +6026,12 @@
6026 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
6027 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
6028 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
6029 #define SQLITE_DBSTATUS_CACHE_HIT 7
6030 #define SQLITE_DBSTATUS_CACHE_MISS 8
6031 #define SQLITE_DBSTATUS_CACHE_WRITE 9
6032 #define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
6033
6034
6035 /*
6036 ** CAPI3REF: Prepared Statement Status
6037 **
@@ -6587,15 +6643,16 @@
6643
6644
6645 /*
6646 ** CAPI3REF: String Comparison
6647 **
6648 ** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
6649 ** and extensions to compare the contents of two buffers containing UTF-8
6650 ** strings in a case-independent fashion, using the same definition of "case
6651 ** independence" that SQLite uses internally when comparing identifiers.
6652 */
6653 SQLITE_API int sqlite3_stricmp(const char *, const char *);
6654 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
6655
6656 /*
6657 ** CAPI3REF: Error Logging Interface
6658 **
6659
+20 -4
--- src/stat.c
+++ src/stat.c
@@ -19,10 +19,26 @@
1919
**
2020
*/
2121
#include <string.h>
2222
#include "config.h"
2323
#include "stat.h"
24
+
25
+/*
26
+** For a sufficiently large integer, provide an alternative
27
+** representation as MB or GB or TB.
28
+*/
29
+static void bigSizeName(int nOut, char *zOut, sqlite3_int64 v){
30
+ if( v<100000 ){
31
+ sqlite3_snprintf(nOut, zOut, "%lld bytes", v);
32
+ }else if( v<1000000000 ){
33
+ sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fMB)",
34
+ v, (double)v/1000000.0);
35
+ }else{
36
+ sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fGB)",
37
+ v, (double)v/1000000000.0);
38
+ }
39
+}
2440
2541
/*
2642
** WEBPAGE: stat
2743
**
2844
** Show statistics and global information about the repository.
@@ -40,12 +56,12 @@
4056
brief = P("brief")!=0;
4157
style_header("Repository Statistics");
4258
@ <table class="label-value">
4359
@ <tr><th>Repository&nbsp;Size:</th><td>
4460
fsize = file_size(g.zRepositoryName);
45
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", fsize);
46
- @ %s(zBuf) bytes
61
+ bigSizeName(sizeof(zBuf), zBuf, fsize);
62
+ @ %s(zBuf)
4763
@ </td></tr>
4864
if( !brief ){
4965
@ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
5066
n = db_int(0, "SELECT count(*) FROM blob");
5167
m = db_int(0, "SELECT count(*) FROM delta");
@@ -60,12 +76,12 @@
6076
db_step(&q);
6177
t = db_column_int64(&q, 0);
6278
szAvg = db_column_int(&q, 1);
6379
szMax = db_column_int(&q, 2);
6480
db_finalize(&q);
65
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
66
- @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
81
+ bigSizeName(sizeof(zBuf), zBuf, t);
82
+ @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) total
6783
@ </td></tr>
6884
@ <tr><th>Compression&nbsp;Ratio:</th><td>
6985
if( t/fsize < 5 ){
7086
b = 10;
7187
fsize /= 10;
7288
--- src/stat.c
+++ src/stat.c
@@ -19,10 +19,26 @@
19 **
20 */
21 #include <string.h>
22 #include "config.h"
23 #include "stat.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
25 /*
26 ** WEBPAGE: stat
27 **
28 ** Show statistics and global information about the repository.
@@ -40,12 +56,12 @@
40 brief = P("brief")!=0;
41 style_header("Repository Statistics");
42 @ <table class="label-value">
43 @ <tr><th>Repository&nbsp;Size:</th><td>
44 fsize = file_size(g.zRepositoryName);
45 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", fsize);
46 @ %s(zBuf) bytes
47 @ </td></tr>
48 if( !brief ){
49 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
50 n = db_int(0, "SELECT count(*) FROM blob");
51 m = db_int(0, "SELECT count(*) FROM delta");
@@ -60,12 +76,12 @@
60 db_step(&q);
61 t = db_column_int64(&q, 0);
62 szAvg = db_column_int(&q, 1);
63 szMax = db_column_int(&q, 2);
64 db_finalize(&q);
65 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
66 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
67 @ </td></tr>
68 @ <tr><th>Compression&nbsp;Ratio:</th><td>
69 if( t/fsize < 5 ){
70 b = 10;
71 fsize /= 10;
72
--- src/stat.c
+++ src/stat.c
@@ -19,10 +19,26 @@
19 **
20 */
21 #include <string.h>
22 #include "config.h"
23 #include "stat.h"
24
25 /*
26 ** For a sufficiently large integer, provide an alternative
27 ** representation as MB or GB or TB.
28 */
29 static void bigSizeName(int nOut, char *zOut, sqlite3_int64 v){
30 if( v<100000 ){
31 sqlite3_snprintf(nOut, zOut, "%lld bytes", v);
32 }else if( v<1000000000 ){
33 sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fMB)",
34 v, (double)v/1000000.0);
35 }else{
36 sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fGB)",
37 v, (double)v/1000000000.0);
38 }
39 }
40
41 /*
42 ** WEBPAGE: stat
43 **
44 ** Show statistics and global information about the repository.
@@ -40,12 +56,12 @@
56 brief = P("brief")!=0;
57 style_header("Repository Statistics");
58 @ <table class="label-value">
59 @ <tr><th>Repository&nbsp;Size:</th><td>
60 fsize = file_size(g.zRepositoryName);
61 bigSizeName(sizeof(zBuf), zBuf, fsize);
62 @ %s(zBuf)
63 @ </td></tr>
64 if( !brief ){
65 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
66 n = db_int(0, "SELECT count(*) FROM blob");
67 m = db_int(0, "SELECT count(*) FROM delta");
@@ -60,12 +76,12 @@
76 db_step(&q);
77 t = db_column_int64(&q, 0);
78 szAvg = db_column_int(&q, 1);
79 szMax = db_column_int(&q, 2);
80 db_finalize(&q);
81 bigSizeName(sizeof(zBuf), zBuf, t);
82 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) total
83 @ </td></tr>
84 @ <tr><th>Compression&nbsp;Ratio:</th><td>
85 if( t/fsize < 5 ){
86 b = 10;
87 fsize /= 10;
88
+20 -14
--- src/style.c
+++ src/style.c
@@ -813,28 +813,34 @@
813813
814814
/*
815815
** WEBPAGE: style.css
816816
*/
817817
void page_style_css(void){
818
- const char *zCSS = 0;
818
+ Blob css;
819819
int i;
820820
821821
cgi_set_content_type("text/css");
822
- zCSS = db_get("css",(char*)zDefaultCSS);
823
- /* append user defined css */
824
- cgi_append_content(zCSS, -1);
822
+ blob_init(&css, db_get("css",(char*)zDefaultCSS), -1);
823
+
825824
/* add special missing definitions */
826
- for (i=1;cssDefaultList[i].elementClass;i++)
827
- if (!strstr(zCSS,cssDefaultList[i].elementClass)) {
828
- cgi_append_content("/* ", -1);
829
- cgi_append_content(cssDefaultList[i].comment, -1);
830
- cgi_append_content(" */\n", -1);
831
- cgi_append_content(cssDefaultList[i].elementClass, -1);
832
- cgi_append_content(" {\n", -1);
833
- cgi_append_content(cssDefaultList[i].value, -1);
834
- cgi_append_content("}\n\n", -1);
835
- }
825
+ for(i=1; cssDefaultList[i].elementClass; i++){
826
+ if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){
827
+ blob_appendf(&css, "/* %s */\n%s {\n%s}\n",
828
+ cssDefaultList[i].comment,
829
+ cssDefaultList[i].elementClass,
830
+ cssDefaultList[i].value);
831
+ }
832
+ }
833
+
834
+ /* Process through TH1 in order to give an opportunity to substitute
835
+ ** variables such as $baseurl.
836
+ */
837
+ Th_Store("baseurl", g.zBaseURL);
838
+ Th_Store("home", g.zTop);
839
+ Th_Render(blob_str(&css));
840
+
841
+ /* Tell CGI that the content returned by this page is considered cacheable */
836842
g.isConst = 1;
837843
}
838844
839845
/*
840846
** WEBPAGE: test_env
841847
--- src/style.c
+++ src/style.c
@@ -813,28 +813,34 @@
813
814 /*
815 ** WEBPAGE: style.css
816 */
817 void page_style_css(void){
818 const char *zCSS = 0;
819 int i;
820
821 cgi_set_content_type("text/css");
822 zCSS = db_get("css",(char*)zDefaultCSS);
823 /* append user defined css */
824 cgi_append_content(zCSS, -1);
825 /* add special missing definitions */
826 for (i=1;cssDefaultList[i].elementClass;i++)
827 if (!strstr(zCSS,cssDefaultList[i].elementClass)) {
828 cgi_append_content("/* ", -1);
829 cgi_append_content(cssDefaultList[i].comment, -1);
830 cgi_append_content(" */\n", -1);
831 cgi_append_content(cssDefaultList[i].elementClass, -1);
832 cgi_append_content(" {\n", -1);
833 cgi_append_content(cssDefaultList[i].value, -1);
834 cgi_append_content("}\n\n", -1);
835 }
 
 
 
 
 
 
 
836 g.isConst = 1;
837 }
838
839 /*
840 ** WEBPAGE: test_env
841
--- src/style.c
+++ src/style.c
@@ -813,28 +813,34 @@
813
814 /*
815 ** WEBPAGE: style.css
816 */
817 void page_style_css(void){
818 Blob css;
819 int i;
820
821 cgi_set_content_type("text/css");
822 blob_init(&css, db_get("css",(char*)zDefaultCSS), -1);
823
 
824 /* add special missing definitions */
825 for(i=1; cssDefaultList[i].elementClass; i++){
826 if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){
827 blob_appendf(&css, "/* %s */\n%s {\n%s}\n",
828 cssDefaultList[i].comment,
829 cssDefaultList[i].elementClass,
830 cssDefaultList[i].value);
831 }
832 }
833
834 /* Process through TH1 in order to give an opportunity to substitute
835 ** variables such as $baseurl.
836 */
837 Th_Store("baseurl", g.zBaseURL);
838 Th_Store("home", g.zTop);
839 Th_Render(blob_str(&css));
840
841 /* Tell CGI that the content returned by this page is considered cacheable */
842 g.isConst = 1;
843 }
844
845 /*
846 ** WEBPAGE: test_env
847
+1 -1
--- src/url.c
+++ src/url.c
@@ -187,11 +187,11 @@
187187
fossil_panic("unknown repository: %s", zUrl);
188188
}
189189
if( g.urlIsFile ){
190190
Blob cfile;
191191
dehttpize(zFile);
192
- file_canonical_name(zFile, &cfile);
192
+ file_canonical_name(zFile, &cfile, 0);
193193
free(zFile);
194194
g.urlProtocol = "file";
195195
g.urlPath = "";
196196
g.urlName = mprintf("%b", &cfile);
197197
g.urlCanonical = mprintf("file://%T", g.urlName);
198198
--- src/url.c
+++ src/url.c
@@ -187,11 +187,11 @@
187 fossil_panic("unknown repository: %s", zUrl);
188 }
189 if( g.urlIsFile ){
190 Blob cfile;
191 dehttpize(zFile);
192 file_canonical_name(zFile, &cfile);
193 free(zFile);
194 g.urlProtocol = "file";
195 g.urlPath = "";
196 g.urlName = mprintf("%b", &cfile);
197 g.urlCanonical = mprintf("file://%T", g.urlName);
198
--- src/url.c
+++ src/url.c
@@ -187,11 +187,11 @@
187 fossil_panic("unknown repository: %s", zUrl);
188 }
189 if( g.urlIsFile ){
190 Blob cfile;
191 dehttpize(zFile);
192 file_canonical_name(zFile, &cfile, 0);
193 free(zFile);
194 g.urlProtocol = "file";
195 g.urlPath = "";
196 g.urlName = mprintf("%b", &cfile);
197 g.urlCanonical = mprintf("file://%T", g.urlName);
198
+1 -1
--- src/winhttp.c
+++ src/winhttp.c
@@ -596,11 +596,11 @@
596596
zRepository = find_option("repository", "R", 1);
597597
if( !zRepository ){
598598
db_must_be_within_tree();
599599
}else if( file_isdir(zRepository)==1 ){
600600
g.zRepositoryName = mprintf("%s", zRepository);
601
- file_simplify_name(g.zRepositoryName, -1);
601
+ file_simplify_name(g.zRepositoryName, -1, 0);
602602
}else{
603603
db_open_repository(zRepository);
604604
}
605605
db_close(0);
606606
verify_all_options();
607607
608608
ADDED test/diff-test-1.wiki
--- src/winhttp.c
+++ src/winhttp.c
@@ -596,11 +596,11 @@
596 zRepository = find_option("repository", "R", 1);
597 if( !zRepository ){
598 db_must_be_within_tree();
599 }else if( file_isdir(zRepository)==1 ){
600 g.zRepositoryName = mprintf("%s", zRepository);
601 file_simplify_name(g.zRepositoryName, -1);
602 }else{
603 db_open_repository(zRepository);
604 }
605 db_close(0);
606 verify_all_options();
607
608 DDED test/diff-test-1.wiki
--- src/winhttp.c
+++ src/winhttp.c
@@ -596,11 +596,11 @@
596 zRepository = find_option("repository", "R", 1);
597 if( !zRepository ){
598 db_must_be_within_tree();
599 }else if( file_isdir(zRepository)==1 ){
600 g.zRepositoryName = mprintf("%s", zRepository);
601 file_simplify_name(g.zRepositoryName, -1, 0);
602 }else{
603 db_open_repository(zRepository);
604 }
605 db_close(0);
606 verify_all_options();
607
608 DDED test/diff-test-1.wiki

No diff available

--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -13,10 +13,15 @@
1313
<li><p>
1414
Click on each of the links in in the
1515
[./graph-test-1.wiki] document and verify that all graphs are
1616
rendered correctly.
1717
18
+<li><p>
19
+Click on each of the links in in the
20
+[./diff-test-1.wiki] document and verify that all diffs are
21
+rendered correctly.
22
+
1823
<li><p>
1924
Verify correct name-change tracking behavior (no net changes) for:
2025
<blockquote><b>
2126
fossil test-name-changes --debug b120bc8b262ac 374920b20944b
2227
</b></blockquote>
2328
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -13,10 +13,15 @@
13 <li><p>
14 Click on each of the links in in the
15 [./graph-test-1.wiki] document and verify that all graphs are
16 rendered correctly.
17
 
 
 
 
 
18 <li><p>
19 Verify correct name-change tracking behavior (no net changes) for:
20 <blockquote><b>
21 fossil test-name-changes --debug b120bc8b262ac 374920b20944b
22 </b></blockquote>
23
--- test/release-checklist.wiki
+++ test/release-checklist.wiki
@@ -13,10 +13,15 @@
13 <li><p>
14 Click on each of the links in in the
15 [./graph-test-1.wiki] document and verify that all graphs are
16 rendered correctly.
17
18 <li><p>
19 Click on each of the links in in the
20 [./diff-test-1.wiki] document and verify that all diffs are
21 rendered correctly.
22
23 <li><p>
24 Verify correct name-change tracking behavior (no net changes) for:
25 <blockquote><b>
26 fossil test-name-changes --debug b120bc8b262ac 374920b20944b
27 </b></blockquote>
28
+19 -5
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -22,17 +22,17 @@
2222
SSL =
2323
2424
CFLAGS = -o
2525
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27
-LIBS = $(DMDIR)\extra\lib\ zlib wsock32
27
+LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
2929
SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
3030
31
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
31
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
3232
33
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$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
33
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$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
3434
3535
3636
RC=$(DMDIR)\bin\rcc
3737
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
3838
@@ -46,11 +46,11 @@
4646
4747
$(OBJDIR)\fossil.res: $B\win\fossil.rc
4848
$(RC) $(RCFLAGS) -o$@ $**
4949
5050
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51
- +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
51
+ +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
5252
+echo fossil >> $@
5353
+echo fossil >> $@
5454
+echo $(LIBS) >> $@
5555
+echo. >> $@
5656
+echo fossil >> $@
@@ -98,10 +98,12 @@
9898
$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
9999
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
100100
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
101101
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
102102
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
103
+$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
104
+$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
103105
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
104106
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
105107
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
106108
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
107109
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -365,10 +367,22 @@
365367
$(OBJDIR)\json_diff$O : json_diff_.c json_diff.h
366368
$(TCC) -o$@ -c json_diff_.c
367369
368370
json_diff_.c : $(SRCDIR)\json_diff.c
369371
+translate$E $** > $@
372
+
373
+$(OBJDIR)\json_dir$O : json_dir_.c json_dir.h
374
+ $(TCC) -o$@ -c json_dir_.c
375
+
376
+json_dir_.c : $(SRCDIR)\json_dir.c
377
+ +translate$E $** > $@
378
+
379
+$(OBJDIR)\json_finfo$O : json_finfo_.c json_finfo.h
380
+ $(TCC) -o$@ -c json_finfo_.c
381
+
382
+json_finfo_.c : $(SRCDIR)\json_finfo.c
383
+ +translate$E $** > $@
370384
371385
$(OBJDIR)\json_login$O : json_login_.c json_login.h
372386
$(TCC) -o$@ -c json_login_.c
373387
374388
json_login_.c : $(SRCDIR)\json_login.c
@@ -679,7 +693,7 @@
679693
680694
zip_.c : $(SRCDIR)\zip.c
681695
+translate$E $** > $@
682696
683697
headers: makeheaders$E page_index.h VERSION.h
684
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
698
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
685699
@copy /Y nul: headers
686700
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -22,17 +22,17 @@
22 SSL =
23
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
30
31 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
32
33 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$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
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -98,10 +98,12 @@
98 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
99 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
100 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
101 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
102 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
 
 
103 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
104 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
105 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
106 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
107 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -365,10 +367,22 @@
365 $(OBJDIR)\json_diff$O : json_diff_.c json_diff.h
366 $(TCC) -o$@ -c json_diff_.c
367
368 json_diff_.c : $(SRCDIR)\json_diff.c
369 +translate$E $** > $@
 
 
 
 
 
 
 
 
 
 
 
 
370
371 $(OBJDIR)\json_login$O : json_login_.c json_login.h
372 $(TCC) -o$@ -c json_login_.c
373
374 json_login_.c : $(SRCDIR)\json_login.c
@@ -679,7 +693,7 @@
679
680 zip_.c : $(SRCDIR)\zip.c
681 +translate$E $** > $@
682
683 headers: makeheaders$E page_index.h VERSION.h
684 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
685 @copy /Y nul: headers
686
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -22,17 +22,17 @@
22 SSL =
23
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
30
31 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
32
33 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$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
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -98,10 +98,12 @@
98 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
99 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
100 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
101 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
102 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
103 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
104 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
105 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
106 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
107 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
108 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
109 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -365,10 +367,22 @@
367 $(OBJDIR)\json_diff$O : json_diff_.c json_diff.h
368 $(TCC) -o$@ -c json_diff_.c
369
370 json_diff_.c : $(SRCDIR)\json_diff.c
371 +translate$E $** > $@
372
373 $(OBJDIR)\json_dir$O : json_dir_.c json_dir.h
374 $(TCC) -o$@ -c json_dir_.c
375
376 json_dir_.c : $(SRCDIR)\json_dir.c
377 +translate$E $** > $@
378
379 $(OBJDIR)\json_finfo$O : json_finfo_.c json_finfo.h
380 $(TCC) -o$@ -c json_finfo_.c
381
382 json_finfo_.c : $(SRCDIR)\json_finfo.c
383 +translate$E $** > $@
384
385 $(OBJDIR)\json_login$O : json_login_.c json_login.h
386 $(TCC) -o$@ -c json_login_.c
387
388 json_login_.c : $(SRCDIR)\json_login.c
@@ -679,7 +693,7 @@
693
694 zip_.c : $(SRCDIR)\zip.c
695 +translate$E $** > $@
696
697 headers: makeheaders$E page_index.h VERSION.h
698 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
699 @copy /Y nul: headers
700
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150150
# or linking with it will not work (exact reason unknown).
151151
#
152152
ifdef FOSSIL_ENABLE_TCL
153153
LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
154154
else
155
-LIB += -lws2_32
155
+LIB += -lkernel32 -lws2_32
156156
endif
157157
158158
#### Tcl shell for use in running the fossil test suite. This is only
159159
# used for testing.
160160
#
@@ -215,10 +215,12 @@
215215
$(SRCDIR)/json.c \
216216
$(SRCDIR)/json_artifact.c \
217217
$(SRCDIR)/json_branch.c \
218218
$(SRCDIR)/json_config.c \
219219
$(SRCDIR)/json_diff.c \
220
+ $(SRCDIR)/json_dir.c \
221
+ $(SRCDIR)/json_finfo.c \
220222
$(SRCDIR)/json_login.c \
221223
$(SRCDIR)/json_query.c \
222224
$(SRCDIR)/json_report.c \
223225
$(SRCDIR)/json_tag.c \
224226
$(SRCDIR)/json_timeline.c \
@@ -312,10 +314,12 @@
312314
$(OBJDIR)/json_.c \
313315
$(OBJDIR)/json_artifact_.c \
314316
$(OBJDIR)/json_branch_.c \
315317
$(OBJDIR)/json_config_.c \
316318
$(OBJDIR)/json_diff_.c \
319
+ $(OBJDIR)/json_dir_.c \
320
+ $(OBJDIR)/json_finfo_.c \
317321
$(OBJDIR)/json_login_.c \
318322
$(OBJDIR)/json_query_.c \
319323
$(OBJDIR)/json_report_.c \
320324
$(OBJDIR)/json_tag_.c \
321325
$(OBJDIR)/json_timeline_.c \
@@ -409,10 +413,12 @@
409413
$(OBJDIR)/json.o \
410414
$(OBJDIR)/json_artifact.o \
411415
$(OBJDIR)/json_branch.o \
412416
$(OBJDIR)/json_config.o \
413417
$(OBJDIR)/json_diff.o \
418
+ $(OBJDIR)/json_dir.o \
419
+ $(OBJDIR)/json_finfo.o \
414420
$(OBJDIR)/json_login.o \
415421
$(OBJDIR)/json_query.o \
416422
$(OBJDIR)/json_report.o \
417423
$(OBJDIR)/json_tag.o \
418424
$(OBJDIR)/json_timeline.o \
@@ -531,11 +537,11 @@
531537
532538
533539
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
534540
$(MKINDEX) $(TRANS_SRC) >$@
535541
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
536
- $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
542
+ $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
537543
echo Done >$(OBJDIR)/headers
538544
539545
$(OBJDIR)/headers: Makefile
540546
Makefile:
541547
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -837,10 +843,24 @@
837843
838844
$(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
839845
$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
840846
841847
json_diff.h: $(OBJDIR)/headers
848
+$(OBJDIR)/json_dir_.c: $(SRCDIR)/json_dir.c $(OBJDIR)/translate
849
+ $(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c
850
+
851
+$(OBJDIR)/json_dir.o: $(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
852
+ $(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c
853
+
854
+json_dir.h: $(OBJDIR)/headers
855
+$(OBJDIR)/json_finfo_.c: $(SRCDIR)/json_finfo.c $(OBJDIR)/translate
856
+ $(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c
857
+
858
+$(OBJDIR)/json_finfo.o: $(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
859
+ $(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c
860
+
861
+json_finfo.h: $(OBJDIR)/headers
842862
$(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
843863
$(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
844864
845865
$(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
846866
$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
@@ -1207,11 +1227,11 @@
12071227
$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
12081228
12091229
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
12101230
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
12111231
1212
-$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1232
+$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
12131233
12141234
$(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
12151235
$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
12161236
12171237
$(OBJDIR)/th.o: $(SRCDIR)/th.c
12181238
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150 # or linking with it will not work (exact reason unknown).
151 #
152 ifdef FOSSIL_ENABLE_TCL
153 LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
154 else
155 LIB += -lws2_32
156 endif
157
158 #### Tcl shell for use in running the fossil test suite. This is only
159 # used for testing.
160 #
@@ -215,10 +215,12 @@
215 $(SRCDIR)/json.c \
216 $(SRCDIR)/json_artifact.c \
217 $(SRCDIR)/json_branch.c \
218 $(SRCDIR)/json_config.c \
219 $(SRCDIR)/json_diff.c \
 
 
220 $(SRCDIR)/json_login.c \
221 $(SRCDIR)/json_query.c \
222 $(SRCDIR)/json_report.c \
223 $(SRCDIR)/json_tag.c \
224 $(SRCDIR)/json_timeline.c \
@@ -312,10 +314,12 @@
312 $(OBJDIR)/json_.c \
313 $(OBJDIR)/json_artifact_.c \
314 $(OBJDIR)/json_branch_.c \
315 $(OBJDIR)/json_config_.c \
316 $(OBJDIR)/json_diff_.c \
 
 
317 $(OBJDIR)/json_login_.c \
318 $(OBJDIR)/json_query_.c \
319 $(OBJDIR)/json_report_.c \
320 $(OBJDIR)/json_tag_.c \
321 $(OBJDIR)/json_timeline_.c \
@@ -409,10 +413,12 @@
409 $(OBJDIR)/json.o \
410 $(OBJDIR)/json_artifact.o \
411 $(OBJDIR)/json_branch.o \
412 $(OBJDIR)/json_config.o \
413 $(OBJDIR)/json_diff.o \
 
 
414 $(OBJDIR)/json_login.o \
415 $(OBJDIR)/json_query.o \
416 $(OBJDIR)/json_report.o \
417 $(OBJDIR)/json_tag.o \
418 $(OBJDIR)/json_timeline.o \
@@ -531,11 +537,11 @@
531
532
533 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
534 $(MKINDEX) $(TRANS_SRC) >$@
535 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
536 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
537 echo Done >$(OBJDIR)/headers
538
539 $(OBJDIR)/headers: Makefile
540 Makefile:
541 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -837,10 +843,24 @@
837
838 $(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
839 $(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
840
841 json_diff.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842 $(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
843 $(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
844
845 $(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
846 $(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
@@ -1207,11 +1227,11 @@
1207 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1208
1209 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1210 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1211
1212 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1213
1214 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1215 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1216
1217 $(OBJDIR)/th.o: $(SRCDIR)/th.c
1218
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150 # or linking with it will not work (exact reason unknown).
151 #
152 ifdef FOSSIL_ENABLE_TCL
153 LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
154 else
155 LIB += -lkernel32 -lws2_32
156 endif
157
158 #### Tcl shell for use in running the fossil test suite. This is only
159 # used for testing.
160 #
@@ -215,10 +215,12 @@
215 $(SRCDIR)/json.c \
216 $(SRCDIR)/json_artifact.c \
217 $(SRCDIR)/json_branch.c \
218 $(SRCDIR)/json_config.c \
219 $(SRCDIR)/json_diff.c \
220 $(SRCDIR)/json_dir.c \
221 $(SRCDIR)/json_finfo.c \
222 $(SRCDIR)/json_login.c \
223 $(SRCDIR)/json_query.c \
224 $(SRCDIR)/json_report.c \
225 $(SRCDIR)/json_tag.c \
226 $(SRCDIR)/json_timeline.c \
@@ -312,10 +314,12 @@
314 $(OBJDIR)/json_.c \
315 $(OBJDIR)/json_artifact_.c \
316 $(OBJDIR)/json_branch_.c \
317 $(OBJDIR)/json_config_.c \
318 $(OBJDIR)/json_diff_.c \
319 $(OBJDIR)/json_dir_.c \
320 $(OBJDIR)/json_finfo_.c \
321 $(OBJDIR)/json_login_.c \
322 $(OBJDIR)/json_query_.c \
323 $(OBJDIR)/json_report_.c \
324 $(OBJDIR)/json_tag_.c \
325 $(OBJDIR)/json_timeline_.c \
@@ -409,10 +413,12 @@
413 $(OBJDIR)/json.o \
414 $(OBJDIR)/json_artifact.o \
415 $(OBJDIR)/json_branch.o \
416 $(OBJDIR)/json_config.o \
417 $(OBJDIR)/json_diff.o \
418 $(OBJDIR)/json_dir.o \
419 $(OBJDIR)/json_finfo.o \
420 $(OBJDIR)/json_login.o \
421 $(OBJDIR)/json_query.o \
422 $(OBJDIR)/json_report.o \
423 $(OBJDIR)/json_tag.o \
424 $(OBJDIR)/json_timeline.o \
@@ -531,11 +537,11 @@
537
538
539 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
540 $(MKINDEX) $(TRANS_SRC) >$@
541 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
542 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
543 echo Done >$(OBJDIR)/headers
544
545 $(OBJDIR)/headers: Makefile
546 Makefile:
547 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -837,10 +843,24 @@
843
844 $(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
845 $(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
846
847 json_diff.h: $(OBJDIR)/headers
848 $(OBJDIR)/json_dir_.c: $(SRCDIR)/json_dir.c $(OBJDIR)/translate
849 $(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c
850
851 $(OBJDIR)/json_dir.o: $(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
852 $(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c
853
854 json_dir.h: $(OBJDIR)/headers
855 $(OBJDIR)/json_finfo_.c: $(SRCDIR)/json_finfo.c $(OBJDIR)/translate
856 $(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c
857
858 $(OBJDIR)/json_finfo.o: $(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
859 $(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c
860
861 json_finfo.h: $(OBJDIR)/headers
862 $(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
863 $(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
864
865 $(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
866 $(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
@@ -1207,11 +1227,11 @@
1227 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1228
1229 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1230 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1231
1232 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1233
1234 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1235 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1236
1237 $(OBJDIR)/th.o: $(SRCDIR)/th.c
1238
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -35,11 +35,11 @@
3535
#
3636
FOSSIL_ENABLE_SSL = 1
3737
3838
#### Enable scripting support via Tcl/Tk
3939
#
40
-FOSSIL_ENABLE_TCL = 1
40
+# FOSSIL_ENABLE_TCL = 1
4141
4242
#### Use the Tcl source directory instead of the install directory?
4343
# This is useful when Tcl has been compiled statically with MinGW.
4444
#
4545
FOSSIL_TCL_SOURCE = 1
@@ -150,11 +150,11 @@
150150
# or linking with it will not work (exact reason unknown).
151151
#
152152
ifdef FOSSIL_ENABLE_TCL
153153
LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
154154
else
155
-LIB += -lws2_32
155
+LIB += -lkernel32 -lws2_32
156156
endif
157157
158158
#### Tcl shell for use in running the fossil test suite. This is only
159159
# used for testing.
160160
#
@@ -215,10 +215,12 @@
215215
$(SRCDIR)/json.c \
216216
$(SRCDIR)/json_artifact.c \
217217
$(SRCDIR)/json_branch.c \
218218
$(SRCDIR)/json_config.c \
219219
$(SRCDIR)/json_diff.c \
220
+ $(SRCDIR)/json_dir.c \
221
+ $(SRCDIR)/json_finfo.c \
220222
$(SRCDIR)/json_login.c \
221223
$(SRCDIR)/json_query.c \
222224
$(SRCDIR)/json_report.c \
223225
$(SRCDIR)/json_tag.c \
224226
$(SRCDIR)/json_timeline.c \
@@ -312,10 +314,12 @@
312314
$(OBJDIR)/json_.c \
313315
$(OBJDIR)/json_artifact_.c \
314316
$(OBJDIR)/json_branch_.c \
315317
$(OBJDIR)/json_config_.c \
316318
$(OBJDIR)/json_diff_.c \
319
+ $(OBJDIR)/json_dir_.c \
320
+ $(OBJDIR)/json_finfo_.c \
317321
$(OBJDIR)/json_login_.c \
318322
$(OBJDIR)/json_query_.c \
319323
$(OBJDIR)/json_report_.c \
320324
$(OBJDIR)/json_tag_.c \
321325
$(OBJDIR)/json_timeline_.c \
@@ -409,10 +413,12 @@
409413
$(OBJDIR)/json.o \
410414
$(OBJDIR)/json_artifact.o \
411415
$(OBJDIR)/json_branch.o \
412416
$(OBJDIR)/json_config.o \
413417
$(OBJDIR)/json_diff.o \
418
+ $(OBJDIR)/json_dir.o \
419
+ $(OBJDIR)/json_finfo.o \
414420
$(OBJDIR)/json_login.o \
415421
$(OBJDIR)/json_query.o \
416422
$(OBJDIR)/json_report.o \
417423
$(OBJDIR)/json_tag.o \
418424
$(OBJDIR)/json_timeline.o \
@@ -531,11 +537,11 @@
531537
532538
533539
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
534540
$(MKINDEX) $(TRANS_SRC) >$@
535541
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
536
- $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
542
+ $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
537543
echo Done >$(OBJDIR)/headers
538544
539545
$(OBJDIR)/headers: Makefile
540546
Makefile:
541547
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -837,10 +843,24 @@
837843
838844
$(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
839845
$(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
840846
841847
json_diff.h: $(OBJDIR)/headers
848
+$(OBJDIR)/json_dir_.c: $(SRCDIR)/json_dir.c $(OBJDIR)/translate
849
+ $(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c
850
+
851
+$(OBJDIR)/json_dir.o: $(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
852
+ $(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c
853
+
854
+json_dir.h: $(OBJDIR)/headers
855
+$(OBJDIR)/json_finfo_.c: $(SRCDIR)/json_finfo.c $(OBJDIR)/translate
856
+ $(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c
857
+
858
+$(OBJDIR)/json_finfo.o: $(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
859
+ $(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c
860
+
861
+json_finfo.h: $(OBJDIR)/headers
842862
$(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
843863
$(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
844864
845865
$(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
846866
$(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
@@ -1207,11 +1227,11 @@
12071227
$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
12081228
12091229
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
12101230
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
12111231
1212
-$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1232
+$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
12131233
12141234
$(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
12151235
$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
12161236
12171237
$(OBJDIR)/th.o: $(SRCDIR)/th.c
12181238
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -35,11 +35,11 @@
35 #
36 FOSSIL_ENABLE_SSL = 1
37
38 #### Enable scripting support via Tcl/Tk
39 #
40 FOSSIL_ENABLE_TCL = 1
41
42 #### Use the Tcl source directory instead of the install directory?
43 # This is useful when Tcl has been compiled statically with MinGW.
44 #
45 FOSSIL_TCL_SOURCE = 1
@@ -150,11 +150,11 @@
150 # or linking with it will not work (exact reason unknown).
151 #
152 ifdef FOSSIL_ENABLE_TCL
153 LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
154 else
155 LIB += -lws2_32
156 endif
157
158 #### Tcl shell for use in running the fossil test suite. This is only
159 # used for testing.
160 #
@@ -215,10 +215,12 @@
215 $(SRCDIR)/json.c \
216 $(SRCDIR)/json_artifact.c \
217 $(SRCDIR)/json_branch.c \
218 $(SRCDIR)/json_config.c \
219 $(SRCDIR)/json_diff.c \
 
 
220 $(SRCDIR)/json_login.c \
221 $(SRCDIR)/json_query.c \
222 $(SRCDIR)/json_report.c \
223 $(SRCDIR)/json_tag.c \
224 $(SRCDIR)/json_timeline.c \
@@ -312,10 +314,12 @@
312 $(OBJDIR)/json_.c \
313 $(OBJDIR)/json_artifact_.c \
314 $(OBJDIR)/json_branch_.c \
315 $(OBJDIR)/json_config_.c \
316 $(OBJDIR)/json_diff_.c \
 
 
317 $(OBJDIR)/json_login_.c \
318 $(OBJDIR)/json_query_.c \
319 $(OBJDIR)/json_report_.c \
320 $(OBJDIR)/json_tag_.c \
321 $(OBJDIR)/json_timeline_.c \
@@ -409,10 +413,12 @@
409 $(OBJDIR)/json.o \
410 $(OBJDIR)/json_artifact.o \
411 $(OBJDIR)/json_branch.o \
412 $(OBJDIR)/json_config.o \
413 $(OBJDIR)/json_diff.o \
 
 
414 $(OBJDIR)/json_login.o \
415 $(OBJDIR)/json_query.o \
416 $(OBJDIR)/json_report.o \
417 $(OBJDIR)/json_tag.o \
418 $(OBJDIR)/json_timeline.o \
@@ -531,11 +537,11 @@
531
532
533 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
534 $(MKINDEX) $(TRANS_SRC) >$@
535 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
536 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
537 echo Done >$(OBJDIR)/headers
538
539 $(OBJDIR)/headers: Makefile
540 Makefile:
541 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -837,10 +843,24 @@
837
838 $(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
839 $(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
840
841 json_diff.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842 $(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
843 $(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
844
845 $(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
846 $(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
@@ -1207,11 +1227,11 @@
1207 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1208
1209 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1210 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1211
1212 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1213
1214 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1215 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1216
1217 $(OBJDIR)/th.o: $(SRCDIR)/th.c
1218
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -35,11 +35,11 @@
35 #
36 FOSSIL_ENABLE_SSL = 1
37
38 #### Enable scripting support via Tcl/Tk
39 #
40 # FOSSIL_ENABLE_TCL = 1
41
42 #### Use the Tcl source directory instead of the install directory?
43 # This is useful when Tcl has been compiled statically with MinGW.
44 #
45 FOSSIL_TCL_SOURCE = 1
@@ -150,11 +150,11 @@
150 # or linking with it will not work (exact reason unknown).
151 #
152 ifdef FOSSIL_ENABLE_TCL
153 LIB += -lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32
154 else
155 LIB += -lkernel32 -lws2_32
156 endif
157
158 #### Tcl shell for use in running the fossil test suite. This is only
159 # used for testing.
160 #
@@ -215,10 +215,12 @@
215 $(SRCDIR)/json.c \
216 $(SRCDIR)/json_artifact.c \
217 $(SRCDIR)/json_branch.c \
218 $(SRCDIR)/json_config.c \
219 $(SRCDIR)/json_diff.c \
220 $(SRCDIR)/json_dir.c \
221 $(SRCDIR)/json_finfo.c \
222 $(SRCDIR)/json_login.c \
223 $(SRCDIR)/json_query.c \
224 $(SRCDIR)/json_report.c \
225 $(SRCDIR)/json_tag.c \
226 $(SRCDIR)/json_timeline.c \
@@ -312,10 +314,12 @@
314 $(OBJDIR)/json_.c \
315 $(OBJDIR)/json_artifact_.c \
316 $(OBJDIR)/json_branch_.c \
317 $(OBJDIR)/json_config_.c \
318 $(OBJDIR)/json_diff_.c \
319 $(OBJDIR)/json_dir_.c \
320 $(OBJDIR)/json_finfo_.c \
321 $(OBJDIR)/json_login_.c \
322 $(OBJDIR)/json_query_.c \
323 $(OBJDIR)/json_report_.c \
324 $(OBJDIR)/json_tag_.c \
325 $(OBJDIR)/json_timeline_.c \
@@ -409,10 +413,12 @@
413 $(OBJDIR)/json.o \
414 $(OBJDIR)/json_artifact.o \
415 $(OBJDIR)/json_branch.o \
416 $(OBJDIR)/json_config.o \
417 $(OBJDIR)/json_diff.o \
418 $(OBJDIR)/json_dir.o \
419 $(OBJDIR)/json_finfo.o \
420 $(OBJDIR)/json_login.o \
421 $(OBJDIR)/json_query.o \
422 $(OBJDIR)/json_report.o \
423 $(OBJDIR)/json_tag.o \
424 $(OBJDIR)/json_timeline.o \
@@ -531,11 +537,11 @@
537
538
539 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
540 $(MKINDEX) $(TRANS_SRC) >$@
541 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
542 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
543 echo Done >$(OBJDIR)/headers
544
545 $(OBJDIR)/headers: Makefile
546 Makefile:
547 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -837,10 +843,24 @@
843
844 $(OBJDIR)/json_diff.o: $(OBJDIR)/json_diff_.c $(OBJDIR)/json_diff.h $(SRCDIR)/config.h
845 $(XTCC) -o $(OBJDIR)/json_diff.o -c $(OBJDIR)/json_diff_.c
846
847 json_diff.h: $(OBJDIR)/headers
848 $(OBJDIR)/json_dir_.c: $(SRCDIR)/json_dir.c $(OBJDIR)/translate
849 $(TRANSLATE) $(SRCDIR)/json_dir.c >$(OBJDIR)/json_dir_.c
850
851 $(OBJDIR)/json_dir.o: $(OBJDIR)/json_dir_.c $(OBJDIR)/json_dir.h $(SRCDIR)/config.h
852 $(XTCC) -o $(OBJDIR)/json_dir.o -c $(OBJDIR)/json_dir_.c
853
854 json_dir.h: $(OBJDIR)/headers
855 $(OBJDIR)/json_finfo_.c: $(SRCDIR)/json_finfo.c $(OBJDIR)/translate
856 $(TRANSLATE) $(SRCDIR)/json_finfo.c >$(OBJDIR)/json_finfo_.c
857
858 $(OBJDIR)/json_finfo.o: $(OBJDIR)/json_finfo_.c $(OBJDIR)/json_finfo.h $(SRCDIR)/config.h
859 $(XTCC) -o $(OBJDIR)/json_finfo.o -c $(OBJDIR)/json_finfo_.c
860
861 json_finfo.h: $(OBJDIR)/headers
862 $(OBJDIR)/json_login_.c: $(SRCDIR)/json_login.c $(OBJDIR)/translate
863 $(TRANSLATE) $(SRCDIR)/json_login.c >$(OBJDIR)/json_login_.c
864
865 $(OBJDIR)/json_login.o: $(OBJDIR)/json_login_.c $(OBJDIR)/json_login.h $(SRCDIR)/config.h
866 $(XTCC) -o $(OBJDIR)/json_login.o -c $(OBJDIR)/json_login_.c
@@ -1207,11 +1227,11 @@
1227 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1228
1229 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1230 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1231
1232 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1233
1234 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1235 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1236
1237 $(OBJDIR)/th.o: $(SRCDIR)/th.c
1238
+19 -3
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -40,13 +40,13 @@
4040
LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
4141
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
4242
4343
SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
4444
45
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
45
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
4646
47
-OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\json$O $(OX)\json_artifact$O $(OX)\json_branch$O $(OX)\json_config$O $(OX)\json_diff$O $(OX)\json_login$O $(OX)\json_query$O $(OX)\json_report$O $(OX)\json_tag$O $(OX)\json_timeline$O $(OX)\json_user$O $(OX)\json_wiki$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\xfersetup$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
47
+OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\json$O $(OX)\json_artifact$O $(OX)\json_branch$O $(OX)\json_config$O $(OX)\json_diff$O $(OX)\json_dir$O $(OX)\json_finfo$O $(OX)\json_login$O $(OX)\json_query$O $(OX)\json_report$O $(OX)\json_tag$O $(OX)\json_timeline$O $(OX)\json_user$O $(OX)\json_wiki$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\xfersetup$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
4848
4949
5050
APPNAME = $(OX)\fossil$(E)
5151
5252
all: $(OX) $(APPNAME)
@@ -97,10 +97,12 @@
9797
echo $(OX)\json.obj >> $@
9898
echo $(OX)\json_artifact.obj >> $@
9999
echo $(OX)\json_branch.obj >> $@
100100
echo $(OX)\json_config.obj >> $@
101101
echo $(OX)\json_diff.obj >> $@
102
+ echo $(OX)\json_dir.obj >> $@
103
+ echo $(OX)\json_finfo.obj >> $@
102104
echo $(OX)\json_login.obj >> $@
103105
echo $(OX)\json_query.obj >> $@
104106
echo $(OX)\json_report.obj >> $@
105107
echo $(OX)\json_tag.obj >> $@
106108
echo $(OX)\json_timeline.obj >> $@
@@ -206,10 +208,12 @@
206208
$(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
207209
$(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
208210
$(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
209211
$(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
210212
$(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
213
+$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
214
+$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
211215
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
212216
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
213217
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
214218
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
215219
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -472,10 +476,22 @@
472476
$(OX)\json_diff$O : json_diff_.c json_diff.h
473477
$(TCC) /Fo$@ -c json_diff_.c
474478
475479
json_diff_.c : $(SRCDIR)\json_diff.c
476480
translate$E $** > $@
481
+
482
+$(OX)\json_dir$O : json_dir_.c json_dir.h
483
+ $(TCC) /Fo$@ -c json_dir_.c
484
+
485
+json_dir_.c : $(SRCDIR)\json_dir.c
486
+ translate$E $** > $@
487
+
488
+$(OX)\json_finfo$O : json_finfo_.c json_finfo.h
489
+ $(TCC) /Fo$@ -c json_finfo_.c
490
+
491
+json_finfo_.c : $(SRCDIR)\json_finfo.c
492
+ translate$E $** > $@
477493
478494
$(OX)\json_login$O : json_login_.c json_login.h
479495
$(TCC) /Fo$@ -c json_login_.c
480496
481497
json_login_.c : $(SRCDIR)\json_login.c
@@ -786,7 +802,7 @@
786802
787803
zip_.c : $(SRCDIR)\zip.c
788804
translate$E $** > $@
789805
790806
headers: makeheaders$E page_index.h VERSION.h
791
- makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
807
+ makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
792808
@copy /Y nul: headers
793809
794810
ADDED www/background.jpg
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -40,13 +40,13 @@
40 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
41 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
42
43 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
44
45 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
46
47 OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\json$O $(OX)\json_artifact$O $(OX)\json_branch$O $(OX)\json_config$O $(OX)\json_diff$O $(OX)\json_login$O $(OX)\json_query$O $(OX)\json_report$O $(OX)\json_tag$O $(OX)\json_timeline$O $(OX)\json_user$O $(OX)\json_wiki$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\xfersetup$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
48
49
50 APPNAME = $(OX)\fossil$(E)
51
52 all: $(OX) $(APPNAME)
@@ -97,10 +97,12 @@
97 echo $(OX)\json.obj >> $@
98 echo $(OX)\json_artifact.obj >> $@
99 echo $(OX)\json_branch.obj >> $@
100 echo $(OX)\json_config.obj >> $@
101 echo $(OX)\json_diff.obj >> $@
 
 
102 echo $(OX)\json_login.obj >> $@
103 echo $(OX)\json_query.obj >> $@
104 echo $(OX)\json_report.obj >> $@
105 echo $(OX)\json_tag.obj >> $@
106 echo $(OX)\json_timeline.obj >> $@
@@ -206,10 +208,12 @@
206 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
207 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
208 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
209 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
210 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
 
 
211 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
212 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
213 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
214 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
215 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -472,10 +476,22 @@
472 $(OX)\json_diff$O : json_diff_.c json_diff.h
473 $(TCC) /Fo$@ -c json_diff_.c
474
475 json_diff_.c : $(SRCDIR)\json_diff.c
476 translate$E $** > $@
 
 
 
 
 
 
 
 
 
 
 
 
477
478 $(OX)\json_login$O : json_login_.c json_login.h
479 $(TCC) /Fo$@ -c json_login_.c
480
481 json_login_.c : $(SRCDIR)\json_login.c
@@ -786,7 +802,7 @@
786
787 zip_.c : $(SRCDIR)\zip.c
788 translate$E $** > $@
789
790 headers: makeheaders$E page_index.h VERSION.h
791 makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
792 @copy /Y nul: headers
793
794 DDED www/background.jpg
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -40,13 +40,13 @@
40 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
41 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
42
43 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT3 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
44
45 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c xfersetup_.c zip_.c
46
47 OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\json$O $(OX)\json_artifact$O $(OX)\json_branch$O $(OX)\json_config$O $(OX)\json_diff$O $(OX)\json_dir$O $(OX)\json_finfo$O $(OX)\json_login$O $(OX)\json_query$O $(OX)\json_report$O $(OX)\json_tag$O $(OX)\json_timeline$O $(OX)\json_user$O $(OX)\json_wiki$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\xfersetup$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
48
49
50 APPNAME = $(OX)\fossil$(E)
51
52 all: $(OX) $(APPNAME)
@@ -97,10 +97,12 @@
97 echo $(OX)\json.obj >> $@
98 echo $(OX)\json_artifact.obj >> $@
99 echo $(OX)\json_branch.obj >> $@
100 echo $(OX)\json_config.obj >> $@
101 echo $(OX)\json_diff.obj >> $@
102 echo $(OX)\json_dir.obj >> $@
103 echo $(OX)\json_finfo.obj >> $@
104 echo $(OX)\json_login.obj >> $@
105 echo $(OX)\json_query.obj >> $@
106 echo $(OX)\json_report.obj >> $@
107 echo $(OX)\json_tag.obj >> $@
108 echo $(OX)\json_timeline.obj >> $@
@@ -206,10 +208,12 @@
208 $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h
209 $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h
210 $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h
211 $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h
212 $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h
213 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
214 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
215 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
216 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
217 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
218 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
219 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
@@ -472,10 +476,22 @@
476 $(OX)\json_diff$O : json_diff_.c json_diff.h
477 $(TCC) /Fo$@ -c json_diff_.c
478
479 json_diff_.c : $(SRCDIR)\json_diff.c
480 translate$E $** > $@
481
482 $(OX)\json_dir$O : json_dir_.c json_dir.h
483 $(TCC) /Fo$@ -c json_dir_.c
484
485 json_dir_.c : $(SRCDIR)\json_dir.c
486 translate$E $** > $@
487
488 $(OX)\json_finfo$O : json_finfo_.c json_finfo.h
489 $(TCC) /Fo$@ -c json_finfo_.c
490
491 json_finfo_.c : $(SRCDIR)\json_finfo.c
492 translate$E $** > $@
493
494 $(OX)\json_login$O : json_login_.c json_login.h
495 $(TCC) /Fo$@ -c json_login_.c
496
497 json_login_.c : $(SRCDIR)\json_login.c
@@ -786,7 +802,7 @@
802
803 zip_.c : $(SRCDIR)\zip.c
804 translate$E $** > $@
805
806 headers: makeheaders$E page_index.h VERSION.h
807 makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_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 login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.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
808 @copy /Y nul: headers
809
810 DDED www/background.jpg

Binary file

--- www/changes.wiki
+++ www/changes.wiki
@@ -1,8 +1,8 @@
11
<title>Change Log</title>
22
3
-<h2>Changes For Version 1.22 (2012-02-xx)</h2>
3
+<h2>Changes For Version 1.22 (2012-03-17)</h2>
44
* Greatly improved "diff" processing including the new --brief option,
55
partial line matching, colorized in-line diffs, and better performance.
66
* Promote "allow-symlinks" to a versionable setting
77
* Harden the CGI processing logic against DOS attacks
88
* Add the ability to run TH1 scripts after sync requests
@@ -9,11 +9,18 @@
99
* Store the repository name in _FOSSIL_ as it is type in the "open" command,
1010
possibly as a relative pathname.
1111
* Make ".fslckout" the alternative name for the "_FOSSIL_" file.
1212
* Change the "ssh:" transfer method to allow all access regardless of
1313
user permission.
14
- * Various minor bug fixes
14
+ * Improvements to the timeline messages associated with tag changes.
15
+ (Requires a "[/help/rebuild | fossil rebuild]" to take effect.)
16
+ * Various additions and fixes for the JSON API.
17
+ * Improved merge-with-rename handling.
18
+ * --cherrypick merges use their origin's commit message by default.
19
+ * Added support for multiple concurrent logins per user.
20
+ * Update to use SQLite version 3.7.11.
21
+ * Various minor bug fixes.
1522
1623
<h2>Changes For Version 1.21 (2011-12-13)</h2>
1724
* Added side-by-side diffs in the command-line interface
1825
* Automatically enable hyperlinks if the UserAgent string in the
1926
HTTP header suggests that the requestor is a human and not a bot.
2027
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,8 +1,8 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.22 (2012-02-xx)</h2>
4 * Greatly improved "diff" processing including the new --brief option,
5 partial line matching, colorized in-line diffs, and better performance.
6 * Promote "allow-symlinks" to a versionable setting
7 * Harden the CGI processing logic against DOS attacks
8 * Add the ability to run TH1 scripts after sync requests
@@ -9,11 +9,18 @@
9 * Store the repository name in _FOSSIL_ as it is type in the "open" command,
10 possibly as a relative pathname.
11 * Make ".fslckout" the alternative name for the "_FOSSIL_" file.
12 * Change the "ssh:" transfer method to allow all access regardless of
13 user permission.
14 * Various minor bug fixes
 
 
 
 
 
 
 
15
16 <h2>Changes For Version 1.21 (2011-12-13)</h2>
17 * Added side-by-side diffs in the command-line interface
18 * Automatically enable hyperlinks if the UserAgent string in the
19 HTTP header suggests that the requestor is a human and not a bot.
20
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,8 +1,8 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.22 (2012-03-17)</h2>
4 * Greatly improved "diff" processing including the new --brief option,
5 partial line matching, colorized in-line diffs, and better performance.
6 * Promote "allow-symlinks" to a versionable setting
7 * Harden the CGI processing logic against DOS attacks
8 * Add the ability to run TH1 scripts after sync requests
@@ -9,11 +9,18 @@
9 * Store the repository name in _FOSSIL_ as it is type in the "open" command,
10 possibly as a relative pathname.
11 * Make ".fslckout" the alternative name for the "_FOSSIL_" file.
12 * Change the "ssh:" transfer method to allow all access regardless of
13 user permission.
14 * Improvements to the timeline messages associated with tag changes.
15 (Requires a "[/help/rebuild | fossil rebuild]" to take effect.)
16 * Various additions and fixes for the JSON API.
17 * Improved merge-with-rename handling.
18 * --cherrypick merges use their origin's commit message by default.
19 * Added support for multiple concurrent logins per user.
20 * Update to use SQLite version 3.7.11.
21 * Various minor bug fixes.
22
23 <h2>Changes For Version 1.21 (2011-12-13)</h2>
24 * Added side-by-side diffs in the command-line interface
25 * Automatically enable hyperlinks if the UserAgent string in the
26 HTTP header suggests that the requestor is a human and not a bot.
27
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -4,24 +4,34 @@
44
# the fossil_download_checksums.html page.
55
#
66
#
77
set out [open download.html w]
88
puts $out \
9
-{<html>
9
+{<!DOCTYPE html><html>
1010
<head>
11
-<title>Fossil: Downloads</title>
11
+<title>Fossil: Timeline</title>
1212
<link rel="stylesheet" href="/fossil/style.css" type="text/css"
1313
media="screen">
1414
</head>
1515
<body>
1616
<div class="header">
1717
<div class="logo">
18
- <img src="/fossil/doc/tip/www/fossil_logo_small.gif" alt="logo">
18
+ <img src="/fossil/logo" alt="logo">
19
+ <br /><nobr>Fossil</nobr>
1920
</div>
21
+
2022
<div class="title">Fossil Downloads</div>
2123
</div>
22
-<div class="mainmenu"><a href='/fossil/doc/tip/www/index.wiki'>Home</a><a href='/fossil/timeline'>Timeline</a><a href='/fossil/brlist'>Branches</a><a href='/fossil/taglist'>Tags</a><a href='/fossil/reportlist'>Tickets</a><a href='/fossil/wiki'>Wiki</a><a href='/fossil/login'>Login</a></div>
24
+<div class="mainmenu">
25
+<a href='/fossil/doc/trunk/www/index.wiki'>Home</a>
26
+<a href='/fossil/timeline'>Timeline</a>
27
+<a href='/fossil/dir?ci=tip'>Files</a>
28
+<a href='/fossil/brlist'>Branches</a>
29
+<a href='/fossil/taglist'>Tags</a>
30
+<a href='/fossil/reportlist'>Tickets</a>
31
+<a href='/fossil/wiki'>Wiki</a>
32
+</div>
2333
<div class="content">
2434
<p>
2535
2636
<center><font size=4>
2737
<b>To install Fossil &rarr;</b> download the stand-alone executable
2838
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -4,24 +4,34 @@
4 # the fossil_download_checksums.html page.
5 #
6 #
7 set out [open download.html w]
8 puts $out \
9 {<html>
10 <head>
11 <title>Fossil: Downloads</title>
12 <link rel="stylesheet" href="/fossil/style.css" type="text/css"
13 media="screen">
14 </head>
15 <body>
16 <div class="header">
17 <div class="logo">
18 <img src="/fossil/doc/tip/www/fossil_logo_small.gif" alt="logo">
 
19 </div>
 
20 <div class="title">Fossil Downloads</div>
21 </div>
22 <div class="mainmenu"><a href='/fossil/doc/tip/www/index.wiki'>Home</a><a href='/fossil/timeline'>Timeline</a><a href='/fossil/brlist'>Branches</a><a href='/fossil/taglist'>Tags</a><a href='/fossil/reportlist'>Tickets</a><a href='/fossil/wiki'>Wiki</a><a href='/fossil/login'>Login</a></div>
 
 
 
 
 
 
 
 
23 <div class="content">
24 <p>
25
26 <center><font size=4>
27 <b>To install Fossil &rarr;</b> download the stand-alone executable
28
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -4,24 +4,34 @@
4 # the fossil_download_checksums.html page.
5 #
6 #
7 set out [open download.html w]
8 puts $out \
9 {<!DOCTYPE html><html>
10 <head>
11 <title>Fossil: Timeline</title>
12 <link rel="stylesheet" href="/fossil/style.css" type="text/css"
13 media="screen">
14 </head>
15 <body>
16 <div class="header">
17 <div class="logo">
18 <img src="/fossil/logo" alt="logo">
19 <br /><nobr>Fossil</nobr>
20 </div>
21
22 <div class="title">Fossil Downloads</div>
23 </div>
24 <div class="mainmenu">
25 <a href='/fossil/doc/trunk/www/index.wiki'>Home</a>
26 <a href='/fossil/timeline'>Timeline</a>
27 <a href='/fossil/dir?ci=tip'>Files</a>
28 <a href='/fossil/brlist'>Branches</a>
29 <a href='/fossil/taglist'>Tags</a>
30 <a href='/fossil/reportlist'>Tickets</a>
31 <a href='/fossil/wiki'>Wiki</a>
32 </div>
33 <div class="content">
34 <p>
35
36 <center><font size=4>
37 <b>To install Fossil &rarr;</b> download the stand-alone executable
38

Keyboard Shortcuts

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