Fossil SCM

Merge trunk

andygoth 2016-10-12 18:35 andygoth-circa merge
Commit a7d576ddb2198bdf5976a17dee31d77d518140a5
+21 -8
--- src/add.c
+++ src/add.c
@@ -71,29 +71,42 @@
7171
".fos-journal",
7272
".fos-wal",
7373
".fos-shm",
7474
};
7575
76
- /* Names of auxiliary files generated by SQLite when the "manifest"
77
- ** property is enabled
76
+ /* Possible names of auxiliary files generated when the "manifest" property
77
+ ** is used
7878
*/
79
- static const char *const azManifest[] = {
80
- "manifest",
81
- "manifest.uuid",
79
+ static const struct {
80
+ const char *fname;
81
+ int flg;
82
+ }aManifestflags[] = {
83
+ { "manifest", MFESTFLG_RAW },
84
+ { "manifest.uuid", MFESTFLG_UUID },
85
+ { "manifest.tags", MFESTFLG_TAGS }
8286
};
87
+ static const char *azManifests[3];
8388
8489
/*
8590
** Names of repository files, if they exist in the checkout.
8691
*/
8792
static const char *azRepo[4] = { 0, 0, 0, 0 };
8893
8994
/* Cached setting "manifest" */
9095
static int cachedManifest = -1;
96
+ static int numManifests;
9197
9298
if( cachedManifest == -1 ){
99
+ int i;
93100
Blob repo;
94
- cachedManifest = db_get_boolean("manifest",0);
101
+ cachedManifest = db_get_manifest_setting();
102
+ numManifests = 0;
103
+ for(i=0; i<count(aManifestflags); i++){
104
+ if( cachedManifest&aManifestflags[i].flg ) {
105
+ azManifests[numManifests++] = aManifestflags[i].fname;
106
+ }
107
+ }
95108
blob_zero(&repo);
96109
if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){
97110
const char *zRepo = blob_str(&repo);
98111
azRepo[0] = zRepo;
99112
azRepo[1] = mprintf("%s-journal", zRepo);
@@ -104,12 +117,12 @@
104117
105118
if( N<0 ) return 0;
106119
if( N<count(azName) ) return azName[N];
107120
N -= count(azName);
108121
if( cachedManifest ){
109
- if( N<count(azManifest) ) return azManifest[N];
110
- N -= count(azManifest);
122
+ if( N<numManifests ) return azManifests[N];
123
+ N -= numManifests;
111124
}
112125
if( !omitRepo && N<count(azRepo) ) return azRepo[N];
113126
return 0;
114127
}
115128
116129
--- src/add.c
+++ src/add.c
@@ -71,29 +71,42 @@
71 ".fos-journal",
72 ".fos-wal",
73 ".fos-shm",
74 };
75
76 /* Names of auxiliary files generated by SQLite when the "manifest"
77 ** property is enabled
78 */
79 static const char *const azManifest[] = {
80 "manifest",
81 "manifest.uuid",
 
 
 
 
82 };
 
83
84 /*
85 ** Names of repository files, if they exist in the checkout.
86 */
87 static const char *azRepo[4] = { 0, 0, 0, 0 };
88
89 /* Cached setting "manifest" */
90 static int cachedManifest = -1;
 
91
92 if( cachedManifest == -1 ){
 
93 Blob repo;
94 cachedManifest = db_get_boolean("manifest",0);
 
 
 
 
 
 
95 blob_zero(&repo);
96 if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){
97 const char *zRepo = blob_str(&repo);
98 azRepo[0] = zRepo;
99 azRepo[1] = mprintf("%s-journal", zRepo);
@@ -104,12 +117,12 @@
104
105 if( N<0 ) return 0;
106 if( N<count(azName) ) return azName[N];
107 N -= count(azName);
108 if( cachedManifest ){
109 if( N<count(azManifest) ) return azManifest[N];
110 N -= count(azManifest);
111 }
112 if( !omitRepo && N<count(azRepo) ) return azRepo[N];
113 return 0;
114 }
115
116
--- src/add.c
+++ src/add.c
@@ -71,29 +71,42 @@
71 ".fos-journal",
72 ".fos-wal",
73 ".fos-shm",
74 };
75
76 /* Possible names of auxiliary files generated when the "manifest" property
77 ** is used
78 */
79 static const struct {
80 const char *fname;
81 int flg;
82 }aManifestflags[] = {
83 { "manifest", MFESTFLG_RAW },
84 { "manifest.uuid", MFESTFLG_UUID },
85 { "manifest.tags", MFESTFLG_TAGS }
86 };
87 static const char *azManifests[3];
88
89 /*
90 ** Names of repository files, if they exist in the checkout.
91 */
92 static const char *azRepo[4] = { 0, 0, 0, 0 };
93
94 /* Cached setting "manifest" */
95 static int cachedManifest = -1;
96 static int numManifests;
97
98 if( cachedManifest == -1 ){
99 int i;
100 Blob repo;
101 cachedManifest = db_get_manifest_setting();
102 numManifests = 0;
103 for(i=0; i<count(aManifestflags); i++){
104 if( cachedManifest&aManifestflags[i].flg ) {
105 azManifests[numManifests++] = aManifestflags[i].fname;
106 }
107 }
108 blob_zero(&repo);
109 if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){
110 const char *zRepo = blob_str(&repo);
111 azRepo[0] = zRepo;
112 azRepo[1] = mprintf("%s-journal", zRepo);
@@ -104,12 +117,12 @@
117
118 if( N<0 ) return 0;
119 if( N<count(azName) ) return azName[N];
120 N -= count(azName);
121 if( cachedManifest ){
122 if( N<numManifests ) return azManifests[N];
123 N -= numManifests;
124 }
125 if( !omitRepo && N<count(azRepo) ) return azRepo[N];
126 return 0;
127 }
128
129
+2 -2
--- src/allrepo.c
+++ src/allrepo.c
@@ -375,11 +375,11 @@
375375
" FROM global_config"
376376
" WHERE substr(name, 1, 5)=='repo:'"
377377
" ORDER BY 1"
378378
);
379379
}
380
- db_multi_exec("CREATE TEMP TABLE todel(x TEXT)");
380
+ db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
381381
db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
382382
while( db_step(&q)==SQLITE_ROW ){
383383
const char *zFilename = db_column_text(&q, 0);
384384
#if !USE_SEE
385385
if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
@@ -386,11 +386,11 @@
386386
#endif
387387
if( file_access(zFilename, F_OK)
388388
|| !file_is_canonical(zFilename)
389389
|| (useCheckouts && file_isdir(zFilename)!=1)
390390
){
391
- db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
391
+ db_multi_exec("INSERT INTO toDel VALUES(%Q)", db_column_text(&q, 1));
392392
nToDel++;
393393
continue;
394394
}
395395
if( zCmd[0]=='l' ){
396396
fossil_print("%s\n", zFilename);
397397
--- src/allrepo.c
+++ src/allrepo.c
@@ -375,11 +375,11 @@
375 " FROM global_config"
376 " WHERE substr(name, 1, 5)=='repo:'"
377 " ORDER BY 1"
378 );
379 }
380 db_multi_exec("CREATE TEMP TABLE todel(x TEXT)");
381 db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
382 while( db_step(&q)==SQLITE_ROW ){
383 const char *zFilename = db_column_text(&q, 0);
384 #if !USE_SEE
385 if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
@@ -386,11 +386,11 @@
386 #endif
387 if( file_access(zFilename, F_OK)
388 || !file_is_canonical(zFilename)
389 || (useCheckouts && file_isdir(zFilename)!=1)
390 ){
391 db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
392 nToDel++;
393 continue;
394 }
395 if( zCmd[0]=='l' ){
396 fossil_print("%s\n", zFilename);
397
--- src/allrepo.c
+++ src/allrepo.c
@@ -375,11 +375,11 @@
375 " FROM global_config"
376 " WHERE substr(name, 1, 5)=='repo:'"
377 " ORDER BY 1"
378 );
379 }
380 db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
381 db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
382 while( db_step(&q)==SQLITE_ROW ){
383 const char *zFilename = db_column_text(&q, 0);
384 #if !USE_SEE
385 if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
@@ -386,11 +386,11 @@
386 #endif
387 if( file_access(zFilename, F_OK)
388 || !file_is_canonical(zFilename)
389 || (useCheckouts && file_isdir(zFilename)!=1)
390 ){
391 db_multi_exec("INSERT INTO toDel VALUES(%Q)", db_column_text(&q, 1));
392 nToDel++;
393 continue;
394 }
395 if( zCmd[0]=='l' ){
396 fossil_print("%s\n", zFilename);
397
+11 -5
--- src/blob.c
+++ src/blob.c
@@ -851,27 +851,33 @@
851851
int blob_write_to_file(Blob *pBlob, const char *zFilename){
852852
FILE *out;
853853
int nWrote;
854854
855855
if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
856
- nWrote = blob_size(pBlob);
856
+ blob_is_init(pBlob);
857857
#if defined(_WIN32)
858
- if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){
859
- return nWrote;
860
- }
858
+ nWrote = fossil_utf8_to_console(blob_buffer(pBlob), blob_size(pBlob), 0);
859
+ if( nWrote>=0 ) return nWrote;
861860
fflush(stdout);
862861
_setmode(_fileno(stdout), _O_BINARY);
863862
#endif
864
- fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
863
+ nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), stdout);
865864
#if defined(_WIN32)
866865
fflush(stdout);
867866
_setmode(_fileno(stdout), _O_TEXT);
868867
#endif
869868
}else{
870869
file_mkfolder(zFilename, 1, 0);
871870
out = fossil_fopen(zFilename, "wb");
872871
if( out==0 ){
872
+#if _WIN32
873
+ const char *zReserved = file_is_win_reserved(zFilename);
874
+ if( zReserved ){
875
+ fossil_fatal("cannot open \"%s\" because \"%s\" is "
876
+ "a reserved name on Windows", zFilename, zReserved);
877
+ }
878
+#endif
873879
fossil_fatal_recursive("unable to open file \"%s\" for writing",
874880
zFilename);
875881
return 0;
876882
}
877883
blob_is_init(pBlob);
878884
--- src/blob.c
+++ src/blob.c
@@ -851,27 +851,33 @@
851 int blob_write_to_file(Blob *pBlob, const char *zFilename){
852 FILE *out;
853 int nWrote;
854
855 if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
856 nWrote = blob_size(pBlob);
857 #if defined(_WIN32)
858 if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){
859 return nWrote;
860 }
861 fflush(stdout);
862 _setmode(_fileno(stdout), _O_BINARY);
863 #endif
864 fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
865 #if defined(_WIN32)
866 fflush(stdout);
867 _setmode(_fileno(stdout), _O_TEXT);
868 #endif
869 }else{
870 file_mkfolder(zFilename, 1, 0);
871 out = fossil_fopen(zFilename, "wb");
872 if( out==0 ){
 
 
 
 
 
 
 
873 fossil_fatal_recursive("unable to open file \"%s\" for writing",
874 zFilename);
875 return 0;
876 }
877 blob_is_init(pBlob);
878
--- src/blob.c
+++ src/blob.c
@@ -851,27 +851,33 @@
851 int blob_write_to_file(Blob *pBlob, const char *zFilename){
852 FILE *out;
853 int nWrote;
854
855 if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
856 blob_is_init(pBlob);
857 #if defined(_WIN32)
858 nWrote = fossil_utf8_to_console(blob_buffer(pBlob), blob_size(pBlob), 0);
859 if( nWrote>=0 ) return nWrote;
 
860 fflush(stdout);
861 _setmode(_fileno(stdout), _O_BINARY);
862 #endif
863 nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), stdout);
864 #if defined(_WIN32)
865 fflush(stdout);
866 _setmode(_fileno(stdout), _O_TEXT);
867 #endif
868 }else{
869 file_mkfolder(zFilename, 1, 0);
870 out = fossil_fopen(zFilename, "wb");
871 if( out==0 ){
872 #if _WIN32
873 const char *zReserved = file_is_win_reserved(zFilename);
874 if( zReserved ){
875 fossil_fatal("cannot open \"%s\" because \"%s\" is "
876 "a reserved name on Windows", zFilename, zReserved);
877 }
878 #endif
879 fossil_fatal_recursive("unable to open file \"%s\" for writing",
880 zFilename);
881 return 0;
882 }
883 blob_is_init(pBlob);
884
+13 -3
--- src/checkin.c
+++ src/checkin.c
@@ -1869,11 +1869,11 @@
18691869
sCiInfo.zUserOvrd = find_option("user-override",0,1);
18701870
db_must_be_within_tree();
18711871
noSign = db_get_boolean("omitsign", 0)|noSign;
18721872
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
18731873
useCksum = db_get_boolean("repo-cksum", 1);
1874
- outputManifest = db_get_boolean("manifest", 0);
1874
+ outputManifest = db_get_manifest_setting();
18751875
verify_all_options();
18761876
18771877
/* Escape special characters in tags and put all tags in sorted order */
18781878
if( nTag ){
18791879
int i;
@@ -2230,11 +2230,11 @@
22302230
** and rollback the transaction.
22312231
*/
22322232
if( dryRunFlag ){
22332233
blob_write_to_file(&manifest, "");
22342234
}
2235
- if( outputManifest ){
2235
+ if( outputManifest & MFESTFLG_RAW ){
22362236
zManifestFile = mprintf("%smanifest", g.zLocalRoot);
22372237
blob_write_to_file(&manifest, zManifestFile);
22382238
blob_reset(&manifest);
22392239
blob_read_from_file(&manifest, zManifestFile);
22402240
free(zManifestFile);
@@ -2264,11 +2264,11 @@
22642264
}
22652265
}
22662266
db_finalize(&q);
22672267
22682268
fossil_print("New_Version: %s\n", zUuid);
2269
- if( outputManifest ){
2269
+ if( outputManifest & MFESTFLG_UUID ){
22702270
zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
22712271
blob_zero(&muuid);
22722272
blob_appendf(&muuid, "%s\n", zUuid);
22732273
blob_write_to_file(&muuid, zManifestFile);
22742274
free(zManifestFile);
@@ -2346,13 +2346,23 @@
23462346
if( dryRunFlag ){
23472347
db_end_transaction(1);
23482348
exit(1);
23492349
}
23502350
db_end_transaction(0);
2351
+
2352
+ if( outputManifest & MFESTFLG_TAGS ){
2353
+ Blob tagslist;
2354
+ zManifestFile = mprintf("%smanifest.tags", g.zLocalRoot);
2355
+ blob_zero(&tagslist);
2356
+ get_checkin_taglist(nvid, &tagslist);
2357
+ blob_write_to_file(&tagslist, zManifestFile);
2358
+ blob_reset(&tagslist);
2359
+ free(zManifestFile);
2360
+ }
23512361
23522362
if( !g.markPrivate ){
23532363
autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0);
23542364
}
23552365
if( count_nonbranch_children(vid)>1 ){
23562366
fossil_print("**** warning: a fork has occurred *****\n");
23572367
}
23582368
}
23592369
--- src/checkin.c
+++ src/checkin.c
@@ -1869,11 +1869,11 @@
1869 sCiInfo.zUserOvrd = find_option("user-override",0,1);
1870 db_must_be_within_tree();
1871 noSign = db_get_boolean("omitsign", 0)|noSign;
1872 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1873 useCksum = db_get_boolean("repo-cksum", 1);
1874 outputManifest = db_get_boolean("manifest", 0);
1875 verify_all_options();
1876
1877 /* Escape special characters in tags and put all tags in sorted order */
1878 if( nTag ){
1879 int i;
@@ -2230,11 +2230,11 @@
2230 ** and rollback the transaction.
2231 */
2232 if( dryRunFlag ){
2233 blob_write_to_file(&manifest, "");
2234 }
2235 if( outputManifest ){
2236 zManifestFile = mprintf("%smanifest", g.zLocalRoot);
2237 blob_write_to_file(&manifest, zManifestFile);
2238 blob_reset(&manifest);
2239 blob_read_from_file(&manifest, zManifestFile);
2240 free(zManifestFile);
@@ -2264,11 +2264,11 @@
2264 }
2265 }
2266 db_finalize(&q);
2267
2268 fossil_print("New_Version: %s\n", zUuid);
2269 if( outputManifest ){
2270 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
2271 blob_zero(&muuid);
2272 blob_appendf(&muuid, "%s\n", zUuid);
2273 blob_write_to_file(&muuid, zManifestFile);
2274 free(zManifestFile);
@@ -2346,13 +2346,23 @@
2346 if( dryRunFlag ){
2347 db_end_transaction(1);
2348 exit(1);
2349 }
2350 db_end_transaction(0);
 
 
 
 
 
 
 
 
 
 
2351
2352 if( !g.markPrivate ){
2353 autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0);
2354 }
2355 if( count_nonbranch_children(vid)>1 ){
2356 fossil_print("**** warning: a fork has occurred *****\n");
2357 }
2358 }
2359
--- src/checkin.c
+++ src/checkin.c
@@ -1869,11 +1869,11 @@
1869 sCiInfo.zUserOvrd = find_option("user-override",0,1);
1870 db_must_be_within_tree();
1871 noSign = db_get_boolean("omitsign", 0)|noSign;
1872 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1873 useCksum = db_get_boolean("repo-cksum", 1);
1874 outputManifest = db_get_manifest_setting();
1875 verify_all_options();
1876
1877 /* Escape special characters in tags and put all tags in sorted order */
1878 if( nTag ){
1879 int i;
@@ -2230,11 +2230,11 @@
2230 ** and rollback the transaction.
2231 */
2232 if( dryRunFlag ){
2233 blob_write_to_file(&manifest, "");
2234 }
2235 if( outputManifest & MFESTFLG_RAW ){
2236 zManifestFile = mprintf("%smanifest", g.zLocalRoot);
2237 blob_write_to_file(&manifest, zManifestFile);
2238 blob_reset(&manifest);
2239 blob_read_from_file(&manifest, zManifestFile);
2240 free(zManifestFile);
@@ -2264,11 +2264,11 @@
2264 }
2265 }
2266 db_finalize(&q);
2267
2268 fossil_print("New_Version: %s\n", zUuid);
2269 if( outputManifest & MFESTFLG_UUID ){
2270 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
2271 blob_zero(&muuid);
2272 blob_appendf(&muuid, "%s\n", zUuid);
2273 blob_write_to_file(&muuid, zManifestFile);
2274 free(zManifestFile);
@@ -2346,13 +2346,23 @@
2346 if( dryRunFlag ){
2347 db_end_transaction(1);
2348 exit(1);
2349 }
2350 db_end_transaction(0);
2351
2352 if( outputManifest & MFESTFLG_TAGS ){
2353 Blob tagslist;
2354 zManifestFile = mprintf("%smanifest.tags", g.zLocalRoot);
2355 blob_zero(&tagslist);
2356 get_checkin_taglist(nvid, &tagslist);
2357 blob_write_to_file(&tagslist, zManifestFile);
2358 blob_reset(&tagslist);
2359 free(zManifestFile);
2360 }
2361
2362 if( !g.markPrivate ){
2363 autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0);
2364 }
2365 if( count_nonbranch_children(vid)>1 ){
2366 fossil_print("**** warning: a fork has occurred *****\n");
2367 }
2368 }
2369
+65 -7
--- src/checkout.c
+++ src/checkout.c
@@ -127,44 +127,102 @@
127127
128128
/*
129129
** If the "manifest" setting is true, then automatically generate
130130
** files named "manifest" and "manifest.uuid" containing, respectively,
131131
** the text of the manifest and the artifact ID of the manifest.
132
+** If the manifest setting is set, but is not a boolean value, then treat
133
+** each character as a flag to enable writing "manifest", "manifest.uuid" or
134
+** "manifest.tags".
132135
*/
133136
void manifest_to_disk(int vid){
134137
char *zManFile;
135138
Blob manifest;
136139
Blob hash;
140
+ Blob taglist;
141
+ int flg;
142
+
143
+ flg = db_get_manifest_setting();
137144
138
- if( db_get_boolean("manifest",0) ){
145
+ if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
139146
blob_zero(&manifest);
140147
content_get(vid, &manifest);
141
- zManFile = mprintf("%smanifest", g.zLocalRoot);
142148
blob_zero(&hash);
143149
sha1sum_blob(&manifest, &hash);
144150
sterilize_manifest(&manifest);
151
+ }
152
+ if( flg & MFESTFLG_RAW ){
153
+ zManFile = mprintf("%smanifest", g.zLocalRoot);
145154
blob_write_to_file(&manifest, zManFile);
146155
free(zManFile);
147
- zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
148
- blob_append(&hash, "\n", 1);
149
- blob_write_to_file(&hash, zManFile);
150
- free(zManFile);
151
- blob_reset(&hash);
152156
}else{
153157
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
154158
zManFile = mprintf("%smanifest", g.zLocalRoot);
155159
file_delete(zManFile);
156160
free(zManFile);
157161
}
162
+ }
163
+ if( flg & MFESTFLG_UUID ){
164
+ zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
165
+ blob_append(&hash, "\n", 1);
166
+ blob_write_to_file(&hash, zManFile);
167
+ free(zManFile);
168
+ blob_reset(&hash);
169
+ }else{
158170
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
159171
zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
160172
file_delete(zManFile);
161173
free(zManFile);
162174
}
163175
}
176
+ if( flg & MFESTFLG_TAGS ){
177
+ blob_zero(&taglist);
178
+ zManFile = mprintf("%smanifest.tags", g.zLocalRoot);
179
+ get_checkin_taglist(vid, &taglist);
180
+ blob_write_to_file(&taglist, zManFile);
181
+ free(zManFile);
182
+ blob_reset(&taglist);
183
+ }else{
184
+ if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.tags'") ){
185
+ zManFile = mprintf("%smanifest.tags", g.zLocalRoot);
186
+ file_delete(zManFile);
187
+ free(zManFile);
188
+ }
189
+ }
190
+}
164191
192
+/*
193
+** Find the branch name and all symbolic tags for a particular check-in
194
+** identified by "rid".
195
+**
196
+** The branch name is actually only extracted if this procedure is run
197
+** from within a local check-out. And the branch name is not the branch
198
+** name for "rid" but rather the branch name for the current check-out.
199
+** It is unclear if the rid parameter is always the same as the current
200
+** check-out.
201
+*/
202
+void get_checkin_taglist(int rid, Blob *pOut){
203
+ Stmt stmt;
204
+ char *zCurrent;
205
+ blob_reset(pOut);
206
+ zCurrent = db_text(0, "SELECT value FROM tagxref"
207
+ " WHERE rid=%d AND tagid=%d", rid, TAG_BRANCH);
208
+ blob_appendf(pOut, "branch %s\n", zCurrent);
209
+ db_prepare(&stmt, "SELECT substr(tagname, 5)"
210
+ " FROM tagxref, tag"
211
+ " WHERE tagxref.rid=%d"
212
+ " AND tagxref.tagtype>0"
213
+ " AND tag.tagid=tagxref.tagid"
214
+ " AND tag.tagname GLOB 'sym-*'", rid);
215
+ while( db_step(&stmt)==SQLITE_ROW ){
216
+ const char *zName;
217
+ zName = db_column_text(&stmt, 0);
218
+ blob_appendf(pOut, "tag %s\n", zName);
219
+ }
220
+ db_reset(&stmt);
221
+ db_finalize(&stmt);
165222
}
223
+
166224
167225
/*
168226
** COMMAND: checkout*
169227
** COMMAND: co*
170228
**
171229
--- src/checkout.c
+++ src/checkout.c
@@ -127,44 +127,102 @@
127
128 /*
129 ** If the "manifest" setting is true, then automatically generate
130 ** files named "manifest" and "manifest.uuid" containing, respectively,
131 ** the text of the manifest and the artifact ID of the manifest.
 
 
 
132 */
133 void manifest_to_disk(int vid){
134 char *zManFile;
135 Blob manifest;
136 Blob hash;
 
 
 
 
137
138 if( db_get_boolean("manifest",0) ){
139 blob_zero(&manifest);
140 content_get(vid, &manifest);
141 zManFile = mprintf("%smanifest", g.zLocalRoot);
142 blob_zero(&hash);
143 sha1sum_blob(&manifest, &hash);
144 sterilize_manifest(&manifest);
 
 
 
145 blob_write_to_file(&manifest, zManFile);
146 free(zManFile);
147 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
148 blob_append(&hash, "\n", 1);
149 blob_write_to_file(&hash, zManFile);
150 free(zManFile);
151 blob_reset(&hash);
152 }else{
153 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
154 zManFile = mprintf("%smanifest", g.zLocalRoot);
155 file_delete(zManFile);
156 free(zManFile);
157 }
 
 
 
 
 
 
 
 
158 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
159 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
160 file_delete(zManFile);
161 free(zManFile);
162 }
163 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165 }
 
166
167 /*
168 ** COMMAND: checkout*
169 ** COMMAND: co*
170 **
171
--- src/checkout.c
+++ src/checkout.c
@@ -127,44 +127,102 @@
127
128 /*
129 ** If the "manifest" setting is true, then automatically generate
130 ** files named "manifest" and "manifest.uuid" containing, respectively,
131 ** the text of the manifest and the artifact ID of the manifest.
132 ** If the manifest setting is set, but is not a boolean value, then treat
133 ** each character as a flag to enable writing "manifest", "manifest.uuid" or
134 ** "manifest.tags".
135 */
136 void manifest_to_disk(int vid){
137 char *zManFile;
138 Blob manifest;
139 Blob hash;
140 Blob taglist;
141 int flg;
142
143 flg = db_get_manifest_setting();
144
145 if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
146 blob_zero(&manifest);
147 content_get(vid, &manifest);
 
148 blob_zero(&hash);
149 sha1sum_blob(&manifest, &hash);
150 sterilize_manifest(&manifest);
151 }
152 if( flg & MFESTFLG_RAW ){
153 zManFile = mprintf("%smanifest", g.zLocalRoot);
154 blob_write_to_file(&manifest, zManFile);
155 free(zManFile);
 
 
 
 
 
156 }else{
157 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
158 zManFile = mprintf("%smanifest", g.zLocalRoot);
159 file_delete(zManFile);
160 free(zManFile);
161 }
162 }
163 if( flg & MFESTFLG_UUID ){
164 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
165 blob_append(&hash, "\n", 1);
166 blob_write_to_file(&hash, zManFile);
167 free(zManFile);
168 blob_reset(&hash);
169 }else{
170 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
171 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
172 file_delete(zManFile);
173 free(zManFile);
174 }
175 }
176 if( flg & MFESTFLG_TAGS ){
177 blob_zero(&taglist);
178 zManFile = mprintf("%smanifest.tags", g.zLocalRoot);
179 get_checkin_taglist(vid, &taglist);
180 blob_write_to_file(&taglist, zManFile);
181 free(zManFile);
182 blob_reset(&taglist);
183 }else{
184 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.tags'") ){
185 zManFile = mprintf("%smanifest.tags", g.zLocalRoot);
186 file_delete(zManFile);
187 free(zManFile);
188 }
189 }
190 }
191
192 /*
193 ** Find the branch name and all symbolic tags for a particular check-in
194 ** identified by "rid".
195 **
196 ** The branch name is actually only extracted if this procedure is run
197 ** from within a local check-out. And the branch name is not the branch
198 ** name for "rid" but rather the branch name for the current check-out.
199 ** It is unclear if the rid parameter is always the same as the current
200 ** check-out.
201 */
202 void get_checkin_taglist(int rid, Blob *pOut){
203 Stmt stmt;
204 char *zCurrent;
205 blob_reset(pOut);
206 zCurrent = db_text(0, "SELECT value FROM tagxref"
207 " WHERE rid=%d AND tagid=%d", rid, TAG_BRANCH);
208 blob_appendf(pOut, "branch %s\n", zCurrent);
209 db_prepare(&stmt, "SELECT substr(tagname, 5)"
210 " FROM tagxref, tag"
211 " WHERE tagxref.rid=%d"
212 " AND tagxref.tagtype>0"
213 " AND tag.tagid=tagxref.tagid"
214 " AND tag.tagname GLOB 'sym-*'", rid);
215 while( db_step(&stmt)==SQLITE_ROW ){
216 const char *zName;
217 zName = db_column_text(&stmt, 0);
218 blob_appendf(pOut, "tag %s\n", zName);
219 }
220 db_reset(&stmt);
221 db_finalize(&stmt);
222 }
223
224
225 /*
226 ** COMMAND: checkout*
227 ** COMMAND: co*
228 **
229
+42 -4
--- src/db.c
+++ src/db.c
@@ -2270,10 +2270,45 @@
22702270
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
22712271
}
22722272
void db_lset_int(const char *zName, int value){
22732273
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
22742274
}
2275
+
2276
+#if INTERFACE
2277
+/* Manifest generation flags */
2278
+#define MFESTFLG_RAW 0x01
2279
+#define MFESTFLG_UUID 0x02
2280
+#define MFESTFLG_TAGS 0x04
2281
+#endif /* INTERFACE */
2282
+
2283
+/*
2284
+** Get the manifest setting. For backwards compatibility first check if the
2285
+** value is a boolean. If it's not a boolean, treat each character as a flag
2286
+** to enable a manifest type. This system puts certain boundary conditions on
2287
+** which letters can be used to represent flags (any permutation of flags must
2288
+** not be able to fully form one of the boolean values).
2289
+*/
2290
+int db_get_manifest_setting(void){
2291
+ int flg;
2292
+ char *zVal = db_get("manifest", 0);
2293
+ if( zVal==0 || is_false(zVal) ){
2294
+ return 0;
2295
+ }else if( is_truth(zVal) ){
2296
+ return MFESTFLG_RAW|MFESTFLG_UUID;
2297
+ }
2298
+ flg = 0;
2299
+ while( *zVal ){
2300
+ switch( *zVal ){
2301
+ case 'r': flg |= MFESTFLG_RAW; break;
2302
+ case 'u': flg |= MFESTFLG_UUID; break;
2303
+ case 't': flg |= MFESTFLG_TAGS; break;
2304
+ }
2305
+ zVal++;
2306
+ }
2307
+ return flg;
2308
+}
2309
+
22752310
22762311
/*
22772312
** Record the name of a local repository in the global_config() database.
22782313
** The repository filename %s is recorded as an entry with a "name" field
22792314
** of the following form:
@@ -2570,11 +2605,11 @@
25702605
{ "https-login", 0, 0, 0, 0, "off" },
25712606
{ "ignore-glob", 0, 40, 1, 0, "" },
25722607
{ "keep-glob", 0, 40, 1, 0, "" },
25732608
{ "localauth", 0, 0, 0, 0, "off" },
25742609
{ "main-branch", 0, 40, 0, 0, "trunk" },
2575
- { "manifest", 0, 0, 1, 0, "off" },
2610
+ { "manifest", 0, 5, 1, 0, "off" },
25762611
{ "max-loadavg", 0, 25, 0, 0, "0.0" },
25772612
{ "max-upload", 0, 25, 0, 0, "250000" },
25782613
{ "mtime-changes", 0, 0, 0, 0, "on" },
25792614
#if FOSSIL_ENABLE_LEGACY_MV_RM
25802615
{ "mv-rm-files", 0, 0, 0, 0, "off" },
@@ -2775,13 +2810,16 @@
27752810
** false, all HTTP requests from localhost have
27762811
** unrestricted access to the repository.
27772812
**
27782813
** main-branch The primary branch for the project. Default: trunk
27792814
**
2780
-** manifest If enabled, automatically create files "manifest" and
2781
-** (versionable) "manifest.uuid" in every checkout. The SQLite and
2782
-** Fossil repositories both require this. Default: off.
2815
+** manifest If set to a true boolean value, automatically create
2816
+** (versionable) files "manifest" and "manifest.uuid" in every checkout.
2817
+** Optionally use combinations of characters 'r'
2818
+** for "manifest", 'u' for "manifest.uuid" and 't' for
2819
+** "manifest.tags". The SQLite and Fossil repositories
2820
+** both require manifests. Default: off.
27832821
**
27842822
** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
27852823
** are disallowed if the system load average goes above this
27862824
** value. "0.0" means no limit. This only works on unix.
27872825
** Only local settings of this value make a difference since
27882826
--- src/db.c
+++ src/db.c
@@ -2270,10 +2270,45 @@
2270 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
2271 }
2272 void db_lset_int(const char *zName, int value){
2273 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
2274 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2275
2276 /*
2277 ** Record the name of a local repository in the global_config() database.
2278 ** The repository filename %s is recorded as an entry with a "name" field
2279 ** of the following form:
@@ -2570,11 +2605,11 @@
2570 { "https-login", 0, 0, 0, 0, "off" },
2571 { "ignore-glob", 0, 40, 1, 0, "" },
2572 { "keep-glob", 0, 40, 1, 0, "" },
2573 { "localauth", 0, 0, 0, 0, "off" },
2574 { "main-branch", 0, 40, 0, 0, "trunk" },
2575 { "manifest", 0, 0, 1, 0, "off" },
2576 { "max-loadavg", 0, 25, 0, 0, "0.0" },
2577 { "max-upload", 0, 25, 0, 0, "250000" },
2578 { "mtime-changes", 0, 0, 0, 0, "on" },
2579 #if FOSSIL_ENABLE_LEGACY_MV_RM
2580 { "mv-rm-files", 0, 0, 0, 0, "off" },
@@ -2775,13 +2810,16 @@
2775 ** false, all HTTP requests from localhost have
2776 ** unrestricted access to the repository.
2777 **
2778 ** main-branch The primary branch for the project. Default: trunk
2779 **
2780 ** manifest If enabled, automatically create files "manifest" and
2781 ** (versionable) "manifest.uuid" in every checkout. The SQLite and
2782 ** Fossil repositories both require this. Default: off.
 
 
 
2783 **
2784 ** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
2785 ** are disallowed if the system load average goes above this
2786 ** value. "0.0" means no limit. This only works on unix.
2787 ** Only local settings of this value make a difference since
2788
--- src/db.c
+++ src/db.c
@@ -2270,10 +2270,45 @@
2270 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
2271 }
2272 void db_lset_int(const char *zName, int value){
2273 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
2274 }
2275
2276 #if INTERFACE
2277 /* Manifest generation flags */
2278 #define MFESTFLG_RAW 0x01
2279 #define MFESTFLG_UUID 0x02
2280 #define MFESTFLG_TAGS 0x04
2281 #endif /* INTERFACE */
2282
2283 /*
2284 ** Get the manifest setting. For backwards compatibility first check if the
2285 ** value is a boolean. If it's not a boolean, treat each character as a flag
2286 ** to enable a manifest type. This system puts certain boundary conditions on
2287 ** which letters can be used to represent flags (any permutation of flags must
2288 ** not be able to fully form one of the boolean values).
2289 */
2290 int db_get_manifest_setting(void){
2291 int flg;
2292 char *zVal = db_get("manifest", 0);
2293 if( zVal==0 || is_false(zVal) ){
2294 return 0;
2295 }else if( is_truth(zVal) ){
2296 return MFESTFLG_RAW|MFESTFLG_UUID;
2297 }
2298 flg = 0;
2299 while( *zVal ){
2300 switch( *zVal ){
2301 case 'r': flg |= MFESTFLG_RAW; break;
2302 case 'u': flg |= MFESTFLG_UUID; break;
2303 case 't': flg |= MFESTFLG_TAGS; break;
2304 }
2305 zVal++;
2306 }
2307 return flg;
2308 }
2309
2310
2311 /*
2312 ** Record the name of a local repository in the global_config() database.
2313 ** The repository filename %s is recorded as an entry with a "name" field
2314 ** of the following form:
@@ -2570,11 +2605,11 @@
2605 { "https-login", 0, 0, 0, 0, "off" },
2606 { "ignore-glob", 0, 40, 1, 0, "" },
2607 { "keep-glob", 0, 40, 1, 0, "" },
2608 { "localauth", 0, 0, 0, 0, "off" },
2609 { "main-branch", 0, 40, 0, 0, "trunk" },
2610 { "manifest", 0, 5, 1, 0, "off" },
2611 { "max-loadavg", 0, 25, 0, 0, "0.0" },
2612 { "max-upload", 0, 25, 0, 0, "250000" },
2613 { "mtime-changes", 0, 0, 0, 0, "on" },
2614 #if FOSSIL_ENABLE_LEGACY_MV_RM
2615 { "mv-rm-files", 0, 0, 0, 0, "off" },
@@ -2775,13 +2810,16 @@
2810 ** false, all HTTP requests from localhost have
2811 ** unrestricted access to the repository.
2812 **
2813 ** main-branch The primary branch for the project. Default: trunk
2814 **
2815 ** manifest If set to a true boolean value, automatically create
2816 ** (versionable) files "manifest" and "manifest.uuid" in every checkout.
2817 ** Optionally use combinations of characters 'r'
2818 ** for "manifest", 'u' for "manifest.uuid" and 't' for
2819 ** "manifest.tags". The SQLite and Fossil repositories
2820 ** both require manifests. Default: off.
2821 **
2822 ** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
2823 ** are disallowed if the system load average goes above this
2824 ** value. "0.0" means no limit. This only works on unix.
2825 ** Only local settings of this value make a difference since
2826
+3 -3
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -29,16 +29,16 @@
2929
const char *zOrig, *zTarg;
3030
int lenOrig, lenTarg;
3131
int len;
3232
char *zRes;
3333
blob_zero(pDelta);
34
- zOrig = blob_buffer(pOriginal);
34
+ zOrig = blob_materialize(pOriginal);
3535
lenOrig = blob_size(pOriginal);
36
- zTarg = blob_buffer(pTarget);
36
+ zTarg = blob_materialize(pTarget);
3737
lenTarg = blob_size(pTarget);
3838
blob_resize(pDelta, lenTarg+16);
39
- zRes = blob_buffer(pDelta);
39
+ zRes = blob_materialize(pDelta);
4040
len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
4141
blob_resize(pDelta, len);
4242
return 0;
4343
}
4444
4545
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -29,16 +29,16 @@
29 const char *zOrig, *zTarg;
30 int lenOrig, lenTarg;
31 int len;
32 char *zRes;
33 blob_zero(pDelta);
34 zOrig = blob_buffer(pOriginal);
35 lenOrig = blob_size(pOriginal);
36 zTarg = blob_buffer(pTarget);
37 lenTarg = blob_size(pTarget);
38 blob_resize(pDelta, lenTarg+16);
39 zRes = blob_buffer(pDelta);
40 len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
41 blob_resize(pDelta, len);
42 return 0;
43 }
44
45
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -29,16 +29,16 @@
29 const char *zOrig, *zTarg;
30 int lenOrig, lenTarg;
31 int len;
32 char *zRes;
33 blob_zero(pDelta);
34 zOrig = blob_materialize(pOriginal);
35 lenOrig = blob_size(pOriginal);
36 zTarg = blob_materialize(pTarget);
37 lenTarg = blob_size(pTarget);
38 blob_resize(pDelta, lenTarg+16);
39 zRes = blob_materialize(pDelta);
40 len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
41 blob_resize(pDelta, len);
42 return 0;
43 }
44
45
+5 -1
--- src/diff.c
+++ src/diff.c
@@ -146,11 +146,15 @@
146146
147147
/* Count the number of lines in the input file. Include the last line
148148
** in the count even if it lacks the \n terminator
149149
*/
150150
for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
151
- if( z2[0]!=0 ) nLine++;
151
+ if( z2[0]!=0 ){
152
+ nLine++;
153
+ do{ z2++; }while( z2[0] );
154
+ }
155
+ if( n!=(int)(z2-z) ) return 0;
152156
153157
a = fossil_malloc( sizeof(a[0])*nLine );
154158
memset(a, 0, sizeof(a[0])*nLine);
155159
if( nLine==0 ){
156160
*pnLine = 0;
157161
--- src/diff.c
+++ src/diff.c
@@ -146,11 +146,15 @@
146
147 /* Count the number of lines in the input file. Include the last line
148 ** in the count even if it lacks the \n terminator
149 */
150 for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
151 if( z2[0]!=0 ) nLine++;
 
 
 
 
152
153 a = fossil_malloc( sizeof(a[0])*nLine );
154 memset(a, 0, sizeof(a[0])*nLine);
155 if( nLine==0 ){
156 *pnLine = 0;
157
--- src/diff.c
+++ src/diff.c
@@ -146,11 +146,15 @@
146
147 /* Count the number of lines in the input file. Include the last line
148 ** in the count even if it lacks the \n terminator
149 */
150 for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
151 if( z2[0]!=0 ){
152 nLine++;
153 do{ z2++; }while( z2[0] );
154 }
155 if( n!=(int)(z2-z) ) return 0;
156
157 a = fossil_malloc( sizeof(a[0])*nLine );
158 memset(a, 0, sizeof(a[0])*nLine);
159 if( nLine==0 ){
160 *pnLine = 0;
161
+3 -3
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -774,12 +774,12 @@
774774
** If the "--to VERSION" option appears, it specifies the check-in from
775775
** which the second version of the file or files is taken. If there is
776776
** no "--to" option then the (possibly edited) files in the current check-out
777777
** are used.
778778
**
779
-** If the "--checkin VERSION" option shows the changes made by
780
-** check-in VERSION relative to its primary parent
779
+** The "--checkin VERSION" option shows the changes made by
780
+** check-in VERSION relative to its primary parent.
781781
**
782782
** The "-i" command-line option forces the use of the internal diff logic
783783
** rather than any external diff program that might be configured using
784784
** the "setting" command. If no external diff program is configured, then
785785
** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff".
@@ -922,11 +922,11 @@
922922
if( pFileDir ){
923923
int i;
924924
for(i=0; pFileDir[i].zName; i++){
925925
if( pFileDir[i].nUsed==0
926926
&& strcmp(pFileDir[0].zName,".")!=0
927
- && !file_isdir(g.argv[i+2])
927
+ && !file_wd_isdir(g.argv[i+2])
928928
){
929929
fossil_fatal("not found: '%s'", g.argv[i+2]);
930930
}
931931
fossil_free(pFileDir[i].zName);
932932
}
933933
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -774,12 +774,12 @@
774 ** If the "--to VERSION" option appears, it specifies the check-in from
775 ** which the second version of the file or files is taken. If there is
776 ** no "--to" option then the (possibly edited) files in the current check-out
777 ** are used.
778 **
779 ** If the "--checkin VERSION" option shows the changes made by
780 ** check-in VERSION relative to its primary parent
781 **
782 ** The "-i" command-line option forces the use of the internal diff logic
783 ** rather than any external diff program that might be configured using
784 ** the "setting" command. If no external diff program is configured, then
785 ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff".
@@ -922,11 +922,11 @@
922 if( pFileDir ){
923 int i;
924 for(i=0; pFileDir[i].zName; i++){
925 if( pFileDir[i].nUsed==0
926 && strcmp(pFileDir[0].zName,".")!=0
927 && !file_isdir(g.argv[i+2])
928 ){
929 fossil_fatal("not found: '%s'", g.argv[i+2]);
930 }
931 fossil_free(pFileDir[i].zName);
932 }
933
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -774,12 +774,12 @@
774 ** If the "--to VERSION" option appears, it specifies the check-in from
775 ** which the second version of the file or files is taken. If there is
776 ** no "--to" option then the (possibly edited) files in the current check-out
777 ** are used.
778 **
779 ** The "--checkin VERSION" option shows the changes made by
780 ** check-in VERSION relative to its primary parent.
781 **
782 ** The "-i" command-line option forces the use of the internal diff logic
783 ** rather than any external diff program that might be configured using
784 ** the "setting" command. If no external diff program is configured, then
785 ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff".
@@ -922,11 +922,11 @@
922 if( pFileDir ){
923 int i;
924 for(i=0; pFileDir[i].zName; i++){
925 if( pFileDir[i].nUsed==0
926 && strcmp(pFileDir[0].zName,".")!=0
927 && !file_wd_isdir(g.argv[i+2])
928 ){
929 fossil_fatal("not found: '%s'", g.argv[i+2]);
930 }
931 fossil_free(pFileDir[i].zName);
932 }
933
+62 -11
--- src/file.c
+++ src/file.c
@@ -293,24 +293,36 @@
293293
}
294294
return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
295295
}
296296
297297
/*
298
-** Same as file_isdir(), but takes into account symlinks.
298
+** Same as file_isdir(), but takes into account symlinks. Return 1 if
299
+** zFilename is a directory -OR- a symlink that points to a directory.
300
+** Return 0 if zFilename does not exist. Return 2 if zFilename exists
301
+** but is something other than a directory.
299302
*/
300303
int file_wd_isdir(const char *zFilename){
301304
int rc;
305
+ char *zFN;
302306
303
- if( zFilename ){
304
- char *zFN = mprintf("%s", zFilename);
305
- file_simplify_name(zFN, -1, 0);
306
- rc = getStat(zFN, 1);
307
- free(zFN);
307
+ zFN = mprintf("%s", zFilename);
308
+ file_simplify_name(zFN, -1, 0);
309
+ rc = getStat(zFN, 1);
310
+ if( rc ){
311
+ rc = 0; /* It does not exist at all. */
312
+ }else if( S_ISDIR(fileStat.st_mode) ){
313
+ rc = 1; /* It exists and is a real directory. */
314
+ }else if( S_ISLNK(fileStat.st_mode) ){
315
+ Blob content;
316
+ blob_read_link(&content, zFN); /* It exists and is a link. */
317
+ rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */
318
+ blob_reset(&content);
308319
}else{
309
- rc = getStat(0, 1);
320
+ rc = 2; /* It exists and is something else. */
310321
}
311
- return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
322
+ free(zFN);
323
+ return rc;
312324
}
313325
314326
315327
/*
316328
** Wrapper around the access() system call.
@@ -471,16 +483,16 @@
471483
#if !defined(_WIN32)
472484
struct stat buf;
473485
if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
474486
if( onoff ){
475487
int targetMode = (buf.st_mode & 0444)>>2;
476
- if( (buf.st_mode & 0100) == 0 ){
488
+ if( (buf.st_mode & 0100)==0 ){
477489
chmod(zFilename, buf.st_mode | targetMode);
478490
rc = 1;
479491
}
480492
}else{
481
- if( (buf.st_mode & 0100) != 0 ){
493
+ if( (buf.st_mode & 0100)!=0 ){
482494
chmod(zFilename, buf.st_mode & ~0111);
483495
rc = 1;
484496
}
485497
}
486498
#endif /* _WIN32 */
@@ -600,11 +612,11 @@
600612
** The if stops us from trying to create a directory of a drive letter
601613
** C: in this example.
602614
*/
603615
if( !(i==2 && zName[1]==':') ){
604616
#endif
605
- if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){
617
+ if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){
606618
if (errorReturn <= 0) {
607619
fossil_fatal_recursive("unable to create directory %s", zName);
608620
}
609621
rc = errorReturn;
610622
break;
@@ -1384,5 +1396,44 @@
13841396
#else
13851397
FILE *f = fopen(zName, zMode);
13861398
#endif
13871399
return f;
13881400
}
1401
+
1402
+/*
1403
+** Return non-NULL if zFilename contains pathname elements that
1404
+** are reserved on Windows. The returned string is the disallowed
1405
+** path element.
1406
+*/
1407
+const char *file_is_win_reserved(const char *zPath){
1408
+ static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" };
1409
+ static char zReturn[5];
1410
+ int i;
1411
+ while( zPath[0] ){
1412
+ for(i=0; i<ArraySize(azRes); i++){
1413
+ if( sqlite3_strnicmp(zPath, azRes[i], 3)==0
1414
+ && ((i>=4 && fossil_isdigit(zPath[3])
1415
+ && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0))
1416
+ || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0)))
1417
+ ){
1418
+ sqlite3_snprintf(5,zReturn,"%.*s", i>=4 ? 4 : 3, zPath);
1419
+ return zReturn;
1420
+ }
1421
+ }
1422
+ while( zPath[0] && zPath[0]!='/' ) zPath++;
1423
+ while( zPath[0]=='/' ) zPath++;
1424
+ }
1425
+ return 0;
1426
+}
1427
+
1428
+/*
1429
+** COMMAND: test-valid-for-windows
1430
+** Usage: fossil test-valid-for-windows FILENAME ....
1431
+**
1432
+** Show which filenames are not valid for Windows
1433
+*/
1434
+void file_test_valid_for_windows(void){
1435
+ int i;
1436
+ for(i=2; i<g.argc; i++){
1437
+ fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]);
1438
+ }
1439
+}
13891440
--- src/file.c
+++ src/file.c
@@ -293,24 +293,36 @@
293 }
294 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
295 }
296
297 /*
298 ** Same as file_isdir(), but takes into account symlinks.
 
 
 
299 */
300 int file_wd_isdir(const char *zFilename){
301 int rc;
 
302
303 if( zFilename ){
304 char *zFN = mprintf("%s", zFilename);
305 file_simplify_name(zFN, -1, 0);
306 rc = getStat(zFN, 1);
307 free(zFN);
 
 
 
 
 
 
 
308 }else{
309 rc = getStat(0, 1);
310 }
311 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
 
312 }
313
314
315 /*
316 ** Wrapper around the access() system call.
@@ -471,16 +483,16 @@
471 #if !defined(_WIN32)
472 struct stat buf;
473 if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
474 if( onoff ){
475 int targetMode = (buf.st_mode & 0444)>>2;
476 if( (buf.st_mode & 0100) == 0 ){
477 chmod(zFilename, buf.st_mode | targetMode);
478 rc = 1;
479 }
480 }else{
481 if( (buf.st_mode & 0100) != 0 ){
482 chmod(zFilename, buf.st_mode & ~0111);
483 rc = 1;
484 }
485 }
486 #endif /* _WIN32 */
@@ -600,11 +612,11 @@
600 ** The if stops us from trying to create a directory of a drive letter
601 ** C: in this example.
602 */
603 if( !(i==2 && zName[1]==':') ){
604 #endif
605 if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){
606 if (errorReturn <= 0) {
607 fossil_fatal_recursive("unable to create directory %s", zName);
608 }
609 rc = errorReturn;
610 break;
@@ -1384,5 +1396,44 @@
1384 #else
1385 FILE *f = fopen(zName, zMode);
1386 #endif
1387 return f;
1388 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1389
--- src/file.c
+++ src/file.c
@@ -293,24 +293,36 @@
293 }
294 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
295 }
296
297 /*
298 ** Same as file_isdir(), but takes into account symlinks. Return 1 if
299 ** zFilename is a directory -OR- a symlink that points to a directory.
300 ** Return 0 if zFilename does not exist. Return 2 if zFilename exists
301 ** but is something other than a directory.
302 */
303 int file_wd_isdir(const char *zFilename){
304 int rc;
305 char *zFN;
306
307 zFN = mprintf("%s", zFilename);
308 file_simplify_name(zFN, -1, 0);
309 rc = getStat(zFN, 1);
310 if( rc ){
311 rc = 0; /* It does not exist at all. */
312 }else if( S_ISDIR(fileStat.st_mode) ){
313 rc = 1; /* It exists and is a real directory. */
314 }else if( S_ISLNK(fileStat.st_mode) ){
315 Blob content;
316 blob_read_link(&content, zFN); /* It exists and is a link. */
317 rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */
318 blob_reset(&content);
319 }else{
320 rc = 2; /* It exists and is something else. */
321 }
322 free(zFN);
323 return rc;
324 }
325
326
327 /*
328 ** Wrapper around the access() system call.
@@ -471,16 +483,16 @@
483 #if !defined(_WIN32)
484 struct stat buf;
485 if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
486 if( onoff ){
487 int targetMode = (buf.st_mode & 0444)>>2;
488 if( (buf.st_mode & 0100)==0 ){
489 chmod(zFilename, buf.st_mode | targetMode);
490 rc = 1;
491 }
492 }else{
493 if( (buf.st_mode & 0100)!=0 ){
494 chmod(zFilename, buf.st_mode & ~0111);
495 rc = 1;
496 }
497 }
498 #endif /* _WIN32 */
@@ -600,11 +612,11 @@
612 ** The if stops us from trying to create a directory of a drive letter
613 ** C: in this example.
614 */
615 if( !(i==2 && zName[1]==':') ){
616 #endif
617 if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){
618 if (errorReturn <= 0) {
619 fossil_fatal_recursive("unable to create directory %s", zName);
620 }
621 rc = errorReturn;
622 break;
@@ -1384,5 +1396,44 @@
1396 #else
1397 FILE *f = fopen(zName, zMode);
1398 #endif
1399 return f;
1400 }
1401
1402 /*
1403 ** Return non-NULL if zFilename contains pathname elements that
1404 ** are reserved on Windows. The returned string is the disallowed
1405 ** path element.
1406 */
1407 const char *file_is_win_reserved(const char *zPath){
1408 static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" };
1409 static char zReturn[5];
1410 int i;
1411 while( zPath[0] ){
1412 for(i=0; i<ArraySize(azRes); i++){
1413 if( sqlite3_strnicmp(zPath, azRes[i], 3)==0
1414 && ((i>=4 && fossil_isdigit(zPath[3])
1415 && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0))
1416 || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0)))
1417 ){
1418 sqlite3_snprintf(5,zReturn,"%.*s", i>=4 ? 4 : 3, zPath);
1419 return zReturn;
1420 }
1421 }
1422 while( zPath[0] && zPath[0]!='/' ) zPath++;
1423 while( zPath[0]=='/' ) zPath++;
1424 }
1425 return 0;
1426 }
1427
1428 /*
1429 ** COMMAND: test-valid-for-windows
1430 ** Usage: fossil test-valid-for-windows FILENAME ....
1431 **
1432 ** Show which filenames are not valid for Windows
1433 */
1434 void file_test_valid_for_windows(void){
1435 int i;
1436 for(i=2; i<g.argc; i++){
1437 fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]);
1438 }
1439 }
1440
--- src/main.mk
+++ src/main.mk
@@ -498,10 +498,12 @@
498498
-DSQLITE_OMIT_DECLTYPE \
499499
-DSQLITE_OMIT_DEPRECATED \
500500
-DSQLITE_OMIT_PROGRESS_CALLBACK \
501501
-DSQLITE_OMIT_SHARED_CACHE \
502502
-DSQLITE_OMIT_LOAD_EXTENSION \
503
+ -DSQLITE_MAX_EXPR_DEPTH=0 \
504
+ -DSQLITE_USE_ALLOCA \
503505
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
504506
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
505507
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
506508
-DSQLITE_ENABLE_FTS4 \
507509
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
508510
--- src/main.mk
+++ src/main.mk
@@ -498,10 +498,12 @@
498 -DSQLITE_OMIT_DECLTYPE \
499 -DSQLITE_OMIT_DEPRECATED \
500 -DSQLITE_OMIT_PROGRESS_CALLBACK \
501 -DSQLITE_OMIT_SHARED_CACHE \
502 -DSQLITE_OMIT_LOAD_EXTENSION \
 
 
503 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
504 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
505 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
506 -DSQLITE_ENABLE_FTS4 \
507 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
508
--- src/main.mk
+++ src/main.mk
@@ -498,10 +498,12 @@
498 -DSQLITE_OMIT_DECLTYPE \
499 -DSQLITE_OMIT_DEPRECATED \
500 -DSQLITE_OMIT_PROGRESS_CALLBACK \
501 -DSQLITE_OMIT_SHARED_CACHE \
502 -DSQLITE_OMIT_LOAD_EXTENSION \
503 -DSQLITE_MAX_EXPR_DEPTH=0 \
504 -DSQLITE_USE_ALLOCA \
505 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
506 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
507 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
508 -DSQLITE_ENABLE_FTS4 \
509 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
510
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -164,10 +164,12 @@
164164
-DSQLITE_OMIT_DECLTYPE
165165
-DSQLITE_OMIT_DEPRECATED
166166
-DSQLITE_OMIT_PROGRESS_CALLBACK
167167
-DSQLITE_OMIT_SHARED_CACHE
168168
-DSQLITE_OMIT_LOAD_EXTENSION
169
+ -DSQLITE_MAX_EXPR_DEPTH=0
170
+ -DSQLITE_USE_ALLOCA
169171
-DSQLITE_ENABLE_LOCKING_STYLE=0
170172
-DSQLITE_DEFAULT_FILE_FORMAT=4
171173
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
172174
-DSQLITE_ENABLE_FTS4
173175
-DSQLITE_ENABLE_FTS3_PARENTHESIS
174176
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -164,10 +164,12 @@
164 -DSQLITE_OMIT_DECLTYPE
165 -DSQLITE_OMIT_DEPRECATED
166 -DSQLITE_OMIT_PROGRESS_CALLBACK
167 -DSQLITE_OMIT_SHARED_CACHE
168 -DSQLITE_OMIT_LOAD_EXTENSION
 
 
169 -DSQLITE_ENABLE_LOCKING_STYLE=0
170 -DSQLITE_DEFAULT_FILE_FORMAT=4
171 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
172 -DSQLITE_ENABLE_FTS4
173 -DSQLITE_ENABLE_FTS3_PARENTHESIS
174
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -164,10 +164,12 @@
164 -DSQLITE_OMIT_DECLTYPE
165 -DSQLITE_OMIT_DEPRECATED
166 -DSQLITE_OMIT_PROGRESS_CALLBACK
167 -DSQLITE_OMIT_SHARED_CACHE
168 -DSQLITE_OMIT_LOAD_EXTENSION
169 -DSQLITE_MAX_EXPR_DEPTH=0
170 -DSQLITE_USE_ALLOCA
171 -DSQLITE_ENABLE_LOCKING_STYLE=0
172 -DSQLITE_DEFAULT_FILE_FORMAT=4
173 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
174 -DSQLITE_ENABLE_FTS4
175 -DSQLITE_ENABLE_FTS3_PARENTHESIS
176
+329 -361
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -381,11 +381,11 @@
381381
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382382
** [sqlite_version()] and [sqlite_source_id()].
383383
*/
384384
#define SQLITE_VERSION "3.15.0"
385385
#define SQLITE_VERSION_NUMBER 3015000
386
-#define SQLITE_SOURCE_ID "2016-09-28 16:05:53 40c0fb0af678797c39a99853f9f4102464c16f4b"
386
+#define SQLITE_SOURCE_ID "2016-10-12 15:15:30 61f0526978af667781c57bcc87510e4524efd0d8"
387387
388388
/*
389389
** CAPI3REF: Run-Time Library Version Numbers
390390
** KEYWORDS: sqlite3_version, sqlite3_sourceid
391391
**
@@ -15515,39 +15515,27 @@
1551515515
u8 mayAbort; /* True if statement may throw an ABORT exception */
1551615516
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
1551715517
u8 okConstFactor; /* OK to factor out constants */
1551815518
u8 disableLookaside; /* Number of times lookaside has been disabled */
1551915519
u8 nColCache; /* Number of entries in aColCache[] */
15520
- int aTempReg[8]; /* Holding area for temporary registers */
1552115520
int nRangeReg; /* Size of the temporary register block */
1552215521
int iRangeReg; /* First register in temporary register block */
1552315522
int nErr; /* Number of errors seen */
1552415523
int nTab; /* Number of previously allocated VDBE cursors */
1552515524
int nMem; /* Number of memory cells used so far */
15526
- int nSet; /* Number of sets used so far */
1552715525
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
1552815526
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
15529
- int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
1553015527
int ckBase; /* Base register of data during check constraints */
1553115528
int iSelfTab; /* Table of an index whose exprs are being coded */
1553215529
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
1553315530
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
1553415531
int nLabel; /* Number of labels used */
1553515532
int *aLabel; /* Space to hold the labels */
15536
- struct yColCache {
15537
- int iTable; /* Table cursor number */
15538
- i16 iColumn; /* Table column number */
15539
- u8 tempReg; /* iReg is a temp register that needs to be freed */
15540
- int iLevel; /* Nesting level */
15541
- int iReg; /* Reg with value of this column. 0 means none. */
15542
- int lru; /* Least recently used entry has the smallest value */
15543
- } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
1554415533
ExprList *pConstExpr;/* Constant expressions */
1554515534
Token constraintName;/* Name of the constraint currently being parsed */
1554615535
yDbMask writeMask; /* Start a write transaction on these databases */
1554715536
yDbMask cookieMask; /* Bitmask of schema verified databases */
15548
- int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
1554915537
int regRowid; /* Register holding rowid of CREATE TABLE entry */
1555015538
int regRoot; /* Register holding root page number for new objects */
1555115539
int nMaxArg; /* Max args passed to user function by sub-program */
1555215540
#if SELECTTRACE_ENABLED
1555315541
int nSelect; /* Number of SELECT statements seen */
@@ -15556,21 +15544,38 @@
1555615544
#ifndef SQLITE_OMIT_SHARED_CACHE
1555715545
int nTableLock; /* Number of locks in aTableLock */
1555815546
TableLock *aTableLock; /* Required table locks for shared-cache mode */
1555915547
#endif
1556015548
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
15561
-
15562
- /* Information used while coding trigger programs. */
1556315549
Parse *pToplevel; /* Parse structure for main program (or NULL) */
1556415550
Table *pTriggerTab; /* Table triggers are being coded for */
1556515551
int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
1556615552
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
1556715553
u32 oldmask; /* Mask of old.* columns referenced */
1556815554
u32 newmask; /* Mask of new.* columns referenced */
1556915555
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
1557015556
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
1557115557
u8 disableTriggers; /* True to disable triggers */
15558
+
15559
+ /**************************************************************************
15560
+ ** Fields above must be initialized to zero. The fields that follow,
15561
+ ** down to the beginning of the recursive section, do not need to be
15562
+ ** initialized as they will be set before being used. The boundary is
15563
+ ** determined by offsetof(Parse,aColCache).
15564
+ **************************************************************************/
15565
+
15566
+ struct yColCache {
15567
+ int iTable; /* Table cursor number */
15568
+ i16 iColumn; /* Table column number */
15569
+ u8 tempReg; /* iReg is a temp register that needs to be freed */
15570
+ int iLevel; /* Nesting level */
15571
+ int iReg; /* Reg with value of this column. 0 means none. */
15572
+ int lru; /* Least recently used entry has the smallest value */
15573
+ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
15574
+ int aTempReg[8]; /* Holding area for temporary registers */
15575
+ Token sNameToken; /* Token with unqualified schema object name */
15576
+ Token sLastToken; /* The last token parsed */
1557215577
1557315578
/************************************************************************
1557415579
** Above is constant between recursions. Below is reset before and after
1557515580
** each recursion. The boundary between these two regions is determined
1557615581
** using offsetof(Parse,nVar) so the nVar field must be the first field
@@ -15583,11 +15588,10 @@
1558315588
u8 explain; /* True if the EXPLAIN flag is found on the query */
1558415589
#ifndef SQLITE_OMIT_VIRTUALTABLE
1558515590
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
1558615591
int nVtabLock; /* Number of virtual tables to lock */
1558715592
#endif
15588
- int nAlias; /* Number of aliased result set columns */
1558915593
int nHeight; /* Expression tree height of current sub-select */
1559015594
#ifndef SQLITE_OMIT_EXPLAIN
1559115595
int iSelectId; /* ID of current select for EXPLAIN output */
1559215596
int iNextSelectId; /* Next available select ID for EXPLAIN output */
1559315597
#endif
@@ -15595,12 +15599,10 @@
1559515599
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
1559615600
const char *zTail; /* All SQL text past the last semicolon parsed */
1559715601
Table *pNewTable; /* A table being constructed by CREATE TABLE */
1559815602
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
1559915603
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
15600
- Token sNameToken; /* Token with unqualified schema object name */
15601
- Token sLastToken; /* The last token parsed */
1560215604
#ifndef SQLITE_OMIT_VIRTUALTABLE
1560315605
Token sArg; /* Complete text of a module argument */
1560415606
Table **apVtabLock; /* Pointer to virtual tables needing locking */
1560515607
#endif
1560615608
Table *pZombieTab; /* List of Table objects to delete after code gen */
@@ -15607,10 +15609,18 @@
1560715609
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
1560815610
With *pWith; /* Current WITH clause, or NULL */
1560915611
With *pWithToFree; /* Free this WITH object at the end of the parse */
1561015612
};
1561115613
15614
+/*
15615
+** Sizes and pointers of various parts of the Parse object.
15616
+*/
15617
+#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/
15618
+#define PARSE_RECURSE_SZ offsetof(Parse,nVar) /* Recursive part */
15619
+#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
15620
+#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
15621
+
1561215622
/*
1561315623
** Return true if currently inside an sqlite3_declare_vtab() call.
1561415624
*/
1561515625
#ifdef SQLITE_OMIT_VIRTUALTABLE
1561615626
#define IN_DECLARE_VTAB 0
@@ -16170,11 +16180,11 @@
1617016180
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
1617116181
SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
1617216182
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
1617316183
SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
1617416184
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
16175
-SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*);
16185
+SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
1617616186
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
1617716187
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
1617816188
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
1617916189
SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int);
1618016190
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
@@ -16990,20 +17000,17 @@
1699017000
** If x is a lower-case ASCII character, then its upper-case equivalent
1699117001
** is (x - 0x20). Therefore toupper() can be implemented as:
1699217002
**
1699317003
** (x & ~(map[x]&0x20))
1699417004
**
16995
-** Standard function tolower() is implemented using the sqlite3UpperToLower[]
17005
+** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
1699617006
** array. tolower() is used more often than toupper() by SQLite.
1699717007
**
16998
-** Bit 0x40 is set if the character non-alphanumeric and can be used in an
17008
+** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
1699917009
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
1700017010
** non-ASCII UTF character. Hence the test for whether or not a character is
1700117011
** part of an identifier is 0x46.
17002
-**
17003
-** SQLite's versions are identical to the standard versions assuming a
17004
-** locale of "C". They are implemented as macros in sqliteInt.h.
1700517012
*/
1700617013
#ifdef SQLITE_ASCII
1700717014
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
1700817015
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
1700917016
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
@@ -17072,11 +17079,11 @@
1707217079
#ifndef SQLITE_SORTER_PMASZ
1707317080
# define SQLITE_SORTER_PMASZ 250
1707417081
#endif
1707517082
1707617083
/* Statement journals spill to disk when their size exceeds the following
17077
-** threashold (in bytes). 0 means that statement journals are created and
17084
+** threshold (in bytes). 0 means that statement journals are created and
1707817085
** written to disk immediately (the default behavior for SQLite versions
1707917086
** before 3.12.0). -1 means always keep the entire statement journal in
1708017087
** memory. (The statement journal is also always held entirely in memory
1708117088
** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this
1708217089
** setting.)
@@ -17160,11 +17167,11 @@
1716017167
1716117168
/*
1716217169
** The value of the "pending" byte must be 0x40000000 (1 byte past the
1716317170
** 1-gibabyte boundary) in a compatible database. SQLite never uses
1716417171
** the database page that contains the pending byte. It never attempts
17165
-** to read or write that page. The pending byte page is set assign
17172
+** to read or write that page. The pending byte page is set aside
1716617173
** for use by the VFS layers as space for managing file locks.
1716717174
**
1716817175
** During testing, it is often desirable to move the pending byte to
1716917176
** a different position in the file. This allows code that has to
1717017177
** deal with the pending byte to run on files that are much smaller
@@ -17720,13 +17727,10 @@
1772017727
typedef unsigned Bool;
1772117728
1772217729
/* Opaque type used by code in vdbesort.c */
1772317730
typedef struct VdbeSorter VdbeSorter;
1772417731
17725
-/* Opaque type used by the explainer */
17726
-typedef struct Explain Explain;
17727
-
1772817732
/* Elements of the linked list at Vdbe.pAuxData */
1772917733
typedef struct AuxData AuxData;
1773017734
1773117735
/* Types of VDBE cursors */
1773217736
#define CURTYPE_BTREE 0
@@ -17797,10 +17801,16 @@
1779717801
/* 2*nField extra array elements allocated for aType[], beyond the one
1779817802
** static element declared in the structure. nField total array slots for
1779917803
** aType[] and nField+1 array slots for aOffset[] */
1780017804
};
1780117805
17806
+
17807
+/*
17808
+** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
17809
+*/
17810
+#define CACHE_STALE 0
17811
+
1780217812
/*
1780317813
** When a sub-program is executed (OP_Program), a structure of this type
1780417814
** is allocated to store the current value of the program counter, as
1780517815
** well as the current memory cell array and various other frame specific
1780617816
** values stored in the Vdbe struct. When the sub-program is finished,
@@ -17841,15 +17851,10 @@
1784117851
int nDbChange; /* Value of db->nChange */
1784217852
};
1784317853
1784417854
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
1784517855
17846
-/*
17847
-** A value for VdbeCursor.cacheValid that means the cache is always invalid.
17848
-*/
17849
-#define CACHE_STALE 0
17850
-
1785117856
/*
1785217857
** Internally, the vdbe manipulates nearly all SQL values as Mem
1785317858
** structures. Each Mem struct may cache multiple representations (string,
1785417859
** integer etc.) of the same value.
1785517860
*/
@@ -17986,22 +17991,10 @@
1798617991
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
1798717992
u8 argc; /* Number of arguments */
1798817993
sqlite3_value *argv[1]; /* Argument set */
1798917994
};
1799017995
17991
-/*
17992
-** An Explain object accumulates indented output which is helpful
17993
-** in describing recursive data structures.
17994
-*/
17995
-struct Explain {
17996
- Vdbe *pVdbe; /* Attach the explanation to this Vdbe */
17997
- StrAccum str; /* The string being accumulated */
17998
- int nIndent; /* Number of elements in aIndent */
17999
- u16 aIndent[100]; /* Levels of indentation */
18000
- char zBase[100]; /* Initial space */
18001
-};
18002
-
1800317996
/* A bitfield type for use inside of structures. Always follow with :N where
1800417997
** N is the number of bits.
1800517998
*/
1800617999
typedef unsigned bft; /* Bit Field Type */
1800718000
@@ -18022,57 +18015,61 @@
1802218015
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
1802318016
** is really a pointer to an instance of this structure.
1802418017
*/
1802518018
struct Vdbe {
1802618019
sqlite3 *db; /* The database connection that owns this statement */
18020
+ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
18021
+ Parse *pParse; /* Parsing context used to create this Vdbe */
18022
+ ynVar nVar; /* Number of entries in aVar[] */
18023
+ ynVar nzVar; /* Number of entries in azVar[] */
18024
+ u32 magic; /* Magic number for sanity checking */
18025
+ int nMem; /* Number of memory locations currently allocated */
18026
+ int nCursor; /* Number of slots in apCsr[] */
18027
+ u32 cacheCtr; /* VdbeCursor row cache generation counter */
18028
+ int pc; /* The program counter */
18029
+ int rc; /* Value to return */
18030
+ int nChange; /* Number of db changes made since last reset */
18031
+ int iStatement; /* Statement number (or 0 if has not opened stmt) */
18032
+ i64 iCurrentTime; /* Value of julianday('now') for this statement */
18033
+ i64 nFkConstraint; /* Number of imm. FK constraints this VM */
18034
+ i64 nStmtDefCons; /* Number of def. constraints when stmt started */
18035
+ i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
18036
+
18037
+ /* When allocating a new Vdbe object, all of the fields below should be
18038
+ ** initialized to zero or NULL */
18039
+
1802718040
Op *aOp; /* Space to hold the virtual machine's program */
1802818041
Mem *aMem; /* The memory locations */
1802918042
Mem **apArg; /* Arguments to currently executing user function */
1803018043
Mem *aColName; /* Column names to return */
1803118044
Mem *pResultSet; /* Pointer to an array of results */
18032
- Parse *pParse; /* Parsing context used to create this Vdbe */
18033
- int nMem; /* Number of memory locations currently allocated */
18034
- int nOp; /* Number of instructions in the program */
18035
- int nCursor; /* Number of slots in apCsr[] */
18036
- u32 magic; /* Magic number for sanity checking */
1803718045
char *zErrMsg; /* Error message written here */
18038
- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
1803918046
VdbeCursor **apCsr; /* One element of this array for each open cursor */
1804018047
Mem *aVar; /* Values for the OP_Variable opcode. */
1804118048
char **azVar; /* Name of variables */
18042
- ynVar nVar; /* Number of entries in aVar[] */
18043
- ynVar nzVar; /* Number of entries in azVar[] */
18044
- u32 cacheCtr; /* VdbeCursor row cache generation counter */
18045
- int pc; /* The program counter */
18046
- int rc; /* Value to return */
18049
+#ifndef SQLITE_OMIT_TRACE
18050
+ i64 startTime; /* Time when query started - used for profiling */
18051
+#endif
18052
+ int nOp; /* Number of instructions in the program */
1804718053
#ifdef SQLITE_DEBUG
1804818054
int rcApp; /* errcode set by sqlite3_result_error_code() */
1804918055
#endif
1805018056
u16 nResColumn; /* Number of columns in one row of the result set */
1805118057
u8 errorAction; /* Recovery action to do in case of an error */
18058
+ u8 minWriteFileFormat; /* Minimum file format for writable database files */
1805218059
bft expired:1; /* True if the VM needs to be recompiled */
1805318060
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
18054
- u8 minWriteFileFormat; /* Minimum file format for writable database files */
1805518061
bft explain:2; /* True if EXPLAIN present on SQL command */
1805618062
bft changeCntOn:1; /* True to update the change-counter */
1805718063
bft runOnlyOnce:1; /* Automatically expire on reset */
1805818064
bft usesStmtJournal:1; /* True if uses a statement journal */
1805918065
bft readOnly:1; /* True for statements that do not write */
1806018066
bft bIsReader:1; /* True for statements that read */
1806118067
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
18062
- int nChange; /* Number of db changes made since last reset */
1806318068
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
1806418069
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
18065
- int iStatement; /* Statement number (or 0 if has not opened stmt) */
1806618070
u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
18067
-#ifndef SQLITE_OMIT_TRACE
18068
- i64 startTime; /* Time when query started - used for profiling */
18069
-#endif
18070
- i64 iCurrentTime; /* Value of julianday('now') for this statement */
18071
- i64 nFkConstraint; /* Number of imm. FK constraints this VM */
18072
- i64 nStmtDefCons; /* Number of def. constraints when stmt started */
18073
- i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
1807418071
char *zSql; /* Text of the SQL statement that generated this */
1807518072
void *pFree; /* Free this when deleting the vdbe */
1807618073
VdbeFrame *pFrame; /* Parent frame */
1807718074
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
1807818075
int nFrame; /* Number of frames in pFrame list */
@@ -18087,14 +18084,15 @@
1808718084
};
1808818085
1808918086
/*
1809018087
** The following are allowed values for Vdbe.magic
1809118088
*/
18092
-#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
18093
-#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
18094
-#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
18095
-#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
18089
+#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */
18090
+#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */
18091
+#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */
18092
+#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
18093
+#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
1809618094
1809718095
/*
1809818096
** Structure used to store the context required by the
1809918097
** sqlite3_preupdate_*() API functions.
1810018098
*/
@@ -28776,11 +28774,15 @@
2877628774
*/
2877728775
static unsigned int strHash(const char *z){
2877828776
unsigned int h = 0;
2877928777
unsigned char c;
2878028778
while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
28781
- h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
28779
+ /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
28780
+ ** 0x9e3779b1 is 2654435761 which is the closest prime number to
28781
+ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
28782
+ h += sqlite3UpperToLower[c];
28783
+ h *= 0x9e3779b1;
2878228784
}
2878328785
return h;
2878428786
}
2878528787
2878628788
@@ -44019,11 +44021,11 @@
4401944021
){
4402044022
PgHdr *pPgHdr;
4402144023
assert( pPage!=0 );
4402244024
pPgHdr = (PgHdr*)pPage->pExtra;
4402344025
assert( pPgHdr->pPage==0 );
44024
- memset(pPgHdr, 0, sizeof(PgHdr));
44026
+ memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty));
4402544027
pPgHdr->pPage = pPage;
4402644028
pPgHdr->pData = pPage->pBuf;
4402744029
pPgHdr->pExtra = (void *)&pPgHdr[1];
4402844030
memset(pPgHdr->pExtra, 0, pCache->szExtra);
4402944031
pPgHdr->pCache = pCache;
@@ -58985,11 +58987,11 @@
5898558987
int bias, /* Bias search to the high end */
5898658988
int *pRes /* Write search results here */
5898758989
){
5898858990
int rc; /* Status code */
5898958991
UnpackedRecord *pIdxKey; /* Unpacked index key */
58990
- char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */
58992
+ char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */
5899158993
char *pFree = 0;
5899258994
5899358995
if( pKey ){
5899458996
assert( nKey==(i64)(int)nKey );
5899558997
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
@@ -64322,12 +64324,10 @@
6432264324
nSrc = pX->nData;
6432364325
assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */
6432464326
nHeader += putVarint32(&pCell[nHeader], nPayload);
6432564327
nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
6432664328
}else{
64327
- assert( pX->nData==0 );
64328
- assert( pX->nZero==0 );
6432964329
assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
6433064330
nSrc = nPayload = (int)pX->nKey;
6433164331
pSrc = pX->pKey;
6433264332
nHeader += putVarint32(&pCell[nHeader], nPayload);
6433364333
}
@@ -68023,26 +68023,20 @@
6802368023
*/
6802468024
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
6802568025
int i = sqlite3FindDbName(pDb, zDb);
6802668026
6802768027
if( i==1 ){
68028
- Parse *pParse;
68028
+ Parse sParse;
6802968029
int rc = 0;
68030
- pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
68031
- if( pParse==0 ){
68032
- sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory");
68033
- rc = SQLITE_NOMEM_BKPT;
68034
- }else{
68035
- pParse->db = pDb;
68036
- if( sqlite3OpenTempDatabase(pParse) ){
68037
- sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
68038
- rc = SQLITE_ERROR;
68039
- }
68040
- sqlite3DbFree(pErrorDb, pParse->zErrMsg);
68041
- sqlite3ParserReset(pParse);
68042
- sqlite3StackFree(pErrorDb, pParse);
68043
- }
68030
+ memset(&sParse, 0, sizeof(sParse));
68031
+ sParse.db = pDb;
68032
+ if( sqlite3OpenTempDatabase(&sParse) ){
68033
+ sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
68034
+ rc = SQLITE_ERROR;
68035
+ }
68036
+ sqlite3DbFree(pErrorDb, sParse.zErrMsg);
68037
+ sqlite3ParserReset(&sParse);
6804468038
if( rc ){
6804568039
return 0;
6804668040
}
6804768041
}
6804868042
@@ -69042,10 +69036,11 @@
6904269036
assert( (pMem->flags&MEM_RowSet)==0 );
6904369037
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
6904469038
6904569039
6904669040
if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
69041
+ pMem->enc = 0;
6904769042
return SQLITE_NOMEM_BKPT;
6904869043
}
6904969044
6905069045
/* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
6905169046
** string representation of the value. Then, if the required encoding
@@ -69341,11 +69336,11 @@
6934169336
switch( aff ){
6934269337
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
6934369338
if( (pMem->flags & MEM_Blob)==0 ){
6934469339
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
6934569340
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69346
- MemSetTypeFlag(pMem, MEM_Blob);
69341
+ if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
6934769342
}else{
6934869343
pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
6934969344
}
6935069345
break;
6935169346
}
@@ -70018,14 +70013,11 @@
7001870013
sqlite3_value *pVal = 0;
7001970014
int negInt = 1;
7002070015
const char *zNeg = "";
7002170016
int rc = SQLITE_OK;
7002270017
70023
- if( !pExpr ){
70024
- *ppVal = 0;
70025
- return SQLITE_OK;
70026
- }
70018
+ assert( pExpr!=0 );
7002770019
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
7002870020
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
7002970021
7003070022
/* Compressed expressions only appear when parsing the DEFAULT clause
7003170023
** on a table column definition, and hence only when pCtx==0. This
@@ -70145,11 +70137,11 @@
7014570137
Expr *pExpr, /* The expression to evaluate */
7014670138
u8 enc, /* Encoding to use */
7014770139
u8 affinity, /* Affinity to use */
7014870140
sqlite3_value **ppVal /* Write the new value here */
7014970141
){
70150
- return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
70142
+ return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
7015170143
}
7015270144
7015370145
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
7015470146
/*
7015570147
** The implementation of the sqlite_record() function. This function accepts
@@ -70488,12 +70480,13 @@
7048870480
** Create a new virtual database engine.
7048970481
*/
7049070482
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
7049170483
sqlite3 *db = pParse->db;
7049270484
Vdbe *p;
70493
- p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
70485
+ p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) );
7049470486
if( p==0 ) return 0;
70487
+ memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp));
7049570488
p->db = db;
7049670489
if( db->pVdbe ){
7049770490
db->pVdbe->pPrev = p;
7049870491
}
7049970492
p->pNext = db->pVdbe;
@@ -70651,13 +70644,12 @@
7065170644
#endif
7065270645
#ifdef SQLITE_DEBUG
7065370646
if( p->db->flags & SQLITE_VdbeAddopTrace ){
7065470647
int jj, kk;
7065570648
Parse *pParse = p->pParse;
70656
- for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
70649
+ for(jj=kk=0; jj<pParse->nColCache; jj++){
7065770650
struct yColCache *x = pParse->aColCache + jj;
70658
- if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
7065970651
printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
7066070652
kk++;
7066170653
}
7066270654
if( kk ) printf("\n");
7066370655
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
@@ -70841,11 +70833,10 @@
7084170833
assert( j<p->nLabel );
7084270834
assert( j>=0 );
7084370835
if( p->aLabel ){
7084470836
p->aLabel[j] = v->nOp;
7084570837
}
70846
- p->iFixedOp = v->nOp - 1;
7084770838
}
7084870839
7084970840
/*
7085070841
** Mark the VDBE as one that can only be run one time.
7085170842
*/
@@ -71232,19 +71223,19 @@
7123271223
}
7123371224
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
7123471225
sqlite3VdbeGetOp(p,addr)->p3 = val;
7123571226
}
7123671227
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
71237
- if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5;
71228
+ assert( p->nOp>0 || p->db->mallocFailed );
71229
+ if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
7123871230
}
7123971231
7124071232
/*
7124171233
** Change the P2 operand of instruction addr so that it points to
7124271234
** the address of the next instruction to be coded.
7124371235
*/
7124471236
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
71245
- p->pParse->iFixedOp = p->nOp - 1;
7124671237
sqlite3VdbeChangeP2(p, addr, p->nOp);
7124771238
}
7124871239
7124971240
7125071241
/*
@@ -71363,11 +71354,11 @@
7136371354
/*
7136471355
** If the last opcode is "op" and it is not a jump destination,
7136571356
** then remove it. Return true if and only if an opcode was removed.
7136671357
*/
7136771358
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
71368
- if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
71359
+ if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){
7136971360
return sqlite3VdbeChangeToNoop(p, p->nOp-1);
7137071361
}else{
7137171362
return 0;
7137271363
}
7137371364
}
@@ -71925,10 +71916,25 @@
7192571916
zCom
7192671917
);
7192771918
fflush(pOut);
7192871919
}
7192971920
#endif
71921
+
71922
+/*
71923
+** Initialize an array of N Mem element.
71924
+*/
71925
+static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
71926
+ while( (N--)>0 ){
71927
+ p->db = db;
71928
+ p->flags = flags;
71929
+ p->szMalloc = 0;
71930
+#ifdef SQLITE_DEBUG
71931
+ p->pScopyFrom = 0;
71932
+#endif
71933
+ p++;
71934
+ }
71935
+}
7193071936
7193171937
/*
7193271938
** Release an array of N Mem elements
7193371939
*/
7193471940
static void releaseMemArray(Mem *p, int N){
@@ -72137,10 +72143,11 @@
7213772143
return SQLITE_ERROR;
7213872144
}
7213972145
pMem->flags = MEM_Str|MEM_Term;
7214072146
zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
7214172147
if( zP4!=pMem->z ){
72148
+ pMem->n = 0;
7214272149
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
7214372150
}else{
7214472151
assert( pMem->z!=0 );
7214572152
pMem->n = sqlite3Strlen30(pMem->z);
7214672153
pMem->enc = SQLITE_UTF8;
@@ -72279,11 +72286,11 @@
7227972286
SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
7228072287
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
7228172288
int i;
7228272289
#endif
7228372290
assert( p!=0 );
72284
- assert( p->magic==VDBE_MAGIC_INIT );
72291
+ assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
7228572292
7228672293
/* There should be at least one opcode.
7228772294
*/
7228872295
assert( p->nOp>0 );
7228972296
@@ -72368,14 +72375,11 @@
7236872375
n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
7236972376
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
7237072377
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
7237172378
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
7237272379
assert( x.nFree>=0 );
72373
- if( x.nFree>0 ){
72374
- memset(x.pSpace, 0, x.nFree);
72375
- assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
72376
- }
72380
+ assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
7237772381
7237872382
resolveP2Values(p, &nArg);
7237972383
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
7238072384
if( pParse->explain && nMem<10 ){
7238172385
nMem = 10;
@@ -72400,34 +72404,34 @@
7240072404
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
7240172405
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
7240272406
p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
7240372407
#endif
7240472408
if( x.nNeeded==0 ) break;
72405
- x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded);
72409
+ x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
7240672410
x.nFree = x.nNeeded;
7240772411
}while( !db->mallocFailed );
7240872412
72409
- p->nCursor = nCursor;
72410
- if( p->aVar ){
72411
- p->nVar = (ynVar)nVar;
72412
- for(n=0; n<nVar; n++){
72413
- p->aVar[n].flags = MEM_Null;
72414
- p->aVar[n].db = db;
72415
- }
72416
- }
7241772413
p->nzVar = pParse->nzVar;
7241872414
p->azVar = pParse->azVar;
7241972415
pParse->nzVar = 0;
7242072416
pParse->azVar = 0;
72421
- if( p->aMem ){
72422
- p->nMem = nMem;
72423
- for(n=0; n<nMem; n++){
72424
- p->aMem[n].flags = MEM_Undefined;
72425
- p->aMem[n].db = db;
72426
- }
72427
- }
7242872417
p->explain = pParse->explain;
72418
+ if( db->mallocFailed ){
72419
+ p->nVar = 0;
72420
+ p->nCursor = 0;
72421
+ p->nMem = 0;
72422
+ }else{
72423
+ p->nCursor = nCursor;
72424
+ p->nVar = (ynVar)nVar;
72425
+ initMemArray(p->aVar, nVar, db, MEM_Null);
72426
+ p->nMem = nMem;
72427
+ initMemArray(p->aMem, nMem, db, MEM_Undefined);
72428
+ memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
72429
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
72430
+ memset(p->anExec, 0, p->nOp*sizeof(i64));
72431
+#endif
72432
+ }
7242972433
sqlite3VdbeRewind(p);
7243072434
}
7243172435
7243272436
/*
7243372437
** Close a VDBE cursor and release all the resources that cursor
@@ -72575,17 +72579,13 @@
7257572579
7257672580
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
7257772581
sqlite3DbFree(db, p->aColName);
7257872582
n = nResColumn*COLNAME_N;
7257972583
p->nResColumn = (u16)nResColumn;
72580
- p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
72584
+ p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
7258172585
if( p->aColName==0 ) return;
72582
- while( n-- > 0 ){
72583
- pColName->flags = MEM_Null;
72584
- pColName->db = p->db;
72585
- pColName++;
72586
- }
72586
+ initMemArray(p->aColName, n, p->db, MEM_Null);
7258772587
}
7258872588
7258972589
/*
7259072590
** Set the name of the idx'th column to be returned by the SQL statement.
7259172591
** zName must be a pointer to a nul terminated string.
@@ -73343,11 +73343,11 @@
7334373343
fclose(out);
7334473344
}
7334573345
}
7334673346
#endif
7334773347
p->iCurrentTime = 0;
73348
- p->magic = VDBE_MAGIC_INIT;
73348
+ p->magic = VDBE_MAGIC_RESET;
7334973349
return p->rc & db->errMask;
7335073350
}
7335173351
7335273352
/*
7335373353
** Clean up and delete a VDBE after execution. Return an integer which is
@@ -73407,23 +73407,25 @@
7340773407
*/
7340873408
SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
7340973409
SubProgram *pSub, *pNext;
7341073410
int i;
7341173411
assert( p->db==0 || p->db==db );
73412
- releaseMemArray(p->aVar, p->nVar);
7341373412
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
7341473413
for(pSub=p->pProgram; pSub; pSub=pNext){
7341573414
pNext = pSub->pNext;
7341673415
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
7341773416
sqlite3DbFree(db, pSub);
7341873417
}
73419
- for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
73420
- sqlite3DbFree(db, p->azVar);
73418
+ if( p->magic!=VDBE_MAGIC_INIT ){
73419
+ releaseMemArray(p->aVar, p->nVar);
73420
+ for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
73421
+ sqlite3DbFree(db, p->azVar);
73422
+ sqlite3DbFree(db, p->pFree);
73423
+ }
7342173424
vdbeFreeOpArray(db, p->aOp, p->nOp);
7342273425
sqlite3DbFree(db, p->aColName);
7342373426
sqlite3DbFree(db, p->zSql);
73424
- sqlite3DbFree(db, p->pFree);
7342573427
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
7342673428
for(i=0; i<p->nScan; i++){
7342773429
sqlite3DbFree(db, p->aScan[i].zName);
7342873430
}
7342973431
sqlite3DbFree(db, p->aScan);
@@ -76665,11 +76667,11 @@
7666576667
/*
7666676668
** Return true if the prepared statement is in need of being reset.
7666776669
*/
7666876670
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
7666976671
Vdbe *v = (Vdbe*)pStmt;
76670
- return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
76672
+ return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
7667176673
}
7667276674
7667376675
/*
7667476676
** Return a pointer to the next prepared statement after pStmt associated
7667576677
** with database connection pDb. If pStmt is NULL, return the first
@@ -78417,15 +78419,17 @@
7841778419
u16 nullFlag;
7841878420
pOut = out2Prerelease(p, pOp);
7841978421
cnt = pOp->p3-pOp->p2;
7842078422
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
7842178423
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
78424
+ pOut->n = 0;
7842278425
while( cnt>0 ){
7842378426
pOut++;
7842478427
memAboutToChange(p, pOut);
7842578428
sqlite3VdbeMemSetNull(pOut);
7842678429
pOut->flags = nullFlag;
78430
+ pOut->n = 0;
7842778431
cnt--;
7842878432
}
7842978433
break;
7843078434
}
7843178435
@@ -82338,13 +82342,10 @@
8233882342
if( pOp->opcode==OP_SorterInsert ){
8233982343
rc = sqlite3VdbeSorterWrite(pC, pIn2);
8234082344
}else{
8234182345
x.nKey = pIn2->n;
8234282346
x.pKey = pIn2->z;
82343
- x.nData = 0;
82344
- x.nZero = 0;
82345
- x.pData = 0;
8234682347
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
8234782348
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
8234882349
);
8234982350
assert( pC->deferredMoveto==0 );
8235082351
pC->cacheStatus = CACHE_STALE;
@@ -88783,11 +88784,10 @@
8878388784
const char *zDb;
8878488785
Expr *pRight;
8878588786
8878688787
/* if( pSrcList==0 ) break; */
8878788788
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
88788
- /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/
8878988789
pRight = pExpr->pRight;
8879088790
if( pRight->op==TK_ID ){
8879188791
zDb = 0;
8879288792
zTable = pExpr->pLeft->u.zToken;
8879388793
zColumn = pRight->u.zToken;
@@ -88812,11 +88812,10 @@
8881288812
const char *zId; /* The function name. */
8881388813
FuncDef *pDef; /* Information about the function */
8881488814
u8 enc = ENC(pParse->db); /* The database encoding */
8881588815
8881688816
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
88817
- notValid(pParse, pNC, "functions", NC_PartIdx);
8881888817
zId = pExpr->u.zToken;
8881988818
nId = sqlite3Strlen30(zId);
8882088819
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
8882188820
if( pDef==0 ){
8882288821
pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -88872,11 +88871,12 @@
8887288871
}
8887388872
if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
8887488873
/* Date/time functions that use 'now', and other functions like
8887588874
** sqlite_version() that might change over time cannot be used
8887688875
** in an index. */
88877
- notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr);
88876
+ notValid(pParse, pNC, "non-deterministic functions",
88877
+ NC_IdxExpr|NC_PartIdx);
8887888878
}
8887988879
}
8888088880
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
8888188881
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
8888288882
pNC->nErr++;
@@ -90412,11 +90412,11 @@
9041290412
** stored in u.zToken. Instead, the integer values is written
9041390413
** into u.iValue and the EP_IntValue flag is set. No extra storage
9041490414
** is allocated to hold the integer text and the dequote flag is ignored.
9041590415
*/
9041690416
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
90417
- sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
90417
+ sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */
9041890418
int op, /* Expression opcode */
9041990419
const Token *pToken, /* Token argument. Might be NULL */
9042090420
int dequote /* True to dequote */
9042190421
){
9042290422
Expr *pNew;
@@ -90630,40 +90630,40 @@
9063090630
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
9063190631
** as the previous instance of the same wildcard. Or if this is the first
9063290632
** instance of the wildcard, the next sequential variable number is
9063390633
** assigned.
9063490634
*/
90635
-SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
90635
+SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
9063690636
sqlite3 *db = pParse->db;
9063790637
const char *z;
9063890638
9063990639
if( pExpr==0 ) return;
9064090640
assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
9064190641
z = pExpr->u.zToken;
9064290642
assert( z!=0 );
9064390643
assert( z[0]!=0 );
90644
+ assert( n==sqlite3Strlen30(z) );
9064490645
if( z[1]==0 ){
9064590646
/* Wildcard of the form "?". Assign the next variable number */
9064690647
assert( z[0]=='?' );
9064790648
pExpr->iColumn = (ynVar)(++pParse->nVar);
9064890649
}else{
90649
- ynVar x = 0;
90650
- u32 n = sqlite3Strlen30(z);
90650
+ ynVar x;
9065190651
if( z[0]=='?' ){
9065290652
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
9065390653
** use it as the variable number */
9065490654
i64 i;
9065590655
int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
90656
- pExpr->iColumn = x = (ynVar)i;
90656
+ x = (ynVar)i;
9065790657
testcase( i==0 );
9065890658
testcase( i==1 );
9065990659
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
9066090660
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
9066190661
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
9066290662
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
9066390663
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
90664
- x = 0;
90664
+ return;
9066590665
}
9066690666
if( i>pParse->nVar ){
9066790667
pParse->nVar = (int)i;
9066890668
}
9066990669
}else{
@@ -90670,37 +90670,35 @@
9067090670
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
9067190671
** number as the prior appearance of the same name, or if the name
9067290672
** has never appeared before, reuse the same variable number
9067390673
*/
9067490674
ynVar i;
90675
- for(i=0; i<pParse->nzVar; i++){
90675
+ for(i=x=0; i<pParse->nzVar; i++){
9067690676
if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
90677
- pExpr->iColumn = x = (ynVar)i+1;
90678
- break;
90679
- }
90680
- }
90681
- if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
90682
- }
90683
- if( x>0 ){
90684
- if( x>pParse->nzVar ){
90685
- char **a;
90686
- a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
90687
- if( a==0 ){
90688
- assert( db->mallocFailed ); /* Error reported through mallocFailed */
90689
- return;
90690
- }
90691
- pParse->azVar = a;
90692
- memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
90693
- pParse->nzVar = x;
90694
- }
90695
- if( z[0]!='?' || pParse->azVar[x-1]==0 ){
90696
- sqlite3DbFree(db, pParse->azVar[x-1]);
90697
- pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
90698
- }
90699
- }
90700
- }
90701
- if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
90677
+ x = (ynVar)i+1;
90678
+ break;
90679
+ }
90680
+ }
90681
+ if( x==0 ) x = (ynVar)(++pParse->nVar);
90682
+ }
90683
+ pExpr->iColumn = x;
90684
+ if( x>pParse->nzVar ){
90685
+ char **a;
90686
+ a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
90687
+ if( a==0 ){
90688
+ assert( db->mallocFailed ); /* Error reported through mallocFailed */
90689
+ return;
90690
+ }
90691
+ pParse->azVar = a;
90692
+ memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
90693
+ pParse->nzVar = x;
90694
+ }
90695
+ if( pParse->azVar[x-1]==0 ){
90696
+ pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
90697
+ }
90698
+ }
90699
+ if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
9070290700
sqlite3ErrorMsg(pParse, "too many SQL variables");
9070390701
}
9070490702
}
9070590703
9070690704
/*
@@ -92656,36 +92654,23 @@
9265692654
#endif
9265792655
}
9265892656
}
9265992657
}
9266092658
92661
-#if defined(SQLITE_DEBUG)
92662
-/*
92663
-** Verify the consistency of the column cache
92664
-*/
92665
-static int cacheIsValid(Parse *pParse){
92666
- int i, n;
92667
- for(i=n=0; i<SQLITE_N_COLCACHE; i++){
92668
- if( pParse->aColCache[i].iReg>0 ) n++;
92669
- }
92670
- return n==pParse->nColCache;
92671
-}
92672
-#endif
92673
-
92674
-/*
92675
-** Clear a cache entry.
92676
-*/
92677
-static void cacheEntryClear(Parse *pParse, struct yColCache *p){
92678
- if( p->tempReg ){
92659
+/*
92660
+** Erase column-cache entry number i
92661
+*/
92662
+static void cacheEntryClear(Parse *pParse, int i){
92663
+ if( pParse->aColCache[i].tempReg ){
9267992664
if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
92680
- pParse->aTempReg[pParse->nTempReg++] = p->iReg;
92665
+ pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
9268192666
}
92682
- p->tempReg = 0;
9268392667
}
92684
- p->iReg = 0;
9268592668
pParse->nColCache--;
92686
- assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
92669
+ if( i<pParse->nColCache ){
92670
+ pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
92671
+ }
9268792672
}
9268892673
9268992674
9269092675
/*
9269192676
** Record in the column cache that a particular column from a
@@ -92711,64 +92696,52 @@
9271192696
**
9271292697
** Actually, the way the column cache is currently used, we are guaranteed
9271392698
** that the object will never already be in cache. Verify this guarantee.
9271492699
*/
9271592700
#ifndef NDEBUG
92716
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92717
- assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
92701
+ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
92702
+ assert( p->iTable!=iTab || p->iColumn!=iCol );
9271892703
}
9271992704
#endif
9272092705
92721
- /* Find an empty slot and replace it */
92722
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92723
- if( p->iReg==0 ){
92724
- p->iLevel = pParse->iCacheLevel;
92725
- p->iTable = iTab;
92726
- p->iColumn = iCol;
92727
- p->iReg = iReg;
92728
- p->tempReg = 0;
92729
- p->lru = pParse->iCacheCnt++;
92730
- pParse->nColCache++;
92731
- assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
92732
- return;
92733
- }
92734
- }
92735
-
92736
- /* Replace the last recently used */
92737
- minLru = 0x7fffffff;
92738
- idxLru = -1;
92739
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92740
- if( p->lru<minLru ){
92741
- idxLru = i;
92742
- minLru = p->lru;
92743
- }
92744
- }
92745
- if( ALWAYS(idxLru>=0) ){
92706
+ /* If the cache is already full, delete the least recently used entry */
92707
+ if( pParse->nColCache>=SQLITE_N_COLCACHE ){
92708
+ minLru = 0x7fffffff;
92709
+ idxLru = -1;
92710
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92711
+ if( p->lru<minLru ){
92712
+ idxLru = i;
92713
+ minLru = p->lru;
92714
+ }
92715
+ }
9274692716
p = &pParse->aColCache[idxLru];
92747
- p->iLevel = pParse->iCacheLevel;
92748
- p->iTable = iTab;
92749
- p->iColumn = iCol;
92750
- p->iReg = iReg;
92751
- p->tempReg = 0;
92752
- p->lru = pParse->iCacheCnt++;
92753
- assert( cacheIsValid(pParse) );
92754
- return;
92755
- }
92717
+ }else{
92718
+ p = &pParse->aColCache[pParse->nColCache++];
92719
+ }
92720
+
92721
+ /* Add the new entry to the end of the cache */
92722
+ p->iLevel = pParse->iCacheLevel;
92723
+ p->iTable = iTab;
92724
+ p->iColumn = iCol;
92725
+ p->iReg = iReg;
92726
+ p->tempReg = 0;
92727
+ p->lru = pParse->iCacheCnt++;
9275692728
}
9275792729
9275892730
/*
9275992731
** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
9276092732
** Purge the range of registers from the column cache.
9276192733
*/
9276292734
SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
92763
- struct yColCache *p;
92764
- if( iReg<=0 || pParse->nColCache==0 ) return;
92765
- p = &pParse->aColCache[SQLITE_N_COLCACHE-1];
92766
- while(1){
92767
- if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p);
92768
- if( p==pParse->aColCache ) break;
92769
- p--;
92735
+ int i = 0;
92736
+ while( i<pParse->nColCache ){
92737
+ struct yColCache *p = &pParse->aColCache[i];
92738
+ if( p->iReg >= iReg && p->iReg < iReg+nReg ){
92739
+ cacheEntryClear(pParse, i);
92740
+ }else{
92741
+ i++;
92742
+ }
9277092743
}
9277192744
}
9277292745
9277392746
/*
9277492747
** Remember the current column cache context. Any new entries added
@@ -92788,22 +92761,23 @@
9278892761
** Remove from the column cache any entries that were added since the
9278992762
** the previous sqlite3ExprCachePush operation. In other words, restore
9279092763
** the cache to the state it was in prior the most recent Push.
9279192764
*/
9279292765
SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
92793
- int i;
92794
- struct yColCache *p;
92766
+ int i = 0;
9279592767
assert( pParse->iCacheLevel>=1 );
9279692768
pParse->iCacheLevel--;
9279792769
#ifdef SQLITE_DEBUG
9279892770
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
9279992771
printf("POP to %d\n", pParse->iCacheLevel);
9280092772
}
9280192773
#endif
92802
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92803
- if( p->iReg && p->iLevel>pParse->iCacheLevel ){
92804
- cacheEntryClear(pParse, p);
92774
+ while( i<pParse->nColCache ){
92775
+ if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
92776
+ cacheEntryClear(pParse, i);
92777
+ }else{
92778
+ i++;
9280592779
}
9280692780
}
9280792781
}
9280892782
9280992783
/*
@@ -92813,11 +92787,11 @@
9281392787
** get them all.
9281492788
*/
9281592789
static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
9281692790
int i;
9281792791
struct yColCache *p;
92818
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92792
+ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
9281992793
if( p->iReg==iReg ){
9282092794
p->tempReg = 0;
9282192795
}
9282292796
}
9282392797
}
@@ -92891,12 +92865,12 @@
9289192865
){
9289292866
Vdbe *v = pParse->pVdbe;
9289392867
int i;
9289492868
struct yColCache *p;
9289592869
92896
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92897
- if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
92870
+ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
92871
+ if( p->iTable==iTable && p->iColumn==iColumn ){
9289892872
p->lru = pParse->iCacheCnt++;
9289992873
sqlite3ExprCachePinRegister(pParse, p->iReg);
9290092874
return p->iReg;
9290192875
}
9290292876
}
@@ -92924,22 +92898,24 @@
9292492898
/*
9292592899
** Clear all column cache entries.
9292692900
*/
9292792901
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
9292892902
int i;
92929
- struct yColCache *p;
9293092903
9293192904
#if SQLITE_DEBUG
9293292905
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
9293392906
printf("CLEAR\n");
9293492907
}
9293592908
#endif
92936
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92937
- if( p->iReg ){
92938
- cacheEntryClear(pParse, p);
92909
+ for(i=0; i<pParse->nColCache; i++){
92910
+ if( pParse->aColCache[i].tempReg
92911
+ && pParse->nTempReg<ArraySize(pParse->aTempReg)
92912
+ ){
92913
+ pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
9293992914
}
9294092915
}
92916
+ pParse->nColCache = 0;
9294192917
}
9294292918
9294392919
/*
9294492920
** Record the fact that an affinity change has occurred on iCount
9294592921
** registers starting with iStart.
@@ -92967,11 +92943,11 @@
9296792943
** and does not appear in a normal build.
9296892944
*/
9296992945
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
9297092946
int i;
9297192947
struct yColCache *p;
92972
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92948
+ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
9297392949
int r = p->iReg;
9297492950
if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
9297592951
}
9297692952
return 0;
9297792953
}
@@ -94663,11 +94639,11 @@
9466394639
*/
9466494640
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
9466594641
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
9466694642
int i;
9466794643
struct yColCache *p;
94668
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
94644
+ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
9466994645
if( p->iReg==iReg ){
9467094646
p->tempReg = 1;
9467194647
return;
9467294648
}
9467394649
}
@@ -98433,11 +98409,10 @@
9843398409
*/
9843498410
v = sqlite3GetVdbe(pParse);
9843598411
assert( !pParse->isMultiWrite
9843698412
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
9843798413
if( v ){
98438
- while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
9843998414
sqlite3VdbeAddOp0(v, OP_Halt);
9844098415
9844198416
#if SQLITE_USER_AUTHENTICATION
9844298417
if( pParse->nTableLock>0 && db->init.busy==0 ){
9844398418
sqlite3UserAuthInit(db);
@@ -98460,18 +98435,20 @@
9846098435
){
9846198436
int iDb, i;
9846298437
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
9846398438
sqlite3VdbeJumpHere(v, 0);
9846498439
for(iDb=0; iDb<db->nDb; iDb++){
98440
+ Schema *pSchema;
9846598441
if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
9846698442
sqlite3VdbeUsesBtree(v, iDb);
98443
+ pSchema = db->aDb[iDb].pSchema;
9846798444
sqlite3VdbeAddOp4Int(v,
9846898445
OP_Transaction, /* Opcode */
9846998446
iDb, /* P1 */
9847098447
DbMaskTest(pParse->writeMask,iDb), /* P2 */
98471
- pParse->cookieValue[iDb], /* P3 */
98472
- db->aDb[iDb].pSchema->iGeneration /* P4 */
98448
+ pSchema->schema_cookie, /* P3 */
98449
+ pSchema->iGeneration /* P4 */
9847398450
);
9847498451
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
9847598452
VdbeComment((v,
9847698453
"usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
9847798454
}
@@ -98518,20 +98495,10 @@
9851898495
sqlite3VdbeMakeReady(v, pParse);
9851998496
pParse->rc = SQLITE_DONE;
9852098497
}else{
9852198498
pParse->rc = SQLITE_ERROR;
9852298499
}
98523
-
98524
- /* We are done with this Parse object. There is no need to de-initialize it */
98525
-#if 0
98526
- pParse->colNamesSet = 0;
98527
- pParse->nTab = 0;
98528
- pParse->nMem = 0;
98529
- pParse->nSet = 0;
98530
- pParse->nVar = 0;
98531
- DbMaskZero(pParse->cookieMask);
98532
-#endif
9853398500
}
9853498501
9853598502
/*
9853698503
** Run the parser and code generator recursively in order to generate
9853798504
** code for the SQL statement given onto the end of the pParse context
@@ -98547,12 +98514,11 @@
9854798514
SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
9854898515
va_list ap;
9854998516
char *zSql;
9855098517
char *zErrMsg = 0;
9855198518
sqlite3 *db = pParse->db;
98552
-# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
98553
- char saveBuf[SAVE_SZ];
98519
+ char saveBuf[PARSE_TAIL_SZ];
9855498520
9855598521
if( pParse->nErr ) return;
9855698522
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
9855798523
va_start(ap, zFormat);
9855898524
zSql = sqlite3VMPrintf(db, zFormat, ap);
@@ -98559,16 +98525,16 @@
9855998525
va_end(ap);
9856098526
if( zSql==0 ){
9856198527
return; /* A malloc must have failed */
9856298528
}
9856398529
pParse->nested++;
98564
- memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
98565
- memset(&pParse->nVar, 0, SAVE_SZ);
98530
+ memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
98531
+ memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
9856698532
sqlite3RunParser(pParse, zSql, &zErrMsg);
9856798533
sqlite3DbFree(db, zErrMsg);
9856898534
sqlite3DbFree(db, zSql);
98569
- memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
98535
+ memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
9857098536
pParse->nested--;
9857198537
}
9857298538
9857398539
#if SQLITE_USER_AUTHENTICATION
9857498540
/*
@@ -102331,19 +102297,17 @@
102331102297
** will occur at the end of the top-level VDBE and will be generated
102332102298
** later, by sqlite3FinishCoding().
102333102299
*/
102334102300
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
102335102301
Parse *pToplevel = sqlite3ParseToplevel(pParse);
102336
- sqlite3 *db = pToplevel->db;
102337102302
102338
- assert( iDb>=0 && iDb<db->nDb );
102339
- assert( db->aDb[iDb].pBt!=0 || iDb==1 );
102303
+ assert( iDb>=0 && iDb<pParse->db->nDb );
102304
+ assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
102340102305
assert( iDb<SQLITE_MAX_ATTACHED+2 );
102341
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
102306
+ assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
102342102307
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
102343102308
DbMaskSet(pToplevel->cookieMask, iDb);
102344
- pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
102345102309
if( !OMIT_TEMPDB && iDb==1 ){
102346102310
sqlite3OpenTempDatabase(pToplevel);
102347102311
}
102348102312
}
102349102313
}
@@ -109551,10 +109515,11 @@
109551109515
}
109552109516
if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest);
109553109517
sqlite3ReleaseTempReg(pParse, regRowid);
109554109518
sqlite3ReleaseTempReg(pParse, regData);
109555109519
if( emptyDestTest ){
109520
+ sqlite3AutoincrementEnd(pParse);
109556109521
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
109557109522
sqlite3VdbeJumpHere(v, emptyDestTest);
109558109523
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
109559109524
return 0;
109560109525
}else{
@@ -114047,22 +114012,18 @@
114047114012
int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
114048114013
Vdbe *pReprepare, /* VM being reprepared */
114049114014
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
114050114015
const char **pzTail /* OUT: End of parsed string */
114051114016
){
114052
- Parse *pParse; /* Parsing context */
114053114017
char *zErrMsg = 0; /* Error message */
114054114018
int rc = SQLITE_OK; /* Result code */
114055114019
int i; /* Loop counter */
114056
-
114057
- /* Allocate the parsing context */
114058
- pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
114059
- if( pParse==0 ){
114060
- rc = SQLITE_NOMEM_BKPT;
114061
- goto end_prepare;
114062
- }
114063
- pParse->pReprepare = pReprepare;
114020
+ Parse sParse; /* Parsing context */
114021
+
114022
+ memset(&sParse, 0, PARSE_HDR_SZ);
114023
+ memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
114024
+ sParse.pReprepare = pReprepare;
114064114025
assert( ppStmt && *ppStmt==0 );
114065114026
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
114066114027
assert( sqlite3_mutex_held(db->mutex) );
114067114028
114068114029
/* Check to verify that it is possible to get a read lock on all
@@ -114102,12 +114063,11 @@
114102114063
}
114103114064
}
114104114065
114105114066
sqlite3VtabUnlockList(db);
114106114067
114107
- pParse->db = db;
114108
- pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */
114068
+ sParse.db = db;
114109114069
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
114110114070
char *zSqlCopy;
114111114071
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
114112114072
testcase( nBytes==mxLen );
114113114073
testcase( nBytes==mxLen+1 );
@@ -114116,65 +114076,65 @@
114116114076
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
114117114077
goto end_prepare;
114118114078
}
114119114079
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
114120114080
if( zSqlCopy ){
114121
- sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);
114122
- pParse->zTail = &zSql[pParse->zTail-zSqlCopy];
114081
+ sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
114082
+ sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
114123114083
sqlite3DbFree(db, zSqlCopy);
114124114084
}else{
114125
- pParse->zTail = &zSql[nBytes];
114085
+ sParse.zTail = &zSql[nBytes];
114126114086
}
114127114087
}else{
114128
- sqlite3RunParser(pParse, zSql, &zErrMsg);
114088
+ sqlite3RunParser(&sParse, zSql, &zErrMsg);
114129114089
}
114130
- assert( 0==pParse->nQueryLoop );
114090
+ assert( 0==sParse.nQueryLoop );
114131114091
114132
- if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
114133
- if( pParse->checkSchema ){
114134
- schemaIsValid(pParse);
114092
+ if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
114093
+ if( sParse.checkSchema ){
114094
+ schemaIsValid(&sParse);
114135114095
}
114136114096
if( db->mallocFailed ){
114137
- pParse->rc = SQLITE_NOMEM_BKPT;
114097
+ sParse.rc = SQLITE_NOMEM_BKPT;
114138114098
}
114139114099
if( pzTail ){
114140
- *pzTail = pParse->zTail;
114100
+ *pzTail = sParse.zTail;
114141114101
}
114142
- rc = pParse->rc;
114102
+ rc = sParse.rc;
114143114103
114144114104
#ifndef SQLITE_OMIT_EXPLAIN
114145
- if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
114105
+ if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
114146114106
static const char * const azColName[] = {
114147114107
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
114148114108
"selectid", "order", "from", "detail"
114149114109
};
114150114110
int iFirst, mx;
114151
- if( pParse->explain==2 ){
114152
- sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
114111
+ if( sParse.explain==2 ){
114112
+ sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
114153114113
iFirst = 8;
114154114114
mx = 12;
114155114115
}else{
114156
- sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
114116
+ sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
114157114117
iFirst = 0;
114158114118
mx = 8;
114159114119
}
114160114120
for(i=iFirst; i<mx; i++){
114161
- sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
114121
+ sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
114162114122
azColName[i], SQLITE_STATIC);
114163114123
}
114164114124
}
114165114125
#endif
114166114126
114167114127
if( db->init.busy==0 ){
114168
- Vdbe *pVdbe = pParse->pVdbe;
114169
- sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
114128
+ Vdbe *pVdbe = sParse.pVdbe;
114129
+ sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
114170114130
}
114171
- if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
114172
- sqlite3VdbeFinalize(pParse->pVdbe);
114131
+ if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
114132
+ sqlite3VdbeFinalize(sParse.pVdbe);
114173114133
assert(!(*ppStmt));
114174114134
}else{
114175
- *ppStmt = (sqlite3_stmt*)pParse->pVdbe;
114135
+ *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
114176114136
}
114177114137
114178114138
if( zErrMsg ){
114179114139
sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
114180114140
sqlite3DbFree(db, zErrMsg);
@@ -114181,20 +114141,19 @@
114181114141
}else{
114182114142
sqlite3Error(db, rc);
114183114143
}
114184114144
114185114145
/* Delete any TriggerPrg structures allocated while parsing this statement. */
114186
- while( pParse->pTriggerPrg ){
114187
- TriggerPrg *pT = pParse->pTriggerPrg;
114188
- pParse->pTriggerPrg = pT->pNext;
114146
+ while( sParse.pTriggerPrg ){
114147
+ TriggerPrg *pT = sParse.pTriggerPrg;
114148
+ sParse.pTriggerPrg = pT->pNext;
114189114149
sqlite3DbFree(db, pT);
114190114150
}
114191114151
114192114152
end_prepare:
114193114153
114194
- sqlite3ParserReset(pParse);
114195
- sqlite3StackFree(db, pParse);
114154
+ sqlite3ParserReset(&sParse);
114196114155
rc = sqlite3ApiExit(db, rc);
114197114156
assert( (rc&db->errMask)==rc );
114198114157
return rc;
114199114158
}
114200114159
static int sqlite3LockAndPrepare(
@@ -115395,11 +115354,11 @@
115395115354
** Allocate a KeyInfo object sufficient for an index of N key columns and
115396115355
** X extra columns.
115397115356
*/
115398115357
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
115399115358
int nExtra = (N+X)*(sizeof(CollSeq*)+1);
115400
- KeyInfo *p = sqlite3DbMallocRaw(db, sizeof(KeyInfo) + nExtra);
115359
+ KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
115401115360
if( p ){
115402115361
p->aSortOrder = (u8*)&p->aColl[N+X];
115403115362
p->nField = (u16)N;
115404115363
p->nXField = (u16)X;
115405115364
p->enc = ENC(db);
@@ -124055,24 +124014,24 @@
124055124014
** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
124056124015
** is only able to process joins with 64 or fewer tables.
124057124016
*/
124058124017
struct WhereTerm {
124059124018
Expr *pExpr; /* Pointer to the subexpression that is this term */
124019
+ WhereClause *pWC; /* The clause this term is part of */
124020
+ LogEst truthProb; /* Probability of truth for this expression */
124021
+ u16 wtFlags; /* TERM_xxx bit flags. See below */
124022
+ u16 eOperator; /* A WO_xx value describing <op> */
124023
+ u8 nChild; /* Number of children that must disable us */
124024
+ u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
124060124025
int iParent; /* Disable pWC->a[iParent] when this term disabled */
124061124026
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
124062124027
int iField; /* Field in (?,?,?) IN (SELECT...) vector */
124063124028
union {
124064124029
int leftColumn; /* Column number of X in "X <op> <expr>" */
124065124030
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
124066124031
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
124067124032
} u;
124068
- LogEst truthProb; /* Probability of truth for this expression */
124069
- u16 eOperator; /* A WO_xx value describing <op> */
124070
- u16 wtFlags; /* TERM_xxx bit flags. See below */
124071
- u8 nChild; /* Number of children that must disable us */
124072
- u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
124073
- WhereClause *pWC; /* The clause this term is part of */
124074124033
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
124075124034
Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
124076124035
};
124077124036
124078124037
/*
@@ -124221,29 +124180,29 @@
124221124180
struct WhereInfo {
124222124181
Parse *pParse; /* Parsing and code generating context */
124223124182
SrcList *pTabList; /* List of tables in the join */
124224124183
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
124225124184
ExprList *pDistinctSet; /* DISTINCT over all these values */
124226
- WhereLoop *pLoops; /* List of all WhereLoop objects */
124227
- Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
124228
- LogEst nRowOut; /* Estimated number of output rows */
124229124185
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
124186
+ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
124187
+ int iContinue; /* Jump here to continue with next record */
124188
+ int iBreak; /* Jump here to break out of the loop */
124189
+ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
124230124190
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
124191
+ u8 nLevel; /* Number of nested loop */
124231124192
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
124232124193
u8 sorted; /* True if really sorted (not just grouped) */
124233124194
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
124234124195
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
124235124196
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
124236
- u8 nLevel; /* Number of nested loop */
124237124197
u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
124238124198
int iTop; /* The very beginning of the WHERE loop */
124239
- int iContinue; /* Jump here to continue with next record */
124240
- int iBreak; /* Jump here to break out of the loop */
124241
- int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
124242
- int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
124243
- WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
124199
+ WhereLoop *pLoops; /* List of all WhereLoop objects */
124200
+ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
124201
+ LogEst nRowOut; /* Estimated number of output rows */
124244124202
WhereClause sWC; /* Decomposition of the WHERE clause */
124203
+ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
124245124204
WhereLevel a[1]; /* Information about each nest loop in WHERE */
124246124205
};
124247124206
124248124207
/*
124249124208
** Private interfaces - callable only by other where.c routines.
@@ -124703,11 +124662,10 @@
124703124662
**
124704124663
** * the comparison will be performed with no affinity, or
124705124664
** * the affinity change in zAff is guaranteed not to change the value.
124706124665
*/
124707124666
static void updateRangeAffinityStr(
124708
- Parse *pParse, /* Parse context */
124709124667
Expr *pRight, /* RHS of comparison */
124710124668
int n, /* Number of vector elements in comparison */
124711124669
char *zAff /* Affinity string to modify */
124712124670
){
124713124671
int i;
@@ -125789,15 +125747,15 @@
125789125747
assert( (bRev & ~1)==0 );
125790125748
pLevel->iLikeRepCntr <<=1;
125791125749
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125792125750
}
125793125751
#endif
125794
- if( pRangeStart==0
125795
- && (j = pIdx->aiColumn[nEq])>=0
125796
- && pIdx->pTable->aCol[j].notNull==0
125797
- ){
125798
- bSeekPastNull = 1;
125752
+ if( pRangeStart==0 ){
125753
+ j = pIdx->aiColumn[nEq];
125754
+ if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
125755
+ bSeekPastNull = 1;
125756
+ }
125799125757
}
125800125758
}
125801125759
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125802125760
125803125761
/* If we are doing a reverse order scan on an ascending index, or
@@ -125843,11 +125801,11 @@
125843125801
){
125844125802
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125845125803
VdbeCoverage(v);
125846125804
}
125847125805
if( zStartAff ){
125848
- updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]);
125806
+ updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
125849125807
}
125850125808
nConstraint += nBtm;
125851125809
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125852125810
if( sqlite3ExprIsVector(pRight)==0 ){
125853125811
disableTerm(pLevel, pRangeStart);
@@ -125893,11 +125851,11 @@
125893125851
){
125894125852
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125895125853
VdbeCoverage(v);
125896125854
}
125897125855
if( zEndAff ){
125898
- updateRangeAffinityStr(pParse, pRight, nTop, zEndAff);
125856
+ updateRangeAffinityStr(pRight, nTop, zEndAff);
125899125857
codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125900125858
}else{
125901125859
assert( pParse->db->mallocFailed );
125902125860
}
125903125861
nConstraint += nTop;
@@ -126329,11 +126287,11 @@
126329126287
** and we are coding the t1 loop and the t2 loop has not yet coded,
126330126288
** then we cannot use the "t1.a=t2.b" constraint, but we can code
126331126289
** the implied "t1.a=123" constraint.
126332126290
*/
126333126291
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
126334
- Expr *pE, *pEAlt;
126292
+ Expr *pE, sEAlt;
126335126293
WhereTerm *pAlt;
126336126294
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
126337126295
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
126338126296
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
126339126297
if( pTerm->leftCursor!=iCur ) continue;
@@ -126347,17 +126305,13 @@
126347126305
if( pAlt->wtFlags & (TERM_CODED) ) continue;
126348126306
testcase( pAlt->eOperator & WO_EQ );
126349126307
testcase( pAlt->eOperator & WO_IS );
126350126308
testcase( pAlt->eOperator & WO_IN );
126351126309
VdbeModuleComment((v, "begin transitive constraint"));
126352
- pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
126353
- if( pEAlt ){
126354
- *pEAlt = *pAlt->pExpr;
126355
- pEAlt->pLeft = pE->pLeft;
126356
- sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL);
126357
- sqlite3StackFree(db, pEAlt);
126358
- }
126310
+ sEAlt = *pAlt->pExpr;
126311
+ sEAlt.pLeft = pE->pLeft;
126312
+ sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
126359126313
}
126360126314
126361126315
/* For a LEFT OUTER JOIN, generate code that will record the fact that
126362126316
** at least one row of the right table has matched the left table.
126363126317
*/
@@ -126462,11 +126416,10 @@
126462126416
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
126463126417
if( pOld!=pWC->aStatic ){
126464126418
sqlite3DbFree(db, pOld);
126465126419
}
126466126420
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
126467
- memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm));
126468126421
}
126469126422
pTerm = &pWC->a[idx = pWC->nTerm++];
126470126423
if( p && ExprHasProperty(p, EP_Unlikely) ){
126471126424
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
126472126425
}else{
@@ -126474,10 +126427,12 @@
126474126427
}
126475126428
pTerm->pExpr = sqlite3ExprSkipCollate(p);
126476126429
pTerm->wtFlags = wtFlags;
126477126430
pTerm->pWC = pWC;
126478126431
pTerm->iParent = -1;
126432
+ memset(&pTerm->eOperator, 0,
126433
+ sizeof(WhereTerm) - offsetof(WhereTerm,eOperator));
126479126434
return idx;
126480126435
}
126481126436
126482126437
/*
126483126438
** Return TRUE if the given operator is one of the operators that is
@@ -130048,11 +130003,11 @@
130048130003
** CREATE INDEX ... ON (a, b, c, d, e)
130049130004
**
130050130005
** then this function would be invoked with nEq=1. The value returned in
130051130006
** this case is 3.
130052130007
*/
130053
-int whereRangeVectorLen(
130008
+static int whereRangeVectorLen(
130054130009
Parse *pParse, /* Parsing context */
130055130010
int iCur, /* Cursor open on pIdx */
130056130011
Index *pIdx, /* The index to be used for a inequality constraint */
130057130012
int nEq, /* Number of prior equality constraints on same index */
130058130013
WhereTerm *pTerm /* The vector inequality constraint */
@@ -131494,11 +131449,11 @@
131494131449
if( rev ) *pRevMask |= MASKBIT(iLoop);
131495131450
revSet = 1;
131496131451
}
131497131452
}
131498131453
if( isMatch ){
131499
- if( iColumn<0 ){
131454
+ if( iColumn==XN_ROWID ){
131500131455
testcase( distinctColumns==0 );
131501131456
distinctColumns = 1;
131502131457
}
131503131458
obSat |= MASKBIT(i);
131504131459
}else{
@@ -131948,15 +131903,20 @@
131948131903
}
131949131904
}else{
131950131905
pWInfo->nOBSat = pFrom->isOrdered;
131951131906
pWInfo->revMask = pFrom->revLoop;
131952131907
if( pWInfo->nOBSat<=0 ){
131908
+ u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
131953131909
pWInfo->nOBSat = 0;
131954
- if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){
131910
+ if( nLoop>0 && (wsFlags & WHERE_ONEROW)==0
131911
+ && (wsFlags & (WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
131912
+ ){
131955131913
Bitmask m = 0;
131956131914
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
131957131915
WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
131916
+ testcase( wsFlags & WHERE_IPK );
131917
+ testcase( wsFlags & WHERE_COLUMN_IN );
131958131918
if( rc==pWInfo->pOrderBy->nExpr ){
131959131919
pWInfo->bOrderedInnerLoop = 1;
131960131920
pWInfo->revMask = m;
131961131921
}
131962131922
}
@@ -132232,26 +132192,29 @@
132232132192
** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
132233132193
** field (type Bitmask) it must be aligned on an 8-byte boundary on
132234132194
** some architectures. Hence the ROUND8() below.
132235132195
*/
132236132196
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
132237
- pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
132197
+ pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
132238132198
if( db->mallocFailed ){
132239132199
sqlite3DbFree(db, pWInfo);
132240132200
pWInfo = 0;
132241132201
goto whereBeginError;
132242132202
}
132243
- pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
132244
- pWInfo->nLevel = nTabList;
132245132203
pWInfo->pParse = pParse;
132246132204
pWInfo->pTabList = pTabList;
132247132205
pWInfo->pOrderBy = pOrderBy;
132248132206
pWInfo->pDistinctSet = pDistinctSet;
132207
+ pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
132208
+ pWInfo->nLevel = nTabList;
132249132209
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
132250132210
pWInfo->wctrlFlags = wctrlFlags;
132251132211
pWInfo->iLimit = iAuxArg;
132252132212
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
132213
+ memset(&pWInfo->nOBSat, 0,
132214
+ offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
132215
+ memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
132253132216
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
132254132217
pMaskSet = &pWInfo->sMaskSet;
132255132218
sWLB.pWInfo = pWInfo;
132256132219
sWLB.pWC = &pWInfo->sWC;
132257132220
sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
@@ -135704,12 +135667,13 @@
135704135667
yymsp[0].minor.yy190 = yylhsminor.yy190;
135705135668
break;
135706135669
case 159: /* expr ::= VARIABLE */
135707135670
{
135708135671
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
135672
+ u32 n = yymsp[0].minor.yy0.n;
135709135673
spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0);
135710
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr);
135674
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n);
135711135675
}else{
135712135676
/* When doing a nested parse, one can include terms in an expression
135713135677
** that look like this: #1 #2 ... These terms refer to registers
135714135678
** in the virtual machine. #N is the N-th register. */
135715135679
Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
@@ -136478,11 +136442,11 @@
136478136442
}
136479136443
#endif
136480136444
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
136481136445
yymajor = YYNOCODE;
136482136446
}else{
136483
- while( yypParser->yytos >= &yypParser->yystack
136447
+ while( yypParser->yytos >= yypParser->yystack
136484136448
&& yymx != YYERRORSYMBOL
136485136449
&& (yyact = yy_find_reduce_action(
136486136450
yypParser->yytos->stateno,
136487136451
YYERRORSYMBOL)) >= YY_MIN_REDUCE
136488136452
){
@@ -164335,14 +164299,16 @@
164335164299
char *zSql;
164336164300
sqlite3_stmt *p;
164337164301
int rc;
164338164302
i64 nRow = 0;
164339164303
164340
- if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1",
164341
- 0,0,0,0,0,0)==SQLITE_ERROR ){
164304
+ rc = sqlite3_table_column_metadata(
164305
+ db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
164306
+ );
164307
+ if( rc!=SQLITE_OK ){
164342164308
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164343
- return SQLITE_OK;
164309
+ return rc==SQLITE_ERROR ? SQLITE_OK : rc;
164344164310
}
164345164311
zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164346164312
if( zSql==0 ){
164347164313
rc = SQLITE_NOMEM;
164348164314
}else{
@@ -181169,11 +181135,11 @@
181169181135
}
181170181136
#endif
181171181137
fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion);
181172181138
fts5yymajor = fts5YYNOCODE;
181173181139
}else{
181174
- while( fts5yypParser->fts5yytos >= &fts5yypParser->fts5yystack
181140
+ while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack
181175181141
&& fts5yymx != fts5YYERRORSYMBOL
181176181142
&& (fts5yyact = fts5yy_find_reduce_action(
181177181143
fts5yypParser->fts5yytos->stateno,
181178181144
fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE
181179181145
){
@@ -181535,10 +181501,13 @@
181535181501
int nToken, /* Size of token in bytes */
181536181502
int iStartOff, /* Start offset of token */
181537181503
int iEndOff /* End offset of token */
181538181504
){
181539181505
int rc = SQLITE_OK;
181506
+
181507
+ UNUSED_PARAM2(pToken, nToken);
181508
+ UNUSED_PARAM(iEndOff);
181540181509
181541181510
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181542181511
Fts5SFinder *p = (Fts5SFinder*)pContext;
181543181512
if( p->iPos>0 ){
181544181513
int i;
@@ -181691,11 +181660,10 @@
181691181660
for(jj=0; jj<(sFinder.nFirst-1); jj++){
181692181661
if( sFinder.aFirst[jj+1]>io ) break;
181693181662
}
181694181663
181695181664
if( sFinder.aFirst[jj]<io ){
181696
- int nScore;
181697181665
memset(aSeen, 0, nPhrase);
181698181666
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181699181667
sFinder.aFirst[jj], nToken, &nScore, 0
181700181668
);
181701181669
@@ -195626,11 +195594,11 @@
195626195594
int nArg, /* Number of args */
195627195595
sqlite3_value **apUnused /* Function arguments */
195628195596
){
195629195597
assert( nArg==0 );
195630195598
UNUSED_PARAM2(nArg, apUnused);
195631
- sqlite3_result_text(pCtx, "fts5: 2016-09-16 17:50:57 e3d9efa2770cd789ece3f4db4941b901c8b805ad", -1, SQLITE_TRANSIENT);
195599
+ sqlite3_result_text(pCtx, "fts5: 2016-10-10 14:48:36 6624c4964b63e259d5ee006eaa7ec79ddadbd6a6", -1, SQLITE_TRANSIENT);
195632195600
}
195633195601
195634195602
static int fts5Init(sqlite3 *db){
195635195603
static const sqlite3_module fts5Mod = {
195636195604
/* iVersion */ 2,
195637195605
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -381,11 +381,11 @@
381 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382 ** [sqlite_version()] and [sqlite_source_id()].
383 */
384 #define SQLITE_VERSION "3.15.0"
385 #define SQLITE_VERSION_NUMBER 3015000
386 #define SQLITE_SOURCE_ID "2016-09-28 16:05:53 40c0fb0af678797c39a99853f9f4102464c16f4b"
387
388 /*
389 ** CAPI3REF: Run-Time Library Version Numbers
390 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
391 **
@@ -15515,39 +15515,27 @@
15515 u8 mayAbort; /* True if statement may throw an ABORT exception */
15516 u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
15517 u8 okConstFactor; /* OK to factor out constants */
15518 u8 disableLookaside; /* Number of times lookaside has been disabled */
15519 u8 nColCache; /* Number of entries in aColCache[] */
15520 int aTempReg[8]; /* Holding area for temporary registers */
15521 int nRangeReg; /* Size of the temporary register block */
15522 int iRangeReg; /* First register in temporary register block */
15523 int nErr; /* Number of errors seen */
15524 int nTab; /* Number of previously allocated VDBE cursors */
15525 int nMem; /* Number of memory cells used so far */
15526 int nSet; /* Number of sets used so far */
15527 int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
15528 int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
15529 int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
15530 int ckBase; /* Base register of data during check constraints */
15531 int iSelfTab; /* Table of an index whose exprs are being coded */
15532 int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
15533 int iCacheCnt; /* Counter used to generate aColCache[].lru values */
15534 int nLabel; /* Number of labels used */
15535 int *aLabel; /* Space to hold the labels */
15536 struct yColCache {
15537 int iTable; /* Table cursor number */
15538 i16 iColumn; /* Table column number */
15539 u8 tempReg; /* iReg is a temp register that needs to be freed */
15540 int iLevel; /* Nesting level */
15541 int iReg; /* Reg with value of this column. 0 means none. */
15542 int lru; /* Least recently used entry has the smallest value */
15543 } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
15544 ExprList *pConstExpr;/* Constant expressions */
15545 Token constraintName;/* Name of the constraint currently being parsed */
15546 yDbMask writeMask; /* Start a write transaction on these databases */
15547 yDbMask cookieMask; /* Bitmask of schema verified databases */
15548 int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
15549 int regRowid; /* Register holding rowid of CREATE TABLE entry */
15550 int regRoot; /* Register holding root page number for new objects */
15551 int nMaxArg; /* Max args passed to user function by sub-program */
15552 #if SELECTTRACE_ENABLED
15553 int nSelect; /* Number of SELECT statements seen */
@@ -15556,21 +15544,38 @@
15556 #ifndef SQLITE_OMIT_SHARED_CACHE
15557 int nTableLock; /* Number of locks in aTableLock */
15558 TableLock *aTableLock; /* Required table locks for shared-cache mode */
15559 #endif
15560 AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
15561
15562 /* Information used while coding trigger programs. */
15563 Parse *pToplevel; /* Parse structure for main program (or NULL) */
15564 Table *pTriggerTab; /* Table triggers are being coded for */
15565 int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
15566 u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
15567 u32 oldmask; /* Mask of old.* columns referenced */
15568 u32 newmask; /* Mask of new.* columns referenced */
15569 u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
15570 u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
15571 u8 disableTriggers; /* True to disable triggers */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15572
15573 /************************************************************************
15574 ** Above is constant between recursions. Below is reset before and after
15575 ** each recursion. The boundary between these two regions is determined
15576 ** using offsetof(Parse,nVar) so the nVar field must be the first field
@@ -15583,11 +15588,10 @@
15583 u8 explain; /* True if the EXPLAIN flag is found on the query */
15584 #ifndef SQLITE_OMIT_VIRTUALTABLE
15585 u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
15586 int nVtabLock; /* Number of virtual tables to lock */
15587 #endif
15588 int nAlias; /* Number of aliased result set columns */
15589 int nHeight; /* Expression tree height of current sub-select */
15590 #ifndef SQLITE_OMIT_EXPLAIN
15591 int iSelectId; /* ID of current select for EXPLAIN output */
15592 int iNextSelectId; /* Next available select ID for EXPLAIN output */
15593 #endif
@@ -15595,12 +15599,10 @@
15595 Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
15596 const char *zTail; /* All SQL text past the last semicolon parsed */
15597 Table *pNewTable; /* A table being constructed by CREATE TABLE */
15598 Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
15599 const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
15600 Token sNameToken; /* Token with unqualified schema object name */
15601 Token sLastToken; /* The last token parsed */
15602 #ifndef SQLITE_OMIT_VIRTUALTABLE
15603 Token sArg; /* Complete text of a module argument */
15604 Table **apVtabLock; /* Pointer to virtual tables needing locking */
15605 #endif
15606 Table *pZombieTab; /* List of Table objects to delete after code gen */
@@ -15607,10 +15609,18 @@
15607 TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
15608 With *pWith; /* Current WITH clause, or NULL */
15609 With *pWithToFree; /* Free this WITH object at the end of the parse */
15610 };
15611
 
 
 
 
 
 
 
 
15612 /*
15613 ** Return true if currently inside an sqlite3_declare_vtab() call.
15614 */
15615 #ifdef SQLITE_OMIT_VIRTUALTABLE
15616 #define IN_DECLARE_VTAB 0
@@ -16170,11 +16180,11 @@
16170 SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
16171 SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
16172 SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
16173 SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
16174 SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
16175 SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*);
16176 SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
16177 SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
16178 SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
16179 SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int);
16180 SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
@@ -16990,20 +17000,17 @@
16990 ** If x is a lower-case ASCII character, then its upper-case equivalent
16991 ** is (x - 0x20). Therefore toupper() can be implemented as:
16992 **
16993 ** (x & ~(map[x]&0x20))
16994 **
16995 ** Standard function tolower() is implemented using the sqlite3UpperToLower[]
16996 ** array. tolower() is used more often than toupper() by SQLite.
16997 **
16998 ** Bit 0x40 is set if the character non-alphanumeric and can be used in an
16999 ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
17000 ** non-ASCII UTF character. Hence the test for whether or not a character is
17001 ** part of an identifier is 0x46.
17002 **
17003 ** SQLite's versions are identical to the standard versions assuming a
17004 ** locale of "C". They are implemented as macros in sqliteInt.h.
17005 */
17006 #ifdef SQLITE_ASCII
17007 SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
17008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
17009 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
@@ -17072,11 +17079,11 @@
17072 #ifndef SQLITE_SORTER_PMASZ
17073 # define SQLITE_SORTER_PMASZ 250
17074 #endif
17075
17076 /* Statement journals spill to disk when their size exceeds the following
17077 ** threashold (in bytes). 0 means that statement journals are created and
17078 ** written to disk immediately (the default behavior for SQLite versions
17079 ** before 3.12.0). -1 means always keep the entire statement journal in
17080 ** memory. (The statement journal is also always held entirely in memory
17081 ** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this
17082 ** setting.)
@@ -17160,11 +17167,11 @@
17160
17161 /*
17162 ** The value of the "pending" byte must be 0x40000000 (1 byte past the
17163 ** 1-gibabyte boundary) in a compatible database. SQLite never uses
17164 ** the database page that contains the pending byte. It never attempts
17165 ** to read or write that page. The pending byte page is set assign
17166 ** for use by the VFS layers as space for managing file locks.
17167 **
17168 ** During testing, it is often desirable to move the pending byte to
17169 ** a different position in the file. This allows code that has to
17170 ** deal with the pending byte to run on files that are much smaller
@@ -17720,13 +17727,10 @@
17720 typedef unsigned Bool;
17721
17722 /* Opaque type used by code in vdbesort.c */
17723 typedef struct VdbeSorter VdbeSorter;
17724
17725 /* Opaque type used by the explainer */
17726 typedef struct Explain Explain;
17727
17728 /* Elements of the linked list at Vdbe.pAuxData */
17729 typedef struct AuxData AuxData;
17730
17731 /* Types of VDBE cursors */
17732 #define CURTYPE_BTREE 0
@@ -17797,10 +17801,16 @@
17797 /* 2*nField extra array elements allocated for aType[], beyond the one
17798 ** static element declared in the structure. nField total array slots for
17799 ** aType[] and nField+1 array slots for aOffset[] */
17800 };
17801
 
 
 
 
 
 
17802 /*
17803 ** When a sub-program is executed (OP_Program), a structure of this type
17804 ** is allocated to store the current value of the program counter, as
17805 ** well as the current memory cell array and various other frame specific
17806 ** values stored in the Vdbe struct. When the sub-program is finished,
@@ -17841,15 +17851,10 @@
17841 int nDbChange; /* Value of db->nChange */
17842 };
17843
17844 #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
17845
17846 /*
17847 ** A value for VdbeCursor.cacheValid that means the cache is always invalid.
17848 */
17849 #define CACHE_STALE 0
17850
17851 /*
17852 ** Internally, the vdbe manipulates nearly all SQL values as Mem
17853 ** structures. Each Mem struct may cache multiple representations (string,
17854 ** integer etc.) of the same value.
17855 */
@@ -17986,22 +17991,10 @@
17986 u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
17987 u8 argc; /* Number of arguments */
17988 sqlite3_value *argv[1]; /* Argument set */
17989 };
17990
17991 /*
17992 ** An Explain object accumulates indented output which is helpful
17993 ** in describing recursive data structures.
17994 */
17995 struct Explain {
17996 Vdbe *pVdbe; /* Attach the explanation to this Vdbe */
17997 StrAccum str; /* The string being accumulated */
17998 int nIndent; /* Number of elements in aIndent */
17999 u16 aIndent[100]; /* Levels of indentation */
18000 char zBase[100]; /* Initial space */
18001 };
18002
18003 /* A bitfield type for use inside of structures. Always follow with :N where
18004 ** N is the number of bits.
18005 */
18006 typedef unsigned bft; /* Bit Field Type */
18007
@@ -18022,57 +18015,61 @@
18022 ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
18023 ** is really a pointer to an instance of this structure.
18024 */
18025 struct Vdbe {
18026 sqlite3 *db; /* The database connection that owns this statement */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18027 Op *aOp; /* Space to hold the virtual machine's program */
18028 Mem *aMem; /* The memory locations */
18029 Mem **apArg; /* Arguments to currently executing user function */
18030 Mem *aColName; /* Column names to return */
18031 Mem *pResultSet; /* Pointer to an array of results */
18032 Parse *pParse; /* Parsing context used to create this Vdbe */
18033 int nMem; /* Number of memory locations currently allocated */
18034 int nOp; /* Number of instructions in the program */
18035 int nCursor; /* Number of slots in apCsr[] */
18036 u32 magic; /* Magic number for sanity checking */
18037 char *zErrMsg; /* Error message written here */
18038 Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
18039 VdbeCursor **apCsr; /* One element of this array for each open cursor */
18040 Mem *aVar; /* Values for the OP_Variable opcode. */
18041 char **azVar; /* Name of variables */
18042 ynVar nVar; /* Number of entries in aVar[] */
18043 ynVar nzVar; /* Number of entries in azVar[] */
18044 u32 cacheCtr; /* VdbeCursor row cache generation counter */
18045 int pc; /* The program counter */
18046 int rc; /* Value to return */
18047 #ifdef SQLITE_DEBUG
18048 int rcApp; /* errcode set by sqlite3_result_error_code() */
18049 #endif
18050 u16 nResColumn; /* Number of columns in one row of the result set */
18051 u8 errorAction; /* Recovery action to do in case of an error */
 
18052 bft expired:1; /* True if the VM needs to be recompiled */
18053 bft doingRerun:1; /* True if rerunning after an auto-reprepare */
18054 u8 minWriteFileFormat; /* Minimum file format for writable database files */
18055 bft explain:2; /* True if EXPLAIN present on SQL command */
18056 bft changeCntOn:1; /* True to update the change-counter */
18057 bft runOnlyOnce:1; /* Automatically expire on reset */
18058 bft usesStmtJournal:1; /* True if uses a statement journal */
18059 bft readOnly:1; /* True for statements that do not write */
18060 bft bIsReader:1; /* True for statements that read */
18061 bft isPrepareV2:1; /* True if prepared with prepare_v2() */
18062 int nChange; /* Number of db changes made since last reset */
18063 yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
18064 yDbMask lockMask; /* Subset of btreeMask that requires a lock */
18065 int iStatement; /* Statement number (or 0 if has not opened stmt) */
18066 u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
18067 #ifndef SQLITE_OMIT_TRACE
18068 i64 startTime; /* Time when query started - used for profiling */
18069 #endif
18070 i64 iCurrentTime; /* Value of julianday('now') for this statement */
18071 i64 nFkConstraint; /* Number of imm. FK constraints this VM */
18072 i64 nStmtDefCons; /* Number of def. constraints when stmt started */
18073 i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
18074 char *zSql; /* Text of the SQL statement that generated this */
18075 void *pFree; /* Free this when deleting the vdbe */
18076 VdbeFrame *pFrame; /* Parent frame */
18077 VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
18078 int nFrame; /* Number of frames in pFrame list */
@@ -18087,14 +18084,15 @@
18087 };
18088
18089 /*
18090 ** The following are allowed values for Vdbe.magic
18091 */
18092 #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
18093 #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
18094 #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
18095 #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
 
18096
18097 /*
18098 ** Structure used to store the context required by the
18099 ** sqlite3_preupdate_*() API functions.
18100 */
@@ -28776,11 +28774,15 @@
28776 */
28777 static unsigned int strHash(const char *z){
28778 unsigned int h = 0;
28779 unsigned char c;
28780 while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
28781 h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
 
 
 
 
28782 }
28783 return h;
28784 }
28785
28786
@@ -44019,11 +44021,11 @@
44019 ){
44020 PgHdr *pPgHdr;
44021 assert( pPage!=0 );
44022 pPgHdr = (PgHdr*)pPage->pExtra;
44023 assert( pPgHdr->pPage==0 );
44024 memset(pPgHdr, 0, sizeof(PgHdr));
44025 pPgHdr->pPage = pPage;
44026 pPgHdr->pData = pPage->pBuf;
44027 pPgHdr->pExtra = (void *)&pPgHdr[1];
44028 memset(pPgHdr->pExtra, 0, pCache->szExtra);
44029 pPgHdr->pCache = pCache;
@@ -58985,11 +58987,11 @@
58985 int bias, /* Bias search to the high end */
58986 int *pRes /* Write search results here */
58987 ){
58988 int rc; /* Status code */
58989 UnpackedRecord *pIdxKey; /* Unpacked index key */
58990 char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */
58991 char *pFree = 0;
58992
58993 if( pKey ){
58994 assert( nKey==(i64)(int)nKey );
58995 pIdxKey = sqlite3VdbeAllocUnpackedRecord(
@@ -64322,12 +64324,10 @@
64322 nSrc = pX->nData;
64323 assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */
64324 nHeader += putVarint32(&pCell[nHeader], nPayload);
64325 nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
64326 }else{
64327 assert( pX->nData==0 );
64328 assert( pX->nZero==0 );
64329 assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
64330 nSrc = nPayload = (int)pX->nKey;
64331 pSrc = pX->pKey;
64332 nHeader += putVarint32(&pCell[nHeader], nPayload);
64333 }
@@ -68023,26 +68023,20 @@
68023 */
68024 static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
68025 int i = sqlite3FindDbName(pDb, zDb);
68026
68027 if( i==1 ){
68028 Parse *pParse;
68029 int rc = 0;
68030 pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
68031 if( pParse==0 ){
68032 sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory");
68033 rc = SQLITE_NOMEM_BKPT;
68034 }else{
68035 pParse->db = pDb;
68036 if( sqlite3OpenTempDatabase(pParse) ){
68037 sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
68038 rc = SQLITE_ERROR;
68039 }
68040 sqlite3DbFree(pErrorDb, pParse->zErrMsg);
68041 sqlite3ParserReset(pParse);
68042 sqlite3StackFree(pErrorDb, pParse);
68043 }
68044 if( rc ){
68045 return 0;
68046 }
68047 }
68048
@@ -69042,10 +69036,11 @@
69042 assert( (pMem->flags&MEM_RowSet)==0 );
69043 assert( EIGHT_BYTE_ALIGNMENT(pMem) );
69044
69045
69046 if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
 
69047 return SQLITE_NOMEM_BKPT;
69048 }
69049
69050 /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
69051 ** string representation of the value. Then, if the required encoding
@@ -69341,11 +69336,11 @@
69341 switch( aff ){
69342 case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
69343 if( (pMem->flags & MEM_Blob)==0 ){
69344 sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
69345 assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69346 MemSetTypeFlag(pMem, MEM_Blob);
69347 }else{
69348 pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
69349 }
69350 break;
69351 }
@@ -70018,14 +70013,11 @@
70018 sqlite3_value *pVal = 0;
70019 int negInt = 1;
70020 const char *zNeg = "";
70021 int rc = SQLITE_OK;
70022
70023 if( !pExpr ){
70024 *ppVal = 0;
70025 return SQLITE_OK;
70026 }
70027 while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
70028 if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
70029
70030 /* Compressed expressions only appear when parsing the DEFAULT clause
70031 ** on a table column definition, and hence only when pCtx==0. This
@@ -70145,11 +70137,11 @@
70145 Expr *pExpr, /* The expression to evaluate */
70146 u8 enc, /* Encoding to use */
70147 u8 affinity, /* Affinity to use */
70148 sqlite3_value **ppVal /* Write the new value here */
70149 ){
70150 return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
70151 }
70152
70153 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
70154 /*
70155 ** The implementation of the sqlite_record() function. This function accepts
@@ -70488,12 +70480,13 @@
70488 ** Create a new virtual database engine.
70489 */
70490 SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
70491 sqlite3 *db = pParse->db;
70492 Vdbe *p;
70493 p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
70494 if( p==0 ) return 0;
 
70495 p->db = db;
70496 if( db->pVdbe ){
70497 db->pVdbe->pPrev = p;
70498 }
70499 p->pNext = db->pVdbe;
@@ -70651,13 +70644,12 @@
70651 #endif
70652 #ifdef SQLITE_DEBUG
70653 if( p->db->flags & SQLITE_VdbeAddopTrace ){
70654 int jj, kk;
70655 Parse *pParse = p->pParse;
70656 for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
70657 struct yColCache *x = pParse->aColCache + jj;
70658 if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
70659 printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
70660 kk++;
70661 }
70662 if( kk ) printf("\n");
70663 sqlite3VdbePrintOp(0, i, &p->aOp[i]);
@@ -70841,11 +70833,10 @@
70841 assert( j<p->nLabel );
70842 assert( j>=0 );
70843 if( p->aLabel ){
70844 p->aLabel[j] = v->nOp;
70845 }
70846 p->iFixedOp = v->nOp - 1;
70847 }
70848
70849 /*
70850 ** Mark the VDBE as one that can only be run one time.
70851 */
@@ -71232,19 +71223,19 @@
71232 }
71233 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
71234 sqlite3VdbeGetOp(p,addr)->p3 = val;
71235 }
71236 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
71237 if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5;
 
71238 }
71239
71240 /*
71241 ** Change the P2 operand of instruction addr so that it points to
71242 ** the address of the next instruction to be coded.
71243 */
71244 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
71245 p->pParse->iFixedOp = p->nOp - 1;
71246 sqlite3VdbeChangeP2(p, addr, p->nOp);
71247 }
71248
71249
71250 /*
@@ -71363,11 +71354,11 @@
71363 /*
71364 ** If the last opcode is "op" and it is not a jump destination,
71365 ** then remove it. Return true if and only if an opcode was removed.
71366 */
71367 SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
71368 if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
71369 return sqlite3VdbeChangeToNoop(p, p->nOp-1);
71370 }else{
71371 return 0;
71372 }
71373 }
@@ -71925,10 +71916,25 @@
71925 zCom
71926 );
71927 fflush(pOut);
71928 }
71929 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71930
71931 /*
71932 ** Release an array of N Mem elements
71933 */
71934 static void releaseMemArray(Mem *p, int N){
@@ -72137,10 +72143,11 @@
72137 return SQLITE_ERROR;
72138 }
72139 pMem->flags = MEM_Str|MEM_Term;
72140 zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
72141 if( zP4!=pMem->z ){
 
72142 sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
72143 }else{
72144 assert( pMem->z!=0 );
72145 pMem->n = sqlite3Strlen30(pMem->z);
72146 pMem->enc = SQLITE_UTF8;
@@ -72279,11 +72286,11 @@
72279 SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
72280 #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
72281 int i;
72282 #endif
72283 assert( p!=0 );
72284 assert( p->magic==VDBE_MAGIC_INIT );
72285
72286 /* There should be at least one opcode.
72287 */
72288 assert( p->nOp>0 );
72289
@@ -72368,14 +72375,11 @@
72368 n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
72369 x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
72370 assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
72371 x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
72372 assert( x.nFree>=0 );
72373 if( x.nFree>0 ){
72374 memset(x.pSpace, 0, x.nFree);
72375 assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
72376 }
72377
72378 resolveP2Values(p, &nArg);
72379 p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
72380 if( pParse->explain && nMem<10 ){
72381 nMem = 10;
@@ -72400,34 +72404,34 @@
72400 p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
72401 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
72402 p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
72403 #endif
72404 if( x.nNeeded==0 ) break;
72405 x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded);
72406 x.nFree = x.nNeeded;
72407 }while( !db->mallocFailed );
72408
72409 p->nCursor = nCursor;
72410 if( p->aVar ){
72411 p->nVar = (ynVar)nVar;
72412 for(n=0; n<nVar; n++){
72413 p->aVar[n].flags = MEM_Null;
72414 p->aVar[n].db = db;
72415 }
72416 }
72417 p->nzVar = pParse->nzVar;
72418 p->azVar = pParse->azVar;
72419 pParse->nzVar = 0;
72420 pParse->azVar = 0;
72421 if( p->aMem ){
72422 p->nMem = nMem;
72423 for(n=0; n<nMem; n++){
72424 p->aMem[n].flags = MEM_Undefined;
72425 p->aMem[n].db = db;
72426 }
72427 }
72428 p->explain = pParse->explain;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72429 sqlite3VdbeRewind(p);
72430 }
72431
72432 /*
72433 ** Close a VDBE cursor and release all the resources that cursor
@@ -72575,17 +72579,13 @@
72575
72576 releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
72577 sqlite3DbFree(db, p->aColName);
72578 n = nResColumn*COLNAME_N;
72579 p->nResColumn = (u16)nResColumn;
72580 p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
72581 if( p->aColName==0 ) return;
72582 while( n-- > 0 ){
72583 pColName->flags = MEM_Null;
72584 pColName->db = p->db;
72585 pColName++;
72586 }
72587 }
72588
72589 /*
72590 ** Set the name of the idx'th column to be returned by the SQL statement.
72591 ** zName must be a pointer to a nul terminated string.
@@ -73343,11 +73343,11 @@
73343 fclose(out);
73344 }
73345 }
73346 #endif
73347 p->iCurrentTime = 0;
73348 p->magic = VDBE_MAGIC_INIT;
73349 return p->rc & db->errMask;
73350 }
73351
73352 /*
73353 ** Clean up and delete a VDBE after execution. Return an integer which is
@@ -73407,23 +73407,25 @@
73407 */
73408 SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
73409 SubProgram *pSub, *pNext;
73410 int i;
73411 assert( p->db==0 || p->db==db );
73412 releaseMemArray(p->aVar, p->nVar);
73413 releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
73414 for(pSub=p->pProgram; pSub; pSub=pNext){
73415 pNext = pSub->pNext;
73416 vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
73417 sqlite3DbFree(db, pSub);
73418 }
73419 for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
73420 sqlite3DbFree(db, p->azVar);
 
 
 
 
73421 vdbeFreeOpArray(db, p->aOp, p->nOp);
73422 sqlite3DbFree(db, p->aColName);
73423 sqlite3DbFree(db, p->zSql);
73424 sqlite3DbFree(db, p->pFree);
73425 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
73426 for(i=0; i<p->nScan; i++){
73427 sqlite3DbFree(db, p->aScan[i].zName);
73428 }
73429 sqlite3DbFree(db, p->aScan);
@@ -76665,11 +76667,11 @@
76665 /*
76666 ** Return true if the prepared statement is in need of being reset.
76667 */
76668 SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
76669 Vdbe *v = (Vdbe*)pStmt;
76670 return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
76671 }
76672
76673 /*
76674 ** Return a pointer to the next prepared statement after pStmt associated
76675 ** with database connection pDb. If pStmt is NULL, return the first
@@ -78417,15 +78419,17 @@
78417 u16 nullFlag;
78418 pOut = out2Prerelease(p, pOp);
78419 cnt = pOp->p3-pOp->p2;
78420 assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
78421 pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
 
78422 while( cnt>0 ){
78423 pOut++;
78424 memAboutToChange(p, pOut);
78425 sqlite3VdbeMemSetNull(pOut);
78426 pOut->flags = nullFlag;
 
78427 cnt--;
78428 }
78429 break;
78430 }
78431
@@ -82338,13 +82342,10 @@
82338 if( pOp->opcode==OP_SorterInsert ){
82339 rc = sqlite3VdbeSorterWrite(pC, pIn2);
82340 }else{
82341 x.nKey = pIn2->n;
82342 x.pKey = pIn2->z;
82343 x.nData = 0;
82344 x.nZero = 0;
82345 x.pData = 0;
82346 rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
82347 ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
82348 );
82349 assert( pC->deferredMoveto==0 );
82350 pC->cacheStatus = CACHE_STALE;
@@ -88783,11 +88784,10 @@
88783 const char *zDb;
88784 Expr *pRight;
88785
88786 /* if( pSrcList==0 ) break; */
88787 notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
88788 /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/
88789 pRight = pExpr->pRight;
88790 if( pRight->op==TK_ID ){
88791 zDb = 0;
88792 zTable = pExpr->pLeft->u.zToken;
88793 zColumn = pRight->u.zToken;
@@ -88812,11 +88812,10 @@
88812 const char *zId; /* The function name. */
88813 FuncDef *pDef; /* Information about the function */
88814 u8 enc = ENC(pParse->db); /* The database encoding */
88815
88816 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
88817 notValid(pParse, pNC, "functions", NC_PartIdx);
88818 zId = pExpr->u.zToken;
88819 nId = sqlite3Strlen30(zId);
88820 pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
88821 if( pDef==0 ){
88822 pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -88872,11 +88871,12 @@
88872 }
88873 if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
88874 /* Date/time functions that use 'now', and other functions like
88875 ** sqlite_version() that might change over time cannot be used
88876 ** in an index. */
88877 notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr);
 
88878 }
88879 }
88880 if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
88881 sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
88882 pNC->nErr++;
@@ -90412,11 +90412,11 @@
90412 ** stored in u.zToken. Instead, the integer values is written
90413 ** into u.iValue and the EP_IntValue flag is set. No extra storage
90414 ** is allocated to hold the integer text and the dequote flag is ignored.
90415 */
90416 SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
90417 sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
90418 int op, /* Expression opcode */
90419 const Token *pToken, /* Token argument. Might be NULL */
90420 int dequote /* True to dequote */
90421 ){
90422 Expr *pNew;
@@ -90630,40 +90630,40 @@
90630 ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
90631 ** as the previous instance of the same wildcard. Or if this is the first
90632 ** instance of the wildcard, the next sequential variable number is
90633 ** assigned.
90634 */
90635 SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
90636 sqlite3 *db = pParse->db;
90637 const char *z;
90638
90639 if( pExpr==0 ) return;
90640 assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
90641 z = pExpr->u.zToken;
90642 assert( z!=0 );
90643 assert( z[0]!=0 );
 
90644 if( z[1]==0 ){
90645 /* Wildcard of the form "?". Assign the next variable number */
90646 assert( z[0]=='?' );
90647 pExpr->iColumn = (ynVar)(++pParse->nVar);
90648 }else{
90649 ynVar x = 0;
90650 u32 n = sqlite3Strlen30(z);
90651 if( z[0]=='?' ){
90652 /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
90653 ** use it as the variable number */
90654 i64 i;
90655 int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
90656 pExpr->iColumn = x = (ynVar)i;
90657 testcase( i==0 );
90658 testcase( i==1 );
90659 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
90660 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
90661 if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
90662 sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
90663 db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
90664 x = 0;
90665 }
90666 if( i>pParse->nVar ){
90667 pParse->nVar = (int)i;
90668 }
90669 }else{
@@ -90670,37 +90670,35 @@
90670 /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
90671 ** number as the prior appearance of the same name, or if the name
90672 ** has never appeared before, reuse the same variable number
90673 */
90674 ynVar i;
90675 for(i=0; i<pParse->nzVar; i++){
90676 if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
90677 pExpr->iColumn = x = (ynVar)i+1;
90678 break;
90679 }
90680 }
90681 if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
90682 }
90683 if( x>0 ){
90684 if( x>pParse->nzVar ){
90685 char **a;
90686 a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
90687 if( a==0 ){
90688 assert( db->mallocFailed ); /* Error reported through mallocFailed */
90689 return;
90690 }
90691 pParse->azVar = a;
90692 memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
90693 pParse->nzVar = x;
90694 }
90695 if( z[0]!='?' || pParse->azVar[x-1]==0 ){
90696 sqlite3DbFree(db, pParse->azVar[x-1]);
90697 pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
90698 }
90699 }
90700 }
90701 if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
90702 sqlite3ErrorMsg(pParse, "too many SQL variables");
90703 }
90704 }
90705
90706 /*
@@ -92656,36 +92654,23 @@
92656 #endif
92657 }
92658 }
92659 }
92660
92661 #if defined(SQLITE_DEBUG)
92662 /*
92663 ** Verify the consistency of the column cache
92664 */
92665 static int cacheIsValid(Parse *pParse){
92666 int i, n;
92667 for(i=n=0; i<SQLITE_N_COLCACHE; i++){
92668 if( pParse->aColCache[i].iReg>0 ) n++;
92669 }
92670 return n==pParse->nColCache;
92671 }
92672 #endif
92673
92674 /*
92675 ** Clear a cache entry.
92676 */
92677 static void cacheEntryClear(Parse *pParse, struct yColCache *p){
92678 if( p->tempReg ){
92679 if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
92680 pParse->aTempReg[pParse->nTempReg++] = p->iReg;
92681 }
92682 p->tempReg = 0;
92683 }
92684 p->iReg = 0;
92685 pParse->nColCache--;
92686 assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
 
 
92687 }
92688
92689
92690 /*
92691 ** Record in the column cache that a particular column from a
@@ -92711,64 +92696,52 @@
92711 **
92712 ** Actually, the way the column cache is currently used, we are guaranteed
92713 ** that the object will never already be in cache. Verify this guarantee.
92714 */
92715 #ifndef NDEBUG
92716 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92717 assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
92718 }
92719 #endif
92720
92721 /* Find an empty slot and replace it */
92722 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92723 if( p->iReg==0 ){
92724 p->iLevel = pParse->iCacheLevel;
92725 p->iTable = iTab;
92726 p->iColumn = iCol;
92727 p->iReg = iReg;
92728 p->tempReg = 0;
92729 p->lru = pParse->iCacheCnt++;
92730 pParse->nColCache++;
92731 assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
92732 return;
92733 }
92734 }
92735
92736 /* Replace the last recently used */
92737 minLru = 0x7fffffff;
92738 idxLru = -1;
92739 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92740 if( p->lru<minLru ){
92741 idxLru = i;
92742 minLru = p->lru;
92743 }
92744 }
92745 if( ALWAYS(idxLru>=0) ){
92746 p = &pParse->aColCache[idxLru];
92747 p->iLevel = pParse->iCacheLevel;
92748 p->iTable = iTab;
92749 p->iColumn = iCol;
92750 p->iReg = iReg;
92751 p->tempReg = 0;
92752 p->lru = pParse->iCacheCnt++;
92753 assert( cacheIsValid(pParse) );
92754 return;
92755 }
 
 
92756 }
92757
92758 /*
92759 ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
92760 ** Purge the range of registers from the column cache.
92761 */
92762 SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
92763 struct yColCache *p;
92764 if( iReg<=0 || pParse->nColCache==0 ) return;
92765 p = &pParse->aColCache[SQLITE_N_COLCACHE-1];
92766 while(1){
92767 if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p);
92768 if( p==pParse->aColCache ) break;
92769 p--;
 
92770 }
92771 }
92772
92773 /*
92774 ** Remember the current column cache context. Any new entries added
@@ -92788,22 +92761,23 @@
92788 ** Remove from the column cache any entries that were added since the
92789 ** the previous sqlite3ExprCachePush operation. In other words, restore
92790 ** the cache to the state it was in prior the most recent Push.
92791 */
92792 SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
92793 int i;
92794 struct yColCache *p;
92795 assert( pParse->iCacheLevel>=1 );
92796 pParse->iCacheLevel--;
92797 #ifdef SQLITE_DEBUG
92798 if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
92799 printf("POP to %d\n", pParse->iCacheLevel);
92800 }
92801 #endif
92802 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92803 if( p->iReg && p->iLevel>pParse->iCacheLevel ){
92804 cacheEntryClear(pParse, p);
 
 
92805 }
92806 }
92807 }
92808
92809 /*
@@ -92813,11 +92787,11 @@
92813 ** get them all.
92814 */
92815 static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
92816 int i;
92817 struct yColCache *p;
92818 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92819 if( p->iReg==iReg ){
92820 p->tempReg = 0;
92821 }
92822 }
92823 }
@@ -92891,12 +92865,12 @@
92891 ){
92892 Vdbe *v = pParse->pVdbe;
92893 int i;
92894 struct yColCache *p;
92895
92896 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92897 if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
92898 p->lru = pParse->iCacheCnt++;
92899 sqlite3ExprCachePinRegister(pParse, p->iReg);
92900 return p->iReg;
92901 }
92902 }
@@ -92924,22 +92898,24 @@
92924 /*
92925 ** Clear all column cache entries.
92926 */
92927 SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
92928 int i;
92929 struct yColCache *p;
92930
92931 #if SQLITE_DEBUG
92932 if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
92933 printf("CLEAR\n");
92934 }
92935 #endif
92936 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92937 if( p->iReg ){
92938 cacheEntryClear(pParse, p);
 
 
92939 }
92940 }
 
92941 }
92942
92943 /*
92944 ** Record the fact that an affinity change has occurred on iCount
92945 ** registers starting with iStart.
@@ -92967,11 +92943,11 @@
92967 ** and does not appear in a normal build.
92968 */
92969 static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
92970 int i;
92971 struct yColCache *p;
92972 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92973 int r = p->iReg;
92974 if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
92975 }
92976 return 0;
92977 }
@@ -94663,11 +94639,11 @@
94663 */
94664 SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
94665 if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
94666 int i;
94667 struct yColCache *p;
94668 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
94669 if( p->iReg==iReg ){
94670 p->tempReg = 1;
94671 return;
94672 }
94673 }
@@ -98433,11 +98409,10 @@
98433 */
98434 v = sqlite3GetVdbe(pParse);
98435 assert( !pParse->isMultiWrite
98436 || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
98437 if( v ){
98438 while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
98439 sqlite3VdbeAddOp0(v, OP_Halt);
98440
98441 #if SQLITE_USER_AUTHENTICATION
98442 if( pParse->nTableLock>0 && db->init.busy==0 ){
98443 sqlite3UserAuthInit(db);
@@ -98460,18 +98435,20 @@
98460 ){
98461 int iDb, i;
98462 assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
98463 sqlite3VdbeJumpHere(v, 0);
98464 for(iDb=0; iDb<db->nDb; iDb++){
 
98465 if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
98466 sqlite3VdbeUsesBtree(v, iDb);
 
98467 sqlite3VdbeAddOp4Int(v,
98468 OP_Transaction, /* Opcode */
98469 iDb, /* P1 */
98470 DbMaskTest(pParse->writeMask,iDb), /* P2 */
98471 pParse->cookieValue[iDb], /* P3 */
98472 db->aDb[iDb].pSchema->iGeneration /* P4 */
98473 );
98474 if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
98475 VdbeComment((v,
98476 "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
98477 }
@@ -98518,20 +98495,10 @@
98518 sqlite3VdbeMakeReady(v, pParse);
98519 pParse->rc = SQLITE_DONE;
98520 }else{
98521 pParse->rc = SQLITE_ERROR;
98522 }
98523
98524 /* We are done with this Parse object. There is no need to de-initialize it */
98525 #if 0
98526 pParse->colNamesSet = 0;
98527 pParse->nTab = 0;
98528 pParse->nMem = 0;
98529 pParse->nSet = 0;
98530 pParse->nVar = 0;
98531 DbMaskZero(pParse->cookieMask);
98532 #endif
98533 }
98534
98535 /*
98536 ** Run the parser and code generator recursively in order to generate
98537 ** code for the SQL statement given onto the end of the pParse context
@@ -98547,12 +98514,11 @@
98547 SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
98548 va_list ap;
98549 char *zSql;
98550 char *zErrMsg = 0;
98551 sqlite3 *db = pParse->db;
98552 # define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
98553 char saveBuf[SAVE_SZ];
98554
98555 if( pParse->nErr ) return;
98556 assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
98557 va_start(ap, zFormat);
98558 zSql = sqlite3VMPrintf(db, zFormat, ap);
@@ -98559,16 +98525,16 @@
98559 va_end(ap);
98560 if( zSql==0 ){
98561 return; /* A malloc must have failed */
98562 }
98563 pParse->nested++;
98564 memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
98565 memset(&pParse->nVar, 0, SAVE_SZ);
98566 sqlite3RunParser(pParse, zSql, &zErrMsg);
98567 sqlite3DbFree(db, zErrMsg);
98568 sqlite3DbFree(db, zSql);
98569 memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
98570 pParse->nested--;
98571 }
98572
98573 #if SQLITE_USER_AUTHENTICATION
98574 /*
@@ -102331,19 +102297,17 @@
102331 ** will occur at the end of the top-level VDBE and will be generated
102332 ** later, by sqlite3FinishCoding().
102333 */
102334 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
102335 Parse *pToplevel = sqlite3ParseToplevel(pParse);
102336 sqlite3 *db = pToplevel->db;
102337
102338 assert( iDb>=0 && iDb<db->nDb );
102339 assert( db->aDb[iDb].pBt!=0 || iDb==1 );
102340 assert( iDb<SQLITE_MAX_ATTACHED+2 );
102341 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
102342 if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
102343 DbMaskSet(pToplevel->cookieMask, iDb);
102344 pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
102345 if( !OMIT_TEMPDB && iDb==1 ){
102346 sqlite3OpenTempDatabase(pToplevel);
102347 }
102348 }
102349 }
@@ -109551,10 +109515,11 @@
109551 }
109552 if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest);
109553 sqlite3ReleaseTempReg(pParse, regRowid);
109554 sqlite3ReleaseTempReg(pParse, regData);
109555 if( emptyDestTest ){
 
109556 sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
109557 sqlite3VdbeJumpHere(v, emptyDestTest);
109558 sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
109559 return 0;
109560 }else{
@@ -114047,22 +114012,18 @@
114047 int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
114048 Vdbe *pReprepare, /* VM being reprepared */
114049 sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
114050 const char **pzTail /* OUT: End of parsed string */
114051 ){
114052 Parse *pParse; /* Parsing context */
114053 char *zErrMsg = 0; /* Error message */
114054 int rc = SQLITE_OK; /* Result code */
114055 int i; /* Loop counter */
114056
114057 /* Allocate the parsing context */
114058 pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
114059 if( pParse==0 ){
114060 rc = SQLITE_NOMEM_BKPT;
114061 goto end_prepare;
114062 }
114063 pParse->pReprepare = pReprepare;
114064 assert( ppStmt && *ppStmt==0 );
114065 /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
114066 assert( sqlite3_mutex_held(db->mutex) );
114067
114068 /* Check to verify that it is possible to get a read lock on all
@@ -114102,12 +114063,11 @@
114102 }
114103 }
114104
114105 sqlite3VtabUnlockList(db);
114106
114107 pParse->db = db;
114108 pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */
114109 if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
114110 char *zSqlCopy;
114111 int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
114112 testcase( nBytes==mxLen );
114113 testcase( nBytes==mxLen+1 );
@@ -114116,65 +114076,65 @@
114116 rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
114117 goto end_prepare;
114118 }
114119 zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
114120 if( zSqlCopy ){
114121 sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);
114122 pParse->zTail = &zSql[pParse->zTail-zSqlCopy];
114123 sqlite3DbFree(db, zSqlCopy);
114124 }else{
114125 pParse->zTail = &zSql[nBytes];
114126 }
114127 }else{
114128 sqlite3RunParser(pParse, zSql, &zErrMsg);
114129 }
114130 assert( 0==pParse->nQueryLoop );
114131
114132 if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
114133 if( pParse->checkSchema ){
114134 schemaIsValid(pParse);
114135 }
114136 if( db->mallocFailed ){
114137 pParse->rc = SQLITE_NOMEM_BKPT;
114138 }
114139 if( pzTail ){
114140 *pzTail = pParse->zTail;
114141 }
114142 rc = pParse->rc;
114143
114144 #ifndef SQLITE_OMIT_EXPLAIN
114145 if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
114146 static const char * const azColName[] = {
114147 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
114148 "selectid", "order", "from", "detail"
114149 };
114150 int iFirst, mx;
114151 if( pParse->explain==2 ){
114152 sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
114153 iFirst = 8;
114154 mx = 12;
114155 }else{
114156 sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
114157 iFirst = 0;
114158 mx = 8;
114159 }
114160 for(i=iFirst; i<mx; i++){
114161 sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
114162 azColName[i], SQLITE_STATIC);
114163 }
114164 }
114165 #endif
114166
114167 if( db->init.busy==0 ){
114168 Vdbe *pVdbe = pParse->pVdbe;
114169 sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
114170 }
114171 if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
114172 sqlite3VdbeFinalize(pParse->pVdbe);
114173 assert(!(*ppStmt));
114174 }else{
114175 *ppStmt = (sqlite3_stmt*)pParse->pVdbe;
114176 }
114177
114178 if( zErrMsg ){
114179 sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
114180 sqlite3DbFree(db, zErrMsg);
@@ -114181,20 +114141,19 @@
114181 }else{
114182 sqlite3Error(db, rc);
114183 }
114184
114185 /* Delete any TriggerPrg structures allocated while parsing this statement. */
114186 while( pParse->pTriggerPrg ){
114187 TriggerPrg *pT = pParse->pTriggerPrg;
114188 pParse->pTriggerPrg = pT->pNext;
114189 sqlite3DbFree(db, pT);
114190 }
114191
114192 end_prepare:
114193
114194 sqlite3ParserReset(pParse);
114195 sqlite3StackFree(db, pParse);
114196 rc = sqlite3ApiExit(db, rc);
114197 assert( (rc&db->errMask)==rc );
114198 return rc;
114199 }
114200 static int sqlite3LockAndPrepare(
@@ -115395,11 +115354,11 @@
115395 ** Allocate a KeyInfo object sufficient for an index of N key columns and
115396 ** X extra columns.
115397 */
115398 SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
115399 int nExtra = (N+X)*(sizeof(CollSeq*)+1);
115400 KeyInfo *p = sqlite3DbMallocRaw(db, sizeof(KeyInfo) + nExtra);
115401 if( p ){
115402 p->aSortOrder = (u8*)&p->aColl[N+X];
115403 p->nField = (u16)N;
115404 p->nXField = (u16)X;
115405 p->enc = ENC(db);
@@ -124055,24 +124014,24 @@
124055 ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
124056 ** is only able to process joins with 64 or fewer tables.
124057 */
124058 struct WhereTerm {
124059 Expr *pExpr; /* Pointer to the subexpression that is this term */
 
 
 
 
 
 
124060 int iParent; /* Disable pWC->a[iParent] when this term disabled */
124061 int leftCursor; /* Cursor number of X in "X <op> <expr>" */
124062 int iField; /* Field in (?,?,?) IN (SELECT...) vector */
124063 union {
124064 int leftColumn; /* Column number of X in "X <op> <expr>" */
124065 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
124066 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
124067 } u;
124068 LogEst truthProb; /* Probability of truth for this expression */
124069 u16 eOperator; /* A WO_xx value describing <op> */
124070 u16 wtFlags; /* TERM_xxx bit flags. See below */
124071 u8 nChild; /* Number of children that must disable us */
124072 u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
124073 WhereClause *pWC; /* The clause this term is part of */
124074 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
124075 Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
124076 };
124077
124078 /*
@@ -124221,29 +124180,29 @@
124221 struct WhereInfo {
124222 Parse *pParse; /* Parsing and code generating context */
124223 SrcList *pTabList; /* List of tables in the join */
124224 ExprList *pOrderBy; /* The ORDER BY clause or NULL */
124225 ExprList *pDistinctSet; /* DISTINCT over all these values */
124226 WhereLoop *pLoops; /* List of all WhereLoop objects */
124227 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
124228 LogEst nRowOut; /* Estimated number of output rows */
124229 LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
 
 
 
 
124230 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
 
124231 i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
124232 u8 sorted; /* True if really sorted (not just grouped) */
124233 u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
124234 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
124235 u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
124236 u8 nLevel; /* Number of nested loop */
124237 u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
124238 int iTop; /* The very beginning of the WHERE loop */
124239 int iContinue; /* Jump here to continue with next record */
124240 int iBreak; /* Jump here to break out of the loop */
124241 int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
124242 int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
124243 WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
124244 WhereClause sWC; /* Decomposition of the WHERE clause */
 
124245 WhereLevel a[1]; /* Information about each nest loop in WHERE */
124246 };
124247
124248 /*
124249 ** Private interfaces - callable only by other where.c routines.
@@ -124703,11 +124662,10 @@
124703 **
124704 ** * the comparison will be performed with no affinity, or
124705 ** * the affinity change in zAff is guaranteed not to change the value.
124706 */
124707 static void updateRangeAffinityStr(
124708 Parse *pParse, /* Parse context */
124709 Expr *pRight, /* RHS of comparison */
124710 int n, /* Number of vector elements in comparison */
124711 char *zAff /* Affinity string to modify */
124712 ){
124713 int i;
@@ -125789,15 +125747,15 @@
125789 assert( (bRev & ~1)==0 );
125790 pLevel->iLikeRepCntr <<=1;
125791 pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125792 }
125793 #endif
125794 if( pRangeStart==0
125795 && (j = pIdx->aiColumn[nEq])>=0
125796 && pIdx->pTable->aCol[j].notNull==0
125797 ){
125798 bSeekPastNull = 1;
125799 }
125800 }
125801 assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125802
125803 /* If we are doing a reverse order scan on an ascending index, or
@@ -125843,11 +125801,11 @@
125843 ){
125844 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125845 VdbeCoverage(v);
125846 }
125847 if( zStartAff ){
125848 updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]);
125849 }
125850 nConstraint += nBtm;
125851 testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125852 if( sqlite3ExprIsVector(pRight)==0 ){
125853 disableTerm(pLevel, pRangeStart);
@@ -125893,11 +125851,11 @@
125893 ){
125894 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125895 VdbeCoverage(v);
125896 }
125897 if( zEndAff ){
125898 updateRangeAffinityStr(pParse, pRight, nTop, zEndAff);
125899 codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125900 }else{
125901 assert( pParse->db->mallocFailed );
125902 }
125903 nConstraint += nTop;
@@ -126329,11 +126287,11 @@
126329 ** and we are coding the t1 loop and the t2 loop has not yet coded,
126330 ** then we cannot use the "t1.a=t2.b" constraint, but we can code
126331 ** the implied "t1.a=123" constraint.
126332 */
126333 for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
126334 Expr *pE, *pEAlt;
126335 WhereTerm *pAlt;
126336 if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
126337 if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
126338 if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
126339 if( pTerm->leftCursor!=iCur ) continue;
@@ -126347,17 +126305,13 @@
126347 if( pAlt->wtFlags & (TERM_CODED) ) continue;
126348 testcase( pAlt->eOperator & WO_EQ );
126349 testcase( pAlt->eOperator & WO_IS );
126350 testcase( pAlt->eOperator & WO_IN );
126351 VdbeModuleComment((v, "begin transitive constraint"));
126352 pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
126353 if( pEAlt ){
126354 *pEAlt = *pAlt->pExpr;
126355 pEAlt->pLeft = pE->pLeft;
126356 sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL);
126357 sqlite3StackFree(db, pEAlt);
126358 }
126359 }
126360
126361 /* For a LEFT OUTER JOIN, generate code that will record the fact that
126362 ** at least one row of the right table has matched the left table.
126363 */
@@ -126462,11 +126416,10 @@
126462 memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
126463 if( pOld!=pWC->aStatic ){
126464 sqlite3DbFree(db, pOld);
126465 }
126466 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
126467 memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm));
126468 }
126469 pTerm = &pWC->a[idx = pWC->nTerm++];
126470 if( p && ExprHasProperty(p, EP_Unlikely) ){
126471 pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
126472 }else{
@@ -126474,10 +126427,12 @@
126474 }
126475 pTerm->pExpr = sqlite3ExprSkipCollate(p);
126476 pTerm->wtFlags = wtFlags;
126477 pTerm->pWC = pWC;
126478 pTerm->iParent = -1;
 
 
126479 return idx;
126480 }
126481
126482 /*
126483 ** Return TRUE if the given operator is one of the operators that is
@@ -130048,11 +130003,11 @@
130048 ** CREATE INDEX ... ON (a, b, c, d, e)
130049 **
130050 ** then this function would be invoked with nEq=1. The value returned in
130051 ** this case is 3.
130052 */
130053 int whereRangeVectorLen(
130054 Parse *pParse, /* Parsing context */
130055 int iCur, /* Cursor open on pIdx */
130056 Index *pIdx, /* The index to be used for a inequality constraint */
130057 int nEq, /* Number of prior equality constraints on same index */
130058 WhereTerm *pTerm /* The vector inequality constraint */
@@ -131494,11 +131449,11 @@
131494 if( rev ) *pRevMask |= MASKBIT(iLoop);
131495 revSet = 1;
131496 }
131497 }
131498 if( isMatch ){
131499 if( iColumn<0 ){
131500 testcase( distinctColumns==0 );
131501 distinctColumns = 1;
131502 }
131503 obSat |= MASKBIT(i);
131504 }else{
@@ -131948,15 +131903,20 @@
131948 }
131949 }else{
131950 pWInfo->nOBSat = pFrom->isOrdered;
131951 pWInfo->revMask = pFrom->revLoop;
131952 if( pWInfo->nOBSat<=0 ){
 
131953 pWInfo->nOBSat = 0;
131954 if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){
 
 
131955 Bitmask m = 0;
131956 int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
131957 WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
 
 
131958 if( rc==pWInfo->pOrderBy->nExpr ){
131959 pWInfo->bOrderedInnerLoop = 1;
131960 pWInfo->revMask = m;
131961 }
131962 }
@@ -132232,26 +132192,29 @@
132232 ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
132233 ** field (type Bitmask) it must be aligned on an 8-byte boundary on
132234 ** some architectures. Hence the ROUND8() below.
132235 */
132236 nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
132237 pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
132238 if( db->mallocFailed ){
132239 sqlite3DbFree(db, pWInfo);
132240 pWInfo = 0;
132241 goto whereBeginError;
132242 }
132243 pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
132244 pWInfo->nLevel = nTabList;
132245 pWInfo->pParse = pParse;
132246 pWInfo->pTabList = pTabList;
132247 pWInfo->pOrderBy = pOrderBy;
132248 pWInfo->pDistinctSet = pDistinctSet;
 
 
132249 pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
132250 pWInfo->wctrlFlags = wctrlFlags;
132251 pWInfo->iLimit = iAuxArg;
132252 pWInfo->savedNQueryLoop = pParse->nQueryLoop;
 
 
 
132253 assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
132254 pMaskSet = &pWInfo->sMaskSet;
132255 sWLB.pWInfo = pWInfo;
132256 sWLB.pWC = &pWInfo->sWC;
132257 sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
@@ -135704,12 +135667,13 @@
135704 yymsp[0].minor.yy190 = yylhsminor.yy190;
135705 break;
135706 case 159: /* expr ::= VARIABLE */
135707 {
135708 if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
 
135709 spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0);
135710 sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr);
135711 }else{
135712 /* When doing a nested parse, one can include terms in an expression
135713 ** that look like this: #1 #2 ... These terms refer to registers
135714 ** in the virtual machine. #N is the N-th register. */
135715 Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
@@ -136478,11 +136442,11 @@
136478 }
136479 #endif
136480 yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
136481 yymajor = YYNOCODE;
136482 }else{
136483 while( yypParser->yytos >= &yypParser->yystack
136484 && yymx != YYERRORSYMBOL
136485 && (yyact = yy_find_reduce_action(
136486 yypParser->yytos->stateno,
136487 YYERRORSYMBOL)) >= YY_MIN_REDUCE
136488 ){
@@ -164335,14 +164299,16 @@
164335 char *zSql;
164336 sqlite3_stmt *p;
164337 int rc;
164338 i64 nRow = 0;
164339
164340 if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1",
164341 0,0,0,0,0,0)==SQLITE_ERROR ){
 
 
164342 pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164343 return SQLITE_OK;
164344 }
164345 zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164346 if( zSql==0 ){
164347 rc = SQLITE_NOMEM;
164348 }else{
@@ -181169,11 +181135,11 @@
181169 }
181170 #endif
181171 fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion);
181172 fts5yymajor = fts5YYNOCODE;
181173 }else{
181174 while( fts5yypParser->fts5yytos >= &fts5yypParser->fts5yystack
181175 && fts5yymx != fts5YYERRORSYMBOL
181176 && (fts5yyact = fts5yy_find_reduce_action(
181177 fts5yypParser->fts5yytos->stateno,
181178 fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE
181179 ){
@@ -181535,10 +181501,13 @@
181535 int nToken, /* Size of token in bytes */
181536 int iStartOff, /* Start offset of token */
181537 int iEndOff /* End offset of token */
181538 ){
181539 int rc = SQLITE_OK;
 
 
 
181540
181541 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181542 Fts5SFinder *p = (Fts5SFinder*)pContext;
181543 if( p->iPos>0 ){
181544 int i;
@@ -181691,11 +181660,10 @@
181691 for(jj=0; jj<(sFinder.nFirst-1); jj++){
181692 if( sFinder.aFirst[jj+1]>io ) break;
181693 }
181694
181695 if( sFinder.aFirst[jj]<io ){
181696 int nScore;
181697 memset(aSeen, 0, nPhrase);
181698 rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181699 sFinder.aFirst[jj], nToken, &nScore, 0
181700 );
181701
@@ -195626,11 +195594,11 @@
195626 int nArg, /* Number of args */
195627 sqlite3_value **apUnused /* Function arguments */
195628 ){
195629 assert( nArg==0 );
195630 UNUSED_PARAM2(nArg, apUnused);
195631 sqlite3_result_text(pCtx, "fts5: 2016-09-16 17:50:57 e3d9efa2770cd789ece3f4db4941b901c8b805ad", -1, SQLITE_TRANSIENT);
195632 }
195633
195634 static int fts5Init(sqlite3 *db){
195635 static const sqlite3_module fts5Mod = {
195636 /* iVersion */ 2,
195637
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -381,11 +381,11 @@
381 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382 ** [sqlite_version()] and [sqlite_source_id()].
383 */
384 #define SQLITE_VERSION "3.15.0"
385 #define SQLITE_VERSION_NUMBER 3015000
386 #define SQLITE_SOURCE_ID "2016-10-12 15:15:30 61f0526978af667781c57bcc87510e4524efd0d8"
387
388 /*
389 ** CAPI3REF: Run-Time Library Version Numbers
390 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
391 **
@@ -15515,39 +15515,27 @@
15515 u8 mayAbort; /* True if statement may throw an ABORT exception */
15516 u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
15517 u8 okConstFactor; /* OK to factor out constants */
15518 u8 disableLookaside; /* Number of times lookaside has been disabled */
15519 u8 nColCache; /* Number of entries in aColCache[] */
 
15520 int nRangeReg; /* Size of the temporary register block */
15521 int iRangeReg; /* First register in temporary register block */
15522 int nErr; /* Number of errors seen */
15523 int nTab; /* Number of previously allocated VDBE cursors */
15524 int nMem; /* Number of memory cells used so far */
 
15525 int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
15526 int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
 
15527 int ckBase; /* Base register of data during check constraints */
15528 int iSelfTab; /* Table of an index whose exprs are being coded */
15529 int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
15530 int iCacheCnt; /* Counter used to generate aColCache[].lru values */
15531 int nLabel; /* Number of labels used */
15532 int *aLabel; /* Space to hold the labels */
 
 
 
 
 
 
 
 
15533 ExprList *pConstExpr;/* Constant expressions */
15534 Token constraintName;/* Name of the constraint currently being parsed */
15535 yDbMask writeMask; /* Start a write transaction on these databases */
15536 yDbMask cookieMask; /* Bitmask of schema verified databases */
 
15537 int regRowid; /* Register holding rowid of CREATE TABLE entry */
15538 int regRoot; /* Register holding root page number for new objects */
15539 int nMaxArg; /* Max args passed to user function by sub-program */
15540 #if SELECTTRACE_ENABLED
15541 int nSelect; /* Number of SELECT statements seen */
@@ -15556,21 +15544,38 @@
15544 #ifndef SQLITE_OMIT_SHARED_CACHE
15545 int nTableLock; /* Number of locks in aTableLock */
15546 TableLock *aTableLock; /* Required table locks for shared-cache mode */
15547 #endif
15548 AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
 
 
15549 Parse *pToplevel; /* Parse structure for main program (or NULL) */
15550 Table *pTriggerTab; /* Table triggers are being coded for */
15551 int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
15552 u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
15553 u32 oldmask; /* Mask of old.* columns referenced */
15554 u32 newmask; /* Mask of new.* columns referenced */
15555 u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
15556 u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
15557 u8 disableTriggers; /* True to disable triggers */
15558
15559 /**************************************************************************
15560 ** Fields above must be initialized to zero. The fields that follow,
15561 ** down to the beginning of the recursive section, do not need to be
15562 ** initialized as they will be set before being used. The boundary is
15563 ** determined by offsetof(Parse,aColCache).
15564 **************************************************************************/
15565
15566 struct yColCache {
15567 int iTable; /* Table cursor number */
15568 i16 iColumn; /* Table column number */
15569 u8 tempReg; /* iReg is a temp register that needs to be freed */
15570 int iLevel; /* Nesting level */
15571 int iReg; /* Reg with value of this column. 0 means none. */
15572 int lru; /* Least recently used entry has the smallest value */
15573 } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
15574 int aTempReg[8]; /* Holding area for temporary registers */
15575 Token sNameToken; /* Token with unqualified schema object name */
15576 Token sLastToken; /* The last token parsed */
15577
15578 /************************************************************************
15579 ** Above is constant between recursions. Below is reset before and after
15580 ** each recursion. The boundary between these two regions is determined
15581 ** using offsetof(Parse,nVar) so the nVar field must be the first field
@@ -15583,11 +15588,10 @@
15588 u8 explain; /* True if the EXPLAIN flag is found on the query */
15589 #ifndef SQLITE_OMIT_VIRTUALTABLE
15590 u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
15591 int nVtabLock; /* Number of virtual tables to lock */
15592 #endif
 
15593 int nHeight; /* Expression tree height of current sub-select */
15594 #ifndef SQLITE_OMIT_EXPLAIN
15595 int iSelectId; /* ID of current select for EXPLAIN output */
15596 int iNextSelectId; /* Next available select ID for EXPLAIN output */
15597 #endif
@@ -15595,12 +15599,10 @@
15599 Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
15600 const char *zTail; /* All SQL text past the last semicolon parsed */
15601 Table *pNewTable; /* A table being constructed by CREATE TABLE */
15602 Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
15603 const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
 
 
15604 #ifndef SQLITE_OMIT_VIRTUALTABLE
15605 Token sArg; /* Complete text of a module argument */
15606 Table **apVtabLock; /* Pointer to virtual tables needing locking */
15607 #endif
15608 Table *pZombieTab; /* List of Table objects to delete after code gen */
@@ -15607,10 +15609,18 @@
15609 TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
15610 With *pWith; /* Current WITH clause, or NULL */
15611 With *pWithToFree; /* Free this WITH object at the end of the parse */
15612 };
15613
15614 /*
15615 ** Sizes and pointers of various parts of the Parse object.
15616 */
15617 #define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/
15618 #define PARSE_RECURSE_SZ offsetof(Parse,nVar) /* Recursive part */
15619 #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
15620 #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
15621
15622 /*
15623 ** Return true if currently inside an sqlite3_declare_vtab() call.
15624 */
15625 #ifdef SQLITE_OMIT_VIRTUALTABLE
15626 #define IN_DECLARE_VTAB 0
@@ -16170,11 +16180,11 @@
16180 SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
16181 SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
16182 SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
16183 SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
16184 SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
16185 SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
16186 SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
16187 SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
16188 SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
16189 SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int);
16190 SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
@@ -16990,20 +17000,17 @@
17000 ** If x is a lower-case ASCII character, then its upper-case equivalent
17001 ** is (x - 0x20). Therefore toupper() can be implemented as:
17002 **
17003 ** (x & ~(map[x]&0x20))
17004 **
17005 ** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
17006 ** array. tolower() is used more often than toupper() by SQLite.
17007 **
17008 ** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
17009 ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
17010 ** non-ASCII UTF character. Hence the test for whether or not a character is
17011 ** part of an identifier is 0x46.
 
 
 
17012 */
17013 #ifdef SQLITE_ASCII
17014 SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
17015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
17016 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
@@ -17072,11 +17079,11 @@
17079 #ifndef SQLITE_SORTER_PMASZ
17080 # define SQLITE_SORTER_PMASZ 250
17081 #endif
17082
17083 /* Statement journals spill to disk when their size exceeds the following
17084 ** threshold (in bytes). 0 means that statement journals are created and
17085 ** written to disk immediately (the default behavior for SQLite versions
17086 ** before 3.12.0). -1 means always keep the entire statement journal in
17087 ** memory. (The statement journal is also always held entirely in memory
17088 ** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this
17089 ** setting.)
@@ -17160,11 +17167,11 @@
17167
17168 /*
17169 ** The value of the "pending" byte must be 0x40000000 (1 byte past the
17170 ** 1-gibabyte boundary) in a compatible database. SQLite never uses
17171 ** the database page that contains the pending byte. It never attempts
17172 ** to read or write that page. The pending byte page is set aside
17173 ** for use by the VFS layers as space for managing file locks.
17174 **
17175 ** During testing, it is often desirable to move the pending byte to
17176 ** a different position in the file. This allows code that has to
17177 ** deal with the pending byte to run on files that are much smaller
@@ -17720,13 +17727,10 @@
17727 typedef unsigned Bool;
17728
17729 /* Opaque type used by code in vdbesort.c */
17730 typedef struct VdbeSorter VdbeSorter;
17731
 
 
 
17732 /* Elements of the linked list at Vdbe.pAuxData */
17733 typedef struct AuxData AuxData;
17734
17735 /* Types of VDBE cursors */
17736 #define CURTYPE_BTREE 0
@@ -17797,10 +17801,16 @@
17801 /* 2*nField extra array elements allocated for aType[], beyond the one
17802 ** static element declared in the structure. nField total array slots for
17803 ** aType[] and nField+1 array slots for aOffset[] */
17804 };
17805
17806
17807 /*
17808 ** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
17809 */
17810 #define CACHE_STALE 0
17811
17812 /*
17813 ** When a sub-program is executed (OP_Program), a structure of this type
17814 ** is allocated to store the current value of the program counter, as
17815 ** well as the current memory cell array and various other frame specific
17816 ** values stored in the Vdbe struct. When the sub-program is finished,
@@ -17841,15 +17851,10 @@
17851 int nDbChange; /* Value of db->nChange */
17852 };
17853
17854 #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
17855
 
 
 
 
 
17856 /*
17857 ** Internally, the vdbe manipulates nearly all SQL values as Mem
17858 ** structures. Each Mem struct may cache multiple representations (string,
17859 ** integer etc.) of the same value.
17860 */
@@ -17986,22 +17991,10 @@
17991 u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
17992 u8 argc; /* Number of arguments */
17993 sqlite3_value *argv[1]; /* Argument set */
17994 };
17995
 
 
 
 
 
 
 
 
 
 
 
 
17996 /* A bitfield type for use inside of structures. Always follow with :N where
17997 ** N is the number of bits.
17998 */
17999 typedef unsigned bft; /* Bit Field Type */
18000
@@ -18022,57 +18015,61 @@
18015 ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
18016 ** is really a pointer to an instance of this structure.
18017 */
18018 struct Vdbe {
18019 sqlite3 *db; /* The database connection that owns this statement */
18020 Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
18021 Parse *pParse; /* Parsing context used to create this Vdbe */
18022 ynVar nVar; /* Number of entries in aVar[] */
18023 ynVar nzVar; /* Number of entries in azVar[] */
18024 u32 magic; /* Magic number for sanity checking */
18025 int nMem; /* Number of memory locations currently allocated */
18026 int nCursor; /* Number of slots in apCsr[] */
18027 u32 cacheCtr; /* VdbeCursor row cache generation counter */
18028 int pc; /* The program counter */
18029 int rc; /* Value to return */
18030 int nChange; /* Number of db changes made since last reset */
18031 int iStatement; /* Statement number (or 0 if has not opened stmt) */
18032 i64 iCurrentTime; /* Value of julianday('now') for this statement */
18033 i64 nFkConstraint; /* Number of imm. FK constraints this VM */
18034 i64 nStmtDefCons; /* Number of def. constraints when stmt started */
18035 i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
18036
18037 /* When allocating a new Vdbe object, all of the fields below should be
18038 ** initialized to zero or NULL */
18039
18040 Op *aOp; /* Space to hold the virtual machine's program */
18041 Mem *aMem; /* The memory locations */
18042 Mem **apArg; /* Arguments to currently executing user function */
18043 Mem *aColName; /* Column names to return */
18044 Mem *pResultSet; /* Pointer to an array of results */
 
 
 
 
 
18045 char *zErrMsg; /* Error message written here */
 
18046 VdbeCursor **apCsr; /* One element of this array for each open cursor */
18047 Mem *aVar; /* Values for the OP_Variable opcode. */
18048 char **azVar; /* Name of variables */
18049 #ifndef SQLITE_OMIT_TRACE
18050 i64 startTime; /* Time when query started - used for profiling */
18051 #endif
18052 int nOp; /* Number of instructions in the program */
 
18053 #ifdef SQLITE_DEBUG
18054 int rcApp; /* errcode set by sqlite3_result_error_code() */
18055 #endif
18056 u16 nResColumn; /* Number of columns in one row of the result set */
18057 u8 errorAction; /* Recovery action to do in case of an error */
18058 u8 minWriteFileFormat; /* Minimum file format for writable database files */
18059 bft expired:1; /* True if the VM needs to be recompiled */
18060 bft doingRerun:1; /* True if rerunning after an auto-reprepare */
 
18061 bft explain:2; /* True if EXPLAIN present on SQL command */
18062 bft changeCntOn:1; /* True to update the change-counter */
18063 bft runOnlyOnce:1; /* Automatically expire on reset */
18064 bft usesStmtJournal:1; /* True if uses a statement journal */
18065 bft readOnly:1; /* True for statements that do not write */
18066 bft bIsReader:1; /* True for statements that read */
18067 bft isPrepareV2:1; /* True if prepared with prepare_v2() */
 
18068 yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
18069 yDbMask lockMask; /* Subset of btreeMask that requires a lock */
 
18070 u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
 
 
 
 
 
 
 
18071 char *zSql; /* Text of the SQL statement that generated this */
18072 void *pFree; /* Free this when deleting the vdbe */
18073 VdbeFrame *pFrame; /* Parent frame */
18074 VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
18075 int nFrame; /* Number of frames in pFrame list */
@@ -18087,14 +18084,15 @@
18084 };
18085
18086 /*
18087 ** The following are allowed values for Vdbe.magic
18088 */
18089 #define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */
18090 #define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */
18091 #define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */
18092 #define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
18093 #define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
18094
18095 /*
18096 ** Structure used to store the context required by the
18097 ** sqlite3_preupdate_*() API functions.
18098 */
@@ -28776,11 +28774,15 @@
28774 */
28775 static unsigned int strHash(const char *z){
28776 unsigned int h = 0;
28777 unsigned char c;
28778 while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
28779 /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
28780 ** 0x9e3779b1 is 2654435761 which is the closest prime number to
28781 ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
28782 h += sqlite3UpperToLower[c];
28783 h *= 0x9e3779b1;
28784 }
28785 return h;
28786 }
28787
28788
@@ -44019,11 +44021,11 @@
44021 ){
44022 PgHdr *pPgHdr;
44023 assert( pPage!=0 );
44024 pPgHdr = (PgHdr*)pPage->pExtra;
44025 assert( pPgHdr->pPage==0 );
44026 memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty));
44027 pPgHdr->pPage = pPage;
44028 pPgHdr->pData = pPage->pBuf;
44029 pPgHdr->pExtra = (void *)&pPgHdr[1];
44030 memset(pPgHdr->pExtra, 0, pCache->szExtra);
44031 pPgHdr->pCache = pCache;
@@ -58985,11 +58987,11 @@
58987 int bias, /* Bias search to the high end */
58988 int *pRes /* Write search results here */
58989 ){
58990 int rc; /* Status code */
58991 UnpackedRecord *pIdxKey; /* Unpacked index key */
58992 char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */
58993 char *pFree = 0;
58994
58995 if( pKey ){
58996 assert( nKey==(i64)(int)nKey );
58997 pIdxKey = sqlite3VdbeAllocUnpackedRecord(
@@ -64322,12 +64324,10 @@
64324 nSrc = pX->nData;
64325 assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */
64326 nHeader += putVarint32(&pCell[nHeader], nPayload);
64327 nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
64328 }else{
 
 
64329 assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
64330 nSrc = nPayload = (int)pX->nKey;
64331 pSrc = pX->pKey;
64332 nHeader += putVarint32(&pCell[nHeader], nPayload);
64333 }
@@ -68023,26 +68023,20 @@
68023 */
68024 static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
68025 int i = sqlite3FindDbName(pDb, zDb);
68026
68027 if( i==1 ){
68028 Parse sParse;
68029 int rc = 0;
68030 memset(&sParse, 0, sizeof(sParse));
68031 sParse.db = pDb;
68032 if( sqlite3OpenTempDatabase(&sParse) ){
68033 sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
68034 rc = SQLITE_ERROR;
68035 }
68036 sqlite3DbFree(pErrorDb, sParse.zErrMsg);
68037 sqlite3ParserReset(&sParse);
 
 
 
 
 
 
68038 if( rc ){
68039 return 0;
68040 }
68041 }
68042
@@ -69042,10 +69036,11 @@
69036 assert( (pMem->flags&MEM_RowSet)==0 );
69037 assert( EIGHT_BYTE_ALIGNMENT(pMem) );
69038
69039
69040 if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
69041 pMem->enc = 0;
69042 return SQLITE_NOMEM_BKPT;
69043 }
69044
69045 /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
69046 ** string representation of the value. Then, if the required encoding
@@ -69341,11 +69336,11 @@
69336 switch( aff ){
69337 case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
69338 if( (pMem->flags & MEM_Blob)==0 ){
69339 sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
69340 assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69341 if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
69342 }else{
69343 pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
69344 }
69345 break;
69346 }
@@ -70018,14 +70013,11 @@
70013 sqlite3_value *pVal = 0;
70014 int negInt = 1;
70015 const char *zNeg = "";
70016 int rc = SQLITE_OK;
70017
70018 assert( pExpr!=0 );
 
 
 
70019 while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
70020 if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
70021
70022 /* Compressed expressions only appear when parsing the DEFAULT clause
70023 ** on a table column definition, and hence only when pCtx==0. This
@@ -70145,11 +70137,11 @@
70137 Expr *pExpr, /* The expression to evaluate */
70138 u8 enc, /* Encoding to use */
70139 u8 affinity, /* Affinity to use */
70140 sqlite3_value **ppVal /* Write the new value here */
70141 ){
70142 return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
70143 }
70144
70145 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
70146 /*
70147 ** The implementation of the sqlite_record() function. This function accepts
@@ -70488,12 +70480,13 @@
70480 ** Create a new virtual database engine.
70481 */
70482 SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
70483 sqlite3 *db = pParse->db;
70484 Vdbe *p;
70485 p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) );
70486 if( p==0 ) return 0;
70487 memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp));
70488 p->db = db;
70489 if( db->pVdbe ){
70490 db->pVdbe->pPrev = p;
70491 }
70492 p->pNext = db->pVdbe;
@@ -70651,13 +70644,12 @@
70644 #endif
70645 #ifdef SQLITE_DEBUG
70646 if( p->db->flags & SQLITE_VdbeAddopTrace ){
70647 int jj, kk;
70648 Parse *pParse = p->pParse;
70649 for(jj=kk=0; jj<pParse->nColCache; jj++){
70650 struct yColCache *x = pParse->aColCache + jj;
 
70651 printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
70652 kk++;
70653 }
70654 if( kk ) printf("\n");
70655 sqlite3VdbePrintOp(0, i, &p->aOp[i]);
@@ -70841,11 +70833,10 @@
70833 assert( j<p->nLabel );
70834 assert( j>=0 );
70835 if( p->aLabel ){
70836 p->aLabel[j] = v->nOp;
70837 }
 
70838 }
70839
70840 /*
70841 ** Mark the VDBE as one that can only be run one time.
70842 */
@@ -71232,19 +71223,19 @@
71223 }
71224 SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
71225 sqlite3VdbeGetOp(p,addr)->p3 = val;
71226 }
71227 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
71228 assert( p->nOp>0 || p->db->mallocFailed );
71229 if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
71230 }
71231
71232 /*
71233 ** Change the P2 operand of instruction addr so that it points to
71234 ** the address of the next instruction to be coded.
71235 */
71236 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
 
71237 sqlite3VdbeChangeP2(p, addr, p->nOp);
71238 }
71239
71240
71241 /*
@@ -71363,11 +71354,11 @@
71354 /*
71355 ** If the last opcode is "op" and it is not a jump destination,
71356 ** then remove it. Return true if and only if an opcode was removed.
71357 */
71358 SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
71359 if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){
71360 return sqlite3VdbeChangeToNoop(p, p->nOp-1);
71361 }else{
71362 return 0;
71363 }
71364 }
@@ -71925,10 +71916,25 @@
71916 zCom
71917 );
71918 fflush(pOut);
71919 }
71920 #endif
71921
71922 /*
71923 ** Initialize an array of N Mem element.
71924 */
71925 static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
71926 while( (N--)>0 ){
71927 p->db = db;
71928 p->flags = flags;
71929 p->szMalloc = 0;
71930 #ifdef SQLITE_DEBUG
71931 p->pScopyFrom = 0;
71932 #endif
71933 p++;
71934 }
71935 }
71936
71937 /*
71938 ** Release an array of N Mem elements
71939 */
71940 static void releaseMemArray(Mem *p, int N){
@@ -72137,10 +72143,11 @@
72143 return SQLITE_ERROR;
72144 }
72145 pMem->flags = MEM_Str|MEM_Term;
72146 zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
72147 if( zP4!=pMem->z ){
72148 pMem->n = 0;
72149 sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
72150 }else{
72151 assert( pMem->z!=0 );
72152 pMem->n = sqlite3Strlen30(pMem->z);
72153 pMem->enc = SQLITE_UTF8;
@@ -72279,11 +72286,11 @@
72286 SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
72287 #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
72288 int i;
72289 #endif
72290 assert( p!=0 );
72291 assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
72292
72293 /* There should be at least one opcode.
72294 */
72295 assert( p->nOp>0 );
72296
@@ -72368,14 +72375,11 @@
72375 n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
72376 x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
72377 assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
72378 x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
72379 assert( x.nFree>=0 );
72380 assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
 
 
 
72381
72382 resolveP2Values(p, &nArg);
72383 p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
72384 if( pParse->explain && nMem<10 ){
72385 nMem = 10;
@@ -72400,34 +72404,34 @@
72404 p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
72405 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
72406 p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
72407 #endif
72408 if( x.nNeeded==0 ) break;
72409 x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
72410 x.nFree = x.nNeeded;
72411 }while( !db->mallocFailed );
72412
 
 
 
 
 
 
 
 
72413 p->nzVar = pParse->nzVar;
72414 p->azVar = pParse->azVar;
72415 pParse->nzVar = 0;
72416 pParse->azVar = 0;
 
 
 
 
 
 
 
72417 p->explain = pParse->explain;
72418 if( db->mallocFailed ){
72419 p->nVar = 0;
72420 p->nCursor = 0;
72421 p->nMem = 0;
72422 }else{
72423 p->nCursor = nCursor;
72424 p->nVar = (ynVar)nVar;
72425 initMemArray(p->aVar, nVar, db, MEM_Null);
72426 p->nMem = nMem;
72427 initMemArray(p->aMem, nMem, db, MEM_Undefined);
72428 memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
72429 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
72430 memset(p->anExec, 0, p->nOp*sizeof(i64));
72431 #endif
72432 }
72433 sqlite3VdbeRewind(p);
72434 }
72435
72436 /*
72437 ** Close a VDBE cursor and release all the resources that cursor
@@ -72575,17 +72579,13 @@
72579
72580 releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
72581 sqlite3DbFree(db, p->aColName);
72582 n = nResColumn*COLNAME_N;
72583 p->nResColumn = (u16)nResColumn;
72584 p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
72585 if( p->aColName==0 ) return;
72586 initMemArray(p->aColName, n, p->db, MEM_Null);
 
 
 
 
72587 }
72588
72589 /*
72590 ** Set the name of the idx'th column to be returned by the SQL statement.
72591 ** zName must be a pointer to a nul terminated string.
@@ -73343,11 +73343,11 @@
73343 fclose(out);
73344 }
73345 }
73346 #endif
73347 p->iCurrentTime = 0;
73348 p->magic = VDBE_MAGIC_RESET;
73349 return p->rc & db->errMask;
73350 }
73351
73352 /*
73353 ** Clean up and delete a VDBE after execution. Return an integer which is
@@ -73407,23 +73407,25 @@
73407 */
73408 SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
73409 SubProgram *pSub, *pNext;
73410 int i;
73411 assert( p->db==0 || p->db==db );
 
73412 releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
73413 for(pSub=p->pProgram; pSub; pSub=pNext){
73414 pNext = pSub->pNext;
73415 vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
73416 sqlite3DbFree(db, pSub);
73417 }
73418 if( p->magic!=VDBE_MAGIC_INIT ){
73419 releaseMemArray(p->aVar, p->nVar);
73420 for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
73421 sqlite3DbFree(db, p->azVar);
73422 sqlite3DbFree(db, p->pFree);
73423 }
73424 vdbeFreeOpArray(db, p->aOp, p->nOp);
73425 sqlite3DbFree(db, p->aColName);
73426 sqlite3DbFree(db, p->zSql);
 
73427 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
73428 for(i=0; i<p->nScan; i++){
73429 sqlite3DbFree(db, p->aScan[i].zName);
73430 }
73431 sqlite3DbFree(db, p->aScan);
@@ -76665,11 +76667,11 @@
76667 /*
76668 ** Return true if the prepared statement is in need of being reset.
76669 */
76670 SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
76671 Vdbe *v = (Vdbe*)pStmt;
76672 return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
76673 }
76674
76675 /*
76676 ** Return a pointer to the next prepared statement after pStmt associated
76677 ** with database connection pDb. If pStmt is NULL, return the first
@@ -78417,15 +78419,17 @@
78419 u16 nullFlag;
78420 pOut = out2Prerelease(p, pOp);
78421 cnt = pOp->p3-pOp->p2;
78422 assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
78423 pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
78424 pOut->n = 0;
78425 while( cnt>0 ){
78426 pOut++;
78427 memAboutToChange(p, pOut);
78428 sqlite3VdbeMemSetNull(pOut);
78429 pOut->flags = nullFlag;
78430 pOut->n = 0;
78431 cnt--;
78432 }
78433 break;
78434 }
78435
@@ -82338,13 +82342,10 @@
82342 if( pOp->opcode==OP_SorterInsert ){
82343 rc = sqlite3VdbeSorterWrite(pC, pIn2);
82344 }else{
82345 x.nKey = pIn2->n;
82346 x.pKey = pIn2->z;
 
 
 
82347 rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
82348 ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
82349 );
82350 assert( pC->deferredMoveto==0 );
82351 pC->cacheStatus = CACHE_STALE;
@@ -88783,11 +88784,10 @@
88784 const char *zDb;
88785 Expr *pRight;
88786
88787 /* if( pSrcList==0 ) break; */
88788 notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
 
88789 pRight = pExpr->pRight;
88790 if( pRight->op==TK_ID ){
88791 zDb = 0;
88792 zTable = pExpr->pLeft->u.zToken;
88793 zColumn = pRight->u.zToken;
@@ -88812,11 +88812,10 @@
88812 const char *zId; /* The function name. */
88813 FuncDef *pDef; /* Information about the function */
88814 u8 enc = ENC(pParse->db); /* The database encoding */
88815
88816 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
 
88817 zId = pExpr->u.zToken;
88818 nId = sqlite3Strlen30(zId);
88819 pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
88820 if( pDef==0 ){
88821 pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -88872,11 +88871,12 @@
88871 }
88872 if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
88873 /* Date/time functions that use 'now', and other functions like
88874 ** sqlite_version() that might change over time cannot be used
88875 ** in an index. */
88876 notValid(pParse, pNC, "non-deterministic functions",
88877 NC_IdxExpr|NC_PartIdx);
88878 }
88879 }
88880 if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
88881 sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
88882 pNC->nErr++;
@@ -90412,11 +90412,11 @@
90412 ** stored in u.zToken. Instead, the integer values is written
90413 ** into u.iValue and the EP_IntValue flag is set. No extra storage
90414 ** is allocated to hold the integer text and the dequote flag is ignored.
90415 */
90416 SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
90417 sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */
90418 int op, /* Expression opcode */
90419 const Token *pToken, /* Token argument. Might be NULL */
90420 int dequote /* True to dequote */
90421 ){
90422 Expr *pNew;
@@ -90630,40 +90630,40 @@
90630 ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
90631 ** as the previous instance of the same wildcard. Or if this is the first
90632 ** instance of the wildcard, the next sequential variable number is
90633 ** assigned.
90634 */
90635 SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
90636 sqlite3 *db = pParse->db;
90637 const char *z;
90638
90639 if( pExpr==0 ) return;
90640 assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
90641 z = pExpr->u.zToken;
90642 assert( z!=0 );
90643 assert( z[0]!=0 );
90644 assert( n==sqlite3Strlen30(z) );
90645 if( z[1]==0 ){
90646 /* Wildcard of the form "?". Assign the next variable number */
90647 assert( z[0]=='?' );
90648 pExpr->iColumn = (ynVar)(++pParse->nVar);
90649 }else{
90650 ynVar x;
 
90651 if( z[0]=='?' ){
90652 /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
90653 ** use it as the variable number */
90654 i64 i;
90655 int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
90656 x = (ynVar)i;
90657 testcase( i==0 );
90658 testcase( i==1 );
90659 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
90660 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
90661 if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
90662 sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
90663 db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
90664 return;
90665 }
90666 if( i>pParse->nVar ){
90667 pParse->nVar = (int)i;
90668 }
90669 }else{
@@ -90670,37 +90670,35 @@
90670 /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
90671 ** number as the prior appearance of the same name, or if the name
90672 ** has never appeared before, reuse the same variable number
90673 */
90674 ynVar i;
90675 for(i=x=0; i<pParse->nzVar; i++){
90676 if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
90677 x = (ynVar)i+1;
90678 break;
90679 }
90680 }
90681 if( x==0 ) x = (ynVar)(++pParse->nVar);
90682 }
90683 pExpr->iColumn = x;
90684 if( x>pParse->nzVar ){
90685 char **a;
90686 a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
90687 if( a==0 ){
90688 assert( db->mallocFailed ); /* Error reported through mallocFailed */
90689 return;
90690 }
90691 pParse->azVar = a;
90692 memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
90693 pParse->nzVar = x;
90694 }
90695 if( pParse->azVar[x-1]==0 ){
90696 pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
90697 }
90698 }
90699 if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
 
 
90700 sqlite3ErrorMsg(pParse, "too many SQL variables");
90701 }
90702 }
90703
90704 /*
@@ -92656,36 +92654,23 @@
92654 #endif
92655 }
92656 }
92657 }
92658
92659 /*
92660 ** Erase column-cache entry number i
92661 */
92662 static void cacheEntryClear(Parse *pParse, int i){
92663 if( pParse->aColCache[i].tempReg ){
 
 
 
 
 
 
 
 
 
 
 
 
 
92664 if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
92665 pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
92666 }
 
92667 }
 
92668 pParse->nColCache--;
92669 if( i<pParse->nColCache ){
92670 pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
92671 }
92672 }
92673
92674
92675 /*
92676 ** Record in the column cache that a particular column from a
@@ -92711,64 +92696,52 @@
92696 **
92697 ** Actually, the way the column cache is currently used, we are guaranteed
92698 ** that the object will never already be in cache. Verify this guarantee.
92699 */
92700 #ifndef NDEBUG
92701 for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
92702 assert( p->iTable!=iTab || p->iColumn!=iCol );
92703 }
92704 #endif
92705
92706 /* If the cache is already full, delete the least recently used entry */
92707 if( pParse->nColCache>=SQLITE_N_COLCACHE ){
92708 minLru = 0x7fffffff;
92709 idxLru = -1;
92710 for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
92711 if( p->lru<minLru ){
92712 idxLru = i;
92713 minLru = p->lru;
92714 }
92715 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92716 p = &pParse->aColCache[idxLru];
92717 }else{
92718 p = &pParse->aColCache[pParse->nColCache++];
92719 }
92720
92721 /* Add the new entry to the end of the cache */
92722 p->iLevel = pParse->iCacheLevel;
92723 p->iTable = iTab;
92724 p->iColumn = iCol;
92725 p->iReg = iReg;
92726 p->tempReg = 0;
92727 p->lru = pParse->iCacheCnt++;
92728 }
92729
92730 /*
92731 ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
92732 ** Purge the range of registers from the column cache.
92733 */
92734 SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
92735 int i = 0;
92736 while( i<pParse->nColCache ){
92737 struct yColCache *p = &pParse->aColCache[i];
92738 if( p->iReg >= iReg && p->iReg < iReg+nReg ){
92739 cacheEntryClear(pParse, i);
92740 }else{
92741 i++;
92742 }
92743 }
92744 }
92745
92746 /*
92747 ** Remember the current column cache context. Any new entries added
@@ -92788,22 +92761,23 @@
92761 ** Remove from the column cache any entries that were added since the
92762 ** the previous sqlite3ExprCachePush operation. In other words, restore
92763 ** the cache to the state it was in prior the most recent Push.
92764 */
92765 SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
92766 int i = 0;
 
92767 assert( pParse->iCacheLevel>=1 );
92768 pParse->iCacheLevel--;
92769 #ifdef SQLITE_DEBUG
92770 if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
92771 printf("POP to %d\n", pParse->iCacheLevel);
92772 }
92773 #endif
92774 while( i<pParse->nColCache ){
92775 if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
92776 cacheEntryClear(pParse, i);
92777 }else{
92778 i++;
92779 }
92780 }
92781 }
92782
92783 /*
@@ -92813,11 +92787,11 @@
92787 ** get them all.
92788 */
92789 static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
92790 int i;
92791 struct yColCache *p;
92792 for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
92793 if( p->iReg==iReg ){
92794 p->tempReg = 0;
92795 }
92796 }
92797 }
@@ -92891,12 +92865,12 @@
92865 ){
92866 Vdbe *v = pParse->pVdbe;
92867 int i;
92868 struct yColCache *p;
92869
92870 for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
92871 if( p->iTable==iTable && p->iColumn==iColumn ){
92872 p->lru = pParse->iCacheCnt++;
92873 sqlite3ExprCachePinRegister(pParse, p->iReg);
92874 return p->iReg;
92875 }
92876 }
@@ -92924,22 +92898,24 @@
92898 /*
92899 ** Clear all column cache entries.
92900 */
92901 SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
92902 int i;
 
92903
92904 #if SQLITE_DEBUG
92905 if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
92906 printf("CLEAR\n");
92907 }
92908 #endif
92909 for(i=0; i<pParse->nColCache; i++){
92910 if( pParse->aColCache[i].tempReg
92911 && pParse->nTempReg<ArraySize(pParse->aTempReg)
92912 ){
92913 pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
92914 }
92915 }
92916 pParse->nColCache = 0;
92917 }
92918
92919 /*
92920 ** Record the fact that an affinity change has occurred on iCount
92921 ** registers starting with iStart.
@@ -92967,11 +92943,11 @@
92943 ** and does not appear in a normal build.
92944 */
92945 static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
92946 int i;
92947 struct yColCache *p;
92948 for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
92949 int r = p->iReg;
92950 if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
92951 }
92952 return 0;
92953 }
@@ -94663,11 +94639,11 @@
94639 */
94640 SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
94641 if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
94642 int i;
94643 struct yColCache *p;
94644 for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
94645 if( p->iReg==iReg ){
94646 p->tempReg = 1;
94647 return;
94648 }
94649 }
@@ -98433,11 +98409,10 @@
98409 */
98410 v = sqlite3GetVdbe(pParse);
98411 assert( !pParse->isMultiWrite
98412 || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
98413 if( v ){
 
98414 sqlite3VdbeAddOp0(v, OP_Halt);
98415
98416 #if SQLITE_USER_AUTHENTICATION
98417 if( pParse->nTableLock>0 && db->init.busy==0 ){
98418 sqlite3UserAuthInit(db);
@@ -98460,18 +98435,20 @@
98435 ){
98436 int iDb, i;
98437 assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
98438 sqlite3VdbeJumpHere(v, 0);
98439 for(iDb=0; iDb<db->nDb; iDb++){
98440 Schema *pSchema;
98441 if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
98442 sqlite3VdbeUsesBtree(v, iDb);
98443 pSchema = db->aDb[iDb].pSchema;
98444 sqlite3VdbeAddOp4Int(v,
98445 OP_Transaction, /* Opcode */
98446 iDb, /* P1 */
98447 DbMaskTest(pParse->writeMask,iDb), /* P2 */
98448 pSchema->schema_cookie, /* P3 */
98449 pSchema->iGeneration /* P4 */
98450 );
98451 if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
98452 VdbeComment((v,
98453 "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
98454 }
@@ -98518,20 +98495,10 @@
98495 sqlite3VdbeMakeReady(v, pParse);
98496 pParse->rc = SQLITE_DONE;
98497 }else{
98498 pParse->rc = SQLITE_ERROR;
98499 }
 
 
 
 
 
 
 
 
 
 
98500 }
98501
98502 /*
98503 ** Run the parser and code generator recursively in order to generate
98504 ** code for the SQL statement given onto the end of the pParse context
@@ -98547,12 +98514,11 @@
98514 SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
98515 va_list ap;
98516 char *zSql;
98517 char *zErrMsg = 0;
98518 sqlite3 *db = pParse->db;
98519 char saveBuf[PARSE_TAIL_SZ];
 
98520
98521 if( pParse->nErr ) return;
98522 assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
98523 va_start(ap, zFormat);
98524 zSql = sqlite3VMPrintf(db, zFormat, ap);
@@ -98559,16 +98525,16 @@
98525 va_end(ap);
98526 if( zSql==0 ){
98527 return; /* A malloc must have failed */
98528 }
98529 pParse->nested++;
98530 memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
98531 memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
98532 sqlite3RunParser(pParse, zSql, &zErrMsg);
98533 sqlite3DbFree(db, zErrMsg);
98534 sqlite3DbFree(db, zSql);
98535 memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
98536 pParse->nested--;
98537 }
98538
98539 #if SQLITE_USER_AUTHENTICATION
98540 /*
@@ -102331,19 +102297,17 @@
102297 ** will occur at the end of the top-level VDBE and will be generated
102298 ** later, by sqlite3FinishCoding().
102299 */
102300 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
102301 Parse *pToplevel = sqlite3ParseToplevel(pParse);
 
102302
102303 assert( iDb>=0 && iDb<pParse->db->nDb );
102304 assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
102305 assert( iDb<SQLITE_MAX_ATTACHED+2 );
102306 assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
102307 if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
102308 DbMaskSet(pToplevel->cookieMask, iDb);
 
102309 if( !OMIT_TEMPDB && iDb==1 ){
102310 sqlite3OpenTempDatabase(pToplevel);
102311 }
102312 }
102313 }
@@ -109551,10 +109515,11 @@
109515 }
109516 if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest);
109517 sqlite3ReleaseTempReg(pParse, regRowid);
109518 sqlite3ReleaseTempReg(pParse, regData);
109519 if( emptyDestTest ){
109520 sqlite3AutoincrementEnd(pParse);
109521 sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
109522 sqlite3VdbeJumpHere(v, emptyDestTest);
109523 sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
109524 return 0;
109525 }else{
@@ -114047,22 +114012,18 @@
114012 int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
114013 Vdbe *pReprepare, /* VM being reprepared */
114014 sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
114015 const char **pzTail /* OUT: End of parsed string */
114016 ){
 
114017 char *zErrMsg = 0; /* Error message */
114018 int rc = SQLITE_OK; /* Result code */
114019 int i; /* Loop counter */
114020 Parse sParse; /* Parsing context */
114021
114022 memset(&sParse, 0, PARSE_HDR_SZ);
114023 memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
114024 sParse.pReprepare = pReprepare;
 
 
 
114025 assert( ppStmt && *ppStmt==0 );
114026 /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
114027 assert( sqlite3_mutex_held(db->mutex) );
114028
114029 /* Check to verify that it is possible to get a read lock on all
@@ -114102,12 +114063,11 @@
114063 }
114064 }
114065
114066 sqlite3VtabUnlockList(db);
114067
114068 sParse.db = db;
 
114069 if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
114070 char *zSqlCopy;
114071 int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
114072 testcase( nBytes==mxLen );
114073 testcase( nBytes==mxLen+1 );
@@ -114116,65 +114076,65 @@
114076 rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
114077 goto end_prepare;
114078 }
114079 zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
114080 if( zSqlCopy ){
114081 sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
114082 sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
114083 sqlite3DbFree(db, zSqlCopy);
114084 }else{
114085 sParse.zTail = &zSql[nBytes];
114086 }
114087 }else{
114088 sqlite3RunParser(&sParse, zSql, &zErrMsg);
114089 }
114090 assert( 0==sParse.nQueryLoop );
114091
114092 if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
114093 if( sParse.checkSchema ){
114094 schemaIsValid(&sParse);
114095 }
114096 if( db->mallocFailed ){
114097 sParse.rc = SQLITE_NOMEM_BKPT;
114098 }
114099 if( pzTail ){
114100 *pzTail = sParse.zTail;
114101 }
114102 rc = sParse.rc;
114103
114104 #ifndef SQLITE_OMIT_EXPLAIN
114105 if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
114106 static const char * const azColName[] = {
114107 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
114108 "selectid", "order", "from", "detail"
114109 };
114110 int iFirst, mx;
114111 if( sParse.explain==2 ){
114112 sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
114113 iFirst = 8;
114114 mx = 12;
114115 }else{
114116 sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
114117 iFirst = 0;
114118 mx = 8;
114119 }
114120 for(i=iFirst; i<mx; i++){
114121 sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
114122 azColName[i], SQLITE_STATIC);
114123 }
114124 }
114125 #endif
114126
114127 if( db->init.busy==0 ){
114128 Vdbe *pVdbe = sParse.pVdbe;
114129 sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
114130 }
114131 if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
114132 sqlite3VdbeFinalize(sParse.pVdbe);
114133 assert(!(*ppStmt));
114134 }else{
114135 *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
114136 }
114137
114138 if( zErrMsg ){
114139 sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
114140 sqlite3DbFree(db, zErrMsg);
@@ -114181,20 +114141,19 @@
114141 }else{
114142 sqlite3Error(db, rc);
114143 }
114144
114145 /* Delete any TriggerPrg structures allocated while parsing this statement. */
114146 while( sParse.pTriggerPrg ){
114147 TriggerPrg *pT = sParse.pTriggerPrg;
114148 sParse.pTriggerPrg = pT->pNext;
114149 sqlite3DbFree(db, pT);
114150 }
114151
114152 end_prepare:
114153
114154 sqlite3ParserReset(&sParse);
 
114155 rc = sqlite3ApiExit(db, rc);
114156 assert( (rc&db->errMask)==rc );
114157 return rc;
114158 }
114159 static int sqlite3LockAndPrepare(
@@ -115395,11 +115354,11 @@
115354 ** Allocate a KeyInfo object sufficient for an index of N key columns and
115355 ** X extra columns.
115356 */
115357 SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
115358 int nExtra = (N+X)*(sizeof(CollSeq*)+1);
115359 KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
115360 if( p ){
115361 p->aSortOrder = (u8*)&p->aColl[N+X];
115362 p->nField = (u16)N;
115363 p->nXField = (u16)X;
115364 p->enc = ENC(db);
@@ -124055,24 +124014,24 @@
124014 ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
124015 ** is only able to process joins with 64 or fewer tables.
124016 */
124017 struct WhereTerm {
124018 Expr *pExpr; /* Pointer to the subexpression that is this term */
124019 WhereClause *pWC; /* The clause this term is part of */
124020 LogEst truthProb; /* Probability of truth for this expression */
124021 u16 wtFlags; /* TERM_xxx bit flags. See below */
124022 u16 eOperator; /* A WO_xx value describing <op> */
124023 u8 nChild; /* Number of children that must disable us */
124024 u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
124025 int iParent; /* Disable pWC->a[iParent] when this term disabled */
124026 int leftCursor; /* Cursor number of X in "X <op> <expr>" */
124027 int iField; /* Field in (?,?,?) IN (SELECT...) vector */
124028 union {
124029 int leftColumn; /* Column number of X in "X <op> <expr>" */
124030 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
124031 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
124032 } u;
 
 
 
 
 
 
124033 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
124034 Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
124035 };
124036
124037 /*
@@ -124221,29 +124180,29 @@
124180 struct WhereInfo {
124181 Parse *pParse; /* Parsing and code generating context */
124182 SrcList *pTabList; /* List of tables in the join */
124183 ExprList *pOrderBy; /* The ORDER BY clause or NULL */
124184 ExprList *pDistinctSet; /* DISTINCT over all these values */
 
 
 
124185 LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
124186 int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
124187 int iContinue; /* Jump here to continue with next record */
124188 int iBreak; /* Jump here to break out of the loop */
124189 int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
124190 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
124191 u8 nLevel; /* Number of nested loop */
124192 i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
124193 u8 sorted; /* True if really sorted (not just grouped) */
124194 u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
124195 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
124196 u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
 
124197 u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
124198 int iTop; /* The very beginning of the WHERE loop */
124199 WhereLoop *pLoops; /* List of all WhereLoop objects */
124200 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
124201 LogEst nRowOut; /* Estimated number of output rows */
 
 
124202 WhereClause sWC; /* Decomposition of the WHERE clause */
124203 WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
124204 WhereLevel a[1]; /* Information about each nest loop in WHERE */
124205 };
124206
124207 /*
124208 ** Private interfaces - callable only by other where.c routines.
@@ -124703,11 +124662,10 @@
124662 **
124663 ** * the comparison will be performed with no affinity, or
124664 ** * the affinity change in zAff is guaranteed not to change the value.
124665 */
124666 static void updateRangeAffinityStr(
 
124667 Expr *pRight, /* RHS of comparison */
124668 int n, /* Number of vector elements in comparison */
124669 char *zAff /* Affinity string to modify */
124670 ){
124671 int i;
@@ -125789,15 +125747,15 @@
125747 assert( (bRev & ~1)==0 );
125748 pLevel->iLikeRepCntr <<=1;
125749 pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125750 }
125751 #endif
125752 if( pRangeStart==0 ){
125753 j = pIdx->aiColumn[nEq];
125754 if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
125755 bSeekPastNull = 1;
125756 }
125757 }
125758 }
125759 assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125760
125761 /* If we are doing a reverse order scan on an ascending index, or
@@ -125843,11 +125801,11 @@
125801 ){
125802 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125803 VdbeCoverage(v);
125804 }
125805 if( zStartAff ){
125806 updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
125807 }
125808 nConstraint += nBtm;
125809 testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125810 if( sqlite3ExprIsVector(pRight)==0 ){
125811 disableTerm(pLevel, pRangeStart);
@@ -125893,11 +125851,11 @@
125851 ){
125852 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125853 VdbeCoverage(v);
125854 }
125855 if( zEndAff ){
125856 updateRangeAffinityStr(pRight, nTop, zEndAff);
125857 codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125858 }else{
125859 assert( pParse->db->mallocFailed );
125860 }
125861 nConstraint += nTop;
@@ -126329,11 +126287,11 @@
126287 ** and we are coding the t1 loop and the t2 loop has not yet coded,
126288 ** then we cannot use the "t1.a=t2.b" constraint, but we can code
126289 ** the implied "t1.a=123" constraint.
126290 */
126291 for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
126292 Expr *pE, sEAlt;
126293 WhereTerm *pAlt;
126294 if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
126295 if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
126296 if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
126297 if( pTerm->leftCursor!=iCur ) continue;
@@ -126347,17 +126305,13 @@
126305 if( pAlt->wtFlags & (TERM_CODED) ) continue;
126306 testcase( pAlt->eOperator & WO_EQ );
126307 testcase( pAlt->eOperator & WO_IS );
126308 testcase( pAlt->eOperator & WO_IN );
126309 VdbeModuleComment((v, "begin transitive constraint"));
126310 sEAlt = *pAlt->pExpr;
126311 sEAlt.pLeft = pE->pLeft;
126312 sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
 
 
 
 
126313 }
126314
126315 /* For a LEFT OUTER JOIN, generate code that will record the fact that
126316 ** at least one row of the right table has matched the left table.
126317 */
@@ -126462,11 +126416,10 @@
126416 memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
126417 if( pOld!=pWC->aStatic ){
126418 sqlite3DbFree(db, pOld);
126419 }
126420 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
 
126421 }
126422 pTerm = &pWC->a[idx = pWC->nTerm++];
126423 if( p && ExprHasProperty(p, EP_Unlikely) ){
126424 pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
126425 }else{
@@ -126474,10 +126427,12 @@
126427 }
126428 pTerm->pExpr = sqlite3ExprSkipCollate(p);
126429 pTerm->wtFlags = wtFlags;
126430 pTerm->pWC = pWC;
126431 pTerm->iParent = -1;
126432 memset(&pTerm->eOperator, 0,
126433 sizeof(WhereTerm) - offsetof(WhereTerm,eOperator));
126434 return idx;
126435 }
126436
126437 /*
126438 ** Return TRUE if the given operator is one of the operators that is
@@ -130048,11 +130003,11 @@
130003 ** CREATE INDEX ... ON (a, b, c, d, e)
130004 **
130005 ** then this function would be invoked with nEq=1. The value returned in
130006 ** this case is 3.
130007 */
130008 static int whereRangeVectorLen(
130009 Parse *pParse, /* Parsing context */
130010 int iCur, /* Cursor open on pIdx */
130011 Index *pIdx, /* The index to be used for a inequality constraint */
130012 int nEq, /* Number of prior equality constraints on same index */
130013 WhereTerm *pTerm /* The vector inequality constraint */
@@ -131494,11 +131449,11 @@
131449 if( rev ) *pRevMask |= MASKBIT(iLoop);
131450 revSet = 1;
131451 }
131452 }
131453 if( isMatch ){
131454 if( iColumn==XN_ROWID ){
131455 testcase( distinctColumns==0 );
131456 distinctColumns = 1;
131457 }
131458 obSat |= MASKBIT(i);
131459 }else{
@@ -131948,15 +131903,20 @@
131903 }
131904 }else{
131905 pWInfo->nOBSat = pFrom->isOrdered;
131906 pWInfo->revMask = pFrom->revLoop;
131907 if( pWInfo->nOBSat<=0 ){
131908 u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
131909 pWInfo->nOBSat = 0;
131910 if( nLoop>0 && (wsFlags & WHERE_ONEROW)==0
131911 && (wsFlags & (WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
131912 ){
131913 Bitmask m = 0;
131914 int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
131915 WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
131916 testcase( wsFlags & WHERE_IPK );
131917 testcase( wsFlags & WHERE_COLUMN_IN );
131918 if( rc==pWInfo->pOrderBy->nExpr ){
131919 pWInfo->bOrderedInnerLoop = 1;
131920 pWInfo->revMask = m;
131921 }
131922 }
@@ -132232,26 +132192,29 @@
132192 ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
132193 ** field (type Bitmask) it must be aligned on an 8-byte boundary on
132194 ** some architectures. Hence the ROUND8() below.
132195 */
132196 nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
132197 pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
132198 if( db->mallocFailed ){
132199 sqlite3DbFree(db, pWInfo);
132200 pWInfo = 0;
132201 goto whereBeginError;
132202 }
 
 
132203 pWInfo->pParse = pParse;
132204 pWInfo->pTabList = pTabList;
132205 pWInfo->pOrderBy = pOrderBy;
132206 pWInfo->pDistinctSet = pDistinctSet;
132207 pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
132208 pWInfo->nLevel = nTabList;
132209 pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
132210 pWInfo->wctrlFlags = wctrlFlags;
132211 pWInfo->iLimit = iAuxArg;
132212 pWInfo->savedNQueryLoop = pParse->nQueryLoop;
132213 memset(&pWInfo->nOBSat, 0,
132214 offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
132215 memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
132216 assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
132217 pMaskSet = &pWInfo->sMaskSet;
132218 sWLB.pWInfo = pWInfo;
132219 sWLB.pWC = &pWInfo->sWC;
132220 sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
@@ -135704,12 +135667,13 @@
135667 yymsp[0].minor.yy190 = yylhsminor.yy190;
135668 break;
135669 case 159: /* expr ::= VARIABLE */
135670 {
135671 if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
135672 u32 n = yymsp[0].minor.yy0.n;
135673 spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0);
135674 sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n);
135675 }else{
135676 /* When doing a nested parse, one can include terms in an expression
135677 ** that look like this: #1 #2 ... These terms refer to registers
135678 ** in the virtual machine. #N is the N-th register. */
135679 Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
@@ -136478,11 +136442,11 @@
136442 }
136443 #endif
136444 yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
136445 yymajor = YYNOCODE;
136446 }else{
136447 while( yypParser->yytos >= yypParser->yystack
136448 && yymx != YYERRORSYMBOL
136449 && (yyact = yy_find_reduce_action(
136450 yypParser->yytos->stateno,
136451 YYERRORSYMBOL)) >= YY_MIN_REDUCE
136452 ){
@@ -164335,14 +164299,16 @@
164299 char *zSql;
164300 sqlite3_stmt *p;
164301 int rc;
164302 i64 nRow = 0;
164303
164304 rc = sqlite3_table_column_metadata(
164305 db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
164306 );
164307 if( rc!=SQLITE_OK ){
164308 pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164309 return rc==SQLITE_ERROR ? SQLITE_OK : rc;
164310 }
164311 zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164312 if( zSql==0 ){
164313 rc = SQLITE_NOMEM;
164314 }else{
@@ -181169,11 +181135,11 @@
181135 }
181136 #endif
181137 fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion);
181138 fts5yymajor = fts5YYNOCODE;
181139 }else{
181140 while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack
181141 && fts5yymx != fts5YYERRORSYMBOL
181142 && (fts5yyact = fts5yy_find_reduce_action(
181143 fts5yypParser->fts5yytos->stateno,
181144 fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE
181145 ){
@@ -181535,10 +181501,13 @@
181501 int nToken, /* Size of token in bytes */
181502 int iStartOff, /* Start offset of token */
181503 int iEndOff /* End offset of token */
181504 ){
181505 int rc = SQLITE_OK;
181506
181507 UNUSED_PARAM2(pToken, nToken);
181508 UNUSED_PARAM(iEndOff);
181509
181510 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181511 Fts5SFinder *p = (Fts5SFinder*)pContext;
181512 if( p->iPos>0 ){
181513 int i;
@@ -181691,11 +181660,10 @@
181660 for(jj=0; jj<(sFinder.nFirst-1); jj++){
181661 if( sFinder.aFirst[jj+1]>io ) break;
181662 }
181663
181664 if( sFinder.aFirst[jj]<io ){
 
181665 memset(aSeen, 0, nPhrase);
181666 rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181667 sFinder.aFirst[jj], nToken, &nScore, 0
181668 );
181669
@@ -195626,11 +195594,11 @@
195594 int nArg, /* Number of args */
195595 sqlite3_value **apUnused /* Function arguments */
195596 ){
195597 assert( nArg==0 );
195598 UNUSED_PARAM2(nArg, apUnused);
195599 sqlite3_result_text(pCtx, "fts5: 2016-10-10 14:48:36 6624c4964b63e259d5ee006eaa7ec79ddadbd6a6", -1, SQLITE_TRANSIENT);
195600 }
195601
195602 static int fts5Init(sqlite3 *db){
195603 static const sqlite3_module fts5Mod = {
195604 /* iVersion */ 2,
195605
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,11 +121,11 @@
121121
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122122
** [sqlite_version()] and [sqlite_source_id()].
123123
*/
124124
#define SQLITE_VERSION "3.15.0"
125125
#define SQLITE_VERSION_NUMBER 3015000
126
-#define SQLITE_SOURCE_ID "2016-09-28 16:05:53 40c0fb0af678797c39a99853f9f4102464c16f4b"
126
+#define SQLITE_SOURCE_ID "2016-10-12 15:15:30 61f0526978af667781c57bcc87510e4524efd0d8"
127127
128128
/*
129129
** CAPI3REF: Run-Time Library Version Numbers
130130
** KEYWORDS: sqlite3_version, sqlite3_sourceid
131131
**
132132
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,11 +121,11 @@
121 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122 ** [sqlite_version()] and [sqlite_source_id()].
123 */
124 #define SQLITE_VERSION "3.15.0"
125 #define SQLITE_VERSION_NUMBER 3015000
126 #define SQLITE_SOURCE_ID "2016-09-28 16:05:53 40c0fb0af678797c39a99853f9f4102464c16f4b"
127
128 /*
129 ** CAPI3REF: Run-Time Library Version Numbers
130 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
131 **
132
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,11 +121,11 @@
121 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122 ** [sqlite_version()] and [sqlite_source_id()].
123 */
124 #define SQLITE_VERSION "3.15.0"
125 #define SQLITE_VERSION_NUMBER 3015000
126 #define SQLITE_SOURCE_ID "2016-10-12 15:15:30 61f0526978af667781c57bcc87510e4524efd0d8"
127
128 /*
129 ** CAPI3REF: Run-Time Library Version Numbers
130 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
131 **
132
+14 -16
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
2525
** SQL code to implement the tables needed by the stash.
2626
*/
2727
static const char zStashInit[] =
2828
@ CREATE TABLE IF NOT EXISTS localdb.stash(
2929
@ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30
-@ vid INTEGER, -- The baseline check-out for this stash
30
+@ vid INTEGER, -- The baseline checkout for this stash
3131
@ comment TEXT, -- Comment for this stash. Or NULL
3232
@ ctime TIMESTAMP -- When the stash was created
3333
@ );
3434
@ CREATE TABLE IF NOT EXISTS localdb.stashfile(
3535
@ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196196
}
197197
return stashid;
198198
}
199199
200200
/*
201
-** Apply a stash to the current check-out.
201
+** Apply a stash to the current checkout.
202202
*/
203203
static void stash_apply(int stashid, int nConflict){
204204
int vid;
205205
Stmt q;
206206
db_prepare(&q,
@@ -420,60 +420,58 @@
420420
** Save the current changes in the working tree as a new stash.
421421
** Then revert the changes back to the last check-in. If FILES
422422
** are listed, then only stash and revert the named files. The
423423
** "save" verb can be omitted if and only if there are no other
424424
** arguments. The "snapshot" verb works the same as "save" but
425
-** omits the revert, keeping the check-out unchanged.
425
+** omits the revert, keeping the checkout unchanged.
426426
**
427
-** fossil stash list ?-v|--verbose?
428
-** fossil stash ls ?-v|--verbose?
427
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
429428
**
430429
** List all changes sets currently stashed. Show information about
431430
** individual files in each changeset if -v or --verbose is used.
432431
**
433432
** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
434433
**
435
-** Show the content of a stash
434
+** Show the contents of a stash.
436435
**
437436
** fossil stash pop
438437
** fossil stash apply ?STASHID?
439438
**
440439
** Apply STASHID or the most recently create stash to the current
441
-** working check-out. The "pop" command deletes that changeset from
440
+** working checkout. The "pop" command deletes that changeset from
442441
** the stash after applying it but the "apply" command retains the
443442
** changeset.
444443
**
445444
** fossil stash goto ?STASHID?
446445
**
447446
** Update to the baseline checkout for STASHID then apply the
448447
** changes of STASHID. Keep STASHID so that it can be reused
449448
** This command is undoable.
450449
**
451
-** fossil stash drop ?STASHID? ?-a|--all?
452
-** fossil stash rm ?STASHID? ?-a|--all?
450
+** fossil stash drop|rm ?STASHID? ?-a|--all?
453451
**
454452
** Forget everything about STASHID. Forget the whole stash if the
455453
** -a|--all flag is used. Individual drops are undoable but -a|--all
456454
** is not.
457455
**
458
-** fossil stash diff ?STASHID?
459
-** fossil stash gdiff ?STASHID?
456
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
457
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
460458
**
461459
** Show diffs of the current working directory and what that
462460
** directory would be if STASHID were applied.
463461
**
464462
** SUMMARY:
465463
** fossil stash
466464
** fossil stash save ?-m|--comment COMMENT? ?FILES...?
467465
** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
468
-** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
466
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
469467
** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
470468
** fossil stash pop
471
-** fossil stash apply ?STASHID?
472
-** fossil stash goto ?STASHID?
473
-** fossil stash rm|drop ?STASHID? ?-a|--all?
474
-** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
469
+** fossil stash apply|goto ?STASHID?
470
+** fossil stash drop|rm ?STASHID? ?-a|--all?
471
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
472
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
475473
*/
476474
void stash_cmd(void){
477475
const char *zCmd;
478476
int nCmd;
479477
int stashid = 0;
480478
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
25 ** SQL code to implement the tables needed by the stash.
26 */
27 static const char zStashInit[] =
28 @ CREATE TABLE IF NOT EXISTS localdb.stash(
29 @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30 @ vid INTEGER, -- The baseline check-out for this stash
31 @ comment TEXT, -- Comment for this stash. Or NULL
32 @ ctime TIMESTAMP -- When the stash was created
33 @ );
34 @ CREATE TABLE IF NOT EXISTS localdb.stashfile(
35 @ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196 }
197 return stashid;
198 }
199
200 /*
201 ** Apply a stash to the current check-out.
202 */
203 static void stash_apply(int stashid, int nConflict){
204 int vid;
205 Stmt q;
206 db_prepare(&q,
@@ -420,60 +420,58 @@
420 ** Save the current changes in the working tree as a new stash.
421 ** Then revert the changes back to the last check-in. If FILES
422 ** are listed, then only stash and revert the named files. The
423 ** "save" verb can be omitted if and only if there are no other
424 ** arguments. The "snapshot" verb works the same as "save" but
425 ** omits the revert, keeping the check-out unchanged.
426 **
427 ** fossil stash list ?-v|--verbose?
428 ** fossil stash ls ?-v|--verbose?
429 **
430 ** List all changes sets currently stashed. Show information about
431 ** individual files in each changeset if -v or --verbose is used.
432 **
433 ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
434 **
435 ** Show the content of a stash
436 **
437 ** fossil stash pop
438 ** fossil stash apply ?STASHID?
439 **
440 ** Apply STASHID or the most recently create stash to the current
441 ** working check-out. The "pop" command deletes that changeset from
442 ** the stash after applying it but the "apply" command retains the
443 ** changeset.
444 **
445 ** fossil stash goto ?STASHID?
446 **
447 ** Update to the baseline checkout for STASHID then apply the
448 ** changes of STASHID. Keep STASHID so that it can be reused
449 ** This command is undoable.
450 **
451 ** fossil stash drop ?STASHID? ?-a|--all?
452 ** fossil stash rm ?STASHID? ?-a|--all?
453 **
454 ** Forget everything about STASHID. Forget the whole stash if the
455 ** -a|--all flag is used. Individual drops are undoable but -a|--all
456 ** is not.
457 **
458 ** fossil stash diff ?STASHID?
459 ** fossil stash gdiff ?STASHID?
460 **
461 ** Show diffs of the current working directory and what that
462 ** directory would be if STASHID were applied.
463 **
464 ** SUMMARY:
465 ** fossil stash
466 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
467 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
468 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
469 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
470 ** fossil stash pop
471 ** fossil stash apply ?STASHID?
472 ** fossil stash goto ?STASHID?
473 ** fossil stash rm|drop ?STASHID? ?-a|--all?
474 ** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
475 */
476 void stash_cmd(void){
477 const char *zCmd;
478 int nCmd;
479 int stashid = 0;
480
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
25 ** SQL code to implement the tables needed by the stash.
26 */
27 static const char zStashInit[] =
28 @ CREATE TABLE IF NOT EXISTS localdb.stash(
29 @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30 @ vid INTEGER, -- The baseline checkout for this stash
31 @ comment TEXT, -- Comment for this stash. Or NULL
32 @ ctime TIMESTAMP -- When the stash was created
33 @ );
34 @ CREATE TABLE IF NOT EXISTS localdb.stashfile(
35 @ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196 }
197 return stashid;
198 }
199
200 /*
201 ** Apply a stash to the current checkout.
202 */
203 static void stash_apply(int stashid, int nConflict){
204 int vid;
205 Stmt q;
206 db_prepare(&q,
@@ -420,60 +420,58 @@
420 ** Save the current changes in the working tree as a new stash.
421 ** Then revert the changes back to the last check-in. If FILES
422 ** are listed, then only stash and revert the named files. The
423 ** "save" verb can be omitted if and only if there are no other
424 ** arguments. The "snapshot" verb works the same as "save" but
425 ** omits the revert, keeping the checkout unchanged.
426 **
427 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
 
428 **
429 ** List all changes sets currently stashed. Show information about
430 ** individual files in each changeset if -v or --verbose is used.
431 **
432 ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
433 **
434 ** Show the contents of a stash.
435 **
436 ** fossil stash pop
437 ** fossil stash apply ?STASHID?
438 **
439 ** Apply STASHID or the most recently create stash to the current
440 ** working checkout. The "pop" command deletes that changeset from
441 ** the stash after applying it but the "apply" command retains the
442 ** changeset.
443 **
444 ** fossil stash goto ?STASHID?
445 **
446 ** Update to the baseline checkout for STASHID then apply the
447 ** changes of STASHID. Keep STASHID so that it can be reused
448 ** This command is undoable.
449 **
450 ** fossil stash drop|rm ?STASHID? ?-a|--all?
 
451 **
452 ** Forget everything about STASHID. Forget the whole stash if the
453 ** -a|--all flag is used. Individual drops are undoable but -a|--all
454 ** is not.
455 **
456 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
457 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
458 **
459 ** Show diffs of the current working directory and what that
460 ** directory would be if STASHID were applied.
461 **
462 ** SUMMARY:
463 ** fossil stash
464 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
465 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
466 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
467 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
468 ** fossil stash pop
469 ** fossil stash apply|goto ?STASHID?
470 ** fossil stash drop|rm ?STASHID? ?-a|--all?
471 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
472 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
473 */
474 void stash_cmd(void){
475 const char *zCmd;
476 int nCmd;
477 int stashid = 0;
478
+1
--- src/tag.c
+++ src/tag.c
@@ -359,10 +359,11 @@
359359
}else{
360360
nrid = content_put(&ctrl);
361361
manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
362362
}
363363
assert( blob_is_reset(&ctrl) );
364
+ manifest_to_disk(rid);
364365
}
365366
366367
/*
367368
** COMMAND: tag
368369
**
369370
--- src/tag.c
+++ src/tag.c
@@ -359,10 +359,11 @@
359 }else{
360 nrid = content_put(&ctrl);
361 manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
362 }
363 assert( blob_is_reset(&ctrl) );
 
364 }
365
366 /*
367 ** COMMAND: tag
368 **
369
--- src/tag.c
+++ src/tag.c
@@ -359,10 +359,11 @@
359 }else{
360 nrid = content_put(&ctrl);
361 manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
362 }
363 assert( blob_is_reset(&ctrl) );
364 manifest_to_disk(rid);
365 }
366
367 /*
368 ** COMMAND: tag
369 **
370
+52 -16
--- src/tar.c
+++ src/tar.c
@@ -475,11 +475,11 @@
475475
Blob mfile, hash, file;
476476
Manifest *pManifest;
477477
ManifestFile *pFile;
478478
Blob filename;
479479
int nPrefix;
480
- char *zName;
480
+ char *zName = 0;
481481
unsigned int mTime;
482482
483483
content_get(rid, &mfile);
484484
if( blob_size(&mfile)==0 ){
485485
blob_zero(pTar);
@@ -493,28 +493,64 @@
493493
}
494494
nPrefix = blob_size(&filename);
495495
496496
pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
497497
if( pManifest ){
498
+ int flg, eflg = 0;
498499
mTime = (pManifest->rDate - 2440587.5)*86400.0;
499500
tar_begin(mTime);
500
- if( (pInclude==0 || glob_match(pInclude, "manifest"))
501
- && !glob_match(pExclude, "manifest")
502
- && db_get_boolean("manifest", 0)
503
- ){
504
- blob_append(&filename, "manifest", -1);
505
- zName = blob_str(&filename);
506
- sha1sum_blob(&mfile, &hash);
507
- sterilize_manifest(&mfile);
508
- tar_add_file(zName, &mfile, 0, mTime);
501
+ flg = db_get_manifest_setting();
502
+ if( flg ){
503
+ /* eflg is the effective flags, taking include/exclude into account */
504
+ if( (pInclude==0 || glob_match(pInclude, "manifest"))
505
+ && !glob_match(pExclude, "manifest")
506
+ && (flg & MFESTFLG_RAW) ){
507
+ eflg |= MFESTFLG_RAW;
508
+ }
509
+ if( (pInclude==0 || glob_match(pInclude, "manifest.uuid"))
510
+ && !glob_match(pExclude, "manifest.uuid")
511
+ && (flg & MFESTFLG_UUID) ){
512
+ eflg |= MFESTFLG_UUID;
513
+ }
514
+ if( (pInclude==0 || glob_match(pInclude, "manifest.tags"))
515
+ && !glob_match(pExclude, "manifest.tags")
516
+ && (flg & MFESTFLG_TAGS) ){
517
+ eflg |= MFESTFLG_TAGS;
518
+ }
519
+
520
+ if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
521
+ if( eflg & MFESTFLG_RAW ){
522
+ blob_append(&filename, "manifest", -1);
523
+ zName = blob_str(&filename);
524
+ }
525
+ if( eflg & MFESTFLG_UUID ){
526
+ sha1sum_blob(&mfile, &hash);
527
+ }
528
+ if( eflg & MFESTFLG_RAW ) {
529
+ sterilize_manifest(&mfile);
530
+ tar_add_file(zName, &mfile, 0, mTime);
531
+ }
532
+ }
509533
blob_reset(&mfile);
510
- blob_append(&hash, "\n", 1);
511
- blob_resize(&filename, nPrefix);
512
- blob_append(&filename, "manifest.uuid", -1);
513
- zName = blob_str(&filename);
514
- tar_add_file(zName, &hash, 0, mTime);
515
- blob_reset(&hash);
534
+ if( eflg & MFESTFLG_UUID ){
535
+ blob_append(&hash, "\n", 1);
536
+ blob_resize(&filename, nPrefix);
537
+ blob_append(&filename, "manifest.uuid", -1);
538
+ zName = blob_str(&filename);
539
+ tar_add_file(zName, &hash, 0, mTime);
540
+ blob_reset(&hash);
541
+ }
542
+ if( eflg & MFESTFLG_TAGS ){
543
+ Blob tagslist;
544
+ blob_zero(&tagslist);
545
+ get_checkin_taglist(rid, &tagslist);
546
+ blob_resize(&filename, nPrefix);
547
+ blob_append(&filename, "manifest.tags", -1);
548
+ zName = blob_str(&filename);
549
+ tar_add_file(zName, &tagslist, 0, mTime);
550
+ blob_reset(&tagslist);
551
+ }
516552
}
517553
manifest_file_rewind(pManifest);
518554
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
519555
int fid;
520556
if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
521557
--- src/tar.c
+++ src/tar.c
@@ -475,11 +475,11 @@
475 Blob mfile, hash, file;
476 Manifest *pManifest;
477 ManifestFile *pFile;
478 Blob filename;
479 int nPrefix;
480 char *zName;
481 unsigned int mTime;
482
483 content_get(rid, &mfile);
484 if( blob_size(&mfile)==0 ){
485 blob_zero(pTar);
@@ -493,28 +493,64 @@
493 }
494 nPrefix = blob_size(&filename);
495
496 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
497 if( pManifest ){
 
498 mTime = (pManifest->rDate - 2440587.5)*86400.0;
499 tar_begin(mTime);
500 if( (pInclude==0 || glob_match(pInclude, "manifest"))
501 && !glob_match(pExclude, "manifest")
502 && db_get_boolean("manifest", 0)
503 ){
504 blob_append(&filename, "manifest", -1);
505 zName = blob_str(&filename);
506 sha1sum_blob(&mfile, &hash);
507 sterilize_manifest(&mfile);
508 tar_add_file(zName, &mfile, 0, mTime);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509 blob_reset(&mfile);
510 blob_append(&hash, "\n", 1);
511 blob_resize(&filename, nPrefix);
512 blob_append(&filename, "manifest.uuid", -1);
513 zName = blob_str(&filename);
514 tar_add_file(zName, &hash, 0, mTime);
515 blob_reset(&hash);
 
 
 
 
 
 
 
 
 
 
 
 
516 }
517 manifest_file_rewind(pManifest);
518 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
519 int fid;
520 if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
521
--- src/tar.c
+++ src/tar.c
@@ -475,11 +475,11 @@
475 Blob mfile, hash, file;
476 Manifest *pManifest;
477 ManifestFile *pFile;
478 Blob filename;
479 int nPrefix;
480 char *zName = 0;
481 unsigned int mTime;
482
483 content_get(rid, &mfile);
484 if( blob_size(&mfile)==0 ){
485 blob_zero(pTar);
@@ -493,28 +493,64 @@
493 }
494 nPrefix = blob_size(&filename);
495
496 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
497 if( pManifest ){
498 int flg, eflg = 0;
499 mTime = (pManifest->rDate - 2440587.5)*86400.0;
500 tar_begin(mTime);
501 flg = db_get_manifest_setting();
502 if( flg ){
503 /* eflg is the effective flags, taking include/exclude into account */
504 if( (pInclude==0 || glob_match(pInclude, "manifest"))
505 && !glob_match(pExclude, "manifest")
506 && (flg & MFESTFLG_RAW) ){
507 eflg |= MFESTFLG_RAW;
508 }
509 if( (pInclude==0 || glob_match(pInclude, "manifest.uuid"))
510 && !glob_match(pExclude, "manifest.uuid")
511 && (flg & MFESTFLG_UUID) ){
512 eflg |= MFESTFLG_UUID;
513 }
514 if( (pInclude==0 || glob_match(pInclude, "manifest.tags"))
515 && !glob_match(pExclude, "manifest.tags")
516 && (flg & MFESTFLG_TAGS) ){
517 eflg |= MFESTFLG_TAGS;
518 }
519
520 if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
521 if( eflg & MFESTFLG_RAW ){
522 blob_append(&filename, "manifest", -1);
523 zName = blob_str(&filename);
524 }
525 if( eflg & MFESTFLG_UUID ){
526 sha1sum_blob(&mfile, &hash);
527 }
528 if( eflg & MFESTFLG_RAW ) {
529 sterilize_manifest(&mfile);
530 tar_add_file(zName, &mfile, 0, mTime);
531 }
532 }
533 blob_reset(&mfile);
534 if( eflg & MFESTFLG_UUID ){
535 blob_append(&hash, "\n", 1);
536 blob_resize(&filename, nPrefix);
537 blob_append(&filename, "manifest.uuid", -1);
538 zName = blob_str(&filename);
539 tar_add_file(zName, &hash, 0, mTime);
540 blob_reset(&hash);
541 }
542 if( eflg & MFESTFLG_TAGS ){
543 Blob tagslist;
544 blob_zero(&tagslist);
545 get_checkin_taglist(rid, &tagslist);
546 blob_resize(&filename, nPrefix);
547 blob_append(&filename, "manifest.tags", -1);
548 zName = blob_str(&filename);
549 tar_add_file(zName, &tagslist, 0, mTime);
550 blob_reset(&tagslist);
551 }
552 }
553 manifest_file_rewind(pManifest);
554 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
555 int fid;
556 if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
557
+34 -16
--- src/timeline.c
+++ src/timeline.c
@@ -26,10 +26,19 @@
2626
/*
2727
** The value of one second in julianday notation
2828
*/
2929
#define ONE_SECOND (1.0/86400.0)
3030
31
+/*
32
+** timeline mode options
33
+*/
34
+#define TIMELINE_MODE_NONE 0
35
+#define TIMELINE_MODE_BEFORE 1
36
+#define TIMELINE_MODE_AFTER 2
37
+#define TIMELINE_MODE_CHILDREN 3
38
+#define TIMELINE_MODE_PARENTS 4
39
+
3140
/*
3241
** Add an appropriate tag to the output if "rid" is unpublished (private)
3342
*/
3443
#define UNPUB_TAG "<em>(unpublished)</em>"
3544
void tag_private_status(int rid){
@@ -2029,10 +2038,17 @@
20292038
&& z[4]=='-'
20302039
&& z[7]=='-'
20312040
&& fossil_isdigit(z[0])
20322041
&& fossil_isdigit(z[5]);
20332042
}
2043
+
2044
+/*
2045
+** Return true if the input string can be converted to a julianday.
2046
+*/
2047
+static int fossil_is_julianday(const char *zDate){
2048
+ return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd WHERE jd IS NOT NULL)", zDate);
2049
+}
20342050
20352051
/*
20362052
** COMMAND: timeline
20372053
**
20382054
** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -2087,11 +2103,11 @@
20872103
char *zOrigin;
20882104
char *zDate;
20892105
Blob sql;
20902106
int objid = 0;
20912107
Blob uuid;
2092
- int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
2108
+ int mode = TIMELINE_MODE_NONE;
20932109
int verboseFlag = 0 ;
20942110
int iOffset;
20952111
const char *zFilePattern = 0;
20962112
Blob treeName;
20972113
@@ -2128,21 +2144,21 @@
21282144
verify_all_options();
21292145
21302146
if( g.argc>=4 ){
21312147
k = strlen(g.argv[2]);
21322148
if( strncmp(g.argv[2],"before",k)==0 ){
2133
- mode = 1;
2149
+ mode = TIMELINE_MODE_BEFORE;
21342150
}else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
2135
- mode = 2;
2151
+ mode = TIMELINE_MODE_AFTER;
21362152
}else if( strncmp(g.argv[2],"descendants",k)==0 ){
2137
- mode = 3;
2153
+ mode = TIMELINE_MODE_CHILDREN;
21382154
}else if( strncmp(g.argv[2],"children",k)==0 ){
2139
- mode = 3;
2155
+ mode = TIMELINE_MODE_CHILDREN;
21402156
}else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
2141
- mode = 4;
2157
+ mode = TIMELINE_MODE_PARENTS;
21422158
}else if( strncmp(g.argv[2],"parents",k)==0 ){
2143
- mode = 4;
2159
+ mode = TIMELINE_MODE_PARENTS;
21442160
}else if(!zType && !zLimit){
21452161
usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? "
21462162
"?-W|--width WIDTH? ?-p|--path PATH");
21472163
}
21482164
if( '-' != *g.argv[3] ){
@@ -2157,11 +2173,11 @@
21572173
}
21582174
k = strlen(zOrigin);
21592175
blob_zero(&uuid);
21602176
blob_append(&uuid, zOrigin, -1);
21612177
if( fossil_strcmp(zOrigin, "now")==0 ){
2162
- if( mode==3 || mode==4 ){
2178
+ if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){
21632179
fossil_fatal("cannot compute descendants or ancestors of a date");
21642180
}
21652181
zDate = mprintf("(SELECT datetime('now'))");
21662182
}else if( strncmp(zOrigin, "current", k)==0 ){
21672183
if( !g.localOpen ){
@@ -2170,19 +2186,21 @@
21702186
objid = db_lget_int("checkout",0);
21712187
zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
21722188
}else if( name_to_uuid(&uuid, 0, "*")==0 ){
21732189
objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
21742190
zDate = mprintf("(SELECT mtime FROM event WHERE objid=%d)", objid);
2175
- }else{
2191
+ }else if( fossil_is_julianday(zOrigin) ){
21762192
const char *zShift = "";
2177
- if( mode==3 || mode==4 ){
2193
+ if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){
21782194
fossil_fatal("cannot compute descendants or ancestors of a date");
21792195
}
2180
- if( mode==0 ){
2196
+ if( mode==TIMELINE_MODE_NONE ){
21812197
if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
21822198
}
21832199
zDate = mprintf("(SELECT julianday(%Q%s, fromLocal()))", zOrigin, zShift);
2200
+ }else{
2201
+ fossil_fatal("unknown check-in or invalid date: %s", zOrigin);
21842202
}
21852203
21862204
if( zFilePattern ){
21872205
if( zType==0 ){
21882206
/* When zFilePattern is specified and type is not specified, only show
@@ -2195,21 +2213,21 @@
21952213
* zFilePattern. */
21962214
zFilePattern = 0;
21972215
}
21982216
}
21992217
2200
- if( mode==0 ) mode = 1;
2218
+ if( mode==TIMELINE_MODE_NONE ) mode = TIMELINE_MODE_BEFORE;
22012219
blob_zero(&sql);
22022220
blob_append(&sql, timeline_query_for_tty(), -1);
22032221
blob_append_sql(&sql, "\n AND event.mtime %s %s",
2204
- (mode==1 || mode==4) ? "<=" : ">=",
2205
- zDate /*safe-for-%s*/
2222
+ ( mode==TIMELINE_MODE_BEFORE ||
2223
+ mode==TIMELINE_MODE_PARENTS ) ? "<=" : ">=", zDate /*safe-for-%s*/
22062224
);
22072225
2208
- if( mode==3 || mode==4 ){
2226
+ if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){
22092227
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
2210
- if( mode==3 ){
2228
+ if( mode==TIMELINE_MODE_CHILDREN ){
22112229
compute_descendants(objid, n);
22122230
}else{
22132231
compute_ancestors(objid, n, 0);
22142232
}
22152233
blob_append_sql(&sql, "\n AND blob.rid IN ok");
22162234
--- src/timeline.c
+++ src/timeline.c
@@ -26,10 +26,19 @@
26 /*
27 ** The value of one second in julianday notation
28 */
29 #define ONE_SECOND (1.0/86400.0)
30
 
 
 
 
 
 
 
 
 
31 /*
32 ** Add an appropriate tag to the output if "rid" is unpublished (private)
33 */
34 #define UNPUB_TAG "<em>(unpublished)</em>"
35 void tag_private_status(int rid){
@@ -2029,10 +2038,17 @@
2029 && z[4]=='-'
2030 && z[7]=='-'
2031 && fossil_isdigit(z[0])
2032 && fossil_isdigit(z[5]);
2033 }
 
 
 
 
 
 
 
2034
2035 /*
2036 ** COMMAND: timeline
2037 **
2038 ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -2087,11 +2103,11 @@
2087 char *zOrigin;
2088 char *zDate;
2089 Blob sql;
2090 int objid = 0;
2091 Blob uuid;
2092 int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
2093 int verboseFlag = 0 ;
2094 int iOffset;
2095 const char *zFilePattern = 0;
2096 Blob treeName;
2097
@@ -2128,21 +2144,21 @@
2128 verify_all_options();
2129
2130 if( g.argc>=4 ){
2131 k = strlen(g.argv[2]);
2132 if( strncmp(g.argv[2],"before",k)==0 ){
2133 mode = 1;
2134 }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
2135 mode = 2;
2136 }else if( strncmp(g.argv[2],"descendants",k)==0 ){
2137 mode = 3;
2138 }else if( strncmp(g.argv[2],"children",k)==0 ){
2139 mode = 3;
2140 }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
2141 mode = 4;
2142 }else if( strncmp(g.argv[2],"parents",k)==0 ){
2143 mode = 4;
2144 }else if(!zType && !zLimit){
2145 usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? "
2146 "?-W|--width WIDTH? ?-p|--path PATH");
2147 }
2148 if( '-' != *g.argv[3] ){
@@ -2157,11 +2173,11 @@
2157 }
2158 k = strlen(zOrigin);
2159 blob_zero(&uuid);
2160 blob_append(&uuid, zOrigin, -1);
2161 if( fossil_strcmp(zOrigin, "now")==0 ){
2162 if( mode==3 || mode==4 ){
2163 fossil_fatal("cannot compute descendants or ancestors of a date");
2164 }
2165 zDate = mprintf("(SELECT datetime('now'))");
2166 }else if( strncmp(zOrigin, "current", k)==0 ){
2167 if( !g.localOpen ){
@@ -2170,19 +2186,21 @@
2170 objid = db_lget_int("checkout",0);
2171 zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
2172 }else if( name_to_uuid(&uuid, 0, "*")==0 ){
2173 objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
2174 zDate = mprintf("(SELECT mtime FROM event WHERE objid=%d)", objid);
2175 }else{
2176 const char *zShift = "";
2177 if( mode==3 || mode==4 ){
2178 fossil_fatal("cannot compute descendants or ancestors of a date");
2179 }
2180 if( mode==0 ){
2181 if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
2182 }
2183 zDate = mprintf("(SELECT julianday(%Q%s, fromLocal()))", zOrigin, zShift);
 
 
2184 }
2185
2186 if( zFilePattern ){
2187 if( zType==0 ){
2188 /* When zFilePattern is specified and type is not specified, only show
@@ -2195,21 +2213,21 @@
2195 * zFilePattern. */
2196 zFilePattern = 0;
2197 }
2198 }
2199
2200 if( mode==0 ) mode = 1;
2201 blob_zero(&sql);
2202 blob_append(&sql, timeline_query_for_tty(), -1);
2203 blob_append_sql(&sql, "\n AND event.mtime %s %s",
2204 (mode==1 || mode==4) ? "<=" : ">=",
2205 zDate /*safe-for-%s*/
2206 );
2207
2208 if( mode==3 || mode==4 ){
2209 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
2210 if( mode==3 ){
2211 compute_descendants(objid, n);
2212 }else{
2213 compute_ancestors(objid, n, 0);
2214 }
2215 blob_append_sql(&sql, "\n AND blob.rid IN ok");
2216
--- src/timeline.c
+++ src/timeline.c
@@ -26,10 +26,19 @@
26 /*
27 ** The value of one second in julianday notation
28 */
29 #define ONE_SECOND (1.0/86400.0)
30
31 /*
32 ** timeline mode options
33 */
34 #define TIMELINE_MODE_NONE 0
35 #define TIMELINE_MODE_BEFORE 1
36 #define TIMELINE_MODE_AFTER 2
37 #define TIMELINE_MODE_CHILDREN 3
38 #define TIMELINE_MODE_PARENTS 4
39
40 /*
41 ** Add an appropriate tag to the output if "rid" is unpublished (private)
42 */
43 #define UNPUB_TAG "<em>(unpublished)</em>"
44 void tag_private_status(int rid){
@@ -2029,10 +2038,17 @@
2038 && z[4]=='-'
2039 && z[7]=='-'
2040 && fossil_isdigit(z[0])
2041 && fossil_isdigit(z[5]);
2042 }
2043
2044 /*
2045 ** Return true if the input string can be converted to a julianday.
2046 */
2047 static int fossil_is_julianday(const char *zDate){
2048 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd WHERE jd IS NOT NULL)", zDate);
2049 }
2050
2051 /*
2052 ** COMMAND: timeline
2053 **
2054 ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS?
@@ -2087,11 +2103,11 @@
2103 char *zOrigin;
2104 char *zDate;
2105 Blob sql;
2106 int objid = 0;
2107 Blob uuid;
2108 int mode = TIMELINE_MODE_NONE;
2109 int verboseFlag = 0 ;
2110 int iOffset;
2111 const char *zFilePattern = 0;
2112 Blob treeName;
2113
@@ -2128,21 +2144,21 @@
2144 verify_all_options();
2145
2146 if( g.argc>=4 ){
2147 k = strlen(g.argv[2]);
2148 if( strncmp(g.argv[2],"before",k)==0 ){
2149 mode = TIMELINE_MODE_BEFORE;
2150 }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){
2151 mode = TIMELINE_MODE_AFTER;
2152 }else if( strncmp(g.argv[2],"descendants",k)==0 ){
2153 mode = TIMELINE_MODE_CHILDREN;
2154 }else if( strncmp(g.argv[2],"children",k)==0 ){
2155 mode = TIMELINE_MODE_CHILDREN;
2156 }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
2157 mode = TIMELINE_MODE_PARENTS;
2158 }else if( strncmp(g.argv[2],"parents",k)==0 ){
2159 mode = TIMELINE_MODE_PARENTS;
2160 }else if(!zType && !zLimit){
2161 usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? "
2162 "?-W|--width WIDTH? ?-p|--path PATH");
2163 }
2164 if( '-' != *g.argv[3] ){
@@ -2157,11 +2173,11 @@
2173 }
2174 k = strlen(zOrigin);
2175 blob_zero(&uuid);
2176 blob_append(&uuid, zOrigin, -1);
2177 if( fossil_strcmp(zOrigin, "now")==0 ){
2178 if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){
2179 fossil_fatal("cannot compute descendants or ancestors of a date");
2180 }
2181 zDate = mprintf("(SELECT datetime('now'))");
2182 }else if( strncmp(zOrigin, "current", k)==0 ){
2183 if( !g.localOpen ){
@@ -2170,19 +2186,21 @@
2186 objid = db_lget_int("checkout",0);
2187 zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
2188 }else if( name_to_uuid(&uuid, 0, "*")==0 ){
2189 objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
2190 zDate = mprintf("(SELECT mtime FROM event WHERE objid=%d)", objid);
2191 }else if( fossil_is_julianday(zOrigin) ){
2192 const char *zShift = "";
2193 if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){
2194 fossil_fatal("cannot compute descendants or ancestors of a date");
2195 }
2196 if( mode==TIMELINE_MODE_NONE ){
2197 if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
2198 }
2199 zDate = mprintf("(SELECT julianday(%Q%s, fromLocal()))", zOrigin, zShift);
2200 }else{
2201 fossil_fatal("unknown check-in or invalid date: %s", zOrigin);
2202 }
2203
2204 if( zFilePattern ){
2205 if( zType==0 ){
2206 /* When zFilePattern is specified and type is not specified, only show
@@ -2195,21 +2213,21 @@
2213 * zFilePattern. */
2214 zFilePattern = 0;
2215 }
2216 }
2217
2218 if( mode==TIMELINE_MODE_NONE ) mode = TIMELINE_MODE_BEFORE;
2219 blob_zero(&sql);
2220 blob_append(&sql, timeline_query_for_tty(), -1);
2221 blob_append_sql(&sql, "\n AND event.mtime %s %s",
2222 ( mode==TIMELINE_MODE_BEFORE ||
2223 mode==TIMELINE_MODE_PARENTS ) ? "<=" : ">=", zDate /*safe-for-%s*/
2224 );
2225
2226 if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){
2227 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
2228 if( mode==TIMELINE_MODE_CHILDREN ){
2229 compute_descendants(objid, n);
2230 }else{
2231 compute_ancestors(objid, n, 0);
2232 }
2233 blob_append_sql(&sql, "\n AND blob.rid IN ok");
2234
+3 -2
--- src/undo.c
+++ src/undo.c
@@ -477,14 +477,15 @@
477477
if( undo_available==0 ){
478478
fossil_print("No undo or redo is available\n");
479479
}else{
480480
Stmt q;
481481
int nChng = 0;
482
+ const char *zArticle = undo_available==1 ? "An" : "A";
482483
zCmd = undo_available==1 ? "undo" : "redo";
483
- fossil_print("A %s is available for the following command:\n\n"
484
+ fossil_print("%s %s is available for the following command:\n\n"
484485
" %s %s\n\n",
485
- zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
486
+ zArticle, zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
486487
db_prepare(&q,
487488
"SELECT existsflag, pathname FROM undo ORDER BY pathname"
488489
);
489490
while( db_step(&q)==SQLITE_ROW ){
490491
if( nChng==0 ){
491492
--- src/undo.c
+++ src/undo.c
@@ -477,14 +477,15 @@
477 if( undo_available==0 ){
478 fossil_print("No undo or redo is available\n");
479 }else{
480 Stmt q;
481 int nChng = 0;
 
482 zCmd = undo_available==1 ? "undo" : "redo";
483 fossil_print("A %s is available for the following command:\n\n"
484 " %s %s\n\n",
485 zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
486 db_prepare(&q,
487 "SELECT existsflag, pathname FROM undo ORDER BY pathname"
488 );
489 while( db_step(&q)==SQLITE_ROW ){
490 if( nChng==0 ){
491
--- src/undo.c
+++ src/undo.c
@@ -477,14 +477,15 @@
477 if( undo_available==0 ){
478 fossil_print("No undo or redo is available\n");
479 }else{
480 Stmt q;
481 int nChng = 0;
482 const char *zArticle = undo_available==1 ? "An" : "A";
483 zCmd = undo_available==1 ? "undo" : "redo";
484 fossil_print("%s %s is available for the following command:\n\n"
485 " %s %s\n\n",
486 zArticle, zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
487 db_prepare(&q,
488 "SELECT existsflag, pathname FROM undo ORDER BY pathname"
489 );
490 while( db_step(&q)==SQLITE_ROW ){
491 if( nChng==0 ){
492
+32 -11
--- src/unversioned.c
+++ src/unversioned.c
@@ -190,13 +190,26 @@
190190
}
191191
return syncFlags;
192192
}
193193
194194
/*
195
+** Return true if the zName contains any whitespace
196
+*/
197
+static int contains_whitespace(const char *zName){
198
+ while( zName[0] ){
199
+ if( fossil_isspace(zName[0]) ) return 1;
200
+ zName++;
201
+ }
202
+ return 0;
203
+}
204
+
205
+/*
206
+** COMMAND: uv*
195207
** COMMAND: unversioned
196208
**
197209
** Usage: %fossil unversioned SUBCOMMAND ARGS...
210
+** or: %fossil uv SUBCOMMAND ARGS..
198211
**
199212
** Unversioned files (UV-files) are artifacts that are synced and are available
200213
** for download but which do not preserve history. Only the most recent version
201214
** of each UV-file is retained. Changes to an UV-file are permanent and cannot
202215
** be undone, so use appropriate caution with this command.
@@ -214,35 +227,40 @@
214227
**
215228
** edit FILE Bring up FILE in a text editor for modification.
216229
**
217230
** export FILE OUTPUT Write the content of FILE into OUTPUT on disk
218231
**
219
-** list | ls Show all unversioned files held in the local repository.
232
+** list | ls Show all unversioned files held in the local
233
+** repository.
220234
**
221
-** revert ?URL? Restore the state of all unversioned files in the local
222
-** repository to match the remote repository URL.
235
+** revert ?URL? Restore the state of all unversioned files in the
236
+** local repository to match the remote repository
237
+** URL.
238
+**
223239
** Options:
224240
** -v|--verbose Extra diagnostic output
225241
** -n|--dryrun Show what would have happened
226242
**
227
-** rm FILE ... Remove an unversioned files from the local repository.
243
+** remove | rm FILE ... Remove unversioned files from the local repository.
228244
** Changes are not pushed to other repositories until
229
-** the next sync.
245
+** the next sync.
230246
**
231247
** sync ?URL? Synchronize the state of all unversioned files with
232
-** the remote repository URL. The most recent version of
233
-** each file is propagate to all repositories and all
234
-** prior versions are permanently forgotten.
248
+** the remote repository URL. The most recent version
249
+** of each file is propagate to all repositories and
250
+** all prior versions are permanently forgotten.
251
+**
235252
** Options:
236253
** -v|--verbose Extra diagnostic output
237254
** -n|--dryrun Show what would have happened
238255
**
239256
** touch FILE ... Update the TIMESTAMP on all of the listed files
240257
**
241258
** Options:
242259
**
243
-** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for "add" and "rm".
260
+** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add",
261
+** "edit", "remove", and "touch" subcommands.
244262
*/
245263
void unversioned_cmd(void){
246264
const char *zCmd;
247265
int nCmd;
248266
const char *zMtime = find_option("mtime", 0, 1);
@@ -271,10 +289,13 @@
271289
for(i=3; i<g.argc; i++){
272290
zIn = zAs ? zAs : g.argv[i];
273291
if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){
274292
fossil_fatal("'%Q' is not an acceptable filename", zIn);
275293
}
294
+ if( contains_whitespace(zIn) ){
295
+ fossil_fatal("names of unversioned files may not contain whitespace");
296
+ }
276297
blob_init(&file,0,0);
277298
blob_read_from_file(&file, g.argv[i]);
278299
unversioned_write(zIn, &file, mtime);
279300
blob_reset(&file);
280301
}
@@ -389,11 +410,11 @@
389410
}else if( memcmp(zCmd, "revert", nCmd)==0 ){
390411
unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
391412
g.argv[1] = "sync";
392413
g.argv[2] = "--uv-noop";
393414
sync_unversioned(syncFlags);
394
- }else if( memcmp(zCmd, "rm", nCmd)==0 ){
415
+ }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){
395416
int i;
396417
verify_all_options();
397418
db_begin_transaction();
398419
for(i=3; i<g.argc; i++){
399420
db_multi_exec(
@@ -420,11 +441,11 @@
420441
);
421442
}
422443
db_unset("uv-hash", 0);
423444
db_end_transaction(0);
424445
}else{
425
- usage("add|cat|edit|export|ls|revert|rm|sync|touch");
446
+ usage("add|cat|edit|export|list|revert|remove|sync|touch");
426447
}
427448
}
428449
429450
/*
430451
** WEBPAGE: uvlist
431452
--- src/unversioned.c
+++ src/unversioned.c
@@ -190,13 +190,26 @@
190 }
191 return syncFlags;
192 }
193
194 /*
 
 
 
 
 
 
 
 
 
 
 
 
195 ** COMMAND: unversioned
196 **
197 ** Usage: %fossil unversioned SUBCOMMAND ARGS...
 
198 **
199 ** Unversioned files (UV-files) are artifacts that are synced and are available
200 ** for download but which do not preserve history. Only the most recent version
201 ** of each UV-file is retained. Changes to an UV-file are permanent and cannot
202 ** be undone, so use appropriate caution with this command.
@@ -214,35 +227,40 @@
214 **
215 ** edit FILE Bring up FILE in a text editor for modification.
216 **
217 ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk
218 **
219 ** list | ls Show all unversioned files held in the local repository.
 
220 **
221 ** revert ?URL? Restore the state of all unversioned files in the local
222 ** repository to match the remote repository URL.
 
 
223 ** Options:
224 ** -v|--verbose Extra diagnostic output
225 ** -n|--dryrun Show what would have happened
226 **
227 ** rm FILE ... Remove an unversioned files from the local repository.
228 ** Changes are not pushed to other repositories until
229 ** the next sync.
230 **
231 ** sync ?URL? Synchronize the state of all unversioned files with
232 ** the remote repository URL. The most recent version of
233 ** each file is propagate to all repositories and all
234 ** prior versions are permanently forgotten.
 
235 ** Options:
236 ** -v|--verbose Extra diagnostic output
237 ** -n|--dryrun Show what would have happened
238 **
239 ** touch FILE ... Update the TIMESTAMP on all of the listed files
240 **
241 ** Options:
242 **
243 ** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for "add" and "rm".
 
244 */
245 void unversioned_cmd(void){
246 const char *zCmd;
247 int nCmd;
248 const char *zMtime = find_option("mtime", 0, 1);
@@ -271,10 +289,13 @@
271 for(i=3; i<g.argc; i++){
272 zIn = zAs ? zAs : g.argv[i];
273 if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){
274 fossil_fatal("'%Q' is not an acceptable filename", zIn);
275 }
 
 
 
276 blob_init(&file,0,0);
277 blob_read_from_file(&file, g.argv[i]);
278 unversioned_write(zIn, &file, mtime);
279 blob_reset(&file);
280 }
@@ -389,11 +410,11 @@
389 }else if( memcmp(zCmd, "revert", nCmd)==0 ){
390 unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
391 g.argv[1] = "sync";
392 g.argv[2] = "--uv-noop";
393 sync_unversioned(syncFlags);
394 }else if( memcmp(zCmd, "rm", nCmd)==0 ){
395 int i;
396 verify_all_options();
397 db_begin_transaction();
398 for(i=3; i<g.argc; i++){
399 db_multi_exec(
@@ -420,11 +441,11 @@
420 );
421 }
422 db_unset("uv-hash", 0);
423 db_end_transaction(0);
424 }else{
425 usage("add|cat|edit|export|ls|revert|rm|sync|touch");
426 }
427 }
428
429 /*
430 ** WEBPAGE: uvlist
431
--- src/unversioned.c
+++ src/unversioned.c
@@ -190,13 +190,26 @@
190 }
191 return syncFlags;
192 }
193
194 /*
195 ** Return true if the zName contains any whitespace
196 */
197 static int contains_whitespace(const char *zName){
198 while( zName[0] ){
199 if( fossil_isspace(zName[0]) ) return 1;
200 zName++;
201 }
202 return 0;
203 }
204
205 /*
206 ** COMMAND: uv*
207 ** COMMAND: unversioned
208 **
209 ** Usage: %fossil unversioned SUBCOMMAND ARGS...
210 ** or: %fossil uv SUBCOMMAND ARGS..
211 **
212 ** Unversioned files (UV-files) are artifacts that are synced and are available
213 ** for download but which do not preserve history. Only the most recent version
214 ** of each UV-file is retained. Changes to an UV-file are permanent and cannot
215 ** be undone, so use appropriate caution with this command.
@@ -214,35 +227,40 @@
227 **
228 ** edit FILE Bring up FILE in a text editor for modification.
229 **
230 ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk
231 **
232 ** list | ls Show all unversioned files held in the local
233 ** repository.
234 **
235 ** revert ?URL? Restore the state of all unversioned files in the
236 ** local repository to match the remote repository
237 ** URL.
238 **
239 ** Options:
240 ** -v|--verbose Extra diagnostic output
241 ** -n|--dryrun Show what would have happened
242 **
243 ** remove | rm FILE ... Remove unversioned files from the local repository.
244 ** Changes are not pushed to other repositories until
245 ** the next sync.
246 **
247 ** sync ?URL? Synchronize the state of all unversioned files with
248 ** the remote repository URL. The most recent version
249 ** of each file is propagate to all repositories and
250 ** all prior versions are permanently forgotten.
251 **
252 ** Options:
253 ** -v|--verbose Extra diagnostic output
254 ** -n|--dryrun Show what would have happened
255 **
256 ** touch FILE ... Update the TIMESTAMP on all of the listed files
257 **
258 ** Options:
259 **
260 ** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add",
261 ** "edit", "remove", and "touch" subcommands.
262 */
263 void unversioned_cmd(void){
264 const char *zCmd;
265 int nCmd;
266 const char *zMtime = find_option("mtime", 0, 1);
@@ -271,10 +289,13 @@
289 for(i=3; i<g.argc; i++){
290 zIn = zAs ? zAs : g.argv[i];
291 if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){
292 fossil_fatal("'%Q' is not an acceptable filename", zIn);
293 }
294 if( contains_whitespace(zIn) ){
295 fossil_fatal("names of unversioned files may not contain whitespace");
296 }
297 blob_init(&file,0,0);
298 blob_read_from_file(&file, g.argv[i]);
299 unversioned_write(zIn, &file, mtime);
300 blob_reset(&file);
301 }
@@ -389,11 +410,11 @@
410 }else if( memcmp(zCmd, "revert", nCmd)==0 ){
411 unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
412 g.argv[1] = "sync";
413 g.argv[2] = "--uv-noop";
414 sync_unversioned(syncFlags);
415 }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){
416 int i;
417 verify_all_options();
418 db_begin_transaction();
419 for(i=3; i<g.argc; i++){
420 db_multi_exec(
@@ -420,11 +441,11 @@
441 );
442 }
443 db_unset("uv-hash", 0);
444 db_end_transaction(0);
445 }else{
446 usage("add|cat|edit|export|list|revert|remove|sync|touch");
447 }
448 }
449
450 /*
451 ** WEBPAGE: uvlist
452
+1 -1
--- src/utf8.c
+++ src/utf8.c
@@ -317,11 +317,11 @@
317317
wchar_t *zUnicode; /* Unicode version of zUtf8 */
318318
DWORD dummy;
319319
Blob blob;
320320
321321
static int istty[2] = { -1, -1 };
322
- if( istty[toStdErr] == -1 ){
322
+ if( istty[toStdErr]==-1 ){
323323
istty[toStdErr] = _isatty(toStdErr + 1) != 0;
324324
}
325325
if( !istty[toStdErr] ){
326326
/* stdout/stderr is not a console. */
327327
return -1;
328328
--- src/utf8.c
+++ src/utf8.c
@@ -317,11 +317,11 @@
317 wchar_t *zUnicode; /* Unicode version of zUtf8 */
318 DWORD dummy;
319 Blob blob;
320
321 static int istty[2] = { -1, -1 };
322 if( istty[toStdErr] == -1 ){
323 istty[toStdErr] = _isatty(toStdErr + 1) != 0;
324 }
325 if( !istty[toStdErr] ){
326 /* stdout/stderr is not a console. */
327 return -1;
328
--- src/utf8.c
+++ src/utf8.c
@@ -317,11 +317,11 @@
317 wchar_t *zUnicode; /* Unicode version of zUtf8 */
318 DWORD dummy;
319 Blob blob;
320
321 static int istty[2] = { -1, -1 };
322 if( istty[toStdErr]==-1 ){
323 istty[toStdErr] = _isatty(toStdErr + 1) != 0;
324 }
325 if( !istty[toStdErr] ){
326 /* stdout/stderr is not a console. */
327 return -1;
328
+6 -6
--- src/vfile.c
+++ src/vfile.c
@@ -264,19 +264,19 @@
264264
}
265265
}
266266
}
267267
#ifndef _WIN32
268268
if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){
269
- if( origPerm == currentPerm ){
269
+ if( origPerm==currentPerm ){
270270
chnged = 0;
271
- }else if( currentPerm == PERM_EXE ){
271
+ }else if( currentPerm==PERM_EXE ){
272272
chnged = 6;
273
- }else if( currentPerm == PERM_LNK ){
273
+ }else if( currentPerm==PERM_LNK ){
274274
chnged = 7;
275
- }else if( origPerm == PERM_EXE ){
275
+ }else if( origPerm==PERM_EXE ){
276276
chnged = 8;
277
- }else if( origPerm == PERM_LNK ){
277
+ }else if( origPerm==PERM_LNK ){
278278
chnged = 9;
279279
}
280280
}
281281
#endif
282282
if( currentMtime!=oldMtime || chnged!=oldChnged ){
@@ -348,11 +348,11 @@
348348
blob_reset(&content);
349349
continue;
350350
}
351351
}
352352
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
353
- if( file_wd_isdir(zName) == 1 ){
353
+ if( file_wd_isdir(zName)==1 ){
354354
/*TODO(dchest): remove directories? */
355355
fossil_fatal("%s is directory, cannot overwrite\n", zName);
356356
}
357357
if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){
358358
file_delete(zName);
359359
--- src/vfile.c
+++ src/vfile.c
@@ -264,19 +264,19 @@
264 }
265 }
266 }
267 #ifndef _WIN32
268 if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){
269 if( origPerm == currentPerm ){
270 chnged = 0;
271 }else if( currentPerm == PERM_EXE ){
272 chnged = 6;
273 }else if( currentPerm == PERM_LNK ){
274 chnged = 7;
275 }else if( origPerm == PERM_EXE ){
276 chnged = 8;
277 }else if( origPerm == PERM_LNK ){
278 chnged = 9;
279 }
280 }
281 #endif
282 if( currentMtime!=oldMtime || chnged!=oldChnged ){
@@ -348,11 +348,11 @@
348 blob_reset(&content);
349 continue;
350 }
351 }
352 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
353 if( file_wd_isdir(zName) == 1 ){
354 /*TODO(dchest): remove directories? */
355 fossil_fatal("%s is directory, cannot overwrite\n", zName);
356 }
357 if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){
358 file_delete(zName);
359
--- src/vfile.c
+++ src/vfile.c
@@ -264,19 +264,19 @@
264 }
265 }
266 }
267 #ifndef _WIN32
268 if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){
269 if( origPerm==currentPerm ){
270 chnged = 0;
271 }else if( currentPerm==PERM_EXE ){
272 chnged = 6;
273 }else if( currentPerm==PERM_LNK ){
274 chnged = 7;
275 }else if( origPerm==PERM_EXE ){
276 chnged = 8;
277 }else if( origPerm==PERM_LNK ){
278 chnged = 9;
279 }
280 }
281 #endif
282 if( currentMtime!=oldMtime || chnged!=oldChnged ){
@@ -348,11 +348,11 @@
348 blob_reset(&content);
349 continue;
350 }
351 }
352 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
353 if( file_wd_isdir(zName)==1 ){
354 /*TODO(dchest): remove directories? */
355 fossil_fatal("%s is directory, cannot overwrite\n", zName);
356 }
357 if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){
358 file_delete(zName);
359
+88 -15
--- src/winhttp.c
+++ src/winhttp.c
@@ -24,10 +24,24 @@
2424
/* This code is for win32 only */
2525
#include <windows.h>
2626
#include <process.h>
2727
#include "winhttp.h"
2828
29
+/*
30
+** The HttpServer structure holds information about an instance of
31
+** the HTTP server itself.
32
+*/
33
+typedef struct HttpServer HttpServer;
34
+struct HttpServer {
35
+ HANDLE hStoppedEvent; /* Event to signal when server is stopped,
36
+ ** must be closed by callee. */
37
+ char *zStopper; /* The stopper file name, must be freed by
38
+ ** callee. */
39
+ SOCKET listener; /* Socket on which the server is listening,
40
+ ** may be closed by callee. */
41
+};
42
+
2943
/*
3044
** The HttpRequest structure holds information about each incoming
3145
** HTTP request.
3246
*/
3347
typedef struct HttpRequest HttpRequest;
@@ -70,10 +84,51 @@
7084
const char *zService,
7185
const char *zErr
7286
){
7387
fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
7488
}
89
+
90
+/*
91
+** Make sure the server stops as soon as possible after the stopper file
92
+** is found. If there is no stopper file name, do nothing.
93
+*/
94
+static void win32_server_stopper(void *pAppData){
95
+ HttpServer *p = (HttpServer*)pAppData;
96
+ if( p!=0 ){
97
+ HANDLE hStoppedEvent = p->hStoppedEvent;
98
+ const char *zStopper = p->zStopper;
99
+ SOCKET listener = p->listener;
100
+ if( hStoppedEvent!=NULL && zStopper!=0 && listener!=INVALID_SOCKET ){
101
+ while( 1 ){
102
+ DWORD dwResult = WaitForMultipleObjectsEx(1, &hStoppedEvent, FALSE,
103
+ 1000, TRUE);
104
+ if( dwResult!=WAIT_IO_COMPLETION && dwResult!=WAIT_TIMEOUT ){
105
+ /* The event is either invalid, signaled, or abandoned. Bail
106
+ ** out now because those conditions should indicate the parent
107
+ ** thread is dead or dying. */
108
+ break;
109
+ }
110
+ if( file_size(zStopper)>=0 ){
111
+ /* The stopper file has been found. Attempt to close the server
112
+ ** listener socket now and then exit. */
113
+ closesocket(listener);
114
+ p->listener = INVALID_SOCKET;
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ if( hStoppedEvent!=NULL ){
120
+ CloseHandle(hStoppedEvent);
121
+ p->hStoppedEvent = NULL;
122
+ }
123
+ if( zStopper!=0 ){
124
+ fossil_free(p->zStopper);
125
+ p->zStopper = 0;
126
+ }
127
+ fossil_free(p);
128
+ }
129
+}
75130
76131
/*
77132
** Process a single incoming HTTP request.
78133
*/
79134
static void win32_http_request(void *pAppData){
@@ -163,11 +218,11 @@
163218
if( in ) fclose(in);
164219
closesocket(p->s);
165220
file_delete(zRequestFName);
166221
file_delete(zReplyFName);
167222
file_delete(zCmdFName);
168
- free(p);
223
+ fossil_free(p);
169224
}
170225
171226
/*
172227
** Process a single incoming SCGI request.
173228
*/
@@ -225,11 +280,11 @@
225280
if( out ) fclose(out);
226281
if( in ) fclose(in);
227282
closesocket(p->s);
228283
file_delete(zRequestFName);
229284
file_delete(zReplyFName);
230
- free(p);
285
+ fossil_free(p);
231286
}
232287
233288
234289
/*
235290
** Start a listening socket and process incoming HTTP requests on
@@ -243,19 +298,19 @@
243298
const char *zNotFound, /* The --notfound option, or NULL */
244299
const char *zFileGlob, /* The --fileglob option, or NULL */
245300
const char *zIpAddr, /* Bind to this IP address, if not NULL */
246301
int flags /* One or more HTTP_SERVER_ flags */
247302
){
303
+ HANDLE hStoppedEvent;
248304
WSADATA wd;
249305
SOCKET s = INVALID_SOCKET;
250306
SOCKADDR_IN addr;
251307
int idCnt = 0;
252308
int iPort = mnPort;
253309
Blob options;
254310
wchar_t zTmpPath[MAX_PATH];
255311
256
- if( zStopper ) file_delete(zStopper);
257312
blob_zero(&options);
258313
if( zBaseUrl ){
259314
blob_appendf(&options, " --baseurl %s", zBaseUrl);
260315
}
261316
if( zNotFound ){
@@ -324,17 +379,35 @@
324379
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
325380
fossil_print("Launch webbrowser: %s\n", zBrowser);
326381
fossil_system(zBrowser);
327382
}
328383
fossil_print("Type Ctrl-C to stop the HTTP server\n");
384
+ /* Create an event used to signal when this server is exiting. */
385
+ hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
386
+ assert( hStoppedEvent!=NULL );
387
+ /* If there is a stopper file name, start the dedicated thread now.
388
+ ** It will attempt to close the listener socket within 1 second of
389
+ ** the stopper file being created. */
390
+ if( zStopper ){
391
+ HttpServer *pServer = fossil_malloc(sizeof(HttpServer));
392
+ memset(pServer, 0, sizeof(HttpServer));
393
+ DuplicateHandle(GetCurrentProcess(), hStoppedEvent,
394
+ GetCurrentProcess(), &pServer->hStoppedEvent,
395
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
396
+ assert( pServer->hStoppedEvent!=NULL );
397
+ pServer->zStopper = fossil_strdup(zStopper);
398
+ pServer->listener = s;
399
+ file_delete(zStopper);
400
+ _beginthread(win32_server_stopper, 0, (void*)pServer);
401
+ }
329402
/* Set the service status to running and pass the listener socket to the
330403
** service handling procedures. */
331404
win32_http_service_running(s);
332405
for(;;){
333406
SOCKET client;
334407
SOCKADDR_IN client_addr;
335
- HttpRequest *p;
408
+ HttpRequest *pRequest;
336409
int len = sizeof(client_addr);
337410
int wsaError;
338411
339412
client = accept(s, (struct sockaddr*)&client_addr, &len);
340413
if( client==INVALID_SOCKET ){
@@ -347,27 +420,27 @@
347420
}else{
348421
closesocket(s);
349422
WSACleanup();
350423
fossil_fatal("error from accept()");
351424
}
352
- }else if( zStopper && file_size(zStopper)>=0 ){
353
- break;
354
- }
355
- p = fossil_malloc( sizeof(*p) );
356
- p->id = ++idCnt;
357
- p->s = client;
358
- p->addr = client_addr;
359
- p->flags = flags;
360
- p->zOptions = blob_str(&options);
425
+ }
426
+ pRequest = fossil_malloc(sizeof(HttpRequest));
427
+ pRequest->id = ++idCnt;
428
+ pRequest->s = client;
429
+ pRequest->addr = client_addr;
430
+ pRequest->flags = flags;
431
+ pRequest->zOptions = blob_str(&options);
361432
if( flags & HTTP_SERVER_SCGI ){
362
- _beginthread(win32_scgi_request, 0, (void*)p);
433
+ _beginthread(win32_scgi_request, 0, (void*)pRequest);
363434
}else{
364
- _beginthread(win32_http_request, 0, (void*)p);
435
+ _beginthread(win32_http_request, 0, (void*)pRequest);
365436
}
366437
}
367438
closesocket(s);
368439
WSACleanup();
440
+ SetEvent(hStoppedEvent);
441
+ CloseHandle(hStoppedEvent);
369442
}
370443
371444
/*
372445
** The HttpService structure is used to pass information to the service main
373446
** function and to the service control handler function.
374447
--- src/winhttp.c
+++ src/winhttp.c
@@ -24,10 +24,24 @@
24 /* This code is for win32 only */
25 #include <windows.h>
26 #include <process.h>
27 #include "winhttp.h"
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29 /*
30 ** The HttpRequest structure holds information about each incoming
31 ** HTTP request.
32 */
33 typedef struct HttpRequest HttpRequest;
@@ -70,10 +84,51 @@
70 const char *zService,
71 const char *zErr
72 ){
73 fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
74 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
76 /*
77 ** Process a single incoming HTTP request.
78 */
79 static void win32_http_request(void *pAppData){
@@ -163,11 +218,11 @@
163 if( in ) fclose(in);
164 closesocket(p->s);
165 file_delete(zRequestFName);
166 file_delete(zReplyFName);
167 file_delete(zCmdFName);
168 free(p);
169 }
170
171 /*
172 ** Process a single incoming SCGI request.
173 */
@@ -225,11 +280,11 @@
225 if( out ) fclose(out);
226 if( in ) fclose(in);
227 closesocket(p->s);
228 file_delete(zRequestFName);
229 file_delete(zReplyFName);
230 free(p);
231 }
232
233
234 /*
235 ** Start a listening socket and process incoming HTTP requests on
@@ -243,19 +298,19 @@
243 const char *zNotFound, /* The --notfound option, or NULL */
244 const char *zFileGlob, /* The --fileglob option, or NULL */
245 const char *zIpAddr, /* Bind to this IP address, if not NULL */
246 int flags /* One or more HTTP_SERVER_ flags */
247 ){
 
248 WSADATA wd;
249 SOCKET s = INVALID_SOCKET;
250 SOCKADDR_IN addr;
251 int idCnt = 0;
252 int iPort = mnPort;
253 Blob options;
254 wchar_t zTmpPath[MAX_PATH];
255
256 if( zStopper ) file_delete(zStopper);
257 blob_zero(&options);
258 if( zBaseUrl ){
259 blob_appendf(&options, " --baseurl %s", zBaseUrl);
260 }
261 if( zNotFound ){
@@ -324,17 +379,35 @@
324 zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
325 fossil_print("Launch webbrowser: %s\n", zBrowser);
326 fossil_system(zBrowser);
327 }
328 fossil_print("Type Ctrl-C to stop the HTTP server\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329 /* Set the service status to running and pass the listener socket to the
330 ** service handling procedures. */
331 win32_http_service_running(s);
332 for(;;){
333 SOCKET client;
334 SOCKADDR_IN client_addr;
335 HttpRequest *p;
336 int len = sizeof(client_addr);
337 int wsaError;
338
339 client = accept(s, (struct sockaddr*)&client_addr, &len);
340 if( client==INVALID_SOCKET ){
@@ -347,27 +420,27 @@
347 }else{
348 closesocket(s);
349 WSACleanup();
350 fossil_fatal("error from accept()");
351 }
352 }else if( zStopper && file_size(zStopper)>=0 ){
353 break;
354 }
355 p = fossil_malloc( sizeof(*p) );
356 p->id = ++idCnt;
357 p->s = client;
358 p->addr = client_addr;
359 p->flags = flags;
360 p->zOptions = blob_str(&options);
361 if( flags & HTTP_SERVER_SCGI ){
362 _beginthread(win32_scgi_request, 0, (void*)p);
363 }else{
364 _beginthread(win32_http_request, 0, (void*)p);
365 }
366 }
367 closesocket(s);
368 WSACleanup();
 
 
369 }
370
371 /*
372 ** The HttpService structure is used to pass information to the service main
373 ** function and to the service control handler function.
374
--- src/winhttp.c
+++ src/winhttp.c
@@ -24,10 +24,24 @@
24 /* This code is for win32 only */
25 #include <windows.h>
26 #include <process.h>
27 #include "winhttp.h"
28
29 /*
30 ** The HttpServer structure holds information about an instance of
31 ** the HTTP server itself.
32 */
33 typedef struct HttpServer HttpServer;
34 struct HttpServer {
35 HANDLE hStoppedEvent; /* Event to signal when server is stopped,
36 ** must be closed by callee. */
37 char *zStopper; /* The stopper file name, must be freed by
38 ** callee. */
39 SOCKET listener; /* Socket on which the server is listening,
40 ** may be closed by callee. */
41 };
42
43 /*
44 ** The HttpRequest structure holds information about each incoming
45 ** HTTP request.
46 */
47 typedef struct HttpRequest HttpRequest;
@@ -70,10 +84,51 @@
84 const char *zService,
85 const char *zErr
86 ){
87 fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
88 }
89
90 /*
91 ** Make sure the server stops as soon as possible after the stopper file
92 ** is found. If there is no stopper file name, do nothing.
93 */
94 static void win32_server_stopper(void *pAppData){
95 HttpServer *p = (HttpServer*)pAppData;
96 if( p!=0 ){
97 HANDLE hStoppedEvent = p->hStoppedEvent;
98 const char *zStopper = p->zStopper;
99 SOCKET listener = p->listener;
100 if( hStoppedEvent!=NULL && zStopper!=0 && listener!=INVALID_SOCKET ){
101 while( 1 ){
102 DWORD dwResult = WaitForMultipleObjectsEx(1, &hStoppedEvent, FALSE,
103 1000, TRUE);
104 if( dwResult!=WAIT_IO_COMPLETION && dwResult!=WAIT_TIMEOUT ){
105 /* The event is either invalid, signaled, or abandoned. Bail
106 ** out now because those conditions should indicate the parent
107 ** thread is dead or dying. */
108 break;
109 }
110 if( file_size(zStopper)>=0 ){
111 /* The stopper file has been found. Attempt to close the server
112 ** listener socket now and then exit. */
113 closesocket(listener);
114 p->listener = INVALID_SOCKET;
115 break;
116 }
117 }
118 }
119 if( hStoppedEvent!=NULL ){
120 CloseHandle(hStoppedEvent);
121 p->hStoppedEvent = NULL;
122 }
123 if( zStopper!=0 ){
124 fossil_free(p->zStopper);
125 p->zStopper = 0;
126 }
127 fossil_free(p);
128 }
129 }
130
131 /*
132 ** Process a single incoming HTTP request.
133 */
134 static void win32_http_request(void *pAppData){
@@ -163,11 +218,11 @@
218 if( in ) fclose(in);
219 closesocket(p->s);
220 file_delete(zRequestFName);
221 file_delete(zReplyFName);
222 file_delete(zCmdFName);
223 fossil_free(p);
224 }
225
226 /*
227 ** Process a single incoming SCGI request.
228 */
@@ -225,11 +280,11 @@
280 if( out ) fclose(out);
281 if( in ) fclose(in);
282 closesocket(p->s);
283 file_delete(zRequestFName);
284 file_delete(zReplyFName);
285 fossil_free(p);
286 }
287
288
289 /*
290 ** Start a listening socket and process incoming HTTP requests on
@@ -243,19 +298,19 @@
298 const char *zNotFound, /* The --notfound option, or NULL */
299 const char *zFileGlob, /* The --fileglob option, or NULL */
300 const char *zIpAddr, /* Bind to this IP address, if not NULL */
301 int flags /* One or more HTTP_SERVER_ flags */
302 ){
303 HANDLE hStoppedEvent;
304 WSADATA wd;
305 SOCKET s = INVALID_SOCKET;
306 SOCKADDR_IN addr;
307 int idCnt = 0;
308 int iPort = mnPort;
309 Blob options;
310 wchar_t zTmpPath[MAX_PATH];
311
 
312 blob_zero(&options);
313 if( zBaseUrl ){
314 blob_appendf(&options, " --baseurl %s", zBaseUrl);
315 }
316 if( zNotFound ){
@@ -324,17 +379,35 @@
379 zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
380 fossil_print("Launch webbrowser: %s\n", zBrowser);
381 fossil_system(zBrowser);
382 }
383 fossil_print("Type Ctrl-C to stop the HTTP server\n");
384 /* Create an event used to signal when this server is exiting. */
385 hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
386 assert( hStoppedEvent!=NULL );
387 /* If there is a stopper file name, start the dedicated thread now.
388 ** It will attempt to close the listener socket within 1 second of
389 ** the stopper file being created. */
390 if( zStopper ){
391 HttpServer *pServer = fossil_malloc(sizeof(HttpServer));
392 memset(pServer, 0, sizeof(HttpServer));
393 DuplicateHandle(GetCurrentProcess(), hStoppedEvent,
394 GetCurrentProcess(), &pServer->hStoppedEvent,
395 0, FALSE, DUPLICATE_SAME_ACCESS);
396 assert( pServer->hStoppedEvent!=NULL );
397 pServer->zStopper = fossil_strdup(zStopper);
398 pServer->listener = s;
399 file_delete(zStopper);
400 _beginthread(win32_server_stopper, 0, (void*)pServer);
401 }
402 /* Set the service status to running and pass the listener socket to the
403 ** service handling procedures. */
404 win32_http_service_running(s);
405 for(;;){
406 SOCKET client;
407 SOCKADDR_IN client_addr;
408 HttpRequest *pRequest;
409 int len = sizeof(client_addr);
410 int wsaError;
411
412 client = accept(s, (struct sockaddr*)&client_addr, &len);
413 if( client==INVALID_SOCKET ){
@@ -347,27 +420,27 @@
420 }else{
421 closesocket(s);
422 WSACleanup();
423 fossil_fatal("error from accept()");
424 }
425 }
426 pRequest = fossil_malloc(sizeof(HttpRequest));
427 pRequest->id = ++idCnt;
428 pRequest->s = client;
429 pRequest->addr = client_addr;
430 pRequest->flags = flags;
431 pRequest->zOptions = blob_str(&options);
 
 
432 if( flags & HTTP_SERVER_SCGI ){
433 _beginthread(win32_scgi_request, 0, (void*)pRequest);
434 }else{
435 _beginthread(win32_http_request, 0, (void*)pRequest);
436 }
437 }
438 closesocket(s);
439 WSACleanup();
440 SetEvent(hStoppedEvent);
441 CloseHandle(hStoppedEvent);
442 }
443
444 /*
445 ** The HttpService structure is used to pass information to the service main
446 ** function and to the service control handler function.
447
+55 -17
--- src/zip.c
+++ src/zip.c
@@ -350,29 +350,67 @@
350350
}
351351
nPrefix = blob_size(&filename);
352352
353353
pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
354354
if( pManifest ){
355
- char *zName;
355
+ int flg, eflg = 0;
356
+ char *zName = 0;
356357
zip_set_timedate(pManifest->rDate);
357
- if( (pInclude==0 || glob_match(pInclude, "manifest"))
358
- && !glob_match(pExclude, "manifest")
359
- && db_get_boolean("manifest", 0)
360
- ){
361
- blob_append(&filename, "manifest", -1);
362
- zName = blob_str(&filename);
363
- zip_add_folders(zName);
364
- sha1sum_blob(&mfile, &hash);
365
- sterilize_manifest(&mfile);
366
- zip_add_file(zName, &mfile, 0);
358
+ flg = db_get_manifest_setting();
359
+ if( flg ){
360
+ /* eflg is the effective flags, taking include/exclude into account */
361
+ if( (pInclude==0 || glob_match(pInclude, "manifest"))
362
+ && !glob_match(pExclude, "manifest")
363
+ && (flg & MFESTFLG_RAW) ){
364
+ eflg |= MFESTFLG_RAW;
365
+ }
366
+ if( (pInclude==0 || glob_match(pInclude, "manifest.uuid"))
367
+ && !glob_match(pExclude, "manifest.uuid")
368
+ && (flg & MFESTFLG_UUID) ){
369
+ eflg |= MFESTFLG_UUID;
370
+ }
371
+ if( (pInclude==0 || glob_match(pInclude, "manifest.tags"))
372
+ && !glob_match(pExclude, "manifest.tags")
373
+ && (flg & MFESTFLG_TAGS) ){
374
+ eflg |= MFESTFLG_TAGS;
375
+ }
376
+
377
+ if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
378
+ if( eflg & MFESTFLG_RAW ){
379
+ blob_append(&filename, "manifest", -1);
380
+ zName = blob_str(&filename);
381
+ zip_add_folders(zName);
382
+ }
383
+ if( eflg & MFESTFLG_UUID ){
384
+ sha1sum_blob(&mfile, &hash);
385
+ }
386
+ if( eflg & MFESTFLG_RAW ){
387
+ sterilize_manifest(&mfile);
388
+ zip_add_file(zName, &mfile, 0);
389
+ }
390
+ }
367391
blob_reset(&mfile);
368
- blob_append(&hash, "\n", 1);
369
- blob_resize(&filename, nPrefix);
370
- blob_append(&filename, "manifest.uuid", -1);
371
- zName = blob_str(&filename);
372
- zip_add_file(zName, &hash, 0);
373
- blob_reset(&hash);
392
+ if( eflg & MFESTFLG_UUID ){
393
+ blob_append(&hash, "\n", 1);
394
+ blob_resize(&filename, nPrefix);
395
+ blob_append(&filename, "manifest.uuid", -1);
396
+ zName = blob_str(&filename);
397
+ zip_add_folders(zName);
398
+ zip_add_file(zName, &hash, 0);
399
+ blob_reset(&hash);
400
+ }
401
+ if( eflg & MFESTFLG_TAGS ){
402
+ Blob tagslist;
403
+ blob_zero(&tagslist);
404
+ get_checkin_taglist(rid, &tagslist);
405
+ blob_resize(&filename, nPrefix);
406
+ blob_append(&filename, "manifest.tags", -1);
407
+ zName = blob_str(&filename);
408
+ zip_add_folders(zName);
409
+ zip_add_file(zName, &tagslist, 0);
410
+ blob_reset(&tagslist);
411
+ }
374412
}
375413
manifest_file_rewind(pManifest);
376414
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
377415
int fid;
378416
if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
379417
--- src/zip.c
+++ src/zip.c
@@ -350,29 +350,67 @@
350 }
351 nPrefix = blob_size(&filename);
352
353 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
354 if( pManifest ){
355 char *zName;
 
356 zip_set_timedate(pManifest->rDate);
357 if( (pInclude==0 || glob_match(pInclude, "manifest"))
358 && !glob_match(pExclude, "manifest")
359 && db_get_boolean("manifest", 0)
360 ){
361 blob_append(&filename, "manifest", -1);
362 zName = blob_str(&filename);
363 zip_add_folders(zName);
364 sha1sum_blob(&mfile, &hash);
365 sterilize_manifest(&mfile);
366 zip_add_file(zName, &mfile, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367 blob_reset(&mfile);
368 blob_append(&hash, "\n", 1);
369 blob_resize(&filename, nPrefix);
370 blob_append(&filename, "manifest.uuid", -1);
371 zName = blob_str(&filename);
372 zip_add_file(zName, &hash, 0);
373 blob_reset(&hash);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374 }
375 manifest_file_rewind(pManifest);
376 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
377 int fid;
378 if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
379
--- src/zip.c
+++ src/zip.c
@@ -350,29 +350,67 @@
350 }
351 nPrefix = blob_size(&filename);
352
353 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
354 if( pManifest ){
355 int flg, eflg = 0;
356 char *zName = 0;
357 zip_set_timedate(pManifest->rDate);
358 flg = db_get_manifest_setting();
359 if( flg ){
360 /* eflg is the effective flags, taking include/exclude into account */
361 if( (pInclude==0 || glob_match(pInclude, "manifest"))
362 && !glob_match(pExclude, "manifest")
363 && (flg & MFESTFLG_RAW) ){
364 eflg |= MFESTFLG_RAW;
365 }
366 if( (pInclude==0 || glob_match(pInclude, "manifest.uuid"))
367 && !glob_match(pExclude, "manifest.uuid")
368 && (flg & MFESTFLG_UUID) ){
369 eflg |= MFESTFLG_UUID;
370 }
371 if( (pInclude==0 || glob_match(pInclude, "manifest.tags"))
372 && !glob_match(pExclude, "manifest.tags")
373 && (flg & MFESTFLG_TAGS) ){
374 eflg |= MFESTFLG_TAGS;
375 }
376
377 if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
378 if( eflg & MFESTFLG_RAW ){
379 blob_append(&filename, "manifest", -1);
380 zName = blob_str(&filename);
381 zip_add_folders(zName);
382 }
383 if( eflg & MFESTFLG_UUID ){
384 sha1sum_blob(&mfile, &hash);
385 }
386 if( eflg & MFESTFLG_RAW ){
387 sterilize_manifest(&mfile);
388 zip_add_file(zName, &mfile, 0);
389 }
390 }
391 blob_reset(&mfile);
392 if( eflg & MFESTFLG_UUID ){
393 blob_append(&hash, "\n", 1);
394 blob_resize(&filename, nPrefix);
395 blob_append(&filename, "manifest.uuid", -1);
396 zName = blob_str(&filename);
397 zip_add_folders(zName);
398 zip_add_file(zName, &hash, 0);
399 blob_reset(&hash);
400 }
401 if( eflg & MFESTFLG_TAGS ){
402 Blob tagslist;
403 blob_zero(&tagslist);
404 get_checkin_taglist(rid, &tagslist);
405 blob_resize(&filename, nPrefix);
406 blob_append(&filename, "manifest.tags", -1);
407 zName = blob_str(&filename);
408 zip_add_folders(zName);
409 zip_add_file(zName, &tagslist, 0);
410 blob_reset(&tagslist);
411 }
412 }
413 manifest_file_rewind(pManifest);
414 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
415 int fid;
416 if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
417
+12 -3
--- test/delta1.test
+++ test/delta1.test
@@ -34,18 +34,27 @@
3434
set f1 [read_file $f]
3535
write_file t1 $f1
3636
for {set i 0} {$i<100} {incr i} {
3737
write_file t2 [random_changes $f1 1 1 0 0.1]
3838
fossil test-delta t1 t2
39
- test delta-$base-$i-1 {$RESULT=="ok"}
39
+ test delta-$base-$i-1 {[normalize_result]=="ok"}
4040
write_file t2 [random_changes $f1 1 1 0 0.2]
4141
fossil test-delta t1 t2
42
- test delta-$base-$i-2 {$RESULT=="ok"}
42
+ test delta-$base-$i-2 {[normalize_result]=="ok"}
4343
write_file t2 [random_changes $f1 1 1 0 0.4]
4444
fossil test-delta t1 t2
45
- test delta-$base-$i-3 {$RESULT=="ok"}
45
+ test delta-$base-$i-3 {[normalize_result]=="ok"}
4646
}
4747
}
4848
49
+set empties { "" "" "" a a "" }
50
+set i 0
51
+foreach {f1 f2} $empties {
52
+ incr i
53
+ write_file t1 $f1
54
+ write_file t2 $f2
55
+ fossil test-delta t1 t2
56
+ test delta-empty-$i {[normalize_result]=="ok"}
57
+}
4958
###############################################################################
5059
5160
test_cleanup
5261
5362
ADDED test/fake-editor.tcl
--- test/delta1.test
+++ test/delta1.test
@@ -34,18 +34,27 @@
34 set f1 [read_file $f]
35 write_file t1 $f1
36 for {set i 0} {$i<100} {incr i} {
37 write_file t2 [random_changes $f1 1 1 0 0.1]
38 fossil test-delta t1 t2
39 test delta-$base-$i-1 {$RESULT=="ok"}
40 write_file t2 [random_changes $f1 1 1 0 0.2]
41 fossil test-delta t1 t2
42 test delta-$base-$i-2 {$RESULT=="ok"}
43 write_file t2 [random_changes $f1 1 1 0 0.4]
44 fossil test-delta t1 t2
45 test delta-$base-$i-3 {$RESULT=="ok"}
46 }
47 }
48
 
 
 
 
 
 
 
 
 
49 ###############################################################################
50
51 test_cleanup
52
53 DDED test/fake-editor.tcl
--- test/delta1.test
+++ test/delta1.test
@@ -34,18 +34,27 @@
34 set f1 [read_file $f]
35 write_file t1 $f1
36 for {set i 0} {$i<100} {incr i} {
37 write_file t2 [random_changes $f1 1 1 0 0.1]
38 fossil test-delta t1 t2
39 test delta-$base-$i-1 {[normalize_result]=="ok"}
40 write_file t2 [random_changes $f1 1 1 0 0.2]
41 fossil test-delta t1 t2
42 test delta-$base-$i-2 {[normalize_result]=="ok"}
43 write_file t2 [random_changes $f1 1 1 0 0.4]
44 fossil test-delta t1 t2
45 test delta-$base-$i-3 {[normalize_result]=="ok"}
46 }
47 }
48
49 set empties { "" "" "" a a "" }
50 set i 0
51 foreach {f1 f2} $empties {
52 incr i
53 write_file t1 $f1
54 write_file t2 $f2
55 fossil test-delta t1 t2
56 test delta-empty-$i {[normalize_result]=="ok"}
57 }
58 ###############################################################################
59
60 test_cleanup
61
62 DDED test/fake-editor.tcl
--- a/test/fake-editor.tcl
+++ b/test/fake-editor.tcl
@@ -0,0 +1,2 @@
1
+#
2
+# Copyright (
--- a/test/fake-editor.tcl
+++ b/test/fake-editor.tcl
@@ -0,0 +1,2 @@
 
 
--- a/test/fake-editor.tcl
+++ b/test/fake-editor.tcl
@@ -0,0 +1,2 @@
1 #
2 # Copyright (
+1 -1
--- test/json.test
+++ test/json.test
@@ -23,11 +23,11 @@
2323
# practice of eliminating all trace of the fossil json command when
2424
# not configured. If that changes, these conditions might not prevent
2525
# the rest of this file from running.
2626
fossil test-th-eval "hasfeature json"
2727
28
-if {$::RESULT ne "1"} then {
28
+if {[normalize_result] ne "1"} then {
2929
puts "Fossil was not compiled with JSON support."
3030
test_cleanup_then_return
3131
}
3232
3333
# We need a JSON parser to effectively test the JSON produced by
3434
--- test/json.test
+++ test/json.test
@@ -23,11 +23,11 @@
23 # practice of eliminating all trace of the fossil json command when
24 # not configured. If that changes, these conditions might not prevent
25 # the rest of this file from running.
26 fossil test-th-eval "hasfeature json"
27
28 if {$::RESULT ne "1"} then {
29 puts "Fossil was not compiled with JSON support."
30 test_cleanup_then_return
31 }
32
33 # We need a JSON parser to effectively test the JSON produced by
34
--- test/json.test
+++ test/json.test
@@ -23,11 +23,11 @@
23 # practice of eliminating all trace of the fossil json command when
24 # not configured. If that changes, these conditions might not prevent
25 # the rest of this file from running.
26 fossil test-th-eval "hasfeature json"
27
28 if {[normalize_result] ne "1"} then {
29 puts "Fossil was not compiled with JSON support."
30 test_cleanup_then_return
31 }
32
33 # We need a JSON parser to effectively test the JSON produced by
34
--- test/mv-rm.test
+++ test/mv-rm.test
@@ -15,10 +15,12 @@
1515
#
1616
############################################################################
1717
#
1818
# MV / RM Commands
1919
#
20
+
21
+set path [file dirname [info script]]
2022
2123
require_no_open_checkout
2224
2325
########################################
2426
# Setup: Add Files and Commit #
2527
2628
ADDED test/set-manifest.test
--- test/mv-rm.test
+++ test/mv-rm.test
@@ -15,10 +15,12 @@
15 #
16 ############################################################################
17 #
18 # MV / RM Commands
19 #
 
 
20
21 require_no_open_checkout
22
23 ########################################
24 # Setup: Add Files and Commit #
25
26 DDED test/set-manifest.test
--- test/mv-rm.test
+++ test/mv-rm.test
@@ -15,10 +15,12 @@
15 #
16 ############################################################################
17 #
18 # MV / RM Commands
19 #
20
21 set path [file dirname [info script]]
22
23 require_no_open_checkout
24
25 ########################################
26 # Setup: Add Files and Commit #
27
28 DDED test/set-manifest.test
--- a/test/set-manifest.test
+++ b/test/set-manifest.test
@@ -0,0 +1,113 @@
1
+#
2
+# Copyright (c) 2016 D. Richard Hipp
3
+#
4
+# This program is free software; you can redistribute it and/or
5
+# modify it under the terms of the Simplified BSD License (also
6
+# known as the "2-Clause License" or "FreeBSD License".)
7
+#
8
+# This program is distributed in the hope that it will be useful,
9
+# but without any warranty; without even the implied warranty of
10
+# merchantability or fitness for a particular purpose.
11
+#
12
+# Author contact information:
13
+# [email protected]
14
+# http://www.hwaci.com/drh/
15
+#
16
+############################################################################
17
+#
18
+# Test manifest setting
19
+#
20
+
21
+t (c) 2016 D. Richard Hipp
22
+#
23
+# This program is free software; you can redistribute it and/or
24
+# modify it under the terms of the Simplified BSD License (also
25
+# known as the "2-Clause License" or "FreeBSD License".)
26
+#
27
+# T#
28
+# Copyright (c) 20
29
+
30
+proc file_contains {fname match} {
31
+ set fp [open $fname r]
32
+ set contents [read $fp]
33
+ close $fp
34
+ set lines [split $contents "\n"]
35
+ foreach line $lines {
36
+ if {[regexp $match $line]} {
37
+ return 1
38
+ }
39
+ }
40
+ return 0
41
+}
42
+
43
+# We need SHA1 to effectively test the manifest files produced by
44
+# fossil. It looks like the one from tcllib is exactly what we need.
45
+# On ActiveTcl, add it with teacup. On other platforms, YMMV.
46
+# teacup install sha1
47
+if {[catch {package require sha1}] != 0} then {
48
+ puts "The \"sha1\" package is not available."
49
+ test_cleanup_then_return
50
+}
51
+
52
+# We need a respository, so let it have one.
53
+test_setup
54
+
55
+#### Verify classic behavior of the manifest setting
56
+
57
+# Setting is off by default, and there are no extra files.
58
+fossil settings manifest
59
+test "set-manifest-1" {[regexp {^manifest *$} $RESULT]}
60
+set filelist [$v" {$RESULT eq ""}
61
+ fossi D. Richard Hipp
62
+#
63
+# This program is free software; you can redistribute it and/or
64
+# modify it under the terms of the Simplified BSD License (also
65
+# known as the "2-Clause License" or "FreeBSD License".)
66
+#
67
+# This program is distributed in the hope that it will be useful,
68
+# buithout any warranty; without even the implied warranty of
69
+# mer#
70
+# Copyright manifes$ckid eq $uuid} foreach f $filelist {
71
+ test "set-manifest-2-$v-f-$f" {[file isfile $f]}
72
+ }
73
+}
74
+
75
+# ... and manifest.uuid is the checkout's hash
76
+fossil info
77
+regexp {(?m)^checkout:\s+([0-9a-f]{40,64})\s.*$} $RESULT ckoutline ckid
78
+set uuid [string trim [read_file "manifest.uuid"]]
79
+test "set-manifest-2-uuid" {[same_uuid $ckid $uuid]}
80
+
81
+
82
+# ... which is also the SHA1 of the file "manifest" before it was
83
+#License" or "FreeBSD License0
84
+
85
+proc file_contains {fname match}e "manifest"] "" ma2-manifest" {$muuid eq $uuidequire sha1}] != 0} then close $fp
86
+ set lines [split $contents "\n"]
87
+ foreach line $lines {
88
+ if {[regexp $match $line]} {
89
+ return 1
90
+ }
91
+ }
92
+ return 0
93
+}
94
+
95
+# We need SHA1 to effectively test the manifest files produced by
96
+# fossil. It looks like the one from tcllib is exactly what we need.
97
+# On ActiveTcl, add it with teacup. On other platforms, YMMV.
98
+# teacup install sha1
99
+if {[catch {package require sha1}] != 0} then {
100
+ puts "The \"sha1\" package is not available."
101
+ test_cleanup_then_return
102
+}
103
+
104
+# We need a respository, so let it have one.
105
+test_setup
106
+
107
+#### Verify classic behavior of the manifest setting
108
+
109
+# Setting is off by default, and there are no extra files.
110
+fossil settings manifest
111
+test "set-manifest-1" {[regexp {^manifest *$} $RESULT]}
112
+set filelist [$v" {$RESULT eq ""}
113
+ fossi D. R
--- a/test/set-manifest.test
+++ b/test/set-manifest.test
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/set-manifest.test
+++ b/test/set-manifest.test
@@ -0,0 +1,113 @@
1 #
2 # Copyright (c) 2016 D. Richard Hipp
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the Simplified BSD License (also
6 # known as the "2-Clause License" or "FreeBSD License".)
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but without any warranty; without even the implied warranty of
10 # merchantability or fitness for a particular purpose.
11 #
12 # Author contact information:
13 # [email protected]
14 # http://www.hwaci.com/drh/
15 #
16 ############################################################################
17 #
18 # Test manifest setting
19 #
20
21 t (c) 2016 D. Richard Hipp
22 #
23 # This program is free software; you can redistribute it and/or
24 # modify it under the terms of the Simplified BSD License (also
25 # known as the "2-Clause License" or "FreeBSD License".)
26 #
27 # T#
28 # Copyright (c) 20
29
30 proc file_contains {fname match} {
31 set fp [open $fname r]
32 set contents [read $fp]
33 close $fp
34 set lines [split $contents "\n"]
35 foreach line $lines {
36 if {[regexp $match $line]} {
37 return 1
38 }
39 }
40 return 0
41 }
42
43 # We need SHA1 to effectively test the manifest files produced by
44 # fossil. It looks like the one from tcllib is exactly what we need.
45 # On ActiveTcl, add it with teacup. On other platforms, YMMV.
46 # teacup install sha1
47 if {[catch {package require sha1}] != 0} then {
48 puts "The \"sha1\" package is not available."
49 test_cleanup_then_return
50 }
51
52 # We need a respository, so let it have one.
53 test_setup
54
55 #### Verify classic behavior of the manifest setting
56
57 # Setting is off by default, and there are no extra files.
58 fossil settings manifest
59 test "set-manifest-1" {[regexp {^manifest *$} $RESULT]}
60 set filelist [$v" {$RESULT eq ""}
61 fossi D. Richard Hipp
62 #
63 # This program is free software; you can redistribute it and/or
64 # modify it under the terms of the Simplified BSD License (also
65 # known as the "2-Clause License" or "FreeBSD License".)
66 #
67 # This program is distributed in the hope that it will be useful,
68 # buithout any warranty; without even the implied warranty of
69 # mer#
70 # Copyright manifes$ckid eq $uuid} foreach f $filelist {
71 test "set-manifest-2-$v-f-$f" {[file isfile $f]}
72 }
73 }
74
75 # ... and manifest.uuid is the checkout's hash
76 fossil info
77 regexp {(?m)^checkout:\s+([0-9a-f]{40,64})\s.*$} $RESULT ckoutline ckid
78 set uuid [string trim [read_file "manifest.uuid"]]
79 test "set-manifest-2-uuid" {[same_uuid $ckid $uuid]}
80
81
82 # ... which is also the SHA1 of the file "manifest" before it was
83 #License" or "FreeBSD License0
84
85 proc file_contains {fname match}e "manifest"] "" ma2-manifest" {$muuid eq $uuidequire sha1}] != 0} then close $fp
86 set lines [split $contents "\n"]
87 foreach line $lines {
88 if {[regexp $match $line]} {
89 return 1
90 }
91 }
92 return 0
93 }
94
95 # We need SHA1 to effectively test the manifest files produced by
96 # fossil. It looks like the one from tcllib is exactly what we need.
97 # On ActiveTcl, add it with teacup. On other platforms, YMMV.
98 # teacup install sha1
99 if {[catch {package require sha1}] != 0} then {
100 puts "The \"sha1\" package is not available."
101 test_cleanup_then_return
102 }
103
104 # We need a respository, so let it have one.
105 test_setup
106
107 #### Verify classic behavior of the manifest setting
108
109 # Setting is off by default, and there are no extra files.
110 fossil settings manifest
111 test "set-manifest-1" {[regexp {^manifest *$} $RESULT]}
112 set filelist [$v" {$RESULT eq ""}
113 fossi D. R
--- test/settings-repo.test
+++ test/settings-repo.test
@@ -16,12 +16,15 @@
1616
############################################################################
1717
#
1818
# The "settings" and "unset" commands that may modify the repository.
1919
#
2020
21
+set path [file dirname [info script]]
22
+
2123
require_no_open_checkout
22
-set dir [file dirname [info script]]; test_setup
24
+
25
+test_setup
2326
2427
###############################################################################
2528
#
2629
# Complete syntax as tested:
2730
#
2831
--- test/settings-repo.test
+++ test/settings-repo.test
@@ -16,12 +16,15 @@
16 ############################################################################
17 #
18 # The "settings" and "unset" commands that may modify the repository.
19 #
20
 
 
21 require_no_open_checkout
22 set dir [file dirname [info script]]; test_setup
 
23
24 ###############################################################################
25 #
26 # Complete syntax as tested:
27 #
28
--- test/settings-repo.test
+++ test/settings-repo.test
@@ -16,12 +16,15 @@
16 ############################################################################
17 #
18 # The "settings" and "unset" commands that may modify the repository.
19 #
20
21 set path [file dirname [info script]]
22
23 require_no_open_checkout
24
25 test_setup
26
27 ###############################################################################
28 #
29 # Complete syntax as tested:
30 #
31
--- test/settings.test
+++ test/settings.test
@@ -16,11 +16,11 @@
1616
############################################################################
1717
#
1818
# The "settings" and "unset" commands.
1919
#
2020
21
-set dir [file dirname [info script]]; test_setup
21
+set path [file dirname [info script]]; test_setup
2222
2323
###############################################################################
2424
#
2525
# Complete syntax as tested:
2626
#
2727
2828
ADDED test/symlinks.test
--- test/settings.test
+++ test/settings.test
@@ -16,11 +16,11 @@
16 ############################################################################
17 #
18 # The "settings" and "unset" commands.
19 #
20
21 set dir [file dirname [info script]]; test_setup
22
23 ###############################################################################
24 #
25 # Complete syntax as tested:
26 #
27
28 DDED test/symlinks.test
--- test/settings.test
+++ test/settings.test
@@ -16,11 +16,11 @@
16 ############################################################################
17 #
18 # The "settings" and "unset" commands.
19 #
20
21 set path [file dirname [info script]]; test_setup
22
23 ###############################################################################
24 #
25 # Complete syntax as tested:
26 #
27
28 DDED test/symlinks.test
--- a/test/symlinks.test
+++ b/test/symlinks.test
@@ -0,0 +1,68 @@
1
+#
2
+# Copyright (c) 2016 D. Richard Hipp
3
+#
4
+# This program is free software; you can redistribute it and/or
5
+# modify it under the terms of the Simplified BSD License (also
6
+# known as the "2-Clause License" or "FreeBSD License".)
7
+#
8
+# This program is distributed in the hope that it will be useful,
9
+# but without any warranty; without even the implied warranty of
10
+# merchantability or fitness for a particular purpose.
11
+#
12
+# Author contact information:
13
+# [email protected]
14
+# http://www.hwaci.com/drh/
15
+#
16
+############################################################################
17
+#
18
+# Symbolic link tests.
19
+#
20
+
21
+set path [file dirname [info script]]
22
+
23
+if {$tcl_platform(platform) eq "windows"allow
24
+puts $RESULTmlinks are not supported on Windows."
25
+ test_cleanup_then_returnon
26
+
27
+fossil test-th-eval --open-con"setting allow-symlinks"
28
+
29
+itory [normalize_result]
30
+
31
+if {[string length $repository] == 0} {
32
+ puts "Detection of the open repository file failed."
33
+ test_cleanup_then_return
34
+}
35
+
36
+#######################################
37
+# Use symbolic link to a directory... #
38
+##############fossil commit -m "c1"_then_returnon
39
+
40
+fossil test-th-eval --open-con"setting allow-symlinks"
41
+
42
+itory [normalize_rght (c) 2016 D. Rich#
43
+# Copyright up_then_returnon
44
+
45
+fossil test-th-eval --open-con"setting allow-symlinks"
46
+
47
+itory [normalize_result]
48
+
49
+if {[string length $repository] == 0} {
50
+ puts "Detection of the open repository file failed."
51
+ test_cleanup_then_return
52
+}
53
+
54
+#######################################
55
+# Use symbolic link to a directory... #
56
+#######################################
57
+
58
+file mkdir [file join $rootDir subdirA]
59
+exec ln -s [file join $rootDir subdirA] symdirA
60
+
61
+###############################################################################
62
+
63
+write_file [file join $rootDir subdirA f1.txt] "f1"
64
+write_file [file join $rootDir subdirA f2.txt] "f2"
65
+
66
+test symlinks-dir-1 {[file exists [file join $rootDir subdirA f1.txt]] eq 1}
67
+test symlinks-dir-2 {[file exists [file join $rootDir symdirA f1.txt]] eq 1}
68
+test symlinks-di
--- a/test/symlinks.test
+++ b/test/symlinks.test
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/symlinks.test
+++ b/test/symlinks.test
@@ -0,0 +1,68 @@
1 #
2 # Copyright (c) 2016 D. Richard Hipp
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the Simplified BSD License (also
6 # known as the "2-Clause License" or "FreeBSD License".)
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but without any warranty; without even the implied warranty of
10 # merchantability or fitness for a particular purpose.
11 #
12 # Author contact information:
13 # [email protected]
14 # http://www.hwaci.com/drh/
15 #
16 ############################################################################
17 #
18 # Symbolic link tests.
19 #
20
21 set path [file dirname [info script]]
22
23 if {$tcl_platform(platform) eq "windows"allow
24 puts $RESULTmlinks are not supported on Windows."
25 test_cleanup_then_returnon
26
27 fossil test-th-eval --open-con"setting allow-symlinks"
28
29 itory [normalize_result]
30
31 if {[string length $repository] == 0} {
32 puts "Detection of the open repository file failed."
33 test_cleanup_then_return
34 }
35
36 #######################################
37 # Use symbolic link to a directory... #
38 ##############fossil commit -m "c1"_then_returnon
39
40 fossil test-th-eval --open-con"setting allow-symlinks"
41
42 itory [normalize_rght (c) 2016 D. Rich#
43 # Copyright up_then_returnon
44
45 fossil test-th-eval --open-con"setting allow-symlinks"
46
47 itory [normalize_result]
48
49 if {[string length $repository] == 0} {
50 puts "Detection of the open repository file failed."
51 test_cleanup_then_return
52 }
53
54 #######################################
55 # Use symbolic link to a directory... #
56 #######################################
57
58 file mkdir [file join $rootDir subdirA]
59 exec ln -s [file join $rootDir subdirA] symdirA
60
61 ###############################################################################
62
63 write_file [file join $rootDir subdirA f1.txt] "f1"
64 write_file [file join $rootDir subdirA f2.txt] "f2"
65
66 test symlinks-dir-1 {[file exists [file join $rootDir subdirA f1.txt]] eq 1}
67 test symlinks-dir-2 {[file exists [file join $rootDir symdirA f1.txt]] eq 1}
68 test symlinks-di
+107 -18
--- test/tester.tcl
+++ test/tester.tcl
@@ -136,13 +136,20 @@
136136
#
137137
proc fossil_maybe_answer {answer args} {
138138
global fossilexe
139139
set cmd $fossilexe
140140
set expectError 0
141
- if {[lindex $args end] eq "-expectError"} {
141
+ set index [lsearch -exact $args -expectError]
142
+ if {$index != -1} {
142143
set expectError 1
143
- set args [lrange $args 0 end-1]
144
+ set args [lreplace $args $index $index]
145
+ }
146
+ set keepNewline 0
147
+ set index [lsearch -exact $args -keepNewline]
148
+ if {$index != -1} {
149
+ set keepNewline 1
150
+ set args [lreplace $args $index $index]
144151
}
145152
foreach a $args {
146153
lappend cmd $a
147154
}
148155
protOut $cmd
@@ -150,14 +157,22 @@
150157
flush stdout
151158
if {[string length $answer] > 0} {
152159
protOut $answer
153160
set prompt_file [file join $::tempPath fossil_prompt_answer]
154161
write_file $prompt_file $answer\n
155
- set rc [catch {eval exec $cmd <$prompt_file} result]
162
+ if {$keepNewline} {
163
+ set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result]
164
+ } else {
165
+ set rc [catch {eval exec $cmd <$prompt_file} result]
166
+ }
156167
file delete $prompt_file
157168
} else {
158
- set rc [catch {eval exec $cmd} result]
169
+ if {$keepNewline} {
170
+ set rc [catch {eval exec -keepnewline $cmd} result]
171
+ } else {
172
+ set rc [catch {eval exec $cmd} result]
173
+ }
159174
}
160175
global RESULT CODE
161176
set CODE $rc
162177
if {($rc && !$expectError) || (!$rc && $expectError)} {
163178
protOut "ERROR: $result" 1
@@ -210,11 +225,11 @@
210225
th1-setup \
211226
th1-uri-regexp]
212227
213228
fossil test-th-eval "hasfeature tcl"
214229
215
- if {$::RESULT eq "1"} {
230
+ if {[normalize_result] eq "1"} {
216231
lappend result tcl-setup
217232
}
218233
219234
return [lsort -dictionary $result]
220235
}
@@ -275,29 +290,29 @@
275290
uv-sync \
276291
web-browser]
277292
278293
fossil test-th-eval "hasfeature legacyMvRm"
279294
280
- if {$::RESULT eq "1"} {
295
+ if {[normalize_result] eq "1"} {
281296
lappend result mv-rm-files
282297
}
283298
284299
fossil test-th-eval "hasfeature tcl"
285300
286
- if {$::RESULT eq "1"} {
301
+ if {[normalize_result] eq "1"} {
287302
lappend result tcl tcl-setup
288303
}
289304
290305
fossil test-th-eval "hasfeature th1Docs"
291306
292
- if {$::RESULT eq "1"} {
307
+ if {[normalize_result] eq "1"} {
293308
lappend result th1-docs
294309
}
295310
296311
fossil test-th-eval "hasfeature th1Hooks"
297312
298
- if {$::RESULT eq "1"} {
313
+ if {[normalize_result] eq "1"} {
299314
lappend result th1-hooks
300315
}
301316
302317
return [lsort -dictionary $result]
303318
}
@@ -440,27 +455,27 @@
440455
441456
# This procedure only returns non-zero if the Tcl integration feature was
442457
# enabled at compile-time and is now enabled at runtime.
443458
proc is_tcl_usable_by_fossil {} {
444459
fossil test-th-eval "hasfeature tcl"
445
- if {$::RESULT ne "1"} {return 0}
460
+ if {[normalize_result] ne "1"} {return 0}
446461
fossil test-th-eval "setting tcl"
447
- if {$::RESULT eq "1"} {return 1}
462
+ if {[normalize_result] eq "1"} {return 1}
448463
fossil test-th-eval --open-config "setting tcl"
449
- if {$::RESULT eq "1"} {return 1}
464
+ if {[normalize_result] eq "1"} {return 1}
450465
return [info exists ::env(TH1_ENABLE_TCL)]
451466
}
452467
453468
# This procedure only returns non-zero if the TH1 hooks feature was enabled
454469
# at compile-time and is now enabled at runtime.
455470
proc are_th1_hooks_usable_by_fossil {} {
456471
fossil test-th-eval "hasfeature th1Hooks"
457
- if {$::RESULT ne "1"} {return 0}
472
+ if {[normalize_result] ne "1"} {return 0}
458473
fossil test-th-eval "setting th1-hooks"
459
- if {$::RESULT eq "1"} {return 1}
474
+ if {[normalize_result] eq "1"} {return 1}
460475
fossil test-th-eval --open-config "setting th1-hooks"
461
- if {$::RESULT eq "1"} {return 1}
476
+ if {[normalize_result] eq "1"} {return 1}
462477
return [info exists ::env(TH1_ENABLE_HOOKS)]
463478
}
464479
465480
# This (rarely used) procedure is designed to run a test within the Fossil
466481
# source checkout (e.g. one that does NOT modify any state), while saving
@@ -560,14 +575,14 @@
560575
# NOTE: Check if we can use any of the environment variables.
561576
#
562577
foreach name $names {
563578
set value [getEnvironmentVariable $name]
564579
565
- if {[string length $value] > 0} then {
580
+ if {[string length $value] > 0} {
566581
set value [file normalize $value]
567582
568
- if {[file exists $value] && [file isdirectory $value]} then {
583
+ if {[file exists $value] && [file isdirectory $value]} {
569584
return $value
570585
}
571586
}
572587
}
573588
@@ -575,11 +590,11 @@
575590
# NOTE: On non-Windows systems, fallback to /tmp if it is usable.
576591
#
577592
if {$::tcl_platform(platform) ne "windows"} {
578593
set value /tmp
579594
580
- if {[file exists $value] && [file isdirectory $value]} then {
595
+ if {[file exists $value] && [file isdirectory $value]} {
581596
return $value
582597
}
583598
}
584599
585600
#
@@ -732,10 +747,84 @@
732747
}
733748
append out \n$line
734749
}
735750
return [string range $out 1 end]
736751
}
752
+
753
+# This procedure executes the "fossil server" command. The return value
754
+# is the new process identifier. The varName argument refers to a variable
755
+# where the "stop argument" is to be stored. This value must eventually be
756
+# passed to the [test_stop_server] procedure.
757
+proc test_start_server { repository {varName ""} } {
758
+ global fossilexe
759
+ set command [list exec $fossilexe server]
760
+ if {[string length $varName] > 0} {
761
+ upvar 1 $varName stopArg
762
+ }
763
+ if {$::tcl_platform(platform) eq "windows"} {
764
+ set stopArg [file join [getTemporaryPath] [appendArgs \
765
+ [string trim [clock seconds] -] _ [getSeqNo] .stopper]]
766
+ lappend command --stopper $stopArg
767
+ }
768
+ lappend command $repository &
769
+ set pid [eval $command]
770
+ if {$::tcl_platform(platform) ne "windows"} {
771
+ set stopArg $pid
772
+ }
773
+ return $pid
774
+}
775
+
776
+# This procedure stops a Fossil server instance that was previously started
777
+# by the [test_start_server] procedure. The value of the "stop argument"
778
+# will vary by platform as will the exact method used to stop the server.
779
+proc test_stop_server { stopArg pid } {
780
+ if {$::tcl_platform(platform) eq "windows"} {
781
+ #
782
+ # NOTE: On Windows, the "stop argument" must be the name of a file
783
+ # that does NOT already exist.
784
+ #
785
+ if {![file exists $stopArg] && \
786
+ [catch {write_file $stopArg [clock seconds]}] == 0} then {
787
+ while {1} {
788
+ if {[catch {
789
+ #
790
+ # NOTE: Using the TaskList utility requires Windows XP or
791
+ # later.
792
+ #
793
+ exec tasklist.exe /FI "PID eq $pid"
794
+ } result] != 0 || ![regexp -- " $pid " $result]} then {
795
+ break
796
+ }
797
+ after 1000; # wait a bit...
798
+ }
799
+ file delete $stopArg
800
+ return true
801
+ }
802
+ } else {
803
+ #
804
+ # NOTE: On Unix, the "stop argument" must be an integer identifier
805
+ # that refers to an existing process.
806
+ #
807
+ if {[regexp {^(?:-)?\d+$} $stopArg] && \
808
+ [catch {exec kill -TERM $stopArg}] == 0} then {
809
+ while {1} {
810
+ if {[catch {
811
+ #
812
+ # TODO: Is this portable to all the supported variants of
813
+ # Unix? It should be, it's POSIX.
814
+ #
815
+ exec ps -p $pid
816
+ } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} then {
817
+ break
818
+ }
819
+ after 1000; # wait a bit...
820
+ }
821
+ return true
822
+ }
823
+ }
824
+ return false
825
+}
737826
738827
# Executes the "fossil http" command. The entire content of the HTTP request
739828
# is read from the data file name, with [subst] being performed on it prior to
740829
# submission. Temporary input and output files are created and deleted. The
741830
# result will be the contents of the temoprary output file.
742831
--- test/tester.tcl
+++ test/tester.tcl
@@ -136,13 +136,20 @@
136 #
137 proc fossil_maybe_answer {answer args} {
138 global fossilexe
139 set cmd $fossilexe
140 set expectError 0
141 if {[lindex $args end] eq "-expectError"} {
 
142 set expectError 1
143 set args [lrange $args 0 end-1]
 
 
 
 
 
 
144 }
145 foreach a $args {
146 lappend cmd $a
147 }
148 protOut $cmd
@@ -150,14 +157,22 @@
150 flush stdout
151 if {[string length $answer] > 0} {
152 protOut $answer
153 set prompt_file [file join $::tempPath fossil_prompt_answer]
154 write_file $prompt_file $answer\n
155 set rc [catch {eval exec $cmd <$prompt_file} result]
 
 
 
 
156 file delete $prompt_file
157 } else {
158 set rc [catch {eval exec $cmd} result]
 
 
 
 
159 }
160 global RESULT CODE
161 set CODE $rc
162 if {($rc && !$expectError) || (!$rc && $expectError)} {
163 protOut "ERROR: $result" 1
@@ -210,11 +225,11 @@
210 th1-setup \
211 th1-uri-regexp]
212
213 fossil test-th-eval "hasfeature tcl"
214
215 if {$::RESULT eq "1"} {
216 lappend result tcl-setup
217 }
218
219 return [lsort -dictionary $result]
220 }
@@ -275,29 +290,29 @@
275 uv-sync \
276 web-browser]
277
278 fossil test-th-eval "hasfeature legacyMvRm"
279
280 if {$::RESULT eq "1"} {
281 lappend result mv-rm-files
282 }
283
284 fossil test-th-eval "hasfeature tcl"
285
286 if {$::RESULT eq "1"} {
287 lappend result tcl tcl-setup
288 }
289
290 fossil test-th-eval "hasfeature th1Docs"
291
292 if {$::RESULT eq "1"} {
293 lappend result th1-docs
294 }
295
296 fossil test-th-eval "hasfeature th1Hooks"
297
298 if {$::RESULT eq "1"} {
299 lappend result th1-hooks
300 }
301
302 return [lsort -dictionary $result]
303 }
@@ -440,27 +455,27 @@
440
441 # This procedure only returns non-zero if the Tcl integration feature was
442 # enabled at compile-time and is now enabled at runtime.
443 proc is_tcl_usable_by_fossil {} {
444 fossil test-th-eval "hasfeature tcl"
445 if {$::RESULT ne "1"} {return 0}
446 fossil test-th-eval "setting tcl"
447 if {$::RESULT eq "1"} {return 1}
448 fossil test-th-eval --open-config "setting tcl"
449 if {$::RESULT eq "1"} {return 1}
450 return [info exists ::env(TH1_ENABLE_TCL)]
451 }
452
453 # This procedure only returns non-zero if the TH1 hooks feature was enabled
454 # at compile-time and is now enabled at runtime.
455 proc are_th1_hooks_usable_by_fossil {} {
456 fossil test-th-eval "hasfeature th1Hooks"
457 if {$::RESULT ne "1"} {return 0}
458 fossil test-th-eval "setting th1-hooks"
459 if {$::RESULT eq "1"} {return 1}
460 fossil test-th-eval --open-config "setting th1-hooks"
461 if {$::RESULT eq "1"} {return 1}
462 return [info exists ::env(TH1_ENABLE_HOOKS)]
463 }
464
465 # This (rarely used) procedure is designed to run a test within the Fossil
466 # source checkout (e.g. one that does NOT modify any state), while saving
@@ -560,14 +575,14 @@
560 # NOTE: Check if we can use any of the environment variables.
561 #
562 foreach name $names {
563 set value [getEnvironmentVariable $name]
564
565 if {[string length $value] > 0} then {
566 set value [file normalize $value]
567
568 if {[file exists $value] && [file isdirectory $value]} then {
569 return $value
570 }
571 }
572 }
573
@@ -575,11 +590,11 @@
575 # NOTE: On non-Windows systems, fallback to /tmp if it is usable.
576 #
577 if {$::tcl_platform(platform) ne "windows"} {
578 set value /tmp
579
580 if {[file exists $value] && [file isdirectory $value]} then {
581 return $value
582 }
583 }
584
585 #
@@ -732,10 +747,84 @@
732 }
733 append out \n$line
734 }
735 return [string range $out 1 end]
736 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
737
738 # Executes the "fossil http" command. The entire content of the HTTP request
739 # is read from the data file name, with [subst] being performed on it prior to
740 # submission. Temporary input and output files are created and deleted. The
741 # result will be the contents of the temoprary output file.
742
--- test/tester.tcl
+++ test/tester.tcl
@@ -136,13 +136,20 @@
136 #
137 proc fossil_maybe_answer {answer args} {
138 global fossilexe
139 set cmd $fossilexe
140 set expectError 0
141 set index [lsearch -exact $args -expectError]
142 if {$index != -1} {
143 set expectError 1
144 set args [lreplace $args $index $index]
145 }
146 set keepNewline 0
147 set index [lsearch -exact $args -keepNewline]
148 if {$index != -1} {
149 set keepNewline 1
150 set args [lreplace $args $index $index]
151 }
152 foreach a $args {
153 lappend cmd $a
154 }
155 protOut $cmd
@@ -150,14 +157,22 @@
157 flush stdout
158 if {[string length $answer] > 0} {
159 protOut $answer
160 set prompt_file [file join $::tempPath fossil_prompt_answer]
161 write_file $prompt_file $answer\n
162 if {$keepNewline} {
163 set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result]
164 } else {
165 set rc [catch {eval exec $cmd <$prompt_file} result]
166 }
167 file delete $prompt_file
168 } else {
169 if {$keepNewline} {
170 set rc [catch {eval exec -keepnewline $cmd} result]
171 } else {
172 set rc [catch {eval exec $cmd} result]
173 }
174 }
175 global RESULT CODE
176 set CODE $rc
177 if {($rc && !$expectError) || (!$rc && $expectError)} {
178 protOut "ERROR: $result" 1
@@ -210,11 +225,11 @@
225 th1-setup \
226 th1-uri-regexp]
227
228 fossil test-th-eval "hasfeature tcl"
229
230 if {[normalize_result] eq "1"} {
231 lappend result tcl-setup
232 }
233
234 return [lsort -dictionary $result]
235 }
@@ -275,29 +290,29 @@
290 uv-sync \
291 web-browser]
292
293 fossil test-th-eval "hasfeature legacyMvRm"
294
295 if {[normalize_result] eq "1"} {
296 lappend result mv-rm-files
297 }
298
299 fossil test-th-eval "hasfeature tcl"
300
301 if {[normalize_result] eq "1"} {
302 lappend result tcl tcl-setup
303 }
304
305 fossil test-th-eval "hasfeature th1Docs"
306
307 if {[normalize_result] eq "1"} {
308 lappend result th1-docs
309 }
310
311 fossil test-th-eval "hasfeature th1Hooks"
312
313 if {[normalize_result] eq "1"} {
314 lappend result th1-hooks
315 }
316
317 return [lsort -dictionary $result]
318 }
@@ -440,27 +455,27 @@
455
456 # This procedure only returns non-zero if the Tcl integration feature was
457 # enabled at compile-time and is now enabled at runtime.
458 proc is_tcl_usable_by_fossil {} {
459 fossil test-th-eval "hasfeature tcl"
460 if {[normalize_result] ne "1"} {return 0}
461 fossil test-th-eval "setting tcl"
462 if {[normalize_result] eq "1"} {return 1}
463 fossil test-th-eval --open-config "setting tcl"
464 if {[normalize_result] eq "1"} {return 1}
465 return [info exists ::env(TH1_ENABLE_TCL)]
466 }
467
468 # This procedure only returns non-zero if the TH1 hooks feature was enabled
469 # at compile-time and is now enabled at runtime.
470 proc are_th1_hooks_usable_by_fossil {} {
471 fossil test-th-eval "hasfeature th1Hooks"
472 if {[normalize_result] ne "1"} {return 0}
473 fossil test-th-eval "setting th1-hooks"
474 if {[normalize_result] eq "1"} {return 1}
475 fossil test-th-eval --open-config "setting th1-hooks"
476 if {[normalize_result] eq "1"} {return 1}
477 return [info exists ::env(TH1_ENABLE_HOOKS)]
478 }
479
480 # This (rarely used) procedure is designed to run a test within the Fossil
481 # source checkout (e.g. one that does NOT modify any state), while saving
@@ -560,14 +575,14 @@
575 # NOTE: Check if we can use any of the environment variables.
576 #
577 foreach name $names {
578 set value [getEnvironmentVariable $name]
579
580 if {[string length $value] > 0} {
581 set value [file normalize $value]
582
583 if {[file exists $value] && [file isdirectory $value]} {
584 return $value
585 }
586 }
587 }
588
@@ -575,11 +590,11 @@
590 # NOTE: On non-Windows systems, fallback to /tmp if it is usable.
591 #
592 if {$::tcl_platform(platform) ne "windows"} {
593 set value /tmp
594
595 if {[file exists $value] && [file isdirectory $value]} {
596 return $value
597 }
598 }
599
600 #
@@ -732,10 +747,84 @@
747 }
748 append out \n$line
749 }
750 return [string range $out 1 end]
751 }
752
753 # This procedure executes the "fossil server" command. The return value
754 # is the new process identifier. The varName argument refers to a variable
755 # where the "stop argument" is to be stored. This value must eventually be
756 # passed to the [test_stop_server] procedure.
757 proc test_start_server { repository {varName ""} } {
758 global fossilexe
759 set command [list exec $fossilexe server]
760 if {[string length $varName] > 0} {
761 upvar 1 $varName stopArg
762 }
763 if {$::tcl_platform(platform) eq "windows"} {
764 set stopArg [file join [getTemporaryPath] [appendArgs \
765 [string trim [clock seconds] -] _ [getSeqNo] .stopper]]
766 lappend command --stopper $stopArg
767 }
768 lappend command $repository &
769 set pid [eval $command]
770 if {$::tcl_platform(platform) ne "windows"} {
771 set stopArg $pid
772 }
773 return $pid
774 }
775
776 # This procedure stops a Fossil server instance that was previously started
777 # by the [test_start_server] procedure. The value of the "stop argument"
778 # will vary by platform as will the exact method used to stop the server.
779 proc test_stop_server { stopArg pid } {
780 if {$::tcl_platform(platform) eq "windows"} {
781 #
782 # NOTE: On Windows, the "stop argument" must be the name of a file
783 # that does NOT already exist.
784 #
785 if {![file exists $stopArg] && \
786 [catch {write_file $stopArg [clock seconds]}] == 0} then {
787 while {1} {
788 if {[catch {
789 #
790 # NOTE: Using the TaskList utility requires Windows XP or
791 # later.
792 #
793 exec tasklist.exe /FI "PID eq $pid"
794 } result] != 0 || ![regexp -- " $pid " $result]} then {
795 break
796 }
797 after 1000; # wait a bit...
798 }
799 file delete $stopArg
800 return true
801 }
802 } else {
803 #
804 # NOTE: On Unix, the "stop argument" must be an integer identifier
805 # that refers to an existing process.
806 #
807 if {[regexp {^(?:-)?\d+$} $stopArg] && \
808 [catch {exec kill -TERM $stopArg}] == 0} then {
809 while {1} {
810 if {[catch {
811 #
812 # TODO: Is this portable to all the supported variants of
813 # Unix? It should be, it's POSIX.
814 #
815 exec ps -p $pid
816 } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} then {
817 break
818 }
819 after 1000; # wait a bit...
820 }
821 return true
822 }
823 }
824 return false
825 }
826
827 # Executes the "fossil http" command. The entire content of the HTTP request
828 # is read from the data file name, with [subst] being performed on it prior to
829 # submission. Temporary input and output files are created and deleted. The
830 # result will be the contents of the temoprary output file.
831
--- test/th1-docs.test
+++ test/th1-docs.test
@@ -18,18 +18,18 @@
1818
# TH1 Docs
1919
#
2020
2121
fossil test-th-eval "hasfeature th1Docs"
2222
23
-if {$::RESULT ne "1"} {
23
+if {[normalize_result] ne "1"} {
2424
puts "Fossil was not compiled with TH1 docs support."
2525
test_cleanup_then_return
2626
}
2727
2828
fossil test-th-eval "hasfeature tcl"
2929
30
-if {$::RESULT ne "1"} {
30
+if {[normalize_result] ne "1"} {
3131
puts "Fossil was not compiled with Tcl support."
3232
test_cleanup_then_return
3333
}
3434
3535
###############################################################################
3636
--- test/th1-docs.test
+++ test/th1-docs.test
@@ -18,18 +18,18 @@
18 # TH1 Docs
19 #
20
21 fossil test-th-eval "hasfeature th1Docs"
22
23 if {$::RESULT ne "1"} {
24 puts "Fossil was not compiled with TH1 docs support."
25 test_cleanup_then_return
26 }
27
28 fossil test-th-eval "hasfeature tcl"
29
30 if {$::RESULT ne "1"} {
31 puts "Fossil was not compiled with Tcl support."
32 test_cleanup_then_return
33 }
34
35 ###############################################################################
36
--- test/th1-docs.test
+++ test/th1-docs.test
@@ -18,18 +18,18 @@
18 # TH1 Docs
19 #
20
21 fossil test-th-eval "hasfeature th1Docs"
22
23 if {[normalize_result] ne "1"} {
24 puts "Fossil was not compiled with TH1 docs support."
25 test_cleanup_then_return
26 }
27
28 fossil test-th-eval "hasfeature tcl"
29
30 if {[normalize_result] ne "1"} {
31 puts "Fossil was not compiled with Tcl support."
32 test_cleanup_then_return
33 }
34
35 ###############################################################################
36
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -18,11 +18,11 @@
1818
# TH1 Hooks
1919
#
2020
2121
fossil test-th-eval "hasfeature th1Hooks"
2222
23
-if {$::RESULT ne "1"} {
23
+if {[normalize_result] ne "1"} {
2424
puts "Fossil was not compiled with TH1 hooks support."
2525
test_cleanup_then_return
2626
}
2727
2828
###############################################################################
@@ -75,12 +75,17 @@
7575
return -code 2 "TH_RETURN return code"
7676
} elseif {$::cmd_name eq "timeline"} {
7777
set length [llength $::cmd_args]
7878
set length [expr {$length - 1}]
7979
if {[lindex $::cmd_args $length] eq "custom"} {
80
+ append_hook_log "CUSTOM TIMELINE"
8081
emit_hook_log
8182
return "custom timeline"
83
+ } elseif {[lindex $::cmd_args $length] eq "custom2"} {
84
+ emit_hook_log
85
+ puts "+++ some stuff here +++"
86
+ continue "custom2 timeline"
8287
} elseif {[lindex $::cmd_args $length] eq "now"} {
8388
emit_hook_log
8489
return "now timeline"
8590
} else {
8691
emit_hook_log
@@ -122,15 +127,21 @@
122127
123128
saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
124129
125130
###############################################################################
126131
127
-fossil timeline custom; # NOTE: Bad "WHEN" argument.
132
+fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument.
128133
test th1-cmd-hooks-1a {[normalize_result] eq \
134
+{<h1><b>command_hook timeline CUSTOM TIMELINE</b></h1>
135
+unknown check-in or invalid date: custom}}
136
+
137
+###############################################################################
138
+
139
+fossil timeline custom2; # NOTE: Bad "WHEN" argument.
140
+test th1-cmd-hooks-1b {[normalize_result] eq \
129141
{<h1><b>command_hook timeline</b></h1>
130
-+++ no more data (0) +++
131
-
++++ some stuff here +++
132142
<h1><b>command_hook timeline command_notify timeline</b></h1>}}
133143
134144
###############################################################################
135145
136146
fossil timeline
137147
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -18,11 +18,11 @@
18 # TH1 Hooks
19 #
20
21 fossil test-th-eval "hasfeature th1Hooks"
22
23 if {$::RESULT ne "1"} {
24 puts "Fossil was not compiled with TH1 hooks support."
25 test_cleanup_then_return
26 }
27
28 ###############################################################################
@@ -75,12 +75,17 @@
75 return -code 2 "TH_RETURN return code"
76 } elseif {$::cmd_name eq "timeline"} {
77 set length [llength $::cmd_args]
78 set length [expr {$length - 1}]
79 if {[lindex $::cmd_args $length] eq "custom"} {
 
80 emit_hook_log
81 return "custom timeline"
 
 
 
 
82 } elseif {[lindex $::cmd_args $length] eq "now"} {
83 emit_hook_log
84 return "now timeline"
85 } else {
86 emit_hook_log
@@ -122,15 +127,21 @@
122
123 saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
124
125 ###############################################################################
126
127 fossil timeline custom; # NOTE: Bad "WHEN" argument.
128 test th1-cmd-hooks-1a {[normalize_result] eq \
 
 
 
 
 
 
 
129 {<h1><b>command_hook timeline</b></h1>
130 +++ no more data (0) +++
131
++++ some stuff here +++
132 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
133
134 ###############################################################################
135
136 fossil timeline
137
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -18,11 +18,11 @@
18 # TH1 Hooks
19 #
20
21 fossil test-th-eval "hasfeature th1Hooks"
22
23 if {[normalize_result] ne "1"} {
24 puts "Fossil was not compiled with TH1 hooks support."
25 test_cleanup_then_return
26 }
27
28 ###############################################################################
@@ -75,12 +75,17 @@
75 return -code 2 "TH_RETURN return code"
76 } elseif {$::cmd_name eq "timeline"} {
77 set length [llength $::cmd_args]
78 set length [expr {$length - 1}]
79 if {[lindex $::cmd_args $length] eq "custom"} {
80 append_hook_log "CUSTOM TIMELINE"
81 emit_hook_log
82 return "custom timeline"
83 } elseif {[lindex $::cmd_args $length] eq "custom2"} {
84 emit_hook_log
85 puts "+++ some stuff here +++"
86 continue "custom2 timeline"
87 } elseif {[lindex $::cmd_args $length] eq "now"} {
88 emit_hook_log
89 return "now timeline"
90 } else {
91 emit_hook_log
@@ -122,15 +127,21 @@
127
128 saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
129
130 ###############################################################################
131
132 fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument.
133 test th1-cmd-hooks-1a {[normalize_result] eq \
134 {<h1><b>command_hook timeline CUSTOM TIMELINE</b></h1>
135 unknown check-in or invalid date: custom}}
136
137 ###############################################################################
138
139 fossil timeline custom2; # NOTE: Bad "WHEN" argument.
140 test th1-cmd-hooks-1b {[normalize_result] eq \
141 {<h1><b>command_hook timeline</b></h1>
 
 
++++ some stuff here +++
142 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
143
144 ###############################################################################
145
146 fossil timeline
147
--- test/th1-repo.test
+++ test/th1-repo.test
@@ -19,10 +19,12 @@
1919
############################################################################
2020
#
2121
# TH1 tests that may modify the repository
2222
#
2323
24
+set path [file dirname [info script]]
25
+
2426
require_no_open_checkout
2527
2628
########################################
2729
# Setup: Add Files and Commit #
2830
########################################
@@ -51,12 +53,10 @@
5153
set files_md [list subdirB/f5.md subdirB/f6.md subdirB/f8.md subdirC/f10.md]
5254
5355
fossil add $rootDir
5456
fossil commit -m "c1"
5557
56
-set dir [file dirname [info script]]
57
-
5858
###############################################################################
5959
6060
fossil test-th-eval --open-config "dir trunk subdir*/*.md"
6161
test th1-dir-1 {[llength $RESULT] eq [llength $files_md]}
6262
6363
--- test/th1-repo.test
+++ test/th1-repo.test
@@ -19,10 +19,12 @@
19 ############################################################################
20 #
21 # TH1 tests that may modify the repository
22 #
23
 
 
24 require_no_open_checkout
25
26 ########################################
27 # Setup: Add Files and Commit #
28 ########################################
@@ -51,12 +53,10 @@
51 set files_md [list subdirB/f5.md subdirB/f6.md subdirB/f8.md subdirC/f10.md]
52
53 fossil add $rootDir
54 fossil commit -m "c1"
55
56 set dir [file dirname [info script]]
57
58 ###############################################################################
59
60 fossil test-th-eval --open-config "dir trunk subdir*/*.md"
61 test th1-dir-1 {[llength $RESULT] eq [llength $files_md]}
62
63
--- test/th1-repo.test
+++ test/th1-repo.test
@@ -19,10 +19,12 @@
19 ############################################################################
20 #
21 # TH1 tests that may modify the repository
22 #
23
24 set path [file dirname [info script]]
25
26 require_no_open_checkout
27
28 ########################################
29 # Setup: Add Files and Commit #
30 ########################################
@@ -51,12 +53,10 @@
53 set files_md [list subdirB/f5.md subdirB/f6.md subdirB/f8.md subdirC/f10.md]
54
55 fossil add $rootDir
56 fossil commit -m "c1"
57
 
 
58 ###############################################################################
59
60 fossil test-th-eval --open-config "dir trunk subdir*/*.md"
61 test th1-dir-1 {[llength $RESULT] eq [llength $files_md]}
62
63
+12 -12
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -16,17 +16,17 @@
1616
############################################################################
1717
#
1818
# TH1/Tcl integration
1919
#
2020
21
-set dir [file dirname [info script]]
21
+set path [file dirname [info script]]
2222
2323
###############################################################################
2424
2525
fossil test-th-eval "hasfeature tcl"
2626
27
-if {$::RESULT ne "1"} {
27
+if {[normalize_result] ne "1"} {
2828
puts "Fossil was not compiled with Tcl support."
2929
test_cleanup_then_return
3030
}
3131
3232
###############################################################################
@@ -38,11 +38,11 @@
3838
set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test.
3939
4040
###############################################################################
4141
4242
fossil test-th-render --open-config \
43
- [file nativename [file join $dir th1-tcl1.txt]]
43
+ [file nativename [file join $path th1-tcl1.txt]]
4444
4545
test th1-tcl-1 {[regexp -- {^tclReady\(before\) = 0
4646
tclReady\(after\) = 1
4747
\d+
4848
\d+
@@ -65,62 +65,62 @@
6565
6666
###############################################################################
6767
6868
if {[catch {package require sqlite3}] == 0} {
6969
fossil test-th-render --open-config \
70
- [file nativename [file join $dir th1-tcl2.txt]]
70
+ [file nativename [file join $path th1-tcl2.txt]]
7171
7272
test th1-tcl-2 {[regexp -- {^\d+$} [normalize_result]]}
7373
} else {
7474
puts stderr "Skipping 'th1-tcl-2', SQLite package for Tcl not available"
7575
}
7676
7777
###############################################################################
7878
7979
fossil test-th-render --open-config \
80
- [file nativename [file join $dir th1-tcl3.txt]]
80
+ [file nativename [file join $path th1-tcl3.txt]]
8181
8282
test th1-tcl-3 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
8383
invalid command name &quot;bad_command&quot;</p>}}
8484
8585
###############################################################################
8686
8787
fossil test-th-render --open-config \
88
- [file nativename [file join $dir th1-tcl4.txt]]
88
+ [file nativename [file join $path th1-tcl4.txt]]
8989
9090
test th1-tcl-4 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
9191
divide by zero</p>}}
9292
9393
###############################################################################
9494
9595
fossil test-th-render --open-config \
96
- [file nativename [file join $dir th1-tcl5.txt]]
96
+ [file nativename [file join $path th1-tcl5.txt]]
9797
9898
test th1-tcl-5 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
9999
Tcl command not found: bad_command</p>} || $RESULT eq {<hr /><p\
100100
class="thmainError">ERROR: invalid command name &quot;bad_command&quot;</p>}}
101101
102102
###############################################################################
103103
104104
fossil test-th-render --open-config \
105
- [file nativename [file join $dir th1-tcl6.txt]]
105
+ [file nativename [file join $path th1-tcl6.txt]]
106106
107107
test th1-tcl-6 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
108108
no such command: bad_command</p>}}
109109
110110
###############################################################################
111111
112112
fossil test-th-render --open-config \
113
- [file nativename [file join $dir th1-tcl7.txt]]
113
+ [file nativename [file join $path th1-tcl7.txt]]
114114
115115
test th1-tcl-7 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
116116
syntax error in expression: &quot;2**0&quot;</p>}}
117117
118118
###############################################################################
119119
120120
fossil test-th-render --open-config \
121
- [file nativename [file join $dir th1-tcl8.txt]]
121
+ [file nativename [file join $path th1-tcl8.txt]]
122122
123123
test th1-tcl-8 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
124124
cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr /><p\
125125
class="thmainError">ERROR: tailcall can only be called from a proc or\
126126
lambda</p>} || $RESULT eq {<hr /><p class="thmainError">ERROR: This test\
@@ -127,14 +127,14 @@
127127
requires Tcl 8.6 or higher.</p>}}
128128
129129
###############################################################################
130130
131131
fossil test-th-render --open-config \
132
- [file nativename [file join $dir th1-tcl9.txt]]
132
+ [file nativename [file join $path th1-tcl9.txt]]
133133
134134
test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
135
-[list test-th-render --open-config [file nativename [file join $dir \
135
+[list test-th-render --open-config [file nativename [file join $path \
136136
th1-tcl9.txt]]]]}
137137
138138
###############################################################################
139139
140140
fossil test-th-eval "tclMakeSafe a"
141141
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -16,17 +16,17 @@
16 ############################################################################
17 #
18 # TH1/Tcl integration
19 #
20
21 set dir [file dirname [info script]]
22
23 ###############################################################################
24
25 fossil test-th-eval "hasfeature tcl"
26
27 if {$::RESULT ne "1"} {
28 puts "Fossil was not compiled with Tcl support."
29 test_cleanup_then_return
30 }
31
32 ###############################################################################
@@ -38,11 +38,11 @@
38 set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test.
39
40 ###############################################################################
41
42 fossil test-th-render --open-config \
43 [file nativename [file join $dir th1-tcl1.txt]]
44
45 test th1-tcl-1 {[regexp -- {^tclReady\(before\) = 0
46 tclReady\(after\) = 1
47 \d+
48 \d+
@@ -65,62 +65,62 @@
65
66 ###############################################################################
67
68 if {[catch {package require sqlite3}] == 0} {
69 fossil test-th-render --open-config \
70 [file nativename [file join $dir th1-tcl2.txt]]
71
72 test th1-tcl-2 {[regexp -- {^\d+$} [normalize_result]]}
73 } else {
74 puts stderr "Skipping 'th1-tcl-2', SQLite package for Tcl not available"
75 }
76
77 ###############################################################################
78
79 fossil test-th-render --open-config \
80 [file nativename [file join $dir th1-tcl3.txt]]
81
82 test th1-tcl-3 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
83 invalid command name &quot;bad_command&quot;</p>}}
84
85 ###############################################################################
86
87 fossil test-th-render --open-config \
88 [file nativename [file join $dir th1-tcl4.txt]]
89
90 test th1-tcl-4 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
91 divide by zero</p>}}
92
93 ###############################################################################
94
95 fossil test-th-render --open-config \
96 [file nativename [file join $dir th1-tcl5.txt]]
97
98 test th1-tcl-5 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
99 Tcl command not found: bad_command</p>} || $RESULT eq {<hr /><p\
100 class="thmainError">ERROR: invalid command name &quot;bad_command&quot;</p>}}
101
102 ###############################################################################
103
104 fossil test-th-render --open-config \
105 [file nativename [file join $dir th1-tcl6.txt]]
106
107 test th1-tcl-6 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
108 no such command: bad_command</p>}}
109
110 ###############################################################################
111
112 fossil test-th-render --open-config \
113 [file nativename [file join $dir th1-tcl7.txt]]
114
115 test th1-tcl-7 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
116 syntax error in expression: &quot;2**0&quot;</p>}}
117
118 ###############################################################################
119
120 fossil test-th-render --open-config \
121 [file nativename [file join $dir th1-tcl8.txt]]
122
123 test th1-tcl-8 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
124 cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr /><p\
125 class="thmainError">ERROR: tailcall can only be called from a proc or\
126 lambda</p>} || $RESULT eq {<hr /><p class="thmainError">ERROR: This test\
@@ -127,14 +127,14 @@
127 requires Tcl 8.6 or higher.</p>}}
128
129 ###############################################################################
130
131 fossil test-th-render --open-config \
132 [file nativename [file join $dir th1-tcl9.txt]]
133
134 test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
135 [list test-th-render --open-config [file nativename [file join $dir \
136 th1-tcl9.txt]]]]}
137
138 ###############################################################################
139
140 fossil test-th-eval "tclMakeSafe a"
141
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -16,17 +16,17 @@
16 ############################################################################
17 #
18 # TH1/Tcl integration
19 #
20
21 set path [file dirname [info script]]
22
23 ###############################################################################
24
25 fossil test-th-eval "hasfeature tcl"
26
27 if {[normalize_result] ne "1"} {
28 puts "Fossil was not compiled with Tcl support."
29 test_cleanup_then_return
30 }
31
32 ###############################################################################
@@ -38,11 +38,11 @@
38 set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test.
39
40 ###############################################################################
41
42 fossil test-th-render --open-config \
43 [file nativename [file join $path th1-tcl1.txt]]
44
45 test th1-tcl-1 {[regexp -- {^tclReady\(before\) = 0
46 tclReady\(after\) = 1
47 \d+
48 \d+
@@ -65,62 +65,62 @@
65
66 ###############################################################################
67
68 if {[catch {package require sqlite3}] == 0} {
69 fossil test-th-render --open-config \
70 [file nativename [file join $path th1-tcl2.txt]]
71
72 test th1-tcl-2 {[regexp -- {^\d+$} [normalize_result]]}
73 } else {
74 puts stderr "Skipping 'th1-tcl-2', SQLite package for Tcl not available"
75 }
76
77 ###############################################################################
78
79 fossil test-th-render --open-config \
80 [file nativename [file join $path th1-tcl3.txt]]
81
82 test th1-tcl-3 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
83 invalid command name &quot;bad_command&quot;</p>}}
84
85 ###############################################################################
86
87 fossil test-th-render --open-config \
88 [file nativename [file join $path th1-tcl4.txt]]
89
90 test th1-tcl-4 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
91 divide by zero</p>}}
92
93 ###############################################################################
94
95 fossil test-th-render --open-config \
96 [file nativename [file join $path th1-tcl5.txt]]
97
98 test th1-tcl-5 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
99 Tcl command not found: bad_command</p>} || $RESULT eq {<hr /><p\
100 class="thmainError">ERROR: invalid command name &quot;bad_command&quot;</p>}}
101
102 ###############################################################################
103
104 fossil test-th-render --open-config \
105 [file nativename [file join $path th1-tcl6.txt]]
106
107 test th1-tcl-6 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
108 no such command: bad_command</p>}}
109
110 ###############################################################################
111
112 fossil test-th-render --open-config \
113 [file nativename [file join $path th1-tcl7.txt]]
114
115 test th1-tcl-7 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
116 syntax error in expression: &quot;2**0&quot;</p>}}
117
118 ###############################################################################
119
120 fossil test-th-render --open-config \
121 [file nativename [file join $path th1-tcl8.txt]]
122
123 test th1-tcl-8 {$RESULT eq {<hr /><p class="thmainError">ERROR:\
124 cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr /><p\
125 class="thmainError">ERROR: tailcall can only be called from a proc or\
126 lambda</p>} || $RESULT eq {<hr /><p class="thmainError">ERROR: This test\
@@ -127,14 +127,14 @@
127 requires Tcl 8.6 or higher.</p>}}
128
129 ###############################################################################
130
131 fossil test-th-render --open-config \
132 [file nativename [file join $path th1-tcl9.txt]]
133
134 test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
135 [list test-th-render --open-config [file nativename [file join $path \
136 th1-tcl9.txt]]]]}
137
138 ###############################################################################
139
140 fossil test-th-eval "tclMakeSafe a"
141
+2 -2
--- test/th1.test
+++ test/th1.test
@@ -16,11 +16,11 @@
1616
############################################################################
1717
#
1818
# TH1 Commands
1919
#
2020
21
-set dir [file dirname [info script]]; test_setup
21
+set path [file dirname [info script]]; test_setup
2222
2323
###############################################################################
2424
2525
set th1Tcl [is_tcl_usable_by_fossil]
2626
set th1Hooks [are_th1_hooks_usable_by_fossil]
@@ -1468,11 +1468,11 @@
14681468
</div>
14691469
}}}
14701470
14711471
###############################################################################
14721472
1473
-set markdown [read_file [file join $dir markdown-test1.md]]
1473
+set markdown [read_file [file join $path markdown-test1.md]]
14741474
fossil test-th-eval [string map \
14751475
[list %markdown% $markdown] {markdown {%markdown%}}]
14761476
test th1-markdown-5 {[normalize_result] eq \
14771477
{{Markdown Formatter Test Document} {<div class="markdown">
14781478
14791479
14801480
ADDED test/unversioned.test
--- test/th1.test
+++ test/th1.test
@@ -16,11 +16,11 @@
16 ############################################################################
17 #
18 # TH1 Commands
19 #
20
21 set dir [file dirname [info script]]; test_setup
22
23 ###############################################################################
24
25 set th1Tcl [is_tcl_usable_by_fossil]
26 set th1Hooks [are_th1_hooks_usable_by_fossil]
@@ -1468,11 +1468,11 @@
1468 </div>
1469 }}}
1470
1471 ###############################################################################
1472
1473 set markdown [read_file [file join $dir markdown-test1.md]]
1474 fossil test-th-eval [string map \
1475 [list %markdown% $markdown] {markdown {%markdown%}}]
1476 test th1-markdown-5 {[normalize_result] eq \
1477 {{Markdown Formatter Test Document} {<div class="markdown">
1478
1479
1480 DDED test/unversioned.test
--- test/th1.test
+++ test/th1.test
@@ -16,11 +16,11 @@
16 ############################################################################
17 #
18 # TH1 Commands
19 #
20
21 set path [file dirname [info script]]; test_setup
22
23 ###############################################################################
24
25 set th1Tcl [is_tcl_usable_by_fossil]
26 set th1Hooks [are_th1_hooks_usable_by_fossil]
@@ -1468,11 +1468,11 @@
1468 </div>
1469 }}}
1470
1471 ###############################################################################
1472
1473 set markdown [read_file [file join $path markdown-test1.md]]
1474 fossil test-th-eval [string map \
1475 [list %markdown% $markdown] {markdown {%markdown%}}]
1476 test th1-markdown-5 {[normalize_result] eq \
1477 {{Markdown Formatter Test Document} {<div class="markdown">
1478
1479
1480 DDED test/unversioned.test
--- a/test/unversioned.test
+++ b/test/unversioned.test
@@ -0,0 +1,2 @@
1
+nam]
2
+8080/set pid"Started\".]
--- a/test/unversioned.test
+++ b/test/unversioned.test
@@ -0,0 +1,2 @@
 
 
--- a/test/unversioned.test
+++ b/test/unversioned.test
@@ -0,0 +1,2 @@
1 nam]
2 8080/set pid"Started\".]
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,11 +83,11 @@
8383
8484
# define the SQLite files, which need special flags on compile
8585
SQLITESRC=sqlite3.c
8686
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
8787
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88
-SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI
88
+SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI
8989
9090
# define the SQLite shell files, which need special flags on compile
9191
SQLITESHELLSRC=shell.c
9292
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
9393
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
9494
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,11 +83,11 @@
83
84 # define the SQLite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI
89
90 # define the SQLite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,11 +83,11 @@
83
84 # define the SQLite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI
89
90 # define the SQLite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,11 +24,11 @@
2424
CFLAGS = -o
2525
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
29
-SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
29
+SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
3030
3131
SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
3333
SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
3535
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,11 +24,11 @@
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 = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,11 +24,11 @@
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 = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2174,10 +2174,12 @@
21742174
-DSQLITE_OMIT_DECLTYPE \
21752175
-DSQLITE_OMIT_DEPRECATED \
21762176
-DSQLITE_OMIT_PROGRESS_CALLBACK \
21772177
-DSQLITE_OMIT_SHARED_CACHE \
21782178
-DSQLITE_OMIT_LOAD_EXTENSION \
2179
+ -DSQLITE_MAX_EXPR_DEPTH=0 \
2180
+ -DSQLITE_USE_ALLOCA \
21792181
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
21802182
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
21812183
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
21822184
-DSQLITE_ENABLE_FTS4 \
21832185
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
21842186
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2174,10 +2174,12 @@
2174 -DSQLITE_OMIT_DECLTYPE \
2175 -DSQLITE_OMIT_DEPRECATED \
2176 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2177 -DSQLITE_OMIT_SHARED_CACHE \
2178 -DSQLITE_OMIT_LOAD_EXTENSION \
 
 
2179 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
2180 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
2181 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
2182 -DSQLITE_ENABLE_FTS4 \
2183 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
2184
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2174,10 +2174,12 @@
2174 -DSQLITE_OMIT_DECLTYPE \
2175 -DSQLITE_OMIT_DEPRECATED \
2176 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2177 -DSQLITE_OMIT_SHARED_CACHE \
2178 -DSQLITE_OMIT_LOAD_EXTENSION \
2179 -DSQLITE_MAX_EXPR_DEPTH=0 \
2180 -DSQLITE_USE_ALLOCA \
2181 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
2182 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
2183 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
2184 -DSQLITE_ENABLE_FTS4 \
2185 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
2186
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -2174,10 +2174,12 @@
21742174
-DSQLITE_OMIT_DECLTYPE \
21752175
-DSQLITE_OMIT_DEPRECATED \
21762176
-DSQLITE_OMIT_PROGRESS_CALLBACK \
21772177
-DSQLITE_OMIT_SHARED_CACHE \
21782178
-DSQLITE_OMIT_LOAD_EXTENSION \
2179
+ -DSQLITE_MAX_EXPR_DEPTH=0 \
2180
+ -DSQLITE_USE_ALLOCA \
21792181
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
21802182
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
21812183
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
21822184
-DSQLITE_ENABLE_FTS4 \
21832185
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
21842186
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -2174,10 +2174,12 @@
2174 -DSQLITE_OMIT_DECLTYPE \
2175 -DSQLITE_OMIT_DEPRECATED \
2176 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2177 -DSQLITE_OMIT_SHARED_CACHE \
2178 -DSQLITE_OMIT_LOAD_EXTENSION \
 
 
2179 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
2180 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
2181 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
2182 -DSQLITE_ENABLE_FTS4 \
2183 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
2184
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -2174,10 +2174,12 @@
2174 -DSQLITE_OMIT_DECLTYPE \
2175 -DSQLITE_OMIT_DEPRECATED \
2176 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2177 -DSQLITE_OMIT_SHARED_CACHE \
2178 -DSQLITE_OMIT_LOAD_EXTENSION \
2179 -DSQLITE_MAX_EXPR_DEPTH=0 \
2180 -DSQLITE_USE_ALLOCA \
2181 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
2182 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
2183 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
2184 -DSQLITE_ENABLE_FTS4 \
2185 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
2186
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -321,10 +321,12 @@
321321
/DSQLITE_OMIT_DECLTYPE \
322322
/DSQLITE_OMIT_DEPRECATED \
323323
/DSQLITE_OMIT_PROGRESS_CALLBACK \
324324
/DSQLITE_OMIT_SHARED_CACHE \
325325
/DSQLITE_OMIT_LOAD_EXTENSION \
326
+ /DSQLITE_MAX_EXPR_DEPTH=0 \
327
+ /DSQLITE_USE_ALLOCA \
326328
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
327329
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
328330
/DSQLITE_ENABLE_EXPLAIN_COMMENTS \
329331
/DSQLITE_ENABLE_FTS4 \
330332
/DSQLITE_ENABLE_FTS3_PARENTHESIS \
331333
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -321,10 +321,12 @@
321 /DSQLITE_OMIT_DECLTYPE \
322 /DSQLITE_OMIT_DEPRECATED \
323 /DSQLITE_OMIT_PROGRESS_CALLBACK \
324 /DSQLITE_OMIT_SHARED_CACHE \
325 /DSQLITE_OMIT_LOAD_EXTENSION \
 
 
326 /DSQLITE_ENABLE_LOCKING_STYLE=0 \
327 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
328 /DSQLITE_ENABLE_EXPLAIN_COMMENTS \
329 /DSQLITE_ENABLE_FTS4 \
330 /DSQLITE_ENABLE_FTS3_PARENTHESIS \
331
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -321,10 +321,12 @@
321 /DSQLITE_OMIT_DECLTYPE \
322 /DSQLITE_OMIT_DEPRECATED \
323 /DSQLITE_OMIT_PROGRESS_CALLBACK \
324 /DSQLITE_OMIT_SHARED_CACHE \
325 /DSQLITE_OMIT_LOAD_EXTENSION \
326 /DSQLITE_MAX_EXPR_DEPTH=0 \
327 /DSQLITE_USE_ALLOCA \
328 /DSQLITE_ENABLE_LOCKING_STYLE=0 \
329 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
330 /DSQLITE_ENABLE_EXPLAIN_COMMENTS \
331 /DSQLITE_ENABLE_FTS4 \
332 /DSQLITE_ENABLE_FTS3_PARENTHESIS \
333
--- www/aboutcgi.wiki
+++ www/aboutcgi.wiki
@@ -131,11 +131,11 @@
131131
<li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132132
<li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133133
</ol>
134134
In both cases, the CGI script is called "/fossil". For case (A),
135135
the PATH_INFO variable will be "info/c14ecc43" and so the
136
-"[/help?cmd=/info]" webpage will be generated and the suffix of
136
+"[/help?cmd=/info|/info]" webpage will be generated and the suffix of
137137
PATH_INFO will be converted into the "name" query parameter, which
138138
identifies the artifact about which information is requested.
139139
In case (B), the PATH_INFO is just "info", but the same "name"
140140
query parameter is set explicitly by the URL itself.
141141
</blockquote>
142142
--- www/aboutcgi.wiki
+++ www/aboutcgi.wiki
@@ -131,11 +131,11 @@
131 <li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132 <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133 </ol>
134 In both cases, the CGI script is called "/fossil". For case (A),
135 the PATH_INFO variable will be "info/c14ecc43" and so the
136 "[/help?cmd=/info]" webpage will be generated and the suffix of
137 PATH_INFO will be converted into the "name" query parameter, which
138 identifies the artifact about which information is requested.
139 In case (B), the PATH_INFO is just "info", but the same "name"
140 query parameter is set explicitly by the URL itself.
141 </blockquote>
142
--- www/aboutcgi.wiki
+++ www/aboutcgi.wiki
@@ -131,11 +131,11 @@
131 <li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132 <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133 </ol>
134 In both cases, the CGI script is called "/fossil". For case (A),
135 the PATH_INFO variable will be "info/c14ecc43" and so the
136 "[/help?cmd=/info|/info]" webpage will be generated and the suffix of
137 PATH_INFO will be converted into the "name" query parameter, which
138 identifies the artifact about which information is requested.
139 In case (B), the PATH_INFO is just "info", but the same "name"
140 query parameter is set explicitly by the URL itself.
141 </blockquote>
142
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,13 @@
88
* The [/uv/download.html|download page] is moved into
99
[./unvers.wiki|unversioned content] so that the self-hosting Fossil
1010
websites no longer uses any external content.
1111
* Added the "Search" button to the graphical diff generated by
1212
the --tk option on the [/help?cmd=diff|diff] command.
13
+ * Added the "--checkin VERSION" option to the
14
+ [/help?cmd=diff|diff] command.
15
+ * Various performance enhancements to the [/help?cmd=diff|diff] command.
1316
* Update internal Unicode character tables, used in regular expression
1417
handling, from version 8.0 to 9.0.
1518
* Update the built-in SQLite to version 3.15 (beta). Fossil now requires
1619
the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
1720
in SQLite version 3.15 and later and so Fossil will not work with
1821
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,13 @@
8 * The [/uv/download.html|download page] is moved into
9 [./unvers.wiki|unversioned content] so that the self-hosting Fossil
10 websites no longer uses any external content.
11 * Added the "Search" button to the graphical diff generated by
12 the --tk option on the [/help?cmd=diff|diff] command.
 
 
 
13 * Update internal Unicode character tables, used in regular expression
14 handling, from version 8.0 to 9.0.
15 * Update the built-in SQLite to version 3.15 (beta). Fossil now requires
16 the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
17 in SQLite version 3.15 and later and so Fossil will not work with
18
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,13 @@
8 * The [/uv/download.html|download page] is moved into
9 [./unvers.wiki|unversioned content] so that the self-hosting Fossil
10 websites no longer uses any external content.
11 * Added the "Search" button to the graphical diff generated by
12 the --tk option on the [/help?cmd=diff|diff] command.
13 * Added the "--checkin VERSION" option to the
14 [/help?cmd=diff|diff] command.
15 * Various performance enhancements to the [/help?cmd=diff|diff] command.
16 * Update internal Unicode character tables, used in regular expression
17 handling, from version 8.0 to 9.0.
18 * Update the built-in SQLite to version 3.15 (beta). Fossil now requires
19 the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
20 in SQLite version 3.15 and later and so Fossil will not work with
21
+3 -3
--- www/sync.wiki
+++ www/sync.wiki
@@ -220,11 +220,11 @@
220220
introduced to improve the speed of the transfer of content by sending the
221221
compressed artifact directly from the server database to the client.</p>
222222
223223
<p>Compressed File cards are similar to File cards, sharing the same
224224
in-line "payload" data characteristics and also the same treatment of
225
-direct content or delta content. It comes in two different formats
225
+direct content or delta content. Cfile cards come in two different formats
226226
depending on whether the artifact is sent directly or as a delta from
227227
some other artifact.</p>
228228
229229
<blockquote>
230230
<b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
@@ -277,11 +277,11 @@
277277
for the unversioned file, or "<b>-</b>" for deleted content.
278278
The <i>size</i> field is the (uncompressed) size of the content
279279
in bytes. The <i>flags</i> field is an integer which is interpreted
280280
as an array of bits. The 0x0004 bit of <i>flags</i> indicates that
281281
the <i>content</i> is to be omitted. The content might be omitted if
282
-it is too large to transmit, or if the send merely wants to update the
282
+it is too large to transmit, or if the sender merely wants to update the
283283
modification time of the file without changing the files content.
284284
The <i>content</i> is the (uncompressed) content of the file.
285285
286286
<p>The receiver should only accept the uvfile card if the hash and
287287
size match the content and if the mtime is newer than any existing
@@ -398,11 +398,11 @@
398398
identified by the first argument is private on the sender and should
399399
be ignored unless a "--private" [/help?cmd=sync|sync] is occurring.
400400
401401
<h4>3.6.1 Unversioned Igot Cards</h4>
402402
403
-<p>Zero or more "uvigot" cards are sent from client to server when
403
+<p>Zero or more "uvigot" cards are sent from server to client when
404404
synchronizing unversioned content. The format of a uvigot card is
405405
as follows:
406406
407407
<blockquote>
408408
<b>uvigot</b> <i>name mtime hash size</i>
409409
--- www/sync.wiki
+++ www/sync.wiki
@@ -220,11 +220,11 @@
220 introduced to improve the speed of the transfer of content by sending the
221 compressed artifact directly from the server database to the client.</p>
222
223 <p>Compressed File cards are similar to File cards, sharing the same
224 in-line "payload" data characteristics and also the same treatment of
225 direct content or delta content. It comes in two different formats
226 depending on whether the artifact is sent directly or as a delta from
227 some other artifact.</p>
228
229 <blockquote>
230 <b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
@@ -277,11 +277,11 @@
277 for the unversioned file, or "<b>-</b>" for deleted content.
278 The <i>size</i> field is the (uncompressed) size of the content
279 in bytes. The <i>flags</i> field is an integer which is interpreted
280 as an array of bits. The 0x0004 bit of <i>flags</i> indicates that
281 the <i>content</i> is to be omitted. The content might be omitted if
282 it is too large to transmit, or if the send merely wants to update the
283 modification time of the file without changing the files content.
284 The <i>content</i> is the (uncompressed) content of the file.
285
286 <p>The receiver should only accept the uvfile card if the hash and
287 size match the content and if the mtime is newer than any existing
@@ -398,11 +398,11 @@
398 identified by the first argument is private on the sender and should
399 be ignored unless a "--private" [/help?cmd=sync|sync] is occurring.
400
401 <h4>3.6.1 Unversioned Igot Cards</h4>
402
403 <p>Zero or more "uvigot" cards are sent from client to server when
404 synchronizing unversioned content. The format of a uvigot card is
405 as follows:
406
407 <blockquote>
408 <b>uvigot</b> <i>name mtime hash size</i>
409
--- www/sync.wiki
+++ www/sync.wiki
@@ -220,11 +220,11 @@
220 introduced to improve the speed of the transfer of content by sending the
221 compressed artifact directly from the server database to the client.</p>
222
223 <p>Compressed File cards are similar to File cards, sharing the same
224 in-line "payload" data characteristics and also the same treatment of
225 direct content or delta content. Cfile cards come in two different formats
226 depending on whether the artifact is sent directly or as a delta from
227 some other artifact.</p>
228
229 <blockquote>
230 <b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br>
@@ -277,11 +277,11 @@
277 for the unversioned file, or "<b>-</b>" for deleted content.
278 The <i>size</i> field is the (uncompressed) size of the content
279 in bytes. The <i>flags</i> field is an integer which is interpreted
280 as an array of bits. The 0x0004 bit of <i>flags</i> indicates that
281 the <i>content</i> is to be omitted. The content might be omitted if
282 it is too large to transmit, or if the sender merely wants to update the
283 modification time of the file without changing the files content.
284 The <i>content</i> is the (uncompressed) content of the file.
285
286 <p>The receiver should only accept the uvfile card if the hash and
287 size match the content and if the mtime is newer than any existing
@@ -398,11 +398,11 @@
398 identified by the first argument is private on the sender and should
399 be ignored unless a "--private" [/help?cmd=sync|sync] is occurring.
400
401 <h4>3.6.1 Unversioned Igot Cards</h4>
402
403 <p>Zero or more "uvigot" cards are sent from server to client when
404 synchronizing unversioned content. The format of a uvigot card is
405 as follows:
406
407 <blockquote>
408 <b>uvigot</b> <i>name mtime hash size</i>
409
+12 -8
--- www/th1.md
+++ www/th1.md
@@ -164,20 +164,20 @@
164164
* render
165165
* repository
166166
* searchable
167167
* setParameter
168168
* setting
169
+ * stime
169170
* styleHeader
170171
* styleFooter
171172
* tclEval
172173
* tclExpr
173174
* tclInvoke
174175
* tclIsSafe
175176
* tclMakeSafe
176177
* tclReady
177178
* trace
178
- * stime
179179
* utime
180180
* verifyCsrf
181181
* wiki
182182
183183
Each of the commands above is documented by a block comment above their
@@ -249,11 +249,11 @@
249249
250250
Renders STRING as wiki content; however, only links are handled. No
251251
other markup is processed.
252252
253253
<a name="dir"></a>TH1 dir Command
--------------------------------------------
254
+---------------------------------
254255
255256
* dir CHECKIN ?GLOB? ?DETAILS?
256257
257258
Returns a list containing all files in CHECKIN. If GLOB is given only
258259
the files matching the pattern GLOB within CHECKIN will be returned.
@@ -400,11 +400,11 @@
400400
401401
Returns one more than the number of \n characters in STRING. But
402402
never returns less than MIN or more than MAX.
403403
404404
<a name="markdown"></a>TH1 markdown Command
----------------------------------------------
405
+-------------------------------------------
405406
406407
* markdown STRING
407408
408409
Renders the input string as markdown. The result is a two-element list.
409410
The first element contains the body, rendered as HTML. The second element
@@ -517,10 +517,18 @@
517517
-----------------------------------------
518518
519519
* setting name
520520
521521
Gets and returns the value of the specified setting.
522
+
523
+<a name="stime"></a>TH1 stime Command
524
+-------------------------------------
525
+
526
+ * stime
527
+
528
+Returns the number of microseconds of CPU time consumed by the current
529
+process in system space.
522530
523531
<a name="styleHeader"></a>TH1 styleHeader Command
524532
-------------------------------------------------
525533
526534
* styleHeader TITLE
@@ -577,11 +585,11 @@
577585
578586
Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
579587
will be created automatically if it has not been already.
580588
581589
<a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
----------------------------------------------
590
+-------------------------------------------------
582591
583592
**This command requires the Tcl integration feature.**
584593
585594
* tclMakeSafe
586595
@@ -603,18 +611,10 @@
603611
604612
* trace STRING
605613
606614
Generates a TH1 trace message if TH1 tracing is enabled.
607615
608
-<a name="stime"></a>TH1 stime Command
--------------------------------------
609
-
610
- * stime
611
-
612
-Returns the number of microseconds of CPU time consumed by the current
613
-process in system space.
614
-
615616
<a name="utime"></a>TH1 utime Command
616617
-------------------------------------
617618
618619
* utime
619620
620621
--- www/th1.md
+++ www/th1.md
@@ -164,20 +164,20 @@
164 * render
165 * repository
166 * searchable
167 * setParameter
168 * setting
 
169 * styleHeader
170 * styleFooter
171 * tclEval
172 * tclExpr
173 * tclInvoke
174 * tclIsSafe
175 * tclMakeSafe
176 * tclReady
177 * trace
178 * stime
179 * utime
180 * verifyCsrf
181 * wiki
182
183 Each of the commands above is documented by a block comment above their
@@ -249,11 +249,11 @@
249
250 Renders STRING as wiki content; however, only links are handled. No
251 other markup is processed.
252
253 <a name="dir"></a>TH1 dir Command
--------------------------------------------
 
254
255 * dir CHECKIN ?GLOB? ?DETAILS?
256
257 Returns a list containing all files in CHECKIN. If GLOB is given only
258 the files matching the pattern GLOB within CHECKIN will be returned.
@@ -400,11 +400,11 @@
400
401 Returns one more than the number of \n characters in STRING. But
402 never returns less than MIN or more than MAX.
403
404 <a name="markdown"></a>TH1 markdown Command
----------------------------------------------
 
405
406 * markdown STRING
407
408 Renders the input string as markdown. The result is a two-element list.
409 The first element contains the body, rendered as HTML. The second element
@@ -517,10 +517,18 @@
517 -----------------------------------------
518
519 * setting name
520
521 Gets and returns the value of the specified setting.
 
 
 
 
 
 
 
 
522
523 <a name="styleHeader"></a>TH1 styleHeader Command
524 -------------------------------------------------
525
526 * styleHeader TITLE
@@ -577,11 +585,11 @@
577
578 Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
579 will be created automatically if it has not been already.
580
581 <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
----------------------------------------------
 
582
583 **This command requires the Tcl integration feature.**
584
585 * tclMakeSafe
586
@@ -603,18 +611,10 @@
603
604 * trace STRING
605
606 Generates a TH1 trace message if TH1 tracing is enabled.
607
608 <a name="stime"></a>TH1 stime Command
--------------------------------------
609
610 * stime
611
612 Returns the number of microseconds of CPU time consumed by the current
613 process in system space.
614
615 <a name="utime"></a>TH1 utime Command
616 -------------------------------------
617
618 * utime
619
620
--- www/th1.md
+++ www/th1.md
@@ -164,20 +164,20 @@
164 * render
165 * repository
166 * searchable
167 * setParameter
168 * setting
169 * stime
170 * styleHeader
171 * styleFooter
172 * tclEval
173 * tclExpr
174 * tclInvoke
175 * tclIsSafe
176 * tclMakeSafe
177 * tclReady
178 * trace
 
179 * utime
180 * verifyCsrf
181 * wiki
182
183 Each of the commands above is documented by a block comment above their
@@ -249,11 +249,11 @@
249
250 Renders STRING as wiki content; however, only links are handled. No
251 other markup is processed.
252
253 <a name="dir"></a>TH1 dir Command
--------------------------------------------
254 ---------------------------------
255
256 * dir CHECKIN ?GLOB? ?DETAILS?
257
258 Returns a list containing all files in CHECKIN. If GLOB is given only
259 the files matching the pattern GLOB within CHECKIN will be returned.
@@ -400,11 +400,11 @@
400
401 Returns one more than the number of \n characters in STRING. But
402 never returns less than MIN or more than MAX.
403
404 <a name="markdown"></a>TH1 markdown Command
----------------------------------------------
405 -------------------------------------------
406
407 * markdown STRING
408
409 Renders the input string as markdown. The result is a two-element list.
410 The first element contains the body, rendered as HTML. The second element
@@ -517,10 +517,18 @@
517 -----------------------------------------
518
519 * setting name
520
521 Gets and returns the value of the specified setting.
522
523 <a name="stime"></a>TH1 stime Command
524 -------------------------------------
525
526 * stime
527
528 Returns the number of microseconds of CPU time consumed by the current
529 process in system space.
530
531 <a name="styleHeader"></a>TH1 styleHeader Command
532 -------------------------------------------------
533
534 * styleHeader TITLE
@@ -577,11 +585,11 @@
585
586 Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
587 will be created automatically if it has not been already.
588
589 <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
----------------------------------------------
590 -------------------------------------------------
591
592 **This command requires the Tcl integration feature.**
593
594 * tclMakeSafe
595
@@ -603,18 +611,10 @@
611
612 * trace STRING
613
614 Generates a TH1 trace message if TH1 tracing is enabled.
615
 
--------------------------------------
 
 
 
 
 
 
616 <a name="utime"></a>TH1 utime Command
617 -------------------------------------
618
619 * utime
620
621

Keyboard Shortcuts

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