Fossil SCM

merge trunk

jan.nijtmans 2013-01-26 16:27 UTC allow-backslash-in-card-filename merge
Commit 013854ae7616e0ae0dd7ab64639c11a492e5ab3d
--- src/allrepo.c
+++ src/allrepo.c
@@ -144,10 +144,11 @@
144144
collect_argument(&extra, "compress");
145145
collect_argument(&extra, "noverify");
146146
collect_argument_value(&extra, "pagesize");
147147
collect_argument(&extra, "vacuum");
148148
collect_argument(&extra, "deanalyze");
149
+ collect_argument(&extra, "analyze");
149150
collect_argument(&extra, "wal");
150151
collect_argument(&extra, "stat");
151152
}else if( strncmp(zCmd, "sync", n)==0 ){
152153
zCmd = "sync -autourl -R";
153154
collect_argument(&extra, "verbose");
154155
--- src/allrepo.c
+++ src/allrepo.c
@@ -144,10 +144,11 @@
144 collect_argument(&extra, "compress");
145 collect_argument(&extra, "noverify");
146 collect_argument_value(&extra, "pagesize");
147 collect_argument(&extra, "vacuum");
148 collect_argument(&extra, "deanalyze");
 
149 collect_argument(&extra, "wal");
150 collect_argument(&extra, "stat");
151 }else if( strncmp(zCmd, "sync", n)==0 ){
152 zCmd = "sync -autourl -R";
153 collect_argument(&extra, "verbose");
154
--- src/allrepo.c
+++ src/allrepo.c
@@ -144,10 +144,11 @@
144 collect_argument(&extra, "compress");
145 collect_argument(&extra, "noverify");
146 collect_argument_value(&extra, "pagesize");
147 collect_argument(&extra, "vacuum");
148 collect_argument(&extra, "deanalyze");
149 collect_argument(&extra, "analyze");
150 collect_argument(&extra, "wal");
151 collect_argument(&extra, "stat");
152 }else if( strncmp(zCmd, "sync", n)==0 ){
153 zCmd = "sync -autourl -R";
154 collect_argument(&extra, "verbose");
155
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1,6 +1,9 @@
11
#ifdef FOSSIL_ENABLE_JSON
2
+#ifndef CSON_FOSSIL_MODE
3
+#define CSON_FOSSIL_MODE
4
+#endif
25
/* auto-generated! Do not edit! */
36
/* begin file include/wh/cson/cson.h */
47
#if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
58
#define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
69
710
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1,6 +1,9 @@
1 #ifdef FOSSIL_ENABLE_JSON
 
 
 
2 /* auto-generated! Do not edit! */
3 /* begin file include/wh/cson/cson.h */
4 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
5 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
6
7
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1,6 +1,9 @@
1 #ifdef FOSSIL_ENABLE_JSON
2 #ifndef CSON_FOSSIL_MODE
3 #define CSON_FOSSIL_MODE
4 #endif
5 /* auto-generated! Do not edit! */
6 /* begin file include/wh/cson/cson.h */
7 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
8 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
9
10
+42 -46
--- src/db.c
+++ src/db.c
@@ -484,20 +484,30 @@
484484
/*
485485
** Execute multiple SQL statements.
486486
*/
487487
int db_multi_exec(const char *zSql, ...){
488488
Blob sql;
489
- int rc;
489
+ int rc = SQLITE_OK;
490490
va_list ap;
491
- char *zErr = 0;
491
+ const char *z, *zEnd;
492
+ sqlite3_stmt *pStmt;
492493
blob_init(&sql, 0, 0);
493494
va_start(ap, zSql);
494495
blob_vappendf(&sql, zSql, ap);
495496
va_end(ap);
496
- rc = sqlite3_exec(g.db, blob_buffer(&sql), 0, 0, &zErr);
497
- if( rc!=SQLITE_OK ){
498
- db_err("%s\n%s", zErr, blob_buffer(&sql));
497
+ z = blob_str(&sql);
498
+ while( rc==SQLITE_OK && z[0] ){
499
+ pStmt = 0;
500
+ rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd);
501
+ if( rc!=SQLITE_OK ) break;
502
+ if( pStmt ){
503
+ db.nPrepare++;
504
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){}
505
+ rc = sqlite3_finalize(pStmt);
506
+ if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z);
507
+ }
508
+ z = zEnd;
499509
}
500510
blob_reset(&sql);
501511
return rc;
502512
}
503513
@@ -642,15 +652,11 @@
642652
sqlite3 *db;
643653
int rc;
644654
const char *zSql;
645655
va_list ap;
646656
647
- rc = sqlite3_open(zFileName, &db);
648
- if( rc!=SQLITE_OK ){
649
- db_err("[%s] %s", zFileName, sqlite3_errmsg(db));
650
- }
651
- sqlite3_busy_timeout(db, 5000);
657
+ db = db_open(zFileName);
652658
sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
653659
rc = sqlite3_exec(db, zSchema, 0, 0, 0);
654660
if( rc!=SQLITE_OK ){
655661
db_err(sqlite3_errmsg(db));
656662
}
@@ -697,11 +703,11 @@
697703
698704
/*
699705
** Open a database file. Return a pointer to the new database
700706
** connection. An error results in process abort.
701707
*/
702
-static sqlite3 *openDatabase(const char *zDbName){
708
+LOCAL sqlite3 *db_open(const char *zDbName){
703709
int rc;
704710
const char *zVfs;
705711
sqlite3 *db;
706712
707713
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
@@ -717,10 +723,23 @@
717723
sqlite3_busy_timeout(db, 5000);
718724
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
719725
sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
720726
sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
721727
db_checkin_mtime_function, 0, 0);
728
+ sqlite3_create_function(db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
729
+ sqlite3_create_function(db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
730
+ sqlite3_create_function(db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
731
+ sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
732
+ sqlite3_create_function(
733
+ db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
734
+ );
735
+ sqlite3_create_function(
736
+ db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
737
+ );
738
+ if( g.fSqlTrace ) sqlite3_trace(db, db_sql_trace, 0);
739
+ re_add_sql_func(db);
740
+ sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
722741
return db;
723742
}
724743
725744
726745
/*
@@ -748,13 +767,12 @@
748767
const char *zLabel,
749768
int *pWasAttached
750769
){
751770
if( !g.db ){
752771
assert( g.zMainDbType==0 );
753
- g.db = openDatabase(zDbName);
772
+ g.db = db_open(zDbName);
754773
g.zMainDbType = zLabel;
755
- db_connection_init();
756774
if ( pWasAttached ) *pWasAttached = 0;
757775
}else{
758776
assert( g.zMainDbType!=0 );
759777
db_attach(zDbName, zLabel);
760778
if ( pWasAttached ) *pWasAttached = 1;
@@ -821,11 +839,11 @@
821839
db_open_or_attach(zDbName, "configdb", &g.useAttach);
822840
g.dbConfig = 0;
823841
g.zConfigDbType = 0;
824842
}else{
825843
g.useAttach = 0;
826
- g.dbConfig = openDatabase(zDbName);
844
+ g.dbConfig = db_open(zDbName);
827845
g.zConfigDbType = "configdb";
828846
}
829847
g.configOpen = 1;
830848
free(zDbName);
831849
}
@@ -1445,11 +1463,11 @@
14451463
** SQL functions for debugging.
14461464
**
14471465
** The print() function writes its arguments on stdout, but only
14481466
** if the -sqlprint command-line option is turned on.
14491467
*/
1450
-static void db_sql_print(
1468
+LOCAL void db_sql_print(
14511469
sqlite3_context *context,
14521470
int argc,
14531471
sqlite3_value **argv
14541472
){
14551473
int i;
@@ -1458,20 +1476,20 @@
14581476
char c = i==argc-1 ? '\n' : ' ';
14591477
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
14601478
}
14611479
}
14621480
}
1463
-static void db_sql_trace(void *notUsed, const char *zSql){
1481
+LOCAL void db_sql_trace(void *notUsed, const char *zSql){
14641482
int n = strlen(zSql);
14651483
fossil_trace("%s%s\n", zSql, (n>0 && zSql[n-1]==';') ? "" : ";");
14661484
}
14671485
14681486
/*
14691487
** Implement the user() SQL function. user() takes no arguments and
14701488
** returns the user ID of the current user.
14711489
*/
1472
-static void db_sql_user(
1490
+LOCAL void db_sql_user(
14731491
sqlite3_context *context,
14741492
int argc,
14751493
sqlite3_value **argv
14761494
){
14771495
if( g.zLogin!=0 ){
@@ -1483,11 +1501,11 @@
14831501
** Implement the cgi() SQL function. cgi() takes an argument which is
14841502
** a name of CGI query parameter. The value of that parameter is returned,
14851503
** if available. Optional second argument will be returned if the first
14861504
** doesn't exist as a CGI parameter.
14871505
*/
1488
-static void db_sql_cgi(sqlite3_context *context, int argc, sqlite3_value **argv){
1506
+LOCAL void db_sql_cgi(sqlite3_context *context, int argc, sqlite3_value **argv){
14891507
const char* zP;
14901508
if( argc!=1 && argc!=2 ) return;
14911509
zP = P((const char*)sqlite3_value_text(argv[0]));
14921510
if( zP ){
14931511
sqlite3_result_text(context, zP, -1, SQLITE_STATIC);
@@ -1514,11 +1532,11 @@
15141532
** (meaning that id was named on the command-line).
15151533
**
15161534
** In the second form (3 arguments) return argument X if true and Y
15171535
** if false. Except if Y is NULL then always return X.
15181536
*/
1519
-static void file_is_selected(
1537
+LOCAL void file_is_selected(
15201538
sqlite3_context *context,
15211539
int argc,
15221540
sqlite3_value **argv
15231541
){
15241542
int rc = 0;
@@ -1602,32 +1620,10 @@
16021620
zOut = mprintf("%s", zKey);
16031621
}
16041622
return zOut;
16051623
}
16061624
1607
-/*
1608
-** This function registers auxiliary functions when the SQLite
1609
-** database connection is first established.
1610
-*/
1611
-void db_connection_init(void){
1612
- sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1613
- sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1614
- sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1615
- sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1616
- sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
1617
- sqlite3_create_function(
1618
- g.db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
1619
- );
1620
- sqlite3_create_function(
1621
- g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
1622
- );
1623
- if( g.fSqlTrace ){
1624
- sqlite3_trace(g.db, db_sql_trace, 0);
1625
- }
1626
- re_add_sql_func(g.db);
1627
-}
1628
-
16291625
/*
16301626
** Return true if the string zVal represents "true" (or "false").
16311627
*/
16321628
int is_truth(const char *zVal){
16331629
static const char *const azOn[] = { "on", "yes", "true", "1" };
@@ -2176,18 +2172,18 @@
21762172
** diff-command External command to run when performing a diff.
21772173
** If undefined, the internal text diff will be used.
21782174
**
21792175
** dont-push Prevent this repository from pushing from client to
21802176
** server. Useful when setting up a private branch.
2177
+**
2178
+** editor Text editor command used for check-in comments.
21812179
**
21822180
** empty-dirs A comma or newline-separated list of pathnames. On
21832181
** (versionable) update and checkout commands, if no file or directory
21842182
** exists with that name, an empty directory will be
21852183
** created.
21862184
**
2187
-** editor Text editor command used for check-in comments.
2188
-**
21892185
** gdiff-command External command to run when performing a graphical
21902186
** diff. If undefined, text diff will be used.
21912187
**
21922188
** gmerge-command A graphical merge conflict resolver command operating
21932189
** on four files.
@@ -2245,10 +2241,13 @@
22452241
**
22462242
** self-register Allow users to register themselves through the HTTP UI.
22472243
** This is useful if you want to see other names than
22482244
** "Anonymous" in e.g. ticketing system. On the other hand
22492245
** users can not be deleted. Default: off.
2246
+**
2247
+** ssh-command Command used to talk to a remote machine with
2248
+** the "ssh://" protocol.
22502249
**
22512250
** ssl-ca-location The full pathname to a file containing PEM encoded
22522251
** CA root certificates, or a directory of certificates
22532252
** with filenames formed from the certificate hashes as
22542253
** required by OpenSSL.
@@ -2264,13 +2263,10 @@
22642263
** the certificate and private key files.
22652264
** This identity will be presented to SSL servers to
22662265
** authenticate this client, in addition to the normal
22672266
** password authentication.
22682267
**
2269
-** ssh-command Command used to talk to a remote machine with
2270
-** the "ssh://" protocol.
2271
-**
22722268
** tcl If enabled (and Fossil was compiled with Tcl support),
22732269
** Tcl integration commands will be added to the TH1
22742270
** interpreter, allowing arbitrary Tcl expressions and
22752271
** scripts to be evaluated from TH1. Additionally, the Tcl
22762272
** interpreter will be able to evaluate arbitrary TH1
22772273
--- src/db.c
+++ src/db.c
@@ -484,20 +484,30 @@
484 /*
485 ** Execute multiple SQL statements.
486 */
487 int db_multi_exec(const char *zSql, ...){
488 Blob sql;
489 int rc;
490 va_list ap;
491 char *zErr = 0;
 
492 blob_init(&sql, 0, 0);
493 va_start(ap, zSql);
494 blob_vappendf(&sql, zSql, ap);
495 va_end(ap);
496 rc = sqlite3_exec(g.db, blob_buffer(&sql), 0, 0, &zErr);
497 if( rc!=SQLITE_OK ){
498 db_err("%s\n%s", zErr, blob_buffer(&sql));
 
 
 
 
 
 
 
 
 
499 }
500 blob_reset(&sql);
501 return rc;
502 }
503
@@ -642,15 +652,11 @@
642 sqlite3 *db;
643 int rc;
644 const char *zSql;
645 va_list ap;
646
647 rc = sqlite3_open(zFileName, &db);
648 if( rc!=SQLITE_OK ){
649 db_err("[%s] %s", zFileName, sqlite3_errmsg(db));
650 }
651 sqlite3_busy_timeout(db, 5000);
652 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
653 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
654 if( rc!=SQLITE_OK ){
655 db_err(sqlite3_errmsg(db));
656 }
@@ -697,11 +703,11 @@
697
698 /*
699 ** Open a database file. Return a pointer to the new database
700 ** connection. An error results in process abort.
701 */
702 static sqlite3 *openDatabase(const char *zDbName){
703 int rc;
704 const char *zVfs;
705 sqlite3 *db;
706
707 if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
@@ -717,10 +723,23 @@
717 sqlite3_busy_timeout(db, 5000);
718 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
719 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
720 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
721 db_checkin_mtime_function, 0, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
722 return db;
723 }
724
725
726 /*
@@ -748,13 +767,12 @@
748 const char *zLabel,
749 int *pWasAttached
750 ){
751 if( !g.db ){
752 assert( g.zMainDbType==0 );
753 g.db = openDatabase(zDbName);
754 g.zMainDbType = zLabel;
755 db_connection_init();
756 if ( pWasAttached ) *pWasAttached = 0;
757 }else{
758 assert( g.zMainDbType!=0 );
759 db_attach(zDbName, zLabel);
760 if ( pWasAttached ) *pWasAttached = 1;
@@ -821,11 +839,11 @@
821 db_open_or_attach(zDbName, "configdb", &g.useAttach);
822 g.dbConfig = 0;
823 g.zConfigDbType = 0;
824 }else{
825 g.useAttach = 0;
826 g.dbConfig = openDatabase(zDbName);
827 g.zConfigDbType = "configdb";
828 }
829 g.configOpen = 1;
830 free(zDbName);
831 }
@@ -1445,11 +1463,11 @@
1445 ** SQL functions for debugging.
1446 **
1447 ** The print() function writes its arguments on stdout, but only
1448 ** if the -sqlprint command-line option is turned on.
1449 */
1450 static void db_sql_print(
1451 sqlite3_context *context,
1452 int argc,
1453 sqlite3_value **argv
1454 ){
1455 int i;
@@ -1458,20 +1476,20 @@
1458 char c = i==argc-1 ? '\n' : ' ';
1459 fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
1460 }
1461 }
1462 }
1463 static void db_sql_trace(void *notUsed, const char *zSql){
1464 int n = strlen(zSql);
1465 fossil_trace("%s%s\n", zSql, (n>0 && zSql[n-1]==';') ? "" : ";");
1466 }
1467
1468 /*
1469 ** Implement the user() SQL function. user() takes no arguments and
1470 ** returns the user ID of the current user.
1471 */
1472 static void db_sql_user(
1473 sqlite3_context *context,
1474 int argc,
1475 sqlite3_value **argv
1476 ){
1477 if( g.zLogin!=0 ){
@@ -1483,11 +1501,11 @@
1483 ** Implement the cgi() SQL function. cgi() takes an argument which is
1484 ** a name of CGI query parameter. The value of that parameter is returned,
1485 ** if available. Optional second argument will be returned if the first
1486 ** doesn't exist as a CGI parameter.
1487 */
1488 static void db_sql_cgi(sqlite3_context *context, int argc, sqlite3_value **argv){
1489 const char* zP;
1490 if( argc!=1 && argc!=2 ) return;
1491 zP = P((const char*)sqlite3_value_text(argv[0]));
1492 if( zP ){
1493 sqlite3_result_text(context, zP, -1, SQLITE_STATIC);
@@ -1514,11 +1532,11 @@
1514 ** (meaning that id was named on the command-line).
1515 **
1516 ** In the second form (3 arguments) return argument X if true and Y
1517 ** if false. Except if Y is NULL then always return X.
1518 */
1519 static void file_is_selected(
1520 sqlite3_context *context,
1521 int argc,
1522 sqlite3_value **argv
1523 ){
1524 int rc = 0;
@@ -1602,32 +1620,10 @@
1602 zOut = mprintf("%s", zKey);
1603 }
1604 return zOut;
1605 }
1606
1607 /*
1608 ** This function registers auxiliary functions when the SQLite
1609 ** database connection is first established.
1610 */
1611 void db_connection_init(void){
1612 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1613 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1614 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1615 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1616 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
1617 sqlite3_create_function(
1618 g.db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
1619 );
1620 sqlite3_create_function(
1621 g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
1622 );
1623 if( g.fSqlTrace ){
1624 sqlite3_trace(g.db, db_sql_trace, 0);
1625 }
1626 re_add_sql_func(g.db);
1627 }
1628
1629 /*
1630 ** Return true if the string zVal represents "true" (or "false").
1631 */
1632 int is_truth(const char *zVal){
1633 static const char *const azOn[] = { "on", "yes", "true", "1" };
@@ -2176,18 +2172,18 @@
2176 ** diff-command External command to run when performing a diff.
2177 ** If undefined, the internal text diff will be used.
2178 **
2179 ** dont-push Prevent this repository from pushing from client to
2180 ** server. Useful when setting up a private branch.
 
 
2181 **
2182 ** empty-dirs A comma or newline-separated list of pathnames. On
2183 ** (versionable) update and checkout commands, if no file or directory
2184 ** exists with that name, an empty directory will be
2185 ** created.
2186 **
2187 ** editor Text editor command used for check-in comments.
2188 **
2189 ** gdiff-command External command to run when performing a graphical
2190 ** diff. If undefined, text diff will be used.
2191 **
2192 ** gmerge-command A graphical merge conflict resolver command operating
2193 ** on four files.
@@ -2245,10 +2241,13 @@
2245 **
2246 ** self-register Allow users to register themselves through the HTTP UI.
2247 ** This is useful if you want to see other names than
2248 ** "Anonymous" in e.g. ticketing system. On the other hand
2249 ** users can not be deleted. Default: off.
 
 
 
2250 **
2251 ** ssl-ca-location The full pathname to a file containing PEM encoded
2252 ** CA root certificates, or a directory of certificates
2253 ** with filenames formed from the certificate hashes as
2254 ** required by OpenSSL.
@@ -2264,13 +2263,10 @@
2264 ** the certificate and private key files.
2265 ** This identity will be presented to SSL servers to
2266 ** authenticate this client, in addition to the normal
2267 ** password authentication.
2268 **
2269 ** ssh-command Command used to talk to a remote machine with
2270 ** the "ssh://" protocol.
2271 **
2272 ** tcl If enabled (and Fossil was compiled with Tcl support),
2273 ** Tcl integration commands will be added to the TH1
2274 ** interpreter, allowing arbitrary Tcl expressions and
2275 ** scripts to be evaluated from TH1. Additionally, the Tcl
2276 ** interpreter will be able to evaluate arbitrary TH1
2277
--- src/db.c
+++ src/db.c
@@ -484,20 +484,30 @@
484 /*
485 ** Execute multiple SQL statements.
486 */
487 int db_multi_exec(const char *zSql, ...){
488 Blob sql;
489 int rc = SQLITE_OK;
490 va_list ap;
491 const char *z, *zEnd;
492 sqlite3_stmt *pStmt;
493 blob_init(&sql, 0, 0);
494 va_start(ap, zSql);
495 blob_vappendf(&sql, zSql, ap);
496 va_end(ap);
497 z = blob_str(&sql);
498 while( rc==SQLITE_OK && z[0] ){
499 pStmt = 0;
500 rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd);
501 if( rc!=SQLITE_OK ) break;
502 if( pStmt ){
503 db.nPrepare++;
504 while( sqlite3_step(pStmt)==SQLITE_ROW ){}
505 rc = sqlite3_finalize(pStmt);
506 if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z);
507 }
508 z = zEnd;
509 }
510 blob_reset(&sql);
511 return rc;
512 }
513
@@ -642,15 +652,11 @@
652 sqlite3 *db;
653 int rc;
654 const char *zSql;
655 va_list ap;
656
657 db = db_open(zFileName);
 
 
 
 
658 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
659 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
660 if( rc!=SQLITE_OK ){
661 db_err(sqlite3_errmsg(db));
662 }
@@ -697,11 +703,11 @@
703
704 /*
705 ** Open a database file. Return a pointer to the new database
706 ** connection. An error results in process abort.
707 */
708 LOCAL sqlite3 *db_open(const char *zDbName){
709 int rc;
710 const char *zVfs;
711 sqlite3 *db;
712
713 if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
@@ -717,10 +723,23 @@
723 sqlite3_busy_timeout(db, 5000);
724 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
725 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
726 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
727 db_checkin_mtime_function, 0, 0);
728 sqlite3_create_function(db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
729 sqlite3_create_function(db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
730 sqlite3_create_function(db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
731 sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
732 sqlite3_create_function(
733 db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
734 );
735 sqlite3_create_function(
736 db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
737 );
738 if( g.fSqlTrace ) sqlite3_trace(db, db_sql_trace, 0);
739 re_add_sql_func(db);
740 sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
741 return db;
742 }
743
744
745 /*
@@ -748,13 +767,12 @@
767 const char *zLabel,
768 int *pWasAttached
769 ){
770 if( !g.db ){
771 assert( g.zMainDbType==0 );
772 g.db = db_open(zDbName);
773 g.zMainDbType = zLabel;
 
774 if ( pWasAttached ) *pWasAttached = 0;
775 }else{
776 assert( g.zMainDbType!=0 );
777 db_attach(zDbName, zLabel);
778 if ( pWasAttached ) *pWasAttached = 1;
@@ -821,11 +839,11 @@
839 db_open_or_attach(zDbName, "configdb", &g.useAttach);
840 g.dbConfig = 0;
841 g.zConfigDbType = 0;
842 }else{
843 g.useAttach = 0;
844 g.dbConfig = db_open(zDbName);
845 g.zConfigDbType = "configdb";
846 }
847 g.configOpen = 1;
848 free(zDbName);
849 }
@@ -1445,11 +1463,11 @@
1463 ** SQL functions for debugging.
1464 **
1465 ** The print() function writes its arguments on stdout, but only
1466 ** if the -sqlprint command-line option is turned on.
1467 */
1468 LOCAL void db_sql_print(
1469 sqlite3_context *context,
1470 int argc,
1471 sqlite3_value **argv
1472 ){
1473 int i;
@@ -1458,20 +1476,20 @@
1476 char c = i==argc-1 ? '\n' : ' ';
1477 fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
1478 }
1479 }
1480 }
1481 LOCAL void db_sql_trace(void *notUsed, const char *zSql){
1482 int n = strlen(zSql);
1483 fossil_trace("%s%s\n", zSql, (n>0 && zSql[n-1]==';') ? "" : ";");
1484 }
1485
1486 /*
1487 ** Implement the user() SQL function. user() takes no arguments and
1488 ** returns the user ID of the current user.
1489 */
1490 LOCAL void db_sql_user(
1491 sqlite3_context *context,
1492 int argc,
1493 sqlite3_value **argv
1494 ){
1495 if( g.zLogin!=0 ){
@@ -1483,11 +1501,11 @@
1501 ** Implement the cgi() SQL function. cgi() takes an argument which is
1502 ** a name of CGI query parameter. The value of that parameter is returned,
1503 ** if available. Optional second argument will be returned if the first
1504 ** doesn't exist as a CGI parameter.
1505 */
1506 LOCAL void db_sql_cgi(sqlite3_context *context, int argc, sqlite3_value **argv){
1507 const char* zP;
1508 if( argc!=1 && argc!=2 ) return;
1509 zP = P((const char*)sqlite3_value_text(argv[0]));
1510 if( zP ){
1511 sqlite3_result_text(context, zP, -1, SQLITE_STATIC);
@@ -1514,11 +1532,11 @@
1532 ** (meaning that id was named on the command-line).
1533 **
1534 ** In the second form (3 arguments) return argument X if true and Y
1535 ** if false. Except if Y is NULL then always return X.
1536 */
1537 LOCAL void file_is_selected(
1538 sqlite3_context *context,
1539 int argc,
1540 sqlite3_value **argv
1541 ){
1542 int rc = 0;
@@ -1602,32 +1620,10 @@
1620 zOut = mprintf("%s", zKey);
1621 }
1622 return zOut;
1623 }
1624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1625 /*
1626 ** Return true if the string zVal represents "true" (or "false").
1627 */
1628 int is_truth(const char *zVal){
1629 static const char *const azOn[] = { "on", "yes", "true", "1" };
@@ -2176,18 +2172,18 @@
2172 ** diff-command External command to run when performing a diff.
2173 ** If undefined, the internal text diff will be used.
2174 **
2175 ** dont-push Prevent this repository from pushing from client to
2176 ** server. Useful when setting up a private branch.
2177 **
2178 ** editor Text editor command used for check-in comments.
2179 **
2180 ** empty-dirs A comma or newline-separated list of pathnames. On
2181 ** (versionable) update and checkout commands, if no file or directory
2182 ** exists with that name, an empty directory will be
2183 ** created.
2184 **
 
 
2185 ** gdiff-command External command to run when performing a graphical
2186 ** diff. If undefined, text diff will be used.
2187 **
2188 ** gmerge-command A graphical merge conflict resolver command operating
2189 ** on four files.
@@ -2245,10 +2241,13 @@
2241 **
2242 ** self-register Allow users to register themselves through the HTTP UI.
2243 ** This is useful if you want to see other names than
2244 ** "Anonymous" in e.g. ticketing system. On the other hand
2245 ** users can not be deleted. Default: off.
2246 **
2247 ** ssh-command Command used to talk to a remote machine with
2248 ** the "ssh://" protocol.
2249 **
2250 ** ssl-ca-location The full pathname to a file containing PEM encoded
2251 ** CA root certificates, or a directory of certificates
2252 ** with filenames formed from the certificate hashes as
2253 ** required by OpenSSL.
@@ -2264,13 +2263,10 @@
2263 ** the certificate and private key files.
2264 ** This identity will be presented to SSL servers to
2265 ** authenticate this client, in addition to the normal
2266 ** password authentication.
2267 **
 
 
 
2268 ** tcl If enabled (and Fossil was compiled with Tcl support),
2269 ** Tcl integration commands will be added to the TH1
2270 ** interpreter, allowing arbitrary Tcl expressions and
2271 ** scripts to be evaluated from TH1. Additionally, the Tcl
2272 ** interpreter will be able to evaluate arbitrary TH1
2273
+2 -3
--- src/encode.c
+++ src/encode.c
@@ -131,18 +131,17 @@
131131
static char *EncodeHttp(const char *zIn, int n, int encodeSlash){
132132
int c;
133133
int i = 0;
134134
int count = 0;
135135
char *zOut;
136
- int other;
137136
# define IsSafeChar(X) \
138137
(fossil_isalnum(X) || (X)=='.' || (X)=='$' \
139
- || (X)=='~' || (X)=='-' || (X)=='_' || (X)==other)
138
+ || (X)=='~' || (X)=='-' || (X)=='_' \
139
+ || (!encodeSlash && ((X)=='/' || (X)==':')))
140140
141141
if( zIn==0 ) return 0;
142142
if( n<0 ) n = strlen(zIn);
143
- other = encodeSlash ? 'a' : '/';
144143
while( i<n && (c = zIn[i])!=0 ){
145144
if( IsSafeChar(c) || c==' ' ){
146145
count++;
147146
}else{
148147
count += 3;
149148
--- src/encode.c
+++ src/encode.c
@@ -131,18 +131,17 @@
131 static char *EncodeHttp(const char *zIn, int n, int encodeSlash){
132 int c;
133 int i = 0;
134 int count = 0;
135 char *zOut;
136 int other;
137 # define IsSafeChar(X) \
138 (fossil_isalnum(X) || (X)=='.' || (X)=='$' \
139 || (X)=='~' || (X)=='-' || (X)=='_' || (X)==other)
 
140
141 if( zIn==0 ) return 0;
142 if( n<0 ) n = strlen(zIn);
143 other = encodeSlash ? 'a' : '/';
144 while( i<n && (c = zIn[i])!=0 ){
145 if( IsSafeChar(c) || c==' ' ){
146 count++;
147 }else{
148 count += 3;
149
--- src/encode.c
+++ src/encode.c
@@ -131,18 +131,17 @@
131 static char *EncodeHttp(const char *zIn, int n, int encodeSlash){
132 int c;
133 int i = 0;
134 int count = 0;
135 char *zOut;
 
136 # define IsSafeChar(X) \
137 (fossil_isalnum(X) || (X)=='.' || (X)=='$' \
138 || (X)=='~' || (X)=='-' || (X)=='_' \
139 || (!encodeSlash && ((X)=='/' || (X)==':')))
140
141 if( zIn==0 ) return 0;
142 if( n<0 ) n = strlen(zIn);
 
143 while( i<n && (c = zIn[i])!=0 ){
144 if( IsSafeChar(c) || c==' ' ){
145 count++;
146 }else{
147 count += 3;
148
+52 -29
--- src/file.c
+++ src/file.c
@@ -483,53 +483,76 @@
483483
** a file in a repository. Valid filenames follow all of the
484484
** following rules:
485485
**
486486
** * Does not begin with "/"
487487
** * Does not contain any path element named "." or ".."
488
+** * Does not contain any of these characters in the path: "\"
488489
** * Does not end with "/".
489490
** * Does not contain two or more "/" characters in a row.
490491
** * Contains at least one character
491492
**
492
-** Invalid UTF8 characters and "\". result in a false return if
493
-** bStrictUtf8 is true. If bStrictUtf8 is false, invalid UTF8
494
-** characters and "\" are silently ignored.
493
+** Invalid UTF8 characters result in a false return if bStrictUtf8 is
494
+** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
495
+** ignored. See http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
496
+** and http://en.wikipedia.org/wiki/Unicode (for the noncharacters)
497
+**
498
+** The bStrictUtf8 flag is true for new inputs, but is false when parsing
499
+** legacy manifests, for backwards compatibility.
495500
*/
496501
int file_is_simple_pathname(const char *z, int bStrictUtf8){
497502
int i;
498
- char c = z[0];
503
+ unsigned char c = (unsigned char) z[0];
504
+ char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00;
499505
if( c=='/' || c==0 ) return 0;
500506
if( c=='.' ){
501507
if( z[1]=='/' || z[1]==0 ) return 0;
502508
if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
503509
}
504
- for(i=0; (c=z[i])!=0; i++){
505
- if( bStrictUtf8 ){
506
- if( c & 0x80 ){
507
- if( (c & 0xf0) == 0xf0 ) {
510
+ for(i=0; (c=(unsigned char)z[i])!=0; i++){
511
+ if( c & maskNonAscii ){
512
+ if( (z[++i]&0xc0)!=0x80 ){
513
+ /* Invalid first continuation byte */
514
+ return 0;
515
+ }
516
+ if( c<0xc2 ){
517
+ /* Invalid 1-byte UTF-8 sequence, or 2-byte overlong form. */
518
+ return 0;
519
+ }else if( (c&0xe0)==0xe0 ){
520
+ /* 3-byte or more */
521
+ int unicode;
522
+ if( c&0x10 ){
508523
/* Unicode characters > U+FFFF are not supported.
509524
* Windows XP and earlier cannot handle them.
510525
*/
511526
return 0;
512527
}
513
- if( (c & 0xf0) == 0xe0 ) {
514
- /* This is a 3-byte UTF-8 character */
515
- if ( (c & 0xfe) == 0xee ){
516
- /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
517
- if ( !(c & 1) || ((z[i+1] & 0xff) < 0xa4) ){
518
- /* Unicode character in the range U+E000 - U+F8FF are for
519
- * private use, they shouldn't occur in filenames. */
520
- return 0;
521
- }
522
- }else if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
523
- /* Unicode character in the range U+D800 - U+DFFF are for
524
- * surrogate pairs, they shouldn't occur in filenames. */
525
- return 0;
526
- }
527
- }
528
- }else if( c=='\\' ){
529
- return 0;
530
- }
528
+ /* This is a 3-byte UTF-8 character */
529
+ unicode = ((c&0x0f)<<12) + ((z[i]&0x3f)<<6) + (z[i+1]&0x3f);
530
+ if( unicode <= 0x07ff ){
531
+ /* overlong form */
532
+ return 0;
533
+ }else if( unicode>=0xe000 ){
534
+ /* U+E000..U+FFFF */
535
+ if( (unicode<=0xf8ff) || (unicode>=0xfffe) ){
536
+ /* U+E000..U+F8FF are for private use.
537
+ * U+FFFE..U+FFFF are noncharacters. */
538
+ return 0;
539
+ } else if( (unicode>=0xfdd0) && (unicode<=0xfdef) ){
540
+ /* U+FDD0..U+FDEF are noncharacters. */
541
+ return 0;
542
+ }
543
+ }else if( (unicode>=0xd800) && (unicode<=0xdfff) ){
544
+ /* U+D800..U+DFFF are for surrogate pairs. */
545
+ return 0;
546
+ }
547
+ if( (z[++i]&0xc0)!=0x80 ){
548
+ /* Invalid second continuation byte */
549
+ return 0;
550
+ }
551
+ }
552
+ }else if( bStrictUtf8 && (c=='\\') ){
553
+ return 0;
531554
}
532555
if( c=='/' ){
533556
if( z[i+1]=='/' ) return 0;
534557
if( z[i+1]=='.' ){
535558
if( z[i+2]=='/' || z[i+2]==0 ) return 0;
@@ -578,11 +601,11 @@
578601
if( z[i]=='\\' ) z[i] = '/';
579602
}
580603
#endif
581604
582605
/* Removing trailing "/" characters */
583
- if ( !slash ){
606
+ if( !slash ){
584607
while( n>1 && z[n-1]=='/' ){ n--; }
585608
}
586609
587610
/* Remove duplicate '/' characters. Except, two // at the beginning
588611
** of a pathname is allowed since this is important on windows. */
@@ -835,11 +858,11 @@
835858
if( zPwd[i]==0 ){
836859
blob_append(pOut, ".", 1);
837860
}else{
838861
blob_append(pOut, "..", 2);
839862
for(j=i+1; zPwd[j]; j++){
840
- if( zPwd[j]=='/' ) {
863
+ if( zPwd[j]=='/' ){
841864
blob_append(pOut, "/..", 3);
842865
}
843866
}
844867
}
845868
return;
@@ -852,11 +875,11 @@
852875
return;
853876
}
854877
while( zPath[i-1]!='/' ){ i--; }
855878
blob_set(&tmp, "../");
856879
for(j=i; zPwd[j]; j++){
857
- if( zPwd[j]=='/' ) {
880
+ if( zPwd[j]=='/' ){
858881
blob_append(&tmp, "../", 3);
859882
}
860883
}
861884
blob_append(&tmp, &zPath[i], -1);
862885
blob_reset(pOut);
863886
--- src/file.c
+++ src/file.c
@@ -483,53 +483,76 @@
483 ** a file in a repository. Valid filenames follow all of the
484 ** following rules:
485 **
486 ** * Does not begin with "/"
487 ** * Does not contain any path element named "." or ".."
 
488 ** * Does not end with "/".
489 ** * Does not contain two or more "/" characters in a row.
490 ** * Contains at least one character
491 **
492 ** Invalid UTF8 characters and "\". result in a false return if
493 ** bStrictUtf8 is true. If bStrictUtf8 is false, invalid UTF8
494 ** characters and "\" are silently ignored.
 
 
 
 
495 */
496 int file_is_simple_pathname(const char *z, int bStrictUtf8){
497 int i;
498 char c = z[0];
 
499 if( c=='/' || c==0 ) return 0;
500 if( c=='.' ){
501 if( z[1]=='/' || z[1]==0 ) return 0;
502 if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
503 }
504 for(i=0; (c=z[i])!=0; i++){
505 if( bStrictUtf8 ){
506 if( c & 0x80 ){
507 if( (c & 0xf0) == 0xf0 ) {
 
 
 
 
 
 
 
 
 
508 /* Unicode characters > U+FFFF are not supported.
509 * Windows XP and earlier cannot handle them.
510 */
511 return 0;
512 }
513 if( (c & 0xf0) == 0xe0 ) {
514 /* This is a 3-byte UTF-8 character */
515 if ( (c & 0xfe) == 0xee ){
516 /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
517 if ( !(c & 1) || ((z[i+1] & 0xff) < 0xa4) ){
518 /* Unicode character in the range U+E000 - U+F8FF are for
519 * private use, they shouldn't occur in filenames. */
520 return 0;
521 }
522 }else if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
523 /* Unicode character in the range U+D800 - U+DFFF are for
524 * surrogate pairs, they shouldn't occur in filenames. */
525 return 0;
526 }
527 }
528 }else if( c=='\\' ){
529 return 0;
530 }
 
 
 
 
 
 
 
 
531 }
532 if( c=='/' ){
533 if( z[i+1]=='/' ) return 0;
534 if( z[i+1]=='.' ){
535 if( z[i+2]=='/' || z[i+2]==0 ) return 0;
@@ -578,11 +601,11 @@
578 if( z[i]=='\\' ) z[i] = '/';
579 }
580 #endif
581
582 /* Removing trailing "/" characters */
583 if ( !slash ){
584 while( n>1 && z[n-1]=='/' ){ n--; }
585 }
586
587 /* Remove duplicate '/' characters. Except, two // at the beginning
588 ** of a pathname is allowed since this is important on windows. */
@@ -835,11 +858,11 @@
835 if( zPwd[i]==0 ){
836 blob_append(pOut, ".", 1);
837 }else{
838 blob_append(pOut, "..", 2);
839 for(j=i+1; zPwd[j]; j++){
840 if( zPwd[j]=='/' ) {
841 blob_append(pOut, "/..", 3);
842 }
843 }
844 }
845 return;
@@ -852,11 +875,11 @@
852 return;
853 }
854 while( zPath[i-1]!='/' ){ i--; }
855 blob_set(&tmp, "../");
856 for(j=i; zPwd[j]; j++){
857 if( zPwd[j]=='/' ) {
858 blob_append(&tmp, "../", 3);
859 }
860 }
861 blob_append(&tmp, &zPath[i], -1);
862 blob_reset(pOut);
863
--- src/file.c
+++ src/file.c
@@ -483,53 +483,76 @@
483 ** a file in a repository. Valid filenames follow all of the
484 ** following rules:
485 **
486 ** * Does not begin with "/"
487 ** * Does not contain any path element named "." or ".."
488 ** * Does not contain any of these characters in the path: "\"
489 ** * Does not end with "/".
490 ** * Does not contain two or more "/" characters in a row.
491 ** * Contains at least one character
492 **
493 ** Invalid UTF8 characters result in a false return if bStrictUtf8 is
494 ** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
495 ** ignored. See http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
496 ** and http://en.wikipedia.org/wiki/Unicode (for the noncharacters)
497 **
498 ** The bStrictUtf8 flag is true for new inputs, but is false when parsing
499 ** legacy manifests, for backwards compatibility.
500 */
501 int file_is_simple_pathname(const char *z, int bStrictUtf8){
502 int i;
503 unsigned char c = (unsigned char) z[0];
504 char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00;
505 if( c=='/' || c==0 ) return 0;
506 if( c=='.' ){
507 if( z[1]=='/' || z[1]==0 ) return 0;
508 if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
509 }
510 for(i=0; (c=(unsigned char)z[i])!=0; i++){
511 if( c & maskNonAscii ){
512 if( (z[++i]&0xc0)!=0x80 ){
513 /* Invalid first continuation byte */
514 return 0;
515 }
516 if( c<0xc2 ){
517 /* Invalid 1-byte UTF-8 sequence, or 2-byte overlong form. */
518 return 0;
519 }else if( (c&0xe0)==0xe0 ){
520 /* 3-byte or more */
521 int unicode;
522 if( c&0x10 ){
523 /* Unicode characters > U+FFFF are not supported.
524 * Windows XP and earlier cannot handle them.
525 */
526 return 0;
527 }
528 /* This is a 3-byte UTF-8 character */
529 unicode = ((c&0x0f)<<12) + ((z[i]&0x3f)<<6) + (z[i+1]&0x3f);
530 if( unicode <= 0x07ff ){
531 /* overlong form */
532 return 0;
533 }else if( unicode>=0xe000 ){
534 /* U+E000..U+FFFF */
535 if( (unicode<=0xf8ff) || (unicode>=0xfffe) ){
536 /* U+E000..U+F8FF are for private use.
537 * U+FFFE..U+FFFF are noncharacters. */
538 return 0;
539 } else if( (unicode>=0xfdd0) && (unicode<=0xfdef) ){
540 /* U+FDD0..U+FDEF are noncharacters. */
541 return 0;
542 }
543 }else if( (unicode>=0xd800) && (unicode<=0xdfff) ){
544 /* U+D800..U+DFFF are for surrogate pairs. */
545 return 0;
546 }
547 if( (z[++i]&0xc0)!=0x80 ){
548 /* Invalid second continuation byte */
549 return 0;
550 }
551 }
552 }else if( bStrictUtf8 && (c=='\\') ){
553 return 0;
554 }
555 if( c=='/' ){
556 if( z[i+1]=='/' ) return 0;
557 if( z[i+1]=='.' ){
558 if( z[i+2]=='/' || z[i+2]==0 ) return 0;
@@ -578,11 +601,11 @@
601 if( z[i]=='\\' ) z[i] = '/';
602 }
603 #endif
604
605 /* Removing trailing "/" characters */
606 if( !slash ){
607 while( n>1 && z[n-1]=='/' ){ n--; }
608 }
609
610 /* Remove duplicate '/' characters. Except, two // at the beginning
611 ** of a pathname is allowed since this is important on windows. */
@@ -835,11 +858,11 @@
858 if( zPwd[i]==0 ){
859 blob_append(pOut, ".", 1);
860 }else{
861 blob_append(pOut, "..", 2);
862 for(j=i+1; zPwd[j]; j++){
863 if( zPwd[j]=='/' ){
864 blob_append(pOut, "/..", 3);
865 }
866 }
867 }
868 return;
@@ -852,11 +875,11 @@
875 return;
876 }
877 while( zPath[i-1]!='/' ){ i--; }
878 blob_set(&tmp, "../");
879 for(j=i; zPwd[j]; j++){
880 if( zPwd[j]=='/' ){
881 blob_append(&tmp, "../", 3);
882 }
883 }
884 blob_append(&tmp, &zPath[i], -1);
885 blob_reset(pOut);
886
+52 -29
--- src/file.c
+++ src/file.c
@@ -483,53 +483,76 @@
483483
** a file in a repository. Valid filenames follow all of the
484484
** following rules:
485485
**
486486
** * Does not begin with "/"
487487
** * Does not contain any path element named "." or ".."
488
+** * Does not contain any of these characters in the path: "\"
488489
** * Does not end with "/".
489490
** * Does not contain two or more "/" characters in a row.
490491
** * Contains at least one character
491492
**
492
-** Invalid UTF8 characters and "\". result in a false return if
493
-** bStrictUtf8 is true. If bStrictUtf8 is false, invalid UTF8
494
-** characters and "\" are silently ignored.
493
+** Invalid UTF8 characters result in a false return if bStrictUtf8 is
494
+** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
495
+** ignored. See http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
496
+** and http://en.wikipedia.org/wiki/Unicode (for the noncharacters)
497
+**
498
+** The bStrictUtf8 flag is true for new inputs, but is false when parsing
499
+** legacy manifests, for backwards compatibility.
495500
*/
496501
int file_is_simple_pathname(const char *z, int bStrictUtf8){
497502
int i;
498
- char c = z[0];
503
+ unsigned char c = (unsigned char) z[0];
504
+ char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00;
499505
if( c=='/' || c==0 ) return 0;
500506
if( c=='.' ){
501507
if( z[1]=='/' || z[1]==0 ) return 0;
502508
if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
503509
}
504
- for(i=0; (c=z[i])!=0; i++){
505
- if( bStrictUtf8 ){
506
- if( c & 0x80 ){
507
- if( (c & 0xf0) == 0xf0 ) {
510
+ for(i=0; (c=(unsigned char)z[i])!=0; i++){
511
+ if( c & maskNonAscii ){
512
+ if( (z[++i]&0xc0)!=0x80 ){
513
+ /* Invalid first continuation byte */
514
+ return 0;
515
+ }
516
+ if( c<0xc2 ){
517
+ /* Invalid 1-byte UTF-8 sequence, or 2-byte overlong form. */
518
+ return 0;
519
+ }else if( (c&0xe0)==0xe0 ){
520
+ /* 3-byte or more */
521
+ int unicode;
522
+ if( c&0x10 ){
508523
/* Unicode characters > U+FFFF are not supported.
509524
* Windows XP and earlier cannot handle them.
510525
*/
511526
return 0;
512527
}
513
- if( (c & 0xf0) == 0xe0 ) {
514
- /* This is a 3-byte UTF-8 character */
515
- if ( (c & 0xfe) == 0xee ){
516
- /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
517
- if ( !(c & 1) || ((z[i+1] & 0xff) < 0xa4) ){
518
- /* Unicode character in the range U+E000 - U+F8FF are for
519
- * private use, they shouldn't occur in filenames. */
520
- return 0;
521
- }
522
- }else if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
523
- /* Unicode character in the range U+D800 - U+DFFF are for
524
- * surrogate pairs, they shouldn't occur in filenames. */
525
- return 0;
526
- }
527
- }
528
- }else if( c=='\\' ){
529
- return 0;
530
- }
528
+ /* This is a 3-byte UTF-8 character */
529
+ unicode = ((c&0x0f)<<12) + ((z[i]&0x3f)<<6) + (z[i+1]&0x3f);
530
+ if( unicode <= 0x07ff ){
531
+ /* overlong form */
532
+ return 0;
533
+ }else if( unicode>=0xe000 ){
534
+ /* U+E000..U+FFFF */
535
+ if( (unicode<=0xf8ff) || (unicode>=0xfffe) ){
536
+ /* U+E000..U+F8FF are for private use.
537
+ * U+FFFE..U+FFFF are noncharacters. */
538
+ return 0;
539
+ } else if( (unicode>=0xfdd0) && (unicode<=0xfdef) ){
540
+ /* U+FDD0..U+FDEF are noncharacters. */
541
+ return 0;
542
+ }
543
+ }else if( (unicode>=0xd800) && (unicode<=0xdfff) ){
544
+ /* U+D800..U+DFFF are for surrogate pairs. */
545
+ return 0;
546
+ }
547
+ if( (z[++i]&0xc0)!=0x80 ){
548
+ /* Invalid second continuation byte */
549
+ return 0;
550
+ }
551
+ }
552
+ }else if( bStrictUtf8 && (c=='\\') ){
553
+ return 0;
531554
}
532555
if( c=='/' ){
533556
if( z[i+1]=='/' ) return 0;
534557
if( z[i+1]=='.' ){
535558
if( z[i+2]=='/' || z[i+2]==0 ) return 0;
@@ -578,11 +601,11 @@
578601
if( z[i]=='\\' ) z[i] = '/';
579602
}
580603
#endif
581604
582605
/* Removing trailing "/" characters */
583
- if ( !slash ){
606
+ if( !slash ){
584607
while( n>1 && z[n-1]=='/' ){ n--; }
585608
}
586609
587610
/* Remove duplicate '/' characters. Except, two // at the beginning
588611
** of a pathname is allowed since this is important on windows. */
@@ -835,11 +858,11 @@
835858
if( zPwd[i]==0 ){
836859
blob_append(pOut, ".", 1);
837860
}else{
838861
blob_append(pOut, "..", 2);
839862
for(j=i+1; zPwd[j]; j++){
840
- if( zPwd[j]=='/' ) {
863
+ if( zPwd[j]=='/' ){
841864
blob_append(pOut, "/..", 3);
842865
}
843866
}
844867
}
845868
return;
@@ -852,11 +875,11 @@
852875
return;
853876
}
854877
while( zPath[i-1]!='/' ){ i--; }
855878
blob_set(&tmp, "../");
856879
for(j=i; zPwd[j]; j++){
857
- if( zPwd[j]=='/' ) {
880
+ if( zPwd[j]=='/' ){
858881
blob_append(&tmp, "../", 3);
859882
}
860883
}
861884
blob_append(&tmp, &zPath[i], -1);
862885
blob_reset(pOut);
863886
--- src/file.c
+++ src/file.c
@@ -483,53 +483,76 @@
483 ** a file in a repository. Valid filenames follow all of the
484 ** following rules:
485 **
486 ** * Does not begin with "/"
487 ** * Does not contain any path element named "." or ".."
 
488 ** * Does not end with "/".
489 ** * Does not contain two or more "/" characters in a row.
490 ** * Contains at least one character
491 **
492 ** Invalid UTF8 characters and "\". result in a false return if
493 ** bStrictUtf8 is true. If bStrictUtf8 is false, invalid UTF8
494 ** characters and "\" are silently ignored.
 
 
 
 
495 */
496 int file_is_simple_pathname(const char *z, int bStrictUtf8){
497 int i;
498 char c = z[0];
 
499 if( c=='/' || c==0 ) return 0;
500 if( c=='.' ){
501 if( z[1]=='/' || z[1]==0 ) return 0;
502 if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
503 }
504 for(i=0; (c=z[i])!=0; i++){
505 if( bStrictUtf8 ){
506 if( c & 0x80 ){
507 if( (c & 0xf0) == 0xf0 ) {
 
 
 
 
 
 
 
 
 
508 /* Unicode characters > U+FFFF are not supported.
509 * Windows XP and earlier cannot handle them.
510 */
511 return 0;
512 }
513 if( (c & 0xf0) == 0xe0 ) {
514 /* This is a 3-byte UTF-8 character */
515 if ( (c & 0xfe) == 0xee ){
516 /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */
517 if ( !(c & 1) || ((z[i+1] & 0xff) < 0xa4) ){
518 /* Unicode character in the range U+E000 - U+F8FF are for
519 * private use, they shouldn't occur in filenames. */
520 return 0;
521 }
522 }else if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){
523 /* Unicode character in the range U+D800 - U+DFFF are for
524 * surrogate pairs, they shouldn't occur in filenames. */
525 return 0;
526 }
527 }
528 }else if( c=='\\' ){
529 return 0;
530 }
 
 
 
 
 
 
 
 
531 }
532 if( c=='/' ){
533 if( z[i+1]=='/' ) return 0;
534 if( z[i+1]=='.' ){
535 if( z[i+2]=='/' || z[i+2]==0 ) return 0;
@@ -578,11 +601,11 @@
578 if( z[i]=='\\' ) z[i] = '/';
579 }
580 #endif
581
582 /* Removing trailing "/" characters */
583 if ( !slash ){
584 while( n>1 && z[n-1]=='/' ){ n--; }
585 }
586
587 /* Remove duplicate '/' characters. Except, two // at the beginning
588 ** of a pathname is allowed since this is important on windows. */
@@ -835,11 +858,11 @@
835 if( zPwd[i]==0 ){
836 blob_append(pOut, ".", 1);
837 }else{
838 blob_append(pOut, "..", 2);
839 for(j=i+1; zPwd[j]; j++){
840 if( zPwd[j]=='/' ) {
841 blob_append(pOut, "/..", 3);
842 }
843 }
844 }
845 return;
@@ -852,11 +875,11 @@
852 return;
853 }
854 while( zPath[i-1]!='/' ){ i--; }
855 blob_set(&tmp, "../");
856 for(j=i; zPwd[j]; j++){
857 if( zPwd[j]=='/' ) {
858 blob_append(&tmp, "../", 3);
859 }
860 }
861 blob_append(&tmp, &zPath[i], -1);
862 blob_reset(pOut);
863
--- src/file.c
+++ src/file.c
@@ -483,53 +483,76 @@
483 ** a file in a repository. Valid filenames follow all of the
484 ** following rules:
485 **
486 ** * Does not begin with "/"
487 ** * Does not contain any path element named "." or ".."
488 ** * Does not contain any of these characters in the path: "\"
489 ** * Does not end with "/".
490 ** * Does not contain two or more "/" characters in a row.
491 ** * Contains at least one character
492 **
493 ** Invalid UTF8 characters result in a false return if bStrictUtf8 is
494 ** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
495 ** ignored. See http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
496 ** and http://en.wikipedia.org/wiki/Unicode (for the noncharacters)
497 **
498 ** The bStrictUtf8 flag is true for new inputs, but is false when parsing
499 ** legacy manifests, for backwards compatibility.
500 */
501 int file_is_simple_pathname(const char *z, int bStrictUtf8){
502 int i;
503 unsigned char c = (unsigned char) z[0];
504 char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00;
505 if( c=='/' || c==0 ) return 0;
506 if( c=='.' ){
507 if( z[1]=='/' || z[1]==0 ) return 0;
508 if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
509 }
510 for(i=0; (c=(unsigned char)z[i])!=0; i++){
511 if( c & maskNonAscii ){
512 if( (z[++i]&0xc0)!=0x80 ){
513 /* Invalid first continuation byte */
514 return 0;
515 }
516 if( c<0xc2 ){
517 /* Invalid 1-byte UTF-8 sequence, or 2-byte overlong form. */
518 return 0;
519 }else if( (c&0xe0)==0xe0 ){
520 /* 3-byte or more */
521 int unicode;
522 if( c&0x10 ){
523 /* Unicode characters > U+FFFF are not supported.
524 * Windows XP and earlier cannot handle them.
525 */
526 return 0;
527 }
528 /* This is a 3-byte UTF-8 character */
529 unicode = ((c&0x0f)<<12) + ((z[i]&0x3f)<<6) + (z[i+1]&0x3f);
530 if( unicode <= 0x07ff ){
531 /* overlong form */
532 return 0;
533 }else if( unicode>=0xe000 ){
534 /* U+E000..U+FFFF */
535 if( (unicode<=0xf8ff) || (unicode>=0xfffe) ){
536 /* U+E000..U+F8FF are for private use.
537 * U+FFFE..U+FFFF are noncharacters. */
538 return 0;
539 } else if( (unicode>=0xfdd0) && (unicode<=0xfdef) ){
540 /* U+FDD0..U+FDEF are noncharacters. */
541 return 0;
542 }
543 }else if( (unicode>=0xd800) && (unicode<=0xdfff) ){
544 /* U+D800..U+DFFF are for surrogate pairs. */
545 return 0;
546 }
547 if( (z[++i]&0xc0)!=0x80 ){
548 /* Invalid second continuation byte */
549 return 0;
550 }
551 }
552 }else if( bStrictUtf8 && (c=='\\') ){
553 return 0;
554 }
555 if( c=='/' ){
556 if( z[i+1]=='/' ) return 0;
557 if( z[i+1]=='.' ){
558 if( z[i+2]=='/' || z[i+2]==0 ) return 0;
@@ -578,11 +601,11 @@
601 if( z[i]=='\\' ) z[i] = '/';
602 }
603 #endif
604
605 /* Removing trailing "/" characters */
606 if( !slash ){
607 while( n>1 && z[n-1]=='/' ){ n--; }
608 }
609
610 /* Remove duplicate '/' characters. Except, two // at the beginning
611 ** of a pathname is allowed since this is important on windows. */
@@ -835,11 +858,11 @@
858 if( zPwd[i]==0 ){
859 blob_append(pOut, ".", 1);
860 }else{
861 blob_append(pOut, "..", 2);
862 for(j=i+1; zPwd[j]; j++){
863 if( zPwd[j]=='/' ){
864 blob_append(pOut, "/..", 3);
865 }
866 }
867 }
868 return;
@@ -852,11 +875,11 @@
875 return;
876 }
877 while( zPath[i-1]!='/' ){ i--; }
878 blob_set(&tmp, "../");
879 for(j=i; zPwd[j]; j++){
880 if( zPwd[j]=='/' ){
881 blob_append(&tmp, "../", 3);
882 }
883 }
884 blob_append(&tmp, &zPath[i], -1);
885 blob_reset(pOut);
886
+1 -1
--- src/info.c
+++ src/info.c
@@ -208,11 +208,11 @@
208208
fossil_print("project-code: %s\n", db_get("project-code", ""));
209209
vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
210210
if( vid ){
211211
show_common_info(vid, "checkout:", 1, 1);
212212
}
213
- fossil_print("checkin-count: %d\n",
213
+ fossil_print("checkins: %d\n",
214214
db_int(-1, "SELECT count(distinct mid) FROM mlink /*scan*/"));
215215
}else{
216216
int rid;
217217
rid = name_to_rid(g.argv[2]);
218218
if( rid==0 ){
219219
--- src/info.c
+++ src/info.c
@@ -208,11 +208,11 @@
208 fossil_print("project-code: %s\n", db_get("project-code", ""));
209 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
210 if( vid ){
211 show_common_info(vid, "checkout:", 1, 1);
212 }
213 fossil_print("checkin-count: %d\n",
214 db_int(-1, "SELECT count(distinct mid) FROM mlink /*scan*/"));
215 }else{
216 int rid;
217 rid = name_to_rid(g.argv[2]);
218 if( rid==0 ){
219
--- src/info.c
+++ src/info.c
@@ -208,11 +208,11 @@
208 fossil_print("project-code: %s\n", db_get("project-code", ""));
209 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
210 if( vid ){
211 show_common_info(vid, "checkout:", 1, 1);
212 }
213 fossil_print("checkins: %d\n",
214 db_int(-1, "SELECT count(distinct mid) FROM mlink /*scan*/"));
215 }else{
216 int rid;
217 rid = name_to_rid(g.argv[2]);
218 if( rid==0 ){
219
+1 -3
--- src/json.c
+++ src/json.c
@@ -2085,15 +2085,13 @@
20852085
cson_object_set(jo, "ticketCount", cson_value_new_integer((cson_int_t)n));
20862086
}/*full*/
20872087
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
20882088
" + 0.99");
20892089
cson_object_set(jo, "ageDays", cson_value_new_integer((cson_int_t)n));
2090
- cson_object_set(jo, "ageYears", cson_value_new_double(n/365.24));
2090
+ cson_object_set(jo, "ageYears", cson_value_new_double(n/365.2425));
20912091
sqlite3_snprintf(BufLen, zBuf, db_get("project-code",""));
20922092
SETBUF(jo, "projectCode");
2093
- sqlite3_snprintf(BufLen, zBuf, db_get("server-code",""));
2094
- SETBUF(jo, "serverCode");
20952093
cson_object_set(jo, "compiler", cson_value_new_string(COMPILER_NAME, strlen(COMPILER_NAME)));
20962094
20972095
jv2 = cson_value_new_object();
20982096
jo2 = cson_value_get_object(jv2);
20992097
cson_object_set(jo, "sqlite", jv2);
21002098
--- src/json.c
+++ src/json.c
@@ -2085,15 +2085,13 @@
2085 cson_object_set(jo, "ticketCount", cson_value_new_integer((cson_int_t)n));
2086 }/*full*/
2087 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
2088 " + 0.99");
2089 cson_object_set(jo, "ageDays", cson_value_new_integer((cson_int_t)n));
2090 cson_object_set(jo, "ageYears", cson_value_new_double(n/365.24));
2091 sqlite3_snprintf(BufLen, zBuf, db_get("project-code",""));
2092 SETBUF(jo, "projectCode");
2093 sqlite3_snprintf(BufLen, zBuf, db_get("server-code",""));
2094 SETBUF(jo, "serverCode");
2095 cson_object_set(jo, "compiler", cson_value_new_string(COMPILER_NAME, strlen(COMPILER_NAME)));
2096
2097 jv2 = cson_value_new_object();
2098 jo2 = cson_value_get_object(jv2);
2099 cson_object_set(jo, "sqlite", jv2);
2100
--- src/json.c
+++ src/json.c
@@ -2085,15 +2085,13 @@
2085 cson_object_set(jo, "ticketCount", cson_value_new_integer((cson_int_t)n));
2086 }/*full*/
2087 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
2088 " + 0.99");
2089 cson_object_set(jo, "ageDays", cson_value_new_integer((cson_int_t)n));
2090 cson_object_set(jo, "ageYears", cson_value_new_double(n/365.2425));
2091 sqlite3_snprintf(BufLen, zBuf, db_get("project-code",""));
2092 SETBUF(jo, "projectCode");
 
 
2093 cson_object_set(jo, "compiler", cson_value_new_string(COMPILER_NAME, strlen(COMPILER_NAME)));
2094
2095 jv2 = cson_value_new_object();
2096 jo2 = cson_value_get_object(jv2);
2097 cson_object_set(jo, "sqlite", jv2);
2098
+1 -1
--- src/main.mk
+++ src/main.mk
@@ -1146,11 +1146,11 @@
11461146
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
11471147
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
11481148
11491149
11501150
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1151
- $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1151
+ $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
11521152
11531153
#
11541154
# The list of all the targets that do not correspond to real files. This stops
11551155
# 'make' from getting confused when someone makes an error in a rule.
11561156
#
11571157
--- src/main.mk
+++ src/main.mk
@@ -1146,11 +1146,11 @@
1146 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
1147 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
1148
1149
1150 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1151 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1152
1153 #
1154 # The list of all the targets that do not correspond to real files. This stops
1155 # 'make' from getting confused when someone makes an error in a rule.
1156 #
1157
--- src/main.mk
+++ src/main.mk
@@ -1146,11 +1146,11 @@
1146 $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
1147 $(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
1148
1149
1150 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1151 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1152
1153 #
1154 # The list of all the targets that do not correspond to real files. This stops
1155 # 'make' from getting confused when someone makes an error in a rule.
1156 #
1157
+30 -11
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -308,11 +308,11 @@
308308
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"
309309
310310
set opt {}
311311
writeln {
312312
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
313
- $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
313
+ $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
314314
315315
#
316316
# The list of all the targets that do not correspond to real files. This stops
317317
# 'make' from getting confused when someone makes an error in a rule.
318318
#
@@ -751,11 +751,11 @@
751751
set opt $SQLITE_OPTIONS
752752
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
753753
754754
set opt {}
755755
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
756
-writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
756
+writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
757757
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
758758
759759
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
760760
set opt {-Dmain=sqlite3_shell}
761761
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
@@ -959,18 +959,35 @@
959959
960960
# zlib options
961961
ZINCDIR = $(B)\compat\zlib
962962
ZLIBDIR = $(B)\compat\zlib
963963
ZLIB = zlib.lib
964
+
965
+# Uncomment to enable JSON API
966
+# FOSSIL_ENABLE_JSON = 1
967
+
968
+# Uncomment to enable markdown support
969
+# FOSSIL_ENABLE_MARKDOWN = 1
964970
965971
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
966972
967973
CFLAGS = -nologo -MT -O2
968974
BCC = $(CC) $(CFLAGS)
969975
TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
976
+RCC = rc -D_WIN32 -D_MSC_VER $(INCL)
970977
LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
971978
LIBDIR = -LIBPATH:$(ZLIBDIR)
979
+
980
+!ifdef FOSSIL_ENABLE_JSON
981
+TCC = $(TCC) -DFOSSIL_ENABLE_JSON
982
+RCC = $(RCC) -DFOSSIL_ENABLE_JSON
983
+!endif
984
+
985
+!ifdef FOSSIL_ENABLE_MARKDOWN
986
+TCC = $(TCC) -DFOSSIL_ENABLE_MARKDOWN
987
+RCC = $(RCC) -DFOSSIL_ENABLE_MARKDOWN
988
+!endif
972989
}
973990
regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
974991
set j " \\\n "
975992
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
976993
writeln -nonewline "SRC = "
@@ -981,24 +998,22 @@
981998
writeln -nonewline " "
982999
}
9831000
writeln -nonewline "${s}_.c"; incr i
9841001
}
9851002
writeln "\n"
1003
+set AdditionalObj [list shell sqlite3 th th_lang cson_amalgamation]
9861004
writeln -nonewline "OBJ = "
9871005
set i 0
988
-foreach s [lsort $src] {
1006
+foreach s [lsort [concat $src $AdditionalObj]] {
9891007
if {$i > 0} {
9901008
writeln " \\"
9911009
writeln -nonewline " "
9921010
}
9931011
writeln -nonewline "\$(OX)\\$s\$O"; incr i
9941012
}
9951013
writeln " \\"
996
-writeln " \$(OX)\\shell\$O \\"
997
-writeln " \$(OX)\\sqlite3\$O \\"
998
-writeln " \$(OX)\\th\$O \\"
999
-writeln " \$(OX)\\th_lang\$O"
1014
+writeln -nonewline " \$(OX)\\fossil.res\n"
10001015
writeln {
10011016
APPNAME = $(OX)\fossil$(E)
10021017
10031018
all: $(OX) $(APPNAME)
10041019
@@ -1006,15 +1021,15 @@
10061021
@echo Building zlib from "$(ZLIBDIR)"...
10071022
@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
10081023
10091024
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
10101025
cd $(OX)
1011
- link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj @linkopts
1026
+ link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
10121027
10131028
$(OX)\linkopts: $B\win\Makefile.msc}
10141029
set redir {>}
1015
-foreach s [lsort [concat $src {shell sqlite3 th th_lang}]] {
1030
+foreach s [lsort [concat $src $AdditionalObj]] {
10161031
writeln "\techo \$(OX)\\$s.obj $redir \$@"
10171032
set redir {>>}
10181033
}
10191034
writeln "\techo \$(LIBS) >> \$@\n\n"
10201035
@@ -1047,12 +1062,12 @@
10471062
$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
10481063
$(TCC) /Fo$@ -c $**
10491064
10501065
VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
10511066
$** > $@
1052
-$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
1053
- cp $(SRCDIR)\cson_amalgamation.h $@
1067
+$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
1068
+ $(TCC) /Fo$@ -c $**
10541069
10551070
page_index.h: mkindex$E $(SRC)
10561071
$** > $@
10571072
10581073
clean:
@@ -1062,10 +1077,11 @@
10621077
-del *.h
10631078
-del *.map
10641079
-del *.manifest
10651080
-del headers
10661081
-del linkopts
1082
+ -del *.res
10671083
10681084
realclean: clean
10691085
-del $(APPNAME)
10701086
-del translate$E
10711087
-del mkindex$E
@@ -1092,10 +1108,13 @@
10921108
writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
10931109
writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
10941110
writeln "${s}_.c : \$(SRCDIR)\\$s.c"
10951111
writeln "\ttranslate\$E \$** > \$@\n"
10961112
}
1113
+
1114
+writeln "fossil.res : \$B\\win\\fossil.rc"
1115
+writeln "\t\$(RCC) -fo \$@ \$**"
10971116
10981117
writeln "headers: makeheaders\$E page_index.h VERSION.h"
10991118
writeln -nonewline "\tmakeheaders\$E "
11001119
set i 0
11011120
foreach s [lsort $src] {
11021121
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -308,11 +308,11 @@
308 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"
309
310 set opt {}
311 writeln {
312 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
313 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
314
315 #
316 # The list of all the targets that do not correspond to real files. This stops
317 # 'make' from getting confused when someone makes an error in a rule.
318 #
@@ -751,11 +751,11 @@
751 set opt $SQLITE_OPTIONS
752 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
753
754 set opt {}
755 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
756 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE\n"
757 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
758
759 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
760 set opt {-Dmain=sqlite3_shell}
761 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
@@ -959,18 +959,35 @@
959
960 # zlib options
961 ZINCDIR = $(B)\compat\zlib
962 ZLIBDIR = $(B)\compat\zlib
963 ZLIB = zlib.lib
 
 
 
 
 
 
964
965 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
966
967 CFLAGS = -nologo -MT -O2
968 BCC = $(CC) $(CFLAGS)
969 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
 
970 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
971 LIBDIR = -LIBPATH:$(ZLIBDIR)
 
 
 
 
 
 
 
 
 
 
972 }
973 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
974 set j " \\\n "
975 writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
976 writeln -nonewline "SRC = "
@@ -981,24 +998,22 @@
981 writeln -nonewline " "
982 }
983 writeln -nonewline "${s}_.c"; incr i
984 }
985 writeln "\n"
 
986 writeln -nonewline "OBJ = "
987 set i 0
988 foreach s [lsort $src] {
989 if {$i > 0} {
990 writeln " \\"
991 writeln -nonewline " "
992 }
993 writeln -nonewline "\$(OX)\\$s\$O"; incr i
994 }
995 writeln " \\"
996 writeln " \$(OX)\\shell\$O \\"
997 writeln " \$(OX)\\sqlite3\$O \\"
998 writeln " \$(OX)\\th\$O \\"
999 writeln " \$(OX)\\th_lang\$O"
1000 writeln {
1001 APPNAME = $(OX)\fossil$(E)
1002
1003 all: $(OX) $(APPNAME)
1004
@@ -1006,15 +1021,15 @@
1006 @echo Building zlib from "$(ZLIBDIR)"...
1007 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
1008
1009 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
1010 cd $(OX)
1011 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj @linkopts
1012
1013 $(OX)\linkopts: $B\win\Makefile.msc}
1014 set redir {>}
1015 foreach s [lsort [concat $src {shell sqlite3 th th_lang}]] {
1016 writeln "\techo \$(OX)\\$s.obj $redir \$@"
1017 set redir {>>}
1018 }
1019 writeln "\techo \$(LIBS) >> \$@\n\n"
1020
@@ -1047,12 +1062,12 @@
1047 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
1048 $(TCC) /Fo$@ -c $**
1049
1050 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
1051 $** > $@
1052 $(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
1053 cp $(SRCDIR)\cson_amalgamation.h $@
1054
1055 page_index.h: mkindex$E $(SRC)
1056 $** > $@
1057
1058 clean:
@@ -1062,10 +1077,11 @@
1062 -del *.h
1063 -del *.map
1064 -del *.manifest
1065 -del headers
1066 -del linkopts
 
1067
1068 realclean: clean
1069 -del $(APPNAME)
1070 -del translate$E
1071 -del mkindex$E
@@ -1092,10 +1108,13 @@
1092 writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
1093 writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
1094 writeln "${s}_.c : \$(SRCDIR)\\$s.c"
1095 writeln "\ttranslate\$E \$** > \$@\n"
1096 }
 
 
 
1097
1098 writeln "headers: makeheaders\$E page_index.h VERSION.h"
1099 writeln -nonewline "\tmakeheaders\$E "
1100 set i 0
1101 foreach s [lsort $src] {
1102
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -308,11 +308,11 @@
308 writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"
309
310 set opt {}
311 writeln {
312 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
313 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
314
315 #
316 # The list of all the targets that do not correspond to real files. This stops
317 # 'make' from getting confused when someone makes an error in a rule.
318 #
@@ -751,11 +751,11 @@
751 set opt $SQLITE_OPTIONS
752 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
753
754 set opt {}
755 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
756 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
757 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
758
759 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
760 set opt {-Dmain=sqlite3_shell}
761 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
@@ -959,18 +959,35 @@
959
960 # zlib options
961 ZINCDIR = $(B)\compat\zlib
962 ZLIBDIR = $(B)\compat\zlib
963 ZLIB = zlib.lib
964
965 # Uncomment to enable JSON API
966 # FOSSIL_ENABLE_JSON = 1
967
968 # Uncomment to enable markdown support
969 # FOSSIL_ENABLE_MARKDOWN = 1
970
971 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
972
973 CFLAGS = -nologo -MT -O2
974 BCC = $(CC) $(CFLAGS)
975 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
976 RCC = rc -D_WIN32 -D_MSC_VER $(INCL)
977 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
978 LIBDIR = -LIBPATH:$(ZLIBDIR)
979
980 !ifdef FOSSIL_ENABLE_JSON
981 TCC = $(TCC) -DFOSSIL_ENABLE_JSON
982 RCC = $(RCC) -DFOSSIL_ENABLE_JSON
983 !endif
984
985 !ifdef FOSSIL_ENABLE_MARKDOWN
986 TCC = $(TCC) -DFOSSIL_ENABLE_MARKDOWN
987 RCC = $(RCC) -DFOSSIL_ENABLE_MARKDOWN
988 !endif
989 }
990 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
991 set j " \\\n "
992 writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
993 writeln -nonewline "SRC = "
@@ -981,24 +998,22 @@
998 writeln -nonewline " "
999 }
1000 writeln -nonewline "${s}_.c"; incr i
1001 }
1002 writeln "\n"
1003 set AdditionalObj [list shell sqlite3 th th_lang cson_amalgamation]
1004 writeln -nonewline "OBJ = "
1005 set i 0
1006 foreach s [lsort [concat $src $AdditionalObj]] {
1007 if {$i > 0} {
1008 writeln " \\"
1009 writeln -nonewline " "
1010 }
1011 writeln -nonewline "\$(OX)\\$s\$O"; incr i
1012 }
1013 writeln " \\"
1014 writeln -nonewline " \$(OX)\\fossil.res\n"
 
 
 
1015 writeln {
1016 APPNAME = $(OX)\fossil$(E)
1017
1018 all: $(OX) $(APPNAME)
1019
@@ -1006,15 +1021,15 @@
1021 @echo Building zlib from "$(ZLIBDIR)"...
1022 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
1023
1024 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
1025 cd $(OX)
1026 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
1027
1028 $(OX)\linkopts: $B\win\Makefile.msc}
1029 set redir {>}
1030 foreach s [lsort [concat $src $AdditionalObj]] {
1031 writeln "\techo \$(OX)\\$s.obj $redir \$@"
1032 set redir {>>}
1033 }
1034 writeln "\techo \$(LIBS) >> \$@\n\n"
1035
@@ -1047,12 +1062,12 @@
1062 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
1063 $(TCC) /Fo$@ -c $**
1064
1065 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
1066 $** > $@
1067 $(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
1068 $(TCC) /Fo$@ -c $**
1069
1070 page_index.h: mkindex$E $(SRC)
1071 $** > $@
1072
1073 clean:
@@ -1062,10 +1077,11 @@
1077 -del *.h
1078 -del *.map
1079 -del *.manifest
1080 -del headers
1081 -del linkopts
1082 -del *.res
1083
1084 realclean: clean
1085 -del $(APPNAME)
1086 -del translate$E
1087 -del mkindex$E
@@ -1092,10 +1108,13 @@
1108 writeln "\$(OX)\\$s\$O : ${s}_.c ${s}.h"
1109 writeln "\t\$(TCC) /Fo\$@ -c ${s}_.c\n"
1110 writeln "${s}_.c : \$(SRCDIR)\\$s.c"
1111 writeln "\ttranslate\$E \$** > \$@\n"
1112 }
1113
1114 writeln "fossil.res : \$B\\win\\fossil.rc"
1115 writeln "\t\$(RCC) -fo \$@ \$**"
1116
1117 writeln "headers: makeheaders\$E page_index.h VERSION.h"
1118 writeln -nonewline "\tmakeheaders\$E "
1119 set i 0
1120 foreach s [lsort $src] {
1121
--- src/merge.c
+++ src/merge.c
@@ -205,10 +205,11 @@
205205
fossil_free(zCom);
206206
}
207207
db_finalize(&q);
208208
}else{
209209
usage("?OPTIONS? ?VERSION?");
210
+ return;
210211
}
211212
212213
if( zPivot ){
213214
pid = name_to_typed_rid(zPivot, "ci");
214215
if( pid==0 || !is_a_version(pid) ){
215216
--- src/merge.c
+++ src/merge.c
@@ -205,10 +205,11 @@
205 fossil_free(zCom);
206 }
207 db_finalize(&q);
208 }else{
209 usage("?OPTIONS? ?VERSION?");
 
210 }
211
212 if( zPivot ){
213 pid = name_to_typed_rid(zPivot, "ci");
214 if( pid==0 || !is_a_version(pid) ){
215
--- src/merge.c
+++ src/merge.c
@@ -205,10 +205,11 @@
205 fossil_free(zCom);
206 }
207 db_finalize(&q);
208 }else{
209 usage("?OPTIONS? ?VERSION?");
210 return;
211 }
212
213 if( zPivot ){
214 pid = name_to_typed_rid(zPivot, "ci");
215 if( pid==0 || !is_a_version(pid) ){
216
--- src/rebuild.c
+++ src/rebuild.c
@@ -524,10 +524,11 @@
524524
** --noverify Skip the verification of changes to the BLOB table
525525
** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
526526
** --randomize Scan artifacts in a random order
527527
** --vacuum Run VACUUM on the database after rebuilding
528528
** --deanalyze Remove ANALYZE tables from the database
529
+** --analyze Run ANALYZE on the database after rebuilding
529530
** --wal Set Write-Ahead-Log journalling mode on the database
530531
** --stats Show artifact statistics after rebuilding
531532
**
532533
** See also: deconstruct, reconstruct
533534
*/
@@ -540,19 +541,21 @@
540541
const char *zPagesize;
541542
int newPagesize = 0;
542543
int activateWal;
543544
int runVacuum;
544545
int runDeanalyze;
546
+ int runAnalyze;
545547
int runCompress;
546548
int showStats;
547549
548550
omitVerify = find_option("noverify",0,0)!=0;
549551
forceFlag = find_option("force","f",0)!=0;
550552
randomizeFlag = find_option("randomize", 0, 0)!=0;
551553
doClustering = find_option("cluster", 0, 0)!=0;
552554
runVacuum = find_option("vacuum",0,0)!=0;
553555
runDeanalyze = find_option("deanalyze",0,0)!=0;
556
+ runAnalyze = find_option("analyze",0,0)!=0;
554557
runCompress = find_option("compress",0,0)!=0;
555558
zPagesize = find_option("pagesize",0,1);
556559
showStats = find_option("stats",0,0)!=0;
557560
if( zPagesize ){
558561
newPagesize = atoi(zPagesize);
@@ -605,10 +608,15 @@
605608
}
606609
if( runDeanalyze ){
607610
db_multi_exec("DROP TABLE IF EXISTS sqlite_stat1;"
608611
"DROP TABLE IF EXISTS sqlite_stat3;");
609612
}
613
+ if( runAnalyze ){
614
+ fossil_print("Analyzing the database... "); fflush(stdout);
615
+ db_multi_exec("ANALYZE;");
616
+ fossil_print("done\n");
617
+ }
610618
if( runVacuum ){
611619
fossil_print("Vacuuming the database... "); fflush(stdout);
612620
db_multi_exec("VACUUM");
613621
fossil_print("done\n");
614622
}
615623
--- src/rebuild.c
+++ src/rebuild.c
@@ -524,10 +524,11 @@
524 ** --noverify Skip the verification of changes to the BLOB table
525 ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
526 ** --randomize Scan artifacts in a random order
527 ** --vacuum Run VACUUM on the database after rebuilding
528 ** --deanalyze Remove ANALYZE tables from the database
 
529 ** --wal Set Write-Ahead-Log journalling mode on the database
530 ** --stats Show artifact statistics after rebuilding
531 **
532 ** See also: deconstruct, reconstruct
533 */
@@ -540,19 +541,21 @@
540 const char *zPagesize;
541 int newPagesize = 0;
542 int activateWal;
543 int runVacuum;
544 int runDeanalyze;
 
545 int runCompress;
546 int showStats;
547
548 omitVerify = find_option("noverify",0,0)!=0;
549 forceFlag = find_option("force","f",0)!=0;
550 randomizeFlag = find_option("randomize", 0, 0)!=0;
551 doClustering = find_option("cluster", 0, 0)!=0;
552 runVacuum = find_option("vacuum",0,0)!=0;
553 runDeanalyze = find_option("deanalyze",0,0)!=0;
 
554 runCompress = find_option("compress",0,0)!=0;
555 zPagesize = find_option("pagesize",0,1);
556 showStats = find_option("stats",0,0)!=0;
557 if( zPagesize ){
558 newPagesize = atoi(zPagesize);
@@ -605,10 +608,15 @@
605 }
606 if( runDeanalyze ){
607 db_multi_exec("DROP TABLE IF EXISTS sqlite_stat1;"
608 "DROP TABLE IF EXISTS sqlite_stat3;");
609 }
 
 
 
 
 
610 if( runVacuum ){
611 fossil_print("Vacuuming the database... "); fflush(stdout);
612 db_multi_exec("VACUUM");
613 fossil_print("done\n");
614 }
615
--- src/rebuild.c
+++ src/rebuild.c
@@ -524,10 +524,11 @@
524 ** --noverify Skip the verification of changes to the BLOB table
525 ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
526 ** --randomize Scan artifacts in a random order
527 ** --vacuum Run VACUUM on the database after rebuilding
528 ** --deanalyze Remove ANALYZE tables from the database
529 ** --analyze Run ANALYZE on the database after rebuilding
530 ** --wal Set Write-Ahead-Log journalling mode on the database
531 ** --stats Show artifact statistics after rebuilding
532 **
533 ** See also: deconstruct, reconstruct
534 */
@@ -540,19 +541,21 @@
541 const char *zPagesize;
542 int newPagesize = 0;
543 int activateWal;
544 int runVacuum;
545 int runDeanalyze;
546 int runAnalyze;
547 int runCompress;
548 int showStats;
549
550 omitVerify = find_option("noverify",0,0)!=0;
551 forceFlag = find_option("force","f",0)!=0;
552 randomizeFlag = find_option("randomize", 0, 0)!=0;
553 doClustering = find_option("cluster", 0, 0)!=0;
554 runVacuum = find_option("vacuum",0,0)!=0;
555 runDeanalyze = find_option("deanalyze",0,0)!=0;
556 runAnalyze = find_option("analyze",0,0)!=0;
557 runCompress = find_option("compress",0,0)!=0;
558 zPagesize = find_option("pagesize",0,1);
559 showStats = find_option("stats",0,0)!=0;
560 if( zPagesize ){
561 newPagesize = atoi(zPagesize);
@@ -605,10 +608,15 @@
608 }
609 if( runDeanalyze ){
610 db_multi_exec("DROP TABLE IF EXISTS sqlite_stat1;"
611 "DROP TABLE IF EXISTS sqlite_stat3;");
612 }
613 if( runAnalyze ){
614 fossil_print("Analyzing the database... "); fflush(stdout);
615 db_multi_exec("ANALYZE;");
616 fossil_print("done\n");
617 }
618 if( runVacuum ){
619 fossil_print("Vacuuming the database... "); fflush(stdout);
620 db_multi_exec("VACUUM");
621 fossil_print("done\n");
622 }
623
+7 -7
--- src/regexp.c
+++ src/regexp.c
@@ -172,11 +172,11 @@
172172
return (c>='0' && c<='9');
173173
}
174174
175175
/* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
176176
static int re_space_char(int c){
177
- return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f' ;
177
+ return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
178178
}
179179
180180
/* Run a compiled regular expression on the zero-terminated input
181181
** string zIn[]. Return true on a match and false if there is no match.
182182
*/
@@ -401,17 +401,17 @@
401401
){
402402
p->sIn.i += 5;
403403
return v;
404404
}
405405
}
406
- if( c=='x' ){
406
+ if( c=='x' && p->sIn.i+2<p->sIn.mx ){
407407
const unsigned char *zIn = p->sIn.z + p->sIn.i;
408
- if( p->sIn.i+2<p->sIn.mx ){
409
- if( re_hex(zIn[1],&v) && re_hex(zIn[2],&v) ){
410
- p->sIn.i += 3;
411
- return v;
412
- }
408
+ if( re_hex(zIn[1],&v)
409
+ && re_hex(zIn[2],&v)
410
+ ){
411
+ p->sIn.i += 3;
412
+ return v;
413413
}
414414
}
415415
for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
416416
if( zEsc[i] ){
417417
if( i<6 ) c = zTrans[i];
418418
--- src/regexp.c
+++ src/regexp.c
@@ -172,11 +172,11 @@
172 return (c>='0' && c<='9');
173 }
174
175 /* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
176 static int re_space_char(int c){
177 return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f' ;
178 }
179
180 /* Run a compiled regular expression on the zero-terminated input
181 ** string zIn[]. Return true on a match and false if there is no match.
182 */
@@ -401,17 +401,17 @@
401 ){
402 p->sIn.i += 5;
403 return v;
404 }
405 }
406 if( c=='x' ){
407 const unsigned char *zIn = p->sIn.z + p->sIn.i;
408 if( p->sIn.i+2<p->sIn.mx ){
409 if( re_hex(zIn[1],&v) && re_hex(zIn[2],&v) ){
410 p->sIn.i += 3;
411 return v;
412 }
413 }
414 }
415 for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
416 if( zEsc[i] ){
417 if( i<6 ) c = zTrans[i];
418
--- src/regexp.c
+++ src/regexp.c
@@ -172,11 +172,11 @@
172 return (c>='0' && c<='9');
173 }
174
175 /* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
176 static int re_space_char(int c){
177 return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
178 }
179
180 /* Run a compiled regular expression on the zero-terminated input
181 ** string zIn[]. Return true on a match and false if there is no match.
182 */
@@ -401,17 +401,17 @@
401 ){
402 p->sIn.i += 5;
403 return v;
404 }
405 }
406 if( c=='x' && p->sIn.i+2<p->sIn.mx ){
407 const unsigned char *zIn = p->sIn.z + p->sIn.i;
408 if( re_hex(zIn[1],&v)
409 && re_hex(zIn[2],&v)
410 ){
411 p->sIn.i += 3;
412 return v;
413 }
414 }
415 for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
416 if( zEsc[i] ){
417 if( i<6 ) c = zTrans[i];
418
--- src/setup.c
+++ src/setup.c
@@ -917,10 +917,19 @@
917917
@ to this many bytes, uncompressed. If the client requires more data
918918
@ than this, then the client will issue multiple HTTP requests.
919919
@ Values below 1 million are not recommended. 5 million is a
920920
@ reasonable number.</p>
921921
922
+ @ <hr />
923
+ entry_attribute("Download time limit", 11, "max-download-time", "mxdwnt",
924
+ "30");
925
+
926
+ @ <p>Fossil tries to spend less than this many seconds gathering
927
+ @ the out-bound data of sync, clone, and pull packets.
928
+ @ If the client request takes longer, a partial reply is given similar
929
+ @ to the download packet limit. 30s is a reasonable default.</p>
930
+
922931
@ <hr />
923932
onoff_attribute(
924933
"Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
925934
"auto-hyperlink", "autohyperlink", 1);
926935
@ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
927936
--- src/setup.c
+++ src/setup.c
@@ -917,10 +917,19 @@
917 @ to this many bytes, uncompressed. If the client requires more data
918 @ than this, then the client will issue multiple HTTP requests.
919 @ Values below 1 million are not recommended. 5 million is a
920 @ reasonable number.</p>
921
 
 
 
 
 
 
 
 
 
922 @ <hr />
923 onoff_attribute(
924 "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
925 "auto-hyperlink", "autohyperlink", 1);
926 @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
927
--- src/setup.c
+++ src/setup.c
@@ -917,10 +917,19 @@
917 @ to this many bytes, uncompressed. If the client requires more data
918 @ than this, then the client will issue multiple HTTP requests.
919 @ Values below 1 million are not recommended. 5 million is a
920 @ reasonable number.</p>
921
922 @ <hr />
923 entry_attribute("Download time limit", 11, "max-download-time", "mxdwnt",
924 "30");
925
926 @ <p>Fossil tries to spend less than this many seconds gathering
927 @ the out-bound data of sync, clone, and pull packets.
928 @ If the client request takes longer, a partial reply is given similar
929 @ to the download packet limit. 30s is a reasonable default.</p>
930
931 @ <hr />
932 onoff_attribute(
933 "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
934 "auto-hyperlink", "autohyperlink", 1);
935 @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
936
+199 -93
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -673,11 +673,11 @@
673673
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674674
** [sqlite_version()] and [sqlite_source_id()].
675675
*/
676676
#define SQLITE_VERSION "3.7.16"
677677
#define SQLITE_VERSION_NUMBER 3007016
678
-#define SQLITE_SOURCE_ID "2013-01-09 11:31:17 5774f2175ce621dfc4b6b93f7ee13fd66f3ec2b9"
678
+#define SQLITE_SOURCE_ID "2013-01-17 17:20:49 38852f158ab20bb4d7b264af987ec1538052bec3"
679679
680680
/*
681681
** CAPI3REF: Run-Time Library Version Numbers
682682
** KEYWORDS: sqlite3_version, sqlite3_sourceid
683683
**
@@ -8238,10 +8238,15 @@
82388238
** A convenience macro that returns the number of elements in
82398239
** an array.
82408240
*/
82418241
#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
82428242
8243
+/*
8244
+** Determine if the argument is a power of two
8245
+*/
8246
+#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
8247
+
82438248
/*
82448249
** The following value as a destructor means to use sqlite3DbFree().
82458250
** The sqlite3DbFree() routine requires two parameters instead of the
82468251
** one parameter that destructors normally want. So we have to introduce
82478252
** this magic value that the code knows to handle differently. Any
@@ -10042,10 +10047,11 @@
1004210047
#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
1004310048
#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
1004410049
#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
1004510050
#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
1004610051
#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
10052
+#define SQLITE_Transitive 0x0200 /* Transitive constraints */
1004710053
#define SQLITE_AllOpts 0xffff /* All optimizations */
1004810054
1004910055
/*
1005010056
** Macros for testing whether or not optimizations are enabled or disabled.
1005110057
*/
@@ -93581,11 +93587,11 @@
9358193587
sqlite3_rekey(db, zKey, i/2);
9358293588
}
9358393589
}else
9358493590
#endif
9358593591
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
93586
- if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
93592
+ if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
9358793593
#ifdef SQLITE_HAS_CODEC
9358893594
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
9358993595
sqlite3_activate_see(&zRight[4]);
9359093596
}
9359193597
#endif
@@ -102802,12 +102808,12 @@
102802102808
Expr *pExpr; /* Pointer to the subexpression that is this term */
102803102809
int iParent; /* Disable pWC->a[iParent] when this term disabled */
102804102810
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
102805102811
union {
102806102812
int leftColumn; /* Column number of X in "X <op> <expr>" */
102807
- WhereOrInfo *pOrInfo; /* Extra information if eOperator==WO_OR */
102808
- WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */
102813
+ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
102814
+ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
102809102815
} u;
102810102816
u16 eOperator; /* A WO_xx value describing <op> */
102811102817
u8 wtFlags; /* TERM_xxx bit flags. See below */
102812102818
u8 nChild; /* Number of children that must disable us */
102813102819
WhereClause *pWC; /* The clause this term is part of */
@@ -102931,10 +102937,11 @@
102931102937
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
102932102938
#define WO_MATCH 0x040
102933102939
#define WO_ISNULL 0x080
102934102940
#define WO_OR 0x100 /* Two or more OR-connected terms */
102935102941
#define WO_AND 0x200 /* Two or more AND-connected terms */
102942
+#define WO_EQUIV 0x400 /* Of the form A==B, both columns */
102936102943
#define WO_NOOP 0x800 /* This term does not restrict search space */
102937102944
102938102945
#define WO_ALL 0xfff /* Mask of all possible WO_* values */
102939102946
#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
102940102947
@@ -103333,58 +103340,112 @@
103333103340
/*
103334103341
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
103335103342
** where X is a reference to the iColumn of table iCur and <op> is one of
103336103343
** the WO_xx operator codes specified by the op parameter.
103337103344
** Return a pointer to the term. Return 0 if not found.
103345
+**
103346
+** The term returned might by Y=<expr> if there is another constraint in
103347
+** the WHERE clause that specifies that X=Y. Any such constraints will be
103348
+** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
103349
+** aEquiv[] array holds X and all its equivalents, with each SQL variable
103350
+** taking up two slots in aEquiv[]. The first slot is for the cursor number
103351
+** and the second is for the column number. There are 22 slots in aEquiv[]
103352
+** so that means we can look for X plus up to 10 other equivalent values.
103353
+** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
103354
+** and ... and A9=A10 and A10=<expr>.
103355
+**
103356
+** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
103357
+** then try for the one with no dependencies on <expr> - in other words where
103358
+** <expr> is a constant expression of some kind. Only return entries of
103359
+** the form "X <op> Y" where Y is a column in another table if no terms of
103360
+** the form "X <op> <const-expr>" exist. Other than this priority, if there
103361
+** are two or more terms that match, then the choice of which term to return
103362
+** is arbitrary.
103338103363
*/
103339103364
static WhereTerm *findTerm(
103340103365
WhereClause *pWC, /* The WHERE clause to be searched */
103341103366
int iCur, /* Cursor number of LHS */
103342103367
int iColumn, /* Column number of LHS */
103343103368
Bitmask notReady, /* RHS must not overlap with this mask */
103344103369
u32 op, /* Mask of WO_xx values describing operator */
103345103370
Index *pIdx /* Must be compatible with this index, if not NULL */
103346103371
){
103347
- WhereTerm *pTerm;
103348
- int k;
103372
+ WhereTerm *pTerm; /* Term being examined as possible result */
103373
+ WhereTerm *pResult = 0; /* The answer to return */
103374
+ WhereClause *pWCOrig = pWC; /* Original pWC value */
103375
+ int j, k; /* Loop counters */
103376
+ Expr *pX; /* Pointer to an expression */
103377
+ Parse *pParse; /* Parsing context */
103378
+ int iOrigCol = iColumn; /* Original value of iColumn */
103379
+ int nEquiv = 2; /* Number of entires in aEquiv[] */
103380
+ int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */
103381
+ int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */
103382
+
103349103383
assert( iCur>=0 );
103350
- op &= WO_ALL;
103351
- for(; pWC; pWC=pWC->pOuter){
103352
- for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
103353
- if( pTerm->leftCursor==iCur
103354
- && (pTerm->prereqRight & notReady)==0
103355
- && pTerm->u.leftColumn==iColumn
103356
- && (pTerm->eOperator & op)!=0
103357
- ){
103358
- if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
103359
- Expr *pX = pTerm->pExpr;
103360
- CollSeq *pColl;
103361
- char idxaff;
103362
- int j;
103363
- Parse *pParse = pWC->pParse;
103364
-
103365
- idxaff = pIdx->pTable->aCol[iColumn].affinity;
103366
- if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
103367
-
103368
- /* Figure out the collation sequence required from an index for
103369
- ** it to be useful for optimising expression pX. Store this
103370
- ** value in variable pColl.
103371
- */
103372
- assert(pX->pLeft);
103373
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
103374
- if( pColl==0 ) pColl = pParse->db->pDfltColl;
103375
-
103376
- for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
103377
- if( NEVER(j>=pIdx->nColumn) ) return 0;
103378
- }
103379
- if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
103380
- }
103381
- return pTerm;
103382
- }
103383
- }
103384
- }
103385
- return 0;
103384
+ aEquiv[0] = iCur;
103385
+ aEquiv[1] = iColumn;
103386
+ for(;;){
103387
+ for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
103388
+ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
103389
+ if( pTerm->leftCursor==iCur
103390
+ && pTerm->u.leftColumn==iColumn
103391
+ ){
103392
+ if( (pTerm->prereqRight & notReady)==0
103393
+ && (pTerm->eOperator & op & WO_ALL)!=0
103394
+ ){
103395
+ if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
103396
+ CollSeq *pColl;
103397
+ char idxaff;
103398
+
103399
+ pX = pTerm->pExpr;
103400
+ pParse = pWC->pParse;
103401
+ idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
103402
+ if( !sqlite3IndexAffinityOk(pX, idxaff) ){
103403
+ continue;
103404
+ }
103405
+
103406
+ /* Figure out the collation sequence required from an index for
103407
+ ** it to be useful for optimising expression pX. Store this
103408
+ ** value in variable pColl.
103409
+ */
103410
+ assert(pX->pLeft);
103411
+ pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
103412
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
103413
+
103414
+ for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
103415
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
103416
+ }
103417
+ if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
103418
+ continue;
103419
+ }
103420
+ }
103421
+ pResult = pTerm;
103422
+ if( pTerm->prereqRight==0 ) goto findTerm_success;
103423
+ }
103424
+ if( (pTerm->eOperator & WO_EQUIV)!=0
103425
+ && nEquiv<ArraySize(aEquiv)
103426
+ ){
103427
+ pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
103428
+ assert( pX->op==TK_COLUMN );
103429
+ for(j=0; j<nEquiv; j+=2){
103430
+ if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
103431
+ }
103432
+ if( j==nEquiv ){
103433
+ aEquiv[j] = pX->iTable;
103434
+ aEquiv[j+1] = pX->iColumn;
103435
+ nEquiv += 2;
103436
+ }
103437
+ }
103438
+ }
103439
+ }
103440
+ }
103441
+ if( iEquiv>=nEquiv ) break;
103442
+ iCur = aEquiv[iEquiv++];
103443
+ iColumn = aEquiv[iEquiv++];
103444
+ }
103445
+findTerm_success:
103446
+ return pResult;
103386103447
}
103387103448
103388103449
/* Forward reference */
103389103450
static void exprAnalyze(SrcList*, WhereClause*, int);
103390103451
@@ -103658,11 +103719,10 @@
103658103719
indexable = ~(Bitmask)0;
103659103720
chngToIN = ~(pWC->vmask);
103660103721
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
103661103722
if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
103662103723
WhereAndInfo *pAndInfo;
103663
- assert( pOrTerm->eOperator==0 );
103664103724
assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
103665103725
chngToIN = 0;
103666103726
pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
103667103727
if( pAndInfo ){
103668103728
WhereClause *pAndWC;
@@ -103697,11 +103757,11 @@
103697103757
if( pOrTerm->wtFlags & TERM_VIRTUAL ){
103698103758
WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
103699103759
b |= getMask(pMaskSet, pOther->leftCursor);
103700103760
}
103701103761
indexable &= b;
103702
- if( pOrTerm->eOperator!=WO_EQ ){
103762
+ if( (pOrTerm->eOperator & WO_EQ)==0 ){
103703103763
chngToIN = 0;
103704103764
}else{
103705103765
chngToIN &= b;
103706103766
}
103707103767
}
@@ -103748,11 +103808,11 @@
103748103808
** and column is found but leave okToChngToIN false if not found.
103749103809
*/
103750103810
for(j=0; j<2 && !okToChngToIN; j++){
103751103811
pOrTerm = pOrWc->a;
103752103812
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
103753
- assert( pOrTerm->eOperator==WO_EQ );
103813
+ assert( pOrTerm->eOperator & WO_EQ );
103754103814
pOrTerm->wtFlags &= ~TERM_OR_OK;
103755103815
if( pOrTerm->leftCursor==iCursor ){
103756103816
/* This is the 2-bit case and we are on the second iteration and
103757103817
** current term is from the first iteration. So skip this term. */
103758103818
assert( j==1 );
@@ -103774,21 +103834,21 @@
103774103834
}
103775103835
if( i<0 ){
103776103836
/* No candidate table+column was found. This can only occur
103777103837
** on the second iteration */
103778103838
assert( j==1 );
103779
- assert( (chngToIN&(chngToIN-1))==0 );
103839
+ assert( IsPowerOfTwo(chngToIN) );
103780103840
assert( chngToIN==getMask(pMaskSet, iCursor) );
103781103841
break;
103782103842
}
103783103843
testcase( j==1 );
103784103844
103785103845
/* We have found a candidate table and column. Check to see if that
103786103846
** table and column is common to every term in the OR clause */
103787103847
okToChngToIN = 1;
103788103848
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
103789
- assert( pOrTerm->eOperator==WO_EQ );
103849
+ assert( pOrTerm->eOperator & WO_EQ );
103790103850
if( pOrTerm->leftCursor!=iCursor ){
103791103851
pOrTerm->wtFlags &= ~TERM_OR_OK;
103792103852
}else if( pOrTerm->u.leftColumn!=iColumn ){
103793103853
okToChngToIN = 0;
103794103854
}else{
@@ -103820,11 +103880,11 @@
103820103880
Expr *pLeft = 0; /* The LHS of the IN operator */
103821103881
Expr *pNew; /* The complete IN operator */
103822103882
103823103883
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
103824103884
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
103825
- assert( pOrTerm->eOperator==WO_EQ );
103885
+ assert( pOrTerm->eOperator & WO_EQ );
103826103886
assert( pOrTerm->leftCursor==iCursor );
103827103887
assert( pOrTerm->u.leftColumn==iColumn );
103828103888
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
103829103889
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
103830103890
pLeft = pOrTerm->pExpr->pLeft;
@@ -103849,11 +103909,10 @@
103849103909
pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
103850103910
}
103851103911
}
103852103912
}
103853103913
#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
103854
-
103855103914
103856103915
/*
103857103916
** The input to this routine is an WhereTerm structure with only the
103858103917
** "pExpr" field filled in. The job of this routine is to analyze the
103859103918
** subexpression and populate all the other fields of the WhereTerm
@@ -103919,21 +103978,23 @@
103919103978
}
103920103979
pTerm->prereqAll = prereqAll;
103921103980
pTerm->leftCursor = -1;
103922103981
pTerm->iParent = -1;
103923103982
pTerm->eOperator = 0;
103924
- if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
103983
+ if( allowedOp(op) ){
103925103984
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
103926103985
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
103986
+ u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
103927103987
if( pLeft->op==TK_COLUMN ){
103928103988
pTerm->leftCursor = pLeft->iTable;
103929103989
pTerm->u.leftColumn = pLeft->iColumn;
103930
- pTerm->eOperator = operatorMask(op);
103990
+ pTerm->eOperator = operatorMask(op) & opMask;
103931103991
}
103932103992
if( pRight && pRight->op==TK_COLUMN ){
103933103993
WhereTerm *pNew;
103934103994
Expr *pDup;
103995
+ u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
103935103996
if( pTerm->leftCursor>=0 ){
103936103997
int idxNew;
103937103998
pDup = sqlite3ExprDup(db, pExpr, 0);
103938103999
if( db->mallocFailed ){
103939104000
sqlite3ExprDelete(db, pDup);
@@ -103944,10 +104005,17 @@
103944104005
pNew = &pWC->a[idxNew];
103945104006
pNew->iParent = idxTerm;
103946104007
pTerm = &pWC->a[idxTerm];
103947104008
pTerm->nChild = 1;
103948104009
pTerm->wtFlags |= TERM_COPIED;
104010
+ if( pExpr->op==TK_EQ
104011
+ && !ExprHasProperty(pExpr, EP_FromJoin)
104012
+ && OptimizationEnabled(db, SQLITE_Transitive)
104013
+ ){
104014
+ pTerm->eOperator |= WO_EQUIV;
104015
+ eExtraOp = WO_EQUIV;
104016
+ }
103949104017
}else{
103950104018
pDup = pExpr;
103951104019
pNew = pTerm;
103952104020
}
103953104021
exprCommute(pParse, pDup);
@@ -103955,11 +104023,11 @@
103955104023
pNew->leftCursor = pLeft->iTable;
103956104024
pNew->u.leftColumn = pLeft->iColumn;
103957104025
testcase( (prereqLeft | extraRight) != prereqLeft );
103958104026
pNew->prereqRight = prereqLeft | extraRight;
103959104027
pNew->prereqAll = prereqAll;
103960
- pNew->eOperator = operatorMask(pDup->op);
104028
+ pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
103961104029
}
103962104030
}
103963104031
103964104032
#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
103965104033
/* If a term is the BETWEEN operator, create two new virtual terms
@@ -104414,11 +104482,11 @@
104414104482
return;
104415104483
}
104416104484
104417104485
/* Search the WHERE clause terms for a usable WO_OR term. */
104418104486
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
104419
- if( pTerm->eOperator==WO_OR
104487
+ if( (pTerm->eOperator & WO_OR)!=0
104420104488
&& ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
104421104489
&& (pTerm->u.pOrInfo->indexable & maskSrc)!=0
104422104490
){
104423104491
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
104424104492
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
@@ -104435,11 +104503,11 @@
104435104503
sBOI.ppIdxInfo = 0;
104436104504
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
104437104505
WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
104438104506
(pOrTerm - pOrWC->a), (pTerm - pWC->a)
104439104507
));
104440
- if( pOrTerm->eOperator==WO_AND ){
104508
+ if( (pOrTerm->eOperator& WO_AND)!=0 ){
104441104509
sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
104442104510
bestIndex(&sBOI);
104443104511
}else if( pOrTerm->leftCursor==iCur ){
104444104512
WhereClause tempWC;
104445104513
tempWC.pParse = pWC->pParse;
@@ -104496,11 +104564,11 @@
104496104564
struct SrcList_item *pSrc, /* Table we are trying to access */
104497104565
Bitmask notReady /* Tables in outer loops of the join */
104498104566
){
104499104567
char aff;
104500104568
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
104501
- if( pTerm->eOperator!=WO_EQ ) return 0;
104569
+ if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
104502104570
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
104503104571
aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
104504104572
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
104505104573
return 1;
104506104574
}
@@ -104758,13 +104826,13 @@
104758104826
104759104827
/* Count the number of possible WHERE clause constraints referring
104760104828
** to this virtual table */
104761104829
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104762104830
if( pTerm->leftCursor != pSrc->iCursor ) continue;
104763
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104764
- testcase( pTerm->eOperator==WO_IN );
104765
- testcase( pTerm->eOperator==WO_ISNULL );
104831
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
104832
+ testcase( pTerm->eOperator & WO_IN );
104833
+ testcase( pTerm->eOperator & WO_ISNULL );
104766104834
if( pTerm->eOperator & (WO_ISNULL) ) continue;
104767104835
if( pTerm->wtFlags & TERM_VNULL ) continue;
104768104836
nTerm++;
104769104837
}
104770104838
@@ -104811,18 +104879,18 @@
104811104879
pUsage;
104812104880
104813104881
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104814104882
u8 op;
104815104883
if( pTerm->leftCursor != pSrc->iCursor ) continue;
104816
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104817
- testcase( pTerm->eOperator==WO_IN );
104818
- testcase( pTerm->eOperator==WO_ISNULL );
104884
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
104885
+ testcase( pTerm->eOperator & WO_IN );
104886
+ testcase( pTerm->eOperator & WO_ISNULL );
104819104887
if( pTerm->eOperator & (WO_ISNULL) ) continue;
104820104888
if( pTerm->wtFlags & TERM_VNULL ) continue;
104821104889
pIdxCons[j].iColumn = pTerm->u.leftColumn;
104822104890
pIdxCons[j].iTermOffset = i;
104823
- op = (u8)pTerm->eOperator;
104891
+ op = (u8)pTerm->eOperator & WO_ALL;
104824104892
if( op==WO_IN ) op = WO_EQ;
104825104893
pIdxCons[j].op = op;
104826104894
/* The direct assignment in the previous line is possible only because
104827104895
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
104828104896
** following asserts verify this fact. */
@@ -104988,11 +105056,11 @@
104988105056
pUsage = pIdxInfo->aConstraintUsage;
104989105057
for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
104990105058
j = pIdxCons->iTermOffset;
104991105059
pTerm = &pWC->a[j];
104992105060
if( (pTerm->prereqRight&p->notReady)==0
104993
- && (bAllowIN || pTerm->eOperator!=WO_IN)
105061
+ && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
104994105062
){
104995105063
pIdxCons->usable = 1;
104996105064
}else{
104997105065
pIdxCons->usable = 0;
104998105066
}
@@ -105020,11 +105088,11 @@
105020105088
for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
105021105089
if( pUsage[i].argvIndex>0 ){
105022105090
j = pIdxCons->iTermOffset;
105023105091
pTerm = &pWC->a[j];
105024105092
p->cost.used |= pTerm->prereqRight;
105025
- if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){
105093
+ if( (pTerm->eOperator & WO_IN)!=0 && pUsage[i].omit==0 ){
105026105094
/* Do not attempt to use an IN constraint if the virtual table
105027105095
** says that the equivalent EQ constraint cannot be safely omitted.
105028105096
** If we do attempt to use such a constraint, some rows might be
105029105097
** repeated in the output. */
105030105098
break;
@@ -105326,28 +105394,28 @@
105326105394
u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
105327105395
105328105396
if( pLower ){
105329105397
Expr *pExpr = pLower->pExpr->pRight;
105330105398
rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
105331
- assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
105399
+ assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
105332105400
if( rc==SQLITE_OK
105333105401
&& whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
105334105402
){
105335105403
iLower = a[0];
105336
- if( pLower->eOperator==WO_GT ) iLower += a[1];
105404
+ if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
105337105405
}
105338105406
sqlite3ValueFree(pRangeVal);
105339105407
}
105340105408
if( rc==SQLITE_OK && pUpper ){
105341105409
Expr *pExpr = pUpper->pExpr->pRight;
105342105410
rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
105343
- assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
105411
+ assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
105344105412
if( rc==SQLITE_OK
105345105413
&& whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
105346105414
){
105347105415
iUpper = a[0];
105348
- if( pUpper->eOperator==WO_LE ) iUpper += a[1];
105416
+ if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
105349105417
}
105350105418
sqlite3ValueFree(pRangeVal);
105351105419
}
105352105420
if( rc==SQLITE_OK ){
105353105421
if( iUpper<=iLower ){
@@ -105651,16 +105719,16 @@
105651105719
** if there are any X= or X IS NULL constraints in the WHERE clause. */
105652105720
pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
105653105721
WO_EQ|WO_ISNULL|WO_IN, pIdx);
105654105722
if( pConstraint==0 ){
105655105723
isEq = 0;
105656
- }else if( pConstraint->eOperator==WO_IN ){
105724
+ }else if( (pConstraint->eOperator & WO_IN)!=0 ){
105657105725
/* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
105658105726
** because we do not know in what order the values on the RHS of the IN
105659105727
** operator will occur. */
105660105728
break;
105661
- }else if( pConstraint->eOperator==WO_ISNULL ){
105729
+ }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
105662105730
uniqueNotNull = 0;
105663105731
isEq = 1; /* "X IS NULL" means X has only a single value */
105664105732
}else if( pConstraint->prereqRight==0 ){
105665105733
isEq = 1; /* Constraint "X=constant" means X has only a single value */
105666105734
}else{
@@ -106069,16 +106137,17 @@
106069106137
*/
106070106138
if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
106071106139
&& pFirstTerm!=0 && aiRowEst[1]>1 ){
106072106140
assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
106073106141
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
106074
- testcase( pFirstTerm->eOperator==WO_EQ );
106075
- testcase( pFirstTerm->eOperator==WO_ISNULL );
106142
+ testcase( pFirstTerm->eOperator & WO_EQ );
106143
+ testcase( pFirstTerm->eOperator & WO_EQUIV );
106144
+ testcase( pFirstTerm->eOperator & WO_ISNULL );
106076106145
whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
106077106146
&pc.plan.nRow);
106078106147
}else if( bInEst==0 ){
106079
- assert( pFirstTerm->eOperator==WO_IN );
106148
+ assert( pFirstTerm->eOperator & WO_IN );
106080106149
whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
106081106150
&pc.plan.nRow);
106082106151
}
106083106152
}
106084106153
#endif /* SQLITE_ENABLE_STAT3 */
@@ -106221,11 +106290,11 @@
106221106290
** more selective intentionally because of the subjective
106222106291
** observation that indexed range constraints really are more
106223106292
** selective in practice, on average. */
106224106293
pc.plan.nRow /= 3;
106225106294
}
106226
- }else if( pTerm->eOperator!=WO_NOOP ){
106295
+ }else if( (pTerm->eOperator & WO_NOOP)==0 ){
106227106296
/* Any other expression lowers the output row count by half */
106228106297
pc.plan.nRow /= 2;
106229106298
}
106230106299
}
106231106300
if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
@@ -106273,12 +106342,13 @@
106273106342
assert( pSrc->pIndex==0
106274106343
|| p->cost.plan.u.pIdx==0
106275106344
|| p->cost.plan.u.pIdx==pSrc->pIndex
106276106345
);
106277106346
106278
- WHERETRACE((" best index is: %s\n",
106279
- p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
106347
+ WHERETRACE((" best index is %s cost=%.1f\n",
106348
+ p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
106349
+ p->cost.rCost));
106280106350
106281106351
bestOrClauseIndex(p);
106282106352
bestAutomaticIndex(p);
106283106353
p->cost.plan.wsFlags |= eqTermMask;
106284106354
}
@@ -106856,11 +106926,10 @@
106856106926
*/
106857106927
iReleaseReg = sqlite3GetTempReg(pParse);
106858106928
pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
106859106929
assert( pTerm!=0 );
106860106930
assert( pTerm->pExpr!=0 );
106861
- assert( pTerm->leftCursor==iCur );
106862106931
assert( omitTable==0 );
106863106932
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
106864106933
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
106865106934
addrNxt = pLevel->addrNxt;
106866106935
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
@@ -107247,11 +107316,11 @@
107247107316
int ii; /* Loop counter */
107248107317
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
107249107318
107250107319
pTerm = pLevel->plan.u.pTerm;
107251107320
assert( pTerm!=0 );
107252
- assert( pTerm->eOperator==WO_OR );
107321
+ assert( pTerm->eOperator & WO_OR );
107253107322
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
107254107323
pOrWc = &pTerm->u.pOrInfo->wc;
107255107324
pLevel->op = OP_Return;
107256107325
pLevel->p1 = regReturn;
107257107326
@@ -107320,11 +107389,11 @@
107320107389
}
107321107390
}
107322107391
107323107392
for(ii=0; ii<pOrWc->nTerm; ii++){
107324107393
WhereTerm *pOrTerm = &pOrWc->a[ii];
107325
- if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
107394
+ if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
107326107395
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
107327107396
Expr *pOrExpr = pOrTerm->pExpr;
107328107397
if( pAndExpr ){
107329107398
pAndExpr->pLeft = pOrExpr;
107330107399
pOrExpr = pAndExpr;
@@ -107775,10 +107844,11 @@
107775107844
Index *pIdx; /* Index for FROM table at pTabItem */
107776107845
int j; /* For looping over FROM tables */
107777107846
int bestJ = -1; /* The value of j */
107778107847
Bitmask m; /* Bitmask value for j or bestJ */
107779107848
int isOptimal; /* Iterator for optimal/non-optimal search */
107849
+ int ckOptimal; /* Do the optimal scan check */
107780107850
int nUnconstrained; /* Number tables without INDEXED BY */
107781107851
Bitmask notIndexed; /* Mask of tables that cannot use an index */
107782107852
107783107853
memset(&bestPlan, 0, sizeof(bestPlan));
107784107854
bestPlan.rCost = SQLITE_BIG_DBL;
@@ -107809,14 +107879,12 @@
107809107879
**
107810107880
** The second loop iteration is only performed if no optimal scan
107811107881
** strategies were found by the first iteration. This second iteration
107812107882
** is used to search for the lowest cost scan overall.
107813107883
**
107814
- ** Previous versions of SQLite performed only the second iteration -
107815
- ** the next outermost loop was always that with the lowest overall
107816
- ** cost. However, this meant that SQLite could select the wrong plan
107817
- ** for scripts such as the following:
107884
+ ** Without the optimal scan step (the first iteration) a suboptimal
107885
+ ** plan might be chosen for queries like this:
107818107886
**
107819107887
** CREATE TABLE t1(a, b);
107820107888
** CREATE TABLE t2(c, d);
107821107889
** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
107822107890
**
@@ -107827,20 +107895,44 @@
107827107895
** algorithm may choose to use t2 for the outer loop, which is a much
107828107896
** costlier approach.
107829107897
*/
107830107898
nUnconstrained = 0;
107831107899
notIndexed = 0;
107832
- for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
107900
+
107901
+ /* The optimal scan check only occurs if there are two or more tables
107902
+ ** available to be reordered */
107903
+ if( iFrom==nTabList-1 ){
107904
+ ckOptimal = 0; /* Common case of just one table in the FROM clause */
107905
+ }else{
107906
+ ckOptimal = -1;
107833107907
for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
107834
- int doNotReorder; /* True if this table should not be reordered */
107835
-
107836
- doNotReorder = (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0;
107837
- if( j!=iFrom && doNotReorder ) break;
107838107908
m = getMask(pMaskSet, sWBI.pSrc->iCursor);
107839107909
if( (m & sWBI.notValid)==0 ){
107840107910
if( j==iFrom ) iFrom++;
107841107911
continue;
107912
+ }
107913
+ if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
107914
+ if( ++ckOptimal ) break;
107915
+ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
107916
+ }
107917
+ }
107918
+ assert( ckOptimal==0 || ckOptimal==1 );
107919
+
107920
+ for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
107921
+ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
107922
+ if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
107923
+ /* This break and one like it in the ckOptimal computation loop
107924
+ ** above prevent table reordering across LEFT and CROSS JOINs.
107925
+ ** The LEFT JOIN case is necessary for correctness. The prohibition
107926
+ ** against reordering across a CROSS JOIN is an SQLite feature that
107927
+ ** allows the developer to control table reordering */
107928
+ break;
107929
+ }
107930
+ m = getMask(pMaskSet, sWBI.pSrc->iCursor);
107931
+ if( (m & sWBI.notValid)==0 ){
107932
+ assert( j>iFrom );
107933
+ continue;
107842107934
}
107843107935
sWBI.notReady = (isOptimal ? m : sWBI.notValid);
107844107936
if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
107845107937
107846107938
WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
@@ -107866,12 +107958,12 @@
107866107958
if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
107867107959
notIndexed |= m;
107868107960
}
107869107961
if( isOptimal ){
107870107962
pWInfo->a[j].rOptCost = sWBI.cost.rCost;
107871
- }else if( iFrom<nTabList-1 ){
107872
- /* If two or more tables have nearly the same outer loop cost,
107963
+ }else if( ckOptimal ){
107964
+ /* If two or more tables have nearly the same outer loop cost, but
107873107965
** very different inner loop (optimal) cost, we want to choose
107874107966
** for the outer loop that table which benefits the least from
107875107967
** being in the inner loop. The following code scales the
107876107968
** outer loop cost estimate to accomplish that. */
107877107969
WHERETRACE((" scaling cost from %.1f to %.1f\n",
@@ -107912,15 +108004,23 @@
107912108004
sWBI.cost.rCost, sWBI.cost.plan.nRow,
107913108005
sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
107914108006
bestPlan = sWBI.cost;
107915108007
bestJ = j;
107916108008
}
107917
- if( doNotReorder ) break;
108009
+
108010
+ /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that
108011
+ ** table y (and not table z) is always the next inner loop inside
108012
+ ** of table x. */
108013
+ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
107918108014
}
107919108015
}
107920108016
assert( bestJ>=0 );
107921108017
assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
108018
+ assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
108019
+ testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
108020
+ testcase( bestJ>iFrom && bestJ<nTabList-1
108021
+ && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
107922108022
WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
107923108023
" cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
107924108024
bestJ, pTabList->a[bestJ].pTab->zName,
107925108025
pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
107926108026
bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
@@ -136646,11 +136746,12 @@
136646136746
** would fit in a single node, use a smaller node-size.
136647136747
*/
136648136748
static int getNodeSize(
136649136749
sqlite3 *db, /* Database handle */
136650136750
Rtree *pRtree, /* Rtree handle */
136651
- int isCreate /* True for xCreate, false for xConnect */
136751
+ int isCreate, /* True for xCreate, false for xConnect */
136752
+ char **pzErr /* OUT: Error message, if any */
136652136753
){
136653136754
int rc;
136654136755
char *zSql;
136655136756
if( isCreate ){
136656136757
int iPageSize = 0;
@@ -136659,17 +136760,22 @@
136659136760
if( rc==SQLITE_OK ){
136660136761
pRtree->iNodeSize = iPageSize-64;
136661136762
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
136662136763
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
136663136764
}
136765
+ }else{
136766
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
136664136767
}
136665136768
}else{
136666136769
zSql = sqlite3_mprintf(
136667136770
"SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
136668136771
pRtree->zDb, pRtree->zName
136669136772
);
136670136773
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
136774
+ if( rc!=SQLITE_OK ){
136775
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
136776
+ }
136671136777
}
136672136778
136673136779
sqlite3_free(zSql);
136674136780
return rc;
136675136781
}
@@ -136729,11 +136835,11 @@
136729136835
pRtree->eCoordType = eCoordType;
136730136836
memcpy(pRtree->zDb, argv[1], nDb);
136731136837
memcpy(pRtree->zName, argv[2], nName);
136732136838
136733136839
/* Figure out the node size to use. */
136734
- rc = getNodeSize(db, pRtree, isCreate);
136840
+ rc = getNodeSize(db, pRtree, isCreate, pzErr);
136735136841
136736136842
/* Create/Connect to the underlying relational database schema. If
136737136843
** that is successful, call sqlite3_declare_vtab() to configure
136738136844
** the r-tree table schema.
136739136845
*/
136740136846
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -673,11 +673,11 @@
673 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674 ** [sqlite_version()] and [sqlite_source_id()].
675 */
676 #define SQLITE_VERSION "3.7.16"
677 #define SQLITE_VERSION_NUMBER 3007016
678 #define SQLITE_SOURCE_ID "2013-01-09 11:31:17 5774f2175ce621dfc4b6b93f7ee13fd66f3ec2b9"
679
680 /*
681 ** CAPI3REF: Run-Time Library Version Numbers
682 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
683 **
@@ -8238,10 +8238,15 @@
8238 ** A convenience macro that returns the number of elements in
8239 ** an array.
8240 */
8241 #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
8242
 
 
 
 
 
8243 /*
8244 ** The following value as a destructor means to use sqlite3DbFree().
8245 ** The sqlite3DbFree() routine requires two parameters instead of the
8246 ** one parameter that destructors normally want. So we have to introduce
8247 ** this magic value that the code knows to handle differently. Any
@@ -10042,10 +10047,11 @@
10042 #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
10043 #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
10044 #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
10045 #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
10046 #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
 
10047 #define SQLITE_AllOpts 0xffff /* All optimizations */
10048
10049 /*
10050 ** Macros for testing whether or not optimizations are enabled or disabled.
10051 */
@@ -93581,11 +93587,11 @@
93581 sqlite3_rekey(db, zKey, i/2);
93582 }
93583 }else
93584 #endif
93585 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
93586 if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
93587 #ifdef SQLITE_HAS_CODEC
93588 if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
93589 sqlite3_activate_see(&zRight[4]);
93590 }
93591 #endif
@@ -102802,12 +102808,12 @@
102802 Expr *pExpr; /* Pointer to the subexpression that is this term */
102803 int iParent; /* Disable pWC->a[iParent] when this term disabled */
102804 int leftCursor; /* Cursor number of X in "X <op> <expr>" */
102805 union {
102806 int leftColumn; /* Column number of X in "X <op> <expr>" */
102807 WhereOrInfo *pOrInfo; /* Extra information if eOperator==WO_OR */
102808 WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */
102809 } u;
102810 u16 eOperator; /* A WO_xx value describing <op> */
102811 u8 wtFlags; /* TERM_xxx bit flags. See below */
102812 u8 nChild; /* Number of children that must disable us */
102813 WhereClause *pWC; /* The clause this term is part of */
@@ -102931,10 +102937,11 @@
102931 #define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
102932 #define WO_MATCH 0x040
102933 #define WO_ISNULL 0x080
102934 #define WO_OR 0x100 /* Two or more OR-connected terms */
102935 #define WO_AND 0x200 /* Two or more AND-connected terms */
 
102936 #define WO_NOOP 0x800 /* This term does not restrict search space */
102937
102938 #define WO_ALL 0xfff /* Mask of all possible WO_* values */
102939 #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
102940
@@ -103333,58 +103340,112 @@
103333 /*
103334 ** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
103335 ** where X is a reference to the iColumn of table iCur and <op> is one of
103336 ** the WO_xx operator codes specified by the op parameter.
103337 ** Return a pointer to the term. Return 0 if not found.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103338 */
103339 static WhereTerm *findTerm(
103340 WhereClause *pWC, /* The WHERE clause to be searched */
103341 int iCur, /* Cursor number of LHS */
103342 int iColumn, /* Column number of LHS */
103343 Bitmask notReady, /* RHS must not overlap with this mask */
103344 u32 op, /* Mask of WO_xx values describing operator */
103345 Index *pIdx /* Must be compatible with this index, if not NULL */
103346 ){
103347 WhereTerm *pTerm;
103348 int k;
 
 
 
 
 
 
 
 
 
103349 assert( iCur>=0 );
103350 op &= WO_ALL;
103351 for(; pWC; pWC=pWC->pOuter){
103352 for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
103353 if( pTerm->leftCursor==iCur
103354 && (pTerm->prereqRight & notReady)==0
103355 && pTerm->u.leftColumn==iColumn
103356 && (pTerm->eOperator & op)!=0
103357 ){
103358 if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
103359 Expr *pX = pTerm->pExpr;
103360 CollSeq *pColl;
103361 char idxaff;
103362 int j;
103363 Parse *pParse = pWC->pParse;
103364
103365 idxaff = pIdx->pTable->aCol[iColumn].affinity;
103366 if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
103367
103368 /* Figure out the collation sequence required from an index for
103369 ** it to be useful for optimising expression pX. Store this
103370 ** value in variable pColl.
103371 */
103372 assert(pX->pLeft);
103373 pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
103374 if( pColl==0 ) pColl = pParse->db->pDfltColl;
103375
103376 for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
103377 if( NEVER(j>=pIdx->nColumn) ) return 0;
103378 }
103379 if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
103380 }
103381 return pTerm;
103382 }
103383 }
103384 }
103385 return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103386 }
103387
103388 /* Forward reference */
103389 static void exprAnalyze(SrcList*, WhereClause*, int);
103390
@@ -103658,11 +103719,10 @@
103658 indexable = ~(Bitmask)0;
103659 chngToIN = ~(pWC->vmask);
103660 for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
103661 if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
103662 WhereAndInfo *pAndInfo;
103663 assert( pOrTerm->eOperator==0 );
103664 assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
103665 chngToIN = 0;
103666 pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
103667 if( pAndInfo ){
103668 WhereClause *pAndWC;
@@ -103697,11 +103757,11 @@
103697 if( pOrTerm->wtFlags & TERM_VIRTUAL ){
103698 WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
103699 b |= getMask(pMaskSet, pOther->leftCursor);
103700 }
103701 indexable &= b;
103702 if( pOrTerm->eOperator!=WO_EQ ){
103703 chngToIN = 0;
103704 }else{
103705 chngToIN &= b;
103706 }
103707 }
@@ -103748,11 +103808,11 @@
103748 ** and column is found but leave okToChngToIN false if not found.
103749 */
103750 for(j=0; j<2 && !okToChngToIN; j++){
103751 pOrTerm = pOrWc->a;
103752 for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
103753 assert( pOrTerm->eOperator==WO_EQ );
103754 pOrTerm->wtFlags &= ~TERM_OR_OK;
103755 if( pOrTerm->leftCursor==iCursor ){
103756 /* This is the 2-bit case and we are on the second iteration and
103757 ** current term is from the first iteration. So skip this term. */
103758 assert( j==1 );
@@ -103774,21 +103834,21 @@
103774 }
103775 if( i<0 ){
103776 /* No candidate table+column was found. This can only occur
103777 ** on the second iteration */
103778 assert( j==1 );
103779 assert( (chngToIN&(chngToIN-1))==0 );
103780 assert( chngToIN==getMask(pMaskSet, iCursor) );
103781 break;
103782 }
103783 testcase( j==1 );
103784
103785 /* We have found a candidate table and column. Check to see if that
103786 ** table and column is common to every term in the OR clause */
103787 okToChngToIN = 1;
103788 for(; i>=0 && okToChngToIN; i--, pOrTerm++){
103789 assert( pOrTerm->eOperator==WO_EQ );
103790 if( pOrTerm->leftCursor!=iCursor ){
103791 pOrTerm->wtFlags &= ~TERM_OR_OK;
103792 }else if( pOrTerm->u.leftColumn!=iColumn ){
103793 okToChngToIN = 0;
103794 }else{
@@ -103820,11 +103880,11 @@
103820 Expr *pLeft = 0; /* The LHS of the IN operator */
103821 Expr *pNew; /* The complete IN operator */
103822
103823 for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
103824 if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
103825 assert( pOrTerm->eOperator==WO_EQ );
103826 assert( pOrTerm->leftCursor==iCursor );
103827 assert( pOrTerm->u.leftColumn==iColumn );
103828 pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
103829 pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
103830 pLeft = pOrTerm->pExpr->pLeft;
@@ -103849,11 +103909,10 @@
103849 pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
103850 }
103851 }
103852 }
103853 #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
103854
103855
103856 /*
103857 ** The input to this routine is an WhereTerm structure with only the
103858 ** "pExpr" field filled in. The job of this routine is to analyze the
103859 ** subexpression and populate all the other fields of the WhereTerm
@@ -103919,21 +103978,23 @@
103919 }
103920 pTerm->prereqAll = prereqAll;
103921 pTerm->leftCursor = -1;
103922 pTerm->iParent = -1;
103923 pTerm->eOperator = 0;
103924 if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
103925 Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
103926 Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
 
103927 if( pLeft->op==TK_COLUMN ){
103928 pTerm->leftCursor = pLeft->iTable;
103929 pTerm->u.leftColumn = pLeft->iColumn;
103930 pTerm->eOperator = operatorMask(op);
103931 }
103932 if( pRight && pRight->op==TK_COLUMN ){
103933 WhereTerm *pNew;
103934 Expr *pDup;
 
103935 if( pTerm->leftCursor>=0 ){
103936 int idxNew;
103937 pDup = sqlite3ExprDup(db, pExpr, 0);
103938 if( db->mallocFailed ){
103939 sqlite3ExprDelete(db, pDup);
@@ -103944,10 +104005,17 @@
103944 pNew = &pWC->a[idxNew];
103945 pNew->iParent = idxTerm;
103946 pTerm = &pWC->a[idxTerm];
103947 pTerm->nChild = 1;
103948 pTerm->wtFlags |= TERM_COPIED;
 
 
 
 
 
 
 
103949 }else{
103950 pDup = pExpr;
103951 pNew = pTerm;
103952 }
103953 exprCommute(pParse, pDup);
@@ -103955,11 +104023,11 @@
103955 pNew->leftCursor = pLeft->iTable;
103956 pNew->u.leftColumn = pLeft->iColumn;
103957 testcase( (prereqLeft | extraRight) != prereqLeft );
103958 pNew->prereqRight = prereqLeft | extraRight;
103959 pNew->prereqAll = prereqAll;
103960 pNew->eOperator = operatorMask(pDup->op);
103961 }
103962 }
103963
103964 #ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
103965 /* If a term is the BETWEEN operator, create two new virtual terms
@@ -104414,11 +104482,11 @@
104414 return;
104415 }
104416
104417 /* Search the WHERE clause terms for a usable WO_OR term. */
104418 for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
104419 if( pTerm->eOperator==WO_OR
104420 && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
104421 && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
104422 ){
104423 WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
104424 WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
@@ -104435,11 +104503,11 @@
104435 sBOI.ppIdxInfo = 0;
104436 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
104437 WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
104438 (pOrTerm - pOrWC->a), (pTerm - pWC->a)
104439 ));
104440 if( pOrTerm->eOperator==WO_AND ){
104441 sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
104442 bestIndex(&sBOI);
104443 }else if( pOrTerm->leftCursor==iCur ){
104444 WhereClause tempWC;
104445 tempWC.pParse = pWC->pParse;
@@ -104496,11 +104564,11 @@
104496 struct SrcList_item *pSrc, /* Table we are trying to access */
104497 Bitmask notReady /* Tables in outer loops of the join */
104498 ){
104499 char aff;
104500 if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
104501 if( pTerm->eOperator!=WO_EQ ) return 0;
104502 if( (pTerm->prereqRight & notReady)!=0 ) return 0;
104503 aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
104504 if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
104505 return 1;
104506 }
@@ -104758,13 +104826,13 @@
104758
104759 /* Count the number of possible WHERE clause constraints referring
104760 ** to this virtual table */
104761 for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104762 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104763 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104764 testcase( pTerm->eOperator==WO_IN );
104765 testcase( pTerm->eOperator==WO_ISNULL );
104766 if( pTerm->eOperator & (WO_ISNULL) ) continue;
104767 if( pTerm->wtFlags & TERM_VNULL ) continue;
104768 nTerm++;
104769 }
104770
@@ -104811,18 +104879,18 @@
104811 pUsage;
104812
104813 for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104814 u8 op;
104815 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104816 assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
104817 testcase( pTerm->eOperator==WO_IN );
104818 testcase( pTerm->eOperator==WO_ISNULL );
104819 if( pTerm->eOperator & (WO_ISNULL) ) continue;
104820 if( pTerm->wtFlags & TERM_VNULL ) continue;
104821 pIdxCons[j].iColumn = pTerm->u.leftColumn;
104822 pIdxCons[j].iTermOffset = i;
104823 op = (u8)pTerm->eOperator;
104824 if( op==WO_IN ) op = WO_EQ;
104825 pIdxCons[j].op = op;
104826 /* The direct assignment in the previous line is possible only because
104827 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
104828 ** following asserts verify this fact. */
@@ -104988,11 +105056,11 @@
104988 pUsage = pIdxInfo->aConstraintUsage;
104989 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
104990 j = pIdxCons->iTermOffset;
104991 pTerm = &pWC->a[j];
104992 if( (pTerm->prereqRight&p->notReady)==0
104993 && (bAllowIN || pTerm->eOperator!=WO_IN)
104994 ){
104995 pIdxCons->usable = 1;
104996 }else{
104997 pIdxCons->usable = 0;
104998 }
@@ -105020,11 +105088,11 @@
105020 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
105021 if( pUsage[i].argvIndex>0 ){
105022 j = pIdxCons->iTermOffset;
105023 pTerm = &pWC->a[j];
105024 p->cost.used |= pTerm->prereqRight;
105025 if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){
105026 /* Do not attempt to use an IN constraint if the virtual table
105027 ** says that the equivalent EQ constraint cannot be safely omitted.
105028 ** If we do attempt to use such a constraint, some rows might be
105029 ** repeated in the output. */
105030 break;
@@ -105326,28 +105394,28 @@
105326 u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
105327
105328 if( pLower ){
105329 Expr *pExpr = pLower->pExpr->pRight;
105330 rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
105331 assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
105332 if( rc==SQLITE_OK
105333 && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
105334 ){
105335 iLower = a[0];
105336 if( pLower->eOperator==WO_GT ) iLower += a[1];
105337 }
105338 sqlite3ValueFree(pRangeVal);
105339 }
105340 if( rc==SQLITE_OK && pUpper ){
105341 Expr *pExpr = pUpper->pExpr->pRight;
105342 rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
105343 assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
105344 if( rc==SQLITE_OK
105345 && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
105346 ){
105347 iUpper = a[0];
105348 if( pUpper->eOperator==WO_LE ) iUpper += a[1];
105349 }
105350 sqlite3ValueFree(pRangeVal);
105351 }
105352 if( rc==SQLITE_OK ){
105353 if( iUpper<=iLower ){
@@ -105651,16 +105719,16 @@
105651 ** if there are any X= or X IS NULL constraints in the WHERE clause. */
105652 pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
105653 WO_EQ|WO_ISNULL|WO_IN, pIdx);
105654 if( pConstraint==0 ){
105655 isEq = 0;
105656 }else if( pConstraint->eOperator==WO_IN ){
105657 /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
105658 ** because we do not know in what order the values on the RHS of the IN
105659 ** operator will occur. */
105660 break;
105661 }else if( pConstraint->eOperator==WO_ISNULL ){
105662 uniqueNotNull = 0;
105663 isEq = 1; /* "X IS NULL" means X has only a single value */
105664 }else if( pConstraint->prereqRight==0 ){
105665 isEq = 1; /* Constraint "X=constant" means X has only a single value */
105666 }else{
@@ -106069,16 +106137,17 @@
106069 */
106070 if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
106071 && pFirstTerm!=0 && aiRowEst[1]>1 ){
106072 assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
106073 if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
106074 testcase( pFirstTerm->eOperator==WO_EQ );
106075 testcase( pFirstTerm->eOperator==WO_ISNULL );
 
106076 whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
106077 &pc.plan.nRow);
106078 }else if( bInEst==0 ){
106079 assert( pFirstTerm->eOperator==WO_IN );
106080 whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
106081 &pc.plan.nRow);
106082 }
106083 }
106084 #endif /* SQLITE_ENABLE_STAT3 */
@@ -106221,11 +106290,11 @@
106221 ** more selective intentionally because of the subjective
106222 ** observation that indexed range constraints really are more
106223 ** selective in practice, on average. */
106224 pc.plan.nRow /= 3;
106225 }
106226 }else if( pTerm->eOperator!=WO_NOOP ){
106227 /* Any other expression lowers the output row count by half */
106228 pc.plan.nRow /= 2;
106229 }
106230 }
106231 if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
@@ -106273,12 +106342,13 @@
106273 assert( pSrc->pIndex==0
106274 || p->cost.plan.u.pIdx==0
106275 || p->cost.plan.u.pIdx==pSrc->pIndex
106276 );
106277
106278 WHERETRACE((" best index is: %s\n",
106279 p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
 
106280
106281 bestOrClauseIndex(p);
106282 bestAutomaticIndex(p);
106283 p->cost.plan.wsFlags |= eqTermMask;
106284 }
@@ -106856,11 +106926,10 @@
106856 */
106857 iReleaseReg = sqlite3GetTempReg(pParse);
106858 pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
106859 assert( pTerm!=0 );
106860 assert( pTerm->pExpr!=0 );
106861 assert( pTerm->leftCursor==iCur );
106862 assert( omitTable==0 );
106863 testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
106864 iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
106865 addrNxt = pLevel->addrNxt;
106866 sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
@@ -107247,11 +107316,11 @@
107247 int ii; /* Loop counter */
107248 Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
107249
107250 pTerm = pLevel->plan.u.pTerm;
107251 assert( pTerm!=0 );
107252 assert( pTerm->eOperator==WO_OR );
107253 assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
107254 pOrWc = &pTerm->u.pOrInfo->wc;
107255 pLevel->op = OP_Return;
107256 pLevel->p1 = regReturn;
107257
@@ -107320,11 +107389,11 @@
107320 }
107321 }
107322
107323 for(ii=0; ii<pOrWc->nTerm; ii++){
107324 WhereTerm *pOrTerm = &pOrWc->a[ii];
107325 if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
107326 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
107327 Expr *pOrExpr = pOrTerm->pExpr;
107328 if( pAndExpr ){
107329 pAndExpr->pLeft = pOrExpr;
107330 pOrExpr = pAndExpr;
@@ -107775,10 +107844,11 @@
107775 Index *pIdx; /* Index for FROM table at pTabItem */
107776 int j; /* For looping over FROM tables */
107777 int bestJ = -1; /* The value of j */
107778 Bitmask m; /* Bitmask value for j or bestJ */
107779 int isOptimal; /* Iterator for optimal/non-optimal search */
 
107780 int nUnconstrained; /* Number tables without INDEXED BY */
107781 Bitmask notIndexed; /* Mask of tables that cannot use an index */
107782
107783 memset(&bestPlan, 0, sizeof(bestPlan));
107784 bestPlan.rCost = SQLITE_BIG_DBL;
@@ -107809,14 +107879,12 @@
107809 **
107810 ** The second loop iteration is only performed if no optimal scan
107811 ** strategies were found by the first iteration. This second iteration
107812 ** is used to search for the lowest cost scan overall.
107813 **
107814 ** Previous versions of SQLite performed only the second iteration -
107815 ** the next outermost loop was always that with the lowest overall
107816 ** cost. However, this meant that SQLite could select the wrong plan
107817 ** for scripts such as the following:
107818 **
107819 ** CREATE TABLE t1(a, b);
107820 ** CREATE TABLE t2(c, d);
107821 ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
107822 **
@@ -107827,20 +107895,44 @@
107827 ** algorithm may choose to use t2 for the outer loop, which is a much
107828 ** costlier approach.
107829 */
107830 nUnconstrained = 0;
107831 notIndexed = 0;
107832 for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
 
 
 
 
 
 
107833 for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
107834 int doNotReorder; /* True if this table should not be reordered */
107835
107836 doNotReorder = (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0;
107837 if( j!=iFrom && doNotReorder ) break;
107838 m = getMask(pMaskSet, sWBI.pSrc->iCursor);
107839 if( (m & sWBI.notValid)==0 ){
107840 if( j==iFrom ) iFrom++;
107841 continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107842 }
107843 sWBI.notReady = (isOptimal ? m : sWBI.notValid);
107844 if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
107845
107846 WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
@@ -107866,12 +107958,12 @@
107866 if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
107867 notIndexed |= m;
107868 }
107869 if( isOptimal ){
107870 pWInfo->a[j].rOptCost = sWBI.cost.rCost;
107871 }else if( iFrom<nTabList-1 ){
107872 /* If two or more tables have nearly the same outer loop cost,
107873 ** very different inner loop (optimal) cost, we want to choose
107874 ** for the outer loop that table which benefits the least from
107875 ** being in the inner loop. The following code scales the
107876 ** outer loop cost estimate to accomplish that. */
107877 WHERETRACE((" scaling cost from %.1f to %.1f\n",
@@ -107912,15 +108004,23 @@
107912 sWBI.cost.rCost, sWBI.cost.plan.nRow,
107913 sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
107914 bestPlan = sWBI.cost;
107915 bestJ = j;
107916 }
107917 if( doNotReorder ) break;
 
 
 
 
107918 }
107919 }
107920 assert( bestJ>=0 );
107921 assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
 
 
 
 
107922 WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
107923 " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
107924 bestJ, pTabList->a[bestJ].pTab->zName,
107925 pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
107926 bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
@@ -136646,11 +136746,12 @@
136646 ** would fit in a single node, use a smaller node-size.
136647 */
136648 static int getNodeSize(
136649 sqlite3 *db, /* Database handle */
136650 Rtree *pRtree, /* Rtree handle */
136651 int isCreate /* True for xCreate, false for xConnect */
 
136652 ){
136653 int rc;
136654 char *zSql;
136655 if( isCreate ){
136656 int iPageSize = 0;
@@ -136659,17 +136760,22 @@
136659 if( rc==SQLITE_OK ){
136660 pRtree->iNodeSize = iPageSize-64;
136661 if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
136662 pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
136663 }
 
 
136664 }
136665 }else{
136666 zSql = sqlite3_mprintf(
136667 "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
136668 pRtree->zDb, pRtree->zName
136669 );
136670 rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
 
 
 
136671 }
136672
136673 sqlite3_free(zSql);
136674 return rc;
136675 }
@@ -136729,11 +136835,11 @@
136729 pRtree->eCoordType = eCoordType;
136730 memcpy(pRtree->zDb, argv[1], nDb);
136731 memcpy(pRtree->zName, argv[2], nName);
136732
136733 /* Figure out the node size to use. */
136734 rc = getNodeSize(db, pRtree, isCreate);
136735
136736 /* Create/Connect to the underlying relational database schema. If
136737 ** that is successful, call sqlite3_declare_vtab() to configure
136738 ** the r-tree table schema.
136739 */
136740
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -673,11 +673,11 @@
673 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674 ** [sqlite_version()] and [sqlite_source_id()].
675 */
676 #define SQLITE_VERSION "3.7.16"
677 #define SQLITE_VERSION_NUMBER 3007016
678 #define SQLITE_SOURCE_ID "2013-01-17 17:20:49 38852f158ab20bb4d7b264af987ec1538052bec3"
679
680 /*
681 ** CAPI3REF: Run-Time Library Version Numbers
682 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
683 **
@@ -8238,10 +8238,15 @@
8238 ** A convenience macro that returns the number of elements in
8239 ** an array.
8240 */
8241 #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
8242
8243 /*
8244 ** Determine if the argument is a power of two
8245 */
8246 #define IsPowerOfTwo(X) (((X)&((X)-1))==0)
8247
8248 /*
8249 ** The following value as a destructor means to use sqlite3DbFree().
8250 ** The sqlite3DbFree() routine requires two parameters instead of the
8251 ** one parameter that destructors normally want. So we have to introduce
8252 ** this magic value that the code knows to handle differently. Any
@@ -10042,10 +10047,11 @@
10047 #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
10048 #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
10049 #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
10050 #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
10051 #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
10052 #define SQLITE_Transitive 0x0200 /* Transitive constraints */
10053 #define SQLITE_AllOpts 0xffff /* All optimizations */
10054
10055 /*
10056 ** Macros for testing whether or not optimizations are enabled or disabled.
10057 */
@@ -93581,11 +93587,11 @@
93587 sqlite3_rekey(db, zKey, i/2);
93588 }
93589 }else
93590 #endif
93591 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
93592 if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
93593 #ifdef SQLITE_HAS_CODEC
93594 if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
93595 sqlite3_activate_see(&zRight[4]);
93596 }
93597 #endif
@@ -102802,12 +102808,12 @@
102808 Expr *pExpr; /* Pointer to the subexpression that is this term */
102809 int iParent; /* Disable pWC->a[iParent] when this term disabled */
102810 int leftCursor; /* Cursor number of X in "X <op> <expr>" */
102811 union {
102812 int leftColumn; /* Column number of X in "X <op> <expr>" */
102813 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
102814 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
102815 } u;
102816 u16 eOperator; /* A WO_xx value describing <op> */
102817 u8 wtFlags; /* TERM_xxx bit flags. See below */
102818 u8 nChild; /* Number of children that must disable us */
102819 WhereClause *pWC; /* The clause this term is part of */
@@ -102931,10 +102937,11 @@
102937 #define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
102938 #define WO_MATCH 0x040
102939 #define WO_ISNULL 0x080
102940 #define WO_OR 0x100 /* Two or more OR-connected terms */
102941 #define WO_AND 0x200 /* Two or more AND-connected terms */
102942 #define WO_EQUIV 0x400 /* Of the form A==B, both columns */
102943 #define WO_NOOP 0x800 /* This term does not restrict search space */
102944
102945 #define WO_ALL 0xfff /* Mask of all possible WO_* values */
102946 #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
102947
@@ -103333,58 +103340,112 @@
103340 /*
103341 ** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
103342 ** where X is a reference to the iColumn of table iCur and <op> is one of
103343 ** the WO_xx operator codes specified by the op parameter.
103344 ** Return a pointer to the term. Return 0 if not found.
103345 **
103346 ** The term returned might by Y=<expr> if there is another constraint in
103347 ** the WHERE clause that specifies that X=Y. Any such constraints will be
103348 ** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
103349 ** aEquiv[] array holds X and all its equivalents, with each SQL variable
103350 ** taking up two slots in aEquiv[]. The first slot is for the cursor number
103351 ** and the second is for the column number. There are 22 slots in aEquiv[]
103352 ** so that means we can look for X plus up to 10 other equivalent values.
103353 ** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
103354 ** and ... and A9=A10 and A10=<expr>.
103355 **
103356 ** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
103357 ** then try for the one with no dependencies on <expr> - in other words where
103358 ** <expr> is a constant expression of some kind. Only return entries of
103359 ** the form "X <op> Y" where Y is a column in another table if no terms of
103360 ** the form "X <op> <const-expr>" exist. Other than this priority, if there
103361 ** are two or more terms that match, then the choice of which term to return
103362 ** is arbitrary.
103363 */
103364 static WhereTerm *findTerm(
103365 WhereClause *pWC, /* The WHERE clause to be searched */
103366 int iCur, /* Cursor number of LHS */
103367 int iColumn, /* Column number of LHS */
103368 Bitmask notReady, /* RHS must not overlap with this mask */
103369 u32 op, /* Mask of WO_xx values describing operator */
103370 Index *pIdx /* Must be compatible with this index, if not NULL */
103371 ){
103372 WhereTerm *pTerm; /* Term being examined as possible result */
103373 WhereTerm *pResult = 0; /* The answer to return */
103374 WhereClause *pWCOrig = pWC; /* Original pWC value */
103375 int j, k; /* Loop counters */
103376 Expr *pX; /* Pointer to an expression */
103377 Parse *pParse; /* Parsing context */
103378 int iOrigCol = iColumn; /* Original value of iColumn */
103379 int nEquiv = 2; /* Number of entires in aEquiv[] */
103380 int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */
103381 int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */
103382
103383 assert( iCur>=0 );
103384 aEquiv[0] = iCur;
103385 aEquiv[1] = iColumn;
103386 for(;;){
103387 for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
103388 for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
103389 if( pTerm->leftCursor==iCur
103390 && pTerm->u.leftColumn==iColumn
103391 ){
103392 if( (pTerm->prereqRight & notReady)==0
103393 && (pTerm->eOperator & op & WO_ALL)!=0
103394 ){
103395 if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
103396 CollSeq *pColl;
103397 char idxaff;
103398
103399 pX = pTerm->pExpr;
103400 pParse = pWC->pParse;
103401 idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
103402 if( !sqlite3IndexAffinityOk(pX, idxaff) ){
103403 continue;
103404 }
103405
103406 /* Figure out the collation sequence required from an index for
103407 ** it to be useful for optimising expression pX. Store this
103408 ** value in variable pColl.
103409 */
103410 assert(pX->pLeft);
103411 pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
103412 if( pColl==0 ) pColl = pParse->db->pDfltColl;
103413
103414 for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
103415 if( NEVER(j>=pIdx->nColumn) ) return 0;
103416 }
103417 if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
103418 continue;
103419 }
103420 }
103421 pResult = pTerm;
103422 if( pTerm->prereqRight==0 ) goto findTerm_success;
103423 }
103424 if( (pTerm->eOperator & WO_EQUIV)!=0
103425 && nEquiv<ArraySize(aEquiv)
103426 ){
103427 pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
103428 assert( pX->op==TK_COLUMN );
103429 for(j=0; j<nEquiv; j+=2){
103430 if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
103431 }
103432 if( j==nEquiv ){
103433 aEquiv[j] = pX->iTable;
103434 aEquiv[j+1] = pX->iColumn;
103435 nEquiv += 2;
103436 }
103437 }
103438 }
103439 }
103440 }
103441 if( iEquiv>=nEquiv ) break;
103442 iCur = aEquiv[iEquiv++];
103443 iColumn = aEquiv[iEquiv++];
103444 }
103445 findTerm_success:
103446 return pResult;
103447 }
103448
103449 /* Forward reference */
103450 static void exprAnalyze(SrcList*, WhereClause*, int);
103451
@@ -103658,11 +103719,10 @@
103719 indexable = ~(Bitmask)0;
103720 chngToIN = ~(pWC->vmask);
103721 for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
103722 if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
103723 WhereAndInfo *pAndInfo;
 
