Fossil SCM

Merge trunk

jan.nijtmans 2019-05-13 21:48 UTC openssl-1.1 merge
Commit 91a0d5a55f3865a8c391cc86f47084bc0dd7529d74c837573ba21efaba9bcddd
+15
--- a/README.md
+++ b/README.md
@@ -0,0 +1,15 @@
1
+# About Fossil
2
+
3
+Fossil is a distributed version control system that has been widely
4
+used since 2007. Fossil was originally designed to support the
5
+[SQLite](https://sqlite.org) project but has been adopted by many other
6
+projects as well.
7
+
8
+Fossil is self-hosting at <https://fossil-scm.org>.
9
+
10
+If you are reading this on GitHub, then you are looking at a Git mirror
11
+of the self-hosting Fossil repository. The purpose of that mirror is to
12
+test and exercise Fossil's ability to export a Git mirror. Nobody much
13
+uses the GitHub mirror, except to verify that the mirror logic works. If
14
+you want to know more about Fossil, visit the official self-hosting site
15
+linked above.
--- a/README.md
+++ b/README.md
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/README.md
+++ b/README.md
@@ -0,0 +1,15 @@
1 # About Fossil
2
3 Fossil is a distributed version control system that has been widely
4 used since 2007. Fossil was originally designed to support the
5 [SQLite](https://sqlite.org) project but has been adopted by many other
6 projects as well.
7
8 Fossil is self-hosting at <https://fossil-scm.org>.
9
10 If you are reading this on GitHub, then you are looking at a Git mirror
11 of the self-hosting Fossil repository. The purpose of that mirror is to
12 test and exercise Fossil's ability to export a Git mirror. Nobody much
13 uses the GitHub mirror, except to verify that the mirror logic works. If
14 you want to know more about Fossil, visit the official self-hosting site
15 linked above.
+5 -4
--- auto.def
+++ auto.def
@@ -126,17 +126,17 @@
126126
# the code below will append -ldl to LIBS.
127127
#
128128
foreach extralibs {{} {-ldl}} {
129129
130130
# Locate the system SQLite by searching for sqlite3_open(). Then check
131
- # if sqlite3_create_window_function can be found as well. If we can find open() but
132
- # not create_window_function(), then the system SQLite is too old to link against
131
+ # if sqlite3_stmt_isexplain can be found as well. If we can find open() but
132
+ # not stmt_isexplain(), then the system SQLite is too old to link against
133133
# fossil.
134134
#
135135
if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} {
136
- if {![check-function-in-lib sqlite3_create_window_function sqlite3 $extralibs]} {
137
- user-error "system sqlite3 too old (require >= 3.25.0)"
136
+ if {![check-function-in-lib sqlite3_stmt_isexplain sqlite3 $extralibs]} {
137
+ user-error "system sqlite3 too old (require >= 3.28.0)"
138138
}
139139
140140
# Success. Update symbols and return.
141141
#
142142
define USE_SYSTEM_SQLITE 1
@@ -376,10 +376,11 @@
376376
if {[string match *-darwin* [get-define host]]} {
377377
if {[cctest -cflags {-Wdeprecated-declarations}]} {
378378
define-append EXTRA_CFLAGS -Wdeprecated-declarations
379379
}
380380
}
381
+ cc-check-function-in-lib BIO_ADDR_hostname_string ssl
381382
} else {
382383
user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
383384
}
384385
} else {
385386
if {[info exists ::zlib_lib]} {
386387
--- auto.def
+++ auto.def
@@ -126,17 +126,17 @@
126 # the code below will append -ldl to LIBS.
127 #
128 foreach extralibs {{} {-ldl}} {
129
130 # Locate the system SQLite by searching for sqlite3_open(). Then check
131 # if sqlite3_create_window_function can be found as well. If we can find open() but
132 # not create_window_function(), then the system SQLite is too old to link against
133 # fossil.
134 #
135 if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} {
136 if {![check-function-in-lib sqlite3_create_window_function sqlite3 $extralibs]} {
137 user-error "system sqlite3 too old (require >= 3.25.0)"
138 }
139
140 # Success. Update symbols and return.
141 #
142 define USE_SYSTEM_SQLITE 1
@@ -376,10 +376,11 @@
376 if {[string match *-darwin* [get-define host]]} {
377 if {[cctest -cflags {-Wdeprecated-declarations}]} {
378 define-append EXTRA_CFLAGS -Wdeprecated-declarations
379 }
380 }
 
381 } else {
382 user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
383 }
384 } else {
385 if {[info exists ::zlib_lib]} {
386
--- auto.def
+++ auto.def
@@ -126,17 +126,17 @@
126 # the code below will append -ldl to LIBS.
127 #
128 foreach extralibs {{} {-ldl}} {
129
130 # Locate the system SQLite by searching for sqlite3_open(). Then check
131 # if sqlite3_stmt_isexplain can be found as well. If we can find open() but
132 # not stmt_isexplain(), then the system SQLite is too old to link against
133 # fossil.
134 #
135 if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} {
136 if {![check-function-in-lib sqlite3_stmt_isexplain sqlite3 $extralibs]} {
137 user-error "system sqlite3 too old (require >= 3.28.0)"
138 }
139
140 # Success. Update symbols and return.
141 #
142 define USE_SYSTEM_SQLITE 1
@@ -376,10 +376,11 @@
376 if {[string match *-darwin* [get-define host]]} {
377 if {[cctest -cflags {-Wdeprecated-declarations}]} {
378 define-append EXTRA_CFLAGS -Wdeprecated-declarations
379 }
380 }
381 cc-check-function-in-lib BIO_ADDR_hostname_string ssl
382 } else {
383 user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
384 }
385 } else {
386 if {[info exists ::zlib_lib]} {
387
--- autosetup/find-tclsh
+++ autosetup/find-tclsh
@@ -2,11 +2,11 @@
22
# Looks for a suitable tclsh or jimsh in the PATH
33
# If not found, builds a bootstrap jimsh from source
44
d=`dirname "$0"`
55
{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
66
PATH="$PATH:$d"; export PATH
7
-for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do
7
+for tclsh in jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; do
88
{ $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
99
done
1010
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
1111
for cc in ${CC_FOR_BUILD:-cc} gcc; do
1212
{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
1313
--- autosetup/find-tclsh
+++ autosetup/find-tclsh
@@ -2,11 +2,11 @@
2 # Looks for a suitable tclsh or jimsh in the PATH
3 # If not found, builds a bootstrap jimsh from source
4 d=`dirname "$0"`
5 { "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
6 PATH="$PATH:$d"; export PATH
7 for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do
8 { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
9 done
10 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
11 for cc in ${CC_FOR_BUILD:-cc} gcc; do
12 { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
13
--- autosetup/find-tclsh
+++ autosetup/find-tclsh
@@ -2,11 +2,11 @@
2 # Looks for a suitable tclsh or jimsh in the PATH
3 # If not found, builds a bootstrap jimsh from source
4 d=`dirname "$0"`
5 { "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
6 PATH="$PATH:$d"; export PATH
7 for tclsh in jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; do
8 { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
9 done
10 echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
11 for cc in ${CC_FOR_BUILD:-cc} gcc; do
12 { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
13
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -63,11 +63,11 @@
6363
<a href="$logourl">
6464
<img src="$logo_image_url" border="0" alt="$project_name">
6565
</a>
6666
</div>
6767
<div class="title">$<title></div>
68
- <div class="status"><th1>
68
+ <div class="status"><nobr><th1>
6969
if {[info exists login]} {
7070
puts "Logged in as $login"
7171
} else {
7272
puts "Not logged in"
7373
}
7474
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -63,11 +63,11 @@
63 <a href="$logourl">
64 <img src="$logo_image_url" border="0" alt="$project_name">
65 </a>
66 </div>
67 <div class="title">$<title></div>
68 <div class="status"><th1>
69 if {[info exists login]} {
70 puts "Logged in as $login"
71 } else {
72 puts "Not logged in"
73 }
74
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -63,11 +63,11 @@
63 <a href="$logourl">
64 <img src="$logo_image_url" border="0" alt="$project_name">
65 </a>
66 </div>
67 <div class="title">$<title></div>
68 <div class="status"><nobr><th1>
69 if {[info exists login]} {
70 puts "Logged in as $login"
71 } else {
72 puts "Not logged in"
73 }
74
+89 -5
--- src/backoffice.c
+++ src/backoffice.c
@@ -80,10 +80,11 @@
8080
# include <signal.h>
8181
# include <errno.h>
8282
# include <fcntl.h>
8383
# define GETPID getpid
8484
#endif
85
+#include <time.h>
8586
8687
/*
8788
** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
8889
** processing run is valid. Each backoffice run monopolizes the lease for
8990
** at least this amount of time. Hopefully all backoffice processing is
@@ -454,10 +455,12 @@
454455
){
455456
/* Another backoffice process is already queued up to run. This
456457
** process does not need to do any backoffice work and can stop
457458
** immediately. */
458459
db_end_transaction(0);
460
+ backofficeTrace("/***** Backoffice Processing Not Needed In %d *****/\n",
461
+ GETPID());
459462
break;
460463
}
461464
if( x.tmCurrent<tmNow && backofficeProcessDone(x.idCurrent) ){
462465
/* This process can start doing backoffice work immediately */
463466
x.idCurrent = idSelf;
@@ -474,10 +477,13 @@
474477
if( backofficeNoDelay || db_get_boolean("backoffice-nodelay",0) ){
475478
/* If the no-delay flag is set, exit immediately rather than queuing
476479
** up. Assume that some future request will come along and handle any
477480
** necessary backoffice work. */
478481
db_end_transaction(0);
482
+ backofficeTrace(
483
+ "/***** Backoffice No-Delay Exit For %d *****/\n",
484
+ GETPID());
479485
break;
480486
}
481487
/* This process needs to queue up and wait for the current lease
482488
** to expire before continuing. */
483489
x.idNext = idSelf;
@@ -535,20 +541,98 @@
535541
}
536542
537543
/*
538544
** COMMAND: backoffice*
539545
**
540
-** Usage: backoffice [-R repository]
546
+** Usage: backoffice [OPTIONS...] [REPOSITORIES...]
547
+**
548
+** Run backoffice processing on the repositories listed. If no
549
+** repository is specified, run it on the repository of the local checkout.
550
+**
551
+** This might be done by a cron job or similar to make sure backoffice
552
+** processing happens periodically. Or, the --poll option can be used
553
+** to run this command as a daemon that will periodically invoke backoffice
554
+** on collection of repositories.
555
+**
556
+** OPTIONS:
557
+**
558
+** --debug Show what this command is doing.
559
+**
560
+** --nodelay Do not queue up or wait for a backoffice job
561
+** to complete. If no work is available or if
562
+** backoffice has run recently, return immediately.
563
+** The --nodelay option is implied if more than
564
+** one repository is listed on the command-line.
565
+**
566
+** --poll N Repeat backoffice calls for repositories that
567
+** change in appoximately N-second intervals.
568
+** N less than 1 turns polling off (the default).
541569
**
542
-** Run backoffice processing. This might be done by a cron job or
543
-** similar to make sure backoffice processing happens periodically.
570
+** --trace Enable debugging output on stderr
544571
*/
545572
void backoffice_command(void){
573
+ int nPoll;
574
+ const char *zPoll;
575
+ int bDebug = 0;
576
+ unsigned int nCmd = 0;
546577
if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
547
- db_find_and_open_repository(0,0);
578
+ if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1;
579
+ zPoll = find_option("poll",0,1);
580
+ nPoll = zPoll ? atoi(zPoll) : 0;
581
+ bDebug = find_option("debug",0,0)!=0;
582
+
583
+ /* Silently consume the -R or --repository flag, leaving behind its
584
+ ** argument. This is for legacy compatibility. Older versions of the
585
+ ** backoffice command only ran on a single repository that was specified
586
+ ** using the -R option. */
587
+ (void)find_option("repository","R",0);
588
+
548589
verify_all_options();
549
- backoffice_thread();
590
+ if( g.argc>3 || nPoll>0 ){
591
+ /* Either there are multiple repositories named on the command-line
592
+ ** or we are polling. In either case, each backoffice should be run
593
+ ** using a separate sub-process */
594
+ int i;
595
+ time_t iNow = 0;
596
+ time_t ix;
597
+ while( 1 /* exit via "break;" */){
598
+ time_t iNext = time(0);
599
+ for(i=2; i<g.argc; i++){
600
+ Blob cmd;
601
+ if( !file_isfile(g.argv[i], ExtFILE) ) continue;
602
+ if( iNow && iNow>file_mtime(g.argv[i],ExtFILE) ) continue;
603
+ blob_init(&cmd, 0, 0);
604
+ blob_append_escaped_arg(&cmd, g.nameOfExe);
605
+ blob_append(&cmd, " backoffice --nodelay", -1);
606
+ if( g.fAnyTrace ){
607
+ blob_append(&cmd, " --trace", -1);
608
+ }
609
+ blob_append_escaped_arg(&cmd, g.argv[i]);
610
+ nCmd++;
611
+ if( bDebug ){
612
+ fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
613
+ }
614
+ fossil_system(blob_str(&cmd));
615
+ blob_reset(&cmd);
616
+ }
617
+ if( nPoll<1 ) break;
618
+ iNow = iNext;
619
+ ix = time(0);
620
+ if( ix < iNow+nPoll ){
621
+ sqlite3_int64 nMS = (iNow + nPoll - ix)*1000;
622
+ if( bDebug )fossil_print("SLEEP: %lld\n", nMS);
623
+ sqlite3_sleep((int)nMS);
624
+ }
625
+ }
626
+ }else{
627
+ if( g.argc==3 ){
628
+ g.zRepositoryOption = g.argv[2];
629
+ g.argc--;
630
+ }
631
+ db_find_and_open_repository(0,0);
632
+ backoffice_thread();
633
+ }
550634
}
551635
552636
/*
553637
** This is the main interface to backoffice from the rest of the system.
554638
** This routine launches either backoffice_thread() directly or as a
555639
--- src/backoffice.c
+++ src/backoffice.c
@@ -80,10 +80,11 @@
80 # include <signal.h>
81 # include <errno.h>
82 # include <fcntl.h>
83 # define GETPID getpid
84 #endif
 
85
86 /*
87 ** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
88 ** processing run is valid. Each backoffice run monopolizes the lease for
89 ** at least this amount of time. Hopefully all backoffice processing is
@@ -454,10 +455,12 @@
454 ){
455 /* Another backoffice process is already queued up to run. This
456 ** process does not need to do any backoffice work and can stop
457 ** immediately. */
458 db_end_transaction(0);
 
 
459 break;
460 }
461 if( x.tmCurrent<tmNow && backofficeProcessDone(x.idCurrent) ){
462 /* This process can start doing backoffice work immediately */
463 x.idCurrent = idSelf;
@@ -474,10 +477,13 @@
474 if( backofficeNoDelay || db_get_boolean("backoffice-nodelay",0) ){
475 /* If the no-delay flag is set, exit immediately rather than queuing
476 ** up. Assume that some future request will come along and handle any
477 ** necessary backoffice work. */
478 db_end_transaction(0);
 
 
 
479 break;
480 }
481 /* This process needs to queue up and wait for the current lease
482 ** to expire before continuing. */
483 x.idNext = idSelf;
@@ -535,20 +541,98 @@
535 }
536
537 /*
538 ** COMMAND: backoffice*
539 **
540 ** Usage: backoffice [-R repository]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
541 **
542 ** Run backoffice processing. This might be done by a cron job or
543 ** similar to make sure backoffice processing happens periodically.
544 */
545 void backoffice_command(void){
 
 
 
 
546 if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
547 db_find_and_open_repository(0,0);
 
 
 
 
 
 
 
 
 
 
548 verify_all_options();
549 backoffice_thread();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550 }
551
552 /*
553 ** This is the main interface to backoffice from the rest of the system.
554 ** This routine launches either backoffice_thread() directly or as a
555
--- src/backoffice.c
+++ src/backoffice.c
@@ -80,10 +80,11 @@
80 # include <signal.h>
81 # include <errno.h>
82 # include <fcntl.h>
83 # define GETPID getpid
84 #endif
85 #include <time.h>
86
87 /*
88 ** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
89 ** processing run is valid. Each backoffice run monopolizes the lease for
90 ** at least this amount of time. Hopefully all backoffice processing is
@@ -454,10 +455,12 @@
455 ){
456 /* Another backoffice process is already queued up to run. This
457 ** process does not need to do any backoffice work and can stop
458 ** immediately. */
459 db_end_transaction(0);
460 backofficeTrace("/***** Backoffice Processing Not Needed In %d *****/\n",
461 GETPID());
462 break;
463 }
464 if( x.tmCurrent<tmNow && backofficeProcessDone(x.idCurrent) ){
465 /* This process can start doing backoffice work immediately */
466 x.idCurrent = idSelf;
@@ -474,10 +477,13 @@
477 if( backofficeNoDelay || db_get_boolean("backoffice-nodelay",0) ){
478 /* If the no-delay flag is set, exit immediately rather than queuing
479 ** up. Assume that some future request will come along and handle any
480 ** necessary backoffice work. */
481 db_end_transaction(0);
482 backofficeTrace(
483 "/***** Backoffice No-Delay Exit For %d *****/\n",
484 GETPID());
485 break;
486 }
487 /* This process needs to queue up and wait for the current lease
488 ** to expire before continuing. */
489 x.idNext = idSelf;
@@ -535,20 +541,98 @@
541 }
542
543 /*
544 ** COMMAND: backoffice*
545 **
546 ** Usage: backoffice [OPTIONS...] [REPOSITORIES...]
547 **
548 ** Run backoffice processing on the repositories listed. If no
549 ** repository is specified, run it on the repository of the local checkout.
550 **
551 ** This might be done by a cron job or similar to make sure backoffice
552 ** processing happens periodically. Or, the --poll option can be used
553 ** to run this command as a daemon that will periodically invoke backoffice
554 ** on collection of repositories.
555 **
556 ** OPTIONS:
557 **
558 ** --debug Show what this command is doing.
559 **
560 ** --nodelay Do not queue up or wait for a backoffice job
561 ** to complete. If no work is available or if
562 ** backoffice has run recently, return immediately.
563 ** The --nodelay option is implied if more than
564 ** one repository is listed on the command-line.
565 **
566 ** --poll N Repeat backoffice calls for repositories that
567 ** change in appoximately N-second intervals.
568 ** N less than 1 turns polling off (the default).
569 **
570 ** --trace Enable debugging output on stderr
 
571 */
572 void backoffice_command(void){
573 int nPoll;
574 const char *zPoll;
575 int bDebug = 0;
576 unsigned int nCmd = 0;
577 if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
578 if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1;
579 zPoll = find_option("poll",0,1);
580 nPoll = zPoll ? atoi(zPoll) : 0;
581 bDebug = find_option("debug",0,0)!=0;
582
583 /* Silently consume the -R or --repository flag, leaving behind its
584 ** argument. This is for legacy compatibility. Older versions of the
585 ** backoffice command only ran on a single repository that was specified
586 ** using the -R option. */
587 (void)find_option("repository","R",0);
588
589 verify_all_options();
590 if( g.argc>3 || nPoll>0 ){
591 /* Either there are multiple repositories named on the command-line
592 ** or we are polling. In either case, each backoffice should be run
593 ** using a separate sub-process */
594 int i;
595 time_t iNow = 0;
596 time_t ix;
597 while( 1 /* exit via "break;" */){
598 time_t iNext = time(0);
599 for(i=2; i<g.argc; i++){
600 Blob cmd;
601 if( !file_isfile(g.argv[i], ExtFILE) ) continue;
602 if( iNow && iNow>file_mtime(g.argv[i],ExtFILE) ) continue;
603 blob_init(&cmd, 0, 0);
604 blob_append_escaped_arg(&cmd, g.nameOfExe);
605 blob_append(&cmd, " backoffice --nodelay", -1);
606 if( g.fAnyTrace ){
607 blob_append(&cmd, " --trace", -1);
608 }
609 blob_append_escaped_arg(&cmd, g.argv[i]);
610 nCmd++;
611 if( bDebug ){
612 fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
613 }
614 fossil_system(blob_str(&cmd));
615 blob_reset(&cmd);
616 }
617 if( nPoll<1 ) break;
618 iNow = iNext;
619 ix = time(0);
620 if( ix < iNow+nPoll ){
621 sqlite3_int64 nMS = (iNow + nPoll - ix)*1000;
622 if( bDebug )fossil_print("SLEEP: %lld\n", nMS);
623 sqlite3_sleep((int)nMS);
624 }
625 }
626 }else{
627 if( g.argc==3 ){
628 g.zRepositoryOption = g.argv[2];
629 g.argc--;
630 }
631 db_find_and_open_repository(0,0);
632 backoffice_thread();
633 }
634 }
635
636 /*
637 ** This is the main interface to backoffice from the rest of the system.
638 ** This routine launches either backoffice_thread() directly or as a
639
--- src/capabilities.c
+++ src/capabilities.c
@@ -364,13 +364,13 @@
364364
" FROM t LEFT JOIN user ON t.id=user.login"
365365
" UNION ALL"
366366
" SELECT 'New User Default', fullcap(%Q), 10, 1"
367367
" UNION ALL"
368368
" SELECT 'Regular User', fullcap(capunion(cap)), 20, count(*) FROM user"
369
- " WHERE cap NOT GLOB '*[as]*'"
369
+ " WHERE cap NOT GLOB '*[as]*' AND login NOT IN (SELECT id FROM t)"
370370
" UNION ALL"
371
- " SELECT 'Adminstator', fullcap(capunion(cap)), 30, count(*) FROM user"
371
+ " SELECT 'Adminstrator', fullcap(capunion(cap)), 30, count(*) FROM user"
372372
" WHERE cap GLOB '*[as]*'"
373373
" ORDER BY 3 ASC",
374374
db_get("default-perms","")
375375
);
376376
@ <table id='capabilitySummary' cellpadding="0" cellspacing="0" border="1">
377377
--- src/capabilities.c
+++ src/capabilities.c
@@ -364,13 +364,13 @@
364 " FROM t LEFT JOIN user ON t.id=user.login"
365 " UNION ALL"
366 " SELECT 'New User Default', fullcap(%Q), 10, 1"
367 " UNION ALL"
368 " SELECT 'Regular User', fullcap(capunion(cap)), 20, count(*) FROM user"
369 " WHERE cap NOT GLOB '*[as]*'"
370 " UNION ALL"
371 " SELECT 'Adminstator', fullcap(capunion(cap)), 30, count(*) FROM user"
372 " WHERE cap GLOB '*[as]*'"
373 " ORDER BY 3 ASC",
374 db_get("default-perms","")
375 );
376 @ <table id='capabilitySummary' cellpadding="0" cellspacing="0" border="1">
377
--- src/capabilities.c
+++ src/capabilities.c
@@ -364,13 +364,13 @@
364 " FROM t LEFT JOIN user ON t.id=user.login"
365 " UNION ALL"
366 " SELECT 'New User Default', fullcap(%Q), 10, 1"
367 " UNION ALL"
368 " SELECT 'Regular User', fullcap(capunion(cap)), 20, count(*) FROM user"
369 " WHERE cap NOT GLOB '*[as]*' AND login NOT IN (SELECT id FROM t)"
370 " UNION ALL"
371 " SELECT 'Adminstrator', fullcap(capunion(cap)), 30, count(*) FROM user"
372 " WHERE cap GLOB '*[as]*'"
373 " ORDER BY 3 ASC",
374 db_get("default-perms","")
375 );
376 @ <table id='capabilitySummary' cellpadding="0" cellspacing="0" border="1">
377
+4 -2
--- src/checkin.c
+++ src/checkin.c
@@ -1209,11 +1209,11 @@
12091209
if( g.zLocalRoot!=0 ){
12101210
file_relative_name(g.zLocalRoot, &fname, 1);
12111211
zFile = db_text(0, "SELECT '%qci-comment-'||hex(randomblob(6))||'.txt'",
12121212
blob_str(&fname));
12131213
}else{
1214
- file_tempname(&fname, "ci-comment");
1214
+ file_tempname(&fname, "ci-comment",0);
12151215
zFile = mprintf("%s", blob_str(&fname));
12161216
}
12171217
blob_reset(&fname);
12181218
}
12191219
#if defined(_WIN32)
@@ -2613,11 +2613,13 @@
26132613
blob_reset(&tagslist);
26142614
free(zManifestFile);
26152615
}
26162616
26172617
if( !g.markPrivate ){
2618
- autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0);
2618
+ int syncFlags = SYNC_PUSH | SYNC_PULL | SYNC_IFABLE;
2619
+ int nTries = db_get_int("autosync-tries",1);
2620
+ autosync_loop(syncFlags, nTries, 0);
26192621
}
26202622
if( count_nonbranch_children(vid)>1 ){
26212623
fossil_print("**** warning: a fork has occurred *****\n");
26222624
}
26232625
}
26242626
--- src/checkin.c
+++ src/checkin.c
@@ -1209,11 +1209,11 @@
1209 if( g.zLocalRoot!=0 ){
1210 file_relative_name(g.zLocalRoot, &fname, 1);
1211 zFile = db_text(0, "SELECT '%qci-comment-'||hex(randomblob(6))||'.txt'",
1212 blob_str(&fname));
1213 }else{
1214 file_tempname(&fname, "ci-comment");
1215 zFile = mprintf("%s", blob_str(&fname));
1216 }
1217 blob_reset(&fname);
1218 }
1219 #if defined(_WIN32)
@@ -2613,11 +2613,13 @@
2613 blob_reset(&tagslist);
2614 free(zManifestFile);
2615 }
2616
2617 if( !g.markPrivate ){
2618 autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0);
 
 
2619 }
2620 if( count_nonbranch_children(vid)>1 ){
2621 fossil_print("**** warning: a fork has occurred *****\n");
2622 }
2623 }
2624
--- src/checkin.c
+++ src/checkin.c
@@ -1209,11 +1209,11 @@
1209 if( g.zLocalRoot!=0 ){
1210 file_relative_name(g.zLocalRoot, &fname, 1);
1211 zFile = db_text(0, "SELECT '%qci-comment-'||hex(randomblob(6))||'.txt'",
1212 blob_str(&fname));
1213 }else{
1214 file_tempname(&fname, "ci-comment",0);
1215 zFile = mprintf("%s", blob_str(&fname));
1216 }
1217 blob_reset(&fname);
1218 }
1219 #if defined(_WIN32)
@@ -2613,11 +2613,13 @@
2613 blob_reset(&tagslist);
2614 free(zManifestFile);
2615 }
2616
2617 if( !g.markPrivate ){
2618 int syncFlags = SYNC_PUSH | SYNC_PULL | SYNC_IFABLE;
2619 int nTries = db_get_int("autosync-tries",1);
2620 autosync_loop(syncFlags, nTries, 0);
2621 }
2622 if( count_nonbranch_children(vid)>1 ){
2623 fossil_print("**** warning: a fork has occurred *****\n");
2624 }
2625 }
2626
+1 -1
--- src/content.c
+++ src/content.c
@@ -598,11 +598,11 @@
598598
if( !pBlob ){
599599
db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
600600
}
601601
}
602602
if( g.markPrivate || isPrivate ){
603
- db_multi_exec("INSERT INTO private VALUES(%d)", rid);
603
+ db_multi_exec("INSERT OR IGNORE INTO private VALUES(%d)", rid);
604604
markAsUnclustered = 0;
605605
}
606606
if( nBlob==0 ) blob_reset(&cmpr);
607607
608608
/* If the srcId is specified, then the data we just added is
609609
--- src/content.c
+++ src/content.c
@@ -598,11 +598,11 @@
598 if( !pBlob ){
599 db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
600 }
601 }
602 if( g.markPrivate || isPrivate ){
603 db_multi_exec("INSERT INTO private VALUES(%d)", rid);
604 markAsUnclustered = 0;
605 }
606 if( nBlob==0 ) blob_reset(&cmpr);
607
608 /* If the srcId is specified, then the data we just added is
609
--- src/content.c
+++ src/content.c
@@ -598,11 +598,11 @@
598 if( !pBlob ){
599 db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
600 }
601 }
602 if( g.markPrivate || isPrivate ){
603 db_multi_exec("INSERT OR IGNORE INTO private VALUES(%d)", rid);
604 markAsUnclustered = 0;
605 }
606 if( nBlob==0 ) blob_reset(&cmpr);
607
608 /* If the srcId is specified, then the data we just added is
609
+3 -18
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -213,11 +213,10 @@
213213
}
214214
215215
/* Release memory resources */
216216
blob_reset(&file2);
217217
}else{
218
- int cnt = 0;
219218
Blob nameFile1; /* Name of temporary file to old pFile1 content */
220219
Blob cmd; /* Text of command to run */
221220
222221
if( !fIncludeBinary ){
223222
Blob file2;
@@ -246,15 +245,11 @@
246245
blob_reset(&file2);
247246
}
248247
249248
/* Construct a temporary file to hold pFile1 based on the name of
250249
** zFile2 */
251
- blob_zero(&nameFile1);
252
- do{
253
- blob_reset(&nameFile1);
254
- blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
255
- }while( file_access(blob_str(&nameFile1),F_OK)==0 );
250
+ file_tempname(&nameFile1, zFile2, "orig");
256251
blob_write_to_file(pFile1, blob_str(&nameFile1));
257252
258253
/* Construct the external diff command */
259254
blob_zero(&cmd);
260255
blob_append(&cmd, zDiffCmd, -1);
@@ -317,12 +312,10 @@
317312
blob_reset(&out);
318313
}else{
319314
Blob cmd;
320315
Blob temp1;
321316
Blob temp2;
322
- Blob prefix1;
323
- Blob prefix2;
324317
325318
if( !fIncludeBinary ){
326319
if( isBin1 || isBin2 ){
327320
fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
328321
return;
@@ -336,19 +329,13 @@
336329
}
337330
glob_free(pBinary);
338331
}
339332
}
340333
341
- /* Construct a prefix for the temporary file names */
342
- blob_zero(&prefix1);
343
- blob_zero(&prefix2);
344
- blob_appendf(&prefix1, "%s-v1", zName);
345
- blob_appendf(&prefix2, "%s-v2", zName);
346
-
347334
/* Construct a temporary file names */
348
- file_tempname(&temp1, blob_str(&prefix1));
349
- file_tempname(&temp2, blob_str(&prefix2));
335
+ file_tempname(&temp1, zName, "before");
336
+ file_tempname(&temp2, zName, "after");
350337
blob_write_to_file(pFile1, blob_str(&temp1));
351338
blob_write_to_file(pFile2, blob_str(&temp2));
352339
353340
/* Construct the external diff command */
354341
blob_zero(&cmd);
@@ -361,12 +348,10 @@
361348
362349
/* Delete the temporary file and clean up memory used */
363350
file_delete(blob_str(&temp1));
364351
file_delete(blob_str(&temp2));
365352
366
- blob_reset(&prefix1);
367
- blob_reset(&prefix2);
368353
blob_reset(&temp1);
369354
blob_reset(&temp2);
370355
blob_reset(&cmd);
371356
}
372357
}
373358
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -213,11 +213,10 @@
213 }
214
215 /* Release memory resources */
216 blob_reset(&file2);
217 }else{
218 int cnt = 0;
219 Blob nameFile1; /* Name of temporary file to old pFile1 content */
220 Blob cmd; /* Text of command to run */
221
222 if( !fIncludeBinary ){
223 Blob file2;
@@ -246,15 +245,11 @@
246 blob_reset(&file2);
247 }
248
249 /* Construct a temporary file to hold pFile1 based on the name of
250 ** zFile2 */
251 blob_zero(&nameFile1);
252 do{
253 blob_reset(&nameFile1);
254 blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
255 }while( file_access(blob_str(&nameFile1),F_OK)==0 );
256 blob_write_to_file(pFile1, blob_str(&nameFile1));
257
258 /* Construct the external diff command */
259 blob_zero(&cmd);
260 blob_append(&cmd, zDiffCmd, -1);
@@ -317,12 +312,10 @@
317 blob_reset(&out);
318 }else{
319 Blob cmd;
320 Blob temp1;
321 Blob temp2;
322 Blob prefix1;
323 Blob prefix2;
324
325 if( !fIncludeBinary ){
326 if( isBin1 || isBin2 ){
327 fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
328 return;
@@ -336,19 +329,13 @@
336 }
337 glob_free(pBinary);
338 }
339 }
340
341 /* Construct a prefix for the temporary file names */
342 blob_zero(&prefix1);
343 blob_zero(&prefix2);
344 blob_appendf(&prefix1, "%s-v1", zName);
345 blob_appendf(&prefix2, "%s-v2", zName);
346
347 /* Construct a temporary file names */
348 file_tempname(&temp1, blob_str(&prefix1));
349 file_tempname(&temp2, blob_str(&prefix2));
350 blob_write_to_file(pFile1, blob_str(&temp1));
351 blob_write_to_file(pFile2, blob_str(&temp2));
352
353 /* Construct the external diff command */
354 blob_zero(&cmd);
@@ -361,12 +348,10 @@
361
362 /* Delete the temporary file and clean up memory used */
363 file_delete(blob_str(&temp1));
364 file_delete(blob_str(&temp2));
365
366 blob_reset(&prefix1);
367 blob_reset(&prefix2);
368 blob_reset(&temp1);
369 blob_reset(&temp2);
370 blob_reset(&cmd);
371 }
372 }
373
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -213,11 +213,10 @@
213 }
214
215 /* Release memory resources */
216 blob_reset(&file2);
217 }else{
 
218 Blob nameFile1; /* Name of temporary file to old pFile1 content */
219 Blob cmd; /* Text of command to run */
220
221 if( !fIncludeBinary ){
222 Blob file2;
@@ -246,15 +245,11 @@
245 blob_reset(&file2);
246 }
247
248 /* Construct a temporary file to hold pFile1 based on the name of
249 ** zFile2 */
250 file_tempname(&nameFile1, zFile2, "orig");
 
 
 
 
251 blob_write_to_file(pFile1, blob_str(&nameFile1));
252
253 /* Construct the external diff command */
254 blob_zero(&cmd);
255 blob_append(&cmd, zDiffCmd, -1);
@@ -317,12 +312,10 @@
312 blob_reset(&out);
313 }else{
314 Blob cmd;
315 Blob temp1;
316 Blob temp2;
 
 
317
318 if( !fIncludeBinary ){
319 if( isBin1 || isBin2 ){
320 fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
321 return;
@@ -336,19 +329,13 @@
329 }
330 glob_free(pBinary);
331 }
332 }
333
 
 
 
 
 
 
334 /* Construct a temporary file names */
335 file_tempname(&temp1, zName, "before");
336 file_tempname(&temp2, zName, "after");
337 blob_write_to_file(pFile1, blob_str(&temp1));
338 blob_write_to_file(pFile2, blob_str(&temp2));
339
340 /* Construct the external diff command */
341 blob_zero(&cmd);
@@ -361,12 +348,10 @@
348
349 /* Delete the temporary file and clean up memory used */
350 file_delete(blob_str(&temp1));
351 file_delete(blob_str(&temp2));
352
 
 
353 blob_reset(&temp1);
354 blob_reset(&temp2);
355 blob_reset(&cmd);
356 }
357 }
358
+881 -38
--- src/export.c
+++ src/export.c
@@ -28,25 +28,26 @@
2828
const char *zTrunkName; /* Name of trunk branch */
2929
} gexport;
3030
3131
#if INTERFACE
3232
/*
33
-** struct mark_t
34
-** holds information for translating between git commits
35
-** and fossil commits.
36
-** -git_name: This is the mark name that identifies the commit to git.
37
-** It will always begin with a ':'.
38
-** -rid: The unique object ID that identifies this commit within the
39
-** repository database.
40
-** -uuid: The SHA-1/SHA-3 of artifact corresponding to rid.
33
+** Each line in a git-fast-export "marK" file is an instance of
34
+** this object.
4135
*/
42
-struct mark_t{
43
- char *name;
44
- int rid;
45
- char uuid[65];
36
+struct mark_t {
37
+ char *name; /* Name of the mark. Also starts with ":" */
38
+ int rid; /* Corresponding object in the BLOB table */
39
+ char uuid[65]; /* The GIT hash name for this object */
4640
};
4741
#endif
42
+
43
+#if defined(_WIN32) || defined(WIN32)
44
+# undef popen
45
+# define popen _popen
46
+# undef pclose
47
+# define pclose _pclose
48
+#endif
4849
4950
/*
5051
** Output a "committer" record for the given user.
5152
** NOTE: the given user name may be an email itself.
5253
*/
@@ -297,18 +298,18 @@
297298
}
298299
return zMark;
299300
}
300301
301302
/*
302
-** parse_mark()
303
-** Create a new (mark,rid,uuid) entry in the 'xmark' table given a line
304
-** from a marks file. Return the cross-ref information as a struct mark_t
305
-** in *mark.
306
-** This function returns -1 in the case that the line is blank, malformed, or
307
-** the rid/uuid named in 'line' does not match what is in the repository
308
-** database. Otherwise, 0 is returned.
309
-** mark->name is dynamically allocated, and owned by the caller.
303
+** Parse a single line of the mark file. Store the result in the mark object.
304
+**
305
+** "line" is a single line of input.
306
+** This function returns -1 in the case that the line is blank, malformed, or
307
+** the rid/uuid named in 'line' does not match what is in the repository
308
+** database. Otherwise, 0 is returned.
309
+**
310
+** mark->name is dynamically allocated, and owned by the caller.
310311
*/
311312
int parse_mark(char *line, struct mark_t *mark){
312313
char *cur_tok;
313314
char type_;
314315
cur_tok = strtok(line, " \t");
@@ -361,23 +362,24 @@
361362
insert_commit_xref(mark->rid, mark->name, mark->uuid);
362363
return 0;
363364
}
364365
365366
/*
366
-** import_marks()
367
-** Import the marks specified in file 'f' into the 'xmark' table.
368
-** If 'blobs' is non-null, insert all blob marks into it.
369
-** If 'vers' is non-null, insert all commit marks into it.
370
-** If 'unused_marks' is non-null, upon return of this function, all values
371
-** x >= *unused_marks are free to use as marks, i.e. they do not clash with
372
-** any marks appearing in the marks file.
373
-** Each line in the file must be at most 100 characters in length. This
374
-** seems like a reasonable maximum for a 40-character uuid, and 1-13
375
-** character rid.
376
-** The function returns -1 if any of the lines in file 'f' are malformed,
377
-** or the rid/uuid information doesn't match what is in the repository
378
-** database. Otherwise, 0 is returned.
367
+** Import the marks specified in file 'f';
368
+** If 'blobs' is non-null, insert all blob marks into it.
369
+** If 'vers' is non-null, insert all commit marks into it.
370
+** If 'unused_marks' is non-null, upon return of this function, all values
371
+** x >= *unused_marks are free to use as marks, i.e. they do not clash with
372
+** any marks appearing in the marks file.
373
+**
374
+** Each line in the file must be at most 100 characters in length. This
375
+** seems like a reasonable maximum for a 40-character uuid, and 1-13
376
+** character rid.
377
+**
378
+** The function returns -1 if any of the lines in file 'f' are malformed,
379
+** or the rid/uuid information doesn't match what is in the repository
380
+** database. Otherwise, 0 is returned.
379381
*/
380382
int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
381383
char line[101];
382384
while(fgets(line, sizeof(line), f)){
383385
struct mark_t mark;
@@ -452,13 +454,13 @@
452454
}while( (rid = bag_next(vers, rid))!=0 );
453455
}
454456
}
455457
}
456458
457
-/*
458
-** COMMAND: export
459
-**
459
+/* This is the original header command (and hence documentation) for
460
+** the "fossil export" command:
461
+**
460462
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
461463
**
462464
** Write an export of all check-ins to standard output. The export is
463465
** written in the git-fast-export file format assuming the --git option is
464466
** provided. The git-fast-export format is currently the only VCS
@@ -483,10 +485,15 @@
483485
** --rename-trunk NAME use NAME as name of exported trunk branch
484486
** --repository|-R REPOSITORY export the given REPOSITORY
485487
**
486488
** See also: import
487489
*/
490
+/*
491
+** COMMAND: export*
492
+**
493
+** This command is deprecated. Use "fossil git export" instead.
494
+*/
488495
void export_cmd(void){
489496
Stmt q, q2, q3;
490497
Bag blobs, vers;
491498
unsigned int unused_mark = 1;
492499
const char *markfile_in;
@@ -507,11 +514,12 @@
507514
verify_all_options();
508515
if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
509516
510517
db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
511518
db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
512
- db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT)");
519
+ db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT,"
520
+ " tuuid TEXT)");
513521
db_multi_exec("CREATE INDEX xmark_trid ON xmark(trid)");
514522
if( markfile_in!=0 ){
515523
Stmt qb,qc;
516524
FILE *f;
517525
int rid;
@@ -754,11 +762,11 @@
754762
** );
755763
**
756764
** This table contains all check-ins of the repository in topological
757765
** order. "Topological order" means that every parent check-in comes
758766
** before all of its children. Topological order is *almost* the same
759
-** thing as "ORDER BY event.mtime". Differences only arrise when there
767
+** thing as "ORDER BY event.mtime". Differences only arise when there
760768
** are timewarps. In as much as Git hates timewarps, we have to compute
761769
** a correct topological order when doing an export.
762770
**
763771
** Since mtime is a usually already nearly in topological order, the
764772
** algorithm is to start with mtime, then make adjustments as necessary
@@ -835,5 +843,840 @@
835843
int n;
836844
db_find_and_open_repository(0, 0);
837845
n = topological_sort_checkins(1);
838846
fossil_print("%d reorderings required\n", n);
839847
}
848
+
849
+/***************************************************************************
850
+** Implementation of the "fossil git" command follows. We hope that the
851
+** new code that follows will largely replace the legacy "fossil export"
852
+** and "fossil import" code above.
853
+*/
854
+
855
+/* Verbosity level. Higher means more output.
856
+**
857
+** 0 print nothing at all
858
+** 1 Errors only
859
+** 2 Progress information (This is the default)
860
+** 3 Extra details
861
+*/
862
+#define VERB_ERROR 1
863
+#define VERB_NORMAL 2
864
+#define VERB_EXTRA 3
865
+static int gitmirror_verbosity = VERB_NORMAL;
866
+
867
+/*
868
+** Output routine that depends on verbosity
869
+*/
870
+static void gitmirror_message(int iLevel, const char *zFormat, ...){
871
+ va_list ap;
872
+ if( iLevel>gitmirror_verbosity ) return;
873
+ va_start(ap, zFormat);
874
+ fossil_vprint(zFormat, ap);
875
+ va_end(ap);
876
+}
877
+
878
+/*
879
+** Convert characters of z[] that are not allowed to be in branch or
880
+** tag names into "_".
881
+*/
882
+static void gitmirror_sanitize_name(char *z){
883
+ static unsigned char aSafe[] = {
884
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
885
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
886
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
887
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2x */
888
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* 3x */
889
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
890
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, /* 5x */
891
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
892
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* 7x */
893
+ };
894
+ unsigned char *zu = (unsigned char*)z;
895
+ int i;
896
+ for(i=0; zu[i]; i++){
897
+ if( zu[i]>0x7f || !aSafe[zu[i]] ){
898
+ zu[i] = '_';
899
+ }else if( zu[i]=='/' && (i==0 || zu[i+1]==0 || zu[i+1]=='/') ){
900
+ zu[i] = '_';
901
+ }else if( zu[i]=='.' && (zu[i+1]==0 || zu[i+1]=='.'
902
+ || (i>0 && zu[i-1]=='.')) ){
903
+ zu[i] = '_';
904
+ }
905
+ }
906
+}
907
+
908
+/*
909
+** Quote a filename as a C-style string using \\ and \" if necessary.
910
+** If quoting is not necessary, just return a copy of the input string.
911
+**
912
+** The return value is a held in memory obtained from fossil_malloc()
913
+** and must be freed by the caller.
914
+*/
915
+static char *gitmirror_quote_filename_if_needed(const char *zIn){
916
+ int i, j;
917
+ char c;
918
+ int nSpecial = 0;
919
+ char *zOut;
920
+ for(i=0; (c = zIn[i])!=0; i++){
921
+ if( c=='\\' || c=='"' || c=='\n' ){
922
+ nSpecial++;
923
+ }
924
+ }
925
+ if( nSpecial==0 ){
926
+ return fossil_strdup(zIn);
927
+ }
928
+ zOut = fossil_malloc( i+nSpecial+3 );
929
+ zOut[0] = '"';
930
+ for(i=0, j=1; (c = zIn[i])!=0; i++){
931
+ if( c=='\\' || c=='"' || c=='\n' ){
932
+ zOut[j++] = '\\';
933
+ if( c=='\n' ){
934
+ zOut[j++] = 'n';
935
+ }else{
936
+ zOut[j++] = c;
937
+ }
938
+ }else{
939
+ zOut[j++] = c;
940
+ }
941
+ }
942
+ zOut[j++] = '"';
943
+ zOut[j] = 0;
944
+ return zOut;
945
+}
946
+
947
+/*
948
+** Find the Git-name corresponding to the Fossil-name zUuid.
949
+**
950
+** If the mark does not exist and if the bCreate flag is false, then
951
+** return NULL. If the mark does not exist and the bCreate flag is true,
952
+** then create the mark.
953
+**
954
+** The string returned is obtained from fossil_malloc() and should
955
+** be freed by the caller.
956
+*/
957
+static char *gitmirror_find_mark(const char *zUuid, int isFile, int bCreate){
958
+ static Stmt sFind, sIns;
959
+ db_static_prepare(&sFind,
960
+ "SELECT coalesce(githash,printf(':%%d',id))"
961
+ " FROM mirror.mmark WHERE uuid=:uuid AND isfile=:isfile"
962
+ );
963
+ db_bind_text(&sFind, ":uuid", zUuid);
964
+ db_bind_int(&sFind, ":isfile", isFile!=0);
965
+ if( db_step(&sFind)==SQLITE_ROW ){
966
+ char *zMark = fossil_strdup(db_column_text(&sFind, 0));
967
+ db_reset(&sFind);
968
+ return zMark;
969
+ }
970
+ db_reset(&sFind);
971
+ if( !bCreate ){
972
+ return 0;
973
+ }
974
+ db_static_prepare(&sIns,
975
+ "INSERT INTO mirror.mmark(uuid,isfile) VALUES(:uuid,:isfile)"
976
+ );
977
+ db_bind_text(&sIns, ":uuid", zUuid);
978
+ db_bind_int(&sIns, ":isfile", isFile!=0);
979
+ db_step(&sIns);
980
+ db_reset(&sIns);
981
+ return mprintf(":%d", db_last_insert_rowid());
982
+}
983
+
984
+/* This is the SHA3-256 hash of an empty file */
985
+static const char zEmptySha3[] =
986
+ "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
987
+
988
+/*
989
+** Export a single file named by zUuid.
990
+**
991
+** Return 0 on success and non-zero on any failure.
992
+**
993
+** If zUuid is a shunned file, then treat it as if it were any empty file.
994
+** But files that are missing from the repository but have not been officially
995
+** shunned cause an error return. Except, if bPhantomOk is true, then missing
996
+** files are replaced by an empty file.
997
+*/
998
+static int gitmirror_send_file(FILE *xCmd, const char *zUuid, int bPhantomOk){
999
+ char *zMark;
1000
+ int rid;
1001
+ int rc;
1002
+ Blob data;
1003
+ rid = fast_uuid_to_rid(zUuid);
1004
+ if( rid<0 ){
1005
+ if( bPhantomOk || uuid_is_shunned(zUuid) ){
1006
+ gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
1007
+ zUuid = zEmptySha3;
1008
+ }else{
1009
+ return 1;
1010
+ }
1011
+ }else{
1012
+ rc = content_get(rid, &data);
1013
+ if( rc==0 ){
1014
+ if( bPhantomOk ){
1015
+ blob_init(&data, 0, 0);
1016
+ gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
1017
+ zUuid = zEmptySha3;
1018
+ }else{
1019
+ return 1;
1020
+ }
1021
+ }
1022
+ }
1023
+ zMark = gitmirror_find_mark(zUuid, 1, 1);
1024
+ if( zMark[0]==':' ){
1025
+ fprintf(xCmd, "blob\nmark %s\ndata %d\n", zMark, blob_size(&data));
1026
+ fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
1027
+ fprintf(xCmd, "\n");
1028
+ }
1029
+ fossil_free(zMark);
1030
+ blob_reset(&data);
1031
+ return 0;
1032
+}
1033
+
1034
+/*
1035
+** Transfer a check-in over to the mirror. "rid" is the BLOB.RID for
1036
+** the check-in to export.
1037
+**
1038
+** If any ancestor of the check-in has not yet been exported, then
1039
+** invoke this routine recursively to export the ancestor first.
1040
+** This can only happen on a timewarp, so deep nesting is unlikely.
1041
+**
1042
+** Before sending the check-in, first make sure all associated files
1043
+** have already been exported, and send "blob" records for any that
1044
+** have not been. Update the MIRROR.MMARK table so that it holds the
1045
+** marks for the exported files.
1046
+**
1047
+** Return zero on success and non-zero if the export should be stopped.
1048
+*/
1049
+static int gitmirror_send_checkin(
1050
+ FILE *xCmd, /* Write fast-import text on this pipe */
1051
+ int rid, /* BLOB.RID for the check-in to export */
1052
+ const char *zUuid, /* BLOB.UUID for the check-in to export */
1053
+ int *pnLimit, /* Stop when the counter reaches zero */
1054
+ int fManifest /* MFESTFLG_* values */
1055
+){
1056
+ Manifest *pMan; /* The check-in to be output */
1057
+ int i; /* Loop counter */
1058
+ int iParent; /* Which immediate ancestor is primary. -1 for none */
1059
+ Stmt q; /* An SQL query */
1060
+ char *zBranch; /* The branch of the check-in */
1061
+ char *zMark; /* The Git-name of the check-in */
1062
+ Blob sql; /* String of SQL for part of the query */
1063
+ Blob comment; /* The comment text for the check-in */
1064
+ int nErr = 0; /* Number of errors */
1065
+ int bPhantomOk; /* True if phantom files should be ignored */
1066
+
1067
+ pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
1068
+ if( pMan==0 ){
1069
+ /* Must be a phantom. Return without doing anything, and in particular
1070
+ ** without creating a mark for this check-in. */
1071
+ gitmirror_message(VERB_NORMAL, "missing check-in: %s\n", zUuid);
1072
+ return 0;
1073
+ }
1074
+
1075
+ /* Check to see if any parent logins have not yet been processed, and
1076
+ ** if so, create them */
1077
+ for(i=0; i<pMan->nParent; i++){
1078
+ char *zPMark = gitmirror_find_mark(pMan->azParent[i], 0, 0);
1079
+ if( zPMark==0 ){
1080
+ int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
1081
+ pMan->azParent[i]);
1082
+ int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i],
1083
+ pnLimit, fManifest);
1084
+ if( rc || *pnLimit<=0 ){
1085
+ manifest_destroy(pMan);
1086
+ return 1;
1087
+ }
1088
+ }
1089
+ fossil_free(zPMark);
1090
+ }
1091
+
1092
+ /* Ignore phantom files on check-ins that are over one year old */
1093
+ bPhantomOk = db_int(0, "SELECT %.6f<julianday('now','-1 year')",
1094
+ pMan->rDate);
1095
+
1096
+ /* Make sure all necessary files have been exported */
1097
+ db_prepare(&q,
1098
+ "SELECT uuid FROM files_of_checkin(%Q)"
1099
+ " WHERE uuid NOT IN (SELECT uuid FROM mirror.mmark)",
1100
+ zUuid
1101
+ );
1102
+ while( db_step(&q)==SQLITE_ROW ){
1103
+ const char *zFUuid = db_column_text(&q, 0);
1104
+ int n = gitmirror_send_file(xCmd, zFUuid, bPhantomOk);
1105
+ nErr += n;
1106
+ if( n ) gitmirror_message(VERB_ERROR, "missing file: %s\n", zFUuid);
1107
+ }
1108
+ db_finalize(&q);
1109
+
1110
+ /* If some required files could not be exported, abandon the check-in
1111
+ ** export */
1112
+ if( nErr ){
1113
+ gitmirror_message(VERB_ERROR,
1114
+ "export of %s abandoned due to missing files\n", zUuid);
1115
+ *pnLimit = 0;
1116
+ return 1;
1117
+ }
1118
+
1119
+ /* Figure out which branch this check-in is a member of */
1120
+ zBranch = db_text(0,
1121
+ "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=%d",
1122
+ TAG_BRANCH, rid
1123
+ );
1124
+ if( fossil_strcmp(zBranch,"trunk")==0 ){
1125
+ fossil_free(zBranch);
1126
+ zBranch = mprintf("master");
1127
+ }else if( zBranch==0 ){
1128
+ zBranch = mprintf("unknown");
1129
+ }else{
1130
+ gitmirror_sanitize_name(zBranch);
1131
+ }
1132
+
1133
+ /* Export the check-in */
1134
+ fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
1135
+ fossil_free(zBranch);
1136
+ zMark = gitmirror_find_mark(zUuid,0,1);
1137
+ fprintf(xCmd, "mark %s\n", zMark);
1138
+ fossil_free(zMark);
1139
+ fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
1140
+ pMan->zUser, pMan->zUser,
1141
+ (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
1142
+ );
1143
+ blob_init(&comment, pMan->zComment, -1);
1144
+ if( blob_size(&comment)==0 ){
1145
+ blob_append(&comment, "(no comment)", -1);
1146
+ }
1147
+ blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid);
1148
+ fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment));
1149
+ blob_reset(&comment);
1150
+ iParent = -1; /* Which ancestor is the primary parent */
1151
+ for(i=0; i<pMan->nParent; i++){
1152
+ char *zOther = gitmirror_find_mark(pMan->azParent[i],0,0);
1153
+ if( zOther==0 ) continue;
1154
+ if( iParent<0 ){
1155
+ iParent = i;
1156
+ fprintf(xCmd, "from %s\n", zOther);
1157
+ }else{
1158
+ fprintf(xCmd, "merge %s\n", zOther);
1159
+ }
1160
+ fossil_free(zOther);
1161
+ }
1162
+ if( iParent>=0 ){
1163
+ db_prepare(&q,
1164
+ "SELECT filename FROM files_of_checkin(%Q)"
1165
+ " EXCEPT SELECT filename FROM files_of_checkin(%Q)",
1166
+ pMan->azParent[iParent], zUuid
1167
+ );
1168
+ while( db_step(&q)==SQLITE_ROW ){
1169
+ fprintf(xCmd, "D %s\n", db_column_text(&q,0));
1170
+ }
1171
+ db_finalize(&q);
1172
+ }
1173
+ blob_init(&sql, 0, 0);
1174
+ blob_append_sql(&sql,
1175
+ "SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
1176
+ zUuid
1177
+ );
1178
+ if( pMan->nParent ){
1179
+ blob_append_sql(&sql,
1180
+ " EXCEPT SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
1181
+ pMan->azParent[0]);
1182
+ }
1183
+ db_prepare(&q,
1184
+ "SELECT x.filename, x.perm,"
1185
+ " coalesce(mmark.githash,printf(':%%d',mmark.id))"
1186
+ " FROM (%s) AS x, mirror.mmark"
1187
+ " WHERE mmark.uuid=x.uuid AND isfile",
1188
+ blob_sql_text(&sql)
1189
+ );
1190
+ blob_reset(&sql);
1191
+ while( db_step(&q)==SQLITE_ROW ){
1192
+ const char *zFilename = db_column_text(&q,0);
1193
+ const char *zMode = db_column_text(&q,1);
1194
+ const char *zMark = db_column_text(&q,2);
1195
+ const char *zGitMode = "100644";
1196
+ char *zFNQuoted = 0;
1197
+ if( zMode ){
1198
+ if( strchr(zMode,'x') ) zGitMode = "100755";
1199
+ if( strchr(zMode,'l') ) zGitMode = "120000";
1200
+ }
1201
+ zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
1202
+ fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted);
1203
+ fossil_free(zFNQuoted);
1204
+ }
1205
+ db_finalize(&q);
1206
+
1207
+ /* Include Fossil-generated auxiliary files in the check-in */
1208
+ if( fManifest & MFESTFLG_RAW ){
1209
+ Blob manifest;
1210
+ content_get(rid, &manifest);
1211
+ fprintf(xCmd,"M 100644 inline manifest\ndata %d\n%s\n",
1212
+ blob_size(&manifest), blob_str(&manifest));
1213
+ blob_reset(&manifest);
1214
+ }
1215
+ if( fManifest & MFESTFLG_UUID ){
1216
+ int n = (int)strlen(zUuid);
1217
+ fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
1218
+ }
1219
+ if( fManifest & MFESTFLG_TAGS ){
1220
+ Blob tagslist;
1221
+ blob_init(&tagslist, 0, 0);
1222
+ get_checkin_taglist(rid, &tagslist);
1223
+ fprintf(xCmd,"M 100644 inline manifest.tags\ndata %d\n%s\n",
1224
+ blob_size(&tagslist), blob_str(&tagslist));
1225
+ blob_reset(&tagslist);
1226
+ }
1227
+
1228
+ /* The check-in is finished, so decrement the counter */
1229
+ (*pnLimit)--;
1230
+ return 0;
1231
+}
1232
+
1233
+/*
1234
+** Implementation of the "fossil git export" command.
1235
+*/
1236
+void gitmirror_export_command(void){
1237
+ const char *zLimit; /* Text of the --limit flag */
1238
+ int nLimit = 0x7fffffff; /* Numeric value of the --limit flag */
1239
+ int nTotal = 0; /* Total number of check-ins to export */
1240
+ char *zMirror; /* Name of the mirror */
1241
+ char *z; /* Generic string */
1242
+ char *zCmd; /* git command to run as a subprocess */
1243
+ const char *zDebug = 0; /* Value of the --debug flag */
1244
+ const char *zAutoPush = 0; /* Value of the --autopush flag */
1245
+ char *zPushUrl; /* URL to sync the mirror to */
1246
+ double rEnd; /* time of most recent export */
1247
+ int rc; /* Result code */
1248
+ int bForce; /* Do the export and sync even if no changes*/
1249
+ int bNeedRepack = 0; /* True if we should run repack at the end */
1250
+ int fManifest; /* Current "manifest" setting */
1251
+ FILE *xCmd; /* Pipe to the "git fast-import" command */
1252
+ FILE *pMarks; /* Git mark files */
1253
+ Stmt q; /* Queries */
1254
+ char zLine[200]; /* One line of a mark file */
1255
+
1256
+ zDebug = find_option("debug",0,1);
1257
+ db_find_and_open_repository(0, 0);
1258
+ zLimit = find_option("limit", 0, 1);
1259
+ if( zLimit ){
1260
+ nLimit = (unsigned int)atoi(zLimit);
1261
+ if( nLimit<=0 ) fossil_fatal("--limit must be positive");
1262
+ }
1263
+ zAutoPush = find_option("autopush",0,1);
1264
+ bForce = find_option("force","f",0)!=0;
1265
+ gitmirror_verbosity = VERB_NORMAL;
1266
+ while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; }
1267
+ while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; }
1268
+ verify_all_options();
1269
+ if( g.argc!=4 && g.argc!=3 ){ usage("export ?MIRROR?"); }
1270
+ if( g.argc==4 ){
1271
+ Blob mirror;
1272
+ file_canonical_name(g.argv[3], &mirror, 0);
1273
+ db_set("last-git-export-repo", blob_str(&mirror), 0);
1274
+ blob_reset(&mirror);
1275
+ }
1276
+ zMirror = db_get("last-git-export-repo", 0);
1277
+ if( zMirror==0 ){
1278
+ fossil_fatal("no Git repository specified");
1279
+ }
1280
+
1281
+ /* Make sure the GIT repository directory exists */
1282
+ rc = file_mkdir(zMirror, ExtFILE, 0);
1283
+ if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror);
1284
+
1285
+ /* Make sure GIT has been initialized */
1286
+ z = mprintf("%s/.git", zMirror);
1287
+ if( !file_isdir(z, ExtFILE) ){
1288
+ zCmd = mprintf("git init '%s'",zMirror);
1289
+ gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
1290
+ rc = fossil_system(zCmd);
1291
+ if( rc ){
1292
+ fossil_fatal("cannot initialize the git repository using: \"%s\"", zCmd);
1293
+ }
1294
+ fossil_free(zCmd);
1295
+ bNeedRepack = 1;
1296
+ }
1297
+ fossil_free(z);
1298
+
1299
+ /* Make sure the .mirror_state subdirectory exists */
1300
+ z = mprintf("%s/.mirror_state", zMirror);
1301
+ rc = file_mkdir(z, ExtFILE, 0);
1302
+ if( rc ) fossil_fatal("cannot create directory \"%s\"", z);
1303
+ fossil_free(z);
1304
+
1305
+ /* Attach the .mirror_state/db database */
1306
+ db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
1307
+ db_begin_write();
1308
+ db_multi_exec(
1309
+ "CREATE TABLE IF NOT EXISTS mirror.mconfig(\n"
1310
+ " key TEXT PRIMARY KEY,\n"
1311
+ " Value ANY\n"
1312
+ ") WITHOUT ROWID;\n"
1313
+ "CREATE TABLE IF NOT EXISTS mirror.mmark(\n"
1314
+ " id INTEGER PRIMARY KEY,\n"
1315
+ " uuid TEXT,\n"
1316
+ " isfile BOOLEAN,\n"
1317
+ " githash TEXT,\n"
1318
+ " UNIQUE(uuid,isfile)\n"
1319
+ ");"
1320
+ );
1321
+ if( !db_table_has_column("mirror","mmark","isfile") ){
1322
+ db_multi_exec(
1323
+ "ALTER TABLE mirror.mmark RENAME TO mmark_old;"
1324
+ "CREATE TABLE IF NOT EXISTS mirror.mmark(\n"
1325
+ " id INTEGER PRIMARY KEY,\n"
1326
+ " uuid TEXT,\n"
1327
+ " isfile BOOLEAN,\n"
1328
+ " githash TEXT,\n"
1329
+ " UNIQUE(uuid,isfile)\n"
1330
+ ");"
1331
+ "INSERT OR IGNORE INTO mirror.mmark(id,uuid,githash,isfile)"
1332
+ " SELECT id,uuid,githash,"
1333
+ " NOT EXISTS(SELECT 1 FROM repository.event, repository.blob"
1334
+ " WHERE event.objid=blob.rid"
1335
+ " AND blob.uuid=mmark_old.uuid)"
1336
+ " FROM mirror.mmark_old;\n"
1337
+ "DROP TABLE mirror.mmark_old;\n"
1338
+ );
1339
+ }
1340
+
1341
+ /* Change the autopush setting if the --autopush flag is present */
1342
+ if( zAutoPush ){
1343
+ if( is_false(zAutoPush) ){
1344
+ db_multi_exec("DELETE FROM mirror.mconfig WHERE key='autopush'");
1345
+ }else{
1346
+ db_multi_exec(
1347
+ "REPLACE INTO mirror.mconfig(key,value)"
1348
+ "VALUES('autopush',%Q)",
1349
+ zAutoPush
1350
+ );
1351
+ }
1352
+ }
1353
+
1354
+ /* See if there is any work to be done. Exit early if not, before starting
1355
+ ** the "git fast-import" command. */
1356
+ if( !bForce
1357
+ && !db_exists("SELECT 1 FROM event WHERE type IN ('ci','t')"
1358
+ " AND mtime>coalesce((SELECT value FROM mconfig"
1359
+ " WHERE key='start'),0.0)")
1360
+ ){
1361
+ gitmirror_message(VERB_NORMAL, "no changes\n");
1362
+ db_commit_transaction();
1363
+ return;
1364
+ }
1365
+
1366
+ /* Do we need to include manifest files in the clone? */
1367
+ fManifest = db_get_manifest_setting();
1368
+
1369
+ /* Change to the MIRROR directory so that the Git commands will work */
1370
+ rc = file_chdir(zMirror, 0);
1371
+ if( rc ) fossil_fatal("cannot change the working directory to \"%s\"",
1372
+ zMirror);
1373
+
1374
+ /* Start up the git fast-import command */
1375
+ if( zDebug ){
1376
+ if( fossil_strcmp(zDebug,"stdout")==0 ){
1377
+ xCmd = stdout;
1378
+ }else{
1379
+ xCmd = fopen(zDebug, "wb");
1380
+ if( xCmd==0 ) fossil_fatal("cannot open file \"%s\" for writing", zDebug);
1381
+ }
1382
+ }else{
1383
+ zCmd = mprintf("git fast-import"
1384
+ " --export-marks=.mirror_state/marks.txt"
1385
+ " --quiet --done");
1386
+ gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
1387
+ xCmd = popen(zCmd, "w");
1388
+ if( zCmd==0 ){
1389
+ fossil_fatal("cannot start the \"git fast-import\" command");
1390
+ }
1391
+ fossil_free(zCmd);
1392
+ }
1393
+
1394
+ /* Run the export */
1395
+ rEnd = 0.0;
1396
+ db_multi_exec(
1397
+ "CREATE TEMP TABLE tomirror(objid,mtime,uuid);\n"
1398
+ "INSERT INTO tomirror "
1399
+ "SELECT objid, mtime, blob.uuid FROM event, blob\n"
1400
+ " WHERE type='ci'"
1401
+ " AND mtime>coalesce((SELECT value FROM mconfig WHERE key='start'),0.0)"
1402
+ " AND blob.rid=event.objid"
1403
+ " AND blob.uuid NOT IN (SELECT uuid FROM mirror.mmark WHERE NOT isfile);"
1404
+ );
1405
+ nTotal = db_int(0, "SELECT count(*) FROM tomirror");
1406
+ if( nLimit<nTotal ){
1407
+ nTotal = nLimit;
1408
+ }else if( nLimit>nTotal ){
1409
+ nLimit = nTotal;
1410
+ }
1411
+ db_prepare(&q,
1412
+ "SELECT objid, mtime, uuid FROM tomirror ORDER BY mtime"
1413
+ );
1414
+ while( nLimit && db_step(&q)==SQLITE_ROW ){
1415
+ int rid = db_column_int(&q, 0);
1416
+ double rMTime = db_column_double(&q, 1);
1417
+ const char *zUuid = db_column_text(&q, 2);
1418
+ if( rMTime>rEnd ) rEnd = rMTime;
1419
+ rc = gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
1420
+ if( rc ) break;
1421
+ gitmirror_message(VERB_NORMAL,"%d/%d \r", nTotal-nLimit, nTotal);
1422
+ fflush(stdout);
1423
+ }
1424
+ db_finalize(&q);
1425
+ fprintf(xCmd, "done\n");
1426
+ if( zDebug ){
1427
+ if( xCmd!=stdout ) fclose(xCmd);
1428
+ }else{
1429
+ pclose(xCmd);
1430
+ }
1431
+ gitmirror_message(VERB_NORMAL, "%d check-ins added to the %s\n",
1432
+ nTotal-nLimit, zMirror);
1433
+
1434
+ /* Read the export-marks file. Transfer the new marks over into
1435
+ ** the import-marks file.
1436
+ */
1437
+ pMarks = fopen(".mirror_state/marks.txt", "rb");
1438
+ if( pMarks ){
1439
+ db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id");
1440
+ while( fgets(zLine, sizeof(zLine), pMarks) ){
1441
+ int j, k;
1442
+ if( zLine[0]!=':' ) continue;
1443
+ db_bind_int(&q, ":id", atoi(zLine+1));
1444
+ for(j=1; zLine[j] && zLine[j]!=' '; j++){}
1445
+ if( zLine[j]!=' ' ) continue;
1446
+ j++;
1447
+ if( zLine[j]==0 ) continue;
1448
+ for(k=j; fossil_isalnum(zLine[k]); k++){}
1449
+ zLine[k] = 0;
1450
+ db_bind_text(&q, ":githash", &zLine[j]);
1451
+ db_step(&q);
1452
+ db_reset(&q);
1453
+ }
1454
+ db_finalize(&q);
1455
+ fclose(pMarks);
1456
+ file_delete(".mirror_state/marks.txt");
1457
+ }else{
1458
+ fossil_fatal("git fast-import didn't generate a marks file!");
1459
+ }
1460
+ db_multi_exec(
1461
+ "CREATE INDEX IF NOT EXISTS mirror.mmarkx1 ON mmark(githash);"
1462
+ );
1463
+
1464
+ /* Do any tags that have been created since the start time */
1465
+ db_prepare(&q,
1466
+ "SELECT substr(tagname,5), githash"
1467
+ " FROM (SELECT tagxref.tagid AS xtagid, tagname, rid, max(mtime) AS mtime"
1468
+ " FROM tagxref JOIN tag ON tag.tagid=tagxref.tagid"
1469
+ " WHERE tag.tagname GLOB 'sym-*'"
1470
+ " AND tagxref.tagtype=1"
1471
+ " AND tagxref.mtime > coalesce((SELECT value FROM mconfig"
1472
+ " WHERE key='start'),0.0)"
1473
+ " GROUP BY tagxref.tagid) AS tx"
1474
+ " JOIN blob ON tx.rid=blob.rid"
1475
+ " JOIN mmark ON mmark.uuid=blob.uuid;"
1476
+ );
1477
+ while( db_step(&q)==SQLITE_ROW ){
1478
+ char *zTagname = fossil_strdup(db_column_text(&q,0));
1479
+ const char *zObj = db_column_text(&q,1);
1480
+ char *zTagCmd;
1481
+ gitmirror_sanitize_name(zTagname);
1482
+ zTagCmd = mprintf("git tag -f \"%s\" %s", zTagname, zObj);
1483
+ fossil_free(zTagname);
1484
+ gitmirror_message(VERB_NORMAL, "%s\n", zTagCmd);
1485
+ fossil_system(zTagCmd);
1486
+ fossil_free(zTagCmd);
1487
+ }
1488
+ db_finalize(&q);
1489
+
1490
+ /* Update all references that might have changed since the start time */
1491
+ db_prepare(&q,
1492
+ "SELECT"
1493
+ " tagxref.value AS name,"
1494
+ " max(event.mtime) AS mtime,"
1495
+ " mmark.githash AS gitckin"
1496
+ " FROM tagxref, tag, event, blob, mmark"
1497
+ " WHERE tagxref.tagid=tag.tagid"
1498
+ " AND tagxref.tagtype>0"
1499
+ " AND tag.tagname='branch'"
1500
+ " AND event.objid=tagxref.rid"
1501
+ " AND event.mtime > coalesce((SELECT value FROM mconfig"
1502
+ " WHERE key='start'),0.0)"
1503
+ " AND blob.rid=tagxref.rid"
1504
+ " AND mmark.uuid=blob.uuid"
1505
+ " GROUP BY 1"
1506
+ );
1507
+ while( db_step(&q)==SQLITE_ROW ){
1508
+ char *zBrname = fossil_strdup(db_column_text(&q,0));
1509
+ const char *zObj = db_column_text(&q,2);
1510
+ char *zRefCmd;
1511
+ if( fossil_strcmp(zBrname,"trunk")==0 ){
1512
+ fossil_free(zBrname);
1513
+ zBrname = fossil_strdup("master");
1514
+ }else{
1515
+ gitmirror_sanitize_name(zBrname);
1516
+ }
1517
+ zRefCmd = mprintf("git update-ref \"refs/heads/%s\" %s", zBrname, zObj);
1518
+ fossil_free(zBrname);
1519
+ gitmirror_message(VERB_NORMAL, "%s\n", zRefCmd);
1520
+ fossil_system(zRefCmd);
1521
+ fossil_free(zRefCmd);
1522
+ }
1523
+ db_finalize(&q);
1524
+
1525
+ /* Update the start time */
1526
+ if( rEnd>0.0 ){
1527
+ db_prepare(&q, "REPLACE INTO mirror.mconfig(key,value) VALUES('start',:x)");
1528
+ db_bind_double(&q, ":x", rEnd);
1529
+ db_step(&q);
1530
+ db_finalize(&q);
1531
+ }
1532
+ db_commit_transaction();
1533
+
1534
+ /* Maybe run a git repack */
1535
+ if( bNeedRepack ){
1536
+ const char *zRepack = "git repack -adf";
1537
+ gitmirror_message(VERB_NORMAL, "%s\n", zRepack);
1538
+ fossil_system(zRepack);
1539
+ }
1540
+
1541
+ /* Optionally do a "git push" */
1542
+ zPushUrl = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
1543
+ if( zPushUrl ){
1544
+ char *zPushCmd;
1545
+ UrlData url;
1546
+ if( sqlite3_strglob("http*", zPushUrl)==0 ){
1547
+ url_parse_local(zPushUrl, 0, &url);
1548
+ zPushCmd = mprintf("git push --mirror %s", url.canonical);
1549
+ }else{
1550
+ zPushCmd = mprintf("git push --mirror %s", zPushUrl);
1551
+ }
1552
+ gitmirror_message(VERB_NORMAL, "%s\n", zPushCmd);
1553
+ fossil_free(zPushCmd);
1554
+ zPushCmd = mprintf("git push --mirror %s", zPushUrl);
1555
+ fossil_system(zPushCmd);
1556
+ fossil_free(zPushCmd);
1557
+ }
1558
+}
1559
+
1560
+/*
1561
+** Implementation of the "fossil git status" command.
1562
+**
1563
+** Show the status of a "git export".
1564
+*/
1565
+void gitmirror_status_command(void){
1566
+ char *zMirror;
1567
+ char *z;
1568
+ int n, k;
1569
+ db_find_and_open_repository(0, 0);
1570
+ verify_all_options();
1571
+ zMirror = db_get("last-git-export-repo", 0);
1572
+ if( zMirror==0 ){
1573
+ fossil_print("Git mirror: none\n");
1574
+ return;
1575
+ }
1576
+ fossil_print("Git mirror: %s\n", zMirror);
1577
+ db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
1578
+ z = db_text(0, "SELECT datetime(value) FROM mconfig WHERE key='start'");
1579
+ if( z ){
1580
+ double rAge = db_double(0.0, "SELECT julianday('now') - value"
1581
+ " FROM mconfig WHERE key='start'");
1582
+ if( rAge>1.0/86400.0 ){
1583
+ fossil_print("Last export: %s (%z ago)\n", z, human_readable_age(rAge));
1584
+ }else{
1585
+ fossil_print("Last export: %s (moments ago)\n", z);
1586
+ }
1587
+ }
1588
+ z = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
1589
+ if( z==0 ){
1590
+ fossil_print("Autopush: off\n");
1591
+ }else{
1592
+ UrlData url;
1593
+ url_parse_local(z, 0, &url);
1594
+ fossil_print("Autopush: %s\n", url.canonical);
1595
+ }
1596
+ n = db_int(0,
1597
+ "SELECT count(*) FROM event"
1598
+ " WHERE type='ci'"
1599
+ " AND mtime>coalesce((SELECT value FROM mconfig"
1600
+ " WHERE key='start'),0.0)"
1601
+ );
1602
+ if( n==0 ){
1603
+ fossil_print("Status: up-to-date\n");
1604
+ }else{
1605
+ fossil_print("Status: %d check-in%s awaiting export\n",
1606
+ n, n==1 ? "" : "s");
1607
+ }
1608
+ n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile");
1609
+ k = db_int(0, "SELECT count(*) FROm mmark WHERE NOT isfile");
1610
+ fossil_print("Exported: %d check-ins and %d file blobs\n", k, n);
1611
+}
1612
+
1613
+/*
1614
+** COMMAND: git
1615
+**
1616
+** Usage: %fossil git SUBCOMMAND
1617
+**
1618
+** Do incremental import or export operations between Fossil and Git.
1619
+** Subcommands:
1620
+**
1621
+** fossil git export [MIRROR] [OPTIONS]
1622
+**
1623
+** Write content from the Fossil repository into the Git repository
1624
+** in directory MIRROR. The Git repository is created if it does not
1625
+** already exist. If the Git repository does already exist, then
1626
+** new content added to fossil since the previous export is appended.
1627
+**
1628
+** Repeat this command whenever new checkins are added to the Fossil
1629
+** repository in order to reflect those changes into the mirror. If
1630
+** the MIRROR option is omitted, the repository from the previous
1631
+** invocation is used.
1632
+**
1633
+** The MIRROR directory will contain a subdirectory named
1634
+** ".mirror_state" that contains information that Fossil needs to
1635
+** do incremental exports. Do not attempt to manage or edit the files
1636
+** in that directory since doing so can disrupt future incremental
1637
+** exports.
1638
+**
1639
+** Options:
1640
+** --autopush URL Automatically do a 'git push' to URL. The
1641
+** URL is remembered and used on subsequent exports
1642
+** to the same repository. Or if URL is "off" the
1643
+** auto-push mechanism is disabled
1644
+** --debug FILE Write fast-export text to FILE rather than
1645
+** piping it into "git fast-import".
1646
+** --force|-f Do the export even if nothing has changed
1647
+** --limit N Add no more than N new check-ins to MIRROR.
1648
+** Useful for debugging
1649
+** --quiet|-q Reduce output. Repeat for even less output.
1650
+** --verbose|-v More output.
1651
+**
1652
+** fossil git import MIRROR
1653
+**
1654
+** TBD...
1655
+**
1656
+** fossil git status
1657
+**
1658
+** Show the status of the current Git mirror, if there is one.
1659
+*/
1660
+void gitmirror_command(void){
1661
+ char *zCmd;
1662
+ int nCmd;
1663
+ if( g.argc<3 ){
1664
+ usage("export ARGS...");
1665
+ }
1666
+ zCmd = g.argv[2];
1667
+ nCmd = (int)strlen(zCmd);
1668
+ if( nCmd>2 && strncmp(zCmd,"export",nCmd)==0 ){
1669
+ gitmirror_export_command();
1670
+ }else
1671
+ if( nCmd>2 && strncmp(zCmd,"import",nCmd)==0 ){
1672
+ fossil_fatal("not yet implemented - check back later");
1673
+ }else
1674
+ if( nCmd>2 && strncmp(zCmd,"status",nCmd)==0 ){
1675
+ gitmirror_status_command();
1676
+ }else
1677
+ {
1678
+ fossil_fatal("unknown subcommand \"%s\": should be one of "
1679
+ "\"export\", \"import\", \"status\"",
1680
+ zCmd);
1681
+ }
1682
+}
8401683
--- src/export.c
+++ src/export.c
@@ -28,25 +28,26 @@
28 const char *zTrunkName; /* Name of trunk branch */
29 } gexport;
30
31 #if INTERFACE
32 /*
33 ** struct mark_t
34 ** holds information for translating between git commits
35 ** and fossil commits.
36 ** -git_name: This is the mark name that identifies the commit to git.
37 ** It will always begin with a ':'.
38 ** -rid: The unique object ID that identifies this commit within the
39 ** repository database.
40 ** -uuid: The SHA-1/SHA-3 of artifact corresponding to rid.
41 */
42 struct mark_t{
43 char *name;
44 int rid;
45 char uuid[65];
46 };
47 #endif
 
 
 
 
 
 
 
48
49 /*
50 ** Output a "committer" record for the given user.
51 ** NOTE: the given user name may be an email itself.
52 */
@@ -297,18 +298,18 @@
297 }
298 return zMark;
299 }
300
301 /*
302 ** parse_mark()
303 ** Create a new (mark,rid,uuid) entry in the 'xmark' table given a line
304 ** from a marks file. Return the cross-ref information as a struct mark_t
305 ** in *mark.
306 ** This function returns -1 in the case that the line is blank, malformed, or
307 ** the rid/uuid named in 'line' does not match what is in the repository
308 ** database. Otherwise, 0 is returned.
309 ** mark->name is dynamically allocated, and owned by the caller.
310 */
311 int parse_mark(char *line, struct mark_t *mark){
312 char *cur_tok;
313 char type_;
314 cur_tok = strtok(line, " \t");
@@ -361,23 +362,24 @@
361 insert_commit_xref(mark->rid, mark->name, mark->uuid);
362 return 0;
363 }
364
365 /*
366 ** import_marks()
367 ** Import the marks specified in file 'f' into the 'xmark' table.
368 ** If 'blobs' is non-null, insert all blob marks into it.
369 ** If 'vers' is non-null, insert all commit marks into it.
370 ** If 'unused_marks' is non-null, upon return of this function, all values
371 ** x >= *unused_marks are free to use as marks, i.e. they do not clash with
372 ** any marks appearing in the marks file.
373 ** Each line in the file must be at most 100 characters in length. This
374 ** seems like a reasonable maximum for a 40-character uuid, and 1-13
375 ** character rid.
376 ** The function returns -1 if any of the lines in file 'f' are malformed,
377 ** or the rid/uuid information doesn't match what is in the repository
378 ** database. Otherwise, 0 is returned.
 
379 */
380 int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
381 char line[101];
382 while(fgets(line, sizeof(line), f)){
383 struct mark_t mark;
@@ -452,13 +454,13 @@
452 }while( (rid = bag_next(vers, rid))!=0 );
453 }
454 }
455 }
456
457 /*
458 ** COMMAND: export
459 **
460 ** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
461 **
462 ** Write an export of all check-ins to standard output. The export is
463 ** written in the git-fast-export file format assuming the --git option is
464 ** provided. The git-fast-export format is currently the only VCS
@@ -483,10 +485,15 @@
483 ** --rename-trunk NAME use NAME as name of exported trunk branch
484 ** --repository|-R REPOSITORY export the given REPOSITORY
485 **
486 ** See also: import
487 */
 
 
 
 
 
488 void export_cmd(void){
489 Stmt q, q2, q3;
490 Bag blobs, vers;
491 unsigned int unused_mark = 1;
492 const char *markfile_in;
@@ -507,11 +514,12 @@
507 verify_all_options();
508 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
509
510 db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
511 db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
512 db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT)");
 
513 db_multi_exec("CREATE INDEX xmark_trid ON xmark(trid)");
514 if( markfile_in!=0 ){
515 Stmt qb,qc;
516 FILE *f;
517 int rid;
@@ -754,11 +762,11 @@
754 ** );
755 **
756 ** This table contains all check-ins of the repository in topological
757 ** order. "Topological order" means that every parent check-in comes
758 ** before all of its children. Topological order is *almost* the same
759 ** thing as "ORDER BY event.mtime". Differences only arrise when there
760 ** are timewarps. In as much as Git hates timewarps, we have to compute
761 ** a correct topological order when doing an export.
762 **
763 ** Since mtime is a usually already nearly in topological order, the
764 ** algorithm is to start with mtime, then make adjustments as necessary
@@ -835,5 +843,840 @@
835 int n;
836 db_find_and_open_repository(0, 0);
837 n = topological_sort_checkins(1);
838 fossil_print("%d reorderings required\n", n);
839 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
840
--- src/export.c
+++ src/export.c
@@ -28,25 +28,26 @@
28 const char *zTrunkName; /* Name of trunk branch */
29 } gexport;
30
31 #if INTERFACE
32 /*
33 ** Each line in a git-fast-export "marK" file is an instance of
34 ** this object.
 
 
 
 
 
 
35 */
36 struct mark_t {
37 char *name; /* Name of the mark. Also starts with ":" */
38 int rid; /* Corresponding object in the BLOB table */
39 char uuid[65]; /* The GIT hash name for this object */
40 };
41 #endif
42
43 #if defined(_WIN32) || defined(WIN32)
44 # undef popen
45 # define popen _popen
46 # undef pclose
47 # define pclose _pclose
48 #endif
49
50 /*
51 ** Output a "committer" record for the given user.
52 ** NOTE: the given user name may be an email itself.
53 */
@@ -297,18 +298,18 @@
298 }
299 return zMark;
300 }
301
302 /*
303 ** Parse a single line of the mark file. Store the result in the mark object.
304 **
305 ** "line" is a single line of input.
306 ** This function returns -1 in the case that the line is blank, malformed, or
307 ** the rid/uuid named in 'line' does not match what is in the repository
308 ** database. Otherwise, 0 is returned.
309 **
310 ** mark->name is dynamically allocated, and owned by the caller.
311 */
312 int parse_mark(char *line, struct mark_t *mark){
313 char *cur_tok;
314 char type_;
315 cur_tok = strtok(line, " \t");
@@ -361,23 +362,24 @@
362 insert_commit_xref(mark->rid, mark->name, mark->uuid);
363 return 0;
364 }
365
366 /*
367 ** Import the marks specified in file 'f';
368 ** If 'blobs' is non-null, insert all blob marks into it.
369 ** If 'vers' is non-null, insert all commit marks into it.
370 ** If 'unused_marks' is non-null, upon return of this function, all values
371 ** x >= *unused_marks are free to use as marks, i.e. they do not clash with
372 ** any marks appearing in the marks file.
373 **
374 ** Each line in the file must be at most 100 characters in length. This
375 ** seems like a reasonable maximum for a 40-character uuid, and 1-13
376 ** character rid.
377 **
378 ** The function returns -1 if any of the lines in file 'f' are malformed,
379 ** or the rid/uuid information doesn't match what is in the repository
380 ** database. Otherwise, 0 is returned.
381 */
382 int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
383 char line[101];
384 while(fgets(line, sizeof(line), f)){
385 struct mark_t mark;
@@ -452,13 +454,13 @@
454 }while( (rid = bag_next(vers, rid))!=0 );
455 }
456 }
457 }
458
459 /* This is the original header command (and hence documentation) for
460 ** the "fossil export" command:
461 **
462 ** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
463 **
464 ** Write an export of all check-ins to standard output. The export is
465 ** written in the git-fast-export file format assuming the --git option is
466 ** provided. The git-fast-export format is currently the only VCS
@@ -483,10 +485,15 @@
485 ** --rename-trunk NAME use NAME as name of exported trunk branch
486 ** --repository|-R REPOSITORY export the given REPOSITORY
487 **
488 ** See also: import
489 */
490 /*
491 ** COMMAND: export*
492 **
493 ** This command is deprecated. Use "fossil git export" instead.
494 */
495 void export_cmd(void){
496 Stmt q, q2, q3;
497 Bag blobs, vers;
498 unsigned int unused_mark = 1;
499 const char *markfile_in;
@@ -507,11 +514,12 @@
514 verify_all_options();
515 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
516
517 db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
518 db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
519 db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT,"
520 " tuuid TEXT)");
521 db_multi_exec("CREATE INDEX xmark_trid ON xmark(trid)");
522 if( markfile_in!=0 ){
523 Stmt qb,qc;
524 FILE *f;
525 int rid;
@@ -754,11 +762,11 @@
762 ** );
763 **
764 ** This table contains all check-ins of the repository in topological
765 ** order. "Topological order" means that every parent check-in comes
766 ** before all of its children. Topological order is *almost* the same
767 ** thing as "ORDER BY event.mtime". Differences only arise when there
768 ** are timewarps. In as much as Git hates timewarps, we have to compute
769 ** a correct topological order when doing an export.
770 **
771 ** Since mtime is a usually already nearly in topological order, the
772 ** algorithm is to start with mtime, then make adjustments as necessary
@@ -835,5 +843,840 @@
843 int n;
844 db_find_and_open_repository(0, 0);
845 n = topological_sort_checkins(1);
846 fossil_print("%d reorderings required\n", n);
847 }
848
849 /***************************************************************************
850 ** Implementation of the "fossil git" command follows. We hope that the
851 ** new code that follows will largely replace the legacy "fossil export"
852 ** and "fossil import" code above.
853 */
854
855 /* Verbosity level. Higher means more output.
856 **
857 ** 0 print nothing at all
858 ** 1 Errors only
859 ** 2 Progress information (This is the default)
860 ** 3 Extra details
861 */
862 #define VERB_ERROR 1
863 #define VERB_NORMAL 2
864 #define VERB_EXTRA 3
865 static int gitmirror_verbosity = VERB_NORMAL;
866
867 /*
868 ** Output routine that depends on verbosity
869 */
870 static void gitmirror_message(int iLevel, const char *zFormat, ...){
871 va_list ap;
872 if( iLevel>gitmirror_verbosity ) return;
873 va_start(ap, zFormat);
874 fossil_vprint(zFormat, ap);
875 va_end(ap);
876 }
877
878 /*
879 ** Convert characters of z[] that are not allowed to be in branch or
880 ** tag names into "_".
881 */
882 static void gitmirror_sanitize_name(char *z){
883 static unsigned char aSafe[] = {
884 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
885 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
886 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
887 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2x */
888 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* 3x */
889 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
890 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, /* 5x */
891 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
892 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* 7x */
893 };
894 unsigned char *zu = (unsigned char*)z;
895 int i;
896 for(i=0; zu[i]; i++){
897 if( zu[i]>0x7f || !aSafe[zu[i]] ){
898 zu[i] = '_';
899 }else if( zu[i]=='/' && (i==0 || zu[i+1]==0 || zu[i+1]=='/') ){
900 zu[i] = '_';
901 }else if( zu[i]=='.' && (zu[i+1]==0 || zu[i+1]=='.'
902 || (i>0 && zu[i-1]=='.')) ){
903 zu[i] = '_';
904 }
905 }
906 }
907
908 /*
909 ** Quote a filename as a C-style string using \\ and \" if necessary.
910 ** If quoting is not necessary, just return a copy of the input string.
911 **
912 ** The return value is a held in memory obtained from fossil_malloc()
913 ** and must be freed by the caller.
914 */
915 static char *gitmirror_quote_filename_if_needed(const char *zIn){
916 int i, j;
917 char c;
918 int nSpecial = 0;
919 char *zOut;
920 for(i=0; (c = zIn[i])!=0; i++){
921 if( c=='\\' || c=='"' || c=='\n' ){
922 nSpecial++;
923 }
924 }
925 if( nSpecial==0 ){
926 return fossil_strdup(zIn);
927 }
928 zOut = fossil_malloc( i+nSpecial+3 );
929 zOut[0] = '"';
930 for(i=0, j=1; (c = zIn[i])!=0; i++){
931 if( c=='\\' || c=='"' || c=='\n' ){
932 zOut[j++] = '\\';
933 if( c=='\n' ){
934 zOut[j++] = 'n';
935 }else{
936 zOut[j++] = c;
937 }
938 }else{
939 zOut[j++] = c;
940 }
941 }
942 zOut[j++] = '"';
943 zOut[j] = 0;
944 return zOut;
945 }
946
947 /*
948 ** Find the Git-name corresponding to the Fossil-name zUuid.
949 **
950 ** If the mark does not exist and if the bCreate flag is false, then
951 ** return NULL. If the mark does not exist and the bCreate flag is true,
952 ** then create the mark.
953 **
954 ** The string returned is obtained from fossil_malloc() and should
955 ** be freed by the caller.
956 */
957 static char *gitmirror_find_mark(const char *zUuid, int isFile, int bCreate){
958 static Stmt sFind, sIns;
959 db_static_prepare(&sFind,
960 "SELECT coalesce(githash,printf(':%%d',id))"
961 " FROM mirror.mmark WHERE uuid=:uuid AND isfile=:isfile"
962 );
963 db_bind_text(&sFind, ":uuid", zUuid);
964 db_bind_int(&sFind, ":isfile", isFile!=0);
965 if( db_step(&sFind)==SQLITE_ROW ){
966 char *zMark = fossil_strdup(db_column_text(&sFind, 0));
967 db_reset(&sFind);
968 return zMark;
969 }
970 db_reset(&sFind);
971 if( !bCreate ){
972 return 0;
973 }
974 db_static_prepare(&sIns,
975 "INSERT INTO mirror.mmark(uuid,isfile) VALUES(:uuid,:isfile)"
976 );
977 db_bind_text(&sIns, ":uuid", zUuid);
978 db_bind_int(&sIns, ":isfile", isFile!=0);
979 db_step(&sIns);
980 db_reset(&sIns);
981 return mprintf(":%d", db_last_insert_rowid());
982 }
983
984 /* This is the SHA3-256 hash of an empty file */
985 static const char zEmptySha3[] =
986 "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
987
988 /*
989 ** Export a single file named by zUuid.
990 **
991 ** Return 0 on success and non-zero on any failure.
992 **
993 ** If zUuid is a shunned file, then treat it as if it were any empty file.
994 ** But files that are missing from the repository but have not been officially
995 ** shunned cause an error return. Except, if bPhantomOk is true, then missing
996 ** files are replaced by an empty file.
997 */
998 static int gitmirror_send_file(FILE *xCmd, const char *zUuid, int bPhantomOk){
999 char *zMark;
1000 int rid;
1001 int rc;
1002 Blob data;
1003 rid = fast_uuid_to_rid(zUuid);
1004 if( rid<0 ){
1005 if( bPhantomOk || uuid_is_shunned(zUuid) ){
1006 gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
1007 zUuid = zEmptySha3;
1008 }else{
1009 return 1;
1010 }
1011 }else{
1012 rc = content_get(rid, &data);
1013 if( rc==0 ){
1014 if( bPhantomOk ){
1015 blob_init(&data, 0, 0);
1016 gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
1017 zUuid = zEmptySha3;
1018 }else{
1019 return 1;
1020 }
1021 }
1022 }
1023 zMark = gitmirror_find_mark(zUuid, 1, 1);
1024 if( zMark[0]==':' ){
1025 fprintf(xCmd, "blob\nmark %s\ndata %d\n", zMark, blob_size(&data));
1026 fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
1027 fprintf(xCmd, "\n");
1028 }
1029 fossil_free(zMark);
1030 blob_reset(&data);
1031 return 0;
1032 }
1033
1034 /*
1035 ** Transfer a check-in over to the mirror. "rid" is the BLOB.RID for
1036 ** the check-in to export.
1037 **
1038 ** If any ancestor of the check-in has not yet been exported, then
1039 ** invoke this routine recursively to export the ancestor first.
1040 ** This can only happen on a timewarp, so deep nesting is unlikely.
1041 **
1042 ** Before sending the check-in, first make sure all associated files
1043 ** have already been exported, and send "blob" records for any that
1044 ** have not been. Update the MIRROR.MMARK table so that it holds the
1045 ** marks for the exported files.
1046 **
1047 ** Return zero on success and non-zero if the export should be stopped.
1048 */
1049 static int gitmirror_send_checkin(
1050 FILE *xCmd, /* Write fast-import text on this pipe */
1051 int rid, /* BLOB.RID for the check-in to export */
1052 const char *zUuid, /* BLOB.UUID for the check-in to export */
1053 int *pnLimit, /* Stop when the counter reaches zero */
1054 int fManifest /* MFESTFLG_* values */
1055 ){
1056 Manifest *pMan; /* The check-in to be output */
1057 int i; /* Loop counter */
1058 int iParent; /* Which immediate ancestor is primary. -1 for none */
1059 Stmt q; /* An SQL query */
1060 char *zBranch; /* The branch of the check-in */
1061 char *zMark; /* The Git-name of the check-in */
1062 Blob sql; /* String of SQL for part of the query */
1063 Blob comment; /* The comment text for the check-in */
1064 int nErr = 0; /* Number of errors */
1065 int bPhantomOk; /* True if phantom files should be ignored */
1066
1067 pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
1068 if( pMan==0 ){
1069 /* Must be a phantom. Return without doing anything, and in particular
1070 ** without creating a mark for this check-in. */
1071 gitmirror_message(VERB_NORMAL, "missing check-in: %s\n", zUuid);
1072 return 0;
1073 }
1074
1075 /* Check to see if any parent logins have not yet been processed, and
1076 ** if so, create them */
1077 for(i=0; i<pMan->nParent; i++){
1078 char *zPMark = gitmirror_find_mark(pMan->azParent[i], 0, 0);
1079 if( zPMark==0 ){
1080 int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
1081 pMan->azParent[i]);
1082 int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i],
1083 pnLimit, fManifest);
1084 if( rc || *pnLimit<=0 ){
1085 manifest_destroy(pMan);
1086 return 1;
1087 }
1088 }
1089 fossil_free(zPMark);
1090 }
1091
1092 /* Ignore phantom files on check-ins that are over one year old */
1093 bPhantomOk = db_int(0, "SELECT %.6f<julianday('now','-1 year')",
1094 pMan->rDate);
1095
1096 /* Make sure all necessary files have been exported */
1097 db_prepare(&q,
1098 "SELECT uuid FROM files_of_checkin(%Q)"
1099 " WHERE uuid NOT IN (SELECT uuid FROM mirror.mmark)",
1100 zUuid
1101 );
1102 while( db_step(&q)==SQLITE_ROW ){
1103 const char *zFUuid = db_column_text(&q, 0);
1104 int n = gitmirror_send_file(xCmd, zFUuid, bPhantomOk);
1105 nErr += n;
1106 if( n ) gitmirror_message(VERB_ERROR, "missing file: %s\n", zFUuid);
1107 }
1108 db_finalize(&q);
1109
1110 /* If some required files could not be exported, abandon the check-in
1111 ** export */
1112 if( nErr ){
1113 gitmirror_message(VERB_ERROR,
1114 "export of %s abandoned due to missing files\n", zUuid);
1115 *pnLimit = 0;
1116 return 1;
1117 }
1118
1119 /* Figure out which branch this check-in is a member of */
1120 zBranch = db_text(0,
1121 "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=%d",
1122 TAG_BRANCH, rid
1123 );
1124 if( fossil_strcmp(zBranch,"trunk")==0 ){
1125 fossil_free(zBranch);
1126 zBranch = mprintf("master");
1127 }else if( zBranch==0 ){
1128 zBranch = mprintf("unknown");
1129 }else{
1130 gitmirror_sanitize_name(zBranch);
1131 }
1132
1133 /* Export the check-in */
1134 fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
1135 fossil_free(zBranch);
1136 zMark = gitmirror_find_mark(zUuid,0,1);
1137 fprintf(xCmd, "mark %s\n", zMark);
1138 fossil_free(zMark);
1139 fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
1140 pMan->zUser, pMan->zUser,
1141 (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
1142 );
1143 blob_init(&comment, pMan->zComment, -1);
1144 if( blob_size(&comment)==0 ){
1145 blob_append(&comment, "(no comment)", -1);
1146 }
1147 blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid);
1148 fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment));
1149 blob_reset(&comment);
1150 iParent = -1; /* Which ancestor is the primary parent */
1151 for(i=0; i<pMan->nParent; i++){
1152 char *zOther = gitmirror_find_mark(pMan->azParent[i],0,0);
1153 if( zOther==0 ) continue;
1154 if( iParent<0 ){
1155 iParent = i;
1156 fprintf(xCmd, "from %s\n", zOther);
1157 }else{
1158 fprintf(xCmd, "merge %s\n", zOther);
1159 }
1160 fossil_free(zOther);
1161 }
1162 if( iParent>=0 ){
1163 db_prepare(&q,
1164 "SELECT filename FROM files_of_checkin(%Q)"
1165 " EXCEPT SELECT filename FROM files_of_checkin(%Q)",
1166 pMan->azParent[iParent], zUuid
1167 );
1168 while( db_step(&q)==SQLITE_ROW ){
1169 fprintf(xCmd, "D %s\n", db_column_text(&q,0));
1170 }
1171 db_finalize(&q);
1172 }
1173 blob_init(&sql, 0, 0);
1174 blob_append_sql(&sql,
1175 "SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
1176 zUuid
1177 );
1178 if( pMan->nParent ){
1179 blob_append_sql(&sql,
1180 " EXCEPT SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
1181 pMan->azParent[0]);
1182 }
1183 db_prepare(&q,
1184 "SELECT x.filename, x.perm,"
1185 " coalesce(mmark.githash,printf(':%%d',mmark.id))"
1186 " FROM (%s) AS x, mirror.mmark"
1187 " WHERE mmark.uuid=x.uuid AND isfile",
1188 blob_sql_text(&sql)
1189 );
1190 blob_reset(&sql);
1191 while( db_step(&q)==SQLITE_ROW ){
1192 const char *zFilename = db_column_text(&q,0);
1193 const char *zMode = db_column_text(&q,1);
1194 const char *zMark = db_column_text(&q,2);
1195 const char *zGitMode = "100644";
1196 char *zFNQuoted = 0;
1197 if( zMode ){
1198 if( strchr(zMode,'x') ) zGitMode = "100755";
1199 if( strchr(zMode,'l') ) zGitMode = "120000";
1200 }
1201 zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
1202 fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted);
1203 fossil_free(zFNQuoted);
1204 }
1205 db_finalize(&q);
1206
1207 /* Include Fossil-generated auxiliary files in the check-in */
1208 if( fManifest & MFESTFLG_RAW ){
1209 Blob manifest;
1210 content_get(rid, &manifest);
1211 fprintf(xCmd,"M 100644 inline manifest\ndata %d\n%s\n",
1212 blob_size(&manifest), blob_str(&manifest));
1213 blob_reset(&manifest);
1214 }
1215 if( fManifest & MFESTFLG_UUID ){
1216 int n = (int)strlen(zUuid);
1217 fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
1218 }
1219 if( fManifest & MFESTFLG_TAGS ){
1220 Blob tagslist;
1221 blob_init(&tagslist, 0, 0);
1222 get_checkin_taglist(rid, &tagslist);
1223 fprintf(xCmd,"M 100644 inline manifest.tags\ndata %d\n%s\n",
1224 blob_size(&tagslist), blob_str(&tagslist));
1225 blob_reset(&tagslist);
1226 }
1227
1228 /* The check-in is finished, so decrement the counter */
1229 (*pnLimit)--;
1230 return 0;
1231 }
1232
1233 /*
1234 ** Implementation of the "fossil git export" command.
1235 */
1236 void gitmirror_export_command(void){
1237 const char *zLimit; /* Text of the --limit flag */
1238 int nLimit = 0x7fffffff; /* Numeric value of the --limit flag */
1239 int nTotal = 0; /* Total number of check-ins to export */
1240 char *zMirror; /* Name of the mirror */
1241 char *z; /* Generic string */
1242 char *zCmd; /* git command to run as a subprocess */
1243 const char *zDebug = 0; /* Value of the --debug flag */
1244 const char *zAutoPush = 0; /* Value of the --autopush flag */
1245 char *zPushUrl; /* URL to sync the mirror to */
1246 double rEnd; /* time of most recent export */
1247 int rc; /* Result code */
1248 int bForce; /* Do the export and sync even if no changes*/
1249 int bNeedRepack = 0; /* True if we should run repack at the end */
1250 int fManifest; /* Current "manifest" setting */
1251 FILE *xCmd; /* Pipe to the "git fast-import" command */
1252 FILE *pMarks; /* Git mark files */
1253 Stmt q; /* Queries */
1254 char zLine[200]; /* One line of a mark file */
1255
1256 zDebug = find_option("debug",0,1);
1257 db_find_and_open_repository(0, 0);
1258 zLimit = find_option("limit", 0, 1);
1259 if( zLimit ){
1260 nLimit = (unsigned int)atoi(zLimit);
1261 if( nLimit<=0 ) fossil_fatal("--limit must be positive");
1262 }
1263 zAutoPush = find_option("autopush",0,1);
1264 bForce = find_option("force","f",0)!=0;
1265 gitmirror_verbosity = VERB_NORMAL;
1266 while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; }
1267 while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; }
1268 verify_all_options();
1269 if( g.argc!=4 && g.argc!=3 ){ usage("export ?MIRROR?"); }
1270 if( g.argc==4 ){
1271 Blob mirror;
1272 file_canonical_name(g.argv[3], &mirror, 0);
1273 db_set("last-git-export-repo", blob_str(&mirror), 0);
1274 blob_reset(&mirror);
1275 }
1276 zMirror = db_get("last-git-export-repo", 0);
1277 if( zMirror==0 ){
1278 fossil_fatal("no Git repository specified");
1279 }
1280
1281 /* Make sure the GIT repository directory exists */
1282 rc = file_mkdir(zMirror, ExtFILE, 0);
1283 if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror);
1284
1285 /* Make sure GIT has been initialized */
1286 z = mprintf("%s/.git", zMirror);
1287 if( !file_isdir(z, ExtFILE) ){
1288 zCmd = mprintf("git init '%s'",zMirror);
1289 gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
1290 rc = fossil_system(zCmd);
1291 if( rc ){
1292 fossil_fatal("cannot initialize the git repository using: \"%s\"", zCmd);
1293 }
1294 fossil_free(zCmd);
1295 bNeedRepack = 1;
1296 }
1297 fossil_free(z);
1298
1299 /* Make sure the .mirror_state subdirectory exists */
1300 z = mprintf("%s/.mirror_state", zMirror);
1301 rc = file_mkdir(z, ExtFILE, 0);
1302 if( rc ) fossil_fatal("cannot create directory \"%s\"", z);
1303 fossil_free(z);
1304
1305 /* Attach the .mirror_state/db database */
1306 db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
1307 db_begin_write();
1308 db_multi_exec(
1309 "CREATE TABLE IF NOT EXISTS mirror.mconfig(\n"
1310 " key TEXT PRIMARY KEY,\n"
1311 " Value ANY\n"
1312 ") WITHOUT ROWID;\n"
1313 "CREATE TABLE IF NOT EXISTS mirror.mmark(\n"
1314 " id INTEGER PRIMARY KEY,\n"
1315 " uuid TEXT,\n"
1316 " isfile BOOLEAN,\n"
1317 " githash TEXT,\n"
1318 " UNIQUE(uuid,isfile)\n"
1319 ");"
1320 );
1321 if( !db_table_has_column("mirror","mmark","isfile") ){
1322 db_multi_exec(
1323 "ALTER TABLE mirror.mmark RENAME TO mmark_old;"
1324 "CREATE TABLE IF NOT EXISTS mirror.mmark(\n"
1325 " id INTEGER PRIMARY KEY,\n"
1326 " uuid TEXT,\n"
1327 " isfile BOOLEAN,\n"
1328 " githash TEXT,\n"
1329 " UNIQUE(uuid,isfile)\n"
1330 ");"
1331 "INSERT OR IGNORE INTO mirror.mmark(id,uuid,githash,isfile)"
1332 " SELECT id,uuid,githash,"
1333 " NOT EXISTS(SELECT 1 FROM repository.event, repository.blob"
1334 " WHERE event.objid=blob.rid"
1335 " AND blob.uuid=mmark_old.uuid)"
1336 " FROM mirror.mmark_old;\n"
1337 "DROP TABLE mirror.mmark_old;\n"
1338 );
1339 }
1340
1341 /* Change the autopush setting if the --autopush flag is present */
1342 if( zAutoPush ){
1343 if( is_false(zAutoPush) ){
1344 db_multi_exec("DELETE FROM mirror.mconfig WHERE key='autopush'");
1345 }else{
1346 db_multi_exec(
1347 "REPLACE INTO mirror.mconfig(key,value)"
1348 "VALUES('autopush',%Q)",
1349 zAutoPush
1350 );
1351 }
1352 }
1353
1354 /* See if there is any work to be done. Exit early if not, before starting
1355 ** the "git fast-import" command. */
1356 if( !bForce
1357 && !db_exists("SELECT 1 FROM event WHERE type IN ('ci','t')"
1358 " AND mtime>coalesce((SELECT value FROM mconfig"
1359 " WHERE key='start'),0.0)")
1360 ){
1361 gitmirror_message(VERB_NORMAL, "no changes\n");
1362 db_commit_transaction();
1363 return;
1364 }
1365
1366 /* Do we need to include manifest files in the clone? */
1367 fManifest = db_get_manifest_setting();
1368
1369 /* Change to the MIRROR directory so that the Git commands will work */
1370 rc = file_chdir(zMirror, 0);
1371 if( rc ) fossil_fatal("cannot change the working directory to \"%s\"",
1372 zMirror);
1373
1374 /* Start up the git fast-import command */
1375 if( zDebug ){
1376 if( fossil_strcmp(zDebug,"stdout")==0 ){
1377 xCmd = stdout;
1378 }else{
1379 xCmd = fopen(zDebug, "wb");
1380 if( xCmd==0 ) fossil_fatal("cannot open file \"%s\" for writing", zDebug);
1381 }
1382 }else{
1383 zCmd = mprintf("git fast-import"
1384 " --export-marks=.mirror_state/marks.txt"
1385 " --quiet --done");
1386 gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
1387 xCmd = popen(zCmd, "w");
1388 if( zCmd==0 ){
1389 fossil_fatal("cannot start the \"git fast-import\" command");
1390 }
1391 fossil_free(zCmd);
1392 }
1393
1394 /* Run the export */
1395 rEnd = 0.0;
1396 db_multi_exec(
1397 "CREATE TEMP TABLE tomirror(objid,mtime,uuid);\n"
1398 "INSERT INTO tomirror "
1399 "SELECT objid, mtime, blob.uuid FROM event, blob\n"
1400 " WHERE type='ci'"
1401 " AND mtime>coalesce((SELECT value FROM mconfig WHERE key='start'),0.0)"
1402 " AND blob.rid=event.objid"
1403 " AND blob.uuid NOT IN (SELECT uuid FROM mirror.mmark WHERE NOT isfile);"
1404 );
1405 nTotal = db_int(0, "SELECT count(*) FROM tomirror");
1406 if( nLimit<nTotal ){
1407 nTotal = nLimit;
1408 }else if( nLimit>nTotal ){
1409 nLimit = nTotal;
1410 }
1411 db_prepare(&q,
1412 "SELECT objid, mtime, uuid FROM tomirror ORDER BY mtime"
1413 );
1414 while( nLimit && db_step(&q)==SQLITE_ROW ){
1415 int rid = db_column_int(&q, 0);
1416 double rMTime = db_column_double(&q, 1);
1417 const char *zUuid = db_column_text(&q, 2);
1418 if( rMTime>rEnd ) rEnd = rMTime;
1419 rc = gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
1420 if( rc ) break;
1421 gitmirror_message(VERB_NORMAL,"%d/%d \r", nTotal-nLimit, nTotal);
1422 fflush(stdout);
1423 }
1424 db_finalize(&q);
1425 fprintf(xCmd, "done\n");
1426 if( zDebug ){
1427 if( xCmd!=stdout ) fclose(xCmd);
1428 }else{
1429 pclose(xCmd);
1430 }
1431 gitmirror_message(VERB_NORMAL, "%d check-ins added to the %s\n",
1432 nTotal-nLimit, zMirror);
1433
1434 /* Read the export-marks file. Transfer the new marks over into
1435 ** the import-marks file.
1436 */
1437 pMarks = fopen(".mirror_state/marks.txt", "rb");
1438 if( pMarks ){
1439 db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id");
1440 while( fgets(zLine, sizeof(zLine), pMarks) ){
1441 int j, k;
1442 if( zLine[0]!=':' ) continue;
1443 db_bind_int(&q, ":id", atoi(zLine+1));
1444 for(j=1; zLine[j] && zLine[j]!=' '; j++){}
1445 if( zLine[j]!=' ' ) continue;
1446 j++;
1447 if( zLine[j]==0 ) continue;
1448 for(k=j; fossil_isalnum(zLine[k]); k++){}
1449 zLine[k] = 0;
1450 db_bind_text(&q, ":githash", &zLine[j]);
1451 db_step(&q);
1452 db_reset(&q);
1453 }
1454 db_finalize(&q);
1455 fclose(pMarks);
1456 file_delete(".mirror_state/marks.txt");
1457 }else{
1458 fossil_fatal("git fast-import didn't generate a marks file!");
1459 }
1460 db_multi_exec(
1461 "CREATE INDEX IF NOT EXISTS mirror.mmarkx1 ON mmark(githash);"
1462 );
1463
1464 /* Do any tags that have been created since the start time */
1465 db_prepare(&q,
1466 "SELECT substr(tagname,5), githash"
1467 " FROM (SELECT tagxref.tagid AS xtagid, tagname, rid, max(mtime) AS mtime"
1468 " FROM tagxref JOIN tag ON tag.tagid=tagxref.tagid"
1469 " WHERE tag.tagname GLOB 'sym-*'"
1470 " AND tagxref.tagtype=1"
1471 " AND tagxref.mtime > coalesce((SELECT value FROM mconfig"
1472 " WHERE key='start'),0.0)"
1473 " GROUP BY tagxref.tagid) AS tx"
1474 " JOIN blob ON tx.rid=blob.rid"
1475 " JOIN mmark ON mmark.uuid=blob.uuid;"
1476 );
1477 while( db_step(&q)==SQLITE_ROW ){
1478 char *zTagname = fossil_strdup(db_column_text(&q,0));
1479 const char *zObj = db_column_text(&q,1);
1480 char *zTagCmd;
1481 gitmirror_sanitize_name(zTagname);
1482 zTagCmd = mprintf("git tag -f \"%s\" %s", zTagname, zObj);
1483 fossil_free(zTagname);
1484 gitmirror_message(VERB_NORMAL, "%s\n", zTagCmd);
1485 fossil_system(zTagCmd);
1486 fossil_free(zTagCmd);
1487 }
1488 db_finalize(&q);
1489
1490 /* Update all references that might have changed since the start time */
1491 db_prepare(&q,
1492 "SELECT"
1493 " tagxref.value AS name,"
1494 " max(event.mtime) AS mtime,"
1495 " mmark.githash AS gitckin"
1496 " FROM tagxref, tag, event, blob, mmark"
1497 " WHERE tagxref.tagid=tag.tagid"
1498 " AND tagxref.tagtype>0"
1499 " AND tag.tagname='branch'"
1500 " AND event.objid=tagxref.rid"
1501 " AND event.mtime > coalesce((SELECT value FROM mconfig"
1502 " WHERE key='start'),0.0)"
1503 " AND blob.rid=tagxref.rid"
1504 " AND mmark.uuid=blob.uuid"
1505 " GROUP BY 1"
1506 );
1507 while( db_step(&q)==SQLITE_ROW ){
1508 char *zBrname = fossil_strdup(db_column_text(&q,0));
1509 const char *zObj = db_column_text(&q,2);
1510 char *zRefCmd;
1511 if( fossil_strcmp(zBrname,"trunk")==0 ){
1512 fossil_free(zBrname);
1513 zBrname = fossil_strdup("master");
1514 }else{
1515 gitmirror_sanitize_name(zBrname);
1516 }
1517 zRefCmd = mprintf("git update-ref \"refs/heads/%s\" %s", zBrname, zObj);
1518 fossil_free(zBrname);
1519 gitmirror_message(VERB_NORMAL, "%s\n", zRefCmd);
1520 fossil_system(zRefCmd);
1521 fossil_free(zRefCmd);
1522 }
1523 db_finalize(&q);
1524
1525 /* Update the start time */
1526 if( rEnd>0.0 ){
1527 db_prepare(&q, "REPLACE INTO mirror.mconfig(key,value) VALUES('start',:x)");
1528 db_bind_double(&q, ":x", rEnd);
1529 db_step(&q);
1530 db_finalize(&q);
1531 }
1532 db_commit_transaction();
1533
1534 /* Maybe run a git repack */
1535 if( bNeedRepack ){
1536 const char *zRepack = "git repack -adf";
1537 gitmirror_message(VERB_NORMAL, "%s\n", zRepack);
1538 fossil_system(zRepack);
1539 }
1540
1541 /* Optionally do a "git push" */
1542 zPushUrl = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
1543 if( zPushUrl ){
1544 char *zPushCmd;
1545 UrlData url;
1546 if( sqlite3_strglob("http*", zPushUrl)==0 ){
1547 url_parse_local(zPushUrl, 0, &url);
1548 zPushCmd = mprintf("git push --mirror %s", url.canonical);
1549 }else{
1550 zPushCmd = mprintf("git push --mirror %s", zPushUrl);
1551 }
1552 gitmirror_message(VERB_NORMAL, "%s\n", zPushCmd);
1553 fossil_free(zPushCmd);
1554 zPushCmd = mprintf("git push --mirror %s", zPushUrl);
1555 fossil_system(zPushCmd);
1556 fossil_free(zPushCmd);
1557 }
1558 }
1559
1560 /*
1561 ** Implementation of the "fossil git status" command.
1562 **
1563 ** Show the status of a "git export".
1564 */
1565 void gitmirror_status_command(void){
1566 char *zMirror;
1567 char *z;
1568 int n, k;
1569 db_find_and_open_repository(0, 0);
1570 verify_all_options();
1571 zMirror = db_get("last-git-export-repo", 0);
1572 if( zMirror==0 ){
1573 fossil_print("Git mirror: none\n");
1574 return;
1575 }
1576 fossil_print("Git mirror: %s\n", zMirror);
1577 db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
1578 z = db_text(0, "SELECT datetime(value) FROM mconfig WHERE key='start'");
1579 if( z ){
1580 double rAge = db_double(0.0, "SELECT julianday('now') - value"
1581 " FROM mconfig WHERE key='start'");
1582 if( rAge>1.0/86400.0 ){
1583 fossil_print("Last export: %s (%z ago)\n", z, human_readable_age(rAge));
1584 }else{
1585 fossil_print("Last export: %s (moments ago)\n", z);
1586 }
1587 }
1588 z = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
1589 if( z==0 ){
1590 fossil_print("Autopush: off\n");
1591 }else{
1592 UrlData url;
1593 url_parse_local(z, 0, &url);
1594 fossil_print("Autopush: %s\n", url.canonical);
1595 }
1596 n = db_int(0,
1597 "SELECT count(*) FROM event"
1598 " WHERE type='ci'"
1599 " AND mtime>coalesce((SELECT value FROM mconfig"
1600 " WHERE key='start'),0.0)"
1601 );
1602 if( n==0 ){
1603 fossil_print("Status: up-to-date\n");
1604 }else{
1605 fossil_print("Status: %d check-in%s awaiting export\n",
1606 n, n==1 ? "" : "s");
1607 }
1608 n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile");
1609 k = db_int(0, "SELECT count(*) FROm mmark WHERE NOT isfile");
1610 fossil_print("Exported: %d check-ins and %d file blobs\n", k, n);
1611 }
1612
1613 /*
1614 ** COMMAND: git
1615 **
1616 ** Usage: %fossil git SUBCOMMAND
1617 **
1618 ** Do incremental import or export operations between Fossil and Git.
1619 ** Subcommands:
1620 **
1621 ** fossil git export [MIRROR] [OPTIONS]
1622 **
1623 ** Write content from the Fossil repository into the Git repository
1624 ** in directory MIRROR. The Git repository is created if it does not
1625 ** already exist. If the Git repository does already exist, then
1626 ** new content added to fossil since the previous export is appended.
1627 **
1628 ** Repeat this command whenever new checkins are added to the Fossil
1629 ** repository in order to reflect those changes into the mirror. If
1630 ** the MIRROR option is omitted, the repository from the previous
1631 ** invocation is used.
1632 **
1633 ** The MIRROR directory will contain a subdirectory named
1634 ** ".mirror_state" that contains information that Fossil needs to
1635 ** do incremental exports. Do not attempt to manage or edit the files
1636 ** in that directory since doing so can disrupt future incremental
1637 ** exports.
1638 **
1639 ** Options:
1640 ** --autopush URL Automatically do a 'git push' to URL. The
1641 ** URL is remembered and used on subsequent exports
1642 ** to the same repository. Or if URL is "off" the
1643 ** auto-push mechanism is disabled
1644 ** --debug FILE Write fast-export text to FILE rather than
1645 ** piping it into "git fast-import".
1646 ** --force|-f Do the export even if nothing has changed
1647 ** --limit N Add no more than N new check-ins to MIRROR.
1648 ** Useful for debugging
1649 ** --quiet|-q Reduce output. Repeat for even less output.
1650 ** --verbose|-v More output.
1651 **
1652 ** fossil git import MIRROR
1653 **
1654 ** TBD...
1655 **
1656 ** fossil git status
1657 **
1658 ** Show the status of the current Git mirror, if there is one.
1659 */
1660 void gitmirror_command(void){
1661 char *zCmd;
1662 int nCmd;
1663 if( g.argc<3 ){
1664 usage("export ARGS...");
1665 }
1666 zCmd = g.argv[2];
1667 nCmd = (int)strlen(zCmd);
1668 if( nCmd>2 && strncmp(zCmd,"export",nCmd)==0 ){
1669 gitmirror_export_command();
1670 }else
1671 if( nCmd>2 && strncmp(zCmd,"import",nCmd)==0 ){
1672 fossil_fatal("not yet implemented - check back later");
1673 }else
1674 if( nCmd>2 && strncmp(zCmd,"status",nCmd)==0 ){
1675 gitmirror_status_command();
1676 }else
1677 {
1678 fossil_fatal("unknown subcommand \"%s\": should be one of "
1679 "\"export\", \"import\", \"status\"",
1680 zCmd);
1681 }
1682 }
1683
+45 -10
--- src/file.c
+++ src/file.c
@@ -1459,13 +1459,20 @@
14591459
blob_set(pPath, "/");
14601460
}
14611461
}
14621462
14631463
/*
1464
-** Construct a random temporary filename into pBuf starting with zPrefix.
1464
+** Construct a random temporary filename into pBuf where the name of
1465
+** the temporary file is derived from zBasis. The suffix on the temp
1466
+** file is the same as the suffix on zBasis, and the temp file has
1467
+** the root of zBasis in its name.
1468
+**
1469
+** If zTag is not NULL, then try to create the temp-file using zTag
1470
+** as a differentiator. If that fails, or if zTag is NULL, then use
1471
+** a bunch of random characters as the tag.
14651472
*/
1466
-void file_tempname(Blob *pBuf, const char *zPrefix){
1473
+void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
14671474
#if defined(_WIN32)
14681475
const char *azDirs[] = {
14691476
0, /* GetTempPath */
14701477
0, /* TEMP */
14711478
0, /* TMP */
@@ -1488,10 +1495,12 @@
14881495
"0123456789";
14891496
unsigned int i;
14901497
const char *zDir = ".";
14911498
int cnt = 0;
14921499
char zRand[16];
1500
+ int nBasis;
1501
+ const char *zSuffix;
14931502
14941503
#if defined(_WIN32)
14951504
wchar_t zTmpPath[MAX_PATH];
14961505
14971506
if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1513,19 +1522,43 @@
15131522
if( !file_isdir(azDirs[i], ExtFILE) ) continue;
15141523
zDir = azDirs[i];
15151524
break;
15161525
}
15171526
1527
+ assert( zBasis!=0 );
1528
+ zSuffix = 0;
1529
+ for(i=0; zBasis[i]; i++){
1530
+ if( zBasis[i]=='/' || zBasis[i]=='\\' ){
1531
+ zBasis += i+1;
1532
+ i = -1;
1533
+ }else if( zBasis[i]=='.' ){
1534
+ zSuffix = zBasis + i;
1535
+ }
1536
+ }
1537
+ if( zSuffix==0 || zSuffix<=zBasis ){
1538
+ zSuffix = "";
1539
+ nBasis = i;
1540
+ }else{
1541
+ nBasis = (int)(zSuffix - zBasis);
1542
+ }
1543
+ if( nBasis==0 ){
1544
+ nBasis = 6;
1545
+ zBasis = "fossil";
1546
+ }
15181547
do{
15191548
blob_zero(pBuf);
15201549
if( cnt++>20 ) fossil_panic("cannot generate a temporary filename");
1521
- sqlite3_randomness(15, zRand);
1522
- for(i=0; i<15; i++){
1523
- zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ];
1550
+ if( zTag==0 ){
1551
+ sqlite3_randomness(15, zRand);
1552
+ for(i=0; i<15; i++){
1553
+ zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ];
1554
+ }
1555
+ zRand[15] = 0;
1556
+ zTag = zRand;
15241557
}
1525
- zRand[15] = 0;
1526
- blob_appendf(pBuf, "%s/%s-%s.txt", zDir, zPrefix ? zPrefix : "", zRand);
1558
+ blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
1559
+ zTag = 0;
15271560
}while( file_size(blob_str(pBuf), ExtFILE)>=0 );
15281561
15291562
#if defined(_WIN32)
15301563
fossil_path_free((char *)azDirs[0]);
15311564
fossil_path_free((char *)azDirs[1]);
@@ -1557,28 +1590,30 @@
15571590
}
15581591
15591592
15601593
/*
15611594
** COMMAND: test-tempname
1562
-** Usage: fossil test-name [--time SUFFIX] BASENAME ...
1595
+** Usage: fossil test-name [--time SUFFIX] [--tag NAME] BASENAME ...
15631596
**
15641597
** Generate temporary filenames derived from BASENAME. Use the --time
1565
-** option to generate temp names based on the time of day.
1598
+** option to generate temp names based on the time of day. If --tag NAME
1599
+** is specified, try to use NAME as the differentiator in the temp file.
15661600
*/
15671601
void file_test_tempname(void){
15681602
int i;
15691603
const char *zSuffix = find_option("time",0,1);
15701604
Blob x = BLOB_INITIALIZER;
15711605
char *z;
1606
+ const char *zTag = find_option("tag",0,1);
15721607
verify_all_options();
15731608
for(i=2; i<g.argc; i++){
15741609
if( zSuffix ){
15751610
z = file_time_tempname(g.argv[i], zSuffix);
15761611
fossil_print("%s\n", z);
15771612
fossil_free(z);
15781613
}else{
1579
- file_tempname(&x, g.argv[i]);
1614
+ file_tempname(&x, g.argv[i], zTag);
15801615
fossil_print("%s\n", blob_str(&x));
15811616
blob_reset(&x);
15821617
}
15831618
}
15841619
}
15851620
--- src/file.c
+++ src/file.c
@@ -1459,13 +1459,20 @@
1459 blob_set(pPath, "/");
1460 }
1461 }
1462
1463 /*
1464 ** Construct a random temporary filename into pBuf starting with zPrefix.
 
 
 
 
 
 
 
1465 */
1466 void file_tempname(Blob *pBuf, const char *zPrefix){
1467 #if defined(_WIN32)
1468 const char *azDirs[] = {
1469 0, /* GetTempPath */
1470 0, /* TEMP */
1471 0, /* TMP */
@@ -1488,10 +1495,12 @@
1488 "0123456789";
1489 unsigned int i;
1490 const char *zDir = ".";
1491 int cnt = 0;
1492 char zRand[16];
 
 
1493
1494 #if defined(_WIN32)
1495 wchar_t zTmpPath[MAX_PATH];
1496
1497 if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1513,19 +1522,43 @@
1513 if( !file_isdir(azDirs[i], ExtFILE) ) continue;
1514 zDir = azDirs[i];
1515 break;
1516 }
1517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1518 do{
1519 blob_zero(pBuf);
1520 if( cnt++>20 ) fossil_panic("cannot generate a temporary filename");
1521 sqlite3_randomness(15, zRand);
1522 for(i=0; i<15; i++){
1523 zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ];
 
 
 
 
1524 }
1525 zRand[15] = 0;
1526 blob_appendf(pBuf, "%s/%s-%s.txt", zDir, zPrefix ? zPrefix : "", zRand);
1527 }while( file_size(blob_str(pBuf), ExtFILE)>=0 );
1528
1529 #if defined(_WIN32)
1530 fossil_path_free((char *)azDirs[0]);
1531 fossil_path_free((char *)azDirs[1]);
@@ -1557,28 +1590,30 @@
1557 }
1558
1559
1560 /*
1561 ** COMMAND: test-tempname
1562 ** Usage: fossil test-name [--time SUFFIX] BASENAME ...
1563 **
1564 ** Generate temporary filenames derived from BASENAME. Use the --time
1565 ** option to generate temp names based on the time of day.
 
1566 */
1567 void file_test_tempname(void){
1568 int i;
1569 const char *zSuffix = find_option("time",0,1);
1570 Blob x = BLOB_INITIALIZER;
1571 char *z;
 
1572 verify_all_options();
1573 for(i=2; i<g.argc; i++){
1574 if( zSuffix ){
1575 z = file_time_tempname(g.argv[i], zSuffix);
1576 fossil_print("%s\n", z);
1577 fossil_free(z);
1578 }else{
1579 file_tempname(&x, g.argv[i]);
1580 fossil_print("%s\n", blob_str(&x));
1581 blob_reset(&x);
1582 }
1583 }
1584 }
1585
--- src/file.c
+++ src/file.c
@@ -1459,13 +1459,20 @@
1459 blob_set(pPath, "/");
1460 }
1461 }
1462
1463 /*
1464 ** Construct a random temporary filename into pBuf where the name of
1465 ** the temporary file is derived from zBasis. The suffix on the temp
1466 ** file is the same as the suffix on zBasis, and the temp file has
1467 ** the root of zBasis in its name.
1468 **
1469 ** If zTag is not NULL, then try to create the temp-file using zTag
1470 ** as a differentiator. If that fails, or if zTag is NULL, then use
1471 ** a bunch of random characters as the tag.
1472 */
1473 void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
1474 #if defined(_WIN32)
1475 const char *azDirs[] = {
1476 0, /* GetTempPath */
1477 0, /* TEMP */
1478 0, /* TMP */
@@ -1488,10 +1495,12 @@
1495 "0123456789";
1496 unsigned int i;
1497 const char *zDir = ".";
1498 int cnt = 0;
1499 char zRand[16];
1500 int nBasis;
1501 const char *zSuffix;
1502
1503 #if defined(_WIN32)
1504 wchar_t zTmpPath[MAX_PATH];
1505
1506 if( GetTempPathW(MAX_PATH, zTmpPath) ){
@@ -1513,19 +1522,43 @@
1522 if( !file_isdir(azDirs[i], ExtFILE) ) continue;
1523 zDir = azDirs[i];
1524 break;
1525 }
1526
1527 assert( zBasis!=0 );
1528 zSuffix = 0;
1529 for(i=0; zBasis[i]; i++){
1530 if( zBasis[i]=='/' || zBasis[i]=='\\' ){
1531 zBasis += i+1;
1532 i = -1;
1533 }else if( zBasis[i]=='.' ){
1534 zSuffix = zBasis + i;
1535 }
1536 }
1537 if( zSuffix==0 || zSuffix<=zBasis ){
1538 zSuffix = "";
1539 nBasis = i;
1540 }else{
1541 nBasis = (int)(zSuffix - zBasis);
1542 }
1543 if( nBasis==0 ){
1544 nBasis = 6;
1545 zBasis = "fossil";
1546 }
1547 do{
1548 blob_zero(pBuf);
1549 if( cnt++>20 ) fossil_panic("cannot generate a temporary filename");
1550 if( zTag==0 ){
1551 sqlite3_randomness(15, zRand);
1552 for(i=0; i<15; i++){
1553 zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ];
1554 }
1555 zRand[15] = 0;
1556 zTag = zRand;
1557 }
1558 blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
1559 zTag = 0;
1560 }while( file_size(blob_str(pBuf), ExtFILE)>=0 );
1561
1562 #if defined(_WIN32)
1563 fossil_path_free((char *)azDirs[0]);
1564 fossil_path_free((char *)azDirs[1]);
@@ -1557,28 +1590,30 @@
1590 }
1591
1592
1593 /*
1594 ** COMMAND: test-tempname
1595 ** Usage: fossil test-name [--time SUFFIX] [--tag NAME] BASENAME ...
1596 **
1597 ** Generate temporary filenames derived from BASENAME. Use the --time
1598 ** option to generate temp names based on the time of day. If --tag NAME
1599 ** is specified, try to use NAME as the differentiator in the temp file.
1600 */
1601 void file_test_tempname(void){
1602 int i;
1603 const char *zSuffix = find_option("time",0,1);
1604 Blob x = BLOB_INITIALIZER;
1605 char *z;
1606 const char *zTag = find_option("tag",0,1);
1607 verify_all_options();
1608 for(i=2; i<g.argc; i++){
1609 if( zSuffix ){
1610 z = file_time_tempname(g.argv[i], zSuffix);
1611 fossil_print("%s\n", z);
1612 fossil_free(z);
1613 }else{
1614 file_tempname(&x, g.argv[i], zTag);
1615 fossil_print("%s\n", blob_str(&x));
1616 blob_reset(&x);
1617 }
1618 }
1619 }
1620
+1 -1
--- src/graph.c
+++ src/graph.c
@@ -589,11 +589,11 @@
589589
iMrail = j;
590590
break;
591591
}
592592
}
593593
if( iMrail==-1 ){
594
- iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
594
+ iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0);
595595
if( p->mxRail>=GR_MAX_RAIL ) return;
596596
mergeRiserFrom[iMrail] = parentRid;
597597
}
598598
mask = BIT(iMrail);
599599
if( i>=pRow->nNonCherrypick ){
600600
--- src/graph.c
+++ src/graph.c
@@ -589,11 +589,11 @@
589 iMrail = j;
590 break;
591 }
592 }
593 if( iMrail==-1 ){
594 iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
595 if( p->mxRail>=GR_MAX_RAIL ) return;
596 mergeRiserFrom[iMrail] = parentRid;
597 }
598 mask = BIT(iMrail);
599 if( i>=pRow->nNonCherrypick ){
600
--- src/graph.c
+++ src/graph.c
@@ -589,11 +589,11 @@
589 iMrail = j;
590 break;
591 }
592 }
593 if( iMrail==-1 ){
594 iMrail = findFreeRail(p, pRow->idx, p->pLast->idx, 0);
595 if( p->mxRail>=GR_MAX_RAIL ) return;
596 mergeRiserFrom[iMrail] = parentRid;
597 }
598 mask = BIT(iMrail);
599 if( i>=pRow->nNonCherrypick ){
600
+1 -1
--- src/graph.js
+++ src/graph.js
@@ -348,11 +348,11 @@
348348
for(var i=0; i<tx.rowinfo.length; i++ ){
349349
var e = document.getElementById("m"+tx.rowinfo[i].id);
350350
tx.rowinfo[i].y = absoluteY(e) - canvasY;
351351
tx.rowinfo[i].x = tx.rowinfo[i].r*railPitch;
352352
}
353
- var tlBtm = document.querySelector(".timelineBottom");
353
+ var tlBtm = document.getElementById(tx.bottomRowId);
354354
if( tlBtm.offsetHeight<node.h ){
355355
tlBtm.style.height = node.h + "px";
356356
}
357357
var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight;
358358
for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm;
359359
--- src/graph.js
+++ src/graph.js
@@ -348,11 +348,11 @@
348 for(var i=0; i<tx.rowinfo.length; i++ ){
349 var e = document.getElementById("m"+tx.rowinfo[i].id);
350 tx.rowinfo[i].y = absoluteY(e) - canvasY;
351 tx.rowinfo[i].x = tx.rowinfo[i].r*railPitch;
352 }
353 var tlBtm = document.querySelector(".timelineBottom");
354 if( tlBtm.offsetHeight<node.h ){
355 tlBtm.style.height = node.h + "px";
356 }
357 var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight;
358 for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm;
359
--- src/graph.js
+++ src/graph.js
@@ -348,11 +348,11 @@
348 for(var i=0; i<tx.rowinfo.length; i++ ){
349 var e = document.getElementById("m"+tx.rowinfo[i].id);
350 tx.rowinfo[i].y = absoluteY(e) - canvasY;
351 tx.rowinfo[i].x = tx.rowinfo[i].r*railPitch;
352 }
353 var tlBtm = document.getElementById(tx.bottomRowId);
354 if( tlBtm.offsetHeight<node.h ){
355 tlBtm.style.height = node.h + "px";
356 }
357 var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight;
358 for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm;
359
+2 -1
--- src/http.c
+++ src/http.c
@@ -108,11 +108,11 @@
108108
if( i>0 && g.url.path[i-1]=='/' ){
109109
zSep = "";
110110
}else{
111111
zSep = "/";
112112
}
113
- blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.url.path, zSep);
113
+ blob_appendf(pHdr, "POST %s%s HTTP/1.0\r\n", g.url.path, zSep);
114114
if( g.url.proxyAuth ){
115115
blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
116116
}
117117
if( g.zHttpAuth && g.zHttpAuth[0] ){
118118
const char *zCredentials = g.zHttpAuth;
@@ -345,10 +345,11 @@
345345
transport_close(&g.url);
346346
transport_global_shutdown(&g.url);
347347
fSeenHttpAuth = 0;
348348
if( g.zHttpAuth ) free(g.zHttpAuth);
349349
g.zHttpAuth = get_httpauth();
350
+ url_remember();
350351
return http_exchange(pSend, pReply, useLogin, maxRedirect);
351352
}else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
352353
if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
353354
isCompressed = 0;
354355
}else if( fossil_strnicmp(&zLine[14],
355356
--- src/http.c
+++ src/http.c
@@ -108,11 +108,11 @@
108 if( i>0 && g.url.path[i-1]=='/' ){
109 zSep = "";
110 }else{
111 zSep = "/";
112 }
113 blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.url.path, zSep);
114 if( g.url.proxyAuth ){
115 blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
116 }
117 if( g.zHttpAuth && g.zHttpAuth[0] ){
118 const char *zCredentials = g.zHttpAuth;
@@ -345,10 +345,11 @@
345 transport_close(&g.url);
346 transport_global_shutdown(&g.url);
347 fSeenHttpAuth = 0;
348 if( g.zHttpAuth ) free(g.zHttpAuth);
349 g.zHttpAuth = get_httpauth();
 
350 return http_exchange(pSend, pReply, useLogin, maxRedirect);
351 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
352 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
353 isCompressed = 0;
354 }else if( fossil_strnicmp(&zLine[14],
355
--- src/http.c
+++ src/http.c
@@ -108,11 +108,11 @@
108 if( i>0 && g.url.path[i-1]=='/' ){
109 zSep = "";
110 }else{
111 zSep = "/";
112 }
113 blob_appendf(pHdr, "POST %s%s HTTP/1.0\r\n", g.url.path, zSep);
114 if( g.url.proxyAuth ){
115 blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
116 }
117 if( g.zHttpAuth && g.zHttpAuth[0] ){
118 const char *zCredentials = g.zHttpAuth;
@@ -345,10 +345,11 @@
345 transport_close(&g.url);
346 transport_global_shutdown(&g.url);
347 fSeenHttpAuth = 0;
348 if( g.zHttpAuth ) free(g.zHttpAuth);
349 g.zHttpAuth = get_httpauth();
350 url_remember();
351 return http_exchange(pSend, pReply, useLogin, maxRedirect);
352 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
353 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
354 isCompressed = 0;
355 }else if( fossil_strnicmp(&zLine[14],
356
+8 -1
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -387,13 +387,20 @@
387387
/* Set the Global.zIpAddr variable to the server we are talking to.
388388
** This is used to populate the ipaddr column of the rcvfrom table,
389389
** if any files are received from the server.
390390
*/
391391
{
392
+#ifdef HAVE_BIO_ADDR_HOSTNAME_STRING
393
+ char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
394
+ g.zIpAddr = mprintf("%s", ip);
395
+ OPENSSL_free(ip);
396
+#else
392397
/* IPv4 only code */
393
- const unsigned char *ip = (const unsigned char *) BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
398
+ const unsigned char *ip;
399
+ ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
394400
g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
401
+#endif
395402
}
396403
397404
X509_free(cert);
398405
return 0;
399406
}
400407
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -387,13 +387,20 @@
387 /* Set the Global.zIpAddr variable to the server we are talking to.
388 ** This is used to populate the ipaddr column of the rcvfrom table,
389 ** if any files are received from the server.
390 */
391 {
 
 
 
 
 
392 /* IPv4 only code */
393 const unsigned char *ip = (const unsigned char *) BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
 
394 g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
 
395 }
396
397 X509_free(cert);
398 return 0;
399 }
400
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -387,13 +387,20 @@
387 /* Set the Global.zIpAddr variable to the server we are talking to.
388 ** This is used to populate the ipaddr column of the rcvfrom table,
389 ** if any files are received from the server.
390 */
391 {
392 #ifdef HAVE_BIO_ADDR_HOSTNAME_STRING
393 char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
394 g.zIpAddr = mprintf("%s", ip);
395 OPENSSL_free(ip);
396 #else
397 /* IPv4 only code */
398 const unsigned char *ip;
399 ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
400 g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
401 #endif
402 }
403
404 X509_free(cert);
405 return 0;
406 }
407
+41 -6
--- src/info.c
+++ src/info.c
@@ -1756,12 +1756,10 @@
17561756
** to view artifacts that are images.
17571757
*/
17581758
void rawartifact_page(void){
17591759
int rid = 0;
17601760
char *zUuid;
1761
- const char *zMime;
1762
- Blob content;
17631761
17641762
if( P("ci") && P("filename") ){
17651763
rid = artifact_from_ci_and_filename(0, 0);
17661764
}
17671765
if( rid==0 ){
@@ -1773,11 +1771,48 @@
17731771
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
17741772
if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
17751773
g.isConst = 1;
17761774
}
17771775
free(zUuid);
1778
- zMime = P("m");
1776
+ deliver_artifact(rid, P("m"));
1777
+}
1778
+
1779
+
1780
+/*
1781
+** WEBPAGE: secureraw
1782
+** URL: /secureraw/HASH?m=TYPE
1783
+**
1784
+** Return the uninterpreted content of an artifact. This is similar
1785
+** to /raw except in this case the only way to specify the artifact
1786
+** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
1787
+** accepted.
1788
+*/
1789
+void secure_rawartifact_page(void){
1790
+ int rid = 0;
1791
+ const char *zUuid = PD("name", "");
1792
+
1793
+ login_check_credentials();
1794
+ if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1795
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
1796
+ if( rid==0 ){
1797
+ cgi_set_status(404, "Not Found");
1798
+ @ Unknown artifact: "%h(zUuid)"
1799
+ return;
1800
+ }
1801
+ g.isConst = 1;
1802
+ deliver_artifact(rid, P("m"));
1803
+}
1804
+
1805
+
1806
+/*
1807
+** Generate a verbatim artifact as the result of an HTTP request.
1808
+** If zMime is not NULL, use it as the MIME-type. If zMime is
1809
+** NULL, guess at the MIME-type based on the filename
1810
+** associated with the artifact.
1811
+*/
1812
+void deliver_artifact(int rid, const char *zMime){
1813
+ Blob content;
17791814
if( zMime==0 ){
17801815
char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
17811816
" WHERE mlink.fid=%d"
17821817
" AND filename.fnid=mlink.fnid", rid);
17831818
if( !zFName ){
@@ -2216,13 +2251,10 @@
22162251
style_submenu_element("Parsed", "%R/info/%s", zUuid);
22172252
}
22182253
if( descOnly ){
22192254
style_submenu_element("Content", "%R/artifact/%s", zUuid);
22202255
}else{
2221
- if( zLn==0 || atoi(zLn)==0 ){
2222
- style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2223
- }
22242256
@ <hr />
22252257
content_get(rid, &content);
22262258
if( renderAsWiki ){
22272259
wiki_render_by_mimetype(&content, zMime);
22282260
}else if( renderAsHtml ){
@@ -2237,10 +2269,13 @@
22372269
@ }
22382270
@ );
22392271
@ </script>
22402272
}else{
22412273
style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
2274
+ if( zLn==0 || atoi(zLn)==0 ){
2275
+ style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2276
+ }
22422277
blob_to_utf8_no_bom(&content, 0);
22432278
zMime = mimetype_from_content(&content);
22442279
@ <blockquote>
22452280
if( zMime==0 ){
22462281
const char *z;
22472282
--- src/info.c
+++ src/info.c
@@ -1756,12 +1756,10 @@
1756 ** to view artifacts that are images.
1757 */
1758 void rawartifact_page(void){
1759 int rid = 0;
1760 char *zUuid;
1761 const char *zMime;
1762 Blob content;
1763
1764 if( P("ci") && P("filename") ){
1765 rid = artifact_from_ci_and_filename(0, 0);
1766 }
1767 if( rid==0 ){
@@ -1773,11 +1771,48 @@
1773 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1774 if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
1775 g.isConst = 1;
1776 }
1777 free(zUuid);
1778 zMime = P("m");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1779 if( zMime==0 ){
1780 char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
1781 " WHERE mlink.fid=%d"
1782 " AND filename.fnid=mlink.fnid", rid);
1783 if( !zFName ){
@@ -2216,13 +2251,10 @@
2216 style_submenu_element("Parsed", "%R/info/%s", zUuid);
2217 }
2218 if( descOnly ){
2219 style_submenu_element("Content", "%R/artifact/%s", zUuid);
2220 }else{
2221 if( zLn==0 || atoi(zLn)==0 ){
2222 style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2223 }
2224 @ <hr />
2225 content_get(rid, &content);
2226 if( renderAsWiki ){
2227 wiki_render_by_mimetype(&content, zMime);
2228 }else if( renderAsHtml ){
@@ -2237,10 +2269,13 @@
2237 @ }
2238 @ );
2239 @ </script>
2240 }else{
2241 style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
 
 
 
2242 blob_to_utf8_no_bom(&content, 0);
2243 zMime = mimetype_from_content(&content);
2244 @ <blockquote>
2245 if( zMime==0 ){
2246 const char *z;
2247
--- src/info.c
+++ src/info.c
@@ -1756,12 +1756,10 @@
1756 ** to view artifacts that are images.
1757 */
1758 void rawartifact_page(void){
1759 int rid = 0;
1760 char *zUuid;
 
 
1761
1762 if( P("ci") && P("filename") ){
1763 rid = artifact_from_ci_and_filename(0, 0);
1764 }
1765 if( rid==0 ){
@@ -1773,11 +1771,48 @@
1771 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1772 if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
1773 g.isConst = 1;
1774 }
1775 free(zUuid);
1776 deliver_artifact(rid, P("m"));
1777 }
1778
1779
1780 /*
1781 ** WEBPAGE: secureraw
1782 ** URL: /secureraw/HASH?m=TYPE
1783 **
1784 ** Return the uninterpreted content of an artifact. This is similar
1785 ** to /raw except in this case the only way to specify the artifact
1786 ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
1787 ** accepted.
1788 */
1789 void secure_rawartifact_page(void){
1790 int rid = 0;
1791 const char *zUuid = PD("name", "");
1792
1793 login_check_credentials();
1794 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1795 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
1796 if( rid==0 ){
1797 cgi_set_status(404, "Not Found");
1798 @ Unknown artifact: "%h(zUuid)"
1799 return;
1800 }
1801 g.isConst = 1;
1802 deliver_artifact(rid, P("m"));
1803 }
1804
1805
1806 /*
1807 ** Generate a verbatim artifact as the result of an HTTP request.
1808 ** If zMime is not NULL, use it as the MIME-type. If zMime is
1809 ** NULL, guess at the MIME-type based on the filename
1810 ** associated with the artifact.
1811 */
1812 void deliver_artifact(int rid, const char *zMime){
1813 Blob content;
1814 if( zMime==0 ){
1815 char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
1816 " WHERE mlink.fid=%d"
1817 " AND filename.fnid=mlink.fnid", rid);
1818 if( !zFName ){
@@ -2216,13 +2251,10 @@
2251 style_submenu_element("Parsed", "%R/info/%s", zUuid);
2252 }
2253 if( descOnly ){
2254 style_submenu_element("Content", "%R/artifact/%s", zUuid);
2255 }else{
 
 
 
2256 @ <hr />
2257 content_get(rid, &content);
2258 if( renderAsWiki ){
2259 wiki_render_by_mimetype(&content, zMime);
2260 }else if( renderAsHtml ){
@@ -2237,10 +2269,13 @@
2269 @ }
2270 @ );
2271 @ </script>
2272 }else{
2273 style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
2274 if( zLn==0 || atoi(zLn)==0 ){
2275 style_submenu_checkbox("ln", "Line Numbers", 0, 0);
2276 }
2277 blob_to_utf8_no_bom(&content, 0);
2278 zMime = mimetype_from_content(&content);
2279 @ <blockquote>
2280 if( zMime==0 ){
2281 const char *z;
2282
--- src/login.c
+++ src/login.c
@@ -697,10 +697,11 @@
697697
@ <input type="hidden" name="anon" value="1" />
698698
}
699699
if( g.zLogin ){
700700
@ <p>Currently logged in as <b>%h(g.zLogin)</b>.
701701
@ <input type="submit" name="out" value="Logout"></p>
702
+ @ </form>
702703
}else{
703704
@ <table class="login_out">
704705
@ <tr>
705706
@ <td class="form_label">User ID:</td>
706707
if( anonFlag ){
707708
--- src/login.c
+++ src/login.c
@@ -697,10 +697,11 @@
697 @ <input type="hidden" name="anon" value="1" />
698 }
699 if( g.zLogin ){
700 @ <p>Currently logged in as <b>%h(g.zLogin)</b>.
701 @ <input type="submit" name="out" value="Logout"></p>
 
702 }else{
703 @ <table class="login_out">
704 @ <tr>
705 @ <td class="form_label">User ID:</td>
706 if( anonFlag ){
707
--- src/login.c
+++ src/login.c
@@ -697,10 +697,11 @@
697 @ <input type="hidden" name="anon" value="1" />
698 }
699 if( g.zLogin ){
700 @ <p>Currently logged in as <b>%h(g.zLogin)</b>.
701 @ <input type="submit" name="out" value="Logout"></p>
702 @ </form>
703 }else{
704 @ <table class="login_out">
705 @ <tr>
706 @ <td class="form_label">User ID:</td>
707 if( anonFlag ){
708
+9
--- src/main.c
+++ src/main.c
@@ -2639,10 +2639,19 @@
26392639
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
26402640
db_close(1);
26412641
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
26422642
fossil_fatal("unable to listen on TCP socket %d", iPort);
26432643
}
2644
+ /* For the parent process, the cgi_http_server() command above never
2645
+ ** returns (except in the case of an error). Instead, for each incoming
2646
+ ** client connection, a child process is created, file descriptors 0
2647
+ ** and 1 are bound to that connection, and the child returns.
2648
+ **
2649
+ ** So, when control reaches this point, we are running as a
2650
+ ** child process, the HTTP or SCGI request is pending on file
2651
+ ** descriptor 0 and the reply should be written to file descriptor 1.
2652
+ */
26442653
if( zMaxLatency ){
26452654
signal(SIGALRM, sigalrm_handler);
26462655
alarm(atoi(zMaxLatency));
26472656
}
26482657
g.httpIn = stdin;
26492658
--- src/main.c
+++ src/main.c
@@ -2639,10 +2639,19 @@
2639 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2640 db_close(1);
2641 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2642 fossil_fatal("unable to listen on TCP socket %d", iPort);
2643 }
 
 
 
 
 
 
 
 
 
2644 if( zMaxLatency ){
2645 signal(SIGALRM, sigalrm_handler);
2646 alarm(atoi(zMaxLatency));
2647 }
2648 g.httpIn = stdin;
2649
--- src/main.c
+++ src/main.c
@@ -2639,10 +2639,19 @@
2639 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2640 db_close(1);
2641 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2642 fossil_fatal("unable to listen on TCP socket %d", iPort);
2643 }
2644 /* For the parent process, the cgi_http_server() command above never
2645 ** returns (except in the case of an error). Instead, for each incoming
2646 ** client connection, a child process is created, file descriptors 0
2647 ** and 1 are bound to that connection, and the child returns.
2648 **
2649 ** So, when control reaches this point, we are running as a
2650 ** child process, the HTTP or SCGI request is pending on file
2651 ** descriptor 0 and the reply should be written to file descriptor 1.
2652 */
2653 if( zMaxLatency ){
2654 signal(SIGALRM, sigalrm_handler);
2655 alarm(atoi(zMaxLatency));
2656 }
2657 g.httpIn = stdin;
2658
+1 -1
--- src/main.mk
+++ src/main.mk
@@ -509,11 +509,11 @@
509509
510510
511511
512512
all: $(OBJDIR) $(APPNAME)
513513
514
-install: $(APPNAME)
514
+install: all
515515
mkdir -p $(INSTALLDIR)
516516
cp $(APPNAME) $(INSTALLDIR)
517517
518518
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
519519
$(OBJDIR)/codecheck1 $(TRANS_SRC)
520520
--- src/main.mk
+++ src/main.mk
@@ -509,11 +509,11 @@
509
510
511
512 all: $(OBJDIR) $(APPNAME)
513
514 install: $(APPNAME)
515 mkdir -p $(INSTALLDIR)
516 cp $(APPNAME) $(INSTALLDIR)
517
518 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
519 $(OBJDIR)/codecheck1 $(TRANS_SRC)
520
--- src/main.mk
+++ src/main.mk
@@ -509,11 +509,11 @@
509
510
511
512 all: $(OBJDIR) $(APPNAME)
513
514 install: all
515 mkdir -p $(INSTALLDIR)
516 cp $(APPNAME) $(INSTALLDIR)
517
518 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
519 $(OBJDIR)/codecheck1 $(TRANS_SRC)
520
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -318,11 +318,11 @@
318318
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
319319
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
320320
<<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
321321
all: $(OBJDIR) $(APPNAME)
322322
323
-install: $(APPNAME)
323
+install: all
324324
mkdir -p $(INSTALLDIR)
325325
cp $(APPNAME) $(INSTALLDIR)
326326
327327
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
328328
$(OBJDIR)/codecheck1 $(TRANS_SRC)
329329
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -318,11 +318,11 @@
318 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
319 <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
320 <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
321 all: $(OBJDIR) $(APPNAME)
322
323 install: $(APPNAME)
324 mkdir -p $(INSTALLDIR)
325 cp $(APPNAME) $(INSTALLDIR)
326
327 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
328 $(OBJDIR)/codecheck1 $(TRANS_SRC)
329
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -318,11 +318,11 @@
318 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
319 <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
320 <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
321 all: $(OBJDIR) $(APPNAME)
322
323 install: all
324 mkdir -p $(INSTALLDIR)
325 cp $(APPNAME) $(INSTALLDIR)
326
327 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
328 $(OBJDIR)/codecheck1 $(TRANS_SRC)
329
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -318,11 +318,11 @@
318318
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
319319
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
320320
<<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
321321
all: $(OBJDIR) $(APPNAME)
322322
323
-install: $(APPNAME)
323
+install: all
324324
mkdir -p $(INSTALLDIR)
325325
cp $(APPNAME) $(INSTALLDIR)
326326
327327
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
328328
$(OBJDIR)/codecheck1 $(TRANS_SRC)
329329
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -318,11 +318,11 @@
318 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
319 <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
320 <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
321 all: $(OBJDIR) $(APPNAME)
322
323 install: $(APPNAME)
324 mkdir -p $(INSTALLDIR)
325 cp $(APPNAME) $(INSTALLDIR)
326
327 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
328 $(OBJDIR)/codecheck1 $(TRANS_SRC)
329
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -318,11 +318,11 @@
318 <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
319 <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
320 <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
321 all: $(OBJDIR) $(APPNAME)
322
323 install: all
324 mkdir -p $(INSTALLDIR)
325 cp $(APPNAME) $(INSTALLDIR)
326
327 codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
328 $(OBJDIR)/codecheck1 $(TRANS_SRC)
329
+1 -1
--- src/markdown.c
+++ src/markdown.c
@@ -1208,11 +1208,11 @@
12081208
12091209
if( i>=size || data[i]<'0' || data[i]>'9' ) return 0;
12101210
while( i<size && data[i]>='0' && data[i]<='9' ){ i++; }
12111211
12121212
if( i+1>=size
1213
- || data[i]!='.'
1213
+ || (data[i]!='.' && data[i]!=')')
12141214
|| (data[i+1]!=' ' && data[i+1]!='\t')
12151215
){
12161216
return 0;
12171217
}
12181218
i = i+2;
12191219
--- src/markdown.c
+++ src/markdown.c
@@ -1208,11 +1208,11 @@
1208
1209 if( i>=size || data[i]<'0' || data[i]>'9' ) return 0;
1210 while( i<size && data[i]>='0' && data[i]<='9' ){ i++; }
1211
1212 if( i+1>=size
1213 || data[i]!='.'
1214 || (data[i+1]!=' ' && data[i+1]!='\t')
1215 ){
1216 return 0;
1217 }
1218 i = i+2;
1219
--- src/markdown.c
+++ src/markdown.c
@@ -1208,11 +1208,11 @@
1208
1209 if( i>=size || data[i]<'0' || data[i]>'9' ) return 0;
1210 while( i<size && data[i]>='0' && data[i]<='9' ){ i++; }
1211
1212 if( i+1>=size
1213 || (data[i]!='.' && data[i]!=')')
1214 || (data[i+1]!=' ' && data[i+1]!='\t')
1215 ){
1216 return 0;
1217 }
1218 i = i+2;
1219
--- src/markdown.md
+++ src/markdown.md
@@ -58,10 +58,11 @@
5858
>
5959
* bullet item
6060
+ bullet item
6161
- bullet item
6262
1. numbered item
63
+ 2) numbered item
6364
6465
> A two-level list is created by placing additional whitespace before the
6566
> **\***/**+**/**-**/**1.** of the secondary items.
6667
6768
>
6869
--- src/markdown.md
+++ src/markdown.md
@@ -58,10 +58,11 @@
58 >
59 * bullet item
60 + bullet item
61 - bullet item
62 1. numbered item
 
63
64 > A two-level list is created by placing additional whitespace before the
65 > **\***/**+**/**-**/**1.** of the secondary items.
66
67 >
68
--- src/markdown.md
+++ src/markdown.md
@@ -58,10 +58,11 @@
58 >
59 * bullet item
60 + bullet item
61 - bullet item
62 1. numbered item
63 2) numbered item
64
65 > A two-level list is created by placing additional whitespace before the
66 > **\***/**+**/**-**/**1.** of the secondary items.
67
68 >
69
+1 -1
--- src/merge.c
+++ src/merge.c
@@ -752,11 +752,11 @@
752752
zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
753753
}
754754
zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
755755
if( file_size(zFullNewPath, RepoFILE)>=0 ){
756756
Blob tmpPath;
757
- file_tempname(&tmpPath, "");
757
+ file_tempname(&tmpPath, "", 0);
758758
db_multi_exec("INSERT INTO tmprn(fn,tmpfn) VALUES(%Q,%Q)",
759759
zNewName, blob_str(&tmpPath));
760760
if( file_islink(zFullNewPath) ){
761761
symlink_copy(zFullNewPath, blob_str(&tmpPath));
762762
}else{
763763
--- src/merge.c
+++ src/merge.c
@@ -752,11 +752,11 @@
752 zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
753 }
754 zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
755 if( file_size(zFullNewPath, RepoFILE)>=0 ){
756 Blob tmpPath;
757 file_tempname(&tmpPath, "");
758 db_multi_exec("INSERT INTO tmprn(fn,tmpfn) VALUES(%Q,%Q)",
759 zNewName, blob_str(&tmpPath));
760 if( file_islink(zFullNewPath) ){
761 symlink_copy(zFullNewPath, blob_str(&tmpPath));
762 }else{
763
--- src/merge.c
+++ src/merge.c
@@ -752,11 +752,11 @@
752 zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
753 }
754 zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
755 if( file_size(zFullNewPath, RepoFILE)>=0 ){
756 Blob tmpPath;
757 file_tempname(&tmpPath, "", 0);
758 db_multi_exec("INSERT INTO tmprn(fn,tmpfn) VALUES(%Q,%Q)",
759 zNewName, blob_str(&tmpPath));
760 if( file_islink(zFullNewPath) ){
761 symlink_copy(zFullNewPath, blob_str(&tmpPath));
762 }else{
763
+83 -1
--- src/name.c
+++ src/name.c
@@ -38,10 +38,77 @@
3838
if( z[7]!='-') return 0;
3939
if( !fossil_isdigit(z[8]) ) return 0;
4040
if( !fossil_isdigit(z[9]) ) return 0;
4141
return 1;
4242
}
43
+
44
+/*
45
+** Check to see if the string might be a compact date/time that omits
46
+** the punctuation. Example: "20190327084549" instead of
47
+** "2019-03-27 08:45:49". If the string is of the appropriate form,
48
+** then return an alternative string (in static space) that is the same
49
+** string with punctuation inserted.
50
+**
51
+** If the bVerifyNotAHash flag is true, then a check is made to see if
52
+** the string is a hash prefix and NULL is returned if it is. If the
53
+** bVerifyNotAHash flag is false, then the result is determined by syntax
54
+** of the input string only, without reference to the artifact table.
55
+*/
56
+char *fossil_expand_datetime(const char *zIn, int bVerifyNotAHash){
57
+ static char zEDate[20];
58
+ static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
59
+ int n = (int)strlen(zIn);
60
+ int i, j;
61
+
62
+ /* Only three forms allowed:
63
+ ** (1) YYYYMMDD
64
+ ** (2) YYYYMMDDHHMM
65
+ ** (3) YYYYMMDDHHMMSS
66
+ */
67
+ if( n!=8 && n!=12 && n!=14 ) return 0;
68
+
69
+ /* Every character must be a digit */
70
+ for(i=0; fossil_isdigit(zIn[i]); i++){}
71
+ if( i!=n ) return 0;
72
+
73
+ /* Expand the date */
74
+ for(i=j=0; zIn[i]; i++){
75
+ if( i>=4 && (i%2)==0 ){
76
+ zEDate[j++] = aPunct[i/2];
77
+ }
78
+ zEDate[j++] = zIn[i];
79
+ }
80
+ zEDate[j] = 0;
81
+
82
+ /* Check for reasonable date values.
83
+ ** Offset references:
84
+ ** YYYY-MM-DD HH:MM:SS
85
+ ** 0123456789 12345678
86
+ */
87
+
88
+ i = atoi(zEDate);
89
+ if( i<1970 || i>2100 ) return 0;
90
+ i = atoi(zEDate+5);
91
+ if( i<1 || i>12 ) return 0;
92
+ i = atoi(zEDate+8);
93
+ if( i<1 || i>31 ) return 0;
94
+ if( n>8 ){
95
+ i = atoi(zEDate+11);
96
+ if( i>24 ) return 0;
97
+ i = atoi(zEDate+14);
98
+ if( i>60 ) return 0;
99
+ if( n==14 && atoi(zEDate+17)>60 ) return 0;
100
+ }
101
+
102
+ /* The string is not also a hash prefix */
103
+ if( bVerifyNotAHash ){
104
+ if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%q*'",zIn) ) return 0;
105
+ }
106
+
107
+ /* It looks like this may be a date. Return it with punctuation added. */
108
+ return zEDate;
109
+}
43110
44111
/*
45112
** Return the RID that is the "root" of the branch that contains
46113
** check-in "rid" if inBranch==0 or the first check-in in the branch
47114
** if inBranch==1.
@@ -114,10 +181,11 @@
114181
int nTag;
115182
int i;
116183
int startOfBranch = 0;
117184
const char *zXTag; /* zTag with optional [...] removed */
118185
int nXTag; /* Size of zXTag */
186
+ const char *zDate; /* Expanded date-time string */
119187
120188
if( zType==0 || zType[0]==0 ){
121189
zType = "*";
122190
}else if( zType[0]=='b' ){
123191
zType = "ci";
@@ -150,15 +218,17 @@
150218
if( rid ) return rid;
151219
}
152220
153221
/* Date and times */
154222
if( memcmp(zTag, "date:", 5)==0 ){
223
+ zDate = fossil_expand_datetime(&zTag[5],0);
224
+ if( zDate==0 ) zDate = &zTag[5];
155225
rid = db_int(0,
156226
"SELECT objid FROM event"
157227
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
158228
" ORDER BY mtime DESC LIMIT 1",
159
- &zTag[5], zType);
229
+ zDate, zType);
160230
return rid;
161231
}
162232
if( fossil_isdate(zTag) ){
163233
rid = db_int(0,
164234
"SELECT objid FROM event"
@@ -283,10 +353,22 @@
283353
);
284354
if( rid>0 ){
285355
if( startOfBranch ) rid = start_of_branch(rid,1);
286356
return rid;
287357
}
358
+
359
+ /* Pure numeric date/time */
360
+ zDate = fossil_expand_datetime(zTag, 0);
361
+ if( zDate ){
362
+ rid = db_int(0,
363
+ "SELECT objid FROM event"
364
+ " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
365
+ " ORDER BY mtime DESC LIMIT 1",
366
+ zDate, zType);
367
+ if( rid) return rid;
368
+ }
369
+
288370
289371
/* Undocumented: numeric tags get translated directly into the RID */
290372
if( memcmp(zTag, "rid:", 4)==0 ){
291373
zTag += 4;
292374
for(i=0; fossil_isdigit(zTag[i]); i++){}
293375
--- src/name.c
+++ src/name.c
@@ -38,10 +38,77 @@
38 if( z[7]!='-') return 0;
39 if( !fossil_isdigit(z[8]) ) return 0;
40 if( !fossil_isdigit(z[9]) ) return 0;
41 return 1;
42 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
44 /*
45 ** Return the RID that is the "root" of the branch that contains
46 ** check-in "rid" if inBranch==0 or the first check-in in the branch
47 ** if inBranch==1.
@@ -114,10 +181,11 @@
114 int nTag;
115 int i;
116 int startOfBranch = 0;
117 const char *zXTag; /* zTag with optional [...] removed */
118 int nXTag; /* Size of zXTag */
 
119
120 if( zType==0 || zType[0]==0 ){
121 zType = "*";
122 }else if( zType[0]=='b' ){
123 zType = "ci";
@@ -150,15 +218,17 @@
150 if( rid ) return rid;
151 }
152
153 /* Date and times */
154 if( memcmp(zTag, "date:", 5)==0 ){
 
 
155 rid = db_int(0,
156 "SELECT objid FROM event"
157 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
158 " ORDER BY mtime DESC LIMIT 1",
159 &zTag[5], zType);
160 return rid;
161 }
162 if( fossil_isdate(zTag) ){
163 rid = db_int(0,
164 "SELECT objid FROM event"
@@ -283,10 +353,22 @@
283 );
284 if( rid>0 ){
285 if( startOfBranch ) rid = start_of_branch(rid,1);
286 return rid;
287 }
 
 
 
 
 
 
 
 
 
 
 
 
288
289 /* Undocumented: numeric tags get translated directly into the RID */
290 if( memcmp(zTag, "rid:", 4)==0 ){
291 zTag += 4;
292 for(i=0; fossil_isdigit(zTag[i]); i++){}
293
--- src/name.c
+++ src/name.c
@@ -38,10 +38,77 @@
38 if( z[7]!='-') return 0;
39 if( !fossil_isdigit(z[8]) ) return 0;
40 if( !fossil_isdigit(z[9]) ) return 0;
41 return 1;
42 }
43
44 /*
45 ** Check to see if the string might be a compact date/time that omits
46 ** the punctuation. Example: "20190327084549" instead of
47 ** "2019-03-27 08:45:49". If the string is of the appropriate form,
48 ** then return an alternative string (in static space) that is the same
49 ** string with punctuation inserted.
50 **
51 ** If the bVerifyNotAHash flag is true, then a check is made to see if
52 ** the string is a hash prefix and NULL is returned if it is. If the
53 ** bVerifyNotAHash flag is false, then the result is determined by syntax
54 ** of the input string only, without reference to the artifact table.
55 */
56 char *fossil_expand_datetime(const char *zIn, int bVerifyNotAHash){
57 static char zEDate[20];
58 static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
59 int n = (int)strlen(zIn);
60 int i, j;
61
62 /* Only three forms allowed:
63 ** (1) YYYYMMDD
64 ** (2) YYYYMMDDHHMM
65 ** (3) YYYYMMDDHHMMSS
66 */
67 if( n!=8 && n!=12 && n!=14 ) return 0;
68
69 /* Every character must be a digit */
70 for(i=0; fossil_isdigit(zIn[i]); i++){}
71 if( i!=n ) return 0;
72
73 /* Expand the date */
74 for(i=j=0; zIn[i]; i++){
75 if( i>=4 && (i%2)==0 ){
76 zEDate[j++] = aPunct[i/2];
77 }
78 zEDate[j++] = zIn[i];
79 }
80 zEDate[j] = 0;
81
82 /* Check for reasonable date values.
83 ** Offset references:
84 ** YYYY-MM-DD HH:MM:SS
85 ** 0123456789 12345678
86 */
87
88 i = atoi(zEDate);
89 if( i<1970 || i>2100 ) return 0;
90 i = atoi(zEDate+5);
91 if( i<1 || i>12 ) return 0;
92 i = atoi(zEDate+8);
93 if( i<1 || i>31 ) return 0;
94 if( n>8 ){
95 i = atoi(zEDate+11);
96 if( i>24 ) return 0;
97 i = atoi(zEDate+14);
98 if( i>60 ) return 0;
99 if( n==14 && atoi(zEDate+17)>60 ) return 0;
100 }
101
102 /* The string is not also a hash prefix */
103 if( bVerifyNotAHash ){
104 if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%q*'",zIn) ) return 0;
105 }
106
107 /* It looks like this may be a date. Return it with punctuation added. */
108 return zEDate;
109 }
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid" if inBranch==0 or the first check-in in the branch
114 ** if inBranch==1.
@@ -114,10 +181,11 @@
181 int nTag;
182 int i;
183 int startOfBranch = 0;
184 const char *zXTag; /* zTag with optional [...] removed */
185 int nXTag; /* Size of zXTag */
186 const char *zDate; /* Expanded date-time string */
187
188 if( zType==0 || zType[0]==0 ){
189 zType = "*";
190 }else if( zType[0]=='b' ){
191 zType = "ci";
@@ -150,15 +218,17 @@
218 if( rid ) return rid;
219 }
220
221 /* Date and times */
222 if( memcmp(zTag, "date:", 5)==0 ){
223 zDate = fossil_expand_datetime(&zTag[5],0);
224 if( zDate==0 ) zDate = &zTag[5];
225 rid = db_int(0,
226 "SELECT objid FROM event"
227 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
228 " ORDER BY mtime DESC LIMIT 1",
229 zDate, zType);
230 return rid;
231 }
232 if( fossil_isdate(zTag) ){
233 rid = db_int(0,
234 "SELECT objid FROM event"
@@ -283,10 +353,22 @@
353 );
354 if( rid>0 ){
355 if( startOfBranch ) rid = start_of_branch(rid,1);
356 return rid;
357 }
358
359 /* Pure numeric date/time */
360 zDate = fossil_expand_datetime(zTag, 0);
361 if( zDate ){
362 rid = db_int(0,
363 "SELECT objid FROM event"
364 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
365 " ORDER BY mtime DESC LIMIT 1",
366 zDate, zType);
367 if( rid) return rid;
368 }
369
370
371 /* Undocumented: numeric tags get translated directly into the RID */
372 if( memcmp(zTag, "rid:", 4)==0 ){
373 zTag += 4;
374 for(i=0; fossil_isdigit(zTag[i]); i++){}
375
+10
--- src/printf.c
+++ src/printf.c
@@ -964,10 +964,20 @@
964964
vxprintf(&b, zFormat, ap);
965965
fossil_puts(blob_str(&b), 0);
966966
blob_reset(&b);
967967
}
968968
va_end(ap);
969
+}
970
+void fossil_vprint(const char *zFormat, va_list ap){
971
+ if( g.cgiOutput ){
972
+ cgi_vprintf(zFormat, ap);
973
+ }else{
974
+ Blob b = empty_blob;
975
+ vxprintf(&b, zFormat, ap);
976
+ fossil_puts(blob_str(&b), 0);
977
+ blob_reset(&b);
978
+ }
969979
}
970980
971981
/*
972982
** Print a trace message on standard error.
973983
*/
974984
--- src/printf.c
+++ src/printf.c
@@ -964,10 +964,20 @@
964 vxprintf(&b, zFormat, ap);
965 fossil_puts(blob_str(&b), 0);
966 blob_reset(&b);
967 }
968 va_end(ap);
 
 
 
 
 
 
 
 
 
 
969 }
970
971 /*
972 ** Print a trace message on standard error.
973 */
974
--- src/printf.c
+++ src/printf.c
@@ -964,10 +964,20 @@
964 vxprintf(&b, zFormat, ap);
965 fossil_puts(blob_str(&b), 0);
966 blob_reset(&b);
967 }
968 va_end(ap);
969 }
970 void fossil_vprint(const char *zFormat, va_list ap){
971 if( g.cgiOutput ){
972 cgi_vprintf(zFormat, ap);
973 }else{
974 Blob b = empty_blob;
975 vxprintf(&b, zFormat, ap);
976 fossil_puts(blob_str(&b), 0);
977 blob_reset(&b);
978 }
979 }
980
981 /*
982 ** Print a trace message on standard error.
983 */
984
--- src/security_audit.c
+++ src/security_audit.c
@@ -36,12 +36,17 @@
3636
3737
3838
/*
3939
** WEBPAGE: secaudit0
4040
**
41
-** Run a security audit of the current Fossil setup.
42
-** This page requires administrator access
41
+** Run a security audit of the current Fossil setup, looking
42
+** for configuration problems that might allow unauthorized
43
+** access to the repository.
44
+**
45
+** This page requires administrator access. It is usually
46
+** accessed using the Admin/Security-Audit menu option
47
+** from any of the default skins.
4348
*/
4449
void secaudit0_page(void){
4550
const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */
4651
const char *zPubPages; /* GLOB pattern for public pages */
4752
const char *zSelfCap; /* Capabilities of self-registered users */
@@ -288,11 +293,11 @@
288293
fossil_free(z);
289294
if( n>3 ){
290295
@ <li><p><b>WARNING:</b>
291296
@ Administrator privilege is granted to
292297
@ <a href='setup_ulist?with=as'>%d(n) users</a>.
293
- @ Ideally, administator privilege ('s' or 'a') should only
298
+ @ Ideally, administrator privilege ('s' or 'a') should only
294299
@ be granted to one or two users.
295300
}
296301
}
297302
298303
/* The push-unversioned privilege should only be provided to
299304
--- src/security_audit.c
+++ src/security_audit.c
@@ -36,12 +36,17 @@
36
37
38 /*
39 ** WEBPAGE: secaudit0
40 **
41 ** Run a security audit of the current Fossil setup.
42 ** This page requires administrator access
 
 
 
 
 
43 */
44 void secaudit0_page(void){
45 const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */
46 const char *zPubPages; /* GLOB pattern for public pages */
47 const char *zSelfCap; /* Capabilities of self-registered users */
@@ -288,11 +293,11 @@
288 fossil_free(z);
289 if( n>3 ){
290 @ <li><p><b>WARNING:</b>
291 @ Administrator privilege is granted to
292 @ <a href='setup_ulist?with=as'>%d(n) users</a>.
293 @ Ideally, administator privilege ('s' or 'a') should only
294 @ be granted to one or two users.
295 }
296 }
297
298 /* The push-unversioned privilege should only be provided to
299
--- src/security_audit.c
+++ src/security_audit.c
@@ -36,12 +36,17 @@
36
37
38 /*
39 ** WEBPAGE: secaudit0
40 **
41 ** Run a security audit of the current Fossil setup, looking
42 ** for configuration problems that might allow unauthorized
43 ** access to the repository.
44 **
45 ** This page requires administrator access. It is usually
46 ** accessed using the Admin/Security-Audit menu option
47 ** from any of the default skins.
48 */
49 void secaudit0_page(void){
50 const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */
51 const char *zPubPages; /* GLOB pattern for public pages */
52 const char *zSelfCap; /* Capabilities of self-registered users */
@@ -288,11 +293,11 @@
293 fossil_free(z);
294 if( n>3 ){
295 @ <li><p><b>WARNING:</b>
296 @ Administrator privilege is granted to
297 @ <a href='setup_ulist?with=as'>%d(n) users</a>.
298 @ Ideally, administrator privilege ('s' or 'a') should only
299 @ be granted to one or two users.
300 }
301 }
302
303 /* The push-unversioned privilege should only be provided to
304
+1928 -54
--- src/shell.c
+++ src/shell.c
@@ -981,10 +981,11 @@
981981
982982
/*
983983
** We need several support functions from the SQLite core.
984984
*/
985985
986
+/* #include "sqlite3.h" */
986987
987988
/*
988989
** We need several things from the ANSI and MSVCRT headers.
989990
*/
990991
@@ -1334,10 +1335,11 @@
13341335
**
13351336
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
13361337
** is used. If SIZE is included it must be one of the integers 224, 256,
13371338
** 384, or 512, to determine SHA3 hash variant that is computed.
13381339
*/
1340
+/* #include "sqlite3ext.h" */
13391341
SQLITE_EXTENSION_INIT1
13401342
#include <assert.h>
13411343
#include <string.h>
13421344
#include <stdarg.h>
13431345
/* typedef sqlite3_uint64 u64; */
@@ -2097,10 +2099,11 @@
20972099
** If a non-NULL value is specified for the optional $dir parameter and
20982100
** $path is a relative path, then $path is interpreted relative to $dir.
20992101
** And the paths returned in the "name" column of the table are also
21002102
** relative to directory $dir.
21012103
*/
2104
+/* #include "sqlite3ext.h" */
21022105
SQLITE_EXTENSION_INIT1
21032106
#include <stdio.h>
21042107
#include <string.h>
21052108
#include <assert.h>
21062109
@@ -2175,17 +2178,17 @@
21752178
if( nIn>mxBlob ){
21762179
sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
21772180
fclose(in);
21782181
return;
21792182
}
2180
- pBuf = sqlite3_malloc64( nIn );
2183
+ pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
21812184
if( pBuf==0 ){
21822185
sqlite3_result_error_nomem(ctx);
21832186
fclose(in);
21842187
return;
21852188
}
2186
- if( 1==fread(pBuf, nIn, 1, in) ){
2189
+ if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
21872190
sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
21882191
}else{
21892192
sqlite3_result_error_code(ctx, SQLITE_IOERR);
21902193
sqlite3_free(pBuf);
21912194
}
@@ -2316,19 +2319,19 @@
23162319
23172320
/*
23182321
** Argument zFile is the name of a file that will be created and/or written
23192322
** by SQL function writefile(). This function ensures that the directory
23202323
** zFile will be written to exists, creating it if required. The permissions
2321
-** for any path components created by this function are set to (mode&0777).
2324
+** for any path components created by this function are set in accordance
2325
+** with the current umask.
23222326
**
23232327
** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
23242328
** SQLITE_OK is returned if the directory is successfully created, or
23252329
** SQLITE_ERROR otherwise.
23262330
*/
23272331
static int makeDirectory(
2328
- const char *zFile,
2329
- mode_t mode
2332
+ const char *zFile
23302333
){
23312334
char *zCopy = sqlite3_mprintf("%s", zFile);
23322335
int rc = SQLITE_OK;
23332336
23342337
if( zCopy==0 ){
@@ -2345,11 +2348,11 @@
23452348
if( i==nCopy ) break;
23462349
zCopy[i] = '\0';
23472350
23482351
rc2 = fileStat(zCopy, &sStat);
23492352
if( rc2!=0 ){
2350
- if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
2353
+ if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
23512354
}else{
23522355
if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
23532356
}
23542357
zCopy[i] = '/';
23552358
i++;
@@ -2503,11 +2506,11 @@
25032506
mtime = sqlite3_value_int64(argv[3]);
25042507
}
25052508
25062509
res = writeFile(context, zFile, argv[1], mode, mtime);
25072510
if( res==1 && errno==ENOENT ){
2508
- if( makeDirectory(zFile, mode)==SQLITE_OK ){
2511
+ if( makeDirectory(zFile)==SQLITE_OK ){
25092512
res = writeFile(context, zFile, argv[1], mode, mtime);
25102513
}
25112514
}
25122515
25132516
if( argc>2 && res!=0 ){
@@ -3054,10 +3057,11 @@
30543057
** This virtual table operates at the speed of human typing, and so there
30553058
** is no attempt to make it fast. Even a slow implementation will be much
30563059
** faster than any human can type.
30573060
**
30583061
*/
3062
+/* #include "sqlite3ext.h" */
30593063
SQLITE_EXTENSION_INIT1
30603064
#include <assert.h>
30613065
#include <string.h>
30623066
#include <ctype.h>
30633067
@@ -3570,10 +3574,11 @@
35703574
** database in a separate file.
35713575
**
35723576
** If the file being opened is not an appended database, then this shim is
35733577
** a pass-through into the default underlying VFS.
35743578
**/
3579
+/* #include "sqlite3ext.h" */
35753580
SQLITE_EXTENSION_INIT1
35763581
#include <string.h>
35773582
#include <assert.h>
35783583
35793584
/* The append mark at the end of the database is:
@@ -4226,10 +4231,11 @@
42264231
** * No support for encryption
42274232
** * No support for ZIP archives spanning multiple files
42284233
** * No support for zip64 extensions
42294234
** * Only the "inflate/deflate" (zlib) compression method is supported
42304235
*/
4236
+/* #include "sqlite3ext.h" */
42314237
SQLITE_EXTENSION_INIT1
42324238
#include <stdio.h>
42334239
#include <string.h>
42344240
#include <assert.h>
42354241
@@ -6396,10 +6402,11 @@
63966402
**
63976403
** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
63986404
** for working with sqlar archives and used by the shell tool's built-in
63996405
** sqlar support.
64006406
*/
6407
+/* #include "sqlite3ext.h" */
64016408
SQLITE_EXTENSION_INIT1
64026409
#include <zlib.h>
64036410
64046411
/*
64056412
** Implementation of the "sqlar_compress(X)" SQL function.
@@ -6518,10 +6525,11 @@
65186525
**
65196526
*************************************************************************
65206527
*/
65216528
65226529
6530
+/* #include "sqlite3.h" */
65236531
65246532
typedef struct sqlite3expert sqlite3expert;
65256533
65266534
/*
65276535
** Create a new sqlite3expert object.
@@ -6686,10 +6694,11 @@
66866694
** May you find forgiveness for yourself and forgive others.
66876695
** May you share freely, never taking more than you give.
66886696
**
66896697
*************************************************************************
66906698
*/
6699
+/* #include "sqlite3expert.h" */
66916700
#include <assert.h>
66926701
#include <string.h>
66936702
#include <stdio.h>
66946703
66956704
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -8628,10 +8637,867 @@
86288637
}
86298638
86308639
#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
86318640
86328641
/************************* End ../ext/expert/sqlite3expert.c ********************/
8642
+
8643
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8644
+/************************* Begin ../ext/misc/dbdata.c ******************/
8645
+/*
8646
+** 2019-04-17
8647
+**
8648
+** The author disclaims copyright to this source code. In place of
8649
+** a legal notice, here is a blessing:
8650
+**
8651
+** May you do good and not evil.
8652
+** May you find forgiveness for yourself and forgive others.
8653
+** May you share freely, never taking more than you give.
8654
+**
8655
+******************************************************************************
8656
+**
8657
+** This file contains an implementation of two eponymous virtual tables,
8658
+** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
8659
+** "sqlite_dbpage" eponymous virtual table be available.
8660
+**
8661
+** SQLITE_DBDATA:
8662
+** sqlite_dbdata is used to extract data directly from a database b-tree
8663
+** page and its associated overflow pages, bypassing the b-tree layer.
8664
+** The table schema is equivalent to:
8665
+**
8666
+** CREATE TABLE sqlite_dbdata(
8667
+** pgno INTEGER,
8668
+** cell INTEGER,
8669
+** field INTEGER,
8670
+** value ANY,
8671
+** schema TEXT HIDDEN
8672
+** );
8673
+**
8674
+** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
8675
+** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
8676
+** "schema".
8677
+**
8678
+** Each page of the database is inspected. If it cannot be interpreted as
8679
+** a b-tree page, or if it is a b-tree page containing 0 entries, the
8680
+** sqlite_dbdata table contains no rows for that page. Otherwise, the
8681
+** table contains one row for each field in the record associated with
8682
+** each cell on the page. For intkey b-trees, the key value is stored in
8683
+** field -1.
8684
+**
8685
+** For example, for the database:
8686
+**
8687
+** CREATE TABLE t1(a, b); -- root page is page 2
8688
+** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
8689
+** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
8690
+**
8691
+** the sqlite_dbdata table contains, as well as from entries related to
8692
+** page 1, content equivalent to:
8693
+**
8694
+** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
8695
+** (2, 0, -1, 5 ),
8696
+** (2, 0, 0, 'v' ),
8697
+** (2, 0, 1, 'five'),
8698
+** (2, 1, -1, 10 ),
8699
+** (2, 1, 0, 'x' ),
8700
+** (2, 1, 1, 'ten' );
8701
+**
8702
+** If database corruption is encountered, this module does not report an
8703
+** error. Instead, it attempts to extract as much data as possible and
8704
+** ignores the corruption.
8705
+**
8706
+** SQLITE_DBPTR:
8707
+** The sqlite_dbptr table has the following schema:
8708
+**
8709
+** CREATE TABLE sqlite_dbptr(
8710
+** pgno INTEGER,
8711
+** child INTEGER,
8712
+** schema TEXT HIDDEN
8713
+** );
8714
+**
8715
+** It contains one entry for each b-tree pointer between a parent and
8716
+** child page in the database.
8717
+*/
8718
+#if !defined(SQLITEINT_H)
8719
+/* #include "sqlite3ext.h" */
8720
+
8721
+/* typedef unsigned char u8; */
8722
+
8723
+#endif
8724
+SQLITE_EXTENSION_INIT1
8725
+#include <string.h>
8726
+#include <assert.h>
8727
+
8728
+#define DBDATA_PADDING_BYTES 100
8729
+
8730
+typedef struct DbdataTable DbdataTable;
8731
+typedef struct DbdataCursor DbdataCursor;
8732
+
8733
+/* Cursor object */
8734
+struct DbdataCursor {
8735
+ sqlite3_vtab_cursor base; /* Base class. Must be first */
8736
+ sqlite3_stmt *pStmt; /* For fetching database pages */
8737
+
8738
+ int iPgno; /* Current page number */
8739
+ u8 *aPage; /* Buffer containing page */
8740
+ int nPage; /* Size of aPage[] in bytes */
8741
+ int nCell; /* Number of cells on aPage[] */
8742
+ int iCell; /* Current cell number */
8743
+ int bOnePage; /* True to stop after one page */
8744
+ int szDb;
8745
+ sqlite3_int64 iRowid;
8746
+
8747
+ /* Only for the sqlite_dbdata table */
8748
+ u8 *pRec; /* Buffer containing current record */
8749
+ int nRec; /* Size of pRec[] in bytes */
8750
+ int nHdr; /* Size of header in bytes */
8751
+ int iField; /* Current field number */
8752
+ u8 *pHdrPtr;
8753
+ u8 *pPtr;
8754
+
8755
+ sqlite3_int64 iIntkey; /* Integer key value */
8756
+};
8757
+
8758
+/* Table object */
8759
+struct DbdataTable {
8760
+ sqlite3_vtab base; /* Base class. Must be first */
8761
+ sqlite3 *db; /* The database connection */
8762
+ sqlite3_stmt *pStmt; /* For fetching database pages */
8763
+ int bPtr; /* True for sqlite3_dbptr table */
8764
+};
8765
+
8766
+/* Column and schema definitions for sqlite_dbdata */
8767
+#define DBDATA_COLUMN_PGNO 0
8768
+#define DBDATA_COLUMN_CELL 1
8769
+#define DBDATA_COLUMN_FIELD 2
8770
+#define DBDATA_COLUMN_VALUE 3
8771
+#define DBDATA_COLUMN_SCHEMA 4
8772
+#define DBDATA_SCHEMA \
8773
+ "CREATE TABLE x(" \
8774
+ " pgno INTEGER," \
8775
+ " cell INTEGER," \
8776
+ " field INTEGER," \
8777
+ " value ANY," \
8778
+ " schema TEXT HIDDEN" \
8779
+ ")"
8780
+
8781
+/* Column and schema definitions for sqlite_dbptr */
8782
+#define DBPTR_COLUMN_PGNO 0
8783
+#define DBPTR_COLUMN_CHILD 1
8784
+#define DBPTR_COLUMN_SCHEMA 2
8785
+#define DBPTR_SCHEMA \
8786
+ "CREATE TABLE x(" \
8787
+ " pgno INTEGER," \
8788
+ " child INTEGER," \
8789
+ " schema TEXT HIDDEN" \
8790
+ ")"
8791
+
8792
+/*
8793
+** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
8794
+** table.
8795
+*/
8796
+static int dbdataConnect(
8797
+ sqlite3 *db,
8798
+ void *pAux,
8799
+ int argc, const char *const*argv,
8800
+ sqlite3_vtab **ppVtab,
8801
+ char **pzErr
8802
+){
8803
+ DbdataTable *pTab = 0;
8804
+ int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
8805
+
8806
+ if( rc==SQLITE_OK ){
8807
+ pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
8808
+ if( pTab==0 ){
8809
+ rc = SQLITE_NOMEM;
8810
+ }else{
8811
+ memset(pTab, 0, sizeof(DbdataTable));
8812
+ pTab->db = db;
8813
+ pTab->bPtr = (pAux!=0);
8814
+ }
8815
+ }
8816
+
8817
+ *ppVtab = (sqlite3_vtab*)pTab;
8818
+ return rc;
8819
+}
8820
+
8821
+/*
8822
+** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
8823
+*/
8824
+static int dbdataDisconnect(sqlite3_vtab *pVtab){
8825
+ DbdataTable *pTab = (DbdataTable*)pVtab;
8826
+ if( pTab ){
8827
+ sqlite3_finalize(pTab->pStmt);
8828
+ sqlite3_free(pVtab);
8829
+ }
8830
+ return SQLITE_OK;
8831
+}
8832
+
8833
+/*
8834
+** This function interprets two types of constraints:
8835
+**
8836
+** schema=?
8837
+** pgno=?
8838
+**
8839
+** If neither are present, idxNum is set to 0. If schema=? is present,
8840
+** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
8841
+** in idxNum is set.
8842
+**
8843
+** If both parameters are present, schema is in position 0 and pgno in
8844
+** position 1.
8845
+*/
8846
+static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
8847
+ DbdataTable *pTab = (DbdataTable*)tab;
8848
+ int i;
8849
+ int iSchema = -1;
8850
+ int iPgno = -1;
8851
+ int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
8852
+
8853
+ for(i=0; i<pIdx->nConstraint; i++){
8854
+ struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
8855
+ if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
8856
+ if( p->iColumn==colSchema ){
8857
+ if( p->usable==0 ) return SQLITE_CONSTRAINT;
8858
+ iSchema = i;
8859
+ }
8860
+ if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
8861
+ iPgno = i;
8862
+ }
8863
+ }
8864
+ }
8865
+
8866
+ if( iSchema>=0 ){
8867
+ pIdx->aConstraintUsage[iSchema].argvIndex = 1;
8868
+ pIdx->aConstraintUsage[iSchema].omit = 1;
8869
+ }
8870
+ if( iPgno>=0 ){
8871
+ pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
8872
+ pIdx->aConstraintUsage[iPgno].omit = 1;
8873
+ pIdx->estimatedCost = 100;
8874
+ pIdx->estimatedRows = 50;
8875
+
8876
+ if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
8877
+ int iCol = pIdx->aOrderBy[0].iColumn;
8878
+ if( pIdx->nOrderBy==1 ){
8879
+ pIdx->orderByConsumed = (iCol==0 || iCol==1);
8880
+ }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
8881
+ pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
8882
+ }
8883
+ }
8884
+
8885
+ }else{
8886
+ pIdx->estimatedCost = 100000000;
8887
+ pIdx->estimatedRows = 1000000000;
8888
+ }
8889
+ pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
8890
+ return SQLITE_OK;
8891
+}
8892
+
8893
+/*
8894
+** Open a new sqlite_dbdata or sqlite_dbptr cursor.
8895
+*/
8896
+static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
8897
+ DbdataCursor *pCsr;
8898
+
8899
+ pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
8900
+ if( pCsr==0 ){
8901
+ return SQLITE_NOMEM;
8902
+ }else{
8903
+ memset(pCsr, 0, sizeof(DbdataCursor));
8904
+ pCsr->base.pVtab = pVTab;
8905
+ }
8906
+
8907
+ *ppCursor = (sqlite3_vtab_cursor *)pCsr;
8908
+ return SQLITE_OK;
8909
+}
8910
+
8911
+/*
8912
+** Restore a cursor object to the state it was in when first allocated
8913
+** by dbdataOpen().
8914
+*/
8915
+static void dbdataResetCursor(DbdataCursor *pCsr){
8916
+ DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
8917
+ if( pTab->pStmt==0 ){
8918
+ pTab->pStmt = pCsr->pStmt;
8919
+ }else{
8920
+ sqlite3_finalize(pCsr->pStmt);
8921
+ }
8922
+ pCsr->pStmt = 0;
8923
+ pCsr->iPgno = 1;
8924
+ pCsr->iCell = 0;
8925
+ pCsr->iField = 0;
8926
+ pCsr->bOnePage = 0;
8927
+ sqlite3_free(pCsr->aPage);
8928
+ sqlite3_free(pCsr->pRec);
8929
+ pCsr->pRec = 0;
8930
+ pCsr->aPage = 0;
8931
+}
8932
+
8933
+/*
8934
+** Close an sqlite_dbdata or sqlite_dbptr cursor.
8935
+*/
8936
+static int dbdataClose(sqlite3_vtab_cursor *pCursor){
8937
+ DbdataCursor *pCsr = (DbdataCursor*)pCursor;
8938
+ dbdataResetCursor(pCsr);
8939
+ sqlite3_free(pCsr);
8940
+ return SQLITE_OK;
8941
+}
8942
+
8943
+/*
8944
+** Utility methods to decode 16 and 32-bit big-endian unsigned integers.
8945
+*/
8946
+static unsigned int get_uint16(unsigned char *a){
8947
+ return (a[0]<<8)|a[1];
8948
+}
8949
+static unsigned int get_uint32(unsigned char *a){
8950
+ return ((unsigned int)a[0]<<24)
8951
+ | ((unsigned int)a[1]<<16)
8952
+ | ((unsigned int)a[2]<<8)
8953
+ | ((unsigned int)a[3]);
8954
+}
8955
+
8956
+/*
8957
+** Load page pgno from the database via the sqlite_dbpage virtual table.
8958
+** If successful, set (*ppPage) to point to a buffer containing the page
8959
+** data, (*pnPage) to the size of that buffer in bytes and return
8960
+** SQLITE_OK. In this case it is the responsibility of the caller to
8961
+** eventually free the buffer using sqlite3_free().
8962
+**
8963
+** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
8964
+** return an SQLite error code.
8965
+*/
8966
+static int dbdataLoadPage(
8967
+ DbdataCursor *pCsr, /* Cursor object */
8968
+ unsigned int pgno, /* Page number of page to load */
8969
+ u8 **ppPage, /* OUT: pointer to page buffer */
8970
+ int *pnPage /* OUT: Size of (*ppPage) in bytes */
8971
+){
8972
+ int rc2;
8973
+ int rc = SQLITE_OK;
8974
+ sqlite3_stmt *pStmt = pCsr->pStmt;
8975
+
8976
+ *ppPage = 0;
8977
+ *pnPage = 0;
8978
+ sqlite3_bind_int64(pStmt, 2, pgno);
8979
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
8980
+ int nCopy = sqlite3_column_bytes(pStmt, 0);
8981
+ if( nCopy>0 ){
8982
+ u8 *pPage;
8983
+ pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
8984
+ if( pPage==0 ){
8985
+ rc = SQLITE_NOMEM;
8986
+ }else{
8987
+ const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
8988
+ memcpy(pPage, pCopy, nCopy);
8989
+ memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
8990
+ }
8991
+ *ppPage = pPage;
8992
+ *pnPage = nCopy;
8993
+ }
8994
+ }
8995
+ rc2 = sqlite3_reset(pStmt);
8996
+ if( rc==SQLITE_OK ) rc = rc2;
8997
+
8998
+ return rc;
8999
+}
9000
+
9001
+/*
9002
+** Read a varint. Put the value in *pVal and return the number of bytes.
9003
+*/
9004
+static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
9005
+ sqlite3_int64 v = 0;
9006
+ int i;
9007
+ for(i=0; i<8; i++){
9008
+ v = (v<<7) + (z[i]&0x7f);
9009
+ if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
9010
+ }
9011
+ v = (v<<8) + (z[i]&0xff);
9012
+ *pVal = v;
9013
+ return 9;
9014
+}
9015
+
9016
+/*
9017
+** Return the number of bytes of space used by an SQLite value of type
9018
+** eType.
9019
+*/
9020
+static int dbdataValueBytes(int eType){
9021
+ switch( eType ){
9022
+ case 0: case 8: case 9:
9023
+ case 10: case 11:
9024
+ return 0;
9025
+ case 1:
9026
+ return 1;
9027
+ case 2:
9028
+ return 2;
9029
+ case 3:
9030
+ return 3;
9031
+ case 4:
9032
+ return 4;
9033
+ case 5:
9034
+ return 6;
9035
+ case 6:
9036
+ case 7:
9037
+ return 8;
9038
+ default:
9039
+ if( eType>0 ){
9040
+ return ((eType-12) / 2);
9041
+ }
9042
+ return 0;
9043
+ }
9044
+}
9045
+
9046
+/*
9047
+** Load a value of type eType from buffer pData and use it to set the
9048
+** result of context object pCtx.
9049
+*/
9050
+static void dbdataValue(
9051
+ sqlite3_context *pCtx,
9052
+ int eType,
9053
+ u8 *pData,
9054
+ int nData
9055
+){
9056
+ if( eType>=0 && dbdataValueBytes(eType)<=nData ){
9057
+ switch( eType ){
9058
+ case 0:
9059
+ case 10:
9060
+ case 11:
9061
+ sqlite3_result_null(pCtx);
9062
+ break;
9063
+
9064
+ case 8:
9065
+ sqlite3_result_int(pCtx, 0);
9066
+ break;
9067
+ case 9:
9068
+ sqlite3_result_int(pCtx, 1);
9069
+ break;
9070
+
9071
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
9072
+ sqlite3_uint64 v = (signed char)pData[0];
9073
+ pData++;
9074
+ switch( eType ){
9075
+ case 7:
9076
+ case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
9077
+ case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
9078
+ case 4: v = (v<<8) + pData[0]; pData++;
9079
+ case 3: v = (v<<8) + pData[0]; pData++;
9080
+ case 2: v = (v<<8) + pData[0]; pData++;
9081
+ }
9082
+
9083
+ if( eType==7 ){
9084
+ double r;
9085
+ memcpy(&r, &v, sizeof(r));
9086
+ sqlite3_result_double(pCtx, r);
9087
+ }else{
9088
+ sqlite3_result_int64(pCtx, (sqlite3_int64)v);
9089
+ }
9090
+ break;
9091
+ }
9092
+
9093
+ default: {
9094
+ int n = ((eType-12) / 2);
9095
+ if( eType % 2 ){
9096
+ sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
9097
+ }else{
9098
+ sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
9099
+ }
9100
+ }
9101
+ }
9102
+ }
9103
+}
9104
+
9105
+/*
9106
+** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
9107
+*/
9108
+static int dbdataNext(sqlite3_vtab_cursor *pCursor){
9109
+ DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9110
+ DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9111
+
9112
+ pCsr->iRowid++;
9113
+ while( 1 ){
9114
+ int rc;
9115
+ int iOff = (pCsr->iPgno==1 ? 100 : 0);
9116
+ int bNextPage = 0;
9117
+
9118
+ if( pCsr->aPage==0 ){
9119
+ while( 1 ){
9120
+ if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
9121
+ rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
9122
+ if( rc!=SQLITE_OK ) return rc;
9123
+ if( pCsr->aPage ) break;
9124
+ pCsr->iPgno++;
9125
+ }
9126
+ pCsr->iCell = pTab->bPtr ? -2 : 0;
9127
+ pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
9128
+ }
9129
+
9130
+ if( pTab->bPtr ){
9131
+ if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
9132
+ pCsr->iCell = pCsr->nCell;
9133
+ }
9134
+ pCsr->iCell++;
9135
+ if( pCsr->iCell>=pCsr->nCell ){
9136
+ sqlite3_free(pCsr->aPage);
9137
+ pCsr->aPage = 0;
9138
+ if( pCsr->bOnePage ) return SQLITE_OK;
9139
+ pCsr->iPgno++;
9140
+ }else{
9141
+ return SQLITE_OK;
9142
+ }
9143
+ }else{
9144
+ /* If there is no record loaded, load it now. */
9145
+ if( pCsr->pRec==0 ){
9146
+ int bHasRowid = 0;
9147
+ int nPointer = 0;
9148
+ sqlite3_int64 nPayload = 0;
9149
+ sqlite3_int64 nHdr = 0;
9150
+ int iHdr;
9151
+ int U, X;
9152
+ int nLocal;
9153
+
9154
+ switch( pCsr->aPage[iOff] ){
9155
+ case 0x02:
9156
+ nPointer = 4;
9157
+ break;
9158
+ case 0x0a:
9159
+ break;
9160
+ case 0x0d:
9161
+ bHasRowid = 1;
9162
+ break;
9163
+ default:
9164
+ /* This is not a b-tree page with records on it. Continue. */
9165
+ pCsr->iCell = pCsr->nCell;
9166
+ break;
9167
+ }
9168
+
9169
+ if( pCsr->iCell>=pCsr->nCell ){
9170
+ bNextPage = 1;
9171
+ }else{
9172
+
9173
+ iOff += 8 + nPointer + pCsr->iCell*2;
9174
+ if( iOff>pCsr->nPage ){
9175
+ bNextPage = 1;
9176
+ }else{
9177
+ iOff = get_uint16(&pCsr->aPage[iOff]);
9178
+ }
9179
+
9180
+ /* For an interior node cell, skip past the child-page number */
9181
+ iOff += nPointer;
9182
+
9183
+ /* Load the "byte of payload including overflow" field */
9184
+ if( bNextPage || iOff>pCsr->nPage ){
9185
+ bNextPage = 1;
9186
+ }else{
9187
+ iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
9188
+ }
9189
+
9190
+ /* If this is a leaf intkey cell, load the rowid */
9191
+ if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
9192
+ iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
9193
+ }
9194
+
9195
+ /* Figure out how much data to read from the local page */
9196
+ U = pCsr->nPage;
9197
+ if( bHasRowid ){
9198
+ X = U-35;
9199
+ }else{
9200
+ X = ((U-12)*64/255)-23;
9201
+ }
9202
+ if( nPayload<=X ){
9203
+ nLocal = nPayload;
9204
+ }else{
9205
+ int M, K;
9206
+ M = ((U-12)*32/255)-23;
9207
+ K = M+((nPayload-M)%(U-4));
9208
+ if( K<=X ){
9209
+ nLocal = K;
9210
+ }else{
9211
+ nLocal = M;
9212
+ }
9213
+ }
9214
+
9215
+ if( bNextPage || nLocal+iOff>pCsr->nPage ){
9216
+ bNextPage = 1;
9217
+ }else{
9218
+
9219
+ /* Allocate space for payload. And a bit more to catch small buffer
9220
+ ** overruns caused by attempting to read a varint or similar from
9221
+ ** near the end of a corrupt record. */
9222
+ pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
9223
+ if( pCsr->pRec==0 ) return SQLITE_NOMEM;
9224
+ memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
9225
+ pCsr->nRec = nPayload;
9226
+
9227
+ /* Load the nLocal bytes of payload */
9228
+ memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
9229
+ iOff += nLocal;
9230
+
9231
+ /* Load content from overflow pages */
9232
+ if( nPayload>nLocal ){
9233
+ sqlite3_int64 nRem = nPayload - nLocal;
9234
+ unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
9235
+ while( nRem>0 ){
9236
+ u8 *aOvfl = 0;
9237
+ int nOvfl = 0;
9238
+ int nCopy;
9239
+ rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
9240
+ assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
9241
+ if( rc!=SQLITE_OK ) return rc;
9242
+ if( aOvfl==0 ) break;
9243
+
9244
+ nCopy = U-4;
9245
+ if( nCopy>nRem ) nCopy = nRem;
9246
+ memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
9247
+ nRem -= nCopy;
9248
+
9249
+ pgnoOvfl = get_uint32(aOvfl);
9250
+ sqlite3_free(aOvfl);
9251
+ }
9252
+ }
9253
+
9254
+ iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
9255
+ pCsr->nHdr = nHdr;
9256
+ pCsr->pHdrPtr = &pCsr->pRec[iHdr];
9257
+ pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
9258
+ pCsr->iField = (bHasRowid ? -1 : 0);
9259
+ }
9260
+ }
9261
+ }else{
9262
+ pCsr->iField++;
9263
+ if( pCsr->iField>0 ){
9264
+ sqlite3_int64 iType;
9265
+ if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
9266
+ bNextPage = 1;
9267
+ }else{
9268
+ pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
9269
+ pCsr->pPtr += dbdataValueBytes(iType);
9270
+ }
9271
+ }
9272
+ }
9273
+
9274
+ if( bNextPage ){
9275
+ sqlite3_free(pCsr->aPage);
9276
+ sqlite3_free(pCsr->pRec);
9277
+ pCsr->aPage = 0;
9278
+ pCsr->pRec = 0;
9279
+ if( pCsr->bOnePage ) return SQLITE_OK;
9280
+ pCsr->iPgno++;
9281
+ }else{
9282
+ if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
9283
+ return SQLITE_OK;
9284
+ }
9285
+
9286
+ /* Advance to the next cell. The next iteration of the loop will load
9287
+ ** the record and so on. */
9288
+ sqlite3_free(pCsr->pRec);
9289
+ pCsr->pRec = 0;
9290
+ pCsr->iCell++;
9291
+ }
9292
+ }
9293
+ }
9294
+
9295
+ assert( !"can't get here" );
9296
+ return SQLITE_OK;
9297
+}
9298
+
9299
+/*
9300
+** Return true if the cursor is at EOF.
9301
+*/
9302
+static int dbdataEof(sqlite3_vtab_cursor *pCursor){
9303
+ DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9304
+ return pCsr->aPage==0;
9305
+}
9306
+
9307
+/*
9308
+** Determine the size in pages of database zSchema (where zSchema is
9309
+** "main", "temp" or the name of an attached database) and set
9310
+** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
9311
+** an SQLite error code.
9312
+*/
9313
+static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
9314
+ DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
9315
+ char *zSql = 0;
9316
+ int rc, rc2;
9317
+ sqlite3_stmt *pStmt = 0;
9318
+
9319
+ zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
9320
+ if( zSql==0 ) return SQLITE_NOMEM;
9321
+ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
9322
+ sqlite3_free(zSql);
9323
+ if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9324
+ pCsr->szDb = sqlite3_column_int(pStmt, 0);
9325
+ }
9326
+ rc2 = sqlite3_finalize(pStmt);
9327
+ if( rc==SQLITE_OK ) rc = rc2;
9328
+ return rc;
9329
+}
9330
+
9331
+/*
9332
+** xFilter method for sqlite_dbdata and sqlite_dbptr.
9333
+*/
9334
+static int dbdataFilter(
9335
+ sqlite3_vtab_cursor *pCursor,
9336
+ int idxNum, const char *idxStr,
9337
+ int argc, sqlite3_value **argv
9338
+){
9339
+ DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9340
+ DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9341
+ int rc = SQLITE_OK;
9342
+ const char *zSchema = "main";
9343
+
9344
+ dbdataResetCursor(pCsr);
9345
+ assert( pCsr->iPgno==1 );
9346
+ if( idxNum & 0x01 ){
9347
+ zSchema = (const char*)sqlite3_value_text(argv[0]);
9348
+ }
9349
+ if( idxNum & 0x02 ){
9350
+ pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
9351
+ pCsr->bOnePage = 1;
9352
+ }else{
9353
+ pCsr->nPage = dbdataDbsize(pCsr, zSchema);
9354
+ rc = dbdataDbsize(pCsr, zSchema);
9355
+ }
9356
+
9357
+ if( rc==SQLITE_OK ){
9358
+ if( pTab->pStmt ){
9359
+ pCsr->pStmt = pTab->pStmt;
9360
+ pTab->pStmt = 0;
9361
+ }else{
9362
+ rc = sqlite3_prepare_v2(pTab->db,
9363
+ "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
9364
+ &pCsr->pStmt, 0
9365
+ );
9366
+ }
9367
+ }
9368
+ if( rc==SQLITE_OK ){
9369
+ rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
9370
+ }else{
9371
+ pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
9372
+ }
9373
+ if( rc==SQLITE_OK ){
9374
+ rc = dbdataNext(pCursor);
9375
+ }
9376
+ return rc;
9377
+}
9378
+
9379
+/*
9380
+** Return a column for the sqlite_dbdata or sqlite_dbptr table.
9381
+*/
9382
+static int dbdataColumn(
9383
+ sqlite3_vtab_cursor *pCursor,
9384
+ sqlite3_context *ctx,
9385
+ int i
9386
+){
9387
+ DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9388
+ DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9389
+ if( pTab->bPtr ){
9390
+ switch( i ){
9391
+ case DBPTR_COLUMN_PGNO:
9392
+ sqlite3_result_int64(ctx, pCsr->iPgno);
9393
+ break;
9394
+ case DBPTR_COLUMN_CHILD: {
9395
+ int iOff = pCsr->iPgno==1 ? 100 : 0;
9396
+ if( pCsr->iCell<0 ){
9397
+ iOff += 8;
9398
+ }else{
9399
+ iOff += 12 + pCsr->iCell*2;
9400
+ if( iOff>pCsr->nPage ) return SQLITE_OK;
9401
+ iOff = get_uint16(&pCsr->aPage[iOff]);
9402
+ }
9403
+ if( iOff<=pCsr->nPage ){
9404
+ sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
9405
+ }
9406
+ break;
9407
+ }
9408
+ }
9409
+ }else{
9410
+ switch( i ){
9411
+ case DBDATA_COLUMN_PGNO:
9412
+ sqlite3_result_int64(ctx, pCsr->iPgno);
9413
+ break;
9414
+ case DBDATA_COLUMN_CELL:
9415
+ sqlite3_result_int(ctx, pCsr->iCell);
9416
+ break;
9417
+ case DBDATA_COLUMN_FIELD:
9418
+ sqlite3_result_int(ctx, pCsr->iField);
9419
+ break;
9420
+ case DBDATA_COLUMN_VALUE: {
9421
+ if( pCsr->iField<0 ){
9422
+ sqlite3_result_int64(ctx, pCsr->iIntkey);
9423
+ }else{
9424
+ sqlite3_int64 iType;
9425
+ dbdataGetVarint(pCsr->pHdrPtr, &iType);
9426
+ dbdataValue(
9427
+ ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
9428
+ );
9429
+ }
9430
+ break;
9431
+ }
9432
+ }
9433
+ }
9434
+ return SQLITE_OK;
9435
+}
9436
+
9437
+/*
9438
+** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
9439
+*/
9440
+static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
9441
+ DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9442
+ *pRowid = pCsr->iRowid;
9443
+ return SQLITE_OK;
9444
+}
9445
+
9446
+
9447
+/*
9448
+** Invoke this routine to register the "sqlite_dbdata" virtual table module
9449
+*/
9450
+static int sqlite3DbdataRegister(sqlite3 *db){
9451
+ static sqlite3_module dbdata_module = {
9452
+ 0, /* iVersion */
9453
+ 0, /* xCreate */
9454
+ dbdataConnect, /* xConnect */
9455
+ dbdataBestIndex, /* xBestIndex */
9456
+ dbdataDisconnect, /* xDisconnect */
9457
+ 0, /* xDestroy */
9458
+ dbdataOpen, /* xOpen - open a cursor */
9459
+ dbdataClose, /* xClose - close a cursor */
9460
+ dbdataFilter, /* xFilter - configure scan constraints */
9461
+ dbdataNext, /* xNext - advance a cursor */
9462
+ dbdataEof, /* xEof - check for end of scan */
9463
+ dbdataColumn, /* xColumn - read data */
9464
+ dbdataRowid, /* xRowid - read data */
9465
+ 0, /* xUpdate */
9466
+ 0, /* xBegin */
9467
+ 0, /* xSync */
9468
+ 0, /* xCommit */
9469
+ 0, /* xRollback */
9470
+ 0, /* xFindMethod */
9471
+ 0, /* xRename */
9472
+ 0, /* xSavepoint */
9473
+ 0, /* xRelease */
9474
+ 0, /* xRollbackTo */
9475
+ 0 /* xShadowName */
9476
+ };
9477
+
9478
+ int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
9479
+ if( rc==SQLITE_OK ){
9480
+ rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
9481
+ }
9482
+ return rc;
9483
+}
9484
+
9485
+#ifdef _WIN32
9486
+
9487
+#endif
9488
+int sqlite3_dbdata_init(
9489
+ sqlite3 *db,
9490
+ char **pzErrMsg,
9491
+ const sqlite3_api_routines *pApi
9492
+){
9493
+ SQLITE_EXTENSION_INIT2(pApi);
9494
+ return sqlite3DbdataRegister(db);
9495
+}
9496
+
9497
+/************************* End ../ext/misc/dbdata.c ********************/
9498
+#endif
86339499
86349500
#if defined(SQLITE_ENABLE_SESSION)
86359501
/*
86369502
** State information for a single open session
86379503
*/
@@ -9358,10 +10224,12 @@
935810224
**
935910225
** This routine converts some CREATE TABLE statements for shadow tables
936010226
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
936110227
*/
936210228
static void printSchemaLine(FILE *out, const char *z, const char *zTail){
10229
+ if( z==0 ) return;
10230
+ if( zTail==0 ) return;
936310231
if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
936410232
utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
936510233
}else{
936610234
utf8_printf(out, "%s%s", z, zTail);
936710235
}
@@ -10427,10 +11295,70 @@
1042711295
#endif
1042811296
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
1042911297
sqlite3WhereTrace = savedWhereTrace;
1043011298
#endif
1043111299
}
11300
+
11301
+/* Create the TEMP table used to store parameter bindings */
11302
+static void bind_table_init(ShellState *p){
11303
+ int wrSchema = 0;
11304
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
11305
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
11306
+ sqlite3_exec(p->db,
11307
+ "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
11308
+ " key TEXT PRIMARY KEY,\n"
11309
+ " value ANY\n"
11310
+ ") WITHOUT ROWID;",
11311
+ 0, 0, 0);
11312
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
11313
+}
11314
+
11315
+/*
11316
+** Bind parameters on a prepared statement.
11317
+**
11318
+** Parameter bindings are taken from a TEMP table of the form:
11319
+**
11320
+** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
11321
+** WITHOUT ROWID;
11322
+**
11323
+** No bindings occur if this table does not exist. The special character '$'
11324
+** is included in the table name to help prevent collisions with actual tables.
11325
+** The table must be in the TEMP schema.
11326
+*/
11327
+static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
11328
+ int nVar;
11329
+ int i;
11330
+ int rc;
11331
+ sqlite3_stmt *pQ = 0;
11332
+
11333
+ nVar = sqlite3_bind_parameter_count(pStmt);
11334
+ if( nVar==0 ) return; /* Nothing to do */
11335
+ if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
11336
+ "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
11337
+ return; /* Parameter table does not exist */
11338
+ }
11339
+ rc = sqlite3_prepare_v2(pArg->db,
11340
+ "SELECT value FROM temp.sqlite_parameters"
11341
+ " WHERE key=?1", -1, &pQ, 0);
11342
+ if( rc || pQ==0 ) return;
11343
+ for(i=1; i<=nVar; i++){
11344
+ char zNum[30];
11345
+ const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
11346
+ if( zVar==0 ){
11347
+ sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
11348
+ zVar = zNum;
11349
+ }
11350
+ sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
11351
+ if( sqlite3_step(pQ)==SQLITE_ROW ){
11352
+ sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
11353
+ }else{
11354
+ sqlite3_bind_null(pStmt, i);
11355
+ }
11356
+ sqlite3_reset(pQ);
11357
+ }
11358
+ sqlite3_finalize(pQ);
11359
+}
1043211360
1043311361
/*
1043411362
** Run a prepared statement
1043511363
*/
1043611364
static void exec_prepared_stmt(
@@ -10680,11 +11608,11 @@
1068011608
if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
1068111609
utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
1068211610
}
1068311611
1068411612
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
10685
- if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
11613
+ if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
1068611614
sqlite3_stmt *pExplain;
1068711615
char *zEQP;
1068811616
int triggerEQP = 0;
1068911617
disable_debug_trace_modes();
1069011618
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
@@ -10729,17 +11657,14 @@
1072911657
}
1073011658
1073111659
if( pArg ){
1073211660
pArg->cMode = pArg->mode;
1073311661
if( pArg->autoExplain ){
10734
- if( sqlite3_column_count(pStmt)==8
10735
- && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
10736
- ){
11662
+ if( sqlite3_stmt_isexplain(pStmt)==1 ){
1073711663
pArg->cMode = MODE_Explain;
1073811664
}
10739
- if( sqlite3_column_count(pStmt)==4
10740
- && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){
11665
+ if( sqlite3_stmt_isexplain(pStmt)==2 ){
1074111666
pArg->cMode = MODE_EQP;
1074211667
}
1074311668
}
1074411669
1074511670
/* If the shell is currently in ".explain" mode, gather the extra
@@ -10747,10 +11672,11 @@
1074711672
if( pArg->cMode==MODE_Explain ){
1074811673
explain_data_prepare(pArg, pStmt);
1074911674
}
1075011675
}
1075111676
11677
+ bind_prepared_stmt(pArg, pStmt);
1075211678
exec_prepared_stmt(pArg, pStmt);
1075311679
explain_data_delete(pArg);
1075411680
eqp_render(pArg);
1075511681
1075611682
/* print usage stats if stats on */
@@ -11076,11 +12002,12 @@
1107612002
static const char *(azHelp[]) = {
1107712003
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
1107812004
".archive ... Manage SQL archives",
1107912005
" Each command must have exactly one of the following options:",
1108012006
" -c, --create Create a new archive",
11081
- " -u, --update Update or add files to an existing archive",
12007
+ " -u, --update Add files or update files with changed mtime",
12008
+ " -i, --insert Like -u but always add even if mtime unchanged",
1108212009
" -t, --list List contents of archive",
1108312010
" -x, --extract Extract files from archive",
1108412011
" Optional arguments:",
1108512012
" -v, --verbose Print each filename as it is processed",
1108612013
" -f FILE, --file FILE Operate on archive FILE (default is current db)",
@@ -11111,11 +12038,11 @@
1111112038
".dbinfo ?DB? Show status information about the database",
1111212039
".dump ?TABLE? ... Render all database content as SQL",
1111312040
" Options:",
1111412041
" --preserve-rowids Include ROWID values in the output",
1111512042
" --newlines Allow unescaped newline characters in output",
11116
- " TABLE is LIKE pattern for the tables to dump",
12043
+ " TABLE is a LIKE pattern for the tables to dump",
1111712044
".echo on|off Turn command echo on or off",
1111812045
".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
1111912046
" Other Modes:",
1112012047
#ifdef SQLITE_DEBUG
1112112048
" test Show raw EXPLAIN QUERY PLAN output",
@@ -11178,10 +12105,17 @@
1117812105
" --new Initialize FILE to an empty database",
1117912106
" --readonly Open FILE readonly",
1118012107
" --zip FILE is a ZIP archive",
1118112108
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
1118212109
" If FILE begins with '|' then open it as a pipe.",
12110
+ ".parameter CMD ... Manage SQL parameter bindings",
12111
+ " clear Erase all bindings",
12112
+ " init Initialize the TEMP table that holds bindings",
12113
+ " list List the current parameter bindings",
12114
+ " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
12115
+ " PARAMETER should start with '$', ':', '@', or '?'",
12116
+ " unset PARAMETER Remove PARAMETER from the binding table",
1118312117
".print STRING... Print literal STRING",
1118412118
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
1118512119
".progress N Invoke progress handler after every N opcodes",
1118612120
" --limit N Interrupt after N progress callbacks",
1118712121
" --once Do no more than one progress interrupt",
@@ -11189,10 +12123,13 @@
1118912123
" --reset Reset the count for each input and interrupt",
1119012124
#endif
1119112125
".prompt MAIN CONTINUE Replace the standard prompts",
1119212126
".quit Exit this program",
1119312127
".read FILE Read input from FILE",
12128
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
12129
+ ".recover Recover as much data as possible from corrupt db.",
12130
+#endif
1119412131
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
1119512132
".save FILE Write in-memory database into FILE",
1119612133
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
1119712134
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
1119812135
" Options:",
@@ -11473,11 +12410,11 @@
1147312410
int pgsz = 0;
1147412411
int iOffset = 0;
1147512412
int j, k;
1147612413
int rc;
1147712414
FILE *in;
11478
- unsigned char x[16];
12415
+ unsigned int x[16];
1147912416
char zLine[1000];
1148012417
if( p->zDbFilename ){
1148112418
in = fopen(p->zDbFilename, "r");
1148212419
if( in==0 ){
1148312420
utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
@@ -11485,18 +12422,19 @@
1148512422
}
1148612423
nLine = 0;
1148712424
}else{
1148812425
in = p->in;
1148912426
nLine = p->lineno;
12427
+ if( in==0 ) in = stdin;
1149012428
}
1149112429
*pnData = 0;
1149212430
nLine++;
1149312431
if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
1149412432
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
1149512433
if( rc!=2 ) goto readHexDb_error;
11496
- if( n<=0 ) goto readHexDb_error;
11497
- a = sqlite3_malloc( n );
12434
+ if( n<0 ) goto readHexDb_error;
12435
+ a = sqlite3_malloc( n ? n : 1 );
1149812436
if( a==0 ){
1149912437
utf8_printf(stderr, "Out of memory!\n");
1150012438
goto readHexDb_error;
1150112439
}
1150212440
memset(a, 0, n);
@@ -11511,18 +12449,18 @@
1151112449
continue;
1151212450
}
1151312451
if( strncmp(zLine, "| end ", 6)==0 ){
1151412452
break;
1151512453
}
11516
- rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
11517
- " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
12454
+ rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
1151812455
&j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
1151912456
&x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
1152012457
if( rc==17 ){
1152112458
k = iOffset+j;
1152212459
if( k+16<=n ){
11523
- memcpy(a+k, x, 16);
12460
+ int ii;
12461
+ for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
1152412462
}
1152512463
}
1152612464
}
1152712465
*pnData = n;
1152812466
if( in!=p->in ){
@@ -11531,11 +12469,11 @@
1153112469
p->lineno = nLine;
1153212470
}
1153312471
return a;
1153412472
1153512473
readHexDb_error:
11536
- if( in!=stdin ){
12474
+ if( in!=p->in ){
1153712475
fclose(in);
1153812476
}else{
1153912477
while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
1154012478
nLine++;
1154112479
if(strncmp(zLine, "| end ", 6)==0 ) break;
@@ -11545,10 +12483,131 @@
1154512483
sqlite3_free(a);
1154612484
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
1154712485
return 0;
1154812486
}
1154912487
#endif /* SQLITE_ENABLE_DESERIALIZE */
12488
+
12489
+/*
12490
+** Scalar function "shell_int32". The first argument to this function
12491
+** must be a blob. The second a non-negative integer. This function
12492
+** reads and returns a 32-bit big-endian integer from byte
12493
+** offset (4*<arg2>) of the blob.
12494
+*/
12495
+static void shellInt32(
12496
+ sqlite3_context *context,
12497
+ int argc,
12498
+ sqlite3_value **argv
12499
+){
12500
+ const unsigned char *pBlob;
12501
+ int nBlob;
12502
+ int iInt;
12503
+
12504
+ UNUSED_PARAMETER(argc);
12505
+ nBlob = sqlite3_value_bytes(argv[0]);
12506
+ pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
12507
+ iInt = sqlite3_value_int(argv[1]);
12508
+
12509
+ if( iInt>=0 && (iInt+1)*4<=nBlob ){
12510
+ const unsigned char *a = &pBlob[iInt*4];
12511
+ sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
12512
+ + ((sqlite3_int64)a[1]<<16)
12513
+ + ((sqlite3_int64)a[2]<< 8)
12514
+ + ((sqlite3_int64)a[3]<< 0);
12515
+ sqlite3_result_int64(context, iVal);
12516
+ }
12517
+}
12518
+
12519
+/*
12520
+** Scalar function "shell_escape_crnl" used by the .recover command.
12521
+** The argument passed to this function is the output of built-in
12522
+** function quote(). If the first character of the input is "'",
12523
+** indicating that the value passed to quote() was a text value,
12524
+** then this function searches the input for "\n" and "\r" characters
12525
+** and adds a wrapper similar to the following:
12526
+**
12527
+** replace(replace(<input>, '\n', char(10), '\r', char(13));
12528
+**
12529
+** Or, if the first character of the input is not "'", then a copy
12530
+** of the input is returned.
12531
+*/
12532
+static void shellEscapeCrnl(
12533
+ sqlite3_context *context,
12534
+ int argc,
12535
+ sqlite3_value **argv
12536
+){
12537
+ const char *zText = (const char*)sqlite3_value_text(argv[0]);
12538
+ UNUSED_PARAMETER(argc);
12539
+ if( zText[0]=='\'' ){
12540
+ int nText = sqlite3_value_bytes(argv[0]);
12541
+ int i;
12542
+ char zBuf1[20];
12543
+ char zBuf2[20];
12544
+ const char *zNL = 0;
12545
+ const char *zCR = 0;
12546
+ int nCR = 0;
12547
+ int nNL = 0;
12548
+
12549
+ for(i=0; zText[i]; i++){
12550
+ if( zNL==0 && zText[i]=='\n' ){
12551
+ zNL = unused_string(zText, "\\n", "\\012", zBuf1);
12552
+ nNL = (int)strlen(zNL);
12553
+ }
12554
+ if( zCR==0 && zText[i]=='\r' ){
12555
+ zCR = unused_string(zText, "\\r", "\\015", zBuf2);
12556
+ nCR = (int)strlen(zCR);
12557
+ }
12558
+ }
12559
+
12560
+ if( zNL || zCR ){
12561
+ int iOut = 0;
12562
+ i64 nMax = (nNL > nCR) ? nNL : nCR;
12563
+ i64 nAlloc = nMax * nText + (nMax+64)*2;
12564
+ char *zOut = (char*)sqlite3_malloc64(nAlloc);
12565
+ if( zOut==0 ){
12566
+ sqlite3_result_error_nomem(context);
12567
+ return;
12568
+ }
12569
+
12570
+ if( zNL && zCR ){
12571
+ memcpy(&zOut[iOut], "replace(replace(", 16);
12572
+ iOut += 16;
12573
+ }else{
12574
+ memcpy(&zOut[iOut], "replace(", 8);
12575
+ iOut += 8;
12576
+ }
12577
+ for(i=0; zText[i]; i++){
12578
+ if( zText[i]=='\n' ){
12579
+ memcpy(&zOut[iOut], zNL, nNL);
12580
+ iOut += nNL;
12581
+ }else if( zText[i]=='\r' ){
12582
+ memcpy(&zOut[iOut], zCR, nCR);
12583
+ iOut += nCR;
12584
+ }else{
12585
+ zOut[iOut] = zText[i];
12586
+ iOut++;
12587
+ }
12588
+ }
12589
+
12590
+ if( zNL ){
12591
+ memcpy(&zOut[iOut], ",'", 2); iOut += 2;
12592
+ memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
12593
+ memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
12594
+ }
12595
+ if( zCR ){
12596
+ memcpy(&zOut[iOut], ",'", 2); iOut += 2;
12597
+ memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
12598
+ memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
12599
+ }
12600
+
12601
+ sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
12602
+ sqlite3_free(zOut);
12603
+ return;
12604
+ }
12605
+ }
12606
+
12607
+ sqlite3_result_value(context, argv[0]);
12608
+}
1155012609
1155112610
/* Flags for open_db().
1155212611
**
1155312612
** The default behavior of open_db() is to exit(1) if the database fails to
1155412613
** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
@@ -11614,10 +12673,13 @@
1161412673
sqlite3_enable_load_extension(p->db, 1);
1161512674
#endif
1161612675
sqlite3_fileio_init(p->db, 0, 0);
1161712676
sqlite3_shathree_init(p->db, 0, 0);
1161812677
sqlite3_completion_init(p->db, 0, 0);
12678
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
12679
+ sqlite3_dbdata_init(p->db, 0, 0);
12680
+#endif
1161912681
#ifdef SQLITE_HAVE_ZLIB
1162012682
sqlite3_zipfile_init(p->db, 0, 0);
1162112683
sqlite3_sqlar_init(p->db, 0, 0);
1162212684
#endif
1162312685
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
@@ -11624,10 +12686,14 @@
1162412686
shellAddSchemaName, 0, 0);
1162512687
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
1162612688
shellModuleSchema, 0, 0);
1162712689
sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
1162812690
shellPutsFunc, 0, 0);
12691
+ sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
12692
+ shellEscapeCrnl, 0, 0);
12693
+ sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
12694
+ shellInt32, 0, 0);
1162912695
#ifndef SQLITE_NOHAVE_SYSTEM
1163012696
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
1163112697
editFunc, 0, 0);
1163212698
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
1163312699
editFunc, 0, 0);
@@ -11647,11 +12713,10 @@
1164712713
if( p->openMode==SHELL_OPEN_DESERIALIZE ){
1164812714
aData = (unsigned char*)readFile(p->zDbFilename, &nData);
1164912715
}else{
1165012716
aData = readHexDb(p, &nData);
1165112717
if( aData==0 ){
11652
- utf8_printf(stderr, "Error in hexdb input\n");
1165312718
return;
1165412719
}
1165512720
}
1165612721
rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
1165712722
SQLITE_DESERIALIZE_RESIZEABLE |
@@ -12390,20 +13455,31 @@
1239013455
{ "number of views:",
1239113456
"SELECT count(*) FROM %s WHERE type='view'" },
1239213457
{ "schema size:",
1239313458
"SELECT total(length(sql)) FROM %s" },
1239413459
};
12395
- int i;
13460
+ int i, rc;
1239613461
unsigned iDataVersion;
1239713462
char *zSchemaTab;
1239813463
char *zDb = nArg>=2 ? azArg[1] : "main";
1239913464
sqlite3_stmt *pStmt = 0;
1240013465
unsigned char aHdr[100];
1240113466
open_db(p, 0);
1240213467
if( p->db==0 ) return 1;
12403
- sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
12404
- -1, &pStmt, 0);
13468
+ rc = sqlite3_prepare_v2(p->db,
13469
+ "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
13470
+ -1, &pStmt, 0);
13471
+ if( rc ){
13472
+ if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
13473
+ utf8_printf(stderr, "the \".dbinfo\" command requires the "
13474
+ "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
13475
+ }else{
13476
+ utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
13477
+ }
13478
+ sqlite3_finalize(pStmt);
13479
+ return 1;
13480
+ }
1240513481
sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
1240613482
if( sqlite3_step(pStmt)==SQLITE_ROW
1240713483
&& sqlite3_column_bytes(pStmt,0)>100
1240813484
){
1240913485
memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
@@ -12867,14 +13943,11 @@
1286713943
raw_printf(stderr, "Where sub-commands are:\n");
1286813944
raw_printf(stderr, " fkey-indexes\n");
1286913945
return SQLITE_ERROR;
1287013946
}
1287113947
12872
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
12873
-/*********************************************************************************
12874
-** The ".archive" or ".ar" command.
12875
-*/
13948
+#if !defined SQLITE_OMIT_VIRTUALTABLE
1287613949
static void shellPrepare(
1287713950
sqlite3 *db,
1287813951
int *pRc,
1287913952
const char *zSql,
1288013953
sqlite3_stmt **ppStmt
@@ -12889,11 +13962,18 @@
1288913962
*pRc = rc;
1289013963
}
1289113964
}
1289213965
}
1289313966
12894
-static void shellPreparePrintf(
13967
+/*
13968
+** Create a prepared statement using printf-style arguments for the SQL.
13969
+**
13970
+** This routine is could be marked "static". But it is not always used,
13971
+** depending on compile-time options. By omitting the "static", we avoid
13972
+** nuisance compiler warnings about "defined but not used".
13973
+*/
13974
+void shellPreparePrintf(
1289513975
sqlite3 *db,
1289613976
int *pRc,
1289713977
sqlite3_stmt **ppStmt,
1289813978
const char *zFmt,
1289913979
...
@@ -12912,11 +13992,17 @@
1291213992
sqlite3_free(z);
1291313993
}
1291413994
}
1291513995
}
1291613996
12917
-static void shellFinalize(
13997
+/* Finalize the prepared statement created using shellPreparePrintf().
13998
+**
13999
+** This routine is could be marked "static". But it is not always used,
14000
+** depending on compile-time options. By omitting the "static", we avoid
14001
+** nuisance compiler warnings about "defined but not used".
14002
+*/
14003
+void shellFinalize(
1291814004
int *pRc,
1291914005
sqlite3_stmt *pStmt
1292014006
){
1292114007
if( pStmt ){
1292214008
sqlite3 *db = sqlite3_db_handle(pStmt);
@@ -12928,11 +14014,17 @@
1292814014
*pRc = rc;
1292914015
}
1293014016
}
1293114017
}
1293214018
12933
-static void shellReset(
14019
+/* Reset the prepared statement created using shellPreparePrintf().
14020
+**
14021
+** This routine is could be marked "static". But it is not always used,
14022
+** depending on compile-time options. By omitting the "static", we avoid
14023
+** nuisance compiler warnings about "defined but not used".
14024
+*/
14025
+void shellReset(
1293414026
int *pRc,
1293514027
sqlite3_stmt *pStmt
1293614028
){
1293714029
int rc = sqlite3_reset(pStmt);
1293814030
if( *pRc==SQLITE_OK ){
@@ -12941,10 +14033,16 @@
1294114033
raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
1294214034
}
1294314035
*pRc = rc;
1294414036
}
1294514037
}
14038
+#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
14039
+
14040
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
14041
+/*********************************************************************************
14042
+** The ".archive" or ".ar" command.
14043
+*/
1294614044
/*
1294714045
** Structure representing a single ".ar" command.
1294814046
*/
1294914047
typedef struct ArCommand ArCommand;
1295014048
struct ArCommand {
@@ -12993,30 +14091,32 @@
1299314091
1299414092
/*
1299514093
** Values for ArCommand.eCmd.
1299614094
*/
1299714095
#define AR_CMD_CREATE 1
12998
-#define AR_CMD_EXTRACT 2
12999
-#define AR_CMD_LIST 3
13000
-#define AR_CMD_UPDATE 4
13001
-#define AR_CMD_HELP 5
14096
+#define AR_CMD_UPDATE 2
14097
+#define AR_CMD_INSERT 3
14098
+#define AR_CMD_EXTRACT 4
14099
+#define AR_CMD_LIST 5
14100
+#define AR_CMD_HELP 6
1300214101
1300314102
/*
1300414103
** Other (non-command) switches.
1300514104
*/
13006
-#define AR_SWITCH_VERBOSE 6
13007
-#define AR_SWITCH_FILE 7
13008
-#define AR_SWITCH_DIRECTORY 8
13009
-#define AR_SWITCH_APPEND 9
13010
-#define AR_SWITCH_DRYRUN 10
14105
+#define AR_SWITCH_VERBOSE 7
14106
+#define AR_SWITCH_FILE 8
14107
+#define AR_SWITCH_DIRECTORY 9
14108
+#define AR_SWITCH_APPEND 10
14109
+#define AR_SWITCH_DRYRUN 11
1301114110
1301214111
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
1301314112
switch( eSwitch ){
1301414113
case AR_CMD_CREATE:
1301514114
case AR_CMD_EXTRACT:
1301614115
case AR_CMD_LIST:
1301714116
case AR_CMD_UPDATE:
14117
+ case AR_CMD_INSERT:
1301814118
case AR_CMD_HELP:
1301914119
if( pAr->eCmd ){
1302014120
return arErrorMsg(pAr, "multiple command options");
1302114121
}
1302214122
pAr->eCmd = eSwitch;
@@ -13059,10 +14159,11 @@
1305914159
u8 eSwitch;
1306014160
u8 bArg;
1306114161
} aSwitch[] = {
1306214162
{ "create", 'c', AR_CMD_CREATE, 0 },
1306314163
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
14164
+ { "insert", 'i', AR_CMD_INSERT, 0 },
1306414165
{ "list", 't', AR_CMD_LIST, 0 },
1306514166
{ "update", 'u', AR_CMD_UPDATE, 0 },
1306614167
{ "help", 'h', AR_CMD_HELP, 0 },
1306714168
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
1306814169
{ "file", 'f', AR_SWITCH_FILE, 1 },
@@ -13394,23 +14495,31 @@
1339414495
return rc;
1339514496
}
1339614497
1339714498
1339814499
/*
13399
-** Implementation of .ar "create" and "update" commands.
14500
+** Implementation of .ar "create", "insert", and "update" commands.
14501
+**
14502
+** create -> Create a new SQL archive
14503
+** insert -> Insert or reinsert all files listed
14504
+** update -> Insert files that have changed or that were not
14505
+** previously in the archive
1340014506
**
1340114507
** Create the "sqlar" table in the database if it does not already exist.
1340214508
** Then add each file in the azFile[] array to the archive. Directories
1340314509
** are added recursively. If argument bVerbose is non-zero, a message is
1340414510
** printed on stdout for each file archived.
1340514511
**
1340614512
** The create command is the same as update, except that it drops
13407
-** any existing "sqlar" table before beginning.
14513
+** any existing "sqlar" table before beginning. The "insert" command
14514
+** always overwrites every file named on the command-line, where as
14515
+** "update" only overwrites if the size or mtime or mode has changed.
1340814516
*/
1340914517
static int arCreateOrUpdateCommand(
1341014518
ArCommand *pAr, /* Command arguments and options */
13411
- int bUpdate /* true for a --create. false for --update */
14519
+ int bUpdate, /* true for a --create. */
14520
+ int bOnlyIfChanged /* Only update if file has changed */
1341214521
){
1341314522
const char *zCreate =
1341414523
"CREATE TABLE IF NOT EXISTS sqlar(\n"
1341514524
" name TEXT PRIMARY KEY, -- name of the file\n"
1341614525
" mode INT, -- access permissions\n"
@@ -13428,26 +14537,28 @@
1342814537
" CASE substr(lsmode(mode),1,1)\n"
1342914538
" WHEN '-' THEN length(data)\n"
1343014539
" WHEN 'd' THEN 0\n"
1343114540
" ELSE -1 END,\n"
1343214541
" sqlar_compress(data)\n"
13433
- " FROM fsdir(%Q,%Q)\n"
13434
- " WHERE lsmode(mode) NOT LIKE '?%%';",
14542
+ " FROM fsdir(%Q,%Q) AS disk\n"
14543
+ " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
14544
+ ,
1343514545
"REPLACE INTO %s(name,mode,mtime,data)\n"
1343614546
" SELECT\n"
1343714547
" %s,\n"
1343814548
" mode,\n"
1343914549
" mtime,\n"
1344014550
" data\n"
13441
- " FROM fsdir(%Q,%Q)\n"
13442
- " WHERE lsmode(mode) NOT LIKE '?%%';"
14551
+ " FROM fsdir(%Q,%Q) AS disk\n"
14552
+ " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
1344314553
};
1344414554
int i; /* For iterating through azFile[] */
1344514555
int rc; /* Return code */
1344614556
const char *zTab = 0; /* SQL table into which to insert */
1344714557
char *zSql;
1344814558
char zTemp[50];
14559
+ char *zExists = 0;
1344914560
1345014561
arExecSql(pAr, "PRAGMA page_size=512");
1345114562
rc = arExecSql(pAr, "SAVEPOINT ar;");
1345214563
if( rc!=SQLITE_OK ) return rc;
1345314564
zTemp[0] = 0;
@@ -13474,14 +14585,25 @@
1347414585
rc = arExecSql(pAr, zDrop);
1347514586
if( rc!=SQLITE_OK ) goto end_ar_transaction;
1347614587
}
1347714588
rc = arExecSql(pAr, zCreate);
1347814589
}
14590
+ if( bOnlyIfChanged ){
14591
+ zExists = sqlite3_mprintf(
14592
+ " AND NOT EXISTS("
14593
+ "SELECT 1 FROM %s AS mem"
14594
+ " WHERE mem.name=disk.name"
14595
+ " AND mem.mtime=disk.mtime"
14596
+ " AND mem.mode=disk.mode)", zTab);
14597
+ }else{
14598
+ zExists = sqlite3_mprintf("");
14599
+ }
14600
+ if( zExists==0 ) rc = SQLITE_NOMEM;
1347914601
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
1348014602
char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
1348114603
pAr->bVerbose ? "shell_putsnl(name)" : "name",
13482
- pAr->azArg[i], pAr->zDir);
14604
+ pAr->azArg[i], pAr->zDir, zExists);
1348314605
rc = arExecSql(pAr, zSql2);
1348414606
sqlite3_free(zSql2);
1348514607
}
1348614608
end_ar_transaction:
1348714609
if( rc!=SQLITE_OK ){
@@ -13492,10 +14614,11 @@
1349214614
zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
1349314615
arExecSql(pAr, zSql);
1349414616
sqlite3_free(zSql);
1349514617
}
1349614618
}
14619
+ sqlite3_free(zExists);
1349714620
return rc;
1349814621
}
1349914622
1350014623
/*
1350114624
** Implementation of ".ar" dot command.
@@ -13530,11 +14653,12 @@
1353014653
}
1353114654
cmd.bZip = 1;
1353214655
}else if( cmd.zFile ){
1353314656
int flags;
1353414657
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
13535
- if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
14658
+ if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
14659
+ || cmd.eCmd==AR_CMD_UPDATE ){
1353614660
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
1353714661
}else{
1353814662
flags = SQLITE_OPEN_READONLY;
1353914663
}
1354014664
cmd.db = 0;
@@ -13567,11 +14691,11 @@
1356714691
cmd.zSrcTable = sqlite3_mprintf("sqlar");
1356814692
}
1356914693
1357014694
switch( cmd.eCmd ){
1357114695
case AR_CMD_CREATE:
13572
- rc = arCreateOrUpdateCommand(&cmd, 0);
14696
+ rc = arCreateOrUpdateCommand(&cmd, 0, 0);
1357314697
break;
1357414698
1357514699
case AR_CMD_EXTRACT:
1357614700
rc = arExtractCommand(&cmd);
1357714701
break;
@@ -13582,13 +14706,17 @@
1358214706
1358314707
case AR_CMD_HELP:
1358414708
arUsage(pState->out);
1358514709
break;
1358614710
14711
+ case AR_CMD_INSERT:
14712
+ rc = arCreateOrUpdateCommand(&cmd, 1, 0);
14713
+ break;
14714
+
1358714715
default:
1358814716
assert( cmd.eCmd==AR_CMD_UPDATE );
13589
- rc = arCreateOrUpdateCommand(&cmd, 1);
14717
+ rc = arCreateOrUpdateCommand(&cmd, 1, 1);
1359014718
break;
1359114719
}
1359214720
}
1359314721
end_ar_command:
1359414722
if( cmd.db!=pState->db ){
@@ -13600,10 +14728,639 @@
1360014728
}
1360114729
/* End of the ".archive" or ".ar" command logic
1360214730
**********************************************************************************/
1360314731
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
1360414732
14733
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
14734
+/*
14735
+** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
14736
+** Otherwise, the SQL statement or statements in zSql are executed using
14737
+** database connection db and the error code written to *pRc before
14738
+** this function returns.
14739
+*/
14740
+static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
14741
+ int rc = *pRc;
14742
+ if( rc==SQLITE_OK ){
14743
+ char *zErr = 0;
14744
+ rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
14745
+ if( rc!=SQLITE_OK ){
14746
+ raw_printf(stderr, "SQL error: %s\n", zErr);
14747
+ }
14748
+ *pRc = rc;
14749
+ }
14750
+}
14751
+
14752
+/*
14753
+** Like shellExec(), except that zFmt is a printf() style format string.
14754
+*/
14755
+static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
14756
+ char *z = 0;
14757
+ if( *pRc==SQLITE_OK ){
14758
+ va_list ap;
14759
+ va_start(ap, zFmt);
14760
+ z = sqlite3_vmprintf(zFmt, ap);
14761
+ va_end(ap);
14762
+ if( z==0 ){
14763
+ *pRc = SQLITE_NOMEM;
14764
+ }else{
14765
+ shellExec(db, pRc, z);
14766
+ }
14767
+ sqlite3_free(z);
14768
+ }
14769
+}
14770
+
14771
+/*
14772
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
14773
+** Otherwise, an attempt is made to allocate, zero and return a pointer
14774
+** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
14775
+** to SQLITE_NOMEM and NULL returned.
14776
+*/
14777
+static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
14778
+ void *pRet = 0;
14779
+ if( *pRc==SQLITE_OK ){
14780
+ pRet = sqlite3_malloc64(nByte);
14781
+ if( pRet==0 ){
14782
+ *pRc = SQLITE_NOMEM;
14783
+ }else{
14784
+ memset(pRet, 0, nByte);
14785
+ }
14786
+ }
14787
+ return pRet;
14788
+}
14789
+
14790
+/*
14791
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
14792
+** Otherwise, zFmt is treated as a printf() style string. The result of
14793
+** formatting it along with any trailing arguments is written into a
14794
+** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
14795
+** It is the responsibility of the caller to eventually free this buffer
14796
+** using a call to sqlite3_free().
14797
+**
14798
+** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
14799
+** pointer returned.
14800
+*/
14801
+static char *shellMPrintf(int *pRc, const char *zFmt, ...){
14802
+ char *z = 0;
14803
+ if( *pRc==SQLITE_OK ){
14804
+ va_list ap;
14805
+ va_start(ap, zFmt);
14806
+ z = sqlite3_vmprintf(zFmt, ap);
14807
+ va_end(ap);
14808
+ if( z==0 ){
14809
+ *pRc = SQLITE_NOMEM;
14810
+ }
14811
+ }
14812
+ return z;
14813
+}
14814
+
14815
+/*
14816
+** When running the ".recover" command, each output table, and the special
14817
+** orphaned row table if it is required, is represented by an instance
14818
+** of the following struct.
14819
+*/
14820
+typedef struct RecoverTable RecoverTable;
14821
+struct RecoverTable {
14822
+ char *zQuoted; /* Quoted version of table name */
14823
+ int nCol; /* Number of columns in table */
14824
+ char **azlCol; /* Array of column lists */
14825
+ int iPk; /* Index of IPK column */
14826
+};
14827
+
14828
+/*
14829
+** Free a RecoverTable object allocated by recoverFindTable() or
14830
+** recoverOrphanTable().
14831
+*/
14832
+static void recoverFreeTable(RecoverTable *pTab){
14833
+ if( pTab ){
14834
+ sqlite3_free(pTab->zQuoted);
14835
+ if( pTab->azlCol ){
14836
+ int i;
14837
+ for(i=0; i<=pTab->nCol; i++){
14838
+ sqlite3_free(pTab->azlCol[i]);
14839
+ }
14840
+ sqlite3_free(pTab->azlCol);
14841
+ }
14842
+ sqlite3_free(pTab);
14843
+ }
14844
+}
14845
+
14846
+/*
14847
+** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
14848
+** Otherwise, it allocates and returns a RecoverTable object based on the
14849
+** final four arguments passed to this function. It is the responsibility
14850
+** of the caller to eventually free the returned object using
14851
+** recoverFreeTable().
14852
+*/
14853
+static RecoverTable *recoverNewTable(
14854
+ int *pRc, /* IN/OUT: Error code */
14855
+ const char *zName, /* Name of table */
14856
+ const char *zSql, /* CREATE TABLE statement */
14857
+ int bIntkey,
14858
+ int nCol
14859
+){
14860
+ sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
14861
+ int rc = *pRc;
14862
+ RecoverTable *pTab = 0;
14863
+
14864
+ pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
14865
+ if( rc==SQLITE_OK ){
14866
+ int nSqlCol = 0;
14867
+ int bSqlIntkey = 0;
14868
+ sqlite3_stmt *pStmt = 0;
14869
+
14870
+ rc = sqlite3_open("", &dbtmp);
14871
+ if( rc==SQLITE_OK ){
14872
+ rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
14873
+ }
14874
+ if( rc==SQLITE_OK ){
14875
+ rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
14876
+ if( rc==SQLITE_ERROR ){
14877
+ rc = SQLITE_OK;
14878
+ goto finished;
14879
+ }
14880
+ }
14881
+ shellPreparePrintf(dbtmp, &rc, &pStmt,
14882
+ "SELECT count(*) FROM pragma_table_info(%Q)", zName
14883
+ );
14884
+ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14885
+ nSqlCol = sqlite3_column_int(pStmt, 0);
14886
+ }
14887
+ shellFinalize(&rc, pStmt);
14888
+
14889
+ if( rc!=SQLITE_OK || nSqlCol<nCol ){
14890
+ goto finished;
14891
+ }
14892
+
14893
+ shellPreparePrintf(dbtmp, &rc, &pStmt,
14894
+ "SELECT ("
14895
+ " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
14896
+ ") FROM sqlite_master WHERE name = %Q", zName
14897
+ );
14898
+ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14899
+ bSqlIntkey = sqlite3_column_int(pStmt, 0);
14900
+ }
14901
+ shellFinalize(&rc, pStmt);
14902
+
14903
+ if( bIntkey==bSqlIntkey ){
14904
+ int i;
14905
+ const char *zPk = "_rowid_";
14906
+ sqlite3_stmt *pPkFinder = 0;
14907
+
14908
+ /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
14909
+ ** set zPk to the name of the PK column, and pTab->iPk to the index
14910
+ ** of the column, where columns are 0-numbered from left to right.
14911
+ ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
14912
+ ** leave zPk as "_rowid_" and pTab->iPk at -2. */
14913
+ pTab->iPk = -2;
14914
+ if( bIntkey ){
14915
+ shellPreparePrintf(dbtmp, &rc, &pPkFinder,
14916
+ "SELECT cid, name FROM pragma_table_info(%Q) "
14917
+ " WHERE pk=1 AND type='integer' COLLATE nocase"
14918
+ " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
14919
+ , zName, zName
14920
+ );
14921
+ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
14922
+ pTab->iPk = sqlite3_column_int(pPkFinder, 0);
14923
+ zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
14924
+ }
14925
+ }
14926
+
14927
+ pTab->zQuoted = shellMPrintf(&rc, "%Q", zName);
14928
+ pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
14929
+ pTab->nCol = nSqlCol;
14930
+
14931
+ if( bIntkey ){
14932
+ pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
14933
+ }else{
14934
+ pTab->azlCol[0] = shellMPrintf(&rc, "");
14935
+ }
14936
+ i = 1;
14937
+ shellPreparePrintf(dbtmp, &rc, &pStmt,
14938
+ "SELECT %Q || group_concat(name, ', ') "
14939
+ " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
14940
+ "FROM pragma_table_info(%Q)",
14941
+ bIntkey ? ", " : "", pTab->iPk,
14942
+ bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
14943
+ zName
14944
+ );
14945
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14946
+ const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
14947
+ pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
14948
+ i++;
14949
+ }
14950
+ shellFinalize(&rc, pStmt);
14951
+
14952
+ shellFinalize(&rc, pPkFinder);
14953
+ }
14954
+ }
14955
+
14956
+ finished:
14957
+ sqlite3_close(dbtmp);
14958
+ *pRc = rc;
14959
+ if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
14960
+ recoverFreeTable(pTab);
14961
+ pTab = 0;
14962
+ }
14963
+ return pTab;
14964
+}
14965
+
14966
+/*
14967
+** This function is called to search the schema recovered from the
14968
+** sqlite_master table of the (possibly) corrupt database as part
14969
+** of a ".recover" command. Specifically, for a table with root page
14970
+** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
14971
+** table must be a WITHOUT ROWID table, or if non-zero, not one of
14972
+** those.
14973
+**
14974
+** If a table is found, a (RecoverTable*) object is returned. Or, if
14975
+** no such table is found, but bIntkey is false and iRoot is the
14976
+** root page of an index in the recovered schema, then (*pbNoop) is
14977
+** set to true and NULL returned. Or, if there is no such table or
14978
+** index, NULL is returned and (*pbNoop) set to 0, indicating that
14979
+** the caller should write data to the orphans table.
14980
+*/
14981
+static RecoverTable *recoverFindTable(
14982
+ ShellState *pState, /* Shell state object */
14983
+ int *pRc, /* IN/OUT: Error code */
14984
+ int iRoot, /* Root page of table */
14985
+ int bIntkey, /* True for an intkey table */
14986
+ int nCol, /* Number of columns in table */
14987
+ int *pbNoop /* OUT: True if iRoot is root of index */
14988
+){
14989
+ sqlite3_stmt *pStmt = 0;
14990
+ RecoverTable *pRet = 0;
14991
+ int bNoop = 0;
14992
+ const char *zSql = 0;
14993
+ const char *zName = 0;
14994
+
14995
+ /* Search the recovered schema for an object with root page iRoot. */
14996
+ shellPreparePrintf(pState->db, pRc, &pStmt,
14997
+ "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
14998
+ );
14999
+ while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15000
+ const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
15001
+ if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
15002
+ bNoop = 1;
15003
+ break;
15004
+ }
15005
+ if( sqlite3_stricmp(zType, "table")==0 ){
15006
+ zName = (const char*)sqlite3_column_text(pStmt, 1);
15007
+ zSql = (const char*)sqlite3_column_text(pStmt, 2);
15008
+ pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
15009
+ break;
15010
+ }
15011
+ }
15012
+
15013
+ shellFinalize(pRc, pStmt);
15014
+ *pbNoop = bNoop;
15015
+ return pRet;
15016
+}
15017
+
15018
+/*
15019
+** Return a RecoverTable object representing the orphans table.
15020
+*/
15021
+static RecoverTable *recoverOrphanTable(
15022
+ ShellState *pState, /* Shell state object */
15023
+ int *pRc, /* IN/OUT: Error code */
15024
+ const char *zLostAndFound, /* Base name for orphans table */
15025
+ int nCol /* Number of user data columns */
15026
+){
15027
+ RecoverTable *pTab = 0;
15028
+ if( nCol>=0 && *pRc==SQLITE_OK ){
15029
+ int i;
15030
+
15031
+ /* This block determines the name of the orphan table. The prefered
15032
+ ** name is zLostAndFound. But if that clashes with another name
15033
+ ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
15034
+ ** and so on until a non-clashing name is found. */
15035
+ int iTab = 0;
15036
+ char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
15037
+ sqlite3_stmt *pTest = 0;
15038
+ shellPrepare(pState->db, pRc,
15039
+ "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
15040
+ );
15041
+ if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
15042
+ while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
15043
+ shellReset(pRc, pTest);
15044
+ sqlite3_free(zTab);
15045
+ zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
15046
+ sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
15047
+ }
15048
+ shellFinalize(pRc, pTest);
15049
+
15050
+ pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
15051
+ if( pTab ){
15052
+ pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab);
15053
+ pTab->nCol = nCol;
15054
+ pTab->iPk = -2;
15055
+ if( nCol>0 ){
15056
+ pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
15057
+ if( pTab->azlCol ){
15058
+ pTab->azlCol[nCol] = shellMPrintf(pRc, "");
15059
+ for(i=nCol-1; i>=0; i--){
15060
+ pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
15061
+ }
15062
+ }
15063
+ }
15064
+
15065
+ if( *pRc!=SQLITE_OK ){
15066
+ recoverFreeTable(pTab);
15067
+ pTab = 0;
15068
+ }else{
15069
+ raw_printf(pState->out,
15070
+ "CREATE TABLE %s(rootpgno INTEGER, "
15071
+ "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
15072
+ );
15073
+ for(i=0; i<nCol; i++){
15074
+ raw_printf(pState->out, ", c%d", i);
15075
+ }
15076
+ raw_printf(pState->out, ");\n");
15077
+ }
15078
+ }
15079
+ sqlite3_free(zTab);
15080
+ }
15081
+ return pTab;
15082
+}
15083
+
15084
+/*
15085
+** This function is called to recover data from the database. A script
15086
+** to construct a new database containing all recovered data is output
15087
+** on stream pState->out.
15088
+*/
15089
+static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
15090
+ int rc = SQLITE_OK;
15091
+ sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
15092
+ sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
15093
+ sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
15094
+ const char *zRecoveryDb = ""; /* Name of "recovery" database */
15095
+ const char *zLostAndFound = "lost_and_found";
15096
+ int i;
15097
+ int nOrphan = -1;
15098
+ RecoverTable *pOrphan = 0;
15099
+
15100
+ int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
15101
+ for(i=1; i<nArg; i++){
15102
+ char *z = azArg[i];
15103
+ int n;
15104
+ if( z[0]=='-' && z[1]=='-' ) z++;
15105
+ n = strlen(z);
15106
+ if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
15107
+ bFreelist = 0;
15108
+ }else
15109
+ if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
15110
+ i++;
15111
+ zRecoveryDb = azArg[i];
15112
+ }else
15113
+ if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
15114
+ i++;
15115
+ zLostAndFound = azArg[i];
15116
+ }
15117
+ else{
15118
+ raw_printf(stderr, "unexpected option: %s\n", azArg[i]);
15119
+ raw_printf(stderr, "options are:\n");
15120
+ raw_printf(stderr, " --freelist-corrupt\n");
15121
+ raw_printf(stderr, " --recovery-db DATABASE\n");
15122
+ raw_printf(stderr, " --lost-and-found TABLE-NAME\n");
15123
+ return 1;
15124
+ }
15125
+ }
15126
+
15127
+ shellExecPrintf(pState->db, &rc,
15128
+ /* Attach an in-memory database named 'recovery'. Create an indexed
15129
+ ** cache of the sqlite_dbptr virtual table. */
15130
+ "ATTACH %Q AS recovery;"
15131
+ "DROP TABLE IF EXISTS recovery.dbptr;"
15132
+ "DROP TABLE IF EXISTS recovery.freelist;"
15133
+ "DROP TABLE IF EXISTS recovery.map;"
15134
+ "DROP TABLE IF EXISTS recovery.schema;"
15135
+ "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
15136
+ );
15137
+
15138
+ if( bFreelist ){
15139
+ shellExec(pState->db, &rc,
15140
+ "WITH trunk(pgno) AS ("
15141
+ " SELECT shell_int32("
15142
+ " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
15143
+ " WHERE x>0"
15144
+ " UNION"
15145
+ " SELECT shell_int32("
15146
+ " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
15147
+ " FROM trunk WHERE x>0"
15148
+ "),"
15149
+ "freelist(data, n, freepgno) AS ("
15150
+ " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
15151
+ " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
15152
+ " UNION ALL"
15153
+ " SELECT data, n-1, shell_int32(data, 2+n) "
15154
+ " FROM freelist WHERE n>=0"
15155
+ ")"
15156
+ "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
15157
+ );
15158
+ }
15159
+
15160
+ shellExec(pState->db, &rc,
15161
+ "CREATE TABLE recovery.dbptr("
15162
+ " pgno, child, PRIMARY KEY(child, pgno)"
15163
+ ") WITHOUT ROWID;"
15164
+ "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
15165
+ " SELECT * FROM sqlite_dbptr"
15166
+ " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
15167
+
15168
+ /* Delete any pointer to page 1. This ensures that page 1 is considered
15169
+ ** a root page, regardless of how corrupt the db is. */
15170
+ "DELETE FROM recovery.dbptr WHERE child = 1;"
15171
+
15172
+ /* Delete all pointers to any pages that have more than one pointer
15173
+ ** to them. Such pages will be treated as root pages when recovering
15174
+ ** data. */
15175
+ "DELETE FROM recovery.dbptr WHERE child IN ("
15176
+ " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
15177
+ ");"
15178
+
15179
+ /* Create the "map" table that will (eventually) contain instructions
15180
+ ** for dealing with each page in the db that contains one or more
15181
+ ** records. */
15182
+ "CREATE TABLE recovery.map("
15183
+ "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
15184
+ ");"
15185
+
15186
+ /* Populate table [map]. If there are circular loops of pages in the
15187
+ ** database, the following adds all pages in such a loop to the map
15188
+ ** as individual root pages. This could be handled better. */
15189
+ "WITH pages(i, maxlen) AS ("
15190
+ " SELECT page_count, ("
15191
+ " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
15192
+ " ) FROM pragma_page_count WHERE page_count>0"
15193
+ " UNION ALL"
15194
+ " SELECT i-1, ("
15195
+ " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
15196
+ " ) FROM pages WHERE i>=2"
15197
+ ")"
15198
+ "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
15199
+ " SELECT i, maxlen, NULL, ("
15200
+ " WITH p(orig, pgno, parent) AS ("
15201
+ " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
15202
+ " UNION "
15203
+ " SELECT i, p.parent, "
15204
+ " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
15205
+ " )"
15206
+ " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
15207
+ ") "
15208
+ "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"
15209
+ "UPDATE recovery.map AS o SET intkey = ("
15210
+ " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
15211
+ ");"
15212
+
15213
+ /* Extract data from page 1 and any linked pages into table
15214
+ ** recovery.schema. With the same schema as an sqlite_master table. */
15215
+ "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
15216
+ "INSERT INTO recovery.schema SELECT "
15217
+ " max(CASE WHEN field=0 THEN value ELSE NULL END),"
15218
+ " max(CASE WHEN field=1 THEN value ELSE NULL END),"
15219
+ " max(CASE WHEN field=2 THEN value ELSE NULL END),"
15220
+ " max(CASE WHEN field=3 THEN value ELSE NULL END),"
15221
+ " max(CASE WHEN field=4 THEN value ELSE NULL END)"
15222
+ "FROM sqlite_dbdata WHERE pgno IN ("
15223
+ " SELECT pgno FROM recovery.map WHERE root=1"
15224
+ ")"
15225
+ "GROUP BY pgno, cell;"
15226
+ "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
15227
+ );
15228
+
15229
+ /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
15230
+ ** CREATE TABLE statements that extracted from the existing schema. */
15231
+ if( rc==SQLITE_OK ){
15232
+ sqlite3_stmt *pStmt = 0;
15233
+ raw_printf(pState->out, "BEGIN;\n");
15234
+ raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
15235
+ shellPrepare(pState->db, &rc,
15236
+ "SELECT sql FROM recovery.schema "
15237
+ "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
15238
+ );
15239
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15240
+ const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
15241
+ raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
15242
+ &zCreateTable[12]
15243
+ );
15244
+ }
15245
+ shellFinalize(&rc, pStmt);
15246
+ }
15247
+
15248
+ /* Figure out if an orphan table will be required. And if so, how many
15249
+ ** user columns it should contain */
15250
+ shellPrepare(pState->db, &rc,
15251
+ "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
15252
+ , &pLoop
15253
+ );
15254
+ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
15255
+ nOrphan = sqlite3_column_int(pLoop, 0);
15256
+ }
15257
+ shellFinalize(&rc, pLoop);
15258
+ pLoop = 0;
15259
+
15260
+ shellPrepare(pState->db, &rc,
15261
+ "SELECT pgno FROM recovery.map WHERE root=?", &pPages
15262
+ );
15263
+ shellPrepare(pState->db, &rc,
15264
+ "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')"
15265
+ "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
15266
+ "GROUP BY cell", &pCells
15267
+ );
15268
+
15269
+ /* Loop through each root page. */
15270
+ shellPrepare(pState->db, &rc,
15271
+ "SELECT root, intkey, max(maxlen) FROM recovery.map"
15272
+ " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
15273
+ " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
15274
+ ")", &pLoop
15275
+ );
15276
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
15277
+ int iRoot = sqlite3_column_int(pLoop, 0);
15278
+ int bIntkey = sqlite3_column_int(pLoop, 1);
15279
+ int nCol = sqlite3_column_int(pLoop, 2);
15280
+ int bNoop = 0;
15281
+ RecoverTable *pTab;
15282
+
15283
+ pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
15284
+ if( bNoop || rc ) continue;
15285
+ if( pTab==0 ){
15286
+ if( pOrphan==0 ){
15287
+ pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
15288
+ }
15289
+ pTab = pOrphan;
15290
+ if( pTab==0 ) break;
15291
+ }
15292
+
15293
+ if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){
15294
+ raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
15295
+ }
15296
+ sqlite3_bind_int(pPages, 1, iRoot);
15297
+ sqlite3_bind_int(pCells, 2, pTab->iPk);
15298
+
15299
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
15300
+ int iPgno = sqlite3_column_int(pPages, 0);
15301
+ sqlite3_bind_int(pCells, 1, iPgno);
15302
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
15303
+ int nField = sqlite3_column_int(pCells, 0);
15304
+ const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
15305
+
15306
+ nField = nField+1;
15307
+ if( pTab==pOrphan ){
15308
+ raw_printf(pState->out,
15309
+ "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
15310
+ pTab->zQuoted, iRoot, iPgno, nField,
15311
+ bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField]
15312
+ );
15313
+ }else{
15314
+ raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
15315
+ pTab->zQuoted, pTab->azlCol[nField], zVal
15316
+ );
15317
+ }
15318
+ }
15319
+ shellReset(&rc, pCells);
15320
+ }
15321
+ shellReset(&rc, pPages);
15322
+ if( pTab!=pOrphan ) recoverFreeTable(pTab);
15323
+ }
15324
+ shellFinalize(&rc, pLoop);
15325
+ shellFinalize(&rc, pPages);
15326
+ shellFinalize(&rc, pCells);
15327
+ recoverFreeTable(pOrphan);
15328
+
15329
+ /* The rest of the schema */
15330
+ if( rc==SQLITE_OK ){
15331
+ sqlite3_stmt *pStmt = 0;
15332
+ shellPrepare(pState->db, &rc,
15333
+ "SELECT sql, name FROM recovery.schema "
15334
+ "WHERE sql NOT LIKE 'create table%'", &pStmt
15335
+ );
15336
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15337
+ const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
15338
+ if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
15339
+ const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
15340
+ char *zPrint = shellMPrintf(&rc,
15341
+ "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)",
15342
+ zName, zName, zSql
15343
+ );
15344
+ raw_printf(pState->out, "%s;\n", zPrint);
15345
+ sqlite3_free(zPrint);
15346
+ }else{
15347
+ raw_printf(pState->out, "%s;\n", zSql);
15348
+ }
15349
+ }
15350
+ shellFinalize(&rc, pStmt);
15351
+ }
15352
+
15353
+ if( rc==SQLITE_OK ){
15354
+ raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
15355
+ raw_printf(pState->out, "COMMIT;\n");
15356
+ }
15357
+ sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
15358
+ return rc;
15359
+}
15360
+#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
15361
+
1360515362
1360615363
/*
1360715364
** If an input line begins with "." then invoke this routine to
1360815365
** process that line.
1360915366
**
@@ -13887,10 +15644,17 @@
1388715644
1388815645
if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
1388915646
rc = shell_dbinfo_command(p, nArg, azArg);
1389015647
}else
1389115648
15649
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
15650
+ if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
15651
+ open_db(p, 0);
15652
+ rc = recoverDatabaseCmd(p, nArg, azArg);
15653
+ }else
15654
+#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
15655
+
1389215656
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
1389315657
const char *zLike = 0;
1389415658
int i;
1389515659
int savedShowHeader = p->showHeader;
1389615660
int savedShellFlags = p->shellFlgs;
@@ -13924,11 +15688,13 @@
1392415688
goto meta_command_exit;
1392515689
}else{
1392615690
zLike = azArg[i];
1392715691
}
1392815692
}
15693
+
1392915694
open_db(p, 0);
15695
+
1393015696
/* When playing back a "dump", the content might appear in an order
1393115697
** which causes immediate foreign key constraints to be violated.
1393215698
** So disable foreign-key constraint enforcement to prevent problems. */
1393315699
raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
1393415700
raw_printf(p->out, "BEGIN TRANSACTION;\n");
@@ -13972,11 +15738,11 @@
1397215738
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
1397315739
p->writableSchema = 0;
1397415740
}
1397515741
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
1397615742
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
13977
- raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
15743
+ raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
1397815744
p->showHeader = savedShowHeader;
1397915745
p->shellFlgs = savedShellFlags;
1398015746
}else
1398115747
1398215748
if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
@@ -14708,10 +16474,118 @@
1470816474
} else {
1470916475
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
1471016476
}
1471116477
}
1471216478
}else
16479
+
16480
+ if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
16481
+ open_db(p,0);
16482
+ if( nArg<=1 ) goto parameter_syntax_error;
16483
+
16484
+ /* .parameter clear
16485
+ ** Clear all bind parameters by dropping the TEMP table that holds them.
16486
+ */
16487
+ if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
16488
+ int wrSchema = 0;
16489
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
16490
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
16491
+ sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
16492
+ 0, 0, 0);
16493
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
16494
+ }else
16495
+
16496
+ /* .parameter list
16497
+ ** List all bind parameters.
16498
+ */
16499
+ if( nArg==2 && strcmp(azArg[1],"list")==0 ){
16500
+ sqlite3_stmt *pStmt = 0;
16501
+ int rx;
16502
+ int len = 0;
16503
+ rx = sqlite3_prepare_v2(p->db,
16504
+ "SELECT max(length(key)) "
16505
+ "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
16506
+ if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
16507
+ len = sqlite3_column_int(pStmt, 0);
16508
+ if( len>40 ) len = 40;
16509
+ }
16510
+ sqlite3_finalize(pStmt);
16511
+ pStmt = 0;
16512
+ if( len ){
16513
+ rx = sqlite3_prepare_v2(p->db,
16514
+ "SELECT key, quote(value) "
16515
+ "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
16516
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
16517
+ utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
16518
+ sqlite3_column_text(pStmt,1));
16519
+ }
16520
+ sqlite3_finalize(pStmt);
16521
+ }
16522
+ }else
16523
+
16524
+ /* .parameter init
16525
+ ** Make sure the TEMP table used to hold bind parameters exists.
16526
+ ** Create it if necessary.
16527
+ */
16528
+ if( nArg==2 && strcmp(azArg[1],"init")==0 ){
16529
+ bind_table_init(p);
16530
+ }else
16531
+
16532
+ /* .parameter set NAME VALUE
16533
+ ** Set or reset a bind parameter. NAME should be the full parameter
16534
+ ** name exactly as it appears in the query. (ex: $abc, @def). The
16535
+ ** VALUE can be in either SQL literal notation, or if not it will be
16536
+ ** understood to be a text string.
16537
+ */
16538
+ if( nArg==4 && strcmp(azArg[1],"set")==0 ){
16539
+ int rx;
16540
+ char *zSql;
16541
+ sqlite3_stmt *pStmt;
16542
+ const char *zKey = azArg[2];
16543
+ const char *zValue = azArg[3];
16544
+ bind_table_init(p);
16545
+ zSql = sqlite3_mprintf(
16546
+ "REPLACE INTO temp.sqlite_parameters(key,value)"
16547
+ "VALUES(%Q,%s);", zKey, zValue);
16548
+ if( zSql==0 ) shell_out_of_memory();
16549
+ pStmt = 0;
16550
+ rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16551
+ sqlite3_free(zSql);
16552
+ if( rx!=SQLITE_OK ){
16553
+ sqlite3_finalize(pStmt);
16554
+ pStmt = 0;
16555
+ zSql = sqlite3_mprintf(
16556
+ "REPLACE INTO temp.sqlite_parameters(key,value)"
16557
+ "VALUES(%Q,%Q);", zKey, zValue);
16558
+ if( zSql==0 ) shell_out_of_memory();
16559
+ rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16560
+ sqlite3_free(zSql);
16561
+ if( rx!=SQLITE_OK ){
16562
+ utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
16563
+ sqlite3_finalize(pStmt);
16564
+ pStmt = 0;
16565
+ rc = 1;
16566
+ }
16567
+ }
16568
+ sqlite3_step(pStmt);
16569
+ sqlite3_finalize(pStmt);
16570
+ }else
16571
+
16572
+ /* .parameter unset NAME
16573
+ ** Remove the NAME binding from the parameter binding table, if it
16574
+ ** exists.
16575
+ */
16576
+ if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
16577
+ char *zSql = sqlite3_mprintf(
16578
+ "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
16579
+ if( zSql==0 ) shell_out_of_memory();
16580
+ sqlite3_exec(p->db, zSql, 0, 0, 0);
16581
+ sqlite3_free(zSql);
16582
+ }else
16583
+ /* If no command name matches, show a syntax error */
16584
+ parameter_syntax_error:
16585
+ showHelp(p->out, "parameter");
16586
+ }else
1471316587
1471416588
if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
1471516589
int i;
1471616590
for(i=1; i<nArg; i++){
1471716591
if( i>1 ) raw_printf(p->out, " ");
1471816592
--- src/shell.c
+++ src/shell.c
@@ -981,10 +981,11 @@
981
982 /*
983 ** We need several support functions from the SQLite core.
984 */
985
 
986
987 /*
988 ** We need several things from the ANSI and MSVCRT headers.
989 */
990
@@ -1334,10 +1335,11 @@
1334 **
1335 ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
1336 ** is used. If SIZE is included it must be one of the integers 224, 256,
1337 ** 384, or 512, to determine SHA3 hash variant that is computed.
1338 */
 
1339 SQLITE_EXTENSION_INIT1
1340 #include <assert.h>
1341 #include <string.h>
1342 #include <stdarg.h>
1343 /* typedef sqlite3_uint64 u64; */
@@ -2097,10 +2099,11 @@
2097 ** If a non-NULL value is specified for the optional $dir parameter and
2098 ** $path is a relative path, then $path is interpreted relative to $dir.
2099 ** And the paths returned in the "name" column of the table are also
2100 ** relative to directory $dir.
2101 */
 
2102 SQLITE_EXTENSION_INIT1
2103 #include <stdio.h>
2104 #include <string.h>
2105 #include <assert.h>
2106
@@ -2175,17 +2178,17 @@
2175 if( nIn>mxBlob ){
2176 sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
2177 fclose(in);
2178 return;
2179 }
2180 pBuf = sqlite3_malloc64( nIn );
2181 if( pBuf==0 ){
2182 sqlite3_result_error_nomem(ctx);
2183 fclose(in);
2184 return;
2185 }
2186 if( 1==fread(pBuf, nIn, 1, in) ){
2187 sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
2188 }else{
2189 sqlite3_result_error_code(ctx, SQLITE_IOERR);
2190 sqlite3_free(pBuf);
2191 }
@@ -2316,19 +2319,19 @@
2316
2317 /*
2318 ** Argument zFile is the name of a file that will be created and/or written
2319 ** by SQL function writefile(). This function ensures that the directory
2320 ** zFile will be written to exists, creating it if required. The permissions
2321 ** for any path components created by this function are set to (mode&0777).
 
2322 **
2323 ** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
2324 ** SQLITE_OK is returned if the directory is successfully created, or
2325 ** SQLITE_ERROR otherwise.
2326 */
2327 static int makeDirectory(
2328 const char *zFile,
2329 mode_t mode
2330 ){
2331 char *zCopy = sqlite3_mprintf("%s", zFile);
2332 int rc = SQLITE_OK;
2333
2334 if( zCopy==0 ){
@@ -2345,11 +2348,11 @@
2345 if( i==nCopy ) break;
2346 zCopy[i] = '\0';
2347
2348 rc2 = fileStat(zCopy, &sStat);
2349 if( rc2!=0 ){
2350 if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
2351 }else{
2352 if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
2353 }
2354 zCopy[i] = '/';
2355 i++;
@@ -2503,11 +2506,11 @@
2503 mtime = sqlite3_value_int64(argv[3]);
2504 }
2505
2506 res = writeFile(context, zFile, argv[1], mode, mtime);
2507 if( res==1 && errno==ENOENT ){
2508 if( makeDirectory(zFile, mode)==SQLITE_OK ){
2509 res = writeFile(context, zFile, argv[1], mode, mtime);
2510 }
2511 }
2512
2513 if( argc>2 && res!=0 ){
@@ -3054,10 +3057,11 @@
3054 ** This virtual table operates at the speed of human typing, and so there
3055 ** is no attempt to make it fast. Even a slow implementation will be much
3056 ** faster than any human can type.
3057 **
3058 */
 
3059 SQLITE_EXTENSION_INIT1
3060 #include <assert.h>
3061 #include <string.h>
3062 #include <ctype.h>
3063
@@ -3570,10 +3574,11 @@
3570 ** database in a separate file.
3571 **
3572 ** If the file being opened is not an appended database, then this shim is
3573 ** a pass-through into the default underlying VFS.
3574 **/
 
3575 SQLITE_EXTENSION_INIT1
3576 #include <string.h>
3577 #include <assert.h>
3578
3579 /* The append mark at the end of the database is:
@@ -4226,10 +4231,11 @@
4226 ** * No support for encryption
4227 ** * No support for ZIP archives spanning multiple files
4228 ** * No support for zip64 extensions
4229 ** * Only the "inflate/deflate" (zlib) compression method is supported
4230 */
 
4231 SQLITE_EXTENSION_INIT1
4232 #include <stdio.h>
4233 #include <string.h>
4234 #include <assert.h>
4235
@@ -6396,10 +6402,11 @@
6396 **
6397 ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
6398 ** for working with sqlar archives and used by the shell tool's built-in
6399 ** sqlar support.
6400 */
 
6401 SQLITE_EXTENSION_INIT1
6402 #include <zlib.h>
6403
6404 /*
6405 ** Implementation of the "sqlar_compress(X)" SQL function.
@@ -6518,10 +6525,11 @@
6518 **
6519 *************************************************************************
6520 */
6521
6522
 
6523
6524 typedef struct sqlite3expert sqlite3expert;
6525
6526 /*
6527 ** Create a new sqlite3expert object.
@@ -6686,10 +6694,11 @@
6686 ** May you find forgiveness for yourself and forgive others.
6687 ** May you share freely, never taking more than you give.
6688 **
6689 *************************************************************************
6690 */
 
6691 #include <assert.h>
6692 #include <string.h>
6693 #include <stdio.h>
6694
6695 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -8628,10 +8637,867 @@
8628 }
8629
8630 #endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8631
8632 /************************* End ../ext/expert/sqlite3expert.c ********************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8633
8634 #if defined(SQLITE_ENABLE_SESSION)
8635 /*
8636 ** State information for a single open session
8637 */
@@ -9358,10 +10224,12 @@
9358 **
9359 ** This routine converts some CREATE TABLE statements for shadow tables
9360 ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
9361 */
9362 static void printSchemaLine(FILE *out, const char *z, const char *zTail){
 
 
9363 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
9364 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
9365 }else{
9366 utf8_printf(out, "%s%s", z, zTail);
9367 }
@@ -10427,10 +11295,70 @@
10427 #endif
10428 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
10429 sqlite3WhereTrace = savedWhereTrace;
10430 #endif
10431 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10432
10433 /*
10434 ** Run a prepared statement
10435 */
10436 static void exec_prepared_stmt(
@@ -10680,11 +11608,11 @@
10680 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
10681 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
10682 }
10683
10684 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
10685 if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
10686 sqlite3_stmt *pExplain;
10687 char *zEQP;
10688 int triggerEQP = 0;
10689 disable_debug_trace_modes();
10690 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
@@ -10729,17 +11657,14 @@
10729 }
10730
10731 if( pArg ){
10732 pArg->cMode = pArg->mode;
10733 if( pArg->autoExplain ){
10734 if( sqlite3_column_count(pStmt)==8
10735 && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
10736 ){
10737 pArg->cMode = MODE_Explain;
10738 }
10739 if( sqlite3_column_count(pStmt)==4
10740 && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){
10741 pArg->cMode = MODE_EQP;
10742 }
10743 }
10744
10745 /* If the shell is currently in ".explain" mode, gather the extra
@@ -10747,10 +11672,11 @@
10747 if( pArg->cMode==MODE_Explain ){
10748 explain_data_prepare(pArg, pStmt);
10749 }
10750 }
10751
 
10752 exec_prepared_stmt(pArg, pStmt);
10753 explain_data_delete(pArg);
10754 eqp_render(pArg);
10755
10756 /* print usage stats if stats on */
@@ -11076,11 +12002,12 @@
11076 static const char *(azHelp[]) = {
11077 #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
11078 ".archive ... Manage SQL archives",
11079 " Each command must have exactly one of the following options:",
11080 " -c, --create Create a new archive",
11081 " -u, --update Update or add files to an existing archive",
 
11082 " -t, --list List contents of archive",
11083 " -x, --extract Extract files from archive",
11084 " Optional arguments:",
11085 " -v, --verbose Print each filename as it is processed",
11086 " -f FILE, --file FILE Operate on archive FILE (default is current db)",
@@ -11111,11 +12038,11 @@
11111 ".dbinfo ?DB? Show status information about the database",
11112 ".dump ?TABLE? ... Render all database content as SQL",
11113 " Options:",
11114 " --preserve-rowids Include ROWID values in the output",
11115 " --newlines Allow unescaped newline characters in output",
11116 " TABLE is LIKE pattern for the tables to dump",
11117 ".echo on|off Turn command echo on or off",
11118 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
11119 " Other Modes:",
11120 #ifdef SQLITE_DEBUG
11121 " test Show raw EXPLAIN QUERY PLAN output",
@@ -11178,10 +12105,17 @@
11178 " --new Initialize FILE to an empty database",
11179 " --readonly Open FILE readonly",
11180 " --zip FILE is a ZIP archive",
11181 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
11182 " If FILE begins with '|' then open it as a pipe.",
 
 
 
 
 
 
 
11183 ".print STRING... Print literal STRING",
11184 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
11185 ".progress N Invoke progress handler after every N opcodes",
11186 " --limit N Interrupt after N progress callbacks",
11187 " --once Do no more than one progress interrupt",
@@ -11189,10 +12123,13 @@
11189 " --reset Reset the count for each input and interrupt",
11190 #endif
11191 ".prompt MAIN CONTINUE Replace the standard prompts",
11192 ".quit Exit this program",
11193 ".read FILE Read input from FILE",
 
 
 
11194 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
11195 ".save FILE Write in-memory database into FILE",
11196 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
11197 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
11198 " Options:",
@@ -11473,11 +12410,11 @@
11473 int pgsz = 0;
11474 int iOffset = 0;
11475 int j, k;
11476 int rc;
11477 FILE *in;
11478 unsigned char x[16];
11479 char zLine[1000];
11480 if( p->zDbFilename ){
11481 in = fopen(p->zDbFilename, "r");
11482 if( in==0 ){
11483 utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
@@ -11485,18 +12422,19 @@
11485 }
11486 nLine = 0;
11487 }else{
11488 in = p->in;
11489 nLine = p->lineno;
 
11490 }
11491 *pnData = 0;
11492 nLine++;
11493 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
11494 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
11495 if( rc!=2 ) goto readHexDb_error;
11496 if( n<=0 ) goto readHexDb_error;
11497 a = sqlite3_malloc( n );
11498 if( a==0 ){
11499 utf8_printf(stderr, "Out of memory!\n");
11500 goto readHexDb_error;
11501 }
11502 memset(a, 0, n);
@@ -11511,18 +12449,18 @@
11511 continue;
11512 }
11513 if( strncmp(zLine, "| end ", 6)==0 ){
11514 break;
11515 }
11516 rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
11517 " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
11518 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
11519 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
11520 if( rc==17 ){
11521 k = iOffset+j;
11522 if( k+16<=n ){
11523 memcpy(a+k, x, 16);
 
11524 }
11525 }
11526 }
11527 *pnData = n;
11528 if( in!=p->in ){
@@ -11531,11 +12469,11 @@
11531 p->lineno = nLine;
11532 }
11533 return a;
11534
11535 readHexDb_error:
11536 if( in!=stdin ){
11537 fclose(in);
11538 }else{
11539 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
11540 nLine++;
11541 if(strncmp(zLine, "| end ", 6)==0 ) break;
@@ -11545,10 +12483,131 @@
11545 sqlite3_free(a);
11546 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
11547 return 0;
11548 }
11549 #endif /* SQLITE_ENABLE_DESERIALIZE */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11550
11551 /* Flags for open_db().
11552 **
11553 ** The default behavior of open_db() is to exit(1) if the database fails to
11554 ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
@@ -11614,10 +12673,13 @@
11614 sqlite3_enable_load_extension(p->db, 1);
11615 #endif
11616 sqlite3_fileio_init(p->db, 0, 0);
11617 sqlite3_shathree_init(p->db, 0, 0);
11618 sqlite3_completion_init(p->db, 0, 0);
 
 
 
11619 #ifdef SQLITE_HAVE_ZLIB
11620 sqlite3_zipfile_init(p->db, 0, 0);
11621 sqlite3_sqlar_init(p->db, 0, 0);
11622 #endif
11623 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
@@ -11624,10 +12686,14 @@
11624 shellAddSchemaName, 0, 0);
11625 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
11626 shellModuleSchema, 0, 0);
11627 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
11628 shellPutsFunc, 0, 0);
 
 
 
 
11629 #ifndef SQLITE_NOHAVE_SYSTEM
11630 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
11631 editFunc, 0, 0);
11632 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
11633 editFunc, 0, 0);
@@ -11647,11 +12713,10 @@
11647 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
11648 aData = (unsigned char*)readFile(p->zDbFilename, &nData);
11649 }else{
11650 aData = readHexDb(p, &nData);
11651 if( aData==0 ){
11652 utf8_printf(stderr, "Error in hexdb input\n");
11653 return;
11654 }
11655 }
11656 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
11657 SQLITE_DESERIALIZE_RESIZEABLE |
@@ -12390,20 +13455,31 @@
12390 { "number of views:",
12391 "SELECT count(*) FROM %s WHERE type='view'" },
12392 { "schema size:",
12393 "SELECT total(length(sql)) FROM %s" },
12394 };
12395 int i;
12396 unsigned iDataVersion;
12397 char *zSchemaTab;
12398 char *zDb = nArg>=2 ? azArg[1] : "main";
12399 sqlite3_stmt *pStmt = 0;
12400 unsigned char aHdr[100];
12401 open_db(p, 0);
12402 if( p->db==0 ) return 1;
12403 sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
12404 -1, &pStmt, 0);
 
 
 
 
 
 
 
 
 
 
 
12405 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
12406 if( sqlite3_step(pStmt)==SQLITE_ROW
12407 && sqlite3_column_bytes(pStmt,0)>100
12408 ){
12409 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
@@ -12867,14 +13943,11 @@
12867 raw_printf(stderr, "Where sub-commands are:\n");
12868 raw_printf(stderr, " fkey-indexes\n");
12869 return SQLITE_ERROR;
12870 }
12871
12872 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
12873 /*********************************************************************************
12874 ** The ".archive" or ".ar" command.
12875 */
12876 static void shellPrepare(
12877 sqlite3 *db,
12878 int *pRc,
12879 const char *zSql,
12880 sqlite3_stmt **ppStmt
@@ -12889,11 +13962,18 @@
12889 *pRc = rc;
12890 }
12891 }
12892 }
12893
12894 static void shellPreparePrintf(
 
 
 
 
 
 
 
12895 sqlite3 *db,
12896 int *pRc,
12897 sqlite3_stmt **ppStmt,
12898 const char *zFmt,
12899 ...
@@ -12912,11 +13992,17 @@
12912 sqlite3_free(z);
12913 }
12914 }
12915 }
12916
12917 static void shellFinalize(
 
 
 
 
 
 
12918 int *pRc,
12919 sqlite3_stmt *pStmt
12920 ){
12921 if( pStmt ){
12922 sqlite3 *db = sqlite3_db_handle(pStmt);
@@ -12928,11 +14014,17 @@
12928 *pRc = rc;
12929 }
12930 }
12931 }
12932
12933 static void shellReset(
 
 
 
 
 
 
12934 int *pRc,
12935 sqlite3_stmt *pStmt
12936 ){
12937 int rc = sqlite3_reset(pStmt);
12938 if( *pRc==SQLITE_OK ){
@@ -12941,10 +14033,16 @@
12941 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
12942 }
12943 *pRc = rc;
12944 }
12945 }
 
 
 
 
 
 
12946 /*
12947 ** Structure representing a single ".ar" command.
12948 */
12949 typedef struct ArCommand ArCommand;
12950 struct ArCommand {
@@ -12993,30 +14091,32 @@
12993
12994 /*
12995 ** Values for ArCommand.eCmd.
12996 */
12997 #define AR_CMD_CREATE 1
12998 #define AR_CMD_EXTRACT 2
12999 #define AR_CMD_LIST 3
13000 #define AR_CMD_UPDATE 4
13001 #define AR_CMD_HELP 5
 
13002
13003 /*
13004 ** Other (non-command) switches.
13005 */
13006 #define AR_SWITCH_VERBOSE 6
13007 #define AR_SWITCH_FILE 7
13008 #define AR_SWITCH_DIRECTORY 8
13009 #define AR_SWITCH_APPEND 9
13010 #define AR_SWITCH_DRYRUN 10
13011
13012 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
13013 switch( eSwitch ){
13014 case AR_CMD_CREATE:
13015 case AR_CMD_EXTRACT:
13016 case AR_CMD_LIST:
13017 case AR_CMD_UPDATE:
 
13018 case AR_CMD_HELP:
13019 if( pAr->eCmd ){
13020 return arErrorMsg(pAr, "multiple command options");
13021 }
13022 pAr->eCmd = eSwitch;
@@ -13059,10 +14159,11 @@
13059 u8 eSwitch;
13060 u8 bArg;
13061 } aSwitch[] = {
13062 { "create", 'c', AR_CMD_CREATE, 0 },
13063 { "extract", 'x', AR_CMD_EXTRACT, 0 },
 
13064 { "list", 't', AR_CMD_LIST, 0 },
13065 { "update", 'u', AR_CMD_UPDATE, 0 },
13066 { "help", 'h', AR_CMD_HELP, 0 },
13067 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
13068 { "file", 'f', AR_SWITCH_FILE, 1 },
@@ -13394,23 +14495,31 @@
13394 return rc;
13395 }
13396
13397
13398 /*
13399 ** Implementation of .ar "create" and "update" commands.
 
 
 
 
 
13400 **
13401 ** Create the "sqlar" table in the database if it does not already exist.
13402 ** Then add each file in the azFile[] array to the archive. Directories
13403 ** are added recursively. If argument bVerbose is non-zero, a message is
13404 ** printed on stdout for each file archived.
13405 **
13406 ** The create command is the same as update, except that it drops
13407 ** any existing "sqlar" table before beginning.
 
 
13408 */
13409 static int arCreateOrUpdateCommand(
13410 ArCommand *pAr, /* Command arguments and options */
13411 int bUpdate /* true for a --create. false for --update */
 
13412 ){
13413 const char *zCreate =
13414 "CREATE TABLE IF NOT EXISTS sqlar(\n"
13415 " name TEXT PRIMARY KEY, -- name of the file\n"
13416 " mode INT, -- access permissions\n"
@@ -13428,26 +14537,28 @@
13428 " CASE substr(lsmode(mode),1,1)\n"
13429 " WHEN '-' THEN length(data)\n"
13430 " WHEN 'd' THEN 0\n"
13431 " ELSE -1 END,\n"
13432 " sqlar_compress(data)\n"
13433 " FROM fsdir(%Q,%Q)\n"
13434 " WHERE lsmode(mode) NOT LIKE '?%%';",
 
13435 "REPLACE INTO %s(name,mode,mtime,data)\n"
13436 " SELECT\n"
13437 " %s,\n"
13438 " mode,\n"
13439 " mtime,\n"
13440 " data\n"
13441 " FROM fsdir(%Q,%Q)\n"
13442 " WHERE lsmode(mode) NOT LIKE '?%%';"
13443 };
13444 int i; /* For iterating through azFile[] */
13445 int rc; /* Return code */
13446 const char *zTab = 0; /* SQL table into which to insert */
13447 char *zSql;
13448 char zTemp[50];
 
13449
13450 arExecSql(pAr, "PRAGMA page_size=512");
13451 rc = arExecSql(pAr, "SAVEPOINT ar;");
13452 if( rc!=SQLITE_OK ) return rc;
13453 zTemp[0] = 0;
@@ -13474,14 +14585,25 @@
13474 rc = arExecSql(pAr, zDrop);
13475 if( rc!=SQLITE_OK ) goto end_ar_transaction;
13476 }
13477 rc = arExecSql(pAr, zCreate);
13478 }
 
 
 
 
 
 
 
 
 
 
 
13479 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
13480 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
13481 pAr->bVerbose ? "shell_putsnl(name)" : "name",
13482 pAr->azArg[i], pAr->zDir);
13483 rc = arExecSql(pAr, zSql2);
13484 sqlite3_free(zSql2);
13485 }
13486 end_ar_transaction:
13487 if( rc!=SQLITE_OK ){
@@ -13492,10 +14614,11 @@
13492 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
13493 arExecSql(pAr, zSql);
13494 sqlite3_free(zSql);
13495 }
13496 }
 
13497 return rc;
13498 }
13499
13500 /*
13501 ** Implementation of ".ar" dot command.
@@ -13530,11 +14653,12 @@
13530 }
13531 cmd.bZip = 1;
13532 }else if( cmd.zFile ){
13533 int flags;
13534 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
13535 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
 
13536 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
13537 }else{
13538 flags = SQLITE_OPEN_READONLY;
13539 }
13540 cmd.db = 0;
@@ -13567,11 +14691,11 @@
13567 cmd.zSrcTable = sqlite3_mprintf("sqlar");
13568 }
13569
13570 switch( cmd.eCmd ){
13571 case AR_CMD_CREATE:
13572 rc = arCreateOrUpdateCommand(&cmd, 0);
13573 break;
13574
13575 case AR_CMD_EXTRACT:
13576 rc = arExtractCommand(&cmd);
13577 break;
@@ -13582,13 +14706,17 @@
13582
13583 case AR_CMD_HELP:
13584 arUsage(pState->out);
13585 break;
13586
 
 
 
 
13587 default:
13588 assert( cmd.eCmd==AR_CMD_UPDATE );
13589 rc = arCreateOrUpdateCommand(&cmd, 1);
13590 break;
13591 }
13592 }
13593 end_ar_command:
13594 if( cmd.db!=pState->db ){
@@ -13600,10 +14728,639 @@
13600 }
13601 /* End of the ".archive" or ".ar" command logic
13602 **********************************************************************************/
13603 #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
13604
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13605
13606 /*
13607 ** If an input line begins with "." then invoke this routine to
13608 ** process that line.
13609 **
@@ -13887,10 +15644,17 @@
13887
13888 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
13889 rc = shell_dbinfo_command(p, nArg, azArg);
13890 }else
13891
 
 
 
 
 
 
 
13892 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
13893 const char *zLike = 0;
13894 int i;
13895 int savedShowHeader = p->showHeader;
13896 int savedShellFlags = p->shellFlgs;
@@ -13924,11 +15688,13 @@
13924 goto meta_command_exit;
13925 }else{
13926 zLike = azArg[i];
13927 }
13928 }
 
13929 open_db(p, 0);
 
13930 /* When playing back a "dump", the content might appear in an order
13931 ** which causes immediate foreign key constraints to be violated.
13932 ** So disable foreign-key constraint enforcement to prevent problems. */
13933 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
13934 raw_printf(p->out, "BEGIN TRANSACTION;\n");
@@ -13972,11 +15738,11 @@
13972 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
13973 p->writableSchema = 0;
13974 }
13975 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
13976 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
13977 raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
13978 p->showHeader = savedShowHeader;
13979 p->shellFlgs = savedShellFlags;
13980 }else
13981
13982 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
@@ -14708,10 +16474,118 @@
14708 } else {
14709 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
14710 }
14711 }
14712 }else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14713
14714 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
14715 int i;
14716 for(i=1; i<nArg; i++){
14717 if( i>1 ) raw_printf(p->out, " ");
14718
--- src/shell.c
+++ src/shell.c
@@ -981,10 +981,11 @@
981
982 /*
983 ** We need several support functions from the SQLite core.
984 */
985
986 /* #include "sqlite3.h" */
987
988 /*
989 ** We need several things from the ANSI and MSVCRT headers.
990 */
991
@@ -1334,10 +1335,11 @@
1335 **
1336 ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
1337 ** is used. If SIZE is included it must be one of the integers 224, 256,
1338 ** 384, or 512, to determine SHA3 hash variant that is computed.
1339 */
1340 /* #include "sqlite3ext.h" */
1341 SQLITE_EXTENSION_INIT1
1342 #include <assert.h>
1343 #include <string.h>
1344 #include <stdarg.h>
1345 /* typedef sqlite3_uint64 u64; */
@@ -2097,10 +2099,11 @@
2099 ** If a non-NULL value is specified for the optional $dir parameter and
2100 ** $path is a relative path, then $path is interpreted relative to $dir.
2101 ** And the paths returned in the "name" column of the table are also
2102 ** relative to directory $dir.
2103 */
2104 /* #include "sqlite3ext.h" */
2105 SQLITE_EXTENSION_INIT1
2106 #include <stdio.h>
2107 #include <string.h>
2108 #include <assert.h>
2109
@@ -2175,17 +2178,17 @@
2178 if( nIn>mxBlob ){
2179 sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
2180 fclose(in);
2181 return;
2182 }
2183 pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
2184 if( pBuf==0 ){
2185 sqlite3_result_error_nomem(ctx);
2186 fclose(in);
2187 return;
2188 }
2189 if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
2190 sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
2191 }else{
2192 sqlite3_result_error_code(ctx, SQLITE_IOERR);
2193 sqlite3_free(pBuf);
2194 }
@@ -2316,19 +2319,19 @@
2319
2320 /*
2321 ** Argument zFile is the name of a file that will be created and/or written
2322 ** by SQL function writefile(). This function ensures that the directory
2323 ** zFile will be written to exists, creating it if required. The permissions
2324 ** for any path components created by this function are set in accordance
2325 ** with the current umask.
2326 **
2327 ** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
2328 ** SQLITE_OK is returned if the directory is successfully created, or
2329 ** SQLITE_ERROR otherwise.
2330 */
2331 static int makeDirectory(
2332 const char *zFile
 
2333 ){
2334 char *zCopy = sqlite3_mprintf("%s", zFile);
2335 int rc = SQLITE_OK;
2336
2337 if( zCopy==0 ){
@@ -2345,11 +2348,11 @@
2348 if( i==nCopy ) break;
2349 zCopy[i] = '\0';
2350
2351 rc2 = fileStat(zCopy, &sStat);
2352 if( rc2!=0 ){
2353 if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
2354 }else{
2355 if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
2356 }
2357 zCopy[i] = '/';
2358 i++;
@@ -2503,11 +2506,11 @@
2506 mtime = sqlite3_value_int64(argv[3]);
2507 }
2508
2509 res = writeFile(context, zFile, argv[1], mode, mtime);
2510 if( res==1 && errno==ENOENT ){
2511 if( makeDirectory(zFile)==SQLITE_OK ){
2512 res = writeFile(context, zFile, argv[1], mode, mtime);
2513 }
2514 }
2515
2516 if( argc>2 && res!=0 ){
@@ -3054,10 +3057,11 @@
3057 ** This virtual table operates at the speed of human typing, and so there
3058 ** is no attempt to make it fast. Even a slow implementation will be much
3059 ** faster than any human can type.
3060 **
3061 */
3062 /* #include "sqlite3ext.h" */
3063 SQLITE_EXTENSION_INIT1
3064 #include <assert.h>
3065 #include <string.h>
3066 #include <ctype.h>
3067
@@ -3570,10 +3574,11 @@
3574 ** database in a separate file.
3575 **
3576 ** If the file being opened is not an appended database, then this shim is
3577 ** a pass-through into the default underlying VFS.
3578 **/
3579 /* #include "sqlite3ext.h" */
3580 SQLITE_EXTENSION_INIT1
3581 #include <string.h>
3582 #include <assert.h>
3583
3584 /* The append mark at the end of the database is:
@@ -4226,10 +4231,11 @@
4231 ** * No support for encryption
4232 ** * No support for ZIP archives spanning multiple files
4233 ** * No support for zip64 extensions
4234 ** * Only the "inflate/deflate" (zlib) compression method is supported
4235 */
4236 /* #include "sqlite3ext.h" */
4237 SQLITE_EXTENSION_INIT1
4238 #include <stdio.h>
4239 #include <string.h>
4240 #include <assert.h>
4241
@@ -6396,10 +6402,11 @@
6402 **
6403 ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
6404 ** for working with sqlar archives and used by the shell tool's built-in
6405 ** sqlar support.
6406 */
6407 /* #include "sqlite3ext.h" */
6408 SQLITE_EXTENSION_INIT1
6409 #include <zlib.h>
6410
6411 /*
6412 ** Implementation of the "sqlar_compress(X)" SQL function.
@@ -6518,10 +6525,11 @@
6525 **
6526 *************************************************************************
6527 */
6528
6529
6530 /* #include "sqlite3.h" */
6531
6532 typedef struct sqlite3expert sqlite3expert;
6533
6534 /*
6535 ** Create a new sqlite3expert object.
@@ -6686,10 +6694,11 @@
6694 ** May you find forgiveness for yourself and forgive others.
6695 ** May you share freely, never taking more than you give.
6696 **
6697 *************************************************************************
6698 */
6699 /* #include "sqlite3expert.h" */
6700 #include <assert.h>
6701 #include <string.h>
6702 #include <stdio.h>
6703
6704 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -8628,10 +8637,867 @@
8637 }
8638
8639 #endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8640
8641 /************************* End ../ext/expert/sqlite3expert.c ********************/
8642
8643 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8644 /************************* Begin ../ext/misc/dbdata.c ******************/
8645 /*
8646 ** 2019-04-17
8647 **
8648 ** The author disclaims copyright to this source code. In place of
8649 ** a legal notice, here is a blessing:
8650 **
8651 ** May you do good and not evil.
8652 ** May you find forgiveness for yourself and forgive others.
8653 ** May you share freely, never taking more than you give.
8654 **
8655 ******************************************************************************
8656 **
8657 ** This file contains an implementation of two eponymous virtual tables,
8658 ** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
8659 ** "sqlite_dbpage" eponymous virtual table be available.
8660 **
8661 ** SQLITE_DBDATA:
8662 ** sqlite_dbdata is used to extract data directly from a database b-tree
8663 ** page and its associated overflow pages, bypassing the b-tree layer.
8664 ** The table schema is equivalent to:
8665 **
8666 ** CREATE TABLE sqlite_dbdata(
8667 ** pgno INTEGER,
8668 ** cell INTEGER,
8669 ** field INTEGER,
8670 ** value ANY,
8671 ** schema TEXT HIDDEN
8672 ** );
8673 **
8674 ** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
8675 ** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
8676 ** "schema".
8677 **
8678 ** Each page of the database is inspected. If it cannot be interpreted as
8679 ** a b-tree page, or if it is a b-tree page containing 0 entries, the
8680 ** sqlite_dbdata table contains no rows for that page. Otherwise, the
8681 ** table contains one row for each field in the record associated with
8682 ** each cell on the page. For intkey b-trees, the key value is stored in
8683 ** field -1.
8684 **
8685 ** For example, for the database:
8686 **
8687 ** CREATE TABLE t1(a, b); -- root page is page 2
8688 ** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
8689 ** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
8690 **
8691 ** the sqlite_dbdata table contains, as well as from entries related to
8692 ** page 1, content equivalent to:
8693 **
8694 ** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
8695 ** (2, 0, -1, 5 ),
8696 ** (2, 0, 0, 'v' ),
8697 ** (2, 0, 1, 'five'),
8698 ** (2, 1, -1, 10 ),
8699 ** (2, 1, 0, 'x' ),
8700 ** (2, 1, 1, 'ten' );
8701 **
8702 ** If database corruption is encountered, this module does not report an
8703 ** error. Instead, it attempts to extract as much data as possible and
8704 ** ignores the corruption.
8705 **
8706 ** SQLITE_DBPTR:
8707 ** The sqlite_dbptr table has the following schema:
8708 **
8709 ** CREATE TABLE sqlite_dbptr(
8710 ** pgno INTEGER,
8711 ** child INTEGER,
8712 ** schema TEXT HIDDEN
8713 ** );
8714 **
8715 ** It contains one entry for each b-tree pointer between a parent and
8716 ** child page in the database.
8717 */
8718 #if !defined(SQLITEINT_H)
8719 /* #include "sqlite3ext.h" */
8720
8721 /* typedef unsigned char u8; */
8722
8723 #endif
8724 SQLITE_EXTENSION_INIT1
8725 #include <string.h>
8726 #include <assert.h>
8727
8728 #define DBDATA_PADDING_BYTES 100
8729
8730 typedef struct DbdataTable DbdataTable;
8731 typedef struct DbdataCursor DbdataCursor;
8732
8733 /* Cursor object */
8734 struct DbdataCursor {
8735 sqlite3_vtab_cursor base; /* Base class. Must be first */
8736 sqlite3_stmt *pStmt; /* For fetching database pages */
8737
8738 int iPgno; /* Current page number */
8739 u8 *aPage; /* Buffer containing page */
8740 int nPage; /* Size of aPage[] in bytes */
8741 int nCell; /* Number of cells on aPage[] */
8742 int iCell; /* Current cell number */
8743 int bOnePage; /* True to stop after one page */
8744 int szDb;
8745 sqlite3_int64 iRowid;
8746
8747 /* Only for the sqlite_dbdata table */
8748 u8 *pRec; /* Buffer containing current record */
8749 int nRec; /* Size of pRec[] in bytes */
8750 int nHdr; /* Size of header in bytes */
8751 int iField; /* Current field number */
8752 u8 *pHdrPtr;
8753 u8 *pPtr;
8754
8755 sqlite3_int64 iIntkey; /* Integer key value */
8756 };
8757
8758 /* Table object */
8759 struct DbdataTable {
8760 sqlite3_vtab base; /* Base class. Must be first */
8761 sqlite3 *db; /* The database connection */
8762 sqlite3_stmt *pStmt; /* For fetching database pages */
8763 int bPtr; /* True for sqlite3_dbptr table */
8764 };
8765
8766 /* Column and schema definitions for sqlite_dbdata */
8767 #define DBDATA_COLUMN_PGNO 0
8768 #define DBDATA_COLUMN_CELL 1
8769 #define DBDATA_COLUMN_FIELD 2
8770 #define DBDATA_COLUMN_VALUE 3
8771 #define DBDATA_COLUMN_SCHEMA 4
8772 #define DBDATA_SCHEMA \
8773 "CREATE TABLE x(" \
8774 " pgno INTEGER," \
8775 " cell INTEGER," \
8776 " field INTEGER," \
8777 " value ANY," \
8778 " schema TEXT HIDDEN" \
8779 ")"
8780
8781 /* Column and schema definitions for sqlite_dbptr */
8782 #define DBPTR_COLUMN_PGNO 0
8783 #define DBPTR_COLUMN_CHILD 1
8784 #define DBPTR_COLUMN_SCHEMA 2
8785 #define DBPTR_SCHEMA \
8786 "CREATE TABLE x(" \
8787 " pgno INTEGER," \
8788 " child INTEGER," \
8789 " schema TEXT HIDDEN" \
8790 ")"
8791
8792 /*
8793 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
8794 ** table.
8795 */
8796 static int dbdataConnect(
8797 sqlite3 *db,
8798 void *pAux,
8799 int argc, const char *const*argv,
8800 sqlite3_vtab **ppVtab,
8801 char **pzErr
8802 ){
8803 DbdataTable *pTab = 0;
8804 int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
8805
8806 if( rc==SQLITE_OK ){
8807 pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
8808 if( pTab==0 ){
8809 rc = SQLITE_NOMEM;
8810 }else{
8811 memset(pTab, 0, sizeof(DbdataTable));
8812 pTab->db = db;
8813 pTab->bPtr = (pAux!=0);
8814 }
8815 }
8816
8817 *ppVtab = (sqlite3_vtab*)pTab;
8818 return rc;
8819 }
8820
8821 /*
8822 ** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
8823 */
8824 static int dbdataDisconnect(sqlite3_vtab *pVtab){
8825 DbdataTable *pTab = (DbdataTable*)pVtab;
8826 if( pTab ){
8827 sqlite3_finalize(pTab->pStmt);
8828 sqlite3_free(pVtab);
8829 }
8830 return SQLITE_OK;
8831 }
8832
8833 /*
8834 ** This function interprets two types of constraints:
8835 **
8836 ** schema=?
8837 ** pgno=?
8838 **
8839 ** If neither are present, idxNum is set to 0. If schema=? is present,
8840 ** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
8841 ** in idxNum is set.
8842 **
8843 ** If both parameters are present, schema is in position 0 and pgno in
8844 ** position 1.
8845 */
8846 static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
8847 DbdataTable *pTab = (DbdataTable*)tab;
8848 int i;
8849 int iSchema = -1;
8850 int iPgno = -1;
8851 int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
8852
8853 for(i=0; i<pIdx->nConstraint; i++){
8854 struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
8855 if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
8856 if( p->iColumn==colSchema ){
8857 if( p->usable==0 ) return SQLITE_CONSTRAINT;
8858 iSchema = i;
8859 }
8860 if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
8861 iPgno = i;
8862 }
8863 }
8864 }
8865
8866 if( iSchema>=0 ){
8867 pIdx->aConstraintUsage[iSchema].argvIndex = 1;
8868 pIdx->aConstraintUsage[iSchema].omit = 1;
8869 }
8870 if( iPgno>=0 ){
8871 pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
8872 pIdx->aConstraintUsage[iPgno].omit = 1;
8873 pIdx->estimatedCost = 100;
8874 pIdx->estimatedRows = 50;
8875
8876 if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
8877 int iCol = pIdx->aOrderBy[0].iColumn;
8878 if( pIdx->nOrderBy==1 ){
8879 pIdx->orderByConsumed = (iCol==0 || iCol==1);
8880 }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
8881 pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
8882 }
8883 }
8884
8885 }else{
8886 pIdx->estimatedCost = 100000000;
8887 pIdx->estimatedRows = 1000000000;
8888 }
8889 pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
8890 return SQLITE_OK;
8891 }
8892
8893 /*
8894 ** Open a new sqlite_dbdata or sqlite_dbptr cursor.
8895 */
8896 static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
8897 DbdataCursor *pCsr;
8898
8899 pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
8900 if( pCsr==0 ){
8901 return SQLITE_NOMEM;
8902 }else{
8903 memset(pCsr, 0, sizeof(DbdataCursor));
8904 pCsr->base.pVtab = pVTab;
8905 }
8906
8907 *ppCursor = (sqlite3_vtab_cursor *)pCsr;
8908 return SQLITE_OK;
8909 }
8910
8911 /*
8912 ** Restore a cursor object to the state it was in when first allocated
8913 ** by dbdataOpen().
8914 */
8915 static void dbdataResetCursor(DbdataCursor *pCsr){
8916 DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
8917 if( pTab->pStmt==0 ){
8918 pTab->pStmt = pCsr->pStmt;
8919 }else{
8920 sqlite3_finalize(pCsr->pStmt);
8921 }
8922 pCsr->pStmt = 0;
8923 pCsr->iPgno = 1;
8924 pCsr->iCell = 0;
8925 pCsr->iField = 0;
8926 pCsr->bOnePage = 0;
8927 sqlite3_free(pCsr->aPage);
8928 sqlite3_free(pCsr->pRec);
8929 pCsr->pRec = 0;
8930 pCsr->aPage = 0;
8931 }
8932
8933 /*
8934 ** Close an sqlite_dbdata or sqlite_dbptr cursor.
8935 */
8936 static int dbdataClose(sqlite3_vtab_cursor *pCursor){
8937 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
8938 dbdataResetCursor(pCsr);
8939 sqlite3_free(pCsr);
8940 return SQLITE_OK;
8941 }
8942
8943 /*
8944 ** Utility methods to decode 16 and 32-bit big-endian unsigned integers.
8945 */
8946 static unsigned int get_uint16(unsigned char *a){
8947 return (a[0]<<8)|a[1];
8948 }
8949 static unsigned int get_uint32(unsigned char *a){
8950 return ((unsigned int)a[0]<<24)
8951 | ((unsigned int)a[1]<<16)
8952 | ((unsigned int)a[2]<<8)
8953 | ((unsigned int)a[3]);
8954 }
8955
8956 /*
8957 ** Load page pgno from the database via the sqlite_dbpage virtual table.
8958 ** If successful, set (*ppPage) to point to a buffer containing the page
8959 ** data, (*pnPage) to the size of that buffer in bytes and return
8960 ** SQLITE_OK. In this case it is the responsibility of the caller to
8961 ** eventually free the buffer using sqlite3_free().
8962 **
8963 ** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
8964 ** return an SQLite error code.
8965 */
8966 static int dbdataLoadPage(
8967 DbdataCursor *pCsr, /* Cursor object */
8968 unsigned int pgno, /* Page number of page to load */
8969 u8 **ppPage, /* OUT: pointer to page buffer */
8970 int *pnPage /* OUT: Size of (*ppPage) in bytes */
8971 ){
8972 int rc2;
8973 int rc = SQLITE_OK;
8974 sqlite3_stmt *pStmt = pCsr->pStmt;
8975
8976 *ppPage = 0;
8977 *pnPage = 0;
8978 sqlite3_bind_int64(pStmt, 2, pgno);
8979 if( SQLITE_ROW==sqlite3_step(pStmt) ){
8980 int nCopy = sqlite3_column_bytes(pStmt, 0);
8981 if( nCopy>0 ){
8982 u8 *pPage;
8983 pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
8984 if( pPage==0 ){
8985 rc = SQLITE_NOMEM;
8986 }else{
8987 const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
8988 memcpy(pPage, pCopy, nCopy);
8989 memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
8990 }
8991 *ppPage = pPage;
8992 *pnPage = nCopy;
8993 }
8994 }
8995 rc2 = sqlite3_reset(pStmt);
8996 if( rc==SQLITE_OK ) rc = rc2;
8997
8998 return rc;
8999 }
9000
9001 /*
9002 ** Read a varint. Put the value in *pVal and return the number of bytes.
9003 */
9004 static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
9005 sqlite3_int64 v = 0;
9006 int i;
9007 for(i=0; i<8; i++){
9008 v = (v<<7) + (z[i]&0x7f);
9009 if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
9010 }
9011 v = (v<<8) + (z[i]&0xff);
9012 *pVal = v;
9013 return 9;
9014 }
9015
9016 /*
9017 ** Return the number of bytes of space used by an SQLite value of type
9018 ** eType.
9019 */
9020 static int dbdataValueBytes(int eType){
9021 switch( eType ){
9022 case 0: case 8: case 9:
9023 case 10: case 11:
9024 return 0;
9025 case 1:
9026 return 1;
9027 case 2:
9028 return 2;
9029 case 3:
9030 return 3;
9031 case 4:
9032 return 4;
9033 case 5:
9034 return 6;
9035 case 6:
9036 case 7:
9037 return 8;
9038 default:
9039 if( eType>0 ){
9040 return ((eType-12) / 2);
9041 }
9042 return 0;
9043 }
9044 }
9045
9046 /*
9047 ** Load a value of type eType from buffer pData and use it to set the
9048 ** result of context object pCtx.
9049 */
9050 static void dbdataValue(
9051 sqlite3_context *pCtx,
9052 int eType,
9053 u8 *pData,
9054 int nData
9055 ){
9056 if( eType>=0 && dbdataValueBytes(eType)<=nData ){
9057 switch( eType ){
9058 case 0:
9059 case 10:
9060 case 11:
9061 sqlite3_result_null(pCtx);
9062 break;
9063
9064 case 8:
9065 sqlite3_result_int(pCtx, 0);
9066 break;
9067 case 9:
9068 sqlite3_result_int(pCtx, 1);
9069 break;
9070
9071 case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
9072 sqlite3_uint64 v = (signed char)pData[0];
9073 pData++;
9074 switch( eType ){
9075 case 7:
9076 case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
9077 case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
9078 case 4: v = (v<<8) + pData[0]; pData++;
9079 case 3: v = (v<<8) + pData[0]; pData++;
9080 case 2: v = (v<<8) + pData[0]; pData++;
9081 }
9082
9083 if( eType==7 ){
9084 double r;
9085 memcpy(&r, &v, sizeof(r));
9086 sqlite3_result_double(pCtx, r);
9087 }else{
9088 sqlite3_result_int64(pCtx, (sqlite3_int64)v);
9089 }
9090 break;
9091 }
9092
9093 default: {
9094 int n = ((eType-12) / 2);
9095 if( eType % 2 ){
9096 sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
9097 }else{
9098 sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
9099 }
9100 }
9101 }
9102 }
9103 }
9104
9105 /*
9106 ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
9107 */
9108 static int dbdataNext(sqlite3_vtab_cursor *pCursor){
9109 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9110 DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9111
9112 pCsr->iRowid++;
9113 while( 1 ){
9114 int rc;
9115 int iOff = (pCsr->iPgno==1 ? 100 : 0);
9116 int bNextPage = 0;
9117
9118 if( pCsr->aPage==0 ){
9119 while( 1 ){
9120 if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
9121 rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
9122 if( rc!=SQLITE_OK ) return rc;
9123 if( pCsr->aPage ) break;
9124 pCsr->iPgno++;
9125 }
9126 pCsr->iCell = pTab->bPtr ? -2 : 0;
9127 pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
9128 }
9129
9130 if( pTab->bPtr ){
9131 if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
9132 pCsr->iCell = pCsr->nCell;
9133 }
9134 pCsr->iCell++;
9135 if( pCsr->iCell>=pCsr->nCell ){
9136 sqlite3_free(pCsr->aPage);
9137 pCsr->aPage = 0;
9138 if( pCsr->bOnePage ) return SQLITE_OK;
9139 pCsr->iPgno++;
9140 }else{
9141 return SQLITE_OK;
9142 }
9143 }else{
9144 /* If there is no record loaded, load it now. */
9145 if( pCsr->pRec==0 ){
9146 int bHasRowid = 0;
9147 int nPointer = 0;
9148 sqlite3_int64 nPayload = 0;
9149 sqlite3_int64 nHdr = 0;
9150 int iHdr;
9151 int U, X;
9152 int nLocal;
9153
9154 switch( pCsr->aPage[iOff] ){
9155 case 0x02:
9156 nPointer = 4;
9157 break;
9158 case 0x0a:
9159 break;
9160 case 0x0d:
9161 bHasRowid = 1;
9162 break;
9163 default:
9164 /* This is not a b-tree page with records on it. Continue. */
9165 pCsr->iCell = pCsr->nCell;
9166 break;
9167 }
9168
9169 if( pCsr->iCell>=pCsr->nCell ){
9170 bNextPage = 1;
9171 }else{
9172
9173 iOff += 8 + nPointer + pCsr->iCell*2;
9174 if( iOff>pCsr->nPage ){
9175 bNextPage = 1;
9176 }else{
9177 iOff = get_uint16(&pCsr->aPage[iOff]);
9178 }
9179
9180 /* For an interior node cell, skip past the child-page number */
9181 iOff += nPointer;
9182
9183 /* Load the "byte of payload including overflow" field */
9184 if( bNextPage || iOff>pCsr->nPage ){
9185 bNextPage = 1;
9186 }else{
9187 iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
9188 }
9189
9190 /* If this is a leaf intkey cell, load the rowid */
9191 if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
9192 iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
9193 }
9194
9195 /* Figure out how much data to read from the local page */
9196 U = pCsr->nPage;
9197 if( bHasRowid ){
9198 X = U-35;
9199 }else{
9200 X = ((U-12)*64/255)-23;
9201 }
9202 if( nPayload<=X ){
9203 nLocal = nPayload;
9204 }else{
9205 int M, K;
9206 M = ((U-12)*32/255)-23;
9207 K = M+((nPayload-M)%(U-4));
9208 if( K<=X ){
9209 nLocal = K;
9210 }else{
9211 nLocal = M;
9212 }
9213 }
9214
9215 if( bNextPage || nLocal+iOff>pCsr->nPage ){
9216 bNextPage = 1;
9217 }else{
9218
9219 /* Allocate space for payload. And a bit more to catch small buffer
9220 ** overruns caused by attempting to read a varint or similar from
9221 ** near the end of a corrupt record. */
9222 pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
9223 if( pCsr->pRec==0 ) return SQLITE_NOMEM;
9224 memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
9225 pCsr->nRec = nPayload;
9226
9227 /* Load the nLocal bytes of payload */
9228 memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
9229 iOff += nLocal;
9230
9231 /* Load content from overflow pages */
9232 if( nPayload>nLocal ){
9233 sqlite3_int64 nRem = nPayload - nLocal;
9234 unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
9235 while( nRem>0 ){
9236 u8 *aOvfl = 0;
9237 int nOvfl = 0;
9238 int nCopy;
9239 rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
9240 assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
9241 if( rc!=SQLITE_OK ) return rc;
9242 if( aOvfl==0 ) break;
9243
9244 nCopy = U-4;
9245 if( nCopy>nRem ) nCopy = nRem;
9246 memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
9247 nRem -= nCopy;
9248
9249 pgnoOvfl = get_uint32(aOvfl);
9250 sqlite3_free(aOvfl);
9251 }
9252 }
9253
9254 iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
9255 pCsr->nHdr = nHdr;
9256 pCsr->pHdrPtr = &pCsr->pRec[iHdr];
9257 pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
9258 pCsr->iField = (bHasRowid ? -1 : 0);
9259 }
9260 }
9261 }else{
9262 pCsr->iField++;
9263 if( pCsr->iField>0 ){
9264 sqlite3_int64 iType;
9265 if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
9266 bNextPage = 1;
9267 }else{
9268 pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
9269 pCsr->pPtr += dbdataValueBytes(iType);
9270 }
9271 }
9272 }
9273
9274 if( bNextPage ){
9275 sqlite3_free(pCsr->aPage);
9276 sqlite3_free(pCsr->pRec);
9277 pCsr->aPage = 0;
9278 pCsr->pRec = 0;
9279 if( pCsr->bOnePage ) return SQLITE_OK;
9280 pCsr->iPgno++;
9281 }else{
9282 if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
9283 return SQLITE_OK;
9284 }
9285
9286 /* Advance to the next cell. The next iteration of the loop will load
9287 ** the record and so on. */
9288 sqlite3_free(pCsr->pRec);
9289 pCsr->pRec = 0;
9290 pCsr->iCell++;
9291 }
9292 }
9293 }
9294
9295 assert( !"can't get here" );
9296 return SQLITE_OK;
9297 }
9298
9299 /*
9300 ** Return true if the cursor is at EOF.
9301 */
9302 static int dbdataEof(sqlite3_vtab_cursor *pCursor){
9303 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9304 return pCsr->aPage==0;
9305 }
9306
9307 /*
9308 ** Determine the size in pages of database zSchema (where zSchema is
9309 ** "main", "temp" or the name of an attached database) and set
9310 ** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
9311 ** an SQLite error code.
9312 */
9313 static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
9314 DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
9315 char *zSql = 0;
9316 int rc, rc2;
9317 sqlite3_stmt *pStmt = 0;
9318
9319 zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
9320 if( zSql==0 ) return SQLITE_NOMEM;
9321 rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
9322 sqlite3_free(zSql);
9323 if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9324 pCsr->szDb = sqlite3_column_int(pStmt, 0);
9325 }
9326 rc2 = sqlite3_finalize(pStmt);
9327 if( rc==SQLITE_OK ) rc = rc2;
9328 return rc;
9329 }
9330
9331 /*
9332 ** xFilter method for sqlite_dbdata and sqlite_dbptr.
9333 */
9334 static int dbdataFilter(
9335 sqlite3_vtab_cursor *pCursor,
9336 int idxNum, const char *idxStr,
9337 int argc, sqlite3_value **argv
9338 ){
9339 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9340 DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9341 int rc = SQLITE_OK;
9342 const char *zSchema = "main";
9343
9344 dbdataResetCursor(pCsr);
9345 assert( pCsr->iPgno==1 );
9346 if( idxNum & 0x01 ){
9347 zSchema = (const char*)sqlite3_value_text(argv[0]);
9348 }
9349 if( idxNum & 0x02 ){
9350 pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
9351 pCsr->bOnePage = 1;
9352 }else{
9353 pCsr->nPage = dbdataDbsize(pCsr, zSchema);
9354 rc = dbdataDbsize(pCsr, zSchema);
9355 }
9356
9357 if( rc==SQLITE_OK ){
9358 if( pTab->pStmt ){
9359 pCsr->pStmt = pTab->pStmt;
9360 pTab->pStmt = 0;
9361 }else{
9362 rc = sqlite3_prepare_v2(pTab->db,
9363 "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
9364 &pCsr->pStmt, 0
9365 );
9366 }
9367 }
9368 if( rc==SQLITE_OK ){
9369 rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
9370 }else{
9371 pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
9372 }
9373 if( rc==SQLITE_OK ){
9374 rc = dbdataNext(pCursor);
9375 }
9376 return rc;
9377 }
9378
9379 /*
9380 ** Return a column for the sqlite_dbdata or sqlite_dbptr table.
9381 */
9382 static int dbdataColumn(
9383 sqlite3_vtab_cursor *pCursor,
9384 sqlite3_context *ctx,
9385 int i
9386 ){
9387 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9388 DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9389 if( pTab->bPtr ){
9390 switch( i ){
9391 case DBPTR_COLUMN_PGNO:
9392 sqlite3_result_int64(ctx, pCsr->iPgno);
9393 break;
9394 case DBPTR_COLUMN_CHILD: {
9395 int iOff = pCsr->iPgno==1 ? 100 : 0;
9396 if( pCsr->iCell<0 ){
9397 iOff += 8;
9398 }else{
9399 iOff += 12 + pCsr->iCell*2;
9400 if( iOff>pCsr->nPage ) return SQLITE_OK;
9401 iOff = get_uint16(&pCsr->aPage[iOff]);
9402 }
9403 if( iOff<=pCsr->nPage ){
9404 sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
9405 }
9406 break;
9407 }
9408 }
9409 }else{
9410 switch( i ){
9411 case DBDATA_COLUMN_PGNO:
9412 sqlite3_result_int64(ctx, pCsr->iPgno);
9413 break;
9414 case DBDATA_COLUMN_CELL:
9415 sqlite3_result_int(ctx, pCsr->iCell);
9416 break;
9417 case DBDATA_COLUMN_FIELD:
9418 sqlite3_result_int(ctx, pCsr->iField);
9419 break;
9420 case DBDATA_COLUMN_VALUE: {
9421 if( pCsr->iField<0 ){
9422 sqlite3_result_int64(ctx, pCsr->iIntkey);
9423 }else{
9424 sqlite3_int64 iType;
9425 dbdataGetVarint(pCsr->pHdrPtr, &iType);
9426 dbdataValue(
9427 ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
9428 );
9429 }
9430 break;
9431 }
9432 }
9433 }
9434 return SQLITE_OK;
9435 }
9436
9437 /*
9438 ** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
9439 */
9440 static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
9441 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9442 *pRowid = pCsr->iRowid;
9443 return SQLITE_OK;
9444 }
9445
9446
9447 /*
9448 ** Invoke this routine to register the "sqlite_dbdata" virtual table module
9449 */
9450 static int sqlite3DbdataRegister(sqlite3 *db){
9451 static sqlite3_module dbdata_module = {
9452 0, /* iVersion */
9453 0, /* xCreate */
9454 dbdataConnect, /* xConnect */
9455 dbdataBestIndex, /* xBestIndex */
9456 dbdataDisconnect, /* xDisconnect */
9457 0, /* xDestroy */
9458 dbdataOpen, /* xOpen - open a cursor */
9459 dbdataClose, /* xClose - close a cursor */
9460 dbdataFilter, /* xFilter - configure scan constraints */
9461 dbdataNext, /* xNext - advance a cursor */
9462 dbdataEof, /* xEof - check for end of scan */
9463 dbdataColumn, /* xColumn - read data */
9464 dbdataRowid, /* xRowid - read data */
9465 0, /* xUpdate */
9466 0, /* xBegin */
9467 0, /* xSync */
9468 0, /* xCommit */
9469 0, /* xRollback */
9470 0, /* xFindMethod */
9471 0, /* xRename */
9472 0, /* xSavepoint */
9473 0, /* xRelease */
9474 0, /* xRollbackTo */
9475 0 /* xShadowName */
9476 };
9477
9478 int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
9479 if( rc==SQLITE_OK ){
9480 rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
9481 }
9482 return rc;
9483 }
9484
9485 #ifdef _WIN32
9486
9487 #endif
9488 int sqlite3_dbdata_init(
9489 sqlite3 *db,
9490 char **pzErrMsg,
9491 const sqlite3_api_routines *pApi
9492 ){
9493 SQLITE_EXTENSION_INIT2(pApi);
9494 return sqlite3DbdataRegister(db);
9495 }
9496
9497 /************************* End ../ext/misc/dbdata.c ********************/
9498 #endif
9499
9500 #if defined(SQLITE_ENABLE_SESSION)
9501 /*
9502 ** State information for a single open session
9503 */
@@ -9358,10 +10224,12 @@
10224 **
10225 ** This routine converts some CREATE TABLE statements for shadow tables
10226 ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
10227 */
10228 static void printSchemaLine(FILE *out, const char *z, const char *zTail){
10229 if( z==0 ) return;
10230 if( zTail==0 ) return;
10231 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
10232 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
10233 }else{
10234 utf8_printf(out, "%s%s", z, zTail);
10235 }
@@ -10427,10 +11295,70 @@
11295 #endif
11296 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
11297 sqlite3WhereTrace = savedWhereTrace;
11298 #endif
11299 }
11300
11301 /* Create the TEMP table used to store parameter bindings */
11302 static void bind_table_init(ShellState *p){
11303 int wrSchema = 0;
11304 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
11305 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
11306 sqlite3_exec(p->db,
11307 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
11308 " key TEXT PRIMARY KEY,\n"
11309 " value ANY\n"
11310 ") WITHOUT ROWID;",
11311 0, 0, 0);
11312 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
11313 }
11314
11315 /*
11316 ** Bind parameters on a prepared statement.
11317 **
11318 ** Parameter bindings are taken from a TEMP table of the form:
11319 **
11320 ** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
11321 ** WITHOUT ROWID;
11322 **
11323 ** No bindings occur if this table does not exist. The special character '$'
11324 ** is included in the table name to help prevent collisions with actual tables.
11325 ** The table must be in the TEMP schema.
11326 */
11327 static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
11328 int nVar;
11329 int i;
11330 int rc;
11331 sqlite3_stmt *pQ = 0;
11332
11333 nVar = sqlite3_bind_parameter_count(pStmt);
11334 if( nVar==0 ) return; /* Nothing to do */
11335 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
11336 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
11337 return; /* Parameter table does not exist */
11338 }
11339 rc = sqlite3_prepare_v2(pArg->db,
11340 "SELECT value FROM temp.sqlite_parameters"
11341 " WHERE key=?1", -1, &pQ, 0);
11342 if( rc || pQ==0 ) return;
11343 for(i=1; i<=nVar; i++){
11344 char zNum[30];
11345 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
11346 if( zVar==0 ){
11347 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
11348 zVar = zNum;
11349 }
11350 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
11351 if( sqlite3_step(pQ)==SQLITE_ROW ){
11352 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
11353 }else{
11354 sqlite3_bind_null(pStmt, i);
11355 }
11356 sqlite3_reset(pQ);
11357 }
11358 sqlite3_finalize(pQ);
11359 }
11360
11361 /*
11362 ** Run a prepared statement
11363 */
11364 static void exec_prepared_stmt(
@@ -10680,11 +11608,11 @@
11608 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
11609 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
11610 }
11611
11612 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
11613 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
11614 sqlite3_stmt *pExplain;
11615 char *zEQP;
11616 int triggerEQP = 0;
11617 disable_debug_trace_modes();
11618 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
@@ -10729,17 +11657,14 @@
11657 }
11658
11659 if( pArg ){
11660 pArg->cMode = pArg->mode;
11661 if( pArg->autoExplain ){
11662 if( sqlite3_stmt_isexplain(pStmt)==1 ){
 
 
11663 pArg->cMode = MODE_Explain;
11664 }
11665 if( sqlite3_stmt_isexplain(pStmt)==2 ){
 
11666 pArg->cMode = MODE_EQP;
11667 }
11668 }
11669
11670 /* If the shell is currently in ".explain" mode, gather the extra
@@ -10747,10 +11672,11 @@
11672 if( pArg->cMode==MODE_Explain ){
11673 explain_data_prepare(pArg, pStmt);
11674 }
11675 }
11676
11677 bind_prepared_stmt(pArg, pStmt);
11678 exec_prepared_stmt(pArg, pStmt);
11679 explain_data_delete(pArg);
11680 eqp_render(pArg);
11681
11682 /* print usage stats if stats on */
@@ -11076,11 +12002,12 @@
12002 static const char *(azHelp[]) = {
12003 #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
12004 ".archive ... Manage SQL archives",
12005 " Each command must have exactly one of the following options:",
12006 " -c, --create Create a new archive",
12007 " -u, --update Add files or update files with changed mtime",
12008 " -i, --insert Like -u but always add even if mtime unchanged",
12009 " -t, --list List contents of archive",
12010 " -x, --extract Extract files from archive",
12011 " Optional arguments:",
12012 " -v, --verbose Print each filename as it is processed",
12013 " -f FILE, --file FILE Operate on archive FILE (default is current db)",
@@ -11111,11 +12038,11 @@
12038 ".dbinfo ?DB? Show status information about the database",
12039 ".dump ?TABLE? ... Render all database content as SQL",
12040 " Options:",
12041 " --preserve-rowids Include ROWID values in the output",
12042 " --newlines Allow unescaped newline characters in output",
12043 " TABLE is a LIKE pattern for the tables to dump",
12044 ".echo on|off Turn command echo on or off",
12045 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
12046 " Other Modes:",
12047 #ifdef SQLITE_DEBUG
12048 " test Show raw EXPLAIN QUERY PLAN output",
@@ -11178,10 +12105,17 @@
12105 " --new Initialize FILE to an empty database",
12106 " --readonly Open FILE readonly",
12107 " --zip FILE is a ZIP archive",
12108 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
12109 " If FILE begins with '|' then open it as a pipe.",
12110 ".parameter CMD ... Manage SQL parameter bindings",
12111 " clear Erase all bindings",
12112 " init Initialize the TEMP table that holds bindings",
12113 " list List the current parameter bindings",
12114 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
12115 " PARAMETER should start with '$', ':', '@', or '?'",
12116 " unset PARAMETER Remove PARAMETER from the binding table",
12117 ".print STRING... Print literal STRING",
12118 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
12119 ".progress N Invoke progress handler after every N opcodes",
12120 " --limit N Interrupt after N progress callbacks",
12121 " --once Do no more than one progress interrupt",
@@ -11189,10 +12123,13 @@
12123 " --reset Reset the count for each input and interrupt",
12124 #endif
12125 ".prompt MAIN CONTINUE Replace the standard prompts",
12126 ".quit Exit this program",
12127 ".read FILE Read input from FILE",
12128 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
12129 ".recover Recover as much data as possible from corrupt db.",
12130 #endif
12131 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
12132 ".save FILE Write in-memory database into FILE",
12133 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
12134 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
12135 " Options:",
@@ -11473,11 +12410,11 @@
12410 int pgsz = 0;
12411 int iOffset = 0;
12412 int j, k;
12413 int rc;
12414 FILE *in;
12415 unsigned int x[16];
12416 char zLine[1000];
12417 if( p->zDbFilename ){
12418 in = fopen(p->zDbFilename, "r");
12419 if( in==0 ){
12420 utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
@@ -11485,18 +12422,19 @@
12422 }
12423 nLine = 0;
12424 }else{
12425 in = p->in;
12426 nLine = p->lineno;
12427 if( in==0 ) in = stdin;
12428 }
12429 *pnData = 0;
12430 nLine++;
12431 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
12432 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
12433 if( rc!=2 ) goto readHexDb_error;
12434 if( n<0 ) goto readHexDb_error;
12435 a = sqlite3_malloc( n ? n : 1 );
12436 if( a==0 ){
12437 utf8_printf(stderr, "Out of memory!\n");
12438 goto readHexDb_error;
12439 }
12440 memset(a, 0, n);
@@ -11511,18 +12449,18 @@
12449 continue;
12450 }
12451 if( strncmp(zLine, "| end ", 6)==0 ){
12452 break;
12453 }
12454 rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
 
12455 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
12456 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
12457 if( rc==17 ){
12458 k = iOffset+j;
12459 if( k+16<=n ){
12460 int ii;
12461 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
12462 }
12463 }
12464 }
12465 *pnData = n;
12466 if( in!=p->in ){
@@ -11531,11 +12469,11 @@
12469 p->lineno = nLine;
12470 }
12471 return a;
12472
12473 readHexDb_error:
12474 if( in!=p->in ){
12475 fclose(in);
12476 }else{
12477 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
12478 nLine++;
12479 if(strncmp(zLine, "| end ", 6)==0 ) break;
@@ -11545,10 +12483,131 @@
12483 sqlite3_free(a);
12484 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
12485 return 0;
12486 }
12487 #endif /* SQLITE_ENABLE_DESERIALIZE */
12488
12489 /*
12490 ** Scalar function "shell_int32". The first argument to this function
12491 ** must be a blob. The second a non-negative integer. This function
12492 ** reads and returns a 32-bit big-endian integer from byte
12493 ** offset (4*<arg2>) of the blob.
12494 */
12495 static void shellInt32(
12496 sqlite3_context *context,
12497 int argc,
12498 sqlite3_value **argv
12499 ){
12500 const unsigned char *pBlob;
12501 int nBlob;
12502 int iInt;
12503
12504 UNUSED_PARAMETER(argc);
12505 nBlob = sqlite3_value_bytes(argv[0]);
12506 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
12507 iInt = sqlite3_value_int(argv[1]);
12508
12509 if( iInt>=0 && (iInt+1)*4<=nBlob ){
12510 const unsigned char *a = &pBlob[iInt*4];
12511 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
12512 + ((sqlite3_int64)a[1]<<16)
12513 + ((sqlite3_int64)a[2]<< 8)
12514 + ((sqlite3_int64)a[3]<< 0);
12515 sqlite3_result_int64(context, iVal);
12516 }
12517 }
12518
12519 /*
12520 ** Scalar function "shell_escape_crnl" used by the .recover command.
12521 ** The argument passed to this function is the output of built-in
12522 ** function quote(). If the first character of the input is "'",
12523 ** indicating that the value passed to quote() was a text value,
12524 ** then this function searches the input for "\n" and "\r" characters
12525 ** and adds a wrapper similar to the following:
12526 **
12527 ** replace(replace(<input>, '\n', char(10), '\r', char(13));
12528 **
12529 ** Or, if the first character of the input is not "'", then a copy
12530 ** of the input is returned.
12531 */
12532 static void shellEscapeCrnl(
12533 sqlite3_context *context,
12534 int argc,
12535 sqlite3_value **argv
12536 ){
12537 const char *zText = (const char*)sqlite3_value_text(argv[0]);
12538 UNUSED_PARAMETER(argc);
12539 if( zText[0]=='\'' ){
12540 int nText = sqlite3_value_bytes(argv[0]);
12541 int i;
12542 char zBuf1[20];
12543 char zBuf2[20];
12544 const char *zNL = 0;
12545 const char *zCR = 0;
12546 int nCR = 0;
12547 int nNL = 0;
12548
12549 for(i=0; zText[i]; i++){
12550 if( zNL==0 && zText[i]=='\n' ){
12551 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
12552 nNL = (int)strlen(zNL);
12553 }
12554 if( zCR==0 && zText[i]=='\r' ){
12555 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
12556 nCR = (int)strlen(zCR);
12557 }
12558 }
12559
12560 if( zNL || zCR ){
12561 int iOut = 0;
12562 i64 nMax = (nNL > nCR) ? nNL : nCR;
12563 i64 nAlloc = nMax * nText + (nMax+64)*2;
12564 char *zOut = (char*)sqlite3_malloc64(nAlloc);
12565 if( zOut==0 ){
12566 sqlite3_result_error_nomem(context);
12567 return;
12568 }
12569
12570 if( zNL && zCR ){
12571 memcpy(&zOut[iOut], "replace(replace(", 16);
12572 iOut += 16;
12573 }else{
12574 memcpy(&zOut[iOut], "replace(", 8);
12575 iOut += 8;
12576 }
12577 for(i=0; zText[i]; i++){
12578 if( zText[i]=='\n' ){
12579 memcpy(&zOut[iOut], zNL, nNL);
12580 iOut += nNL;
12581 }else if( zText[i]=='\r' ){
12582 memcpy(&zOut[iOut], zCR, nCR);
12583 iOut += nCR;
12584 }else{
12585 zOut[iOut] = zText[i];
12586 iOut++;
12587 }
12588 }
12589
12590 if( zNL ){
12591 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
12592 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
12593 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
12594 }
12595 if( zCR ){
12596 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
12597 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
12598 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
12599 }
12600
12601 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
12602 sqlite3_free(zOut);
12603 return;
12604 }
12605 }
12606
12607 sqlite3_result_value(context, argv[0]);
12608 }
12609
12610 /* Flags for open_db().
12611 **
12612 ** The default behavior of open_db() is to exit(1) if the database fails to
12613 ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
@@ -11614,10 +12673,13 @@
12673 sqlite3_enable_load_extension(p->db, 1);
12674 #endif
12675 sqlite3_fileio_init(p->db, 0, 0);
12676 sqlite3_shathree_init(p->db, 0, 0);
12677 sqlite3_completion_init(p->db, 0, 0);
12678 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
12679 sqlite3_dbdata_init(p->db, 0, 0);
12680 #endif
12681 #ifdef SQLITE_HAVE_ZLIB
12682 sqlite3_zipfile_init(p->db, 0, 0);
12683 sqlite3_sqlar_init(p->db, 0, 0);
12684 #endif
12685 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
@@ -11624,10 +12686,14 @@
12686 shellAddSchemaName, 0, 0);
12687 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
12688 shellModuleSchema, 0, 0);
12689 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
12690 shellPutsFunc, 0, 0);
12691 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
12692 shellEscapeCrnl, 0, 0);
12693 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
12694 shellInt32, 0, 0);
12695 #ifndef SQLITE_NOHAVE_SYSTEM
12696 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
12697 editFunc, 0, 0);
12698 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
12699 editFunc, 0, 0);
@@ -11647,11 +12713,10 @@
12713 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
12714 aData = (unsigned char*)readFile(p->zDbFilename, &nData);
12715 }else{
12716 aData = readHexDb(p, &nData);
12717 if( aData==0 ){
 
12718 return;
12719 }
12720 }
12721 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
12722 SQLITE_DESERIALIZE_RESIZEABLE |
@@ -12390,20 +13455,31 @@
13455 { "number of views:",
13456 "SELECT count(*) FROM %s WHERE type='view'" },
13457 { "schema size:",
13458 "SELECT total(length(sql)) FROM %s" },
13459 };
13460 int i, rc;
13461 unsigned iDataVersion;
13462 char *zSchemaTab;
13463 char *zDb = nArg>=2 ? azArg[1] : "main";
13464 sqlite3_stmt *pStmt = 0;
13465 unsigned char aHdr[100];
13466 open_db(p, 0);
13467 if( p->db==0 ) return 1;
13468 rc = sqlite3_prepare_v2(p->db,
13469 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
13470 -1, &pStmt, 0);
13471 if( rc ){
13472 if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
13473 utf8_printf(stderr, "the \".dbinfo\" command requires the "
13474 "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
13475 }else{
13476 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
13477 }
13478 sqlite3_finalize(pStmt);
13479 return 1;
13480 }
13481 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
13482 if( sqlite3_step(pStmt)==SQLITE_ROW
13483 && sqlite3_column_bytes(pStmt,0)>100
13484 ){
13485 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
@@ -12867,14 +13943,11 @@
13943 raw_printf(stderr, "Where sub-commands are:\n");
13944 raw_printf(stderr, " fkey-indexes\n");
13945 return SQLITE_ERROR;
13946 }
13947
13948 #if !defined SQLITE_OMIT_VIRTUALTABLE
 
 
 
13949 static void shellPrepare(
13950 sqlite3 *db,
13951 int *pRc,
13952 const char *zSql,
13953 sqlite3_stmt **ppStmt
@@ -12889,11 +13962,18 @@
13962 *pRc = rc;
13963 }
13964 }
13965 }
13966
13967 /*
13968 ** Create a prepared statement using printf-style arguments for the SQL.
13969 **
13970 ** This routine is could be marked "static". But it is not always used,
13971 ** depending on compile-time options. By omitting the "static", we avoid
13972 ** nuisance compiler warnings about "defined but not used".
13973 */
13974 void shellPreparePrintf(
13975 sqlite3 *db,
13976 int *pRc,
13977 sqlite3_stmt **ppStmt,
13978 const char *zFmt,
13979 ...
@@ -12912,11 +13992,17 @@
13992 sqlite3_free(z);
13993 }
13994 }
13995 }
13996
13997 /* Finalize the prepared statement created using shellPreparePrintf().
13998 **
13999 ** This routine is could be marked "static". But it is not always used,
14000 ** depending on compile-time options. By omitting the "static", we avoid
14001 ** nuisance compiler warnings about "defined but not used".
14002 */
14003 void shellFinalize(
14004 int *pRc,
14005 sqlite3_stmt *pStmt
14006 ){
14007 if( pStmt ){
14008 sqlite3 *db = sqlite3_db_handle(pStmt);
@@ -12928,11 +14014,17 @@
14014 *pRc = rc;
14015 }
14016 }
14017 }
14018
14019 /* Reset the prepared statement created using shellPreparePrintf().
14020 **
14021 ** This routine is could be marked "static". But it is not always used,
14022 ** depending on compile-time options. By omitting the "static", we avoid
14023 ** nuisance compiler warnings about "defined but not used".
14024 */
14025 void shellReset(
14026 int *pRc,
14027 sqlite3_stmt *pStmt
14028 ){
14029 int rc = sqlite3_reset(pStmt);
14030 if( *pRc==SQLITE_OK ){
@@ -12941,10 +14033,16 @@
14033 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
14034 }
14035 *pRc = rc;
14036 }
14037 }
14038 #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
14039
14040 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
14041 /*********************************************************************************
14042 ** The ".archive" or ".ar" command.
14043 */
14044 /*
14045 ** Structure representing a single ".ar" command.
14046 */
14047 typedef struct ArCommand ArCommand;
14048 struct ArCommand {
@@ -12993,30 +14091,32 @@
14091
14092 /*
14093 ** Values for ArCommand.eCmd.
14094 */
14095 #define AR_CMD_CREATE 1
14096 #define AR_CMD_UPDATE 2
14097 #define AR_CMD_INSERT 3
14098 #define AR_CMD_EXTRACT 4
14099 #define AR_CMD_LIST 5
14100 #define AR_CMD_HELP 6
14101
14102 /*
14103 ** Other (non-command) switches.
14104 */
14105 #define AR_SWITCH_VERBOSE 7
14106 #define AR_SWITCH_FILE 8
14107 #define AR_SWITCH_DIRECTORY 9
14108 #define AR_SWITCH_APPEND 10
14109 #define AR_SWITCH_DRYRUN 11
14110
14111 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
14112 switch( eSwitch ){
14113 case AR_CMD_CREATE:
14114 case AR_CMD_EXTRACT:
14115 case AR_CMD_LIST:
14116 case AR_CMD_UPDATE:
14117 case AR_CMD_INSERT:
14118 case AR_CMD_HELP:
14119 if( pAr->eCmd ){
14120 return arErrorMsg(pAr, "multiple command options");
14121 }
14122 pAr->eCmd = eSwitch;
@@ -13059,10 +14159,11 @@
14159 u8 eSwitch;
14160 u8 bArg;
14161 } aSwitch[] = {
14162 { "create", 'c', AR_CMD_CREATE, 0 },
14163 { "extract", 'x', AR_CMD_EXTRACT, 0 },
14164 { "insert", 'i', AR_CMD_INSERT, 0 },
14165 { "list", 't', AR_CMD_LIST, 0 },
14166 { "update", 'u', AR_CMD_UPDATE, 0 },
14167 { "help", 'h', AR_CMD_HELP, 0 },
14168 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
14169 { "file", 'f', AR_SWITCH_FILE, 1 },
@@ -13394,23 +14495,31 @@
14495 return rc;
14496 }
14497
14498
14499 /*
14500 ** Implementation of .ar "create", "insert", and "update" commands.
14501 **
14502 ** create -> Create a new SQL archive
14503 ** insert -> Insert or reinsert all files listed
14504 ** update -> Insert files that have changed or that were not
14505 ** previously in the archive
14506 **
14507 ** Create the "sqlar" table in the database if it does not already exist.
14508 ** Then add each file in the azFile[] array to the archive. Directories
14509 ** are added recursively. If argument bVerbose is non-zero, a message is
14510 ** printed on stdout for each file archived.
14511 **
14512 ** The create command is the same as update, except that it drops
14513 ** any existing "sqlar" table before beginning. The "insert" command
14514 ** always overwrites every file named on the command-line, where as
14515 ** "update" only overwrites if the size or mtime or mode has changed.
14516 */
14517 static int arCreateOrUpdateCommand(
14518 ArCommand *pAr, /* Command arguments and options */
14519 int bUpdate, /* true for a --create. */
14520 int bOnlyIfChanged /* Only update if file has changed */
14521 ){
14522 const char *zCreate =
14523 "CREATE TABLE IF NOT EXISTS sqlar(\n"
14524 " name TEXT PRIMARY KEY, -- name of the file\n"
14525 " mode INT, -- access permissions\n"
@@ -13428,26 +14537,28 @@
14537 " CASE substr(lsmode(mode),1,1)\n"
14538 " WHEN '-' THEN length(data)\n"
14539 " WHEN 'd' THEN 0\n"
14540 " ELSE -1 END,\n"
14541 " sqlar_compress(data)\n"
14542 " FROM fsdir(%Q,%Q) AS disk\n"
14543 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
14544 ,
14545 "REPLACE INTO %s(name,mode,mtime,data)\n"
14546 " SELECT\n"
14547 " %s,\n"
14548 " mode,\n"
14549 " mtime,\n"
14550 " data\n"
14551 " FROM fsdir(%Q,%Q) AS disk\n"
14552 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
14553 };
14554 int i; /* For iterating through azFile[] */
14555 int rc; /* Return code */
14556 const char *zTab = 0; /* SQL table into which to insert */
14557 char *zSql;
14558 char zTemp[50];
14559 char *zExists = 0;
14560
14561 arExecSql(pAr, "PRAGMA page_size=512");
14562 rc = arExecSql(pAr, "SAVEPOINT ar;");
14563 if( rc!=SQLITE_OK ) return rc;
14564 zTemp[0] = 0;
@@ -13474,14 +14585,25 @@
14585 rc = arExecSql(pAr, zDrop);
14586 if( rc!=SQLITE_OK ) goto end_ar_transaction;
14587 }
14588 rc = arExecSql(pAr, zCreate);
14589 }
14590 if( bOnlyIfChanged ){
14591 zExists = sqlite3_mprintf(
14592 " AND NOT EXISTS("
14593 "SELECT 1 FROM %s AS mem"
14594 " WHERE mem.name=disk.name"
14595 " AND mem.mtime=disk.mtime"
14596 " AND mem.mode=disk.mode)", zTab);
14597 }else{
14598 zExists = sqlite3_mprintf("");
14599 }
14600 if( zExists==0 ) rc = SQLITE_NOMEM;
14601 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
14602 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
14603 pAr->bVerbose ? "shell_putsnl(name)" : "name",
14604 pAr->azArg[i], pAr->zDir, zExists);
14605 rc = arExecSql(pAr, zSql2);
14606 sqlite3_free(zSql2);
14607 }
14608 end_ar_transaction:
14609 if( rc!=SQLITE_OK ){
@@ -13492,10 +14614,11 @@
14614 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
14615 arExecSql(pAr, zSql);
14616 sqlite3_free(zSql);
14617 }
14618 }
14619 sqlite3_free(zExists);
14620 return rc;
14621 }
14622
14623 /*
14624 ** Implementation of ".ar" dot command.
@@ -13530,11 +14653,12 @@
14653 }
14654 cmd.bZip = 1;
14655 }else if( cmd.zFile ){
14656 int flags;
14657 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
14658 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
14659 || cmd.eCmd==AR_CMD_UPDATE ){
14660 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
14661 }else{
14662 flags = SQLITE_OPEN_READONLY;
14663 }
14664 cmd.db = 0;
@@ -13567,11 +14691,11 @@
14691 cmd.zSrcTable = sqlite3_mprintf("sqlar");
14692 }
14693
14694 switch( cmd.eCmd ){
14695 case AR_CMD_CREATE:
14696 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
14697 break;
14698
14699 case AR_CMD_EXTRACT:
14700 rc = arExtractCommand(&cmd);
14701 break;
@@ -13582,13 +14706,17 @@
14706
14707 case AR_CMD_HELP:
14708 arUsage(pState->out);
14709 break;
14710
14711 case AR_CMD_INSERT:
14712 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
14713 break;
14714
14715 default:
14716 assert( cmd.eCmd==AR_CMD_UPDATE );
14717 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
14718 break;
14719 }
14720 }
14721 end_ar_command:
14722 if( cmd.db!=pState->db ){
@@ -13600,10 +14728,639 @@
14728 }
14729 /* End of the ".archive" or ".ar" command logic
14730 **********************************************************************************/
14731 #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
14732
14733 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
14734 /*
14735 ** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
14736 ** Otherwise, the SQL statement or statements in zSql are executed using
14737 ** database connection db and the error code written to *pRc before
14738 ** this function returns.
14739 */
14740 static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
14741 int rc = *pRc;
14742 if( rc==SQLITE_OK ){
14743 char *zErr = 0;
14744 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
14745 if( rc!=SQLITE_OK ){
14746 raw_printf(stderr, "SQL error: %s\n", zErr);
14747 }
14748 *pRc = rc;
14749 }
14750 }
14751
14752 /*
14753 ** Like shellExec(), except that zFmt is a printf() style format string.
14754 */
14755 static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
14756 char *z = 0;
14757 if( *pRc==SQLITE_OK ){
14758 va_list ap;
14759 va_start(ap, zFmt);
14760 z = sqlite3_vmprintf(zFmt, ap);
14761 va_end(ap);
14762 if( z==0 ){
14763 *pRc = SQLITE_NOMEM;
14764 }else{
14765 shellExec(db, pRc, z);
14766 }
14767 sqlite3_free(z);
14768 }
14769 }
14770
14771 /*
14772 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
14773 ** Otherwise, an attempt is made to allocate, zero and return a pointer
14774 ** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
14775 ** to SQLITE_NOMEM and NULL returned.
14776 */
14777 static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
14778 void *pRet = 0;
14779 if( *pRc==SQLITE_OK ){
14780 pRet = sqlite3_malloc64(nByte);
14781 if( pRet==0 ){
14782 *pRc = SQLITE_NOMEM;
14783 }else{
14784 memset(pRet, 0, nByte);
14785 }
14786 }
14787 return pRet;
14788 }
14789
14790 /*
14791 ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
14792 ** Otherwise, zFmt is treated as a printf() style string. The result of
14793 ** formatting it along with any trailing arguments is written into a
14794 ** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
14795 ** It is the responsibility of the caller to eventually free this buffer
14796 ** using a call to sqlite3_free().
14797 **
14798 ** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
14799 ** pointer returned.
14800 */
14801 static char *shellMPrintf(int *pRc, const char *zFmt, ...){
14802 char *z = 0;
14803 if( *pRc==SQLITE_OK ){
14804 va_list ap;
14805 va_start(ap, zFmt);
14806 z = sqlite3_vmprintf(zFmt, ap);
14807 va_end(ap);
14808 if( z==0 ){
14809 *pRc = SQLITE_NOMEM;
14810 }
14811 }
14812 return z;
14813 }
14814
14815 /*
14816 ** When running the ".recover" command, each output table, and the special
14817 ** orphaned row table if it is required, is represented by an instance
14818 ** of the following struct.
14819 */
14820 typedef struct RecoverTable RecoverTable;
14821 struct RecoverTable {
14822 char *zQuoted; /* Quoted version of table name */
14823 int nCol; /* Number of columns in table */
14824 char **azlCol; /* Array of column lists */
14825 int iPk; /* Index of IPK column */
14826 };
14827
14828 /*
14829 ** Free a RecoverTable object allocated by recoverFindTable() or
14830 ** recoverOrphanTable().
14831 */
14832 static void recoverFreeTable(RecoverTable *pTab){
14833 if( pTab ){
14834 sqlite3_free(pTab->zQuoted);
14835 if( pTab->azlCol ){
14836 int i;
14837 for(i=0; i<=pTab->nCol; i++){
14838 sqlite3_free(pTab->azlCol[i]);
14839 }
14840 sqlite3_free(pTab->azlCol);
14841 }
14842 sqlite3_free(pTab);
14843 }
14844 }
14845
14846 /*
14847 ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
14848 ** Otherwise, it allocates and returns a RecoverTable object based on the
14849 ** final four arguments passed to this function. It is the responsibility
14850 ** of the caller to eventually free the returned object using
14851 ** recoverFreeTable().
14852 */
14853 static RecoverTable *recoverNewTable(
14854 int *pRc, /* IN/OUT: Error code */
14855 const char *zName, /* Name of table */
14856 const char *zSql, /* CREATE TABLE statement */
14857 int bIntkey,
14858 int nCol
14859 ){
14860 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
14861 int rc = *pRc;
14862 RecoverTable *pTab = 0;
14863
14864 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
14865 if( rc==SQLITE_OK ){
14866 int nSqlCol = 0;
14867 int bSqlIntkey = 0;
14868 sqlite3_stmt *pStmt = 0;
14869
14870 rc = sqlite3_open("", &dbtmp);
14871 if( rc==SQLITE_OK ){
14872 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
14873 }
14874 if( rc==SQLITE_OK ){
14875 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
14876 if( rc==SQLITE_ERROR ){
14877 rc = SQLITE_OK;
14878 goto finished;
14879 }
14880 }
14881 shellPreparePrintf(dbtmp, &rc, &pStmt,
14882 "SELECT count(*) FROM pragma_table_info(%Q)", zName
14883 );
14884 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14885 nSqlCol = sqlite3_column_int(pStmt, 0);
14886 }
14887 shellFinalize(&rc, pStmt);
14888
14889 if( rc!=SQLITE_OK || nSqlCol<nCol ){
14890 goto finished;
14891 }
14892
14893 shellPreparePrintf(dbtmp, &rc, &pStmt,
14894 "SELECT ("
14895 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
14896 ") FROM sqlite_master WHERE name = %Q", zName
14897 );
14898 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14899 bSqlIntkey = sqlite3_column_int(pStmt, 0);
14900 }
14901 shellFinalize(&rc, pStmt);
14902
14903 if( bIntkey==bSqlIntkey ){
14904 int i;
14905 const char *zPk = "_rowid_";
14906 sqlite3_stmt *pPkFinder = 0;
14907
14908 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
14909 ** set zPk to the name of the PK column, and pTab->iPk to the index
14910 ** of the column, where columns are 0-numbered from left to right.
14911 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
14912 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
14913 pTab->iPk = -2;
14914 if( bIntkey ){
14915 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
14916 "SELECT cid, name FROM pragma_table_info(%Q) "
14917 " WHERE pk=1 AND type='integer' COLLATE nocase"
14918 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
14919 , zName, zName
14920 );
14921 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
14922 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
14923 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
14924 }
14925 }
14926
14927 pTab->zQuoted = shellMPrintf(&rc, "%Q", zName);
14928 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
14929 pTab->nCol = nSqlCol;
14930
14931 if( bIntkey ){
14932 pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
14933 }else{
14934 pTab->azlCol[0] = shellMPrintf(&rc, "");
14935 }
14936 i = 1;
14937 shellPreparePrintf(dbtmp, &rc, &pStmt,
14938 "SELECT %Q || group_concat(name, ', ') "
14939 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
14940 "FROM pragma_table_info(%Q)",
14941 bIntkey ? ", " : "", pTab->iPk,
14942 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
14943 zName
14944 );
14945 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14946 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
14947 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
14948 i++;
14949 }
14950 shellFinalize(&rc, pStmt);
14951
14952 shellFinalize(&rc, pPkFinder);
14953 }
14954 }
14955
14956 finished:
14957 sqlite3_close(dbtmp);
14958 *pRc = rc;
14959 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
14960 recoverFreeTable(pTab);
14961 pTab = 0;
14962 }
14963 return pTab;
14964 }
14965
14966 /*
14967 ** This function is called to search the schema recovered from the
14968 ** sqlite_master table of the (possibly) corrupt database as part
14969 ** of a ".recover" command. Specifically, for a table with root page
14970 ** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
14971 ** table must be a WITHOUT ROWID table, or if non-zero, not one of
14972 ** those.
14973 **
14974 ** If a table is found, a (RecoverTable*) object is returned. Or, if
14975 ** no such table is found, but bIntkey is false and iRoot is the
14976 ** root page of an index in the recovered schema, then (*pbNoop) is
14977 ** set to true and NULL returned. Or, if there is no such table or
14978 ** index, NULL is returned and (*pbNoop) set to 0, indicating that
14979 ** the caller should write data to the orphans table.
14980 */
14981 static RecoverTable *recoverFindTable(
14982 ShellState *pState, /* Shell state object */
14983 int *pRc, /* IN/OUT: Error code */
14984 int iRoot, /* Root page of table */
14985 int bIntkey, /* True for an intkey table */
14986 int nCol, /* Number of columns in table */
14987 int *pbNoop /* OUT: True if iRoot is root of index */
14988 ){
14989 sqlite3_stmt *pStmt = 0;
14990 RecoverTable *pRet = 0;
14991 int bNoop = 0;
14992 const char *zSql = 0;
14993 const char *zName = 0;
14994
14995 /* Search the recovered schema for an object with root page iRoot. */
14996 shellPreparePrintf(pState->db, pRc, &pStmt,
14997 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
14998 );
14999 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15000 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
15001 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
15002 bNoop = 1;
15003 break;
15004 }
15005 if( sqlite3_stricmp(zType, "table")==0 ){
15006 zName = (const char*)sqlite3_column_text(pStmt, 1);
15007 zSql = (const char*)sqlite3_column_text(pStmt, 2);
15008 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
15009 break;
15010 }
15011 }
15012
15013 shellFinalize(pRc, pStmt);
15014 *pbNoop = bNoop;
15015 return pRet;
15016 }
15017
15018 /*
15019 ** Return a RecoverTable object representing the orphans table.
15020 */
15021 static RecoverTable *recoverOrphanTable(
15022 ShellState *pState, /* Shell state object */
15023 int *pRc, /* IN/OUT: Error code */
15024 const char *zLostAndFound, /* Base name for orphans table */
15025 int nCol /* Number of user data columns */
15026 ){
15027 RecoverTable *pTab = 0;
15028 if( nCol>=0 && *pRc==SQLITE_OK ){
15029 int i;
15030
15031 /* This block determines the name of the orphan table. The prefered
15032 ** name is zLostAndFound. But if that clashes with another name
15033 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
15034 ** and so on until a non-clashing name is found. */
15035 int iTab = 0;
15036 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
15037 sqlite3_stmt *pTest = 0;
15038 shellPrepare(pState->db, pRc,
15039 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
15040 );
15041 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
15042 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
15043 shellReset(pRc, pTest);
15044 sqlite3_free(zTab);
15045 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
15046 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
15047 }
15048 shellFinalize(pRc, pTest);
15049
15050 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
15051 if( pTab ){
15052 pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab);
15053 pTab->nCol = nCol;
15054 pTab->iPk = -2;
15055 if( nCol>0 ){
15056 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
15057 if( pTab->azlCol ){
15058 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
15059 for(i=nCol-1; i>=0; i--){
15060 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
15061 }
15062 }
15063 }
15064
15065 if( *pRc!=SQLITE_OK ){
15066 recoverFreeTable(pTab);
15067 pTab = 0;
15068 }else{
15069 raw_printf(pState->out,
15070 "CREATE TABLE %s(rootpgno INTEGER, "
15071 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
15072 );
15073 for(i=0; i<nCol; i++){
15074 raw_printf(pState->out, ", c%d", i);
15075 }
15076 raw_printf(pState->out, ");\n");
15077 }
15078 }
15079 sqlite3_free(zTab);
15080 }
15081 return pTab;
15082 }
15083
15084 /*
15085 ** This function is called to recover data from the database. A script
15086 ** to construct a new database containing all recovered data is output
15087 ** on stream pState->out.
15088 */
15089 static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
15090 int rc = SQLITE_OK;
15091 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
15092 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
15093 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
15094 const char *zRecoveryDb = ""; /* Name of "recovery" database */
15095 const char *zLostAndFound = "lost_and_found";
15096 int i;
15097 int nOrphan = -1;
15098 RecoverTable *pOrphan = 0;
15099
15100 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
15101 for(i=1; i<nArg; i++){
15102 char *z = azArg[i];
15103 int n;
15104 if( z[0]=='-' && z[1]=='-' ) z++;
15105 n = strlen(z);
15106 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
15107 bFreelist = 0;
15108 }else
15109 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
15110 i++;
15111 zRecoveryDb = azArg[i];
15112 }else
15113 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
15114 i++;
15115 zLostAndFound = azArg[i];
15116 }
15117 else{
15118 raw_printf(stderr, "unexpected option: %s\n", azArg[i]);
15119 raw_printf(stderr, "options are:\n");
15120 raw_printf(stderr, " --freelist-corrupt\n");
15121 raw_printf(stderr, " --recovery-db DATABASE\n");
15122 raw_printf(stderr, " --lost-and-found TABLE-NAME\n");
15123 return 1;
15124 }
15125 }
15126
15127 shellExecPrintf(pState->db, &rc,
15128 /* Attach an in-memory database named 'recovery'. Create an indexed
15129 ** cache of the sqlite_dbptr virtual table. */
15130 "ATTACH %Q AS recovery;"
15131 "DROP TABLE IF EXISTS recovery.dbptr;"
15132 "DROP TABLE IF EXISTS recovery.freelist;"
15133 "DROP TABLE IF EXISTS recovery.map;"
15134 "DROP TABLE IF EXISTS recovery.schema;"
15135 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
15136 );
15137
15138 if( bFreelist ){
15139 shellExec(pState->db, &rc,
15140 "WITH trunk(pgno) AS ("
15141 " SELECT shell_int32("
15142 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
15143 " WHERE x>0"
15144 " UNION"
15145 " SELECT shell_int32("
15146 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
15147 " FROM trunk WHERE x>0"
15148 "),"
15149 "freelist(data, n, freepgno) AS ("
15150 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
15151 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
15152 " UNION ALL"
15153 " SELECT data, n-1, shell_int32(data, 2+n) "
15154 " FROM freelist WHERE n>=0"
15155 ")"
15156 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
15157 );
15158 }
15159
15160 shellExec(pState->db, &rc,
15161 "CREATE TABLE recovery.dbptr("
15162 " pgno, child, PRIMARY KEY(child, pgno)"
15163 ") WITHOUT ROWID;"
15164 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
15165 " SELECT * FROM sqlite_dbptr"
15166 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
15167
15168 /* Delete any pointer to page 1. This ensures that page 1 is considered
15169 ** a root page, regardless of how corrupt the db is. */
15170 "DELETE FROM recovery.dbptr WHERE child = 1;"
15171
15172 /* Delete all pointers to any pages that have more than one pointer
15173 ** to them. Such pages will be treated as root pages when recovering
15174 ** data. */
15175 "DELETE FROM recovery.dbptr WHERE child IN ("
15176 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
15177 ");"
15178
15179 /* Create the "map" table that will (eventually) contain instructions
15180 ** for dealing with each page in the db that contains one or more
15181 ** records. */
15182 "CREATE TABLE recovery.map("
15183 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
15184 ");"
15185
15186 /* Populate table [map]. If there are circular loops of pages in the
15187 ** database, the following adds all pages in such a loop to the map
15188 ** as individual root pages. This could be handled better. */
15189 "WITH pages(i, maxlen) AS ("
15190 " SELECT page_count, ("
15191 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
15192 " ) FROM pragma_page_count WHERE page_count>0"
15193 " UNION ALL"
15194 " SELECT i-1, ("
15195 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
15196 " ) FROM pages WHERE i>=2"
15197 ")"
15198 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
15199 " SELECT i, maxlen, NULL, ("
15200 " WITH p(orig, pgno, parent) AS ("
15201 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
15202 " UNION "
15203 " SELECT i, p.parent, "
15204 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
15205 " )"
15206 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
15207 ") "
15208 "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"
15209 "UPDATE recovery.map AS o SET intkey = ("
15210 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
15211 ");"
15212
15213 /* Extract data from page 1 and any linked pages into table
15214 ** recovery.schema. With the same schema as an sqlite_master table. */
15215 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
15216 "INSERT INTO recovery.schema SELECT "
15217 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
15218 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
15219 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
15220 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
15221 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
15222 "FROM sqlite_dbdata WHERE pgno IN ("
15223 " SELECT pgno FROM recovery.map WHERE root=1"
15224 ")"
15225 "GROUP BY pgno, cell;"
15226 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
15227 );
15228
15229 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
15230 ** CREATE TABLE statements that extracted from the existing schema. */
15231 if( rc==SQLITE_OK ){
15232 sqlite3_stmt *pStmt = 0;
15233 raw_printf(pState->out, "BEGIN;\n");
15234 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
15235 shellPrepare(pState->db, &rc,
15236 "SELECT sql FROM recovery.schema "
15237 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
15238 );
15239 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15240 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
15241 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
15242 &zCreateTable[12]
15243 );
15244 }
15245 shellFinalize(&rc, pStmt);
15246 }
15247
15248 /* Figure out if an orphan table will be required. And if so, how many
15249 ** user columns it should contain */
15250 shellPrepare(pState->db, &rc,
15251 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
15252 , &pLoop
15253 );
15254 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
15255 nOrphan = sqlite3_column_int(pLoop, 0);
15256 }
15257 shellFinalize(&rc, pLoop);
15258 pLoop = 0;
15259
15260 shellPrepare(pState->db, &rc,
15261 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
15262 );
15263 shellPrepare(pState->db, &rc,
15264 "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')"
15265 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
15266 "GROUP BY cell", &pCells
15267 );
15268
15269 /* Loop through each root page. */
15270 shellPrepare(pState->db, &rc,
15271 "SELECT root, intkey, max(maxlen) FROM recovery.map"
15272 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
15273 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
15274 ")", &pLoop
15275 );
15276 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
15277 int iRoot = sqlite3_column_int(pLoop, 0);
15278 int bIntkey = sqlite3_column_int(pLoop, 1);
15279 int nCol = sqlite3_column_int(pLoop, 2);
15280 int bNoop = 0;
15281 RecoverTable *pTab;
15282
15283 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
15284 if( bNoop || rc ) continue;
15285 if( pTab==0 ){
15286 if( pOrphan==0 ){
15287 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
15288 }
15289 pTab = pOrphan;
15290 if( pTab==0 ) break;
15291 }
15292
15293 if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){
15294 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
15295 }
15296 sqlite3_bind_int(pPages, 1, iRoot);
15297 sqlite3_bind_int(pCells, 2, pTab->iPk);
15298
15299 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
15300 int iPgno = sqlite3_column_int(pPages, 0);
15301 sqlite3_bind_int(pCells, 1, iPgno);
15302 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
15303 int nField = sqlite3_column_int(pCells, 0);
15304 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
15305
15306 nField = nField+1;
15307 if( pTab==pOrphan ){
15308 raw_printf(pState->out,
15309 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
15310 pTab->zQuoted, iRoot, iPgno, nField,
15311 bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField]
15312 );
15313 }else{
15314 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
15315 pTab->zQuoted, pTab->azlCol[nField], zVal
15316 );
15317 }
15318 }
15319 shellReset(&rc, pCells);
15320 }
15321 shellReset(&rc, pPages);
15322 if( pTab!=pOrphan ) recoverFreeTable(pTab);
15323 }
15324 shellFinalize(&rc, pLoop);
15325 shellFinalize(&rc, pPages);
15326 shellFinalize(&rc, pCells);
15327 recoverFreeTable(pOrphan);
15328
15329 /* The rest of the schema */
15330 if( rc==SQLITE_OK ){
15331 sqlite3_stmt *pStmt = 0;
15332 shellPrepare(pState->db, &rc,
15333 "SELECT sql, name FROM recovery.schema "
15334 "WHERE sql NOT LIKE 'create table%'", &pStmt
15335 );
15336 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15337 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
15338 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
15339 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
15340 char *zPrint = shellMPrintf(&rc,
15341 "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)",
15342 zName, zName, zSql
15343 );
15344 raw_printf(pState->out, "%s;\n", zPrint);
15345 sqlite3_free(zPrint);
15346 }else{
15347 raw_printf(pState->out, "%s;\n", zSql);
15348 }
15349 }
15350 shellFinalize(&rc, pStmt);
15351 }
15352
15353 if( rc==SQLITE_OK ){
15354 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
15355 raw_printf(pState->out, "COMMIT;\n");
15356 }
15357 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
15358 return rc;
15359 }
15360 #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
15361
15362
15363 /*
15364 ** If an input line begins with "." then invoke this routine to
15365 ** process that line.
15366 **
@@ -13887,10 +15644,17 @@
15644
15645 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
15646 rc = shell_dbinfo_command(p, nArg, azArg);
15647 }else
15648
15649 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
15650 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
15651 open_db(p, 0);
15652 rc = recoverDatabaseCmd(p, nArg, azArg);
15653 }else
15654 #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
15655
15656 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
15657 const char *zLike = 0;
15658 int i;
15659 int savedShowHeader = p->showHeader;
15660 int savedShellFlags = p->shellFlgs;
@@ -13924,11 +15688,13 @@
15688 goto meta_command_exit;
15689 }else{
15690 zLike = azArg[i];
15691 }
15692 }
15693
15694 open_db(p, 0);
15695
15696 /* When playing back a "dump", the content might appear in an order
15697 ** which causes immediate foreign key constraints to be violated.
15698 ** So disable foreign-key constraint enforcement to prevent problems. */
15699 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
15700 raw_printf(p->out, "BEGIN TRANSACTION;\n");
@@ -13972,11 +15738,11 @@
15738 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
15739 p->writableSchema = 0;
15740 }
15741 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
15742 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
15743 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
15744 p->showHeader = savedShowHeader;
15745 p->shellFlgs = savedShellFlags;
15746 }else
15747
15748 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
@@ -14708,10 +16474,118 @@
16474 } else {
16475 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
16476 }
16477 }
16478 }else
16479
16480 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
16481 open_db(p,0);
16482 if( nArg<=1 ) goto parameter_syntax_error;
16483
16484 /* .parameter clear
16485 ** Clear all bind parameters by dropping the TEMP table that holds them.
16486 */
16487 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
16488 int wrSchema = 0;
16489 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
16490 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
16491 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
16492 0, 0, 0);
16493 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
16494 }else
16495
16496 /* .parameter list
16497 ** List all bind parameters.
16498 */
16499 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
16500 sqlite3_stmt *pStmt = 0;
16501 int rx;
16502 int len = 0;
16503 rx = sqlite3_prepare_v2(p->db,
16504 "SELECT max(length(key)) "
16505 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
16506 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
16507 len = sqlite3_column_int(pStmt, 0);
16508 if( len>40 ) len = 40;
16509 }
16510 sqlite3_finalize(pStmt);
16511 pStmt = 0;
16512 if( len ){
16513 rx = sqlite3_prepare_v2(p->db,
16514 "SELECT key, quote(value) "
16515 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
16516 while( sqlite3_step(pStmt)==SQLITE_ROW ){
16517 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
16518 sqlite3_column_text(pStmt,1));
16519 }
16520 sqlite3_finalize(pStmt);
16521 }
16522 }else
16523
16524 /* .parameter init
16525 ** Make sure the TEMP table used to hold bind parameters exists.
16526 ** Create it if necessary.
16527 */
16528 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
16529 bind_table_init(p);
16530 }else
16531
16532 /* .parameter set NAME VALUE
16533 ** Set or reset a bind parameter. NAME should be the full parameter
16534 ** name exactly as it appears in the query. (ex: $abc, @def). The
16535 ** VALUE can be in either SQL literal notation, or if not it will be
16536 ** understood to be a text string.
16537 */
16538 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
16539 int rx;
16540 char *zSql;
16541 sqlite3_stmt *pStmt;
16542 const char *zKey = azArg[2];
16543 const char *zValue = azArg[3];
16544 bind_table_init(p);
16545 zSql = sqlite3_mprintf(
16546 "REPLACE INTO temp.sqlite_parameters(key,value)"
16547 "VALUES(%Q,%s);", zKey, zValue);
16548 if( zSql==0 ) shell_out_of_memory();
16549 pStmt = 0;
16550 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16551 sqlite3_free(zSql);
16552 if( rx!=SQLITE_OK ){
16553 sqlite3_finalize(pStmt);
16554 pStmt = 0;
16555 zSql = sqlite3_mprintf(
16556 "REPLACE INTO temp.sqlite_parameters(key,value)"
16557 "VALUES(%Q,%Q);", zKey, zValue);
16558 if( zSql==0 ) shell_out_of_memory();
16559 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16560 sqlite3_free(zSql);
16561 if( rx!=SQLITE_OK ){
16562 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
16563 sqlite3_finalize(pStmt);
16564 pStmt = 0;
16565 rc = 1;
16566 }
16567 }
16568 sqlite3_step(pStmt);
16569 sqlite3_finalize(pStmt);
16570 }else
16571
16572 /* .parameter unset NAME
16573 ** Remove the NAME binding from the parameter binding table, if it
16574 ** exists.
16575 */
16576 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
16577 char *zSql = sqlite3_mprintf(
16578 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
16579 if( zSql==0 ) shell_out_of_memory();
16580 sqlite3_exec(p->db, zSql, 0, 0, 0);
16581 sqlite3_free(zSql);
16582 }else
16583 /* If no command name matches, show a syntax error */
16584 parameter_syntax_error:
16585 showHelp(p->out, "parameter");
16586 }else
16587
16588 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
16589 int i;
16590 for(i=1; i<nArg; i++){
16591 if( i>1 ) raw_printf(p->out, " ");
16592
+10 -3
--- src/sitemap.c
+++ src/sitemap.c
@@ -193,15 +193,22 @@
193193
@ </ul>
194194
@ </li>
195195
}
196196
@ <li>Help
197197
@ <ul>
198
- @ <li>%z(href("%R/wiki_rules"))Wiki Formatting Rules</a></li>
199
- @ <li>%z(href("%R/md_rules"))Markdown Formatting Rules</a></li>
198
+ if( g.perm.Admin || g.perm.Write ||
199
+ g.perm.WrForum || g.perm.WrTForum ||
200
+ g.perm.NewWiki || g.perm.ApndWiki || g.perm.WrWiki || g.perm.ModWiki ||
201
+ g.perm.NewTkt || g.perm.ApndTkt || g.perm.WrTkt || g.perm.ModTkt ){
202
+ @ <li>%z(href("%R/wiki_rules"))Wiki Formatting Rules</a></li>
203
+ @ <li>%z(href("%R/md_rules"))Markdown Formatting Rules</a></li>
204
+ }
200205
@ <li>%z(href("%R/help"))List of All Commands and Web Pages</a></li>
201206
@ <li>%z(href("%R/test-all-help"))All "help" text on a single page</a></li>
202
- @ <li>%z(href("%R/mimetype_list"))Filename suffix to mimetype map</a></li>
207
+ if( g.perm.Admin || g.perm.Write || g.perm.WrUnver ){
208
+ @ <li>%z(href("%R/mimetype_list"))Filename suffix to MIME type map</a></li>
209
+ }
203210
@ </ul></li>
204211
if( g.perm.Admin ){
205212
@ <li>%z(href("%R/setup"))Administration Pages</a>
206213
@ <ul>
207214
@ <li>%z(href("%R/modreq"))Pending Moderation Requests</a></li>
208215
--- src/sitemap.c
+++ src/sitemap.c
@@ -193,15 +193,22 @@
193 @ </ul>
194 @ </li>
195 }
196 @ <li>Help
197 @ <ul>
198 @ <li>%z(href("%R/wiki_rules"))Wiki Formatting Rules</a></li>
199 @ <li>%z(href("%R/md_rules"))Markdown Formatting Rules</a></li>
 
 
 
 
 
200 @ <li>%z(href("%R/help"))List of All Commands and Web Pages</a></li>
201 @ <li>%z(href("%R/test-all-help"))All "help" text on a single page</a></li>
202 @ <li>%z(href("%R/mimetype_list"))Filename suffix to mimetype map</a></li>
 
 
203 @ </ul></li>
204 if( g.perm.Admin ){
205 @ <li>%z(href("%R/setup"))Administration Pages</a>
206 @ <ul>
207 @ <li>%z(href("%R/modreq"))Pending Moderation Requests</a></li>
208
--- src/sitemap.c
+++ src/sitemap.c
@@ -193,15 +193,22 @@
193 @ </ul>
194 @ </li>
195 }
196 @ <li>Help
197 @ <ul>
198 if( g.perm.Admin || g.perm.Write ||
199 g.perm.WrForum || g.perm.WrTForum ||
200 g.perm.NewWiki || g.perm.ApndWiki || g.perm.WrWiki || g.perm.ModWiki ||
201 g.perm.NewTkt || g.perm.ApndTkt || g.perm.WrTkt || g.perm.ModTkt ){
202 @ <li>%z(href("%R/wiki_rules"))Wiki Formatting Rules</a></li>
203 @ <li>%z(href("%R/md_rules"))Markdown Formatting Rules</a></li>
204 }
205 @ <li>%z(href("%R/help"))List of All Commands and Web Pages</a></li>
206 @ <li>%z(href("%R/test-all-help"))All "help" text on a single page</a></li>
207 if( g.perm.Admin || g.perm.Write || g.perm.WrUnver ){
208 @ <li>%z(href("%R/mimetype_list"))Filename suffix to MIME type map</a></li>
209 }
210 @ </ul></li>
211 if( g.perm.Admin ){
212 @ <li>%z(href("%R/setup"))Administration Pages</a>
213 @ <ul>
214 @ <li>%z(href("%R/modreq"))Pending Moderation Requests</a></li>
215
+5477 -3983
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.28.0. By combining all the individual C code files into this
3
+** version 3.29.0. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be