Fossil SCM

Merge updates from trunk.

mistachkin 2013-10-11 07:49 UTC allExtra merge
Commit 33d26b91c49b0c2b239fc9bd2a79d5ef35c1d423
--- src/allrepo.c
+++ src/allrepo.c
@@ -112,10 +112,13 @@
112112
**
113113
** Repositories are automatically added to the set of known repositories
114114
** when one of the following commands are run against the repository: clone,
115115
** info, pull, push, or sync. Even previously ignored repositories are
116116
** added back to the list of repositories by these commands.
117
+**
118
+** Options:
119
+** --dontstop Continue with other repositories even after an error
117120
*/
118121
void all_cmd(void){
119122
int n;
120123
Stmt q;
121124
const char *zCmd;
122125
--- src/allrepo.c
+++ src/allrepo.c
@@ -112,10 +112,13 @@
112 **
113 ** Repositories are automatically added to the set of known repositories
114 ** when one of the following commands are run against the repository: clone,
115 ** info, pull, push, or sync. Even previously ignored repositories are
116 ** added back to the list of repositories by these commands.
 
 
 
117 */
118 void all_cmd(void){
119 int n;
120 Stmt q;
121 const char *zCmd;
122
--- src/allrepo.c
+++ src/allrepo.c
@@ -112,10 +112,13 @@
112 **
113 ** Repositories are automatically added to the set of known repositories
114 ** when one of the following commands are run against the repository: clone,
115 ** info, pull, push, or sync. Even previously ignored repositories are
116 ** added back to the list of repositories by these commands.
117 **
118 ** Options:
119 ** --dontstop Continue with other repositories even after an error
120 */
121 void all_cmd(void){
122 int n;
123 Stmt q;
124 const char *zCmd;
125
--- src/allrepo.c
+++ src/allrepo.c
@@ -112,10 +112,13 @@
112112
**
113113
** Repositories are automatically added to the set of known repositories
114114
** when one of the following commands are run against the repository: clone,
115115
** info, pull, push, or sync. Even previously ignored repositories are
116116
** added back to the list of repositories by these commands.
117
+**
118
+** Options:
119
+** --dontstop Continue with other repositories even after an error
117120
*/
118121
void all_cmd(void){
119122
int n;
120123
Stmt q;
121124
const char *zCmd;
122125
--- src/allrepo.c
+++ src/allrepo.c
@@ -112,10 +112,13 @@
112 **
113 ** Repositories are automatically added to the set of known repositories
114 ** when one of the following commands are run against the repository: clone,
115 ** info, pull, push, or sync. Even previously ignored repositories are
116 ** added back to the list of repositories by these commands.
 
 
 
117 */
118 void all_cmd(void){
119 int n;
120 Stmt q;
121 const char *zCmd;
122
--- src/allrepo.c
+++ src/allrepo.c
@@ -112,10 +112,13 @@
112 **
113 ** Repositories are automatically added to the set of known repositories
114 ** when one of the following commands are run against the repository: clone,
115 ** info, pull, push, or sync. Even previously ignored repositories are
116 ** added back to the list of repositories by these commands.
117 **
118 ** Options:
119 ** --dontstop Continue with other repositories even after an error
120 */
121 void all_cmd(void){
122 int n;
123 Stmt q;
124 const char *zCmd;
125
+249
--- src/cgi.c
+++ src/cgi.c
@@ -60,10 +60,17 @@
6060
** Destinations for output text.
6161
*/
6262
#define CGI_HEADER 0
6363
#define CGI_BODY 1
6464
65
+/*
66
+** Flags for SSH HTTP clients
67
+*/
68
+#define CGI_SSH_CLIENT 0x0001 /* Client is SSH */
69
+#define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */
70
+#define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */
71
+
6572
#endif /* INTERFACE */
6673
6774
/*
6875
** The HTTP reply is generated in two pieces: the header and the body.
6976
** These pieces are generated separately because they are not necessary
@@ -1302,10 +1309,234 @@
13021309
}
13031310
}
13041311
cgi_init();
13051312
cgi_trace(0);
13061313
}
1314
+
1315
+/*
1316
+** This routine handles a single HTTP request from an SSH client which is
1317
+** coming in on g.httpIn and which replies on g.httpOut
1318
+**
1319
+** Once all the setup is finished, this procedure returns
1320
+** and subsequent code handles the actual generation of the webpage.
1321
+**
1322
+** It is called in a loop so some variables will need to be replaced
1323
+*/
1324
+void cgi_handle_ssh_http_request(const char *zIpAddr){
1325
+ static int nCycles = 0;
1326
+ static char *zCmd = 0;
1327
+ char *z, *zToken;
1328
+ const char *zType;
1329
+ int i, content_length;
1330
+ char zLine[2000]; /* A single line of input. */
1331
+
1332
+ if( zIpAddr ){
1333
+ if( nCycles==0 ){
1334
+ cgi_setenv("REMOTE_ADDR", zIpAddr);
1335
+ g.zIpAddr = mprintf("%s", zIpAddr);
1336
+ }
1337
+ }else{
1338
+ fossil_panic("missing SSH IP address");
1339
+ }
1340
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1341
+ malformed_request("missing HTTP header");
1342
+ }
1343
+ cgi_trace(zLine);
1344
+ zToken = extract_token(zLine, &z);
1345
+ if( zToken==0 ){
1346
+ malformed_request("malformed HTTP header");
1347
+ }
1348
+
1349
+ if( fossil_strcmp(zToken, "echo")==0 ){
1350
+ /* start looking for probes to complete transport_open */
1351
+ zCmd = cgi_handle_ssh_probes(zLine, sizeof(zLine), z, zToken);
1352
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1353
+ malformed_request("missing HTTP header");
1354
+ }
1355
+ cgi_trace(zLine);
1356
+ zToken = extract_token(zLine, &z);
1357
+ if( zToken==0 ){
1358
+ malformed_request("malformed HTTP header");
1359
+ }
1360
+ }else if( zToken && strlen(zToken)==0 && zCmd ){
1361
+ /* transport_flip request and continued transport_open */
1362
+ cgi_handle_ssh_transport(zCmd);
1363
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1364
+ malformed_request("missing HTTP header");
1365
+ }
1366
+ cgi_trace(zLine);
1367
+ zToken = extract_token(zLine, &z);
1368
+ if( zToken==0 ){
1369
+ malformed_request("malformed HTTP header");
1370
+ }
1371
+ }
1372
+
1373
+ if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
1374
+ && fossil_strcmp(zToken,"HEAD")!=0 ){
1375
+ malformed_request("unsupported HTTP method");
1376
+ }
1377
+
1378
+ if( nCycles==0 ){
1379
+ cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
1380
+ cgi_setenv("REQUEST_METHOD",zToken);
1381
+ }
1382
+
1383
+ zToken = extract_token(z, &z);
1384
+ if( zToken==0 ){
1385
+ malformed_request("malformed URL in HTTP header");
1386
+ }
1387
+ if( nCycles==0 ){
1388
+ cgi_setenv("REQUEST_URI", zToken);
1389
+ cgi_setenv("SCRIPT_NAME", "");
1390
+ }
1391
+
1392
+ for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1393
+ if( zToken[i] ) zToken[i++] = 0;
1394
+ if( nCycles==0 ){
1395
+ cgi_setenv("PATH_INFO", zToken);
1396
+ }else{
1397
+ cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
1398
+ }
1399
+
1400
+ /* Get all the optional fields that follow the first line.
1401
+ */
1402
+ while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1403
+ char *zFieldName;
1404
+ char *zVal;
1405
+
1406
+ cgi_trace(zLine);
1407
+ zFieldName = extract_token(zLine,&zVal);
1408
+ if( zFieldName==0 || *zFieldName==0 ) break;
1409
+ while( fossil_isspace(*zVal) ){ zVal++; }
1410
+ i = strlen(zVal);
1411
+ while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; }
1412
+ zVal[i] = 0;
1413
+ for(i=0; zFieldName[i]; i++){
1414
+ zFieldName[i] = fossil_tolower(zFieldName[i]);
1415
+ }
1416
+ if( fossil_strcmp(zFieldName,"content-length:")==0 ){
1417
+ content_length = atoi(zVal);
1418
+ }else if( fossil_strcmp(zFieldName,"content-type:")==0 ){
1419
+ g.zContentType = zType = mprintf("%s", zVal);
1420
+ }else if( fossil_strcmp(zFieldName,"host:")==0 ){
1421
+ if( nCycles==0 ){
1422
+ cgi_setenv("HTTP_HOST", zVal);
1423
+ }
1424
+ }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1425
+ if( nCycles==0 ){
1426
+ cgi_setenv("HTTP_USER_AGENT", zVal);
1427
+ }
1428
+ }else if( fossil_strcmp(zFieldName,"x-fossil-transport:")==0 ){
1429
+ if( fossil_strnicmp(zVal, "ssh", 3)==0 ){
1430
+ if( nCycles==0 ){
1431
+ g.fSshClient |= CGI_SSH_FOSSIL;
1432
+ g.fullHttpReply = 0;
1433
+ }
1434
+ }
1435
+ }
1436
+ }
1437
+
1438
+ if( nCycles==0 ){
1439
+ if( ! ( g.fSshClient & CGI_SSH_FOSSIL ) ){
1440
+ /* did not find new fossil ssh transport */
1441
+ g.fSshClient &= ~CGI_SSH_CLIENT;
1442
+ g.fullHttpReply = 1;
1443
+ cgi_replace_parameter("REMOTE_ADDR", "127.0.0.1");
1444
+ }
1445
+ }
1446
+
1447
+ cgi_reset_content();
1448
+ cgi_destination(CGI_BODY);
1449
+
1450
+ if( content_length>0 && zType ){
1451
+ blob_zero(&g.cgiIn);
1452
+ if( fossil_strcmp(zType, "application/x-fossil")==0 ){
1453
+ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1454
+ blob_uncompress(&g.cgiIn, &g.cgiIn);
1455
+ }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
1456
+ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1457
+ }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
1458
+ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1459
+ }
1460
+ }
1461
+ cgi_trace(0);
1462
+ nCycles++;
1463
+}
1464
+
1465
+/*
1466
+** This routine handles the old fossil SSH probes
1467
+*/
1468
+char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
1469
+ /* Start looking for probes */
1470
+ while( fossil_strcmp(zToken, "echo")==0 ){
1471
+ zToken = extract_token(z, &z);
1472
+ if( zToken==0 ){
1473
+ malformed_request("malformed probe");
1474
+ }
1475
+ if( fossil_strncmp(zToken, "test", 4)==0 ||
1476
+ fossil_strncmp(zToken, "probe-", 6)==0 ){
1477
+ fprintf(g.httpOut, "%s\n", zToken);
1478
+ fflush(g.httpOut);
1479
+ }else{
1480
+ malformed_request("malformed probe");
1481
+ }
1482
+ if( fgets(zLine, zSize, g.httpIn)==0 ){
1483
+ malformed_request("malformed probe");
1484
+ }
1485
+ cgi_trace(zLine);
1486
+ zToken = extract_token(zLine, &z);
1487
+ if( zToken==0 ){
1488
+ malformed_request("malformed probe");
1489
+ }
1490
+ }
1491
+
1492
+ /* Got all probes now first transport_open is completed
1493
+ ** so return the command that was requested
1494
+ */
1495
+ g.fSshClient |= CGI_SSH_COMPAT;
1496
+ return mprintf("%s", zToken);
1497
+}
1498
+
1499
+/*
1500
+** This routine handles the old fossil SSH transport_flip
1501
+** and transport_open communications if detected.
1502
+*/
1503
+void cgi_handle_ssh_transport(const char *zCmd){
1504
+ char *z, *zToken;
1505
+ char zLine[2000]; /* A single line of input. */
1506
+
1507
+ /* look for second newline of transport_flip */
1508
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1509
+ malformed_request("incorrect transport_flip");
1510
+ }
1511
+ cgi_trace(zLine);
1512
+ zToken = extract_token(zLine, &z);
1513
+ if( zToken && strlen(zToken)==0 ){
1514
+ /* look for path to fossil */
1515
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1516
+ if ( zCmd==0 ){
1517
+ malformed_request("missing fossil command");
1518
+ }else{
1519
+ /* no new command so exit */
1520
+ fossil_exit(0);
1521
+ }
1522
+ }
1523
+ cgi_trace(zLine);
1524
+ zToken = extract_token(zLine, &z);
1525
+ if( zToken==0 ){
1526
+ malformed_request("malformed fossil command");
1527
+ }
1528
+ /* see if we've seen the command */
1529
+ if( zCmd && zCmd[0] && fossil_strcmp(zToken, zCmd)==0 ){
1530
+ return;
1531
+ }else{
1532
+ malformed_request("transport_open failed");
1533
+ }
1534
+ }else{
1535
+ malformed_request("transport_flip failed");
1536
+ }
1537
+}
13071538
13081539
/*
13091540
** This routine handles a single SCGI request which is coming in on
13101541
** g.httpIn and which replies on g.httpOut
13111542
**
@@ -1600,5 +1831,23 @@
16001831
cgi_set_status(304,"Not Modified");
16011832
cgi_reset_content();
16021833
cgi_reply();
16031834
fossil_exit(0);
16041835
}
1836
+
1837
+/*
1838
+** Check to see if the remote client is SSH and return
1839
+** its IP or return default
1840
+*/
1841
+const char *cgi_ssh_remote_addr(const char *zDefault){
1842
+ char *zIndex;
1843
+ const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1844
+
1845
+ if( zSshConn && zSshConn[0] ){
1846
+ char *zSshClient = mprintf("%s",zSshConn);
1847
+ if( (zIndex = strchr(zSshClient,' '))!=0 ){
1848
+ zSshClient[zIndex-zSshClient] = '\0';
1849
+ return zSshClient;
1850
+ }
1851
+ }
1852
+ return zDefault;
1853
+}
16051854
--- src/cgi.c
+++ src/cgi.c
@@ -60,10 +60,17 @@
60 ** Destinations for output text.
61 */
62 #define CGI_HEADER 0
63 #define CGI_BODY 1
64
 
 
 
 
 
 
 
65 #endif /* INTERFACE */
66
67 /*
68 ** The HTTP reply is generated in two pieces: the header and the body.
69 ** These pieces are generated separately because they are not necessary
@@ -1302,10 +1309,234 @@
1302 }
1303 }
1304 cgi_init();
1305 cgi_trace(0);
1306 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1307
1308 /*
1309 ** This routine handles a single SCGI request which is coming in on
1310 ** g.httpIn and which replies on g.httpOut
1311 **
@@ -1600,5 +1831,23 @@
1600 cgi_set_status(304,"Not Modified");
1601 cgi_reset_content();
1602 cgi_reply();
1603 fossil_exit(0);
1604 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1605
--- src/cgi.c
+++ src/cgi.c
@@ -60,10 +60,17 @@
60 ** Destinations for output text.
61 */
62 #define CGI_HEADER 0
63 #define CGI_BODY 1
64
65 /*
66 ** Flags for SSH HTTP clients
67 */
68 #define CGI_SSH_CLIENT 0x0001 /* Client is SSH */
69 #define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */
70 #define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */
71
72 #endif /* INTERFACE */
73
74 /*
75 ** The HTTP reply is generated in two pieces: the header and the body.
76 ** These pieces are generated separately because they are not necessary
@@ -1302,10 +1309,234 @@
1309 }
1310 }
1311 cgi_init();
1312 cgi_trace(0);
1313 }
1314
1315 /*
1316 ** This routine handles a single HTTP request from an SSH client which is
1317 ** coming in on g.httpIn and which replies on g.httpOut
1318 **
1319 ** Once all the setup is finished, this procedure returns
1320 ** and subsequent code handles the actual generation of the webpage.
1321 **
1322 ** It is called in a loop so some variables will need to be replaced
1323 */
1324 void cgi_handle_ssh_http_request(const char *zIpAddr){
1325 static int nCycles = 0;
1326 static char *zCmd = 0;
1327 char *z, *zToken;
1328 const char *zType;
1329 int i, content_length;
1330 char zLine[2000]; /* A single line of input. */
1331
1332 if( zIpAddr ){
1333 if( nCycles==0 ){
1334 cgi_setenv("REMOTE_ADDR", zIpAddr);
1335 g.zIpAddr = mprintf("%s", zIpAddr);
1336 }
1337 }else{
1338 fossil_panic("missing SSH IP address");
1339 }
1340 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1341 malformed_request("missing HTTP header");
1342 }
1343 cgi_trace(zLine);
1344 zToken = extract_token(zLine, &z);
1345 if( zToken==0 ){
1346 malformed_request("malformed HTTP header");
1347 }
1348
1349 if( fossil_strcmp(zToken, "echo")==0 ){
1350 /* start looking for probes to complete transport_open */
1351 zCmd = cgi_handle_ssh_probes(zLine, sizeof(zLine), z, zToken);
1352 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1353 malformed_request("missing HTTP header");
1354 }
1355 cgi_trace(zLine);
1356 zToken = extract_token(zLine, &z);
1357 if( zToken==0 ){
1358 malformed_request("malformed HTTP header");
1359 }
1360 }else if( zToken && strlen(zToken)==0 && zCmd ){
1361 /* transport_flip request and continued transport_open */
1362 cgi_handle_ssh_transport(zCmd);
1363 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1364 malformed_request("missing HTTP header");
1365 }
1366 cgi_trace(zLine);
1367 zToken = extract_token(zLine, &z);
1368 if( zToken==0 ){
1369 malformed_request("malformed HTTP header");
1370 }
1371 }
1372
1373 if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
1374 && fossil_strcmp(zToken,"HEAD")!=0 ){
1375 malformed_request("unsupported HTTP method");
1376 }
1377
1378 if( nCycles==0 ){
1379 cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
1380 cgi_setenv("REQUEST_METHOD",zToken);
1381 }
1382
1383 zToken = extract_token(z, &z);
1384 if( zToken==0 ){
1385 malformed_request("malformed URL in HTTP header");
1386 }
1387 if( nCycles==0 ){
1388 cgi_setenv("REQUEST_URI", zToken);
1389 cgi_setenv("SCRIPT_NAME", "");
1390 }
1391
1392 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1393 if( zToken[i] ) zToken[i++] = 0;
1394 if( nCycles==0 ){
1395 cgi_setenv("PATH_INFO", zToken);
1396 }else{
1397 cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
1398 }
1399
1400 /* Get all the optional fields that follow the first line.
1401 */
1402 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1403 char *zFieldName;
1404 char *zVal;
1405
1406 cgi_trace(zLine);
1407 zFieldName = extract_token(zLine,&zVal);
1408 if( zFieldName==0 || *zFieldName==0 ) break;
1409 while( fossil_isspace(*zVal) ){ zVal++; }
1410 i = strlen(zVal);
1411 while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; }
1412 zVal[i] = 0;
1413 for(i=0; zFieldName[i]; i++){
1414 zFieldName[i] = fossil_tolower(zFieldName[i]);
1415 }
1416 if( fossil_strcmp(zFieldName,"content-length:")==0 ){
1417 content_length = atoi(zVal);
1418 }else if( fossil_strcmp(zFieldName,"content-type:")==0 ){
1419 g.zContentType = zType = mprintf("%s", zVal);
1420 }else if( fossil_strcmp(zFieldName,"host:")==0 ){
1421 if( nCycles==0 ){
1422 cgi_setenv("HTTP_HOST", zVal);
1423 }
1424 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1425 if( nCycles==0 ){
1426 cgi_setenv("HTTP_USER_AGENT", zVal);
1427 }
1428 }else if( fossil_strcmp(zFieldName,"x-fossil-transport:")==0 ){
1429 if( fossil_strnicmp(zVal, "ssh", 3)==0 ){
1430 if( nCycles==0 ){
1431 g.fSshClient |= CGI_SSH_FOSSIL;
1432 g.fullHttpReply = 0;
1433 }
1434 }
1435 }
1436 }
1437
1438 if( nCycles==0 ){
1439 if( ! ( g.fSshClient & CGI_SSH_FOSSIL ) ){
1440 /* did not find new fossil ssh transport */
1441 g.fSshClient &= ~CGI_SSH_CLIENT;
1442 g.fullHttpReply = 1;
1443 cgi_replace_parameter("REMOTE_ADDR", "127.0.0.1");
1444 }
1445 }
1446
1447 cgi_reset_content();
1448 cgi_destination(CGI_BODY);
1449
1450 if( content_length>0 && zType ){
1451 blob_zero(&g.cgiIn);
1452 if( fossil_strcmp(zType, "application/x-fossil")==0 ){
1453 blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1454 blob_uncompress(&g.cgiIn, &g.cgiIn);
1455 }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
1456 blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1457 }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
1458 blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1459 }
1460 }
1461 cgi_trace(0);
1462 nCycles++;
1463 }
1464
1465 /*
1466 ** This routine handles the old fossil SSH probes
1467 */
1468 char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
1469 /* Start looking for probes */
1470 while( fossil_strcmp(zToken, "echo")==0 ){
1471 zToken = extract_token(z, &z);
1472 if( zToken==0 ){
1473 malformed_request("malformed probe");
1474 }
1475 if( fossil_strncmp(zToken, "test", 4)==0 ||
1476 fossil_strncmp(zToken, "probe-", 6)==0 ){
1477 fprintf(g.httpOut, "%s\n", zToken);
1478 fflush(g.httpOut);
1479 }else{
1480 malformed_request("malformed probe");
1481 }
1482 if( fgets(zLine, zSize, g.httpIn)==0 ){
1483 malformed_request("malformed probe");
1484 }
1485 cgi_trace(zLine);
1486 zToken = extract_token(zLine, &z);
1487 if( zToken==0 ){
1488 malformed_request("malformed probe");
1489 }
1490 }
1491
1492 /* Got all probes now first transport_open is completed
1493 ** so return the command that was requested
1494 */
1495 g.fSshClient |= CGI_SSH_COMPAT;
1496 return mprintf("%s", zToken);
1497 }
1498
1499 /*
1500 ** This routine handles the old fossil SSH transport_flip
1501 ** and transport_open communications if detected.
1502 */
1503 void cgi_handle_ssh_transport(const char *zCmd){
1504 char *z, *zToken;
1505 char zLine[2000]; /* A single line of input. */
1506
1507 /* look for second newline of transport_flip */
1508 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1509 malformed_request("incorrect transport_flip");
1510 }
1511 cgi_trace(zLine);
1512 zToken = extract_token(zLine, &z);
1513 if( zToken && strlen(zToken)==0 ){
1514 /* look for path to fossil */
1515 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1516 if ( zCmd==0 ){
1517 malformed_request("missing fossil command");
1518 }else{
1519 /* no new command so exit */
1520 fossil_exit(0);
1521 }
1522 }
1523 cgi_trace(zLine);
1524 zToken = extract_token(zLine, &z);
1525 if( zToken==0 ){
1526 malformed_request("malformed fossil command");
1527 }
1528 /* see if we've seen the command */
1529 if( zCmd && zCmd[0] && fossil_strcmp(zToken, zCmd)==0 ){
1530 return;
1531 }else{
1532 malformed_request("transport_open failed");
1533 }
1534 }else{
1535 malformed_request("transport_flip failed");
1536 }
1537 }
1538
1539 /*
1540 ** This routine handles a single SCGI request which is coming in on
1541 ** g.httpIn and which replies on g.httpOut
1542 **
@@ -1600,5 +1831,23 @@
1831 cgi_set_status(304,"Not Modified");
1832 cgi_reset_content();
1833 cgi_reply();
1834 fossil_exit(0);
1835 }
1836
1837 /*
1838 ** Check to see if the remote client is SSH and return
1839 ** its IP or return default
1840 */
1841 const char *cgi_ssh_remote_addr(const char *zDefault){
1842 char *zIndex;
1843 const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1844
1845 if( zSshConn && zSshConn[0] ){
1846 char *zSshClient = mprintf("%s",zSshConn);
1847 if( (zIndex = strchr(zSshClient,' '))!=0 ){
1848 zSshClient[zIndex-zSshClient] = '\0';
1849 return zSshClient;
1850 }
1851 }
1852 return zDefault;
1853 }
1854
+27 -19
--- src/checkin.c
+++ src/checkin.c
@@ -990,11 +990,17 @@
990990
const char *zColor; /* Modified value of p->zColor */
991991
992992
assert( pBaseline==0 || pBaseline->zBaseline==0 );
993993
assert( pBaseline==0 || zBaselineUuid!=0 );
994994
blob_zero(pOut);
995
- zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
995
+ zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
996
+ "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
997
+ vid, vid);
998
+ if( !zParentUuid ){
999
+ fossil_fatal("Could not find a valid check-in for RID %d. "
1000
+ "Possible checkout/repo mismatch.", vid);
1001
+ }
9961002
if( pBaseline ){
9971003
blob_appendf(pOut, "B %s\n", zBaselineUuid);
9981004
manifest_file_rewind(pBaseline);
9991005
pFile = manifest_file_next(pBaseline, 0);
10001006
nFBcard++;
@@ -1085,28 +1091,30 @@
10851091
nFBcard++;
10861092
}
10871093
if( p->zMimetype && p->zMimetype[0] ){
10881094
blob_appendf(pOut, "N %F\n", p->zMimetype);
10891095
}
1090
- blob_appendf(pOut, "P %s", zParentUuid);
1091
- if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1092
- free(zParentUuid);
1093
- db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1094
- while( db_step(&q)==SQLITE_ROW ){
1095
- char *zMergeUuid;
1096
- int mid = db_column_int(&q, 0);
1097
- if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1098
- zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1099
- if( zMergeUuid ){
1100
- blob_appendf(pOut, " %s", zMergeUuid);
1101
- if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1102
- free(zMergeUuid);
1103
- }
1104
- }
1105
- db_finalize(&q);
1106
- free(zDate);
1107
- blob_appendf(pOut, "\n");
1096
+ if( zParentUuid ){
1097
+ blob_appendf(pOut, "P %s", zParentUuid);
1098
+ if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1099
+ free(zParentUuid);
1100
+ db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1101
+ while( db_step(&q)==SQLITE_ROW ){
1102
+ char *zMergeUuid;
1103
+ int mid = db_column_int(&q, 0);
1104
+ if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1105
+ zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1106
+ if( zMergeUuid ){
1107
+ blob_appendf(pOut, " %s", zMergeUuid);
1108
+ if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1109
+ free(zMergeUuid);
1110
+ }
1111
+ }
1112
+ db_finalize(&q);
1113
+ blob_appendf(pOut, "\n");
1114
+ }
1115
+ free(zDate);
11081116
11091117
db_prepare(&q,
11101118
"SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
11111119
" FROM vmerge, blob"
11121120
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
11131121
--- src/checkin.c
+++ src/checkin.c
@@ -990,11 +990,17 @@
990 const char *zColor; /* Modified value of p->zColor */
991
992 assert( pBaseline==0 || pBaseline->zBaseline==0 );
993 assert( pBaseline==0 || zBaselineUuid!=0 );
994 blob_zero(pOut);
995 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
 
 
 
 
 
 
996 if( pBaseline ){
997 blob_appendf(pOut, "B %s\n", zBaselineUuid);
998 manifest_file_rewind(pBaseline);
999 pFile = manifest_file_next(pBaseline, 0);
1000 nFBcard++;
@@ -1085,28 +1091,30 @@
1085 nFBcard++;
1086 }
1087 if( p->zMimetype && p->zMimetype[0] ){
1088 blob_appendf(pOut, "N %F\n", p->zMimetype);
1089 }
1090 blob_appendf(pOut, "P %s", zParentUuid);
1091 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1092 free(zParentUuid);
1093 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1094 while( db_step(&q)==SQLITE_ROW ){
1095 char *zMergeUuid;
1096 int mid = db_column_int(&q, 0);
1097 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1098 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1099 if( zMergeUuid ){
1100 blob_appendf(pOut, " %s", zMergeUuid);
1101 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1102 free(zMergeUuid);
1103 }
1104 }
1105 db_finalize(&q);
1106 free(zDate);
1107 blob_appendf(pOut, "\n");
 
 
1108
1109 db_prepare(&q,
1110 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1111 " FROM vmerge, blob"
1112 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1113
--- src/checkin.c
+++ src/checkin.c
@@ -990,11 +990,17 @@
990 const char *zColor; /* Modified value of p->zColor */
991
992 assert( pBaseline==0 || pBaseline->zBaseline==0 );
993 assert( pBaseline==0 || zBaselineUuid!=0 );
994 blob_zero(pOut);
995 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
996 "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
997 vid, vid);
998 if( !zParentUuid ){
999 fossil_fatal("Could not find a valid check-in for RID %d. "
1000 "Possible checkout/repo mismatch.", vid);
1001 }
1002 if( pBaseline ){
1003 blob_appendf(pOut, "B %s\n", zBaselineUuid);
1004 manifest_file_rewind(pBaseline);
1005 pFile = manifest_file_next(pBaseline, 0);
1006 nFBcard++;
@@ -1085,28 +1091,30 @@
1091 nFBcard++;
1092 }
1093 if( p->zMimetype && p->zMimetype[0] ){
1094 blob_appendf(pOut, "N %F\n", p->zMimetype);
1095 }
1096 if( zParentUuid ){
1097 blob_appendf(pOut, "P %s", zParentUuid);
1098 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1099 free(zParentUuid);
1100 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1101 while( db_step(&q)==SQLITE_ROW ){
1102 char *zMergeUuid;
1103 int mid = db_column_int(&q, 0);
1104 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1105 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1106 if( zMergeUuid ){
1107 blob_appendf(pOut, " %s", zMergeUuid);
1108 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1109 free(zMergeUuid);
1110 }
1111 }
1112 db_finalize(&q);
1113 blob_appendf(pOut, "\n");
1114 }
1115 free(zDate);
1116
1117 db_prepare(&q,
1118 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1119 " FROM vmerge, blob"
1120 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1121
+27 -19
--- src/checkin.c
+++ src/checkin.c
@@ -990,11 +990,17 @@
990990
const char *zColor; /* Modified value of p->zColor */
991991
992992
assert( pBaseline==0 || pBaseline->zBaseline==0 );
993993
assert( pBaseline==0 || zBaselineUuid!=0 );
994994
blob_zero(pOut);
995
- zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
995
+ zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
996
+ "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
997
+ vid, vid);
998
+ if( !zParentUuid ){
999
+ fossil_fatal("Could not find a valid check-in for RID %d. "
1000
+ "Possible checkout/repo mismatch.", vid);
1001
+ }
9961002
if( pBaseline ){
9971003
blob_appendf(pOut, "B %s\n", zBaselineUuid);
9981004
manifest_file_rewind(pBaseline);
9991005
pFile = manifest_file_next(pBaseline, 0);
10001006
nFBcard++;
@@ -1085,28 +1091,30 @@
10851091
nFBcard++;
10861092
}
10871093
if( p->zMimetype && p->zMimetype[0] ){
10881094
blob_appendf(pOut, "N %F\n", p->zMimetype);
10891095
}
1090
- blob_appendf(pOut, "P %s", zParentUuid);
1091
- if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1092
- free(zParentUuid);
1093
- db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1094
- while( db_step(&q)==SQLITE_ROW ){
1095
- char *zMergeUuid;
1096
- int mid = db_column_int(&q, 0);
1097
- if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1098
- zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1099
- if( zMergeUuid ){
1100
- blob_appendf(pOut, " %s", zMergeUuid);
1101
- if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1102
- free(zMergeUuid);
1103
- }
1104
- }
1105
- db_finalize(&q);
1106
- free(zDate);
1107
- blob_appendf(pOut, "\n");
1096
+ if( zParentUuid ){
1097
+ blob_appendf(pOut, "P %s", zParentUuid);
1098
+ if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1099
+ free(zParentUuid);
1100
+ db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1101
+ while( db_step(&q)==SQLITE_ROW ){
1102
+ char *zMergeUuid;
1103
+ int mid = db_column_int(&q, 0);
1104
+ if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1105
+ zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1106
+ if( zMergeUuid ){
1107
+ blob_appendf(pOut, " %s", zMergeUuid);
1108
+ if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1109
+ free(zMergeUuid);
1110
+ }
1111
+ }
1112
+ db_finalize(&q);
1113
+ blob_appendf(pOut, "\n");
1114
+ }
1115
+ free(zDate);
11081116
11091117
db_prepare(&q,
11101118
"SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
11111119
" FROM vmerge, blob"
11121120
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
11131121
--- src/checkin.c
+++ src/checkin.c
@@ -990,11 +990,17 @@
990 const char *zColor; /* Modified value of p->zColor */
991
992 assert( pBaseline==0 || pBaseline->zBaseline==0 );
993 assert( pBaseline==0 || zBaselineUuid!=0 );
994 blob_zero(pOut);
995 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
 
 
 
 
 
 
996 if( pBaseline ){
997 blob_appendf(pOut, "B %s\n", zBaselineUuid);
998 manifest_file_rewind(pBaseline);
999 pFile = manifest_file_next(pBaseline, 0);
1000 nFBcard++;
@@ -1085,28 +1091,30 @@
1085 nFBcard++;
1086 }
1087 if( p->zMimetype && p->zMimetype[0] ){
1088 blob_appendf(pOut, "N %F\n", p->zMimetype);
1089 }
1090 blob_appendf(pOut, "P %s", zParentUuid);
1091 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1092 free(zParentUuid);
1093 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1094 while( db_step(&q)==SQLITE_ROW ){
1095 char *zMergeUuid;
1096 int mid = db_column_int(&q, 0);
1097 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1098 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1099 if( zMergeUuid ){
1100 blob_appendf(pOut, " %s", zMergeUuid);
1101 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1102 free(zMergeUuid);
1103 }
1104 }
1105 db_finalize(&q);
1106 free(zDate);
1107 blob_appendf(pOut, "\n");
 
 
1108
1109 db_prepare(&q,
1110 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1111 " FROM vmerge, blob"
1112 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1113
--- src/checkin.c
+++ src/checkin.c
@@ -990,11 +990,17 @@
990 const char *zColor; /* Modified value of p->zColor */
991
992 assert( pBaseline==0 || pBaseline->zBaseline==0 );
993 assert( pBaseline==0 || zBaselineUuid!=0 );
994 blob_zero(pOut);
995 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
996 "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
997 vid, vid);
998 if( !zParentUuid ){
999 fossil_fatal("Could not find a valid check-in for RID %d. "
1000 "Possible checkout/repo mismatch.", vid);
1001 }
1002 if( pBaseline ){
1003 blob_appendf(pOut, "B %s\n", zBaselineUuid);
1004 manifest_file_rewind(pBaseline);
1005 pFile = manifest_file_next(pBaseline, 0);
1006 nFBcard++;
@@ -1085,28 +1091,30 @@
1091 nFBcard++;
1092 }
1093 if( p->zMimetype && p->zMimetype[0] ){
1094 blob_appendf(pOut, "N %F\n", p->zMimetype);
1095 }
1096 if( zParentUuid ){
1097 blob_appendf(pOut, "P %s", zParentUuid);
1098 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1099 free(zParentUuid);
1100 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1101 while( db_step(&q)==SQLITE_ROW ){
1102 char *zMergeUuid;
1103 int mid = db_column_int(&q, 0);
1104 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1105 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1106 if( zMergeUuid ){
1107 blob_appendf(pOut, " %s", zMergeUuid);
1108 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1109 free(zMergeUuid);
1110 }
1111 }
1112 db_finalize(&q);
1113 blob_appendf(pOut, "\n");
1114 }
1115 free(zDate);
1116
1117 db_prepare(&q,
1118 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1119 " FROM vmerge, blob"
1120 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
1121
+25
--- src/clone.c
+++ src/clone.c
@@ -107,10 +107,11 @@
107107
**
108108
** Options:
109109
** --admin-user|-A USERNAME Make USERNAME the administrator
110110
** --private Also clone private branches
111111
** --ssl-identity=filename Use the SSL identity if requested by the server
112
+** --ssh-command|-c 'command' Use this SSH command
112113
**
113114
** See also: init
114115
*/
115116
void clone_cmd(void){
116117
char *zPassword;
@@ -117,10 +118,11 @@
117118
const char *zDefaultUser; /* Optional name of the default user */
118119
int nErr = 0;
119120
int bPrivate = 0; /* Also clone private branches */
120121
121122
if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
123
+ clone_ssh_find_options();
122124
url_proxy_options();
123125
if( g.argc < 4 ){
124126
usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
125127
}
126128
db_open_config(0);
@@ -167,10 +169,11 @@
167169
db_multi_exec(
168170
"REPLACE INTO config(name,value,mtime)"
169171
" VALUES('server-code', lower(hex(randomblob(20))), now());"
170172
);
171173
url_enable_proxy(0);
174
+ clone_ssh_db_set_options();
172175
url_get_password_if_needed();
173176
g.xlinkClusterOnly = 1;
174177
nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
175178
g.xlinkClusterOnly = 0;
176179
verify_cancel();
@@ -188,5 +191,27 @@
188191
fossil_print("project-id: %s\n", db_get("project-code", 0));
189192
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
190193
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
191194
db_end_transaction(0);
192195
}
196
+
197
+/*
198
+** Look for SSH clone command line options and setup in globals.
199
+*/
200
+void clone_ssh_find_options(void){
201
+ const char *zSshCmd; /* SSH command string */
202
+
203
+ zSshCmd = find_option("ssh-command","c",1);
204
+ if( zSshCmd && zSshCmd[0] ){
205
+ g.zSshCmd = mprintf("%s", zSshCmd);
206
+ }
207
+}
208
+
209
+/*
210
+** Set SSH options discovered in global variables (set from command line
211
+** options).
212
+*/
213
+void clone_ssh_db_set_options(void){
214
+ if( g.zSshCmd && g.zSshCmd[0] ){
215
+ db_set("ssh-command", g.zSshCmd, 0);
216
+ }
217
+}
193218
--- src/clone.c
+++ src/clone.c
@@ -107,10 +107,11 @@
107 **
108 ** Options:
109 ** --admin-user|-A USERNAME Make USERNAME the administrator
110 ** --private Also clone private branches
111 ** --ssl-identity=filename Use the SSL identity if requested by the server
 
112 **
113 ** See also: init
114 */
115 void clone_cmd(void){
116 char *zPassword;
@@ -117,10 +118,11 @@
117 const char *zDefaultUser; /* Optional name of the default user */
118 int nErr = 0;
119 int bPrivate = 0; /* Also clone private branches */
120
121 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
 
122 url_proxy_options();
123 if( g.argc < 4 ){
124 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
125 }
126 db_open_config(0);
@@ -167,10 +169,11 @@
167 db_multi_exec(
168 "REPLACE INTO config(name,value,mtime)"
169 " VALUES('server-code', lower(hex(randomblob(20))), now());"
170 );
171 url_enable_proxy(0);
 
172 url_get_password_if_needed();
173 g.xlinkClusterOnly = 1;
174 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
175 g.xlinkClusterOnly = 0;
176 verify_cancel();
@@ -188,5 +191,27 @@
188 fossil_print("project-id: %s\n", db_get("project-code", 0));
189 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
190 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
191 db_end_transaction(0);
192 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
--- src/clone.c
+++ src/clone.c
@@ -107,10 +107,11 @@
107 **
108 ** Options:
109 ** --admin-user|-A USERNAME Make USERNAME the administrator
110 ** --private Also clone private branches
111 ** --ssl-identity=filename Use the SSL identity if requested by the server
112 ** --ssh-command|-c 'command' Use this SSH command
113 **
114 ** See also: init
115 */
116 void clone_cmd(void){
117 char *zPassword;
@@ -117,10 +118,11 @@
118 const char *zDefaultUser; /* Optional name of the default user */
119 int nErr = 0;
120 int bPrivate = 0; /* Also clone private branches */
121
122 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
123 clone_ssh_find_options();
124 url_proxy_options();
125 if( g.argc < 4 ){
126 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
127 }
128 db_open_config(0);
@@ -167,10 +169,11 @@
169 db_multi_exec(
170 "REPLACE INTO config(name,value,mtime)"
171 " VALUES('server-code', lower(hex(randomblob(20))), now());"
172 );
173 url_enable_proxy(0);
174 clone_ssh_db_set_options();
175 url_get_password_if_needed();
176 g.xlinkClusterOnly = 1;
177 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
178 g.xlinkClusterOnly = 0;
179 verify_cancel();
@@ -188,5 +191,27 @@
191 fossil_print("project-id: %s\n", db_get("project-code", 0));
192 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
193 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
194 db_end_transaction(0);
195 }
196
197 /*
198 ** Look for SSH clone command line options and setup in globals.
199 */
200 void clone_ssh_find_options(void){
201 const char *zSshCmd; /* SSH command string */
202
203 zSshCmd = find_option("ssh-command","c",1);
204 if( zSshCmd && zSshCmd[0] ){
205 g.zSshCmd = mprintf("%s", zSshCmd);
206 }
207 }
208
209 /*
210 ** Set SSH options discovered in global variables (set from command line
211 ** options).
212 */
213 void clone_ssh_db_set_options(void){
214 if( g.zSshCmd && g.zSshCmd[0] ){
215 db_set("ssh-command", g.zSshCmd, 0);
216 }
217 }
218
--- src/config.h
+++ src/config.h
@@ -24,10 +24,15 @@
2424
#define _LARGE_FILE 1
2525
#ifndef _FILE_OFFSET_BITS
2626
# define _FILE_OFFSET_BITS 64
2727
#endif
2828
#define _LARGEFILE_SOURCE 1
29
+
30
+/* Make sure that in 64-bit builds, _USE_32BIT_TIME_T is NEVER defined. */
31
+#ifdef _WIN64
32
+# undef _USE_32BIT_TIME_T
33
+#endif
2934
3035
#ifdef HAVE_AUTOCONFIG_H
3136
#include "autoconfig.h"
3237
#endif
3338
3439
--- src/config.h
+++ src/config.h
@@ -24,10 +24,15 @@
24 #define _LARGE_FILE 1
25 #ifndef _FILE_OFFSET_BITS
26 # define _FILE_OFFSET_BITS 64
27 #endif
28 #define _LARGEFILE_SOURCE 1
 
 
 
 
 
29
30 #ifdef HAVE_AUTOCONFIG_H
31 #include "autoconfig.h"
32 #endif
33
34
--- src/config.h
+++ src/config.h
@@ -24,10 +24,15 @@
24 #define _LARGE_FILE 1
25 #ifndef _FILE_OFFSET_BITS
26 # define _FILE_OFFSET_BITS 64
27 #endif
28 #define _LARGEFILE_SOURCE 1
29
30 /* Make sure that in 64-bit builds, _USE_32BIT_TIME_T is NEVER defined. */
31 #ifdef _WIN64
32 # undef _USE_32BIT_TIME_T
33 #endif
34
35 #ifdef HAVE_AUTOCONFIG_H
36 #include "autoconfig.h"
37 #endif
38
39
--- src/configure.c
+++ src/configure.c
@@ -98,10 +98,11 @@
9898
{ "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
9999
{ "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
100100
#endif
101101
102102
{ "project-name", CONFIGSET_PROJ },
103
+ { "short-project-name", CONFIGSET_PROJ },
103104
{ "project-description", CONFIGSET_PROJ },
104105
{ "manifest", CONFIGSET_PROJ },
105106
{ "binary-glob", CONFIGSET_PROJ },
106107
{ "clean-glob", CONFIGSET_PROJ },
107108
{ "ignore-glob", CONFIGSET_PROJ },
108109
--- src/configure.c
+++ src/configure.c
@@ -98,10 +98,11 @@
98 { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
99 { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
100 #endif
101
102 { "project-name", CONFIGSET_PROJ },
 
103 { "project-description", CONFIGSET_PROJ },
104 { "manifest", CONFIGSET_PROJ },
105 { "binary-glob", CONFIGSET_PROJ },
106 { "clean-glob", CONFIGSET_PROJ },
107 { "ignore-glob", CONFIGSET_PROJ },
108
--- src/configure.c
+++ src/configure.c
@@ -98,10 +98,11 @@
98 { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
99 { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
100 #endif
101
102 { "project-name", CONFIGSET_PROJ },
103 { "short-project-name", CONFIGSET_PROJ },
104 { "project-description", CONFIGSET_PROJ },
105 { "manifest", CONFIGSET_PROJ },
106 { "binary-glob", CONFIGSET_PROJ },
107 { "clean-glob", CONFIGSET_PROJ },
108 { "ignore-glob", CONFIGSET_PROJ },
109
+27 -11
--- src/diff.c
+++ src/diff.c
@@ -1939,10 +1939,11 @@
19391939
struct AnnVers {
19401940
const char *zFUuid; /* File being analyzed */
19411941
const char *zMUuid; /* Check-in containing the file */
19421942
const char *zDate; /* Date of the check-in */
19431943
const char *zBgColor; /* Suggested background color */
1944
+ const char *zUser; /* Name of user who did the check-in */
19441945
unsigned cnt; /* Number of lines contributed by this check-in */
19451946
} *aVers; /* For each check-in analyzed */
19461947
char **azVers; /* Names of versions analyzed */
19471948
};
19481949
@@ -2061,10 +2062,11 @@
20612062
db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
20622063
db_prepare(&q,
20632064
"SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
20642065
" (SELECT uuid FROM blob WHERE rid=mlink.mid),"
20652066
" date(event.mtime),"
2067
+ " coalesce(event.euser,event.user),"
20662068
" mlink.pid"
20672069
" FROM mlink, event"
20682070
" WHERE mlink.fid=:rid"
20692071
" AND event.objid=mlink.mid"
20702072
" AND mlink.pid NOT IN vseen"
@@ -2074,15 +2076,16 @@
20742076
);
20752077
20762078
db_bind_int(&q, ":rid", rid);
20772079
if( iLimit==0 ) iLimit = 1000000000;
20782080
while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
2079
- int prevId = db_column_int(&q, 3);
2081
+ int prevId = db_column_int(&q, 4);
20802082
p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
20812083
p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
20822084
p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
20832085
p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
2086
+ p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
20842087
if( p->nVers ){
20852088
content_get(rid, &step);
20862089
annotation_step(p, &step, p->nVers-1);
20872090
blob_reset(&step);
20882091
}
@@ -2268,15 +2271,18 @@
22682271
style_footer();
22692272
}
22702273
22712274
/*
22722275
** COMMAND: annotate
2276
+** COMMAND: blame
22732277
**
2274
-** %fossil annotate ?OPTIONS? FILENAME
2278
+** %fossil (annotate|blame) ?OPTIONS? FILENAME
22752279
**
22762280
** Output the text of a file with markings to show when each line of
2277
-** the file was last modified.
2281
+** the file was last modified. The "annotate" command shows line numbers
2282
+** and omits the username. The "blame" command shows the user who made each
2283
+** checkin and omits the line number.
22782284
**
22792285
** Options:
22802286
** --filevers Show file version numbers rather than check-in versions
22812287
** -l|--log List all versions analyzed
22822288
** -n|--limit N Only look backwards in time by N versions
@@ -2295,11 +2301,13 @@
22952301
const char *zLimit; /* The value to the -n|--limit option */
22962302
int iLimit; /* How far back in time to look */
22972303
int showLog; /* True to show the log */
22982304
int fileVers; /* Show file version instead of check-in versions */
22992305
int annFlags = 0; /* Flags to control annotation properties */
2306
+ int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
23002307
2308
+ bBlame = g.argv[1][0]=='b';
23012309
zLimit = find_option("limit","n",1);
23022310
if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
23032311
iLimit = atoi(zLimit);
23042312
showLog = find_option("log","l",0)!=0;
23052313
fileVers = find_option("filevers",0,0)!=0;
@@ -2342,18 +2350,26 @@
23422350
}
23432351
for(i=0; i<ann.nOrig; i++){
23442352
int iVers = ann.aOrig[i].iVers;
23452353
char *z = (char*)ann.aOrig[i].z;
23462354
int n = ann.aOrig[i].n;
2347
- char zPrefix[200];
2348
- z[n] = 0;
2355
+ struct AnnVers *p;
23492356
if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2350
- if( iVers>=0 ){
2351
- struct AnnVers *p = ann.aVers+iVers;
2352
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%.10s %s",
2353
- fileVers ? p->zFUuid : p->zMUuid, p->zDate);
2357
+ p = ann.aVers + iVers;
2358
+ if( bBlame ){
2359
+ if( iVers>=0 ){
2360
+ fossil_print("%.10s %s %13.13s: %.*s\n",
2361
+ fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
2362
+ }else{
2363
+ fossil_print("%35s %.*s\n", "", n, z);
2364
+ }
23542365
}else{
2355
- zPrefix[0] = 0;
2366
+ if( iVers>=0 ){
2367
+ fossil_print("%.10s %s %5d: %.*s\n",
2368
+ fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
2369
+ }else{
2370
+ fossil_print("%21s %5d: %.*s\n",
2371
+ "", i+1, n, z);
2372
+ }
23562373
}
2357
- fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z);
23582374
}
23592375
}
23602376
--- src/diff.c
+++ src/diff.c
@@ -1939,10 +1939,11 @@
1939 struct AnnVers {
1940 const char *zFUuid; /* File being analyzed */
1941 const char *zMUuid; /* Check-in containing the file */
1942 const char *zDate; /* Date of the check-in */
1943 const char *zBgColor; /* Suggested background color */
 
1944 unsigned cnt; /* Number of lines contributed by this check-in */
1945 } *aVers; /* For each check-in analyzed */
1946 char **azVers; /* Names of versions analyzed */
1947 };
1948
@@ -2061,10 +2062,11 @@
2061 db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
2062 db_prepare(&q,
2063 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
2064 " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
2065 " date(event.mtime),"
 
2066 " mlink.pid"
2067 " FROM mlink, event"
2068 " WHERE mlink.fid=:rid"
2069 " AND event.objid=mlink.mid"
2070 " AND mlink.pid NOT IN vseen"
@@ -2074,15 +2076,16 @@
2074 );
2075
2076 db_bind_int(&q, ":rid", rid);
2077 if( iLimit==0 ) iLimit = 1000000000;
2078 while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
2079 int prevId = db_column_int(&q, 3);
2080 p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
2081 p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
2082 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2083 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
 
2084 if( p->nVers ){
2085 content_get(rid, &step);
2086 annotation_step(p, &step, p->nVers-1);
2087 blob_reset(&step);
2088 }
@@ -2268,15 +2271,18 @@
2268 style_footer();
2269 }
2270
2271 /*
2272 ** COMMAND: annotate
 
2273 **
2274 ** %fossil annotate ?OPTIONS? FILENAME
2275 **
2276 ** Output the text of a file with markings to show when each line of
2277 ** the file was last modified.
 
 
2278 **
2279 ** Options:
2280 ** --filevers Show file version numbers rather than check-in versions
2281 ** -l|--log List all versions analyzed
2282 ** -n|--limit N Only look backwards in time by N versions
@@ -2295,11 +2301,13 @@
2295 const char *zLimit; /* The value to the -n|--limit option */
2296 int iLimit; /* How far back in time to look */
2297 int showLog; /* True to show the log */
2298 int fileVers; /* Show file version instead of check-in versions */
2299 int annFlags = 0; /* Flags to control annotation properties */
 
2300
 
2301 zLimit = find_option("limit","n",1);
2302 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
2303 iLimit = atoi(zLimit);
2304 showLog = find_option("log","l",0)!=0;
2305 fileVers = find_option("filevers",0,0)!=0;
@@ -2342,18 +2350,26 @@
2342 }
2343 for(i=0; i<ann.nOrig; i++){
2344 int iVers = ann.aOrig[i].iVers;
2345 char *z = (char*)ann.aOrig[i].z;
2346 int n = ann.aOrig[i].n;
2347 char zPrefix[200];
2348 z[n] = 0;
2349 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2350 if( iVers>=0 ){
2351 struct AnnVers *p = ann.aVers+iVers;
2352 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%.10s %s",
2353 fileVers ? p->zFUuid : p->zMUuid, p->zDate);
 
 
 
 
2354 }else{
2355 zPrefix[0] = 0;
 
 
 
 
 
 
2356 }
2357 fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z);
2358 }
2359 }
2360
--- src/diff.c
+++ src/diff.c
@@ -1939,10 +1939,11 @@
1939 struct AnnVers {
1940 const char *zFUuid; /* File being analyzed */
1941 const char *zMUuid; /* Check-in containing the file */
1942 const char *zDate; /* Date of the check-in */
1943 const char *zBgColor; /* Suggested background color */
1944 const char *zUser; /* Name of user who did the check-in */
1945 unsigned cnt; /* Number of lines contributed by this check-in */
1946 } *aVers; /* For each check-in analyzed */
1947 char **azVers; /* Names of versions analyzed */
1948 };
1949
@@ -2061,10 +2062,11 @@
2062 db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
2063 db_prepare(&q,
2064 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
2065 " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
2066 " date(event.mtime),"
2067 " coalesce(event.euser,event.user),"
2068 " mlink.pid"
2069 " FROM mlink, event"
2070 " WHERE mlink.fid=:rid"
2071 " AND event.objid=mlink.mid"
2072 " AND mlink.pid NOT IN vseen"
@@ -2074,15 +2076,16 @@
2076 );
2077
2078 db_bind_int(&q, ":rid", rid);
2079 if( iLimit==0 ) iLimit = 1000000000;
2080 while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
2081 int prevId = db_column_int(&q, 4);
2082 p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
2083 p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
2084 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2085 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
2086 p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
2087 if( p->nVers ){
2088 content_get(rid, &step);
2089 annotation_step(p, &step, p->nVers-1);
2090 blob_reset(&step);
2091 }
@@ -2268,15 +2271,18 @@
2271 style_footer();
2272 }
2273
2274 /*
2275 ** COMMAND: annotate
2276 ** COMMAND: blame
2277 **
2278 ** %fossil (annotate|blame) ?OPTIONS? FILENAME
2279 **
2280 ** Output the text of a file with markings to show when each line of
2281 ** the file was last modified. The "annotate" command shows line numbers
2282 ** and omits the username. The "blame" command shows the user who made each
2283 ** checkin and omits the line number.
2284 **
2285 ** Options:
2286 ** --filevers Show file version numbers rather than check-in versions
2287 ** -l|--log List all versions analyzed
2288 ** -n|--limit N Only look backwards in time by N versions
@@ -2295,11 +2301,13 @@
2301 const char *zLimit; /* The value to the -n|--limit option */
2302 int iLimit; /* How far back in time to look */
2303 int showLog; /* True to show the log */
2304 int fileVers; /* Show file version instead of check-in versions */
2305 int annFlags = 0; /* Flags to control annotation properties */
2306 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
2307
2308 bBlame = g.argv[1][0]=='b';
2309 zLimit = find_option("limit","n",1);
2310 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
2311 iLimit = atoi(zLimit);
2312 showLog = find_option("log","l",0)!=0;
2313 fileVers = find_option("filevers",0,0)!=0;
@@ -2342,18 +2350,26 @@
2350 }
2351 for(i=0; i<ann.nOrig; i++){
2352 int iVers = ann.aOrig[i].iVers;
2353 char *z = (char*)ann.aOrig[i].z;
2354 int n = ann.aOrig[i].n;
2355 struct AnnVers *p;
 
2356 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2357 p = ann.aVers + iVers;
2358 if( bBlame ){
2359 if( iVers>=0 ){
2360 fossil_print("%.10s %s %13.13s: %.*s\n",
2361 fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
2362 }else{
2363 fossil_print("%35s %.*s\n", "", n, z);
2364 }
2365 }else{
2366 if( iVers>=0 ){
2367 fossil_print("%.10s %s %5d: %.*s\n",
2368 fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
2369 }else{
2370 fossil_print("%21s %5d: %.*s\n",
2371 "", i+1, n, z);
2372 }
2373 }
 
2374 }
2375 }
2376
+20 -6
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -915,11 +915,11 @@
915915
** (3) Delete the temp file.
916916
*/
917917
void diff_tk(const char *zSubCmd, int firstArg){
918918
int i;
919919
Blob script;
920
- char *zTempFile;
920
+ char *zTempFile = 0;
921921
char *zCmd;
922922
blob_zero(&script);
923923
blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v",
924924
g.nameOfExe, zSubCmd);
925925
for(i=firstArg; i<g.argc; i++){
@@ -926,20 +926,34 @@
926926
const char *z = g.argv[i];
927927
if( z[0]=='-' ){
928928
if( strglob("*-html",z) ) continue;
929929
if( strglob("*-y",z) ) continue;
930930
if( strglob("*-i",z) ) continue;
931
+ /* The undocumented --script FILENAME option causes the Tk script to
932
+ ** be written into the FILENAME instead of being run. This is used
933
+ ** for testing and debugging. */
934
+ if( strglob("*-script",z) && i<g.argc-1 ){
935
+ i++;
936
+ zTempFile = g.argv[i];
937
+ continue;
938
+ }
931939
}
932940
blob_append(&script, " ", 1);
933941
shell_escape(&script, z);
934942
}
935943
blob_appendf(&script, "}\n%s", zDiffScript);
936
- zTempFile = write_blob_to_temp_file(&script);
937
- zCmd = mprintf("tclsh \"%s\"", zTempFile);
938
- fossil_system(zCmd);
939
- file_delete(zTempFile);
940
- fossil_free(zCmd);
944
+ if( zTempFile ){
945
+ blob_write_to_file(&script, zTempFile);
946
+ fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
947
+ }else{
948
+ zTempFile = write_blob_to_temp_file(&script);
949
+ zCmd = mprintf("tclsh \"%s\"", zTempFile);
950
+ fossil_system(zCmd);
951
+ file_delete(zTempFile);
952
+ fossil_free(zCmd);
953
+ }
954
+ blob_reset(&script);
941955
}
942956
943957
/*
944958
** Returns non-zero if files that may be binary should be used with external
945959
** diff programs.
946960
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -915,11 +915,11 @@
915 ** (3) Delete the temp file.
916 */
917 void diff_tk(const char *zSubCmd, int firstArg){
918 int i;
919 Blob script;
920 char *zTempFile;
921 char *zCmd;
922 blob_zero(&script);
923 blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v",
924 g.nameOfExe, zSubCmd);
925 for(i=firstArg; i<g.argc; i++){
@@ -926,20 +926,34 @@
926 const char *z = g.argv[i];
927 if( z[0]=='-' ){
928 if( strglob("*-html",z) ) continue;
929 if( strglob("*-y",z) ) continue;
930 if( strglob("*-i",z) ) continue;
 
 
 
 
 
 
 
 
931 }
932 blob_append(&script, " ", 1);
933 shell_escape(&script, z);
934 }
935 blob_appendf(&script, "}\n%s", zDiffScript);
936 zTempFile = write_blob_to_temp_file(&script);
937 zCmd = mprintf("tclsh \"%s\"", zTempFile);
938 fossil_system(zCmd);
939 file_delete(zTempFile);
940 fossil_free(zCmd);
 
 
 
 
 
 
941 }
942
943 /*
944 ** Returns non-zero if files that may be binary should be used with external
945 ** diff programs.
946
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -915,11 +915,11 @@
915 ** (3) Delete the temp file.
916 */
917 void diff_tk(const char *zSubCmd, int firstArg){
918 int i;
919 Blob script;
920 char *zTempFile = 0;
921 char *zCmd;
922 blob_zero(&script);
923 blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v",
924 g.nameOfExe, zSubCmd);
925 for(i=firstArg; i<g.argc; i++){
@@ -926,20 +926,34 @@
926 const char *z = g.argv[i];
927 if( z[0]=='-' ){
928 if( strglob("*-html",z) ) continue;
929 if( strglob("*-y",z) ) continue;
930 if( strglob("*-i",z) ) continue;
931 /* The undocumented --script FILENAME option causes the Tk script to
932 ** be written into the FILENAME instead of being run. This is used
933 ** for testing and debugging. */
934 if( strglob("*-script",z) && i<g.argc-1 ){
935 i++;
936 zTempFile = g.argv[i];
937 continue;
938 }
939 }
940 blob_append(&script, " ", 1);
941 shell_escape(&script, z);
942 }
943 blob_appendf(&script, "}\n%s", zDiffScript);
944 if( zTempFile ){
945 blob_write_to_file(&script, zTempFile);
946 fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
947 }else{
948 zTempFile = write_blob_to_temp_file(&script);
949 zCmd = mprintf("tclsh \"%s\"", zTempFile);
950 fossil_system(zCmd);
951 file_delete(zTempFile);
952 fossil_free(zCmd);
953 }
954 blob_reset(&script);
955 }
956
957 /*
958 ** Returns non-zero if files that may be binary should be used with external
959 ** diff programs.
960
+14 -1
--- src/http.c
+++ src/http.c
@@ -112,10 +112,11 @@
112112
fossil_free(zCredentials);
113113
}
114114
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115115
blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116116
" (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
117
+ if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
117118
if( g.fHttpTrace ){
118119
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
119120
}else{
120121
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
121122
}
@@ -217,10 +218,20 @@
217218
if( iHttpVersion==0 ){
218219
closeConnection = 1;
219220
}else{
220221
closeConnection = 0;
221222
}
223
+ }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
224
+ if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
225
+ if( rc!=200 && rc!=302 ){
226
+ int ii;
227
+ for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
228
+ while( zLine[ii]==' ' ) ii++;
229
+ fossil_warning("server says: %s", &zLine[ii]);
230
+ goto write_err;
231
+ }
232
+ closeConnection = 0;
222233
}else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
223234
for(i=15; fossil_isspace(zLine[i]); i++){}
224235
iLength = atoi(&zLine[i]);
225236
}else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
226237
char c;
@@ -295,12 +306,14 @@
295306
** Close the connection to the server if appropriate.
296307
**
297308
** FIXME: There is some bug in the lower layers that prevents the
298309
** connection from remaining open. The easiest fix for now is to
299310
** simply close and restart the connection for each round-trip.
311
+ **
312
+ ** For SSH we will leave the connection open.
300313
*/
301
- closeConnection = 1; /* FIX ME */
314
+ if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */
302315
if( closeConnection ){
303316
transport_close();
304317
}else{
305318
transport_rewind();
306319
}
307320
--- src/http.c
+++ src/http.c
@@ -112,10 +112,11 @@
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116 " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
 
117 if( g.fHttpTrace ){
118 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
119 }else{
120 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
121 }
@@ -217,10 +218,20 @@
217 if( iHttpVersion==0 ){
218 closeConnection = 1;
219 }else{
220 closeConnection = 0;
221 }
 
 
 
 
 
 
 
 
 
 
222 }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
223 for(i=15; fossil_isspace(zLine[i]); i++){}
224 iLength = atoi(&zLine[i]);
225 }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
226 char c;
@@ -295,12 +306,14 @@
295 ** Close the connection to the server if appropriate.
296 **
297 ** FIXME: There is some bug in the lower layers that prevents the
298 ** connection from remaining open. The easiest fix for now is to
299 ** simply close and restart the connection for each round-trip.
 
 
300 */
301 closeConnection = 1; /* FIX ME */
302 if( closeConnection ){
303 transport_close();
304 }else{
305 transport_rewind();
306 }
307
--- src/http.c
+++ src/http.c
@@ -112,10 +112,11 @@
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116 " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
117 if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
118 if( g.fHttpTrace ){
119 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
120 }else{
121 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
122 }
@@ -217,10 +218,20 @@
218 if( iHttpVersion==0 ){
219 closeConnection = 1;
220 }else{
221 closeConnection = 0;
222 }
223 }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
224 if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
225 if( rc!=200 && rc!=302 ){
226 int ii;
227 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
228 while( zLine[ii]==' ' ) ii++;
229 fossil_warning("server says: %s", &zLine[ii]);
230 goto write_err;
231 }
232 closeConnection = 0;
233 }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
234 for(i=15; fossil_isspace(zLine[i]); i++){}
235 iLength = atoi(&zLine[i]);
236 }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
237 char c;
@@ -295,12 +306,14 @@
306 ** Close the connection to the server if appropriate.
307 **
308 ** FIXME: There is some bug in the lower layers that prevents the
309 ** connection from remaining open. The easiest fix for now is to
310 ** simply close and restart the connection for each round-trip.
311 **
312 ** For SSH we will leave the connection open.
313 */
314 if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */
315 if( closeConnection ){
316 transport_close();
317 }else{
318 transport_rewind();
319 }
320
--- src/http_socket.c
+++ src/http_socket.c
@@ -209,5 +209,22 @@
209209
N -= (size_t)got;
210210
pContent = (void*)&((char*)pContent)[got];
211211
}
212212
return total;
213213
}
214
+
215
+/*
216
+** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
217
+** populated. For hostnames with more than one IP (or if overridden in
218
+** ~/.ssh/config) the rcvfrom may not match the host to which we connect.
219
+*/
220
+void socket_ssh_resolve_addr(void){
221
+ struct hostent *pHost; /* Used to make best effort for rcvfrom */
222
+ struct sockaddr_in addr;
223
+
224
+ memset(&addr, 0, sizeof(addr));
225
+ pHost = gethostbyname(g.urlName);
226
+ if( pHost!=0 ){
227
+ memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
228
+ g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
229
+ }
230
+}
214231
--- src/http_socket.c
+++ src/http_socket.c
@@ -209,5 +209,22 @@
209 N -= (size_t)got;
210 pContent = (void*)&((char*)pContent)[got];
211 }
212 return total;
213 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
--- src/http_socket.c
+++ src/http_socket.c
@@ -209,5 +209,22 @@
209 N -= (size_t)got;
210 pContent = (void*)&((char*)pContent)[got];
211 }
212 return total;
213 }
214
215 /*
216 ** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
217 ** populated. For hostnames with more than one IP (or if overridden in
218 ** ~/.ssh/config) the rcvfrom may not match the host to which we connect.
219 */
220 void socket_ssh_resolve_addr(void){
221 struct hostent *pHost; /* Used to make best effort for rcvfrom */
222 struct sockaddr_in addr;
223
224 memset(&addr, 0, sizeof(addr));
225 pHost = gethostbyname(g.urlName);
226 if( pHost!=0 ){
227 memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
228 g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
229 }
230 }
231
--- src/http_transport.c
+++ src/http_transport.c
@@ -74,25 +74,10 @@
7474
transport.nSent = 0;
7575
transport.nRcvd = 0;
7676
}
7777
}
7878
79
-/*
80
-** Read text from sshIn. Zero-terminate and remove trailing
81
-** whitespace.
82
-*/
83
-static void sshin_read(char *zBuf, int szBuf){
84
- int got;
85
- zBuf[0] = 0;
86
- got = read(sshIn, zBuf, szBuf-1);
87
- while( got>=0 ){
88
- zBuf[got] = 0;
89
- if( got==0 || !fossil_isspace(zBuf[got-1]) ) break;
90
- got--;
91
- }
92
-}
93
-
9479
/*
9580
** Default SSH command
9681
*/
9782
#ifdef __MINGW32__
9883
static char zDefaultSshCmd[] = "ssh -T";
@@ -99,183 +84,60 @@
9984
#else
10085
static char zDefaultSshCmd[] = "ssh -e none -T";
10186
#endif
10287
10388
/*
104
-** Generate a random SSH link problem keyword
105
-*/
106
-static int random_probe(char *zProbe, int nProbe){
107
- unsigned r[4];
108
- sqlite3_randomness(sizeof(r), r);
109
- sqlite3_snprintf(nProbe, zProbe, "probe-%08x%08x%08x%08x",
110
- r[0], r[1], r[2], r[3]);
111
- return (int)strlen(zProbe);
112
-}
113
-
114
-/*
115
-** Bring up an SSH link. This involves sending some "echo" commands and
116
-** get back appropriate responses. The point is to move past the MOTD and
117
-** verify that the link is working.
118
-*/
119
-static void transport_ssh_startup(void){
120
- char *zIn; /* An input line received back from remote */
121
- int nWait; /* Number of times waiting for the MOTD */
122
- char zProbe[40]; /* Text of the random probe */
123
- int nProbe; /* Size of probe message */
124
- int nIn; /* Size of input */
125
- static const int nBuf = 10000; /* Size of input buffer */
126
-
127
- zIn = fossil_malloc(nBuf);
128
- nProbe = random_probe(zProbe, sizeof(zProbe));
129
- fprintf(sshOut, "echo %s\n", zProbe);
130
- fflush(sshOut);
131
- if( g.fSshTrace ){
132
- printf("Sent: [echo %s]\n", zProbe);
133
- fflush(stdout);
134
- }
135
- memset(zIn, '*', nProbe);
136
- for(nWait=1; nWait<=10; nWait++){
137
- sshin_read(zIn+nProbe, nBuf-nProbe);
138
- if( g.fSshTrace ){
139
- printf("Got back-----------------------------------------------\n"
140
- "%s\n"
141
- "-------------------------------------------------------\n",
142
- zIn+nProbe);
143
- }
144
- if( strstr(zIn, zProbe) ) break;
145
- sqlite3_sleep(100*nWait);
146
- nIn = (int)strlen(zIn);
147
- memcpy(zIn, zIn+(nIn-nProbe), nProbe);
148
- if( g.fSshTrace ){
149
- printf("Fetching more text. Looking for [%s]...\n", zProbe);
150
- fflush(stdout);
151
- }
152
- }
153
- nProbe = random_probe(zProbe, sizeof(zProbe));
154
- fprintf(sshOut, "echo %s\n", zProbe);
155
- fflush(sshOut);
156
- if( g.fSshTrace ){
157
- printf("Sent: [echo %s]\n", zProbe);
158
- fflush(stdout);
159
- }
160
- sshin_read(zIn, nBuf);
161
- if( zIn[0]==0 ){
162
- sqlite3_sleep(250);
163
- sshin_read(zIn, nBuf);
164
- }
165
- if( g.fSshTrace ){
166
- printf("Got back-----------------------------------------------\n"
167
- "%s\n"
168
- "-------------------------------------------------------\n", zIn);
169
- }
170
- if( memcmp(zIn, zProbe, nProbe)!=0 ){
171
- pclose2(sshIn, sshOut, sshPid);
172
- fossil_fatal("ssh connection failed: [%s]", zIn);
173
- }
174
- fossil_free(zIn);
175
-}
176
-
177
-/*
178
-** Global initialization of the transport layer
179
-*/
180
-void transport_global_startup(void){
181
- if( g.urlIsSsh ){
182
- /* Only SSH requires a global initialization. For SSH we need to create
183
- ** and run an SSH command to talk to the remote machine.
184
- */
185
- const char *zSsh; /* The base SSH command */
186
- Blob zCmd; /* The SSH command */
187
- char *zHost; /* The host name to contact */
188
- int n; /* Size of prefix string */
189
-
190
- zSsh = db_get("ssh-command", zDefaultSshCmd);
191
- blob_init(&zCmd, zSsh, -1);
192
- if( g.urlPort!=g.urlDfltPort ){
193
-#ifdef __MINGW32__
194
- blob_appendf(&zCmd, " -P %d", g.urlPort);
195
-#else
196
- blob_appendf(&zCmd, " -p %d", g.urlPort);
197
-#endif
198
- }
199
- fossil_force_newline();
200
- fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201
- if( g.urlUser && g.urlUser[0] ){
202
- zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203
-#ifdef __MINGW32__
204
- /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205
- if( g.urlPasswd && g.urlPasswd[0] ){
206
- Blob pw;
207
- blob_zero(&pw);
208
- if( g.urlPasswd[0]=='*' ){
209
- char *zPrompt;
210
- zPrompt = mprintf("Password for [%s]: ", zHost);
211
- prompt_for_password(zPrompt, &pw, 0);
212
- free(zPrompt);
213
- }else{
214
- blob_init(&pw, g.urlPasswd, -1);
215
- }
216
- blob_append(&zCmd, " -pw ", -1);
217
- shell_escape(&zCmd, blob_str(&pw));
218
- blob_reset(&pw);
219
- fossil_print(" -pw ********"); /* Do not show the password text */
220
- }
221
-#endif
222
- }else{
223
- zHost = mprintf("%s", g.urlName);
224
- }
225
- n = blob_size(&zCmd);
226
- blob_append(&zCmd, " ", 1);
227
- shell_escape(&zCmd, zHost);
228
- if( g.urlShell ){
229
- blob_appendf(&zCmd, " %s", g.urlShell);
230
- }else{
231
-#if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232
- /* The following works. But only if the fossil on the remote side
233
- ** is recent enough to support the test-ssh-far-side command. That
234
- ** command was added on 2013-02-06. We will leave this turned off
235
- ** until most fossil servers have upgraded to that version or a later
236
- ** version. The sync will still work as long as the shell on the far
237
- ** side is bash and not tcsh. And if the default far side shell is
238
- ** tcsh, then the shell=/bin/bash query parameter can be used as a
239
- ** work-around. Enable this code after about a year...
240
- */
241
- blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242
-#endif
243
- }
244
- fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245
- free(zHost);
246
- popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247
- if( sshPid==0 ){
248
- fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249
- }
250
- blob_reset(&zCmd);
251
- transport_ssh_startup();
252
- }
253
-}
254
-
255
-/*
256
-** COMMAND: test-ssh-far-side
257
-**
258
-** Read lines of input text, one by one, and evaluate each line using
259
-** system(). The ssh: sync protocol uses this on the far side of the
260
-** SSH link.
261
-*/
262
-void test_ssh_far_side_cmd(void){
263
- int i = 0;
264
- int got;
265
- char zLine[5000];
266
- while( i<sizeof(zLine) ){
267
- got = read(0, zLine+i, 1);
268
- if( got==0 ) return;
269
- if( zLine[i]=='\n' ){
270
- zLine[i] = 0;
271
- system(zLine);
272
- i = 0;
273
- }else{
274
- i++;
275
- }
276
- }
89
+** SSH initialization of the transport layer
90
+*/
91
+int transport_ssh_open(void){
92
+ /* For SSH we need to create and run SSH fossil http
93
+ ** to talk to the remote machine.
94
+ */
95
+ const char *zSsh; /* The base SSH command */
96
+ Blob zCmd; /* The SSH command */
97
+ char *zHost; /* The host name to contact */
98
+ int n; /* Size of prefix string */
99
+
100
+ socket_ssh_resolve_addr();
101
+ zSsh = db_get("ssh-command", zDefaultSshCmd);
102
+ blob_init(&zCmd, zSsh, -1);
103
+ if( g.urlPort!=g.urlDfltPort && g.urlPort ){
104
+#ifdef __MINGW32__
105
+ blob_appendf(&zCmd, " -P %d", g.urlPort);
106
+#else
107
+ blob_appendf(&zCmd, " -p %d", g.urlPort);
108
+#endif
109
+ }
110
+ if( g.fSshTrace ){
111
+ fossil_force_newline();
112
+ fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
113
+ }
114
+ if( g.urlUser && g.urlUser[0] ){
115
+ zHost = mprintf("%s@%s", g.urlUser, g.urlName);
116
+ }else{
117
+ zHost = mprintf("%s", g.urlName);
118
+ }
119
+ n = blob_size(&zCmd);
120
+ blob_append(&zCmd, " ", 1);
121
+ shell_escape(&zCmd, zHost);
122
+ blob_append(&zCmd, " ", 1);
123
+ shell_escape(&zCmd, mprintf("%s", g.urlFossil));
124
+ blob_append(&zCmd, " test-http", 10);
125
+ if( g.urlPath && g.urlPath[0] ){
126
+ blob_append(&zCmd, " ", 1);
127
+ shell_escape(&zCmd, mprintf("%s", g.urlPath));
128
+ }
129
+ if( g.fSshTrace ){
130
+ fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
131
+ }
132
+ free(zHost);
133
+ popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
134
+ if( sshPid==0 ){
135
+ socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
136
+ }
137
+ blob_reset(&zCmd);
138
+ return sshPid==0;
277139
}
278140
279141
/*
280142
** Open a connection to the server. The server is defined by the following
281143
** global variables:
@@ -288,19 +150,12 @@
288150
*/
289151
int transport_open(void){
290152
int rc = 0;
291153
if( transport.isOpen==0 ){
292154
if( g.urlIsSsh ){
293
- Blob cmd;
294
- blob_zero(&cmd);
295
- shell_escape(&cmd, g.urlFossil);
296
- blob_append(&cmd, " test-http ", -1);
297
- shell_escape(&cmd, g.urlPath);
298
- fprintf(sshOut, "%s || true\n", blob_str(&cmd));
299
- fflush(sshOut);
300
- if( g.fSshTrace ) printf("Sent: [%s]\n", blob_str(&cmd));
301
- blob_reset(&cmd);
155
+ rc = transport_ssh_open();
156
+ if( rc==0 ) transport.isOpen = 1;
302157
}else if( g.urlIsHttps ){
303158
#ifdef FOSSIL_ENABLE_SSL
304159
rc = ssl_open();
305160
if( rc==0 ) transport.isOpen = 1;
306161
#else
@@ -340,11 +195,11 @@
340195
if( transport.pLog ){
341196
fclose(transport.pLog);
342197
transport.pLog = 0;
343198
}
344199
if( g.urlIsSsh ){
345
- /* No-op */
200
+ transport_ssh_close();
346201
}else if( g.urlIsHttps ){
347202
#ifdef FOSSIL_ENABLE_SSL
348203
ssl_close();
349204
#endif
350205
}else if( g.urlIsFile ){
@@ -399,13 +254,11 @@
399254
/*
400255
** This routine is called when the outbound message is complete and
401256
** it is time to being receiving a reply.
402257
*/
403258
void transport_flip(void){
404
- if( g.urlIsSsh ){
405
- fprintf(sshOut, "\n\n");
406
- }else if( g.urlIsFile ){
259
+ if( g.urlIsFile ){
407260
char *zCmd;
408261
fclose(transport.pFile);
409262
zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
410263
g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
411264
);
@@ -581,20 +434,32 @@
581434
}
582435
if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583436
return &transport.pBuf[iStart];
584437
}
585438
439
+/*
440
+** Global transport shutdown
441
+*/
586442
void transport_global_shutdown(void){
587
- if( g.urlIsSsh && sshPid ){
588
- /*printf("Closing SSH tunnel: ");*/
589
- fflush(stdout);
590
- pclose2(sshIn, sshOut, sshPid);
591
- sshPid = 0;
443
+ if( g.urlIsSsh ){
444
+ transport_ssh_close();
592445
}
593446
if( g.urlIsHttps ){
594447
#ifdef FOSSIL_ENABLE_SSL
595448
ssl_global_shutdown();
596449
#endif
597450
}else{
598451
socket_global_shutdown();
599452
}
600453
}
454
+
455
+/*
456
+** Close SSH transport.
457
+*/
458
+void transport_ssh_close(void){
459
+ if( sshPid ){
460
+ /*printf("Closing SSH tunnel: ");*/
461
+ fflush(stdout);
462
+ pclose2(sshIn, sshOut, sshPid);
463
+ sshPid = 0;
464
+ }
465
+}
601466
--- src/http_transport.c
+++ src/http_transport.c
@@ -74,25 +74,10 @@
74 transport.nSent = 0;
75 transport.nRcvd = 0;
76 }
77 }
78
79 /*
80 ** Read text from sshIn. Zero-terminate and remove trailing
81 ** whitespace.
82 */
83 static void sshin_read(char *zBuf, int szBuf){
84 int got;
85 zBuf[0] = 0;
86 got = read(sshIn, zBuf, szBuf-1);
87 while( got>=0 ){
88 zBuf[got] = 0;
89 if( got==0 || !fossil_isspace(zBuf[got-1]) ) break;
90 got--;
91 }
92 }
93
94 /*
95 ** Default SSH command
96 */
97 #ifdef __MINGW32__
98 static char zDefaultSshCmd[] = "ssh -T";
@@ -99,183 +84,60 @@
99 #else
100 static char zDefaultSshCmd[] = "ssh -e none -T";
101 #endif
102
103 /*
104 ** Generate a random SSH link problem keyword
105 */
106 static int random_probe(char *zProbe, int nProbe){
107 unsigned r[4];
108 sqlite3_randomness(sizeof(r), r);
109 sqlite3_snprintf(nProbe, zProbe, "probe-%08x%08x%08x%08x",
110 r[0], r[1], r[2], r[3]);
111 return (int)strlen(zProbe);
112 }
113
114 /*
115 ** Bring up an SSH link. This involves sending some "echo" commands and
116 ** get back appropriate responses. The point is to move past the MOTD and
117 ** verify that the link is working.
118 */
119 static void transport_ssh_startup(void){
120 char *zIn; /* An input line received back from remote */
121 int nWait; /* Number of times waiting for the MOTD */
122 char zProbe[40]; /* Text of the random probe */
123 int nProbe; /* Size of probe message */
124 int nIn; /* Size of input */
125 static const int nBuf = 10000; /* Size of input buffer */
126
127 zIn = fossil_malloc(nBuf);
128 nProbe = random_probe(zProbe, sizeof(zProbe));
129 fprintf(sshOut, "echo %s\n", zProbe);
130 fflush(sshOut);
131 if( g.fSshTrace ){
132 printf("Sent: [echo %s]\n", zProbe);
133 fflush(stdout);
134 }
135 memset(zIn, '*', nProbe);
136 for(nWait=1; nWait<=10; nWait++){
137 sshin_read(zIn+nProbe, nBuf-nProbe);
138 if( g.fSshTrace ){
139 printf("Got back-----------------------------------------------\n"
140 "%s\n"
141 "-------------------------------------------------------\n",
142 zIn+nProbe);
143 }
144 if( strstr(zIn, zProbe) ) break;
145 sqlite3_sleep(100*nWait);
146 nIn = (int)strlen(zIn);
147 memcpy(zIn, zIn+(nIn-nProbe), nProbe);
148 if( g.fSshTrace ){
149 printf("Fetching more text. Looking for [%s]...\n", zProbe);
150 fflush(stdout);
151 }
152 }
153 nProbe = random_probe(zProbe, sizeof(zProbe));
154 fprintf(sshOut, "echo %s\n", zProbe);
155 fflush(sshOut);
156 if( g.fSshTrace ){
157 printf("Sent: [echo %s]\n", zProbe);
158 fflush(stdout);
159 }
160 sshin_read(zIn, nBuf);
161 if( zIn[0]==0 ){
162 sqlite3_sleep(250);
163 sshin_read(zIn, nBuf);
164 }
165 if( g.fSshTrace ){
166 printf("Got back-----------------------------------------------\n"
167 "%s\n"
168 "-------------------------------------------------------\n", zIn);
169 }
170 if( memcmp(zIn, zProbe, nProbe)!=0 ){
171 pclose2(sshIn, sshOut, sshPid);
172 fossil_fatal("ssh connection failed: [%s]", zIn);
173 }
174 fossil_free(zIn);
175 }
176
177 /*
178 ** Global initialization of the transport layer
179 */
180 void transport_global_startup(void){
181 if( g.urlIsSsh ){
182 /* Only SSH requires a global initialization. For SSH we need to create
183 ** and run an SSH command to talk to the remote machine.
184 */
185 const char *zSsh; /* The base SSH command */
186 Blob zCmd; /* The SSH command */
187 char *zHost; /* The host name to contact */
188 int n; /* Size of prefix string */
189
190 zSsh = db_get("ssh-command", zDefaultSshCmd);
191 blob_init(&zCmd, zSsh, -1);
192 if( g.urlPort!=g.urlDfltPort ){
193 #ifdef __MINGW32__
194 blob_appendf(&zCmd, " -P %d", g.urlPort);
195 #else
196 blob_appendf(&zCmd, " -p %d", g.urlPort);
197 #endif
198 }
199 fossil_force_newline();
200 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201 if( g.urlUser && g.urlUser[0] ){
202 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203 #ifdef __MINGW32__
204 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205 if( g.urlPasswd && g.urlPasswd[0] ){
206 Blob pw;
207 blob_zero(&pw);
208 if( g.urlPasswd[0]=='*' ){
209 char *zPrompt;
210 zPrompt = mprintf("Password for [%s]: ", zHost);
211 prompt_for_password(zPrompt, &pw, 0);
212 free(zPrompt);
213 }else{
214 blob_init(&pw, g.urlPasswd, -1);
215 }
216 blob_append(&zCmd, " -pw ", -1);
217 shell_escape(&zCmd, blob_str(&pw));
218 blob_reset(&pw);
219 fossil_print(" -pw ********"); /* Do not show the password text */
220 }
221 #endif
222 }else{
223 zHost = mprintf("%s", g.urlName);
224 }
225 n = blob_size(&zCmd);
226 blob_append(&zCmd, " ", 1);
227 shell_escape(&zCmd, zHost);
228 if( g.urlShell ){
229 blob_appendf(&zCmd, " %s", g.urlShell);
230 }else{
231 #if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232 /* The following works. But only if the fossil on the remote side
233 ** is recent enough to support the test-ssh-far-side command. That
234 ** command was added on 2013-02-06. We will leave this turned off
235 ** until most fossil servers have upgraded to that version or a later
236 ** version. The sync will still work as long as the shell on the far
237 ** side is bash and not tcsh. And if the default far side shell is
238 ** tcsh, then the shell=/bin/bash query parameter can be used as a
239 ** work-around. Enable this code after about a year...
240 */
241 blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242 #endif
243 }
244 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245 free(zHost);
246 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247 if( sshPid==0 ){
248 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249 }
250 blob_reset(&zCmd);
251 transport_ssh_startup();
252 }
253 }
254
255 /*
256 ** COMMAND: test-ssh-far-side
257 **
258 ** Read lines of input text, one by one, and evaluate each line using
259 ** system(). The ssh: sync protocol uses this on the far side of the
260 ** SSH link.
261 */
262 void test_ssh_far_side_cmd(void){
263 int i = 0;
264 int got;
265 char zLine[5000];
266 while( i<sizeof(zLine) ){
267 got = read(0, zLine+i, 1);
268 if( got==0 ) return;
269 if( zLine[i]=='\n' ){
270 zLine[i] = 0;
271 system(zLine);
272 i = 0;
273 }else{
274 i++;
275 }
276 }
277 }
278
279 /*
280 ** Open a connection to the server. The server is defined by the following
281 ** global variables:
@@ -288,19 +150,12 @@
288 */
289 int transport_open(void){
290 int rc = 0;
291 if( transport.isOpen==0 ){
292 if( g.urlIsSsh ){
293 Blob cmd;
294 blob_zero(&cmd);
295 shell_escape(&cmd, g.urlFossil);
296 blob_append(&cmd, " test-http ", -1);
297 shell_escape(&cmd, g.urlPath);
298 fprintf(sshOut, "%s || true\n", blob_str(&cmd));
299 fflush(sshOut);
300 if( g.fSshTrace ) printf("Sent: [%s]\n", blob_str(&cmd));
301 blob_reset(&cmd);
302 }else if( g.urlIsHttps ){
303 #ifdef FOSSIL_ENABLE_SSL
304 rc = ssl_open();
305 if( rc==0 ) transport.isOpen = 1;
306 #else
@@ -340,11 +195,11 @@
340 if( transport.pLog ){
341 fclose(transport.pLog);
342 transport.pLog = 0;
343 }
344 if( g.urlIsSsh ){
345 /* No-op */
346 }else if( g.urlIsHttps ){
347 #ifdef FOSSIL_ENABLE_SSL
348 ssl_close();
349 #endif
350 }else if( g.urlIsFile ){
@@ -399,13 +254,11 @@
399 /*
400 ** This routine is called when the outbound message is complete and
401 ** it is time to being receiving a reply.
402 */
403 void transport_flip(void){
404 if( g.urlIsSsh ){
405 fprintf(sshOut, "\n\n");
406 }else if( g.urlIsFile ){
407 char *zCmd;
408 fclose(transport.pFile);
409 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
410 g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
411 );
@@ -581,20 +434,32 @@
581 }
582 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583 return &transport.pBuf[iStart];
584 }
585
 
 
 
586 void transport_global_shutdown(void){
587 if( g.urlIsSsh && sshPid ){
588 /*printf("Closing SSH tunnel: ");*/
589 fflush(stdout);
590 pclose2(sshIn, sshOut, sshPid);
591 sshPid = 0;
592 }
593 if( g.urlIsHttps ){
594 #ifdef FOSSIL_ENABLE_SSL
595 ssl_global_shutdown();
596 #endif
597 }else{
598 socket_global_shutdown();
599 }
600 }
 
 
 
 
 
 
 
 
 
 
 
 
601
--- src/http_transport.c
+++ src/http_transport.c
@@ -74,25 +74,10 @@
74 transport.nSent = 0;
75 transport.nRcvd = 0;
76 }
77 }
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79 /*
80 ** Default SSH command
81 */
82 #ifdef __MINGW32__
83 static char zDefaultSshCmd[] = "ssh -T";
@@ -99,183 +84,60 @@
84 #else
85 static char zDefaultSshCmd[] = "ssh -e none -T";
86 #endif
87
88 /*
89 ** SSH initialization of the transport layer
90 */
91 int transport_ssh_open(void){
92 /* For SSH we need to create and run SSH fossil http
93 ** to talk to the remote machine.
94 */
95 const char *zSsh; /* The base SSH command */
96 Blob zCmd; /* The SSH command */
97 char *zHost; /* The host name to contact */
98 int n; /* Size of prefix string */
99
100 socket_ssh_resolve_addr();
101 zSsh = db_get("ssh-command", zDefaultSshCmd);
102 blob_init(&zCmd, zSsh, -1);
103 if( g.urlPort!=g.urlDfltPort && g.urlPort ){
104 #ifdef __MINGW32__
105 blob_appendf(&zCmd, " -P %d", g.urlPort);
106 #else
107 blob_appendf(&zCmd, " -p %d", g.urlPort);
108 #endif
109 }
110 if( g.fSshTrace ){
111 fossil_force_newline();
112 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
113 }
114 if( g.urlUser && g.urlUser[0] ){
115 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
116 }else{
117 zHost = mprintf("%s", g.urlName);
118 }
119 n = blob_size(&zCmd);
120 blob_append(&zCmd, " ", 1);
121 shell_escape(&zCmd, zHost);
122 blob_append(&zCmd, " ", 1);
123 shell_escape(&zCmd, mprintf("%s", g.urlFossil));
124 blob_append(&zCmd, " test-http", 10);
125 if( g.urlPath && g.urlPath[0] ){
126 blob_append(&zCmd, " ", 1);
127 shell_escape(&zCmd, mprintf("%s", g.urlPath));
128 }
129 if( g.fSshTrace ){
130 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
131 }
132 free(zHost);
133 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
134 if( sshPid==0 ){
135 socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
136 }
137 blob_reset(&zCmd);
138 return sshPid==0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139 }
140
141 /*
142 ** Open a connection to the server. The server is defined by the following
143 ** global variables:
@@ -288,19 +150,12 @@
150 */
151 int transport_open(void){
152 int rc = 0;
153 if( transport.isOpen==0 ){
154 if( g.urlIsSsh ){
155 rc = transport_ssh_open();
156 if( rc==0 ) transport.isOpen = 1;
 
 
 
 
 
 
 
157 }else if( g.urlIsHttps ){
158 #ifdef FOSSIL_ENABLE_SSL
159 rc = ssl_open();
160 if( rc==0 ) transport.isOpen = 1;
161 #else
@@ -340,11 +195,11 @@
195 if( transport.pLog ){
196 fclose(transport.pLog);
197 transport.pLog = 0;
198 }
199 if( g.urlIsSsh ){
200 transport_ssh_close();
201 }else if( g.urlIsHttps ){
202 #ifdef FOSSIL_ENABLE_SSL
203 ssl_close();
204 #endif
205 }else if( g.urlIsFile ){
@@ -399,13 +254,11 @@
254 /*
255 ** This routine is called when the outbound message is complete and
256 ** it is time to being receiving a reply.
257 */
258 void transport_flip(void){
259 if( g.urlIsFile ){
 
 
260 char *zCmd;
261 fclose(transport.pFile);
262 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
263 g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
264 );
@@ -581,20 +434,32 @@
434 }
435 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
436 return &transport.pBuf[iStart];
437 }
438
439 /*
440 ** Global transport shutdown
441 */
442 void transport_global_shutdown(void){
443 if( g.urlIsSsh ){
444 transport_ssh_close();
 
 
 
445 }
446 if( g.urlIsHttps ){
447 #ifdef FOSSIL_ENABLE_SSL
448 ssl_global_shutdown();
449 #endif
450 }else{
451 socket_global_shutdown();
452 }
453 }
454
455 /*
456 ** Close SSH transport.
457 */
458 void transport_ssh_close(void){
459 if( sshPid ){
460 /*printf("Closing SSH tunnel: ");*/
461 fflush(stdout);
462 pclose2(sshIn, sshOut, sshPid);
463 sshPid = 0;
464 }
465 }
466
+16 -3
--- src/info.c
+++ src/info.c
@@ -579,11 +579,23 @@
579579
@ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
580580
}
581581
db_finalize(&q2);
582582
}
583583
if( g.perm.Hyperlink ){
584
- const char *zProjName = db_get("project-name", "unnamed");
584
+ char *zPJ = db_get("short-project-name", 0);
585
+ Blob projName;
586
+ int jj;
587
+ if( zPJ==0 ) zPJ = db_get("project-name", "unnamed");
588
+ blob_zero(&projName);
589
+ blob_append(&projName, zPJ, -1);
590
+ blob_trim(&projName);
591
+ zPJ = blob_str(&projName);
592
+ for(jj=0; zPJ[jj]; jj++){
593
+ if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){
594
+ zPJ[jj] = '_';
595
+ }
596
+ }
585597
@ <tr><th>Timelines:</th><td>
586598
@ %z(href("%R/timeline?f=%S",zUuid))family</a>
587599
if( zParent ){
588600
@ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
589601
}
@@ -605,15 +617,15 @@
605617
606618
607619
/* The Download: line */
608620
if( g.perm.Zip ){
609621
char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
610
- zProjName, zUuid, zUuid);
622
+ zPJ, zUuid, zUuid);
611623
@ </td></tr>
612624
@ <tr><th>Downloads:</th><td>
613625
@ %z(href("%s",zUrl))Tarball</a>
614
- @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
626
+ @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid))
615627
@ ZIP archive</a>
616628
fossil_free(zUrl);
617629
}
618630
@ </td></tr>
619631
@ <tr><th>Other&nbsp;Links:</th>
@@ -624,10 +636,11 @@
624636
if( g.perm.Write ){
625637
@ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
626638
}
627639
@ </td>
628640
@ </tr>
641
+ blob_reset(&projName);
629642
}
630643
@ </table>
631644
}else{
632645
style_header("Check-in Information");
633646
login_anonymous_available();
634647
--- src/info.c
+++ src/info.c
@@ -579,11 +579,23 @@
579 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
580 }
581 db_finalize(&q2);
582 }
583 if( g.perm.Hyperlink ){
584 const char *zProjName = db_get("project-name", "unnamed");
 
 
 
 
 
 
 
 
 
 
 
 
585 @ <tr><th>Timelines:</th><td>
586 @ %z(href("%R/timeline?f=%S",zUuid))family</a>
587 if( zParent ){
588 @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
589 }
@@ -605,15 +617,15 @@
605
606
607 /* The Download: line */
608 if( g.perm.Zip ){
609 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
610 zProjName, zUuid, zUuid);
611 @ </td></tr>
612 @ <tr><th>Downloads:</th><td>
613 @ %z(href("%s",zUrl))Tarball</a>
614 @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
615 @ ZIP archive</a>
616 fossil_free(zUrl);
617 }
618 @ </td></tr>
619 @ <tr><th>Other&nbsp;Links:</th>
@@ -624,10 +636,11 @@
624 if( g.perm.Write ){
625 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
626 }
627 @ </td>
628 @ </tr>
 
629 }
630 @ </table>
631 }else{
632 style_header("Check-in Information");
633 login_anonymous_available();
634
--- src/info.c
+++ src/info.c
@@ -579,11 +579,23 @@
579 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
580 }
581 db_finalize(&q2);
582 }
583 if( g.perm.Hyperlink ){
584 char *zPJ = db_get("short-project-name", 0);
585 Blob projName;
586 int jj;
587 if( zPJ==0 ) zPJ = db_get("project-name", "unnamed");
588 blob_zero(&projName);
589 blob_append(&projName, zPJ, -1);
590 blob_trim(&projName);
591 zPJ = blob_str(&projName);
592 for(jj=0; zPJ[jj]; jj++){
593 if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){
594 zPJ[jj] = '_';
595 }
596 }
597 @ <tr><th>Timelines:</th><td>
598 @ %z(href("%R/timeline?f=%S",zUuid))family</a>
599 if( zParent ){
600 @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
601 }
@@ -605,15 +617,15 @@
617
618
619 /* The Download: line */
620 if( g.perm.Zip ){
621 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
622 zPJ, zUuid, zUuid);
623 @ </td></tr>
624 @ <tr><th>Downloads:</th><td>
625 @ %z(href("%s",zUrl))Tarball</a>
626 @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid))
627 @ ZIP archive</a>
628 fossil_free(zUrl);
629 }
630 @ </td></tr>
631 @ <tr><th>Other&nbsp;Links:</th>
@@ -624,10 +636,11 @@
636 if( g.perm.Write ){
637 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
638 }
639 @ </td>
640 @ </tr>
641 blob_reset(&projName);
642 }
643 @ </table>
644 }else{
645 style_header("Check-in Information");
646 login_anonymous_available();
647
+2 -1
--- src/login.c
+++ src/login.c
@@ -793,11 +793,12 @@
793793
**
794794
** This feature allows the "fossil ui" command to give the user
795795
** full access rights without having to log in.
796796
*/
797797
zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
798
- if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
798
+ if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
799
+ g.fSshClient & CGI_SSH_CLIENT )
799800
&& g.useLocalauth
800801
&& db_get_int("localauth",0)==0
801802
&& P("HTTPS")==0
802803
){
803804
uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
804805
--- src/login.c
+++ src/login.c
@@ -793,11 +793,12 @@
793 **
794 ** This feature allows the "fossil ui" command to give the user
795 ** full access rights without having to log in.
796 */
797 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
798 if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
 
799 && g.useLocalauth
800 && db_get_int("localauth",0)==0
801 && P("HTTPS")==0
802 ){
803 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
804
--- src/login.c
+++ src/login.c
@@ -793,11 +793,12 @@
793 **
794 ** This feature allows the "fossil ui" command to give the user
795 ** full access rights without having to log in.
796 */
797 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
798 if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
799 g.fSshClient & CGI_SSH_CLIENT )
800 && g.useLocalauth
801 && db_get_int("localauth",0)==0
802 && P("HTTPS")==0
803 ){
804 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
805
+38 -5
--- src/main.c
+++ src/main.c
@@ -138,10 +138,12 @@
138138
int fSqlPrint; /* True if -sqlprint flag is present */
139139
int fQuiet; /* True if -quiet flag is present */
140140
int fHttpTrace; /* Trace outbound HTTP requests */
141141
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
142142
int fSshTrace; /* Trace the SSH setup traffic */
143
+ int fSshClient; /* HTTP client flags for SSH client */
144
+ char *zSshCmd; /* SSH command string */
143145
int fNoSync; /* Do not do an autosync ever. --nosync */
144146
char *zPath; /* Name of webpage being served */
145147
char *zExtra; /* Extra path information past the webpage name */
146148
char *zBaseURL; /* Full text of the URL being served */
147149
char *zTop; /* Parent directory of zPath */
@@ -179,11 +181,10 @@
179181
char *urlUser; /* User id for http: */
180182
char *urlPasswd; /* Password for http: */
181183
char *urlCanonical; /* Canonical representation of the URL */
182184
char *urlProxyAuth; /* Proxy-Authorizer: string */
183185
char *urlFossil; /* The fossil query parameter on ssh: */
184
- char *urlShell; /* The shell query parameter on ssh: */
185186
unsigned urlFlags; /* Boolean flags controlling URL processing */
186187
187188
const char *zLogin; /* Login name. "" if not logged in. */
188189
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
189190
** SSL client identity */
@@ -603,10 +604,12 @@
603604
g.fQuiet = find_option("quiet", 0, 0)!=0;
604605
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
605606
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
606607
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
607608
g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
609
+ g.fSshClient = 0;
610
+ g.zSshCmd = 0;
608611
if( g.fSqlTrace ) g.fSqlStats = 1;
609612
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
610613
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
611614
g.zLogin = find_option("user", "U", 1);
612615
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -1314,11 +1317,12 @@
13141317
}
13151318
13161319
/* Find the page that the user has requested, construct and deliver that
13171320
** page.
13181321
*/
1319
- if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
1322
+ if( g.zContentType &&
1323
+ strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
13201324
zPathInfo = "/xfer";
13211325
}
13221326
set_base_url(0);
13231327
if( zPathInfo==0 || zPathInfo[0]==0
13241328
|| (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
@@ -1731,39 +1735,68 @@
17311735
zIpAddr = g.argv[5];
17321736
}else{
17331737
g.httpIn = stdin;
17341738
g.httpOut = stdout;
17351739
zIpAddr = 0;
1740
+ }
1741
+ if( zIpAddr==0 ){
1742
+ zIpAddr = cgi_ssh_remote_addr(0);
1743
+ if( zIpAddr && zIpAddr[0] ){
1744
+ g.fSshClient |= CGI_SSH_CLIENT;
1745
+ }
17361746
}
17371747
find_server_repository(0);
17381748
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
17391749
if( useSCGI ){
17401750
cgi_handle_scgi_request();
1751
+ }else if( g.fSshClient & CGI_SSH_CLIENT ){
1752
+ ssh_request_loop(zIpAddr, glob_create(zFileGlob));
17411753
}else{
17421754
cgi_handle_http_request(zIpAddr);
17431755
}
17441756
process_one_web_page(zNotFound, glob_create(zFileGlob));
17451757
}
1758
+
1759
+/*
1760
+** Process all requests in a single SSH connection if possible.
1761
+*/
1762
+void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
1763
+ do{
1764
+ cgi_handle_ssh_http_request(zIpAddr);
1765
+ process_one_web_page(0, FileGlob);
1766
+ blob_reset(&g.cgiIn);
1767
+ } while ( g.fSshClient & CGI_SSH_FOSSIL ||
1768
+ g.fSshClient & CGI_SSH_COMPAT );
1769
+}
17461770
17471771
/*
17481772
** Note that the following command is used by ssh:// processing.
17491773
**
17501774
** COMMAND: test-http
17511775
** Works like the http command but gives setup permission to all users.
1776
+**
17521777
*/
17531778
void cmd_test_http(void){
1779
+ const char *zIpAddr; /* IP address of remote client */
1780
+
17541781
Th_InitTraceLog();
17551782
login_set_capabilities("sx", 0);
17561783
g.useLocalauth = 1;
1757
- cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
17581784
g.httpIn = stdin;
17591785
g.httpOut = stdout;
17601786
find_server_repository(0);
17611787
g.cgiOutput = 1;
17621788
g.fullHttpReply = 1;
1763
- cgi_handle_http_request(0);
1764
- process_one_web_page(0, 0);
1789
+ zIpAddr = cgi_ssh_remote_addr(0);
1790
+ if( zIpAddr && zIpAddr[0] ){
1791
+ g.fSshClient |= CGI_SSH_CLIENT;
1792
+ ssh_request_loop(zIpAddr, 0);
1793
+ }else{
1794
+ cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1795
+ cgi_handle_http_request(0);
1796
+ process_one_web_page(0, 0);
1797
+ }
17651798
}
17661799
17671800
#if !defined(_WIN32)
17681801
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17691802
/*
17701803
--- src/main.c
+++ src/main.c
@@ -138,10 +138,12 @@
138 int fSqlPrint; /* True if -sqlprint flag is present */
139 int fQuiet; /* True if -quiet flag is present */
140 int fHttpTrace; /* Trace outbound HTTP requests */
141 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
142 int fSshTrace; /* Trace the SSH setup traffic */
 
 
143 int fNoSync; /* Do not do an autosync ever. --nosync */
144 char *zPath; /* Name of webpage being served */
145 char *zExtra; /* Extra path information past the webpage name */
146 char *zBaseURL; /* Full text of the URL being served */
147 char *zTop; /* Parent directory of zPath */
@@ -179,11 +181,10 @@
179 char *urlUser; /* User id for http: */
180 char *urlPasswd; /* Password for http: */
181 char *urlCanonical; /* Canonical representation of the URL */
182 char *urlProxyAuth; /* Proxy-Authorizer: string */
183 char *urlFossil; /* The fossil query parameter on ssh: */
184 char *urlShell; /* The shell query parameter on ssh: */
185 unsigned urlFlags; /* Boolean flags controlling URL processing */
186
187 const char *zLogin; /* Login name. "" if not logged in. */
188 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
189 ** SSL client identity */
@@ -603,10 +604,12 @@
603 g.fQuiet = find_option("quiet", 0, 0)!=0;
604 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
605 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
606 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
607 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
 
 
608 if( g.fSqlTrace ) g.fSqlStats = 1;
609 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
610 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
611 g.zLogin = find_option("user", "U", 1);
612 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -1314,11 +1317,12 @@
1314 }
1315
1316 /* Find the page that the user has requested, construct and deliver that
1317 ** page.
1318 */
1319 if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
 
1320 zPathInfo = "/xfer";
1321 }
1322 set_base_url(0);
1323 if( zPathInfo==0 || zPathInfo[0]==0
1324 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
@@ -1731,39 +1735,68 @@
1731 zIpAddr = g.argv[5];
1732 }else{
1733 g.httpIn = stdin;
1734 g.httpOut = stdout;
1735 zIpAddr = 0;
 
 
 
 
 
 
1736 }
1737 find_server_repository(0);
1738 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1739 if( useSCGI ){
1740 cgi_handle_scgi_request();
 
 
1741 }else{
1742 cgi_handle_http_request(zIpAddr);
1743 }
1744 process_one_web_page(zNotFound, glob_create(zFileGlob));
1745 }
 
 
 
 
 
 
 
 
 
 
 
 
1746
1747 /*
1748 ** Note that the following command is used by ssh:// processing.
1749 **
1750 ** COMMAND: test-http
1751 ** Works like the http command but gives setup permission to all users.
 
1752 */
1753 void cmd_test_http(void){
 
 
1754 Th_InitTraceLog();
1755 login_set_capabilities("sx", 0);
1756 g.useLocalauth = 1;
1757 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1758 g.httpIn = stdin;
1759 g.httpOut = stdout;
1760 find_server_repository(0);
1761 g.cgiOutput = 1;
1762 g.fullHttpReply = 1;
1763 cgi_handle_http_request(0);
1764 process_one_web_page(0, 0);
 
 
 
 
 
 
 
1765 }
1766
1767 #if !defined(_WIN32)
1768 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1769 /*
1770
--- src/main.c
+++ src/main.c
@@ -138,10 +138,12 @@
138 int fSqlPrint; /* True if -sqlprint flag is present */
139 int fQuiet; /* True if -quiet flag is present */
140 int fHttpTrace; /* Trace outbound HTTP requests */
141 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
142 int fSshTrace; /* Trace the SSH setup traffic */
143 int fSshClient; /* HTTP client flags for SSH client */
144 char *zSshCmd; /* SSH command string */
145 int fNoSync; /* Do not do an autosync ever. --nosync */
146 char *zPath; /* Name of webpage being served */
147 char *zExtra; /* Extra path information past the webpage name */
148 char *zBaseURL; /* Full text of the URL being served */
149 char *zTop; /* Parent directory of zPath */
@@ -179,11 +181,10 @@
181 char *urlUser; /* User id for http: */
182 char *urlPasswd; /* Password for http: */
183 char *urlCanonical; /* Canonical representation of the URL */
184 char *urlProxyAuth; /* Proxy-Authorizer: string */
185 char *urlFossil; /* The fossil query parameter on ssh: */
 
186 unsigned urlFlags; /* Boolean flags controlling URL processing */
187
188 const char *zLogin; /* Login name. "" if not logged in. */
189 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
190 ** SSL client identity */
@@ -603,10 +604,12 @@
604 g.fQuiet = find_option("quiet", 0, 0)!=0;
605 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
606 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
607 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
608 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
609 g.fSshClient = 0;
610 g.zSshCmd = 0;
611 if( g.fSqlTrace ) g.fSqlStats = 1;
612 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
613 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
614 g.zLogin = find_option("user", "U", 1);
615 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -1314,11 +1317,12 @@
1317 }
1318
1319 /* Find the page that the user has requested, construct and deliver that
1320 ** page.
1321 */
1322 if( g.zContentType &&
1323 strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
1324 zPathInfo = "/xfer";
1325 }
1326 set_base_url(0);
1327 if( zPathInfo==0 || zPathInfo[0]==0
1328 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
@@ -1731,39 +1735,68 @@
1735 zIpAddr = g.argv[5];
1736 }else{
1737 g.httpIn = stdin;
1738 g.httpOut = stdout;
1739 zIpAddr = 0;
1740 }
1741 if( zIpAddr==0 ){
1742 zIpAddr = cgi_ssh_remote_addr(0);
1743 if( zIpAddr && zIpAddr[0] ){
1744 g.fSshClient |= CGI_SSH_CLIENT;
1745 }
1746 }
1747 find_server_repository(0);
1748 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1749 if( useSCGI ){
1750 cgi_handle_scgi_request();
1751 }else if( g.fSshClient & CGI_SSH_CLIENT ){
1752 ssh_request_loop(zIpAddr, glob_create(zFileGlob));
1753 }else{
1754 cgi_handle_http_request(zIpAddr);
1755 }
1756 process_one_web_page(zNotFound, glob_create(zFileGlob));
1757 }
1758
1759 /*
1760 ** Process all requests in a single SSH connection if possible.
1761 */
1762 void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
1763 do{
1764 cgi_handle_ssh_http_request(zIpAddr);
1765 process_one_web_page(0, FileGlob);
1766 blob_reset(&g.cgiIn);
1767 } while ( g.fSshClient & CGI_SSH_FOSSIL ||
1768 g.fSshClient & CGI_SSH_COMPAT );
1769 }
1770
1771 /*
1772 ** Note that the following command is used by ssh:// processing.
1773 **
1774 ** COMMAND: test-http
1775 ** Works like the http command but gives setup permission to all users.
1776 **
1777 */
1778 void cmd_test_http(void){
1779 const char *zIpAddr; /* IP address of remote client */
1780
1781 Th_InitTraceLog();
1782 login_set_capabilities("sx", 0);
1783 g.useLocalauth = 1;
 
1784 g.httpIn = stdin;
1785 g.httpOut = stdout;
1786 find_server_repository(0);
1787 g.cgiOutput = 1;
1788 g.fullHttpReply = 1;
1789 zIpAddr = cgi_ssh_remote_addr(0);
1790 if( zIpAddr && zIpAddr[0] ){
1791 g.fSshClient |= CGI_SSH_CLIENT;
1792 ssh_request_loop(zIpAddr, 0);
1793 }else{
1794 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1795 cgi_handle_http_request(0);
1796 process_one_web_page(0, 0);
1797 }
1798 }
1799
1800 #if !defined(_WIN32)
1801 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1802 /*
1803
--- src/popen.c
+++ src/popen.c
@@ -27,10 +27,13 @@
2727
** Print a fatal error and quit.
2828
*/
2929
static void win32_fatal_error(const char *zMsg){
3030
fossil_fatal("%s", zMsg);
3131
}
32
+#else
33
+#include <signal.h>
34
+#include <sys/wait.h>
3235
#endif
3336
3437
/*
3538
** The following macros are used to cast pointers to integers and
3639
** integers to pointers. The way you do this varies from one compiler
@@ -171,10 +174,11 @@
171174
close(pout[0]);
172175
close(pout[1]);
173176
*pChildPid = 0;
174177
return 1;
175178
}
179
+ signal(SIGPIPE,SIG_IGN);
176180
if( *pChildPid==0 ){
177181
int fd;
178182
int nErr = 0;
179183
/* This is the child process */
180184
close(0);
@@ -211,7 +215,8 @@
211215
fclose(pOut);
212216
#else
213217
close(fdIn);
214218
fclose(pOut);
215219
kill(childPid, SIGINT);
220
+ while( waitpid(0, 0, WNOHANG)>0 ) {}
216221
#endif
217222
}
218223
--- src/popen.c
+++ src/popen.c
@@ -27,10 +27,13 @@
27 ** Print a fatal error and quit.
28 */
29 static void win32_fatal_error(const char *zMsg){
30 fossil_fatal("%s", zMsg);
31 }
 
 
 
32 #endif
33
34 /*
35 ** The following macros are used to cast pointers to integers and
36 ** integers to pointers. The way you do this varies from one compiler
@@ -171,10 +174,11 @@
171 close(pout[0]);
172 close(pout[1]);
173 *pChildPid = 0;
174 return 1;
175 }
 
176 if( *pChildPid==0 ){
177 int fd;
178 int nErr = 0;
179 /* This is the child process */
180 close(0);
@@ -211,7 +215,8 @@
211 fclose(pOut);
212 #else
213 close(fdIn);
214 fclose(pOut);
215 kill(childPid, SIGINT);
 
216 #endif
217 }
218
--- src/popen.c
+++ src/popen.c
@@ -27,10 +27,13 @@
27 ** Print a fatal error and quit.
28 */
29 static void win32_fatal_error(const char *zMsg){
30 fossil_fatal("%s", zMsg);
31 }
32 #else
33 #include <signal.h>
34 #include <sys/wait.h>
35 #endif
36
37 /*
38 ** The following macros are used to cast pointers to integers and
39 ** integers to pointers. The way you do this varies from one compiler
@@ -171,10 +174,11 @@
174 close(pout[0]);
175 close(pout[1]);
176 *pChildPid = 0;
177 return 1;
178 }
179 signal(SIGPIPE,SIG_IGN);
180 if( *pChildPid==0 ){
181 int fd;
182 int nErr = 0;
183 /* This is the child process */
184 close(0);
@@ -211,7 +215,8 @@
215 fclose(pOut);
216 #else
217 close(fdIn);
218 fclose(pOut);
219 kill(childPid, SIGINT);
220 while( waitpid(0, 0, WNOHANG)>0 ) {}
221 #endif
222 }
223
+10 -2
--- src/setup.c
+++ src/setup.c
@@ -727,11 +727,11 @@
727727
@ capabilities of the <span class="usertype">nobody</span> user are
728728
@ inherited by all users, regardless of whether or not they are logged in.
729729
@ To disable universal access to the repository, make sure no user named
730730
@ <span class="usertype">nobody</span> exists or that the
731731
@ <span class="usertype">nobody</span> user has no capabilities
732
- @ enabled. The password for <span class="usertype">nobody</span> is ignore.
732
+ @ enabled. The password for <span class="usertype">nobody</span> is ignored.
733733
@ To avoid problems with spiders overloading the server, it is recommended
734734
@ that the <span class="capability">h</span> (Hyperlinks) capability be
735735
@ turned off for the <span class="usertype">nobody</span> user.
736736
@ </p></li>
737737
@
@@ -1273,16 +1273,24 @@
12731273
@ <form action="%s(g.zTop)/setup_config" method="post"><div>
12741274
login_insert_csrf_secret();
12751275
@ <hr />
12761276
entry_attribute("Project Name", 60, "project-name", "pn", "", 0);
12771277
@ <p>Give your project a name so visitors know what this site is about.
1278
- @ The project name will also be used as the RSS feed title.</p>
1278
+ @ The project name will also be used as the RSS feed title.
1279
+ @ </p>
12791280
@ <hr />
12801281
textarea_attribute("Project Description", 3, 80,
12811282
"project-description", "pd", "", 0);
12821283
@ <p>Describe your project. This will be used in page headers for search
12831284
@ engines as well as a short RSS description.</p>
1285
+ @ <hr />
1286
+ entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name", "spn", "", 0);
1287
+ @ <p>This is used as a prefix on the names of generated tarballs and ZIP archive.
1288
+ @ For best results, keep this prefix brief and avoid special characters such
1289
+ @ as "/" and "\".
1290
+ @ If no tarball prefix is specified, then the full Project Name above is used.
1291
+ @ </p>
12841292
@ <hr />
12851293
onoff_attribute("Enable WYSIWYG Wiki Editing",
12861294
"wysiwyg-wiki", "wysiwyg-wiki", 0, 0);
12871295
@ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages.
12881296
@ The WYSIWYG editor generates HTML instead of markup, which makes
12891297
--- src/setup.c
+++ src/setup.c
@@ -727,11 +727,11 @@
727 @ capabilities of the <span class="usertype">nobody</span> user are
728 @ inherited by all users, regardless of whether or not they are logged in.
729 @ To disable universal access to the repository, make sure no user named
730 @ <span class="usertype">nobody</span> exists or that the
731 @ <span class="usertype">nobody</span> user has no capabilities
732 @ enabled. The password for <span class="usertype">nobody</span> is ignore.
733 @ To avoid problems with spiders overloading the server, it is recommended
734 @ that the <span class="capability">h</span> (Hyperlinks) capability be
735 @ turned off for the <span class="usertype">nobody</span> user.
736 @ </p></li>
737 @
@@ -1273,16 +1273,24 @@
1273 @ <form action="%s(g.zTop)/setup_config" method="post"><div>
1274 login_insert_csrf_secret();
1275 @ <hr />
1276 entry_attribute("Project Name", 60, "project-name", "pn", "", 0);
1277 @ <p>Give your project a name so visitors know what this site is about.
1278 @ The project name will also be used as the RSS feed title.</p>
 
1279 @ <hr />
1280 textarea_attribute("Project Description", 3, 80,
1281 "project-description", "pd", "", 0);
1282 @ <p>Describe your project. This will be used in page headers for search
1283 @ engines as well as a short RSS description.</p>
 
 
 
 
 
 
 
1284 @ <hr />
1285 onoff_attribute("Enable WYSIWYG Wiki Editing",
1286 "wysiwyg-wiki", "wysiwyg-wiki", 0, 0);
1287 @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages.
1288 @ The WYSIWYG editor generates HTML instead of markup, which makes
1289
--- src/setup.c
+++ src/setup.c
@@ -727,11 +727,11 @@
727 @ capabilities of the <span class="usertype">nobody</span> user are
728 @ inherited by all users, regardless of whether or not they are logged in.
729 @ To disable universal access to the repository, make sure no user named
730 @ <span class="usertype">nobody</span> exists or that the
731 @ <span class="usertype">nobody</span> user has no capabilities
732 @ enabled. The password for <span class="usertype">nobody</span> is ignored.
733 @ To avoid problems with spiders overloading the server, it is recommended
734 @ that the <span class="capability">h</span> (Hyperlinks) capability be
735 @ turned off for the <span class="usertype">nobody</span> user.
736 @ </p></li>
737 @
@@ -1273,16 +1273,24 @@
1273 @ <form action="%s(g.zTop)/setup_config" method="post"><div>
1274 login_insert_csrf_secret();
1275 @ <hr />
1276 entry_attribute("Project Name", 60, "project-name", "pn", "", 0);
1277 @ <p>Give your project a name so visitors know what this site is about.
1278 @ The project name will also be used as the RSS feed title.
1279 @ </p>
1280 @ <hr />
1281 textarea_attribute("Project Description", 3, 80,
1282 "project-description", "pd", "", 0);
1283 @ <p>Describe your project. This will be used in page headers for search
1284 @ engines as well as a short RSS description.</p>
1285 @ <hr />
1286 entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name", "spn", "", 0);
1287 @ <p>This is used as a prefix on the names of generated tarballs and ZIP archive.
1288 @ For best results, keep this prefix brief and avoid special characters such
1289 @ as "/" and "\".
1290 @ If no tarball prefix is specified, then the full Project Name above is used.
1291 @ </p>
1292 @ <hr />
1293 onoff_attribute("Enable WYSIWYG Wiki Editing",
1294 "wysiwyg-wiki", "wysiwyg-wiki", 0, 0);
1295 @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages.
1296 @ The WYSIWYG editor generates HTML instead of markup, which makes
1297
+2 -2
--- src/shell.c
+++ src/shell.c
@@ -972,11 +972,11 @@
972972
int i;
973973
const char *z;
974974
rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
975975
if( rc!=SQLITE_OK || !pSelect ){
976976
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
977
- p->nErr++;
977
+ if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
978978
return rc;
979979
}
980980
rc = sqlite3_step(pSelect);
981981
nResult = sqlite3_column_count(pSelect);
982982
while( rc==SQLITE_ROW ){
@@ -999,11 +999,11 @@
999999
rc = sqlite3_step(pSelect);
10001000
}
10011001
rc = sqlite3_finalize(pSelect);
10021002
if( rc!=SQLITE_OK ){
10031003
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1004
- p->nErr++;
1004
+ if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
10051005
}
10061006
return rc;
10071007
}
10081008
10091009
/*
10101010
--- src/shell.c
+++ src/shell.c
@@ -972,11 +972,11 @@
972 int i;
973 const char *z;
974 rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
975 if( rc!=SQLITE_OK || !pSelect ){
976 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
977 p->nErr++;
978 return rc;
979 }
980 rc = sqlite3_step(pSelect);
981 nResult = sqlite3_column_count(pSelect);
982 while( rc==SQLITE_ROW ){
@@ -999,11 +999,11 @@
999 rc = sqlite3_step(pSelect);
1000 }
1001 rc = sqlite3_finalize(pSelect);
1002 if( rc!=SQLITE_OK ){
1003 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1004 p->nErr++;
1005 }
1006 return rc;
1007 }
1008
1009 /*
1010
--- src/shell.c
+++ src/shell.c
@@ -972,11 +972,11 @@
972 int i;
973 const char *z;
974 rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
975 if( rc!=SQLITE_OK || !pSelect ){
976 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
977 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
978 return rc;
979 }
980 rc = sqlite3_step(pSelect);
981 nResult = sqlite3_column_count(pSelect);
982 while( rc==SQLITE_ROW ){
@@ -999,11 +999,11 @@
999 rc = sqlite3_step(pSelect);
1000 }
1001 rc = sqlite3_finalize(pSelect);
1002 if( rc!=SQLITE_OK ){
1003 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1004 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1005 }
1006 return rc;
1007 }
1008
1009 /*
1010
+1254 -600
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -656,11 +656,11 @@
656656
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657657
** [sqlite_version()] and [sqlite_source_id()].
658658
*/
659659
#define SQLITE_VERSION "3.8.1"
660660
#define SQLITE_VERSION_NUMBER 3008001
661
-#define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
661
+#define SQLITE_SOURCE_ID "2013-10-10 15:04:52 af7abebeb1f70466833bc766d294d721eaef746f"
662662
663663
/*
664664
** CAPI3REF: Run-Time Library Version Numbers
665665
** KEYWORDS: sqlite3_version, sqlite3_sourceid
666666
**
@@ -8272,10 +8272,35 @@
82728272
typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
82738273
#else
82748274
typedef u32 tRowcnt; /* 32-bit is the default */
82758275
#endif
82768276
8277
+/*
8278
+** Estimated quantities used for query planning are stored as 16-bit
8279
+** logarithms. For quantity X, the value stored is 10*log2(X). This
8280
+** gives a possible range of values of approximately 1.0e986 to 1e-986.
8281
+** But the allowed values are "grainy". Not every value is representable.
8282
+** For example, quantities 16 and 17 are both represented by a LogEst
8283
+** of 40. However, since LogEst quantatites are suppose to be estimates,
8284
+** not exact values, this imprecision is not a problem.
8285
+**
8286
+** "LogEst" is short for "Logarithimic Estimate".
8287
+**
8288
+** Examples:
8289
+** 1 -> 0 20 -> 43 10000 -> 132
8290
+** 2 -> 10 25 -> 46 25000 -> 146
8291
+** 3 -> 16 100 -> 66 1000000 -> 199
8292
+** 4 -> 20 1000 -> 99 1048576 -> 200
8293
+** 10 -> 33 1024 -> 100 4294967296 -> 320
8294
+**
8295
+** The LogEst can be negative to indicate fractional values.
8296
+** Examples:
8297
+**
8298
+** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
8299
+*/
8300
+typedef INT16_TYPE LogEst;
8301
+
82778302
/*
82788303
** Macros to determine whether the machine is big or little endian,
82798304
** evaluated at runtime.
82808305
*/
82818306
#ifdef SQLITE_AMALGAMATION
@@ -10419,11 +10444,12 @@
1041910444
char *zDflt; /* Original text of the default value */
1042010445
char *zType; /* Data type for this column */
1042110446
char *zColl; /* Collating sequence. If NULL, use the default */
1042210447
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
1042310448
char affinity; /* One of the SQLITE_AFF_... values */
10424
- u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
10449
+ u8 szEst; /* Estimated size of this column. INT==1 */
10450
+ u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
1042510451
};
1042610452
1042710453
/* Allowed values for Column.colFlags:
1042810454
*/
1042910455
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
@@ -10583,10 +10609,11 @@
1058310609
tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
1058410610
int tnum; /* Root BTree node for this table (see note above) */
1058510611
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
1058610612
i16 nCol; /* Number of columns in this table */
1058710613
u16 nRef; /* Number of pointers to this Table */
10614
+ LogEst szTabRow; /* Estimated size of each table row in bytes */
1058810615
u8 tabFlags; /* Mask of TF_* values */
1058910616
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
1059010617
#ifndef SQLITE_OMIT_ALTERTABLE
1059110618
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
1059210619
#endif
@@ -10694,11 +10721,11 @@
1069410721
#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
1069510722
#define OE_SetNull 7 /* Set the foreign key value to NULL */
1069610723
#define OE_SetDflt 8 /* Set the foreign key value to its default */
1069710724
#define OE_Cascade 9 /* Cascade the changes */
1069810725
10699
-#define OE_Default 99 /* Do whatever the default action is */
10726
+#define OE_Default 10 /* Do whatever the default action is */
1070010727
1070110728
1070210729
/*
1070310730
** An instance of the following structure is passed as the first
1070410731
** argument to sqlite3VdbeKeyCompare and is used to control the
@@ -10781,10 +10808,11 @@
1078110808
Schema *pSchema; /* Schema containing this index */
1078210809
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
1078310810
char **azColl; /* Array of collation sequence names for index */
1078410811
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
1078510812
int tnum; /* DB Page containing root of this index */
10813
+ LogEst szIdxRow; /* Estimated average row size in bytes */
1078610814
u16 nColumn; /* Number of columns in table used by this index */
1078710815
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
1078810816
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
1078910817
unsigned bUnordered:1; /* Use this index for == or IN queries only */
1079010818
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
@@ -11636,10 +11664,11 @@
1163611664
*/
1163711665
typedef struct DbFixer DbFixer;
1163811666
struct DbFixer {
1163911667
Parse *pParse; /* The parsing context. Error messages written here */
1164011668
Schema *pSchema; /* Fix items to this schema */
11669
+ int bVarOnly; /* Check for variable references only */
1164111670
const char *zDb; /* Make sure all objects are contained in this database */
1164211671
const char *zType; /* Type of the container - used for error messages */
1164311672
const Token *pName; /* Name of the container - used for error messages */
1164411673
};
1164511674
@@ -12174,11 +12203,11 @@
1217412203
# define sqlite3AuthContextPush(a,b,c)
1217512204
# define sqlite3AuthContextPop(a) ((void)(a))
1217612205
#endif
1217712206
SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
1217812207
SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
12179
-SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
12208
+SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
1218012209
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
1218112210
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
1218212211
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
1218312212
SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
1218412213
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
@@ -12186,10 +12215,16 @@
1218612215
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
1218712216
SQLITE_PRIVATE int sqlite3Atoi(const char*);
1218812217
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
1218912218
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
1219012219
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
12220
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
12221
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
12222
+#ifndef SQLITE_OMIT_VIRTUALTABLE
12223
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
12224
+#endif
12225
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
1219112226
1219212227
/*
1219312228
** Routines to read and write variable-length integers. These used to
1219412229
** be defined locally, but now we use the varint routines in the util.c
1219512230
** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -12302,11 +12337,11 @@
1230212337
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
1230312338
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
1230412339
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
1230512340
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
1230612341
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12307
-SQLITE_PRIVATE char sqlite3AffinityType(const char*);
12342
+SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
1230812343
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
1230912344
SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
1231012345
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
1231112346
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
1231212347
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -22387,10 +22422,87 @@
2238722422
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
2238822423
if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
2238922424
}
2239022425
}
2239122426
#endif
22427
+
22428
+/*
22429
+** Find (an approximate) sum of two LogEst values. This computation is
22430
+** not a simple "+" operator because LogEst is stored as a logarithmic
22431
+** value.
22432
+**
22433
+*/
22434
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
22435
+ static const unsigned char x[] = {
22436
+ 10, 10, /* 0,1 */
22437
+ 9, 9, /* 2,3 */
22438
+ 8, 8, /* 4,5 */
22439
+ 7, 7, 7, /* 6,7,8 */
22440
+ 6, 6, 6, /* 9,10,11 */
22441
+ 5, 5, 5, /* 12-14 */
22442
+ 4, 4, 4, 4, /* 15-18 */
22443
+ 3, 3, 3, 3, 3, 3, /* 19-24 */
22444
+ 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
22445
+ };
22446
+ if( a>=b ){
22447
+ if( a>b+49 ) return a;
22448
+ if( a>b+31 ) return a+1;
22449
+ return a+x[a-b];
22450
+ }else{
22451
+ if( b>a+49 ) return b;
22452
+ if( b>a+31 ) return b+1;
22453
+ return b+x[b-a];
22454
+ }
22455
+}
22456
+
22457
+/*
22458
+** Convert an integer into a LogEst. In other words, compute a
22459
+** good approximatation for 10*log2(x).
22460
+*/
22461
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
22462
+ static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
22463
+ LogEst y = 40;
22464
+ if( x<8 ){
22465
+ if( x<2 ) return 0;
22466
+ while( x<8 ){ y -= 10; x <<= 1; }
22467
+ }else{
22468
+ while( x>255 ){ y += 40; x >>= 4; }
22469
+ while( x>15 ){ y += 10; x >>= 1; }
22470
+ }
22471
+ return a[x&7] + y - 10;
22472
+}
22473
+
22474
+#ifndef SQLITE_OMIT_VIRTUALTABLE
22475
+/*
22476
+** Convert a double into a LogEst
22477
+** In other words, compute an approximation for 10*log2(x).
22478
+*/
22479
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
22480
+ u64 a;
22481
+ LogEst e;
22482
+ assert( sizeof(x)==8 && sizeof(a)==8 );
22483
+ if( x<=1 ) return 0;
22484
+ if( x<=2000000000 ) return sqlite3LogEst((u64)x);
22485
+ memcpy(&a, &x, 8);
22486
+ e = (a>>52) - 1022;
22487
+ return e*10;
22488
+}
22489
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
22490
+
22491
+/*
22492
+** Convert a LogEst into an integer.
22493
+*/
22494
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
22495
+ u64 n;
22496
+ if( x<10 ) return 1;
22497
+ n = x%10;
22498
+ x /= 10;
22499
+ if( n>=5 ) n -= 2;
22500
+ else if( n>=1 ) n -= 1;
22501
+ if( x>=3 ) return (n+8)<<(x-3);
22502
+ return (n+8)>>(3-x);
22503
+}
2239222504
2239322505
/************** End of util.c ************************************************/
2239422506
/************** Begin file hash.c ********************************************/
2239522507
/*
2239622508
** 2001 September 22
@@ -48986,17 +49098,17 @@
4898649098
** page contain a special header (the "file header") that describes the file.
4898749099
** The format of the file header is as follows:
4898849100
**
4898949101
** OFFSET SIZE DESCRIPTION
4899049102
** 0 16 Header string: "SQLite format 3\000"
48991
-** 16 2 Page size in bytes.
49103
+** 16 2 Page size in bytes. (1 means 65536)
4899249104
** 18 1 File format write version
4899349105
** 19 1 File format read version
4899449106
** 20 1 Bytes of unused space at the end of each page
48995
-** 21 1 Max embedded payload fraction
48996
-** 22 1 Min embedded payload fraction
48997
-** 23 1 Min leaf payload fraction
49107
+** 21 1 Max embedded payload fraction (must be 64)
49108
+** 22 1 Min embedded payload fraction (must be 32)
49109
+** 23 1 Min leaf payload fraction (must be 32)
4899849110
** 24 4 File change counter
4899949111
** 28 4 Reserved for future use
4900049112
** 32 4 First freelist page
4900149113
** 36 4 Number of freelist pages in the file
4900249114
** 40 60 15 4-byte meta values passed to higher layers
@@ -49006,13 +49118,14 @@
4900649118
** 48 4 Size of page cache
4900749119
** 52 4 Largest root-page (auto/incr_vacuum)
4900849120
** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
4900949121
** 60 4 User version
4901049122
** 64 4 Incremental vacuum mode
49011
-** 68 4 unused
49012
-** 72 4 unused
49013
-** 76 4 unused
49123
+** 68 4 Application-ID
49124
+** 72 20 unused
49125
+** 92 4 The version-valid-for number
49126
+** 96 4 SQLITE_VERSION_NUMBER
4901449127
**
4901549128
** All of the integer values are big-endian (most significant byte first).
4901649129
**
4901749130
** The file change counter is incremented when the database is changed
4901849131
** This counter allows other processes to know when the file has changed
@@ -52378,11 +52491,10 @@
5237852491
pBt->max1bytePayload = (u8)pBt->maxLocal;
5237952492
}
5238052493
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
5238152494
pBt->pPage1 = pPage1;
5238252495
pBt->nPage = nPage;
52383
-assert( pPage1->leaf==0 || pPage1->leaf==1 );
5238452496
return SQLITE_OK;
5238552497
5238652498
page1_init_failed:
5238752499
releasePage(pPage1);
5238852500
pBt->pPage1 = 0;
@@ -52538,11 +52650,11 @@
5253852650
** is requested, this is a no-op.
5253952651
*/
5254052652
if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
5254152653
goto trans_begun;
5254252654
}
52543
- assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
52655
+ assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
5254452656
5254552657
/* Write transactions are not possible on a read-only database */
5254652658
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
5254752659
rc = SQLITE_READONLY;
5254852660
goto trans_begun;
@@ -62977,10 +63089,11 @@
6297763089
}
6297863090
fclose(out);
6297963091
}
6298063092
}
6298163093
#endif
63094
+ p->iCurrentTime = 0;
6298263095
p->magic = VDBE_MAGIC_INIT;
6298363096
return p->rc & db->errMask;
6298463097
}
6298563098
6298663099
/*
@@ -76082,11 +76195,11 @@
7608276195
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
7608376196
}
7608476197
#ifndef SQLITE_OMIT_CAST
7608576198
if( op==TK_CAST ){
7608676199
assert( !ExprHasProperty(pExpr, EP_IntValue) );
76087
- return sqlite3AffinityType(pExpr->u.zToken);
76200
+ return sqlite3AffinityType(pExpr->u.zToken, 0);
7608876201
}
7608976202
#endif
7609076203
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
7609176204
&& pExpr->pTab!=0
7609276205
){
@@ -78502,11 +78615,11 @@
7850278615
case TK_CAST: {
7850378616
/* Expressions of the form: CAST(pLeft AS token) */
7850478617
int aff, to_op;
7850578618
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
7850678619
assert( !ExprHasProperty(pExpr, EP_IntValue) );
78507
- aff = sqlite3AffinityType(pExpr->u.zToken);
78620
+ aff = sqlite3AffinityType(pExpr->u.zToken, 0);
7850878621
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
7850978622
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
7851078623
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
7851178624
assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
7851278625
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
@@ -79169,11 +79282,11 @@
7916979282
}
7917079283
#ifndef SQLITE_OMIT_CAST
7917179284
case TK_CAST: {
7917279285
/* Expressions of the form: CAST(pLeft AS token) */
7917379286
const char *zAff = "unk";
79174
- switch( sqlite3AffinityType(pExpr->u.zToken) ){
79287
+ switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
7917579288
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
7917679289
case SQLITE_AFF_NONE: zAff = "NONE"; break;
7917779290
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
7917879291
case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
7917979292
case SQLITE_AFF_REAL: zAff = "REAL"; break;
@@ -81884,16 +81997,16 @@
8188481997
if( zRet==0 ){
8188581998
sqlite3_result_error_nomem(context);
8188681999
return;
8188782000
}
8188882001
81889
- sqlite3_snprintf(24, zRet, "%lld", p->nRow);
82002
+ sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
8189082003
z = zRet + sqlite3Strlen30(zRet);
8189182004
for(i=0; i<(p->nCol-1); i++){
81892
- i64 nDistinct = p->current.anDLt[i] + 1;
81893
- i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
81894
- sqlite3_snprintf(24, z, " %lld", iVal);
82005
+ u64 nDistinct = p->current.anDLt[i] + 1;
82006
+ u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
82007
+ sqlite3_snprintf(24, z, " %llu", iVal);
8189582008
z += sqlite3Strlen30(z);
8189682009
assert( p->current.anEq[i] );
8189782010
}
8189882011
assert( z[0]=='\0' && z>zRet );
8189982012
@@ -81930,11 +82043,11 @@
8193082043
sqlite3_result_error_nomem(context);
8193182044
}else{
8193282045
int i;
8193382046
char *z = zRet;
8193482047
for(i=0; i<p->nCol; i++){
81935
- sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
82048
+ sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
8193682049
z += sqlite3Strlen30(z);
8193782050
}
8193882051
assert( z[0]=='\0' && z>zRet );
8193982052
z[-1] = '\0';
8194082053
sqlite3_result_text(context, zRet, -1, sqlite3_free);
@@ -82391,22 +82504,20 @@
8239182504
** The first argument points to a nul-terminated string containing a
8239282505
** list of space separated integers. Read the first nOut of these into
8239382506
** the array aOut[].
8239482507
*/
8239582508
static void decodeIntArray(
82396
- char *zIntArray,
82397
- int nOut,
82398
- tRowcnt *aOut,
82399
- int *pbUnordered
82509
+ char *zIntArray, /* String containing int array to decode */
82510
+ int nOut, /* Number of slots in aOut[] */
82511
+ tRowcnt *aOut, /* Store integers here */
82512
+ Index *pIndex /* Handle extra flags for this index, if not NULL */
8240082513
){
8240182514
char *z = zIntArray;
8240282515
int c;
8240382516
int i;
8240482517
tRowcnt v;
8240582518
82406
- assert( pbUnordered==0 || *pbUnordered==0 );
82407
-
8240882519
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
8240982520
if( z==0 ) z = "";
8241082521
#else
8241182522
if( NEVER(z==0) ) z = "";
8241282523
#endif
@@ -82417,12 +82528,23 @@
8241782528
z++;
8241882529
}
8241982530
aOut[i] = v;
8242082531
if( *z==' ' ) z++;
8242182532
}
82422
- if( pbUnordered && strcmp(z, "unordered")==0 ){
82423
- *pbUnordered = 1;
82533
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
82534
+ assert( pIndex!=0 );
82535
+#else
82536
+ if( pIndex )
82537
+#endif
82538
+ {
82539
+ if( strcmp(z, "unordered")==0 ){
82540
+ pIndex->bUnordered = 1;
82541
+ }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
82542
+ int v32 = 0;
82543
+ sqlite3GetInt32(z+3, &v32);
82544
+ pIndex->szIdxRow = sqlite3LogEst(v32);
82545
+ }
8242482546
}
8242582547
}
8242682548
8242782549
/*
8242882550
** This callback is invoked once for each index when reading the
@@ -82457,16 +82579,17 @@
8245782579
pIndex = 0;
8245882580
}
8245982581
z = argv[2];
8246082582
8246182583
if( pIndex ){
82462
- int bUnordered = 0;
82463
- decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered);
82584
+ decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex);
8246482585
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
82465
- pIndex->bUnordered = bUnordered;
8246682586
}else{
82467
- decodeIntArray((char*)z, 1, &pTable->nRowEst, 0);
82587
+ Index fakeIdx;
82588
+ fakeIdx.szIdxRow = pTable->szTabRow;
82589
+ decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
82590
+ pTable->szTabRow = fakeIdx.szIdxRow;
8246882591
}
8246982592
8247082593
return 0;
8247182594
}
8247282595
@@ -83185,32 +83308,28 @@
8318583308
#endif /* SQLITE_OMIT_ATTACH */
8318683309
8318783310
/*
8318883311
** Initialize a DbFixer structure. This routine must be called prior
8318983312
** to passing the structure to one of the sqliteFixAAAA() routines below.
83190
-**
83191
-** The return value indicates whether or not fixation is required. TRUE
83192
-** means we do need to fix the database references, FALSE means we do not.
8319383313
*/
83194
-SQLITE_PRIVATE int sqlite3FixInit(
83314
+SQLITE_PRIVATE void sqlite3FixInit(
8319583315
DbFixer *pFix, /* The fixer to be initialized */
8319683316
Parse *pParse, /* Error messages will be written here */
8319783317
int iDb, /* This is the database that must be used */
8319883318
const char *zType, /* "view", "trigger", or "index" */
8319983319
const Token *pName /* Name of the view, trigger, or index */
8320083320
){
8320183321
sqlite3 *db;
8320283322
83203
- if( NEVER(iDb<0) || iDb==1 ) return 0;
8320483323
db = pParse->db;
8320583324
assert( db->nDb>iDb );
8320683325
pFix->pParse = pParse;
8320783326
pFix->zDb = db->aDb[iDb].zName;
8320883327
pFix->pSchema = db->aDb[iDb].pSchema;
8320983328
pFix->zType = zType;
8321083329
pFix->pName = pName;
83211
- return 1;
83330
+ pFix->bVarOnly = (iDb==1);
8321283331
}
8321383332
8321483333
/*
8321583334
** The following set of routines walk through the parse tree and assign
8321683335
** a specific database to all table references where the database name
@@ -83234,19 +83353,21 @@
8323483353
struct SrcList_item *pItem;
8323583354
8323683355
if( NEVER(pList==0) ) return 0;
8323783356
zDb = pFix->zDb;
8323883357
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
83239
- if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83240
- sqlite3ErrorMsg(pFix->pParse,
83241
- "%s %T cannot reference objects in database %s",
83242
- pFix->zType, pFix->pName, pItem->zDatabase);
83243
- return 1;
83244
- }
83245
- sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83246
- pItem->zDatabase = 0;
83247
- pItem->pSchema = pFix->pSchema;
83358
+ if( pFix->bVarOnly==0 ){
83359
+ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83360
+ sqlite3ErrorMsg(pFix->pParse,
83361
+ "%s %T cannot reference objects in database %s",
83362
+ pFix->zType, pFix->pName, pItem->zDatabase);
83363
+ return 1;
83364
+ }
83365
+ sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83366
+ pItem->zDatabase = 0;
83367
+ pItem->pSchema = pFix->pSchema;
83368
+ }
8324883369
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
8324983370
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
8325083371
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
8325183372
#endif
8325283373
}
@@ -83264,13 +83385,25 @@
8326483385
if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
8326583386
return 1;
8326683387
}
8326783388
if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
8326883389
return 1;
83390
+ }
83391
+ if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
83392
+ return 1;
8326983393
}
8327083394
if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
8327183395
return 1;
83396
+ }
83397
+ if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
83398
+ return 1;
83399
+ }
83400
+ if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
83401
+ return 1;
83402
+ }
83403
+ if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
83404
+ return 1;
8327283405
}
8327383406
pSelect = pSelect->pPrior;
8327483407
}
8327583408
return 0;
8327683409
}
@@ -83277,10 +83410,18 @@
8327783410
SQLITE_PRIVATE int sqlite3FixExpr(
8327883411
DbFixer *pFix, /* Context of the fixation */
8327983412
Expr *pExpr /* The expression to be fixed to one database */
8328083413
){
8328183414
while( pExpr ){
83415
+ if( pExpr->op==TK_VARIABLE ){
83416
+ if( pFix->pParse->db->init.busy ){
83417
+ pExpr->op = TK_NULL;
83418
+ }else{
83419
+ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
83420
+ return 1;
83421
+ }
83422
+ }
8328283423
if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
8328383424
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
8328483425
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
8328583426
}else{
8328683427
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
@@ -84460,11 +84601,11 @@
8446084601
}
8446184602
pTable->zName = zName;
8446284603
pTable->iPKey = -1;
8446384604
pTable->pSchema = db->aDb[iDb].pSchema;
8446484605
pTable->nRef = 1;
84465
- pTable->nRowEst = 1000000;
84606
+ pTable->nRowEst = 1048576;
8446684607
assert( pParse->pNewTable==0 );
8446784608
pParse->pNewTable = pTable;
8446884609
8446984610
/* If this is the magic sqlite_sequence table used by autoincrement,
8447084611
** then record a pointer to this table in the main database structure
@@ -84607,10 +84748,11 @@
8460784748
/* If there is no type specified, columns have the default affinity
8460884749
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
8460984750
** be called next to set pCol->affinity correctly.
8461084751
*/
8461184752
pCol->affinity = SQLITE_AFF_NONE;
84753
+ pCol->szEst = 1;
8461284754
p->nCol++;
8461384755
}
8461484756
8461584757
/*
8461684758
** This routine is called by the parser while in the middle of
@@ -84648,26 +84790,30 @@
8464884790
** 'DOUB' | SQLITE_AFF_REAL
8464984791
**
8465084792
** If none of the substrings in the above table are found,
8465184793
** SQLITE_AFF_NUMERIC is returned.
8465284794
*/
84653
-SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
84795
+SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
8465484796
u32 h = 0;
8465584797
char aff = SQLITE_AFF_NUMERIC;
84798
+ const char *zChar = 0;
8465684799
84657
- if( zIn ) while( zIn[0] ){
84800
+ if( zIn==0 ) return aff;
84801
+ while( zIn[0] ){
8465884802
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
8465984803
zIn++;
8466084804
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
84661
- aff = SQLITE_AFF_TEXT;
84805
+ aff = SQLITE_AFF_TEXT;
84806
+ zChar = zIn;
8466284807
}else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
8466384808
aff = SQLITE_AFF_TEXT;
8466484809
}else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
8466584810
aff = SQLITE_AFF_TEXT;
8466684811
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
8466784812
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
8466884813
aff = SQLITE_AFF_NONE;
84814
+ if( zIn[0]=='(' ) zChar = zIn;
8466984815
#ifndef SQLITE_OMIT_FLOATING_POINT
8467084816
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
8467184817
&& aff==SQLITE_AFF_NUMERIC ){
8467284818
aff = SQLITE_AFF_REAL;
8467384819
}else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
@@ -84681,10 +84827,32 @@
8468184827
aff = SQLITE_AFF_INTEGER;
8468284828
break;
8468384829
}
8468484830
}
8468584831
84832
+ /* If pszEst is not NULL, store an estimate of the field size. The
84833
+ ** estimate is scaled so that the size of an integer is 1. */
84834
+ if( pszEst ){
84835
+ *pszEst = 1; /* default size is approx 4 bytes */
84836
+ if( aff<=SQLITE_AFF_NONE ){
84837
+ if( zChar ){
84838
+ while( zChar[0] ){
84839
+ if( sqlite3Isdigit(zChar[0]) ){
84840
+ int v;
84841
+ sqlite3GetInt32(zChar, &v);
84842
+ v = v/4 + 1;
84843
+ if( v>255 ) v = 255;
84844
+ *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
84845
+ break;
84846
+ }
84847
+ zChar++;
84848
+ }
84849
+ }else{
84850
+ *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
84851
+ }
84852
+ }
84853
+ }
8468684854
return aff;
8468784855
}
8468884856
8468984857
/*
8469084858
** This routine is called by the parser while in the middle of
@@ -84702,11 +84870,11 @@
8470284870
p = pParse->pNewTable;
8470384871
if( p==0 || NEVER(p->nCol<1) ) return;
8470484872
pCol = &p->aCol[p->nCol-1];
8470584873
assert( pCol->zType==0 );
8470684874
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
84707
- pCol->affinity = sqlite3AffinityType(pCol->zType);
84875
+ pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
8470884876
}
8470984877
8471084878
/*
8471184879
** The expression is the default value for the most recently added column
8471284880
** of the table currently under construction.
@@ -85050,18 +85218,46 @@
8505085218
testcase( pCol->affinity==SQLITE_AFF_REAL );
8505185219
8505285220
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
8505385221
len = sqlite3Strlen30(zType);
8505485222
assert( pCol->affinity==SQLITE_AFF_NONE
85055
- || pCol->affinity==sqlite3AffinityType(zType) );
85223
+ || pCol->affinity==sqlite3AffinityType(zType, 0) );
8505685224
memcpy(&zStmt[k], zType, len);
8505785225
k += len;
8505885226
assert( k<=n );
8505985227
}
8506085228
sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
8506185229
return zStmt;
8506285230
}
85231
+
85232
+/*
85233
+** Estimate the total row width for a table.
85234
+*/
85235
+static void estimateTableWidth(Table *pTab){
85236
+ unsigned wTable = 0;
85237
+ const Column *pTabCol;
85238
+ int i;
85239
+ for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
85240
+ wTable += pTabCol->szEst;
85241
+ }
85242
+ if( pTab->iPKey<0 ) wTable++;
85243
+ pTab->szTabRow = sqlite3LogEst(wTable*4);
85244
+}
85245
+
85246
+/*
85247
+** Estimate the average size of a row for an index.
85248
+*/
85249
+static void estimateIndexWidth(Index *pIdx){
85250
+ unsigned wIndex = 1;
85251
+ int i;
85252
+ const Column *aCol = pIdx->pTable->aCol;
85253
+ for(i=0; i<pIdx->nColumn; i++){
85254
+ assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol );
85255
+ wIndex += aCol[pIdx->aiColumn[i]].szEst;
85256
+ }
85257
+ pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
85258
+}
8506385259
8506485260
/*
8506585261
** This routine is called to report the final ")" that terminates
8506685262
** a CREATE TABLE statement.
8506785263
**
@@ -85085,13 +85281,14 @@
8508585281
Parse *pParse, /* Parse context */
8508685282
Token *pCons, /* The ',' token after the last column defn. */
8508785283
Token *pEnd, /* The final ')' token in the CREATE TABLE */
8508885284
Select *pSelect /* Select from a "CREATE ... AS SELECT" */
8508985285
){
85090
- Table *p;
85091
- sqlite3 *db = pParse->db;
85092
- int iDb;
85286
+ Table *p; /* The new table */
85287
+ sqlite3 *db = pParse->db; /* The database connection */
85288
+ int iDb; /* Database in which the table lives */
85289
+ Index *pIdx; /* An implied index of the table */
8509385290
8509485291
if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
8509585292
return;
8509685293
}
8509785294
p = pParse->pNewTable;
@@ -85106,10 +85303,16 @@
8510685303
*/
8510785304
if( p->pCheck ){
8510885305
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
8510985306
}
8511085307
#endif /* !defined(SQLITE_OMIT_CHECK) */
85308
+
85309
+ /* Estimate the average row size for the table and for all implied indices */
85310
+ estimateTableWidth(p);
85311
+ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
85312
+ estimateIndexWidth(pIdx);
85313
+ }
8511185314
8511285315
/* If the db->init.busy is 1 it means we are reading the SQL off the
8511385316
** "sqlite_master" or "sqlite_temp_master" table on the disk.
8511485317
** So do not write to the disk again. Extract the root page number
8511585318
** for the table from the db->init.newTnum field. (The page number
@@ -85303,13 +85506,12 @@
8530385506
sqlite3SelectDelete(db, pSelect);
8530485507
return;
8530585508
}
8530685509
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
8530785510
iDb = sqlite3SchemaToIndex(db, p->pSchema);
85308
- if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
85309
- && sqlite3FixSelect(&sFix, pSelect)
85310
- ){
85511
+ sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
85512
+ if( sqlite3FixSelect(&sFix, pSelect) ){
8531185513
sqlite3SelectDelete(db, pSelect);
8531285514
return;
8531385515
}
8531485516
8531585517
/* Make a copy of the entire SELECT statement that defines the view.
@@ -86066,13 +86268,14 @@
8606686268
sqlite3 *db = pParse->db;
8606786269
Db *pDb; /* The specific table containing the indexed database */
8606886270
int iDb; /* Index of the database that is being written */
8606986271
Token *pName = 0; /* Unqualified name of the index to create */
8607086272
struct ExprList_item *pListItem; /* For looping over pList */
86071
- int nCol;
86072
- int nExtra = 0;
86073
- char *zExtra;
86273
+ const Column *pTabCol; /* A column in the table */
86274
+ int nCol; /* Number of columns */
86275
+ int nExtra = 0; /* Space allocated for zExtra[] */
86276
+ char *zExtra; /* Extra space after the Index object */
8607486277
8607586278
assert( pParse->nErr==0 ); /* Never called with prior errors */
8607686279
if( db->mallocFailed || IN_DECLARE_VTAB ){
8607786280
goto exit_create_index;
8607886281
}
@@ -86105,13 +86308,12 @@
8610586308
iDb = 1;
8610686309
}
8610786310
}
8610886311
#endif
8610986312
86110
- if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
86111
- sqlite3FixSrcList(&sFix, pTblName)
86112
- ){
86313
+ sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
86314
+ if( sqlite3FixSrcList(&sFix, pTblName) ){
8611386315
/* Because the parser constructs pTblName from a single identifier,
8611486316
** sqlite3FixSrcList can never fail. */
8611586317
assert(0);
8611686318
}
8611786319
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
@@ -86296,11 +86498,10 @@
8629686498
** same column more than once cannot be an error because that would
8629786499
** break backwards compatibility - it needs to be a warning.
8629886500
*/
8629986501
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
8630086502
const char *zColName = pListItem->zName;
86301
- Column *pTabCol;
8630286503
int requestedSortOrder;
8630386504
char *zColl; /* Collation sequence name */
8630486505
8630586506
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
8630686507
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -86333,10 +86534,11 @@
8633386534
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
8633486535
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
8633586536
if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
8633686537
}
8633786538
sqlite3DefaultRowEst(pIndex);
86539
+ if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
8633886540
8633986541
if( pTab==pParse->pNewTable ){
8634086542
/* This routine has been called to create an automatic index as a
8634186543
** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
8634286544
** a PRIMARY KEY or UNIQUE clause following the column definitions.
@@ -88238,10 +88440,11 @@
8823888440
** API function sqlite3_count_changes) to be set incorrectly. */
8823988441
if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
8824088442
&& 0==sqlite3FkRequired(pParse, pTab, 0, 0)
8824188443
){
8824288444
assert( !isView );
88445
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
8824388446
sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
8824488447
pTab->zName, P4_STATIC);
8824588448
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
8824688449
assert( pIdx->pSchema==pTab->pSchema );
8824788450
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -93487,10 +93690,11 @@
9348793690
(char*)pKey, P4_KEYINFO_HANDOFF);
9348893691
VdbeComment((v, "%s", pSrcIdx->zName));
9348993692
pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
9349093693
sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
9349193694
(char*)pKey, P4_KEYINFO_HANDOFF);
93695
+ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
9349293696
VdbeComment((v, "%s", pDestIdx->zName));
9349393697
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
9349493698
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
9349593699
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
9349693700
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
@@ -94974,181 +95178,363 @@
9497495178
#define PragTyp_HEXKEY 35
9497595179
#define PragTyp_KEY 36
9497695180
#define PragTyp_REKEY 37
9497795181
#define PragTyp_LOCK_STATUS 38
9497895182
#define PragTyp_PARSER_TRACE 39
95183
+#define PragFlag_NeedSchema 0x01
9497995184
static const struct sPragmaNames {
9498095185
const char *const zName; /* Name of pragma */
9498195186
u8 ePragTyp; /* PragTyp_XXX value */
95187
+ u8 mPragFlag; /* Zero or more PragFlag_XXX values */
9498295188
u32 iArg; /* Extra argument */
9498395189
} aPragmaNames[] = {
9498495190
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
94985
- { "activate_extensions", PragTyp_ACTIVATE_EXTENSIONS, 0 },
95191
+ { /* zName: */ "activate_extensions",
95192
+ /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
95193
+ /* ePragFlag: */ 0,
95194
+ /* iArg: */ 0 },
9498695195
#endif
9498795196
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
94988
- { "application_id", PragTyp_HEADER_VALUE, 0 },
95197
+ { /* zName: */ "application_id",
95198
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95199
+ /* ePragFlag: */ 0,
95200
+ /* iArg: */ 0 },
9498995201
#endif
9499095202
#if !defined(SQLITE_OMIT_AUTOVACUUM)
94991
- { "auto_vacuum", PragTyp_AUTO_VACUUM, 0 },
95203
+ { /* zName: */ "auto_vacuum",
95204
+ /* ePragTyp: */ PragTyp_AUTO_VACUUM,
95205
+ /* ePragFlag: */ PragFlag_NeedSchema,
95206
+ /* iArg: */ 0 },
9499295207
#endif
9499395208
#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
94994
- { "automatic_index", PragTyp_FLAG,
94995
- SQLITE_AutoIndex },
95209
+ { /* zName: */ "automatic_index",
95210
+ /* ePragTyp: */ PragTyp_FLAG,
95211
+ /* ePragFlag: */ 0,
95212
+ /* iArg: */ SQLITE_AutoIndex },
9499695213
#endif
94997
- { "busy_timeout", PragTyp_BUSY_TIMEOUT, 0 },
95214
+ { /* zName: */ "busy_timeout",
95215
+ /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
95216
+ /* ePragFlag: */ 0,
95217
+ /* iArg: */ 0 },
9499895218
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
94999
- { "cache_size", PragTyp_CACHE_SIZE, 0 },
95219
+ { /* zName: */ "cache_size",
95220
+ /* ePragTyp: */ PragTyp_CACHE_SIZE,
95221
+ /* ePragFlag: */ PragFlag_NeedSchema,
95222
+ /* iArg: */ 0 },
9500095223
#endif
95001
- { "cache_spill", PragTyp_FLAG,
95002
- SQLITE_CacheSpill },
95003
- { "case_sensitive_like", PragTyp_CASE_SENSITIVE_LIKE, 0 },
95004
- { "checkpoint_fullfsync", PragTyp_FLAG,
95005
- SQLITE_CkptFullFSync },
95224
+ { /* zName: */ "cache_spill",
95225
+ /* ePragTyp: */ PragTyp_FLAG,
95226
+ /* ePragFlag: */ 0,
95227
+ /* iArg: */ SQLITE_CacheSpill },
95228
+ { /* zName: */ "case_sensitive_like",
95229
+ /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
95230
+ /* ePragFlag: */ 0,
95231
+ /* iArg: */ 0 },
95232
+ { /* zName: */ "checkpoint_fullfsync",
95233
+ /* ePragTyp: */ PragTyp_FLAG,
95234
+ /* ePragFlag: */ 0,
95235
+ /* iArg: */ SQLITE_CkptFullFSync },
9500695236
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95007
- { "collation_list", PragTyp_COLLATION_LIST, 0 },
95237
+ { /* zName: */ "collation_list",
95238
+ /* ePragTyp: */ PragTyp_COLLATION_LIST,
95239
+ /* ePragFlag: */ 0,
95240
+ /* iArg: */ 0 },
9500895241
#endif
9500995242
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
95010
- { "compile_options", PragTyp_COMPILE_OPTIONS, 0 },
95243
+ { /* zName: */ "compile_options",
95244
+ /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
95245
+ /* ePragFlag: */ 0,
95246
+ /* iArg: */ 0 },
9501195247
#endif
95012
- { "count_changes", PragTyp_FLAG,
95013
- SQLITE_CountRows },
95248
+ { /* zName: */ "count_changes",
95249
+ /* ePragTyp: */ PragTyp_FLAG,
95250
+ /* ePragFlag: */ 0,
95251
+ /* iArg: */ SQLITE_CountRows },
9501495252
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
95015
- { "data_store_directory", PragTyp_DATA_STORE_DIRECTORY, 0 },
95253
+ { /* zName: */ "data_store_directory",
95254
+ /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
95255
+ /* ePragFlag: */ 0,
95256
+ /* iArg: */ 0 },
9501695257
#endif
9501795258
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95018
- { "database_list", PragTyp_DATABASE_LIST, 0 },
95259
+ { /* zName: */ "database_list",
95260
+ /* ePragTyp: */ PragTyp_DATABASE_LIST,
95261
+ /* ePragFlag: */ PragFlag_NeedSchema,
95262
+ /* iArg: */ 0 },
9501995263
#endif
9502095264
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
95021
- { "default_cache_size", PragTyp_DEFAULT_CACHE_SIZE, 0 },
95265
+ { /* zName: */ "default_cache_size",
95266
+ /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
95267
+ /* ePragFlag: */ PragFlag_NeedSchema,
95268
+ /* iArg: */ 0 },
9502295269
#endif
9502395270
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95024
- { "defer_foreign_keys", PragTyp_FLAG,
95025
- SQLITE_DeferFKs },
95271
+ { /* zName: */ "defer_foreign_keys",
95272
+ /* ePragTyp: */ PragTyp_FLAG,
95273
+ /* ePragFlag: */ 0,
95274
+ /* iArg: */ SQLITE_DeferFKs },
9502695275
#endif
95027
- { "empty_result_callbacks", PragTyp_FLAG,
95028
- SQLITE_NullCallback },
95276
+ { /* zName: */ "empty_result_callbacks",
95277
+ /* ePragTyp: */ PragTyp_FLAG,
95278
+ /* ePragFlag: */ 0,
95279
+ /* iArg: */ SQLITE_NullCallback },
9502995280
#if !defined(SQLITE_OMIT_UTF16)
95030
- { "encoding", PragTyp_ENCODING, 0 },
95281
+ { /* zName: */ "encoding",
95282
+ /* ePragTyp: */ PragTyp_ENCODING,
95283
+ /* ePragFlag: */ 0,
95284
+ /* iArg: */ 0 },
9503195285
#endif
9503295286
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95033
- { "foreign_key_check", PragTyp_FOREIGN_KEY_CHECK, 0 },
95287
+ { /* zName: */ "foreign_key_check",
95288
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
95289
+ /* ePragFlag: */ PragFlag_NeedSchema,
95290
+ /* iArg: */ 0 },
9503495291
#endif
9503595292
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
95036
- { "foreign_key_list", PragTyp_FOREIGN_KEY_LIST, 0 },
95293
+ { /* zName: */ "foreign_key_list",
95294
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
95295
+ /* ePragFlag: */ PragFlag_NeedSchema,
95296
+ /* iArg: */ 0 },
9503795297
#endif
9503895298
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95039
- { "foreign_keys", PragTyp_FLAG,
95040
- SQLITE_ForeignKeys },
95299
+ { /* zName: */ "foreign_keys",
95300
+ /* ePragTyp: */ PragTyp_FLAG,
95301
+ /* ePragFlag: */ 0,
95302
+ /* iArg: */ SQLITE_ForeignKeys },
9504195303
#endif
9504295304
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95043
- { "freelist_count", PragTyp_HEADER_VALUE, 0 },
95305
+ { /* zName: */ "freelist_count",
95306
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95307
+ /* ePragFlag: */ 0,
95308
+ /* iArg: */ 0 },
9504495309
#endif
95045
- { "full_column_names", PragTyp_FLAG,
95046
- SQLITE_FullColNames },
95047
- { "fullfsync", PragTyp_FLAG,
95048
- SQLITE_FullFSync },
95310
+ { /* zName: */ "full_column_names",
95311
+ /* ePragTyp: */ PragTyp_FLAG,
95312
+ /* ePragFlag: */ 0,
95313
+ /* iArg: */ SQLITE_FullColNames },
95314
+ { /* zName: */ "fullfsync",
95315
+ /* ePragTyp: */ PragTyp_FLAG,
95316
+ /* ePragFlag: */ 0,
95317
+ /* iArg: */ SQLITE_FullFSync },
9504995318
#if defined(SQLITE_HAS_CODEC)
95050
- { "hexkey", PragTyp_HEXKEY, 0 },
95319
+ { /* zName: */ "hexkey",
95320
+ /* ePragTyp: */ PragTyp_HEXKEY,
95321
+ /* ePragFlag: */ 0,
95322
+ /* iArg: */ 0 },
95323
+ { /* zName: */ "hexrekey",
95324
+ /* ePragTyp: */ PragTyp_HEXKEY,
95325
+ /* ePragFlag: */ 0,
95326
+ /* iArg: */ 0 },
9505195327
#endif
9505295328
#if !defined(SQLITE_OMIT_CHECK)
95053
- { "ignore_check_constraints", PragTyp_FLAG,
95054
- SQLITE_IgnoreChecks },
95329
+ { /* zName: */ "ignore_check_constraints",
95330
+ /* ePragTyp: */ PragTyp_FLAG,
95331
+ /* ePragFlag: */ 0,
95332
+ /* iArg: */ SQLITE_IgnoreChecks },
9505595333
#endif
9505695334
#if !defined(SQLITE_OMIT_AUTOVACUUM)
95057
- { "incremental_vacuum", PragTyp_INCREMENTAL_VACUUM, 0 },
95335
+ { /* zName: */ "incremental_vacuum",
95336
+ /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
95337
+ /* ePragFlag: */ PragFlag_NeedSchema,
95338
+ /* iArg: */ 0 },
9505895339
#endif
9505995340
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95060
- { "index_info", PragTyp_INDEX_INFO, 0 },
95061
- { "index_list", PragTyp_INDEX_LIST, 0 },
95341
+ { /* zName: */ "index_info",
95342
+ /* ePragTyp: */ PragTyp_INDEX_INFO,
95343
+ /* ePragFlag: */ PragFlag_NeedSchema,
95344
+ /* iArg: */ 0 },
95345
+ { /* zName: */ "index_list",
95346
+ /* ePragTyp: */ PragTyp_INDEX_LIST,
95347
+ /* ePragFlag: */ PragFlag_NeedSchema,
95348
+ /* iArg: */ 0 },
9506295349
#endif
9506395350
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95064
- { "integrity_check", PragTyp_INTEGRITY_CHECK, 0 },
95351
+ { /* zName: */ "integrity_check",
95352
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95353
+ /* ePragFlag: */ PragFlag_NeedSchema,
95354
+ /* iArg: */ 0 },
9506595355
#endif
9506695356
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95067
- { "journal_mode", PragTyp_JOURNAL_MODE, 0 },
95068
- { "journal_size_limit", PragTyp_JOURNAL_SIZE_LIMIT, 0 },
95357
+ { /* zName: */ "journal_mode",
95358
+ /* ePragTyp: */ PragTyp_JOURNAL_MODE,
95359
+ /* ePragFlag: */ PragFlag_NeedSchema,
95360
+ /* iArg: */ 0 },
95361
+ { /* zName: */ "journal_size_limit",
95362
+ /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
95363
+ /* ePragFlag: */ 0,
95364
+ /* iArg: */ 0 },
9506995365
#endif
9507095366
#if defined(SQLITE_HAS_CODEC)
95071
- { "key", PragTyp_KEY, 0 },
95367
+ { /* zName: */ "key",
95368
+ /* ePragTyp: */ PragTyp_KEY,
95369
+ /* ePragFlag: */ 0,
95370
+ /* iArg: */ 0 },
9507295371
#endif
95073
- { "legacy_file_format", PragTyp_FLAG,
95074
- SQLITE_LegacyFileFmt },
95372
+ { /* zName: */ "legacy_file_format",
95373
+ /* ePragTyp: */ PragTyp_FLAG,
95374
+ /* ePragFlag: */ 0,
95375
+ /* iArg: */ SQLITE_LegacyFileFmt },
9507595376
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
95076
- { "lock_proxy_file", PragTyp_LOCK_PROXY_FILE, 0 },
95377
+ { /* zName: */ "lock_proxy_file",
95378
+ /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
95379
+ /* ePragFlag: */ 0,
95380
+ /* iArg: */ 0 },
9507795381
#endif
9507895382
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
95079
- { "lock_status", PragTyp_LOCK_STATUS, 0 },
95080
-#endif
95081
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95082
- { "locking_mode", PragTyp_LOCKING_MODE, 0 },
95083
- { "max_page_count", PragTyp_PAGE_COUNT, 0 },
95084
- { "mmap_size", PragTyp_MMAP_SIZE, 0 },
95085
- { "page_count", PragTyp_PAGE_COUNT, 0 },
95086
- { "page_size", PragTyp_PAGE_SIZE, 0 },
95087
-#endif
95088
-#if defined(SQLITE_DEBUG)
95089
- { "parser_trace", PragTyp_PARSER_TRACE, 0 },
95090
-#endif
95091
- { "query_only", PragTyp_FLAG,
95092
- SQLITE_QueryOnly },
95093
-#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95094
- { "quick_check", PragTyp_INTEGRITY_CHECK, 0 },
95095
-#endif
95096
- { "read_uncommitted", PragTyp_FLAG,
95097
- SQLITE_ReadUncommitted },
95098
- { "recursive_triggers", PragTyp_FLAG,
95099
- SQLITE_RecTriggers },
95100
-#if defined(SQLITE_HAS_CODEC)
95101
- { "rekey", PragTyp_REKEY, 0 },
95102
-#endif
95103
- { "reverse_unordered_selects", PragTyp_FLAG,
95104
- SQLITE_ReverseOrder },
95105
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95106
- { "schema_version", PragTyp_HEADER_VALUE, 0 },
95107
-#endif
95108
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95109
- { "secure_delete", PragTyp_SECURE_DELETE, 0 },
95110
-#endif
95111
- { "short_column_names", PragTyp_FLAG,
95112
- SQLITE_ShortColNames },
95113
- { "shrink_memory", PragTyp_SHRINK_MEMORY, 0 },
95114
- { "soft_heap_limit", PragTyp_SOFT_HEAP_LIMIT, 0 },
95115
-#if defined(SQLITE_DEBUG)
95116
- { "sql_trace", PragTyp_FLAG,
95117
- SQLITE_SqlTrace },
95118
-#endif
95119
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95120
- { "synchronous", PragTyp_SYNCHRONOUS, 0 },
95383
+ { /* zName: */ "lock_status",
95384
+ /* ePragTyp: */ PragTyp_LOCK_STATUS,
95385
+ /* ePragFlag: */ 0,
95386
+ /* iArg: */ 0 },
95387
+#endif
95388
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95389
+ { /* zName: */ "locking_mode",
95390
+ /* ePragTyp: */ PragTyp_LOCKING_MODE,
95391
+ /* ePragFlag: */ 0,
95392
+ /* iArg: */ 0 },
95393
+ { /* zName: */ "max_page_count",
95394
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
95395
+ /* ePragFlag: */ PragFlag_NeedSchema,
95396
+ /* iArg: */ 0 },
95397
+ { /* zName: */ "mmap_size",
95398
+ /* ePragTyp: */ PragTyp_MMAP_SIZE,
95399
+ /* ePragFlag: */ 0,
95400
+ /* iArg: */ 0 },
95401
+ { /* zName: */ "page_count",
95402
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
95403
+ /* ePragFlag: */ PragFlag_NeedSchema,
95404
+ /* iArg: */ 0 },
95405
+ { /* zName: */ "page_size",
95406
+ /* ePragTyp: */ PragTyp_PAGE_SIZE,
95407
+ /* ePragFlag: */ 0,
95408
+ /* iArg: */ 0 },
95409
+#endif
95410
+#if defined(SQLITE_DEBUG)
95411
+ { /* zName: */ "parser_trace",
95412
+ /* ePragTyp: */ PragTyp_PARSER_TRACE,
95413
+ /* ePragFlag: */ 0,
95414
+ /* iArg: */ 0 },
95415
+#endif
95416
+ { /* zName: */ "query_only",
95417
+ /* ePragTyp: */ PragTyp_FLAG,
95418
+ /* ePragFlag: */ 0,
95419
+ /* iArg: */ SQLITE_QueryOnly },
95420
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95421
+ { /* zName: */ "quick_check",
95422
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95423
+ /* ePragFlag: */ PragFlag_NeedSchema,
95424
+ /* iArg: */ 0 },
95425
+#endif
95426
+ { /* zName: */ "read_uncommitted",
95427
+ /* ePragTyp: */ PragTyp_FLAG,
95428
+ /* ePragFlag: */ 0,
95429
+ /* iArg: */ SQLITE_ReadUncommitted },
95430
+ { /* zName: */ "recursive_triggers",
95431
+ /* ePragTyp: */ PragTyp_FLAG,
95432
+ /* ePragFlag: */ 0,
95433
+ /* iArg: */ SQLITE_RecTriggers },
95434
+#if defined(SQLITE_HAS_CODEC)
95435
+ { /* zName: */ "rekey",
95436
+ /* ePragTyp: */ PragTyp_REKEY,
95437
+ /* ePragFlag: */ 0,
95438
+ /* iArg: */ 0 },
95439
+#endif
95440
+ { /* zName: */ "reverse_unordered_selects",
95441
+ /* ePragTyp: */ PragTyp_FLAG,
95442
+ /* ePragFlag: */ 0,
95443
+ /* iArg: */ SQLITE_ReverseOrder },
95444
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95445
+ { /* zName: */ "schema_version",
95446
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95447
+ /* ePragFlag: */ 0,
95448
+ /* iArg: */ 0 },
95449
+#endif
95450
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95451
+ { /* zName: */ "secure_delete",
95452
+ /* ePragTyp: */ PragTyp_SECURE_DELETE,
95453
+ /* ePragFlag: */ 0,
95454
+ /* iArg: */ 0 },
95455
+#endif
95456
+ { /* zName: */ "short_column_names",
95457
+ /* ePragTyp: */ PragTyp_FLAG,
95458
+ /* ePragFlag: */ 0,
95459
+ /* iArg: */ SQLITE_ShortColNames },
95460
+ { /* zName: */ "shrink_memory",
95461
+ /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
95462
+ /* ePragFlag: */ 0,
95463
+ /* iArg: */ 0 },
95464
+ { /* zName: */ "soft_heap_limit",
95465
+ /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
95466
+ /* ePragFlag: */ 0,
95467
+ /* iArg: */ 0 },
95468
+#if defined(SQLITE_DEBUG)
95469
+ { /* zName: */ "sql_trace",
95470
+ /* ePragTyp: */ PragTyp_FLAG,
95471
+ /* ePragFlag: */ 0,
95472
+ /* iArg: */ SQLITE_SqlTrace },
95473
+#endif
95474
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95475
+ { /* zName: */ "synchronous",
95476
+ /* ePragTyp: */ PragTyp_SYNCHRONOUS,
95477
+ /* ePragFlag: */ PragFlag_NeedSchema,
95478
+ /* iArg: */ 0 },
9512195479
#endif
9512295480
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95123
- { "table_info", PragTyp_TABLE_INFO, 0 },
95481
+ { /* zName: */ "table_info",
95482
+ /* ePragTyp: */ PragTyp_TABLE_INFO,
95483
+ /* ePragFlag: */ PragFlag_NeedSchema,
95484
+ /* iArg: */ 0 },
9512495485
#endif
9512595486
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95126
- { "temp_store", PragTyp_TEMP_STORE, 0 },
95127
- { "temp_store_directory", PragTyp_TEMP_STORE_DIRECTORY, 0 },
95487
+ { /* zName: */ "temp_store",
95488
+ /* ePragTyp: */ PragTyp_TEMP_STORE,
95489
+ /* ePragFlag: */ 0,
95490
+ /* iArg: */ 0 },
95491
+ { /* zName: */ "temp_store_directory",
95492
+ /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
95493
+ /* ePragFlag: */ 0,
95494
+ /* iArg: */ 0 },
9512895495
#endif
9512995496
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95130
- { "user_version", PragTyp_HEADER_VALUE, 0 },
95497
+ { /* zName: */ "user_version",
95498
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95499
+ /* ePragFlag: */ 0,
95500
+ /* iArg: */ 0 },
9513195501
#endif
9513295502
#if defined(SQLITE_DEBUG)
95133
- { "vdbe_addoptrace", PragTyp_FLAG,
95134
- SQLITE_VdbeAddopTrace },
95135
- { "vdbe_debug", PragTyp_FLAG,
95136
- SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95137
- { "vdbe_listing", PragTyp_FLAG,
95138
- SQLITE_VdbeListing },
95139
- { "vdbe_trace", PragTyp_FLAG,
95140
- SQLITE_VdbeTrace },
95503
+ { /* zName: */ "vdbe_addoptrace",
95504
+ /* ePragTyp: */ PragTyp_FLAG,
95505
+ /* ePragFlag: */ 0,
95506
+ /* iArg: */ SQLITE_VdbeAddopTrace },
95507
+ { /* zName: */ "vdbe_debug",
95508
+ /* ePragTyp: */ PragTyp_FLAG,
95509
+ /* ePragFlag: */ 0,
95510
+ /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95511
+ { /* zName: */ "vdbe_listing",
95512
+ /* ePragTyp: */ PragTyp_FLAG,
95513
+ /* ePragFlag: */ 0,
95514
+ /* iArg: */ SQLITE_VdbeListing },
95515
+ { /* zName: */ "vdbe_trace",
95516
+ /* ePragTyp: */ PragTyp_FLAG,
95517
+ /* ePragFlag: */ 0,
95518
+ /* iArg: */ SQLITE_VdbeTrace },
9514195519
#endif
9514295520
#if !defined(SQLITE_OMIT_WAL)
95143
- { "wal_autocheckpoint", PragTyp_WAL_AUTOCHECKPOINT, 0 },
95144
- { "wal_checkpoint", PragTyp_WAL_CHECKPOINT, 0 },
95521
+ { /* zName: */ "wal_autocheckpoint",
95522
+ /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
95523
+ /* ePragFlag: */ 0,
95524
+ /* iArg: */ 0 },
95525
+ { /* zName: */ "wal_checkpoint",
95526
+ /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
95527
+ /* ePragFlag: */ PragFlag_NeedSchema,
95528
+ /* iArg: */ 0 },
9514595529
#endif
95146
- { "writable_schema", PragTyp_FLAG,
95147
- SQLITE_WriteSchema|SQLITE_RecoveryMode },
95530
+ { /* zName: */ "writable_schema",
95531
+ /* ePragTyp: */ PragTyp_FLAG,
95532
+ /* ePragFlag: */ 0,
95533
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
9514895534
};
95149
-/* Number of pragmas: 55 on by default, 66 total. */
95535
+/* Number of pragmas: 55 on by default, 67 total. */
9515095536
/* End of the automatically generated pragma table.
9515195537
***************************************************************************/
9515295538
9515395539
/*
9515495540
** Interpret the given string as a safety level. Return 0 for OFF,
@@ -95476,10 +95862,15 @@
9547695862
}else{
9547795863
lwr = mid + 1;
9547895864
}
9547995865
}
9548095866
if( lwr>upr ) goto pragma_out;
95867
+
95868
+ /* Make sure the database schema is loaded if the pragma requires that */
95869
+ if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
95870
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95871
+ }
9548195872
9548295873
/* Jump to the appropriate pragma handler */
9548395874
switch( aPragmaNames[mid].ePragTyp ){
9548495875
9548595876
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -95510,11 +95901,10 @@
9551095901
{ OP_Integer, 0, 1, 0}, /* 6 */
9551195902
{ OP_Noop, 0, 0, 0},
9551295903
{ OP_ResultRow, 1, 1, 0},
9551395904
};
9551495905
int addr;
95515
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9551695906
sqlite3VdbeUsesBtree(v, iDb);
9551795907
if( !zRight ){
9551895908
sqlite3VdbeSetNumCols(v, 1);
9551995909
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
9552095910
pParse->nMem += 2;
@@ -95606,11 +95996,10 @@
9560695996
**
9560795997
** Return the number of pages in the specified database.
9560895998
*/
9560995999
case PragTyp_PAGE_COUNT: {
9561096000
int iReg;
95611
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9561296001
sqlite3CodeVerifySchema(pParse, iDb);
9561396002
iReg = ++pParse->nMem;
9561496003
if( sqlite3Tolower(zLeft[0])=='p' ){
9561596004
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
9561696005
}else{
@@ -95679,18 +96068,10 @@
9567996068
*/
9568096069
case PragTyp_JOURNAL_MODE: {
9568196070
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
9568296071
int ii; /* Loop counter */
9568396072
95684
- /* Force the schema to be loaded on all databases. This causes all
95685
- ** database files to be opened and the journal_modes set. This is
95686
- ** necessary because subsequent processing must know if the databases
95687
- ** are in WAL mode. */
95688
- if( sqlite3ReadSchema(pParse) ){
95689
- goto pragma_out;
95690
- }
95691
-
9569296073
sqlite3VdbeSetNumCols(v, 1);
9569396074
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
9569496075
9569596076
if( zRight==0 ){
9569696077
/* If there is no "=MODE" part of the pragma, do a query for the
@@ -95752,55 +96133,44 @@
9575296133
*/
9575396134
#ifndef SQLITE_OMIT_AUTOVACUUM
9575496135
case PragTyp_AUTO_VACUUM: {
9575596136
Btree *pBt = pDb->pBt;
9575696137
assert( pBt!=0 );
95757
- if( sqlite3ReadSchema(pParse) ){
95758
- goto pragma_out;
95759
- }
9576096138
if( !zRight ){
95761
- int auto_vacuum;
95762
- if( ALWAYS(pBt) ){
95763
- auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
95764
- }else{
95765
- auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
95766
- }
95767
- returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
96139
+ returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
9576896140
}else{
9576996141
int eAuto = getAutoVacuum(zRight);
9577096142
assert( eAuto>=0 && eAuto<=2 );
9577196143
db->nextAutovac = (u8)eAuto;
95772
- if( ALWAYS(eAuto>=0) ){
95773
- /* Call SetAutoVacuum() to set initialize the internal auto and
95774
- ** incr-vacuum flags. This is required in case this connection
95775
- ** creates the database file. It is important that it is created
95776
- ** as an auto-vacuum capable db.
95777
- */
95778
- rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
95779
- if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
95780
- /* When setting the auto_vacuum mode to either "full" or
95781
- ** "incremental", write the value of meta[6] in the database
95782
- ** file. Before writing to meta[6], check that meta[3] indicates
95783
- ** that this really is an auto-vacuum capable database.
95784
- */
95785
- static const VdbeOpList setMeta6[] = {
95786
- { OP_Transaction, 0, 1, 0}, /* 0 */
95787
- { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
95788
- { OP_If, 1, 0, 0}, /* 2 */
95789
- { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
95790
- { OP_Integer, 0, 1, 0}, /* 4 */
95791
- { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
95792
- };
95793
- int iAddr;
95794
- iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
95795
- sqlite3VdbeChangeP1(v, iAddr, iDb);
95796
- sqlite3VdbeChangeP1(v, iAddr+1, iDb);
95797
- sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
95798
- sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
95799
- sqlite3VdbeChangeP1(v, iAddr+5, iDb);
95800
- sqlite3VdbeUsesBtree(v, iDb);
95801
- }
96144
+ /* Call SetAutoVacuum() to set initialize the internal auto and
96145
+ ** incr-vacuum flags. This is required in case this connection
96146
+ ** creates the database file. It is important that it is created
96147
+ ** as an auto-vacuum capable db.
96148
+ */
96149
+ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
96150
+ if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
96151
+ /* When setting the auto_vacuum mode to either "full" or
96152
+ ** "incremental", write the value of meta[6] in the database
96153
+ ** file. Before writing to meta[6], check that meta[3] indicates
96154
+ ** that this really is an auto-vacuum capable database.
96155
+ */
96156
+ static const VdbeOpList setMeta6[] = {
96157
+ { OP_Transaction, 0, 1, 0}, /* 0 */
96158
+ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
96159
+ { OP_If, 1, 0, 0}, /* 2 */
96160
+ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
96161
+ { OP_Integer, 0, 1, 0}, /* 4 */
96162
+ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
96163
+ };
96164
+ int iAddr;
96165
+ iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
96166
+ sqlite3VdbeChangeP1(v, iAddr, iDb);
96167
+ sqlite3VdbeChangeP1(v, iAddr+1, iDb);
96168
+ sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
96169
+ sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
96170
+ sqlite3VdbeChangeP1(v, iAddr+5, iDb);
96171
+ sqlite3VdbeUsesBtree(v, iDb);
9580296172
}
9580396173
}
9580496174
break;
9580596175
}
9580696176
#endif
@@ -95811,13 +96181,10 @@
9581196181
** Do N steps of incremental vacuuming on a database.
9581296182
*/
9581396183
#ifndef SQLITE_OMIT_AUTOVACUUM
9581496184
case PragTyp_INCREMENTAL_VACUUM: {
9581596185
int iLimit, addr;
95816
- if( sqlite3ReadSchema(pParse) ){
95817
- goto pragma_out;
95818
- }
9581996186
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
9582096187
iLimit = 0x7fffffff;
9582196188
}
9582296189
sqlite3BeginWriteOperation(pParse, 0, iDb);
9582396190
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
@@ -95841,11 +96208,10 @@
9584196208
** number of pages in the cache. If N is negative, then the
9584296209
** number of pages is adjusted so that the cache uses -N kibibytes
9584396210
** of memory.
9584496211
*/
9584596212
case PragTyp_CACHE_SIZE: {
95846
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9584796213
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
9584896214
if( !zRight ){
9584996215
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
9585096216
}else{
9585196217
int size = sqlite3Atoi(zRight);
@@ -96062,11 +96428,10 @@
9606296428
** the local value does not make changes to the disk file and the
9606396429
** default value will be restored the next time the database is
9606496430
** opened.
9606596431
*/
9606696432
case PragTyp_SYNCHRONOUS: {
96067
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9606896433
if( !zRight ){
9606996434
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
9607096435
}else{
9607196436
if( !db->autoCommit ){
9607296437
sqlite3ErrorMsg(pParse,
@@ -96124,11 +96489,10 @@
9612496489
** notnull: True if 'NOT NULL' is part of column declaration
9612596490
** dflt_value: The default value for the column, if any.
9612696491
*/
9612796492
case PragTyp_TABLE_INFO: if( zRight ){
9612896493
Table *pTab;
96129
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9613096494
pTab = sqlite3FindTable(db, zRight, zDb);
9613196495
if( pTab ){
9613296496
int i, k;
9613396497
int nHidden = 0;
9613496498
Column *pCol;
@@ -96174,11 +96538,10 @@
9617496538
break;
9617596539
9617696540
case PragTyp_INDEX_INFO: if( zRight ){
9617796541
Index *pIdx;
9617896542
Table *pTab;
96179
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9618096543
pIdx = sqlite3FindIndex(db, zRight, zDb);
9618196544
if( pIdx ){
9618296545
int i;
9618396546
pTab = pIdx->pTable;
9618496547
sqlite3VdbeSetNumCols(v, 3);
@@ -96200,39 +96563,41 @@
9620096563
break;
9620196564
9620296565
case PragTyp_INDEX_LIST: if( zRight ){
9620396566
Index *pIdx;
9620496567
Table *pTab;
96205
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96568
+ int i;
9620696569
pTab = sqlite3FindTable(db, zRight, zDb);
9620796570
if( pTab ){
9620896571
v = sqlite3GetVdbe(pParse);
96209
- pIdx = pTab->pIndex;
96210
- if( pIdx ){
96211
- int i = 0;
96212
- sqlite3VdbeSetNumCols(v, 3);
96213
- pParse->nMem = 3;
96214
- sqlite3CodeVerifySchema(pParse, iDb);
96215
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96216
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96217
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96218
- while(pIdx){
96219
- sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96220
- sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96221
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96222
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
96223
- ++i;
96224
- pIdx = pIdx->pNext;
96225
- }
96572
+ sqlite3VdbeSetNumCols(v, 4);
96573
+ pParse->nMem = 4;
96574
+ sqlite3CodeVerifySchema(pParse, iDb);
96575
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96576
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96577
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96578
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "avgrowsize", SQLITE_STATIC);
96579
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 1);
96580
+ sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
96581
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, 3);
96582
+ sqlite3VdbeAddOp2(v, OP_Integer,
96583
+ (int)sqlite3LogEstToInt(pTab->szTabRow), 4);
96584
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96585
+ for(pIdx=pTab->pIndex, i=1; pIdx; pIdx=pIdx->pNext, i++){
96586
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96587
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96588
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96589
+ sqlite3VdbeAddOp2(v, OP_Integer,
96590
+ (int)sqlite3LogEstToInt(pIdx->szIdxRow), 4);
96591
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
9622696592
}
9622796593
}
9622896594
}
9622996595
break;
9623096596
9623196597
case PragTyp_DATABASE_LIST: {
9623296598
int i;
96233
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9623496599
sqlite3VdbeSetNumCols(v, 3);
9623596600
pParse->nMem = 3;
9623696601
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
9623796602
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
9623896603
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
@@ -96267,11 +96632,10 @@
9626796632
9626896633
#ifndef SQLITE_OMIT_FOREIGN_KEY
9626996634
case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
9627096635
FKey *pFK;
9627196636
Table *pTab;
96272
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9627396637
pTab = sqlite3FindTable(db, zRight, zDb);
9627496638
if( pTab ){
9627596639
v = sqlite3GetVdbe(pParse);
9627696640
pFK = pTab->pFKey;
9627796641
if( pFK ){
@@ -96329,11 +96693,10 @@
9632996693
int regRow; /* Registers to hold a row from pTab */
9633096694
int addrTop; /* Top of a loop checking foreign keys */
9633196695
int addrOk; /* Jump here if the key is OK */
9633296696
int *aiCols; /* child to parent column mapping */
9633396697
96334
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9633596698
regResult = pParse->nMem+1;
9633696699
pParse->nMem += 4;
9633796700
regKey = ++pParse->nMem;
9633896701
regRow = ++pParse->nMem;
9633996702
v = sqlite3GetVdbe(pParse);
@@ -96490,11 +96853,10 @@
9649096853
assert( iDb>=0 );
9649196854
assert( iDb==0 || pId2->z );
9649296855
if( pId2->z==0 ) iDb = -1;
9649396856
9649496857
/* Initialize the VDBE program */
96495
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9649696858
pParse->nMem = 6;
9649796859
sqlite3VdbeSetNumCols(v, 1);
9649896860
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
9649996861
9650096862
/* Set the maximum error count */
@@ -96814,11 +97176,10 @@
9681497176
eMode = SQLITE_CHECKPOINT_FULL;
9681597177
}else if( sqlite3StrICmp(zRight, "restart")==0 ){
9681697178
eMode = SQLITE_CHECKPOINT_RESTART;
9681797179
}
9681897180
}
96819
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9682097181
sqlite3VdbeSetNumCols(v, 3);
9682197182
pParse->nMem = 3;
9682297183
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
9682397184
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
9682497185
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
@@ -96934,16 +97295,16 @@
9693497295
if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
9693597296
break;
9693697297
}
9693797298
case PragTyp_HEXKEY: {
9693897299
if( zRight ){
96939
- int i, h1, h2;
97300
+ u8 iByte;
97301
+ int i;
9694097302
char zKey[40];
96941
- for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
96942
- h1 += 9*(1&(h1>>6));
96943
- h2 += 9*(1&(h2>>6));
96944
- zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
97303
+ for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
97304
+ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
97305
+ if( (i&1)!=0 ) zKey[i/2] = iByte;
9694597306
}
9694697307
if( (zLeft[3] & 0xf)==0xb ){
9694797308
sqlite3_key_v2(db, zDb, zKey, i/2);
9694897309
}else{
9694997310
sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -98913,10 +99274,13 @@
9891399274
}
9891499275
9891599276
/*
9891699277
** Return a pointer to a string containing the 'declaration type' of the
9891799278
** expression pExpr. The string may be treated as static by the caller.
99279
+**
99280
+** Also try to estimate the size of the returned value and return that
99281
+** result in *pEstWidth.
9891899282
**
9891999283
** The declaration type is the exact datatype definition extracted from the
9892099284
** original CREATE TABLE statement if the expression is a column. The
9892199285
** declaration type for a ROWID field is INTEGER. Exactly when an expression
9892299286
** is considered a column can be complex in the presence of subqueries. The
@@ -98927,25 +99291,40 @@
9892799291
** SELECT (SELECT col FROM tbl;
9892899292
** SELECT (SELECT col FROM tbl);
9892999293
** SELECT abc FROM (SELECT col AS abc FROM tbl);
9893099294
**
9893199295
** The declaration type for any expression other than a column is NULL.
99296
+**
99297
+** This routine has either 3 or 6 parameters depending on whether or not
99298
+** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
9893299299
*/
98933
-static const char *columnType(
99300
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
99301
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
99302
+static const char *columnTypeImpl(
99303
+ NameContext *pNC,
99304
+ Expr *pExpr,
99305
+ const char **pzOrigDb,
99306
+ const char **pzOrigTab,
99307
+ const char **pzOrigCol,
99308
+ u8 *pEstWidth
99309
+){
99310
+ char const *zOrigDb = 0;
99311
+ char const *zOrigTab = 0;
99312
+ char const *zOrigCol = 0;
99313
+#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
99314
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
99315
+static const char *columnTypeImpl(
9893499316
NameContext *pNC,
9893599317
Expr *pExpr,
98936
- const char **pzOriginDb,
98937
- const char **pzOriginTab,
98938
- const char **pzOriginCol
99318
+ u8 *pEstWidth
9893999319
){
99320
+#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
9894099321
char const *zType = 0;
98941
- char const *zOriginDb = 0;
98942
- char const *zOriginTab = 0;
98943
- char const *zOriginCol = 0;
9894499322
int j;
99323
+ u8 estWidth = 1;
99324
+
9894599325
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
98946
-
9894799326
switch( pExpr->op ){
9894899327
case TK_AGG_COLUMN:
9894999328
case TK_COLUMN: {
9895099329
/* The expression is a column. Locate the table the column is being
9895199330
** extracted from in NameContext.pSrcList. This table may be real
@@ -99002,29 +99381,39 @@
9900299381
NameContext sNC;
9900399382
Expr *p = pS->pEList->a[iCol].pExpr;
9900499383
sNC.pSrcList = pS->pSrc;
9900599384
sNC.pNext = pNC;
9900699385
sNC.pParse = pNC->pParse;
99007
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99386
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
9900899387
}
9900999388
}else if( ALWAYS(pTab->pSchema) ){
9901099389
/* A real table */
9901199390
assert( !pS );
9901299391
if( iCol<0 ) iCol = pTab->iPKey;
9901399392
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
99393
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
9901499394
if( iCol<0 ){
9901599395
zType = "INTEGER";
99016
- zOriginCol = "rowid";
99396
+ zOrigCol = "rowid";
9901799397
}else{
9901899398
zType = pTab->aCol[iCol].zType;
99019
- zOriginCol = pTab->aCol[iCol].zName;
99399
+ zOrigCol = pTab->aCol[iCol].zName;
99400
+ estWidth = pTab->aCol[iCol].szEst;
9902099401
}
99021
- zOriginTab = pTab->zName;
99402
+ zOrigTab = pTab->zName;
9902299403
if( pNC->pParse ){
9902399404
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
99024
- zOriginDb = pNC->pParse->db->aDb[iDb].zName;
99405
+ zOrigDb = pNC->pParse->db->aDb[iDb].zName;
9902599406
}
99407
+#else
99408
+ if( iCol<0 ){
99409
+ zType = "INTEGER";
99410
+ }else{
99411
+ zType = pTab->aCol[iCol].zType;
99412
+ estWidth = pTab->aCol[iCol].szEst;
99413
+ }
99414
+#endif
9902699415
}
9902799416
break;
9902899417
}
9902999418
#ifndef SQLITE_OMIT_SUBQUERY
9903099419
case TK_SELECT: {
@@ -99037,22 +99426,25 @@
9903799426
Expr *p = pS->pEList->a[0].pExpr;
9903899427
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
9903999428
sNC.pSrcList = pS->pSrc;
9904099429
sNC.pNext = pNC;
9904199430
sNC.pParse = pNC->pParse;
99042
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99431
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
9904399432
break;
9904499433
}
9904599434
#endif
9904699435
}
99047
-
99048
- if( pzOriginDb ){
99049
- assert( pzOriginTab && pzOriginCol );
99050
- *pzOriginDb = zOriginDb;
99051
- *pzOriginTab = zOriginTab;
99052
- *pzOriginCol = zOriginCol;
99436
+
99437
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
99438
+ if( pzOrigDb ){
99439
+ assert( pzOrigTab && pzOrigCol );
99440
+ *pzOrigDb = zOrigDb;
99441
+ *pzOrigTab = zOrigTab;
99442
+ *pzOrigCol = zOrigCol;
9905399443
}
99444
+#endif
99445
+ if( pEstWidth ) *pEstWidth = estWidth;
9905499446
return zType;
9905599447
}
9905699448
9905799449
/*
9905899450
** Generate code that will tell the VDBE the declaration types of columns
@@ -99074,25 +99466,25 @@
9907499466
const char *zType;
9907599467
#ifdef SQLITE_ENABLE_COLUMN_METADATA
9907699468
const char *zOrigDb = 0;
9907799469
const char *zOrigTab = 0;
9907899470
const char *zOrigCol = 0;
99079
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
99471
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
9908099472
9908199473
/* The vdbe must make its own copy of the column-type and other
9908299474
** column specific strings, in case the schema is reset before this
9908399475
** virtual machine is deleted.
9908499476
*/
9908599477
sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
9908699478
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
9908799479
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
9908899480
#else
99089
- zType = columnType(&sNC, p, 0, 0, 0);
99481
+ zType = columnType(&sNC, p, 0, 0, 0, 0);
9909099482
#endif
9909199483
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
9909299484
}
99093
-#endif /* SQLITE_OMIT_DECLTYPE */
99485
+#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
9909499486
}
9909599487
9909699488
/*
9909799489
** Generate code that will tell the VDBE the names of columns
9909899490
** in the result set. This information is used to provide the
@@ -99277,39 +99669,41 @@
9927799669
** This routine requires that all identifiers in the SELECT
9927899670
** statement be resolved.
9927999671
*/
9928099672
static void selectAddColumnTypeAndCollation(
9928199673
Parse *pParse, /* Parsing contexts */
99282
- int nCol, /* Number of columns */
99283
- Column *aCol, /* List of columns */
99674
+ Table *pTab, /* Add column type information to this table */
9928499675
Select *pSelect /* SELECT used to determine types and collations */
9928599676
){
9928699677
sqlite3 *db = pParse->db;
9928799678
NameContext sNC;
9928899679
Column *pCol;
9928999680
CollSeq *pColl;
9929099681
int i;
9929199682
Expr *p;
9929299683
struct ExprList_item *a;
99684
+ u64 szAll = 0;
9929399685
9929499686
assert( pSelect!=0 );
9929599687
assert( (pSelect->selFlags & SF_Resolved)!=0 );
99296
- assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
99688
+ assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
9929799689
if( db->mallocFailed ) return;
9929899690
memset(&sNC, 0, sizeof(sNC));
9929999691
sNC.pSrcList = pSelect->pSrc;
9930099692
a = pSelect->pEList->a;
99301
- for(i=0, pCol=aCol; i<nCol; i++, pCol++){
99693
+ for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
9930299694
p = a[i].pExpr;
99303
- pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
99695
+ pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
99696
+ szAll += pCol->szEst;
9930499697
pCol->affinity = sqlite3ExprAffinity(p);
9930599698
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
9930699699
pColl = sqlite3ExprCollSeq(pParse, p);
9930799700
if( pColl ){
9930899701
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
9930999702
}
9931099703
}
99704
+ pTab->szTabRow = sqlite3LogEst(szAll*4);
9931199705
}
9931299706
9931399707
/*
9931499708
** Given a SELECT statement, generate a Table structure that describes
9931599709
** the result set of that SELECT.
@@ -99333,13 +99727,13 @@
9933399727
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
9933499728
** is disabled */
9933599729
assert( db->lookaside.bEnabled==0 );
9933699730
pTab->nRef = 1;
9933799731
pTab->zName = 0;
99338
- pTab->nRowEst = 1000000;
99732
+ pTab->nRowEst = 1048576;
9933999733
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
99340
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
99734
+ selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
9934199735
pTab->iPKey = -1;
9934299736
if( db->mallocFailed ){
9934399737
sqlite3DeleteTable(db, pTab);
9934499738
return 0;
9934599739
}
@@ -101247,15 +101641,15 @@
101247101641
assert( pFrom->pTab==0 );
101248101642
sqlite3WalkSelect(pWalker, pSel);
101249101643
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
101250101644
if( pTab==0 ) return WRC_Abort;
101251101645
pTab->nRef = 1;
101252
- pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
101646
+ pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
101253101647
while( pSel->pPrior ){ pSel = pSel->pPrior; }
101254101648
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
101255101649
pTab->iPKey = -1;
101256
- pTab->nRowEst = 1000000;
101650
+ pTab->nRowEst = 1048576;
101257101651
pTab->tabFlags |= TF_Ephemeral;
101258101652
#endif
101259101653
}else{
101260101654
/* An ordinary table or view name in the FROM clause */
101261101655
assert( pFrom->pTab==0 );
@@ -101535,11 +101929,11 @@
101535101929
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
101536101930
/* A sub-query in the FROM clause of a SELECT */
101537101931
Select *pSel = pFrom->pSelect;
101538101932
assert( pSel );
101539101933
while( pSel->pPrior ) pSel = pSel->pPrior;
101540
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
101934
+ selectAddColumnTypeAndCollation(pParse, pTab, pSel);
101541101935
}
101542101936
}
101543101937
}
101544101938
return WRC_Continue;
101545101939
}
@@ -102450,29 +102844,29 @@
102450102844
int iRoot = pTab->tnum; /* Root page of scanned b-tree */
102451102845
102452102846
sqlite3CodeVerifySchema(pParse, iDb);
102453102847
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102454102848
102455
- /* Search for the index that has the least amount of columns. If
102456
- ** there is such an index, and it has less columns than the table
102457
- ** does, then we can assume that it consumes less space on disk and
102458
- ** will therefore be cheaper to scan to determine the query result.
102459
- ** In this case set iRoot to the root page number of the index b-tree
102460
- ** and pKeyInfo to the KeyInfo structure required to navigate the
102461
- ** index.
102849
+ /* Search for the index that has the lowest scan cost.
102462102850
**
102463102851
** (2011-04-15) Do not do a full scan of an unordered index.
102852
+ **
102853
+ ** (2013-10-03) Do not count the entires in a partial index.
102464102854
**
102465102855
** In practice the KeyInfo structure will not be used. It is only
102466102856
** passed to keep OP_OpenRead happy.
102467102857
*/
102468102858
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
102469
- if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
102859
+ if( pIdx->bUnordered==0
102860
+ && pIdx->szIdxRow<pTab->szTabRow
102861
+ && pIdx->pPartIdxWhere==0
102862
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
102863
+ ){
102470102864
pBest = pIdx;
102471102865
}
102472102866
}
102473
- if( pBest && pBest->nColumn<pTab->nCol ){
102867
+ if( pBest ){
102474102868
iRoot = pBest->tnum;
102475102869
pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
102476102870
}
102477102871
102478102872
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
@@ -103046,12 +103440,12 @@
103046103440
}
103047103441
103048103442
/* Ensure the table name matches database name and that the table exists */
103049103443
if( db->mallocFailed ) goto trigger_cleanup;
103050103444
assert( pTableName->nSrc==1 );
103051
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
103052
- sqlite3FixSrcList(&sFix, pTableName) ){
103445
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
103446
+ if( sqlite3FixSrcList(&sFix, pTableName) ){
103053103447
goto trigger_cleanup;
103054103448
}
103055103449
pTab = sqlite3SrcListLookup(pParse, pTableName);
103056103450
if( !pTab ){
103057103451
/* The table does not exist. */
@@ -103189,12 +103583,14 @@
103189103583
pStepList->pTrig = pTrig;
103190103584
pStepList = pStepList->pNext;
103191103585
}
103192103586
nameToken.z = pTrig->zName;
103193103587
nameToken.n = sqlite3Strlen30(nameToken.z);
103194
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
103195
- && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
103588
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
103589
+ if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
103590
+ || sqlite3FixExpr(&sFix, pTrig->pWhen)
103591
+ ){
103196103592
goto triggerfinish_cleanup;
103197103593
}
103198103594
103199103595
/* if we are not initializing,
103200103596
** build the sqlite_master entry
@@ -104781,18 +105177,38 @@
104781105177
104782105178
return vacuumFinalize(db, pStmt, pzErrMsg);
104783105179
}
104784105180
104785105181
/*
104786
-** The non-standard VACUUM command is used to clean up the database,
105182
+** The VACUUM command is used to clean up the database,
104787105183
** collapse free space, etc. It is modelled after the VACUUM command
104788
-** in PostgreSQL.
105184
+** in PostgreSQL. The VACUUM command works as follows:
104789105185
**
104790
-** In version 1.0.x of SQLite, the VACUUM command would call
104791
-** gdbm_reorganize() on all the database tables. But beginning
104792
-** with 2.0.0, SQLite no longer uses GDBM so this command has
104793
-** become a no-op.
105186
+** (1) Create a new transient database file
105187
+** (2) Copy all content from the database being vacuumed into
105188
+** the new transient database file
105189
+** (3) Copy content from the transient database back into the
105190
+** original database.
105191
+**
105192
+** The transient database requires temporary disk space approximately
105193
+** equal to the size of the original database. The copy operation of
105194
+** step (3) requires additional temporary disk space approximately equal
105195
+** to the size of the original database for the rollback journal.
105196
+** Hence, temporary disk space that is approximately 2x the size of the
105197
+** orginal database is required. Every page of the database is written
105198
+** approximately 3 times: Once for step (2) and twice for step (3).
105199
+** Two writes per page are required in step (3) because the original
105200
+** database content must be written into the rollback journal prior to
105201
+** overwriting the database with the vacuumed content.
105202
+**
105203
+** Only 1x temporary space and only 1x writes would be required if
105204
+** the copy of step (3) were replace by deleting the original database
105205
+** and renaming the transient database as the original. But that will
105206
+** not work if other processes are attached to the original database.
105207
+** And a power loss in between deleting the original and renaming the
105208
+** transient would cause the database file to appear to be deleted
105209
+** following reboot.
104794105210
*/
104795105211
SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
104796105212
Vdbe *v = sqlite3GetVdbe(pParse);
104797105213
if( v ){
104798105214
sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
@@ -106206,30 +106622,10 @@
106206106622
typedef struct WhereLoopBuilder WhereLoopBuilder;
106207106623
typedef struct WhereScan WhereScan;
106208106624
typedef struct WhereOrCost WhereOrCost;
106209106625
typedef struct WhereOrSet WhereOrSet;
106210106626
106211
-/*
106212
-** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
106213
-** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
106214
-** (Virtual tables can return a larger cost, but let's assume they do not.)
106215
-** So all costs can be stored in a 16-bit integer without risk
106216
-** of overflow.
106217
-**
106218
-** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
106219
-** Instead, a close estimate is used. Any value of X=1 is stored as 0.
106220
-** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
106221
-** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
106222
-**
106223
-** The tool/wherecosttest.c source file implements a command-line program
106224
-** that will convert WhereCosts to integers, convert integers to WhereCosts
106225
-** and do addition and multiplication on WhereCost values. The wherecosttest
106226
-** command-line program is a useful utility to have around when working with
106227
-** this module.
106228
-*/
106229
-typedef short int WhereCost;
106230
-
106231106627
/*
106232106628
** This object contains information needed to implement a single nested
106233106629
** loop in WHERE clause.
106234106630
**
106235106631
** Contrast this object with WhereLoop. This object describes the
@@ -106290,13 +106686,13 @@
106290106686
#ifdef SQLITE_DEBUG
106291106687
char cId; /* Symbolic ID of this loop for debugging use */
106292106688
#endif
106293106689
u8 iTab; /* Position in FROM clause of table for this loop */
106294106690
u8 iSortIdx; /* Sorting index number. 0==None */
106295
- WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
106296
- WhereCost rRun; /* Cost of running each loop */
106297
- WhereCost nOut; /* Estimated number of output rows */
106691
+ LogEst rSetup; /* One-time setup cost (ex: create transient index) */
106692
+ LogEst rRun; /* Cost of running each loop */
106693
+ LogEst nOut; /* Estimated number of output rows */
106298106694
union {
106299106695
struct { /* Information for internal btree tables */
106300106696
int nEq; /* Number of equality constraints */
106301106697
Index *pIndex; /* Index used, or NULL */
106302106698
} btree;
@@ -106322,12 +106718,12 @@
106322106718
** subquery on one operand of an OR operator in the WHERE clause.
106323106719
** See WhereOrSet for additional information
106324106720
*/
106325106721
struct WhereOrCost {
106326106722
Bitmask prereq; /* Prerequisites */
106327
- WhereCost rRun; /* Cost of running this subquery */
106328
- WhereCost nOut; /* Number of outputs for this subquery */
106723
+ LogEst rRun; /* Cost of running this subquery */
106724
+ LogEst nOut; /* Number of outputs for this subquery */
106329106725
};
106330106726
106331106727
/* The WhereOrSet object holds a set of possible WhereOrCosts that
106332106728
** correspond to the subquery(s) of OR-clause processing. Only the
106333106729
** best N_OR_COST elements are retained.
@@ -106361,12 +106757,12 @@
106361106757
** at the end is the choosen query plan.
106362106758
*/
106363106759
struct WherePath {
106364106760
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
106365106761
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
106366
- WhereCost nRow; /* Estimated number of rows generated by this path */
106367
- WhereCost rCost; /* Total cost of this path */
106762
+ LogEst nRow; /* Estimated number of rows generated by this path */
106763
+ LogEst rCost; /* Total cost of this path */
106368106764
u8 isOrdered; /* True if this path satisfies ORDER BY */
106369106765
u8 isOrderedValid; /* True if the isOrdered field is valid */
106370106766
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
106371106767
};
106372106768
@@ -106428,11 +106824,11 @@
106428106824
union {
106429106825
int leftColumn; /* Column number of X in "X <op> <expr>" */
106430106826
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
106431106827
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
106432106828
} u;
106433
- WhereCost truthProb; /* Probability of truth for this expression */
106829
+ LogEst truthProb; /* Probability of truth for this expression */
106434106830
u16 eOperator; /* A WO_xx value describing <op> */
106435106831
u8 wtFlags; /* TERM_xxx bit flags. See below */
106436106832
u8 nChild; /* Number of children that must disable us */
106437106833
WhereClause *pWC; /* The clause this term is part of */
106438106834
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -106576,11 +106972,11 @@
106576106972
SrcList *pTabList; /* List of tables in the join */
106577106973
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
106578106974
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
106579106975
WhereLoop *pLoops; /* List of all WhereLoop objects */
106580106976
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
106581
- WhereCost nRowOut; /* Estimated number of output rows */
106977
+ LogEst nRowOut; /* Estimated number of output rows */
106582106978
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
106583106979
u8 bOBSat; /* ORDER BY satisfied by indices */
106584106980
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
106585106981
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
106586106982
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -106636,30 +107032,15 @@
106636107032
#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
106637107033
#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
106638107034
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
106639107035
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
106640107036
106641
-
106642
-/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
106643
-** A rough approximation is used. The value returned is not exact.
106644
-*/
106645
-static u64 whereCostToInt(WhereCost x){
106646
- u64 n;
106647
- if( x<10 ) return 1;
106648
- n = x%10;
106649
- x /= 10;
106650
- if( n>=5 ) n -= 2;
106651
- else if( n>=1 ) n -= 1;
106652
- if( x>=3 ) return (n+8)<<(x-3);
106653
- return (n+8)>>(3-x);
106654
-}
106655
-
106656107037
/*
106657107038
** Return the estimated number of output rows from a WHERE clause
106658107039
*/
106659107040
SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
106660
- return whereCostToInt(pWInfo->nRowOut);
107041
+ return sqlite3LogEstToInt(pWInfo->nRowOut);
106661107042
}
106662107043
106663107044
/*
106664107045
** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
106665107046
** WHERE clause returns outputs for DISTINCT processing.
@@ -106717,12 +107098,12 @@
106717107098
** so that pSet keeps the N_OR_COST best entries seen so far.
106718107099
*/
106719107100
static int whereOrInsert(
106720107101
WhereOrSet *pSet, /* The WhereOrSet to be updated */
106721107102
Bitmask prereq, /* Prerequisites of the new entry */
106722
- WhereCost rRun, /* Run-cost of the new entry */
106723
- WhereCost nOut /* Number of outputs for the new entry */
107103
+ LogEst rRun, /* Run-cost of the new entry */
107104
+ LogEst nOut /* Number of outputs for the new entry */
106724107105
){
106725107106
u16 i;
106726107107
WhereOrCost *p;
106727107108
for(i=pSet->n, p=pSet->a; i>0; i--, p++){
106728107109
if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
@@ -106803,13 +107184,10 @@
106803107184
if( pWC->a!=pWC->aStatic ){
106804107185
sqlite3DbFree(db, pWC->a);
106805107186
}
106806107187
}
106807107188
106808
-/* Forward declaration */
106809
-static WhereCost whereCost(tRowcnt x);
106810
-
106811107189
/*
106812107190
** Add a single new WhereTerm entry to the WhereClause object pWC.
106813107191
** The new WhereTerm object is constructed from Expr p and with wtFlags.
106814107192
** The index in pWC->a[] of the new WhereTerm is returned on success.
106815107193
** 0 is returned if the new WhereTerm could not be added due to a memory
@@ -106848,11 +107226,11 @@
106848107226
}
106849107227
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
106850107228
}
106851107229
pTerm = &pWC->a[idx = pWC->nTerm++];
106852107230
if( p && ExprHasProperty(p, EP_Unlikely) ){
106853
- pTerm->truthProb = whereCost(p->iTable) - 99;
107231
+ pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
106854107232
}else{
106855107233
pTerm->truthProb = -1;
106856107234
}
106857107235
pTerm->pExpr = sqlite3ExprSkipCollate(p);
106858107236
pTerm->wtFlags = wtFlags;
@@ -108112,79 +108490,16 @@
108112108490
}
108113108491
108114108492
return 0;
108115108493
}
108116108494
108117
-/*
108118
-** Find (an approximate) sum of two WhereCosts. This computation is
108119
-** not a simple "+" operator because WhereCost is stored as a logarithmic
108120
-** value.
108121
-**
108122
-*/
108123
-static WhereCost whereCostAdd(WhereCost a, WhereCost b){
108124
- static const unsigned char x[] = {
108125
- 10, 10, /* 0,1 */
108126
- 9, 9, /* 2,3 */
108127
- 8, 8, /* 4,5 */
108128
- 7, 7, 7, /* 6,7,8 */
108129
- 6, 6, 6, /* 9,10,11 */
108130
- 5, 5, 5, /* 12-14 */
108131
- 4, 4, 4, 4, /* 15-18 */
108132
- 3, 3, 3, 3, 3, 3, /* 19-24 */
108133
- 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
108134
- };
108135
- if( a>=b ){
108136
- if( a>b+49 ) return a;
108137
- if( a>b+31 ) return a+1;
108138
- return a+x[a-b];
108139
- }else{
108140
- if( b>a+49 ) return b;
108141
- if( b>a+31 ) return b+1;
108142
- return b+x[b-a];
108143
- }
108144
-}
108145
-
108146
-/*
108147
-** Convert an integer into a WhereCost. In other words, compute a
108148
-** good approximatation for 10*log2(x).
108149
-*/
108150
-static WhereCost whereCost(tRowcnt x){
108151
- static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
108152
- WhereCost y = 40;
108153
- if( x<8 ){
108154
- if( x<2 ) return 0;
108155
- while( x<8 ){ y -= 10; x <<= 1; }
108156
- }else{
108157
- while( x>255 ){ y += 40; x >>= 4; }
108158
- while( x>15 ){ y += 10; x >>= 1; }
108159
- }
108160
- return a[x&7] + y - 10;
108161
-}
108162
-
108163
-#ifndef SQLITE_OMIT_VIRTUALTABLE
108164
-/*
108165
-** Convert a double (as received from xBestIndex of a virtual table)
108166
-** into a WhereCost. In other words, compute an approximation for
108167
-** 10*log2(x).
108168
-*/
108169
-static WhereCost whereCostFromDouble(double x){
108170
- u64 a;
108171
- WhereCost e;
108172
- assert( sizeof(x)==8 && sizeof(a)==8 );
108173
- if( x<=1 ) return 0;
108174
- if( x<=2000000000 ) return whereCost((tRowcnt)x);
108175
- memcpy(&a, &x, 8);
108176
- e = (a>>52) - 1022;
108177
- return e*10;
108178
-}
108179
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
108180108495
108181108496
/*
108182108497
** Estimate the logarithm of the input value to base 2.
108183108498
*/
108184
-static WhereCost estLog(WhereCost N){
108185
- WhereCost x = whereCost(N);
108499
+static LogEst estLog(LogEst N){
108500
+ LogEst x = sqlite3LogEst(N);
108186108501
return x>33 ? x - 33 : 0;
108187108502
}
108188108503
108189108504
/*
108190108505
** Two routines for printing the content of an sqlite3_index_info
@@ -108693,11 +109008,11 @@
108693109008
**
108694109009
** ... FROM t1 WHERE a > ? AND a < ? ...
108695109010
**
108696109011
** then nEq is set to 0.
108697109012
**
108698
-** When this function is called, *pnOut is set to the whereCost() of the
109013
+** When this function is called, *pnOut is set to the sqlite3LogEst() of the
108699109014
** number of rows that the index scan is expected to visit without
108700109015
** considering the range constraints. If nEq is 0, this is the number of
108701109016
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
108702109017
** to account for the range contraints pLower and pUpper.
108703109018
**
@@ -108709,19 +109024,19 @@
108709109024
static int whereRangeScanEst(
108710109025
Parse *pParse, /* Parsing & code generating context */
108711109026
WhereLoopBuilder *pBuilder,
108712109027
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
108713109028
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
108714
- WhereCost *pnOut /* IN/OUT: Number of rows visited */
109029
+ WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
108715109030
){
108716109031
int rc = SQLITE_OK;
108717
- int nOut = (int)*pnOut;
108718
- WhereCost nNew;
109032
+ int nOut = pLoop->nOut;
109033
+ int nEq = pLoop->u.btree.nEq;
109034
+ LogEst nNew;
108719109035
108720109036
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108721
- Index *p = pBuilder->pNew->u.btree.pIndex;
108722
- int nEq = pBuilder->pNew->u.btree.nEq;
109037
+ Index *p = pLoop->u.btree.pIndex;
108723109038
108724109039
if( p->nSample>0
108725109040
&& nEq==pBuilder->nRecValid
108726109041
&& nEq<p->nSampleCol
108727109042
&& OptimizationEnabled(pParse->db, SQLITE_Stat3)
@@ -108798,18 +109113,18 @@
108798109113
}
108799109114
108800109115
pBuilder->pRec = pRec;
108801109116
if( rc==SQLITE_OK ){
108802109117
if( iUpper>iLower ){
108803
- nNew = whereCost(iUpper - iLower);
109118
+ nNew = sqlite3LogEst(iUpper - iLower);
108804109119
}else{
108805
- nNew = 10; assert( 10==whereCost(2) );
109120
+ nNew = 10; assert( 10==sqlite3LogEst(2) );
108806109121
}
108807109122
if( nNew<nOut ){
108808109123
nOut = nNew;
108809109124
}
108810
- *pnOut = (WhereCost)nOut;
109125
+ pLoop->nOut = (LogEst)nOut;
108811109126
WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
108812109127
(u32)iLower, (u32)iUpper, nOut));
108813109128
return SQLITE_OK;
108814109129
}
108815109130
}
@@ -108820,20 +109135,20 @@
108820109135
assert( pLower || pUpper );
108821109136
/* TUNING: Each inequality constraint reduces the search space 4-fold.
108822109137
** A BETWEEN operator, therefore, reduces the search space 16-fold */
108823109138
nNew = nOut;
108824109139
if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
108825
- nNew -= 20; assert( 20==whereCost(4) );
109140
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
108826109141
nOut--;
108827109142
}
108828109143
if( pUpper ){
108829
- nNew -= 20; assert( 20==whereCost(4) );
109144
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
108830109145
nOut--;
108831109146
}
108832109147
if( nNew<10 ) nNew = 10;
108833109148
if( nNew<nOut ) nOut = nNew;
108834
- *pnOut = (WhereCost)nOut;
109149
+ pLoop->nOut = (LogEst)nOut;
108835109150
return rc;
108836109151
}
108837109152
108838109153
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108839109154
/*
@@ -110473,11 +110788,11 @@
110473110788
*/
110474110789
static int whereLoopAddBtreeIndex(
110475110790
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
110476110791
struct SrcList_item *pSrc, /* FROM clause term being analyzed */
110477110792
Index *pProbe, /* An index on pSrc */
110478
- WhereCost nInMul /* log(Number of iterations due to IN) */
110793
+ LogEst nInMul /* log(Number of iterations due to IN) */
110479110794
){
110480110795
WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
110481110796
Parse *pParse = pWInfo->pParse; /* Parsing context */
110482110797
sqlite3 *db = pParse->db; /* Database connection malloc context */
110483110798
WhereLoop *pNew; /* Template WhereLoop under construction */
@@ -110486,15 +110801,15 @@
110486110801
WhereScan scan; /* Iterator for WHERE terms */
110487110802
Bitmask saved_prereq; /* Original value of pNew->prereq */
110488110803
u16 saved_nLTerm; /* Original value of pNew->nLTerm */
110489110804
int saved_nEq; /* Original value of pNew->u.btree.nEq */
110490110805
u32 saved_wsFlags; /* Original value of pNew->wsFlags */
110491
- WhereCost saved_nOut; /* Original value of pNew->nOut */
110806
+ LogEst saved_nOut; /* Original value of pNew->nOut */
110492110807
int iCol; /* Index of the column in the table */
110493110808
int rc = SQLITE_OK; /* Return code */
110494
- WhereCost nRowEst; /* Estimated index selectivity */
110495
- WhereCost rLogSize; /* Logarithm of table size */
110809
+ LogEst nRowEst; /* Estimated index selectivity */
110810
+ LogEst rLogSize; /* Logarithm of table size */
110496110811
WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
110497110812
110498110813
pNew = pBuilder->pNew;
110499110814
if( db->mallocFailed ) return SQLITE_NOMEM;
110500110815
@@ -110510,11 +110825,11 @@
110510110825
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
110511110826
110512110827
assert( pNew->u.btree.nEq<=pProbe->nColumn );
110513110828
if( pNew->u.btree.nEq < pProbe->nColumn ){
110514110829
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
110515
- nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110830
+ nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110516110831
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
110517110832
}else{
110518110833
iCol = -1;
110519110834
nRowEst = 0;
110520110835
}
@@ -110524,11 +110839,11 @@
110524110839
saved_nLTerm = pNew->nLTerm;
110525110840
saved_wsFlags = pNew->wsFlags;
110526110841
saved_prereq = pNew->prereq;
110527110842
saved_nOut = pNew->nOut;
110528110843
pNew->rSetup = 0;
110529
- rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
110844
+ rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
110530110845
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
110531110846
int nIn = 0;
110532110847
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110533110848
int nRecValid = pBuilder->nRecValid;
110534110849
#endif
@@ -110551,14 +110866,14 @@
110551110866
if( pTerm->eOperator & WO_IN ){
110552110867
Expr *pExpr = pTerm->pExpr;
110553110868
pNew->wsFlags |= WHERE_COLUMN_IN;
110554110869
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
110555110870
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
110556
- nIn = 46; assert( 46==whereCost(25) );
110871
+ nIn = 46; assert( 46==sqlite3LogEst(25) );
110557110872
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
110558110873
/* "x IN (value, value, ...)" */
110559
- nIn = whereCost(pExpr->x.pList->nExpr);
110874
+ nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
110560110875
}
110561110876
pNew->rRun += nIn;
110562110877
pNew->u.btree.nEq++;
110563110878
pNew->nOut = nRowEst + nInMul + nIn;
110564110879
}else if( pTerm->eOperator & (WO_EQ) ){
@@ -110576,11 +110891,11 @@
110576110891
pNew->nOut = nRowEst + nInMul;
110577110892
}else if( pTerm->eOperator & (WO_ISNULL) ){
110578110893
pNew->wsFlags |= WHERE_COLUMN_NULL;
110579110894
pNew->u.btree.nEq++;
110580110895
/* TUNING: IS NULL selects 2 rows */
110581
- nIn = 10; assert( 10==whereCost(2) );
110896
+ nIn = 10; assert( 10==sqlite3LogEst(2) );
110582110897
pNew->nOut = nRowEst + nInMul + nIn;
110583110898
}else if( pTerm->eOperator & (WO_GT|WO_GE) ){
110584110899
testcase( pTerm->eOperator & WO_GT );
110585110900
testcase( pTerm->eOperator & WO_GE );
110586110901
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
@@ -110596,11 +110911,11 @@
110596110911
pNew->aLTerm[pNew->nLTerm-2] : 0;
110597110912
}
110598110913
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
110599110914
/* Adjust nOut and rRun for STAT3 range values */
110600110915
assert( pNew->nOut==saved_nOut );
110601
- whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
110916
+ whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
110602110917
}
110603110918
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110604110919
if( nInMul==0
110605110920
&& pProbe->nSample
110606110921
&& pNew->u.btree.nEq<=pProbe->nSampleCol
@@ -110616,22 +110931,22 @@
110616110931
&& !ExprHasProperty(pExpr, EP_xIsSelect) ){
110617110932
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
110618110933
}
110619110934
assert( nOut==0 || rc==SQLITE_OK );
110620110935
if( nOut ){
110621
- nOut = whereCost(nOut);
110936
+ nOut = sqlite3LogEst(nOut);
110622110937
pNew->nOut = MIN(nOut, saved_nOut);
110623110938
}
110624110939
}
110625110940
#endif
110626110941
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
110627110942
/* Each row involves a step of the index, then a binary search of
110628110943
** the main table */
110629
- pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
110944
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
110630110945
}
110631110946
/* Step cost for each output row */
110632
- pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
110947
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
110633110948
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
110634110949
rc = whereLoopInsert(pBuilder, pNew);
110635110950
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
110636110951
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
110637110952
){
@@ -110727,18 +111042,20 @@
110727111042
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
110728111043
WhereLoop *pNew; /* Template WhereLoop object */
110729111044
int rc = SQLITE_OK; /* Return code */
110730111045
int iSortIdx = 1; /* Index number */
110731111046
int b; /* A boolean value */
110732
- WhereCost rSize; /* number of rows in the table */
110733
- WhereCost rLogSize; /* Logarithm of the number of rows in the table */
111047
+ LogEst rSize; /* number of rows in the table */
111048
+ LogEst rLogSize; /* Logarithm of the number of rows in the table */
110734111049
WhereClause *pWC; /* The parsed WHERE clause */
111050
+ Table *pTab; /* Table being queried */
110735111051
110736111052
pNew = pBuilder->pNew;
110737111053
pWInfo = pBuilder->pWInfo;
110738111054
pTabList = pWInfo->pTabList;
110739111055
pSrc = pTabList->a + pNew->iTab;
111056
+ pTab = pSrc->pTab;
110740111057
pWC = pBuilder->pWC;
110741111058
assert( !IsVirtual(pSrc->pTab) );
110742111059
110743111060
if( pSrc->pIndex ){
110744111061
/* An INDEXED BY clause specifies a particular index to use */
@@ -110752,22 +111069,22 @@
110752111069
memset(&sPk, 0, sizeof(Index));
110753111070
sPk.nColumn = 1;
110754111071
sPk.aiColumn = &aiColumnPk;
110755111072
sPk.aiRowEst = aiRowEstPk;
110756111073
sPk.onError = OE_Replace;
110757
- sPk.pTable = pSrc->pTab;
110758
- aiRowEstPk[0] = pSrc->pTab->nRowEst;
111074
+ sPk.pTable = pTab;
111075
+ aiRowEstPk[0] = pTab->nRowEst;
110759111076
aiRowEstPk[1] = 1;
110760111077
pFirst = pSrc->pTab->pIndex;
110761111078
if( pSrc->notIndexed==0 ){
110762111079
/* The real indices of the table are only considered if the
110763111080
** NOT INDEXED qualifier is omitted from the FROM clause */
110764111081
sPk.pNext = pFirst;
110765111082
}
110766111083
pProbe = &sPk;
110767111084
}
110768
- rSize = whereCost(pSrc->pTab->nRowEst);
111085
+ rSize = sqlite3LogEst(pTab->nRowEst);
110769111086
rLogSize = estLog(rSize);
110770111087
110771111088
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
110772111089
/* Automatic indexes */
110773111090
if( !pBuilder->pOrSet
@@ -110788,17 +111105,17 @@
110788111105
pNew->nLTerm = 1;
110789111106
pNew->aLTerm[0] = pTerm;
110790111107
/* TUNING: One-time cost for computing the automatic index is
110791111108
** approximately 7*N*log2(N) where N is the number of rows in
110792111109
** the table being indexed. */
110793
- pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
111110
+ pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
110794111111
/* TUNING: Each index lookup yields 20 rows in the table. This
110795111112
** is more than the usual guess of 10 rows, since we have no way
110796111113
** of knowning how selective the index will ultimately be. It would
110797111114
** not be unreasonable to make this value much larger. */
110798
- pNew->nOut = 43; assert( 43==whereCost(20) );
110799
- pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
111115
+ pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
111116
+ pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
110800111117
pNew->wsFlags = WHERE_AUTO_INDEX;
110801111118
pNew->prereq = mExtra | pTerm->prereqRight;
110802111119
rc = whereLoopInsert(pBuilder, pNew);
110803111120
}
110804111121
}
@@ -110828,14 +111145,12 @@
110828111145
110829111146
/* Full table scan */
110830111147
pNew->iSortIdx = b ? iSortIdx : 0;
110831111148
/* TUNING: Cost of full table scan is 3*(N + log2(N)).
110832111149
** + The extra 3 factor is to encourage the use of indexed lookups
110833
- ** over full scans. A smaller constant 2 is used for covering
110834
- ** index scans so that a covering index scan will be favored over
110835
- ** a table scan. */
110836
- pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
111150
+ ** over full scans. FIXME */
111151
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
110837111152
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
110838111153
rc = whereLoopInsert(pBuilder, pNew);
110839111154
pNew->nOut = rSize;
110840111155
if( rc ) break;
110841111156
}else{
@@ -110844,26 +111159,25 @@
110844111159
110845111160
/* Full scan via index */
110846111161
if( b
110847111162
|| ( m==0
110848111163
&& pProbe->bUnordered==0
111164
+ && pProbe->szIdxRow<pTab->szTabRow
110849111165
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
110850111166
&& sqlite3GlobalConfig.bUseCis
110851111167
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
110852111168
)
110853111169
){
110854111170
pNew->iSortIdx = b ? iSortIdx : 0;
110855111171
if( m==0 ){
110856
- /* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
110857
- ** + The extra 2 factor is to encourage the use of indexed lookups
110858
- ** over index scans. A table scan uses a factor of 3 so that
110859
- ** index scans are favored over table scans.
110860
- ** + If this covering index might also help satisfy the ORDER BY
110861
- ** clause, then the cost is fudged down slightly so that this
110862
- ** index is favored above other indices that have no hope of
110863
- ** helping with the ORDER BY. */
110864
- pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
111172
+ /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
111173
+ ** + The extra factor K of between 1.1 and 3.0 that depends
111174
+ ** on the relative sizes of the table and the index. K
111175
+ ** is smaller for smaller indices, thus favoring them.
111176
+ */
111177
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
111178
+ (15*pProbe->szIdxRow)/pTab->szTabRow;
110865111179
}else{
110866111180
assert( b!=0 );
110867111181
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
110868111182
** which we will simplify to just N*log2(N) */
110869111183
pNew->rRun = rSize + rLogSize;
@@ -111037,13 +111351,13 @@
111037111351
pIdxInfo->needToFreeIdxStr = 0;
111038111352
pNew->u.vtab.idxStr = pIdxInfo->idxStr;
111039111353
pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
111040111354
&& pIdxInfo->orderByConsumed);
111041111355
pNew->rSetup = 0;
111042
- pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
111356
+ pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
111043111357
/* TUNING: Every virtual table query returns 25 rows */
111044
- pNew->nOut = 46; assert( 46==whereCost(25) );
111358
+ pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
111045111359
whereLoopInsert(pBuilder, pNew);
111046111360
if( pNew->u.vtab.needFree ){
111047111361
sqlite3_free(pNew->u.vtab.idxStr);
111048111362
pNew->u.vtab.needFree = 0;
111049111363
}
@@ -111076,10 +111390,12 @@
111076111390
pWC = pBuilder->pWC;
111077111391
if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
111078111392
pWCEnd = pWC->a + pWC->nTerm;
111079111393
pNew = pBuilder->pNew;
111080111394
memset(&sSum, 0, sizeof(sSum));
111395
+ pItem = pWInfo->pTabList->a + pNew->iTab;
111396
+ iCur = pItem->iCursor;
111081111397
111082111398
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
111083111399
if( (pTerm->eOperator & WO_OR)!=0
111084111400
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
111085111401
){
@@ -111087,12 +111403,10 @@
111087111403
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
111088111404
WhereTerm *pOrTerm;
111089111405
int once = 1;
111090111406
int i, j;
111091111407
111092
- pItem = pWInfo->pTabList->a + pNew->iTab;
111093
- iCur = pItem->iCursor;
111094111408
sSubBuild = *pBuilder;
111095111409
sSubBuild.pOrderBy = 0;
111096111410
sSubBuild.pOrSet = &sCur;
111097111411
111098111412
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
@@ -111129,12 +111443,12 @@
111129111443
whereOrMove(&sPrev, &sSum);
111130111444
sSum.n = 0;
111131111445
for(i=0; i<sPrev.n; i++){
111132111446
for(j=0; j<sCur.n; j++){
111133111447
whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
111134
- whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111135
- whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111448
+ sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111449
+ sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111136111450
}
111137111451
}
111138111452
}
111139111453
}
111140111454
pNew->nLTerm = 1;
@@ -111468,23 +111782,23 @@
111468111782
** costs if nRowEst==0.
111469111783
**
111470111784
** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
111471111785
** error occurs.
111472111786
*/
111473
-static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
111787
+static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
111474111788
int mxChoice; /* Maximum number of simultaneous paths tracked */
111475111789
int nLoop; /* Number of terms in the join */
111476111790
Parse *pParse; /* Parsing context */
111477111791
sqlite3 *db; /* The database connection */
111478111792
int iLoop; /* Loop counter over the terms of the join */
111479111793
int ii, jj; /* Loop counters */
111480111794
int mxI = 0; /* Index of next entry to replace */
111481
- WhereCost rCost; /* Cost of a path */
111482
- WhereCost nOut; /* Number of outputs */
111483
- WhereCost mxCost = 0; /* Maximum cost of a set of paths */
111484
- WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
111485
- WhereCost rSortCost; /* Cost to do a sort */
111795
+ LogEst rCost; /* Cost of a path */
111796
+ LogEst nOut; /* Number of outputs */
111797
+ LogEst mxCost = 0; /* Maximum cost of a set of paths */
111798
+ LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
111799
+ LogEst rSortCost; /* Cost to do a sort */
111486111800
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
111487111801
WherePath *aFrom; /* All nFrom paths at the previous level */
111488111802
WherePath *aTo; /* The nTo best paths at the current level */
111489111803
WherePath *pFrom; /* An element of aFrom[] that we are working on */
111490111804
WherePath *pTo; /* An element of aTo[] that we are working on */
@@ -111517,21 +111831,23 @@
111517111831
/* Seed the search with a single WherePath containing zero WhereLoops.
111518111832
**
111519111833
** TUNING: Do not let the number of iterations go above 25. If the cost
111520111834
** of computing an automatic index is not paid back within the first 25
111521111835
** rows, then do not use the automatic index. */
111522
- aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
111836
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
111523111837
nFrom = 1;
111524111838
111525111839
/* Precompute the cost of sorting the final result set, if the caller
111526111840
** to sqlite3WhereBegin() was concerned about sorting */
111527111841
rSortCost = 0;
111528111842
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
111529111843
aFrom[0].isOrderedValid = 1;
111530111844
}else{
111531
- /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
111532
- ** number of output rows. */
111845
+ /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
111846
+ ** number of output rows. The 48 is the expected size of a row to sort.
111847
+ ** FIXME: compute a better estimate of the 48 multiplier based on the
111848
+ ** result set expressions. */
111533111849
rSortCost = nRowEst + estLog(nRowEst);
111534111850
WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
111535111851
}
111536111852
111537111853
/* Compute successively longer WherePaths using the previous generation
@@ -111547,12 +111863,12 @@
111547111863
u8 isOrdered = pFrom->isOrdered;
111548111864
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
111549111865
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
111550111866
/* At this point, pWLoop is a candidate to be the next loop.
111551111867
** Compute its cost */
111552
- rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111553
- rCost = whereCostAdd(rCost, pFrom->rCost);
111868
+ rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111869
+ rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
111554111870
nOut = pFrom->nRow + pWLoop->nOut;
111555111871
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
111556111872
if( !isOrderedValid ){
111557111873
switch( wherePathSatisfiesOrderBy(pWInfo,
111558111874
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
@@ -111562,11 +111878,11 @@
111562111878
isOrderedValid = 1;
111563111879
break;
111564111880
case 0: /* No. pFrom+pWLoop will require a separate sort */
111565111881
isOrdered = 0;
111566111882
isOrderedValid = 1;
111567
- rCost = whereCostAdd(rCost, rSortCost);
111883
+ rCost = sqlite3LogEstAdd(rCost, rSortCost);
111568111884
break;
111569111885
default: /* Cannot tell yet. Try again on the next iteration */
111570111886
break;
111571111887
}
111572111888
}else{
@@ -111769,11 +112085,11 @@
111769112085
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
111770112086
pLoop->aLTerm[0] = pTerm;
111771112087
pLoop->nLTerm = 1;
111772112088
pLoop->u.btree.nEq = 1;
111773112089
/* TUNING: Cost of a rowid lookup is 10 */
111774
- pLoop->rRun = 33; /* 33==whereCost(10) */
112090
+ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
111775112091
}else{
111776112092
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
111777112093
assert( pLoop->aLTermSpace==pLoop->aLTerm );
111778112094
assert( ArraySize(pLoop->aLTermSpace)==4 );
111779112095
if( pIdx->onError==OE_None
@@ -111792,16 +112108,16 @@
111792112108
}
111793112109
pLoop->nLTerm = j;
111794112110
pLoop->u.btree.nEq = j;
111795112111
pLoop->u.btree.pIndex = pIdx;
111796112112
/* TUNING: Cost of a unique index lookup is 15 */
111797
- pLoop->rRun = 39; /* 39==whereCost(15) */
112113
+ pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
111798112114
break;
111799112115
}
111800112116
}
111801112117
if( pLoop->wsFlags ){
111802
- pLoop->nOut = (WhereCost)1;
112118
+ pLoop->nOut = (LogEst)1;
111803112119
pWInfo->a[0].pWLoop = pLoop;
111804112120
pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
111805112121
pWInfo->a[0].iTabCur = iCur;
111806112122
pWInfo->nRowOut = 1;
111807112123
if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
@@ -112165,11 +112481,11 @@
112165112481
WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
112166112482
pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
112167112483
112168112484
/* If the caller is an UPDATE or DELETE statement that is requesting
112169112485
** to use a one-pass algorithm, determine if this is appropriate.
112170
- ** The one-pass algorithm only works if the WHERE clause constraints
112486
+ ** The one-pass algorithm only works if the WHERE clause constrains
112171112487
** the statement to update a single row.
112172112488
*/
112173112489
assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
112174112490
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
112175112491
&& (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
@@ -121583,10 +121899,16 @@
121583121899
** verifying the operation of the SQLite core.
121584121900
*/
121585121901
int inTransaction; /* True after xBegin but before xCommit/xRollback */
121586121902
int mxSavepoint; /* Largest valid xSavepoint integer */
121587121903
#endif
121904
+
121905
+#ifdef SQLITE_TEST
121906
+ /* True to disable the incremental doclist optimization. This is controled
121907
+ ** by special insert command 'test-no-incr-doclist'. */
121908
+ int bNoIncrDoclist;
121909
+#endif
121588121910
};
121589121911
121590121912
/*
121591121913
** When the core wants to read from the virtual table, it creates a
121592121914
** virtual table cursor (an instance of the following structure) using
@@ -121608,11 +121930,12 @@
121608121930
int nDoclist; /* Size of buffer at aDoclist */
121609121931
u8 bDesc; /* True to sort in descending order */
121610121932
int eEvalmode; /* An FTS3_EVAL_XX constant */
121611121933
int nRowAvg; /* Average size of database rows, in pages */
121612121934
sqlite3_int64 nDoc; /* Documents in table */
121613
-
121935
+ i64 iMinDocid; /* Minimum docid to return */
121936
+ i64 iMaxDocid; /* Maximum docid to return */
121614121937
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
121615121938
u32 *aMatchinfo; /* Information about most recent match */
121616121939
int nMatchinfo; /* Number of elements in aMatchinfo[] */
121617121940
char *zMatchinfo; /* Matchinfo specification */
121618121941
};
@@ -121638,10 +121961,19 @@
121638121961
*/
121639121962
#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
121640121963
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
121641121964
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
121642121965
121966
+/*
121967
+** The lower 16-bits of the sqlite3_index_info.idxNum value set by
121968
+** the xBestIndex() method contains the Fts3Cursor.eSearch value described
121969
+** above. The upper 16-bits contain a combination of the following
121970
+** bits, used to describe extra constraints on full-text searches.
121971
+*/
121972
+#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
121973
+#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
121974
+#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
121643121975
121644121976
struct Fts3Doclist {
121645121977
char *aAll; /* Array containing doclist (or NULL) */
121646121978
int nAll; /* Size of a[] in bytes */
121647121979
char *pNextDocid; /* Pointer to next docid */
@@ -123058,27 +123390,31 @@
123058123390
*/
123059123391
static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
123060123392
Fts3Table *p = (Fts3Table *)pVTab;
123061123393
int i; /* Iterator variable */
123062123394
int iCons = -1; /* Index of constraint to use */
123395
+
123063123396
int iLangidCons = -1; /* Index of langid=x constraint, if present */
123397
+ int iDocidGe = -1; /* Index of docid>=x constraint, if present */
123398
+ int iDocidLe = -1; /* Index of docid<=x constraint, if present */
123399
+ int iIdx;
123064123400
123065123401
/* By default use a full table scan. This is an expensive option,
123066123402
** so search through the constraints to see if a more efficient
123067123403
** strategy is possible.
123068123404
*/
123069123405
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
123070123406
pInfo->estimatedCost = 5000000;
123071123407
for(i=0; i<pInfo->nConstraint; i++){
123408
+ int bDocid; /* True if this constraint is on docid */
123072123409
struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
123073123410
if( pCons->usable==0 ) continue;
123411
+
123412
+ bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
123074123413
123075123414
/* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
123076
- if( iCons<0
123077
- && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123078
- && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
123079
- ){
123415
+ if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
123080123416
pInfo->idxNum = FTS3_DOCID_SEARCH;
123081123417
pInfo->estimatedCost = 1.0;
123082123418
iCons = i;
123083123419
}
123084123420
@@ -123103,18 +123439,42 @@
123103123439
if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123104123440
&& pCons->iColumn==p->nColumn + 2
123105123441
){
123106123442
iLangidCons = i;
123107123443
}
123444
+
123445
+ if( bDocid ){
123446
+ switch( pCons->op ){
123447
+ case SQLITE_INDEX_CONSTRAINT_GE:
123448
+ case SQLITE_INDEX_CONSTRAINT_GT:
123449
+ iDocidGe = i;
123450
+ break;
123451
+
123452
+ case SQLITE_INDEX_CONSTRAINT_LE:
123453
+ case SQLITE_INDEX_CONSTRAINT_LT:
123454
+ iDocidLe = i;
123455
+ break;
123456
+ }
123457
+ }
123108123458
}
123109123459
123460
+ iIdx = 1;
123110123461
if( iCons>=0 ){
123111
- pInfo->aConstraintUsage[iCons].argvIndex = 1;
123462
+ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
123112123463
pInfo->aConstraintUsage[iCons].omit = 1;
123113123464
}
123114123465
if( iLangidCons>=0 ){
123115
- pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
123466
+ pInfo->idxNum |= FTS3_HAVE_LANGID;
123467
+ pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
123468
+ }
123469
+ if( iDocidGe>=0 ){
123470
+ pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
123471
+ pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
123472
+ }
123473
+ if( iDocidLe>=0 ){
123474
+ pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
123475
+ pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
123116123476
}
123117123477
123118123478
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
123119123479
** docid) order. Both ascending and descending are possible.
123120123480
*/
@@ -124556,10 +124916,37 @@
124556124916
rc = fts3EvalNext((Fts3Cursor *)pCursor);
124557124917
}
124558124918
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
124559124919
return rc;
124560124920
}
124921
+
124922
+/*
124923
+** The following are copied from sqliteInt.h.
124924
+**
124925
+** Constants for the largest and smallest possible 64-bit signed integers.
124926
+** These macros are designed to work correctly on both 32-bit and 64-bit
124927
+** compilers.
124928
+*/
124929
+#ifndef SQLITE_AMALGAMATION
124930
+# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
124931
+# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
124932
+#endif
124933
+
124934
+/*
124935
+** If the numeric type of argument pVal is "integer", then return it
124936
+** converted to a 64-bit signed integer. Otherwise, return a copy of
124937
+** the second parameter, iDefault.
124938
+*/
124939
+static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
124940
+ if( pVal ){
124941
+ int eType = sqlite3_value_numeric_type(pVal);
124942
+ if( eType==SQLITE_INTEGER ){
124943
+ return sqlite3_value_int64(pVal);
124944
+ }
124945
+ }
124946
+ return iDefault;
124947
+}
124561124948
124562124949
/*
124563124950
** This is the xFilter interface for the virtual table. See
124564124951
** the virtual table xFilter method documentation for additional
124565124952
** information.
@@ -124582,44 +124969,62 @@
124582124969
int nVal, /* Number of elements in apVal */
124583124970
sqlite3_value **apVal /* Arguments for the indexing scheme */
124584124971
){
124585124972
int rc;
124586124973
char *zSql; /* SQL statement used to access %_content */
124974
+ int eSearch;
124587124975
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
124588124976
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
124977
+
124978
+ sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
124979
+ sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
124980
+ sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
124981
+ sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
124982
+ int iIdx;
124589124983
124590124984
UNUSED_PARAMETER(idxStr);
124591124985
UNUSED_PARAMETER(nVal);
124592124986
124593
- assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
124594
- assert( nVal==0 || nVal==1 || nVal==2 );
124595
- assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
124987
+ eSearch = (idxNum & 0x0000FFFF);
124988
+ assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
124596124989
assert( p->pSegments==0 );
124990
+
124991
+ /* Collect arguments into local variables */
124992
+ iIdx = 0;
124993
+ if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
124994
+ if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
124995
+ if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
124996
+ if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
124997
+ assert( iIdx==nVal );
124597124998
124598124999
/* In case the cursor has been used before, clear it now. */
124599125000
sqlite3_finalize(pCsr->pStmt);
124600125001
sqlite3_free(pCsr->aDoclist);
124601125002
sqlite3Fts3ExprFree(pCsr->pExpr);
124602125003
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
124603125004
125005
+ /* Set the lower and upper bounds on docids to return */
125006
+ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
125007
+ pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
125008
+
124604125009
if( idxStr ){
124605125010
pCsr->bDesc = (idxStr[0]=='D');
124606125011
}else{
124607125012
pCsr->bDesc = p->bDescIdx;
124608125013
}
124609
- pCsr->eSearch = (i16)idxNum;
125014
+ pCsr->eSearch = (i16)eSearch;
124610125015
124611
- if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
124612
- int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
124613
- const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
125016
+ if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
125017
+ int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
125018
+ const char *zQuery = (const char *)sqlite3_value_text(pCons);
124614125019
124615
- if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
125020
+ if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
124616125021
return SQLITE_NOMEM;
124617125022
}
124618125023
124619125024
pCsr->iLangid = 0;
124620
- if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
125025
+ if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
124621125026
124622125027
assert( p->base.zErrMsg==0 );
124623125028
rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
124624125029
p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
124625125030
&p->base.zErrMsg
@@ -124638,11 +125043,11 @@
124638125043
/* Compile a SELECT statement for this cursor. For a full-table-scan, the
124639125044
** statement loops through all rows of the %_content table. For a
124640125045
** full-text query or docid lookup, the statement retrieves a single
124641125046
** row by docid.
124642125047
*/
124643
- if( idxNum==FTS3_FULLSCAN_SEARCH ){
125048
+ if( eSearch==FTS3_FULLSCAN_SEARCH ){
124644125049
zSql = sqlite3_mprintf(
124645125050
"SELECT %s ORDER BY rowid %s",
124646125051
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
124647125052
);
124648125053
if( zSql ){
@@ -124649,14 +125054,14 @@
124649125054
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
124650125055
sqlite3_free(zSql);
124651125056
}else{
124652125057
rc = SQLITE_NOMEM;
124653125058
}
124654
- }else if( idxNum==FTS3_DOCID_SEARCH ){
125059
+ }else if( eSearch==FTS3_DOCID_SEARCH ){
124655125060
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
124656125061
if( rc==SQLITE_OK ){
124657
- rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
125062
+ rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
124658125063
}
124659125064
}
124660125065
if( rc!=SQLITE_OK ) return rc;
124661125066
124662125067
return fts3NextMethod(pCursor);
@@ -125543,10 +125948,16 @@
125543125948
}
125544125949
125545125950
return SQLITE_OK;
125546125951
}
125547125952
125953
+/*
125954
+** Maximum number of tokens a phrase may have to be considered for the
125955
+** incremental doclists strategy.
125956
+*/
125957
+#define MAX_INCR_PHRASE_TOKENS 4
125958
+
125548125959
/*
125549125960
** This function is called for each Fts3Phrase in a full-text query
125550125961
** expression to initialize the mechanism for returning rows. Once this
125551125962
** function has been called successfully on an Fts3Phrase, it may be
125552125963
** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -125556,27 +125967,47 @@
125556125967
** memory within this call.
125557125968
**
125558125969
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
125559125970
*/
125560125971
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
125561
- int rc; /* Error code */
125562
- Fts3PhraseToken *pFirst = &p->aToken[0];
125563125972
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125564
-
125565
- if( pCsr->bDesc==pTab->bDescIdx
125566
- && bOptOk==1
125567
- && p->nToken==1
125568
- && pFirst->pSegcsr
125569
- && pFirst->pSegcsr->bLookup
125570
- && pFirst->bFirst==0
125571
- ){
125973
+ int rc = SQLITE_OK; /* Error code */
125974
+ int i;
125975
+
125976
+ /* Determine if doclists may be loaded from disk incrementally. This is
125977
+ ** possible if the bOptOk argument is true, the FTS doclists will be
125978
+ ** scanned in forward order, and the phrase consists of
125979
+ ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
125980
+ ** tokens or prefix tokens that cannot use a prefix-index. */
125981
+ int bHaveIncr = 0;
125982
+ int bIncrOk = (bOptOk
125983
+ && pCsr->bDesc==pTab->bDescIdx
125984
+ && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
125985
+ && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
125986
+#ifdef SQLITE_TEST
125987
+ && pTab->bNoIncrDoclist==0
125988
+#endif
125989
+ );
125990
+ for(i=0; bIncrOk==1 && i<p->nToken; i++){
125991
+ Fts3PhraseToken *pToken = &p->aToken[i];
125992
+ if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
125993
+ bIncrOk = 0;
125994
+ }
125995
+ if( pToken->pSegcsr ) bHaveIncr = 1;
125996
+ }
125997
+
125998
+ if( bIncrOk && bHaveIncr ){
125572125999
/* Use the incremental approach. */
125573126000
int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
125574
- rc = sqlite3Fts3MsrIncrStart(
125575
- pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
126001
+ for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
126002
+ Fts3PhraseToken *pToken = &p->aToken[i];
126003
+ Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
126004
+ if( pSegcsr ){
126005
+ rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
126006
+ }
126007
+ }
125576126008
p->bIncr = 1;
125577
-
125578126009
}else{
125579126010
/* Load the full doclist for the phrase into memory. */
125580126011
rc = fts3EvalPhraseLoad(pCsr, p);
125581126012
p->bIncr = 0;
125582126013
}
@@ -125680,10 +126111,220 @@
125680126111
}
125681126112
}
125682126113
125683126114
*ppIter = p;
125684126115
}
126116
+
126117
+/*
126118
+** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
126119
+** to true if EOF is reached.
126120
+*/
126121
+static void fts3EvalDlPhraseNext(
126122
+ Fts3Table *pTab,
126123
+ Fts3Doclist *pDL,
126124
+ u8 *pbEof
126125
+){
126126
+ char *pIter; /* Used to iterate through aAll */
126127
+ char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
126128
+
126129
+ if( pDL->pNextDocid ){
126130
+ pIter = pDL->pNextDocid;
126131
+ }else{
126132
+ pIter = pDL->aAll;
126133
+ }
126134
+
126135
+ if( pIter>=pEnd ){
126136
+ /* We have already reached the end of this doclist. EOF. */
126137
+ *pbEof = 1;
126138
+ }else{
126139
+ sqlite3_int64 iDelta;
126140
+ pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
126141
+ if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
126142
+ pDL->iDocid += iDelta;
126143
+ }else{
126144
+ pDL->iDocid -= iDelta;
126145
+ }
126146
+ pDL->pList = pIter;
126147
+ fts3PoslistCopy(0, &pIter);
126148
+ pDL->nList = (int)(pIter - pDL->pList);
126149
+
126150
+ /* pIter now points just past the 0x00 that terminates the position-
126151
+ ** list for document pDL->iDocid. However, if this position-list was
126152
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
126153
+ ** point to the start of the next docid value. The following line deals
126154
+ ** with this case by advancing pIter past the zero-padding added by
126155
+ ** fts3EvalNearTrim(). */
126156
+ while( pIter<pEnd && *pIter==0 ) pIter++;
126157
+
126158
+ pDL->pNextDocid = pIter;
126159
+ assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
126160
+ *pbEof = 0;
126161
+ }
126162
+}
126163
+
126164
+/*
126165
+** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
126166
+*/
126167
+typedef struct TokenDoclist TokenDoclist;
126168
+struct TokenDoclist {
126169
+ int bIgnore;
126170
+ sqlite3_int64 iDocid;
126171
+ char *pList;
126172
+ int nList;
126173
+};
126174
+
126175
+/*
126176
+** Token pToken is an incrementally loaded token that is part of a
126177
+** multi-token phrase. Advance it to the next matching document in the
126178
+** database and populate output variable *p with the details of the new
126179
+** entry. Or, if the iterator has reached EOF, set *pbEof to true.
126180
+**
126181
+** If an error occurs, return an SQLite error code. Otherwise, return
126182
+** SQLITE_OK.
126183
+*/
126184
+static int incrPhraseTokenNext(
126185
+ Fts3Table *pTab, /* Virtual table handle */
126186
+ Fts3Phrase *pPhrase, /* Phrase to advance token of */
126187
+ int iToken, /* Specific token to advance */
126188
+ TokenDoclist *p, /* OUT: Docid and doclist for new entry */
126189
+ u8 *pbEof /* OUT: True if iterator is at EOF */
126190
+){
126191
+ int rc = SQLITE_OK;
126192
+
126193
+ if( pPhrase->iDoclistToken==iToken ){
126194
+ assert( p->bIgnore==0 );
126195
+ assert( pPhrase->aToken[iToken].pSegcsr==0 );
126196
+ fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
126197
+ p->pList = pPhrase->doclist.pList;
126198
+ p->nList = pPhrase->doclist.nList;
126199
+ p->iDocid = pPhrase->doclist.iDocid;
126200
+ }else{
126201
+ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
126202
+ assert( pToken->pDeferred==0 );
126203
+ assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
126204
+ if( pToken->pSegcsr ){
126205
+ assert( p->bIgnore==0 );
126206
+ rc = sqlite3Fts3MsrIncrNext(
126207
+ pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
126208
+ );
126209
+ if( p->pList==0 ) *pbEof = 1;
126210
+ }else{
126211
+ p->bIgnore = 1;
126212
+ }
126213
+ }
126214
+
126215
+ return rc;
126216
+}
126217
+
126218
+
126219
+/*
126220
+** The phrase iterator passed as the second argument:
126221
+**
126222
+** * features at least one token that uses an incremental doclist, and
126223
+**
126224
+** * does not contain any deferred tokens.
126225
+**
126226
+** Advance it to the next matching documnent in the database and populate
126227
+** the Fts3Doclist.pList and nList fields.
126228
+**
126229
+** If there is no "next" entry and no error occurs, then *pbEof is set to
126230
+** 1 before returning. Otherwise, if no error occurs and the iterator is
126231
+** successfully advanced, *pbEof is set to 0.
126232
+**
126233
+** If an error occurs, return an SQLite error code. Otherwise, return
126234
+** SQLITE_OK.
126235
+*/
126236
+static int fts3EvalIncrPhraseNext(
126237
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
126238
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
126239
+ u8 *pbEof /* OUT: Set to 1 if EOF */
126240
+){
126241
+ int rc = SQLITE_OK;
126242
+ Fts3Doclist *pDL = &p->doclist;
126243
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126244
+ u8 bEof = 0;
126245
+
126246
+ /* This is only called if it is guaranteed that the phrase has at least
126247
+ ** one incremental token. In which case the bIncr flag is set. */
126248
+ assert( p->bIncr==1 );
126249
+
126250
+ if( p->nToken==1 && p->bIncr ){
126251
+ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
126252
+ &pDL->iDocid, &pDL->pList, &pDL->nList
126253
+ );
126254
+ if( pDL->pList==0 ) bEof = 1;
126255
+ }else{
126256
+ int bDescDoclist = pCsr->bDesc;
126257
+ struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
126258
+
126259
+ memset(a, 0, sizeof(a));
126260
+ assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
126261
+ assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
126262
+
126263
+ while( bEof==0 ){
126264
+ int bMaxSet = 0;
126265
+ sqlite3_int64 iMax; /* Largest docid for all iterators */
126266
+ int i; /* Used to iterate through tokens */
126267
+
126268
+ /* Advance the iterator for each token in the phrase once. */
126269
+ for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
126270
+ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126271
+ if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
126272
+ iMax = a[i].iDocid;
126273
+ bMaxSet = 1;
126274
+ }
126275
+ }
126276
+ assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
126277
+ assert( rc!=SQLITE_OK || bMaxSet );
126278
+
126279
+ /* Keep advancing iterators until they all point to the same document */
126280
+ for(i=0; i<p->nToken; i++){
126281
+ while( rc==SQLITE_OK && bEof==0
126282
+ && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
126283
+ ){
126284
+ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126285
+ if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
126286
+ iMax = a[i].iDocid;
126287
+ i = 0;
126288
+ }
126289
+ }
126290
+ }
126291
+
126292
+ /* Check if the current entries really are a phrase match */
126293
+ if( bEof==0 ){
126294
+ int nList = 0;
126295
+ int nByte = a[p->nToken-1].nList;
126296
+ char *aDoclist = sqlite3_malloc(nByte+1);
126297
+ if( !aDoclist ) return SQLITE_NOMEM;
126298
+ memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
126299
+
126300
+ for(i=0; i<(p->nToken-1); i++){
126301
+ if( a[i].bIgnore==0 ){
126302
+ char *pL = a[i].pList;
126303
+ char *pR = aDoclist;
126304
+ char *pOut = aDoclist;
126305
+ int nDist = p->nToken-1-i;
126306
+ int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
126307
+ if( res==0 ) break;
126308
+ nList = (pOut - aDoclist);
126309
+ }
126310
+ }
126311
+ if( i==(p->nToken-1) ){
126312
+ pDL->iDocid = iMax;
126313
+ pDL->pList = aDoclist;
126314
+ pDL->nList = nList;
126315
+ pDL->bFreeList = 1;
126316
+ break;
126317
+ }
126318
+ sqlite3_free(aDoclist);
126319
+ }
126320
+ }
126321
+ }
126322
+
126323
+ *pbEof = bEof;
126324
+ return rc;
126325
+}
125685126326
125686126327
/*
125687126328
** Attempt to move the phrase iterator to point to the next matching docid.
125688126329
** If an error occurs, return an SQLite error code. Otherwise, return
125689126330
** SQLITE_OK.
@@ -125700,59 +126341,18 @@
125700126341
int rc = SQLITE_OK;
125701126342
Fts3Doclist *pDL = &p->doclist;
125702126343
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125703126344
125704126345
if( p->bIncr ){
125705
- assert( p->nToken==1 );
125706
- assert( pDL->pNextDocid==0 );
125707
- rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
125708
- &pDL->iDocid, &pDL->pList, &pDL->nList
125709
- );
125710
- if( rc==SQLITE_OK && !pDL->pList ){
125711
- *pbEof = 1;
125712
- }
126346
+ rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
125713126347
}else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
125714126348
sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
125715126349
&pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
125716126350
);
125717126351
pDL->pList = pDL->pNextDocid;
125718126352
}else{
125719
- char *pIter; /* Used to iterate through aAll */
125720
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
125721
- if( pDL->pNextDocid ){
125722
- pIter = pDL->pNextDocid;
125723
- }else{
125724
- pIter = pDL->aAll;
125725
- }
125726
-
125727
- if( pIter>=pEnd ){
125728
- /* We have already reached the end of this doclist. EOF. */
125729
- *pbEof = 1;
125730
- }else{
125731
- sqlite3_int64 iDelta;
125732
- pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
125733
- if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
125734
- pDL->iDocid += iDelta;
125735
- }else{
125736
- pDL->iDocid -= iDelta;
125737
- }
125738
- pDL->pList = pIter;
125739
- fts3PoslistCopy(0, &pIter);
125740
- pDL->nList = (int)(pIter - pDL->pList);
125741
-
125742
- /* pIter now points just past the 0x00 that terminates the position-
125743
- ** list for document pDL->iDocid. However, if this position-list was
125744
- ** edited in place by fts3EvalNearTrim(), then pIter may not actually
125745
- ** point to the start of the next docid value. The following line deals
125746
- ** with this case by advancing pIter past the zero-padding added by
125747
- ** fts3EvalNearTrim(). */
125748
- while( pIter<pEnd && *pIter==0 ) pIter++;
125749
-
125750
- pDL->pNextDocid = pIter;
125751
- assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
125752
- *pbEof = 0;
125753
- }
126353
+ fts3EvalDlPhraseNext(pTab, pDL, pbEof);
125754126354
}
125755126355
125756126356
return rc;
125757126357
}
125758126358
@@ -125773,11 +126373,10 @@
125773126373
** code before returning.
125774126374
*/
125775126375
static void fts3EvalStartReaders(
125776126376
Fts3Cursor *pCsr, /* FTS Cursor handle */
125777126377
Fts3Expr *pExpr, /* Expression to initialize phrases in */
125778
- int bOptOk, /* True to enable incremental loading */
125779126378
int *pRc /* IN/OUT: Error code */
125780126379
){
125781126380
if( pExpr && SQLITE_OK==*pRc ){
125782126381
if( pExpr->eType==FTSQUERY_PHRASE ){
125783126382
int i;
@@ -125784,14 +126383,14 @@
125784126383
int nToken = pExpr->pPhrase->nToken;
125785126384
for(i=0; i<nToken; i++){
125786126385
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
125787126386
}
125788126387
pExpr->bDeferred = (i==nToken);
125789
- *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
126388
+ *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
125790126389
}else{
125791
- fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
125792
- fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
126390
+ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
126391
+ fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
125793126392
pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
125794126393
}
125795126394
}
125796126395
}
125797126396
@@ -126029,11 +126628,11 @@
126029126628
/* Set nLoad4 to the value of (4^nOther) for the next iteration of the
126030126629
** for-loop. Except, limit the value to 2^24 to prevent it from
126031126630
** overflowing the 32-bit integer it is stored in. */
126032126631
if( ii<12 ) nLoad4 = nLoad4*4;
126033126632
126034
- if( ii==0 || pTC->pPhrase->nToken>1 ){
126633
+ if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
126035126634
/* Either this is the cheapest token in the entire query, or it is
126036126635
** part of a multi-token phrase. Either way, the entire doclist will
126037126636
** (eventually) be loaded into memory. It may as well be now. */
126038126637
Fts3PhraseToken *pToken = pTC->pToken;
126039126638
int nList = 0;
@@ -126109,11 +126708,11 @@
126109126708
sqlite3_free(aTC);
126110126709
}
126111126710
}
126112126711
#endif
126113126712
126114
- fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
126713
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
126115126714
return rc;
126116126715
}
126117126716
126118126717
/*
126119126718
** Invalidate the current position list for phrase pPhrase.
@@ -126592,10 +127191,20 @@
126592127191
pCsr->isRequireSeek = 1;
126593127192
pCsr->isMatchinfoNeeded = 1;
126594127193
pCsr->iPrevId = pExpr->iDocid;
126595127194
}while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
126596127195
}
127196
+
127197
+ /* Check if the cursor is past the end of the docid range specified
127198
+ ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
127199
+ if( rc==SQLITE_OK && (
127200
+ (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
127201
+ || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
127202
+ )){
127203
+ pCsr->isEof = 1;
127204
+ }
127205
+
126597127206
return rc;
126598127207
}
126599127208
126600127209
/*
126601127210
** Restart interation for expression pExpr so that the next call to
@@ -126615,16 +127224,20 @@
126615127224
Fts3Phrase *pPhrase = pExpr->pPhrase;
126616127225
126617127226
if( pPhrase ){
126618127227
fts3EvalInvalidatePoslist(pPhrase);
126619127228
if( pPhrase->bIncr ){
126620
- assert( pPhrase->nToken==1 );
126621
- assert( pPhrase->aToken[0].pSegcsr );
126622
- sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
127229
+ int i;
127230
+ for(i=0; i<pPhrase->nToken; i++){
127231
+ Fts3PhraseToken *pToken = &pPhrase->aToken[i];
127232
+ assert( pToken->pDeferred==0 );
127233
+ if( pToken->pSegcsr ){
127234
+ sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
127235
+ }
127236
+ }
126623127237
*pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
126624127238
}
126625
-
126626127239
pPhrase->doclist.pNextDocid = 0;
126627127240
pPhrase->doclist.iDocid = 0;
126628127241
}
126629127242
126630127243
pExpr->iDocid = 0;
@@ -126869,19 +127482,27 @@
126869127482
126870127483
iDocid = pExpr->iDocid;
126871127484
pIter = pPhrase->doclist.pList;
126872127485
if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
126873127486
int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
127487
+ int iMul; /* +1 if csr dir matches index dir, else -1 */
126874127488
int bOr = 0;
126875127489
u8 bEof = 0;
126876
- Fts3Expr *p;
127490
+ u8 bTreeEof = 0;
127491
+ Fts3Expr *p; /* Used to iterate from pExpr to root */
127492
+ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
126877127493
126878127494
/* Check if this phrase descends from an OR expression node. If not,
126879127495
** return NULL. Otherwise, the entry that corresponds to docid
126880
- ** pCsr->iPrevId may lie earlier in the doclist buffer. */
127496
+ ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
127497
+ ** tree that the node is part of has been marked as EOF, but the node
127498
+ ** itself is not EOF, then it may point to an earlier entry. */
127499
+ pNear = pExpr;
126881127500
for(p=pExpr->pParent; p; p=p->pParent){
126882127501
if( p->eType==FTSQUERY_OR ) bOr = 1;
127502
+ if( p->eType==FTSQUERY_NEAR ) pNear = p;
127503
+ if( p->bEof ) bTreeEof = 1;
126883127504
}
126884127505
if( bOr==0 ) return SQLITE_OK;
126885127506
126886127507
/* This is the descendent of an OR node. In this case we cannot use
126887127508
** an incremental phrase. Load the entire doclist for the phrase
@@ -126896,33 +127517,63 @@
126896127517
}
126897127518
pIter = pPhrase->doclist.pList;
126898127519
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
126899127520
if( rc!=SQLITE_OK ) return rc;
126900127521
}
127522
+
127523
+ iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
127524
+ while( bTreeEof==1
127525
+ && pNear->bEof==0
127526
+ && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
127527
+ ){
127528
+ int rc = SQLITE_OK;
127529
+ fts3EvalNextRow(pCsr, pExpr, &rc);
127530
+ if( rc!=SQLITE_OK ) return rc;
127531
+ iDocid = pExpr->iDocid;
127532
+ pIter = pPhrase->doclist.pList;
127533
+ }
126901127534
126902
- if( pExpr->bEof ){
126903
- pIter = 0;
126904
- iDocid = 0;
126905
- }
126906127535
bEof = (pPhrase->doclist.nAll==0);
126907127536
assert( bDescDoclist==0 || bDescDoclist==1 );
126908127537
assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
126909127538
126910
- if( pCsr->bDesc==bDescDoclist ){
126911
- int dummy;
126912
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
126913
- sqlite3Fts3DoclistPrev(
126914
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126915
- &pIter, &iDocid, &dummy, &bEof
126916
- );
126917
- }
126918
- }else{
126919
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
126920
- sqlite3Fts3DoclistNext(
126921
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126922
- &pIter, &iDocid, &bEof
126923
- );
127539
+ if( bEof==0 ){
127540
+ if( pCsr->bDesc==bDescDoclist ){
127541
+ int dummy;
127542
+ if( pNear->bEof ){
127543
+ /* This expression is already at EOF. So position it to point to the
127544
+ ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
127545
+ ** iDocid is already set for this entry, so all that is required is
127546
+ ** to set pIter to point to the first byte of the last position-list
127547
+ ** in the doclist.
127548
+ **
127549
+ ** It would also be correct to set pIter and iDocid to zero. In
127550
+ ** this case, the first call to sqltie3Fts4DoclistPrev() below
127551
+ ** would also move the iterator to point to the last entry in the
127552
+ ** doclist. However, this is expensive, as to do so it has to
127553
+ ** iterate through the entire doclist from start to finish (since
127554
+ ** it does not know the docid for the last entry). */
127555
+ pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
127556
+ fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
127557
+ }
127558
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
127559
+ sqlite3Fts3DoclistPrev(
127560
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127561
+ &pIter, &iDocid, &dummy, &bEof
127562
+ );
127563
+ }
127564
+ }else{
127565
+ if( pNear->bEof ){
127566
+ pIter = 0;
127567
+ iDocid = 0;
127568
+ }
127569
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
127570
+ sqlite3Fts3DoclistNext(
127571
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127572
+ &pIter, &iDocid, &bEof
127573
+ );
127574
+ }
126924127575
}
126925127576
}
126926127577
126927127578
if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
126928127579
}
@@ -135756,11 +136407,11 @@
135756136407
assert( p->bFts4==0 );
135757136408
sqlite3Fts3CreateStatTable(&rc, p);
135758136409
if( rc ) return rc;
135759136410
}
135760136411
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
135761
- if( rc ) return rc;;
136412
+ if( rc ) return rc;
135762136413
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
135763136414
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
135764136415
sqlite3_step(pStmt);
135765136416
rc = sqlite3_reset(pStmt);
135766136417
return rc;
@@ -136025,10 +136676,13 @@
136025136676
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
136026136677
p->nNodeSize = atoi(&zVal[9]);
136027136678
rc = SQLITE_OK;
136028136679
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
136029136680
p->nMaxPendingData = atoi(&zVal[11]);
136681
+ rc = SQLITE_OK;
136682
+ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
136683
+ p->bNoIncrDoclist = atoi(&zVal[21]);
136030136684
rc = SQLITE_OK;
136031136685
#endif
136032136686
}else{
136033136687
rc = SQLITE_ERROR;
136034136688
}
136035136689
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -656,11 +656,11 @@
656 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657 ** [sqlite_version()] and [sqlite_source_id()].
658 */
659 #define SQLITE_VERSION "3.8.1"
660 #define SQLITE_VERSION_NUMBER 3008001
661 #define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
662
663 /*
664 ** CAPI3REF: Run-Time Library Version Numbers
665 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
666 **
@@ -8272,10 +8272,35 @@
8272 typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
8273 #else
8274 typedef u32 tRowcnt; /* 32-bit is the default */
8275 #endif
8276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8277 /*
8278 ** Macros to determine whether the machine is big or little endian,
8279 ** evaluated at runtime.
8280 */
8281 #ifdef SQLITE_AMALGAMATION
@@ -10419,11 +10444,12 @@
10419 char *zDflt; /* Original text of the default value */
10420 char *zType; /* Data type for this column */
10421 char *zColl; /* Collating sequence. If NULL, use the default */
10422 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
10423 char affinity; /* One of the SQLITE_AFF_... values */
10424 u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
 
10425 };
10426
10427 /* Allowed values for Column.colFlags:
10428 */
10429 #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
@@ -10583,10 +10609,11 @@
10583 tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
10584 int tnum; /* Root BTree node for this table (see note above) */
10585 i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
10586 i16 nCol; /* Number of columns in this table */
10587 u16 nRef; /* Number of pointers to this Table */
 
10588 u8 tabFlags; /* Mask of TF_* values */
10589 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10590 #ifndef SQLITE_OMIT_ALTERTABLE
10591 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10592 #endif
@@ -10694,11 +10721,11 @@
10694 #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
10695 #define OE_SetNull 7 /* Set the foreign key value to NULL */
10696 #define OE_SetDflt 8 /* Set the foreign key value to its default */
10697 #define OE_Cascade 9 /* Cascade the changes */
10698
10699 #define OE_Default 99 /* Do whatever the default action is */
10700
10701
10702 /*
10703 ** An instance of the following structure is passed as the first
10704 ** argument to sqlite3VdbeKeyCompare and is used to control the
@@ -10781,10 +10808,11 @@
10781 Schema *pSchema; /* Schema containing this index */
10782 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
10783 char **azColl; /* Array of collation sequence names for index */
10784 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
10785 int tnum; /* DB Page containing root of this index */
 
10786 u16 nColumn; /* Number of columns in table used by this index */
10787 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10788 unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
10789 unsigned bUnordered:1; /* Use this index for == or IN queries only */
10790 unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
@@ -11636,10 +11664,11 @@
11636 */
11637 typedef struct DbFixer DbFixer;
11638 struct DbFixer {
11639 Parse *pParse; /* The parsing context. Error messages written here */
11640 Schema *pSchema; /* Fix items to this schema */
 
11641 const char *zDb; /* Make sure all objects are contained in this database */
11642 const char *zType; /* Type of the container - used for error messages */
11643 const Token *pName; /* Name of the container - used for error messages */
11644 };
11645
@@ -12174,11 +12203,11 @@
12174 # define sqlite3AuthContextPush(a,b,c)
12175 # define sqlite3AuthContextPop(a) ((void)(a))
12176 #endif
12177 SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
12178 SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
12179 SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
12180 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
12181 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
12182 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
12183 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
12184 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
@@ -12186,10 +12215,16 @@
12186 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
12187 SQLITE_PRIVATE int sqlite3Atoi(const char*);
12188 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
12189 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
12190 SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
 
 
 
 
 
 
12191
12192 /*
12193 ** Routines to read and write variable-length integers. These used to
12194 ** be defined locally, but now we use the varint routines in the util.c
12195 ** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -12302,11 +12337,11 @@
12302 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
12303 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
12304 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
12305 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
12306 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12307 SQLITE_PRIVATE char sqlite3AffinityType(const char*);
12308 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
12309 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
12310 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
12311 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
12312 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -22387,10 +22422,87 @@
22387 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
22388 if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
22389 }
22390 }
22391 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22392
22393 /************** End of util.c ************************************************/
22394 /************** Begin file hash.c ********************************************/
22395 /*
22396 ** 2001 September 22
@@ -48986,17 +49098,17 @@
48986 ** page contain a special header (the "file header") that describes the file.
48987 ** The format of the file header is as follows:
48988 **
48989 ** OFFSET SIZE DESCRIPTION
48990 ** 0 16 Header string: "SQLite format 3\000"
48991 ** 16 2 Page size in bytes.
48992 ** 18 1 File format write version
48993 ** 19 1 File format read version
48994 ** 20 1 Bytes of unused space at the end of each page
48995 ** 21 1 Max embedded payload fraction
48996 ** 22 1 Min embedded payload fraction
48997 ** 23 1 Min leaf payload fraction
48998 ** 24 4 File change counter
48999 ** 28 4 Reserved for future use
49000 ** 32 4 First freelist page
49001 ** 36 4 Number of freelist pages in the file
49002 ** 40 60 15 4-byte meta values passed to higher layers
@@ -49006,13 +49118,14 @@
49006 ** 48 4 Size of page cache
49007 ** 52 4 Largest root-page (auto/incr_vacuum)
49008 ** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
49009 ** 60 4 User version
49010 ** 64 4 Incremental vacuum mode
49011 ** 68 4 unused
49012 ** 72 4 unused
49013 ** 76 4 unused
 
49014 **
49015 ** All of the integer values are big-endian (most significant byte first).
49016 **
49017 ** The file change counter is incremented when the database is changed
49018 ** This counter allows other processes to know when the file has changed
@@ -52378,11 +52491,10 @@
52378 pBt->max1bytePayload = (u8)pBt->maxLocal;
52379 }
52380 assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
52381 pBt->pPage1 = pPage1;
52382 pBt->nPage = nPage;
52383 assert( pPage1->leaf==0 || pPage1->leaf==1 );
52384 return SQLITE_OK;
52385
52386 page1_init_failed:
52387 releasePage(pPage1);
52388 pBt->pPage1 = 0;
@@ -52538,11 +52650,11 @@
52538 ** is requested, this is a no-op.
52539 */
52540 if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
52541 goto trans_begun;
52542 }
52543 assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
52544
52545 /* Write transactions are not possible on a read-only database */
52546 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
52547 rc = SQLITE_READONLY;
52548 goto trans_begun;
@@ -62977,10 +63089,11 @@
62977 }
62978 fclose(out);
62979 }
62980 }
62981 #endif
 
62982 p->magic = VDBE_MAGIC_INIT;
62983 return p->rc & db->errMask;
62984 }
62985
62986 /*
@@ -76082,11 +76195,11 @@
76082 return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
76083 }
76084 #ifndef SQLITE_OMIT_CAST
76085 if( op==TK_CAST ){
76086 assert( !ExprHasProperty(pExpr, EP_IntValue) );
76087 return sqlite3AffinityType(pExpr->u.zToken);
76088 }
76089 #endif
76090 if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
76091 && pExpr->pTab!=0
76092 ){
@@ -78502,11 +78615,11 @@
78502 case TK_CAST: {
78503 /* Expressions of the form: CAST(pLeft AS token) */
78504 int aff, to_op;
78505 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
78506 assert( !ExprHasProperty(pExpr, EP_IntValue) );
78507 aff = sqlite3AffinityType(pExpr->u.zToken);
78508 to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
78509 assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
78510 assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
78511 assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
78512 assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
@@ -79169,11 +79282,11 @@
79169 }
79170 #ifndef SQLITE_OMIT_CAST
79171 case TK_CAST: {
79172 /* Expressions of the form: CAST(pLeft AS token) */
79173 const char *zAff = "unk";
79174 switch( sqlite3AffinityType(pExpr->u.zToken) ){
79175 case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
79176 case SQLITE_AFF_NONE: zAff = "NONE"; break;
79177 case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
79178 case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
79179 case SQLITE_AFF_REAL: zAff = "REAL"; break;
@@ -81884,16 +81997,16 @@
81884 if( zRet==0 ){
81885 sqlite3_result_error_nomem(context);
81886 return;
81887 }
81888
81889 sqlite3_snprintf(24, zRet, "%lld", p->nRow);
81890 z = zRet + sqlite3Strlen30(zRet);
81891 for(i=0; i<(p->nCol-1); i++){
81892 i64 nDistinct = p->current.anDLt[i] + 1;
81893 i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
81894 sqlite3_snprintf(24, z, " %lld", iVal);
81895 z += sqlite3Strlen30(z);
81896 assert( p->current.anEq[i] );
81897 }
81898 assert( z[0]=='\0' && z>zRet );
81899
@@ -81930,11 +82043,11 @@
81930 sqlite3_result_error_nomem(context);
81931 }else{
81932 int i;
81933 char *z = zRet;
81934 for(i=0; i<p->nCol; i++){
81935 sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
81936 z += sqlite3Strlen30(z);
81937 }
81938 assert( z[0]=='\0' && z>zRet );
81939 z[-1] = '\0';
81940 sqlite3_result_text(context, zRet, -1, sqlite3_free);
@@ -82391,22 +82504,20 @@
82391 ** The first argument points to a nul-terminated string containing a
82392 ** list of space separated integers. Read the first nOut of these into
82393 ** the array aOut[].
82394 */
82395 static void decodeIntArray(
82396 char *zIntArray,
82397 int nOut,
82398 tRowcnt *aOut,
82399 int *pbUnordered
82400 ){
82401 char *z = zIntArray;
82402 int c;
82403 int i;
82404 tRowcnt v;
82405
82406 assert( pbUnordered==0 || *pbUnordered==0 );
82407
82408 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
82409 if( z==0 ) z = "";
82410 #else
82411 if( NEVER(z==0) ) z = "";
82412 #endif
@@ -82417,12 +82528,23 @@
82417 z++;
82418 }
82419 aOut[i] = v;
82420 if( *z==' ' ) z++;
82421 }
82422 if( pbUnordered && strcmp(z, "unordered")==0 ){
82423 *pbUnordered = 1;
 
 
 
 
 
 
 
 
 
 
 
82424 }
82425 }
82426
82427 /*
82428 ** This callback is invoked once for each index when reading the
@@ -82457,16 +82579,17 @@
82457 pIndex = 0;
82458 }
82459 z = argv[2];
82460
82461 if( pIndex ){
82462 int bUnordered = 0;
82463 decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered);
82464 if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
82465 pIndex->bUnordered = bUnordered;
82466 }else{
82467 decodeIntArray((char*)z, 1, &pTable->nRowEst, 0);
 
 
 
82468 }
82469
82470 return 0;
82471 }
82472
@@ -83185,32 +83308,28 @@
83185 #endif /* SQLITE_OMIT_ATTACH */
83186
83187 /*
83188 ** Initialize a DbFixer structure. This routine must be called prior
83189 ** to passing the structure to one of the sqliteFixAAAA() routines below.
83190 **
83191 ** The return value indicates whether or not fixation is required. TRUE
83192 ** means we do need to fix the database references, FALSE means we do not.
83193 */
83194 SQLITE_PRIVATE int sqlite3FixInit(
83195 DbFixer *pFix, /* The fixer to be initialized */
83196 Parse *pParse, /* Error messages will be written here */
83197 int iDb, /* This is the database that must be used */
83198 const char *zType, /* "view", "trigger", or "index" */
83199 const Token *pName /* Name of the view, trigger, or index */
83200 ){
83201 sqlite3 *db;
83202
83203 if( NEVER(iDb<0) || iDb==1 ) return 0;
83204 db = pParse->db;
83205 assert( db->nDb>iDb );
83206 pFix->pParse = pParse;
83207 pFix->zDb = db->aDb[iDb].zName;
83208 pFix->pSchema = db->aDb[iDb].pSchema;
83209 pFix->zType = zType;
83210 pFix->pName = pName;
83211 return 1;
83212 }
83213
83214 /*
83215 ** The following set of routines walk through the parse tree and assign
83216 ** a specific database to all table references where the database name
@@ -83234,19 +83353,21 @@
83234 struct SrcList_item *pItem;
83235
83236 if( NEVER(pList==0) ) return 0;
83237 zDb = pFix->zDb;
83238 for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
83239 if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83240 sqlite3ErrorMsg(pFix->pParse,
83241 "%s %T cannot reference objects in database %s",
83242 pFix->zType, pFix->pName, pItem->zDatabase);
83243 return 1;
83244 }
83245 sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83246 pItem->zDatabase = 0;
83247 pItem->pSchema = pFix->pSchema;
 
 
83248 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
83249 if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
83250 if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
83251 #endif
83252 }
@@ -83264,13 +83385,25 @@
83264 if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
83265 return 1;
83266 }
83267 if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
83268 return 1;
 
 
 
83269 }
83270 if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
83271 return 1;
 
 
 
 
 
 
 
 
 
83272 }
83273 pSelect = pSelect->pPrior;
83274 }
83275 return 0;
83276 }
@@ -83277,10 +83410,18 @@
83277 SQLITE_PRIVATE int sqlite3FixExpr(
83278 DbFixer *pFix, /* Context of the fixation */
83279 Expr *pExpr /* The expression to be fixed to one database */
83280 ){
83281 while( pExpr ){
 
 
 
 
 
 
 
 
83282 if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
83283 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
83284 if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
83285 }else{
83286 if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
@@ -84460,11 +84601,11 @@
84460 }
84461 pTable->zName = zName;
84462 pTable->iPKey = -1;
84463 pTable->pSchema = db->aDb[iDb].pSchema;
84464 pTable->nRef = 1;
84465 pTable->nRowEst = 1000000;
84466 assert( pParse->pNewTable==0 );
84467 pParse->pNewTable = pTable;
84468
84469 /* If this is the magic sqlite_sequence table used by autoincrement,
84470 ** then record a pointer to this table in the main database structure
@@ -84607,10 +84748,11 @@
84607 /* If there is no type specified, columns have the default affinity
84608 ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
84609 ** be called next to set pCol->affinity correctly.
84610 */
84611 pCol->affinity = SQLITE_AFF_NONE;
 
84612 p->nCol++;
84613 }
84614
84615 /*
84616 ** This routine is called by the parser while in the middle of
@@ -84648,26 +84790,30 @@
84648 ** 'DOUB' | SQLITE_AFF_REAL
84649 **
84650 ** If none of the substrings in the above table are found,
84651 ** SQLITE_AFF_NUMERIC is returned.
84652 */
84653 SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
84654 u32 h = 0;
84655 char aff = SQLITE_AFF_NUMERIC;
 
84656
84657 if( zIn ) while( zIn[0] ){
 
84658 h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
84659 zIn++;
84660 if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
84661 aff = SQLITE_AFF_TEXT;
 
84662 }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
84663 aff = SQLITE_AFF_TEXT;
84664 }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
84665 aff = SQLITE_AFF_TEXT;
84666 }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
84667 && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
84668 aff = SQLITE_AFF_NONE;
 
84669 #ifndef SQLITE_OMIT_FLOATING_POINT
84670 }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
84671 && aff==SQLITE_AFF_NUMERIC ){
84672 aff = SQLITE_AFF_REAL;
84673 }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
@@ -84681,10 +84827,32 @@
84681 aff = SQLITE_AFF_INTEGER;
84682 break;
84683 }
84684 }
84685
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84686 return aff;
84687 }
84688
84689 /*
84690 ** This routine is called by the parser while in the middle of
@@ -84702,11 +84870,11 @@
84702 p = pParse->pNewTable;
84703 if( p==0 || NEVER(p->nCol<1) ) return;
84704 pCol = &p->aCol[p->nCol-1];
84705 assert( pCol->zType==0 );
84706 pCol->zType = sqlite3NameFromToken(pParse->db, pType);
84707 pCol->affinity = sqlite3AffinityType(pCol->zType);
84708 }
84709
84710 /*
84711 ** The expression is the default value for the most recently added column
84712 ** of the table currently under construction.
@@ -85050,18 +85218,46 @@
85050 testcase( pCol->affinity==SQLITE_AFF_REAL );
85051
85052 zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
85053 len = sqlite3Strlen30(zType);
85054 assert( pCol->affinity==SQLITE_AFF_NONE
85055 || pCol->affinity==sqlite3AffinityType(zType) );
85056 memcpy(&zStmt[k], zType, len);
85057 k += len;
85058 assert( k<=n );
85059 }
85060 sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
85061 return zStmt;
85062 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85063
85064 /*
85065 ** This routine is called to report the final ")" that terminates
85066 ** a CREATE TABLE statement.
85067 **
@@ -85085,13 +85281,14 @@
85085 Parse *pParse, /* Parse context */
85086 Token *pCons, /* The ',' token after the last column defn. */
85087 Token *pEnd, /* The final ')' token in the CREATE TABLE */
85088 Select *pSelect /* Select from a "CREATE ... AS SELECT" */
85089 ){
85090 Table *p;
85091 sqlite3 *db = pParse->db;
85092 int iDb;
 
85093
85094 if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
85095 return;
85096 }
85097 p = pParse->pNewTable;
@@ -85106,10 +85303,16 @@
85106 */
85107 if( p->pCheck ){
85108 sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
85109 }
85110 #endif /* !defined(SQLITE_OMIT_CHECK) */
 
 
 
 
 
 
85111
85112 /* If the db->init.busy is 1 it means we are reading the SQL off the
85113 ** "sqlite_master" or "sqlite_temp_master" table on the disk.
85114 ** So do not write to the disk again. Extract the root page number
85115 ** for the table from the db->init.newTnum field. (The page number
@@ -85303,13 +85506,12 @@
85303 sqlite3SelectDelete(db, pSelect);
85304 return;
85305 }
85306 sqlite3TwoPartName(pParse, pName1, pName2, &pName);
85307 iDb = sqlite3SchemaToIndex(db, p->pSchema);
85308 if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
85309 && sqlite3FixSelect(&sFix, pSelect)
85310 ){
85311 sqlite3SelectDelete(db, pSelect);
85312 return;
85313 }
85314
85315 /* Make a copy of the entire SELECT statement that defines the view.
@@ -86066,13 +86268,14 @@
86066 sqlite3 *db = pParse->db;
86067 Db *pDb; /* The specific table containing the indexed database */
86068 int iDb; /* Index of the database that is being written */
86069 Token *pName = 0; /* Unqualified name of the index to create */
86070 struct ExprList_item *pListItem; /* For looping over pList */
86071 int nCol;
86072 int nExtra = 0;
86073 char *zExtra;
 
86074
86075 assert( pParse->nErr==0 ); /* Never called with prior errors */
86076 if( db->mallocFailed || IN_DECLARE_VTAB ){
86077 goto exit_create_index;
86078 }
@@ -86105,13 +86308,12 @@
86105 iDb = 1;
86106 }
86107 }
86108 #endif
86109
86110 if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
86111 sqlite3FixSrcList(&sFix, pTblName)
86112 ){
86113 /* Because the parser constructs pTblName from a single identifier,
86114 ** sqlite3FixSrcList can never fail. */
86115 assert(0);
86116 }
86117 pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
@@ -86296,11 +86498,10 @@
86296 ** same column more than once cannot be an error because that would
86297 ** break backwards compatibility - it needs to be a warning.
86298 */
86299 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
86300 const char *zColName = pListItem->zName;
86301 Column *pTabCol;
86302 int requestedSortOrder;
86303 char *zColl; /* Collation sequence name */
86304
86305 for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
86306 if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -86333,10 +86534,11 @@
86333 requestedSortOrder = pListItem->sortOrder & sortOrderMask;
86334 pIndex->aSortOrder[i] = (u8)requestedSortOrder;
86335 if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
86336 }
86337 sqlite3DefaultRowEst(pIndex);
 
86338
86339 if( pTab==pParse->pNewTable ){
86340 /* This routine has been called to create an automatic index as a
86341 ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
86342 ** a PRIMARY KEY or UNIQUE clause following the column definitions.
@@ -88238,10 +88440,11 @@
88238 ** API function sqlite3_count_changes) to be set incorrectly. */
88239 if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
88240 && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
88241 ){
88242 assert( !isView );
 
88243 sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
88244 pTab->zName, P4_STATIC);
88245 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
88246 assert( pIdx->pSchema==pTab->pSchema );
88247 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -93487,10 +93690,11 @@
93487 (char*)pKey, P4_KEYINFO_HANDOFF);
93488 VdbeComment((v, "%s", pSrcIdx->zName));
93489 pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
93490 sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
93491 (char*)pKey, P4_KEYINFO_HANDOFF);
 
93492 VdbeComment((v, "%s", pDestIdx->zName));
93493 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
93494 sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
93495 sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
93496 sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
@@ -94974,181 +95178,363 @@
94974 #define PragTyp_HEXKEY 35
94975 #define PragTyp_KEY 36
94976 #define PragTyp_REKEY 37
94977 #define PragTyp_LOCK_STATUS 38
94978 #define PragTyp_PARSER_TRACE 39
 
94979 static const struct sPragmaNames {
94980 const char *const zName; /* Name of pragma */
94981 u8 ePragTyp; /* PragTyp_XXX value */
 
94982 u32 iArg; /* Extra argument */
94983 } aPragmaNames[] = {
94984 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
94985 { "activate_extensions", PragTyp_ACTIVATE_EXTENSIONS, 0 },
 
 
 
94986 #endif
94987 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
94988 { "application_id", PragTyp_HEADER_VALUE, 0 },
 
 
 
94989 #endif
94990 #if !defined(SQLITE_OMIT_AUTOVACUUM)
94991 { "auto_vacuum", PragTyp_AUTO_VACUUM, 0 },
 
 
 
94992 #endif
94993 #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
94994 { "automatic_index", PragTyp_FLAG,
94995 SQLITE_AutoIndex },
 
 
94996 #endif
94997 { "busy_timeout", PragTyp_BUSY_TIMEOUT, 0 },
 
 
 
94998 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
94999 { "cache_size", PragTyp_CACHE_SIZE, 0 },
 
 
 
95000 #endif
95001 { "cache_spill", PragTyp_FLAG,
95002 SQLITE_CacheSpill },
95003 { "case_sensitive_like", PragTyp_CASE_SENSITIVE_LIKE, 0 },
95004 { "checkpoint_fullfsync", PragTyp_FLAG,
95005 SQLITE_CkptFullFSync },
 
 
 
 
 
 
 
95006 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95007 { "collation_list", PragTyp_COLLATION_LIST, 0 },
 
 
 
95008 #endif
95009 #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
95010 { "compile_options", PragTyp_COMPILE_OPTIONS, 0 },
 
 
 
95011 #endif
95012 { "count_changes", PragTyp_FLAG,
95013 SQLITE_CountRows },
 
 
95014 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
95015 { "data_store_directory", PragTyp_DATA_STORE_DIRECTORY, 0 },
 
 
 
95016 #endif
95017 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95018 { "database_list", PragTyp_DATABASE_LIST, 0 },
 
 
 
95019 #endif
95020 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
95021 { "default_cache_size", PragTyp_DEFAULT_CACHE_SIZE, 0 },
 
 
 
95022 #endif
95023 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95024 { "defer_foreign_keys", PragTyp_FLAG,
95025 SQLITE_DeferFKs },
 
 
95026 #endif
95027 { "empty_result_callbacks", PragTyp_FLAG,
95028 SQLITE_NullCallback },
 
 
95029 #if !defined(SQLITE_OMIT_UTF16)
95030 { "encoding", PragTyp_ENCODING, 0 },
 
 
 
95031 #endif
95032 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95033 { "foreign_key_check", PragTyp_FOREIGN_KEY_CHECK, 0 },
 
 
 
95034 #endif
95035 #if !defined(SQLITE_OMIT_FOREIGN_KEY)
95036 { "foreign_key_list", PragTyp_FOREIGN_KEY_LIST, 0 },
 
 
 
95037 #endif
95038 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95039 { "foreign_keys", PragTyp_FLAG,
95040 SQLITE_ForeignKeys },
 
 
95041 #endif
95042 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95043 { "freelist_count", PragTyp_HEADER_VALUE, 0 },
 
 
 
95044 #endif
95045 { "full_column_names", PragTyp_FLAG,
95046 SQLITE_FullColNames },
95047 { "fullfsync", PragTyp_FLAG,
95048 SQLITE_FullFSync },
 
 
 
 
95049 #if defined(SQLITE_HAS_CODEC)
95050 { "hexkey", PragTyp_HEXKEY, 0 },
 
 
 
 
 
 
 
95051 #endif
95052 #if !defined(SQLITE_OMIT_CHECK)
95053 { "ignore_check_constraints", PragTyp_FLAG,
95054 SQLITE_IgnoreChecks },
 
 
95055 #endif
95056 #if !defined(SQLITE_OMIT_AUTOVACUUM)
95057 { "incremental_vacuum", PragTyp_INCREMENTAL_VACUUM, 0 },
 
 
 
95058 #endif
95059 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95060 { "index_info", PragTyp_INDEX_INFO, 0 },
95061 { "index_list", PragTyp_INDEX_LIST, 0 },
 
 
 
 
 
 
95062 #endif
95063 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95064 { "integrity_check", PragTyp_INTEGRITY_CHECK, 0 },
 
 
 
95065 #endif
95066 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95067 { "journal_mode", PragTyp_JOURNAL_MODE, 0 },
95068 { "journal_size_limit", PragTyp_JOURNAL_SIZE_LIMIT, 0 },
 
 
 
 
 
 
95069 #endif
95070 #if defined(SQLITE_HAS_CODEC)
95071 { "key", PragTyp_KEY, 0 },
 
 
 
95072 #endif
95073 { "legacy_file_format", PragTyp_FLAG,
95074 SQLITE_LegacyFileFmt },
 
 
95075 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
95076 { "lock_proxy_file", PragTyp_LOCK_PROXY_FILE, 0 },
 
 
 
95077 #endif
95078 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
95079 { "lock_status", PragTyp_LOCK_STATUS, 0 },
95080 #endif
95081 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95082 { "locking_mode", PragTyp_LOCKING_MODE, 0 },
95083 { "max_page_count", PragTyp_PAGE_COUNT, 0 },
95084 { "mmap_size", PragTyp_MMAP_SIZE, 0 },
95085 { "page_count", PragTyp_PAGE_COUNT, 0 },
95086 { "page_size", PragTyp_PAGE_SIZE, 0 },
95087 #endif
95088 #if defined(SQLITE_DEBUG)
95089 { "parser_trace", PragTyp_PARSER_TRACE, 0 },
95090 #endif
95091 { "query_only", PragTyp_FLAG,
95092 SQLITE_QueryOnly },
95093 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95094 { "quick_check", PragTyp_INTEGRITY_CHECK, 0 },
95095 #endif
95096 { "read_uncommitted", PragTyp_FLAG,
95097 SQLITE_ReadUncommitted },
95098 { "recursive_triggers", PragTyp_FLAG,
95099 SQLITE_RecTriggers },
95100 #if defined(SQLITE_HAS_CODEC)
95101 { "rekey", PragTyp_REKEY, 0 },
95102 #endif
95103 { "reverse_unordered_selects", PragTyp_FLAG,
95104 SQLITE_ReverseOrder },
95105 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95106 { "schema_version", PragTyp_HEADER_VALUE, 0 },
95107 #endif
95108 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95109 { "secure_delete", PragTyp_SECURE_DELETE, 0 },
95110 #endif
95111 { "short_column_names", PragTyp_FLAG,
95112 SQLITE_ShortColNames },
95113 { "shrink_memory", PragTyp_SHRINK_MEMORY, 0 },
95114 { "soft_heap_limit", PragTyp_SOFT_HEAP_LIMIT, 0 },
95115 #if defined(SQLITE_DEBUG)
95116 { "sql_trace", PragTyp_FLAG,
95117 SQLITE_SqlTrace },
95118 #endif
95119 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95120 { "synchronous", PragTyp_SYNCHRONOUS, 0 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95121 #endif
95122 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95123 { "table_info", PragTyp_TABLE_INFO, 0 },
 
 
 
95124 #endif
95125 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95126 { "temp_store", PragTyp_TEMP_STORE, 0 },
95127 { "temp_store_directory", PragTyp_TEMP_STORE_DIRECTORY, 0 },
 
 
 
 
 
 
95128 #endif
95129 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95130 { "user_version", PragTyp_HEADER_VALUE, 0 },
 
 
 
95131 #endif
95132 #if defined(SQLITE_DEBUG)
95133 { "vdbe_addoptrace", PragTyp_FLAG,
95134 SQLITE_VdbeAddopTrace },
95135 { "vdbe_debug", PragTyp_FLAG,
95136 SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95137 { "vdbe_listing", PragTyp_FLAG,
95138 SQLITE_VdbeListing },
95139 { "vdbe_trace", PragTyp_FLAG,
95140 SQLITE_VdbeTrace },
 
 
 
 
 
 
 
 
95141 #endif
95142 #if !defined(SQLITE_OMIT_WAL)
95143 { "wal_autocheckpoint", PragTyp_WAL_AUTOCHECKPOINT, 0 },
95144 { "wal_checkpoint", PragTyp_WAL_CHECKPOINT, 0 },
 
 
 
 
 
 
95145 #endif
95146 { "writable_schema", PragTyp_FLAG,
95147 SQLITE_WriteSchema|SQLITE_RecoveryMode },
 
 
95148 };
95149 /* Number of pragmas: 55 on by default, 66 total. */
95150 /* End of the automatically generated pragma table.
95151 ***************************************************************************/
95152
95153 /*
95154 ** Interpret the given string as a safety level. Return 0 for OFF,
@@ -95476,10 +95862,15 @@
95476 }else{
95477 lwr = mid + 1;
95478 }
95479 }
95480 if( lwr>upr ) goto pragma_out;
 
 
 
 
 
95481
95482 /* Jump to the appropriate pragma handler */
95483 switch( aPragmaNames[mid].ePragTyp ){
95484
95485 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -95510,11 +95901,10 @@
95510 { OP_Integer, 0, 1, 0}, /* 6 */
95511 { OP_Noop, 0, 0, 0},
95512 { OP_ResultRow, 1, 1, 0},
95513 };
95514 int addr;
95515 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95516 sqlite3VdbeUsesBtree(v, iDb);
95517 if( !zRight ){
95518 sqlite3VdbeSetNumCols(v, 1);
95519 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
95520 pParse->nMem += 2;
@@ -95606,11 +95996,10 @@
95606 **
95607 ** Return the number of pages in the specified database.
95608 */
95609 case PragTyp_PAGE_COUNT: {
95610 int iReg;
95611 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95612 sqlite3CodeVerifySchema(pParse, iDb);
95613 iReg = ++pParse->nMem;
95614 if( sqlite3Tolower(zLeft[0])=='p' ){
95615 sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
95616 }else{
@@ -95679,18 +96068,10 @@
95679 */
95680 case PragTyp_JOURNAL_MODE: {
95681 int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
95682 int ii; /* Loop counter */
95683
95684 /* Force the schema to be loaded on all databases. This causes all
95685 ** database files to be opened and the journal_modes set. This is
95686 ** necessary because subsequent processing must know if the databases
95687 ** are in WAL mode. */
95688 if( sqlite3ReadSchema(pParse) ){
95689 goto pragma_out;
95690 }
95691
95692 sqlite3VdbeSetNumCols(v, 1);
95693 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
95694
95695 if( zRight==0 ){
95696 /* If there is no "=MODE" part of the pragma, do a query for the
@@ -95752,55 +96133,44 @@
95752 */
95753 #ifndef SQLITE_OMIT_AUTOVACUUM
95754 case PragTyp_AUTO_VACUUM: {
95755 Btree *pBt = pDb->pBt;
95756 assert( pBt!=0 );
95757 if( sqlite3ReadSchema(pParse) ){
95758 goto pragma_out;
95759 }
95760 if( !zRight ){
95761 int auto_vacuum;
95762 if( ALWAYS(pBt) ){
95763 auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
95764 }else{
95765 auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
95766 }
95767 returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
95768 }else{
95769 int eAuto = getAutoVacuum(zRight);
95770 assert( eAuto>=0 && eAuto<=2 );
95771 db->nextAutovac = (u8)eAuto;
95772 if( ALWAYS(eAuto>=0) ){
95773 /* Call SetAutoVacuum() to set initialize the internal auto and
95774 ** incr-vacuum flags. This is required in case this connection
95775 ** creates the database file. It is important that it is created
95776 ** as an auto-vacuum capable db.
95777 */
95778 rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
95779 if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
95780 /* When setting the auto_vacuum mode to either "full" or
95781 ** "incremental", write the value of meta[6] in the database
95782 ** file. Before writing to meta[6], check that meta[3] indicates
95783 ** that this really is an auto-vacuum capable database.
95784 */
95785 static const VdbeOpList setMeta6[] = {
95786 { OP_Transaction, 0, 1, 0}, /* 0 */
95787 { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
95788 { OP_If, 1, 0, 0}, /* 2 */
95789 { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
95790 { OP_Integer, 0, 1, 0}, /* 4 */
95791 { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
95792 };
95793 int iAddr;
95794 iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
95795 sqlite3VdbeChangeP1(v, iAddr, iDb);
95796 sqlite3VdbeChangeP1(v, iAddr+1, iDb);
95797 sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
95798 sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
95799 sqlite3VdbeChangeP1(v, iAddr+5, iDb);
95800 sqlite3VdbeUsesBtree(v, iDb);
95801 }
95802 }
95803 }
95804 break;
95805 }
95806 #endif
@@ -95811,13 +96181,10 @@
95811 ** Do N steps of incremental vacuuming on a database.
95812 */
95813 #ifndef SQLITE_OMIT_AUTOVACUUM
95814 case PragTyp_INCREMENTAL_VACUUM: {
95815 int iLimit, addr;
95816 if( sqlite3ReadSchema(pParse) ){
95817 goto pragma_out;
95818 }
95819 if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
95820 iLimit = 0x7fffffff;
95821 }
95822 sqlite3BeginWriteOperation(pParse, 0, iDb);
95823 sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
@@ -95841,11 +96208,10 @@
95841 ** number of pages in the cache. If N is negative, then the
95842 ** number of pages is adjusted so that the cache uses -N kibibytes
95843 ** of memory.
95844 */
95845 case PragTyp_CACHE_SIZE: {
95846 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95847 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
95848 if( !zRight ){
95849 returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
95850 }else{
95851 int size = sqlite3Atoi(zRight);
@@ -96062,11 +96428,10 @@
96062 ** the local value does not make changes to the disk file and the
96063 ** default value will be restored the next time the database is
96064 ** opened.
96065 */
96066 case PragTyp_SYNCHRONOUS: {
96067 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96068 if( !zRight ){
96069 returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
96070 }else{
96071 if( !db->autoCommit ){
96072 sqlite3ErrorMsg(pParse,
@@ -96124,11 +96489,10 @@
96124 ** notnull: True if 'NOT NULL' is part of column declaration
96125 ** dflt_value: The default value for the column, if any.
96126 */
96127 case PragTyp_TABLE_INFO: if( zRight ){
96128 Table *pTab;
96129 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96130 pTab = sqlite3FindTable(db, zRight, zDb);
96131 if( pTab ){
96132 int i, k;
96133 int nHidden = 0;
96134 Column *pCol;
@@ -96174,11 +96538,10 @@
96174 break;
96175
96176 case PragTyp_INDEX_INFO: if( zRight ){
96177 Index *pIdx;
96178 Table *pTab;
96179 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96180 pIdx = sqlite3FindIndex(db, zRight, zDb);
96181 if( pIdx ){
96182 int i;
96183 pTab = pIdx->pTable;
96184 sqlite3VdbeSetNumCols(v, 3);
@@ -96200,39 +96563,41 @@
96200 break;
96201
96202 case PragTyp_INDEX_LIST: if( zRight ){
96203 Index *pIdx;
96204 Table *pTab;
96205 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96206 pTab = sqlite3FindTable(db, zRight, zDb);
96207 if( pTab ){
96208 v = sqlite3GetVdbe(pParse);
96209 pIdx = pTab->pIndex;
96210 if( pIdx ){
96211 int i = 0;
96212 sqlite3VdbeSetNumCols(v, 3);
96213 pParse->nMem = 3;
96214 sqlite3CodeVerifySchema(pParse, iDb);
96215 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96216 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96217 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96218 while(pIdx){
96219 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96220 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96221 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96222 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
96223 ++i;
96224 pIdx = pIdx->pNext;
96225 }
 
 
 
96226 }
96227 }
96228 }
96229 break;
96230
96231 case PragTyp_DATABASE_LIST: {
96232 int i;
96233 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96234 sqlite3VdbeSetNumCols(v, 3);
96235 pParse->nMem = 3;
96236 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96237 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96238 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
@@ -96267,11 +96632,10 @@
96267
96268 #ifndef SQLITE_OMIT_FOREIGN_KEY
96269 case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
96270 FKey *pFK;
96271 Table *pTab;
96272 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96273 pTab = sqlite3FindTable(db, zRight, zDb);
96274 if( pTab ){
96275 v = sqlite3GetVdbe(pParse);
96276 pFK = pTab->pFKey;
96277 if( pFK ){
@@ -96329,11 +96693,10 @@
96329 int regRow; /* Registers to hold a row from pTab */
96330 int addrTop; /* Top of a loop checking foreign keys */
96331 int addrOk; /* Jump here if the key is OK */
96332 int *aiCols; /* child to parent column mapping */
96333
96334 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96335 regResult = pParse->nMem+1;
96336 pParse->nMem += 4;
96337 regKey = ++pParse->nMem;
96338 regRow = ++pParse->nMem;
96339 v = sqlite3GetVdbe(pParse);
@@ -96490,11 +96853,10 @@
96490 assert( iDb>=0 );
96491 assert( iDb==0 || pId2->z );
96492 if( pId2->z==0 ) iDb = -1;
96493
96494 /* Initialize the VDBE program */
96495 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96496 pParse->nMem = 6;
96497 sqlite3VdbeSetNumCols(v, 1);
96498 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
96499
96500 /* Set the maximum error count */
@@ -96814,11 +97176,10 @@
96814 eMode = SQLITE_CHECKPOINT_FULL;
96815 }else if( sqlite3StrICmp(zRight, "restart")==0 ){
96816 eMode = SQLITE_CHECKPOINT_RESTART;
96817 }
96818 }
96819 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96820 sqlite3VdbeSetNumCols(v, 3);
96821 pParse->nMem = 3;
96822 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
96823 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
96824 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
@@ -96934,16 +97295,16 @@
96934 if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
96935 break;
96936 }
96937 case PragTyp_HEXKEY: {
96938 if( zRight ){
96939 int i, h1, h2;
 
96940 char zKey[40];
96941 for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
96942 h1 += 9*(1&(h1>>6));
96943 h2 += 9*(1&(h2>>6));
96944 zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
96945 }
96946 if( (zLeft[3] & 0xf)==0xb ){
96947 sqlite3_key_v2(db, zDb, zKey, i/2);
96948 }else{
96949 sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -98913,10 +99274,13 @@
98913 }
98914
98915 /*
98916 ** Return a pointer to a string containing the 'declaration type' of the
98917 ** expression pExpr. The string may be treated as static by the caller.
 
 
 
98918 **
98919 ** The declaration type is the exact datatype definition extracted from the
98920 ** original CREATE TABLE statement if the expression is a column. The
98921 ** declaration type for a ROWID field is INTEGER. Exactly when an expression
98922 ** is considered a column can be complex in the presence of subqueries. The
@@ -98927,25 +99291,40 @@
98927 ** SELECT (SELECT col FROM tbl;
98928 ** SELECT (SELECT col FROM tbl);
98929 ** SELECT abc FROM (SELECT col AS abc FROM tbl);
98930 **
98931 ** The declaration type for any expression other than a column is NULL.
 
 
 
98932 */
98933 static const char *columnType(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98934 NameContext *pNC,
98935 Expr *pExpr,
98936 const char **pzOriginDb,
98937 const char **pzOriginTab,
98938 const char **pzOriginCol
98939 ){
 
98940 char const *zType = 0;
98941 char const *zOriginDb = 0;
98942 char const *zOriginTab = 0;
98943 char const *zOriginCol = 0;
98944 int j;
 
 
98945 if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
98946
98947 switch( pExpr->op ){
98948 case TK_AGG_COLUMN:
98949 case TK_COLUMN: {
98950 /* The expression is a column. Locate the table the column is being
98951 ** extracted from in NameContext.pSrcList. This table may be real
@@ -99002,29 +99381,39 @@
99002 NameContext sNC;
99003 Expr *p = pS->pEList->a[iCol].pExpr;
99004 sNC.pSrcList = pS->pSrc;
99005 sNC.pNext = pNC;
99006 sNC.pParse = pNC->pParse;
99007 zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99008 }
99009 }else if( ALWAYS(pTab->pSchema) ){
99010 /* A real table */
99011 assert( !pS );
99012 if( iCol<0 ) iCol = pTab->iPKey;
99013 assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
 
99014 if( iCol<0 ){
99015 zType = "INTEGER";
99016 zOriginCol = "rowid";
99017 }else{
99018 zType = pTab->aCol[iCol].zType;
99019 zOriginCol = pTab->aCol[iCol].zName;
 
99020 }
99021 zOriginTab = pTab->zName;
99022 if( pNC->pParse ){
99023 int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
99024 zOriginDb = pNC->pParse->db->aDb[iDb].zName;
99025 }
 
 
 
 
 
 
 
 
99026 }
99027 break;
99028 }
99029 #ifndef SQLITE_OMIT_SUBQUERY
99030 case TK_SELECT: {
@@ -99037,22 +99426,25 @@
99037 Expr *p = pS->pEList->a[0].pExpr;
99038 assert( ExprHasProperty(pExpr, EP_xIsSelect) );
99039 sNC.pSrcList = pS->pSrc;
99040 sNC.pNext = pNC;
99041 sNC.pParse = pNC->pParse;
99042 zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99043 break;
99044 }
99045 #endif
99046 }
99047
99048 if( pzOriginDb ){
99049 assert( pzOriginTab && pzOriginCol );
99050 *pzOriginDb = zOriginDb;
99051 *pzOriginTab = zOriginTab;
99052 *pzOriginCol = zOriginCol;
 
99053 }
 
 
99054 return zType;
99055 }
99056
99057 /*
99058 ** Generate code that will tell the VDBE the declaration types of columns
@@ -99074,25 +99466,25 @@
99074 const char *zType;
99075 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99076 const char *zOrigDb = 0;
99077 const char *zOrigTab = 0;
99078 const char *zOrigCol = 0;
99079 zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
99080
99081 /* The vdbe must make its own copy of the column-type and other
99082 ** column specific strings, in case the schema is reset before this
99083 ** virtual machine is deleted.
99084 */
99085 sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
99086 sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
99087 sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
99088 #else
99089 zType = columnType(&sNC, p, 0, 0, 0);
99090 #endif
99091 sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
99092 }
99093 #endif /* SQLITE_OMIT_DECLTYPE */
99094 }
99095
99096 /*
99097 ** Generate code that will tell the VDBE the names of columns
99098 ** in the result set. This information is used to provide the
@@ -99277,39 +99669,41 @@
99277 ** This routine requires that all identifiers in the SELECT
99278 ** statement be resolved.
99279 */
99280 static void selectAddColumnTypeAndCollation(
99281 Parse *pParse, /* Parsing contexts */
99282 int nCol, /* Number of columns */
99283 Column *aCol, /* List of columns */
99284 Select *pSelect /* SELECT used to determine types and collations */
99285 ){
99286 sqlite3 *db = pParse->db;
99287 NameContext sNC;
99288 Column *pCol;
99289 CollSeq *pColl;
99290 int i;
99291 Expr *p;
99292 struct ExprList_item *a;
 
99293
99294 assert( pSelect!=0 );
99295 assert( (pSelect->selFlags & SF_Resolved)!=0 );
99296 assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
99297 if( db->mallocFailed ) return;
99298 memset(&sNC, 0, sizeof(sNC));
99299 sNC.pSrcList = pSelect->pSrc;
99300 a = pSelect->pEList->a;
99301 for(i=0, pCol=aCol; i<nCol; i++, pCol++){
99302 p = a[i].pExpr;
99303 pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
 
99304 pCol->affinity = sqlite3ExprAffinity(p);
99305 if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
99306 pColl = sqlite3ExprCollSeq(pParse, p);
99307 if( pColl ){
99308 pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
99309 }
99310 }
 
99311 }
99312
99313 /*
99314 ** Given a SELECT statement, generate a Table structure that describes
99315 ** the result set of that SELECT.
@@ -99333,13 +99727,13 @@
99333 /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
99334 ** is disabled */
99335 assert( db->lookaside.bEnabled==0 );
99336 pTab->nRef = 1;
99337 pTab->zName = 0;
99338 pTab->nRowEst = 1000000;
99339 selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
99340 selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
99341 pTab->iPKey = -1;
99342 if( db->mallocFailed ){
99343 sqlite3DeleteTable(db, pTab);
99344 return 0;
99345 }
@@ -101247,15 +101641,15 @@
101247 assert( pFrom->pTab==0 );
101248 sqlite3WalkSelect(pWalker, pSel);
101249 pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
101250 if( pTab==0 ) return WRC_Abort;
101251 pTab->nRef = 1;
101252 pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
101253 while( pSel->pPrior ){ pSel = pSel->pPrior; }
101254 selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
101255 pTab->iPKey = -1;
101256 pTab->nRowEst = 1000000;
101257 pTab->tabFlags |= TF_Ephemeral;
101258 #endif
101259 }else{
101260 /* An ordinary table or view name in the FROM clause */
101261 assert( pFrom->pTab==0 );
@@ -101535,11 +101929,11 @@
101535 if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
101536 /* A sub-query in the FROM clause of a SELECT */
101537 Select *pSel = pFrom->pSelect;
101538 assert( pSel );
101539 while( pSel->pPrior ) pSel = pSel->pPrior;
101540 selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
101541 }
101542 }
101543 }
101544 return WRC_Continue;
101545 }
@@ -102450,29 +102844,29 @@
102450 int iRoot = pTab->tnum; /* Root page of scanned b-tree */
102451
102452 sqlite3CodeVerifySchema(pParse, iDb);
102453 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102454
102455 /* Search for the index that has the least amount of columns. If
102456 ** there is such an index, and it has less columns than the table
102457 ** does, then we can assume that it consumes less space on disk and
102458 ** will therefore be cheaper to scan to determine the query result.
102459 ** In this case set iRoot to the root page number of the index b-tree
102460 ** and pKeyInfo to the KeyInfo structure required to navigate the
102461 ** index.
102462 **
102463 ** (2011-04-15) Do not do a full scan of an unordered index.
 
 
102464 **
102465 ** In practice the KeyInfo structure will not be used. It is only
102466 ** passed to keep OP_OpenRead happy.
102467 */
102468 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
102469 if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
 
 
 
 
102470 pBest = pIdx;
102471 }
102472 }
102473 if( pBest && pBest->nColumn<pTab->nCol ){
102474 iRoot = pBest->tnum;
102475 pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
102476 }
102477
102478 /* Open a read-only cursor, execute the OP_Count, close the cursor. */
@@ -103046,12 +103440,12 @@
103046 }
103047
103048 /* Ensure the table name matches database name and that the table exists */
103049 if( db->mallocFailed ) goto trigger_cleanup;
103050 assert( pTableName->nSrc==1 );
103051 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
103052 sqlite3FixSrcList(&sFix, pTableName) ){
103053 goto trigger_cleanup;
103054 }
103055 pTab = sqlite3SrcListLookup(pParse, pTableName);
103056 if( !pTab ){
103057 /* The table does not exist. */
@@ -103189,12 +103583,14 @@
103189 pStepList->pTrig = pTrig;
103190 pStepList = pStepList->pNext;
103191 }
103192 nameToken.z = pTrig->zName;
103193 nameToken.n = sqlite3Strlen30(nameToken.z);
103194 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
103195 && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
 
 
103196 goto triggerfinish_cleanup;
103197 }
103198
103199 /* if we are not initializing,
103200 ** build the sqlite_master entry
@@ -104781,18 +105177,38 @@
104781
104782 return vacuumFinalize(db, pStmt, pzErrMsg);
104783 }
104784
104785 /*
104786 ** The non-standard VACUUM command is used to clean up the database,
104787 ** collapse free space, etc. It is modelled after the VACUUM command
104788 ** in PostgreSQL.
104789 **
104790 ** In version 1.0.x of SQLite, the VACUUM command would call
104791 ** gdbm_reorganize() on all the database tables. But beginning
104792 ** with 2.0.0, SQLite no longer uses GDBM so this command has
104793 ** become a no-op.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104794 */
104795 SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
104796 Vdbe *v = sqlite3GetVdbe(pParse);
104797 if( v ){
104798 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
@@ -106206,30 +106622,10 @@
106206 typedef struct WhereLoopBuilder WhereLoopBuilder;
106207 typedef struct WhereScan WhereScan;
106208 typedef struct WhereOrCost WhereOrCost;
106209 typedef struct WhereOrSet WhereOrSet;
106210
106211 /*
106212 ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
106213 ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
106214 ** (Virtual tables can return a larger cost, but let's assume they do not.)
106215 ** So all costs can be stored in a 16-bit integer without risk
106216 ** of overflow.
106217 **
106218 ** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
106219 ** Instead, a close estimate is used. Any value of X=1 is stored as 0.
106220 ** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
106221 ** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
106222 **
106223 ** The tool/wherecosttest.c source file implements a command-line program
106224 ** that will convert WhereCosts to integers, convert integers to WhereCosts
106225 ** and do addition and multiplication on WhereCost values. The wherecosttest
106226 ** command-line program is a useful utility to have around when working with
106227 ** this module.
106228 */
106229 typedef short int WhereCost;
106230
106231 /*
106232 ** This object contains information needed to implement a single nested
106233 ** loop in WHERE clause.
106234 **
106235 ** Contrast this object with WhereLoop. This object describes the
@@ -106290,13 +106686,13 @@
106290 #ifdef SQLITE_DEBUG
106291 char cId; /* Symbolic ID of this loop for debugging use */
106292 #endif
106293 u8 iTab; /* Position in FROM clause of table for this loop */
106294 u8 iSortIdx; /* Sorting index number. 0==None */
106295 WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
106296 WhereCost rRun; /* Cost of running each loop */
106297 WhereCost nOut; /* Estimated number of output rows */
106298 union {
106299 struct { /* Information for internal btree tables */
106300 int nEq; /* Number of equality constraints */
106301 Index *pIndex; /* Index used, or NULL */
106302 } btree;
@@ -106322,12 +106718,12 @@
106322 ** subquery on one operand of an OR operator in the WHERE clause.
106323 ** See WhereOrSet for additional information
106324 */
106325 struct WhereOrCost {
106326 Bitmask prereq; /* Prerequisites */
106327 WhereCost rRun; /* Cost of running this subquery */
106328 WhereCost nOut; /* Number of outputs for this subquery */
106329 };
106330
106331 /* The WhereOrSet object holds a set of possible WhereOrCosts that
106332 ** correspond to the subquery(s) of OR-clause processing. Only the
106333 ** best N_OR_COST elements are retained.
@@ -106361,12 +106757,12 @@
106361 ** at the end is the choosen query plan.
106362 */
106363 struct WherePath {
106364 Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
106365 Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
106366 WhereCost nRow; /* Estimated number of rows generated by this path */
106367 WhereCost rCost; /* Total cost of this path */
106368 u8 isOrdered; /* True if this path satisfies ORDER BY */
106369 u8 isOrderedValid; /* True if the isOrdered field is valid */
106370 WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
106371 };
106372
@@ -106428,11 +106824,11 @@
106428 union {
106429 int leftColumn; /* Column number of X in "X <op> <expr>" */
106430 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
106431 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
106432 } u;
106433 WhereCost truthProb; /* Probability of truth for this expression */
106434 u16 eOperator; /* A WO_xx value describing <op> */
106435 u8 wtFlags; /* TERM_xxx bit flags. See below */
106436 u8 nChild; /* Number of children that must disable us */
106437 WhereClause *pWC; /* The clause this term is part of */
106438 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -106576,11 +106972,11 @@
106576 SrcList *pTabList; /* List of tables in the join */
106577 ExprList *pOrderBy; /* The ORDER BY clause or NULL */
106578 ExprList *pResultSet; /* Result set. DISTINCT operates on these */
106579 WhereLoop *pLoops; /* List of all WhereLoop objects */
106580 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
106581 WhereCost nRowOut; /* Estimated number of output rows */
106582 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
106583 u8 bOBSat; /* ORDER BY satisfied by indices */
106584 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
106585 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
106586 u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -106636,30 +107032,15 @@
106636 #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
106637 #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
106638 #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
106639 #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
106640
106641
106642 /* Convert a WhereCost value (10 times log2(X)) into its integer value X.
106643 ** A rough approximation is used. The value returned is not exact.
106644 */
106645 static u64 whereCostToInt(WhereCost x){
106646 u64 n;
106647 if( x<10 ) return 1;
106648 n = x%10;
106649 x /= 10;
106650 if( n>=5 ) n -= 2;
106651 else if( n>=1 ) n -= 1;
106652 if( x>=3 ) return (n+8)<<(x-3);
106653 return (n+8)>>(3-x);
106654 }
106655
106656 /*
106657 ** Return the estimated number of output rows from a WHERE clause
106658 */
106659 SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
106660 return whereCostToInt(pWInfo->nRowOut);
106661 }
106662
106663 /*
106664 ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
106665 ** WHERE clause returns outputs for DISTINCT processing.
@@ -106717,12 +107098,12 @@
106717 ** so that pSet keeps the N_OR_COST best entries seen so far.
106718 */
106719 static int whereOrInsert(
106720 WhereOrSet *pSet, /* The WhereOrSet to be updated */
106721 Bitmask prereq, /* Prerequisites of the new entry */
106722 WhereCost rRun, /* Run-cost of the new entry */
106723 WhereCost nOut /* Number of outputs for the new entry */
106724 ){
106725 u16 i;
106726 WhereOrCost *p;
106727 for(i=pSet->n, p=pSet->a; i>0; i--, p++){
106728 if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
@@ -106803,13 +107184,10 @@
106803 if( pWC->a!=pWC->aStatic ){
106804 sqlite3DbFree(db, pWC->a);
106805 }
106806 }
106807
106808 /* Forward declaration */
106809 static WhereCost whereCost(tRowcnt x);
106810
106811 /*
106812 ** Add a single new WhereTerm entry to the WhereClause object pWC.
106813 ** The new WhereTerm object is constructed from Expr p and with wtFlags.
106814 ** The index in pWC->a[] of the new WhereTerm is returned on success.
106815 ** 0 is returned if the new WhereTerm could not be added due to a memory
@@ -106848,11 +107226,11 @@
106848 }
106849 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
106850 }
106851 pTerm = &pWC->a[idx = pWC->nTerm++];
106852 if( p && ExprHasProperty(p, EP_Unlikely) ){
106853 pTerm->truthProb = whereCost(p->iTable) - 99;
106854 }else{
106855 pTerm->truthProb = -1;
106856 }
106857 pTerm->pExpr = sqlite3ExprSkipCollate(p);
106858 pTerm->wtFlags = wtFlags;
@@ -108112,79 +108490,16 @@
108112 }
108113
108114 return 0;
108115 }
108116
108117 /*
108118 ** Find (an approximate) sum of two WhereCosts. This computation is
108119 ** not a simple "+" operator because WhereCost is stored as a logarithmic
108120 ** value.
108121 **
108122 */
108123 static WhereCost whereCostAdd(WhereCost a, WhereCost b){
108124 static const unsigned char x[] = {
108125 10, 10, /* 0,1 */
108126 9, 9, /* 2,3 */
108127 8, 8, /* 4,5 */
108128 7, 7, 7, /* 6,7,8 */
108129 6, 6, 6, /* 9,10,11 */
108130 5, 5, 5, /* 12-14 */
108131 4, 4, 4, 4, /* 15-18 */
108132 3, 3, 3, 3, 3, 3, /* 19-24 */
108133 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
108134 };
108135 if( a>=b ){
108136 if( a>b+49 ) return a;
108137 if( a>b+31 ) return a+1;
108138 return a+x[a-b];
108139 }else{
108140 if( b>a+49 ) return b;
108141 if( b>a+31 ) return b+1;
108142 return b+x[b-a];
108143 }
108144 }
108145
108146 /*
108147 ** Convert an integer into a WhereCost. In other words, compute a
108148 ** good approximatation for 10*log2(x).
108149 */
108150 static WhereCost whereCost(tRowcnt x){
108151 static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
108152 WhereCost y = 40;
108153 if( x<8 ){
108154 if( x<2 ) return 0;
108155 while( x<8 ){ y -= 10; x <<= 1; }
108156 }else{
108157 while( x>255 ){ y += 40; x >>= 4; }
108158 while( x>15 ){ y += 10; x >>= 1; }
108159 }
108160 return a[x&7] + y - 10;
108161 }
108162
108163 #ifndef SQLITE_OMIT_VIRTUALTABLE
108164 /*
108165 ** Convert a double (as received from xBestIndex of a virtual table)
108166 ** into a WhereCost. In other words, compute an approximation for
108167 ** 10*log2(x).
108168 */
108169 static WhereCost whereCostFromDouble(double x){
108170 u64 a;
108171 WhereCost e;
108172 assert( sizeof(x)==8 && sizeof(a)==8 );
108173 if( x<=1 ) return 0;
108174 if( x<=2000000000 ) return whereCost((tRowcnt)x);
108175 memcpy(&a, &x, 8);
108176 e = (a>>52) - 1022;
108177 return e*10;
108178 }
108179 #endif /* SQLITE_OMIT_VIRTUALTABLE */
108180
108181 /*
108182 ** Estimate the logarithm of the input value to base 2.
108183 */
108184 static WhereCost estLog(WhereCost N){
108185 WhereCost x = whereCost(N);
108186 return x>33 ? x - 33 : 0;
108187 }
108188
108189 /*
108190 ** Two routines for printing the content of an sqlite3_index_info
@@ -108693,11 +109008,11 @@
108693 **
108694 ** ... FROM t1 WHERE a > ? AND a < ? ...
108695 **
108696 ** then nEq is set to 0.
108697 **
108698 ** When this function is called, *pnOut is set to the whereCost() of the
108699 ** number of rows that the index scan is expected to visit without
108700 ** considering the range constraints. If nEq is 0, this is the number of
108701 ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
108702 ** to account for the range contraints pLower and pUpper.
108703 **
@@ -108709,19 +109024,19 @@
108709 static int whereRangeScanEst(
108710 Parse *pParse, /* Parsing & code generating context */
108711 WhereLoopBuilder *pBuilder,
108712 WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
108713 WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
108714 WhereCost *pnOut /* IN/OUT: Number of rows visited */
108715 ){
108716 int rc = SQLITE_OK;
108717 int nOut = (int)*pnOut;
108718 WhereCost nNew;
 
108719
108720 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108721 Index *p = pBuilder->pNew->u.btree.pIndex;
108722 int nEq = pBuilder->pNew->u.btree.nEq;
108723
108724 if( p->nSample>0
108725 && nEq==pBuilder->nRecValid
108726 && nEq<p->nSampleCol
108727 && OptimizationEnabled(pParse->db, SQLITE_Stat3)
@@ -108798,18 +109113,18 @@
108798 }
108799
108800 pBuilder->pRec = pRec;
108801 if( rc==SQLITE_OK ){
108802 if( iUpper>iLower ){
108803 nNew = whereCost(iUpper - iLower);
108804 }else{
108805 nNew = 10; assert( 10==whereCost(2) );
108806 }
108807 if( nNew<nOut ){
108808 nOut = nNew;
108809 }
108810 *pnOut = (WhereCost)nOut;
108811 WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
108812 (u32)iLower, (u32)iUpper, nOut));
108813 return SQLITE_OK;
108814 }
108815 }
@@ -108820,20 +109135,20 @@
108820 assert( pLower || pUpper );
108821 /* TUNING: Each inequality constraint reduces the search space 4-fold.
108822 ** A BETWEEN operator, therefore, reduces the search space 16-fold */
108823 nNew = nOut;
108824 if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
108825 nNew -= 20; assert( 20==whereCost(4) );
108826 nOut--;
108827 }
108828 if( pUpper ){
108829 nNew -= 20; assert( 20==whereCost(4) );
108830 nOut--;
108831 }
108832 if( nNew<10 ) nNew = 10;
108833 if( nNew<nOut ) nOut = nNew;
108834 *pnOut = (WhereCost)nOut;
108835 return rc;
108836 }
108837
108838 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108839 /*
@@ -110473,11 +110788,11 @@
110473 */
110474 static int whereLoopAddBtreeIndex(
110475 WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
110476 struct SrcList_item *pSrc, /* FROM clause term being analyzed */
110477 Index *pProbe, /* An index on pSrc */
110478 WhereCost nInMul /* log(Number of iterations due to IN) */
110479 ){
110480 WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
110481 Parse *pParse = pWInfo->pParse; /* Parsing context */
110482 sqlite3 *db = pParse->db; /* Database connection malloc context */
110483 WhereLoop *pNew; /* Template WhereLoop under construction */
@@ -110486,15 +110801,15 @@
110486 WhereScan scan; /* Iterator for WHERE terms */
110487 Bitmask saved_prereq; /* Original value of pNew->prereq */
110488 u16 saved_nLTerm; /* Original value of pNew->nLTerm */
110489 int saved_nEq; /* Original value of pNew->u.btree.nEq */
110490 u32 saved_wsFlags; /* Original value of pNew->wsFlags */
110491 WhereCost saved_nOut; /* Original value of pNew->nOut */
110492 int iCol; /* Index of the column in the table */
110493 int rc = SQLITE_OK; /* Return code */
110494 WhereCost nRowEst; /* Estimated index selectivity */
110495 WhereCost rLogSize; /* Logarithm of table size */
110496 WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
110497
110498 pNew = pBuilder->pNew;
110499 if( db->mallocFailed ) return SQLITE_NOMEM;
110500
@@ -110510,11 +110825,11 @@
110510 if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
110511
110512 assert( pNew->u.btree.nEq<=pProbe->nColumn );
110513 if( pNew->u.btree.nEq < pProbe->nColumn ){
110514 iCol = pProbe->aiColumn[pNew->u.btree.nEq];
110515 nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110516 if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
110517 }else{
110518 iCol = -1;
110519 nRowEst = 0;
110520 }
@@ -110524,11 +110839,11 @@
110524 saved_nLTerm = pNew->nLTerm;
110525 saved_wsFlags = pNew->wsFlags;
110526 saved_prereq = pNew->prereq;
110527 saved_nOut = pNew->nOut;
110528 pNew->rSetup = 0;
110529 rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
110530 for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
110531 int nIn = 0;
110532 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110533 int nRecValid = pBuilder->nRecValid;
110534 #endif
@@ -110551,14 +110866,14 @@
110551 if( pTerm->eOperator & WO_IN ){
110552 Expr *pExpr = pTerm->pExpr;
110553 pNew->wsFlags |= WHERE_COLUMN_IN;
110554 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
110555 /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
110556 nIn = 46; assert( 46==whereCost(25) );
110557 }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
110558 /* "x IN (value, value, ...)" */
110559 nIn = whereCost(pExpr->x.pList->nExpr);
110560 }
110561 pNew->rRun += nIn;
110562 pNew->u.btree.nEq++;
110563 pNew->nOut = nRowEst + nInMul + nIn;
110564 }else if( pTerm->eOperator & (WO_EQ) ){
@@ -110576,11 +110891,11 @@
110576 pNew->nOut = nRowEst + nInMul;
110577 }else if( pTerm->eOperator & (WO_ISNULL) ){
110578 pNew->wsFlags |= WHERE_COLUMN_NULL;
110579 pNew->u.btree.nEq++;
110580 /* TUNING: IS NULL selects 2 rows */
110581 nIn = 10; assert( 10==whereCost(2) );
110582 pNew->nOut = nRowEst + nInMul + nIn;
110583 }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
110584 testcase( pTerm->eOperator & WO_GT );
110585 testcase( pTerm->eOperator & WO_GE );
110586 pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
@@ -110596,11 +110911,11 @@
110596 pNew->aLTerm[pNew->nLTerm-2] : 0;
110597 }
110598 if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
110599 /* Adjust nOut and rRun for STAT3 range values */
110600 assert( pNew->nOut==saved_nOut );
110601 whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
110602 }
110603 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110604 if( nInMul==0
110605 && pProbe->nSample
110606 && pNew->u.btree.nEq<=pProbe->nSampleCol
@@ -110616,22 +110931,22 @@
110616 && !ExprHasProperty(pExpr, EP_xIsSelect) ){
110617 rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
110618 }
110619 assert( nOut==0 || rc==SQLITE_OK );
110620 if( nOut ){
110621 nOut = whereCost(nOut);
110622 pNew->nOut = MIN(nOut, saved_nOut);
110623 }
110624 }
110625 #endif
110626 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
110627 /* Each row involves a step of the index, then a binary search of
110628 ** the main table */
110629 pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
110630 }
110631 /* Step cost for each output row */
110632 pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
110633 whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
110634 rc = whereLoopInsert(pBuilder, pNew);
110635 if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
110636 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
110637 ){
@@ -110727,18 +111042,20 @@
110727 struct SrcList_item *pSrc; /* The FROM clause btree term to add */
110728 WhereLoop *pNew; /* Template WhereLoop object */
110729 int rc = SQLITE_OK; /* Return code */
110730 int iSortIdx = 1; /* Index number */
110731 int b; /* A boolean value */
110732 WhereCost rSize; /* number of rows in the table */
110733 WhereCost rLogSize; /* Logarithm of the number of rows in the table */
110734 WhereClause *pWC; /* The parsed WHERE clause */
 
110735
110736 pNew = pBuilder->pNew;
110737 pWInfo = pBuilder->pWInfo;
110738 pTabList = pWInfo->pTabList;
110739 pSrc = pTabList->a + pNew->iTab;
 
110740 pWC = pBuilder->pWC;
110741 assert( !IsVirtual(pSrc->pTab) );
110742
110743 if( pSrc->pIndex ){
110744 /* An INDEXED BY clause specifies a particular index to use */
@@ -110752,22 +111069,22 @@
110752 memset(&sPk, 0, sizeof(Index));
110753 sPk.nColumn = 1;
110754 sPk.aiColumn = &aiColumnPk;
110755 sPk.aiRowEst = aiRowEstPk;
110756 sPk.onError = OE_Replace;
110757 sPk.pTable = pSrc->pTab;
110758 aiRowEstPk[0] = pSrc->pTab->nRowEst;
110759 aiRowEstPk[1] = 1;
110760 pFirst = pSrc->pTab->pIndex;
110761 if( pSrc->notIndexed==0 ){
110762 /* The real indices of the table are only considered if the
110763 ** NOT INDEXED qualifier is omitted from the FROM clause */
110764 sPk.pNext = pFirst;
110765 }
110766 pProbe = &sPk;
110767 }
110768 rSize = whereCost(pSrc->pTab->nRowEst);
110769 rLogSize = estLog(rSize);
110770
110771 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
110772 /* Automatic indexes */
110773 if( !pBuilder->pOrSet
@@ -110788,17 +111105,17 @@
110788 pNew->nLTerm = 1;
110789 pNew->aLTerm[0] = pTerm;
110790 /* TUNING: One-time cost for computing the automatic index is
110791 ** approximately 7*N*log2(N) where N is the number of rows in
110792 ** the table being indexed. */
110793 pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
110794 /* TUNING: Each index lookup yields 20 rows in the table. This
110795 ** is more than the usual guess of 10 rows, since we have no way
110796 ** of knowning how selective the index will ultimately be. It would
110797 ** not be unreasonable to make this value much larger. */
110798 pNew->nOut = 43; assert( 43==whereCost(20) );
110799 pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
110800 pNew->wsFlags = WHERE_AUTO_INDEX;
110801 pNew->prereq = mExtra | pTerm->prereqRight;
110802 rc = whereLoopInsert(pBuilder, pNew);
110803 }
110804 }
@@ -110828,14 +111145,12 @@
110828
110829 /* Full table scan */
110830 pNew->iSortIdx = b ? iSortIdx : 0;
110831 /* TUNING: Cost of full table scan is 3*(N + log2(N)).
110832 ** + The extra 3 factor is to encourage the use of indexed lookups
110833 ** over full scans. A smaller constant 2 is used for covering
110834 ** index scans so that a covering index scan will be favored over
110835 ** a table scan. */
110836 pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
110837 whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
110838 rc = whereLoopInsert(pBuilder, pNew);
110839 pNew->nOut = rSize;
110840 if( rc ) break;
110841 }else{
@@ -110844,26 +111159,25 @@
110844
110845 /* Full scan via index */
110846 if( b
110847 || ( m==0
110848 && pProbe->bUnordered==0
 
110849 && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
110850 && sqlite3GlobalConfig.bUseCis
110851 && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
110852 )
110853 ){
110854 pNew->iSortIdx = b ? iSortIdx : 0;
110855 if( m==0 ){
110856 /* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
110857 ** + The extra 2 factor is to encourage the use of indexed lookups
110858 ** over index scans. A table scan uses a factor of 3 so that
110859 ** index scans are favored over table scans.
110860 ** + If this covering index might also help satisfy the ORDER BY
110861 ** clause, then the cost is fudged down slightly so that this
110862 ** index is favored above other indices that have no hope of
110863 ** helping with the ORDER BY. */
110864 pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
110865 }else{
110866 assert( b!=0 );
110867 /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
110868 ** which we will simplify to just N*log2(N) */
110869 pNew->rRun = rSize + rLogSize;
@@ -111037,13 +111351,13 @@
111037 pIdxInfo->needToFreeIdxStr = 0;
111038 pNew->u.vtab.idxStr = pIdxInfo->idxStr;
111039 pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
111040 && pIdxInfo->orderByConsumed);
111041 pNew->rSetup = 0;
111042 pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
111043 /* TUNING: Every virtual table query returns 25 rows */
111044 pNew->nOut = 46; assert( 46==whereCost(25) );
111045 whereLoopInsert(pBuilder, pNew);
111046 if( pNew->u.vtab.needFree ){
111047 sqlite3_free(pNew->u.vtab.idxStr);
111048 pNew->u.vtab.needFree = 0;
111049 }
@@ -111076,10 +111390,12 @@
111076 pWC = pBuilder->pWC;
111077 if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
111078 pWCEnd = pWC->a + pWC->nTerm;
111079 pNew = pBuilder->pNew;
111080 memset(&sSum, 0, sizeof(sSum));
 
 
111081
111082 for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
111083 if( (pTerm->eOperator & WO_OR)!=0
111084 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
111085 ){
@@ -111087,12 +111403,10 @@
111087 WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
111088 WhereTerm *pOrTerm;
111089 int once = 1;
111090 int i, j;
111091
111092 pItem = pWInfo->pTabList->a + pNew->iTab;
111093 iCur = pItem->iCursor;
111094 sSubBuild = *pBuilder;
111095 sSubBuild.pOrderBy = 0;
111096 sSubBuild.pOrSet = &sCur;
111097
111098 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
@@ -111129,12 +111443,12 @@
111129 whereOrMove(&sPrev, &sSum);
111130 sSum.n = 0;
111131 for(i=0; i<sPrev.n; i++){
111132 for(j=0; j<sCur.n; j++){
111133 whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
111134 whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111135 whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111136 }
111137 }
111138 }
111139 }
111140 pNew->nLTerm = 1;
@@ -111468,23 +111782,23 @@
111468 ** costs if nRowEst==0.
111469 **
111470 ** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
111471 ** error occurs.
111472 */
111473 static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
111474 int mxChoice; /* Maximum number of simultaneous paths tracked */
111475 int nLoop; /* Number of terms in the join */
111476 Parse *pParse; /* Parsing context */
111477 sqlite3 *db; /* The database connection */
111478 int iLoop; /* Loop counter over the terms of the join */
111479 int ii, jj; /* Loop counters */
111480 int mxI = 0; /* Index of next entry to replace */
111481 WhereCost rCost; /* Cost of a path */
111482 WhereCost nOut; /* Number of outputs */
111483 WhereCost mxCost = 0; /* Maximum cost of a set of paths */
111484 WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
111485 WhereCost rSortCost; /* Cost to do a sort */
111486 int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
111487 WherePath *aFrom; /* All nFrom paths at the previous level */
111488 WherePath *aTo; /* The nTo best paths at the current level */
111489 WherePath *pFrom; /* An element of aFrom[] that we are working on */
111490 WherePath *pTo; /* An element of aTo[] that we are working on */
@@ -111517,21 +111831,23 @@
111517 /* Seed the search with a single WherePath containing zero WhereLoops.
111518 **
111519 ** TUNING: Do not let the number of iterations go above 25. If the cost
111520 ** of computing an automatic index is not paid back within the first 25
111521 ** rows, then do not use the automatic index. */
111522 aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
111523 nFrom = 1;
111524
111525 /* Precompute the cost of sorting the final result set, if the caller
111526 ** to sqlite3WhereBegin() was concerned about sorting */
111527 rSortCost = 0;
111528 if( pWInfo->pOrderBy==0 || nRowEst==0 ){
111529 aFrom[0].isOrderedValid = 1;
111530 }else{
111531 /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
111532 ** number of output rows. */
 
 
111533 rSortCost = nRowEst + estLog(nRowEst);
111534 WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
111535 }
111536
111537 /* Compute successively longer WherePaths using the previous generation
@@ -111547,12 +111863,12 @@
111547 u8 isOrdered = pFrom->isOrdered;
111548 if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
111549 if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
111550 /* At this point, pWLoop is a candidate to be the next loop.
111551 ** Compute its cost */
111552 rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111553 rCost = whereCostAdd(rCost, pFrom->rCost);
111554 nOut = pFrom->nRow + pWLoop->nOut;
111555 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
111556 if( !isOrderedValid ){
111557 switch( wherePathSatisfiesOrderBy(pWInfo,
111558 pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
@@ -111562,11 +111878,11 @@
111562 isOrderedValid = 1;
111563 break;
111564 case 0: /* No. pFrom+pWLoop will require a separate sort */
111565 isOrdered = 0;
111566 isOrderedValid = 1;
111567 rCost = whereCostAdd(rCost, rSortCost);
111568 break;
111569 default: /* Cannot tell yet. Try again on the next iteration */
111570 break;
111571 }
111572 }else{
@@ -111769,11 +112085,11 @@
111769 pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
111770 pLoop->aLTerm[0] = pTerm;
111771 pLoop->nLTerm = 1;
111772 pLoop->u.btree.nEq = 1;
111773 /* TUNING: Cost of a rowid lookup is 10 */
111774 pLoop->rRun = 33; /* 33==whereCost(10) */
111775 }else{
111776 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
111777 assert( pLoop->aLTermSpace==pLoop->aLTerm );
111778 assert( ArraySize(pLoop->aLTermSpace)==4 );
111779 if( pIdx->onError==OE_None
@@ -111792,16 +112108,16 @@
111792 }
111793 pLoop->nLTerm = j;
111794 pLoop->u.btree.nEq = j;
111795 pLoop->u.btree.pIndex = pIdx;
111796 /* TUNING: Cost of a unique index lookup is 15 */
111797 pLoop->rRun = 39; /* 39==whereCost(15) */
111798 break;
111799 }
111800 }
111801 if( pLoop->wsFlags ){
111802 pLoop->nOut = (WhereCost)1;
111803 pWInfo->a[0].pWLoop = pLoop;
111804 pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
111805 pWInfo->a[0].iTabCur = iCur;
111806 pWInfo->nRowOut = 1;
111807 if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
@@ -112165,11 +112481,11 @@
112165 WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
112166 pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
112167
112168 /* If the caller is an UPDATE or DELETE statement that is requesting
112169 ** to use a one-pass algorithm, determine if this is appropriate.
112170 ** The one-pass algorithm only works if the WHERE clause constraints
112171 ** the statement to update a single row.
112172 */
112173 assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
112174 if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
112175 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
@@ -121583,10 +121899,16 @@
121583 ** verifying the operation of the SQLite core.
121584 */
121585 int inTransaction; /* True after xBegin but before xCommit/xRollback */
121586 int mxSavepoint; /* Largest valid xSavepoint integer */
121587 #endif
 
 
 
 
 
 
121588 };
121589
121590 /*
121591 ** When the core wants to read from the virtual table, it creates a
121592 ** virtual table cursor (an instance of the following structure) using
@@ -121608,11 +121930,12 @@
121608 int nDoclist; /* Size of buffer at aDoclist */
121609 u8 bDesc; /* True to sort in descending order */
121610 int eEvalmode; /* An FTS3_EVAL_XX constant */
121611 int nRowAvg; /* Average size of database rows, in pages */
121612 sqlite3_int64 nDoc; /* Documents in table */
121613
 
121614 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
121615 u32 *aMatchinfo; /* Information about most recent match */
121616 int nMatchinfo; /* Number of elements in aMatchinfo[] */
121617 char *zMatchinfo; /* Matchinfo specification */
121618 };
@@ -121638,10 +121961,19 @@
121638 */
121639 #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
121640 #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
121641 #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
121642
 
 
 
 
 
 
 
 
 
121643
121644 struct Fts3Doclist {
121645 char *aAll; /* Array containing doclist (or NULL) */
121646 int nAll; /* Size of a[] in bytes */
121647 char *pNextDocid; /* Pointer to next docid */
@@ -123058,27 +123390,31 @@
123058 */
123059 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
123060 Fts3Table *p = (Fts3Table *)pVTab;
123061 int i; /* Iterator variable */
123062 int iCons = -1; /* Index of constraint to use */
 
123063 int iLangidCons = -1; /* Index of langid=x constraint, if present */
 
 
 
123064
123065 /* By default use a full table scan. This is an expensive option,
123066 ** so search through the constraints to see if a more efficient
123067 ** strategy is possible.
123068 */
123069 pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
123070 pInfo->estimatedCost = 5000000;
123071 for(i=0; i<pInfo->nConstraint; i++){
 
123072 struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
123073 if( pCons->usable==0 ) continue;
 
 
123074
123075 /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
123076 if( iCons<0
123077 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123078 && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
123079 ){
123080 pInfo->idxNum = FTS3_DOCID_SEARCH;
123081 pInfo->estimatedCost = 1.0;
123082 iCons = i;
123083 }
123084
@@ -123103,18 +123439,42 @@
123103 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123104 && pCons->iColumn==p->nColumn + 2
123105 ){
123106 iLangidCons = i;
123107 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123108 }
123109
 
123110 if( iCons>=0 ){
123111 pInfo->aConstraintUsage[iCons].argvIndex = 1;
123112 pInfo->aConstraintUsage[iCons].omit = 1;
123113 }
123114 if( iLangidCons>=0 ){
123115 pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
 
 
 
 
 
 
 
 
 
123116 }
123117
123118 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
123119 ** docid) order. Both ascending and descending are possible.
123120 */
@@ -124556,10 +124916,37 @@
124556 rc = fts3EvalNext((Fts3Cursor *)pCursor);
124557 }
124558 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
124559 return rc;
124560 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124561
124562 /*
124563 ** This is the xFilter interface for the virtual table. See
124564 ** the virtual table xFilter method documentation for additional
124565 ** information.
@@ -124582,44 +124969,62 @@
124582 int nVal, /* Number of elements in apVal */
124583 sqlite3_value **apVal /* Arguments for the indexing scheme */
124584 ){
124585 int rc;
124586 char *zSql; /* SQL statement used to access %_content */
 
124587 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
124588 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
 
 
 
 
 
 
124589
124590 UNUSED_PARAMETER(idxStr);
124591 UNUSED_PARAMETER(nVal);
124592
124593 assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
124594 assert( nVal==0 || nVal==1 || nVal==2 );
124595 assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
124596 assert( p->pSegments==0 );
 
 
 
 
 
 
 
 
124597
124598 /* In case the cursor has been used before, clear it now. */
124599 sqlite3_finalize(pCsr->pStmt);
124600 sqlite3_free(pCsr->aDoclist);
124601 sqlite3Fts3ExprFree(pCsr->pExpr);
124602 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
124603
 
 
 
 
124604 if( idxStr ){
124605 pCsr->bDesc = (idxStr[0]=='D');
124606 }else{
124607 pCsr->bDesc = p->bDescIdx;
124608 }
124609 pCsr->eSearch = (i16)idxNum;
124610
124611 if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
124612 int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
124613 const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
124614
124615 if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
124616 return SQLITE_NOMEM;
124617 }
124618
124619 pCsr->iLangid = 0;
124620 if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
124621
124622 assert( p->base.zErrMsg==0 );
124623 rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
124624 p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
124625 &p->base.zErrMsg
@@ -124638,11 +125043,11 @@
124638 /* Compile a SELECT statement for this cursor. For a full-table-scan, the
124639 ** statement loops through all rows of the %_content table. For a
124640 ** full-text query or docid lookup, the statement retrieves a single
124641 ** row by docid.
124642 */
124643 if( idxNum==FTS3_FULLSCAN_SEARCH ){
124644 zSql = sqlite3_mprintf(
124645 "SELECT %s ORDER BY rowid %s",
124646 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
124647 );
124648 if( zSql ){
@@ -124649,14 +125054,14 @@
124649 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
124650 sqlite3_free(zSql);
124651 }else{
124652 rc = SQLITE_NOMEM;
124653 }
124654 }else if( idxNum==FTS3_DOCID_SEARCH ){
124655 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
124656 if( rc==SQLITE_OK ){
124657 rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
124658 }
124659 }
124660 if( rc!=SQLITE_OK ) return rc;
124661
124662 return fts3NextMethod(pCursor);
@@ -125543,10 +125948,16 @@
125543 }
125544
125545 return SQLITE_OK;
125546 }
125547
 
 
 
 
 
 
125548 /*
125549 ** This function is called for each Fts3Phrase in a full-text query
125550 ** expression to initialize the mechanism for returning rows. Once this
125551 ** function has been called successfully on an Fts3Phrase, it may be
125552 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -125556,27 +125967,47 @@
125556 ** memory within this call.
125557 **
125558 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
125559 */
125560 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
125561 int rc; /* Error code */
125562 Fts3PhraseToken *pFirst = &p->aToken[0];
125563 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125564
125565 if( pCsr->bDesc==pTab->bDescIdx
125566 && bOptOk==1
125567 && p->nToken==1
125568 && pFirst->pSegcsr
125569 && pFirst->pSegcsr->bLookup
125570 && pFirst->bFirst==0
125571 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125572 /* Use the incremental approach. */
125573 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
125574 rc = sqlite3Fts3MsrIncrStart(
125575 pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
 
 
 
 
 
125576 p->bIncr = 1;
125577
125578 }else{
125579 /* Load the full doclist for the phrase into memory. */
125580 rc = fts3EvalPhraseLoad(pCsr, p);
125581 p->bIncr = 0;
125582 }
@@ -125680,10 +126111,220 @@
125680 }
125681 }
125682
125683 *ppIter = p;
125684 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125685
125686 /*
125687 ** Attempt to move the phrase iterator to point to the next matching docid.
125688 ** If an error occurs, return an SQLite error code. Otherwise, return
125689 ** SQLITE_OK.
@@ -125700,59 +126341,18 @@
125700 int rc = SQLITE_OK;
125701 Fts3Doclist *pDL = &p->doclist;
125702 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125703
125704 if( p->bIncr ){
125705 assert( p->nToken==1 );
125706 assert( pDL->pNextDocid==0 );
125707 rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
125708 &pDL->iDocid, &pDL->pList, &pDL->nList
125709 );
125710 if( rc==SQLITE_OK && !pDL->pList ){
125711 *pbEof = 1;
125712 }
125713 }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
125714 sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
125715 &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
125716 );
125717 pDL->pList = pDL->pNextDocid;
125718 }else{
125719 char *pIter; /* Used to iterate through aAll */
125720 char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
125721 if( pDL->pNextDocid ){
125722 pIter = pDL->pNextDocid;
125723 }else{
125724 pIter = pDL->aAll;
125725 }
125726
125727 if( pIter>=pEnd ){
125728 /* We have already reached the end of this doclist. EOF. */
125729 *pbEof = 1;
125730 }else{
125731 sqlite3_int64 iDelta;
125732 pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
125733 if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
125734 pDL->iDocid += iDelta;
125735 }else{
125736 pDL->iDocid -= iDelta;
125737 }
125738 pDL->pList = pIter;
125739 fts3PoslistCopy(0, &pIter);
125740 pDL->nList = (int)(pIter - pDL->pList);
125741
125742 /* pIter now points just past the 0x00 that terminates the position-
125743 ** list for document pDL->iDocid. However, if this position-list was
125744 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
125745 ** point to the start of the next docid value. The following line deals
125746 ** with this case by advancing pIter past the zero-padding added by
125747 ** fts3EvalNearTrim(). */
125748 while( pIter<pEnd && *pIter==0 ) pIter++;
125749
125750 pDL->pNextDocid = pIter;
125751 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
125752 *pbEof = 0;
125753 }
125754 }
125755
125756 return rc;
125757 }
125758
@@ -125773,11 +126373,10 @@
125773 ** code before returning.
125774 */
125775 static void fts3EvalStartReaders(
125776 Fts3Cursor *pCsr, /* FTS Cursor handle */
125777 Fts3Expr *pExpr, /* Expression to initialize phrases in */
125778 int bOptOk, /* True to enable incremental loading */
125779 int *pRc /* IN/OUT: Error code */
125780 ){
125781 if( pExpr && SQLITE_OK==*pRc ){
125782 if( pExpr->eType==FTSQUERY_PHRASE ){
125783 int i;
@@ -125784,14 +126383,14 @@
125784 int nToken = pExpr->pPhrase->nToken;
125785 for(i=0; i<nToken; i++){
125786 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
125787 }
125788 pExpr->bDeferred = (i==nToken);
125789 *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
125790 }else{
125791 fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
125792 fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
125793 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
125794 }
125795 }
125796 }
125797
@@ -126029,11 +126628,11 @@
126029 /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
126030 ** for-loop. Except, limit the value to 2^24 to prevent it from
126031 ** overflowing the 32-bit integer it is stored in. */
126032 if( ii<12 ) nLoad4 = nLoad4*4;
126033
126034 if( ii==0 || pTC->pPhrase->nToken>1 ){
126035 /* Either this is the cheapest token in the entire query, or it is
126036 ** part of a multi-token phrase. Either way, the entire doclist will
126037 ** (eventually) be loaded into memory. It may as well be now. */
126038 Fts3PhraseToken *pToken = pTC->pToken;
126039 int nList = 0;
@@ -126109,11 +126708,11 @@
126109 sqlite3_free(aTC);
126110 }
126111 }
126112 #endif
126113
126114 fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
126115 return rc;
126116 }
126117
126118 /*
126119 ** Invalidate the current position list for phrase pPhrase.
@@ -126592,10 +127191,20 @@
126592 pCsr->isRequireSeek = 1;
126593 pCsr->isMatchinfoNeeded = 1;
126594 pCsr->iPrevId = pExpr->iDocid;
126595 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
126596 }
 
 
 
 
 
 
 
 
 
 
126597 return rc;
126598 }
126599
126600 /*
126601 ** Restart interation for expression pExpr so that the next call to
@@ -126615,16 +127224,20 @@
126615 Fts3Phrase *pPhrase = pExpr->pPhrase;
126616
126617 if( pPhrase ){
126618 fts3EvalInvalidatePoslist(pPhrase);
126619 if( pPhrase->bIncr ){
126620 assert( pPhrase->nToken==1 );
126621 assert( pPhrase->aToken[0].pSegcsr );
126622 sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
 
 
 
 
 
126623 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
126624 }
126625
126626 pPhrase->doclist.pNextDocid = 0;
126627 pPhrase->doclist.iDocid = 0;
126628 }
126629
126630 pExpr->iDocid = 0;
@@ -126869,19 +127482,27 @@
126869
126870 iDocid = pExpr->iDocid;
126871 pIter = pPhrase->doclist.pList;
126872 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
126873 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
 
126874 int bOr = 0;
126875 u8 bEof = 0;
126876 Fts3Expr *p;
 
 
126877
126878 /* Check if this phrase descends from an OR expression node. If not,
126879 ** return NULL. Otherwise, the entry that corresponds to docid
126880 ** pCsr->iPrevId may lie earlier in the doclist buffer. */
 
 
 
126881 for(p=pExpr->pParent; p; p=p->pParent){
126882 if( p->eType==FTSQUERY_OR ) bOr = 1;
 
 
126883 }
126884 if( bOr==0 ) return SQLITE_OK;
126885
126886 /* This is the descendent of an OR node. In this case we cannot use
126887 ** an incremental phrase. Load the entire doclist for the phrase
@@ -126896,33 +127517,63 @@
126896 }
126897 pIter = pPhrase->doclist.pList;
126898 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
126899 if( rc!=SQLITE_OK ) return rc;
126900 }
 
 
 
 
 
 
 
 
 
 
 
 
126901
126902 if( pExpr->bEof ){
126903 pIter = 0;
126904 iDocid = 0;
126905 }
126906 bEof = (pPhrase->doclist.nAll==0);
126907 assert( bDescDoclist==0 || bDescDoclist==1 );
126908 assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
126909
126910 if( pCsr->bDesc==bDescDoclist ){
126911 int dummy;
126912 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
126913 sqlite3Fts3DoclistPrev(
126914 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126915 &pIter, &iDocid, &dummy, &bEof
126916 );
126917 }
126918 }else{
126919 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
126920 sqlite3Fts3DoclistNext(
126921 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126922 &pIter, &iDocid, &bEof
126923 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126924 }
126925 }
126926
126927 if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
126928 }
@@ -135756,11 +136407,11 @@
135756 assert( p->bFts4==0 );
135757 sqlite3Fts3CreateStatTable(&rc, p);
135758 if( rc ) return rc;
135759 }
135760 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
135761 if( rc ) return rc;;
135762 sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
135763 sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
135764 sqlite3_step(pStmt);
135765 rc = sqlite3_reset(pStmt);
135766 return rc;
@@ -136025,10 +136676,13 @@
136025 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
136026 p->nNodeSize = atoi(&zVal[9]);
136027 rc = SQLITE_OK;
136028 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
136029 p->nMaxPendingData = atoi(&zVal[11]);
 
 
 
136030 rc = SQLITE_OK;
136031 #endif
136032 }else{
136033 rc = SQLITE_ERROR;
136034 }
136035
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -656,11 +656,11 @@
656 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657 ** [sqlite_version()] and [sqlite_source_id()].
658 */
659 #define SQLITE_VERSION "3.8.1"
660 #define SQLITE_VERSION_NUMBER 3008001
661 #define SQLITE_SOURCE_ID "2013-10-10 15:04:52 af7abebeb1f70466833bc766d294d721eaef746f"
662
663 /*
664 ** CAPI3REF: Run-Time Library Version Numbers
665 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
666 **
@@ -8272,10 +8272,35 @@
8272 typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
8273 #else
8274 typedef u32 tRowcnt; /* 32-bit is the default */
8275 #endif
8276
8277 /*
8278 ** Estimated quantities used for query planning are stored as 16-bit
8279 ** logarithms. For quantity X, the value stored is 10*log2(X). This
8280 ** gives a possible range of values of approximately 1.0e986 to 1e-986.
8281 ** But the allowed values are "grainy". Not every value is representable.
8282 ** For example, quantities 16 and 17 are both represented by a LogEst
8283 ** of 40. However, since LogEst quantatites are suppose to be estimates,
8284 ** not exact values, this imprecision is not a problem.
8285 **
8286 ** "LogEst" is short for "Logarithimic Estimate".
8287 **
8288 ** Examples:
8289 ** 1 -> 0 20 -> 43 10000 -> 132
8290 ** 2 -> 10 25 -> 46 25000 -> 146
8291 ** 3 -> 16 100 -> 66 1000000 -> 199
8292 ** 4 -> 20 1000 -> 99 1048576 -> 200
8293 ** 10 -> 33 1024 -> 100 4294967296 -> 320
8294 **
8295 ** The LogEst can be negative to indicate fractional values.
8296 ** Examples:
8297 **
8298 ** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
8299 */
8300 typedef INT16_TYPE LogEst;
8301
8302 /*
8303 ** Macros to determine whether the machine is big or little endian,
8304 ** evaluated at runtime.
8305 */
8306 #ifdef SQLITE_AMALGAMATION
@@ -10419,11 +10444,12 @@
10444 char *zDflt; /* Original text of the default value */
10445 char *zType; /* Data type for this column */
10446 char *zColl; /* Collating sequence. If NULL, use the default */
10447 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
10448 char affinity; /* One of the SQLITE_AFF_... values */
10449 u8 szEst; /* Estimated size of this column. INT==1 */
10450 u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
10451 };
10452
10453 /* Allowed values for Column.colFlags:
10454 */
10455 #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
@@ -10583,10 +10609,11 @@
10609 tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
10610 int tnum; /* Root BTree node for this table (see note above) */
10611 i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
10612 i16 nCol; /* Number of columns in this table */
10613 u16 nRef; /* Number of pointers to this Table */
10614 LogEst szTabRow; /* Estimated size of each table row in bytes */
10615 u8 tabFlags; /* Mask of TF_* values */
10616 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10617 #ifndef SQLITE_OMIT_ALTERTABLE
10618 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10619 #endif
@@ -10694,11 +10721,11 @@
10721 #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
10722 #define OE_SetNull 7 /* Set the foreign key value to NULL */
10723 #define OE_SetDflt 8 /* Set the foreign key value to its default */
10724 #define OE_Cascade 9 /* Cascade the changes */
10725
10726 #define OE_Default 10 /* Do whatever the default action is */
10727
10728
10729 /*
10730 ** An instance of the following structure is passed as the first
10731 ** argument to sqlite3VdbeKeyCompare and is used to control the
@@ -10781,10 +10808,11 @@
10808 Schema *pSchema; /* Schema containing this index */
10809 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
10810 char **azColl; /* Array of collation sequence names for index */
10811 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
10812 int tnum; /* DB Page containing root of this index */
10813 LogEst szIdxRow; /* Estimated average row size in bytes */
10814 u16 nColumn; /* Number of columns in table used by this index */
10815 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10816 unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
10817 unsigned bUnordered:1; /* Use this index for == or IN queries only */
10818 unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
@@ -11636,10 +11664,11 @@
11664 */
11665 typedef struct DbFixer DbFixer;
11666 struct DbFixer {
11667 Parse *pParse; /* The parsing context. Error messages written here */
11668 Schema *pSchema; /* Fix items to this schema */
11669 int bVarOnly; /* Check for variable references only */
11670 const char *zDb; /* Make sure all objects are contained in this database */
11671 const char *zType; /* Type of the container - used for error messages */
11672 const Token *pName; /* Name of the container - used for error messages */
11673 };
11674
@@ -12174,11 +12203,11 @@
12203 # define sqlite3AuthContextPush(a,b,c)
12204 # define sqlite3AuthContextPop(a) ((void)(a))
12205 #endif
12206 SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
12207 SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
12208 SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
12209 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
12210 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
12211 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
12212 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
12213 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
@@ -12186,10 +12215,16 @@
12215 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
12216 SQLITE_PRIVATE int sqlite3Atoi(const char*);
12217 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
12218 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
12219 SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
12220 SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
12221 SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
12222 #ifndef SQLITE_OMIT_VIRTUALTABLE
12223 SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
12224 #endif
12225 SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
12226
12227 /*
12228 ** Routines to read and write variable-length integers. These used to
12229 ** be defined locally, but now we use the varint routines in the util.c
12230 ** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -12302,11 +12337,11 @@
12337 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
12338 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
12339 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
12340 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
12341 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12342 SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
12343 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
12344 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
12345 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
12346 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
12347 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -22387,10 +22422,87 @@
22422 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
22423 if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
22424 }
22425 }
22426 #endif
22427
22428 /*
22429 ** Find (an approximate) sum of two LogEst values. This computation is
22430 ** not a simple "+" operator because LogEst is stored as a logarithmic
22431 ** value.
22432 **
22433 */
22434 SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
22435 static const unsigned char x[] = {
22436 10, 10, /* 0,1 */
22437 9, 9, /* 2,3 */
22438 8, 8, /* 4,5 */
22439 7, 7, 7, /* 6,7,8 */
22440 6, 6, 6, /* 9,10,11 */
22441 5, 5, 5, /* 12-14 */
22442 4, 4, 4, 4, /* 15-18 */
22443 3, 3, 3, 3, 3, 3, /* 19-24 */
22444 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
22445 };
22446 if( a>=b ){
22447 if( a>b+49 ) return a;
22448 if( a>b+31 ) return a+1;
22449 return a+x[a-b];
22450 }else{
22451 if( b>a+49 ) return b;
22452 if( b>a+31 ) return b+1;
22453 return b+x[b-a];
22454 }
22455 }
22456
22457 /*
22458 ** Convert an integer into a LogEst. In other words, compute a
22459 ** good approximatation for 10*log2(x).
22460 */
22461 SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
22462 static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
22463 LogEst y = 40;
22464 if( x<8 ){
22465 if( x<2 ) return 0;
22466 while( x<8 ){ y -= 10; x <<= 1; }
22467 }else{
22468 while( x>255 ){ y += 40; x >>= 4; }
22469 while( x>15 ){ y += 10; x >>= 1; }
22470 }
22471 return a[x&7] + y - 10;
22472 }
22473
22474 #ifndef SQLITE_OMIT_VIRTUALTABLE
22475 /*
22476 ** Convert a double into a LogEst
22477 ** In other words, compute an approximation for 10*log2(x).
22478 */
22479 SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
22480 u64 a;
22481 LogEst e;
22482 assert( sizeof(x)==8 && sizeof(a)==8 );
22483 if( x<=1 ) return 0;
22484 if( x<=2000000000 ) return sqlite3LogEst((u64)x);
22485 memcpy(&a, &x, 8);
22486 e = (a>>52) - 1022;
22487 return e*10;
22488 }
22489 #endif /* SQLITE_OMIT_VIRTUALTABLE */
22490
22491 /*
22492 ** Convert a LogEst into an integer.
22493 */
22494 SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
22495 u64 n;
22496 if( x<10 ) return 1;
22497 n = x%10;
22498 x /= 10;
22499 if( n>=5 ) n -= 2;
22500 else if( n>=1 ) n -= 1;
22501 if( x>=3 ) return (n+8)<<(x-3);
22502 return (n+8)>>(3-x);
22503 }
22504
22505 /************** End of util.c ************************************************/
22506 /************** Begin file hash.c ********************************************/
22507 /*
22508 ** 2001 September 22
@@ -48986,17 +49098,17 @@
49098 ** page contain a special header (the "file header") that describes the file.
49099 ** The format of the file header is as follows:
49100 **
49101 ** OFFSET SIZE DESCRIPTION
49102 ** 0 16 Header string: "SQLite format 3\000"
49103 ** 16 2 Page size in bytes. (1 means 65536)
49104 ** 18 1 File format write version
49105 ** 19 1 File format read version
49106 ** 20 1 Bytes of unused space at the end of each page
49107 ** 21 1 Max embedded payload fraction (must be 64)
49108 ** 22 1 Min embedded payload fraction (must be 32)
49109 ** 23 1 Min leaf payload fraction (must be 32)
49110 ** 24 4 File change counter
49111 ** 28 4 Reserved for future use
49112 ** 32 4 First freelist page
49113 ** 36 4 Number of freelist pages in the file
49114 ** 40 60 15 4-byte meta values passed to higher layers
@@ -49006,13 +49118,14 @@
49118 ** 48 4 Size of page cache
49119 ** 52 4 Largest root-page (auto/incr_vacuum)
49120 ** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
49121 ** 60 4 User version
49122 ** 64 4 Incremental vacuum mode
49123 ** 68 4 Application-ID
49124 ** 72 20 unused
49125 ** 92 4 The version-valid-for number
49126 ** 96 4 SQLITE_VERSION_NUMBER
49127 **
49128 ** All of the integer values are big-endian (most significant byte first).
49129 **
49130 ** The file change counter is incremented when the database is changed
49131 ** This counter allows other processes to know when the file has changed
@@ -52378,11 +52491,10 @@
52491 pBt->max1bytePayload = (u8)pBt->maxLocal;
52492 }
52493 assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
52494 pBt->pPage1 = pPage1;
52495 pBt->nPage = nPage;
 
52496 return SQLITE_OK;
52497
52498 page1_init_failed:
52499 releasePage(pPage1);
52500 pBt->pPage1 = 0;
@@ -52538,11 +52650,11 @@
52650 ** is requested, this is a no-op.
52651 */
52652 if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
52653 goto trans_begun;
52654 }
52655 assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
52656
52657 /* Write transactions are not possible on a read-only database */
52658 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
52659 rc = SQLITE_READONLY;
52660 goto trans_begun;
@@ -62977,10 +63089,11 @@
63089 }
63090 fclose(out);
63091 }
63092 }
63093 #endif
63094 p->iCurrentTime = 0;
63095 p->magic = VDBE_MAGIC_INIT;
63096 return p->rc & db->errMask;
63097 }
63098
63099 /*
@@ -76082,11 +76195,11 @@
76195 return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
76196 }
76197 #ifndef SQLITE_OMIT_CAST
76198 if( op==TK_CAST ){
76199 assert( !ExprHasProperty(pExpr, EP_IntValue) );
76200 return sqlite3AffinityType(pExpr->u.zToken, 0);
76201 }
76202 #endif
76203 if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
76204 && pExpr->pTab!=0
76205 ){
@@ -78502,11 +78615,11 @@
78615 case TK_CAST: {
78616 /* Expressions of the form: CAST(pLeft AS token) */
78617 int aff, to_op;
78618 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
78619 assert( !ExprHasProperty(pExpr, EP_IntValue) );
78620 aff = sqlite3AffinityType(pExpr->u.zToken, 0);
78621 to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
78622 assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
78623 assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
78624 assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
78625 assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
@@ -79169,11 +79282,11 @@
79282 }
79283 #ifndef SQLITE_OMIT_CAST
79284 case TK_CAST: {
79285 /* Expressions of the form: CAST(pLeft AS token) */
79286 const char *zAff = "unk";
79287 switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
79288 case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
79289 case SQLITE_AFF_NONE: zAff = "NONE"; break;
79290 case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
79291 case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
79292 case SQLITE_AFF_REAL: zAff = "REAL"; break;
@@ -81884,16 +81997,16 @@
81997 if( zRet==0 ){
81998 sqlite3_result_error_nomem(context);
81999 return;
82000 }
82001
82002 sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
82003 z = zRet + sqlite3Strlen30(zRet);
82004 for(i=0; i<(p->nCol-1); i++){
82005 u64 nDistinct = p->current.anDLt[i] + 1;
82006 u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
82007 sqlite3_snprintf(24, z, " %llu", iVal);
82008 z += sqlite3Strlen30(z);
82009 assert( p->current.anEq[i] );
82010 }
82011 assert( z[0]=='\0' && z>zRet );
82012
@@ -81930,11 +82043,11 @@
82043 sqlite3_result_error_nomem(context);
82044 }else{
82045 int i;
82046 char *z = zRet;
82047 for(i=0; i<p->nCol; i++){
82048 sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
82049 z += sqlite3Strlen30(z);
82050 }
82051 assert( z[0]=='\0' && z>zRet );
82052 z[-1] = '\0';
82053 sqlite3_result_text(context, zRet, -1, sqlite3_free);
@@ -82391,22 +82504,20 @@
82504 ** The first argument points to a nul-terminated string containing a
82505 ** list of space separated integers. Read the first nOut of these into
82506 ** the array aOut[].
82507 */
82508 static void decodeIntArray(
82509 char *zIntArray, /* String containing int array to decode */
82510 int nOut, /* Number of slots in aOut[] */
82511 tRowcnt *aOut, /* Store integers here */
82512 Index *pIndex /* Handle extra flags for this index, if not NULL */
82513 ){
82514 char *z = zIntArray;
82515 int c;
82516 int i;
82517 tRowcnt v;
82518
 
 
82519 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
82520 if( z==0 ) z = "";
82521 #else
82522 if( NEVER(z==0) ) z = "";
82523 #endif
@@ -82417,12 +82528,23 @@
82528 z++;
82529 }
82530 aOut[i] = v;
82531 if( *z==' ' ) z++;
82532 }
82533 #ifndef SQLITE_ENABLE_STAT3_OR_STAT4
82534 assert( pIndex!=0 );
82535 #else
82536 if( pIndex )
82537 #endif
82538 {
82539 if( strcmp(z, "unordered")==0 ){
82540 pIndex->bUnordered = 1;
82541 }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
82542 int v32 = 0;
82543 sqlite3GetInt32(z+3, &v32);
82544 pIndex->szIdxRow = sqlite3LogEst(v32);
82545 }
82546 }
82547 }
82548
82549 /*
82550 ** This callback is invoked once for each index when reading the
@@ -82457,16 +82579,17 @@
82579 pIndex = 0;
82580 }
82581 z = argv[2];
82582
82583 if( pIndex ){
82584 decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex);
 
82585 if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
 
82586 }else{
82587 Index fakeIdx;
82588 fakeIdx.szIdxRow = pTable->szTabRow;
82589 decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
82590 pTable->szTabRow = fakeIdx.szIdxRow;
82591 }
82592
82593 return 0;
82594 }
82595
@@ -83185,32 +83308,28 @@
83308 #endif /* SQLITE_OMIT_ATTACH */
83309
83310 /*
83311 ** Initialize a DbFixer structure. This routine must be called prior
83312 ** to passing the structure to one of the sqliteFixAAAA() routines below.
 
 
 
83313 */
83314 SQLITE_PRIVATE void sqlite3FixInit(
83315 DbFixer *pFix, /* The fixer to be initialized */
83316 Parse *pParse, /* Error messages will be written here */
83317 int iDb, /* This is the database that must be used */
83318 const char *zType, /* "view", "trigger", or "index" */
83319 const Token *pName /* Name of the view, trigger, or index */
83320 ){
83321 sqlite3 *db;
83322
 
83323 db = pParse->db;
83324 assert( db->nDb>iDb );
83325 pFix->pParse = pParse;
83326 pFix->zDb = db->aDb[iDb].zName;
83327 pFix->pSchema = db->aDb[iDb].pSchema;
83328 pFix->zType = zType;
83329 pFix->pName = pName;
83330 pFix->bVarOnly = (iDb==1);
83331 }
83332
83333 /*
83334 ** The following set of routines walk through the parse tree and assign
83335 ** a specific database to all table references where the database name
@@ -83234,19 +83353,21 @@
83353 struct SrcList_item *pItem;
83354
83355 if( NEVER(pList==0) ) return 0;
83356 zDb = pFix->zDb;
83357 for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
83358 if( pFix->bVarOnly==0 ){
83359 if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83360 sqlite3ErrorMsg(pFix->pParse,
83361 "%s %T cannot reference objects in database %s",
83362 pFix->zType, pFix->pName, pItem->zDatabase);
83363 return 1;
83364 }
83365 sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83366 pItem->zDatabase = 0;
83367 pItem->pSchema = pFix->pSchema;
83368 }
83369 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
83370 if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
83371 if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
83372 #endif
83373 }
@@ -83264,13 +83385,25 @@
83385 if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
83386 return 1;
83387 }
83388 if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
83389 return 1;
83390 }
83391 if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
83392 return 1;
83393 }
83394 if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
83395 return 1;
83396 }
83397 if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
83398 return 1;
83399 }
83400 if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
83401 return 1;
83402 }
83403 if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
83404 return 1;
83405 }
83406 pSelect = pSelect->pPrior;
83407 }
83408 return 0;
83409 }
@@ -83277,10 +83410,18 @@
83410 SQLITE_PRIVATE int sqlite3FixExpr(
83411 DbFixer *pFix, /* Context of the fixation */
83412 Expr *pExpr /* The expression to be fixed to one database */
83413 ){
83414 while( pExpr ){
83415 if( pExpr->op==TK_VARIABLE ){
83416 if( pFix->pParse->db->init.busy ){
83417 pExpr->op = TK_NULL;
83418 }else{
83419 sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
83420 return 1;
83421 }
83422 }
83423 if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
83424 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
83425 if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
83426 }else{
83427 if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
@@ -84460,11 +84601,11 @@
84601 }
84602 pTable->zName = zName;
84603 pTable->iPKey = -1;
84604 pTable->pSchema = db->aDb[iDb].pSchema;
84605 pTable->nRef = 1;
84606 pTable->nRowEst = 1048576;
84607 assert( pParse->pNewTable==0 );
84608 pParse->pNewTable = pTable;
84609
84610 /* If this is the magic sqlite_sequence table used by autoincrement,
84611 ** then record a pointer to this table in the main database structure
@@ -84607,10 +84748,11 @@
84748 /* If there is no type specified, columns have the default affinity
84749 ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
84750 ** be called next to set pCol->affinity correctly.
84751 */
84752 pCol->affinity = SQLITE_AFF_NONE;
84753 pCol->szEst = 1;
84754 p->nCol++;
84755 }
84756
84757 /*
84758 ** This routine is called by the parser while in the middle of
@@ -84648,26 +84790,30 @@
84790 ** 'DOUB' | SQLITE_AFF_REAL
84791 **
84792 ** If none of the substrings in the above table are found,
84793 ** SQLITE_AFF_NUMERIC is returned.
84794 */
84795 SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
84796 u32 h = 0;
84797 char aff = SQLITE_AFF_NUMERIC;
84798 const char *zChar = 0;
84799
84800 if( zIn==0 ) return aff;
84801 while( zIn[0] ){
84802 h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
84803 zIn++;
84804 if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
84805 aff = SQLITE_AFF_TEXT;
84806 zChar = zIn;
84807 }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
84808 aff = SQLITE_AFF_TEXT;
84809 }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
84810 aff = SQLITE_AFF_TEXT;
84811 }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
84812 && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
84813 aff = SQLITE_AFF_NONE;
84814 if( zIn[0]=='(' ) zChar = zIn;
84815 #ifndef SQLITE_OMIT_FLOATING_POINT
84816 }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
84817 && aff==SQLITE_AFF_NUMERIC ){
84818 aff = SQLITE_AFF_REAL;
84819 }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
@@ -84681,10 +84827,32 @@
84827 aff = SQLITE_AFF_INTEGER;
84828 break;
84829 }
84830 }
84831
84832 /* If pszEst is not NULL, store an estimate of the field size. The
84833 ** estimate is scaled so that the size of an integer is 1. */
84834 if( pszEst ){
84835 *pszEst = 1; /* default size is approx 4 bytes */
84836 if( aff<=SQLITE_AFF_NONE ){
84837 if( zChar ){
84838 while( zChar[0] ){
84839 if( sqlite3Isdigit(zChar[0]) ){
84840 int v;
84841 sqlite3GetInt32(zChar, &v);
84842 v = v/4 + 1;
84843 if( v>255 ) v = 255;
84844 *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
84845 break;
84846 }
84847 zChar++;
84848 }
84849 }else{
84850 *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
84851 }
84852 }
84853 }
84854 return aff;
84855 }
84856
84857 /*
84858 ** This routine is called by the parser while in the middle of
@@ -84702,11 +84870,11 @@
84870 p = pParse->pNewTable;
84871 if( p==0 || NEVER(p->nCol<1) ) return;
84872 pCol = &p->aCol[p->nCol-1];
84873 assert( pCol->zType==0 );
84874 pCol->zType = sqlite3NameFromToken(pParse->db, pType);
84875 pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
84876 }
84877
84878 /*
84879 ** The expression is the default value for the most recently added column
84880 ** of the table currently under construction.
@@ -85050,18 +85218,46 @@
85218 testcase( pCol->affinity==SQLITE_AFF_REAL );
85219
85220 zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
85221 len = sqlite3Strlen30(zType);
85222 assert( pCol->affinity==SQLITE_AFF_NONE
85223 || pCol->affinity==sqlite3AffinityType(zType, 0) );
85224 memcpy(&zStmt[k], zType, len);
85225 k += len;
85226 assert( k<=n );
85227 }
85228 sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
85229 return zStmt;
85230 }
85231
85232 /*
85233 ** Estimate the total row width for a table.
85234 */
85235 static void estimateTableWidth(Table *pTab){
85236 unsigned wTable = 0;
85237 const Column *pTabCol;
85238 int i;
85239 for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
85240 wTable += pTabCol->szEst;
85241 }
85242 if( pTab->iPKey<0 ) wTable++;
85243 pTab->szTabRow = sqlite3LogEst(wTable*4);
85244 }
85245
85246 /*
85247 ** Estimate the average size of a row for an index.
85248 */
85249 static void estimateIndexWidth(Index *pIdx){
85250 unsigned wIndex = 1;
85251 int i;
85252 const Column *aCol = pIdx->pTable->aCol;
85253 for(i=0; i<pIdx->nColumn; i++){
85254 assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol );
85255 wIndex += aCol[pIdx->aiColumn[i]].szEst;
85256 }
85257 pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
85258 }
85259
85260 /*
85261 ** This routine is called to report the final ")" that terminates
85262 ** a CREATE TABLE statement.
85263 **
@@ -85085,13 +85281,14 @@
85281 Parse *pParse, /* Parse context */
85282 Token *pCons, /* The ',' token after the last column defn. */
85283 Token *pEnd, /* The final ')' token in the CREATE TABLE */
85284 Select *pSelect /* Select from a "CREATE ... AS SELECT" */
85285 ){
85286 Table *p; /* The new table */
85287 sqlite3 *db = pParse->db; /* The database connection */
85288 int iDb; /* Database in which the table lives */
85289 Index *pIdx; /* An implied index of the table */
85290
85291 if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
85292 return;
85293 }
85294 p = pParse->pNewTable;
@@ -85106,10 +85303,16 @@
85303 */
85304 if( p->pCheck ){
85305 sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
85306 }
85307 #endif /* !defined(SQLITE_OMIT_CHECK) */
85308
85309 /* Estimate the average row size for the table and for all implied indices */
85310 estimateTableWidth(p);
85311 for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
85312 estimateIndexWidth(pIdx);
85313 }
85314
85315 /* If the db->init.busy is 1 it means we are reading the SQL off the
85316 ** "sqlite_master" or "sqlite_temp_master" table on the disk.
85317 ** So do not write to the disk again. Extract the root page number
85318 ** for the table from the db->init.newTnum field. (The page number
@@ -85303,13 +85506,12 @@
85506 sqlite3SelectDelete(db, pSelect);
85507 return;
85508 }
85509 sqlite3TwoPartName(pParse, pName1, pName2, &pName);
85510 iDb = sqlite3SchemaToIndex(db, p->pSchema);
85511 sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
85512 if( sqlite3FixSelect(&sFix, pSelect) ){
 
85513 sqlite3SelectDelete(db, pSelect);
85514 return;
85515 }
85516
85517 /* Make a copy of the entire SELECT statement that defines the view.
@@ -86066,13 +86268,14 @@
86268 sqlite3 *db = pParse->db;
86269 Db *pDb; /* The specific table containing the indexed database */
86270 int iDb; /* Index of the database that is being written */
86271 Token *pName = 0; /* Unqualified name of the index to create */
86272 struct ExprList_item *pListItem; /* For looping over pList */
86273 const Column *pTabCol; /* A column in the table */
86274 int nCol; /* Number of columns */
86275 int nExtra = 0; /* Space allocated for zExtra[] */
86276 char *zExtra; /* Extra space after the Index object */
86277
86278 assert( pParse->nErr==0 ); /* Never called with prior errors */
86279 if( db->mallocFailed || IN_DECLARE_VTAB ){
86280 goto exit_create_index;
86281 }
@@ -86105,13 +86308,12 @@
86308 iDb = 1;
86309 }
86310 }
86311 #endif
86312
86313 sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
86314 if( sqlite3FixSrcList(&sFix, pTblName) ){
 
86315 /* Because the parser constructs pTblName from a single identifier,
86316 ** sqlite3FixSrcList can never fail. */
86317 assert(0);
86318 }
86319 pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
@@ -86296,11 +86498,10 @@
86498 ** same column more than once cannot be an error because that would
86499 ** break backwards compatibility - it needs to be a warning.
86500 */
86501 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
86502 const char *zColName = pListItem->zName;
 
86503 int requestedSortOrder;
86504 char *zColl; /* Collation sequence name */
86505
86506 for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
86507 if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -86333,10 +86534,11 @@
86534 requestedSortOrder = pListItem->sortOrder & sortOrderMask;
86535 pIndex->aSortOrder[i] = (u8)requestedSortOrder;
86536 if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
86537 }
86538 sqlite3DefaultRowEst(pIndex);
86539 if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
86540
86541 if( pTab==pParse->pNewTable ){
86542 /* This routine has been called to create an automatic index as a
86543 ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
86544 ** a PRIMARY KEY or UNIQUE clause following the column definitions.
@@ -88238,10 +88440,11 @@
88440 ** API function sqlite3_count_changes) to be set incorrectly. */
88441 if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
88442 && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
88443 ){
88444 assert( !isView );
88445 sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
88446 sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
88447 pTab->zName, P4_STATIC);
88448 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
88449 assert( pIdx->pSchema==pTab->pSchema );
88450 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -93487,10 +93690,11 @@
93690 (char*)pKey, P4_KEYINFO_HANDOFF);
93691 VdbeComment((v, "%s", pSrcIdx->zName));
93692 pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
93693 sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
93694 (char*)pKey, P4_KEYINFO_HANDOFF);
93695 sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
93696 VdbeComment((v, "%s", pDestIdx->zName));
93697 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
93698 sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
93699 sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
93700 sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
@@ -94974,181 +95178,363 @@
95178 #define PragTyp_HEXKEY 35
95179 #define PragTyp_KEY 36
95180 #define PragTyp_REKEY 37
95181 #define PragTyp_LOCK_STATUS 38
95182 #define PragTyp_PARSER_TRACE 39
95183 #define PragFlag_NeedSchema 0x01
95184 static const struct sPragmaNames {
95185 const char *const zName; /* Name of pragma */
95186 u8 ePragTyp; /* PragTyp_XXX value */
95187 u8 mPragFlag; /* Zero or more PragFlag_XXX values */
95188 u32 iArg; /* Extra argument */
95189 } aPragmaNames[] = {
95190 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
95191 { /* zName: */ "activate_extensions",
95192 /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
95193 /* ePragFlag: */ 0,
95194 /* iArg: */ 0 },
95195 #endif
95196 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95197 { /* zName: */ "application_id",
95198 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95199 /* ePragFlag: */ 0,
95200 /* iArg: */ 0 },
95201 #endif
95202 #if !defined(SQLITE_OMIT_AUTOVACUUM)
95203 { /* zName: */ "auto_vacuum",
95204 /* ePragTyp: */ PragTyp_AUTO_VACUUM,
95205 /* ePragFlag: */ PragFlag_NeedSchema,
95206 /* iArg: */ 0 },
95207 #endif
95208 #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
95209 { /* zName: */ "automatic_index",
95210 /* ePragTyp: */ PragTyp_FLAG,
95211 /* ePragFlag: */ 0,
95212 /* iArg: */ SQLITE_AutoIndex },
95213 #endif
95214 { /* zName: */ "busy_timeout",
95215 /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
95216 /* ePragFlag: */ 0,
95217 /* iArg: */ 0 },
95218 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95219 { /* zName: */ "cache_size",
95220 /* ePragTyp: */ PragTyp_CACHE_SIZE,
95221 /* ePragFlag: */ PragFlag_NeedSchema,
95222 /* iArg: */ 0 },
95223 #endif
95224 { /* zName: */ "cache_spill",
95225 /* ePragTyp: */ PragTyp_FLAG,
95226 /* ePragFlag: */ 0,
95227 /* iArg: */ SQLITE_CacheSpill },
95228 { /* zName: */ "case_sensitive_like",
95229 /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
95230 /* ePragFlag: */ 0,
95231 /* iArg: */ 0 },
95232 { /* zName: */ "checkpoint_fullfsync",
95233 /* ePragTyp: */ PragTyp_FLAG,
95234 /* ePragFlag: */ 0,
95235 /* iArg: */ SQLITE_CkptFullFSync },
95236 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95237 { /* zName: */ "collation_list",
95238 /* ePragTyp: */ PragTyp_COLLATION_LIST,
95239 /* ePragFlag: */ 0,
95240 /* iArg: */ 0 },
95241 #endif
95242 #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
95243 { /* zName: */ "compile_options",
95244 /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
95245 /* ePragFlag: */ 0,
95246 /* iArg: */ 0 },
95247 #endif
95248 { /* zName: */ "count_changes",
95249 /* ePragTyp: */ PragTyp_FLAG,
95250 /* ePragFlag: */ 0,
95251 /* iArg: */ SQLITE_CountRows },
95252 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
95253 { /* zName: */ "data_store_directory",
95254 /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
95255 /* ePragFlag: */ 0,
95256 /* iArg: */ 0 },
95257 #endif
95258 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95259 { /* zName: */ "database_list",
95260 /* ePragTyp: */ PragTyp_DATABASE_LIST,
95261 /* ePragFlag: */ PragFlag_NeedSchema,
95262 /* iArg: */ 0 },
95263 #endif
95264 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
95265 { /* zName: */ "default_cache_size",
95266 /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
95267 /* ePragFlag: */ PragFlag_NeedSchema,
95268 /* iArg: */ 0 },
95269 #endif
95270 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95271 { /* zName: */ "defer_foreign_keys",
95272 /* ePragTyp: */ PragTyp_FLAG,
95273 /* ePragFlag: */ 0,
95274 /* iArg: */ SQLITE_DeferFKs },
95275 #endif
95276 { /* zName: */ "empty_result_callbacks",
95277 /* ePragTyp: */ PragTyp_FLAG,
95278 /* ePragFlag: */ 0,
95279 /* iArg: */ SQLITE_NullCallback },
95280 #if !defined(SQLITE_OMIT_UTF16)
95281 { /* zName: */ "encoding",
95282 /* ePragTyp: */ PragTyp_ENCODING,
95283 /* ePragFlag: */ 0,
95284 /* iArg: */ 0 },
95285 #endif
95286 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95287 { /* zName: */ "foreign_key_check",
95288 /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
95289 /* ePragFlag: */ PragFlag_NeedSchema,
95290 /* iArg: */ 0 },
95291 #endif
95292 #if !defined(SQLITE_OMIT_FOREIGN_KEY)
95293 { /* zName: */ "foreign_key_list",
95294 /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
95295 /* ePragFlag: */ PragFlag_NeedSchema,
95296 /* iArg: */ 0 },
95297 #endif
95298 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95299 { /* zName: */ "foreign_keys",
95300 /* ePragTyp: */ PragTyp_FLAG,
95301 /* ePragFlag: */ 0,
95302 /* iArg: */ SQLITE_ForeignKeys },
95303 #endif
95304 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95305 { /* zName: */ "freelist_count",
95306 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95307 /* ePragFlag: */ 0,
95308 /* iArg: */ 0 },
95309 #endif
95310 { /* zName: */ "full_column_names",
95311 /* ePragTyp: */ PragTyp_FLAG,
95312 /* ePragFlag: */ 0,
95313 /* iArg: */ SQLITE_FullColNames },
95314 { /* zName: */ "fullfsync",
95315 /* ePragTyp: */ PragTyp_FLAG,
95316 /* ePragFlag: */ 0,
95317 /* iArg: */ SQLITE_FullFSync },
95318 #if defined(SQLITE_HAS_CODEC)
95319 { /* zName: */ "hexkey",
95320 /* ePragTyp: */ PragTyp_HEXKEY,
95321 /* ePragFlag: */ 0,
95322 /* iArg: */ 0 },
95323 { /* zName: */ "hexrekey",
95324 /* ePragTyp: */ PragTyp_HEXKEY,
95325 /* ePragFlag: */ 0,
95326 /* iArg: */ 0 },
95327 #endif
95328 #if !defined(SQLITE_OMIT_CHECK)
95329 { /* zName: */ "ignore_check_constraints",
95330 /* ePragTyp: */ PragTyp_FLAG,
95331 /* ePragFlag: */ 0,
95332 /* iArg: */ SQLITE_IgnoreChecks },
95333 #endif
95334 #if !defined(SQLITE_OMIT_AUTOVACUUM)
95335 { /* zName: */ "incremental_vacuum",
95336 /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
95337 /* ePragFlag: */ PragFlag_NeedSchema,
95338 /* iArg: */ 0 },
95339 #endif
95340 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95341 { /* zName: */ "index_info",
95342 /* ePragTyp: */ PragTyp_INDEX_INFO,
95343 /* ePragFlag: */ PragFlag_NeedSchema,
95344 /* iArg: */ 0 },
95345 { /* zName: */ "index_list",
95346 /* ePragTyp: */ PragTyp_INDEX_LIST,
95347 /* ePragFlag: */ PragFlag_NeedSchema,
95348 /* iArg: */ 0 },
95349 #endif
95350 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95351 { /* zName: */ "integrity_check",
95352 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95353 /* ePragFlag: */ PragFlag_NeedSchema,
95354 /* iArg: */ 0 },
95355 #endif
95356 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95357 { /* zName: */ "journal_mode",
95358 /* ePragTyp: */ PragTyp_JOURNAL_MODE,
95359 /* ePragFlag: */ PragFlag_NeedSchema,
95360 /* iArg: */ 0 },
95361 { /* zName: */ "journal_size_limit",
95362 /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
95363 /* ePragFlag: */ 0,
95364 /* iArg: */ 0 },
95365 #endif
95366 #if defined(SQLITE_HAS_CODEC)
95367 { /* zName: */ "key",
95368 /* ePragTyp: */ PragTyp_KEY,
95369 /* ePragFlag: */ 0,
95370 /* iArg: */ 0 },
95371 #endif
95372 { /* zName: */ "legacy_file_format",
95373 /* ePragTyp: */ PragTyp_FLAG,
95374 /* ePragFlag: */ 0,
95375 /* iArg: */ SQLITE_LegacyFileFmt },
95376 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
95377 { /* zName: */ "lock_proxy_file",
95378 /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
95379 /* ePragFlag: */ 0,
95380 /* iArg: */ 0 },
95381 #endif
95382 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
95383 { /* zName: */ "lock_status",
95384 /* ePragTyp: */ PragTyp_LOCK_STATUS,
95385 /* ePragFlag: */ 0,
95386 /* iArg: */ 0 },
95387 #endif
95388 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95389 { /* zName: */ "locking_mode",
95390 /* ePragTyp: */ PragTyp_LOCKING_MODE,
95391 /* ePragFlag: */ 0,
95392 /* iArg: */ 0 },
95393 { /* zName: */ "max_page_count",
95394 /* ePragTyp: */ PragTyp_PAGE_COUNT,
95395 /* ePragFlag: */ PragFlag_NeedSchema,
95396 /* iArg: */ 0 },
95397 { /* zName: */ "mmap_size",
95398 /* ePragTyp: */ PragTyp_MMAP_SIZE,
95399 /* ePragFlag: */ 0,
95400 /* iArg: */ 0 },
95401 { /* zName: */ "page_count",
95402 /* ePragTyp: */ PragTyp_PAGE_COUNT,
95403 /* ePragFlag: */ PragFlag_NeedSchema,
95404 /* iArg: */ 0 },
95405 { /* zName: */ "page_size",
95406 /* ePragTyp: */ PragTyp_PAGE_SIZE,
95407 /* ePragFlag: */ 0,
95408 /* iArg: */ 0 },
95409 #endif
95410 #if defined(SQLITE_DEBUG)
95411 { /* zName: */ "parser_trace",
95412 /* ePragTyp: */ PragTyp_PARSER_TRACE,
95413 /* ePragFlag: */ 0,
95414 /* iArg: */ 0 },
95415 #endif
95416 { /* zName: */ "query_only",
95417 /* ePragTyp: */ PragTyp_FLAG,
95418 /* ePragFlag: */ 0,
95419 /* iArg: */ SQLITE_QueryOnly },
95420 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95421 { /* zName: */ "quick_check",
95422 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95423 /* ePragFlag: */ PragFlag_NeedSchema,
95424 /* iArg: */ 0 },
95425 #endif
95426 { /* zName: */ "read_uncommitted",
95427 /* ePragTyp: */ PragTyp_FLAG,
95428 /* ePragFlag: */ 0,
95429 /* iArg: */ SQLITE_ReadUncommitted },
95430 { /* zName: */ "recursive_triggers",
95431 /* ePragTyp: */ PragTyp_FLAG,
95432 /* ePragFlag: */ 0,
95433 /* iArg: */ SQLITE_RecTriggers },
95434 #if defined(SQLITE_HAS_CODEC)
95435 { /* zName: */ "rekey",
95436 /* ePragTyp: */ PragTyp_REKEY,
95437 /* ePragFlag: */ 0,
95438 /* iArg: */ 0 },
95439 #endif
95440 { /* zName: */ "reverse_unordered_selects",
95441 /* ePragTyp: */ PragTyp_FLAG,
95442 /* ePragFlag: */ 0,
95443 /* iArg: */ SQLITE_ReverseOrder },
95444 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95445 { /* zName: */ "schema_version",
95446 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95447 /* ePragFlag: */ 0,
95448 /* iArg: */ 0 },
95449 #endif
95450 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95451 { /* zName: */ "secure_delete",
95452 /* ePragTyp: */ PragTyp_SECURE_DELETE,
95453 /* ePragFlag: */ 0,
95454 /* iArg: */ 0 },
95455 #endif
95456 { /* zName: */ "short_column_names",
95457 /* ePragTyp: */ PragTyp_FLAG,
95458 /* ePragFlag: */ 0,
95459 /* iArg: */ SQLITE_ShortColNames },
95460 { /* zName: */ "shrink_memory",
95461 /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
95462 /* ePragFlag: */ 0,
95463 /* iArg: */ 0 },
95464 { /* zName: */ "soft_heap_limit",
95465 /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
95466 /* ePragFlag: */ 0,
95467 /* iArg: */ 0 },
95468 #if defined(SQLITE_DEBUG)
95469 { /* zName: */ "sql_trace",
95470 /* ePragTyp: */ PragTyp_FLAG,
95471 /* ePragFlag: */ 0,
95472 /* iArg: */ SQLITE_SqlTrace },
95473 #endif
95474 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95475 { /* zName: */ "synchronous",
95476 /* ePragTyp: */ PragTyp_SYNCHRONOUS,
95477 /* ePragFlag: */ PragFlag_NeedSchema,
95478 /* iArg: */ 0 },
95479 #endif
95480 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95481 { /* zName: */ "table_info",
95482 /* ePragTyp: */ PragTyp_TABLE_INFO,
95483 /* ePragFlag: */ PragFlag_NeedSchema,
95484 /* iArg: */ 0 },
95485 #endif
95486 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95487 { /* zName: */ "temp_store",
95488 /* ePragTyp: */ PragTyp_TEMP_STORE,
95489 /* ePragFlag: */ 0,
95490 /* iArg: */ 0 },
95491 { /* zName: */ "temp_store_directory",
95492 /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
95493 /* ePragFlag: */ 0,
95494 /* iArg: */ 0 },
95495 #endif
95496 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95497 { /* zName: */ "user_version",
95498 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95499 /* ePragFlag: */ 0,
95500 /* iArg: */ 0 },
95501 #endif
95502 #if defined(SQLITE_DEBUG)
95503 { /* zName: */ "vdbe_addoptrace",
95504 /* ePragTyp: */ PragTyp_FLAG,
95505 /* ePragFlag: */ 0,
95506 /* iArg: */ SQLITE_VdbeAddopTrace },
95507 { /* zName: */ "vdbe_debug",
95508 /* ePragTyp: */ PragTyp_FLAG,
95509 /* ePragFlag: */ 0,
95510 /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95511 { /* zName: */ "vdbe_listing",
95512 /* ePragTyp: */ PragTyp_FLAG,
95513 /* ePragFlag: */ 0,
95514 /* iArg: */ SQLITE_VdbeListing },
95515 { /* zName: */ "vdbe_trace",
95516 /* ePragTyp: */ PragTyp_FLAG,
95517 /* ePragFlag: */ 0,
95518 /* iArg: */ SQLITE_VdbeTrace },
95519 #endif
95520 #if !defined(SQLITE_OMIT_WAL)
95521 { /* zName: */ "wal_autocheckpoint",
95522 /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
95523 /* ePragFlag: */ 0,
95524 /* iArg: */ 0 },
95525 { /* zName: */ "wal_checkpoint",
95526 /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
95527 /* ePragFlag: */ PragFlag_NeedSchema,
95528 /* iArg: */ 0 },
95529 #endif
95530 { /* zName: */ "writable_schema",
95531 /* ePragTyp: */ PragTyp_FLAG,
95532 /* ePragFlag: */ 0,
95533 /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
95534 };
95535 /* Number of pragmas: 55 on by default, 67 total. */
95536 /* End of the automatically generated pragma table.
95537 ***************************************************************************/
95538
95539 /*
95540 ** Interpret the given string as a safety level. Return 0 for OFF,
@@ -95476,10 +95862,15 @@
95862 }else{
95863 lwr = mid + 1;
95864 }
95865 }
95866 if( lwr>upr ) goto pragma_out;
95867
95868 /* Make sure the database schema is loaded if the pragma requires that */
95869 if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
95870 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95871 }
95872
95873 /* Jump to the appropriate pragma handler */
95874 switch( aPragmaNames[mid].ePragTyp ){
95875
95876 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -95510,11 +95901,10 @@
95901 { OP_Integer, 0, 1, 0}, /* 6 */
95902 { OP_Noop, 0, 0, 0},
95903 { OP_ResultRow, 1, 1, 0},
95904 };
95905 int addr;
 
95906 sqlite3VdbeUsesBtree(v, iDb);
95907 if( !zRight ){
95908 sqlite3VdbeSetNumCols(v, 1);
95909 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
95910 pParse->nMem += 2;
@@ -95606,11 +95996,10 @@
95996 **
95997 ** Return the number of pages in the specified database.
95998 */
95999 case PragTyp_PAGE_COUNT: {
96000 int iReg;
 
96001 sqlite3CodeVerifySchema(pParse, iDb);
96002 iReg = ++pParse->nMem;
96003 if( sqlite3Tolower(zLeft[0])=='p' ){
96004 sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
96005 }else{
@@ -95679,18 +96068,10 @@
96068 */
96069 case PragTyp_JOURNAL_MODE: {
96070 int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
96071 int ii; /* Loop counter */
96072
 
 
 
 
 
 
 
 
96073 sqlite3VdbeSetNumCols(v, 1);
96074 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
96075
96076 if( zRight==0 ){
96077 /* If there is no "=MODE" part of the pragma, do a query for the
@@ -95752,55 +96133,44 @@
96133 */
96134 #ifndef SQLITE_OMIT_AUTOVACUUM
96135 case PragTyp_AUTO_VACUUM: {
96136 Btree *pBt = pDb->pBt;
96137 assert( pBt!=0 );
 
 
 
96138 if( !zRight ){
96139 returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
 
 
 
 
 
 
96140 }else{
96141 int eAuto = getAutoVacuum(zRight);
96142 assert( eAuto>=0 && eAuto<=2 );
96143 db->nextAutovac = (u8)eAuto;
96144 /* Call SetAutoVacuum() to set initialize the internal auto and
96145 ** incr-vacuum flags. This is required in case this connection
96146 ** creates the database file. It is important that it is created
96147 ** as an auto-vacuum capable db.
96148 */
96149 rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
96150 if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
96151 /* When setting the auto_vacuum mode to either "full" or
96152 ** "incremental", write the value of meta[6] in the database
96153 ** file. Before writing to meta[6], check that meta[3] indicates
96154 ** that this really is an auto-vacuum capable database.
96155 */
96156 static const VdbeOpList setMeta6[] = {
96157 { OP_Transaction, 0, 1, 0}, /* 0 */
96158 { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
96159 { OP_If, 1, 0, 0}, /* 2 */
96160 { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
96161 { OP_Integer, 0, 1, 0}, /* 4 */
96162 { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
96163 };
96164 int iAddr;
96165 iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
96166 sqlite3VdbeChangeP1(v, iAddr, iDb);
96167 sqlite3VdbeChangeP1(v, iAddr+1, iDb);
96168 sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
96169 sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
96170 sqlite3VdbeChangeP1(v, iAddr+5, iDb);
96171 sqlite3VdbeUsesBtree(v, iDb);
 
 
96172 }
96173 }
96174 break;
96175 }
96176 #endif
@@ -95811,13 +96181,10 @@
96181 ** Do N steps of incremental vacuuming on a database.
96182 */
96183 #ifndef SQLITE_OMIT_AUTOVACUUM
96184 case PragTyp_INCREMENTAL_VACUUM: {
96185 int iLimit, addr;
 
 
 
96186 if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
96187 iLimit = 0x7fffffff;
96188 }
96189 sqlite3BeginWriteOperation(pParse, 0, iDb);
96190 sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
@@ -95841,11 +96208,10 @@
96208 ** number of pages in the cache. If N is negative, then the
96209 ** number of pages is adjusted so that the cache uses -N kibibytes
96210 ** of memory.
96211 */
96212 case PragTyp_CACHE_SIZE: {
 
96213 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
96214 if( !zRight ){
96215 returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
96216 }else{
96217 int size = sqlite3Atoi(zRight);
@@ -96062,11 +96428,10 @@
96428 ** the local value does not make changes to the disk file and the
96429 ** default value will be restored the next time the database is
96430 ** opened.
96431 */
96432 case PragTyp_SYNCHRONOUS: {
 
96433 if( !zRight ){
96434 returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
96435 }else{
96436 if( !db->autoCommit ){
96437 sqlite3ErrorMsg(pParse,
@@ -96124,11 +96489,10 @@
96489 ** notnull: True if 'NOT NULL' is part of column declaration
96490 ** dflt_value: The default value for the column, if any.
96491 */
96492 case PragTyp_TABLE_INFO: if( zRight ){
96493 Table *pTab;
 
96494 pTab = sqlite3FindTable(db, zRight, zDb);
96495 if( pTab ){
96496 int i, k;
96497 int nHidden = 0;
96498 Column *pCol;
@@ -96174,11 +96538,10 @@
96538 break;
96539
96540 case PragTyp_INDEX_INFO: if( zRight ){
96541 Index *pIdx;
96542 Table *pTab;
 
96543 pIdx = sqlite3FindIndex(db, zRight, zDb);
96544 if( pIdx ){
96545 int i;
96546 pTab = pIdx->pTable;
96547 sqlite3VdbeSetNumCols(v, 3);
@@ -96200,39 +96563,41 @@
96563 break;
96564
96565 case PragTyp_INDEX_LIST: if( zRight ){
96566 Index *pIdx;
96567 Table *pTab;
96568 int i;
96569 pTab = sqlite3FindTable(db, zRight, zDb);
96570 if( pTab ){
96571 v = sqlite3GetVdbe(pParse);
96572 sqlite3VdbeSetNumCols(v, 4);
96573 pParse->nMem = 4;
96574 sqlite3CodeVerifySchema(pParse, iDb);
96575 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96576 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96577 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96578 sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "avgrowsize", SQLITE_STATIC);
96579 sqlite3VdbeAddOp2(v, OP_Integer, 0, 1);
96580 sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
96581 sqlite3VdbeAddOp2(v, OP_Integer, 1, 3);
96582 sqlite3VdbeAddOp2(v, OP_Integer,
96583 (int)sqlite3LogEstToInt(pTab->szTabRow), 4);
96584 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96585 for(pIdx=pTab->pIndex, i=1; pIdx; pIdx=pIdx->pNext, i++){
96586 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96587 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96588 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96589 sqlite3VdbeAddOp2(v, OP_Integer,
96590 (int)sqlite3LogEstToInt(pIdx->szIdxRow), 4);
96591 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96592 }
96593 }
96594 }
96595 break;
96596
96597 case PragTyp_DATABASE_LIST: {
96598 int i;
 
96599 sqlite3VdbeSetNumCols(v, 3);
96600 pParse->nMem = 3;
96601 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96602 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96603 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
@@ -96267,11 +96632,10 @@
96632
96633 #ifndef SQLITE_OMIT_FOREIGN_KEY
96634 case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
96635 FKey *pFK;
96636 Table *pTab;
 
96637 pTab = sqlite3FindTable(db, zRight, zDb);
96638 if( pTab ){
96639 v = sqlite3GetVdbe(pParse);
96640 pFK = pTab->pFKey;
96641 if( pFK ){
@@ -96329,11 +96693,10 @@
96693 int regRow; /* Registers to hold a row from pTab */
96694 int addrTop; /* Top of a loop checking foreign keys */
96695 int addrOk; /* Jump here if the key is OK */
96696 int *aiCols; /* child to parent column mapping */
96697
 
96698 regResult = pParse->nMem+1;
96699 pParse->nMem += 4;
96700 regKey = ++pParse->nMem;
96701 regRow = ++pParse->nMem;
96702 v = sqlite3GetVdbe(pParse);
@@ -96490,11 +96853,10 @@
96853 assert( iDb>=0 );
96854 assert( iDb==0 || pId2->z );
96855 if( pId2->z==0 ) iDb = -1;
96856
96857 /* Initialize the VDBE program */
 
96858 pParse->nMem = 6;
96859 sqlite3VdbeSetNumCols(v, 1);
96860 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
96861
96862 /* Set the maximum error count */
@@ -96814,11 +97176,10 @@
97176 eMode = SQLITE_CHECKPOINT_FULL;
97177 }else if( sqlite3StrICmp(zRight, "restart")==0 ){
97178 eMode = SQLITE_CHECKPOINT_RESTART;
97179 }
97180 }
 
97181 sqlite3VdbeSetNumCols(v, 3);
97182 pParse->nMem = 3;
97183 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
97184 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
97185 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
@@ -96934,16 +97295,16 @@
97295 if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
97296 break;
97297 }
97298 case PragTyp_HEXKEY: {
97299 if( zRight ){
97300 u8 iByte;
97301 int i;
97302 char zKey[40];
97303 for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
97304 iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
97305 if( (i&1)!=0 ) zKey[i/2] = iByte;
 
97306 }
97307 if( (zLeft[3] & 0xf)==0xb ){
97308 sqlite3_key_v2(db, zDb, zKey, i/2);
97309 }else{
97310 sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -98913,10 +99274,13 @@
99274 }
99275
99276 /*
99277 ** Return a pointer to a string containing the 'declaration type' of the
99278 ** expression pExpr. The string may be treated as static by the caller.
99279 **
99280 ** Also try to estimate the size of the returned value and return that
99281 ** result in *pEstWidth.
99282 **
99283 ** The declaration type is the exact datatype definition extracted from the
99284 ** original CREATE TABLE statement if the expression is a column. The
99285 ** declaration type for a ROWID field is INTEGER. Exactly when an expression
99286 ** is considered a column can be complex in the presence of subqueries. The
@@ -98927,25 +99291,40 @@
99291 ** SELECT (SELECT col FROM tbl;
99292 ** SELECT (SELECT col FROM tbl);
99293 ** SELECT abc FROM (SELECT col AS abc FROM tbl);
99294 **
99295 ** The declaration type for any expression other than a column is NULL.
99296 **
99297 ** This routine has either 3 or 6 parameters depending on whether or not
99298 ** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
99299 */
99300 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99301 # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
99302 static const char *columnTypeImpl(
99303 NameContext *pNC,
99304 Expr *pExpr,
99305 const char **pzOrigDb,
99306 const char **pzOrigTab,
99307 const char **pzOrigCol,
99308 u8 *pEstWidth
99309 ){
99310 char const *zOrigDb = 0;
99311 char const *zOrigTab = 0;
99312 char const *zOrigCol = 0;
99313 #else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
99314 # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
99315 static const char *columnTypeImpl(
99316 NameContext *pNC,
99317 Expr *pExpr,
99318 u8 *pEstWidth
 
 
99319 ){
99320 #endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
99321 char const *zType = 0;
 
 
 
99322 int j;
99323 u8 estWidth = 1;
99324
99325 if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
 
99326 switch( pExpr->op ){
99327 case TK_AGG_COLUMN:
99328 case TK_COLUMN: {
99329 /* The expression is a column. Locate the table the column is being
99330 ** extracted from in NameContext.pSrcList. This table may be real
@@ -99002,29 +99381,39 @@
99381 NameContext sNC;
99382 Expr *p = pS->pEList->a[iCol].pExpr;
99383 sNC.pSrcList = pS->pSrc;
99384 sNC.pNext = pNC;
99385 sNC.pParse = pNC->pParse;
99386 zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
99387 }
99388 }else if( ALWAYS(pTab->pSchema) ){
99389 /* A real table */
99390 assert( !pS );
99391 if( iCol<0 ) iCol = pTab->iPKey;
99392 assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
99393 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99394 if( iCol<0 ){
99395 zType = "INTEGER";
99396 zOrigCol = "rowid";
99397 }else{
99398 zType = pTab->aCol[iCol].zType;
99399 zOrigCol = pTab->aCol[iCol].zName;
99400 estWidth = pTab->aCol[iCol].szEst;
99401 }
99402 zOrigTab = pTab->zName;
99403 if( pNC->pParse ){
99404 int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
99405 zOrigDb = pNC->pParse->db->aDb[iDb].zName;
99406 }
99407 #else
99408 if( iCol<0 ){
99409 zType = "INTEGER";
99410 }else{
99411 zType = pTab->aCol[iCol].zType;
99412 estWidth = pTab->aCol[iCol].szEst;
99413 }
99414 #endif
99415 }
99416 break;
99417 }
99418 #ifndef SQLITE_OMIT_SUBQUERY
99419 case TK_SELECT: {
@@ -99037,22 +99426,25 @@
99426 Expr *p = pS->pEList->a[0].pExpr;
99427 assert( ExprHasProperty(pExpr, EP_xIsSelect) );
99428 sNC.pSrcList = pS->pSrc;
99429 sNC.pNext = pNC;
99430 sNC.pParse = pNC->pParse;
99431 zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
99432 break;
99433 }
99434 #endif
99435 }
99436
99437 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99438 if( pzOrigDb ){
99439 assert( pzOrigTab && pzOrigCol );
99440 *pzOrigDb = zOrigDb;
99441 *pzOrigTab = zOrigTab;
99442 *pzOrigCol = zOrigCol;
99443 }
99444 #endif
99445 if( pEstWidth ) *pEstWidth = estWidth;
99446 return zType;
99447 }
99448
99449 /*
99450 ** Generate code that will tell the VDBE the declaration types of columns
@@ -99074,25 +99466,25 @@
99466 const char *zType;
99467 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99468 const char *zOrigDb = 0;
99469 const char *zOrigTab = 0;
99470 const char *zOrigCol = 0;
99471 zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
99472
99473 /* The vdbe must make its own copy of the column-type and other
99474 ** column specific strings, in case the schema is reset before this
99475 ** virtual machine is deleted.
99476 */
99477 sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
99478 sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
99479 sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
99480 #else
99481 zType = columnType(&sNC, p, 0, 0, 0, 0);
99482 #endif
99483 sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
99484 }
99485 #endif /* !defined(SQLITE_OMIT_DECLTYPE) */
99486 }
99487
99488 /*
99489 ** Generate code that will tell the VDBE the names of columns
99490 ** in the result set. This information is used to provide the
@@ -99277,39 +99669,41 @@
99669 ** This routine requires that all identifiers in the SELECT
99670 ** statement be resolved.
99671 */
99672 static void selectAddColumnTypeAndCollation(
99673 Parse *pParse, /* Parsing contexts */
99674 Table *pTab, /* Add column type information to this table */
 
99675 Select *pSelect /* SELECT used to determine types and collations */
99676 ){
99677 sqlite3 *db = pParse->db;
99678 NameContext sNC;
99679 Column *pCol;
99680 CollSeq *pColl;
99681 int i;
99682 Expr *p;
99683 struct ExprList_item *a;
99684 u64 szAll = 0;
99685
99686 assert( pSelect!=0 );
99687 assert( (pSelect->selFlags & SF_Resolved)!=0 );
99688 assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
99689 if( db->mallocFailed ) return;
99690 memset(&sNC, 0, sizeof(sNC));
99691 sNC.pSrcList = pSelect->pSrc;
99692 a = pSelect->pEList->a;
99693 for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
99694 p = a[i].pExpr;
99695 pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
99696 szAll += pCol->szEst;
99697 pCol->affinity = sqlite3ExprAffinity(p);
99698 if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
99699 pColl = sqlite3ExprCollSeq(pParse, p);
99700 if( pColl ){
99701 pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
99702 }
99703 }
99704 pTab->szTabRow = sqlite3LogEst(szAll*4);
99705 }
99706
99707 /*
99708 ** Given a SELECT statement, generate a Table structure that describes
99709 ** the result set of that SELECT.
@@ -99333,13 +99727,13 @@
99727 /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
99728 ** is disabled */
99729 assert( db->lookaside.bEnabled==0 );
99730 pTab->nRef = 1;
99731 pTab->zName = 0;
99732 pTab->nRowEst = 1048576;
99733 selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
99734 selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
99735 pTab->iPKey = -1;
99736 if( db->mallocFailed ){
99737 sqlite3DeleteTable(db, pTab);
99738 return 0;
99739 }
@@ -101247,15 +101641,15 @@
101641 assert( pFrom->pTab==0 );
101642 sqlite3WalkSelect(pWalker, pSel);
101643 pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
101644 if( pTab==0 ) return WRC_Abort;
101645 pTab->nRef = 1;
101646 pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
101647 while( pSel->pPrior ){ pSel = pSel->pPrior; }
101648 selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
101649 pTab->iPKey = -1;
101650 pTab->nRowEst = 1048576;
101651 pTab->tabFlags |= TF_Ephemeral;
101652 #endif
101653 }else{
101654 /* An ordinary table or view name in the FROM clause */
101655 assert( pFrom->pTab==0 );
@@ -101535,11 +101929,11 @@
101929 if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
101930 /* A sub-query in the FROM clause of a SELECT */
101931 Select *pSel = pFrom->pSelect;
101932 assert( pSel );
101933 while( pSel->pPrior ) pSel = pSel->pPrior;
101934 selectAddColumnTypeAndCollation(pParse, pTab, pSel);
101935 }
101936 }
101937 }
101938 return WRC_Continue;
101939 }
@@ -102450,29 +102844,29 @@
102844 int iRoot = pTab->tnum; /* Root page of scanned b-tree */
102845
102846 sqlite3CodeVerifySchema(pParse, iDb);
102847 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102848
102849 /* Search for the index that has the lowest scan cost.
 
 
 
 
 
 
102850 **
102851 ** (2011-04-15) Do not do a full scan of an unordered index.
102852 **
102853 ** (2013-10-03) Do not count the entires in a partial index.
102854 **
102855 ** In practice the KeyInfo structure will not be used. It is only
102856 ** passed to keep OP_OpenRead happy.
102857 */
102858 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
102859 if( pIdx->bUnordered==0
102860 && pIdx->szIdxRow<pTab->szTabRow
102861 && pIdx->pPartIdxWhere==0
102862 && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
102863 ){
102864 pBest = pIdx;
102865 }
102866 }
102867 if( pBest ){
102868 iRoot = pBest->tnum;
102869 pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
102870 }
102871
102872 /* Open a read-only cursor, execute the OP_Count, close the cursor. */
@@ -103046,12 +103440,12 @@
103440 }
103441
103442 /* Ensure the table name matches database name and that the table exists */
103443 if( db->mallocFailed ) goto trigger_cleanup;
103444 assert( pTableName->nSrc==1 );
103445 sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
103446 if( sqlite3FixSrcList(&sFix, pTableName) ){
103447 goto trigger_cleanup;
103448 }
103449 pTab = sqlite3SrcListLookup(pParse, pTableName);
103450 if( !pTab ){
103451 /* The table does not exist. */
@@ -103189,12 +103583,14 @@
103583 pStepList->pTrig = pTrig;
103584 pStepList = pStepList->pNext;
103585 }
103586 nameToken.z = pTrig->zName;
103587 nameToken.n = sqlite3Strlen30(nameToken.z);
103588 sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
103589 if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
103590 || sqlite3FixExpr(&sFix, pTrig->pWhen)
103591 ){
103592 goto triggerfinish_cleanup;
103593 }
103594
103595 /* if we are not initializing,
103596 ** build the sqlite_master entry
@@ -104781,18 +105177,38 @@
105177
105178 return vacuumFinalize(db, pStmt, pzErrMsg);
105179 }
105180
105181 /*
105182 ** The VACUUM command is used to clean up the database,
105183 ** collapse free space, etc. It is modelled after the VACUUM command
105184 ** in PostgreSQL. The VACUUM command works as follows:
105185 **
105186 ** (1) Create a new transient database file
105187 ** (2) Copy all content from the database being vacuumed into
105188 ** the new transient database file
105189 ** (3) Copy content from the transient database back into the
105190 ** original database.
105191 **
105192 ** The transient database requires temporary disk space approximately
105193 ** equal to the size of the original database. The copy operation of
105194 ** step (3) requires additional temporary disk space approximately equal
105195 ** to the size of the original database for the rollback journal.
105196 ** Hence, temporary disk space that is approximately 2x the size of the
105197 ** orginal database is required. Every page of the database is written
105198 ** approximately 3 times: Once for step (2) and twice for step (3).
105199 ** Two writes per page are required in step (3) because the original
105200 ** database content must be written into the rollback journal prior to
105201 ** overwriting the database with the vacuumed content.
105202 **
105203 ** Only 1x temporary space and only 1x writes would be required if
105204 ** the copy of step (3) were replace by deleting the original database
105205 ** and renaming the transient database as the original. But that will
105206 ** not work if other processes are attached to the original database.
105207 ** And a power loss in between deleting the original and renaming the
105208 ** transient would cause the database file to appear to be deleted
105209 ** following reboot.
105210 */
105211 SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
105212 Vdbe *v = sqlite3GetVdbe(pParse);
105213 if( v ){
105214 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
@@ -106206,30 +106622,10 @@
106622 typedef struct WhereLoopBuilder WhereLoopBuilder;
106623 typedef struct WhereScan WhereScan;
106624 typedef struct WhereOrCost WhereOrCost;
106625 typedef struct WhereOrSet WhereOrSet;
106626
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106627 /*
106628 ** This object contains information needed to implement a single nested
106629 ** loop in WHERE clause.
106630 **
106631 ** Contrast this object with WhereLoop. This object describes the
@@ -106290,13 +106686,13 @@
106686 #ifdef SQLITE_DEBUG
106687 char cId; /* Symbolic ID of this loop for debugging use */
106688 #endif
106689 u8 iTab; /* Position in FROM clause of table for this loop */
106690 u8 iSortIdx; /* Sorting index number. 0==None */
106691 LogEst rSetup; /* One-time setup cost (ex: create transient index) */
106692 LogEst rRun; /* Cost of running each loop */
106693 LogEst nOut; /* Estimated number of output rows */
106694 union {
106695 struct { /* Information for internal btree tables */
106696 int nEq; /* Number of equality constraints */
106697 Index *pIndex; /* Index used, or NULL */
106698 } btree;
@@ -106322,12 +106718,12 @@
106718 ** subquery on one operand of an OR operator in the WHERE clause.
106719 ** See WhereOrSet for additional information
106720 */
106721 struct WhereOrCost {
106722 Bitmask prereq; /* Prerequisites */
106723 LogEst rRun; /* Cost of running this subquery */
106724 LogEst nOut; /* Number of outputs for this subquery */
106725 };
106726
106727 /* The WhereOrSet object holds a set of possible WhereOrCosts that
106728 ** correspond to the subquery(s) of OR-clause processing. Only the
106729 ** best N_OR_COST elements are retained.
@@ -106361,12 +106757,12 @@
106757 ** at the end is the choosen query plan.
106758 */
106759 struct WherePath {
106760 Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
106761 Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
106762 LogEst nRow; /* Estimated number of rows generated by this path */
106763 LogEst rCost; /* Total cost of this path */
106764 u8 isOrdered; /* True if this path satisfies ORDER BY */
106765 u8 isOrderedValid; /* True if the isOrdered field is valid */
106766 WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
106767 };
106768
@@ -106428,11 +106824,11 @@
106824 union {
106825 int leftColumn; /* Column number of X in "X <op> <expr>" */
106826 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
106827 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
106828 } u;
106829 LogEst truthProb; /* Probability of truth for this expression */
106830 u16 eOperator; /* A WO_xx value describing <op> */
106831 u8 wtFlags; /* TERM_xxx bit flags. See below */
106832 u8 nChild; /* Number of children that must disable us */
106833 WhereClause *pWC; /* The clause this term is part of */
106834 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -106576,11 +106972,11 @@
106972 SrcList *pTabList; /* List of tables in the join */
106973 ExprList *pOrderBy; /* The ORDER BY clause or NULL */
106974 ExprList *pResultSet; /* Result set. DISTINCT operates on these */
106975 WhereLoop *pLoops; /* List of all WhereLoop objects */
106976 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
106977 LogEst nRowOut; /* Estimated number of output rows */
106978 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
106979 u8 bOBSat; /* ORDER BY satisfied by indices */
106980 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
106981 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
106982 u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -106636,30 +107032,15 @@
107032 #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
107033 #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
107034 #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
107035 #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
107036
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107037 /*
107038 ** Return the estimated number of output rows from a WHERE clause
107039 */
107040 SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
107041 return sqlite3LogEstToInt(pWInfo->nRowOut);
107042 }
107043
107044 /*
107045 ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
107046 ** WHERE clause returns outputs for DISTINCT processing.
@@ -106717,12 +107098,12 @@
107098 ** so that pSet keeps the N_OR_COST best entries seen so far.
107099 */
107100 static int whereOrInsert(
107101 WhereOrSet *pSet, /* The WhereOrSet to be updated */
107102 Bitmask prereq, /* Prerequisites of the new entry */
107103 LogEst rRun, /* Run-cost of the new entry */
107104 LogEst nOut /* Number of outputs for the new entry */
107105 ){
107106 u16 i;
107107 WhereOrCost *p;
107108 for(i=pSet->n, p=pSet->a; i>0; i--, p++){
107109 if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
@@ -106803,13 +107184,10 @@
107184 if( pWC->a!=pWC->aStatic ){
107185 sqlite3DbFree(db, pWC->a);
107186 }
107187 }
107188
 
 
 
107189 /*
107190 ** Add a single new WhereTerm entry to the WhereClause object pWC.
107191 ** The new WhereTerm object is constructed from Expr p and with wtFlags.
107192 ** The index in pWC->a[] of the new WhereTerm is returned on success.
107193 ** 0 is returned if the new WhereTerm could not be added due to a memory
@@ -106848,11 +107226,11 @@
107226 }
107227 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
107228 }
107229 pTerm = &pWC->a[idx = pWC->nTerm++];
107230 if( p && ExprHasProperty(p, EP_Unlikely) ){
107231 pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
107232 }else{
107233 pTerm->truthProb = -1;
107234 }
107235 pTerm->pExpr = sqlite3ExprSkipCollate(p);
107236 pTerm->wtFlags = wtFlags;
@@ -108112,79 +108490,16 @@
108490 }
108491
108492 return 0;
108493 }
108494
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108495
108496 /*
108497 ** Estimate the logarithm of the input value to base 2.
108498 */
108499 static LogEst estLog(LogEst N){
108500 LogEst x = sqlite3LogEst(N);
108501 return x>33 ? x - 33 : 0;
108502 }
108503
108504 /*
108505 ** Two routines for printing the content of an sqlite3_index_info
@@ -108693,11 +109008,11 @@
109008 **
109009 ** ... FROM t1 WHERE a > ? AND a < ? ...
109010 **
109011 ** then nEq is set to 0.
109012 **
109013 ** When this function is called, *pnOut is set to the sqlite3LogEst() of the
109014 ** number of rows that the index scan is expected to visit without
109015 ** considering the range constraints. If nEq is 0, this is the number of
109016 ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
109017 ** to account for the range contraints pLower and pUpper.
109018 **
@@ -108709,19 +109024,19 @@
109024 static int whereRangeScanEst(
109025 Parse *pParse, /* Parsing & code generating context */
109026 WhereLoopBuilder *pBuilder,
109027 WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
109028 WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
109029 WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
109030 ){
109031 int rc = SQLITE_OK;
109032 int nOut = pLoop->nOut;
109033 int nEq = pLoop->u.btree.nEq;
109034 LogEst nNew;
109035
109036 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
109037 Index *p = pLoop->u.btree.pIndex;
 
109038
109039 if( p->nSample>0
109040 && nEq==pBuilder->nRecValid
109041 && nEq<p->nSampleCol
109042 && OptimizationEnabled(pParse->db, SQLITE_Stat3)
@@ -108798,18 +109113,18 @@
109113 }
109114
109115 pBuilder->pRec = pRec;
109116 if( rc==SQLITE_OK ){
109117 if( iUpper>iLower ){
109118 nNew = sqlite3LogEst(iUpper - iLower);
109119 }else{
109120 nNew = 10; assert( 10==sqlite3LogEst(2) );
109121 }
109122 if( nNew<nOut ){
109123 nOut = nNew;
109124 }
109125 pLoop->nOut = (LogEst)nOut;
109126 WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
109127 (u32)iLower, (u32)iUpper, nOut));
109128 return SQLITE_OK;
109129 }
109130 }
@@ -108820,20 +109135,20 @@
109135 assert( pLower || pUpper );
109136 /* TUNING: Each inequality constraint reduces the search space 4-fold.
109137 ** A BETWEEN operator, therefore, reduces the search space 16-fold */
109138 nNew = nOut;
109139 if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
109140 nNew -= 20; assert( 20==sqlite3LogEst(4) );
109141 nOut--;
109142 }
109143 if( pUpper ){
109144 nNew -= 20; assert( 20==sqlite3LogEst(4) );
109145 nOut--;
109146 }
109147 if( nNew<10 ) nNew = 10;
109148 if( nNew<nOut ) nOut = nNew;
109149 pLoop->nOut = (LogEst)nOut;
109150 return rc;
109151 }
109152
109153 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
109154 /*
@@ -110473,11 +110788,11 @@
110788 */
110789 static int whereLoopAddBtreeIndex(
110790 WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
110791 struct SrcList_item *pSrc, /* FROM clause term being analyzed */
110792 Index *pProbe, /* An index on pSrc */
110793 LogEst nInMul /* log(Number of iterations due to IN) */
110794 ){
110795 WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
110796 Parse *pParse = pWInfo->pParse; /* Parsing context */
110797 sqlite3 *db = pParse->db; /* Database connection malloc context */
110798 WhereLoop *pNew; /* Template WhereLoop under construction */
@@ -110486,15 +110801,15 @@
110801 WhereScan scan; /* Iterator for WHERE terms */
110802 Bitmask saved_prereq; /* Original value of pNew->prereq */
110803 u16 saved_nLTerm; /* Original value of pNew->nLTerm */
110804 int saved_nEq; /* Original value of pNew->u.btree.nEq */
110805 u32 saved_wsFlags; /* Original value of pNew->wsFlags */
110806 LogEst saved_nOut; /* Original value of pNew->nOut */
110807 int iCol; /* Index of the column in the table */
110808 int rc = SQLITE_OK; /* Return code */
110809 LogEst nRowEst; /* Estimated index selectivity */
110810 LogEst rLogSize; /* Logarithm of table size */
110811 WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
110812
110813 pNew = pBuilder->pNew;
110814 if( db->mallocFailed ) return SQLITE_NOMEM;
110815
@@ -110510,11 +110825,11 @@
110825 if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
110826
110827 assert( pNew->u.btree.nEq<=pProbe->nColumn );
110828 if( pNew->u.btree.nEq < pProbe->nColumn ){
110829 iCol = pProbe->aiColumn[pNew->u.btree.nEq];
110830 nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110831 if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
110832 }else{
110833 iCol = -1;
110834 nRowEst = 0;
110835 }
@@ -110524,11 +110839,11 @@
110839 saved_nLTerm = pNew->nLTerm;
110840 saved_wsFlags = pNew->wsFlags;
110841 saved_prereq = pNew->prereq;
110842 saved_nOut = pNew->nOut;
110843 pNew->rSetup = 0;
110844 rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
110845 for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
110846 int nIn = 0;
110847 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110848 int nRecValid = pBuilder->nRecValid;
110849 #endif
@@ -110551,14 +110866,14 @@
110866 if( pTerm->eOperator & WO_IN ){
110867 Expr *pExpr = pTerm->pExpr;
110868 pNew->wsFlags |= WHERE_COLUMN_IN;
110869 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
110870 /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
110871 nIn = 46; assert( 46==sqlite3LogEst(25) );
110872 }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
110873 /* "x IN (value, value, ...)" */
110874 nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
110875 }
110876 pNew->rRun += nIn;
110877 pNew->u.btree.nEq++;
110878 pNew->nOut = nRowEst + nInMul + nIn;
110879 }else if( pTerm->eOperator & (WO_EQ) ){
@@ -110576,11 +110891,11 @@
110891 pNew->nOut = nRowEst + nInMul;
110892 }else if( pTerm->eOperator & (WO_ISNULL) ){
110893 pNew->wsFlags |= WHERE_COLUMN_NULL;
110894 pNew->u.btree.nEq++;
110895 /* TUNING: IS NULL selects 2 rows */
110896 nIn = 10; assert( 10==sqlite3LogEst(2) );
110897 pNew->nOut = nRowEst + nInMul + nIn;
110898 }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
110899 testcase( pTerm->eOperator & WO_GT );
110900 testcase( pTerm->eOperator & WO_GE );
110901 pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
@@ -110596,11 +110911,11 @@
110911 pNew->aLTerm[pNew->nLTerm-2] : 0;
110912 }
110913 if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
110914 /* Adjust nOut and rRun for STAT3 range values */
110915 assert( pNew->nOut==saved_nOut );
110916 whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
110917 }
110918 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110919 if( nInMul==0
110920 && pProbe->nSample
110921 && pNew->u.btree.nEq<=pProbe->nSampleCol
@@ -110616,22 +110931,22 @@
110931 && !ExprHasProperty(pExpr, EP_xIsSelect) ){
110932 rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
110933 }
110934 assert( nOut==0 || rc==SQLITE_OK );
110935 if( nOut ){
110936 nOut = sqlite3LogEst(nOut);
110937 pNew->nOut = MIN(nOut, saved_nOut);
110938 }
110939 }
110940 #endif
110941 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
110942 /* Each row involves a step of the index, then a binary search of
110943 ** the main table */
110944 pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
110945 }
110946 /* Step cost for each output row */
110947 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
110948 whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
110949 rc = whereLoopInsert(pBuilder, pNew);
110950 if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
110951 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
110952 ){
@@ -110727,18 +111042,20 @@
111042 struct SrcList_item *pSrc; /* The FROM clause btree term to add */
111043 WhereLoop *pNew; /* Template WhereLoop object */
111044 int rc = SQLITE_OK; /* Return code */
111045 int iSortIdx = 1; /* Index number */
111046 int b; /* A boolean value */
111047 LogEst rSize; /* number of rows in the table */
111048 LogEst rLogSize; /* Logarithm of the number of rows in the table */
111049 WhereClause *pWC; /* The parsed WHERE clause */
111050 Table *pTab; /* Table being queried */
111051
111052 pNew = pBuilder->pNew;
111053 pWInfo = pBuilder->pWInfo;
111054 pTabList = pWInfo->pTabList;
111055 pSrc = pTabList->a + pNew->iTab;
111056 pTab = pSrc->pTab;
111057 pWC = pBuilder->pWC;
111058 assert( !IsVirtual(pSrc->pTab) );
111059
111060 if( pSrc->pIndex ){
111061 /* An INDEXED BY clause specifies a particular index to use */
@@ -110752,22 +111069,22 @@
111069 memset(&sPk, 0, sizeof(Index));
111070 sPk.nColumn = 1;
111071 sPk.aiColumn = &aiColumnPk;
111072 sPk.aiRowEst = aiRowEstPk;
111073 sPk.onError = OE_Replace;
111074 sPk.pTable = pTab;
111075 aiRowEstPk[0] = pTab->nRowEst;
111076 aiRowEstPk[1] = 1;
111077 pFirst = pSrc->pTab->pIndex;
111078 if( pSrc->notIndexed==0 ){
111079 /* The real indices of the table are only considered if the
111080 ** NOT INDEXED qualifier is omitted from the FROM clause */
111081 sPk.pNext = pFirst;
111082 }
111083 pProbe = &sPk;
111084 }
111085 rSize = sqlite3LogEst(pTab->nRowEst);
111086 rLogSize = estLog(rSize);
111087
111088 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
111089 /* Automatic indexes */
111090 if( !pBuilder->pOrSet
@@ -110788,17 +111105,17 @@
111105 pNew->nLTerm = 1;
111106 pNew->aLTerm[0] = pTerm;
111107 /* TUNING: One-time cost for computing the automatic index is
111108 ** approximately 7*N*log2(N) where N is the number of rows in
111109 ** the table being indexed. */
111110 pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
111111 /* TUNING: Each index lookup yields 20 rows in the table. This
111112 ** is more than the usual guess of 10 rows, since we have no way
111113 ** of knowning how selective the index will ultimately be. It would
111114 ** not be unreasonable to make this value much larger. */
111115 pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
111116 pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
111117 pNew->wsFlags = WHERE_AUTO_INDEX;
111118 pNew->prereq = mExtra | pTerm->prereqRight;
111119 rc = whereLoopInsert(pBuilder, pNew);
111120 }
111121 }
@@ -110828,14 +111145,12 @@
111145
111146 /* Full table scan */
111147 pNew->iSortIdx = b ? iSortIdx : 0;
111148 /* TUNING: Cost of full table scan is 3*(N + log2(N)).
111149 ** + The extra 3 factor is to encourage the use of indexed lookups
111150 ** over full scans. FIXME */
111151 pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
 
 
111152 whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
111153 rc = whereLoopInsert(pBuilder, pNew);
111154 pNew->nOut = rSize;
111155 if( rc ) break;
111156 }else{
@@ -110844,26 +111159,25 @@
111159
111160 /* Full scan via index */
111161 if( b
111162 || ( m==0
111163 && pProbe->bUnordered==0
111164 && pProbe->szIdxRow<pTab->szTabRow
111165 && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
111166 && sqlite3GlobalConfig.bUseCis
111167 && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
111168 )
111169 ){
111170 pNew->iSortIdx = b ? iSortIdx : 0;
111171 if( m==0 ){
111172 /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
111173 ** + The extra factor K of between 1.1 and 3.0 that depends
111174 ** on the relative sizes of the table and the index. K
111175 ** is smaller for smaller indices, thus favoring them.
111176 */
111177 pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
111178 (15*pProbe->szIdxRow)/pTab->szTabRow;
 
 
111179 }else{
111180 assert( b!=0 );
111181 /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
111182 ** which we will simplify to just N*log2(N) */
111183 pNew->rRun = rSize + rLogSize;
@@ -111037,13 +111351,13 @@
111351 pIdxInfo->needToFreeIdxStr = 0;
111352 pNew->u.vtab.idxStr = pIdxInfo->idxStr;
111353 pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
111354 && pIdxInfo->orderByConsumed);
111355 pNew->rSetup = 0;
111356 pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
111357 /* TUNING: Every virtual table query returns 25 rows */
111358 pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
111359 whereLoopInsert(pBuilder, pNew);
111360 if( pNew->u.vtab.needFree ){
111361 sqlite3_free(pNew->u.vtab.idxStr);
111362 pNew->u.vtab.needFree = 0;
111363 }
@@ -111076,10 +111390,12 @@
111390 pWC = pBuilder->pWC;
111391 if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
111392 pWCEnd = pWC->a + pWC->nTerm;
111393 pNew = pBuilder->pNew;
111394 memset(&sSum, 0, sizeof(sSum));
111395 pItem = pWInfo->pTabList->a + pNew->iTab;
111396 iCur = pItem->iCursor;
111397
111398 for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
111399 if( (pTerm->eOperator & WO_OR)!=0
111400 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
111401 ){
@@ -111087,12 +111403,10 @@
111403 WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
111404 WhereTerm *pOrTerm;
111405 int once = 1;
111406 int i, j;
111407
 
 
111408 sSubBuild = *pBuilder;
111409 sSubBuild.pOrderBy = 0;
111410 sSubBuild.pOrSet = &sCur;
111411
111412 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
@@ -111129,12 +111443,12 @@
111443 whereOrMove(&sPrev, &sSum);
111444 sSum.n = 0;
111445 for(i=0; i<sPrev.n; i++){
111446 for(j=0; j<sCur.n; j++){
111447 whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
111448 sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111449 sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111450 }
111451 }
111452 }
111453 }
111454 pNew->nLTerm = 1;
@@ -111468,23 +111782,23 @@
111782 ** costs if nRowEst==0.
111783 **
111784 ** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
111785 ** error occurs.
111786 */
111787 static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
111788 int mxChoice; /* Maximum number of simultaneous paths tracked */
111789 int nLoop; /* Number of terms in the join */
111790 Parse *pParse; /* Parsing context */
111791 sqlite3 *db; /* The database connection */
111792 int iLoop; /* Loop counter over the terms of the join */
111793 int ii, jj; /* Loop counters */
111794 int mxI = 0; /* Index of next entry to replace */
111795 LogEst rCost; /* Cost of a path */
111796 LogEst nOut; /* Number of outputs */
111797 LogEst mxCost = 0; /* Maximum cost of a set of paths */
111798 LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
111799 LogEst rSortCost; /* Cost to do a sort */
111800 int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
111801 WherePath *aFrom; /* All nFrom paths at the previous level */
111802 WherePath *aTo; /* The nTo best paths at the current level */
111803 WherePath *pFrom; /* An element of aFrom[] that we are working on */
111804 WherePath *pTo; /* An element of aTo[] that we are working on */
@@ -111517,21 +111831,23 @@
111831 /* Seed the search with a single WherePath containing zero WhereLoops.
111832 **
111833 ** TUNING: Do not let the number of iterations go above 25. If the cost
111834 ** of computing an automatic index is not paid back within the first 25
111835 ** rows, then do not use the automatic index. */
111836 aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
111837 nFrom = 1;
111838
111839 /* Precompute the cost of sorting the final result set, if the caller
111840 ** to sqlite3WhereBegin() was concerned about sorting */
111841 rSortCost = 0;
111842 if( pWInfo->pOrderBy==0 || nRowEst==0 ){
111843 aFrom[0].isOrderedValid = 1;
111844 }else{
111845 /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
111846 ** number of output rows. The 48 is the expected size of a row to sort.
111847 ** FIXME: compute a better estimate of the 48 multiplier based on the
111848 ** result set expressions. */
111849 rSortCost = nRowEst + estLog(nRowEst);
111850 WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
111851 }
111852
111853 /* Compute successively longer WherePaths using the previous generation
@@ -111547,12 +111863,12 @@
111863 u8 isOrdered = pFrom->isOrdered;
111864 if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
111865 if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
111866 /* At this point, pWLoop is a candidate to be the next loop.
111867 ** Compute its cost */
111868 rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111869 rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
111870 nOut = pFrom->nRow + pWLoop->nOut;
111871 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
111872 if( !isOrderedValid ){
111873 switch( wherePathSatisfiesOrderBy(pWInfo,
111874 pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
@@ -111562,11 +111878,11 @@
111878 isOrderedValid = 1;
111879 break;
111880 case 0: /* No. pFrom+pWLoop will require a separate sort */
111881 isOrdered = 0;
111882 isOrderedValid = 1;
111883 rCost = sqlite3LogEstAdd(rCost, rSortCost);
111884 break;
111885 default: /* Cannot tell yet. Try again on the next iteration */
111886 break;
111887 }
111888 }else{
@@ -111769,11 +112085,11 @@
112085 pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
112086 pLoop->aLTerm[0] = pTerm;
112087 pLoop->nLTerm = 1;
112088 pLoop->u.btree.nEq = 1;
112089 /* TUNING: Cost of a rowid lookup is 10 */
112090 pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
112091 }else{
112092 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
112093 assert( pLoop->aLTermSpace==pLoop->aLTerm );
112094 assert( ArraySize(pLoop->aLTermSpace)==4 );
112095 if( pIdx->onError==OE_None
@@ -111792,16 +112108,16 @@
112108 }
112109 pLoop->nLTerm = j;
112110 pLoop->u.btree.nEq = j;
112111 pLoop->u.btree.pIndex = pIdx;
112112 /* TUNING: Cost of a unique index lookup is 15 */
112113 pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
112114 break;
112115 }
112116 }
112117 if( pLoop->wsFlags ){
112118 pLoop->nOut = (LogEst)1;
112119 pWInfo->a[0].pWLoop = pLoop;
112120 pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
112121 pWInfo->a[0].iTabCur = iCur;
112122 pWInfo->nRowOut = 1;
112123 if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
@@ -112165,11 +112481,11 @@
112481 WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
112482 pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
112483
112484 /* If the caller is an UPDATE or DELETE statement that is requesting
112485 ** to use a one-pass algorithm, determine if this is appropriate.
112486 ** The one-pass algorithm only works if the WHERE clause constrains
112487 ** the statement to update a single row.
112488 */
112489 assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
112490 if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
112491 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
@@ -121583,10 +121899,16 @@
121899 ** verifying the operation of the SQLite core.
121900 */
121901 int inTransaction; /* True after xBegin but before xCommit/xRollback */
121902 int mxSavepoint; /* Largest valid xSavepoint integer */
121903 #endif
121904
121905 #ifdef SQLITE_TEST
121906 /* True to disable the incremental doclist optimization. This is controled
121907 ** by special insert command 'test-no-incr-doclist'. */
121908 int bNoIncrDoclist;
121909 #endif
121910 };
121911
121912 /*
121913 ** When the core wants to read from the virtual table, it creates a
121914 ** virtual table cursor (an instance of the following structure) using
@@ -121608,11 +121930,12 @@
121930 int nDoclist; /* Size of buffer at aDoclist */
121931 u8 bDesc; /* True to sort in descending order */
121932 int eEvalmode; /* An FTS3_EVAL_XX constant */
121933 int nRowAvg; /* Average size of database rows, in pages */
121934 sqlite3_int64 nDoc; /* Documents in table */
121935 i64 iMinDocid; /* Minimum docid to return */
121936 i64 iMaxDocid; /* Maximum docid to return */
121937 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
121938 u32 *aMatchinfo; /* Information about most recent match */
121939 int nMatchinfo; /* Number of elements in aMatchinfo[] */
121940 char *zMatchinfo; /* Matchinfo specification */
121941 };
@@ -121638,10 +121961,19 @@
121961 */
121962 #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
121963 #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
121964 #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
121965
121966 /*
121967 ** The lower 16-bits of the sqlite3_index_info.idxNum value set by
121968 ** the xBestIndex() method contains the Fts3Cursor.eSearch value described
121969 ** above. The upper 16-bits contain a combination of the following
121970 ** bits, used to describe extra constraints on full-text searches.
121971 */
121972 #define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
121973 #define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
121974 #define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
121975
121976 struct Fts3Doclist {
121977 char *aAll; /* Array containing doclist (or NULL) */
121978 int nAll; /* Size of a[] in bytes */
121979 char *pNextDocid; /* Pointer to next docid */
@@ -123058,27 +123390,31 @@
123390 */
123391 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
123392 Fts3Table *p = (Fts3Table *)pVTab;
123393 int i; /* Iterator variable */
123394 int iCons = -1; /* Index of constraint to use */
123395
123396 int iLangidCons = -1; /* Index of langid=x constraint, if present */
123397 int iDocidGe = -1; /* Index of docid>=x constraint, if present */
123398 int iDocidLe = -1; /* Index of docid<=x constraint, if present */
123399 int iIdx;
123400
123401 /* By default use a full table scan. This is an expensive option,
123402 ** so search through the constraints to see if a more efficient
123403 ** strategy is possible.
123404 */
123405 pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
123406 pInfo->estimatedCost = 5000000;
123407 for(i=0; i<pInfo->nConstraint; i++){
123408 int bDocid; /* True if this constraint is on docid */
123409 struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
123410 if( pCons->usable==0 ) continue;
123411
123412 bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
123413
123414 /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
123415 if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
 
 
 
123416 pInfo->idxNum = FTS3_DOCID_SEARCH;
123417 pInfo->estimatedCost = 1.0;
123418 iCons = i;
123419 }
123420
@@ -123103,18 +123439,42 @@
123439 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123440 && pCons->iColumn==p->nColumn + 2
123441 ){
123442 iLangidCons = i;
123443 }
123444
123445 if( bDocid ){
123446 switch( pCons->op ){
123447 case SQLITE_INDEX_CONSTRAINT_GE:
123448 case SQLITE_INDEX_CONSTRAINT_GT:
123449 iDocidGe = i;
123450 break;
123451
123452 case SQLITE_INDEX_CONSTRAINT_LE:
123453 case SQLITE_INDEX_CONSTRAINT_LT:
123454 iDocidLe = i;
123455 break;
123456 }
123457 }
123458 }
123459
123460 iIdx = 1;
123461 if( iCons>=0 ){
123462 pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
123463 pInfo->aConstraintUsage[iCons].omit = 1;
123464 }
123465 if( iLangidCons>=0 ){
123466 pInfo->idxNum |= FTS3_HAVE_LANGID;
123467 pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
123468 }
123469 if( iDocidGe>=0 ){
123470 pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
123471 pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
123472 }
123473 if( iDocidLe>=0 ){
123474 pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
123475 pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
123476 }
123477
123478 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
123479 ** docid) order. Both ascending and descending are possible.
123480 */
@@ -124556,10 +124916,37 @@
124916 rc = fts3EvalNext((Fts3Cursor *)pCursor);
124917 }
124918 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
124919 return rc;
124920 }
124921
124922 /*
124923 ** The following are copied from sqliteInt.h.
124924 **
124925 ** Constants for the largest and smallest possible 64-bit signed integers.
124926 ** These macros are designed to work correctly on both 32-bit and 64-bit
124927 ** compilers.
124928 */
124929 #ifndef SQLITE_AMALGAMATION
124930 # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
124931 # define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
124932 #endif
124933
124934 /*
124935 ** If the numeric type of argument pVal is "integer", then return it
124936 ** converted to a 64-bit signed integer. Otherwise, return a copy of
124937 ** the second parameter, iDefault.
124938 */
124939 static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
124940 if( pVal ){
124941 int eType = sqlite3_value_numeric_type(pVal);
124942 if( eType==SQLITE_INTEGER ){
124943 return sqlite3_value_int64(pVal);
124944 }
124945 }
124946 return iDefault;
124947 }
124948
124949 /*
124950 ** This is the xFilter interface for the virtual table. See
124951 ** the virtual table xFilter method documentation for additional
124952 ** information.
@@ -124582,44 +124969,62 @@
124969 int nVal, /* Number of elements in apVal */
124970 sqlite3_value **apVal /* Arguments for the indexing scheme */
124971 ){
124972 int rc;
124973 char *zSql; /* SQL statement used to access %_content */
124974 int eSearch;
124975 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
124976 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
124977
124978 sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
124979 sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
124980 sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
124981 sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
124982 int iIdx;
124983
124984 UNUSED_PARAMETER(idxStr);
124985 UNUSED_PARAMETER(nVal);
124986
124987 eSearch = (idxNum & 0x0000FFFF);
124988 assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
 
124989 assert( p->pSegments==0 );
124990
124991 /* Collect arguments into local variables */
124992 iIdx = 0;
124993 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
124994 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
124995 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
124996 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
124997 assert( iIdx==nVal );
124998
124999 /* In case the cursor has been used before, clear it now. */
125000 sqlite3_finalize(pCsr->pStmt);
125001 sqlite3_free(pCsr->aDoclist);
125002 sqlite3Fts3ExprFree(pCsr->pExpr);
125003 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
125004
125005 /* Set the lower and upper bounds on docids to return */
125006 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
125007 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
125008
125009 if( idxStr ){
125010 pCsr->bDesc = (idxStr[0]=='D');
125011 }else{
125012 pCsr->bDesc = p->bDescIdx;
125013 }
125014 pCsr->eSearch = (i16)eSearch;
125015
125016 if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
125017 int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
125018 const char *zQuery = (const char *)sqlite3_value_text(pCons);
125019
125020 if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
125021 return SQLITE_NOMEM;
125022 }
125023
125024 pCsr->iLangid = 0;
125025 if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
125026
125027 assert( p->base.zErrMsg==0 );
125028 rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
125029 p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
125030 &p->base.zErrMsg
@@ -124638,11 +125043,11 @@
125043 /* Compile a SELECT statement for this cursor. For a full-table-scan, the
125044 ** statement loops through all rows of the %_content table. For a
125045 ** full-text query or docid lookup, the statement retrieves a single
125046 ** row by docid.
125047 */
125048 if( eSearch==FTS3_FULLSCAN_SEARCH ){
125049 zSql = sqlite3_mprintf(
125050 "SELECT %s ORDER BY rowid %s",
125051 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
125052 );
125053 if( zSql ){
@@ -124649,14 +125054,14 @@
125054 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
125055 sqlite3_free(zSql);
125056 }else{
125057 rc = SQLITE_NOMEM;
125058 }
125059 }else if( eSearch==FTS3_DOCID_SEARCH ){
125060 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
125061 if( rc==SQLITE_OK ){
125062 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
125063 }
125064 }
125065 if( rc!=SQLITE_OK ) return rc;
125066
125067 return fts3NextMethod(pCursor);
@@ -125543,10 +125948,16 @@
125948 }
125949
125950 return SQLITE_OK;
125951 }
125952
125953 /*
125954 ** Maximum number of tokens a phrase may have to be considered for the
125955 ** incremental doclists strategy.
125956 */
125957 #define MAX_INCR_PHRASE_TOKENS 4
125958
125959 /*
125960 ** This function is called for each Fts3Phrase in a full-text query
125961 ** expression to initialize the mechanism for returning rows. Once this
125962 ** function has been called successfully on an Fts3Phrase, it may be
125963 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -125556,27 +125967,47 @@
125967 ** memory within this call.
125968 **
125969 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
125970 */
125971 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
 
 
125972 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125973 int rc = SQLITE_OK; /* Error code */
125974 int i;
125975
125976 /* Determine if doclists may be loaded from disk incrementally. This is
125977 ** possible if the bOptOk argument is true, the FTS doclists will be
125978 ** scanned in forward order, and the phrase consists of
125979 ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
125980 ** tokens or prefix tokens that cannot use a prefix-index. */
125981 int bHaveIncr = 0;
125982 int bIncrOk = (bOptOk
125983 && pCsr->bDesc==pTab->bDescIdx
125984 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
125985 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
125986 #ifdef SQLITE_TEST
125987 && pTab->bNoIncrDoclist==0
125988 #endif
125989 );
125990 for(i=0; bIncrOk==1 && i<p->nToken; i++){
125991 Fts3PhraseToken *pToken = &p->aToken[i];
125992 if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
125993 bIncrOk = 0;
125994 }
125995 if( pToken->pSegcsr ) bHaveIncr = 1;
125996 }
125997
125998 if( bIncrOk && bHaveIncr ){
125999 /* Use the incremental approach. */
126000 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
126001 for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
126002 Fts3PhraseToken *pToken = &p->aToken[i];
126003 Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
126004 if( pSegcsr ){
126005 rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
126006 }
126007 }
126008 p->bIncr = 1;
 
126009 }else{
126010 /* Load the full doclist for the phrase into memory. */
126011 rc = fts3EvalPhraseLoad(pCsr, p);
126012 p->bIncr = 0;
126013 }
@@ -125680,10 +126111,220 @@
126111 }
126112 }
126113
126114 *ppIter = p;
126115 }
126116
126117 /*
126118 ** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
126119 ** to true if EOF is reached.
126120 */
126121 static void fts3EvalDlPhraseNext(
126122 Fts3Table *pTab,
126123 Fts3Doclist *pDL,
126124 u8 *pbEof
126125 ){
126126 char *pIter; /* Used to iterate through aAll */
126127 char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
126128
126129 if( pDL->pNextDocid ){
126130 pIter = pDL->pNextDocid;
126131 }else{
126132 pIter = pDL->aAll;
126133 }
126134
126135 if( pIter>=pEnd ){
126136 /* We have already reached the end of this doclist. EOF. */
126137 *pbEof = 1;
126138 }else{
126139 sqlite3_int64 iDelta;
126140 pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
126141 if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
126142 pDL->iDocid += iDelta;
126143 }else{
126144 pDL->iDocid -= iDelta;
126145 }
126146 pDL->pList = pIter;
126147 fts3PoslistCopy(0, &pIter);
126148 pDL->nList = (int)(pIter - pDL->pList);
126149
126150 /* pIter now points just past the 0x00 that terminates the position-
126151 ** list for document pDL->iDocid. However, if this position-list was
126152 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
126153 ** point to the start of the next docid value. The following line deals
126154 ** with this case by advancing pIter past the zero-padding added by
126155 ** fts3EvalNearTrim(). */
126156 while( pIter<pEnd && *pIter==0 ) pIter++;
126157
126158 pDL->pNextDocid = pIter;
126159 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
126160 *pbEof = 0;
126161 }
126162 }
126163
126164 /*
126165 ** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
126166 */
126167 typedef struct TokenDoclist TokenDoclist;
126168 struct TokenDoclist {
126169 int bIgnore;
126170 sqlite3_int64 iDocid;
126171 char *pList;
126172 int nList;
126173 };
126174
126175 /*
126176 ** Token pToken is an incrementally loaded token that is part of a
126177 ** multi-token phrase. Advance it to the next matching document in the
126178 ** database and populate output variable *p with the details of the new
126179 ** entry. Or, if the iterator has reached EOF, set *pbEof to true.
126180 **
126181 ** If an error occurs, return an SQLite error code. Otherwise, return
126182 ** SQLITE_OK.
126183 */
126184 static int incrPhraseTokenNext(
126185 Fts3Table *pTab, /* Virtual table handle */
126186 Fts3Phrase *pPhrase, /* Phrase to advance token of */
126187 int iToken, /* Specific token to advance */
126188 TokenDoclist *p, /* OUT: Docid and doclist for new entry */
126189 u8 *pbEof /* OUT: True if iterator is at EOF */
126190 ){
126191 int rc = SQLITE_OK;
126192
126193 if( pPhrase->iDoclistToken==iToken ){
126194 assert( p->bIgnore==0 );
126195 assert( pPhrase->aToken[iToken].pSegcsr==0 );
126196 fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
126197 p->pList = pPhrase->doclist.pList;
126198 p->nList = pPhrase->doclist.nList;
126199 p->iDocid = pPhrase->doclist.iDocid;
126200 }else{
126201 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
126202 assert( pToken->pDeferred==0 );
126203 assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
126204 if( pToken->pSegcsr ){
126205 assert( p->bIgnore==0 );
126206 rc = sqlite3Fts3MsrIncrNext(
126207 pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
126208 );
126209 if( p->pList==0 ) *pbEof = 1;
126210 }else{
126211 p->bIgnore = 1;
126212 }
126213 }
126214
126215 return rc;
126216 }
126217
126218
126219 /*
126220 ** The phrase iterator passed as the second argument:
126221 **
126222 ** * features at least one token that uses an incremental doclist, and
126223 **
126224 ** * does not contain any deferred tokens.
126225 **
126226 ** Advance it to the next matching documnent in the database and populate
126227 ** the Fts3Doclist.pList and nList fields.
126228 **
126229 ** If there is no "next" entry and no error occurs, then *pbEof is set to
126230 ** 1 before returning. Otherwise, if no error occurs and the iterator is
126231 ** successfully advanced, *pbEof is set to 0.
126232 **
126233 ** If an error occurs, return an SQLite error code. Otherwise, return
126234 ** SQLITE_OK.
126235 */
126236 static int fts3EvalIncrPhraseNext(
126237 Fts3Cursor *pCsr, /* FTS Cursor handle */
126238 Fts3Phrase *p, /* Phrase object to advance to next docid */
126239 u8 *pbEof /* OUT: Set to 1 if EOF */
126240 ){
126241 int rc = SQLITE_OK;
126242 Fts3Doclist *pDL = &p->doclist;
126243 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126244 u8 bEof = 0;
126245
126246 /* This is only called if it is guaranteed that the phrase has at least
126247 ** one incremental token. In which case the bIncr flag is set. */
126248 assert( p->bIncr==1 );
126249
126250 if( p->nToken==1 && p->bIncr ){
126251 rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
126252 &pDL->iDocid, &pDL->pList, &pDL->nList
126253 );
126254 if( pDL->pList==0 ) bEof = 1;
126255 }else{
126256 int bDescDoclist = pCsr->bDesc;
126257 struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
126258
126259 memset(a, 0, sizeof(a));
126260 assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
126261 assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
126262
126263 while( bEof==0 ){
126264 int bMaxSet = 0;
126265 sqlite3_int64 iMax; /* Largest docid for all iterators */
126266 int i; /* Used to iterate through tokens */
126267
126268 /* Advance the iterator for each token in the phrase once. */
126269 for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
126270 rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126271 if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
126272 iMax = a[i].iDocid;
126273 bMaxSet = 1;
126274 }
126275 }
126276 assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
126277 assert( rc!=SQLITE_OK || bMaxSet );
126278
126279 /* Keep advancing iterators until they all point to the same document */
126280 for(i=0; i<p->nToken; i++){
126281 while( rc==SQLITE_OK && bEof==0
126282 && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
126283 ){
126284 rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126285 if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
126286 iMax = a[i].iDocid;
126287 i = 0;
126288 }
126289 }
126290 }
126291
126292 /* Check if the current entries really are a phrase match */
126293 if( bEof==0 ){
126294 int nList = 0;
126295 int nByte = a[p->nToken-1].nList;
126296 char *aDoclist = sqlite3_malloc(nByte+1);
126297 if( !aDoclist ) return SQLITE_NOMEM;
126298 memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
126299
126300 for(i=0; i<(p->nToken-1); i++){
126301 if( a[i].bIgnore==0 ){
126302 char *pL = a[i].pList;
126303 char *pR = aDoclist;
126304 char *pOut = aDoclist;
126305 int nDist = p->nToken-1-i;
126306 int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
126307 if( res==0 ) break;
126308 nList = (pOut - aDoclist);
126309 }
126310 }
126311 if( i==(p->nToken-1) ){
126312 pDL->iDocid = iMax;
126313 pDL->pList = aDoclist;
126314 pDL->nList = nList;
126315 pDL->bFreeList = 1;
126316 break;
126317 }
126318 sqlite3_free(aDoclist);
126319 }
126320 }
126321 }
126322
126323 *pbEof = bEof;
126324 return rc;
126325 }
126326
126327 /*
126328 ** Attempt to move the phrase iterator to point to the next matching docid.
126329 ** If an error occurs, return an SQLite error code. Otherwise, return
126330 ** SQLITE_OK.
@@ -125700,59 +126341,18 @@
126341 int rc = SQLITE_OK;
126342 Fts3Doclist *pDL = &p->doclist;
126343 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126344
126345 if( p->bIncr ){
126346 rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
 
 
 
 
 
 
 
126347 }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
126348 sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
126349 &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
126350 );
126351 pDL->pList = pDL->pNextDocid;
126352 }else{
126353 fts3EvalDlPhraseNext(pTab, pDL, pbEof);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126354 }
126355
126356 return rc;
126357 }
126358
@@ -125773,11 +126373,10 @@
126373 ** code before returning.
126374 */
126375 static void fts3EvalStartReaders(
126376 Fts3Cursor *pCsr, /* FTS Cursor handle */
126377 Fts3Expr *pExpr, /* Expression to initialize phrases in */
 
126378 int *pRc /* IN/OUT: Error code */
126379 ){
126380 if( pExpr && SQLITE_OK==*pRc ){
126381 if( pExpr->eType==FTSQUERY_PHRASE ){
126382 int i;
@@ -125784,14 +126383,14 @@
126383 int nToken = pExpr->pPhrase->nToken;
126384 for(i=0; i<nToken; i++){
126385 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
126386 }
126387 pExpr->bDeferred = (i==nToken);
126388 *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
126389 }else{
126390 fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
126391 fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
126392 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
126393 }
126394 }
126395 }
126396
@@ -126029,11 +126628,11 @@
126628 /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
126629 ** for-loop. Except, limit the value to 2^24 to prevent it from
126630 ** overflowing the 32-bit integer it is stored in. */
126631 if( ii<12 ) nLoad4 = nLoad4*4;
126632
126633 if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
126634 /* Either this is the cheapest token in the entire query, or it is
126635 ** part of a multi-token phrase. Either way, the entire doclist will
126636 ** (eventually) be loaded into memory. It may as well be now. */
126637 Fts3PhraseToken *pToken = pTC->pToken;
126638 int nList = 0;
@@ -126109,11 +126708,11 @@
126708 sqlite3_free(aTC);
126709 }
126710 }
126711 #endif
126712
126713 fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
126714 return rc;
126715 }
126716
126717 /*
126718 ** Invalidate the current position list for phrase pPhrase.
@@ -126592,10 +127191,20 @@
127191 pCsr->isRequireSeek = 1;
127192 pCsr->isMatchinfoNeeded = 1;
127193 pCsr->iPrevId = pExpr->iDocid;
127194 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
127195 }
127196
127197 /* Check if the cursor is past the end of the docid range specified
127198 ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
127199 if( rc==SQLITE_OK && (
127200 (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
127201 || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
127202 )){
127203 pCsr->isEof = 1;
127204 }
127205
127206 return rc;
127207 }
127208
127209 /*
127210 ** Restart interation for expression pExpr so that the next call to
@@ -126615,16 +127224,20 @@
127224 Fts3Phrase *pPhrase = pExpr->pPhrase;
127225
127226 if( pPhrase ){
127227 fts3EvalInvalidatePoslist(pPhrase);
127228 if( pPhrase->bIncr ){
127229 int i;
127230 for(i=0; i<pPhrase->nToken; i++){
127231 Fts3PhraseToken *pToken = &pPhrase->aToken[i];
127232 assert( pToken->pDeferred==0 );
127233 if( pToken->pSegcsr ){
127234 sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
127235 }
127236 }
127237 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
127238 }
 
127239 pPhrase->doclist.pNextDocid = 0;
127240 pPhrase->doclist.iDocid = 0;
127241 }
127242
127243 pExpr->iDocid = 0;
@@ -126869,19 +127482,27 @@
127482
127483 iDocid = pExpr->iDocid;
127484 pIter = pPhrase->doclist.pList;
127485 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
127486 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
127487 int iMul; /* +1 if csr dir matches index dir, else -1 */
127488 int bOr = 0;
127489 u8 bEof = 0;
127490 u8 bTreeEof = 0;
127491 Fts3Expr *p; /* Used to iterate from pExpr to root */
127492 Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
127493
127494 /* Check if this phrase descends from an OR expression node. If not,
127495 ** return NULL. Otherwise, the entry that corresponds to docid
127496 ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
127497 ** tree that the node is part of has been marked as EOF, but the node
127498 ** itself is not EOF, then it may point to an earlier entry. */
127499 pNear = pExpr;
127500 for(p=pExpr->pParent; p; p=p->pParent){
127501 if( p->eType==FTSQUERY_OR ) bOr = 1;
127502 if( p->eType==FTSQUERY_NEAR ) pNear = p;
127503 if( p->bEof ) bTreeEof = 1;
127504 }
127505 if( bOr==0 ) return SQLITE_OK;
127506
127507 /* This is the descendent of an OR node. In this case we cannot use
127508 ** an incremental phrase. Load the entire doclist for the phrase
@@ -126896,33 +127517,63 @@
127517 }
127518 pIter = pPhrase->doclist.pList;
127519 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
127520 if( rc!=SQLITE_OK ) return rc;
127521 }
127522
127523 iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
127524 while( bTreeEof==1
127525 && pNear->bEof==0
127526 && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
127527 ){
127528 int rc = SQLITE_OK;
127529 fts3EvalNextRow(pCsr, pExpr, &rc);
127530 if( rc!=SQLITE_OK ) return rc;
127531 iDocid = pExpr->iDocid;
127532 pIter = pPhrase->doclist.pList;
127533 }
127534
 
 
 
 
127535 bEof = (pPhrase->doclist.nAll==0);
127536 assert( bDescDoclist==0 || bDescDoclist==1 );
127537 assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
127538
127539 if( bEof==0 ){
127540 if( pCsr->bDesc==bDescDoclist ){
127541 int dummy;
127542 if( pNear->bEof ){
127543 /* This expression is already at EOF. So position it to point to the
127544 ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
127545 ** iDocid is already set for this entry, so all that is required is
127546 ** to set pIter to point to the first byte of the last position-list
127547 ** in the doclist.
127548 **
127549 ** It would also be correct to set pIter and iDocid to zero. In
127550 ** this case, the first call to sqltie3Fts4DoclistPrev() below
127551 ** would also move the iterator to point to the last entry in the
127552 ** doclist. However, this is expensive, as to do so it has to
127553 ** iterate through the entire doclist from start to finish (since
127554 ** it does not know the docid for the last entry). */
127555 pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
127556 fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
127557 }
127558 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
127559 sqlite3Fts3DoclistPrev(
127560 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127561 &pIter, &iDocid, &dummy, &bEof
127562 );
127563 }
127564 }else{
127565 if( pNear->bEof ){
127566 pIter = 0;
127567 iDocid = 0;
127568 }
127569 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
127570 sqlite3Fts3DoclistNext(
127571 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127572 &pIter, &iDocid, &bEof
127573 );
127574 }
127575 }
127576 }
127577
127578 if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
127579 }
@@ -135756,11 +136407,11 @@
136407 assert( p->bFts4==0 );
136408 sqlite3Fts3CreateStatTable(&rc, p);
136409 if( rc ) return rc;
136410 }
136411 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
136412 if( rc ) return rc;
136413 sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
136414 sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
136415 sqlite3_step(pStmt);
136416 rc = sqlite3_reset(pStmt);
136417 return rc;
@@ -136025,10 +136676,13 @@
136676 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
136677 p->nNodeSize = atoi(&zVal[9]);
136678 rc = SQLITE_OK;
136679 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
136680 p->nMaxPendingData = atoi(&zVal[11]);
136681 rc = SQLITE_OK;
136682 }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
136683 p->bNoIncrDoclist = atoi(&zVal[21]);
136684 rc = SQLITE_OK;
136685 #endif
136686 }else{
136687 rc = SQLITE_ERROR;
136688 }
136689
+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.8.1"
111111
#define SQLITE_VERSION_NUMBER 3008001
112
-#define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
112
+#define SQLITE_SOURCE_ID "2013-10-10 15:04:52 af7abebeb1f70466833bc766d294d721eaef746f"
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.8.1"
111 #define SQLITE_VERSION_NUMBER 3008001
112 #define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
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.8.1"
111 #define SQLITE_VERSION_NUMBER 3008001
112 #define SQLITE_SOURCE_ID "2013-10-10 15:04:52 af7abebeb1f70466833bc766d294d721eaef746f"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+6
--- src/sync.c
+++ src/sync.c
@@ -51,10 +51,12 @@
5151
}
5252
url_parse(0, URL_REMEMBER);
5353
if( g.urlProtocol==0 ) return 0;
5454
if( g.urlUser!=0 && g.urlPasswd==0 ){
5555
g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
56
+ g.urlFlags |= URL_PROMPT_PW;
57
+ url_prompt_for_password();
5658
}
5759
#if 0 /* Disabled for now */
5860
if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
5961
/* When doing an automatic pull, also automatically pull shuns from
6062
** the server if pull_shuns is enabled.
@@ -101,16 +103,20 @@
101103
*/
102104
if( find_option("verily",0,0)!=0 ){
103105
*pSyncFlags |= SYNC_RESYNC;
104106
}
105107
url_proxy_options();
108
+ clone_ssh_find_options();
106109
db_find_and_open_repository(0, 0);
107110
db_open_config(0);
108111
if( g.argc==2 ){
109112
if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
110113
}else if( g.argc==3 ){
111114
zUrl = g.argv[2];
115
+ }
116
+ if( urlFlags & URL_REMEMBER ){
117
+ clone_ssh_db_set_options();
112118
}
113119
url_parse(zUrl, urlFlags);
114120
if( g.urlProtocol==0 ){
115121
if( urlOptional ) fossil_exit(0);
116122
usage("URL");
117123
--- src/sync.c
+++ src/sync.c
@@ -51,10 +51,12 @@
51 }
52 url_parse(0, URL_REMEMBER);
53 if( g.urlProtocol==0 ) return 0;
54 if( g.urlUser!=0 && g.urlPasswd==0 ){
55 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
 
 
56 }
57 #if 0 /* Disabled for now */
58 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
59 /* When doing an automatic pull, also automatically pull shuns from
60 ** the server if pull_shuns is enabled.
@@ -101,16 +103,20 @@
101 */
102 if( find_option("verily",0,0)!=0 ){
103 *pSyncFlags |= SYNC_RESYNC;
104 }
105 url_proxy_options();
 
106 db_find_and_open_repository(0, 0);
107 db_open_config(0);
108 if( g.argc==2 ){
109 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
110 }else if( g.argc==3 ){
111 zUrl = g.argv[2];
 
 
 
112 }
113 url_parse(zUrl, urlFlags);
114 if( g.urlProtocol==0 ){
115 if( urlOptional ) fossil_exit(0);
116 usage("URL");
117
--- src/sync.c
+++ src/sync.c
@@ -51,10 +51,12 @@
51 }
52 url_parse(0, URL_REMEMBER);
53 if( g.urlProtocol==0 ) return 0;
54 if( g.urlUser!=0 && g.urlPasswd==0 ){
55 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
56 g.urlFlags |= URL_PROMPT_PW;
57 url_prompt_for_password();
58 }
59 #if 0 /* Disabled for now */
60 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
61 /* When doing an automatic pull, also automatically pull shuns from
62 ** the server if pull_shuns is enabled.
@@ -101,16 +103,20 @@
103 */
104 if( find_option("verily",0,0)!=0 ){
105 *pSyncFlags |= SYNC_RESYNC;
106 }
107 url_proxy_options();
108 clone_ssh_find_options();
109 db_find_and_open_repository(0, 0);
110 db_open_config(0);
111 if( g.argc==2 ){
112 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
113 }else if( g.argc==3 ){
114 zUrl = g.argv[2];
115 }
116 if( urlFlags & URL_REMEMBER ){
117 clone_ssh_db_set_options();
118 }
119 url_parse(zUrl, urlFlags);
120 if( g.urlProtocol==0 ){
121 if( urlOptional ) fossil_exit(0);
122 usage("URL");
123
+73 -5
--- src/timeline.c
+++ src/timeline.c
@@ -1850,10 +1850,75 @@
18501850
@ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
18511851
}
18521852
db_finalize(&q);
18531853
style_footer();
18541854
}
1855
+
1856
+/*
1857
+** Creates a TEMP VIEW named v_reports which is a wrapper around the
1858
+** EVENT table filtered on event.type. It looks for the request
1859
+** parameter 'type' (reminder: we "should" use 'y' for consistency
1860
+** with /timeline, but /reports uses 'y' for the year) and expects it
1861
+** to contain one of the conventional values from event.type or the
1862
+** value "all", which is treated as equivalent to "*". By default (if
1863
+** no 'y' is specified), "*" is assumed (that is also the default for
1864
+** invalid/unknown filter values). That 'y' filter is the one used for
1865
+** the event list. Note that a filter of "*" or "all" is equivalent to
1866
+** querying against the full event table. The view, however, adds an
1867
+** abstraction level to simplify the implementation code for the
1868
+** various /reports pages.
1869
+**
1870
+** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
1871
+** filter it applies, or '*' if no filter is applied (i.e. if "all" is
1872
+** used).
1873
+*/
1874
+static char stats_report_init_view(){
1875
+ char const * zType = PD("type","*"); /* analog to /timeline?y=... */
1876
+ char const * zRealType = NULL; /* normalized form of zType */
1877
+ char rc = 0; /* result code */
1878
+ switch( (zType && *zType) ? *zType : 0 ){
1879
+ case 'c':
1880
+ case 'C':
1881
+ zRealType = "ci";
1882
+ rc = *zRealType;
1883
+ break;
1884
+ case 'e':
1885
+ case 'E':
1886
+ zRealType = "e";
1887
+ rc = *zRealType;
1888
+ break;
1889
+ case 'g':
1890
+ case 'G':
1891
+ zRealType = "g";
1892
+ rc = *zRealType;
1893
+ break;
1894
+ case 't':
1895
+ case 'T':
1896
+ zRealType = "t";
1897
+ rc = *zRealType;
1898
+ break;
1899
+ case 'w':
1900
+ case 'W':
1901
+ zRealType = "w";
1902
+ rc = *zRealType;
1903
+ break;
1904
+ default:
1905
+ rc = '*';
1906
+ break;
1907
+ }
1908
+ assert(0 != rc);
1909
+ if(zRealType){
1910
+ db_multi_exec("CREATE TEMP VIEW v_reports AS "
1911
+ "SELECT * FROM event WHERE type GLOB %Q",
1912
+ zRealType);
1913
+ }else{
1914
+ db_multi_exec("CREATE TEMP VIEW v_reports AS "
1915
+ "SELECT * FROM event");
1916
+ }
1917
+ return rc;
1918
+}
1919
+
18551920
18561921
/*
18571922
** Helper for stats_report_by_month_year(), which generates a list of
18581923
** week numbers. zTimeframe should be either a timeframe in the form YYYY
18591924
** or YYYY-MM.
@@ -1864,11 +1929,11 @@
18641929
memcpy(yearPart, zTimeframe, 4);
18651930
db_prepare(&stWeek,
18661931
"SELECT DISTINCT strftime('%%W',mtime) AS wk, "
18671932
"count(*) AS n, "
18681933
"substr(date(mtime),1,%d) AS ym "
1869
- "FROM event "
1934
+ "FROM v_reports "
18701935
"WHERE ym=%Q AND mtime < current_timestamp "
18711936
"GROUP BY wk ORDER BY wk",
18721937
strlen(zTimeframe),
18731938
zTimeframe);
18741939
while( SQLITE_ROW == db_step(&stWeek) ){
@@ -1908,16 +1973,17 @@
19081973
Blob header = empty_blob; /* Page header text */
19091974
int nMaxEvents = 1; /* for calculating length of graph
19101975
bars. */
19111976
int iterations = 0; /* number of weeks/months we iterate
19121977
over */
1978
+ stats_report_init_view();
19131979
blob_appendf(&header, "Timeline Events by year%s",
19141980
(includeMonth ? "/month" : ""));
19151981
blob_appendf(&sql,
19161982
"SELECT substr(date(mtime),1,%d) AS timeframe, "
19171983
"count(*) AS eventCount "
1918
- "FROM event ",
1984
+ "FROM v_reports ",
19191985
includeMonth ? 7 : 4);
19201986
if(zUserName&&*zUserName){
19211987
blob_appendf(&sql, " WHERE user=%Q ", zUserName);
19221988
blob_appendf(&header," for user %q", zUserName);
19231989
}
@@ -2053,14 +2119,15 @@
20532119
int rowClass = 0; /* counter for alternating
20542120
row colors */
20552121
Blob sql = empty_blob; /* SQL */
20562122
int nMaxEvents = 1; /* max number of events for
20572123
all rows. */
2124
+ stats_report_init_view();
20582125
blob_append(&sql,
20592126
"SELECT user, "
20602127
"COUNT(*) AS eventCount "
2061
- "FROM event "
2128
+ "FROM v_reports "
20622129
"GROUP BY user ORDER BY eventCount DESC",
20632130
-1);
20642131
db_prepare(&query, blob_str(&sql));
20652132
blob_reset(&sql);
20662133
@ <h1>Timeline Events by User</h1>
@@ -2121,14 +2188,15 @@
21212188
Blob sql = empty_blob;
21222189
int nMaxEvents = 1; /* max number of events for
21232190
all rows. */
21242191
int iterations = 0; /* # of active time periods. */
21252192
2193
+ stats_report_init_view();
21262194
cgi_printf("Select year: ");
21272195
blob_append(&sql,
21282196
"SELECT DISTINCT substr(date(mtime),1,4) AS y "
2129
- "FROM event WHERE 1 ", -1);
2197
+ "FROM v_reports WHERE 1 ", -1);
21302198
if(zUserName&&*zUserName){
21312199
blob_appendf(&sql,"AND user=%Q ", zUserName);
21322200
}
21332201
blob_append(&sql,"GROUP BY y ORDER BY y", -1);
21342202
db_prepare(&qYears, blob_str(&sql));
@@ -2159,11 +2227,11 @@
21592227
blob_appendf(&header, "Timeline events for the calendar weeks "
21602228
"of %h", zYear);
21612229
blob_appendf(&sql,
21622230
"SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
21632231
"count(*) AS n "
2164
- "FROM event "
2232
+ "FROM v_reports "
21652233
"WHERE %Q=substr(date(mtime),1,4) "
21662234
"AND mtime < current_timestamp ",
21672235
zYear);
21682236
if(zUserName&&*zUserName){
21692237
blob_appendf(&sql, " AND user=%Q ", zUserName);
21702238
--- src/timeline.c
+++ src/timeline.c
@@ -1850,10 +1850,75 @@
1850 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1851 }
1852 db_finalize(&q);
1853 style_footer();
1854 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1855
1856 /*
1857 ** Helper for stats_report_by_month_year(), which generates a list of
1858 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
1859 ** or YYYY-MM.
@@ -1864,11 +1929,11 @@
1864 memcpy(yearPart, zTimeframe, 4);
1865 db_prepare(&stWeek,
1866 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
1867 "count(*) AS n, "
1868 "substr(date(mtime),1,%d) AS ym "
1869 "FROM event "
1870 "WHERE ym=%Q AND mtime < current_timestamp "
1871 "GROUP BY wk ORDER BY wk",
1872 strlen(zTimeframe),
1873 zTimeframe);
1874 while( SQLITE_ROW == db_step(&stWeek) ){
@@ -1908,16 +1973,17 @@
1908 Blob header = empty_blob; /* Page header text */
1909 int nMaxEvents = 1; /* for calculating length of graph
1910 bars. */
1911 int iterations = 0; /* number of weeks/months we iterate
1912 over */
 
1913 blob_appendf(&header, "Timeline Events by year%s",
1914 (includeMonth ? "/month" : ""));
1915 blob_appendf(&sql,
1916 "SELECT substr(date(mtime),1,%d) AS timeframe, "
1917 "count(*) AS eventCount "
1918 "FROM event ",
1919 includeMonth ? 7 : 4);
1920 if(zUserName&&*zUserName){
1921 blob_appendf(&sql, " WHERE user=%Q ", zUserName);
1922 blob_appendf(&header," for user %q", zUserName);
1923 }
@@ -2053,14 +2119,15 @@
2053 int rowClass = 0; /* counter for alternating
2054 row colors */
2055 Blob sql = empty_blob; /* SQL */
2056 int nMaxEvents = 1; /* max number of events for
2057 all rows. */
 
2058 blob_append(&sql,
2059 "SELECT user, "
2060 "COUNT(*) AS eventCount "
2061 "FROM event "
2062 "GROUP BY user ORDER BY eventCount DESC",
2063 -1);
2064 db_prepare(&query, blob_str(&sql));
2065 blob_reset(&sql);
2066 @ <h1>Timeline Events by User</h1>
@@ -2121,14 +2188,15 @@
2121 Blob sql = empty_blob;
2122 int nMaxEvents = 1; /* max number of events for
2123 all rows. */
2124 int iterations = 0; /* # of active time periods. */
2125
 
2126 cgi_printf("Select year: ");
2127 blob_append(&sql,
2128 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2129 "FROM event WHERE 1 ", -1);
2130 if(zUserName&&*zUserName){
2131 blob_appendf(&sql,"AND user=%Q ", zUserName);
2132 }
2133 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2134 db_prepare(&qYears, blob_str(&sql));
@@ -2159,11 +2227,11 @@
2159 blob_appendf(&header, "Timeline events for the calendar weeks "
2160 "of %h", zYear);
2161 blob_appendf(&sql,
2162 "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
2163 "count(*) AS n "
2164 "FROM event "
2165 "WHERE %Q=substr(date(mtime),1,4) "
2166 "AND mtime < current_timestamp ",
2167 zYear);
2168 if(zUserName&&*zUserName){
2169 blob_appendf(&sql, " AND user=%Q ", zUserName);
2170
--- src/timeline.c
+++ src/timeline.c
@@ -1850,10 +1850,75 @@
1850 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1851 }
1852 db_finalize(&q);
1853 style_footer();
1854 }
1855
1856 /*
1857 ** Creates a TEMP VIEW named v_reports which is a wrapper around the
1858 ** EVENT table filtered on event.type. It looks for the request
1859 ** parameter 'type' (reminder: we "should" use 'y' for consistency
1860 ** with /timeline, but /reports uses 'y' for the year) and expects it
1861 ** to contain one of the conventional values from event.type or the
1862 ** value "all", which is treated as equivalent to "*". By default (if
1863 ** no 'y' is specified), "*" is assumed (that is also the default for
1864 ** invalid/unknown filter values). That 'y' filter is the one used for
1865 ** the event list. Note that a filter of "*" or "all" is equivalent to
1866 ** querying against the full event table. The view, however, adds an
1867 ** abstraction level to simplify the implementation code for the
1868 ** various /reports pages.
1869 **
1870 ** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
1871 ** filter it applies, or '*' if no filter is applied (i.e. if "all" is
1872 ** used).
1873 */
1874 static char stats_report_init_view(){
1875 char const * zType = PD("type","*"); /* analog to /timeline?y=... */
1876 char const * zRealType = NULL; /* normalized form of zType */
1877 char rc = 0; /* result code */
1878 switch( (zType && *zType) ? *zType : 0 ){
1879 case 'c':
1880 case 'C':
1881 zRealType = "ci";
1882 rc = *zRealType;
1883 break;
1884 case 'e':
1885 case 'E':
1886 zRealType = "e";
1887 rc = *zRealType;
1888 break;
1889 case 'g':
1890 case 'G':
1891 zRealType = "g";
1892 rc = *zRealType;
1893 break;
1894 case 't':
1895 case 'T':
1896 zRealType = "t";
1897 rc = *zRealType;
1898 break;
1899 case 'w':
1900 case 'W':
1901 zRealType = "w";
1902 rc = *zRealType;
1903 break;
1904 default:
1905 rc = '*';
1906 break;
1907 }
1908 assert(0 != rc);
1909 if(zRealType){
1910 db_multi_exec("CREATE TEMP VIEW v_reports AS "
1911 "SELECT * FROM event WHERE type GLOB %Q",
1912 zRealType);
1913 }else{
1914 db_multi_exec("CREATE TEMP VIEW v_reports AS "
1915 "SELECT * FROM event");
1916 }
1917 return rc;
1918 }
1919
1920
1921 /*
1922 ** Helper for stats_report_by_month_year(), which generates a list of
1923 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
1924 ** or YYYY-MM.
@@ -1864,11 +1929,11 @@
1929 memcpy(yearPart, zTimeframe, 4);
1930 db_prepare(&stWeek,
1931 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
1932 "count(*) AS n, "
1933 "substr(date(mtime),1,%d) AS ym "
1934 "FROM v_reports "
1935 "WHERE ym=%Q AND mtime < current_timestamp "
1936 "GROUP BY wk ORDER BY wk",
1937 strlen(zTimeframe),
1938 zTimeframe);
1939 while( SQLITE_ROW == db_step(&stWeek) ){
@@ -1908,16 +1973,17 @@
1973 Blob header = empty_blob; /* Page header text */
1974 int nMaxEvents = 1; /* for calculating length of graph
1975 bars. */
1976 int iterations = 0; /* number of weeks/months we iterate
1977 over */
1978 stats_report_init_view();
1979 blob_appendf(&header, "Timeline Events by year%s",
1980 (includeMonth ? "/month" : ""));
1981 blob_appendf(&sql,
1982 "SELECT substr(date(mtime),1,%d) AS timeframe, "
1983 "count(*) AS eventCount "
1984 "FROM v_reports ",
1985 includeMonth ? 7 : 4);
1986 if(zUserName&&*zUserName){
1987 blob_appendf(&sql, " WHERE user=%Q ", zUserName);
1988 blob_appendf(&header," for user %q", zUserName);
1989 }
@@ -2053,14 +2119,15 @@
2119 int rowClass = 0; /* counter for alternating
2120 row colors */
2121 Blob sql = empty_blob; /* SQL */
2122 int nMaxEvents = 1; /* max number of events for
2123 all rows. */
2124 stats_report_init_view();
2125 blob_append(&sql,
2126 "SELECT user, "
2127 "COUNT(*) AS eventCount "
2128 "FROM v_reports "
2129 "GROUP BY user ORDER BY eventCount DESC",
2130 -1);
2131 db_prepare(&query, blob_str(&sql));
2132 blob_reset(&sql);
2133 @ <h1>Timeline Events by User</h1>
@@ -2121,14 +2188,15 @@
2188 Blob sql = empty_blob;
2189 int nMaxEvents = 1; /* max number of events for
2190 all rows. */
2191 int iterations = 0; /* # of active time periods. */
2192
2193 stats_report_init_view();
2194 cgi_printf("Select year: ");
2195 blob_append(&sql,
2196 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2197 "FROM v_reports WHERE 1 ", -1);
2198 if(zUserName&&*zUserName){
2199 blob_appendf(&sql,"AND user=%Q ", zUserName);
2200 }
2201 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2202 db_prepare(&qYears, blob_str(&sql));
@@ -2159,11 +2227,11 @@
2227 blob_appendf(&header, "Timeline events for the calendar weeks "
2228 "of %h", zYear);
2229 blob_appendf(&sql,
2230 "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
2231 "count(*) AS n "
2232 "FROM v_reports "
2233 "WHERE %Q=substr(date(mtime),1,4) "
2234 "AND mtime < current_timestamp ",
2235 zYear);
2236 if(zUserName&&*zUserName){
2237 blob_appendf(&sql, " AND user=%Q ", zUserName);
2238
+2 -20
--- src/url.c
+++ src/url.c
@@ -100,11 +100,10 @@
100100
}else if( zUrl[0]=='s' ){
101101
g.urlIsSsh = 1;
102102
g.urlProtocol = "ssh";
103103
g.urlDfltPort = 22;
104104
g.urlFossil = "fossil";
105
- g.urlShell = 0;
106105
iStart = 6;
107106
}else{
108107
g.urlIsHttps = 0;
109108
g.urlProtocol = "http";
110109
g.urlDfltPort = 80;
@@ -173,16 +172,10 @@
173172
g.urlFossil = zValue;
174173
dehttpize(g.urlFossil);
175174
zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
176175
cQuerySep = '&';
177176
}
178
- if( fossil_strcmp(zName,"shell")==0 ){
179
- g.urlShell = zValue;
180
- dehttpize(g.urlShell);
181
- zExe = mprintf("%cshell=%T", cQuerySep, g.urlFossil);
182
- cQuerySep = '&';
183
- }
184177
}
185178
186179
dehttpize(g.urlPath);
187180
if( g.urlDfltPort==g.urlPort ){
188181
g.urlCanonical = mprintf(
@@ -444,26 +437,16 @@
444437
if( g.urlIsSsh || g.urlIsFile ) return;
445438
if( isatty(fileno(stdin))
446439
&& (g.urlFlags & URL_PROMPT_PW)!=0
447440
&& (g.urlFlags & URL_PROMPTED)==0
448441
){
449
- char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
450
- Blob x;
451
- fossil_force_newline();
452
- prompt_for_password(zPrompt, &x, 0);
453
- free(zPrompt);
454
- g.urlPasswd = mprintf("%b", &x);
455
- blob_reset(&x);
456442
g.urlFlags |= URL_PROMPTED;
443
+ g.urlPasswd = prompt_for_user_password(g.urlUser);
457444
if( g.urlPasswd[0]
458445
&& (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
459446
){
460
- char c;
461
- prompt_user("remember password (Y/n)? ", &x);
462
- c = blob_str(&x)[0];
463
- blob_reset(&x);
464
- if( c!='n' && c!='N' ){
447
+ if( save_password_prompt() ){
465448
g.urlFlags |= URL_REMEMBER_PW;
466449
if( g.urlFlags & URL_REMEMBER ){
467450
db_set("last-sync-pw", obscure(g.urlPasswd), 0);
468451
}
469452
}
@@ -490,10 +473,9 @@
490473
*/
491474
void url_get_password_if_needed(void){
492475
if( (g.urlUser && g.urlUser[0])
493476
&& (g.urlPasswd==0 || g.urlPasswd[0]==0)
494477
&& isatty(fileno(stdin))
495
- && g.urlIsSsh==0
496478
){
497479
url_prompt_for_password();
498480
}
499481
}
500482
--- src/url.c
+++ src/url.c
@@ -100,11 +100,10 @@
100 }else if( zUrl[0]=='s' ){
101 g.urlIsSsh = 1;
102 g.urlProtocol = "ssh";
103 g.urlDfltPort = 22;
104 g.urlFossil = "fossil";
105 g.urlShell = 0;
106 iStart = 6;
107 }else{
108 g.urlIsHttps = 0;
109 g.urlProtocol = "http";
110 g.urlDfltPort = 80;
@@ -173,16 +172,10 @@
173 g.urlFossil = zValue;
174 dehttpize(g.urlFossil);
175 zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
176 cQuerySep = '&';
177 }
178 if( fossil_strcmp(zName,"shell")==0 ){
179 g.urlShell = zValue;
180 dehttpize(g.urlShell);
181 zExe = mprintf("%cshell=%T", cQuerySep, g.urlFossil);
182 cQuerySep = '&';
183 }
184 }
185
186 dehttpize(g.urlPath);
187 if( g.urlDfltPort==g.urlPort ){
188 g.urlCanonical = mprintf(
@@ -444,26 +437,16 @@
444 if( g.urlIsSsh || g.urlIsFile ) return;
445 if( isatty(fileno(stdin))
446 && (g.urlFlags & URL_PROMPT_PW)!=0
447 && (g.urlFlags & URL_PROMPTED)==0
448 ){
449 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
450 Blob x;
451 fossil_force_newline();
452 prompt_for_password(zPrompt, &x, 0);
453 free(zPrompt);
454 g.urlPasswd = mprintf("%b", &x);
455 blob_reset(&x);
456 g.urlFlags |= URL_PROMPTED;
 
457 if( g.urlPasswd[0]
458 && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
459 ){
460 char c;
461 prompt_user("remember password (Y/n)? ", &x);
462 c = blob_str(&x)[0];
463 blob_reset(&x);
464 if( c!='n' && c!='N' ){
465 g.urlFlags |= URL_REMEMBER_PW;
466 if( g.urlFlags & URL_REMEMBER ){
467 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
468 }
469 }
@@ -490,10 +473,9 @@
490 */
491 void url_get_password_if_needed(void){
492 if( (g.urlUser && g.urlUser[0])
493 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
494 && isatty(fileno(stdin))
495 && g.urlIsSsh==0
496 ){
497 url_prompt_for_password();
498 }
499 }
500
--- src/url.c
+++ src/url.c
@@ -100,11 +100,10 @@
100 }else if( zUrl[0]=='s' ){
101 g.urlIsSsh = 1;
102 g.urlProtocol = "ssh";
103 g.urlDfltPort = 22;
104 g.urlFossil = "fossil";
 
105 iStart = 6;
106 }else{
107 g.urlIsHttps = 0;
108 g.urlProtocol = "http";
109 g.urlDfltPort = 80;
@@ -173,16 +172,10 @@
172 g.urlFossil = zValue;
173 dehttpize(g.urlFossil);
174 zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
175 cQuerySep = '&';
176 }
 
 
 
 
 
 
177 }
178
179 dehttpize(g.urlPath);
180 if( g.urlDfltPort==g.urlPort ){
181 g.urlCanonical = mprintf(
@@ -444,26 +437,16 @@
437 if( g.urlIsSsh || g.urlIsFile ) return;
438 if( isatty(fileno(stdin))
439 && (g.urlFlags & URL_PROMPT_PW)!=0
440 && (g.urlFlags & URL_PROMPTED)==0
441 ){
 
 
 
 
 
 
 
442 g.urlFlags |= URL_PROMPTED;
443 g.urlPasswd = prompt_for_user_password(g.urlUser);
444 if( g.urlPasswd[0]
445 && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
446 ){
447 if( save_password_prompt() ){
 
 
 
 
448 g.urlFlags |= URL_REMEMBER_PW;
449 if( g.urlFlags & URL_REMEMBER ){
450 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
451 }
452 }
@@ -490,10 +473,9 @@
473 */
474 void url_get_password_if_needed(void){
475 if( (g.urlUser && g.urlUser[0])
476 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
477 && isatty(fileno(stdin))
 
478 ){
479 url_prompt_for_password();
480 }
481 }
482
+28 -1
--- src/user.c
+++ src/user.c
@@ -34,11 +34,11 @@
3434
if( z[i]=='\r' || z[i]=='\n' ){
3535
while( i>0 && fossil_isspace(z[i-1]) ){ i--; }
3636
z[i] = 0;
3737
break;
3838
}
39
- if( z[i]<' ' ) z[i] = ' ';
39
+ if( z[i]>0 && z[i]<' ' ) z[i] = ' ';
4040
}
4141
blob_append(pBlob, z, -1);
4242
}
4343
4444
#if defined(_WIN32) || defined(__BIONIC__)
@@ -128,10 +128,37 @@
128128
break;
129129
}
130130
}
131131
blob_reset(&secondTry);
132132
}
133
+
134
+/*
135
+** Prompt to save Fossil user password
136
+*/
137
+int save_password_prompt(){
138
+ Blob x;
139
+ char c;
140
+ prompt_user("remember password (Y/n)? ", &x);
141
+ c = blob_str(&x)[0];
142
+ blob_reset(&x);
143
+ return ( c!='n' && c!='N' );
144
+}
145
+
146
+/*
147
+** Prompt for Fossil user password
148
+*/
149
+char *prompt_for_user_password(const char *zUser){
150
+ char *zPrompt = mprintf("\rpassword for %s: ", zUser);
151
+ char *zPw;
152
+ Blob x;
153
+ fossil_force_newline();
154
+ prompt_for_password(zPrompt, &x, 0);
155
+ free(zPrompt);
156
+ zPw = mprintf("%b", &x);
157
+ blob_reset(&x);
158
+ return zPw;
159
+}
133160
134161
/*
135162
** Prompt the user to enter a single line of text.
136163
*/
137164
void prompt_user(const char *zPrompt, Blob *pIn){
138165
--- src/user.c
+++ src/user.c
@@ -34,11 +34,11 @@
34 if( z[i]=='\r' || z[i]=='\n' ){
35 while( i>0 && fossil_isspace(z[i-1]) ){ i--; }
36 z[i] = 0;
37 break;
38 }
39 if( z[i]<' ' ) z[i] = ' ';
40 }
41 blob_append(pBlob, z, -1);
42 }
43
44 #if defined(_WIN32) || defined(__BIONIC__)
@@ -128,10 +128,37 @@
128 break;
129 }
130 }
131 blob_reset(&secondTry);
132 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
134 /*
135 ** Prompt the user to enter a single line of text.
136 */
137 void prompt_user(const char *zPrompt, Blob *pIn){
138
--- src/user.c
+++ src/user.c
@@ -34,11 +34,11 @@
34 if( z[i]=='\r' || z[i]=='\n' ){
35 while( i>0 && fossil_isspace(z[i-1]) ){ i--; }
36 z[i] = 0;
37 break;
38 }
39 if( z[i]>0 && z[i]<' ' ) z[i] = ' ';
40 }
41 blob_append(pBlob, z, -1);
42 }
43
44 #if defined(_WIN32) || defined(__BIONIC__)
@@ -128,10 +128,37 @@
128 break;
129 }
130 }
131 blob_reset(&secondTry);
132 }
133
134 /*
135 ** Prompt to save Fossil user password
136 */
137 int save_password_prompt(){
138 Blob x;
139 char c;
140 prompt_user("remember password (Y/n)? ", &x);
141 c = blob_str(&x)[0];
142 blob_reset(&x);
143 return ( c!='n' && c!='N' );
144 }
145
146 /*
147 ** Prompt for Fossil user password
148 */
149 char *prompt_for_user_password(const char *zUser){
150 char *zPrompt = mprintf("\rpassword for %s: ", zUser);
151 char *zPw;
152 Blob x;
153 fossil_force_newline();
154 prompt_for_password(zPrompt, &x, 0);
155 free(zPrompt);
156 zPw = mprintf("%b", &x);
157 blob_reset(&x);
158 return zPw;
159 }
160
161 /*
162 ** Prompt the user to enter a single line of text.
163 */
164 void prompt_user(const char *zPrompt, Blob *pIn){
165
+18 -11
--- src/xfer.c
+++ src/xfer.c
@@ -1228,10 +1228,11 @@
12281228
{
12291229
cgi_reset_content();
12301230
@ error bad\scommand:\s%F(blob_str(&xfer.line))
12311231
}
12321232
blobarray_reset(xfer.aToken, xfer.nToken);
1233
+ blob_reset(&xfer.line);
12331234
}
12341235
if( isPush ){
12351236
if( run_push_script()==TH_ERROR ){
12361237
cgi_reset_content();
12371238
@ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
@@ -1255,10 +1256,11 @@
12551256
if( xfer.syncPrivate ) send_private(&xfer);
12561257
}
12571258
if( recvConfig ){
12581259
configure_finalize_receive();
12591260
}
1261
+ db_multi_exec("DROP TABLE onremote");
12601262
manifest_crosslink_end();
12611263
12621264
/* Send the server timestamp last, in case prior processing happened
12631265
** to use up a significant fraction of our time window.
12641266
*/
@@ -1425,11 +1427,10 @@
14251427
nCardSent++;
14261428
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
14271429
if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
14281430
}
14291431
manifest_crosslink_begin();
1430
- transport_global_startup();
14311432
if( syncFlags & SYNC_VERBOSE ){
14321433
fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
14331434
}
14341435
14351436
while( go ){
@@ -1504,11 +1505,22 @@
15041505
*/
15051506
zRandomness = db_text(0, "SELECT hex(randomblob(20))");
15061507
blob_appendf(&send, "# %s\n", zRandomness);
15071508
free(zRandomness);
15081509
1510
+ if( syncFlags & SYNC_VERBOSE ){
1511
+ fossil_print("waiting for server...");
1512
+ }
1513
+ fflush(stdout);
15091514
/* Exchange messages with the server */
1515
+ if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1516
+ MAX_REDIRECTS) ){
1517
+ nErr++;
1518
+ break;
1519
+ }
1520
+
1521
+ /* Output current stats */
15101522
if( syncFlags & SYNC_VERBOSE ){
15111523
fossil_print(zValueFormat, "Sent:",
15121524
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
15131525
xfer.nFileSent, xfer.nDeltaSent);
15141526
}else{
@@ -1520,19 +1532,11 @@
15201532
nCardRcvd = 0;
15211533
xfer.nFileSent = 0;
15221534
xfer.nDeltaSent = 0;
15231535
xfer.nGimmeSent = 0;
15241536
xfer.nIGotSent = 0;
1525
- if( syncFlags & SYNC_VERBOSE ){
1526
- fossil_print("waiting for server...");
1527
- }
1528
- fflush(stdout);
1529
- if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1530
- MAX_REDIRECTS) ){
1531
- nErr++;
1532
- break;
1533
- }
1537
+
15341538
lastPctDone = -1;
15351539
blob_reset(&send);
15361540
rArrivalTime = db_double(0.0, "SELECT julianday('now')");
15371541
15381542
/* Send the send-private pragma if we are trying to sync private data */
@@ -1775,11 +1779,14 @@
17751779
fossil_print("Error: %s\n", zMsg);
17761780
if( fossil_strcmp(zMsg, "login failed")==0 ){
17771781
if( nCycle<2 ){
17781782
g.urlPasswd = 0;
17791783
go = 1;
1780
- if( g.cgiOutput==0 ) url_prompt_for_password();
1784
+ if( g.cgiOutput==0 ){
1785
+ g.urlFlags |= URL_PROMPT_PW;
1786
+ url_prompt_for_password();
1787
+ }
17811788
}
17821789
}else{
17831790
blob_appendf(&xfer.err, "server says: %s\n", zMsg);
17841791
nErr++;
17851792
}
17861793
--- src/xfer.c
+++ src/xfer.c
@@ -1228,10 +1228,11 @@
1228 {
1229 cgi_reset_content();
1230 @ error bad\scommand:\s%F(blob_str(&xfer.line))
1231 }
1232 blobarray_reset(xfer.aToken, xfer.nToken);
 
1233 }
1234 if( isPush ){
1235 if( run_push_script()==TH_ERROR ){
1236 cgi_reset_content();
1237 @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
@@ -1255,10 +1256,11 @@
1255 if( xfer.syncPrivate ) send_private(&xfer);
1256 }
1257 if( recvConfig ){
1258 configure_finalize_receive();
1259 }
 
1260 manifest_crosslink_end();
1261
1262 /* Send the server timestamp last, in case prior processing happened
1263 ** to use up a significant fraction of our time window.
1264 */
@@ -1425,11 +1427,10 @@
1425 nCardSent++;
1426 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1427 if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
1428 }
1429 manifest_crosslink_begin();
1430 transport_global_startup();
1431 if( syncFlags & SYNC_VERBOSE ){
1432 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1433 }
1434
1435 while( go ){
@@ -1504,11 +1505,22 @@
1504 */
1505 zRandomness = db_text(0, "SELECT hex(randomblob(20))");
1506 blob_appendf(&send, "# %s\n", zRandomness);
1507 free(zRandomness);
1508
 
 
 
 
1509 /* Exchange messages with the server */
 
 
 
 
 
 
 
1510 if( syncFlags & SYNC_VERBOSE ){
1511 fossil_print(zValueFormat, "Sent:",
1512 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
1513 xfer.nFileSent, xfer.nDeltaSent);
1514 }else{
@@ -1520,19 +1532,11 @@
1520 nCardRcvd = 0;
1521 xfer.nFileSent = 0;
1522 xfer.nDeltaSent = 0;
1523 xfer.nGimmeSent = 0;
1524 xfer.nIGotSent = 0;
1525 if( syncFlags & SYNC_VERBOSE ){
1526 fossil_print("waiting for server...");
1527 }
1528 fflush(stdout);
1529 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1530 MAX_REDIRECTS) ){
1531 nErr++;
1532 break;
1533 }
1534 lastPctDone = -1;
1535 blob_reset(&send);
1536 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
1537
1538 /* Send the send-private pragma if we are trying to sync private data */
@@ -1775,11 +1779,14 @@
1775 fossil_print("Error: %s\n", zMsg);
1776 if( fossil_strcmp(zMsg, "login failed")==0 ){
1777 if( nCycle<2 ){
1778 g.urlPasswd = 0;
1779 go = 1;
1780 if( g.cgiOutput==0 ) url_prompt_for_password();
 
 
 
1781 }
1782 }else{
1783 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1784 nErr++;
1785 }
1786
--- src/xfer.c
+++ src/xfer.c
@@ -1228,10 +1228,11 @@
1228 {
1229 cgi_reset_content();
1230 @ error bad\scommand:\s%F(blob_str(&xfer.line))
1231 }
1232 blobarray_reset(xfer.aToken, xfer.nToken);
1233 blob_reset(&xfer.line);
1234 }
1235 if( isPush ){
1236 if( run_push_script()==TH_ERROR ){
1237 cgi_reset_content();
1238 @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
@@ -1255,10 +1256,11 @@
1256 if( xfer.syncPrivate ) send_private(&xfer);
1257 }
1258 if( recvConfig ){
1259 configure_finalize_receive();
1260 }
1261 db_multi_exec("DROP TABLE onremote");
1262 manifest_crosslink_end();
1263
1264 /* Send the server timestamp last, in case prior processing happened
1265 ** to use up a significant fraction of our time window.
1266 */
@@ -1425,11 +1427,10 @@
1427 nCardSent++;
1428 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1429 if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
1430 }
1431 manifest_crosslink_begin();
 
1432 if( syncFlags & SYNC_VERBOSE ){
1433 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1434 }
1435
1436 while( go ){
@@ -1504,11 +1505,22 @@
1505 */
1506 zRandomness = db_text(0, "SELECT hex(randomblob(20))");
1507 blob_appendf(&send, "# %s\n", zRandomness);
1508 free(zRandomness);
1509
1510 if( syncFlags & SYNC_VERBOSE ){
1511 fossil_print("waiting for server...");
1512 }
1513 fflush(stdout);
1514 /* Exchange messages with the server */
1515 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1516 MAX_REDIRECTS) ){
1517 nErr++;
1518 break;
1519 }
1520
1521 /* Output current stats */
1522 if( syncFlags & SYNC_VERBOSE ){
1523 fossil_print(zValueFormat, "Sent:",
1524 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
1525 xfer.nFileSent, xfer.nDeltaSent);
1526 }else{
@@ -1520,19 +1532,11 @@
1532 nCardRcvd = 0;
1533 xfer.nFileSent = 0;
1534 xfer.nDeltaSent = 0;
1535 xfer.nGimmeSent = 0;
1536 xfer.nIGotSent = 0;
1537
 
 
 
 
 
 
 
 
1538 lastPctDone = -1;
1539 blob_reset(&send);
1540 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
1541
1542 /* Send the send-private pragma if we are trying to sync private data */
@@ -1775,11 +1779,14 @@
1779 fossil_print("Error: %s\n", zMsg);
1780 if( fossil_strcmp(zMsg, "login failed")==0 ){
1781 if( nCycle<2 ){
1782 g.urlPasswd = 0;
1783 go = 1;
1784 if( g.cgiOutput==0 ){
1785 g.urlFlags |= URL_PROMPT_PW;
1786 url_prompt_for_password();
1787 }
1788 }
1789 }else{
1790 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1791 nErr++;
1792 }
1793
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -10,11 +10,11 @@
1010
Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
1111
that are required for any new code that will be accepted into the Fossil core.
1212
But, of course, if you are writing an extension just for yourself, you can
1313
use any programming style you want.
1414
15
-The source code for Fossil is not feed directly into the C compiler, however.
15
+The source code for Fossil is not sent directly into the C compiler.
1616
There are three separate code [./makefile.wiki#preprocessing|preprocessors]
1717
that run over the code first.
1818
1919
1. The <b>mkindex</b> preprocessor scans all regular source files looking
2020
for special comments that contain "help" text and which identify routines
2121
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -10,11 +10,11 @@
10 Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
11 that are required for any new code that will be accepted into the Fossil core.
12 But, of course, if you are writing an extension just for yourself, you can
13 use any programming style you want.
14
15 The source code for Fossil is not feed directly into the C compiler, however.
16 There are three separate code [./makefile.wiki#preprocessing|preprocessors]
17 that run over the code first.
18
19 1. The <b>mkindex</b> preprocessor scans all regular source files looking
20 for special comments that contain "help" text and which identify routines
21
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -10,11 +10,11 @@
10 Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
11 that are required for any new code that will be accepted into the Fossil core.
12 But, of course, if you are writing an extension just for yourself, you can
13 use any programming style you want.
14
15 The source code for Fossil is not sent directly into the C compiler.
16 There are three separate code [./makefile.wiki#preprocessing|preprocessors]
17 that run over the code first.
18
19 1. The <b>mkindex</b> preprocessor scans all regular source files looking
20 for special comments that contain "help" text and which identify routines
21
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -38,11 +38,11 @@
3838
Server (3) runs as a CGI script on a shared hosting account at
3939
<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
4040
This server demonstrates the ability of
4141
Fossil to run on an economical shared-host web account with no
4242
privileges beyond port 80 HTTP access and CGI. It is not necessary
43
-to have a dedicated computer with administrator to run Fossil.
43
+to have a dedicated computer with administrator privileges to run Fossil.
4444
As far as we are aware,
4545
Fossil is the only full-featured configuration management system
4646
that can run in
4747
such a restricted environment. The CGI script that runs on the
4848
Hurricane Electric server is the same as the CGI script shown above,
4949
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -38,11 +38,11 @@
38 Server (3) runs as a CGI script on a shared hosting account at
39 <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
40 This server demonstrates the ability of
41 Fossil to run on an economical shared-host web account with no
42 privileges beyond port 80 HTTP access and CGI. It is not necessary
43 to have a dedicated computer with administrator to run Fossil.
44 As far as we are aware,
45 Fossil is the only full-featured configuration management system
46 that can run in
47 such a restricted environment. The CGI script that runs on the
48 Hurricane Electric server is the same as the CGI script shown above,
49
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -38,11 +38,11 @@
38 Server (3) runs as a CGI script on a shared hosting account at
39 <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
40 This server demonstrates the ability of
41 Fossil to run on an economical shared-host web account with no
42 privileges beyond port 80 HTTP access and CGI. It is not necessary
43 to have a dedicated computer with administrator privileges to run Fossil.
44 As far as we are aware,
45 Fossil is the only full-featured configuration management system
46 that can run in
47 such a restricted environment. The CGI script that runs on the
48 Hurricane Electric server is the same as the CGI script shown above,
49

Keyboard Shortcuts

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