103724 assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
103725 chngToIN = 0;
103726 pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
103727 if( pAndInfo ){
103728 WhereClause *pAndWC;
@@ -103697,11 +103757,11 @@
103757 if( pOrTerm->wtFlags & TERM_VIRTUAL ){
103758 WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
103759 b |= getMask(pMaskSet, pOther->leftCursor);
103760 }
103761 indexable &= b;
103762 if( (pOrTerm->eOperator & WO_EQ)==0 ){
103763 chngToIN = 0;
103764 }else{
103765 chngToIN &= b;
103766 }
103767 }
@@ -103748,11 +103808,11 @@
103808 ** and column is found but leave okToChngToIN false if not found.
103809 */
103810 for(j=0; j<2 && !okToChngToIN; j++){
103811 pOrTerm = pOrWc->a;
103812 for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
103813 assert( pOrTerm->eOperator & WO_EQ );
103814 pOrTerm->wtFlags &= ~TERM_OR_OK;
103815 if( pOrTerm->leftCursor==iCursor ){
103816 /* This is the 2-bit case and we are on the second iteration and
103817 ** current term is from the first iteration. So skip this term. */
103818 assert( j==1 );
@@ -103774,21 +103834,21 @@
103834 }
103835 if( i<0 ){
103836 /* No candidate table+column was found. This can only occur
103837 ** on the second iteration */
103838 assert( j==1 );
103839 assert( IsPowerOfTwo(chngToIN) );
103840 assert( chngToIN==getMask(pMaskSet, iCursor) );
103841 break;
103842 }
103843 testcase( j==1 );
103844
103845 /* We have found a candidate table and column. Check to see if that
103846 ** table and column is common to every term in the OR clause */
103847 okToChngToIN = 1;
103848 for(; i>=0 && okToChngToIN; i--, pOrTerm++){
103849 assert( pOrTerm->eOperator & WO_EQ );
103850 if( pOrTerm->leftCursor!=iCursor ){
103851 pOrTerm->wtFlags &= ~TERM_OR_OK;
103852 }else if( pOrTerm->u.leftColumn!=iColumn ){
103853 okToChngToIN = 0;
103854 }else{
@@ -103820,11 +103880,11 @@
103880 Expr *pLeft = 0; /* The LHS of the IN operator */
103881 Expr *pNew; /* The complete IN operator */
103882
103883 for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
103884 if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
103885 assert( pOrTerm->eOperator & WO_EQ );
103886 assert( pOrTerm->leftCursor==iCursor );
103887 assert( pOrTerm->u.leftColumn==iColumn );
103888 pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
103889 pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
103890 pLeft = pOrTerm->pExpr->pLeft;
@@ -103849,11 +103909,10 @@
103909 pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
103910 }
103911 }
103912 }
103913 #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
 
