Fossil SCM

Merge enhancements and fixes from trunk.

drh 2015-02-13 21:21 UTC search-enhancements merge
Commit 23c86b503f0f0336703270b47a07b19240aa0859
+2 -2
--- src/attach.c
+++ src/attach.c
@@ -443,11 +443,11 @@
443443
}
444444
445445
if( P("del")
446446
&& ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
447447
){
448
- form_begin(0, "%R/ainfo/%s", zUuid);
448
+ form_begin(0, "%R/ainfo/%!S", zUuid);
449449
@ <p>Confirm you want to delete the attachment shown below.
450450
@ <input type="submit" name="confirm" value="Confirm">
451451
@ </form>
452452
}
453453
@@ -456,11 +456,11 @@
456456
(zWikiName && g.perm.ModWiki);
457457
if( isModerator && (zModAction = P("modaction"))!=0 ){
458458
if( strcmp(zModAction,"delete")==0 ){
459459
moderation_disapprove(rid);
460460
if( zTktUuid ){
461
- cgi_redirectf("%R/tktview/%s", zTktUuid);
461
+ cgi_redirectf("%R/tktview/%!S", zTktUuid);
462462
}else{
463463
cgi_redirectf("%R/wiki?name=%t", zWikiName);
464464
}
465465
return;
466466
}
467467
--- src/attach.c
+++ src/attach.c
@@ -443,11 +443,11 @@
443 }
444
445 if( P("del")
446 && ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
447 ){
448 form_begin(0, "%R/ainfo/%s", zUuid);
449 @ <p>Confirm you want to delete the attachment shown below.
450 @ <input type="submit" name="confirm" value="Confirm">
451 @ </form>
452 }
453
@@ -456,11 +456,11 @@
456 (zWikiName && g.perm.ModWiki);
457 if( isModerator && (zModAction = P("modaction"))!=0 ){
458 if( strcmp(zModAction,"delete")==0 ){
459 moderation_disapprove(rid);
460 if( zTktUuid ){
461 cgi_redirectf("%R/tktview/%s", zTktUuid);
462 }else{
463 cgi_redirectf("%R/wiki?name=%t", zWikiName);
464 }
465 return;
466 }
467
--- src/attach.c
+++ src/attach.c
@@ -443,11 +443,11 @@
443 }
444
445 if( P("del")
446 && ((zTktUuid && g.perm.WrTkt) || (zWikiName && g.perm.WrWiki))
447 ){
448 form_begin(0, "%R/ainfo/%!S", zUuid);
449 @ <p>Confirm you want to delete the attachment shown below.
450 @ <input type="submit" name="confirm" value="Confirm">
451 @ </form>
452 }
453
@@ -456,11 +456,11 @@
456 (zWikiName && g.perm.ModWiki);
457 if( isModerator && (zModAction = P("modaction"))!=0 ){
458 if( strcmp(zModAction,"delete")==0 ){
459 moderation_disapprove(rid);
460 if( zTktUuid ){
461 cgi_redirectf("%R/tktview/%!S", zTktUuid);
462 }else{
463 cgi_redirectf("%R/wiki?name=%t", zWikiName);
464 }
465 return;
466 }
467
+1 -1
--- src/branch.c
+++ src/branch.c
@@ -159,11 +159,11 @@
159159
fossil_fatal("%s\n", g.zErrMsg);
160160
}
161161
assert( blob_is_reset(&branch) );
162162
content_deltify(rootid, brid, 0);
163163
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164
- fossil_print("New branch: %s\n", zUuid);
164
+ fossil_print("New branch: %S\n", zUuid);
165165
if( g.argc==3 ){
166166
fossil_print(
167167
"\n"
168168
"Note: the local check-out has not been updated to the new\n"
169169
" branch. To begin working on the new branch, do this:\n"
170170
--- src/branch.c
+++ src/branch.c
@@ -159,11 +159,11 @@
159 fossil_fatal("%s\n", g.zErrMsg);
160 }
161 assert( blob_is_reset(&branch) );
162 content_deltify(rootid, brid, 0);
163 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164 fossil_print("New branch: %s\n", zUuid);
165 if( g.argc==3 ){
166 fossil_print(
167 "\n"
168 "Note: the local check-out has not been updated to the new\n"
169 " branch. To begin working on the new branch, do this:\n"
170
--- src/branch.c
+++ src/branch.c
@@ -159,11 +159,11 @@
159 fossil_fatal("%s\n", g.zErrMsg);
160 }
161 assert( blob_is_reset(&branch) );
162 content_deltify(rootid, brid, 0);
163 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164 fossil_print("New branch: %S\n", zUuid);
165 if( g.argc==3 ){
166 fossil_print(
167 "\n"
168 "Note: the local check-out has not been updated to the new\n"
169 " branch. To begin working on the new branch, do this:\n"
170
+2 -2
--- src/browse.c
+++ src/browse.c
@@ -181,13 +181,13 @@
181181
url_render(&sURI, "ci", "tip", 0, 0));
182182
}
183183
if( zCI ){
184184
@ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
185185
@ %s(blob_str(&dirname))</h2>
186
- zSubdirLink = mprintf("%R/dir?ci=%s&name=%T", zUuid, zPrefix);
186
+ zSubdirLink = mprintf("%R/dir?name=%T&ci=%!S", zPrefix, zUuid);
187187
if( nD==0 ){
188
- style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
188
+ style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%!S",
189189
zUuid);
190190
}
191191
}else{
192192
@ <h2>The union of all files from all check-ins
193193
@ %s(blob_str(&dirname))</h2>
194194
--- src/browse.c
+++ src/browse.c
@@ -181,13 +181,13 @@
181 url_render(&sURI, "ci", "tip", 0, 0));
182 }
183 if( zCI ){
184 @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
185 @ %s(blob_str(&dirname))</h2>
186 zSubdirLink = mprintf("%R/dir?ci=%s&name=%T", zUuid, zPrefix);
187 if( nD==0 ){
188 style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
189 zUuid);
190 }
191 }else{
192 @ <h2>The union of all files from all check-ins
193 @ %s(blob_str(&dirname))</h2>
194
--- src/browse.c
+++ src/browse.c
@@ -181,13 +181,13 @@
181 url_render(&sURI, "ci", "tip", 0, 0));
182 }
183 if( zCI ){
184 @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
185 @ %s(blob_str(&dirname))</h2>
186 zSubdirLink = mprintf("%R/dir?name=%T&ci=%!S", zPrefix, zUuid);
187 if( nD==0 ){
188 style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%!S",
189 zUuid);
190 }
191 }else{
192 @ <h2>The union of all files from all check-ins
193 @ %s(blob_str(&dirname))</h2>
194
+3 -3
--- src/checkin.c
+++ src/checkin.c
@@ -1936,18 +1936,18 @@
19361936
db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
19371937
" WHERE id=-4");
19381938
while( db_step(&q)==SQLITE_ROW ){
19391939
const char *zIntegrateUuid = db_column_text(&q, 0);
19401940
if( is_a_leaf(db_column_int(&q, 1)) ){
1941
- fossil_print("Closed: %s\n", zIntegrateUuid);
1941
+ fossil_print("Closed: %S\n", zIntegrateUuid);
19421942
}else{
1943
- fossil_print("Not_Closed: %s (not a leaf any more)\n", zIntegrateUuid);
1943
+ fossil_print("Not_Closed: %S (not a leaf any more)\n", zIntegrateUuid);
19441944
}
19451945
}
19461946
db_finalize(&q);
19471947
1948
- fossil_print("New_Version: %s\n", zUuid);
1948
+ fossil_print("New_Version: %S\n", zUuid);
19491949
if( outputManifest ){
19501950
zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
19511951
blob_zero(&muuid);
19521952
blob_appendf(&muuid, "%s\n", zUuid);
19531953
blob_write_to_file(&muuid, zManifestFile);
19541954
--- src/checkin.c
+++ src/checkin.c
@@ -1936,18 +1936,18 @@
1936 db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
1937 " WHERE id=-4");
1938 while( db_step(&q)==SQLITE_ROW ){
1939 const char *zIntegrateUuid = db_column_text(&q, 0);
1940 if( is_a_leaf(db_column_int(&q, 1)) ){
1941 fossil_print("Closed: %s\n", zIntegrateUuid);
1942 }else{
1943 fossil_print("Not_Closed: %s (not a leaf any more)\n", zIntegrateUuid);
1944 }
1945 }
1946 db_finalize(&q);
1947
1948 fossil_print("New_Version: %s\n", zUuid);
1949 if( outputManifest ){
1950 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
1951 blob_zero(&muuid);
1952 blob_appendf(&muuid, "%s\n", zUuid);
1953 blob_write_to_file(&muuid, zManifestFile);
1954
--- src/checkin.c
+++ src/checkin.c
@@ -1936,18 +1936,18 @@
1936 db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
1937 " WHERE id=-4");
1938 while( db_step(&q)==SQLITE_ROW ){
1939 const char *zIntegrateUuid = db_column_text(&q, 0);
1940 if( is_a_leaf(db_column_int(&q, 1)) ){
1941 fossil_print("Closed: %S\n", zIntegrateUuid);
1942 }else{
1943 fossil_print("Not_Closed: %S (not a leaf any more)\n", zIntegrateUuid);
1944 }
1945 }
1946 db_finalize(&q);
1947
1948 fossil_print("New_Version: %S\n", zUuid);
1949 if( outputManifest ){
1950 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
1951 blob_zero(&muuid);
1952 blob_appendf(&muuid, "%s\n", zUuid);
1953 blob_write_to_file(&muuid, zManifestFile);
1954
+4
--- src/db.c
+++ src/db.c
@@ -2389,10 +2389,11 @@
23892389
{ "editor", 0, 32, 0, 0, "" },
23902390
{ "empty-dirs", 0, 40, 1, 0, "" },
23912391
{ "encoding-glob", 0, 40, 1, 0, "" },
23922392
{ "gdiff-command", 0, 40, 0, 0, "gdiff" },
23932393
{ "gmerge-command", 0, 40, 0, 0, "" },
2394
+ { "hash-digits", 0, 5, 0, 0, "10" },
23942395
{ "http-port", 0, 16, 0, 0, "8080" },
23952396
{ "https-login", 0, 0, 0, 0, "off" },
23962397
{ "ignore-glob", 0, 40, 1, 0, "" },
23972398
{ "keep-glob", 0, 40, 1, 0, "" },
23982399
{ "localauth", 0, 0, 0, 0, "off" },
@@ -2565,10 +2566,13 @@
25652566
** gmerge-command A graphical merge conflict resolver command operating
25662567
** on four files.
25672568
** Ex: kdiff3 "%baseline" "%original" "%merge" -o "%output"
25682569
** Ex: xxdiff "%original" "%baseline" "%merge" -M "%output"
25692570
** Ex: meld "%baseline" "%original" "%merge" "%output"
2571
+**
2572
+** hash-digits The number of hexadecimal digits of the SHA1 hash to
2573
+** display. (Default: 10; Minimum: 6)
25702574
**
25712575
** http-port The TCP/IP port number to use by the "server"
25722576
** and "ui" commands. Default: 8080
25732577
**
25742578
** https-login Send login credentials using HTTPS instead of HTTP
25752579
--- src/db.c
+++ src/db.c
@@ -2389,10 +2389,11 @@
2389 { "editor", 0, 32, 0, 0, "" },
2390 { "empty-dirs", 0, 40, 1, 0, "" },
2391 { "encoding-glob", 0, 40, 1, 0, "" },
2392 { "gdiff-command", 0, 40, 0, 0, "gdiff" },
2393 { "gmerge-command", 0, 40, 0, 0, "" },
 
2394 { "http-port", 0, 16, 0, 0, "8080" },
2395 { "https-login", 0, 0, 0, 0, "off" },
2396 { "ignore-glob", 0, 40, 1, 0, "" },
2397 { "keep-glob", 0, 40, 1, 0, "" },
2398 { "localauth", 0, 0, 0, 0, "off" },
@@ -2565,10 +2566,13 @@
2565 ** gmerge-command A graphical merge conflict resolver command operating
2566 ** on four files.
2567 ** Ex: kdiff3 "%baseline" "%original" "%merge" -o "%output"
2568 ** Ex: xxdiff "%original" "%baseline" "%merge" -M "%output"
2569 ** Ex: meld "%baseline" "%original" "%merge" "%output"
 
 
 
2570 **
2571 ** http-port The TCP/IP port number to use by the "server"
2572 ** and "ui" commands. Default: 8080
2573 **
2574 ** https-login Send login credentials using HTTPS instead of HTTP
2575
--- src/db.c
+++ src/db.c
@@ -2389,10 +2389,11 @@
2389 { "editor", 0, 32, 0, 0, "" },
2390 { "empty-dirs", 0, 40, 1, 0, "" },
2391 { "encoding-glob", 0, 40, 1, 0, "" },
2392 { "gdiff-command", 0, 40, 0, 0, "gdiff" },
2393 { "gmerge-command", 0, 40, 0, 0, "" },
2394 { "hash-digits", 0, 5, 0, 0, "10" },
2395 { "http-port", 0, 16, 0, 0, "8080" },
2396 { "https-login", 0, 0, 0, 0, "off" },
2397 { "ignore-glob", 0, 40, 1, 0, "" },
2398 { "keep-glob", 0, 40, 1, 0, "" },
2399 { "localauth", 0, 0, 0, 0, "off" },
@@ -2565,10 +2566,13 @@
2566 ** gmerge-command A graphical merge conflict resolver command operating
2567 ** on four files.
2568 ** Ex: kdiff3 "%baseline" "%original" "%merge" -o "%output"
2569 ** Ex: xxdiff "%original" "%baseline" "%merge" -M "%output"
2570 ** Ex: meld "%baseline" "%original" "%merge" "%output"
2571 **
2572 ** hash-digits The number of hexadecimal digits of the SHA1 hash to
2573 ** display. (Default: 10; Minimum: 6)
2574 **
2575 ** http-port The TCP/IP port number to use by the "server"
2576 ** and "ui" commands. Default: 8080
2577 **
2578 ** https-login Send login credentials using HTTPS instead of HTTP
2579
+18 -6
--- src/doc.c
+++ src/doc.c
@@ -106,10 +106,11 @@
106106
{ "com", 3, "application/x-msdos-program" },
107107
{ "cpio", 4, "application/x-cpio" },
108108
{ "cpt", 3, "application/mac-compactpro" },
109109
{ "csh", 3, "application/x-csh" },
110110
{ "css", 3, "text/css" },
111
+ { "csv", 3, "text/csv" },
111112
{ "dcr", 3, "application/x-director" },
112113
{ "deb", 3, "application/x-debian-package" },
113114
{ "dir", 3, "application/x-director" },
114115
{ "dl", 2, "video/dl" },
115116
{ "dms", 3, "application/octet-stream" },
@@ -291,10 +292,24 @@
291292
{ "xpm", 3, "image/x-xpixmap" },
292293
{ "xwd", 3, "image/x-xwindowdump" },
293294
{ "xyz", 3, "chemical/x-pdb" },
294295
{ "zip", 3, "application/zip" },
295296
};
297
+
298
+/*
299
+** Verify that all entries in the aMime[] table are in sorted order.
300
+** Abort with a fatal error if any is out-of-order.
301
+*/
302
+static void mimetype_verify(void){
303
+ int i;
304
+ for(i=1; i<ArraySize(aMime); i++){
305
+ if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
306
+ fossil_fatal("mimetypes out of sequence: %s before %s",
307
+ aMime[i-1].zSuffix, aMime[i].zSuffix);
308
+ }
309
+ }
310
+}
296311
297312
/*
298313
** Guess the mime-type of a document based on its name.
299314
*/
300315
const char *mimetype_from_name(const char *zName){
@@ -308,16 +323,11 @@
308323
#ifdef FOSSIL_DEBUG
309324
/* This is test code to make sure the table above is in the correct
310325
** order
311326
*/
312327
if( fossil_strcmp(zName, "mimetype-test")==0 ){
313
- for(i=1; i<ArraySize(aMime); i++){
314
- if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
315
- fossil_fatal("mimetypes out of sequence: %s before %s",
316
- aMime[i-1].zSuffix, aMime[i].zSuffix);
317
- }
318
- }
328
+ mimetype_verify();
319329
return "ok";
320330
}
321331
#endif
322332
323333
z = zName;
@@ -356,10 +366,11 @@
356366
** filename is special and verifies the integrity of the mimetype table.
357367
** It should return "ok".
358368
*/
359369
void mimetype_test_cmd(void){
360370
int i;
371
+ mimetype_verify();
361372
for(i=2; i<g.argc; i++){
362373
fossil_print("%-20s -> %s\n", g.argv[i], mimetype_from_name(g.argv[i]));
363374
}
364375
}
365376
@@ -369,10 +380,11 @@
369380
** Show the built-in table used to guess embedded document mimetypes
370381
** from file suffixes.
371382
*/
372383
void mimetype_list_page(void){
373384
int i;
385
+ mimetype_verify();
374386
style_header("Mimetype List");
375387
@ <p>The Fossil <a href="%R/help?cmd=/doc">/doc</a> page uses filename
376388
@ suffixes and the following table to guess at the appropriate mimetype
377389
@ for each document.</p>
378390
@ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'>
379391
--- src/doc.c
+++ src/doc.c
@@ -106,10 +106,11 @@
106 { "com", 3, "application/x-msdos-program" },
107 { "cpio", 4, "application/x-cpio" },
108 { "cpt", 3, "application/mac-compactpro" },
109 { "csh", 3, "application/x-csh" },
110 { "css", 3, "text/css" },
 
111 { "dcr", 3, "application/x-director" },
112 { "deb", 3, "application/x-debian-package" },
113 { "dir", 3, "application/x-director" },
114 { "dl", 2, "video/dl" },
115 { "dms", 3, "application/octet-stream" },
@@ -291,10 +292,24 @@
291 { "xpm", 3, "image/x-xpixmap" },
292 { "xwd", 3, "image/x-xwindowdump" },
293 { "xyz", 3, "chemical/x-pdb" },
294 { "zip", 3, "application/zip" },
295 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
297 /*
298 ** Guess the mime-type of a document based on its name.
299 */
300 const char *mimetype_from_name(const char *zName){
@@ -308,16 +323,11 @@
308 #ifdef FOSSIL_DEBUG
309 /* This is test code to make sure the table above is in the correct
310 ** order
311 */
312 if( fossil_strcmp(zName, "mimetype-test")==0 ){
313 for(i=1; i<ArraySize(aMime); i++){
314 if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
315 fossil_fatal("mimetypes out of sequence: %s before %s",
316 aMime[i-1].zSuffix, aMime[i].zSuffix);
317 }
318 }
319 return "ok";
320 }
321 #endif
322
323 z = zName;
@@ -356,10 +366,11 @@
356 ** filename is special and verifies the integrity of the mimetype table.
357 ** It should return "ok".
358 */
359 void mimetype_test_cmd(void){
360 int i;
 
361 for(i=2; i<g.argc; i++){
362 fossil_print("%-20s -> %s\n", g.argv[i], mimetype_from_name(g.argv[i]));
363 }
364 }
365
@@ -369,10 +380,11 @@
369 ** Show the built-in table used to guess embedded document mimetypes
370 ** from file suffixes.
371 */
372 void mimetype_list_page(void){
373 int i;
 
374 style_header("Mimetype List");
375 @ <p>The Fossil <a href="%R/help?cmd=/doc">/doc</a> page uses filename
376 @ suffixes and the following table to guess at the appropriate mimetype
377 @ for each document.</p>
378 @ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'>
379
--- src/doc.c
+++ src/doc.c
@@ -106,10 +106,11 @@
106 { "com", 3, "application/x-msdos-program" },
107 { "cpio", 4, "application/x-cpio" },
108 { "cpt", 3, "application/mac-compactpro" },
109 { "csh", 3, "application/x-csh" },
110 { "css", 3, "text/css" },
111 { "csv", 3, "text/csv" },
112 { "dcr", 3, "application/x-director" },
113 { "deb", 3, "application/x-debian-package" },
114 { "dir", 3, "application/x-director" },
115 { "dl", 2, "video/dl" },
116 { "dms", 3, "application/octet-stream" },
@@ -291,10 +292,24 @@
292 { "xpm", 3, "image/x-xpixmap" },
293 { "xwd", 3, "image/x-xwindowdump" },
294 { "xyz", 3, "chemical/x-pdb" },
295 { "zip", 3, "application/zip" },
296 };
297
298 /*
299 ** Verify that all entries in the aMime[] table are in sorted order.
300 ** Abort with a fatal error if any is out-of-order.
301 */
302 static void mimetype_verify(void){
303 int i;
304 for(i=1; i<ArraySize(aMime); i++){
305 if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
306 fossil_fatal("mimetypes out of sequence: %s before %s",
307 aMime[i-1].zSuffix, aMime[i].zSuffix);
308 }
309 }
310 }
311
312 /*
313 ** Guess the mime-type of a document based on its name.
314 */
315 const char *mimetype_from_name(const char *zName){
@@ -308,16 +323,11 @@
323 #ifdef FOSSIL_DEBUG
324 /* This is test code to make sure the table above is in the correct
325 ** order
326 */
327 if( fossil_strcmp(zName, "mimetype-test")==0 ){
328 mimetype_verify();
 
 
 
 
 
329 return "ok";
330 }
331 #endif
332
333 z = zName;
@@ -356,10 +366,11 @@
366 ** filename is special and verifies the integrity of the mimetype table.
367 ** It should return "ok".
368 */
369 void mimetype_test_cmd(void){
370 int i;
371 mimetype_verify();
372 for(i=2; i<g.argc; i++){
373 fossil_print("%-20s -> %s\n", g.argv[i], mimetype_from_name(g.argv[i]));
374 }
375 }
376
@@ -369,10 +380,11 @@
380 ** Show the built-in table used to guess embedded document mimetypes
381 ** from file suffixes.
382 */
383 void mimetype_list_page(void){
384 int i;
385 mimetype_verify();
386 style_header("Mimetype List");
387 @ <p>The Fossil <a href="%R/help?cmd=/doc">/doc</a> page uses filename
388 @ suffixes and the following table to guess at the appropriate mimetype
389 @ for each document.</p>
390 @ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'>
391
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -215,11 +215,11 @@
215215
zCiUuid, zCom, zUser, zFileUuid, zBr);
216216
comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
217217
fossil_free(zOut);
218218
}else{
219219
blob_reset(&line);
220
- blob_appendf(&line, "%.10s ", zCiUuid);
220
+ blob_appendf(&line, "%S ", zCiUuid);
221221
blob_appendf(&line, "%.10s ", zDate);
222222
blob_appendf(&line, "%8.8s ", zUser);
223223
blob_appendf(&line, "%8.8s ", zBr);
224224
blob_appendf(&line,"%-39.39s", zCom );
225225
comment_print(blob_str(&line), zCom, 0, iWidth, g.comFmtFlags);
226226
--- src/finfo.c
+++ src/finfo.c
@@ -215,11 +215,11 @@
215 zCiUuid, zCom, zUser, zFileUuid, zBr);
216 comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
217 fossil_free(zOut);
218 }else{
219 blob_reset(&line);
220 blob_appendf(&line, "%.10s ", zCiUuid);
221 blob_appendf(&line, "%.10s ", zDate);
222 blob_appendf(&line, "%8.8s ", zUser);
223 blob_appendf(&line, "%8.8s ", zBr);
224 blob_appendf(&line,"%-39.39s", zCom );
225 comment_print(blob_str(&line), zCom, 0, iWidth, g.comFmtFlags);
226
--- src/finfo.c
+++ src/finfo.c
@@ -215,11 +215,11 @@
215 zCiUuid, zCom, zUser, zFileUuid, zBr);
216 comment_print(zOut, zCom, 11, iWidth, g.comFmtFlags);
217 fossil_free(zOut);
218 }else{
219 blob_reset(&line);
220 blob_appendf(&line, "%S ", zCiUuid);
221 blob_appendf(&line, "%.10s ", zDate);
222 blob_appendf(&line, "%8.8s ", zUser);
223 blob_appendf(&line, "%8.8s ", zBr);
224 blob_appendf(&line,"%-39.39s", zCom );
225 comment_print(blob_str(&line), zCom, 0, iWidth, g.comFmtFlags);
226
+2 -2
--- src/info.c
+++ src/info.c
@@ -1336,11 +1336,11 @@
13361336
}
13371337
@ - %!w(zCom) by
13381338
hyperlink_to_user(zUser,zDate," on");
13391339
hyperlink_to_date(zDate, ".");
13401340
if( pDownloadName && blob_size(pDownloadName)==0 ){
1341
- blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1341
+ blob_appendf(pDownloadName, "%S.txt", zUuid);
13421342
}
13431343
tag_private_status(rid);
13441344
cnt++;
13451345
}
13461346
db_finalize(&q);
@@ -1388,11 +1388,11 @@
13881388
}
13891389
db_finalize(&q);
13901390
if( cnt==0 ){
13911391
@ Control artifact.
13921392
if( pDownloadName && blob_size(pDownloadName)==0 ){
1393
- blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1393
+ blob_appendf(pDownloadName, "%S.txt", zUuid);
13941394
}
13951395
tag_private_status(rid);
13961396
}
13971397
return objType;
13981398
}
13991399
--- src/info.c
+++ src/info.c
@@ -1336,11 +1336,11 @@
1336 }
1337 @ - %!w(zCom) by
1338 hyperlink_to_user(zUser,zDate," on");
1339 hyperlink_to_date(zDate, ".");
1340 if( pDownloadName && blob_size(pDownloadName)==0 ){
1341 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1342 }
1343 tag_private_status(rid);
1344 cnt++;
1345 }
1346 db_finalize(&q);
@@ -1388,11 +1388,11 @@
1388 }
1389 db_finalize(&q);
1390 if( cnt==0 ){
1391 @ Control artifact.
1392 if( pDownloadName && blob_size(pDownloadName)==0 ){
1393 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1394 }
1395 tag_private_status(rid);
1396 }
1397 return objType;
1398 }
1399
--- src/info.c
+++ src/info.c
@@ -1336,11 +1336,11 @@
1336 }
1337 @ - %!w(zCom) by
1338 hyperlink_to_user(zUser,zDate," on");
1339 hyperlink_to_date(zDate, ".");
1340 if( pDownloadName && blob_size(pDownloadName)==0 ){
1341 blob_appendf(pDownloadName, "%S.txt", zUuid);
1342 }
1343 tag_private_status(rid);
1344 cnt++;
1345 }
1346 db_finalize(&q);
@@ -1388,11 +1388,11 @@
1388 }
1389 db_finalize(&q);
1390 if( cnt==0 ){
1391 @ Control artifact.
1392 if( pDownloadName && blob_size(pDownloadName)==0 ){
1393 blob_appendf(pDownloadName, "%S.txt", zUuid);
1394 }
1395 tag_private_status(rid);
1396 }
1397 return objType;
1398 }
1399
+33 -10
--- src/printf.c
+++ src/printf.c
@@ -29,18 +29,42 @@
2929
/* Two custom conversions are used to show a prefix of SHA1 hashes:
3030
**
3131
** %!S Prefix of a length appropriate for URLs
3232
** %S Prefix of a length appropriate for human display
3333
**
34
-** The following macros determine those lengths.
35
-*/
36
-#ifndef FOSSIL_SHA1_PREFIX_LEN
37
-# define FOSSIL_SHA1_PREFIX_LEN 10 /* For %S (human display) */
38
-#endif
39
-#ifndef FOSSIL_SHA1_URLPREFIX_LEN
40
-# define FOSSIL_SHA1_URLPREFIX_LEN 16 /* For %!S (embedded in URLs) */
41
-#endif
34
+** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
35
+** is the default number of digits to display to humans. This value can
36
+** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
37
+** is the minimum number of digits to be used in URLs. The number used
38
+** will always be at least 6 more than the number used for human output,
39
+** or 40 if the number of digits in human output is 34 or more.
40
+*/
41
+#ifndef FOSSIL_HASH_DIGITS
42
+# define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
43
+#endif
44
+#ifndef FOSSIL_HASH_DIGITS_URL
45
+# define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */
46
+#endif
47
+
48
+/*
49
+** Return the number of SHA1 hash digits to display. The number is for
50
+** human output if the bForUrl is false and is destined for a URL if
51
+** bForUrl is false.
52
+*/
53
+static int hashDigits(int bForUrl){
54
+ static int nDigitHuman = 0;
55
+ static int nDigitUrl = 0;
56
+ if( nDigitHuman==0 ){
57
+ nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
58
+ if( nDigitHuman < 6 ) nDigitHuman = 6;
59
+ if( nDigitHuman > 40 ) nDigitHuman = 40;
60
+ nDigitUrl = nDigitHuman + 6;
61
+ if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62
+ if( nDigitUrl > 40 ) nDigitUrl = 40;
63
+ }
64
+ return bForUrl ? nDigitUrl : nDigitHuman;
65
+}
4266
4367
/*
4468
** Conversion types fall into various categories as defined by the
4569
** following enumeration.
4670
*/
@@ -634,12 +658,11 @@
634658
if( bufpt==0 ){
635659
bufpt = "";
636660
}else if( xtype==etDYNSTRING ){
637661
zExtra = bufpt;
638662
}else if( xtype==etSTRINGID ){
639
- precision = flag_altform2 ? FOSSIL_SHA1_URLPREFIX_LEN :
640
- FOSSIL_SHA1_PREFIX_LEN;
663
+ precision = hashDigits(flag_altform2);
641664
}
642665
length = StrNLen32(bufpt, limit);
643666
if( precision>=0 && precision<length ) length = precision;
644667
break;
645668
}
646669
--- src/printf.c
+++ src/printf.c
@@ -29,18 +29,42 @@
29 /* Two custom conversions are used to show a prefix of SHA1 hashes:
30 **
31 ** %!S Prefix of a length appropriate for URLs
32 ** %S Prefix of a length appropriate for human display
33 **
34 ** The following macros determine those lengths.
35 */
36 #ifndef FOSSIL_SHA1_PREFIX_LEN
37 # define FOSSIL_SHA1_PREFIX_LEN 10 /* For %S (human display) */
38 #endif
39 #ifndef FOSSIL_SHA1_URLPREFIX_LEN
40 # define FOSSIL_SHA1_URLPREFIX_LEN 16 /* For %!S (embedded in URLs) */
41 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
43 /*
44 ** Conversion types fall into various categories as defined by the
45 ** following enumeration.
46 */
@@ -634,12 +658,11 @@
634 if( bufpt==0 ){
635 bufpt = "";
636 }else if( xtype==etDYNSTRING ){
637 zExtra = bufpt;
638 }else if( xtype==etSTRINGID ){
639 precision = flag_altform2 ? FOSSIL_SHA1_URLPREFIX_LEN :
640 FOSSIL_SHA1_PREFIX_LEN;
641 }
642 length = StrNLen32(bufpt, limit);
643 if( precision>=0 && precision<length ) length = precision;
644 break;
645 }
646
--- src/printf.c
+++ src/printf.c
@@ -29,18 +29,42 @@
29 /* Two custom conversions are used to show a prefix of SHA1 hashes:
30 **
31 ** %!S Prefix of a length appropriate for URLs
32 ** %S Prefix of a length appropriate for human display
33 **
34 ** The following macros help determine those lengths. FOSSIL_HASH_DIGITS
35 ** is the default number of digits to display to humans. This value can
36 ** be overridden using the hash-digits setting. FOSSIL_HASH_DIGITS_URL
37 ** is the minimum number of digits to be used in URLs. The number used
38 ** will always be at least 6 more than the number used for human output,
39 ** or 40 if the number of digits in human output is 34 or more.
40 */
41 #ifndef FOSSIL_HASH_DIGITS
42 # define FOSSIL_HASH_DIGITS 10 /* For %S (human display) */
43 #endif
44 #ifndef FOSSIL_HASH_DIGITS_URL
45 # define FOSSIL_HASH_DIGITS_URL 16 /* For %!S (embedded in URLs) */
46 #endif
47
48 /*
49 ** Return the number of SHA1 hash digits to display. The number is for
50 ** human output if the bForUrl is false and is destined for a URL if
51 ** bForUrl is false.
52 */
53 static int hashDigits(int bForUrl){
54 static int nDigitHuman = 0;
55 static int nDigitUrl = 0;
56 if( nDigitHuman==0 ){
57 nDigitHuman = db_get_int("hash-digits", FOSSIL_HASH_DIGITS);
58 if( nDigitHuman < 6 ) nDigitHuman = 6;
59 if( nDigitHuman > 40 ) nDigitHuman = 40;
60 nDigitUrl = nDigitHuman + 6;
61 if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
62 if( nDigitUrl > 40 ) nDigitUrl = 40;
63 }
64 return bForUrl ? nDigitUrl : nDigitHuman;
65 }
66
67 /*
68 ** Conversion types fall into various categories as defined by the
69 ** following enumeration.
70 */
@@ -634,12 +658,11 @@
658 if( bufpt==0 ){
659 bufpt = "";
660 }else if( xtype==etDYNSTRING ){
661 zExtra = bufpt;
662 }else if( xtype==etSTRINGID ){
663 precision = hashDigits(flag_altform2);
 
664 }
665 length = StrNLen32(bufpt, limit);
666 if( precision>=0 && precision<length ) length = precision;
667 break;
668 }
669
+1 -1
--- src/search.c
+++ src/search.c
@@ -993,11 +993,11 @@
993993
static void get_stext_by_mimetype(
994994
Blob *pIn,
995995
const char *zMimetype,
996996
Blob *pOut
997997
){
998
- Blob html, title, tail;
998
+ Blob html, title;
999999
blob_init(&html, 0, 0);
10001000
blob_init(&title, 0, 0);
10011001
if( zMimetype==0 ) zMimetype = "text/plain";
10021002
if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 ){
10031003
Blob tail;
10041004
--- src/search.c
+++ src/search.c
@@ -993,11 +993,11 @@
993 static void get_stext_by_mimetype(
994 Blob *pIn,
995 const char *zMimetype,
996 Blob *pOut
997 ){
998 Blob html, title, tail;
999 blob_init(&html, 0, 0);
1000 blob_init(&title, 0, 0);
1001 if( zMimetype==0 ) zMimetype = "text/plain";
1002 if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 ){
1003 Blob tail;
1004
--- src/search.c
+++ src/search.c
@@ -993,11 +993,11 @@
993 static void get_stext_by_mimetype(
994 Blob *pIn,
995 const char *zMimetype,
996 Blob *pOut
997 ){
998 Blob html, title;
999 blob_init(&html, 0, 0);
1000 blob_init(&title, 0, 0);
1001 if( zMimetype==0 ) zMimetype = "text/plain";
1002 if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 ){
1003 Blob tail;
1004
+1 -1
--- src/search.c
+++ src/search.c
@@ -993,11 +993,11 @@
993993
static void get_stext_by_mimetype(
994994
Blob *pIn,
995995
const char *zMimetype,
996996
Blob *pOut
997997
){
998
- Blob html, title, tail;
998
+ Blob html, title;
999999
blob_init(&html, 0, 0);
10001000
blob_init(&title, 0, 0);
10011001
if( zMimetype==0 ) zMimetype = "text/plain";
10021002
if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 ){
10031003
Blob tail;
10041004
--- src/search.c
+++ src/search.c
@@ -993,11 +993,11 @@
993 static void get_stext_by_mimetype(
994 Blob *pIn,
995 const char *zMimetype,
996 Blob *pOut
997 ){
998 Blob html, title, tail;
999 blob_init(&html, 0, 0);
1000 blob_init(&title, 0, 0);
1001 if( zMimetype==0 ) zMimetype = "text/plain";
1002 if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 ){
1003 Blob tail;
1004
--- src/search.c
+++ src/search.c
@@ -993,11 +993,11 @@
993 static void get_stext_by_mimetype(
994 Blob *pIn,
995 const char *zMimetype,
996 Blob *pOut
997 ){
998 Blob html, title;
999 blob_init(&html, 0, 0);
1000 blob_init(&title, 0, 0);
1001 if( zMimetype==0 ) zMimetype = "text/plain";
1002 if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0 ){
1003 Blob tail;
1004
+2 -2
--- src/setup.c
+++ src/setup.c
@@ -1708,11 +1708,11 @@
17081708
login_insert_csrf_secret();
17091709
@ <hr />
17101710
onoff_attribute("Moderate ticket changes",
17111711
"modreq-tkt", "modreq-tkt", 0, 0);
17121712
@ <p>When enabled, any change to tickets is subject to the approval
1713
- @ a ticket moderator - a user with the "q" or Mod-Tkt privilege.
1713
+ @ by a ticket moderator - a user with the "q" or Mod-Tkt privilege.
17141714
@ Ticket changes enter the system and are shown locally, but are not
17151715
@ synced until they are approved. The moderator has the option to
17161716
@ delete the change rather than approve it. Ticket changes made by
17171717
@ a user who has the Mod-Tkt privilege are never subject to
17181718
@ moderation.
@@ -1719,11 +1719,11 @@
17191719
@
17201720
@ <hr />
17211721
onoff_attribute("Moderate wiki changes",
17221722
"modreq-wiki", "modreq-wiki", 0, 0);
17231723
@ <p>When enabled, any change to wiki is subject to the approval
1724
- @ a ticket moderator - a user with the "l" or Mod-Wiki privilege.
1724
+ @ by a wiki moderator - a user with the "l" or Mod-Wiki privilege.
17251725
@ Wiki changes enter the system and are shown locally, but are not
17261726
@ synced until they are approved. The moderator has the option to
17271727
@ delete the change rather than approve it. Wiki changes made by
17281728
@ a user who has the Mod-Wiki privilege are never subject to
17291729
@ moderation.
17301730
--- src/setup.c
+++ src/setup.c
@@ -1708,11 +1708,11 @@
1708 login_insert_csrf_secret();
1709 @ <hr />
1710 onoff_attribute("Moderate ticket changes",
1711 "modreq-tkt", "modreq-tkt", 0, 0);
1712 @ <p>When enabled, any change to tickets is subject to the approval
1713 @ a ticket moderator - a user with the "q" or Mod-Tkt privilege.
1714 @ Ticket changes enter the system and are shown locally, but are not
1715 @ synced until they are approved. The moderator has the option to
1716 @ delete the change rather than approve it. Ticket changes made by
1717 @ a user who has the Mod-Tkt privilege are never subject to
1718 @ moderation.
@@ -1719,11 +1719,11 @@
1719 @
1720 @ <hr />
1721 onoff_attribute("Moderate wiki changes",
1722 "modreq-wiki", "modreq-wiki", 0, 0);
1723 @ <p>When enabled, any change to wiki is subject to the approval
1724 @ a ticket moderator - a user with the "l" or Mod-Wiki privilege.
1725 @ Wiki changes enter the system and are shown locally, but are not
1726 @ synced until they are approved. The moderator has the option to
1727 @ delete the change rather than approve it. Wiki changes made by
1728 @ a user who has the Mod-Wiki privilege are never subject to
1729 @ moderation.
1730
--- src/setup.c
+++ src/setup.c
@@ -1708,11 +1708,11 @@
1708 login_insert_csrf_secret();
1709 @ <hr />
1710 onoff_attribute("Moderate ticket changes",
1711 "modreq-tkt", "modreq-tkt", 0, 0);
1712 @ <p>When enabled, any change to tickets is subject to the approval
1713 @ by a ticket moderator - a user with the "q" or Mod-Tkt privilege.
1714 @ Ticket changes enter the system and are shown locally, but are not
1715 @ synced until they are approved. The moderator has the option to
1716 @ delete the change rather than approve it. Ticket changes made by
1717 @ a user who has the Mod-Tkt privilege are never subject to
1718 @ moderation.
@@ -1719,11 +1719,11 @@
1719 @
1720 @ <hr />
1721 onoff_attribute("Moderate wiki changes",
1722 "modreq-wiki", "modreq-wiki", 0, 0);
1723 @ <p>When enabled, any change to wiki is subject to the approval
1724 @ by a wiki moderator - a user with the "l" or Mod-Wiki privilege.
1725 @ Wiki changes enter the system and are shown locally, but are not
1726 @ synced until they are approved. The moderator has the option to
1727 @ delete the change rather than approve it. Wiki changes made by
1728 @ a user who has the Mod-Wiki privilege are never subject to
1729 @ moderation.
1730
+120 -5
--- src/shell.c
+++ src/shell.c
@@ -1742,10 +1742,11 @@
17421742
static char zHelp[] =
17431743
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
17441744
".bail on|off Stop after hitting an error. Default OFF\n"
17451745
".clone NEWDB Clone data into NEWDB from the existing database\n"
17461746
".databases List names and files of attached databases\n"
1747
+ ".dbinfo ?DB? Show status information about the database\n"
17471748
".dump ?TABLE? ... Dump the database in an SQL text format\n"
17481749
" If TABLE specified, only dump tables matching\n"
17491750
" LIKE pattern TABLE.\n"
17501751
".echo on|off Turn command echo on or off\n"
17511752
".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n"
@@ -1754,12 +1755,12 @@
17541755
" With no args, it turns EXPLAIN on.\n"
17551756
".fullschema Show schema and the content of sqlite_stat tables\n"
17561757
".headers on|off Turn display of headers on or off\n"
17571758
".help Show this message\n"
17581759
".import FILE TABLE Import data from FILE into TABLE\n"
1759
- ".indices ?TABLE? Show names of all indices\n"
1760
- " If TABLE specified, only show indices for tables\n"
1760
+ ".indexes ?TABLE? Show names of all indexes\n"
1761
+ " If TABLE specified, only show indexes for tables\n"
17611762
" matching LIKE pattern TABLE.\n"
17621763
#ifdef SQLITE_ENABLE_IOTRACE
17631764
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
17641765
#endif
17651766
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -2434,10 +2435,119 @@
24342435
output_file_close(p->out);
24352436
}
24362437
p->outfile[0] = 0;
24372438
p->out = stdout;
24382439
}
2440
+
2441
+/*
2442
+** Run an SQL command and return the single integer result.
2443
+*/
2444
+static int db_int(ShellState *p, const char *zSql){
2445
+ sqlite3_stmt *pStmt;
2446
+ int res = 0;
2447
+ sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2448
+ if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
2449
+ res = sqlite3_column_int(pStmt,0);
2450
+ }
2451
+ sqlite3_finalize(pStmt);
2452
+ return res;
2453
+}
2454
+
2455
+/*
2456
+** Convert a 2-byte or 4-byte big-endian integer into a native integer
2457
+*/
2458
+unsigned int get2byteInt(unsigned char *a){
2459
+ return (a[0]<<8) + a[1];
2460
+}
2461
+unsigned int get4byteInt(unsigned char *a){
2462
+ return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
2463
+}
2464
+
2465
+/*
2466
+** Implementation of the ".info" command.
2467
+**
2468
+** Return 1 on error, 2 to exit, and 0 otherwise.
2469
+*/
2470
+static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
2471
+ static const struct { const char *zName; int ofst; } aField[] = {
2472
+ { "file change counter:", 24 },
2473
+ { "database page count:", 28 },
2474
+ { "freelist page count:", 36 },
2475
+ { "schema cookie:", 40 },
2476
+ { "schema format:", 44 },
2477
+ { "default cache size:", 48 },
2478
+ { "autovacuum top root:", 52 },
2479
+ { "incremental vacuum:", 64 },
2480
+ { "text encoding:", 56 },
2481
+ { "user version:", 60 },
2482
+ { "application id:", 68 },
2483
+ { "software version:", 96 },
2484
+ };
2485
+ static const struct { const char *zName; const char *zSql; } aQuery[] = {
2486
+ { "number of tables:",
2487
+ "SELECT count(*) FROM %s WHERE type='table'" },
2488
+ { "number of indexes:",
2489
+ "SELECT count(*) FROM %s WHERE type='index'" },
2490
+ { "number of triggers:",
2491
+ "SELECT count(*) FROM %s WHERE type='trigger'" },
2492
+ { "number of views:",
2493
+ "SELECT count(*) FROM %s WHERE type='view'" },
2494
+ { "schema size:",
2495
+ "SELECT total(length(sql)) FROM %s" },
2496
+ };
2497
+ sqlite3_file *pFile;
2498
+ int i;
2499
+ char *zSchemaTab;
2500
+ char *zDb = nArg>=2 ? azArg[1] : "main";
2501
+ unsigned char aHdr[100];
2502
+ open_db(p, 0);
2503
+ if( p->db==0 ) return 1;
2504
+ sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);
2505
+ if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
2506
+ return 1;
2507
+ }
2508
+ i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
2509
+ if( i!=SQLITE_OK ){
2510
+ fprintf(stderr, "unable to read database header\n");
2511
+ return 1;
2512
+ }
2513
+ i = get2byteInt(aHdr+16);
2514
+ if( i==1 ) i = 65536;
2515
+ fprintf(p->out, "%-20s %d\n", "database page size:", i);
2516
+ fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
2517
+ fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
2518
+ fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
2519
+ for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
2520
+ int ofst = aField[i].ofst;
2521
+ unsigned int val = get4byteInt(aHdr + ofst);
2522
+ fprintf(p->out, "%-20s %u", aField[i].zName, val);
2523
+ switch( ofst ){
2524
+ case 56: {
2525
+ if( val==1 ) fprintf(p->out, " (utf8)");
2526
+ if( val==2 ) fprintf(p->out, " (utf16le)");
2527
+ if( val==3 ) fprintf(p->out, " (utf16be)");
2528
+ }
2529
+ }
2530
+ fprintf(p->out, "\n");
2531
+ }
2532
+ if( zDb==0 ){
2533
+ zSchemaTab = sqlite3_mprintf("main.sqlite_master");
2534
+ }else if( strcmp(zDb,"temp")==0 ){
2535
+ zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
2536
+ }else{
2537
+ zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
2538
+ }
2539
+ for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
2540
+ char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
2541
+ int val = db_int(p, zSql);
2542
+ sqlite3_free(zSql);
2543
+ fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
2544
+ }
2545
+ sqlite3_free(zSchemaTab);
2546
+ return 0;
2547
+}
2548
+
24392549
24402550
/*
24412551
** If an input line begins with "." then invoke this routine to
24422552
** process that line.
24432553
**
@@ -2576,10 +2686,14 @@
25762686
fprintf(stderr,"Error: %s\n", zErrMsg);
25772687
sqlite3_free(zErrMsg);
25782688
rc = 1;
25792689
}
25802690
}else
2691
+
2692
+ if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
2693
+ rc = shell_dbinfo_command(p, nArg, azArg);
2694
+ }else
25812695
25822696
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
25832697
open_db(p, 0);
25842698
/* When playing back a "dump", the content might appear in an order
25852699
** which causes immediate foreign key constraints to be violated.
@@ -2916,11 +3030,11 @@
29163030
sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
29173031
if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
29183032
fprintf(stderr, "%s:%d: expected %d columns but found %d - "
29193033
"filling the rest with NULL\n",
29203034
sCtx.zFile, startLine, nCol, i+1);
2921
- i++;
3035
+ i += 2;
29223036
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
29233037
}
29243038
}
29253039
if( sCtx.cTerm==sCtx.cColSep ){
29263040
do{
@@ -2945,11 +3059,12 @@
29453059
sqlite3_free(sCtx.z);
29463060
sqlite3_finalize(pStmt);
29473061
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
29483062
}else
29493063
2950
- if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
3064
+ if( c=='i' && (strncmp(azArg[0], "indices", n)==0
3065
+ || strncmp(azArg[0], "indexes", n)==0) ){
29513066
ShellState data;
29523067
char *zErrMsg = 0;
29533068
open_db(p, 0);
29543069
memcpy(&data, p, sizeof(data));
29553070
data.showHeader = 0;
@@ -2975,11 +3090,11 @@
29753090
"ORDER BY 1",
29763091
callback, &data, &zErrMsg
29773092
);
29783093
zShellStatic = 0;
29793094
}else{
2980
- fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n");
3095
+ fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
29813096
rc = 1;
29823097
goto meta_command_exit;
29833098
}
29843099
if( zErrMsg ){
29853100
fprintf(stderr,"Error: %s\n", zErrMsg);
29863101
--- src/shell.c
+++ src/shell.c
@@ -1742,10 +1742,11 @@
1742 static char zHelp[] =
1743 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
1744 ".bail on|off Stop after hitting an error. Default OFF\n"
1745 ".clone NEWDB Clone data into NEWDB from the existing database\n"
1746 ".databases List names and files of attached databases\n"
 
1747 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
1748 " If TABLE specified, only dump tables matching\n"
1749 " LIKE pattern TABLE.\n"
1750 ".echo on|off Turn command echo on or off\n"
1751 ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n"
@@ -1754,12 +1755,12 @@
1754 " With no args, it turns EXPLAIN on.\n"
1755 ".fullschema Show schema and the content of sqlite_stat tables\n"
1756 ".headers on|off Turn display of headers on or off\n"
1757 ".help Show this message\n"
1758 ".import FILE TABLE Import data from FILE into TABLE\n"
1759 ".indices ?TABLE? Show names of all indices\n"
1760 " If TABLE specified, only show indices for tables\n"
1761 " matching LIKE pattern TABLE.\n"
1762 #ifdef SQLITE_ENABLE_IOTRACE
1763 ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
1764 #endif
1765 #ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -2434,10 +2435,119 @@
2434 output_file_close(p->out);
2435 }
2436 p->outfile[0] = 0;
2437 p->out = stdout;
2438 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2439
2440 /*
2441 ** If an input line begins with "." then invoke this routine to
2442 ** process that line.
2443 **
@@ -2576,10 +2686,14 @@
2576 fprintf(stderr,"Error: %s\n", zErrMsg);
2577 sqlite3_free(zErrMsg);
2578 rc = 1;
2579 }
2580 }else
 
 
 
 
2581
2582 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
2583 open_db(p, 0);
2584 /* When playing back a "dump", the content might appear in an order
2585 ** which causes immediate foreign key constraints to be violated.
@@ -2916,11 +3030,11 @@
2916 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
2917 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
2918 fprintf(stderr, "%s:%d: expected %d columns but found %d - "
2919 "filling the rest with NULL\n",
2920 sCtx.zFile, startLine, nCol, i+1);
2921 i++;
2922 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
2923 }
2924 }
2925 if( sCtx.cTerm==sCtx.cColSep ){
2926 do{
@@ -2945,11 +3059,12 @@
2945 sqlite3_free(sCtx.z);
2946 sqlite3_finalize(pStmt);
2947 if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
2948 }else
2949
2950 if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
 
2951 ShellState data;
2952 char *zErrMsg = 0;
2953 open_db(p, 0);
2954 memcpy(&data, p, sizeof(data));
2955 data.showHeader = 0;
@@ -2975,11 +3090,11 @@
2975 "ORDER BY 1",
2976 callback, &data, &zErrMsg
2977 );
2978 zShellStatic = 0;
2979 }else{
2980 fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n");
2981 rc = 1;
2982 goto meta_command_exit;
2983 }
2984 if( zErrMsg ){
2985 fprintf(stderr,"Error: %s\n", zErrMsg);
2986
--- src/shell.c
+++ src/shell.c
@@ -1742,10 +1742,11 @@
1742 static char zHelp[] =
1743 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
1744 ".bail on|off Stop after hitting an error. Default OFF\n"
1745 ".clone NEWDB Clone data into NEWDB from the existing database\n"
1746 ".databases List names and files of attached databases\n"
1747 ".dbinfo ?DB? Show status information about the database\n"
1748 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
1749 " If TABLE specified, only dump tables matching\n"
1750 " LIKE pattern TABLE.\n"
1751 ".echo on|off Turn command echo on or off\n"
1752 ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n"
@@ -1754,12 +1755,12 @@
1755 " With no args, it turns EXPLAIN on.\n"
1756 ".fullschema Show schema and the content of sqlite_stat tables\n"
1757 ".headers on|off Turn display of headers on or off\n"
1758 ".help Show this message\n"
1759 ".import FILE TABLE Import data from FILE into TABLE\n"
1760 ".indexes ?TABLE? Show names of all indexes\n"
1761 " If TABLE specified, only show indexes for tables\n"
1762 " matching LIKE pattern TABLE.\n"
1763 #ifdef SQLITE_ENABLE_IOTRACE
1764 ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
1765 #endif
1766 #ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -2434,10 +2435,119 @@
2435 output_file_close(p->out);
2436 }
2437 p->outfile[0] = 0;
2438 p->out = stdout;
2439 }
2440
2441 /*
2442 ** Run an SQL command and return the single integer result.
2443 */
2444 static int db_int(ShellState *p, const char *zSql){
2445 sqlite3_stmt *pStmt;
2446 int res = 0;
2447 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2448 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
2449 res = sqlite3_column_int(pStmt,0);
2450 }
2451 sqlite3_finalize(pStmt);
2452 return res;
2453 }
2454
2455 /*
2456 ** Convert a 2-byte or 4-byte big-endian integer into a native integer
2457 */
2458 unsigned int get2byteInt(unsigned char *a){
2459 return (a[0]<<8) + a[1];
2460 }
2461 unsigned int get4byteInt(unsigned char *a){
2462 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
2463 }
2464
2465 /*
2466 ** Implementation of the ".info" command.
2467 **
2468 ** Return 1 on error, 2 to exit, and 0 otherwise.
2469 */
2470 static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
2471 static const struct { const char *zName; int ofst; } aField[] = {
2472 { "file change counter:", 24 },
2473 { "database page count:", 28 },
2474 { "freelist page count:", 36 },
2475 { "schema cookie:", 40 },
2476 { "schema format:", 44 },
2477 { "default cache size:", 48 },
2478 { "autovacuum top root:", 52 },
2479 { "incremental vacuum:", 64 },
2480 { "text encoding:", 56 },
2481 { "user version:", 60 },
2482 { "application id:", 68 },
2483 { "software version:", 96 },
2484 };
2485 static const struct { const char *zName; const char *zSql; } aQuery[] = {
2486 { "number of tables:",
2487 "SELECT count(*) FROM %s WHERE type='table'" },
2488 { "number of indexes:",
2489 "SELECT count(*) FROM %s WHERE type='index'" },
2490 { "number of triggers:",
2491 "SELECT count(*) FROM %s WHERE type='trigger'" },
2492 { "number of views:",
2493 "SELECT count(*) FROM %s WHERE type='view'" },
2494 { "schema size:",
2495 "SELECT total(length(sql)) FROM %s" },
2496 };
2497 sqlite3_file *pFile;
2498 int i;
2499 char *zSchemaTab;
2500 char *zDb = nArg>=2 ? azArg[1] : "main";
2501 unsigned char aHdr[100];
2502 open_db(p, 0);
2503 if( p->db==0 ) return 1;
2504 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);
2505 if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
2506 return 1;
2507 }
2508 i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
2509 if( i!=SQLITE_OK ){
2510 fprintf(stderr, "unable to read database header\n");
2511 return 1;
2512 }
2513 i = get2byteInt(aHdr+16);
2514 if( i==1 ) i = 65536;
2515 fprintf(p->out, "%-20s %d\n", "database page size:", i);
2516 fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
2517 fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
2518 fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
2519 for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
2520 int ofst = aField[i].ofst;
2521 unsigned int val = get4byteInt(aHdr + ofst);
2522 fprintf(p->out, "%-20s %u", aField[i].zName, val);
2523 switch( ofst ){
2524 case 56: {
2525 if( val==1 ) fprintf(p->out, " (utf8)");
2526 if( val==2 ) fprintf(p->out, " (utf16le)");
2527 if( val==3 ) fprintf(p->out, " (utf16be)");
2528 }
2529 }
2530 fprintf(p->out, "\n");
2531 }
2532 if( zDb==0 ){
2533 zSchemaTab = sqlite3_mprintf("main.sqlite_master");
2534 }else if( strcmp(zDb,"temp")==0 ){
2535 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
2536 }else{
2537 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
2538 }
2539 for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
2540 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
2541 int val = db_int(p, zSql);
2542 sqlite3_free(zSql);
2543 fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
2544 }
2545 sqlite3_free(zSchemaTab);
2546 return 0;
2547 }
2548
2549
2550 /*
2551 ** If an input line begins with "." then invoke this routine to
2552 ** process that line.
2553 **
@@ -2576,10 +2686,14 @@
2686 fprintf(stderr,"Error: %s\n", zErrMsg);
2687 sqlite3_free(zErrMsg);
2688 rc = 1;
2689 }
2690 }else
2691
2692 if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
2693 rc = shell_dbinfo_command(p, nArg, azArg);
2694 }else
2695
2696 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
2697 open_db(p, 0);
2698 /* When playing back a "dump", the content might appear in an order
2699 ** which causes immediate foreign key constraints to be violated.
@@ -2916,11 +3030,11 @@
3030 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
3031 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
3032 fprintf(stderr, "%s:%d: expected %d columns but found %d - "
3033 "filling the rest with NULL\n",
3034 sCtx.zFile, startLine, nCol, i+1);
3035 i += 2;
3036 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
3037 }
3038 }
3039 if( sCtx.cTerm==sCtx.cColSep ){
3040 do{
@@ -2945,11 +3059,12 @@
3059 sqlite3_free(sCtx.z);
3060 sqlite3_finalize(pStmt);
3061 if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
3062 }else
3063
3064 if( c=='i' && (strncmp(azArg[0], "indices", n)==0
3065 || strncmp(azArg[0], "indexes", n)==0) ){
3066 ShellState data;
3067 char *zErrMsg = 0;
3068 open_db(p, 0);
3069 memcpy(&data, p, sizeof(data));
3070 data.showHeader = 0;
@@ -2975,11 +3090,11 @@
3090 "ORDER BY 1",
3091 callback, &data, &zErrMsg
3092 );
3093 zShellStatic = 0;
3094 }else{
3095 fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
3096 rc = 1;
3097 goto meta_command_exit;
3098 }
3099 if( zErrMsg ){
3100 fprintf(stderr,"Error: %s\n", zErrMsg);
3101
+1 -1
--- src/tkt.c
+++ src/tkt.c
@@ -428,11 +428,11 @@
428428
@ <font color="blue">
429429
@ <p>Database fields:</p><ul>
430430
for(i=0; i<nField; i++){
431431
@ <li>aField[%d(i)].zName = "%h(aField[i].zName)";
432432
@ originally = "%h(aField[i].zValue)";
433
- @ currently = "%h(PD(aField[i].zName,""))"";
433
+ @ currently = "%h(PD(aField[i].zName,""))";
434434
if( aField[i].zAppend ){
435435
@ zAppend = "%h(aField[i].zAppend)";
436436
}
437437
@ mUsed = %d(aField[i].mUsed);
438438
}
439439
--- src/tkt.c
+++ src/tkt.c
@@ -428,11 +428,11 @@
428 @ <font color="blue">
429 @ <p>Database fields:</p><ul>
430 for(i=0; i<nField; i++){
431 @ <li>aField[%d(i)].zName = "%h(aField[i].zName)";
432 @ originally = "%h(aField[i].zValue)";
433 @ currently = "%h(PD(aField[i].zName,""))"";
434 if( aField[i].zAppend ){
435 @ zAppend = "%h(aField[i].zAppend)";
436 }
437 @ mUsed = %d(aField[i].mUsed);
438 }
439
--- src/tkt.c
+++ src/tkt.c
@@ -428,11 +428,11 @@
428 @ <font color="blue">
429 @ <p>Database fields:</p><ul>
430 for(i=0; i<nField; i++){
431 @ <li>aField[%d(i)].zName = "%h(aField[i].zName)";
432 @ originally = "%h(aField[i].zValue)";
433 @ currently = "%h(PD(aField[i].zName,""))";
434 if( aField[i].zAppend ){
435 @ zAppend = "%h(aField[i].zAppend)";
436 }
437 @ mUsed = %d(aField[i].mUsed);
438 }
439

Keyboard Shortcuts

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