103914
103915 /*
103916 ** The input to this routine is an WhereTerm structure with only the
103917 ** "pExpr" field filled in. The job of this routine is to analyze the
103918 ** subexpression and populate all the other fields of the WhereTerm
@@ -103919,21 +103978,23 @@
103978 }
103979 pTerm->prereqAll = prereqAll;
103980 pTerm->leftCursor = -1;
103981 pTerm->iParent = -1;
103982 pTerm->eOperator = 0;
103983 if( allowedOp(op) ){
103984 Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
103985 Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
103986 u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
103987 if( pLeft->op==TK_COLUMN ){
103988 pTerm->leftCursor = pLeft->iTable;
103989 pTerm->u.leftColumn = pLeft->iColumn;
103990 pTerm->eOperator = operatorMask(op) & opMask;
103991 }
103992 if( pRight && pRight->op==TK_COLUMN ){
103993 WhereTerm *pNew;
103994 Expr *pDup;
103995 u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
103996 if( pTerm->leftCursor>=0 ){
103997 int idxNew;
103998 pDup = sqlite3ExprDup(db, pExpr, 0);
103999 if( db->mallocFailed ){
104000 sqlite3ExprDelete(db, pDup);
@@ -103944,10 +104005,17 @@
104005 pNew = &pWC->a[idxNew];
104006 pNew->iParent = idxTerm;
104007 pTerm = &pWC->a[idxTerm];
104008 pTerm->nChild = 1;
104009 pTerm->wtFlags |= TERM_COPIED;
104010 if( pExpr->op==TK_EQ
104011 && !ExprHasProperty(pExpr, EP_FromJoin)
104012 && OptimizationEnabled(db, SQLITE_Transitive)
104013 ){
104014 pTerm->eOperator |= WO_EQUIV;
104015 eExtraOp = WO_EQUIV;
104016 }
104017 }else{
104018 pDup = pExpr;
104019 pNew = pTerm;
104020 }
104021 exprCommute(pParse, pDup);
@@ -103955,11 +104023,11 @@
104023 pNew->leftCursor = pLeft->iTable;
104024 pNew->u.leftColumn = pLeft->iColumn;
104025 testcase( (prereqLeft | extraRight) != prereqLeft );
104026 pNew->prereqRight = prereqLeft | extraRight;
104027 pNew->prereqAll = prereqAll;
104028 pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
104029 }
104030 }
104031
104032 #ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
104033 /* If a term is the BETWEEN operator, create two new virtual terms
@@ -104414,11 +104482,11 @@
104482 return;
104483 }
104484
104485 /* Search the WHERE clause terms for a usable WO_OR term. */
104486 for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
104487 if( (pTerm->eOperator & WO_OR)!=0
104488 && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
104489 && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
104490 ){
104491 WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
104492 WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
@@ -104435,11 +104503,11 @@
104503 sBOI.ppIdxInfo = 0;
104504 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
104505 WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
104506 (pOrTerm - pOrWC->a), (pTerm - pWC->a)
104507 ));
104508 if( (pOrTerm->eOperator& WO_AND)!=0 ){
104509 sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
104510 bestIndex(&sBOI);
104511 }else if( pOrTerm->leftCursor==iCur ){
104512 WhereClause tempWC;
104513 tempWC.pParse = pWC->pParse;
@@ -104496,11 +104564,11 @@
104564 struct SrcList_item *pSrc, /* Table we are trying to access */
104565 Bitmask notReady /* Tables in outer loops of the join */
104566 ){
104567 char aff;
104568 if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
104569 if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
104570 if( (pTerm->prereqRight & notReady)!=0 ) return 0;
104571 aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
104572 if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
104573 return 1;
104574 }
@@ -104758,13 +104826,13 @@
104826
104827 /* Count the number of possible WHERE clause constraints referring
104828 ** to this virtual table */
104829 for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104830 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104831 assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
104832 testcase( pTerm->eOperator & WO_IN );
104833 testcase( pTerm->eOperator & WO_ISNULL );
104834 if( pTerm->eOperator & (WO_ISNULL) ) continue;
104835 if( pTerm->wtFlags & TERM_VNULL ) continue;
104836 nTerm++;
104837 }
104838
@@ -104811,18 +104879,18 @@
104879 pUsage;
104880
104881 for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
104882 u8 op;
104883 if( pTerm->leftCursor != pSrc->iCursor ) continue;
104884 assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
104885 testcase( pTerm->eOperator & WO_IN );
104886 testcase( pTerm->eOperator & WO_ISNULL );
104887 if( pTerm->eOperator & (WO_ISNULL) ) continue;
104888 if( pTerm->wtFlags & TERM_VNULL ) continue;
104889 pIdxCons[j].iColumn = pTerm->u.leftColumn;
104890 pIdxCons[j].iTermOffset = i;
104891 op = (u8)pTerm->eOperator & WO_ALL;
104892 if( op==WO_IN ) op = WO_EQ;
104893 pIdxCons[j].op = op;
104894 /* The direct assignment in the previous line is possible only because
104895 ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
104896 ** following asserts verify this fact. */
@@ -104988,11 +105056,11 @@
105056 pUsage = pIdxInfo->aConstraintUsage;
105057 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
105058 j = pIdxCons->iTermOffset;
105059 pTerm = &pWC->a[j];
105060 if( (pTerm->prereqRight&p->notReady)==0
105061 && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
105062 ){
105063 pIdxCons->usable = 1;
105064 }else{
105065 pIdxCons->usable = 0;
105066 }
@@ -105020,11 +105088,11 @@
105088 for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
105089 if( pUsage[i].argvIndex>0 ){
105090 j = pIdxCons->iTermOffset;
105091 pTerm = &pWC->a[j];
105092 p->cost.used |= pTerm->prereqRight;
105093 if( (pTerm->eOperator & WO_IN)!=0 && pUsage[i].omit==0 ){
105094 /* Do not attempt to use an IN constraint if the virtual table
105095 ** says that the equivalent EQ constraint cannot be safely omitted.
105096 ** If we do attempt to use such a constraint, some rows might be
105097 ** repeated in the output. */
105098 break;
@@ -105326,28 +105394,28 @@
105394 u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
105395
105396 if( pLower ){
105397 Expr *pExpr = pLower->pExpr->pRight;
105398 rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
105399 assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
105400 if( rc==SQLITE_OK
105401 && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
105402 ){
105403 iLower = a[0];
105404 if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
105405 }
105406 sqlite3ValueFree(pRangeVal);
105407 }
105408 if( rc==SQLITE_OK && pUpper ){
105409 Expr *pExpr = pUpper->pExpr->pRight;
105410 rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
105411 assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
105412 if( rc==SQLITE_OK
105413 && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
105414 ){
105415 iUpper = a[0];
105416 if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
105417 }
105418 sqlite3ValueFree(pRangeVal);
105419 }
105420 if( rc==SQLITE_OK ){
105421 if( iUpper<=iLower ){
@@ -105651,16 +105719,16 @@
105719 ** if there are any X= or X IS NULL constraints in the WHERE clause. */
105720 pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
105721 WO_EQ|WO_ISNULL|WO_IN, pIdx);
105722 if( pConstraint==0 ){
105723 isEq = 0;
105724 }else if( (pConstraint->eOperator & WO_IN)!=0 ){
105725 /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
105726 ** because we do not know in what order the values on the RHS of the IN
105727 ** operator will occur. */
105728 break;
105729 }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
105730 uniqueNotNull = 0;
105731 isEq = 1; /* "X IS NULL" means X has only a single value */
105732 }else if( pConstraint->prereqRight==0 ){
105733 isEq = 1; /* Constraint "X=constant" means X has only a single value */
105734 }else{
@@ -106069,16 +106137,17 @@
106137 */
106138 if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
106139 && pFirstTerm!=0 && aiRowEst[1]>1 ){
106140 assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
106141 if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
106142 testcase( pFirstTerm->eOperator & WO_EQ );
106143 testcase( pFirstTerm->eOperator & WO_EQUIV );
106144 testcase( pFirstTerm->eOperator & WO_ISNULL );
106145 whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
106146 &pc.plan.nRow);
106147 }else if( bInEst==0 ){
106148 assert( pFirstTerm->eOperator & WO_IN );
106149 whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
106150 &pc.plan.nRow);
106151 }
106152 }
106153 #endif /* SQLITE_ENABLE_STAT3 */
@@ -106221,11 +106290,11 @@
106290 ** more selective intentionally because of the subjective
106291 ** observation that indexed range constraints really are more
106292 ** selective in practice, on average. */
106293 pc.plan.nRow /= 3;
106294 }
106295 }else if( (pTerm->eOperator & WO_NOOP)==0 ){
106296 /* Any other expression lowers the output row count by half */
106297 pc.plan.nRow /= 2;
106298 }
106299 }
106300 if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
@@ -106273,12 +106342,13 @@
106342 assert( pSrc->pIndex==0
106343 || p->cost.plan.u.pIdx==0
106344 || p->cost.plan.u.pIdx==pSrc->pIndex
106345 );
106346
106347 WHERETRACE((" best index is %s cost=%.1f\n",
106348 p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
106349 p->cost.rCost));
106350
106351 bestOrClauseIndex(p);
106352 bestAutomaticIndex(p);
106353 p->cost.plan.wsFlags |= eqTermMask;
106354 }
@@ -106856,11 +106926,10 @@
106926 */
106927 iReleaseReg = sqlite3GetTempReg(pParse);
106928 pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
106929 assert( pTerm!=0 );
106930 assert( pTerm->pExpr!=0 );
 
106931 assert( omitTable==0 );
106932 testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
106933 iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
106934 addrNxt = pLevel->addrNxt;
106935 sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
@@ -107247,11 +107316,11 @@
107316 int ii; /* Loop counter */
107317 Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
107318
107319 pTerm = pLevel->plan.u.pTerm;
107320 assert( pTerm!=0 );
107321 assert( pTerm->eOperator & WO_OR );
107322 assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
107323 pOrWc = &pTerm->u.pOrInfo->wc;
107324 pLevel->op = OP_Return;
107325 pLevel->p1 = regReturn;
107326
@@ -107320,11 +107389,11 @@
107389 }
107390 }
107391
107392 for(ii=0; ii<pOrWc->nTerm; ii++){
107393 WhereTerm *pOrTerm = &pOrWc->a[ii];
107394 if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
107395 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
107396 Expr *pOrExpr = pOrTerm->pExpr;
107397 if( pAndExpr ){
107398 pAndExpr->pLeft = pOrExpr;
107399 pOrExpr = pAndExpr;
@@ -107775,10 +107844,11 @@
107844 Index *pIdx; /* Index for FROM table at pTabItem */
107845 int j; /* For looping over FROM tables */
107846 int bestJ = -1; /* The value of j */
107847 Bitmask m; /* Bitmask value for j or bestJ */
107848 int isOptimal; /* Iterator for optimal/non-optimal search */
107849 int ckOptimal; /* Do the optimal scan check */
107850 int nUnconstrained; /* Number tables without INDEXED BY */
107851 Bitmask notIndexed; /* Mask of tables that cannot use an index */
107852
107853 memset(&bestPlan, 0, sizeof(bestPlan));
107854 bestPlan.rCost = SQLITE_BIG_DBL;
@@ -107809,14 +107879,12 @@
107879 **
107880 ** The second loop iteration is only performed if no optimal scan
107881 ** strategies were found by the first iteration. This second iteration
107882 ** is used to search for the lowest cost scan overall.
107883 **
107884 ** Without the optimal scan step (the first iteration) a suboptimal
107885 ** plan might be chosen for queries like this:
 
 
107886 **
107887 ** CREATE TABLE t1(a, b);
107888 ** CREATE TABLE t2(c, d);
107889 ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
107890 **
@@ -107827,20 +107895,44 @@
107895 ** algorithm may choose to use t2 for the outer loop, which is a much
107896 ** costlier approach.
107897 */
107898 nUnconstrained = 0;
107899 notIndexed = 0;
107900
107901 /* The optimal scan check only occurs if there are two or more tables
107902 ** available to be reordered */
107903 if( iFrom==nTabList-1 ){
107904 ckOptimal = 0; /* Common case of just one table in the FROM clause */
107905 }else{
107906 ckOptimal = -1;
107907 for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
 
 
 
 
107908 m = getMask(pMaskSet, sWBI.pSrc->iCursor);
107909 if( (m & sWBI.notValid)==0 ){
107910 if( j==iFrom ) iFrom++;
107911 continue;
107912 }
107913 if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
107914 if( ++ckOptimal ) break;
107915 if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
107916 }
107917 }
107918 assert( ckOptimal==0 || ckOptimal==1 );
107919
107920 for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
107921 for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
107922 if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
107923 /* This break and one like it in the ckOptimal computation loop
107924 ** above prevent table reordering across LEFT and CROSS JOINs.
107925 ** The LEFT JOIN case is necessary for correctness. The prohibition
107926 ** against reordering across a CROSS JOIN is an SQLite feature that
107927 ** allows the developer to control table reordering */
107928 break;
107929 }
107930 m = getMask(pMaskSet, sWBI.pSrc->iCursor);
107931 if( (m & sWBI.notValid)==0 ){
107932 assert( j>iFrom );
107933 continue;
107934 }
107935 sWBI.notReady = (isOptimal ? m : sWBI.notValid);
107936 if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
107937
107938 WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
@@ -107866,12 +107958,12 @@
107958 if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
107959 notIndexed |= m;
107960 }
107961 if( isOptimal ){
107962 pWInfo->a[j].rOptCost = sWBI.cost.rCost;
107963 }else if( ckOptimal ){
107964 /* If two or more tables have nearly the same outer loop cost, but
107965 ** very different inner loop (optimal) cost, we want to choose
107966 ** for the outer loop that table which benefits the least from
107967 ** being in the inner loop. The following code scales the
107968 ** outer loop cost estimate to accomplish that. */
107969 WHERETRACE((" scaling cost from %.1f to %.1f\n",
@@ -107912,15 +108004,23 @@
108004 sWBI.cost.rCost, sWBI.cost.plan.nRow,
108005 sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
108006 bestPlan = sWBI.cost;
108007 bestJ = j;
108008 }
108009
108010 /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that
108011 ** table y (and not table z) is always the next inner loop inside
108012 ** of table x. */
108013 if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
108014 }
108015 }
108016 assert( bestJ>=0 );
108017 assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
108018 assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
108019 testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
108020 testcase( bestJ>iFrom && bestJ<nTabList-1
108021 && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
108022 WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
108023 " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
108024 bestJ, pTabList->a[bestJ].pTab->zName,
108025 pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
108026 bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
@@ -136646,11 +136746,12 @@
136746 ** would fit in a single node, use a smaller node-size.
136747 */
136748 static int getNodeSize(
136749 sqlite3 *db, /* Database handle */
136750 Rtree *pRtree, /* Rtree handle */
136751 int isCreate, /* True for xCreate, false for xConnect */
136752 char **pzErr /* OUT: Error message, if any */
136753 ){
136754 int rc;
136755 char *zSql;
136756 if( isCreate ){
136757 int iPageSize = 0;
@@ -136659,17 +136760,22 @@
136760 if( rc==SQLITE_OK ){
136761 pRtree->iNodeSize = iPageSize-64;
136762 if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
136763 pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
136764 }
136765 }else{
136766 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
136767 }
136768 }else{
136769 zSql = sqlite3_mprintf(
136770 "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
136771 pRtree->zDb, pRtree->zName
136772 );
136773 rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
136774 if( rc!=SQLITE_OK ){
136775 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
136776 }
136777 }
136778
136779 sqlite3_free(zSql);
136780 return rc;
136781 }
@@ -136729,11 +136835,11 @@
136835 pRtree->eCoordType = eCoordType;
136836 memcpy(pRtree->zDb, argv[1], nDb);
136837 memcpy(pRtree->zName, argv[2], nName);
136838
136839 /* Figure out the node size to use. */
136840 rc = getNodeSize(db, pRtree, isCreate, pzErr);
136841
136842 /* Create/Connect to the underlying relational database schema. If
136843 ** that is successful, call sqlite3_declare_vtab() to configure
136844 ** the r-tree table schema.
136845 */
136846
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.7.16"
111111
#define SQLITE_VERSION_NUMBER 3007016
112
-#define SQLITE_SOURCE_ID "2013-01-09 11:31:17 5774f2175ce621dfc4b6b93f7ee13fd66f3ec2b9"
112
+#define SQLITE_SOURCE_ID "2013-01-17 17:20:49 38852f158ab20bb4d7b264af987ec1538052bec3"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.16"
111 #define SQLITE_VERSION_NUMBER 3007016
112 #define SQLITE_SOURCE_ID "2013-01-09 11:31:17 5774f2175ce621dfc4b6b93f7ee13fd66f3ec2b9"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.16"
111 #define SQLITE_VERSION_NUMBER 3007016
112 #define SQLITE_SOURCE_ID "2013-01-17 17:20:49 38852f158ab20bb4d7b264af987ec1538052bec3"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+25 -31
--- src/stat.c
+++ src/stat.c
@@ -66,11 +66,11 @@
6666
@ </td></tr>
6767
if( !brief ){
6868
@ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
6969
n = db_int(0, "SELECT count(*) FROM blob");
7070
m = db_int(0, "SELECT count(*) FROM delta");
71
- @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
71
+ @ %d(n) (%d(n-m) fulltext and %d(m) deltas)
7272
@ </td></tr>
7373
if( n>0 ){
7474
int a, b;
7575
Stmt q;
7676
@ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
@@ -94,11 +94,11 @@
9494
a = t/fsize;
9595
@ %d(a):%d(b)
9696
@ </td></tr>
9797
}
9898
@ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
99
- n = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
99
+ n = db_int(0, "SELECT count(*) FROM event WHERE type='ci' /*scan*/");
100100
@ %d(n)
101101
@ </td></tr>
102102
@ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
103103
n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
104104
@ %d(n)
@@ -115,17 +115,16 @@
115115
@ </td></tr>
116116
}
117117
@ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
118118
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
119119
" + 0.99");
120
- @ %d(n) days or approximately %.2f(n/365.24) years.
120
+ @ %d(n) days or approximately %.2f(n/365.2425) years.
121121
@ </td></tr>
122122
@ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
123
- @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
124123
@ <tr><th>Fossil&nbsp;Version:</th><td>
125
- @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
126
- @ (%h(COMPILER_NAME))
124
+ @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
125
+ @ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
127126
@ </td></tr>
128127
@ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(SQLITE_SOURCE_ID)
129128
@ [%.10s(&SQLITE_SOURCE_ID[20])] (%s(SQLITE_VERSION))</td></tr>
130129
@ <tr><th>Database&nbsp;Stats:</th><td>
131130
zDb = db_name("repository");
@@ -139,13 +138,20 @@
139138
@ </table>
140139
style_footer();
141140
}
142141
143142
/*
144
-** COMMAND: dbstat
143
+** COMMAND: dbstat*
144
+**
145
+** Usage: %fossil dbstat ?-brief | -b?
146
+**
147
+** Shows statistics and global information about the repository.
145148
**
146
-** Show statistics and global information about the repository.
149
+** The (-brief|-b) option removes any "long-running" statistics, namely
150
+** those whose calculations are known to slow down as the repository
151
+** grows.
152
+**
147153
*/
148154
void dbstat_cmd(void){
149155
i64 t, fsize;
150156
int n, m;
151157
int szMax, szAvg;
@@ -187,43 +193,31 @@
187193
}
188194
a = t/fsize;
189195
fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
190196
}
191197
n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
192
- fossil_print("%*s%d\n", colWidth, "checkin-count:", n);
198
+ fossil_print("%*s%d\n", colWidth, "checkins:", n);
193199
n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
194
- /* FIXME/TODO: add the change-count-per-type to each event type,
195
- ** plus add 'Event' count
196
- */
197
-#if 0
198
- m = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
199
-#endif
200
- fossil_print("%*s%d"/* (%d changes) */"\n", colWidth, "file-count:",
201
- n/*, m */);
200
+ fossil_print("%*s%d across all branches\n", colWidth, "files:", n);
202201
n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
203202
" WHERE tagname GLOB 'wiki-*'");
204
-#if 0
205
- m = db_int(0, "SELECT COUNT(*) FROM blob b JOIN event e WHERE "
206
- "b.rid=e.objid AND e.type='w'");
207
-#endif
208
- fossil_print("%*s%d"/* (%d changes) */"\n", colWidth, "wikipage-count:",
209
- n/*, m */);
203
+ m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'");
204
+ fossil_print("%*s%d (%d changes)\n", colWidth, "wikipages:", n, m);
210205
n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
211206
" WHERE tagname GLOB 'tkt-*'");
212
-#if 0
213
- m = db_int(0, "SELECT COUNT(*) FROM blob b JOIN event e WHERE "
214
- "b.rid=e.objid AND e.type='t'");
215
-#endif
216
- fossil_print("%*s%d"/* (%d changes)*/"\n", colWidth, "ticket-count:",
217
- n/* , m */);
207
+ m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'");
208
+ fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m);
209
+ n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'");
210
+ fossil_print("%*s%d\n", colWidth, "events:", n);
211
+ n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
212
+ fossil_print("%*s%d\n", colWidth, "tagchanges:", n);
218213
}
219214
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
220215
" + 0.99");
221216
fossil_print("%*s%d days or approximately %.2f years.\n",
222
- colWidth, "project-age:", n, n/365.24);
217
+ colWidth, "project-age:", n, n/365.2425);
223218
fossil_print("%*s%s\n", colWidth, "project-id:", db_get("project-code",""));
224
- fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code",""));
225219
fossil_print("%*s%s %s %s (%s)\n",
226220
colWidth, "fossil-version:",
227221
RELEASE_VERSION, MANIFEST_DATE, MANIFEST_VERSION,
228222
COMPILER_NAME);
229223
fossil_print("%*s%.19s [%.10s] (%s)\n",
230224
--- src/stat.c
+++ src/stat.c
@@ -66,11 +66,11 @@
66 @ </td></tr>
67 if( !brief ){
68 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
69 n = db_int(0, "SELECT count(*) FROM blob");
70 m = db_int(0, "SELECT count(*) FROM delta");
71 @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
72 @ </td></tr>
73 if( n>0 ){
74 int a, b;
75 Stmt q;
76 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
@@ -94,11 +94,11 @@
94 a = t/fsize;
95 @ %d(a):%d(b)
96 @ </td></tr>
97 }
98 @ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
99 n = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
100 @ %d(n)
101 @ </td></tr>
102 @ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
103 n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
104 @ %d(n)
@@ -115,17 +115,16 @@
115 @ </td></tr>
116 }
117 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
118 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
119 " + 0.99");
120 @ %d(n) days or approximately %.2f(n/365.24) years.
121 @ </td></tr>
122 @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
123 @ <tr><th>Server&nbsp;ID:</th><td>%h(db_get("server-code",""))</td></tr>
124 @ <tr><th>Fossil&nbsp;Version:</th><td>
125 @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
126 @ (%h(COMPILER_NAME))
127 @ </td></tr>
128 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(SQLITE_SOURCE_ID)
129 @ [%.10s(&SQLITE_SOURCE_ID[20])] (%s(SQLITE_VERSION))</td></tr>
130 @ <tr><th>Database&nbsp;Stats:</th><td>
131 zDb = db_name("repository");
@@ -139,13 +138,20 @@
139 @ </table>
140 style_footer();
141 }
142
143 /*
144 ** COMMAND: dbstat
 
 
 
 
145 **
146 ** Show statistics and global information about the repository.
 
 
 
147 */
148 void dbstat_cmd(void){
149 i64 t, fsize;
150 int n, m;
151 int szMax, szAvg;
@@ -187,43 +193,31 @@
187 }
188 a = t/fsize;
189 fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
190 }
191 n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
192 fossil_print("%*s%d\n", colWidth, "checkin-count:", n);
193 n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
194 /* FIXME/TODO: add the change-count-per-type to each event type,
195 ** plus add 'Event' count
196 */
197 #if 0
198 m = db_int(0, "SELECT count(distinct mid) FROM mlink /*scan*/");
199 #endif
200 fossil_print("%*s%d"/* (%d changes) */"\n", colWidth, "file-count:",
201 n/*, m */);
202 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
203 " WHERE tagname GLOB 'wiki-*'");
204 #if 0
205 m = db_int(0, "SELECT COUNT(*) FROM blob b JOIN event e WHERE "
206 "b.rid=e.objid AND e.type='w'");
207 #endif
208 fossil_print("%*s%d"/* (%d changes) */"\n", colWidth, "wikipage-count:",
209 n/*, m */);
210 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
211 " WHERE tagname GLOB 'tkt-*'");
212 #if 0
213 m = db_int(0, "SELECT COUNT(*) FROM blob b JOIN event e WHERE "
214 "b.rid=e.objid AND e.type='t'");
215 #endif
216 fossil_print("%*s%d"/* (%d changes)*/"\n", colWidth, "ticket-count:",
217 n/* , m */);
218 }
219 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
220 " + 0.99");
221 fossil_print("%*s%d days or approximately %.2f years.\n",
222 colWidth, "project-age:", n, n/365.24);
223 fossil_print("%*s%s\n", colWidth, "project-id:", db_get("project-code",""));
224 fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code",""));
225 fossil_print("%*s%s %s %s (%s)\n",
226 colWidth, "fossil-version:",
227 RELEASE_VERSION, MANIFEST_DATE, MANIFEST_VERSION,
228 COMPILER_NAME);
229 fossil_print("%*s%.19s [%.10s] (%s)\n",
230
--- src/stat.c
+++ src/stat.c
@@ -66,11 +66,11 @@
66 @ </td></tr>
67 if( !brief ){
68 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
69 n = db_int(0, "SELECT count(*) FROM blob");
70 m = db_int(0, "SELECT count(*) FROM delta");
71 @ %d(n) (%d(n-m) fulltext and %d(m) deltas)
72 @ </td></tr>
73 if( n>0 ){
74 int a, b;
75 Stmt q;
76 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
@@ -94,11 +94,11 @@
94 a = t/fsize;
95 @ %d(a):%d(b)
96 @ </td></tr>
97 }
98 @ <tr><th>Number&nbsp;Of&nbsp;Check-ins:</th><td>
99 n = db_int(0, "SELECT count(*) FROM event WHERE type='ci' /*scan*/");
100 @ %d(n)
101 @ </td></tr>
102 @ <tr><th>Number&nbsp;Of&nbsp;Files:</th><td>
103 n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
104 @ %d(n)
@@ -115,17 +115,16 @@
115 @ </td></tr>
116 }
117 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
118 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
119 " + 0.99");
120 @ %d(n) days or approximately %.2f(n/365.2425) years.
121 @ </td></tr>
122 @ <tr><th>Project&nbsp;ID:</th><td>%h(db_get("project-code",""))</td></tr>
 
123 @ <tr><th>Fossil&nbsp;Version:</th><td>
124 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
125 @ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
126 @ </td></tr>
127 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(SQLITE_SOURCE_ID)
128 @ [%.10s(&SQLITE_SOURCE_ID[20])] (%s(SQLITE_VERSION))</td></tr>
129 @ <tr><th>Database&nbsp;Stats:</th><td>
130 zDb = db_name("repository");
@@ -139,13 +138,20 @@
138 @ </table>
139 style_footer();
140 }
141
142 /*
143 ** COMMAND: dbstat*
144 **
145 ** Usage: %fossil dbstat ?-brief | -b?
146 **
147 ** Shows statistics and global information about the repository.
148 **
149 ** The (-brief|-b) option removes any "long-running" statistics, namely
150 ** those whose calculations are known to slow down as the repository
151 ** grows.
152 **
153 */
154 void dbstat_cmd(void){
155 i64 t, fsize;
156 int n, m;
157 int szMax, szAvg;
@@ -187,43 +193,31 @@
193 }
194 a = t/fsize;
195 fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
196 }
197 n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
198 fossil_print("%*s%d\n", colWidth, "checkins:", n);
199 n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
200 fossil_print("%*s%d across all branches\n", colWidth, "files:", n);
 
 
 
 
 
 
 
201 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
202 " WHERE tagname GLOB 'wiki-*'");
203 m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'");
204 fossil_print("%*s%d (%d changes)\n", colWidth, "wikipages:", n, m);
 
 
 
 
205 n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
206 " WHERE tagname GLOB 'tkt-*'");
207 m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'");
208 fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m);
209 n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'");
210 fossil_print("%*s%d\n", colWidth, "events:", n);
211 n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
212 fossil_print("%*s%d\n", colWidth, "tagchanges:", n);
213 }
214 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
215 " + 0.99");
216 fossil_print("%*s%d days or approximately %.2f years.\n",
217 colWidth, "project-age:", n, n/365.2425);
218 fossil_print("%*s%s\n", colWidth, "project-id:", db_get("project-code",""));
 
219 fossil_print("%*s%s %s %s (%s)\n",
220 colWidth, "fossil-version:",
221 RELEASE_VERSION, MANIFEST_DATE, MANIFEST_VERSION,
222 COMPILER_NAME);
223 fossil_print("%*s%.19s [%.10s] (%s)\n",
224
+4 -4
--- src/timeline.c
+++ src/timeline.c
@@ -1507,16 +1507,16 @@
15071507
@ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim)
15081508
@ AS primPlinkCount,
15091509
@ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
15101510
@ event.mtime AS mtime,
15111511
@ tagxref.value AS branch
1512
- @ FROM tag CROSS JOIN event CROSS JOIN blob CROSS JOIN tagxref
1512
+ @ FROM tag CROSS JOIN event CROSS JOIN blob
1513
+ @ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
1514
+ @ AND tagxref.tagtype>0
1515
+ @ AND tagxref.rid=blob.rid
15131516
@ WHERE blob.rid=event.objid
15141517
@ AND tag.tagname='branch'
1515
- @ AND tagxref.tagid=tag.tagid
1516
- @ AND tagxref.tagtype>0
1517
- @ AND tagxref.rid=blob.rid
15181518
;
15191519
return zBaseSql;
15201520
}
15211521
15221522
/*
15231523
--- src/timeline.c
+++ src/timeline.c
@@ -1507,16 +1507,16 @@
1507 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim)
1508 @ AS primPlinkCount,
1509 @ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
1510 @ event.mtime AS mtime,
1511 @ tagxref.value AS branch
1512 @ FROM tag CROSS JOIN event CROSS JOIN blob CROSS JOIN tagxref
 
 
 
1513 @ WHERE blob.rid=event.objid
1514 @ AND tag.tagname='branch'
1515 @ AND tagxref.tagid=tag.tagid
1516 @ AND tagxref.tagtype>0
1517 @ AND tagxref.rid=blob.rid
1518 ;
1519 return zBaseSql;
1520 }
1521
1522 /*
1523
--- src/timeline.c
+++ src/timeline.c
@@ -1507,16 +1507,16 @@
1507 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim)
1508 @ AS primPlinkCount,
1509 @ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
1510 @ event.mtime AS mtime,
1511 @ tagxref.value AS branch
1512 @ FROM tag CROSS JOIN event CROSS JOIN blob
1513 @ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
1514 @ AND tagxref.tagtype>0
1515 @ AND tagxref.rid=blob.rid
1516 @ WHERE blob.rid=event.objid
1517 @ AND tag.tagname='branch'
 
 
 
1518 ;
1519 return zBaseSql;
1520 }
1521
1522 /*
1523
+25 -6
--- src/update.c
+++ src/update.c
@@ -667,10 +667,13 @@
667667
** Usage: %fossil revert ?-r REVISION? ?FILE ...?
668668
**
669669
** Revert to the current repository version of FILE, or to
670670
** the version associated with baseline REVISION if the -r flag
671671
** appears.
672
+**
673
+** If FILE was part of a rename operation, both the original file
674
+** and the renamed file are reverted.
672675
**
673676
** Revert all files if no file name is provided.
674677
**
675678
** If a file is reverted accidently, it can be restored using
676679
** the "fossil undo" command.
@@ -706,11 +709,22 @@
706709
if( g.argc>2 ){
707710
for(i=2; i<g.argc; i++){
708711
Blob fname;
709712
zFile = mprintf("%/", g.argv[i]);
710713
file_tree_name(zFile, &fname, 1);
711
- db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname);
714
+ db_multi_exec(
715
+ "REPLACE INTO torevert VALUES(%B);"
716
+ "INSERT OR IGNORE INTO torevert"
717
+ " SELECT pathname"
718
+ " FROM vfile"
719
+ " WHERE origname IN(%B)"
720
+ " UNION ALL"
721
+ " SELECT origname"
722
+ " FROM vfile"
723
+ " WHERE pathname IN(%B) AND origname IS NOT NULL;",
724
+ &fname, &fname, &fname
725
+ );
712726
blob_reset(&fname);
713727
}
714728
}else{
715729
int vid;
716730
vid = db_lget_int("checkout", 0);
@@ -748,11 +762,17 @@
748762
}else{
749763
undo_save(zFile);
750764
file_delete(zFull);
751765
fossil_print("DELETE: %s\n", zFile);
752766
}
753
- db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
767
+ db_multi_exec(
768
+ "UPDATE vfile"
769
+ " SET pathname=origname, origname=NULL"
770
+ " WHERE pathname=%Q AND origname!=pathname AND origname IS NOT NULL;"
771
+ "DELETE FROM vfile WHERE pathname=%Q",
772
+ zFile, zFile
773
+ );
754774
}else{
755775
sqlite3_int64 mtime;
756776
undo_save(zFile);
757777
if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){
758778
file_delete(zFull);
@@ -765,18 +785,17 @@
765785
file_wd_setexe(zFull, isExe);
766786
fossil_print("REVERTED: %s\n", zFile);
767787
mtime = file_wd_mtime(zFull);
768788
db_multi_exec(
769789
"UPDATE vfile"
770
- " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid,"
771
- " pathname=coalesce(origname,pathname), origname=NULL"
772
- " WHERE pathname=%Q",
773
- mtime, isExe, isLink, zFile
790
+ " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid"
791
+ " WHERE pathname=%Q OR origname=%Q",
792
+ mtime, isExe, isLink, zFile, zFile
774793
);
775794
}
776795
blob_reset(&record);
777796
free(zFull);
778797
}
779798
db_finalize(&q);
780799
undo_finish();
781800
db_end_transaction(0);
782801
}
783802
--- src/update.c
+++ src/update.c
@@ -667,10 +667,13 @@
667 ** Usage: %fossil revert ?-r REVISION? ?FILE ...?
668 **
669 ** Revert to the current repository version of FILE, or to
670 ** the version associated with baseline REVISION if the -r flag
671 ** appears.
 
 
 
672 **
673 ** Revert all files if no file name is provided.
674 **
675 ** If a file is reverted accidently, it can be restored using
676 ** the "fossil undo" command.
@@ -706,11 +709,22 @@
706 if( g.argc>2 ){
707 for(i=2; i<g.argc; i++){
708 Blob fname;
709 zFile = mprintf("%/", g.argv[i]);
710 file_tree_name(zFile, &fname, 1);
711 db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname);
 
 
 
 
 
 
 
 
 
 
 
712 blob_reset(&fname);
713 }
714 }else{
715 int vid;
716 vid = db_lget_int("checkout", 0);
@@ -748,11 +762,17 @@
748 }else{
749 undo_save(zFile);
750 file_delete(zFull);
751 fossil_print("DELETE: %s\n", zFile);
752 }
753 db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
 
 
 
 
 
 
754 }else{
755 sqlite3_int64 mtime;
756 undo_save(zFile);
757 if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){
758 file_delete(zFull);
@@ -765,18 +785,17 @@
765 file_wd_setexe(zFull, isExe);
766 fossil_print("REVERTED: %s\n", zFile);
767 mtime = file_wd_mtime(zFull);
768 db_multi_exec(
769 "UPDATE vfile"
770 " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid,"
771 " pathname=coalesce(origname,pathname), origname=NULL"
772 " WHERE pathname=%Q",
773 mtime, isExe, isLink, zFile
774 );
775 }
776 blob_reset(&record);
777 free(zFull);
778 }
779 db_finalize(&q);
780 undo_finish();
781 db_end_transaction(0);
782 }
783
--- src/update.c
+++ src/update.c
@@ -667,10 +667,13 @@
667 ** Usage: %fossil revert ?-r REVISION? ?FILE ...?
668 **
669 ** Revert to the current repository version of FILE, or to
670 ** the version associated with baseline REVISION if the -r flag
671 ** appears.
672 **
673 ** If FILE was part of a rename operation, both the original file
674 ** and the renamed file are reverted.
675 **
676 ** Revert all files if no file name is provided.
677 **
678 ** If a file is reverted accidently, it can be restored using
679 ** the "fossil undo" command.
@@ -706,11 +709,22 @@
709 if( g.argc>2 ){
710 for(i=2; i<g.argc; i++){
711 Blob fname;
712 zFile = mprintf("%/", g.argv[i]);
713 file_tree_name(zFile, &fname, 1);
714 db_multi_exec(
715 "REPLACE INTO torevert VALUES(%B);"
716 "INSERT OR IGNORE INTO torevert"
717 " SELECT pathname"
718 " FROM vfile"
719 " WHERE origname IN(%B)"
720 " UNION ALL"
721 " SELECT origname"
722 " FROM vfile"
723 " WHERE pathname IN(%B) AND origname IS NOT NULL;",
724 &fname, &fname, &fname
725 );
726 blob_reset(&fname);
727 }
728 }else{
729 int vid;
730 vid = db_lget_int("checkout", 0);
@@ -748,11 +762,17 @@
762 }else{
763 undo_save(zFile);
764 file_delete(zFull);
765 fossil_print("DELETE: %s\n", zFile);
766 }
767 db_multi_exec(
768 "UPDATE vfile"
769 " SET pathname=origname, origname=NULL"
770 " WHERE pathname=%Q AND origname!=pathname AND origname IS NOT NULL;"
771 "DELETE FROM vfile WHERE pathname=%Q",
772 zFile, zFile
773 );
774 }else{
775 sqlite3_int64 mtime;
776 undo_save(zFile);
777 if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){
778 file_delete(zFull);
@@ -765,18 +785,17 @@
785 file_wd_setexe(zFull, isExe);
786 fossil_print("REVERTED: %s\n", zFile);
787 mtime = file_wd_mtime(zFull);
788 db_multi_exec(
789 "UPDATE vfile"
790 " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid"
791 " WHERE pathname=%Q OR origname=%Q",
792 mtime, isExe, isLink, zFile, zFile
 
793 );
794 }
795 blob_reset(&record);
796 free(zFull);
797 }
798 db_finalize(&q);
799 undo_finish();
800 db_end_transaction(0);
801 }
802
+11 -2
--- src/xfer.c
+++ src/xfer.c
@@ -18,10 +18,12 @@
1818
** This file contains code to implement the file transfer protocol.
1919
*/
2020
#include "config.h"
2121
#include "xfer.h"
2222
23
+#include <time.h>
24
+
2325
/*
2426
** This structure holds information about the current state of either
2527
** a client or a server that is participating in xfer.
2628
*/
2729
typedef struct Xfer Xfer;
@@ -40,10 +42,11 @@
4042
int nDeltaRcvd; /* Number of deltas received */
4143
int nDanglingFile; /* Number of dangling deltas received */
4244
int mxSend; /* Stop sending "file" with pOut reaches this size */
4345
u8 syncPrivate; /* True to enable syncing private content */
4446
u8 nextIsPrivate; /* If true, next "file" received is a private */
47
+ time_t maxTime; /* Time when this transfer should be finished */
4548
};
4649
4750
4851
/*
4952
** The input blob contains a UUID. Convert it into a record ID.
@@ -393,11 +396,12 @@
393396
}
394397
if( uuid_is_shunned(blob_str(pUuid)) ){
395398
blob_reset(&uuid);
396399
return;
397400
}
398
- if( pXfer->mxSend<=blob_size(pXfer->pOut) ){
401
+ if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
402
+ pXfer->mxSend<=blob_size(pXfer->pOut) ){
399403
const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
400404
blob_appendf(pXfer->pOut, zFormat, pUuid);
401405
pXfer->nIGotSent++;
402406
blob_reset(&uuid);
403407
return;
@@ -867,10 +871,13 @@
867871
}
868872
blob_zero(&xfer.err);
869873
xfer.pIn = &g.cgiIn;
870874
xfer.pOut = cgi_output_blob();
871875
xfer.mxSend = db_get_int("max-download", 5000000);
876
+ xfer.maxTime = db_get_int("max-download-time", 30);
877
+ if( xfer.maxTime<1 ) xfer.maxTime = 1;
878
+ xfer.maxTime += time(NULL);
872879
g.xferPanic = 1;
873880
874881
db_begin_transaction();
875882
db_multi_exec(
876883
"CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
@@ -1034,11 +1041,12 @@
10341041
if( iVers>=3 ){
10351042
cgi_set_content_type("application/x-fossil-uncompressed");
10361043
}
10371044
blob_is_int(&xfer.aToken[2], &seqno);
10381045
max = db_int(0, "SELECT max(rid) FROM blob");
1039
- while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max ){
1046
+ while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max){
1047
+ if( time(NULL) >= xfer.maxTime ) break;
10401048
if( iVers>=3 ){
10411049
send_compressed_file(&xfer, seqno);
10421050
}else{
10431051
send_file(&xfer, seqno, 0, 1);
10441052
}
@@ -1328,10 +1336,11 @@
13281336
socket_global_init();
13291337
memset(&xfer, 0, sizeof(xfer));
13301338
xfer.pIn = &recv;
13311339
xfer.pOut = &send;
13321340
xfer.mxSend = db_get_int("max-upload", 250000);
1341
+ xfer.maxTime = -1;
13331342
if( syncFlags & SYNC_PRIVATE ){
13341343
g.perm.Private = 1;
13351344
xfer.syncPrivate = 1;
13361345
}
13371346
13381347
13391348
ADDED test/revert.test
--- src/xfer.c
+++ src/xfer.c
@@ -18,10 +18,12 @@
18 ** This file contains code to implement the file transfer protocol.
19 */
20 #include "config.h"
21 #include "xfer.h"
22
 
 
23 /*
24 ** This structure holds information about the current state of either
25 ** a client or a server that is participating in xfer.
26 */
27 typedef struct Xfer Xfer;
@@ -40,10 +42,11 @@
40 int nDeltaRcvd; /* Number of deltas received */
41 int nDanglingFile; /* Number of dangling deltas received */
42 int mxSend; /* Stop sending "file" with pOut reaches this size */
43 u8 syncPrivate; /* True to enable syncing private content */
44 u8 nextIsPrivate; /* If true, next "file" received is a private */
 
45 };
46
47
48 /*
49 ** The input blob contains a UUID. Convert it into a record ID.
@@ -393,11 +396,12 @@
393 }
394 if( uuid_is_shunned(blob_str(pUuid)) ){
395 blob_reset(&uuid);
396 return;
397 }
398 if( pXfer->mxSend<=blob_size(pXfer->pOut) ){
 
399 const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
400 blob_appendf(pXfer->pOut, zFormat, pUuid);
401 pXfer->nIGotSent++;
402 blob_reset(&uuid);
403 return;
@@ -867,10 +871,13 @@
867 }
868 blob_zero(&xfer.err);
869 xfer.pIn = &g.cgiIn;
870 xfer.pOut = cgi_output_blob();
871 xfer.mxSend = db_get_int("max-download", 5000000);
 
 
 
872 g.xferPanic = 1;
873
874 db_begin_transaction();
875 db_multi_exec(
876 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
@@ -1034,11 +1041,12 @@
1034 if( iVers>=3 ){
1035 cgi_set_content_type("application/x-fossil-uncompressed");
1036 }
1037 blob_is_int(&xfer.aToken[2], &seqno);
1038 max = db_int(0, "SELECT max(rid) FROM blob");
1039 while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max ){
 
1040 if( iVers>=3 ){
1041 send_compressed_file(&xfer, seqno);
1042 }else{
1043 send_file(&xfer, seqno, 0, 1);
1044 }
@@ -1328,10 +1336,11 @@
1328 socket_global_init();
1329 memset(&xfer, 0, sizeof(xfer));
1330 xfer.pIn = &recv;
1331 xfer.pOut = &send;
1332 xfer.mxSend = db_get_int("max-upload", 250000);
 
1333 if( syncFlags & SYNC_PRIVATE ){
1334 g.perm.Private = 1;
1335 xfer.syncPrivate = 1;
1336 }
1337
1338
1339 DDED test/revert.test
--- src/xfer.c
+++ src/xfer.c
@@ -18,10 +18,12 @@
18 ** This file contains code to implement the file transfer protocol.
19 */
20 #include "config.h"
21 #include "xfer.h"
22
23 #include <time.h>
24
25 /*
26 ** This structure holds information about the current state of either
27 ** a client or a server that is participating in xfer.
28 */
29 typedef struct Xfer Xfer;
@@ -40,10 +42,11 @@
42 int nDeltaRcvd; /* Number of deltas received */
43 int nDanglingFile; /* Number of dangling deltas received */
44 int mxSend; /* Stop sending "file" with pOut reaches this size */
45 u8 syncPrivate; /* True to enable syncing private content */
46 u8 nextIsPrivate; /* If true, next "file" received is a private */
47 time_t maxTime; /* Time when this transfer should be finished */
48 };
49
50
51 /*
52 ** The input blob contains a UUID. Convert it into a record ID.
@@ -393,11 +396,12 @@
396 }
397 if( uuid_is_shunned(blob_str(pUuid)) ){
398 blob_reset(&uuid);
399 return;
400 }
401 if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
402 pXfer->mxSend<=blob_size(pXfer->pOut) ){
403 const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
404 blob_appendf(pXfer->pOut, zFormat, pUuid);
405 pXfer->nIGotSent++;
406 blob_reset(&uuid);
407 return;
@@ -867,10 +871,13 @@
871 }
872 blob_zero(&xfer.err);
873 xfer.pIn = &g.cgiIn;
874 xfer.pOut = cgi_output_blob();
875 xfer.mxSend = db_get_int("max-download", 5000000);
876 xfer.maxTime = db_get_int("max-download-time", 30);
877 if( xfer.maxTime<1 ) xfer.maxTime = 1;
878 xfer.maxTime += time(NULL);
879 g.xferPanic = 1;
880
881 db_begin_transaction();
882 db_multi_exec(
883 "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
@@ -1034,11 +1041,12 @@
1041 if( iVers>=3 ){
1042 cgi_set_content_type("application/x-fossil-uncompressed");
1043 }
1044 blob_is_int(&xfer.aToken[2], &seqno);
1045 max = db_int(0, "SELECT max(rid) FROM blob");
1046 while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max){
1047 if( time(NULL) >= xfer.maxTime ) break;
1048 if( iVers>=3 ){
1049 send_compressed_file(&xfer, seqno);
1050 }else{
1051 send_file(&xfer, seqno, 0, 1);
1052 }
@@ -1328,10 +1336,11 @@
1336 socket_global_init();
1337 memset(&xfer, 0, sizeof(xfer));
1338 xfer.pIn = &recv;
1339 xfer.pOut = &send;
1340 xfer.mxSend = db_get_int("max-upload", 250000);
1341 xfer.maxTime = -1;
1342 if( syncFlags & SYNC_PRIVATE ){
1343 g.perm.Private = 1;
1344 xfer.syncPrivate = 1;
1345 }
1346
1347
1348 DDED test/revert.test
--- a/test/revert.test
+++ b/test/revert.test
@@ -0,0 +1,26 @@
1
+puts res=$# Fossil will write dexec rm f1po_init# Copytcatch {exec $::exec mvitory} $res]} {
2
+ puts stderr "Cannot ris test within anif {[llength $args] % 2} {
3
+ set revertArgs [lindex $args 0]
4
+ set args [lrange $args 1 end]
5
+ } else {
6
+ set revertArgs {}
7
+ }VERTED: f3
8
+ DELETE:j@Uy,1X@Se,4:: f0G@YW,21@UT,3:ED:1w@WW,3:ED:3t@YT,G:ED: f3
9
+ DELETE:K@hF,O@YG:ED: f3
10
+ DELETE:K@hF,O@Yl,1
11
+ DELETE:a@nd,1WvoIq;-testnormalize-status-list]
12
+ set r]
13
+ if {$result ne $expected} {
14
+ set passed 0
15
+ protOut " Expected:\n [join $expected "\n "]"
16
+ protOut " Got:\n [joh {exec $::fossilexe info} res
17
+if {![regexp {use --repository} $res]} {
18
+ puts stderr "Cannot run this test within an open checkout"
19
+ return
20
+}
21
+repo_init# Copytcatch {exec $::fossilexe info} res
22
+if {![regexp {use --repository} $res]} {
23
+ puts stderr "Cannot run this test witt# Copytcatch {exec $::fossilexe info} res
24
+if {![regexp {use --repository} $res]} {
25
+ put12 f03 f1 {exec $::fossilexe info}t# Copytcatch {exec $::foss4 f2 {exec $::ft# Copytcatch {exec $::foss5 f3 {exec $::fossilexe info} res
26
+if {![re
--- a/test/revert.test
+++ b/test/revert.test
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/revert.test
+++ b/test/revert.test
@@ -0,0 +1,26 @@
1 puts res=$# Fossil will write dexec rm f1po_init# Copytcatch {exec $::exec mvitory} $res]} {
2 puts stderr "Cannot ris test within anif {[llength $args] % 2} {
3 set revertArgs [lindex $args 0]
4 set args [lrange $args 1 end]
5 } else {
6 set revertArgs {}
7 }VERTED: f3
8 DELETE:j@Uy,1X@Se,4:: f0G@YW,21@UT,3:ED:1w@WW,3:ED:3t@YT,G:ED: f3
9 DELETE:K@hF,O@YG:ED: f3
10 DELETE:K@hF,O@Yl,1
11 DELETE:a@nd,1WvoIq;-testnormalize-status-list]
12 set r]
13 if {$result ne $expected} {
14 set passed 0
15 protOut " Expected:\n [join $expected "\n "]"
16 protOut " Got:\n [joh {exec $::fossilexe info} res
17 if {![regexp {use --repository} $res]} {
18 puts stderr "Cannot run this test within an open checkout"
19 return
20 }
21 repo_init# Copytcatch {exec $::fossilexe info} res
22 if {![regexp {use --repository} $res]} {
23 puts stderr "Cannot run this test witt# Copytcatch {exec $::fossilexe info} res
24 if {![regexp {use --repository} $res]} {
25 put12 f03 f1 {exec $::fossilexe info}t# Copytcatch {exec $::foss4 f2 {exec $::ft# Copytcatch {exec $::foss5 f3 {exec $::fossilexe info} res
26 if {![re
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1633,11 +1633,11 @@
16331633
16341634
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
16351635
$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
16361636
16371637
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1638
- $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1638
+ $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
16391639
16401640
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
16411641
16421642
$(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
16431643
$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
16441644
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1633,11 +1633,11 @@
1633
1634 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1635 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1636
1637 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1638 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1639
1640 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1641
1642 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1643 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1644
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1633,11 +1633,11 @@
1633
1634 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1635 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1636
1637 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1638 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1639
1640 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1641
1642 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1643 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1644
+30 -7
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -22,18 +22,35 @@
2222
2323
# zlib options
2424
ZINCDIR = $(B)\compat\zlib
2525
ZLIBDIR = $(B)\compat\zlib
2626
ZLIB = zlib.lib
27
+
28
+# Uncomment to enable JSON API
29
+# FOSSIL_ENABLE_JSON = 1
30
+
31
+# Uncomment to enable markdown support
32
+# FOSSIL_ENABLE_MARKDOWN = 1
2733
2834
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
2935
3036
CFLAGS = -nologo -MT -O2
3137
BCC = $(CC) $(CFLAGS)
3238
TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
39
+RCC = rc -D_WIN32 -D_MSC_VER $(INCL)
3340
LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
3441
LIBDIR = -LIBPATH:$(ZLIBDIR)
42
+
43
+!ifdef FOSSIL_ENABLE_JSON
44
+TCC = $(TCC) -DFOSSIL_ENABLE_JSON
45
+RCC = $(RCC) -DFOSSIL_ENABLE_JSON
46
+!endif
47
+
48
+!ifdef FOSSIL_ENABLE_MARKDOWN
49
+TCC = $(TCC) -DFOSSIL_ENABLE_MARKDOWN
50
+RCC = $(RCC) -DFOSSIL_ENABLE_MARKDOWN
51
+!endif
3552
3653
SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
3754
/DSQLITE_THREADSAFE=0 \
3855
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
3956
/DSQLITE_ENABLE_STAT3 \
@@ -160,10 +177,11 @@
160177
$(OX)\clearsign$O \
161178
$(OX)\clone$O \
162179
$(OX)\comformat$O \
163180
$(OX)\configure$O \
164181
$(OX)\content$O \
182
+ $(OX)\cson_amalgamation$O \
165183
$(OX)\db$O \
166184
$(OX)\delta$O \
167185
$(OX)\deltacmd$O \
168186
$(OX)\descendants$O \
169187
$(OX)\diff$O \
@@ -219,19 +237,23 @@
219237
$(OX)\rss$O \
220238
$(OX)\schema$O \
221239
$(OX)\search$O \
222240
$(OX)\setup$O \
223241
$(OX)\sha1$O \
242
+ $(OX)\shell$O \
224243
$(OX)\shun$O \
225244
$(OX)\skins$O \
226245
$(OX)\sqlcmd$O \
246
+ $(OX)\sqlite3$O \
227247
$(OX)\stash$O \
228248
$(OX)\stat$O \
229249
$(OX)\style$O \
230250
$(OX)\sync$O \
231251
$(OX)\tag$O \
232252
$(OX)\tar$O \
253
+ $(OX)\th$O \
254
+ $(OX)\th_lang$O \
233255
$(OX)\th_main$O \
234256
$(OX)\timeline$O \
235257
$(OX)\tkt$O \
236258
$(OX)\tktsetup$O \
237259
$(OX)\undo$O \
@@ -247,14 +269,11 @@
247269
$(OX)\winhttp$O \
248270
$(OX)\wysiwyg$O \
249271
$(OX)\xfer$O \
250272
$(OX)\xfersetup$O \
251273
$(OX)\zip$O \
252
- $(OX)\shell$O \
253
- $(OX)\sqlite3$O \
254
- $(OX)\th$O \
255
- $(OX)\th_lang$O
274
+ $(OX)\fossil.res
256275
257276
APPNAME = $(OX)\fossil$(E)
258277
259278
all: $(OX) $(APPNAME)
260279
@@ -262,11 +281,11 @@
262281
@echo Building zlib from "$(ZLIBDIR)"...
263282
@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
264283
265284
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
266285
cd $(OX)
267
- link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj @linkopts
286
+ link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
268287
269288
$(OX)\linkopts: $B\win\Makefile.msc
270289
echo $(OX)\add.obj > $@
271290
echo $(OX)\allrepo.obj >> $@
272291
echo $(OX)\attach.obj >> $@
@@ -282,10 +301,11 @@
282301
echo $(OX)\clearsign.obj >> $@
283302
echo $(OX)\clone.obj >> $@
284303
echo $(OX)\comformat.obj >> $@
285304
echo $(OX)\configure.obj >> $@
286305
echo $(OX)\content.obj >> $@
306
+ echo $(OX)\cson_amalgamation.obj >> $@
287307
echo $(OX)\db.obj >> $@
288308
echo $(OX)\delta.obj >> $@
289309
echo $(OX)\deltacmd.obj >> $@
290310
echo $(OX)\descendants.obj >> $@
291311
echo $(OX)\diff.obj >> $@
@@ -407,12 +427,12 @@
407427
$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
408428
$(TCC) /Fo$@ -c $**
409429
410430
VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
411431
$** > $@
412
-$(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
413
- cp $(SRCDIR)\cson_amalgamation.h $@
432
+$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
433
+ $(TCC) /Fo$@ -c $**
414434
415435
page_index.h: mkindex$E $(SRC)
416436
$** > $@
417437
418438
clean:
@@ -422,10 +442,11 @@
422442
-del *.h
423443
-del *.map
424444
-del *.manifest
425445
-del headers
426446
-del linkopts
447
+ -del *.res
427448
428449
realclean: clean
429450
-del $(APPNAME)
430451
-del translate$E
431452
-del mkindex$E
@@ -1070,10 +1091,12 @@
10701091
$(TCC) /Fo$@ -c zip_.c
10711092
10721093
zip_.c : $(SRCDIR)\zip.c
10731094
translate$E $** > $@
10741095
1096
+fossil.res : $B\win\fossil.rc
1097
+ $(RCC) -fo $@ $**
10751098
headers: makeheaders$E page_index.h VERSION.h
10761099
makeheaders$E add_.c:add.h \
10771100
allrepo_.c:allrepo.h \
10781101
attach_.c:attach.h \
10791102
bag_.c:bag.h \
10801103
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -22,18 +22,35 @@
22
23 # zlib options
24 ZINCDIR = $(B)\compat\zlib
25 ZLIBDIR = $(B)\compat\zlib
26 ZLIB = zlib.lib
 
 
 
 
 
 
27
28 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
29
30 CFLAGS = -nologo -MT -O2
31 BCC = $(CC) $(CFLAGS)
32 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
 
33 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
34 LIBDIR = -LIBPATH:$(ZLIBDIR)
 
 
 
 
 
 
 
 
 
 
35
36 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
37 /DSQLITE_THREADSAFE=0 \
38 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
39 /DSQLITE_ENABLE_STAT3 \
@@ -160,10 +177,11 @@
160 $(OX)\clearsign$O \
161 $(OX)\clone$O \
162 $(OX)\comformat$O \
163 $(OX)\configure$O \
164 $(OX)\content$O \
 
165 $(OX)\db$O \
166 $(OX)\delta$O \
167 $(OX)\deltacmd$O \
168 $(OX)\descendants$O \
169 $(OX)\diff$O \
@@ -219,19 +237,23 @@
219 $(OX)\rss$O \
220 $(OX)\schema$O \
221 $(OX)\search$O \
222 $(OX)\setup$O \
223 $(OX)\sha1$O \
 
224 $(OX)\shun$O \
225 $(OX)\skins$O \
226 $(OX)\sqlcmd$O \
 
227 $(OX)\stash$O \
228 $(OX)\stat$O \
229 $(OX)\style$O \
230 $(OX)\sync$O \
231 $(OX)\tag$O \
232 $(OX)\tar$O \
 
 
233 $(OX)\th_main$O \
234 $(OX)\timeline$O \
235 $(OX)\tkt$O \
236 $(OX)\tktsetup$O \
237 $(OX)\undo$O \
@@ -247,14 +269,11 @@
247 $(OX)\winhttp$O \
248 $(OX)\wysiwyg$O \
249 $(OX)\xfer$O \
250 $(OX)\xfersetup$O \
251 $(OX)\zip$O \
252 $(OX)\shell$O \
253 $(OX)\sqlite3$O \
254 $(OX)\th$O \
255 $(OX)\th_lang$O
256
257 APPNAME = $(OX)\fossil$(E)
258
259 all: $(OX) $(APPNAME)
260
@@ -262,11 +281,11 @@
262 @echo Building zlib from "$(ZLIBDIR)"...
263 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
264
265 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
266 cd $(OX)
267 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj @linkopts
268
269 $(OX)\linkopts: $B\win\Makefile.msc
270 echo $(OX)\add.obj > $@
271 echo $(OX)\allrepo.obj >> $@
272 echo $(OX)\attach.obj >> $@
@@ -282,10 +301,11 @@
282 echo $(OX)\clearsign.obj >> $@
283 echo $(OX)\clone.obj >> $@
284 echo $(OX)\comformat.obj >> $@
285 echo $(OX)\configure.obj >> $@
286 echo $(OX)\content.obj >> $@
 
287 echo $(OX)\db.obj >> $@
288 echo $(OX)\delta.obj >> $@
289 echo $(OX)\deltacmd.obj >> $@
290 echo $(OX)\descendants.obj >> $@
291 echo $(OX)\diff.obj >> $@
@@ -407,12 +427,12 @@
407 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
408 $(TCC) /Fo$@ -c $**
409
410 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
411 $** > $@
412 $(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h
413 cp $(SRCDIR)\cson_amalgamation.h $@
414
415 page_index.h: mkindex$E $(SRC)
416 $** > $@
417
418 clean:
@@ -422,10 +442,11 @@
422 -del *.h
423 -del *.map
424 -del *.manifest
425 -del headers
426 -del linkopts
 
427
428 realclean: clean
429 -del $(APPNAME)
430 -del translate$E
431 -del mkindex$E
@@ -1070,10 +1091,12 @@
1070 $(TCC) /Fo$@ -c zip_.c
1071
1072 zip_.c : $(SRCDIR)\zip.c
1073 translate$E $** > $@
1074
 
 
1075 headers: makeheaders$E page_index.h VERSION.h
1076 makeheaders$E add_.c:add.h \
1077 allrepo_.c:allrepo.h \
1078 attach_.c:attach.h \
1079 bag_.c:bag.h \
1080
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -22,18 +22,35 @@
22
23 # zlib options
24 ZINCDIR = $(B)\compat\zlib
25 ZLIBDIR = $(B)\compat\zlib
26 ZLIB = zlib.lib
27
28 # Uncomment to enable JSON API
29 # FOSSIL_ENABLE_JSON = 1
30
31 # Uncomment to enable markdown support
32 # FOSSIL_ENABLE_MARKDOWN = 1
33
34 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
35
36 CFLAGS = -nologo -MT -O2
37 BCC = $(CC) $(CFLAGS)
38 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
39 RCC = rc -D_WIN32 -D_MSC_VER $(INCL)
40 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
41 LIBDIR = -LIBPATH:$(ZLIBDIR)
42
43 !ifdef FOSSIL_ENABLE_JSON
44 TCC = $(TCC) -DFOSSIL_ENABLE_JSON
45 RCC = $(RCC) -DFOSSIL_ENABLE_JSON
46 !endif
47
48 !ifdef FOSSIL_ENABLE_MARKDOWN
49 TCC = $(TCC) -DFOSSIL_ENABLE_MARKDOWN
50 RCC = $(RCC) -DFOSSIL_ENABLE_MARKDOWN
51 !endif
52
53 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
54 /DSQLITE_THREADSAFE=0 \
55 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
56 /DSQLITE_ENABLE_STAT3 \
@@ -160,10 +177,11 @@
177 $(OX)\clearsign$O \
178 $(OX)\clone$O \
179 $(OX)\comformat$O \
180 $(OX)\configure$O \
181 $(OX)\content$O \
182 $(OX)\cson_amalgamation$O \
183 $(OX)\db$O \
184 $(OX)\delta$O \
185 $(OX)\deltacmd$O \
186 $(OX)\descendants$O \
187 $(OX)\diff$O \
@@ -219,19 +237,23 @@
237 $(OX)\rss$O \
238 $(OX)\schema$O \
239 $(OX)\search$O \
240 $(OX)\setup$O \
241 $(OX)\sha1$O \
242 $(OX)\shell$O \
243 $(OX)\shun$O \
244 $(OX)\skins$O \
245 $(OX)\sqlcmd$O \
246 $(OX)\sqlite3$O \
247 $(OX)\stash$O \
248 $(OX)\stat$O \
249 $(OX)\style$O \
250 $(OX)\sync$O \
251 $(OX)\tag$O \
252 $(OX)\tar$O \
253 $(OX)\th$O \
254 $(OX)\th_lang$O \
255 $(OX)\th_main$O \
256 $(OX)\timeline$O \
257 $(OX)\tkt$O \
258 $(OX)\tktsetup$O \
259 $(OX)\undo$O \
@@ -247,14 +269,11 @@
269 $(OX)\winhttp$O \
270 $(OX)\wysiwyg$O \
271 $(OX)\xfer$O \
272 $(OX)\xfersetup$O \
273 $(OX)\zip$O \
274 $(OX)\fossil.res
 
 
 
275
276 APPNAME = $(OX)\fossil$(E)
277
278 all: $(OX) $(APPNAME)
279
@@ -262,11 +281,11 @@
281 @echo Building zlib from "$(ZLIBDIR)"...
282 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
283
284 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
285 cd $(OX)
286 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
287
288 $(OX)\linkopts: $B\win\Makefile.msc
289 echo $(OX)\add.obj > $@
290 echo $(OX)\allrepo.obj >> $@
291 echo $(OX)\attach.obj >> $@
@@ -282,10 +301,11 @@
301 echo $(OX)\clearsign.obj >> $@
302 echo $(OX)\clone.obj >> $@
303 echo $(OX)\comformat.obj >> $@
304 echo $(OX)\configure.obj >> $@
305 echo $(OX)\content.obj >> $@
306 echo $(OX)\cson_amalgamation.obj >> $@
307 echo $(OX)\db.obj >> $@
308 echo $(OX)\delta.obj >> $@
309 echo $(OX)\deltacmd.obj >> $@
310 echo $(OX)\descendants.obj >> $@
311 echo $(OX)\diff.obj >> $@
@@ -407,12 +427,12 @@
427 $(OX)\th_lang$O : $(SRCDIR)\th_lang.c
428 $(TCC) /Fo$@ -c $**
429
430 VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
431 $** > $@
432 $(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
433 $(TCC) /Fo$@ -c $**
434
435 page_index.h: mkindex$E $(SRC)
436 $** > $@
437
438 clean:
@@ -422,10 +442,11 @@
442 -del *.h
443 -del *.map
444 -del *.manifest
445 -del headers
446 -del linkopts
447 -del *.res
448
449 realclean: clean
450 -del $(APPNAME)
451 -del translate$E
452 -del mkindex$E
@@ -1070,10 +1091,12 @@
1091 $(TCC) /Fo$@ -c zip_.c
1092
1093 zip_.c : $(SRCDIR)\zip.c
1094 translate$E $** > $@
1095
1096 fossil.res : $B\win\fossil.rc
1097 $(RCC) -fo $@ $**
1098 headers: makeheaders$E page_index.h VERSION.h
1099 makeheaders$E add_.c:add.h \
1100 allrepo_.c:allrepo.h \
1101 attach_.c:attach.h \
1102 bag_.c:bag.h \
1103

Keyboard Shortcuts

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