Fossil SCM

Latest merge from trunk.

brickviking 2026-02-10 08:49 bv-infotool merge
Commit d03791648f6bc0237d8a7464c213899b7632c5e89d812d04665f096075372b99
108 files changed +1027 -523 +1112 -736 +133 -35 +23 +2 -2 +1 -1 +7 -7 +18 -5 +1 -1 +1 -1 +18 -7 +7 -7 +1 -1 +2 -2 +3 -3 +7 -7 +1 -1 +32 -9 +19 -21 +1 -1 +1 -1 +1 -1 +1 -1 +8 -8 +9 -9 +19 -1 +3 -3 +1 -1 +22 -2 +5 -5 +115 -73 +1 -1 +4 -3 +2 -2 +3 -3 +1 -1 +1 -1 +4 -4 +1 -1 +1 -1 +3 -3 +1 -1 +1 -1 +1 -1 +2 -2 +1 -1 +2 -2 +1 -1 +1 -1 +1 -1 +33 -14 +7 +21 -100 +4 -4 +1 -1 +1 -1 +15 -9 +16 -8 +3 -4 +4 -4 +42 -1 +1 -1 +3 -3 +2 -2 +17 -5 +1 -1 +7 -7 +3 -3 +1 -1 +1 -1 +3 -1 +3 -3 +2 -2 +2 -2 +1 -1 +1 -1 +1 -1 +1 -1 +1 -1 +16 -12 +1 -1 +10 -5 +17 -5 +1 -1 +3 -3 +1 -1 +1 -1 +5 -5 +19 -18 +7 -7 +1 -1 +2 -2 +1 -1 +3 -3 +8 -5 +1 -1 +1 -1 +5 -5 +1 -1 +18 -6 +81 -3 +3 -3 +1 -1 +61 -23 +1 -1 +4 +18 -3 +1 -1
~ extsrc/shell.c ~ extsrc/sqlite3.c ~ extsrc/sqlite3.h ~ src/accordion.js ~ src/add.c ~ src/ajax.c ~ src/alerts.c ~ src/allrepo.c ~ src/backlink.c ~ src/bisect.c ~ src/blob.c ~ src/branch.c ~ src/builtin.c ~ src/cache.c ~ src/captcha.c ~ src/cgi.c ~ src/chat.c ~ src/checkin.c ~ src/checkout.c ~ src/color.c ~ src/comformat.c ~ src/config.h ~ src/configure.c ~ src/content.c ~ src/db.c ~ src/default.css ~ src/delta.c ~ src/descendants.c ~ src/diff.c ~ src/diffcmd.c ~ src/dispatch.c ~ src/event.c ~ src/export.c ~ src/file.c ~ src/fileedit.c ~ src/forum.c ~ src/fossil.confirmer.js ~ src/fossil.diff.js ~ src/fossil.dom.js ~ src/fossil.fetch.js ~ src/fossil.page.chat.js ~ src/fossil.page.fileedit.js ~ src/fossil.page.wikiedit.js ~ src/fossil.pikchr.js ~ src/fossil.wikiedit-wysiwyg.js ~ src/fshell.c ~ src/glob.c ~ src/graph.c ~ src/hname.c ~ src/hook.c ~ src/http.c ~ src/http_socket.c ~ src/http_ssl.c ~ src/json.c ~ src/json_report.c ~ src/json_status.c ~ src/login.c ~ src/main.c ~ src/manifest.c ~ src/markdown.c ~ src/markdown_html.c ~ src/match.c ~ src/merge.c ~ src/merge3.c ~ src/name.c ~ src/piechart.c ~ src/printf.c ~ src/purge.c ~ src/regexp.c ~ src/report.c ~ src/robot.c ~ src/schema.c ~ src/search.c ~ src/security_audit.c ~ src/setup.c ~ src/setupuser.c ~ src/sha1.c ~ src/skins.c ~ src/smtp.c ~ src/sqlcmd.c ~ src/stat.c ~ src/style.c ~ src/sync.c ~ src/tag.c ~ src/tar.c ~ src/terminal.c ~ src/th.c ~ src/th_main.c ~ src/timeline.c ~ src/tkt.c ~ src/tktsetup.c ~ src/undo.c ~ src/unicode.c ~ src/update.c ~ src/util.c ~ src/vfile.c ~ src/wiki.c ~ src/wikiformat.c ~ src/winhttp.c ~ src/xfer.c ~ src/xsystem.c ~ src/zip.c ~ tools/codecheck1.c ~ tools/mkindex.c ~ www/antibot.wiki ~ www/changes.wiki ~ www/customskin.md ~ www/serverext.wiki
+1027 -523
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -35,11 +35,11 @@
3535
** ext/recover/sqlite3recover.h
3636
** src/shell.c.in
3737
**
3838
** To modify this program, get a copy of the canonical SQLite source tree,
3939
** edit the src/shell.c.in file and/or some of the other files that are
40
-** listed above, then rerun the rerun "make shell.c".
40
+** listed above, then rerun the command "make shell.c".
4141
*/
4242
/************************* Begin src/shell.c.in ******************/
4343
/*
4444
** 2001 September 15
4545
**
@@ -49,11 +49,11 @@
4949
** May you do good and not evil.
5050
** May you find forgiveness for yourself and forgive others.
5151
** May you share freely, never taking more than you give.
5252
**
5353
*************************************************************************
54
-** This file contains code to implement the "sqlite" command line
54
+** This file contains code to implement the "sqlite3" command line
5555
** utility for accessing SQLite databases.
5656
*/
5757
#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
5858
/* This needs to come before any includes for MSVC compiler */
5959
#define _CRT_SECURE_NO_WARNINGS
@@ -79,10 +79,14 @@
7979
** should only be used when building the "fiddle" web application, as
8080
** the browser-mode build has much different user input requirements
8181
** and this build mode rewires the user input subsystem to account for
8282
** that.
8383
*/
84
+#if defined(SQLITE_SHELL_FIDDLE)
85
+# undef SQLITE_OMIT_LOAD_EXTENSION
86
+# define SQLITE_OMIT_LOAD_EXTENSION 1
87
+#endif
8488
8589
/*
8690
** Warning pragmas copied from msvc.h in the core.
8791
*/
8892
#if defined(_MSC_VER)
@@ -872,10 +876,11 @@
872876
#ifndef SQLITE_QRF_H
873877
#include "qrf.h"
874878
#endif
875879
#include <string.h>
876880
#include <assert.h>
881
+#include <stdint.h>
877882
878883
/* typedef sqlite3_int64 i64; */
879884
880885
/* A single line in the EQP output */
881886
typedef struct qrfEQPGraphRow qrfEQPGraphRow;
@@ -889,11 +894,12 @@
889894
/* All EQP output is collected into an instance of the following */
890895
typedef struct qrfEQPGraph qrfEQPGraph;
891896
struct qrfEQPGraph {
892897
qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
893898
qrfEQPGraphRow *pLast; /* Last element of the pRow list */
894
- char zPrefix[100]; /* Graph prefix */
899
+ int nWidth; /* Width of the graph */
900
+ char zPrefix[400]; /* Graph prefix */
895901
};
896902
897903
/*
898904
** Private state information. Subject to change from one release to the
899905
** next.
@@ -995,10 +1001,19 @@
9951001
*/
9961002
static void qrfOom(Qrf *p){
9971003
qrfError(p, SQLITE_NOMEM, "out of memory");
9981004
}
9991005
1006
+/*
1007
+** Transfer any error in pStr over into p.
1008
+*/
1009
+static void qrfStrErr(Qrf *p, sqlite3_str *pStr){
1010
+ int rc = pStr ? sqlite3_str_errcode(pStr) : 0;
1011
+ if( rc ){
1012
+ qrfError(p, rc, sqlite3_errstr(rc));
1013
+ }
1014
+}
10001015
10011016
10021017
/*
10031018
** Add a new entry to the EXPLAIN QUERY PLAN data
10041019
*/
@@ -1074,10 +1089,49 @@
10741089
qrfEqpRenderLevel(p, pRow->iEqpId);
10751090
p->u.pGraph->zPrefix[n] = 0;
10761091
}
10771092
}
10781093
}
1094
+
1095
+/*
1096
+** Render the 64-bit value N in a more human-readable format into
1097
+** pOut.
1098
+**
1099
+** + Only show the first three significant digits.
1100
+** + Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18
1101
+*/
1102
+static void qrfApproxInt64(sqlite3_str *pOut, i64 N){
1103
+ static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' };
1104
+ int i;
1105
+ if( N<0 ){
1106
+ N = N==INT64_MIN ? INT64_MAX : -N;
1107
+ sqlite3_str_append(pOut, "-", 1);
1108
+ }
1109
+ if( N<10000 ){
1110
+ sqlite3_str_appendf(pOut, "%4lld ", N);
1111
+ return;
1112
+ }
1113
+ for(i=1; i<=18; i++){
1114
+ N = (N+5)/10;
1115
+ if( N<10000 ){
1116
+ int n = (int)N;
1117
+ switch( i%3 ){
1118
+ case 0:
1119
+ sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10);
1120
+ break;
1121
+ case 1:
1122
+ sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10);
1123
+ break;
1124
+ case 2:
1125
+ sqlite3_str_appendf(pOut, "%4d", n/10);
1126
+ break;
1127
+ }
1128
+ sqlite3_str_append(pOut, &aSuffix[i/3], 1);
1129
+ break;
1130
+ }
1131
+ }
1132
+}
10791133
10801134
/*
10811135
** Display and reset the EXPLAIN QUERY PLAN data
10821136
*/
10831137
static void qrfEqpRender(Qrf *p, i64 nCycle){
@@ -1090,11 +1144,30 @@
10901144
}
10911145
sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3);
10921146
p->u.pGraph->pRow = pRow->pNext;
10931147
sqlite3_free(pRow);
10941148
}else if( nCycle>0 ){
1095
- sqlite3_str_appendf(p->pOut, "QUERY PLAN (cycles=%lld [100%%])\n",nCycle);
1149
+ int nSp = p->u.pGraph->nWidth - 2;
1150
+ if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1151
+ sqlite3_str_appendchar(p->pOut, nSp, ' ');
1152
+ sqlite3_str_appendall(p->pOut,
1153
+ "Cycles Loops (est) Rows (est)\n");
1154
+ sqlite3_str_appendchar(p->pOut, nSp, ' ');
1155
+ sqlite3_str_appendall(p->pOut,
1156
+ "---------- ------------ ------------\n");
1157
+ }else{
1158
+ sqlite3_str_appendchar(p->pOut, nSp, ' ');
1159
+ sqlite3_str_appendall(p->pOut,
1160
+ "Cycles Loops Rows \n");
1161
+ sqlite3_str_appendchar(p->pOut, nSp, ' ');
1162
+ sqlite3_str_appendall(p->pOut,
1163
+ "---------- ----- -----\n");
1164
+ }
1165
+ sqlite3_str_appendall(p->pOut, "QUERY PLAN");
1166
+ sqlite3_str_appendchar(p->pOut, nSp - 10, ' ');
1167
+ qrfApproxInt64(p->pOut, nCycle);
1168
+ sqlite3_str_appendall(p->pOut, " 100%\n");
10961169
}else{
10971170
sqlite3_str_appendall(p->pOut, "QUERY PLAN\n");
10981171
}
10991172
p->u.pGraph->zPrefix[0] = 0;
11001173
qrfEqpRenderLevel(p, 0);
@@ -1145,10 +1218,12 @@
11451218
static const int f = SQLITE_SCANSTAT_COMPLEX;
11461219
sqlite3_stmt *pS = p->pStmt;
11471220
int i = 0;
11481221
i64 nTotal = 0;
11491222
int nWidth = 0;
1223
+ int prevPid = -1; /* Previous iPid */
1224
+ double rEstCum = 1.0; /* Cumulative row estimate */
11501225
sqlite3_str *pLine = sqlite3_str_new(p->db);
11511226
sqlite3_str *pStats = sqlite3_str_new(p->db);
11521227
qrfEqpReset(p);
11531228
11541229
for(i=0; 1; i++){
@@ -1158,11 +1233,11 @@
11581233
break;
11591234
}
11601235
n = (int)strlen(z) + qrfStatsHeight(pS,i)*3;
11611236
if( n>nWidth ) nWidth = n;
11621237
}
1163
- nWidth += 4;
1238
+ nWidth += 2;
11641239
11651240
sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal);
11661241
for(i=0; 1; i++){
11671242
i64 nLoop = 0;
11681243
i64 nRow = 0;
@@ -1173,55 +1248,67 @@
11731248
const char *zName = 0;
11741249
double rEst = 0.0;
11751250
11761251
if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){
11771252
break;
1253
+ }
1254
+ sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
1255
+ if( iPid!=prevPid ){
1256
+ prevPid = iPid;
1257
+ rEstCum = 1.0;
11781258
}
11791259
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst);
1260
+ rEstCum *= rEst;
11801261
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop);
11811262
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow);
11821263
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle);
11831264
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId);
1184
- sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
11851265
sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName);
11861266
11871267
if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
1188
- const char *zSp = "";
1189
- double rpl;
1268
+ int nSp = 0;
11901269
sqlite3_str_reset(pStats);
11911270
if( nCycle>=0 && nTotal>0 ){
1192
- sqlite3_str_appendf(pStats, "cycles=%lld [%d%%]",
1193
- nCycle, ((nCycle*100)+nTotal/2) / nTotal
1271
+ qrfApproxInt64(pStats, nCycle);
1272
+ sqlite3_str_appendf(pStats, " %3d%%",
1273
+ ((nCycle*100)+nTotal/2) / nTotal
11941274
);
1195
- zSp = " ";
1275
+ nSp = 2;
11961276
}
11971277
if( nLoop>=0 ){
1198
- sqlite3_str_appendf(pStats, "%sloops=%lld", zSp, nLoop);
1199
- zSp = " ";
1278
+ if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
1279
+ qrfApproxInt64(pStats, nLoop);
1280
+ nSp = 2;
1281
+ if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1282
+ sqlite3_str_appendf(pStats, " ");
1283
+ qrfApproxInt64(pStats, (i64)(rEstCum/rEst));
1284
+ }
12001285
}
12011286
if( nRow>=0 ){
1202
- sqlite3_str_appendf(pStats, "%srows=%lld", zSp, nRow);
1203
- zSp = " ";
1204
- }
1205
-
1206
- if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1207
- rpl = (double)nRow / (double)nLoop;
1208
- sqlite3_str_appendf(pStats, "%srpl=%.1f est=%.1f", zSp, rpl, rEst);
1209
- }
1210
-
1287
+ if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
1288
+ qrfApproxInt64(pStats, nRow);
1289
+ nSp = 2;
1290
+ if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1291
+ sqlite3_str_appendf(pStats, " ");
1292
+ qrfApproxInt64(pStats, (i64)rEstCum);
1293
+ }
1294
+ }
12111295
sqlite3_str_appendf(pLine,
1212
- "% *s (%s)", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo,
1296
+ "% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo,
12131297
sqlite3_str_value(pStats)
12141298
);
12151299
sqlite3_str_reset(pStats);
12161300
qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine));
12171301
sqlite3_str_reset(pLine);
12181302
}else{
12191303
qrfEqpAppend(p, iId, iPid, zo);
12201304
}
12211305
}
1306
+ if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth;
1307
+ qrfStrErr(p, pLine);
12221308
sqlite3_free(sqlite3_str_finish(pLine));
1309
+ qrfStrErr(p, pStats);
12231310
sqlite3_free(sqlite3_str_finish(pStats));
12241311
#endif
12251312
}
12261313
12271314
@@ -1581,13 +1668,15 @@
15811668
** (3) z[] does not looks like a numeric literal
15821669
*/
15831670
static int qrfRelaxable(Qrf *p, const char *z){
15841671
size_t i, n;
15851672
if( z[0]=='\'' || qrfSpace(z[0]) ) return 0;
1586
- if( z[0]==0 && (p->spec.zNull==0 || p->spec.zNull[0]==0) ) return 0;
1673
+ if( z[0]==0 ){
1674
+ return (p->spec.zNull!=0 && p->spec.zNull[0]!=0);
1675
+ }
15871676
n = strlen(z);
1588
- if( z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
1677
+ if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
15891678
if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0;
15901679
i = (z[0]=='-' || z[0]=='+');
15911680
if( strcmp(z+i,"Inf")==0 ) return 0;
15921681
if( !qrfDigit(z[i]) ) return 1;
15931682
i++;
@@ -2729,10 +2818,11 @@
27292818
int nNL = 0;
27302819
int n, w;
27312820
pStr = sqlite3_str_new(p->db);
27322821
qrfEncodeText(p, pStr, z ? z : "");
27332822
n = sqlite3_str_length(pStr);
2823
+ qrfStrErr(p, pStr);
27342824
z = data.az[data.n] = sqlite3_str_finish(pStr);
27352825
if( p->spec.nTitleLimit ){
27362826
nNL = 0;
27372827
data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
27382828
p->spec.nTitleLimit );
@@ -2756,10 +2846,11 @@
27562846
int n, w;
27572847
int eType = sqlite3_column_type(p->pStmt,i);
27582848
pStr = sqlite3_str_new(p->db);
27592849
qrfRenderValue(p, pStr, i);
27602850
n = sqlite3_str_length(pStr);
2851
+ qrfStrErr(p, pStr);
27612852
z = data.az[data.n] = sqlite3_str_finish(pStr);
27622853
data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
27632854
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
27642855
data.n++;
27652856
if( w>data.a[i].mxW ) data.a[i].mxW = w;
@@ -2910,11 +3001,11 @@
29103001
){
29113002
bRTrim = 1;
29123003
}else{
29133004
bRTrim = 0;
29143005
}
2915
- for(i=0; i<data.n; i+=nColumn){
3006
+ for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){
29163007
int bMore;
29173008
int nRow = 0;
29183009
29193010
/* Draw a single row of the table. This might be the title line
29203011
** (if there is a title line) or a row in the body of the table.
@@ -3097,11 +3188,11 @@
30973188
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
30983189
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
30993190
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
31003191
assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
31013192
3102
- for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt); iOp++){
3193
+ for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){
31033194
int iAddr = sqlite3_column_int(p->pStmt, 0);
31043195
const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
31053196
int p1 = sqlite3_column_int(p->pStmt, 2);
31063197
int p2 = sqlite3_column_int(p->pStmt, 3);
31073198
@@ -3154,11 +3245,11 @@
31543245
nWidth = sizeof(aScanExpWidth)/sizeof(int);
31553246
iIndent = 3;
31563247
}
31573248
if( nArg>nWidth ) nArg = nWidth;
31583249
3159
- for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW; iOp++){
3250
+ for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){
31603251
/* If this is the first row seen, print out the headers */
31613252
if( iOp==0 ){
31623253
for(i=0; i<nArg; i++){
31633254
const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
31643255
qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
@@ -3410,10 +3501,11 @@
34103501
sqlite3_str_append(p->pOut, "\n", 1);
34113502
zVal += iNext;
34123503
}while( zVal[0] );
34133504
sqlite3_str_reset(pVal);
34143505
}
3506
+ qrfStrErr(p, pVal);
34153507
sqlite3_free(sqlite3_str_finish(pVal));
34163508
qrfWrite(p);
34173509
break;
34183510
}
34193511
case QRF_STYLE_Eqp: {
@@ -3473,11 +3565,11 @@
34733565
p->pOut = sqlite3_str_new(p->db);
34743566
if( p->pOut==0 ){
34753567
qrfOom(p);
34763568
return;
34773569
}
3478
- p->iErr = 0;
3570
+ p->iErr = SQLITE_OK;
34793571
p->nCol = sqlite3_column_count(p->pStmt);
34803572
p->nRow = 0;
34813573
sz = sizeof(sqlite3_qrf_spec);
34823574
memcpy(&p->spec, pSpec, sz);
34833575
if( p->spec.zNull==0 ) p->spec.zNull = "";
@@ -3644,17 +3736,27 @@
36443736
sqlite3_free(p->u.sLine.azCol);
36453737
}
36463738
break;
36473739
}
36483740
case QRF_STYLE_Stats:
3649
- case QRF_STYLE_StatsEst:
3741
+ case QRF_STYLE_StatsEst: {
3742
+ i64 nCycle = 0;
3743
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
3744
+ sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE,
3745
+ SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle);
3746
+#endif
3747
+ qrfEqpRender(p, nCycle);
3748
+ qrfWrite(p);
3749
+ break;
3750
+ }
36503751
case QRF_STYLE_Eqp: {
36513752
qrfEqpRender(p, 0);
36523753
qrfWrite(p);
36533754
break;
36543755
}
36553756
}
3757
+ qrfStrErr(p, p->pOut);
36563758
if( p->spec.pzOutput ){
36573759
if( p->spec.pzOutput[0] ){
36583760
sqlite3_int64 n, sz;
36593761
char *zCombined;
36603762
sz = strlen(p->spec.pzOutput[0]);
@@ -3815,13 +3917,10 @@
38153917
38163918
38173919
#define eputz(z) cli_puts(z,stderr)
38183920
#define sputz(fp,z) cli_puts(z,fp)
38193921
3820
-/* True if the timer is enabled */
3821
-static int enableTimer = 0;
3822
-
38233922
/* A version of strcmp() that works with NULL values */
38243923
static int cli_strcmp(const char *a, const char *b){
38253924
if( a==0 ) a = "";
38263925
if( b==0 ) b = "";
38273926
return strcmp(a,b);
@@ -3834,11 +3933,11 @@
38343933
38353934
/* Return the current wall-clock time in microseconds since the
38363935
** Unix epoch (1970-01-01T00:00:00Z)
38373936
*/
38383937
static sqlite3_int64 timeOfDay(void){
3839
-#if defined(_WIN64)
3938
+#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
38403939
sqlite3_uint64 t;
38413940
FILETIME tm;
38423941
GetSystemTimePreciseAsFileTime(&tm);
38433942
t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
38443943
t += 116444736000000000LL;
@@ -3862,154 +3961,10 @@
38623961
(void)gettimeofday(&sNow,0);
38633962
return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
38643963
#endif
38653964
}
38663965
3867
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
3868
-#include <sys/time.h>
3869
-#include <sys/resource.h>
3870
-
3871
-/* VxWorks does not support getrusage() as far as we can determine */
3872
-#if defined(_WRS_KERNEL) || defined(__RTP__)
3873
-struct rusage {
3874
- struct timeval ru_utime; /* user CPU time used */
3875
- struct timeval ru_stime; /* system CPU time used */
3876
-};
3877
-#define getrusage(A,B) memset(B,0,sizeof(*B))
3878
-#endif
3879
-
3880
-
3881
-/* Saved resource information for the beginning of an operation */
3882
-static struct rusage sBegin; /* CPU time at start */
3883
-static sqlite3_int64 iBegin; /* Wall-clock time at start */
3884
-
3885
-/*
3886
-** Begin timing an operation
3887
-*/
3888
-static void beginTimer(void){
3889
- if( enableTimer ){
3890
- getrusage(RUSAGE_SELF, &sBegin);
3891
- iBegin = timeOfDay();
3892
- }
3893
-}
3894
-
3895
-/* Return the difference of two time_structs in seconds */
3896
-static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
3897
- return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
3898
- (double)(pEnd->tv_sec - pStart->tv_sec);
3899
-}
3900
-
3901
-/*
3902
-** Print the timing results.
3903
-*/
3904
-static void endTimer(FILE *out){
3905
- if( enableTimer ){
3906
- sqlite3_int64 iEnd = timeOfDay();
3907
- struct rusage sEnd;
3908
- getrusage(RUSAGE_SELF, &sEnd);
3909
- cli_printf(out, "Run Time: real %.6f user %.6f sys %.6f\n",
3910
- (iEnd - iBegin)*0.000001,
3911
- timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
3912
- timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
3913
- }
3914
-}
3915
-
3916
-#define BEGIN_TIMER beginTimer()
3917
-#define END_TIMER(X) endTimer(X)
3918
-#define HAS_TIMER 1
3919
-
3920
-#elif (defined(_WIN32) || defined(WIN32))
3921
-
3922
-/* Saved resource information for the beginning of an operation */
3923
-static HANDLE hProcess;
3924
-static FILETIME ftKernelBegin;
3925
-static FILETIME ftUserBegin;
3926
-static sqlite3_int64 ftWallBegin;
3927
-typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
3928
- LPFILETIME, LPFILETIME);
3929
-static GETPROCTIMES getProcessTimesAddr = NULL;
3930
-
3931
-/*
3932
-** Check to see if we have timer support. Return 1 if necessary
3933
-** support found (or found previously).
3934
-*/
3935
-static int hasTimer(void){
3936
- if( getProcessTimesAddr ){
3937
- return 1;
3938
- } else {
3939
- /* GetProcessTimes() isn't supported in WIN95 and some other Windows
3940
- ** versions. See if the version we are running on has it, and if it
3941
- ** does, save off a pointer to it and the current process handle.
3942
- */
3943
- hProcess = GetCurrentProcess();
3944
- if( hProcess ){
3945
- HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
3946
- if( NULL != hinstLib ){
3947
- getProcessTimesAddr =
3948
- (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
3949
- if( NULL != getProcessTimesAddr ){
3950
- return 1;
3951
- }
3952
- FreeLibrary(hinstLib);
3953
- }
3954
- }
3955
- }
3956
- return 0;
3957
-}
3958
-
3959
-/*
3960
-** Begin timing an operation
3961
-*/
3962
-static void beginTimer(void){
3963
- if( enableTimer && getProcessTimesAddr ){
3964
- FILETIME ftCreation, ftExit;
3965
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
3966
- &ftKernelBegin,&ftUserBegin);
3967
- ftWallBegin = timeOfDay();
3968
- }
3969
-}
3970
-
3971
-/* Return the difference of two FILETIME structs in seconds */
3972
-static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
3973
- sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
3974
- sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
3975
- return (double) ((i64End - i64Start) / 10000000.0);
3976
-}
3977
-
3978
-/*
3979
-** Print the timing results.
3980
-*/
3981
-static void endTimer(FILE *out){
3982
- if( enableTimer && getProcessTimesAddr){
3983
- FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
3984
- sqlite3_int64 ftWallEnd = timeOfDay();
3985
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
3986
-#ifdef _WIN64
3987
- /* microsecond precision on 64-bit windows */
3988
- cli_printf(out, "Run Time: real %.6f user %f sys %f\n",
3989
- (ftWallEnd - ftWallBegin)*0.000001,
3990
- timeDiff(&ftUserBegin, &ftUserEnd),
3991
- timeDiff(&ftKernelBegin, &ftKernelEnd));
3992
-#else
3993
- /* millisecond precisino on 32-bit windows */
3994
- cli_printf(out, "Run Time: real %.3f user %.3f sys %.3f\n",
3995
- (ftWallEnd - ftWallBegin)*0.000001,
3996
- timeDiff(&ftUserBegin, &ftUserEnd),
3997
- timeDiff(&ftKernelBegin, &ftKernelEnd));
3998
-#endif
3999
- }
4000
-}
4001
-
4002
-#define BEGIN_TIMER beginTimer()
4003
-#define END_TIMER(X) endTimer(X)
4004
-#define HAS_TIMER hasTimer()
4005
-
4006
-#else
4007
-#define BEGIN_TIMER
4008
-#define END_TIMER(X) /*no-op*/
4009
-#define HAS_TIMER 0
4010
-#endif
40113966
40123967
/*
40133968
** Used to prevent warnings about unused parameters
40143969
*/
40153970
#define UNUSED_PARAMETER(x) (void)(x)
@@ -4068,10 +4023,18 @@
40684023
#define PROMPT_LEN_MAX 128
40694024
/* First line prompt. default: "sqlite> " */
40704025
static char mainPrompt[PROMPT_LEN_MAX];
40714026
/* Continuation prompt. default: " ...> " */
40724027
static char continuePrompt[PROMPT_LEN_MAX];
4028
+
4029
+/*
4030
+** Write I/O traces to the following stream.
4031
+*/
4032
+#ifdef SQLITE_ENABLE_IOTRACE
4033
+static FILE *iotrace = 0;
4034
+#endif
4035
+
40734036
40744037
/* This is variant of the standard-library strncpy() routine with the
40754038
** one change that the destination string is always zero-terminated, even
40764039
** if there is no zero-terminator in the first n-1 characters of the source
40774040
** string.
@@ -4188,17 +4151,10 @@
41884151
*/
41894152
static void shell_check_oom(const void *p){
41904153
if( p==0 ) shell_out_of_memory();
41914154
}
41924155
4193
-/*
4194
-** Write I/O traces to the following stream.
4195
-*/
4196
-#ifdef SQLITE_ENABLE_IOTRACE
4197
-static FILE *iotrace = 0;
4198
-#endif
4199
-
42004156
/*
42014157
** This routine works like printf in that its first argument is a
42024158
** format string and subsequent arguments are values to be substituted
42034159
** in place of % fields. The result of formatting this string
42044160
** is written to iotrace.
@@ -8349,13 +8305,13 @@
83498305
}else if( e<-10000 ){
83508306
e = -10000;
83518307
}
83528308
83538309
if( m<0 ){
8310
+ if( m<(-9223372036854775807LL) ) return;
83548311
isNeg = 1;
83558312
m = -m;
8356
- if( m<0 ) return;
83578313
}else if( m==0 && e>-1000 && e<1000 ){
83588314
sqlite3_result_double(context, 0.0);
83598315
return;
83608316
}
83618317
while( (m>>32)&0xffe00000 ){
@@ -9472,11 +9428,11 @@
94729428
** (X) match X
94739429
** X|Y X or Y
94749430
** ^X X occurring at the beginning of the string
94759431
** X$ X occurring at the end of the string
94769432
** . Match any single character
9477
-** \c Character c where c is one of \{}()[]|*+?.
9433
+** \c Character c where c is one of \{}()[]|*+?-.
94789434
** \c C-language escapes for c in afnrtv. ex: \t or \n
94799435
** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
94809436
** \xXX Where XX is exactly 2 hex digits, unicode value XX
94819437
** [abc] Any single character from the set abc
94829438
** [^abc] Any single character not in the set abc
@@ -9857,11 +9813,11 @@
98579813
98589814
/* A backslash character has been seen, read the next character and
98599815
** return its interpretation.
98609816
*/
98619817
static unsigned re_esc_char(ReCompiled *p){
9862
- static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
9818
+ static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-";
98639819
static const char zTrans[] = "\a\f\n\r\t\v";
98649820
int i, v = 0;
98659821
char c;
98669822
if( p->sIn.i>=p->sIn.mx ) return 0;
98679823
c = p->sIn.z[p->sIn.i];
@@ -10180,15 +10136,22 @@
1018010136
}
1018110137
return pRe->zErr;
1018210138
}
1018310139
1018410140
/*
10185
-** Compute a reasonable limit on the length of the REGEXP NFA.
10141
+** The value of LIMIT_MAX_PATTERN_LENGTH.
1018610142
*/
1018710143
static int re_maxlen(sqlite3_context *context){
1018810144
sqlite3 *db = sqlite3_context_db_handle(context);
10189
- return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2;
10145
+ return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1);
10146
+}
10147
+
10148
+/*
10149
+** Maximum NFA size given a maximum pattern length.
10150
+*/
10151
+static int re_maxnfa(int mxlen){
10152
+ return 75+mxlen/2;
1019010153
}
1019110154
1019210155
/*
1019310156
** Implementation of the regexp() SQL function. This function implements
1019410157
** the build-in REGEXP operator. The first argument to the function is the
@@ -10210,14 +10173,21 @@
1021010173
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
1021110174
1021210175
(void)argc; /* Unused */
1021310176
pRe = sqlite3_get_auxdata(context, 0);
1021410177
if( pRe==0 ){
10178
+ int mxLen = re_maxlen(context);
10179
+ int nPattern;
1021510180
zPattern = (const char*)sqlite3_value_text(argv[0]);
1021610181
if( zPattern==0 ) return;
10217
- zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10218
- sqlite3_user_data(context)!=0);
10182
+ nPattern = sqlite3_value_bytes(argv[0]);
10183
+ if( nPattern>mxLen ){
10184
+ zErr = "REGEXP pattern too big";
10185
+ }else{
10186
+ zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen),
10187
+ sqlite3_user_data(context)!=0);
10188
+ }
1021910189
if( zErr ){
1022010190
re_free(pRe);
1022110191
sqlite3_result_error(context, zErr, -1);
1022210192
return;
1022310193
}
@@ -10279,11 +10249,11 @@
1027910249
"ATSTART",
1028010250
};
1028110251
1028210252
zPattern = (const char*)sqlite3_value_text(argv[0]);
1028310253
if( zPattern==0 ) return;
10284
- zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10254
+ zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)),
1028510255
sqlite3_user_data(context)!=0);
1028610256
if( zErr ){
1028710257
re_free(pRe);
1028810258
sqlite3_result_error(context, zErr, -1);
1028910259
return;
@@ -13067,11 +13037,11 @@
1306713037
nFile = (int)strlen(zFile)+1;
1306813038
}
1306913039
1307013040
rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
1307113041
if( rc==SQLITE_OK ){
13072
- pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
13042
+ pNew = (ZipfileTab*)sqlite3_malloc64((i64)nByte+nFile);
1307313043
if( pNew==0 ) return SQLITE_NOMEM;
1307413044
memset(pNew, 0, nByte+nFile);
1307513045
pNew->db = db;
1307613046
pNew->aBuffer = (u8*)&pNew[1];
1307713047
if( zFile ){
@@ -13213,18 +13183,19 @@
1321313183
** sqlite3_free().
1321413184
*/
1321513185
static int zipfileReadData(
1321613186
FILE *pFile, /* Read from this file */
1321713187
u8 *aRead, /* Read into this buffer */
13218
- int nRead, /* Number of bytes to read */
13188
+ i64 nRead, /* Number of bytes to read */
1321913189
i64 iOff, /* Offset to read from */
1322013190
char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
1322113191
){
1322213192
size_t n;
1322313193
fseek(pFile, (long)iOff, SEEK_SET);
13224
- n = fread(aRead, 1, nRead, pFile);
13225
- if( (int)n!=nRead ){
13194
+ n = fread(aRead, 1, (long)nRead, pFile);
13195
+ if( n!=(size_t)nRead ){
13196
+ sqlite3_free(*pzErrmsg);
1322613197
*pzErrmsg = sqlite3_mprintf("error in fread()");
1322713198
return SQLITE_ERROR;
1322813199
}
1322913200
return SQLITE_OK;
1323013201
}
@@ -13237,11 +13208,11 @@
1323713208
if( nWrite>0 ){
1323813209
size_t n = nWrite;
1323913210
fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
1324013211
n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
1324113212
if( (int)n!=nWrite ){
13242
- pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
13213
+ zipfileTableErr(pTab,"error in fwrite()");
1324313214
return SQLITE_ERROR;
1324413215
}
1324513216
pTab->szCurrent += nWrite;
1324613217
}
1324713218
return SQLITE_OK;
@@ -13484,10 +13455,11 @@
1348413455
/*
1348513456
** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a
1348613457
** generic corruption message and return SQLITE_CORRUPT;
1348713458
*/
1348813459
static int zipfileCorrupt(char **pzErr){
13460
+ sqlite3_free(*pzErr);
1348913461
*pzErr = sqlite3_mprintf("zip archive is corrupt");
1349013462
return SQLITE_CORRUPT;
1349113463
}
1349213464
1349313465
/*
@@ -13502,11 +13474,11 @@
1350213474
** final value of (*ppEntry) undefined.
1350313475
*/
1350413476
static int zipfileGetEntry(
1350513477
ZipfileTab *pTab, /* Store any error message here */
1350613478
const u8 *aBlob, /* Pointer to in-memory file image */
13507
- int nBlob, /* Size of aBlob[] in bytes */
13479
+ i64 nBlob, /* Size of aBlob[] in bytes */
1350813480
FILE *pFile, /* If aBlob==0, read from this file */
1350913481
i64 iOff, /* Offset of CDS record */
1351013482
ZipfileEntry **ppEntry /* OUT: Pointer to new object */
1351113483
){
1351213484
u8 *aRead;
@@ -13542,18 +13514,18 @@
1354213514
rc = SQLITE_NOMEM;
1354313515
}else{
1354413516
memset(pNew, 0, sizeof(ZipfileEntry));
1354513517
rc = zipfileReadCDS(aRead, &pNew->cds);
1354613518
if( rc!=SQLITE_OK ){
13547
- *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
13519
+ zipfileTableErr(pTab, "failed to read CDS at offset %lld", iOff);
1354813520
}else if( aBlob==0 ){
1354913521
rc = zipfileReadData(
1355013522
pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
1355113523
);
1355213524
}else{
1355313525
aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
13554
- if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){
13526
+ if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){
1355513527
rc = zipfileCorrupt(pzErr);
1355613528
}
1355713529
}
1355813530
}
1355913531
@@ -13574,19 +13546,19 @@
1357413546
ZipfileLFH lfh;
1357513547
if( pFile ){
1357613548
rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
1357713549
}else{
1357813550
aRead = (u8*)&aBlob[pNew->cds.iOffset];
13579
- if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>(unsigned)nBlob ){
13551
+ if( ((i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){
1358013552
rc = zipfileCorrupt(pzErr);
1358113553
}
1358213554
}
1358313555
1358413556
memset(&lfh, 0, sizeof(lfh));
1358513557
if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
1358613558
if( rc==SQLITE_OK ){
13587
- pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
13559
+ pNew->iDataOff = (i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
1358813560
pNew->iDataOff += lfh.nFile + lfh.nExtra;
1358913561
if( aBlob && pNew->cds.szCompressed ){
1359013562
if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){
1359113563
rc = zipfileCorrupt(pzErr);
1359213564
}else{
@@ -13593,11 +13565,11 @@
1359313565
pNew->aData = &pNew->aExtra[nExtra];
1359413566
memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
1359513567
}
1359613568
}
1359713569
}else{
13598
- *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
13570
+ zipfileTableErr(pTab, "failed to read LFH at offset %d",
1359913571
(int)pNew->cds.iOffset
1360013572
);
1360113573
}
1360213574
}
1360313575
@@ -13617,11 +13589,11 @@
1361713589
static int zipfileNext(sqlite3_vtab_cursor *cur){
1361813590
ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1361913591
int rc = SQLITE_OK;
1362013592
1362113593
if( pCsr->pFile ){
13622
- i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
13594
+ i64 iEof = (i64)pCsr->eocd.iOffset + (i64)pCsr->eocd.nSize;
1362313595
zipfileEntryFree(pCsr->pCurrent);
1362413596
pCsr->pCurrent = 0;
1362513597
if( pCsr->iNextOff>=iEof ){
1362613598
pCsr->bEof = 1;
1362713599
}else{
@@ -13855,16 +13827,16 @@
1385513827
** an English language error message may be left in virtual-table pTab.
1385613828
*/
1385713829
static int zipfileReadEOCD(
1385813830
ZipfileTab *pTab, /* Return errors here */
1385913831
const u8 *aBlob, /* Pointer to in-memory file image */
13860
- int nBlob, /* Size of aBlob[] in bytes */
13832
+ i64 nBlob, /* Size of aBlob[] in bytes */
1386113833
FILE *pFile, /* Read from this file if aBlob==0 */
1386213834
ZipfileEOCD *pEOCD /* Object to populate */
1386313835
){
1386413836
u8 *aRead = pTab->aBuffer; /* Temporary buffer */
13865
- int nRead; /* Bytes to read from file */
13837
+ i64 nRead; /* Bytes to read from file */
1386613838
int rc = SQLITE_OK;
1386713839
1386813840
memset(pEOCD, 0, sizeof(ZipfileEOCD));
1386913841
if( aBlob==0 ){
1387013842
i64 iOff; /* Offset to read from */
@@ -13881,11 +13853,11 @@
1388113853
nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
1388213854
aRead = (u8*)&aBlob[nBlob-nRead];
1388313855
}
1388413856
1388513857
if( rc==SQLITE_OK ){
13886
- int i;
13858
+ i64 i;
1388713859
1388813860
/* Scan backwards looking for the signature bytes */
1388913861
for(i=nRead-20; i>=0; i--){
1389013862
if( aRead[i]==0x50 && aRead[i+1]==0x4b
1389113863
&& aRead[i+2]==0x05 && aRead[i+3]==0x06
@@ -13892,13 +13864,11 @@
1389213864
){
1389313865
break;
1389413866
}
1389513867
}
1389613868
if( i<0 ){
13897
- pTab->base.zErrMsg = sqlite3_mprintf(
13898
- "cannot find end of central directory record"
13899
- );
13869
+ zipfileTableErr(pTab, "cannot find end of central directory record");
1390013870
return SQLITE_ERROR;
1390113871
}
1390213872
1390313873
aRead += i+4;
1390413874
pEOCD->iDisk = zipfileRead16(aRead);
@@ -13939,11 +13909,11 @@
1393913909
pNew->pNext = pBefore;
1394013910
*pp = pNew;
1394113911
}
1394213912
}
1394313913
13944
-static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
13914
+static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){
1394513915
ZipfileEOCD eocd;
1394613916
int rc;
1394713917
int i;
1394813918
i64 iOff;
1394913919
@@ -13987,11 +13957,11 @@
1398713957
zipfileCursorErr(pCsr, "zipfile() function requires an argument");
1398813958
return SQLITE_ERROR;
1398913959
}else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
1399013960
static const u8 aEmptyBlob = 0;
1399113961
const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
13992
- int nBlob = sqlite3_value_bytes(argv[0]);
13962
+ i64 nBlob = sqlite3_value_bytes(argv[0]);
1399313963
assert( pTab->pFirstEntry==0 );
1399413964
if( aBlob==0 ){
1399513965
aBlob = &aEmptyBlob;
1399613966
nBlob = 0;
1399713967
}
@@ -14185,23 +14155,23 @@
1418514155
ZipfileTab *pTab = (ZipfileTab*)pVtab;
1418614156
int rc = SQLITE_OK;
1418714157
1418814158
assert( pTab->pWriteFd==0 );
1418914159
if( pTab->zFile==0 || pTab->zFile[0]==0 ){
14190
- pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
14160
+ zipfileTableErr(pTab, "zipfile: missing filename");
1419114161
return SQLITE_ERROR;
1419214162
}
1419314163
1419414164
/* Open a write fd on the file. Also load the entire central directory
1419514165
** structure into memory. During the transaction any new file data is
1419614166
** appended to the archive file, but the central directory is accumulated
1419714167
** in main-memory until the transaction is committed. */
1419814168
pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
1419914169
if( pTab->pWriteFd==0 ){
14200
- pTab->base.zErrMsg = sqlite3_mprintf(
14201
- "zipfile: failed to open file %s for writing", pTab->zFile
14202
- );
14170
+ zipfileTableErr(pTab,
14171
+ "zipfile: failed to open file %s for writing", pTab->zFile
14172
+ );
1420314173
rc = SQLITE_ERROR;
1420414174
}else{
1420514175
fseek(pTab->pWriteFd, 0, SEEK_END);
1420614176
pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
1420714177
rc = zipfileLoadDirectory(pTab, 0, 0);
@@ -14662,11 +14632,11 @@
1466214632
int nEntry;
1466314633
ZipfileBuffer body;
1466414634
ZipfileBuffer cds;
1466514635
};
1466614636
14667
-static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
14637
+static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
1466814638
if( pBuf->n+nByte>pBuf->nAlloc ){
1466914639
u8 *aNew;
1467014640
sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
1467114641
int nReq = pBuf->n + nByte;
1467214642
@@ -14711,11 +14681,11 @@
1471114681
u32 iCrc32 = 0; /* crc32 of uncompressed data */
1471214682
1471314683
char *zName = 0; /* Path (name) of new entry */
1471414684
int nName = 0; /* Size of zName in bytes */
1471514685
char *zFree = 0; /* Free this before returning */
14716
- int nByte;
14686
+ i64 nByte;
1471714687
1471814688
memset(&e, 0, sizeof(e));
1471914689
p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
1472014690
if( p==0 ) return;
1472114691
@@ -24161,28 +24131,28 @@
2416124131
u8 autoExplain; /* Automatically turn on .explain mode */
2416224132
u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
2416324133
u8 autoEQPtrace; /* autoEQP is in trace mode */
2416424134
u8 scanstatsOn; /* True to display scan stats before each finalize */
2416524135
u8 bAutoScreenWidth; /* Using the TTY to determine screen width */
24166
- u8 mFlags; /* MFLG_ECHO and/or MFLG_CRLF */
24136
+ u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */
2416724137
u8 eMode; /* One of the MODE_ values */
2416824138
sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
2416924139
} Mode;
2417024140
2417124141
/* Flags for Mode.mFlags */
2417224142
#define MFLG_ECHO 0x01 /* Echo inputs to output */
2417324143
#define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
24144
+#define MFLG_HDR 0x04 /* .header used to change headers on/off */
2417424145
2417524146
2417624147
/*
2417724148
** State information about the database connection is contained in an
2417824149
** instance of the following structure.
2417924150
*/
2418024151
typedef struct ShellState ShellState;
2418124152
struct ShellState {
2418224153
sqlite3 *db; /* The database */
24183
- int iCompat; /* Compatibility date YYYYMMDD */
2418424154
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
2418524155
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
2418624156
u8 nEqpLevel; /* Depth of the EQP output graph */
2418724157
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
2418824158
u8 bSafeMode; /* True to prohibit unsafe operations */
@@ -24190,11 +24160,14 @@
2419024160
u8 eRestoreState; /* See comments above doAutoDetectRestore() */
2419124161
unsigned statsOn; /* True to display memory stats before each finalize */
2419224162
unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
2419324163
u8 nPopOutput; /* Revert .output settings when reaching zero */
2419424164
u8 nPopMode; /* Revert .mode settings when reaching zero */
24165
+ u8 enableTimer; /* Enable the timer. 2: permanently 1: only once */
2419524166
int inputNesting; /* Track nesting level of .read and other redirects */
24167
+ double prevTimer; /* Last reported timer value */
24168
+ double tmProgress; /* --timeout option for .progress */
2419624169
i64 lineno; /* Line number of last line read from in */
2419724170
const char *zInFile; /* Name of the input file */
2419824171
int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
2419924172
FILE *in; /* Read commands from this stream */
2420024173
FILE *out; /* Write results here */
@@ -24286,10 +24259,11 @@
2428624259
#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
2428724260
#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress
2428824261
** callback limit is reached, and for each
2428924262
** top-level SQL statement */
2429024263
#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
24264
+#define SHELL_PROGRESS_TMOUT 0x08 /* Stop after tmProgress seconds */
2429124265
2429224266
/* Names of values for Mode.spec.eEsc and Mode.spec.eText
2429324267
*/
2429424268
static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
2429524269
static const char *qrfQuoteNames[] =
@@ -24447,10 +24421,181 @@
2444724421
** Limit input nesting via .read or any other input redirect.
2444824422
** It's not too expensive, so a generous allowance can be made.
2444924423
*/
2445024424
#define MAX_INPUT_NESTING 25
2445124425
24426
+/************************* BEGIN PERFORMANCE TIMER *****************************/
24427
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
24428
+#include <sys/time.h>
24429
+#include <sys/resource.h>
24430
+/* VxWorks does not support getrusage() as far as we can determine */
24431
+#if defined(_WRS_KERNEL) || defined(__RTP__)
24432
+struct rusage {
24433
+ struct timeval ru_utime; /* user CPU time used */
24434
+ struct timeval ru_stime; /* system CPU time used */
24435
+};
24436
+#define getrusage(A,B) memset(B,0,sizeof(*B))
24437
+#endif
24438
+
24439
+/* Saved resource information for the beginning of an operation */
24440
+static struct rusage sBegin; /* CPU time at start */
24441
+static sqlite3_int64 iBegin; /* Wall-clock time at start */
24442
+
24443
+/*
24444
+** Begin timing an operation
24445
+*/
24446
+static void beginTimer(ShellState *p){
24447
+ if( p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 ){
24448
+ getrusage(RUSAGE_SELF, &sBegin);
24449
+ iBegin = timeOfDay();
24450
+ }
24451
+}
24452
+
24453
+/* Return the difference of two time_structs in seconds */
24454
+static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
24455
+ return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
24456
+ (double)(pEnd->tv_sec - pStart->tv_sec);
24457
+}
24458
+
24459
+/* Return the time since the start of the timer in
24460
+** seconds. */
24461
+static double elapseTime(ShellState *NotUsed){
24462
+ (void)NotUsed;
24463
+ if( iBegin==0 ) return 0.0;
24464
+ return (timeOfDay() - iBegin)*0.000001;
24465
+}
24466
+
24467
+/*
24468
+** Print the timing results.
24469
+*/
24470
+static void endTimer(ShellState *p){
24471
+ if( p->enableTimer ){
24472
+ sqlite3_int64 iEnd = timeOfDay();
24473
+ struct rusage sEnd;
24474
+ getrusage(RUSAGE_SELF, &sEnd);
24475
+ p->prevTimer = (iEnd - iBegin)*0.000001;
24476
+ cli_printf(p->out, "Run Time: real %.6f user %.6f sys %.6f\n",
24477
+ p->prevTimer,
24478
+ timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
24479
+ timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
24480
+ if( p->enableTimer==1 ) p->enableTimer = 0;
24481
+ iBegin = 0;
24482
+ }
24483
+}
24484
+
24485
+#define BEGIN_TIMER(X) beginTimer(X)
24486
+#define END_TIMER(X) endTimer(X)
24487
+#define ELAPSE_TIME(X) elapseTime(X)
24488
+#define HAS_TIMER 1
24489
+
24490
+#elif (defined(_WIN32) || defined(WIN32))
24491
+
24492
+/* Saved resource information for the beginning of an operation */
24493
+static HANDLE hProcess;
24494
+static FILETIME ftKernelBegin;
24495
+static FILETIME ftUserBegin;
24496
+static sqlite3_int64 ftWallBegin;
24497
+typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
24498
+ LPFILETIME, LPFILETIME);
24499
+static GETPROCTIMES getProcessTimesAddr = NULL;
24500
+
24501
+/*
24502
+** Check to see if we have timer support. Return 1 if necessary
24503
+** support found (or found previously).
24504
+*/
24505
+static int hasTimer(void){
24506
+ if( getProcessTimesAddr ){
24507
+ return 1;
24508
+ } else {
24509
+ /* GetProcessTimes() isn't supported in WIN95 and some other Windows
24510
+ ** versions. See if the version we are running on has it, and if it
24511
+ ** does, save off a pointer to it and the current process handle.
24512
+ */
24513
+ hProcess = GetCurrentProcess();
24514
+ if( hProcess ){
24515
+ HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
24516
+ if( NULL != hinstLib ){
24517
+ getProcessTimesAddr =
24518
+ (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
24519
+ if( NULL != getProcessTimesAddr ){
24520
+ return 1;
24521
+ }
24522
+ FreeLibrary(hinstLib);
24523
+ }
24524
+ }
24525
+ }
24526
+ return 0;
24527
+}
24528
+
24529
+/*
24530
+** Begin timing an operation
24531
+*/
24532
+static void beginTimer(ShellState *p){
24533
+ if( (p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0)
24534
+ && getProcessTimesAddr
24535
+ ){
24536
+ FILETIME ftCreation, ftExit;
24537
+ getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
24538
+ &ftKernelBegin,&ftUserBegin);
24539
+ ftWallBegin = timeOfDay();
24540
+ }
24541
+}
24542
+
24543
+/* Return the difference of two FILETIME structs in seconds */
24544
+static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
24545
+ sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
24546
+ sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
24547
+ return (double) ((i64End - i64Start) / 10000000.0);
24548
+}
24549
+
24550
+/* Return the time since the start of the timer in
24551
+** seconds. */
24552
+static double elapseTime(ShellState *NotUsed){
24553
+ (void)NotUsed;
24554
+ if( ftWallBegin==0 ) return 0.0;
24555
+ return (timeOfDay() - ftWallBegin)*0.000001;
24556
+}
24557
+
24558
+/*
24559
+** Print the timing results.
24560
+*/
24561
+static void endTimer(ShellState *p){
24562
+ if( p->enableTimer && getProcessTimesAddr){
24563
+ FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
24564
+ sqlite3_int64 ftWallEnd = timeOfDay();
24565
+ getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
24566
+ p->prevTimer = (ftWallEnd - ftWallBegin)*0.000001;
24567
+#ifdef _WIN64
24568
+ /* microsecond precision on 64-bit windows */
24569
+ cli_printf(p->out, "Run Time: real %.6f user %f sys %f\n",
24570
+ p->prevTimer,
24571
+ timeDiff(&ftUserBegin, &ftUserEnd),
24572
+ timeDiff(&ftKernelBegin, &ftKernelEnd));
24573
+#else
24574
+ /* millisecond precisino on 32-bit windows */
24575
+ cli_printf(p->out, "Run Time: real %.3f user %.3f sys %.3f\n",
24576
+ p->prevTimer,
24577
+ timeDiff(&ftUserBegin, &ftUserEnd),
24578
+ timeDiff(&ftKernelBegin, &ftKernelEnd));
24579
+#endif
24580
+ if( p->enableTimer==1 ) p->enableTimer = 0;
24581
+ ftWallBegin = 0;
24582
+ }
24583
+}
24584
+
24585
+#define BEGIN_TIMER(X) beginTimer(X)
24586
+#define ELAPSE_TIME(X) elapseTime(X)
24587
+#define END_TIMER(X) endTimer(X)
24588
+#define HAS_TIMER hasTimer()
24589
+
24590
+#else
24591
+#define BEGIN_TIMER(X) /* no-op */
24592
+#define ELAPSE_TIME(X) 0.0
24593
+#define END_TIMER(X) /*no-op*/
24594
+#define HAS_TIMER 0
24595
+#endif
24596
+/************************* END PERFORMANCE TIMER ******************************/
2445224597
2445324598
/*
2445424599
** Clear a display mode, freeing any allocated memory that it
2445524600
** contains.
2445624601
*/
@@ -24534,11 +24679,13 @@
2453424679
if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]);
2453524680
if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]);
2453624681
if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
2453724682
pM->spec.eText = pI->eText;
2453824683
pM->spec.eBlob = pI->eBlob;
24539
- pM->spec.bTitles = pI->bHdr;
24684
+ if( (pM->mFlags & MFLG_HDR)==0 ){
24685
+ pM->spec.bTitles = pI->bHdr;
24686
+ }
2454024687
pM->spec.eTitle = pI->eHdr;
2454124688
if( pI->mFlg & 0x01 ){
2454224689
pM->spec.bBorder = QRF_No;
2454324690
}else{
2454424691
pM->spec.bBorder = QRF_Auto;
@@ -24570,18 +24717,17 @@
2457024717
p->mode.mFlags = mFlags;
2457124718
}
2457224719
}
2457324720
2457424721
/*
24575
-** Set the mode to the default according to p->iCompat. It assumed
24576
-** that the mode has already been freed and zeroed prior to calling
24577
-** this routine.
24722
+** Set the mode to the default. It assumed that the mode has
24723
+** already been freed and zeroed prior to calling this routine.
2457824724
*/
2457924725
static void modeDefault(ShellState *p){
2458024726
p->mode.spec.iVersion = 1;
2458124727
p->mode.autoExplain = 1;
24582
- if( p->iCompat>=20251115 && (stdin_is_interactive || stdout_is_console) ){
24728
+ if( stdin_is_interactive || stdout_is_console ){
2458324729
modeChange(p, MODE_TTY);
2458424730
}else{
2458524731
modeChange(p, MODE_BATCH);
2458624732
}
2458724733
}
@@ -25371,10 +25517,17 @@
2537125517
** Progress handler callback.
2537225518
*/
2537325519
static int progress_handler(void *pClientData) {
2537425520
ShellState *p = (ShellState*)pClientData;
2537525521
p->nProgress++;
25522
+ if( (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0
25523
+ && ELAPSE_TIME(p)>=p->tmProgress
25524
+ ){
25525
+ cli_printf(p->out, "Progress timeout after %.6f seconds\n",
25526
+ ELAPSE_TIME(p));
25527
+ return 1;
25528
+ }
2537625529
if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
2537725530
cli_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
2537825531
if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2537925532
if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
2538025533
return 1;
@@ -25908,10 +26061,12 @@
2590826061
char *zBuf = sqlite3_malloc64( szVar-5 );
2590926062
if( zBuf ){
2591026063
memcpy(zBuf, &zVar[6], szVar-5);
2591126064
sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
2591226065
}
26066
+ }else if( strcmp(zVar, "$TIMER")==0 ){
26067
+ sqlite3_bind_double(pStmt, i, pArg->prevTimer);
2591326068
#ifdef SQLITE_ENABLE_CARRAY
2591426069
}else if( strncmp(zVar, "$carray_", 8)==0 ){
2591526070
static char *azColorNames[] = {
2591626071
"azure", "black", "blue", "brown", "cyan", "fuchsia", "gold",
2591726072
"gray", "green", "indigo", "khaki", "lime", "magenta", "maroon",
@@ -26167,27 +26322,36 @@
2616726322
pArg->pStmt = pStmt;
2616826323
}
2616926324
2617026325
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
2617126326
isExplain = sqlite3_stmt_isexplain(pStmt);
26172
- if( pArg && pArg->mode.autoEQP && isExplain==0 ){
26327
+ if( pArg && pArg->mode.autoEQP && isExplain==0 && pArg->dot.nArg==0 ){
2617326328
int triggerEQP = 0;
26329
+ u8 savedEnableTimer = pArg->enableTimer;
26330
+ pArg->enableTimer = 0;
2617426331
disable_debug_trace_modes();
2617526332
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
2617626333
if( pArg->mode.autoEQP>=AUTOEQP_trigger ){
2617726334
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
2617826335
}
2617926336
sqlite3_reset(pStmt);
2618026337
spec.eStyle = QRF_STYLE_Auto;
26181
- sqlite3_stmt_explain(pStmt, 2-(pArg->mode.autoEQP>=AUTOEQP_full));
26338
+ sqlite3_stmt_explain(pStmt, 2);
2618226339
sqlite3_format_query_result(pStmt, &spec, 0);
26340
+ if( pArg->mode.autoEQP>=AUTOEQP_full ){
26341
+ sqlite3_reset(pStmt);
26342
+ sqlite3_stmt_explain(pStmt, 1);
26343
+ sqlite3_format_query_result(pStmt, &spec, 0);
26344
+ }
26345
+
2618326346
if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
2618426347
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
2618526348
}
2618626349
sqlite3_reset(pStmt);
2618726350
sqlite3_stmt_explain(pStmt, 0);
2618826351
restore_debug_trace_modes();
26352
+ pArg->enableTimer = savedEnableTimer;
2618926353
}
2619026354
2619126355
bind_prepared_stmt(pArg, pStmt);
2619226356
if( isExplain && pArg->mode.autoExplain ){
2619326357
spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp;
@@ -26604,12 +26768,12 @@
2660426768
".bail on|off Stop after hitting an error. Default OFF",
2660526769
#ifndef SQLITE_SHELL_FIDDLE
2660626770
".cd DIRECTORY Change the working directory to DIRECTORY",
2660726771
#endif
2660826772
".changes on|off Show number of rows changed by SQL",
26773
+ ".check OPTIONS ... Verify the results of a .testcase",
2660926774
#ifndef SQLITE_SHELL_FIDDLE
26610
- ".check GLOB Fail if output since .testcase does not match",
2661126775
".clone NEWDB Clone data into NEWDB from the existing database",
2661226776
#endif
2661326777
".connection [close] [#] Open or close an auxiliary database connection",
2661426778
".crlf ?on|off? Whether or not to use \\r\\n line endings",
2661526779
".databases List names and files of attached databases",
@@ -26721,10 +26885,11 @@
2672126885
".progress N Invoke progress handler after every N opcodes",
2672226886
" --limit N Interrupt after N progress callbacks",
2672326887
" --once Do no more than one progress interrupt",
2672426888
" --quiet|-q No output except at interrupts",
2672526889
" --reset Reset the count for each input and interrupt",
26890
+ " --timeout S Halt after running for S seconds",
2672626891
#endif
2672726892
".prompt MAIN CONTINUE Replace the standard prompts",
2672826893
#ifndef SQLITE_SHELL_FIDDLE
2672926894
".quit Stop interpreting input stream, exit if primary.",
2673026895
".read FILE Read input from FILE or command output",
@@ -26785,17 +26950,15 @@
2678526950
" vmstep Show the virtual machine step count only",
2678626951
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
2678726952
".system CMD ARGS... Run CMD ARGS... in a system shell",
2678826953
#endif
2678926954
".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
26790
-#ifndef SQLITE_SHELL_FIDDLE
26791
- ",testcase NAME Begin redirecting output to 'testcase-out.txt'",
26792
-#endif
26955
+ ".testcase NAME Begin a test case.",
2679326956
",testctrl CMD ... Run various sqlite3_test_control() operations",
2679426957
" Run \".testctrl\" with no arguments for details",
2679526958
".timeout MS Try opening locked tables for MS milliseconds",
26796
- ".timer on|off Turn SQL timer on or off",
26959
+ ".timer on|off|once Turn SQL timer on or off.",
2679726960
#ifndef SQLITE_OMIT_TRACE
2679826961
".trace ?OPTIONS? Output each SQL statement as it is run",
2679926962
" FILE Send output to FILE",
2680026963
" stdout Send output to stdout",
2680126964
" stderr Send output to stderr",
@@ -26836,19 +26999,33 @@
2683626999
"USAGE: .import [OPTIONS] FILE TABLE\n"
2683727000
"\n"
2683827001
"Import CSV or similar text from FILE into TABLE. If TABLE does\n"
2683927002
"not exist, it is created using the first row of FILE as the column\n"
2684027003
"names. If FILE begins with \"|\" then it is a command that is run\n"
26841
-"and the output from the command is used as the input data.\n"
27004
+"and the output from the command is used as the input data. If\n"
27005
+"FILE begins with \"<<\" followed by a label, then content is read from\n"
27006
+"the script until the first line that matches the label.\n"
27007
+"\n"
27008
+"The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n"
27009
+"rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n"
27010
+"the --ascii option is used.\n"
2684227011
"\n"
26843
-"FILE is assumed to be in a CSV format, unless the current mode\n"
26844
-"is \"ascii\" or \"tabs\" or unless one of the options below specify\n"
26845
-"an alternative.\n"
27012
+"The column and row separators must be single ASCII characters. If\n"
27013
+"multiple characters or a Unicode character are specified for the\n"
27014
+"separators, then only the first byte of the separator is used. Except,\n"
27015
+"if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n"
27016
+"understood as a row separator too.\n"
2684627017
"\n"
2684727018
"Options:\n"
26848
-" --ascii Use \\037 and \\036 as column and row separators on input\n"
27019
+" --ascii Do not use RFC-4180 quoting. Use \\037 and \\036\n"
27020
+" as column and row separators on input, unless other\n"
27021
+" delimiters are specified using --colsep and/or --rowsep\n"
27022
+" --colsep CHAR Use CHAR as the column separator.\n"
2684927023
" --csv Input is standard RFC-4180 CSV.\n"
27024
+" --esc CHAR Use CHAR as an escape character in unquoted CSV inputs.\n"
27025
+" --qesc CHAR Use CHAR as an escape character in quoted CSV inputs.\n"
27026
+" --rowsep CHAR Use CHAR as the row separator.\n"
2685027027
" --schema S When creating TABLE, put it in schema S\n"
2685127028
" --skip N Ignore the first N rows of input\n"
2685227029
" -v Verbose mode\n"
2685327030
},
2685427031
{ ".mode",
@@ -26930,23 +27107,17 @@
2693027107
" --bom Prepend a byte-order mark to the output\n"
2693127108
" -e Accumulate output in a temporary text file then\n"
2693227109
" launch a text editor when the redirection ends.\n"
2693327110
" --error-prefix X Use X as the left-margin prefix for error messages.\n"
2693427111
" Set to an empty string to restore the default.\n"
26935
-" --glob GLOB Raise an error if the memory buffer does not match\n"
26936
-" the GLOB pattern.\n"
26937
-" --keep Continue using the same \"memory\" buffer. Do not\n"
26938
-" reset it or delete it. Useful in combination with\n"
26939
-" --glob, --not-glob, and/or --verify.\n"
26940
-" ---notglob GLOB Raise an error if the memory buffer does not match\n"
26941
-" the GLOB pattern.\n"
27112
+" --keep Keep redirecting output to its current destination.\n"
27113
+" Use this option in combination with --show or\n"
27114
+" with --error-prefix when you do not want to stop\n"
27115
+" a current redirection.\n"
2694227116
" --plain Use plain text rather than HTML tables with -w\n"
26943
-" --show Write the memory buffer to the screen, for debugging.\n"
26944
-" --verify ENDMARK Read subsequent lines of text until the first line\n"
26945
-" that matches ENDMARK. Discard the ENDMARK. Compare\n"
26946
-" the text against the accumulated output in memory and\n"
26947
-" raise an error if there are any differences.\n"
27117
+" --show Show output text captured by .testcase or by\n"
27118
+" redirecting to \"memory\".\n"
2694827119
" -w Show the output in a web browser. Output is\n"
2694927120
" written into a temporary HTML file until the\n"
2695027121
" redirect ends, then the web browser is launched.\n"
2695127122
" Query results are shown as HTML tables, unless\n"
2695227123
" the --plain is used too.\n"
@@ -26970,10 +27141,39 @@
2697027141
" file in a web browser\n"
2697127142
" -x Show the output in a spreadsheet. Output is\n"
2697227143
" written to a temp file as CSV then the spreadsheet\n"
2697327144
" is launched when\n"
2697427145
},
27146
+ { ".check",
27147
+"USAGE: .check [OPTIONS] PATTERN\n"
27148
+"\n"
27149
+"Verify results of commands since the most recent .testcase command.\n"
27150
+"Restore output to the console, unless --keep is used.\n"
27151
+"\n"
27152
+"If PATTERN starts with \"<<ENDMARK\" then the actual pattern is taken from\n"
27153
+"subsequent lines of text up to the first line that begins with ENDMARK.\n"
27154
+"All pattern lines and the ENDMARK are discarded.\n"
27155
+"\n"
27156
+"Options:\n"
27157
+" --exact Do an exact comparison including leading and\n"
27158
+" trailing whitespace.\n"
27159
+" --glob Treat PATTERN as a GLOB\n"
27160
+" --keep Do not reset the testcase. More .check commands\n"
27161
+" will follow.\n"
27162
+" --notglob Output should not match PATTERN\n"
27163
+" --show Write testcase output to the screen, for debugging.\n"
27164
+ },
27165
+ { ".testcase",
27166
+"USAGE: .testcase [OPTIONS] NAME\n"
27167
+"\n"
27168
+"Start a new test case identified by NAME. All output\n"
27169
+"through the next \".check\" command is captured for comparison. See the\n"
27170
+"\".check\" commandn for additional informatioon.\n"
27171
+"\n"
27172
+"Options:\n"
27173
+" --error-prefix TEXT Change error message prefix text to TEXT\n"
27174
+ },
2697527175
};
2697627176
2697727177
/*
2697827178
** Return a pointer to usage text for zCmd, or NULL if none exists.
2697927179
*/
@@ -27193,10 +27393,56 @@
2719327393
if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
2719427394
}
2719527395
return 1;
2719627396
}
2719727397
#endif
27398
+
27399
+/*
27400
+** Return the size of the named file in bytes. Or return a negative
27401
+** number if the file does not exist.
27402
+*/
27403
+static sqlite3_int64 fileSize(const char *zFile){
27404
+#if defined(_WIN32) || defined(WIN32)
27405
+ struct _stat64 x;
27406
+ if( _stat64(zFile, &x)!=0 ) return -1;
27407
+ return (sqlite3_int64)x.st_size;
27408
+#else
27409
+ struct stat x;
27410
+ if( stat(zFile, &x)!=0 ) return -1;
27411
+ return (sqlite3_int64)x.st_size;
27412
+#endif
27413
+}
27414
+
27415
+/*
27416
+** Return true if zFile is an SQLite database.
27417
+**
27418
+** Algorithm:
27419
+** * If the file does not exist -> return false
27420
+** * If the size of the file is not a multiple of 512 -> return false
27421
+** * If sqlite3_open() fails -> return false
27422
+** * if sqlite3_prepare() or sqlite3_step() fails -> return false
27423
+** * Otherwise -> return true
27424
+*/
27425
+static int isDatabaseFile(const char *zFile, int openFlags){
27426
+ sqlite3 *db = 0;
27427
+ sqlite3_stmt *pStmt = 0;
27428
+ int rc;
27429
+ sqlite3_int64 sz = fileSize(zFile);
27430
+ if( sz<512 || (sz%512)!=0 ) return 0;
27431
+ if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK
27432
+ && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
27433
+ ==SQLITE_OK
27434
+ && sqlite3_step(pStmt)==SQLITE_ROW
27435
+ ){
27436
+ rc = 1;
27437
+ }else{
27438
+ rc = 0;
27439
+ }
27440
+ sqlite3_finalize(pStmt);
27441
+ sqlite3_close(db);
27442
+ return rc;
27443
+}
2719827444
2719927445
/*
2720027446
** Try to deduce the type of file for zName based on its content. Return
2720127447
** one of the SHELL_OPEN_* constants.
2720227448
**
@@ -27206,24 +27452,16 @@
2720627452
** the type cannot be determined from content.
2720727453
*/
2720827454
int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
2720927455
FILE *f;
2721027456
size_t n;
27211
- sqlite3 *db = 0;
27212
- sqlite3_stmt *pStmt = 0;
2721327457
int rc = SHELL_OPEN_UNSPEC;
2721427458
char zBuf[100];
2721527459
if( access(zName,0)!=0 ) goto database_type_by_name;
27216
- if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
27217
- && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
27218
- ==SQLITE_OK
27219
- && sqlite3_step(pStmt)==SQLITE_ROW
27220
- ){
27460
+ if( isDatabaseFile(zName, openFlags) ){
2722127461
rc = SHELL_OPEN_NORMAL;
2722227462
}
27223
- sqlite3_finalize(pStmt);
27224
- sqlite3_close(db);
2722527463
if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
2722627464
f = sqlite3_fopen(zName, "rb");
2722727465
if( f==0 ) goto database_type_by_name;
2722827466
n = fread(zBuf, 16, 1, f);
2722927467
if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
@@ -27253,10 +27491,39 @@
2725327491
}else{
2725427492
rc = SHELL_OPEN_NORMAL;
2725527493
}
2725627494
return rc;
2725727495
}
27496
+
27497
+/*
27498
+** If the text in z[] is the name of a readable file and that file appears
27499
+** to contain SQL text and/or dot-commands, then return true. If z[] is
27500
+** not a file, or if the file is unreadable, or if the file is a database
27501
+** or anything else that is not SQL text and dot-commands, then return false.
27502
+**
27503
+** If the bLeaveUninit flag is set, then be sure to leave SQLite in an
27504
+** uninitialized state. This means invoking sqlite3_shutdown() after any
27505
+** SQLite API is used.
27506
+**
27507
+** Some amount of guesswork is involved in this decision.
27508
+*/
27509
+static int isScriptFile(const char *z, int bLeaveUninit){
27510
+ sqlite3_int64 sz = fileSize(z);
27511
+ if( sz<=0 ) return 0;
27512
+ if( (sz%512)==0 ){
27513
+ int rc;
27514
+ sqlite3_initialize();
27515
+ rc = isDatabaseFile(z, SQLITE_OPEN_READONLY);
27516
+ if( bLeaveUninit ){
27517
+ sqlite3_shutdown();
27518
+ }
27519
+ if( rc ) return 0; /* Is a database */
27520
+ }
27521
+ if( sqlite3_strlike("%.sql",z,0)==0 ) return 1;
27522
+ if( sqlite3_strlike("%.txt",z,0)==0 ) return 1;
27523
+ return 0;
27524
+}
2725827525
2725927526
#ifndef SQLITE_OMIT_DESERIALIZE
2726027527
/*
2726127528
** Reconstruct an in-memory database using the output from the "dbtotxt"
2726227529
** program. Read content from the file in p->aAuxDb[].zDbFilename.
@@ -27899,20 +28166,24 @@
2789928166
typedef struct ImportCtx ImportCtx;
2790028167
struct ImportCtx {
2790128168
const char *zFile; /* Name of the input file */
2790228169
FILE *in; /* Read the CSV text from this input stream */
2790328170
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
28171
+ char *zIn; /* Input text */
2790428172
char *z; /* Accumulated text for a field */
28173
+ i64 nUsed; /* Bytes of zIn[] used so far */
2790528174
i64 n; /* Number of bytes in z */
2790628175
i64 nAlloc; /* Space allocated for z[] */
2790728176
int nLine; /* Current line number */
2790828177
int nRow; /* Number of rows imported */
2790928178
int nErr; /* Number of errors encountered */
2791028179
int bNotFirst; /* True if one or more bytes already read */
2791128180
int cTerm; /* Character that terminated the most recent field */
2791228181
int cColSep; /* The column separator character. (Usually ",") */
2791328182
int cRowSep; /* The row separator character. (Usually "\n") */
28183
+ int cQEscape; /* Escape character with "...". 0 for none */
28184
+ int cUQEscape; /* Escape character not with "...". 0 for none */
2791428185
};
2791528186
2791628187
/* Clean up resourced used by an ImportCtx */
2791728188
static void import_cleanup(ImportCtx *p){
2791828189
if( p->in!=0 && p->xCloser!=0 ){
@@ -27919,13 +28190,32 @@
2791928190
p->xCloser(p->in);
2792028191
p->in = 0;
2792128192
}
2792228193
sqlite3_free(p->z);
2792328194
p->z = 0;
28195
+ if( p->zIn ){
28196
+ sqlite3_free(p->zIn);
28197
+ p->zIn = 0;
28198
+ }
2792428199
}
2792528200
27926
-/* Append a single byte to z[] */
28201
+/* Read a single character of the .import input text. Return EOF
28202
+** at end-of-file.
28203
+*/
28204
+static int import_getc(ImportCtx *p){
28205
+ if( p->in ){
28206
+ return fgetc(p->in);
28207
+ }else if( p->zIn && p->zIn[p->nUsed]!=0 ){
28208
+ return p->zIn[p->nUsed++];
28209
+ }else{
28210
+ return EOF;
28211
+ }
28212
+}
28213
+
28214
+/* Append a single byte to the field value begin constructed
28215
+** in the p->z[] buffer
28216
+*/
2792728217
static void import_append_char(ImportCtx *p, int c){
2792828218
if( p->n+1>=p->nAlloc ){
2792928219
p->nAlloc += p->nAlloc + 100;
2793028220
p->z = sqlite3_realloc64(p->z, p->nAlloc);
2793128221
shell_check_oom(p->z);
@@ -27937,12 +28227,12 @@
2793728227
** with the option of having a separator other than ",".
2793828228
**
2793928229
** + Input comes from p->in.
2794028230
** + Store results in p->z of length p->n. Space to hold p->z comes
2794128231
** from sqlite3_malloc64().
27942
-** + Use p->cSep as the column separator. The default is ",".
27943
-** + Use p->rSep as the row separator. The default is "\n".
28232
+** + Use p->cColSep as the column separator. The default is ",".
28233
+** + Use p->cRowSep as the row separator. The default is "\n".
2794428234
** + Keep track of the line number in p->nLine.
2794528235
** + Store the character that terminates the field in p->cTerm. Store
2794628236
** EOF on end-of-file.
2794728237
** + Report syntax errors on stderr
2794828238
*/
@@ -27949,23 +28239,30 @@
2794928239
static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
2795028240
int c;
2795128241
int cSep = (u8)p->cColSep;
2795228242
int rSep = (u8)p->cRowSep;
2795328243
p->n = 0;
27954
- c = fgetc(p->in);
28244
+ c = import_getc(p);
2795528245
if( c==EOF || seenInterrupt ){
2795628246
p->cTerm = EOF;
2795728247
return 0;
2795828248
}
2795928249
if( c=='"' ){
2796028250
int pc, ppc;
2796128251
int startLine = p->nLine;
2796228252
int cQuote = c;
28253
+ int cEsc = (u8)p->cQEscape;
2796328254
pc = ppc = 0;
2796428255
while( 1 ){
27965
- c = fgetc(p->in);
28256
+ c = import_getc(p);
2796628257
if( c==rSep ) p->nLine++;
28258
+ if( c==cEsc && cEsc!=0 ){
28259
+ c = import_getc(p);
28260
+ import_append_char(p, c);
28261
+ ppc = pc = 0;
28262
+ continue;
28263
+ }
2796728264
if( c==cQuote ){
2796828265
if( pc==cQuote ){
2796928266
pc = 0;
2797028267
continue;
2797128268
}
@@ -27979,11 +28276,11 @@
2797928276
p->cTerm = c;
2798028277
break;
2798128278
}
2798228279
if( pc==cQuote && c!='\r' ){
2798328280
cli_printf(stderr,"%s:%d: unescaped %c character\n",
27984
- p->zFile, p->nLine, cQuote);
28281
+ p->zFile, p->nLine, cQuote);
2798528282
}
2798628283
if( c==EOF ){
2798728284
cli_printf(stderr,"%s:%d: unterminated %c-quoted field\n",
2798828285
p->zFile, startLine, cQuote);
2798928286
p->cTerm = c;
@@ -27994,26 +28291,28 @@
2799428291
pc = c;
2799528292
}
2799628293
}else{
2799728294
/* If this is the first field being parsed and it begins with the
2799828295
** UTF-8 BOM (0xEF BB BF) then skip the BOM */
28296
+ int cEsc = p->cUQEscape;
2799928297
if( (c&0xff)==0xef && p->bNotFirst==0 ){
2800028298
import_append_char(p, c);
28001
- c = fgetc(p->in);
28299
+ c = import_getc(p);
2800228300
if( (c&0xff)==0xbb ){
2800328301
import_append_char(p, c);
28004
- c = fgetc(p->in);
28302
+ c = import_getc(p);
2800528303
if( (c&0xff)==0xbf ){
2800628304
p->bNotFirst = 1;
2800728305
p->n = 0;
2800828306
return csv_read_one_field(p);
2800928307
}
2801028308
}
2801128309
}
2801228310
while( c!=EOF && c!=cSep && c!=rSep ){
28311
+ if( c==cEsc && cEsc!=0 ) c = import_getc(p);
2801328312
import_append_char(p, c);
28014
- c = fgetc(p->in);
28313
+ c = import_getc(p);
2801528314
}
2801628315
if( c==rSep ){
2801728316
p->nLine++;
2801828317
if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
2801928318
}
@@ -28027,12 +28326,12 @@
2802728326
/* Read a single field of ASCII delimited text.
2802828327
**
2802928328
** + Input comes from p->in.
2803028329
** + Store results in p->z of length p->n. Space to hold p->z comes
2803128330
** from sqlite3_malloc64().
28032
-** + Use p->cSep as the column separator. The default is "\x1F".
28033
-** + Use p->rSep as the row separator. The default is "\x1E".
28331
+** + Use p->cColSep as the column separator. The default is "\x1F".
28332
+** + Use p->cRowSep as the row separator. The default is "\x1E".
2803428333
** + Keep track of the row number in p->nLine.
2803528334
** + Store the character that terminates the field in p->cTerm. Store
2803628335
** EOF on end-of-file.
2803728336
** + Report syntax errors on stderr
2803828337
*/
@@ -28039,18 +28338,18 @@
2803928338
static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
2804028339
int c;
2804128340
int cSep = (u8)p->cColSep;
2804228341
int rSep = (u8)p->cRowSep;
2804328342
p->n = 0;
28044
- c = fgetc(p->in);
28343
+ c = import_getc(p);
2804528344
if( c==EOF || seenInterrupt ){
2804628345
p->cTerm = EOF;
2804728346
return 0;
2804828347
}
2804928348
while( c!=EOF && c!=cSep && c!=rSep ){
2805028349
import_append_char(p, c);
28051
- c = fgetc(p->in);
28350
+ c = import_getc(p);
2805228351
}
2805328352
if( c==rSep ){
2805428353
p->nLine++;
2805528354
}
2805628355
p->cTerm = c;
@@ -30151,11 +30450,11 @@
3015130450
;
3015230451
static const char * const zCollectVar = "\
3015330452
SELECT\
3015430453
'('||x'0a'\
3015530454
|| group_concat(\
30156
- cname||' TEXT',\
30455
+ cname||' ANY',\
3015730456
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
3015830457
||')' AS ColsSpec \
3015930458
FROM (\
3016030459
SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
3016130460
FROM ColNames ORDER BY cpos\
@@ -30351,19 +30650,33 @@
3035130650
** USAGE: .import [OPTIONS] FILE TABLE
3035230651
**
3035330652
** Import CSV or similar text from FILE into TABLE. If TABLE does
3035430653
** not exist, it is created using the first row of FILE as the column
3035530654
** names. If FILE begins with "|" then it is a command that is run
30356
-** and the output from the command is used as the input data.
30655
+** and the output from the command is used as the input data. If
30656
+** FILE begins with "<<" followed by a label, then content is read from
30657
+** the script until the first line that matches the label.
30658
+**
30659
+** The content of FILE is interpreted using RFC-4180 ("CSV") quoting
30660
+** rules unless the current mode is "ascii" or "tabs" or unless one
30661
+** the --ascii option is used.
3035730662
**
30358
-** FILE is assumed to be in a CSV format, unless the current mode
30359
-** is "ascii" or "tabs" or unless one of the options below specify
30360
-** an alternative.
30663
+** The column and row separators must be single ASCII characters. If
30664
+** multiple characters or a Unicode character are specified for the
30665
+** separators, then only the first byte of the separator is used. Except,
30666
+** if the row separator is \n and the mode is not --ascii, then \r\n is
30667
+** understood as a row separator too.
3036130668
**
3036230669
** Options:
30363
-** --ascii Use \037 and \036 as column and row separators on input
30670
+** --ascii Do not use RFC-4180 quoting. Use \037 and \036
30671
+** as column and row separators on input, unless other
30672
+** delimiters are specified using --colsep and/or --rowsep
30673
+** --colsep CHAR Use CHAR as the column separator.
3036430674
** --csv Input is standard RFC-4180 CSV.
30675
+** --esc CHAR Use CHAR as an escape character in unquoted CSV inputs.
30676
+** --qesc CHAR Use CHAR as an escape character in quoted CSV inputs.
30677
+** --rowsep CHAR Use CHAR as the row separator.
3036530678
** --schema S When creating TABLE, put it in schema S
3036630679
** --skip N Ignore the first N rows of input
3036730680
** -v Verbose mode
3036830681
*/
3036930682
static int dotCmdImport(ShellState *p){
@@ -30375,17 +30688,16 @@
3037530688
sqlite3_stmt *pStmt = NULL; /* A statement */
3037630689
int nCol; /* Number of columns in the table */
3037730690
i64 nByte; /* Number of bytes in an SQL string */
3037830691
int i, j; /* Loop counters */
3037930692
int needCommit; /* True to COMMIT or ROLLBACK at end */
30380
- int nSep; /* Number of bytes in spec.zColumnSep */
3038130693
char *zSql = 0; /* An SQL statement */
3038230694
ImportCtx sCtx; /* Reader context */
3038330695
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
3038430696
int eVerbose = 0; /* Larger for more console output */
3038530697
i64 nSkip = 0; /* Initial lines to skip */
30386
- int useOutputMode = 1; /* Use output mode to determine separators */
30698
+ i64 iLineOffset = 0; /* Offset to the first line of input */
3038730699
char *zCreate = 0; /* CREATE TABLE statement text */
3038830700
int rc; /* Result code */
3038930701
3039030702
failIfSafeMode(p, "cannot run .import in safe mode");
3039130703
memset(&sCtx, 0, sizeof(sCtx));
@@ -30411,70 +30723,71 @@
3041130723
}else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
3041230724
zSchema = azArg[++i];
3041330725
}else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
3041430726
nSkip = integerValue(azArg[++i]);
3041530727
}else if( cli_strcmp(z,"-ascii")==0 ){
30416
- sCtx.cColSep = SEP_Unit[0];
30417
- sCtx.cRowSep = SEP_Record[0];
30728
+ if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0];
30729
+ if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0];
3041830730
xRead = ascii_read_one_field;
30419
- useOutputMode = 0;
3042030731
}else if( cli_strcmp(z,"-csv")==0 ){
30421
- sCtx.cColSep = ',';
30422
- sCtx.cRowSep = '\n';
30732
+ if( sCtx.cColSep==0 ) sCtx.cColSep = ',';
30733
+ if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n';
3042330734
xRead = csv_read_one_field;
30424
- useOutputMode = 0;
30735
+ }else if( cli_strcmp(z,"-esc")==0 ){
30736
+ sCtx.cUQEscape = azArg[++i][0];
30737
+ }else if( cli_strcmp(z,"-qesc")==0 ){
30738
+ sCtx.cQEscape = azArg[++i][0];
30739
+ }else if( cli_strcmp(z,"-colsep")==0 ){
30740
+ if( i==nArg-1 ){
30741
+ dotCmdError(p, i, "missing argument", 0);
30742
+ return 1;
30743
+ }
30744
+ i++;
30745
+ sCtx.cColSep = azArg[i][0];
30746
+ }else if( cli_strcmp(z,"-rowsep")==0 ){
30747
+ if( i==nArg-1 ){
30748
+ dotCmdError(p, i, "missing argument", 0);
30749
+ return 1;
30750
+ }
30751
+ i++;
30752
+ sCtx.cRowSep = azArg[i][0];
3042530753
}else{
3042630754
dotCmdError(p, i, "unknown option", 0);
3042730755
return 1;
3042830756
}
3042930757
}
3043030758
if( zTable==0 ){
30431
- cli_printf(p->out, "ERROR: missing %s argument\n",
30759
+ dotCmdError(p, nArg, 0, "Missing %s argument\n",
3043230760
zFile==0 ? "FILE" : "TABLE");
3043330761
return 1;
3043430762
}
3043530763
seenInterrupt = 0;
3043630764
open_db(p, 0);
30437
- if( useOutputMode ){
30438
- /* If neither the --csv or --ascii options are specified, then set
30439
- ** the column and row separator characters from the output mode. */
30440
- if( p->mode.spec.zColumnSep==0 ){
30441
- modeSetStr(&p->mode.spec.zColumnSep, ",");
30442
- nSep = 1;
30443
- }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){
30444
- eputz("Error: non-null column separator required for import\n");
30445
- return 1;
30446
- }
30447
- if( nSep>1 ){
30448
- eputz("Error: multi-character column separators not allowed"
30449
- " for import\n");
30450
- return 1;
30451
- }
30452
- if( p->mode.spec.zRowSep==0 ){
30453
- modeSetStr(&p->mode.spec.zRowSep, "\n");
30454
- nSep = 1;
30455
- }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){
30456
- eputz("Error: non-null row separator required for import\n");
30457
- return 1;
30458
- }
30459
- if( nSep==2 && p->mode.eMode==MODE_Csv
30460
- && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0
30461
- ){
30462
- /* When importing CSV (only), if the row separator is set to the
30463
- ** default output row separator, change it to the default input
30464
- ** row separator. This avoids having to maintain different input
30465
- ** and output row separators. */
30466
- modeSetStr(&p->mode.spec.zRowSep, SEP_Row);
30467
- nSep = strlen30(p->mode.spec.zRowSep);
30468
- }
30469
- if( nSep>1 ){
30470
- eputz("Error: multi-character row separators not allowed"
30471
- " for import\n");
30472
- return 1;
30473
- }
30474
- sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0];
30475
- sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0];
30765
+ if( sCtx.cColSep==0 ){
30766
+ if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){
30767
+ sCtx.cColSep = p->mode.spec.zColumnSep[0];
30768
+ }else{
30769
+ sCtx.cColSep = ',';
30770
+ }
30771
+ }
30772
+ if( (sCtx.cColSep & 0x80)!=0 ){
30773
+ eputz("Error: .import column separator must be ASCII\n");
30774
+ return 1;
30775
+ }
30776
+ if( sCtx.cRowSep==0 ){
30777
+ if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){
30778
+ sCtx.cRowSep = p->mode.spec.zRowSep[0];
30779
+ }else{
30780
+ sCtx.cRowSep = '\n';
30781
+ }
30782
+ }
30783
+ if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){
30784
+ sCtx.cRowSep = '\n';
30785
+ }
30786
+ if( (sCtx.cRowSep & 0x80)!=0 ){
30787
+ eputz("Error: .import row separator must be ASCII\n");
30788
+ return 1;
3047630789
}
3047730790
sCtx.zFile = zFile;
3047830791
sCtx.nLine = 1;
3047930792
if( sCtx.zFile[0]=='|' ){
3048030793
#ifdef SQLITE_OMIT_POPEN
@@ -30483,19 +30796,58 @@
3048330796
#else
3048430797
sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
3048530798
sCtx.zFile = "<pipe>";
3048630799
sCtx.xCloser = pclose;
3048730800
#endif
30801
+ }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){
30802
+ /* Input text comes from subsequent lines of script until the zFile
30803
+ ** delimiter */
30804
+ int nEndMark = strlen30(zFile)-2;
30805
+ char *zEndMark = &zFile[2];
30806
+ sqlite3_str *pContent = sqlite3_str_new(p->db);
30807
+ int ckEnd = 1;
30808
+ i64 iStart = p->lineno;
30809
+ char zLine[2000];
30810
+ sCtx.zFile = p->zInFile;
30811
+ sCtx.nLine = p->lineno+1;
30812
+ iLineOffset = p->lineno;
30813
+ while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
30814
+ if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){
30815
+ ckEnd = 2;
30816
+ if( strchr(zLine,'\n') ) p->lineno++;
30817
+ break;
30818
+ }
30819
+ if( strchr(zLine,'\n') ){
30820
+ p->lineno++;
30821
+ ckEnd = 1;
30822
+ }else{
30823
+ ckEnd = 0;
30824
+ }
30825
+ sqlite3_str_appendall(pContent, zLine);
30826
+ }
30827
+ sCtx.zIn = sqlite3_str_finish(pContent);
30828
+ if( sCtx.zIn==0 ){
30829
+ sCtx.zIn = sqlite3_mprintf("");
30830
+ }
30831
+ if( ckEnd<2 ){
30832
+ i64 savedLn = p->lineno;
30833
+ p->lineno = iStart;
30834
+ dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark);
30835
+ p->lineno = savedLn;
30836
+ import_cleanup(&sCtx);
30837
+ return 1;
30838
+ }
3048830839
}else{
3048930840
sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
3049030841
sCtx.xCloser = fclose;
3049130842
}
30492
- if( sCtx.in==0 ){
30493
- cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile);
30843
+ if( sCtx.in==0 && sCtx.zIn==0 ){
30844
+ dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile);
30845
+ import_cleanup(&sCtx);
3049430846
return 1;
3049530847
}
30496
- if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
30848
+ if( eVerbose>=1 ){
3049730849
char zSep[2];
3049830850
zSep[1] = 0;
3049930851
zSep[0] = sCtx.cColSep;
3050030852
cli_puts("Column separator ", p->out);
3050130853
output_c_string(p->out, zSep);
@@ -30648,10 +31000,14 @@
3064831000
if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
3064931001
z = "";
3065031002
}
3065131003
sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
3065231004
if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
31005
+ if( i==0 && (strcmp(z,"\n")==0 || strcmp(z,"\r\n")==0) ){
31006
+ /* Ignore trailing \n or \r\n when some other row separator */
31007
+ break;
31008
+ }
3065331009
cli_printf(stderr,"%s:%d: expected %d columns but found %d"
3065431010
" - filling the rest with NULL\n",
3065531011
sCtx.zFile, startLine, nCol, i+1);
3065631012
i += 2;
3065731013
while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
@@ -30671,10 +31027,11 @@
3067131027
rc = sqlite3_reset(pStmt);
3067231028
if( rc!=SQLITE_OK ){
3067331029
cli_printf(stderr,"%s:%d: INSERT failed: %s\n",
3067431030
sCtx.zFile, startLine, sqlite3_errmsg(p->db));
3067531031
sCtx.nErr++;
31032
+ if( bail_on_error ) break;
3067631033
}else{
3067731034
sCtx.nRow++;
3067831035
}
3067931036
}
3068031037
}while( sCtx.cTerm!=EOF );
@@ -30683,13 +31040,13 @@
3068331040
sqlite3_finalize(pStmt);
3068431041
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
3068531042
if( eVerbose>0 ){
3068631043
cli_printf(p->out,
3068731044
"Added %d rows with %d errors using %d lines of input\n",
30688
- sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
31045
+ sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset);
3068931046
}
30690
- return 0;
31047
+ return sCtx.nErr ? 1 : 0;
3069131048
}
3069231049
3069331050
3069431051
/*
3069531052
** This function computes what to show the user about the configured
@@ -31100,10 +31457,11 @@
3110031457
if( k<0 ){
3110131458
dotCmdError(p, i, "bad --titles value","%z", zErr);
3110231459
return 1;
3110331460
}
3110431461
p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No;
31462
+ p->mode.mFlags &= ~MFLG_HDR;
3110531463
p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr;
3110631464
chng = 1;
3110731465
}else if( optionMatch(z,"widths") || optionMatch(z,"width") ){
3110831466
int nWidth = 0;
3110931467
short int *aWidth;
@@ -31328,23 +31686,17 @@
3132831686
** --bom Prepend a byte-order mark to the output
3132931687
** -e Accumulate output in a temporary text file then
3133031688
** launch a text editor when the redirection ends.
3133131689
** --error-prefix X Use X as the left-margin prefix for error messages.
3133231690
** Set to an empty string to restore the default.
31333
-** --glob GLOB Raise an error if the memory buffer does not match
31334
-** the GLOB pattern.
31335
-** --keep Continue using the same "memory" buffer. Do not
31336
-** reset it or delete it. Useful in combination with
31337
-** --glob, --not-glob, and/or --verify.
31338
-** ---notglob GLOB Raise an error if the memory buffer does not match
31339
-** the GLOB pattern.
31691
+** --keep Keep redirecting output to its current destination.
31692
+** Use this option in combination with --show or
31693
+** with --error-prefix when you do not want to stop
31694
+** a current redirection.
3134031695
** --plain Use plain text rather than HTML tables with -w
31341
-** --show Write the memory buffer to the screen, for debugging.
31342
-** --verify ENDMARK Read subsequent lines of text until the first line
31343
-** that matches ENDMARK. Discard the ENDMARK. Compare
31344
-** the text against the accumulated output in memory and
31345
-** raise an error if there are any differences.
31696
+** --show Show output text captured by .testcase or by
31697
+** redirecting to "memory".
3134631698
** -w Show the output in a web browser. Output is
3134731699
** written into a temporary HTML file until the
3134831700
** redirect ends, then the web browser is launched.
3134931701
** Query results are shown as HTML tables, unless
3135031702
** the --plain is used too.
@@ -31382,13 +31734,11 @@
3138231734
char *zFile = 0; /* The FILE argument */
3138331735
int i; /* Loop counter */
3138431736
int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
3138531737
int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
3138631738
int bPlain = 0; /* --plain option */
31387
- int bKeep = 0; /* --keep option */
31388
- char *zCheck = 0; /* Argument to --glob, --notglob, --verify */
31389
- int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --verify */
31739
+ int bKeep = 0; /* Keep redirecting */
3139031740
static const char *zBomUtf8 = "\357\273\277";
3139131741
const char *zBom = 0;
3139231742
char c = azArg[0][0];
3139331743
int n = strlen30(azArg[0]);
3139431744
@@ -31410,36 +31760,21 @@
3141031760
zBom = zBomUtf8;
3141131761
}else if( cli_strcmp(z,"-plain")==0 ){
3141231762
bPlain = 1;
3141331763
}else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
3141431764
&& (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
31415
- if( bKeep || eMode || eCheck ){
31765
+ if( bKeep || eMode ){
3141631766
dotCmdError(p, i, "incompatible with prior options",0);
3141731767
goto dotCmdOutput_error;
3141831768
}
3141931769
eMode = z[1];
31420
- }else if( cli_strcmp(z,"-keep")==0 ){
31421
- bKeep = 1;
3142231770
}else if( cli_strcmp(z,"-show")==0 ){
3142331771
if( cli_output_capture ){
3142431772
sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
3142531773
}
31774
+ }else if( cli_strcmp(z,"-keep")==0 ){
3142631775
bKeep = 1;
31427
- }else if( cli_strcmp(z,"-glob")==0
31428
- || cli_strcmp(z,"-notglob")==0
31429
- || cli_strcmp(z,"-verify")==0
31430
- ){
31431
- if( eCheck || eMode ){
31432
- dotCmdError(p, i, "incompatible with prior options",0);
31433
- goto dotCmdOutput_error;
31434
- }
31435
- if( i+1>=nArg ){
31436
- dotCmdError(p, i, "missing argument", 0);
31437
- goto dotCmdOutput_error;
31438
- }
31439
- zCheck = azArg[++i];
31440
- eCheck = z[1]=='g' ? 1 : z[1]=='n' ? 2 : 3;
3144131776
}else if( optionMatch(z,"error-prefix") ){
3144231777
if( i+1>=nArg ){
3144331778
dotCmdError(p, i, "missing argument", 0);
3144431779
return 1;
3144531780
}
@@ -31450,11 +31785,11 @@
3145031785
dotCmdError(p, i, "unknown option", 0);
3145131786
sqlite3_free(zFile);
3145231787
return 1;
3145331788
}
3145431789
}else if( zFile==0 && eMode==0 ){
31455
- if( bKeep || eCheck ){
31790
+ if( bKeep ){
3145631791
dotCmdError(p, i, "incompatible with prior options",0);
3145731792
goto dotCmdOutput_error;
3145831793
}
3145931794
if( cli_strcmp(z, "memory")==0 && bOnce ){
3146031795
dotCmdError(p, 0, "cannot redirect to \"memory\"", 0);
@@ -31486,53 +31821,10 @@
3148631821
if( bOnce ){
3148731822
p->nPopOutput = 2;
3148831823
}else{
3148931824
p->nPopOutput = 0;
3149031825
}
31491
- if( eCheck ){
31492
- char *zTest;
31493
- if( cli_output_capture ){
31494
- zTest = sqlite3_str_value(cli_output_capture);
31495
- }else{
31496
- zTest = "";
31497
- }
31498
- p->nTestRun++;
31499
- if( eCheck==3 ){
31500
- int nCheck = strlen30(zCheck);
31501
- sqlite3_str *pPattern = sqlite3_str_new(p->db);
31502
- char *zPattern;
31503
- sqlite3_int64 iStart = p->lineno;
31504
- char zLine[2000];
31505
- while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31506
- if( strchr(zLine,'\n') ) p->lineno++;
31507
- if( cli_strncmp(zCheck,zLine,nCheck)==0 ) break;
31508
- sqlite3_str_appendall(pPattern, zLine);
31509
- }
31510
- zPattern = sqlite3_str_finish(pPattern);
31511
- if( cli_strcmp(zPattern,zTest)!=0 ){
31512
- sqlite3_fprintf(stderr,
31513
- "%s:%lld: --verify does matches prior output\n",
31514
- p->zInFile, iStart);
31515
- p->nTestErr++;
31516
- }
31517
- sqlite3_free(zPattern);
31518
- }else{
31519
- char *zGlob = sqlite3_mprintf("*%s*", zCheck);
31520
- if( eCheck==1 && sqlite3_strglob(zGlob, zTest)!=0 ){
31521
- sqlite3_fprintf(stderr,
31522
- "%s:%lld: --glob \"%s\" does not match prior output\n",
31523
- p->zInFile, p->lineno, zCheck);
31524
- p->nTestErr++;
31525
- }else if( eCheck==2 && sqlite3_strglob(zGlob, zTest)==0 ){
31526
- sqlite3_fprintf(stderr,
31527
- "%s:%lld: --notglob \"%s\" matches prior output\n",
31528
- p->zInFile, p->lineno, zCheck);
31529
- p->nTestErr++;
31530
- }
31531
- sqlite3_free(zGlob);
31532
- }
31533
- }
3153431826
if( !bKeep ) output_reset(p);
3153531827
#ifndef SQLITE_NOHAVE_SYSTEM
3153631828
if( eMode=='e' || eMode=='x' || eMode=='w' ){
3153731829
p->doXdgOpen = 1;
3153831830
modePush(p);
@@ -31609,10 +31901,199 @@
3160931901
3161031902
dotCmdOutput_error:
3161131903
sqlite3_free(zFile);
3161231904
return 1;
3161331905
}
31906
+
31907
+/*
31908
+** DOT-COMMAND: .check
31909
+** USAGE: .check [OPTIONS] PATTERN
31910
+**
31911
+** Verify results of commands since the most recent .testcase command.
31912
+** Restore output to the console, unless --keep is used.
31913
+**
31914
+** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from
31915
+** subsequent lines of text up to the first line that begins with ENDMARK.
31916
+** All pattern lines and the ENDMARK are discarded.
31917
+**
31918
+** Options:
31919
+** --exact Do an exact comparison including leading and
31920
+** trailing whitespace.
31921
+** --glob Treat PATTERN as a GLOB
31922
+** --keep Do not reset the testcase. More .check commands
31923
+** will follow.
31924
+** --notglob Output should not match PATTERN
31925
+** --show Write testcase output to the screen, for debugging.
31926
+*/
31927
+static int dotCmdCheck(ShellState *p){
31928
+ int nArg = p->dot.nArg; /* Number of arguments */
31929
+ char **azArg = p->dot.azArg; /* Text of the arguments */
31930
+ int i; /* Loop counter */
31931
+ int k; /* Result of pickStr() */
31932
+ char *zTest; /* Textcase result */
31933
+ int bKeep = 0; /* --keep option */
31934
+ char *zCheck = 0; /* PATTERN argument */
31935
+ char *zPattern = 0; /* Actual test pattern */
31936
+ int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */
31937
+ int isOk; /* True if results are OK */
31938
+ sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */
31939
+
31940
+ if( p->zTestcase[0]==0 ){
31941
+ dotCmdError(p, 0, "no .testcase is active", 0);
31942
+ return 1;
31943
+ }
31944
+ for(i=1; i<nArg; i++){
31945
+ char *z = azArg[i];
31946
+ if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
31947
+ if( cli_strcmp(z,"-keep")==0 ){
31948
+ bKeep = 1;
31949
+ }else if( cli_strcmp(z,"-show")==0 ){
31950
+ if( cli_output_capture ){
31951
+ sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31952
+ }
31953
+ bKeep = 1;
31954
+ }else if( z[0]=='-'
31955
+ && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0
31956
+ ){
31957
+ if( eCheck && eCheck!=k+1 ){
31958
+ dotCmdError(p, i, "incompatible with prior options",0);
31959
+ return 1;
31960
+ }
31961
+ eCheck = k+1;
31962
+ }else if( zCheck ){
31963
+ dotCmdError(p, i, "unknown option", 0);
31964
+ return 1;
31965
+ }else{
31966
+ zCheck = azArg[i];
31967
+ }
31968
+ }
31969
+ if( zCheck==0 ){
31970
+ dotCmdError(p, 0, "no PATTERN specified", 0);
31971
+ return 1;
31972
+ }
31973
+ if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){
31974
+ zTest = sqlite3_str_value(cli_output_capture);
31975
+ shell_check_oom(zTest);
31976
+ }else{
31977
+ zTest = "";
31978
+ }
31979
+ p->nTestRun++;
31980
+ if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){
31981
+ int nCheck = strlen30(zCheck);
31982
+ sqlite3_str *pPattern = sqlite3_str_new(p->db);
31983
+ char zLine[2000];
31984
+ while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31985
+ if( strchr(zLine,'\n') ) p->lineno++;
31986
+ if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break;
31987
+ sqlite3_str_appendall(pPattern, zLine);
31988
+ }
31989
+ zPattern = sqlite3_str_finish(pPattern);
31990
+ if( zPattern==0 ){
31991
+ zPattern = sqlite3_mprintf("");
31992
+ }
31993
+ }else{
31994
+ zPattern = zCheck;
31995
+ }
31996
+ shell_check_oom(zPattern);
31997
+ switch( eCheck ){
31998
+ case 1: {
31999
+ char *zGlob = sqlite3_mprintf("*%s*", zPattern);
32000
+ isOk = testcase_glob(zGlob, zTest)!=0;
32001
+ sqlite3_free(zGlob);
32002
+ break;
32003
+ }
32004
+ case 2: {
32005
+ char *zGlob = sqlite3_mprintf("*%s*", zPattern);
32006
+ isOk = testcase_glob(zGlob, zTest)==0;
32007
+ sqlite3_free(zGlob);
32008
+ break;
32009
+ }
32010
+ case 3: {
32011
+ isOk = cli_strcmp(zTest,zPattern)==0;
32012
+ break;
32013
+ }
32014
+ default: {
32015
+ /* Skip leading and trailing \n and \r on both pattern and test output */
32016
+ const char *z1 = zPattern;
32017
+ const char *z2 = zTest;
32018
+ size_t n1, n2;
32019
+ while( z1[0]=='\n' || z1[0]=='\r' ) z1++;
32020
+ n1 = strlen(z1);
32021
+ while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--;
32022
+ while( z2[0]=='\n' || z2[0]=='\r' ) z2++;
32023
+ n2 = strlen(z2);
32024
+ while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--;
32025
+ isOk = n1==n2 && memcmp(z1,z2,n1)==0;
32026
+ break;
32027
+ }
32028
+ }
32029
+ if( !isOk ){
32030
+ sqlite3_fprintf(stderr,
32031
+ "%s:%lld: .check failed for testcase %s\n",
32032
+ p->zInFile, iStart, p->zTestcase);
32033
+ p->nTestErr++;
32034
+ sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern);
32035
+ sqlite3_fprintf(stderr, "Got: [%s]\n", zTest);
32036
+ }
32037
+ if( zPattern!=zCheck ){
32038
+ sqlite3_free(zPattern);
32039
+ }
32040
+ if( !bKeep ){
32041
+ output_reset(p);
32042
+ p->zTestcase[0] = 0;
32043
+ }
32044
+ return 0;
32045
+}
32046
+
32047
+/*
32048
+** DOT-COMMAND: .testcase
32049
+** USAGE: .testcase [OPTIONS] NAME
32050
+**
32051
+** Start a new test case identified by NAME. All output
32052
+** through the next ".check" command is captured for comparison. See the
32053
+** ".check" commandn for additional informatioon.
32054
+**
32055
+** Options:
32056
+** --error-prefix TEXT Change error message prefix text to TEXT
32057
+*/
32058
+static int dotCmdTestcase(ShellState *p){
32059
+ int nArg = p->dot.nArg; /* Number of arguments */
32060
+ char **azArg = p->dot.azArg; /* Text of the arguments */
32061
+ int i; /* Loop counter */
32062
+ const char *zName = 0; /* Testcase name */
32063
+
32064
+ for(i=1; i<nArg; i++){
32065
+ char *z = azArg[i];
32066
+ if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
32067
+ if( optionMatch(z,"error-prefix") ){
32068
+ if( i+1>=nArg ){
32069
+ dotCmdError(p, i, "missing argument", 0);
32070
+ return 1;
32071
+ }
32072
+ free(p->zErrPrefix);
32073
+ i++;
32074
+ p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]);
32075
+ }else if( zName ){
32076
+ dotCmdError(p, i, "unknown option", 0);
32077
+ return 1;
32078
+ }else{
32079
+ zName = azArg[i];
32080
+ }
32081
+ }
32082
+ output_reset(p);
32083
+ if( cli_output_capture ){
32084
+ sqlite3_str_free(cli_output_capture);
32085
+ }
32086
+ cli_output_capture = sqlite3_str_new(0);
32087
+ if( zName ){
32088
+ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName);
32089
+ }else{
32090
+ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld",
32091
+ p->zInFile, p->lineno);
32092
+ }
32093
+ return 0;
32094
+}
3161432095
3161532096
/*
3161632097
** Enlarge the space allocated in p->dot so that it can hold more
3161732098
** than nArg parsed command-line arguments.
3161832099
*/
@@ -31641,11 +32122,11 @@
3164132122
free(p->dot.zCopy);
3164232123
z = p->dot.zCopy = strdup(zLine);
3164332124
shell_check_oom(z);
3164432125
szLine = strlen(z);
3164532126
while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31646
- if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){
32127
+ if( szLine>0 && z[szLine-1]==';' ){
3164732128
szLine--;
3164832129
while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
3164932130
}
3165032131
z[szLine] = 0;
3165132132
parseDotRealloc(p, 2);
@@ -31861,35 +32342,17 @@
3186132342
eputz("Usage: .changes on|off\n");
3186232343
rc = 1;
3186332344
}
3186432345
}else
3186532346
31866
-#ifndef SQLITE_SHELL_FIDDLE
3186732347
/* Cancel output redirection, if it is currently set (by .testcase)
3186832348
** Then read the content of the testcase-out.txt file and compare against
3186932349
** azArg[1]. If there are differences, report an error and exit.
3187032350
*/
3187132351
if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
31872
- char *zRes = 0;
31873
- output_reset(p);
31874
- if( nArg!=2 ){
31875
- eputz("Usage: .check GLOB-PATTERN\n");
31876
- rc = 2;
31877
- }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
31878
- rc = 2;
31879
- }else if( testcase_glob(azArg[1],zRes)==0 ){
31880
- cli_printf(stderr,
31881
- "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
31882
- p->zTestcase, azArg[1], zRes);
31883
- rc = 1;
31884
- }else{
31885
- cli_printf(p->out, "testcase-%s ok\n", p->zTestcase);
31886
- p->nCheck++;
31887
- }
31888
- sqlite3_free(zRes);
32352
+ rc = dotCmdCheck(p);
3188932353
}else
31890
-#endif /* !defined(SQLITE_SHELL_FIDDLE) */
3189132354
3189232355
#ifndef SQLITE_SHELL_FIDDLE
3189332356
if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
3189432357
failIfSafeMode(p, "cannot run .clone in safe mode");
3189532358
if( nArg==2 ){
@@ -32468,10 +32931,11 @@
3246832931
}else
3246932932
3247032933
if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
3247132934
if( nArg==2 ){
3247232935
p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No;
32936
+ p->mode.mFlags |= MFLG_HDR;
3247332937
p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr;
3247432938
}else{
3247532939
eputz("Usage: .headers on|off\n");
3247632940
rc = 1;
3247732941
}
@@ -32521,14 +32985,14 @@
3252132985
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
3252232986
goto meta_command_exit;
3252332987
}
3252432988
zSql = sqlite3_mprintf(
3252532989
"SELECT rootpage, 0 FROM sqlite_schema"
32526
- " WHERE name='%q' AND type='index'"
32990
+ " WHERE type='index' AND lower(name)=lower('%q')"
3252732991
"UNION ALL "
3252832992
"SELECT rootpage, 1 FROM sqlite_schema"
32529
- " WHERE name='%q' AND type='table'"
32993
+ " WHERE type='table' AND lower(name)=lower('%q')"
3253032994
" AND sql LIKE '%%without%%rowid%%'",
3253132995
azArg[1], azArg[1]
3253232996
);
3253332997
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3253432998
sqlite3_free(zSql);
@@ -32682,13 +33146,14 @@
3268233146
goto meta_command_exit;
3268333147
}
3268433148
if( nArg==3 ){
3268533149
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
3268633150
(int)integerValue(azArg[2]));
33151
+ }else{
33152
+ cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
33153
+ sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
3268733154
}
32688
- cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
32689
- sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
3269033155
}
3269133156
}else
3269233157
3269333158
if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
3269433159
open_db(p, 0);
@@ -33027,10 +33492,23 @@
3302733492
continue;
3302833493
}
3302933494
if( cli_strcmp(z,"once")==0 ){
3303033495
p->flgProgress |= SHELL_PROGRESS_ONCE;
3303133496
continue;
33497
+ }
33498
+ if( cli_strcmp(z,"timeout")==0 ){
33499
+ if( i==nArg-1 ){
33500
+ dotCmdError(p, i, "missing argument", 0);
33501
+ return 1;
33502
+ }
33503
+ i++;
33504
+ p->tmProgress = atof(azArg[i]);
33505
+ if( p->tmProgress>0.0 ){
33506
+ p->flgProgress = SHELL_PROGRESS_QUIET|SHELL_PROGRESS_TMOUT;
33507
+ if( nn==0 ) nn = 100;
33508
+ }
33509
+ continue;
3303233510
}
3303333511
if( cli_strcmp(z,"limit")==0 ){
3303433512
if( i+1>=nArg ){
3303533513
eputz("Error: missing argument on --limit\n");
3303633514
rc = 1;
@@ -33233,21 +33711,22 @@
3323333711
|| sqlite3_strlike(zName, "sqlite_schema", '\\')==0
3323433712
|| sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
3323533713
|| sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
3323633714
if( isSchema ){
3323733715
cli_printf(p->out,
33238
- "CREATE TABLE %s (\n"
33716
+ "CREATE TABLE %ssqlite_schema (\n"
3323933717
" type text,\n"
3324033718
" name text,\n"
3324133719
" tbl_name text,\n"
3324233720
" rootpage integer,\n"
3324333721
" sql text\n"
33244
- ");\n", zName);
33722
+ ");\n",
33723
+ sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : ""
33724
+ );
3324533725
}
3324633726
}
33247
- rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
33248
- -1, &pStmt, 0);
33727
+ rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
3324933728
if( rc ){
3325033729
shellDatabaseError(p->db);
3325133730
sqlite3_finalize(pStmt);
3325233731
3325333732
rc = 1;
@@ -33255,11 +33734,11 @@
3325533734
}
3325633735
pSql = sqlite3_str_new(p->db);
3325733736
sqlite3_str_appendf(pSql, "SELECT sql FROM", 0);
3325833737
iSchema = 0;
3325933738
while( sqlite3_step(pStmt)==SQLITE_ROW ){
33260
- const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
33739
+ const char *zDb = (const char*)sqlite3_column_text(pStmt, 1);
3326133740
char zScNum[30];
3326233741
sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
3326333742
sqlite3_str_appendall(pSql, zDiv);
3326433743
zDiv = " UNION ALL ";
3326533744
if( sqlite3_stricmp(zDb, "main")==0 ){
@@ -33275,11 +33754,12 @@
3327533754
" AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname",
3327633755
++iSchema, zDb);
3327733756
sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb);
3327833757
}
3327933758
sqlite3_finalize(pStmt);
33280
-#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
33759
+#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \
33760
+ && !defined(SQLITE_OMIT_VIRTUALTABLE)
3328133761
if( zName ){
3328233762
sqlite3_str_appendall(pSql,
3328333763
" UNION ALL SELECT shell_module_schema(name),"
3328433764
" 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list");
3328533765
}
@@ -33299,11 +33779,11 @@
3329933779
}else{
3330033780
sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName);
3330133781
}
3330233782
}
3330333783
if( bNoSystemTabs ){
33304
- sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCALE '_' AND ");
33784
+ sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ");
3330533785
}
3330633786
sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid");
3330733787
if( bDebug ){
3330833788
cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql));
3330933789
}else{
@@ -34017,25 +34497,15 @@
3401734497
sqlite3_str_free(pSql);
3401834498
modePop(p);
3401934499
if( rc ) return shellDatabaseError(p->db);
3402034500
}else
3402134501
34022
-#ifndef SQLITE_SHELL_FIDDLE
34023
- /* Begin redirecting output to the file "testcase-out.txt" */
34502
+ /* Set the p->zTestcase name and begin redirecting output into
34503
+ ** the cli_output_capture sqlite3_str */
3402434504
if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
34025
- output_reset(p);
34026
- p->out = output_file_open(p, "testcase-out.txt");
34027
- if( p->out==0 ){
34028
- eputz("Error: cannot open 'testcase-out.txt'\n");
34029
- }
34030
- if( nArg>=2 ){
34031
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
34032
- }else{
34033
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
34034
- }
34505
+ rc = dotCmdTestcase(p);
3403534506
}else
34036
-#endif /* !defined(SQLITE_SHELL_FIDDLE) */
3403734507
3403834508
#ifndef SQLITE_UNTESTABLE
3403934509
if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
3404034510
static const struct {
3404134511
const char *zCtrlName; /* Name of a test-control option */
@@ -34527,17 +34997,21 @@
3452734997
sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
3452834998
}else
3452934999
3453035000
if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
3453135001
if( nArg==2 ){
34532
- enableTimer = booleanValue(azArg[1]);
34533
- if( enableTimer && !HAS_TIMER ){
35002
+ if( cli_strcmp(azArg[1],"once")==0 ){
35003
+ p->enableTimer = 1;
35004
+ }else{
35005
+ p->enableTimer = 2*booleanValue(azArg[1]);
35006
+ }
35007
+ if( p->enableTimer && !HAS_TIMER ){
3453435008
eputz("Error: timer not available on this system.\n");
34535
- enableTimer = 0;
35009
+ p->enableTimer = 0;
3453635010
}
3453735011
}else{
34538
- eputz("Usage: .timer on|off\n");
35012
+ eputz("Usage: .timer on|off|once\n");
3453935013
rc = 1;
3454035014
}
3454135015
}else
3454235016
3454335017
#ifndef SQLITE_OMIT_TRACE
@@ -34708,10 +35182,11 @@
3470835182
if( p->nPopOutput ){
3470935183
p->nPopOutput--;
3471035184
if( p->nPopOutput==0 ) output_reset(p);
3471135185
}
3471235186
p->bSafeMode = p->bSafeModePersist;
35187
+ p->dot.nArg = 0;
3471335188
return rc;
3471435189
}
3471535190
3471635191
/* Line scan result and intermediate states (supporting scan resumption)
3471735192
*/
@@ -34944,13 +35419,13 @@
3494435419
char *zErrMsg = 0;
3494535420
3494635421
open_db(p, 0);
3494735422
if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
3494835423
if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
34949
- BEGIN_TIMER;
35424
+ BEGIN_TIMER(p);
3495035425
rc = shell_exec(p, zSql, &zErrMsg);
34951
- END_TIMER(p->out);
35426
+ END_TIMER(p);
3495235427
if( rc || zErrMsg ){
3495335428
char zPrefix[100];
3495435429
const char *zErrorTail;
3495535430
const char *zErrorType;
3495635431
if( zErrMsg==0 ){
@@ -35351,11 +35826,10 @@
3535135826
" -bail stop after hitting an error\n"
3535235827
" -batch force batch I/O\n"
3535335828
" -box set output mode to 'box'\n"
3535435829
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
3535535830
" -column set output mode to 'column'\n"
35356
- " -compat YYYYMMDD set default options for date YYYYMMDD\n"
3535735831
" -csv set output mode to 'csv'\n"
3535835832
#if !defined(SQLITE_OMIT_DESERIALIZE)
3535935833
" -deserialize open the database using sqlite3_deserialize()\n"
3536035834
#endif
3536135835
" -echo print inputs before execution\n"
@@ -35435,15 +35909,10 @@
3543535909
/*
3543635910
** Initialize the state information in data
3543735911
*/
3543835912
static void main_init(ShellState *p) {
3543935913
memset(p, 0, sizeof(*p));
35440
-#if defined(COMPATIBILITY_DATE)
35441
- p->iCompat = COMPATIBILITY_DATE;
35442
-#else
35443
- p->iCompat = 20251116;
35444
-#endif
3544535914
p->pAuxDb = &p->aAuxDb[0];
3544635915
p->shellFlgs = SHFLG_Lookaside;
3544735916
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p);
3544835917
#if !defined(SQLITE_SHELL_FIDDLE)
3544935918
verify_uninitialized();
@@ -35498,29 +35967,65 @@
3549835967
cli_puts(z, p->out);
3549935968
fflush(p->out);
3550035969
return 1;
3550135970
}
3550235971
35503
-#ifndef SQLITE_SHELL_IS_UTF8
35504
-# if (defined(_WIN32) || defined(WIN32)) \
35505
- && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
35506
-# define SQLITE_SHELL_IS_UTF8 (0)
35507
-# else
35508
-# define SQLITE_SHELL_IS_UTF8 (1)
35509
-# endif
35510
-#endif
35511
-
35972
+/* Alternative name to the entry point for Fiddle */
3551235973
#ifdef SQLITE_SHELL_FIDDLE
3551335974
# define main fiddle_main
3551435975
#endif
3551535976
35516
-#if SQLITE_SHELL_IS_UTF8
35517
-int SQLITE_CDECL main(int argc, char **argv){
35518
-#else
35977
+/* Use the wmain() entry point on Windows. Translate arguments to
35978
+** UTF8, then invoke the traditional main() entry point which is
35979
+** renamed using a #define to utf8_main() .
35980
+*/
35981
+#if defined(_WIN32) && !defined(main)
35982
+# define main utf8_main /* Rename entry point to utf_main() */
35983
+int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */
3551935984
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
35520
- char **argv;
35521
-#endif
35985
+ int rc, i;
35986
+ char **argv = malloc( sizeof(char*) * (argc+1) );
35987
+ char **orig = argv;
35988
+ if( argv==0 ){
35989
+ fprintf(stderr, "malloc failed\n");
35990
+ exit(1);
35991
+ }
35992
+ for(i=0; i<argc; i++){
35993
+ int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0);
35994
+ if( nByte==0 ){
35995
+ argv[i] = 0;
35996
+ }else{
35997
+ argv[i] = malloc( nByte );
35998
+ if( argv[i]==0 ){
35999
+ fprintf(stderr, "malloc failed\n");
36000
+ exit(1);
36001
+ }
36002
+ nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0);
36003
+ if( nByte==0 ){
36004
+ free(argv[i]);
36005
+ argv[i] = 0;
36006
+ }
36007
+ }
36008
+ }
36009
+ argv[argc] = 0;
36010
+ rc = utf8_main(argc, argv);
36011
+ for(i=0; i<argc; i++) free(orig[i]);
36012
+ free(argv);
36013
+ return rc;
36014
+}
36015
+#endif /* WIN32 */
36016
+
36017
+/*
36018
+** This is the main entry point for the process. Everything starts here.
36019
+**
36020
+** The "main" identifier may have been #defined to something else:
36021
+**
36022
+** utf8_main On Windows
36023
+** fiddle_main In Fiddle
36024
+** sqlite3_shell Other projects that use shell.c as a subroutine
36025
+*/
36026
+int SQLITE_CDECL main(int argc, char **argv){
3552236027
#ifdef SQLITE_DEBUG
3552336028
sqlite3_int64 mem_main_enter = 0;
3552436029
#endif
3552536030
char *zErrMsg = 0;
3552636031
#ifdef SQLITE_SHELL_FIDDLE
@@ -35538,14 +36043,10 @@
3553836043
int nOptsEnd = argc;
3553936044
int bEnableVfstrace = 0;
3554036045
char **azCmd = 0;
3554136046
int *aiCmd = 0;
3554236047
const char *zVfs = 0; /* Value of -vfs command-line option */
35543
-#if !SQLITE_SHELL_IS_UTF8
35544
- char **argvToFree = 0;
35545
- int argcToFree = 0;
35546
-#endif
3554736048
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
3554836049
3554936050
#ifdef SQLITE_SHELL_FIDDLE
3555036051
stdin_is_interactive = 0;
3555136052
stdout_is_console = 1;
@@ -35596,36 +36097,10 @@
3559636097
exit(1);
3559736098
}
3559836099
#endif
3559936100
main_init(&data);
3560036101
35601
- /* On Windows, we must translate command-line arguments into UTF-8.
35602
- ** The SQLite memory allocator subsystem has to be enabled in order to
35603
- ** do this. But we want to run an sqlite3_shutdown() afterwards so that
35604
- ** subsequent sqlite3_config() calls will work. So copy all results into
35605
- ** memory that does not come from the SQLite memory allocator.
35606
- */
35607
-#if !SQLITE_SHELL_IS_UTF8
35608
- sqlite3_initialize();
35609
- argvToFree = malloc(sizeof(argv[0])*argc*2);
35610
- shell_check_oom(argvToFree);
35611
- argcToFree = argc;
35612
- argv = argvToFree + argc;
35613
- for(i=0; i<argc; i++){
35614
- char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
35615
- i64 n;
35616
- shell_check_oom(z);
35617
- n = strlen(z);
35618
- argv[i] = malloc( n+1 );
35619
- shell_check_oom(argv[i]);
35620
- memcpy(argv[i], z, n+1);
35621
- argvToFree[i] = argv[i];
35622
- sqlite3_free(z);
35623
- }
35624
- sqlite3_shutdown();
35625
-#endif
35626
-
3562736102
assert( argc>=1 && argv && argv[0] );
3562836103
Argv0 = argv[0];
3562936104
3563036105
#ifdef SQLITE_SHELL_DBNAME_PROC
3563136106
{
@@ -35637,11 +36112,11 @@
3563736112
SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
3563836113
warnInmemoryDb = 0;
3563936114
}
3564036115
#endif
3564136116
35642
- /* Do an initial pass through the command-line argument to locate
36117
+ /* Do an initial pass through the command-line arguments to locate
3564336118
** the name of the database file, the name of the initialization file,
3564436119
** the size of the alternative malloc heap, options affecting commands
3564536120
** or SQL run from the command line, and the first command to execute.
3564636121
*/
3564736122
#ifndef SQLITE_SHELL_FIDDLE
@@ -35649,11 +36124,11 @@
3564936124
#endif
3565036125
for(i=1; i<argc; i++){
3565136126
char *z;
3565236127
z = argv[i];
3565336128
if( z[0]!='-' || i>nOptsEnd ){
35654
- if( data.aAuxDb->zDbFilename==0 ){
36129
+ if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){
3565536130
data.aAuxDb->zDbFilename = z;
3565636131
}else{
3565736132
/* Excess arguments are interpreted as SQL (or dot-commands) and
3565836133
** mean that nothing is read from stdin */
3565936134
readStdin = 0;
@@ -35694,15 +36169,10 @@
3569436169
if( n<2 ){
3569536170
sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n");
3569636171
exit(1);
3569736172
}
3569836173
stdout_tty_width = n;
35699
- }else if( cli_strcmp(z,"-compat")==0 ){
35700
- data.iCompat = atoi(cmdline_option_value(argc, argv, ++i));
35701
- modeFree(&data.mode);
35702
- memset(&data.mode, 0, sizeof(data.mode));
35703
- modeDefault(&data);
3570436174
}else if( cli_strcmp(z,"-utf8")==0 ){
3570536175
}else if( cli_strcmp(z,"-no-utf8")==0 ){
3570636176
}else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
3570736177
int val = 0;
3570836178
sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
@@ -35822,10 +36292,20 @@
3582236292
}else if( cli_strcmp(z,"-safe")==0 ){
3582336293
/* no-op - catch this on the second pass */
3582436294
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
3582536295
/* skip over the argument */
3582636296
i++;
36297
+ }else if( cli_strcmp(z,"-test-argv")==0 ){
36298
+ /* Undocumented test option. Print the values in argv[] and exit.
36299
+ ** Use this to verify that any translation of the argv[], for example
36300
+ ** on Windows that receives wargv[] from the OS and must convert
36301
+ ** to UTF8 prior to calling this routine. */
36302
+ int kk;
36303
+ for(kk=0; kk<argc; kk++){
36304
+ sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]);
36305
+ }
36306
+ return 0;
3582736307
}
3582836308
}
3582936309
#ifndef SQLITE_SHELL_FIDDLE
3583036310
if( !bEnableVfstrace ) verify_uninitialized();
3583136311
#endif
@@ -35848,11 +36328,30 @@
3584836328
3584936329
if( zVfs ){
3585036330
sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
3585136331
if( pVfs ){
3585236332
sqlite3_vfs_register(pVfs, 1);
35853
- }else{
36333
+ }
36334
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
36335
+ else if( access(zVfs,0)==0 ){
36336
+ /* If the VFS name is not the name of an existing VFS, but it is
36337
+ ** the name of a file, then try to load that file as an extension.
36338
+ ** Presumably the extension implements the desired VFS. */
36339
+ sqlite3 *db = 0;
36340
+ char *zErr = 0;
36341
+ sqlite3_open(":memory:", &db);
36342
+ sqlite3_enable_load_extension(db, 1);
36343
+ rc = sqlite3_load_extension(db, zVfs, 0, &zErr);
36344
+ sqlite3_close(db);
36345
+ if( (rc&0xff)!=SQLITE_OK ){
36346
+ cli_printf(stderr, "could not load extension VFS \"%s\": %s\n",
36347
+ zVfs, zErr);
36348
+ exit(1);
36349
+ }
36350
+ }
36351
+#endif
36352
+ else{
3585436353
cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs);
3585536354
exit(1);
3585636355
}
3585736356
}
3585836357
@@ -35889,11 +36388,11 @@
3588936388
** is given on the command line, look for a file named ~/.sqliterc and
3589036389
** try to process it.
3589136390
*/
3589236391
if( !noInit ) process_sqliterc(&data,zInitFile);
3589336392
35894
- /* Make a second pass through the command-line argument and set
36393
+ /* Make a second pass through the command-line arguments and set
3589536394
** options. This second pass is delayed until after the initialization
3589636395
** file is processed so that the command-line arguments will override
3589736396
** settings in the initialization file.
3589836397
*/
3589936398
for(i=1; i<argc; i++){
@@ -36015,12 +36514,10 @@
3601536514
stdin_is_interactive = 1;
3601636515
}else if( cli_strcmp(z,"-batch")==0 ){
3601736516
/* already handled */
3601836517
}else if( cli_strcmp(z,"-screenwidth")==0 ){
3601936518
i++;
36020
- }else if( cli_strcmp(z,"-compat")==0 ){
36021
- i++;
3602236519
}else if( cli_strcmp(z,"-utf8")==0 ){
3602336520
/* already handled */
3602436521
}else if( cli_strcmp(z,"-no-utf8")==0 ){
3602536522
/* already handled */
3602636523
}else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
@@ -36116,11 +36613,22 @@
3611636613
** command-line inputs, except for the argToSkip argument which contains
3611736614
** the database filename.
3611836615
*/
3611936616
for(i=0; i<nCmd; i++){
3612036617
echo_group_input(&data, azCmd[i]);
36121
- if( azCmd[i][0]=='.' ){
36618
+ if( isScriptFile(azCmd[i],0) ){
36619
+ FILE *inSaved = data.in;
36620
+ i64 savedLineno = data.lineno;
36621
+ int res = 1;
36622
+ if( (data.in = openChrSource(azCmd[i]))!=0 ){
36623
+ res = process_input(&data, azCmd[i]);
36624
+ fclose(data.in);
36625
+ }
36626
+ data.in = inSaved;
36627
+ data.lineno = savedLineno;
36628
+ if( res ) i = nCmd;
36629
+ }else if( azCmd[i][0]=='.' ){
3612236630
char *zErrCtx = malloc( 64 );
3612336631
shell_check_oom(zErrCtx);
3612436632
sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
3612536633
data.zInFile = "<cmdline>";
3612636634
data.zErrPrefix = zErrCtx;
@@ -36231,14 +36739,10 @@
3623136739
}
3623236740
find_home_dir(1);
3623336741
output_reset(&data);
3623436742
data.doXdgOpen = 0;
3623536743
clearTempFile(&data);
36236
-#if !SQLITE_SHELL_IS_UTF8
36237
- for(i=0; i<argcToFree; i++) free(argvToFree[i]);
36238
- free(argvToFree);
36239
-#endif
3624036744
modeFree(&data.mode);
3624136745
if( data.nSavedModes ){
3624236746
int ii;
3624336747
for(ii=0; ii<data.nSavedModes; ii++){
3624436748
modeFree(&data.aSavedModes[ii].mode);
3624536749
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -35,11 +35,11 @@
35 ** ext/recover/sqlite3recover.h
36 ** src/shell.c.in
37 **
38 ** To modify this program, get a copy of the canonical SQLite source tree,
39 ** edit the src/shell.c.in file and/or some of the other files that are
40 ** listed above, then rerun the rerun "make shell.c".
41 */
42 /************************* Begin src/shell.c.in ******************/
43 /*
44 ** 2001 September 15
45 **
@@ -49,11 +49,11 @@
49 ** May you do good and not evil.
50 ** May you find forgiveness for yourself and forgive others.
51 ** May you share freely, never taking more than you give.
52 **
53 *************************************************************************
54 ** This file contains code to implement the "sqlite" command line
55 ** utility for accessing SQLite databases.
56 */
57 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
58 /* This needs to come before any includes for MSVC compiler */
59 #define _CRT_SECURE_NO_WARNINGS
@@ -79,10 +79,14 @@
79 ** should only be used when building the "fiddle" web application, as
80 ** the browser-mode build has much different user input requirements
81 ** and this build mode rewires the user input subsystem to account for
82 ** that.
83 */
 
 
 
 
84
85 /*
86 ** Warning pragmas copied from msvc.h in the core.
87 */
88 #if defined(_MSC_VER)
@@ -872,10 +876,11 @@
872 #ifndef SQLITE_QRF_H
873 #include "qrf.h"
874 #endif
875 #include <string.h>
876 #include <assert.h>
 
877
878 /* typedef sqlite3_int64 i64; */
879
880 /* A single line in the EQP output */
881 typedef struct qrfEQPGraphRow qrfEQPGraphRow;
@@ -889,11 +894,12 @@
889 /* All EQP output is collected into an instance of the following */
890 typedef struct qrfEQPGraph qrfEQPGraph;
891 struct qrfEQPGraph {
892 qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
893 qrfEQPGraphRow *pLast; /* Last element of the pRow list */
894 char zPrefix[100]; /* Graph prefix */
 
895 };
896
897 /*
898 ** Private state information. Subject to change from one release to the
899 ** next.
@@ -995,10 +1001,19 @@
995 */
996 static void qrfOom(Qrf *p){
997 qrfError(p, SQLITE_NOMEM, "out of memory");
998 }
999
 
 
 
 
 
 
 
 
 
1000
1001
1002 /*
1003 ** Add a new entry to the EXPLAIN QUERY PLAN data
1004 */
@@ -1074,10 +1089,49 @@
1074 qrfEqpRenderLevel(p, pRow->iEqpId);
1075 p->u.pGraph->zPrefix[n] = 0;
1076 }
1077 }
1078 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1079
1080 /*
1081 ** Display and reset the EXPLAIN QUERY PLAN data
1082 */
1083 static void qrfEqpRender(Qrf *p, i64 nCycle){
@@ -1090,11 +1144,30 @@
1090 }
1091 sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3);
1092 p->u.pGraph->pRow = pRow->pNext;
1093 sqlite3_free(pRow);
1094 }else if( nCycle>0 ){
1095 sqlite3_str_appendf(p->pOut, "QUERY PLAN (cycles=%lld [100%%])\n",nCycle);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1096 }else{
1097 sqlite3_str_appendall(p->pOut, "QUERY PLAN\n");
1098 }
1099 p->u.pGraph->zPrefix[0] = 0;
1100 qrfEqpRenderLevel(p, 0);
@@ -1145,10 +1218,12 @@
1145 static const int f = SQLITE_SCANSTAT_COMPLEX;
1146 sqlite3_stmt *pS = p->pStmt;
1147 int i = 0;
1148 i64 nTotal = 0;
1149 int nWidth = 0;
 
 
1150 sqlite3_str *pLine = sqlite3_str_new(p->db);
1151 sqlite3_str *pStats = sqlite3_str_new(p->db);
1152 qrfEqpReset(p);
1153
1154 for(i=0; 1; i++){
@@ -1158,11 +1233,11 @@
1158 break;
1159 }
1160 n = (int)strlen(z) + qrfStatsHeight(pS,i)*3;
1161 if( n>nWidth ) nWidth = n;
1162 }
1163 nWidth += 4;
1164
1165 sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal);
1166 for(i=0; 1; i++){
1167 i64 nLoop = 0;
1168 i64 nRow = 0;
@@ -1173,55 +1248,67 @@
1173 const char *zName = 0;
1174 double rEst = 0.0;
1175
1176 if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){
1177 break;
 
 
 
 
 
1178 }
1179 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst);
 
1180 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop);
1181 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow);
1182 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle);
1183 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId);
1184 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
1185 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName);
1186
1187 if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
1188 const char *zSp = "";
1189 double rpl;
1190 sqlite3_str_reset(pStats);
1191 if( nCycle>=0 && nTotal>0 ){
1192 sqlite3_str_appendf(pStats, "cycles=%lld [%d%%]",
1193 nCycle, ((nCycle*100)+nTotal/2) / nTotal
 
1194 );
1195 zSp = " ";
1196 }
1197 if( nLoop>=0 ){
1198 sqlite3_str_appendf(pStats, "%sloops=%lld", zSp, nLoop);
1199 zSp = " ";
 
 
 
 
 
1200 }
1201 if( nRow>=0 ){
1202 sqlite3_str_appendf(pStats, "%srows=%lld", zSp, nRow);
1203 zSp = " ";
1204 }
1205
1206 if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1207 rpl = (double)nRow / (double)nLoop;
1208 sqlite3_str_appendf(pStats, "%srpl=%.1f est=%.1f", zSp, rpl, rEst);
1209 }
1210
1211 sqlite3_str_appendf(pLine,
1212 "% *s (%s)", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo,
1213 sqlite3_str_value(pStats)
1214 );
1215 sqlite3_str_reset(pStats);
1216 qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine));
1217 sqlite3_str_reset(pLine);
1218 }else{
1219 qrfEqpAppend(p, iId, iPid, zo);
1220 }
1221 }
 
 
1222 sqlite3_free(sqlite3_str_finish(pLine));
 
1223 sqlite3_free(sqlite3_str_finish(pStats));
1224 #endif
1225 }
1226
1227
@@ -1581,13 +1668,15 @@
1581 ** (3) z[] does not looks like a numeric literal
1582 */
1583 static int qrfRelaxable(Qrf *p, const char *z){
1584 size_t i, n;
1585 if( z[0]=='\'' || qrfSpace(z[0]) ) return 0;
1586 if( z[0]==0 && (p->spec.zNull==0 || p->spec.zNull[0]==0) ) return 0;
 
 
1587 n = strlen(z);
1588 if( z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
1589 if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0;
1590 i = (z[0]=='-' || z[0]=='+');
1591 if( strcmp(z+i,"Inf")==0 ) return 0;
1592 if( !qrfDigit(z[i]) ) return 1;
1593 i++;
@@ -2729,10 +2818,11 @@
2729 int nNL = 0;
2730 int n, w;
2731 pStr = sqlite3_str_new(p->db);
2732 qrfEncodeText(p, pStr, z ? z : "");
2733 n = sqlite3_str_length(pStr);
 
2734 z = data.az[data.n] = sqlite3_str_finish(pStr);
2735 if( p->spec.nTitleLimit ){
2736 nNL = 0;
2737 data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
2738 p->spec.nTitleLimit );
@@ -2756,10 +2846,11 @@
2756 int n, w;
2757 int eType = sqlite3_column_type(p->pStmt,i);
2758 pStr = sqlite3_str_new(p->db);
2759 qrfRenderValue(p, pStr, i);
2760 n = sqlite3_str_length(pStr);
 
2761 z = data.az[data.n] = sqlite3_str_finish(pStr);
2762 data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
2763 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2764 data.n++;
2765 if( w>data.a[i].mxW ) data.a[i].mxW = w;
@@ -2910,11 +3001,11 @@
2910 ){
2911 bRTrim = 1;
2912 }else{
2913 bRTrim = 0;
2914 }
2915 for(i=0; i<data.n; i+=nColumn){
2916 int bMore;
2917 int nRow = 0;
2918
2919 /* Draw a single row of the table. This might be the title line
2920 ** (if there is a title line) or a row in the body of the table.
@@ -3097,11 +3188,11 @@
3097 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
3098 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
3099 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
3100 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
3101
3102 for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt); iOp++){
3103 int iAddr = sqlite3_column_int(p->pStmt, 0);
3104 const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
3105 int p1 = sqlite3_column_int(p->pStmt, 2);
3106 int p2 = sqlite3_column_int(p->pStmt, 3);
3107
@@ -3154,11 +3245,11 @@
3154 nWidth = sizeof(aScanExpWidth)/sizeof(int);
3155 iIndent = 3;
3156 }
3157 if( nArg>nWidth ) nArg = nWidth;
3158
3159 for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW; iOp++){
3160 /* If this is the first row seen, print out the headers */
3161 if( iOp==0 ){
3162 for(i=0; i<nArg; i++){
3163 const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
3164 qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
@@ -3410,10 +3501,11 @@
3410 sqlite3_str_append(p->pOut, "\n", 1);
3411 zVal += iNext;
3412 }while( zVal[0] );
3413 sqlite3_str_reset(pVal);
3414 }
 
3415 sqlite3_free(sqlite3_str_finish(pVal));
3416 qrfWrite(p);
3417 break;
3418 }
3419 case QRF_STYLE_Eqp: {
@@ -3473,11 +3565,11 @@
3473 p->pOut = sqlite3_str_new(p->db);
3474 if( p->pOut==0 ){
3475 qrfOom(p);
3476 return;
3477 }
3478 p->iErr = 0;
3479 p->nCol = sqlite3_column_count(p->pStmt);
3480 p->nRow = 0;
3481 sz = sizeof(sqlite3_qrf_spec);
3482 memcpy(&p->spec, pSpec, sz);
3483 if( p->spec.zNull==0 ) p->spec.zNull = "";
@@ -3644,17 +3736,27 @@
3644 sqlite3_free(p->u.sLine.azCol);
3645 }
3646 break;
3647 }
3648 case QRF_STYLE_Stats:
3649 case QRF_STYLE_StatsEst:
 
 
 
 
 
 
 
 
 
3650 case QRF_STYLE_Eqp: {
3651 qrfEqpRender(p, 0);
3652 qrfWrite(p);
3653 break;
3654 }
3655 }
 
3656 if( p->spec.pzOutput ){
3657 if( p->spec.pzOutput[0] ){
3658 sqlite3_int64 n, sz;
3659 char *zCombined;
3660 sz = strlen(p->spec.pzOutput[0]);
@@ -3815,13 +3917,10 @@
3815
3816
3817 #define eputz(z) cli_puts(z,stderr)
3818 #define sputz(fp,z) cli_puts(z,fp)
3819
3820 /* True if the timer is enabled */
3821 static int enableTimer = 0;
3822
3823 /* A version of strcmp() that works with NULL values */
3824 static int cli_strcmp(const char *a, const char *b){
3825 if( a==0 ) a = "";
3826 if( b==0 ) b = "";
3827 return strcmp(a,b);
@@ -3834,11 +3933,11 @@
3834
3835 /* Return the current wall-clock time in microseconds since the
3836 ** Unix epoch (1970-01-01T00:00:00Z)
3837 */
3838 static sqlite3_int64 timeOfDay(void){
3839 #if defined(_WIN64)
3840 sqlite3_uint64 t;
3841 FILETIME tm;
3842 GetSystemTimePreciseAsFileTime(&tm);
3843 t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
3844 t += 116444736000000000LL;
@@ -3862,154 +3961,10 @@
3862 (void)gettimeofday(&sNow,0);
3863 return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
3864 #endif
3865 }
3866
3867 #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
3868 #include <sys/time.h>
3869 #include <sys/resource.h>
3870
3871 /* VxWorks does not support getrusage() as far as we can determine */
3872 #if defined(_WRS_KERNEL) || defined(__RTP__)
3873 struct rusage {
3874 struct timeval ru_utime; /* user CPU time used */
3875 struct timeval ru_stime; /* system CPU time used */
3876 };
3877 #define getrusage(A,B) memset(B,0,sizeof(*B))
3878 #endif
3879
3880
3881 /* Saved resource information for the beginning of an operation */
3882 static struct rusage sBegin; /* CPU time at start */
3883 static sqlite3_int64 iBegin; /* Wall-clock time at start */
3884
3885 /*
3886 ** Begin timing an operation
3887 */
3888 static void beginTimer(void){
3889 if( enableTimer ){
3890 getrusage(RUSAGE_SELF, &sBegin);
3891 iBegin = timeOfDay();
3892 }
3893 }
3894
3895 /* Return the difference of two time_structs in seconds */
3896 static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
3897 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
3898 (double)(pEnd->tv_sec - pStart->tv_sec);
3899 }
3900
3901 /*
3902 ** Print the timing results.
3903 */
3904 static void endTimer(FILE *out){
3905 if( enableTimer ){
3906 sqlite3_int64 iEnd = timeOfDay();
3907 struct rusage sEnd;
3908 getrusage(RUSAGE_SELF, &sEnd);
3909 cli_printf(out, "Run Time: real %.6f user %.6f sys %.6f\n",
3910 (iEnd - iBegin)*0.000001,
3911 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
3912 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
3913 }
3914 }
3915
3916 #define BEGIN_TIMER beginTimer()
3917 #define END_TIMER(X) endTimer(X)
3918 #define HAS_TIMER 1
3919
3920 #elif (defined(_WIN32) || defined(WIN32))
3921
3922 /* Saved resource information for the beginning of an operation */
3923 static HANDLE hProcess;
3924 static FILETIME ftKernelBegin;
3925 static FILETIME ftUserBegin;
3926 static sqlite3_int64 ftWallBegin;
3927 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
3928 LPFILETIME, LPFILETIME);
3929 static GETPROCTIMES getProcessTimesAddr = NULL;
3930
3931 /*
3932 ** Check to see if we have timer support. Return 1 if necessary
3933 ** support found (or found previously).
3934 */
3935 static int hasTimer(void){
3936 if( getProcessTimesAddr ){
3937 return 1;
3938 } else {
3939 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
3940 ** versions. See if the version we are running on has it, and if it
3941 ** does, save off a pointer to it and the current process handle.
3942 */
3943 hProcess = GetCurrentProcess();
3944 if( hProcess ){
3945 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
3946 if( NULL != hinstLib ){
3947 getProcessTimesAddr =
3948 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
3949 if( NULL != getProcessTimesAddr ){
3950 return 1;
3951 }
3952 FreeLibrary(hinstLib);
3953 }
3954 }
3955 }
3956 return 0;
3957 }
3958
3959 /*
3960 ** Begin timing an operation
3961 */
3962 static void beginTimer(void){
3963 if( enableTimer && getProcessTimesAddr ){
3964 FILETIME ftCreation, ftExit;
3965 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
3966 &ftKernelBegin,&ftUserBegin);
3967 ftWallBegin = timeOfDay();
3968 }
3969 }
3970
3971 /* Return the difference of two FILETIME structs in seconds */
3972 static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
3973 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
3974 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
3975 return (double) ((i64End - i64Start) / 10000000.0);
3976 }
3977
3978 /*
3979 ** Print the timing results.
3980 */
3981 static void endTimer(FILE *out){
3982 if( enableTimer && getProcessTimesAddr){
3983 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
3984 sqlite3_int64 ftWallEnd = timeOfDay();
3985 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
3986 #ifdef _WIN64
3987 /* microsecond precision on 64-bit windows */
3988 cli_printf(out, "Run Time: real %.6f user %f sys %f\n",
3989 (ftWallEnd - ftWallBegin)*0.000001,
3990 timeDiff(&ftUserBegin, &ftUserEnd),
3991 timeDiff(&ftKernelBegin, &ftKernelEnd));
3992 #else
3993 /* millisecond precisino on 32-bit windows */
3994 cli_printf(out, "Run Time: real %.3f user %.3f sys %.3f\n",
3995 (ftWallEnd - ftWallBegin)*0.000001,
3996 timeDiff(&ftUserBegin, &ftUserEnd),
3997 timeDiff(&ftKernelBegin, &ftKernelEnd));
3998 #endif
3999 }
4000 }
4001
4002 #define BEGIN_TIMER beginTimer()
4003 #define END_TIMER(X) endTimer(X)
4004 #define HAS_TIMER hasTimer()
4005
4006 #else
4007 #define BEGIN_TIMER
4008 #define END_TIMER(X) /*no-op*/
4009 #define HAS_TIMER 0
4010 #endif
4011
4012 /*
4013 ** Used to prevent warnings about unused parameters
4014 */
4015 #define UNUSED_PARAMETER(x) (void)(x)
@@ -4068,10 +4023,18 @@
4068 #define PROMPT_LEN_MAX 128
4069 /* First line prompt. default: "sqlite> " */
4070 static char mainPrompt[PROMPT_LEN_MAX];
4071 /* Continuation prompt. default: " ...> " */
4072 static char continuePrompt[PROMPT_LEN_MAX];
 
 
 
 
 
 
 
 
4073
4074 /* This is variant of the standard-library strncpy() routine with the
4075 ** one change that the destination string is always zero-terminated, even
4076 ** if there is no zero-terminator in the first n-1 characters of the source
4077 ** string.
@@ -4188,17 +4151,10 @@
4188 */
4189 static void shell_check_oom(const void *p){
4190 if( p==0 ) shell_out_of_memory();
4191 }
4192
4193 /*
4194 ** Write I/O traces to the following stream.
4195 */
4196 #ifdef SQLITE_ENABLE_IOTRACE
4197 static FILE *iotrace = 0;
4198 #endif
4199
4200 /*
4201 ** This routine works like printf in that its first argument is a
4202 ** format string and subsequent arguments are values to be substituted
4203 ** in place of % fields. The result of formatting this string
4204 ** is written to iotrace.
@@ -8349,13 +8305,13 @@
8349 }else if( e<-10000 ){
8350 e = -10000;
8351 }
8352
8353 if( m<0 ){
 
8354 isNeg = 1;
8355 m = -m;
8356 if( m<0 ) return;
8357 }else if( m==0 && e>-1000 && e<1000 ){
8358 sqlite3_result_double(context, 0.0);
8359 return;
8360 }
8361 while( (m>>32)&0xffe00000 ){
@@ -9472,11 +9428,11 @@
9472 ** (X) match X
9473 ** X|Y X or Y
9474 ** ^X X occurring at the beginning of the string
9475 ** X$ X occurring at the end of the string
9476 ** . Match any single character
9477 ** \c Character c where c is one of \{}()[]|*+?.
9478 ** \c C-language escapes for c in afnrtv. ex: \t or \n
9479 ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
9480 ** \xXX Where XX is exactly 2 hex digits, unicode value XX
9481 ** [abc] Any single character from the set abc
9482 ** [^abc] Any single character not in the set abc
@@ -9857,11 +9813,11 @@
9857
9858 /* A backslash character has been seen, read the next character and
9859 ** return its interpretation.
9860 */
9861 static unsigned re_esc_char(ReCompiled *p){
9862 static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
9863 static const char zTrans[] = "\a\f\n\r\t\v";
9864 int i, v = 0;
9865 char c;
9866 if( p->sIn.i>=p->sIn.mx ) return 0;
9867 c = p->sIn.z[p->sIn.i];
@@ -10180,15 +10136,22 @@
10180 }
10181 return pRe->zErr;
10182 }
10183
10184 /*
10185 ** Compute a reasonable limit on the length of the REGEXP NFA.
10186 */
10187 static int re_maxlen(sqlite3_context *context){
10188 sqlite3 *db = sqlite3_context_db_handle(context);
10189 return 75 + sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1)/2;
 
 
 
 
 
 
 
10190 }
10191
10192 /*
10193 ** Implementation of the regexp() SQL function. This function implements
10194 ** the build-in REGEXP operator. The first argument to the function is the
@@ -10210,14 +10173,21 @@
10210 int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
10211
10212 (void)argc; /* Unused */
10213 pRe = sqlite3_get_auxdata(context, 0);
10214 if( pRe==0 ){
 
 
10215 zPattern = (const char*)sqlite3_value_text(argv[0]);
10216 if( zPattern==0 ) return;
10217 zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10218 sqlite3_user_data(context)!=0);
 
 
 
 
 
10219 if( zErr ){
10220 re_free(pRe);
10221 sqlite3_result_error(context, zErr, -1);
10222 return;
10223 }
@@ -10279,11 +10249,11 @@
10279 "ATSTART",
10280 };
10281
10282 zPattern = (const char*)sqlite3_value_text(argv[0]);
10283 if( zPattern==0 ) return;
10284 zErr = re_compile(&pRe, zPattern, re_maxlen(context),
10285 sqlite3_user_data(context)!=0);
10286 if( zErr ){
10287 re_free(pRe);
10288 sqlite3_result_error(context, zErr, -1);
10289 return;
@@ -13067,11 +13037,11 @@
13067 nFile = (int)strlen(zFile)+1;
13068 }
13069
13070 rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
13071 if( rc==SQLITE_OK ){
13072 pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
13073 if( pNew==0 ) return SQLITE_NOMEM;
13074 memset(pNew, 0, nByte+nFile);
13075 pNew->db = db;
13076 pNew->aBuffer = (u8*)&pNew[1];
13077 if( zFile ){
@@ -13213,18 +13183,19 @@
13213 ** sqlite3_free().
13214 */
13215 static int zipfileReadData(
13216 FILE *pFile, /* Read from this file */
13217 u8 *aRead, /* Read into this buffer */
13218 int nRead, /* Number of bytes to read */
13219 i64 iOff, /* Offset to read from */
13220 char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
13221 ){
13222 size_t n;
13223 fseek(pFile, (long)iOff, SEEK_SET);
13224 n = fread(aRead, 1, nRead, pFile);
13225 if( (int)n!=nRead ){
 
13226 *pzErrmsg = sqlite3_mprintf("error in fread()");
13227 return SQLITE_ERROR;
13228 }
13229 return SQLITE_OK;
13230 }
@@ -13237,11 +13208,11 @@
13237 if( nWrite>0 ){
13238 size_t n = nWrite;
13239 fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
13240 n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
13241 if( (int)n!=nWrite ){
13242 pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
13243 return SQLITE_ERROR;
13244 }
13245 pTab->szCurrent += nWrite;
13246 }
13247 return SQLITE_OK;
@@ -13484,10 +13455,11 @@
13484 /*
13485 ** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a
13486 ** generic corruption message and return SQLITE_CORRUPT;
13487 */
13488 static int zipfileCorrupt(char **pzErr){
 
13489 *pzErr = sqlite3_mprintf("zip archive is corrupt");
13490 return SQLITE_CORRUPT;
13491 }
13492
13493 /*
@@ -13502,11 +13474,11 @@
13502 ** final value of (*ppEntry) undefined.
13503 */
13504 static int zipfileGetEntry(
13505 ZipfileTab *pTab, /* Store any error message here */
13506 const u8 *aBlob, /* Pointer to in-memory file image */
13507 int nBlob, /* Size of aBlob[] in bytes */
13508 FILE *pFile, /* If aBlob==0, read from this file */
13509 i64 iOff, /* Offset of CDS record */
13510 ZipfileEntry **ppEntry /* OUT: Pointer to new object */
13511 ){
13512 u8 *aRead;
@@ -13542,18 +13514,18 @@
13542 rc = SQLITE_NOMEM;
13543 }else{
13544 memset(pNew, 0, sizeof(ZipfileEntry));
13545 rc = zipfileReadCDS(aRead, &pNew->cds);
13546 if( rc!=SQLITE_OK ){
13547 *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
13548 }else if( aBlob==0 ){
13549 rc = zipfileReadData(
13550 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
13551 );
13552 }else{
13553 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
13554 if( (iOff + ZIPFILE_LFH_FIXED_SZ + nFile + nExtra)>nBlob ){
13555 rc = zipfileCorrupt(pzErr);
13556 }
13557 }
13558 }
13559
@@ -13574,19 +13546,19 @@
13574 ZipfileLFH lfh;
13575 if( pFile ){
13576 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
13577 }else{
13578 aRead = (u8*)&aBlob[pNew->cds.iOffset];
13579 if( (pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>(unsigned)nBlob ){
13580 rc = zipfileCorrupt(pzErr);
13581 }
13582 }
13583
13584 memset(&lfh, 0, sizeof(lfh));
13585 if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
13586 if( rc==SQLITE_OK ){
13587 pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
13588 pNew->iDataOff += lfh.nFile + lfh.nExtra;
13589 if( aBlob && pNew->cds.szCompressed ){
13590 if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){
13591 rc = zipfileCorrupt(pzErr);
13592 }else{
@@ -13593,11 +13565,11 @@
13593 pNew->aData = &pNew->aExtra[nExtra];
13594 memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
13595 }
13596 }
13597 }else{
13598 *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
13599 (int)pNew->cds.iOffset
13600 );
13601 }
13602 }
13603
@@ -13617,11 +13589,11 @@
13617 static int zipfileNext(sqlite3_vtab_cursor *cur){
13618 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
13619 int rc = SQLITE_OK;
13620
13621 if( pCsr->pFile ){
13622 i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
13623 zipfileEntryFree(pCsr->pCurrent);
13624 pCsr->pCurrent = 0;
13625 if( pCsr->iNextOff>=iEof ){
13626 pCsr->bEof = 1;
13627 }else{
@@ -13855,16 +13827,16 @@
13855 ** an English language error message may be left in virtual-table pTab.
13856 */
13857 static int zipfileReadEOCD(
13858 ZipfileTab *pTab, /* Return errors here */
13859 const u8 *aBlob, /* Pointer to in-memory file image */
13860 int nBlob, /* Size of aBlob[] in bytes */
13861 FILE *pFile, /* Read from this file if aBlob==0 */
13862 ZipfileEOCD *pEOCD /* Object to populate */
13863 ){
13864 u8 *aRead = pTab->aBuffer; /* Temporary buffer */
13865 int nRead; /* Bytes to read from file */
13866 int rc = SQLITE_OK;
13867
13868 memset(pEOCD, 0, sizeof(ZipfileEOCD));
13869 if( aBlob==0 ){
13870 i64 iOff; /* Offset to read from */
@@ -13881,11 +13853,11 @@
13881 nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
13882 aRead = (u8*)&aBlob[nBlob-nRead];
13883 }
13884
13885 if( rc==SQLITE_OK ){
13886 int i;
13887
13888 /* Scan backwards looking for the signature bytes */
13889 for(i=nRead-20; i>=0; i--){
13890 if( aRead[i]==0x50 && aRead[i+1]==0x4b
13891 && aRead[i+2]==0x05 && aRead[i+3]==0x06
@@ -13892,13 +13864,11 @@
13892 ){
13893 break;
13894 }
13895 }
13896 if( i<0 ){
13897 pTab->base.zErrMsg = sqlite3_mprintf(
13898 "cannot find end of central directory record"
13899 );
13900 return SQLITE_ERROR;
13901 }
13902
13903 aRead += i+4;
13904 pEOCD->iDisk = zipfileRead16(aRead);
@@ -13939,11 +13909,11 @@
13939 pNew->pNext = pBefore;
13940 *pp = pNew;
13941 }
13942 }
13943
13944 static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
13945 ZipfileEOCD eocd;
13946 int rc;
13947 int i;
13948 i64 iOff;
13949
@@ -13987,11 +13957,11 @@
13987 zipfileCursorErr(pCsr, "zipfile() function requires an argument");
13988 return SQLITE_ERROR;
13989 }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
13990 static const u8 aEmptyBlob = 0;
13991 const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
13992 int nBlob = sqlite3_value_bytes(argv[0]);
13993 assert( pTab->pFirstEntry==0 );
13994 if( aBlob==0 ){
13995 aBlob = &aEmptyBlob;
13996 nBlob = 0;
13997 }
@@ -14185,23 +14155,23 @@
14185 ZipfileTab *pTab = (ZipfileTab*)pVtab;
14186 int rc = SQLITE_OK;
14187
14188 assert( pTab->pWriteFd==0 );
14189 if( pTab->zFile==0 || pTab->zFile[0]==0 ){
14190 pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
14191 return SQLITE_ERROR;
14192 }
14193
14194 /* Open a write fd on the file. Also load the entire central directory
14195 ** structure into memory. During the transaction any new file data is
14196 ** appended to the archive file, but the central directory is accumulated
14197 ** in main-memory until the transaction is committed. */
14198 pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
14199 if( pTab->pWriteFd==0 ){
14200 pTab->base.zErrMsg = sqlite3_mprintf(
14201 "zipfile: failed to open file %s for writing", pTab->zFile
14202 );
14203 rc = SQLITE_ERROR;
14204 }else{
14205 fseek(pTab->pWriteFd, 0, SEEK_END);
14206 pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
14207 rc = zipfileLoadDirectory(pTab, 0, 0);
@@ -14662,11 +14632,11 @@
14662 int nEntry;
14663 ZipfileBuffer body;
14664 ZipfileBuffer cds;
14665 };
14666
14667 static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
14668 if( pBuf->n+nByte>pBuf->nAlloc ){
14669 u8 *aNew;
14670 sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
14671 int nReq = pBuf->n + nByte;
14672
@@ -14711,11 +14681,11 @@
14711 u32 iCrc32 = 0; /* crc32 of uncompressed data */
14712
14713 char *zName = 0; /* Path (name) of new entry */
14714 int nName = 0; /* Size of zName in bytes */
14715 char *zFree = 0; /* Free this before returning */
14716 int nByte;
14717
14718 memset(&e, 0, sizeof(e));
14719 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
14720 if( p==0 ) return;
14721
@@ -24161,28 +24131,28 @@
24161 u8 autoExplain; /* Automatically turn on .explain mode */
24162 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
24163 u8 autoEQPtrace; /* autoEQP is in trace mode */
24164 u8 scanstatsOn; /* True to display scan stats before each finalize */
24165 u8 bAutoScreenWidth; /* Using the TTY to determine screen width */
24166 u8 mFlags; /* MFLG_ECHO and/or MFLG_CRLF */
24167 u8 eMode; /* One of the MODE_ values */
24168 sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
24169 } Mode;
24170
24171 /* Flags for Mode.mFlags */
24172 #define MFLG_ECHO 0x01 /* Echo inputs to output */
24173 #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
 
24174
24175
24176 /*
24177 ** State information about the database connection is contained in an
24178 ** instance of the following structure.
24179 */
24180 typedef struct ShellState ShellState;
24181 struct ShellState {
24182 sqlite3 *db; /* The database */
24183 int iCompat; /* Compatibility date YYYYMMDD */
24184 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
24185 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
24186 u8 nEqpLevel; /* Depth of the EQP output graph */
24187 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
24188 u8 bSafeMode; /* True to prohibit unsafe operations */
@@ -24190,11 +24160,14 @@
24190 u8 eRestoreState; /* See comments above doAutoDetectRestore() */
24191 unsigned statsOn; /* True to display memory stats before each finalize */
24192 unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
24193 u8 nPopOutput; /* Revert .output settings when reaching zero */
24194 u8 nPopMode; /* Revert .mode settings when reaching zero */
 
24195 int inputNesting; /* Track nesting level of .read and other redirects */
 
 
24196 i64 lineno; /* Line number of last line read from in */
24197 const char *zInFile; /* Name of the input file */
24198 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
24199 FILE *in; /* Read commands from this stream */
24200 FILE *out; /* Write results here */
@@ -24286,10 +24259,11 @@
24286 #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
24287 #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress
24288 ** callback limit is reached, and for each
24289 ** top-level SQL statement */
24290 #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
 
24291
24292 /* Names of values for Mode.spec.eEsc and Mode.spec.eText
24293 */
24294 static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
24295 static const char *qrfQuoteNames[] =
@@ -24447,10 +24421,181 @@
24447 ** Limit input nesting via .read or any other input redirect.
24448 ** It's not too expensive, so a generous allowance can be made.
24449 */
24450 #define MAX_INPUT_NESTING 25
24451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24452
24453 /*
24454 ** Clear a display mode, freeing any allocated memory that it
24455 ** contains.
24456 */
@@ -24534,11 +24679,13 @@
24534 if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]);
24535 if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]);
24536 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24537 pM->spec.eText = pI->eText;
24538 pM->spec.eBlob = pI->eBlob;
24539 pM->spec.bTitles = pI->bHdr;
 
 
24540 pM->spec.eTitle = pI->eHdr;
24541 if( pI->mFlg & 0x01 ){
24542 pM->spec.bBorder = QRF_No;
24543 }else{
24544 pM->spec.bBorder = QRF_Auto;
@@ -24570,18 +24717,17 @@
24570 p->mode.mFlags = mFlags;
24571 }
24572 }
24573
24574 /*
24575 ** Set the mode to the default according to p->iCompat. It assumed
24576 ** that the mode has already been freed and zeroed prior to calling
24577 ** this routine.
24578 */
24579 static void modeDefault(ShellState *p){
24580 p->mode.spec.iVersion = 1;
24581 p->mode.autoExplain = 1;
24582 if( p->iCompat>=20251115 && (stdin_is_interactive || stdout_is_console) ){
24583 modeChange(p, MODE_TTY);
24584 }else{
24585 modeChange(p, MODE_BATCH);
24586 }
24587 }
@@ -25371,10 +25517,17 @@
25371 ** Progress handler callback.
25372 */
25373 static int progress_handler(void *pClientData) {
25374 ShellState *p = (ShellState*)pClientData;
25375 p->nProgress++;
 
 
 
 
 
 
 
25376 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
25377 cli_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
25378 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
25379 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
25380 return 1;
@@ -25908,10 +26061,12 @@
25908 char *zBuf = sqlite3_malloc64( szVar-5 );
25909 if( zBuf ){
25910 memcpy(zBuf, &zVar[6], szVar-5);
25911 sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
25912 }
 
 
25913 #ifdef SQLITE_ENABLE_CARRAY
25914 }else if( strncmp(zVar, "$carray_", 8)==0 ){
25915 static char *azColorNames[] = {
25916 "azure", "black", "blue", "brown", "cyan", "fuchsia", "gold",
25917 "gray", "green", "indigo", "khaki", "lime", "magenta", "maroon",
@@ -26167,27 +26322,36 @@
26167 pArg->pStmt = pStmt;
26168 }
26169
26170 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
26171 isExplain = sqlite3_stmt_isexplain(pStmt);
26172 if( pArg && pArg->mode.autoEQP && isExplain==0 ){
26173 int triggerEQP = 0;
 
 
26174 disable_debug_trace_modes();
26175 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
26176 if( pArg->mode.autoEQP>=AUTOEQP_trigger ){
26177 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
26178 }
26179 sqlite3_reset(pStmt);
26180 spec.eStyle = QRF_STYLE_Auto;
26181 sqlite3_stmt_explain(pStmt, 2-(pArg->mode.autoEQP>=AUTOEQP_full));
26182 sqlite3_format_query_result(pStmt, &spec, 0);
 
 
 
 
 
 
26183 if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
26184 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
26185 }
26186 sqlite3_reset(pStmt);
26187 sqlite3_stmt_explain(pStmt, 0);
26188 restore_debug_trace_modes();
 
26189 }
26190
26191 bind_prepared_stmt(pArg, pStmt);
26192 if( isExplain && pArg->mode.autoExplain ){
26193 spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp;
@@ -26604,12 +26768,12 @@
26604 ".bail on|off Stop after hitting an error. Default OFF",
26605 #ifndef SQLITE_SHELL_FIDDLE
26606 ".cd DIRECTORY Change the working directory to DIRECTORY",
26607 #endif
26608 ".changes on|off Show number of rows changed by SQL",
 
26609 #ifndef SQLITE_SHELL_FIDDLE
26610 ".check GLOB Fail if output since .testcase does not match",
26611 ".clone NEWDB Clone data into NEWDB from the existing database",
26612 #endif
26613 ".connection [close] [#] Open or close an auxiliary database connection",
26614 ".crlf ?on|off? Whether or not to use \\r\\n line endings",
26615 ".databases List names and files of attached databases",
@@ -26721,10 +26885,11 @@
26721 ".progress N Invoke progress handler after every N opcodes",
26722 " --limit N Interrupt after N progress callbacks",
26723 " --once Do no more than one progress interrupt",
26724 " --quiet|-q No output except at interrupts",
26725 " --reset Reset the count for each input and interrupt",
 
26726 #endif
26727 ".prompt MAIN CONTINUE Replace the standard prompts",
26728 #ifndef SQLITE_SHELL_FIDDLE
26729 ".quit Stop interpreting input stream, exit if primary.",
26730 ".read FILE Read input from FILE or command output",
@@ -26785,17 +26950,15 @@
26785 " vmstep Show the virtual machine step count only",
26786 #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
26787 ".system CMD ARGS... Run CMD ARGS... in a system shell",
26788 #endif
26789 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
26790 #ifndef SQLITE_SHELL_FIDDLE
26791 ",testcase NAME Begin redirecting output to 'testcase-out.txt'",
26792 #endif
26793 ",testctrl CMD ... Run various sqlite3_test_control() operations",
26794 " Run \".testctrl\" with no arguments for details",
26795 ".timeout MS Try opening locked tables for MS milliseconds",
26796 ".timer on|off Turn SQL timer on or off",
26797 #ifndef SQLITE_OMIT_TRACE
26798 ".trace ?OPTIONS? Output each SQL statement as it is run",
26799 " FILE Send output to FILE",
26800 " stdout Send output to stdout",
26801 " stderr Send output to stderr",
@@ -26836,19 +26999,33 @@
26836 "USAGE: .import [OPTIONS] FILE TABLE\n"
26837 "\n"
26838 "Import CSV or similar text from FILE into TABLE. If TABLE does\n"
26839 "not exist, it is created using the first row of FILE as the column\n"
26840 "names. If FILE begins with \"|\" then it is a command that is run\n"
26841 "and the output from the command is used as the input data.\n"
 
 
 
 
 
 
26842 "\n"
26843 "FILE is assumed to be in a CSV format, unless the current mode\n"
26844 "is \"ascii\" or \"tabs\" or unless one of the options below specify\n"
26845 "an alternative.\n"
 
 
26846 "\n"
26847 "Options:\n"
26848 " --ascii Use \\037 and \\036 as column and row separators on input\n"
 
 
 
26849 " --csv Input is standard RFC-4180 CSV.\n"
 
 
 
26850 " --schema S When creating TABLE, put it in schema S\n"
26851 " --skip N Ignore the first N rows of input\n"
26852 " -v Verbose mode\n"
26853 },
26854 { ".mode",
@@ -26930,23 +27107,17 @@
26930 " --bom Prepend a byte-order mark to the output\n"
26931 " -e Accumulate output in a temporary text file then\n"
26932 " launch a text editor when the redirection ends.\n"
26933 " --error-prefix X Use X as the left-margin prefix for error messages.\n"
26934 " Set to an empty string to restore the default.\n"
26935 " --glob GLOB Raise an error if the memory buffer does not match\n"
26936 " the GLOB pattern.\n"
26937 " --keep Continue using the same \"memory\" buffer. Do not\n"
26938 " reset it or delete it. Useful in combination with\n"
26939 " --glob, --not-glob, and/or --verify.\n"
26940 " ---notglob GLOB Raise an error if the memory buffer does not match\n"
26941 " the GLOB pattern.\n"
26942 " --plain Use plain text rather than HTML tables with -w\n"
26943 " --show Write the memory buffer to the screen, for debugging.\n"
26944 " --verify ENDMARK Read subsequent lines of text until the first line\n"
26945 " that matches ENDMARK. Discard the ENDMARK. Compare\n"
26946 " the text against the accumulated output in memory and\n"
26947 " raise an error if there are any differences.\n"
26948 " -w Show the output in a web browser. Output is\n"
26949 " written into a temporary HTML file until the\n"
26950 " redirect ends, then the web browser is launched.\n"
26951 " Query results are shown as HTML tables, unless\n"
26952 " the --plain is used too.\n"
@@ -26970,10 +27141,39 @@
26970 " file in a web browser\n"
26971 " -x Show the output in a spreadsheet. Output is\n"
26972 " written to a temp file as CSV then the spreadsheet\n"
26973 " is launched when\n"
26974 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26975 };
26976
26977 /*
26978 ** Return a pointer to usage text for zCmd, or NULL if none exists.
26979 */
@@ -27193,10 +27393,56 @@
27193 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
27194 }
27195 return 1;
27196 }
27197 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27198
27199 /*
27200 ** Try to deduce the type of file for zName based on its content. Return
27201 ** one of the SHELL_OPEN_* constants.
27202 **
@@ -27206,24 +27452,16 @@
27206 ** the type cannot be determined from content.
27207 */
27208 int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
27209 FILE *f;
27210 size_t n;
27211 sqlite3 *db = 0;
27212 sqlite3_stmt *pStmt = 0;
27213 int rc = SHELL_OPEN_UNSPEC;
27214 char zBuf[100];
27215 if( access(zName,0)!=0 ) goto database_type_by_name;
27216 if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
27217 && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
27218 ==SQLITE_OK
27219 && sqlite3_step(pStmt)==SQLITE_ROW
27220 ){
27221 rc = SHELL_OPEN_NORMAL;
27222 }
27223 sqlite3_finalize(pStmt);
27224 sqlite3_close(db);
27225 if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
27226 f = sqlite3_fopen(zName, "rb");
27227 if( f==0 ) goto database_type_by_name;
27228 n = fread(zBuf, 16, 1, f);
27229 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
@@ -27253,10 +27491,39 @@
27253 }else{
27254 rc = SHELL_OPEN_NORMAL;
27255 }
27256 return rc;
27257 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27258
27259 #ifndef SQLITE_OMIT_DESERIALIZE
27260 /*
27261 ** Reconstruct an in-memory database using the output from the "dbtotxt"
27262 ** program. Read content from the file in p->aAuxDb[].zDbFilename.
@@ -27899,20 +28166,24 @@
27899 typedef struct ImportCtx ImportCtx;
27900 struct ImportCtx {
27901 const char *zFile; /* Name of the input file */
27902 FILE *in; /* Read the CSV text from this input stream */
27903 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
 
27904 char *z; /* Accumulated text for a field */
 
27905 i64 n; /* Number of bytes in z */
27906 i64 nAlloc; /* Space allocated for z[] */
27907 int nLine; /* Current line number */
27908 int nRow; /* Number of rows imported */
27909 int nErr; /* Number of errors encountered */
27910 int bNotFirst; /* True if one or more bytes already read */
27911 int cTerm; /* Character that terminated the most recent field */
27912 int cColSep; /* The column separator character. (Usually ",") */
27913 int cRowSep; /* The row separator character. (Usually "\n") */
 
 
27914 };
27915
27916 /* Clean up resourced used by an ImportCtx */
27917 static void import_cleanup(ImportCtx *p){
27918 if( p->in!=0 && p->xCloser!=0 ){
@@ -27919,13 +28190,32 @@
27919 p->xCloser(p->in);
27920 p->in = 0;
27921 }
27922 sqlite3_free(p->z);
27923 p->z = 0;
 
 
 
 
27924 }
27925
27926 /* Append a single byte to z[] */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27927 static void import_append_char(ImportCtx *p, int c){
27928 if( p->n+1>=p->nAlloc ){
27929 p->nAlloc += p->nAlloc + 100;
27930 p->z = sqlite3_realloc64(p->z, p->nAlloc);
27931 shell_check_oom(p->z);
@@ -27937,12 +28227,12 @@
27937 ** with the option of having a separator other than ",".
27938 **
27939 ** + Input comes from p->in.
27940 ** + Store results in p->z of length p->n. Space to hold p->z comes
27941 ** from sqlite3_malloc64().
27942 ** + Use p->cSep as the column separator. The default is ",".
27943 ** + Use p->rSep as the row separator. The default is "\n".
27944 ** + Keep track of the line number in p->nLine.
27945 ** + Store the character that terminates the field in p->cTerm. Store
27946 ** EOF on end-of-file.
27947 ** + Report syntax errors on stderr
27948 */
@@ -27949,23 +28239,30 @@
27949 static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
27950 int c;
27951 int cSep = (u8)p->cColSep;
27952 int rSep = (u8)p->cRowSep;
27953 p->n = 0;
27954 c = fgetc(p->in);
27955 if( c==EOF || seenInterrupt ){
27956 p->cTerm = EOF;
27957 return 0;
27958 }
27959 if( c=='"' ){
27960 int pc, ppc;
27961 int startLine = p->nLine;
27962 int cQuote = c;
 
27963 pc = ppc = 0;
27964 while( 1 ){
27965 c = fgetc(p->in);
27966 if( c==rSep ) p->nLine++;
 
 
 
 
 
 
27967 if( c==cQuote ){
27968 if( pc==cQuote ){
27969 pc = 0;
27970 continue;
27971 }
@@ -27979,11 +28276,11 @@
27979 p->cTerm = c;
27980 break;
27981 }
27982 if( pc==cQuote && c!='\r' ){
27983 cli_printf(stderr,"%s:%d: unescaped %c character\n",
27984 p->zFile, p->nLine, cQuote);
27985 }
27986 if( c==EOF ){
27987 cli_printf(stderr,"%s:%d: unterminated %c-quoted field\n",
27988 p->zFile, startLine, cQuote);
27989 p->cTerm = c;
@@ -27994,26 +28291,28 @@
27994 pc = c;
27995 }
27996 }else{
27997 /* If this is the first field being parsed and it begins with the
27998 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
 
27999 if( (c&0xff)==0xef && p->bNotFirst==0 ){
28000 import_append_char(p, c);
28001 c = fgetc(p->in);
28002 if( (c&0xff)==0xbb ){
28003 import_append_char(p, c);
28004 c = fgetc(p->in);
28005 if( (c&0xff)==0xbf ){
28006 p->bNotFirst = 1;
28007 p->n = 0;
28008 return csv_read_one_field(p);
28009 }
28010 }
28011 }
28012 while( c!=EOF && c!=cSep && c!=rSep ){
 
28013 import_append_char(p, c);
28014 c = fgetc(p->in);
28015 }
28016 if( c==rSep ){
28017 p->nLine++;
28018 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
28019 }
@@ -28027,12 +28326,12 @@
28027 /* Read a single field of ASCII delimited text.
28028 **
28029 ** + Input comes from p->in.
28030 ** + Store results in p->z of length p->n. Space to hold p->z comes
28031 ** from sqlite3_malloc64().
28032 ** + Use p->cSep as the column separator. The default is "\x1F".
28033 ** + Use p->rSep as the row separator. The default is "\x1E".
28034 ** + Keep track of the row number in p->nLine.
28035 ** + Store the character that terminates the field in p->cTerm. Store
28036 ** EOF on end-of-file.
28037 ** + Report syntax errors on stderr
28038 */
@@ -28039,18 +28338,18 @@
28039 static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
28040 int c;
28041 int cSep = (u8)p->cColSep;
28042 int rSep = (u8)p->cRowSep;
28043 p->n = 0;
28044 c = fgetc(p->in);
28045 if( c==EOF || seenInterrupt ){
28046 p->cTerm = EOF;
28047 return 0;
28048 }
28049 while( c!=EOF && c!=cSep && c!=rSep ){
28050 import_append_char(p, c);
28051 c = fgetc(p->in);
28052 }
28053 if( c==rSep ){
28054 p->nLine++;
28055 }
28056 p->cTerm = c;
@@ -30151,11 +30450,11 @@
30151 ;
30152 static const char * const zCollectVar = "\
30153 SELECT\
30154 '('||x'0a'\
30155 || group_concat(\
30156 cname||' TEXT',\
30157 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
30158 ||')' AS ColsSpec \
30159 FROM (\
30160 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
30161 FROM ColNames ORDER BY cpos\
@@ -30351,19 +30650,33 @@
30351 ** USAGE: .import [OPTIONS] FILE TABLE
30352 **
30353 ** Import CSV or similar text from FILE into TABLE. If TABLE does
30354 ** not exist, it is created using the first row of FILE as the column
30355 ** names. If FILE begins with "|" then it is a command that is run
30356 ** and the output from the command is used as the input data.
 
 
 
 
 
 
30357 **
30358 ** FILE is assumed to be in a CSV format, unless the current mode
30359 ** is "ascii" or "tabs" or unless one of the options below specify
30360 ** an alternative.
 
 
30361 **
30362 ** Options:
30363 ** --ascii Use \037 and \036 as column and row separators on input
 
 
 
30364 ** --csv Input is standard RFC-4180 CSV.
 
 
 
30365 ** --schema S When creating TABLE, put it in schema S
30366 ** --skip N Ignore the first N rows of input
30367 ** -v Verbose mode
30368 */
30369 static int dotCmdImport(ShellState *p){
@@ -30375,17 +30688,16 @@
30375 sqlite3_stmt *pStmt = NULL; /* A statement */
30376 int nCol; /* Number of columns in the table */
30377 i64 nByte; /* Number of bytes in an SQL string */
30378 int i, j; /* Loop counters */
30379 int needCommit; /* True to COMMIT or ROLLBACK at end */
30380 int nSep; /* Number of bytes in spec.zColumnSep */
30381 char *zSql = 0; /* An SQL statement */
30382 ImportCtx sCtx; /* Reader context */
30383 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
30384 int eVerbose = 0; /* Larger for more console output */
30385 i64 nSkip = 0; /* Initial lines to skip */
30386 int useOutputMode = 1; /* Use output mode to determine separators */
30387 char *zCreate = 0; /* CREATE TABLE statement text */
30388 int rc; /* Result code */
30389
30390 failIfSafeMode(p, "cannot run .import in safe mode");
30391 memset(&sCtx, 0, sizeof(sCtx));
@@ -30411,70 +30723,71 @@
30411 }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
30412 zSchema = azArg[++i];
30413 }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
30414 nSkip = integerValue(azArg[++i]);
30415 }else if( cli_strcmp(z,"-ascii")==0 ){
30416 sCtx.cColSep = SEP_Unit[0];
30417 sCtx.cRowSep = SEP_Record[0];
30418 xRead = ascii_read_one_field;
30419 useOutputMode = 0;
30420 }else if( cli_strcmp(z,"-csv")==0 ){
30421 sCtx.cColSep = ',';
30422 sCtx.cRowSep = '\n';
30423 xRead = csv_read_one_field;
30424 useOutputMode = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30425 }else{
30426 dotCmdError(p, i, "unknown option", 0);
30427 return 1;
30428 }
30429 }
30430 if( zTable==0 ){
30431 cli_printf(p->out, "ERROR: missing %s argument\n",
30432 zFile==0 ? "FILE" : "TABLE");
30433 return 1;
30434 }
30435 seenInterrupt = 0;
30436 open_db(p, 0);
30437 if( useOutputMode ){
30438 /* If neither the --csv or --ascii options are specified, then set
30439 ** the column and row separator characters from the output mode. */
30440 if( p->mode.spec.zColumnSep==0 ){
30441 modeSetStr(&p->mode.spec.zColumnSep, ",");
30442 nSep = 1;
30443 }else if( (nSep = strlen30(p->mode.spec.zColumnSep))==0 ){
30444 eputz("Error: non-null column separator required for import\n");
30445 return 1;
30446 }
30447 if( nSep>1 ){
30448 eputz("Error: multi-character column separators not allowed"
30449 " for import\n");
30450 return 1;
30451 }
30452 if( p->mode.spec.zRowSep==0 ){
30453 modeSetStr(&p->mode.spec.zRowSep, "\n");
30454 nSep = 1;
30455 }else if( (nSep = strlen30(p->mode.spec.zRowSep))==0 ){
30456 eputz("Error: non-null row separator required for import\n");
30457 return 1;
30458 }
30459 if( nSep==2 && p->mode.eMode==MODE_Csv
30460 && cli_strcmp(p->mode.spec.zRowSep,SEP_CrLf)==0
30461 ){
30462 /* When importing CSV (only), if the row separator is set to the
30463 ** default output row separator, change it to the default input
30464 ** row separator. This avoids having to maintain different input
30465 ** and output row separators. */
30466 modeSetStr(&p->mode.spec.zRowSep, SEP_Row);
30467 nSep = strlen30(p->mode.spec.zRowSep);
30468 }
30469 if( nSep>1 ){
30470 eputz("Error: multi-character row separators not allowed"
30471 " for import\n");
30472 return 1;
30473 }
30474 sCtx.cColSep = (u8)p->mode.spec.zColumnSep[0];
30475 sCtx.cRowSep = (u8)p->mode.spec.zRowSep[0];
30476 }
30477 sCtx.zFile = zFile;
30478 sCtx.nLine = 1;
30479 if( sCtx.zFile[0]=='|' ){
30480 #ifdef SQLITE_OMIT_POPEN
@@ -30483,19 +30796,58 @@
30483 #else
30484 sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
30485 sCtx.zFile = "<pipe>";
30486 sCtx.xCloser = pclose;
30487 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30488 }else{
30489 sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
30490 sCtx.xCloser = fclose;
30491 }
30492 if( sCtx.in==0 ){
30493 cli_printf(stderr,"Error: cannot open \"%s\"\n", zFile);
 
30494 return 1;
30495 }
30496 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
30497 char zSep[2];
30498 zSep[1] = 0;
30499 zSep[0] = sCtx.cColSep;
30500 cli_puts("Column separator ", p->out);
30501 output_c_string(p->out, zSep);
@@ -30648,10 +31000,14 @@
30648 if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
30649 z = "";
30650 }
30651 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
30652 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
 
 
 
 
30653 cli_printf(stderr,"%s:%d: expected %d columns but found %d"
30654 " - filling the rest with NULL\n",
30655 sCtx.zFile, startLine, nCol, i+1);
30656 i += 2;
30657 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
@@ -30671,10 +31027,11 @@
30671 rc = sqlite3_reset(pStmt);
30672 if( rc!=SQLITE_OK ){
30673 cli_printf(stderr,"%s:%d: INSERT failed: %s\n",
30674 sCtx.zFile, startLine, sqlite3_errmsg(p->db));
30675 sCtx.nErr++;
 
30676 }else{
30677 sCtx.nRow++;
30678 }
30679 }
30680 }while( sCtx.cTerm!=EOF );
@@ -30683,13 +31040,13 @@
30683 sqlite3_finalize(pStmt);
30684 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
30685 if( eVerbose>0 ){
30686 cli_printf(p->out,
30687 "Added %d rows with %d errors using %d lines of input\n",
30688 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
30689 }
30690 return 0;
30691 }
30692
30693
30694 /*
30695 ** This function computes what to show the user about the configured
@@ -31100,10 +31457,11 @@
31100 if( k<0 ){
31101 dotCmdError(p, i, "bad --titles value","%z", zErr);
31102 return 1;
31103 }
31104 p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No;
 
31105 p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr;
31106 chng = 1;
31107 }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){
31108 int nWidth = 0;
31109 short int *aWidth;
@@ -31328,23 +31686,17 @@
31328 ** --bom Prepend a byte-order mark to the output
31329 ** -e Accumulate output in a temporary text file then
31330 ** launch a text editor when the redirection ends.
31331 ** --error-prefix X Use X as the left-margin prefix for error messages.
31332 ** Set to an empty string to restore the default.
31333 ** --glob GLOB Raise an error if the memory buffer does not match
31334 ** the GLOB pattern.
31335 ** --keep Continue using the same "memory" buffer. Do not
31336 ** reset it or delete it. Useful in combination with
31337 ** --glob, --not-glob, and/or --verify.
31338 ** ---notglob GLOB Raise an error if the memory buffer does not match
31339 ** the GLOB pattern.
31340 ** --plain Use plain text rather than HTML tables with -w
31341 ** --show Write the memory buffer to the screen, for debugging.
31342 ** --verify ENDMARK Read subsequent lines of text until the first line
31343 ** that matches ENDMARK. Discard the ENDMARK. Compare
31344 ** the text against the accumulated output in memory and
31345 ** raise an error if there are any differences.
31346 ** -w Show the output in a web browser. Output is
31347 ** written into a temporary HTML file until the
31348 ** redirect ends, then the web browser is launched.
31349 ** Query results are shown as HTML tables, unless
31350 ** the --plain is used too.
@@ -31382,13 +31734,11 @@
31382 char *zFile = 0; /* The FILE argument */
31383 int i; /* Loop counter */
31384 int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
31385 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
31386 int bPlain = 0; /* --plain option */
31387 int bKeep = 0; /* --keep option */
31388 char *zCheck = 0; /* Argument to --glob, --notglob, --verify */
31389 int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --verify */
31390 static const char *zBomUtf8 = "\357\273\277";
31391 const char *zBom = 0;
31392 char c = azArg[0][0];
31393 int n = strlen30(azArg[0]);
31394
@@ -31410,36 +31760,21 @@
31410 zBom = zBomUtf8;
31411 }else if( cli_strcmp(z,"-plain")==0 ){
31412 bPlain = 1;
31413 }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
31414 && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
31415 if( bKeep || eMode || eCheck ){
31416 dotCmdError(p, i, "incompatible with prior options",0);
31417 goto dotCmdOutput_error;
31418 }
31419 eMode = z[1];
31420 }else if( cli_strcmp(z,"-keep")==0 ){
31421 bKeep = 1;
31422 }else if( cli_strcmp(z,"-show")==0 ){
31423 if( cli_output_capture ){
31424 sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31425 }
 
31426 bKeep = 1;
31427 }else if( cli_strcmp(z,"-glob")==0
31428 || cli_strcmp(z,"-notglob")==0
31429 || cli_strcmp(z,"-verify")==0
31430 ){
31431 if( eCheck || eMode ){
31432 dotCmdError(p, i, "incompatible with prior options",0);
31433 goto dotCmdOutput_error;
31434 }
31435 if( i+1>=nArg ){
31436 dotCmdError(p, i, "missing argument", 0);
31437 goto dotCmdOutput_error;
31438 }
31439 zCheck = azArg[++i];
31440 eCheck = z[1]=='g' ? 1 : z[1]=='n' ? 2 : 3;
31441 }else if( optionMatch(z,"error-prefix") ){
31442 if( i+1>=nArg ){
31443 dotCmdError(p, i, "missing argument", 0);
31444 return 1;
31445 }
@@ -31450,11 +31785,11 @@
31450 dotCmdError(p, i, "unknown option", 0);
31451 sqlite3_free(zFile);
31452 return 1;
31453 }
31454 }else if( zFile==0 && eMode==0 ){
31455 if( bKeep || eCheck ){
31456 dotCmdError(p, i, "incompatible with prior options",0);
31457 goto dotCmdOutput_error;
31458 }
31459 if( cli_strcmp(z, "memory")==0 && bOnce ){
31460 dotCmdError(p, 0, "cannot redirect to \"memory\"", 0);
@@ -31486,53 +31821,10 @@
31486 if( bOnce ){
31487 p->nPopOutput = 2;
31488 }else{
31489 p->nPopOutput = 0;
31490 }
31491 if( eCheck ){
31492 char *zTest;
31493 if( cli_output_capture ){
31494 zTest = sqlite3_str_value(cli_output_capture);
31495 }else{
31496 zTest = "";
31497 }
31498 p->nTestRun++;
31499 if( eCheck==3 ){
31500 int nCheck = strlen30(zCheck);
31501 sqlite3_str *pPattern = sqlite3_str_new(p->db);
31502 char *zPattern;
31503 sqlite3_int64 iStart = p->lineno;
31504 char zLine[2000];
31505 while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31506 if( strchr(zLine,'\n') ) p->lineno++;
31507 if( cli_strncmp(zCheck,zLine,nCheck)==0 ) break;
31508 sqlite3_str_appendall(pPattern, zLine);
31509 }
31510 zPattern = sqlite3_str_finish(pPattern);
31511 if( cli_strcmp(zPattern,zTest)!=0 ){
31512 sqlite3_fprintf(stderr,
31513 "%s:%lld: --verify does matches prior output\n",
31514 p->zInFile, iStart);
31515 p->nTestErr++;
31516 }
31517 sqlite3_free(zPattern);
31518 }else{
31519 char *zGlob = sqlite3_mprintf("*%s*", zCheck);
31520 if( eCheck==1 && sqlite3_strglob(zGlob, zTest)!=0 ){
31521 sqlite3_fprintf(stderr,
31522 "%s:%lld: --glob \"%s\" does not match prior output\n",
31523 p->zInFile, p->lineno, zCheck);
31524 p->nTestErr++;
31525 }else if( eCheck==2 && sqlite3_strglob(zGlob, zTest)==0 ){
31526 sqlite3_fprintf(stderr,
31527 "%s:%lld: --notglob \"%s\" matches prior output\n",
31528 p->zInFile, p->lineno, zCheck);
31529 p->nTestErr++;
31530 }
31531 sqlite3_free(zGlob);
31532 }
31533 }
31534 if( !bKeep ) output_reset(p);
31535 #ifndef SQLITE_NOHAVE_SYSTEM
31536 if( eMode=='e' || eMode=='x' || eMode=='w' ){
31537 p->doXdgOpen = 1;
31538 modePush(p);
@@ -31609,10 +31901,199 @@
31609
31610 dotCmdOutput_error:
31611 sqlite3_free(zFile);
31612 return 1;
31613 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31614
31615 /*
31616 ** Enlarge the space allocated in p->dot so that it can hold more
31617 ** than nArg parsed command-line arguments.
31618 */
@@ -31641,11 +32122,11 @@
31641 free(p->dot.zCopy);
31642 z = p->dot.zCopy = strdup(zLine);
31643 shell_check_oom(z);
31644 szLine = strlen(z);
31645 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31646 if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){
31647 szLine--;
31648 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31649 }
31650 z[szLine] = 0;
31651 parseDotRealloc(p, 2);
@@ -31861,35 +32342,17 @@
31861 eputz("Usage: .changes on|off\n");
31862 rc = 1;
31863 }
31864 }else
31865
31866 #ifndef SQLITE_SHELL_FIDDLE
31867 /* Cancel output redirection, if it is currently set (by .testcase)
31868 ** Then read the content of the testcase-out.txt file and compare against
31869 ** azArg[1]. If there are differences, report an error and exit.
31870 */
31871 if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
31872 char *zRes = 0;
31873 output_reset(p);
31874 if( nArg!=2 ){
31875 eputz("Usage: .check GLOB-PATTERN\n");
31876 rc = 2;
31877 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
31878 rc = 2;
31879 }else if( testcase_glob(azArg[1],zRes)==0 ){
31880 cli_printf(stderr,
31881 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
31882 p->zTestcase, azArg[1], zRes);
31883 rc = 1;
31884 }else{
31885 cli_printf(p->out, "testcase-%s ok\n", p->zTestcase);
31886 p->nCheck++;
31887 }
31888 sqlite3_free(zRes);
31889 }else
31890 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
31891
31892 #ifndef SQLITE_SHELL_FIDDLE
31893 if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
31894 failIfSafeMode(p, "cannot run .clone in safe mode");
31895 if( nArg==2 ){
@@ -32468,10 +32931,11 @@
32468 }else
32469
32470 if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
32471 if( nArg==2 ){
32472 p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No;
 
32473 p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr;
32474 }else{
32475 eputz("Usage: .headers on|off\n");
32476 rc = 1;
32477 }
@@ -32521,14 +32985,14 @@
32521 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
32522 goto meta_command_exit;
32523 }
32524 zSql = sqlite3_mprintf(
32525 "SELECT rootpage, 0 FROM sqlite_schema"
32526 " WHERE name='%q' AND type='index'"
32527 "UNION ALL "
32528 "SELECT rootpage, 1 FROM sqlite_schema"
32529 " WHERE name='%q' AND type='table'"
32530 " AND sql LIKE '%%without%%rowid%%'",
32531 azArg[1], azArg[1]
32532 );
32533 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
32534 sqlite3_free(zSql);
@@ -32682,13 +33146,14 @@
32682 goto meta_command_exit;
32683 }
32684 if( nArg==3 ){
32685 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
32686 (int)integerValue(azArg[2]));
 
 
 
32687 }
32688 cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
32689 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
32690 }
32691 }else
32692
32693 if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
32694 open_db(p, 0);
@@ -33027,10 +33492,23 @@
33027 continue;
33028 }
33029 if( cli_strcmp(z,"once")==0 ){
33030 p->flgProgress |= SHELL_PROGRESS_ONCE;
33031 continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
33032 }
33033 if( cli_strcmp(z,"limit")==0 ){
33034 if( i+1>=nArg ){
33035 eputz("Error: missing argument on --limit\n");
33036 rc = 1;
@@ -33233,21 +33711,22 @@
33233 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
33234 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
33235 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
33236 if( isSchema ){
33237 cli_printf(p->out,
33238 "CREATE TABLE %s (\n"
33239 " type text,\n"
33240 " name text,\n"
33241 " tbl_name text,\n"
33242 " rootpage integer,\n"
33243 " sql text\n"
33244 ");\n", zName);
 
 
33245 }
33246 }
33247 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
33248 -1, &pStmt, 0);
33249 if( rc ){
33250 shellDatabaseError(p->db);
33251 sqlite3_finalize(pStmt);
33252
33253 rc = 1;
@@ -33255,11 +33734,11 @@
33255 }
33256 pSql = sqlite3_str_new(p->db);
33257 sqlite3_str_appendf(pSql, "SELECT sql FROM", 0);
33258 iSchema = 0;
33259 while( sqlite3_step(pStmt)==SQLITE_ROW ){
33260 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
33261 char zScNum[30];
33262 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
33263 sqlite3_str_appendall(pSql, zDiv);
33264 zDiv = " UNION ALL ";
33265 if( sqlite3_stricmp(zDb, "main")==0 ){
@@ -33275,11 +33754,12 @@
33275 " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname",
33276 ++iSchema, zDb);
33277 sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb);
33278 }
33279 sqlite3_finalize(pStmt);
33280 #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
 
33281 if( zName ){
33282 sqlite3_str_appendall(pSql,
33283 " UNION ALL SELECT shell_module_schema(name),"
33284 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list");
33285 }
@@ -33299,11 +33779,11 @@
33299 }else{
33300 sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName);
33301 }
33302 }
33303 if( bNoSystemTabs ){
33304 sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCALE '_' AND ");
33305 }
33306 sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid");
33307 if( bDebug ){
33308 cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql));
33309 }else{
@@ -34017,25 +34497,15 @@
34017 sqlite3_str_free(pSql);
34018 modePop(p);
34019 if( rc ) return shellDatabaseError(p->db);
34020 }else
34021
34022 #ifndef SQLITE_SHELL_FIDDLE
34023 /* Begin redirecting output to the file "testcase-out.txt" */
34024 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
34025 output_reset(p);
34026 p->out = output_file_open(p, "testcase-out.txt");
34027 if( p->out==0 ){
34028 eputz("Error: cannot open 'testcase-out.txt'\n");
34029 }
34030 if( nArg>=2 ){
34031 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
34032 }else{
34033 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
34034 }
34035 }else
34036 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
34037
34038 #ifndef SQLITE_UNTESTABLE
34039 if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
34040 static const struct {
34041 const char *zCtrlName; /* Name of a test-control option */
@@ -34527,17 +34997,21 @@
34527 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
34528 }else
34529
34530 if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
34531 if( nArg==2 ){
34532 enableTimer = booleanValue(azArg[1]);
34533 if( enableTimer && !HAS_TIMER ){
 
 
 
 
34534 eputz("Error: timer not available on this system.\n");
34535 enableTimer = 0;
34536 }
34537 }else{
34538 eputz("Usage: .timer on|off\n");
34539 rc = 1;
34540 }
34541 }else
34542
34543 #ifndef SQLITE_OMIT_TRACE
@@ -34708,10 +35182,11 @@
34708 if( p->nPopOutput ){
34709 p->nPopOutput--;
34710 if( p->nPopOutput==0 ) output_reset(p);
34711 }
34712 p->bSafeMode = p->bSafeModePersist;
 
34713 return rc;
34714 }
34715
34716 /* Line scan result and intermediate states (supporting scan resumption)
34717 */
@@ -34944,13 +35419,13 @@
34944 char *zErrMsg = 0;
34945
34946 open_db(p, 0);
34947 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
34948 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
34949 BEGIN_TIMER;
34950 rc = shell_exec(p, zSql, &zErrMsg);
34951 END_TIMER(p->out);
34952 if( rc || zErrMsg ){
34953 char zPrefix[100];
34954 const char *zErrorTail;
34955 const char *zErrorType;
34956 if( zErrMsg==0 ){
@@ -35351,11 +35826,10 @@
35351 " -bail stop after hitting an error\n"
35352 " -batch force batch I/O\n"
35353 " -box set output mode to 'box'\n"
35354 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
35355 " -column set output mode to 'column'\n"
35356 " -compat YYYYMMDD set default options for date YYYYMMDD\n"
35357 " -csv set output mode to 'csv'\n"
35358 #if !defined(SQLITE_OMIT_DESERIALIZE)
35359 " -deserialize open the database using sqlite3_deserialize()\n"
35360 #endif
35361 " -echo print inputs before execution\n"
@@ -35435,15 +35909,10 @@
35435 /*
35436 ** Initialize the state information in data
35437 */
35438 static void main_init(ShellState *p) {
35439 memset(p, 0, sizeof(*p));
35440 #if defined(COMPATIBILITY_DATE)
35441 p->iCompat = COMPATIBILITY_DATE;
35442 #else
35443 p->iCompat = 20251116;
35444 #endif
35445 p->pAuxDb = &p->aAuxDb[0];
35446 p->shellFlgs = SHFLG_Lookaside;
35447 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p);
35448 #if !defined(SQLITE_SHELL_FIDDLE)
35449 verify_uninitialized();
@@ -35498,29 +35967,65 @@
35498 cli_puts(z, p->out);
35499 fflush(p->out);
35500 return 1;
35501 }
35502
35503 #ifndef SQLITE_SHELL_IS_UTF8
35504 # if (defined(_WIN32) || defined(WIN32)) \
35505 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
35506 # define SQLITE_SHELL_IS_UTF8 (0)
35507 # else
35508 # define SQLITE_SHELL_IS_UTF8 (1)
35509 # endif
35510 #endif
35511
35512 #ifdef SQLITE_SHELL_FIDDLE
35513 # define main fiddle_main
35514 #endif
35515
35516 #if SQLITE_SHELL_IS_UTF8
35517 int SQLITE_CDECL main(int argc, char **argv){
35518 #else
 
 
 
 
35519 int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
35520 char **argv;
35521 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35522 #ifdef SQLITE_DEBUG
35523 sqlite3_int64 mem_main_enter = 0;
35524 #endif
35525 char *zErrMsg = 0;
35526 #ifdef SQLITE_SHELL_FIDDLE
@@ -35538,14 +36043,10 @@
35538 int nOptsEnd = argc;
35539 int bEnableVfstrace = 0;
35540 char **azCmd = 0;
35541 int *aiCmd = 0;
35542 const char *zVfs = 0; /* Value of -vfs command-line option */
35543 #if !SQLITE_SHELL_IS_UTF8
35544 char **argvToFree = 0;
35545 int argcToFree = 0;
35546 #endif
35547 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
35548
35549 #ifdef SQLITE_SHELL_FIDDLE
35550 stdin_is_interactive = 0;
35551 stdout_is_console = 1;
@@ -35596,36 +36097,10 @@
35596 exit(1);
35597 }
35598 #endif
35599 main_init(&data);
35600
35601 /* On Windows, we must translate command-line arguments into UTF-8.
35602 ** The SQLite memory allocator subsystem has to be enabled in order to
35603 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
35604 ** subsequent sqlite3_config() calls will work. So copy all results into
35605 ** memory that does not come from the SQLite memory allocator.
35606 */
35607 #if !SQLITE_SHELL_IS_UTF8
35608 sqlite3_initialize();
35609 argvToFree = malloc(sizeof(argv[0])*argc*2);
35610 shell_check_oom(argvToFree);
35611 argcToFree = argc;
35612 argv = argvToFree + argc;
35613 for(i=0; i<argc; i++){
35614 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
35615 i64 n;
35616 shell_check_oom(z);
35617 n = strlen(z);
35618 argv[i] = malloc( n+1 );
35619 shell_check_oom(argv[i]);
35620 memcpy(argv[i], z, n+1);
35621 argvToFree[i] = argv[i];
35622 sqlite3_free(z);
35623 }
35624 sqlite3_shutdown();
35625 #endif
35626
35627 assert( argc>=1 && argv && argv[0] );
35628 Argv0 = argv[0];
35629
35630 #ifdef SQLITE_SHELL_DBNAME_PROC
35631 {
@@ -35637,11 +36112,11 @@
35637 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
35638 warnInmemoryDb = 0;
35639 }
35640 #endif
35641
35642 /* Do an initial pass through the command-line argument to locate
35643 ** the name of the database file, the name of the initialization file,
35644 ** the size of the alternative malloc heap, options affecting commands
35645 ** or SQL run from the command line, and the first command to execute.
35646 */
35647 #ifndef SQLITE_SHELL_FIDDLE
@@ -35649,11 +36124,11 @@
35649 #endif
35650 for(i=1; i<argc; i++){
35651 char *z;
35652 z = argv[i];
35653 if( z[0]!='-' || i>nOptsEnd ){
35654 if( data.aAuxDb->zDbFilename==0 ){
35655 data.aAuxDb->zDbFilename = z;
35656 }else{
35657 /* Excess arguments are interpreted as SQL (or dot-commands) and
35658 ** mean that nothing is read from stdin */
35659 readStdin = 0;
@@ -35694,15 +36169,10 @@
35694 if( n<2 ){
35695 sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n");
35696 exit(1);
35697 }
35698 stdout_tty_width = n;
35699 }else if( cli_strcmp(z,"-compat")==0 ){
35700 data.iCompat = atoi(cmdline_option_value(argc, argv, ++i));
35701 modeFree(&data.mode);
35702 memset(&data.mode, 0, sizeof(data.mode));
35703 modeDefault(&data);
35704 }else if( cli_strcmp(z,"-utf8")==0 ){
35705 }else if( cli_strcmp(z,"-no-utf8")==0 ){
35706 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
35707 int val = 0;
35708 sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
@@ -35822,10 +36292,20 @@
35822 }else if( cli_strcmp(z,"-safe")==0 ){
35823 /* no-op - catch this on the second pass */
35824 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
35825 /* skip over the argument */
35826 i++;
 
 
 
 
 
 
 
 
 
 
35827 }
35828 }
35829 #ifndef SQLITE_SHELL_FIDDLE
35830 if( !bEnableVfstrace ) verify_uninitialized();
35831 #endif
@@ -35848,11 +36328,30 @@
35848
35849 if( zVfs ){
35850 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
35851 if( pVfs ){
35852 sqlite3_vfs_register(pVfs, 1);
35853 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35854 cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs);
35855 exit(1);
35856 }
35857 }
35858
@@ -35889,11 +36388,11 @@
35889 ** is given on the command line, look for a file named ~/.sqliterc and
35890 ** try to process it.
35891 */
35892 if( !noInit ) process_sqliterc(&data,zInitFile);
35893
35894 /* Make a second pass through the command-line argument and set
35895 ** options. This second pass is delayed until after the initialization
35896 ** file is processed so that the command-line arguments will override
35897 ** settings in the initialization file.
35898 */
35899 for(i=1; i<argc; i++){
@@ -36015,12 +36514,10 @@
36015 stdin_is_interactive = 1;
36016 }else if( cli_strcmp(z,"-batch")==0 ){
36017 /* already handled */
36018 }else if( cli_strcmp(z,"-screenwidth")==0 ){
36019 i++;
36020 }else if( cli_strcmp(z,"-compat")==0 ){
36021 i++;
36022 }else if( cli_strcmp(z,"-utf8")==0 ){
36023 /* already handled */
36024 }else if( cli_strcmp(z,"-no-utf8")==0 ){
36025 /* already handled */
36026 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
@@ -36116,11 +36613,22 @@
36116 ** command-line inputs, except for the argToSkip argument which contains
36117 ** the database filename.
36118 */
36119 for(i=0; i<nCmd; i++){
36120 echo_group_input(&data, azCmd[i]);
36121 if( azCmd[i][0]=='.' ){
 
 
 
 
 
 
 
 
 
 
 
36122 char *zErrCtx = malloc( 64 );
36123 shell_check_oom(zErrCtx);
36124 sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
36125 data.zInFile = "<cmdline>";
36126 data.zErrPrefix = zErrCtx;
@@ -36231,14 +36739,10 @@
36231 }
36232 find_home_dir(1);
36233 output_reset(&data);
36234 data.doXdgOpen = 0;
36235 clearTempFile(&data);
36236 #if !SQLITE_SHELL_IS_UTF8
36237 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
36238 free(argvToFree);
36239 #endif
36240 modeFree(&data.mode);
36241 if( data.nSavedModes ){
36242 int ii;
36243 for(ii=0; ii<data.nSavedModes; ii++){
36244 modeFree(&data.aSavedModes[ii].mode);
36245
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -35,11 +35,11 @@
35 ** ext/recover/sqlite3recover.h
36 ** src/shell.c.in
37 **
38 ** To modify this program, get a copy of the canonical SQLite source tree,
39 ** edit the src/shell.c.in file and/or some of the other files that are
40 ** listed above, then rerun the command "make shell.c".
41 */
42 /************************* Begin src/shell.c.in ******************/
43 /*
44 ** 2001 September 15
45 **
@@ -49,11 +49,11 @@
49 ** May you do good and not evil.
50 ** May you find forgiveness for yourself and forgive others.
51 ** May you share freely, never taking more than you give.
52 **
53 *************************************************************************
54 ** This file contains code to implement the "sqlite3" command line
55 ** utility for accessing SQLite databases.
56 */
57 #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
58 /* This needs to come before any includes for MSVC compiler */
59 #define _CRT_SECURE_NO_WARNINGS
@@ -79,10 +79,14 @@
79 ** should only be used when building the "fiddle" web application, as
80 ** the browser-mode build has much different user input requirements
81 ** and this build mode rewires the user input subsystem to account for
82 ** that.
83 */
84 #if defined(SQLITE_SHELL_FIDDLE)
85 # undef SQLITE_OMIT_LOAD_EXTENSION
86 # define SQLITE_OMIT_LOAD_EXTENSION 1
87 #endif
88
89 /*
90 ** Warning pragmas copied from msvc.h in the core.
91 */
92 #if defined(_MSC_VER)
@@ -872,10 +876,11 @@
876 #ifndef SQLITE_QRF_H
877 #include "qrf.h"
878 #endif
879 #include <string.h>
880 #include <assert.h>
881 #include <stdint.h>
882
883 /* typedef sqlite3_int64 i64; */
884
885 /* A single line in the EQP output */
886 typedef struct qrfEQPGraphRow qrfEQPGraphRow;
@@ -889,11 +894,12 @@
894 /* All EQP output is collected into an instance of the following */
895 typedef struct qrfEQPGraph qrfEQPGraph;
896 struct qrfEQPGraph {
897 qrfEQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
898 qrfEQPGraphRow *pLast; /* Last element of the pRow list */
899 int nWidth; /* Width of the graph */
900 char zPrefix[400]; /* Graph prefix */
901 };
902
903 /*
904 ** Private state information. Subject to change from one release to the
905 ** next.
@@ -995,10 +1001,19 @@
1001 */
1002 static void qrfOom(Qrf *p){
1003 qrfError(p, SQLITE_NOMEM, "out of memory");
1004 }
1005
1006 /*
1007 ** Transfer any error in pStr over into p.
1008 */
1009 static void qrfStrErr(Qrf *p, sqlite3_str *pStr){
1010 int rc = pStr ? sqlite3_str_errcode(pStr) : 0;
1011 if( rc ){
1012 qrfError(p, rc, sqlite3_errstr(rc));
1013 }
1014 }
1015
1016
1017 /*
1018 ** Add a new entry to the EXPLAIN QUERY PLAN data
1019 */
@@ -1074,10 +1089,49 @@
1089 qrfEqpRenderLevel(p, pRow->iEqpId);
1090 p->u.pGraph->zPrefix[n] = 0;
1091 }
1092 }
1093 }
1094
1095 /*
1096 ** Render the 64-bit value N in a more human-readable format into
1097 ** pOut.
1098 **
1099 ** + Only show the first three significant digits.
1100 ** + Append suffixes K, M, G, T, P, and E for 1e3, 1e6, ... 1e18
1101 */
1102 static void qrfApproxInt64(sqlite3_str *pOut, i64 N){
1103 static const char aSuffix[] = { 'K', 'M', 'G', 'T', 'P', 'E' };
1104 int i;
1105 if( N<0 ){
1106 N = N==INT64_MIN ? INT64_MAX : -N;
1107 sqlite3_str_append(pOut, "-", 1);
1108 }
1109 if( N<10000 ){
1110 sqlite3_str_appendf(pOut, "%4lld ", N);
1111 return;
1112 }
1113 for(i=1; i<=18; i++){
1114 N = (N+5)/10;
1115 if( N<10000 ){
1116 int n = (int)N;
1117 switch( i%3 ){
1118 case 0:
1119 sqlite3_str_appendf(pOut, "%d.%02d", n/1000, (n%1000)/10);
1120 break;
1121 case 1:
1122 sqlite3_str_appendf(pOut, "%2d.%d", n/100, (n%100)/10);
1123 break;
1124 case 2:
1125 sqlite3_str_appendf(pOut, "%4d", n/10);
1126 break;
1127 }
1128 sqlite3_str_append(pOut, &aSuffix[i/3], 1);
1129 break;
1130 }
1131 }
1132 }
1133
1134 /*
1135 ** Display and reset the EXPLAIN QUERY PLAN data
1136 */
1137 static void qrfEqpRender(Qrf *p, i64 nCycle){
@@ -1090,11 +1144,30 @@
1144 }
1145 sqlite3_str_appendf(p->pOut, "%s\n", pRow->zText+3);
1146 p->u.pGraph->pRow = pRow->pNext;
1147 sqlite3_free(pRow);
1148 }else if( nCycle>0 ){
1149 int nSp = p->u.pGraph->nWidth - 2;
1150 if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1151 sqlite3_str_appendchar(p->pOut, nSp, ' ');
1152 sqlite3_str_appendall(p->pOut,
1153 "Cycles Loops (est) Rows (est)\n");
1154 sqlite3_str_appendchar(p->pOut, nSp, ' ');
1155 sqlite3_str_appendall(p->pOut,
1156 "---------- ------------ ------------\n");
1157 }else{
1158 sqlite3_str_appendchar(p->pOut, nSp, ' ');
1159 sqlite3_str_appendall(p->pOut,
1160 "Cycles Loops Rows \n");
1161 sqlite3_str_appendchar(p->pOut, nSp, ' ');
1162 sqlite3_str_appendall(p->pOut,
1163 "---------- ----- -----\n");
1164 }
1165 sqlite3_str_appendall(p->pOut, "QUERY PLAN");
1166 sqlite3_str_appendchar(p->pOut, nSp - 10, ' ');
1167 qrfApproxInt64(p->pOut, nCycle);
1168 sqlite3_str_appendall(p->pOut, " 100%\n");
1169 }else{
1170 sqlite3_str_appendall(p->pOut, "QUERY PLAN\n");
1171 }
1172 p->u.pGraph->zPrefix[0] = 0;
1173 qrfEqpRenderLevel(p, 0);
@@ -1145,10 +1218,12 @@
1218 static const int f = SQLITE_SCANSTAT_COMPLEX;
1219 sqlite3_stmt *pS = p->pStmt;
1220 int i = 0;
1221 i64 nTotal = 0;
1222 int nWidth = 0;
1223 int prevPid = -1; /* Previous iPid */
1224 double rEstCum = 1.0; /* Cumulative row estimate */
1225 sqlite3_str *pLine = sqlite3_str_new(p->db);
1226 sqlite3_str *pStats = sqlite3_str_new(p->db);
1227 qrfEqpReset(p);
1228
1229 for(i=0; 1; i++){
@@ -1158,11 +1233,11 @@
1233 break;
1234 }
1235 n = (int)strlen(z) + qrfStatsHeight(pS,i)*3;
1236 if( n>nWidth ) nWidth = n;
1237 }
1238 nWidth += 2;
1239
1240 sqlite3_stmt_scanstatus_v2(pS,-1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal);
1241 for(i=0; 1; i++){
1242 i64 nLoop = 0;
1243 i64 nRow = 0;
@@ -1173,55 +1248,67 @@
1248 const char *zName = 0;
1249 double rEst = 0.0;
1250
1251 if( sqlite3_stmt_scanstatus_v2(pS,i,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&zo) ){
1252 break;
1253 }
1254 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
1255 if( iPid!=prevPid ){
1256 prevPid = iPid;
1257 rEstCum = 1.0;
1258 }
1259 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_EST,f,(void*)&rEst);
1260 rEstCum *= rEst;
1261 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop);
1262 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow);
1263 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle);
1264 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId);
 
1265 sqlite3_stmt_scanstatus_v2(pS,i, SQLITE_SCANSTAT_NAME,f,(void*)&zName);
1266
1267 if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
1268 int nSp = 0;
 
1269 sqlite3_str_reset(pStats);
1270 if( nCycle>=0 && nTotal>0 ){
1271 qrfApproxInt64(pStats, nCycle);
1272 sqlite3_str_appendf(pStats, " %3d%%",
1273 ((nCycle*100)+nTotal/2) / nTotal
1274 );
1275 nSp = 2;
1276 }
1277 if( nLoop>=0 ){
1278 if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
1279 qrfApproxInt64(pStats, nLoop);
1280 nSp = 2;
1281 if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1282 sqlite3_str_appendf(pStats, " ");
1283 qrfApproxInt64(pStats, (i64)(rEstCum/rEst));
1284 }
1285 }
1286 if( nRow>=0 ){
1287 if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
1288 qrfApproxInt64(pStats, nRow);
1289 nSp = 2;
1290 if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1291 sqlite3_str_appendf(pStats, " ");
1292 qrfApproxInt64(pStats, (i64)rEstCum);
1293 }
1294 }
 
1295 sqlite3_str_appendf(pLine,
1296 "% *s %s", -1*(nWidth-qrfStatsHeight(pS,i)*3), zo,
1297 sqlite3_str_value(pStats)
1298 );
1299 sqlite3_str_reset(pStats);
1300 qrfEqpAppend(p, iId, iPid, sqlite3_str_value(pLine));
1301 sqlite3_str_reset(pLine);
1302 }else{
1303 qrfEqpAppend(p, iId, iPid, zo);
1304 }
1305 }
1306 if( p->u.pGraph ) p->u.pGraph->nWidth = nWidth;
1307 qrfStrErr(p, pLine);
1308 sqlite3_free(sqlite3_str_finish(pLine));
1309 qrfStrErr(p, pStats);
1310 sqlite3_free(sqlite3_str_finish(pStats));
1311 #endif
1312 }
1313
1314
@@ -1581,13 +1668,15 @@
1668 ** (3) z[] does not looks like a numeric literal
1669 */
1670 static int qrfRelaxable(Qrf *p, const char *z){
1671 size_t i, n;
1672 if( z[0]=='\'' || qrfSpace(z[0]) ) return 0;
1673 if( z[0]==0 ){
1674 return (p->spec.zNull!=0 && p->spec.zNull[0]!=0);
1675 }
1676 n = strlen(z);
1677 if( n==0 || z[n-1]=='\'' || qrfSpace(z[n-1]) ) return 0;
1678 if( p->spec.zNull && strcmp(p->spec.zNull,z)==0 ) return 0;
1679 i = (z[0]=='-' || z[0]=='+');
1680 if( strcmp(z+i,"Inf")==0 ) return 0;
1681 if( !qrfDigit(z[i]) ) return 1;
1682 i++;
@@ -2729,10 +2818,11 @@
2818 int nNL = 0;
2819 int n, w;
2820 pStr = sqlite3_str_new(p->db);
2821 qrfEncodeText(p, pStr, z ? z : "");
2822 n = sqlite3_str_length(pStr);
2823 qrfStrErr(p, pStr);
2824 z = data.az[data.n] = sqlite3_str_finish(pStr);
2825 if( p->spec.nTitleLimit ){
2826 nNL = 0;
2827 data.aiWth[data.n] = w = qrfTitleLimit(data.az[data.n],
2828 p->spec.nTitleLimit );
@@ -2756,10 +2846,11 @@
2846 int n, w;
2847 int eType = sqlite3_column_type(p->pStmt,i);
2848 pStr = sqlite3_str_new(p->db);
2849 qrfRenderValue(p, pStr, i);
2850 n = sqlite3_str_length(pStr);
2851 qrfStrErr(p, pStr);
2852 z = data.az[data.n] = sqlite3_str_finish(pStr);
2853 data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
2854 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2855 data.n++;
2856 if( w>data.a[i].mxW ) data.a[i].mxW = w;
@@ -2910,11 +3001,11 @@
3001 ){
3002 bRTrim = 1;
3003 }else{
3004 bRTrim = 0;
3005 }
3006 for(i=0; i<data.n && sqlite3_str_errcode(p->pOut)==SQLITE_OK; i+=nColumn){
3007 int bMore;
3008 int nRow = 0;
3009
3010 /* Draw a single row of the table. This might be the title line
3011 ** (if there is a title line) or a row in the body of the table.
@@ -3097,11 +3188,11 @@
3188 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 0), "addr" ) );
3189 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 1), "opcode" ) );
3190 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 2), "p1" ) );
3191 assert( 0==sqlite3_stricmp( sqlite3_column_name(p->pStmt, 3), "p2" ) );
3192
3193 for(iOp=0; SQLITE_ROW==sqlite3_step(p->pStmt) && !p->iErr; iOp++){
3194 int iAddr = sqlite3_column_int(p->pStmt, 0);
3195 const char *zOp = (const char*)sqlite3_column_text(p->pStmt, 1);
3196 int p1 = sqlite3_column_int(p->pStmt, 2);
3197 int p2 = sqlite3_column_int(p->pStmt, 3);
3198
@@ -3154,11 +3245,11 @@
3245 nWidth = sizeof(aScanExpWidth)/sizeof(int);
3246 iIndent = 3;
3247 }
3248 if( nArg>nWidth ) nArg = nWidth;
3249
3250 for(iOp=0; sqlite3_step(p->pStmt)==SQLITE_ROW && !p->iErr; iOp++){
3251 /* If this is the first row seen, print out the headers */
3252 if( iOp==0 ){
3253 for(i=0; i<nArg; i++){
3254 const char *zCol = sqlite3_column_name(p->pStmt, aMap[i]);
3255 qrfWidthPrint(p,p->pOut, aWidth[i], zCol);
@@ -3410,10 +3501,11 @@
3501 sqlite3_str_append(p->pOut, "\n", 1);
3502 zVal += iNext;
3503 }while( zVal[0] );
3504 sqlite3_str_reset(pVal);
3505 }
3506 qrfStrErr(p, pVal);
3507 sqlite3_free(sqlite3_str_finish(pVal));
3508 qrfWrite(p);
3509 break;
3510 }
3511 case QRF_STYLE_Eqp: {
@@ -3473,11 +3565,11 @@
3565 p->pOut = sqlite3_str_new(p->db);
3566 if( p->pOut==0 ){
3567 qrfOom(p);
3568 return;
3569 }
3570 p->iErr = SQLITE_OK;
3571 p->nCol = sqlite3_column_count(p->pStmt);
3572 p->nRow = 0;
3573 sz = sizeof(sqlite3_qrf_spec);
3574 memcpy(&p->spec, pSpec, sz);
3575 if( p->spec.zNull==0 ) p->spec.zNull = "";
@@ -3644,17 +3736,27 @@
3736 sqlite3_free(p->u.sLine.azCol);
3737 }
3738 break;
3739 }
3740 case QRF_STYLE_Stats:
3741 case QRF_STYLE_StatsEst: {
3742 i64 nCycle = 0;
3743 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
3744 sqlite3_stmt_scanstatus_v2(p->pStmt, -1, SQLITE_SCANSTAT_NCYCLE,
3745 SQLITE_SCANSTAT_COMPLEX, (void*)&nCycle);
3746 #endif
3747 qrfEqpRender(p, nCycle);
3748 qrfWrite(p);
3749 break;
3750 }
3751 case QRF_STYLE_Eqp: {
3752 qrfEqpRender(p, 0);
3753 qrfWrite(p);
3754 break;
3755 }
3756 }
3757 qrfStrErr(p, p->pOut);
3758 if( p->spec.pzOutput ){
3759 if( p->spec.pzOutput[0] ){
3760 sqlite3_int64 n, sz;
3761 char *zCombined;
3762 sz = strlen(p->spec.pzOutput[0]);
@@ -3815,13 +3917,10 @@
3917
3918
3919 #define eputz(z) cli_puts(z,stderr)
3920 #define sputz(fp,z) cli_puts(z,fp)
3921
 
 
 
3922 /* A version of strcmp() that works with NULL values */
3923 static int cli_strcmp(const char *a, const char *b){
3924 if( a==0 ) a = "";
3925 if( b==0 ) b = "";
3926 return strcmp(a,b);
@@ -3834,11 +3933,11 @@
3933
3934 /* Return the current wall-clock time in microseconds since the
3935 ** Unix epoch (1970-01-01T00:00:00Z)
3936 */
3937 static sqlite3_int64 timeOfDay(void){
3938 #if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
3939 sqlite3_uint64 t;
3940 FILETIME tm;
3941 GetSystemTimePreciseAsFileTime(&tm);
3942 t = ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
3943 t += 116444736000000000LL;
@@ -3862,154 +3961,10 @@
3961 (void)gettimeofday(&sNow,0);
3962 return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
3963 #endif
3964 }
3965
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3966
3967 /*
3968 ** Used to prevent warnings about unused parameters
3969 */
3970 #define UNUSED_PARAMETER(x) (void)(x)
@@ -4068,10 +4023,18 @@
4023 #define PROMPT_LEN_MAX 128
4024 /* First line prompt. default: "sqlite> " */
4025 static char mainPrompt[PROMPT_LEN_MAX];
4026 /* Continuation prompt. default: " ...> " */
4027 static char continuePrompt[PROMPT_LEN_MAX];
4028
4029 /*
4030 ** Write I/O traces to the following stream.
4031 */
4032 #ifdef SQLITE_ENABLE_IOTRACE
4033 static FILE *iotrace = 0;
4034 #endif
4035
4036
4037 /* This is variant of the standard-library strncpy() routine with the
4038 ** one change that the destination string is always zero-terminated, even
4039 ** if there is no zero-terminator in the first n-1 characters of the source
4040 ** string.
@@ -4188,17 +4151,10 @@
4151 */
4152 static void shell_check_oom(const void *p){
4153 if( p==0 ) shell_out_of_memory();
4154 }
4155
 
 
 
 
 
 
 
4156 /*
4157 ** This routine works like printf in that its first argument is a
4158 ** format string and subsequent arguments are values to be substituted
4159 ** in place of % fields. The result of formatting this string
4160 ** is written to iotrace.
@@ -8349,13 +8305,13 @@
8305 }else if( e<-10000 ){
8306 e = -10000;
8307 }
8308
8309 if( m<0 ){
8310 if( m<(-9223372036854775807LL) ) return;
8311 isNeg = 1;
8312 m = -m;
 
8313 }else if( m==0 && e>-1000 && e<1000 ){
8314 sqlite3_result_double(context, 0.0);
8315 return;
8316 }
8317 while( (m>>32)&0xffe00000 ){
@@ -9472,11 +9428,11 @@
9428 ** (X) match X
9429 ** X|Y X or Y
9430 ** ^X X occurring at the beginning of the string
9431 ** X$ X occurring at the end of the string
9432 ** . Match any single character
9433 ** \c Character c where c is one of \{}()[]|*+?-.
9434 ** \c C-language escapes for c in afnrtv. ex: \t or \n
9435 ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
9436 ** \xXX Where XX is exactly 2 hex digits, unicode value XX
9437 ** [abc] Any single character from the set abc
9438 ** [^abc] Any single character not in the set abc
@@ -9857,11 +9813,11 @@
9813
9814 /* A backslash character has been seen, read the next character and
9815 ** return its interpretation.
9816 */
9817 static unsigned re_esc_char(ReCompiled *p){
9818 static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]-";
9819 static const char zTrans[] = "\a\f\n\r\t\v";
9820 int i, v = 0;
9821 char c;
9822 if( p->sIn.i>=p->sIn.mx ) return 0;
9823 c = p->sIn.z[p->sIn.i];
@@ -10180,15 +10136,22 @@
10136 }
10137 return pRe->zErr;
10138 }
10139
10140 /*
10141 ** The value of LIMIT_MAX_PATTERN_LENGTH.
10142 */
10143 static int re_maxlen(sqlite3_context *context){
10144 sqlite3 *db = sqlite3_context_db_handle(context);
10145 return sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH,-1);
10146 }
10147
10148 /*
10149 ** Maximum NFA size given a maximum pattern length.
10150 */
10151 static int re_maxnfa(int mxlen){
10152 return 75+mxlen/2;
10153 }
10154
10155 /*
10156 ** Implementation of the regexp() SQL function. This function implements
10157 ** the build-in REGEXP operator. The first argument to the function is the
@@ -10210,14 +10173,21 @@
10173 int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
10174
10175 (void)argc; /* Unused */
10176 pRe = sqlite3_get_auxdata(context, 0);
10177 if( pRe==0 ){
10178 int mxLen = re_maxlen(context);
10179 int nPattern;
10180 zPattern = (const char*)sqlite3_value_text(argv[0]);
10181 if( zPattern==0 ) return;
10182 nPattern = sqlite3_value_bytes(argv[0]);
10183 if( nPattern>mxLen ){
10184 zErr = "REGEXP pattern too big";
10185 }else{
10186 zErr = re_compile(&pRe, zPattern, re_maxnfa(mxLen),
10187 sqlite3_user_data(context)!=0);
10188 }
10189 if( zErr ){
10190 re_free(pRe);
10191 sqlite3_result_error(context, zErr, -1);
10192 return;
10193 }
@@ -10279,11 +10249,11 @@
10249 "ATSTART",
10250 };
10251
10252 zPattern = (const char*)sqlite3_value_text(argv[0]);
10253 if( zPattern==0 ) return;
10254 zErr = re_compile(&pRe, zPattern, re_maxnfa(re_maxlen(context)),
10255 sqlite3_user_data(context)!=0);
10256 if( zErr ){
10257 re_free(pRe);
10258 sqlite3_result_error(context, zErr, -1);
10259 return;
@@ -13067,11 +13037,11 @@
13037 nFile = (int)strlen(zFile)+1;
13038 }
13039
13040 rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
13041 if( rc==SQLITE_OK ){
13042 pNew = (ZipfileTab*)sqlite3_malloc64((i64)nByte+nFile);
13043 if( pNew==0 ) return SQLITE_NOMEM;
13044 memset(pNew, 0, nByte+nFile);
13045 pNew->db = db;
13046 pNew->aBuffer = (u8*)&pNew[1];
13047 if( zFile ){
@@ -13213,18 +13183,19 @@
13183 ** sqlite3_free().
13184 */
13185 static int zipfileReadData(
13186 FILE *pFile, /* Read from this file */
13187 u8 *aRead, /* Read into this buffer */
13188 i64 nRead, /* Number of bytes to read */
13189 i64 iOff, /* Offset to read from */
13190 char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
13191 ){
13192 size_t n;
13193 fseek(pFile, (long)iOff, SEEK_SET);
13194 n = fread(aRead, 1, (long)nRead, pFile);
13195 if( n!=(size_t)nRead ){
13196 sqlite3_free(*pzErrmsg);
13197 *pzErrmsg = sqlite3_mprintf("error in fread()");
13198 return SQLITE_ERROR;
13199 }
13200 return SQLITE_OK;
13201 }
@@ -13237,11 +13208,11 @@
13208 if( nWrite>0 ){
13209 size_t n = nWrite;
13210 fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
13211 n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
13212 if( (int)n!=nWrite ){
13213 zipfileTableErr(pTab,"error in fwrite()");
13214 return SQLITE_ERROR;
13215 }
13216 pTab->szCurrent += nWrite;
13217 }
13218 return SQLITE_OK;
@@ -13484,10 +13455,11 @@
13455 /*
13456 ** Set (*pzErr) to point to a buffer from sqlite3_malloc() containing a
13457 ** generic corruption message and return SQLITE_CORRUPT;
13458 */
13459 static int zipfileCorrupt(char **pzErr){
13460 sqlite3_free(*pzErr);
13461 *pzErr = sqlite3_mprintf("zip archive is corrupt");
13462 return SQLITE_CORRUPT;
13463 }
13464
13465 /*
@@ -13502,11 +13474,11 @@
13474 ** final value of (*ppEntry) undefined.
13475 */
13476 static int zipfileGetEntry(
13477 ZipfileTab *pTab, /* Store any error message here */
13478 const u8 *aBlob, /* Pointer to in-memory file image */
13479 i64 nBlob, /* Size of aBlob[] in bytes */
13480 FILE *pFile, /* If aBlob==0, read from this file */
13481 i64 iOff, /* Offset of CDS record */
13482 ZipfileEntry **ppEntry /* OUT: Pointer to new object */
13483 ){
13484 u8 *aRead;
@@ -13542,18 +13514,18 @@
13514 rc = SQLITE_NOMEM;
13515 }else{
13516 memset(pNew, 0, sizeof(ZipfileEntry));
13517 rc = zipfileReadCDS(aRead, &pNew->cds);
13518 if( rc!=SQLITE_OK ){
13519 zipfileTableErr(pTab, "failed to read CDS at offset %lld", iOff);
13520 }else if( aBlob==0 ){
13521 rc = zipfileReadData(
13522 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
13523 );
13524 }else{
13525 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
13526 if( (iOff + ZIPFILE_CDS_FIXED_SZ + nFile + nExtra)>nBlob ){
13527 rc = zipfileCorrupt(pzErr);
13528 }
13529 }
13530 }
13531
@@ -13574,19 +13546,19 @@
13546 ZipfileLFH lfh;
13547 if( pFile ){
13548 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
13549 }else{
13550 aRead = (u8*)&aBlob[pNew->cds.iOffset];
13551 if( ((i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ)>nBlob ){
13552 rc = zipfileCorrupt(pzErr);
13553 }
13554 }
13555
13556 memset(&lfh, 0, sizeof(lfh));
13557 if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
13558 if( rc==SQLITE_OK ){
13559 pNew->iDataOff = (i64)pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
13560 pNew->iDataOff += lfh.nFile + lfh.nExtra;
13561 if( aBlob && pNew->cds.szCompressed ){
13562 if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){
13563 rc = zipfileCorrupt(pzErr);
13564 }else{
@@ -13593,11 +13565,11 @@
13565 pNew->aData = &pNew->aExtra[nExtra];
13566 memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
13567 }
13568 }
13569 }else{
13570 zipfileTableErr(pTab, "failed to read LFH at offset %d",
13571 (int)pNew->cds.iOffset
13572 );
13573 }
13574 }
13575
@@ -13617,11 +13589,11 @@
13589 static int zipfileNext(sqlite3_vtab_cursor *cur){
13590 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
13591 int rc = SQLITE_OK;
13592
13593 if( pCsr->pFile ){
13594 i64 iEof = (i64)pCsr->eocd.iOffset + (i64)pCsr->eocd.nSize;
13595 zipfileEntryFree(pCsr->pCurrent);
13596 pCsr->pCurrent = 0;
13597 if( pCsr->iNextOff>=iEof ){
13598 pCsr->bEof = 1;
13599 }else{
@@ -13855,16 +13827,16 @@
13827 ** an English language error message may be left in virtual-table pTab.
13828 */
13829 static int zipfileReadEOCD(
13830 ZipfileTab *pTab, /* Return errors here */
13831 const u8 *aBlob, /* Pointer to in-memory file image */
13832 i64 nBlob, /* Size of aBlob[] in bytes */
13833 FILE *pFile, /* Read from this file if aBlob==0 */
13834 ZipfileEOCD *pEOCD /* Object to populate */
13835 ){
13836 u8 *aRead = pTab->aBuffer; /* Temporary buffer */
13837 i64 nRead; /* Bytes to read from file */
13838 int rc = SQLITE_OK;
13839
13840 memset(pEOCD, 0, sizeof(ZipfileEOCD));
13841 if( aBlob==0 ){
13842 i64 iOff; /* Offset to read from */
@@ -13881,11 +13853,11 @@
13853 nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
13854 aRead = (u8*)&aBlob[nBlob-nRead];
13855 }
13856
13857 if( rc==SQLITE_OK ){
13858 i64 i;
13859
13860 /* Scan backwards looking for the signature bytes */
13861 for(i=nRead-20; i>=0; i--){
13862 if( aRead[i]==0x50 && aRead[i+1]==0x4b
13863 && aRead[i+2]==0x05 && aRead[i+3]==0x06
@@ -13892,13 +13864,11 @@
13864 ){
13865 break;
13866 }
13867 }
13868 if( i<0 ){
13869 zipfileTableErr(pTab, "cannot find end of central directory record");
 
 
13870 return SQLITE_ERROR;
13871 }
13872
13873 aRead += i+4;
13874 pEOCD->iDisk = zipfileRead16(aRead);
@@ -13939,11 +13909,11 @@
13909 pNew->pNext = pBefore;
13910 *pp = pNew;
13911 }
13912 }
13913
13914 static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, i64 nBlob){
13915 ZipfileEOCD eocd;
13916 int rc;
13917 int i;
13918 i64 iOff;
13919
@@ -13987,11 +13957,11 @@
13957 zipfileCursorErr(pCsr, "zipfile() function requires an argument");
13958 return SQLITE_ERROR;
13959 }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
13960 static const u8 aEmptyBlob = 0;
13961 const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
13962 i64 nBlob = sqlite3_value_bytes(argv[0]);
13963 assert( pTab->pFirstEntry==0 );
13964 if( aBlob==0 ){
13965 aBlob = &aEmptyBlob;
13966 nBlob = 0;
13967 }
@@ -14185,23 +14155,23 @@
14155 ZipfileTab *pTab = (ZipfileTab*)pVtab;
14156 int rc = SQLITE_OK;
14157
14158 assert( pTab->pWriteFd==0 );
14159 if( pTab->zFile==0 || pTab->zFile[0]==0 ){
14160 zipfileTableErr(pTab, "zipfile: missing filename");
14161 return SQLITE_ERROR;
14162 }
14163
14164 /* Open a write fd on the file. Also load the entire central directory
14165 ** structure into memory. During the transaction any new file data is
14166 ** appended to the archive file, but the central directory is accumulated
14167 ** in main-memory until the transaction is committed. */
14168 pTab->pWriteFd = sqlite3_fopen(pTab->zFile, "ab+");
14169 if( pTab->pWriteFd==0 ){
14170 zipfileTableErr(pTab,
14171 "zipfile: failed to open file %s for writing", pTab->zFile
14172 );
14173 rc = SQLITE_ERROR;
14174 }else{
14175 fseek(pTab->pWriteFd, 0, SEEK_END);
14176 pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
14177 rc = zipfileLoadDirectory(pTab, 0, 0);
@@ -14662,11 +14632,11 @@
14632 int nEntry;
14633 ZipfileBuffer body;
14634 ZipfileBuffer cds;
14635 };
14636
14637 static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
14638 if( pBuf->n+nByte>pBuf->nAlloc ){
14639 u8 *aNew;
14640 sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
14641 int nReq = pBuf->n + nByte;
14642
@@ -14711,11 +14681,11 @@
14681 u32 iCrc32 = 0; /* crc32 of uncompressed data */
14682
14683 char *zName = 0; /* Path (name) of new entry */
14684 int nName = 0; /* Size of zName in bytes */
14685 char *zFree = 0; /* Free this before returning */
14686 i64 nByte;
14687
14688 memset(&e, 0, sizeof(e));
14689 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
14690 if( p==0 ) return;
14691
@@ -24161,28 +24131,28 @@
24131 u8 autoExplain; /* Automatically turn on .explain mode */
24132 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
24133 u8 autoEQPtrace; /* autoEQP is in trace mode */
24134 u8 scanstatsOn; /* True to display scan stats before each finalize */
24135 u8 bAutoScreenWidth; /* Using the TTY to determine screen width */
24136 u8 mFlags; /* MFLG_ECHO, MFLG_CRLF, etc. */
24137 u8 eMode; /* One of the MODE_ values */
24138 sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
24139 } Mode;
24140
24141 /* Flags for Mode.mFlags */
24142 #define MFLG_ECHO 0x01 /* Echo inputs to output */
24143 #define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
24144 #define MFLG_HDR 0x04 /* .header used to change headers on/off */
24145
24146
24147 /*
24148 ** State information about the database connection is contained in an
24149 ** instance of the following structure.
24150 */
24151 typedef struct ShellState ShellState;
24152 struct ShellState {
24153 sqlite3 *db; /* The database */
 
24154 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
24155 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
24156 u8 nEqpLevel; /* Depth of the EQP output graph */
24157 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
24158 u8 bSafeMode; /* True to prohibit unsafe operations */
@@ -24190,11 +24160,14 @@
24160 u8 eRestoreState; /* See comments above doAutoDetectRestore() */
24161 unsigned statsOn; /* True to display memory stats before each finalize */
24162 unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
24163 u8 nPopOutput; /* Revert .output settings when reaching zero */
24164 u8 nPopMode; /* Revert .mode settings when reaching zero */
24165 u8 enableTimer; /* Enable the timer. 2: permanently 1: only once */
24166 int inputNesting; /* Track nesting level of .read and other redirects */
24167 double prevTimer; /* Last reported timer value */
24168 double tmProgress; /* --timeout option for .progress */
24169 i64 lineno; /* Line number of last line read from in */
24170 const char *zInFile; /* Name of the input file */
24171 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
24172 FILE *in; /* Read commands from this stream */
24173 FILE *out; /* Write results here */
@@ -24286,10 +24259,11 @@
24259 #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
24260 #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress
24261 ** callback limit is reached, and for each
24262 ** top-level SQL statement */
24263 #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
24264 #define SHELL_PROGRESS_TMOUT 0x08 /* Stop after tmProgress seconds */
24265
24266 /* Names of values for Mode.spec.eEsc and Mode.spec.eText
24267 */
24268 static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
24269 static const char *qrfQuoteNames[] =
@@ -24447,10 +24421,181 @@
24421 ** Limit input nesting via .read or any other input redirect.
24422 ** It's not too expensive, so a generous allowance can be made.
24423 */
24424 #define MAX_INPUT_NESTING 25
24425
24426 /************************* BEGIN PERFORMANCE TIMER *****************************/
24427 #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
24428 #include <sys/time.h>
24429 #include <sys/resource.h>
24430 /* VxWorks does not support getrusage() as far as we can determine */
24431 #if defined(_WRS_KERNEL) || defined(__RTP__)
24432 struct rusage {
24433 struct timeval ru_utime; /* user CPU time used */
24434 struct timeval ru_stime; /* system CPU time used */
24435 };
24436 #define getrusage(A,B) memset(B,0,sizeof(*B))
24437 #endif
24438
24439 /* Saved resource information for the beginning of an operation */
24440 static struct rusage sBegin; /* CPU time at start */
24441 static sqlite3_int64 iBegin; /* Wall-clock time at start */
24442
24443 /*
24444 ** Begin timing an operation
24445 */
24446 static void beginTimer(ShellState *p){
24447 if( p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0 ){
24448 getrusage(RUSAGE_SELF, &sBegin);
24449 iBegin = timeOfDay();
24450 }
24451 }
24452
24453 /* Return the difference of two time_structs in seconds */
24454 static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
24455 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
24456 (double)(pEnd->tv_sec - pStart->tv_sec);
24457 }
24458
24459 /* Return the time since the start of the timer in
24460 ** seconds. */
24461 static double elapseTime(ShellState *NotUsed){
24462 (void)NotUsed;
24463 if( iBegin==0 ) return 0.0;
24464 return (timeOfDay() - iBegin)*0.000001;
24465 }
24466
24467 /*
24468 ** Print the timing results.
24469 */
24470 static void endTimer(ShellState *p){
24471 if( p->enableTimer ){
24472 sqlite3_int64 iEnd = timeOfDay();
24473 struct rusage sEnd;
24474 getrusage(RUSAGE_SELF, &sEnd);
24475 p->prevTimer = (iEnd - iBegin)*0.000001;
24476 cli_printf(p->out, "Run Time: real %.6f user %.6f sys %.6f\n",
24477 p->prevTimer,
24478 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
24479 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
24480 if( p->enableTimer==1 ) p->enableTimer = 0;
24481 iBegin = 0;
24482 }
24483 }
24484
24485 #define BEGIN_TIMER(X) beginTimer(X)
24486 #define END_TIMER(X) endTimer(X)
24487 #define ELAPSE_TIME(X) elapseTime(X)
24488 #define HAS_TIMER 1
24489
24490 #elif (defined(_WIN32) || defined(WIN32))
24491
24492 /* Saved resource information for the beginning of an operation */
24493 static HANDLE hProcess;
24494 static FILETIME ftKernelBegin;
24495 static FILETIME ftUserBegin;
24496 static sqlite3_int64 ftWallBegin;
24497 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
24498 LPFILETIME, LPFILETIME);
24499 static GETPROCTIMES getProcessTimesAddr = NULL;
24500
24501 /*
24502 ** Check to see if we have timer support. Return 1 if necessary
24503 ** support found (or found previously).
24504 */
24505 static int hasTimer(void){
24506 if( getProcessTimesAddr ){
24507 return 1;
24508 } else {
24509 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
24510 ** versions. See if the version we are running on has it, and if it
24511 ** does, save off a pointer to it and the current process handle.
24512 */
24513 hProcess = GetCurrentProcess();
24514 if( hProcess ){
24515 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
24516 if( NULL != hinstLib ){
24517 getProcessTimesAddr =
24518 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
24519 if( NULL != getProcessTimesAddr ){
24520 return 1;
24521 }
24522 FreeLibrary(hinstLib);
24523 }
24524 }
24525 }
24526 return 0;
24527 }
24528
24529 /*
24530 ** Begin timing an operation
24531 */
24532 static void beginTimer(ShellState *p){
24533 if( (p->enableTimer || (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0)
24534 && getProcessTimesAddr
24535 ){
24536 FILETIME ftCreation, ftExit;
24537 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
24538 &ftKernelBegin,&ftUserBegin);
24539 ftWallBegin = timeOfDay();
24540 }
24541 }
24542
24543 /* Return the difference of two FILETIME structs in seconds */
24544 static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
24545 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
24546 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
24547 return (double) ((i64End - i64Start) / 10000000.0);
24548 }
24549
24550 /* Return the time since the start of the timer in
24551 ** seconds. */
24552 static double elapseTime(ShellState *NotUsed){
24553 (void)NotUsed;
24554 if( ftWallBegin==0 ) return 0.0;
24555 return (timeOfDay() - ftWallBegin)*0.000001;
24556 }
24557
24558 /*
24559 ** Print the timing results.
24560 */
24561 static void endTimer(ShellState *p){
24562 if( p->enableTimer && getProcessTimesAddr){
24563 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
24564 sqlite3_int64 ftWallEnd = timeOfDay();
24565 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
24566 p->prevTimer = (ftWallEnd - ftWallBegin)*0.000001;
24567 #ifdef _WIN64
24568 /* microsecond precision on 64-bit windows */
24569 cli_printf(p->out, "Run Time: real %.6f user %f sys %f\n",
24570 p->prevTimer,
24571 timeDiff(&ftUserBegin, &ftUserEnd),
24572 timeDiff(&ftKernelBegin, &ftKernelEnd));
24573 #else
24574 /* millisecond precisino on 32-bit windows */
24575 cli_printf(p->out, "Run Time: real %.3f user %.3f sys %.3f\n",
24576 p->prevTimer,
24577 timeDiff(&ftUserBegin, &ftUserEnd),
24578 timeDiff(&ftKernelBegin, &ftKernelEnd));
24579 #endif
24580 if( p->enableTimer==1 ) p->enableTimer = 0;
24581 ftWallBegin = 0;
24582 }
24583 }
24584
24585 #define BEGIN_TIMER(X) beginTimer(X)
24586 #define ELAPSE_TIME(X) elapseTime(X)
24587 #define END_TIMER(X) endTimer(X)
24588 #define HAS_TIMER hasTimer()
24589
24590 #else
24591 #define BEGIN_TIMER(X) /* no-op */
24592 #define ELAPSE_TIME(X) 0.0
24593 #define END_TIMER(X) /*no-op*/
24594 #define HAS_TIMER 0
24595 #endif
24596 /************************* END PERFORMANCE TIMER ******************************/
24597
24598 /*
24599 ** Clear a display mode, freeing any allocated memory that it
24600 ** contains.
24601 */
@@ -24534,11 +24679,13 @@
24679 if( pI->eCSep ) modeSetStr(&pM->spec.zColumnSep, aModeStr[pI->eCSep]);
24680 if( pI->eRSep ) modeSetStr(&pM->spec.zRowSep, aModeStr[pI->eRSep]);
24681 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24682 pM->spec.eText = pI->eText;
24683 pM->spec.eBlob = pI->eBlob;
24684 if( (pM->mFlags & MFLG_HDR)==0 ){
24685 pM->spec.bTitles = pI->bHdr;
24686 }
24687 pM->spec.eTitle = pI->eHdr;
24688 if( pI->mFlg & 0x01 ){
24689 pM->spec.bBorder = QRF_No;
24690 }else{
24691 pM->spec.bBorder = QRF_Auto;
@@ -24570,18 +24717,17 @@
24717 p->mode.mFlags = mFlags;
24718 }
24719 }
24720
24721 /*
24722 ** Set the mode to the default. It assumed that the mode has
24723 ** already been freed and zeroed prior to calling this routine.
 
24724 */
24725 static void modeDefault(ShellState *p){
24726 p->mode.spec.iVersion = 1;
24727 p->mode.autoExplain = 1;
24728 if( stdin_is_interactive || stdout_is_console ){
24729 modeChange(p, MODE_TTY);
24730 }else{
24731 modeChange(p, MODE_BATCH);
24732 }
24733 }
@@ -25371,10 +25517,17 @@
25517 ** Progress handler callback.
25518 */
25519 static int progress_handler(void *pClientData) {
25520 ShellState *p = (ShellState*)pClientData;
25521 p->nProgress++;
25522 if( (p->flgProgress & SHELL_PROGRESS_TMOUT)!=0
25523 && ELAPSE_TIME(p)>=p->tmProgress
25524 ){
25525 cli_printf(p->out, "Progress timeout after %.6f seconds\n",
25526 ELAPSE_TIME(p));
25527 return 1;
25528 }
25529 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
25530 cli_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
25531 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
25532 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
25533 return 1;
@@ -25908,10 +26061,12 @@
26061 char *zBuf = sqlite3_malloc64( szVar-5 );
26062 if( zBuf ){
26063 memcpy(zBuf, &zVar[6], szVar-5);
26064 sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
26065 }
26066 }else if( strcmp(zVar, "$TIMER")==0 ){
26067 sqlite3_bind_double(pStmt, i, pArg->prevTimer);
26068 #ifdef SQLITE_ENABLE_CARRAY
26069 }else if( strncmp(zVar, "$carray_", 8)==0 ){
26070 static char *azColorNames[] = {
26071 "azure", "black", "blue", "brown", "cyan", "fuchsia", "gold",
26072 "gray", "green", "indigo", "khaki", "lime", "magenta", "maroon",
@@ -26167,27 +26322,36 @@
26322 pArg->pStmt = pStmt;
26323 }
26324
26325 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
26326 isExplain = sqlite3_stmt_isexplain(pStmt);
26327 if( pArg && pArg->mode.autoEQP && isExplain==0 && pArg->dot.nArg==0 ){
26328 int triggerEQP = 0;
26329 u8 savedEnableTimer = pArg->enableTimer;
26330 pArg->enableTimer = 0;
26331 disable_debug_trace_modes();
26332 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
26333 if( pArg->mode.autoEQP>=AUTOEQP_trigger ){
26334 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
26335 }
26336 sqlite3_reset(pStmt);
26337 spec.eStyle = QRF_STYLE_Auto;
26338 sqlite3_stmt_explain(pStmt, 2);
26339 sqlite3_format_query_result(pStmt, &spec, 0);
26340 if( pArg->mode.autoEQP>=AUTOEQP_full ){
26341 sqlite3_reset(pStmt);
26342 sqlite3_stmt_explain(pStmt, 1);
26343 sqlite3_format_query_result(pStmt, &spec, 0);
26344 }
26345
26346 if( pArg->mode.autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
26347 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
26348 }
26349 sqlite3_reset(pStmt);
26350 sqlite3_stmt_explain(pStmt, 0);
26351 restore_debug_trace_modes();
26352 pArg->enableTimer = savedEnableTimer;
26353 }
26354
26355 bind_prepared_stmt(pArg, pStmt);
26356 if( isExplain && pArg->mode.autoExplain ){
26357 spec.eStyle = isExplain==1 ? QRF_STYLE_Explain : QRF_STYLE_Eqp;
@@ -26604,12 +26768,12 @@
26768 ".bail on|off Stop after hitting an error. Default OFF",
26769 #ifndef SQLITE_SHELL_FIDDLE
26770 ".cd DIRECTORY Change the working directory to DIRECTORY",
26771 #endif
26772 ".changes on|off Show number of rows changed by SQL",
26773 ".check OPTIONS ... Verify the results of a .testcase",
26774 #ifndef SQLITE_SHELL_FIDDLE
 
26775 ".clone NEWDB Clone data into NEWDB from the existing database",
26776 #endif
26777 ".connection [close] [#] Open or close an auxiliary database connection",
26778 ".crlf ?on|off? Whether or not to use \\r\\n line endings",
26779 ".databases List names and files of attached databases",
@@ -26721,10 +26885,11 @@
26885 ".progress N Invoke progress handler after every N opcodes",
26886 " --limit N Interrupt after N progress callbacks",
26887 " --once Do no more than one progress interrupt",
26888 " --quiet|-q No output except at interrupts",
26889 " --reset Reset the count for each input and interrupt",
26890 " --timeout S Halt after running for S seconds",
26891 #endif
26892 ".prompt MAIN CONTINUE Replace the standard prompts",
26893 #ifndef SQLITE_SHELL_FIDDLE
26894 ".quit Stop interpreting input stream, exit if primary.",
26895 ".read FILE Read input from FILE or command output",
@@ -26785,17 +26950,15 @@
26950 " vmstep Show the virtual machine step count only",
26951 #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
26952 ".system CMD ARGS... Run CMD ARGS... in a system shell",
26953 #endif
26954 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
26955 ".testcase NAME Begin a test case.",
 
 
26956 ",testctrl CMD ... Run various sqlite3_test_control() operations",
26957 " Run \".testctrl\" with no arguments for details",
26958 ".timeout MS Try opening locked tables for MS milliseconds",
26959 ".timer on|off|once Turn SQL timer on or off.",
26960 #ifndef SQLITE_OMIT_TRACE
26961 ".trace ?OPTIONS? Output each SQL statement as it is run",
26962 " FILE Send output to FILE",
26963 " stdout Send output to stdout",
26964 " stderr Send output to stderr",
@@ -26836,19 +26999,33 @@
26999 "USAGE: .import [OPTIONS] FILE TABLE\n"
27000 "\n"
27001 "Import CSV or similar text from FILE into TABLE. If TABLE does\n"
27002 "not exist, it is created using the first row of FILE as the column\n"
27003 "names. If FILE begins with \"|\" then it is a command that is run\n"
27004 "and the output from the command is used as the input data. If\n"
27005 "FILE begins with \"<<\" followed by a label, then content is read from\n"
27006 "the script until the first line that matches the label.\n"
27007 "\n"
27008 "The content of FILE is interpreted using RFC-4180 (\"CSV\") quoting\n"
27009 "rules unless the current mode is \"ascii\" or \"tabs\" or unless one\n"
27010 "the --ascii option is used.\n"
27011 "\n"
27012 "The column and row separators must be single ASCII characters. If\n"
27013 "multiple characters or a Unicode character are specified for the\n"
27014 "separators, then only the first byte of the separator is used. Except,\n"
27015 "if the row separator is \\n and the mode is not --ascii, then \\r\\n is\n"
27016 "understood as a row separator too.\n"
27017 "\n"
27018 "Options:\n"
27019 " --ascii Do not use RFC-4180 quoting. Use \\037 and \\036\n"
27020 " as column and row separators on input, unless other\n"
27021 " delimiters are specified using --colsep and/or --rowsep\n"
27022 " --colsep CHAR Use CHAR as the column separator.\n"
27023 " --csv Input is standard RFC-4180 CSV.\n"
27024 " --esc CHAR Use CHAR as an escape character in unquoted CSV inputs.\n"
27025 " --qesc CHAR Use CHAR as an escape character in quoted CSV inputs.\n"
27026 " --rowsep CHAR Use CHAR as the row separator.\n"
27027 " --schema S When creating TABLE, put it in schema S\n"
27028 " --skip N Ignore the first N rows of input\n"
27029 " -v Verbose mode\n"
27030 },
27031 { ".mode",
@@ -26930,23 +27107,17 @@
27107 " --bom Prepend a byte-order mark to the output\n"
27108 " -e Accumulate output in a temporary text file then\n"
27109 " launch a text editor when the redirection ends.\n"
27110 " --error-prefix X Use X as the left-margin prefix for error messages.\n"
27111 " Set to an empty string to restore the default.\n"
27112 " --keep Keep redirecting output to its current destination.\n"
27113 " Use this option in combination with --show or\n"
27114 " with --error-prefix when you do not want to stop\n"
27115 " a current redirection.\n"
 
 
 
27116 " --plain Use plain text rather than HTML tables with -w\n"
27117 " --show Show output text captured by .testcase or by\n"
27118 " redirecting to \"memory\".\n"
 
 
 
27119 " -w Show the output in a web browser. Output is\n"
27120 " written into a temporary HTML file until the\n"
27121 " redirect ends, then the web browser is launched.\n"
27122 " Query results are shown as HTML tables, unless\n"
27123 " the --plain is used too.\n"
@@ -26970,10 +27141,39 @@
27141 " file in a web browser\n"
27142 " -x Show the output in a spreadsheet. Output is\n"
27143 " written to a temp file as CSV then the spreadsheet\n"
27144 " is launched when\n"
27145 },
27146 { ".check",
27147 "USAGE: .check [OPTIONS] PATTERN\n"
27148 "\n"
27149 "Verify results of commands since the most recent .testcase command.\n"
27150 "Restore output to the console, unless --keep is used.\n"
27151 "\n"
27152 "If PATTERN starts with \"<<ENDMARK\" then the actual pattern is taken from\n"
27153 "subsequent lines of text up to the first line that begins with ENDMARK.\n"
27154 "All pattern lines and the ENDMARK are discarded.\n"
27155 "\n"
27156 "Options:\n"
27157 " --exact Do an exact comparison including leading and\n"
27158 " trailing whitespace.\n"
27159 " --glob Treat PATTERN as a GLOB\n"
27160 " --keep Do not reset the testcase. More .check commands\n"
27161 " will follow.\n"
27162 " --notglob Output should not match PATTERN\n"
27163 " --show Write testcase output to the screen, for debugging.\n"
27164 },
27165 { ".testcase",
27166 "USAGE: .testcase [OPTIONS] NAME\n"
27167 "\n"
27168 "Start a new test case identified by NAME. All output\n"
27169 "through the next \".check\" command is captured for comparison. See the\n"
27170 "\".check\" commandn for additional informatioon.\n"
27171 "\n"
27172 "Options:\n"
27173 " --error-prefix TEXT Change error message prefix text to TEXT\n"
27174 },
27175 };
27176
27177 /*
27178 ** Return a pointer to usage text for zCmd, or NULL if none exists.
27179 */
@@ -27193,10 +27393,56 @@
27393 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
27394 }
27395 return 1;
27396 }
27397 #endif
27398
27399 /*
27400 ** Return the size of the named file in bytes. Or return a negative
27401 ** number if the file does not exist.
27402 */
27403 static sqlite3_int64 fileSize(const char *zFile){
27404 #if defined(_WIN32) || defined(WIN32)
27405 struct _stat64 x;
27406 if( _stat64(zFile, &x)!=0 ) return -1;
27407 return (sqlite3_int64)x.st_size;
27408 #else
27409 struct stat x;
27410 if( stat(zFile, &x)!=0 ) return -1;
27411 return (sqlite3_int64)x.st_size;
27412 #endif
27413 }
27414
27415 /*
27416 ** Return true if zFile is an SQLite database.
27417 **
27418 ** Algorithm:
27419 ** * If the file does not exist -> return false
27420 ** * If the size of the file is not a multiple of 512 -> return false
27421 ** * If sqlite3_open() fails -> return false
27422 ** * if sqlite3_prepare() or sqlite3_step() fails -> return false
27423 ** * Otherwise -> return true
27424 */
27425 static int isDatabaseFile(const char *zFile, int openFlags){
27426 sqlite3 *db = 0;
27427 sqlite3_stmt *pStmt = 0;
27428 int rc;
27429 sqlite3_int64 sz = fileSize(zFile);
27430 if( sz<512 || (sz%512)!=0 ) return 0;
27431 if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK
27432 && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
27433 ==SQLITE_OK
27434 && sqlite3_step(pStmt)==SQLITE_ROW
27435 ){
27436 rc = 1;
27437 }else{
27438 rc = 0;
27439 }
27440 sqlite3_finalize(pStmt);
27441 sqlite3_close(db);
27442 return rc;
27443 }
27444
27445 /*
27446 ** Try to deduce the type of file for zName based on its content. Return
27447 ** one of the SHELL_OPEN_* constants.
27448 **
@@ -27206,24 +27452,16 @@
27452 ** the type cannot be determined from content.
27453 */
27454 int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
27455 FILE *f;
27456 size_t n;
 
 
27457 int rc = SHELL_OPEN_UNSPEC;
27458 char zBuf[100];
27459 if( access(zName,0)!=0 ) goto database_type_by_name;
27460 if( isDatabaseFile(zName, openFlags) ){
 
 
 
 
27461 rc = SHELL_OPEN_NORMAL;
27462 }
 
 
27463 if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
27464 f = sqlite3_fopen(zName, "rb");
27465 if( f==0 ) goto database_type_by_name;
27466 n = fread(zBuf, 16, 1, f);
27467 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
@@ -27253,10 +27491,39 @@
27491 }else{
27492 rc = SHELL_OPEN_NORMAL;
27493 }
27494 return rc;
27495 }
27496
27497 /*
27498 ** If the text in z[] is the name of a readable file and that file appears
27499 ** to contain SQL text and/or dot-commands, then return true. If z[] is
27500 ** not a file, or if the file is unreadable, or if the file is a database
27501 ** or anything else that is not SQL text and dot-commands, then return false.
27502 **
27503 ** If the bLeaveUninit flag is set, then be sure to leave SQLite in an
27504 ** uninitialized state. This means invoking sqlite3_shutdown() after any
27505 ** SQLite API is used.
27506 **
27507 ** Some amount of guesswork is involved in this decision.
27508 */
27509 static int isScriptFile(const char *z, int bLeaveUninit){
27510 sqlite3_int64 sz = fileSize(z);
27511 if( sz<=0 ) return 0;
27512 if( (sz%512)==0 ){
27513 int rc;
27514 sqlite3_initialize();
27515 rc = isDatabaseFile(z, SQLITE_OPEN_READONLY);
27516 if( bLeaveUninit ){
27517 sqlite3_shutdown();
27518 }
27519 if( rc ) return 0; /* Is a database */
27520 }
27521 if( sqlite3_strlike("%.sql",z,0)==0 ) return 1;
27522 if( sqlite3_strlike("%.txt",z,0)==0 ) return 1;
27523 return 0;
27524 }
27525
27526 #ifndef SQLITE_OMIT_DESERIALIZE
27527 /*
27528 ** Reconstruct an in-memory database using the output from the "dbtotxt"
27529 ** program. Read content from the file in p->aAuxDb[].zDbFilename.
@@ -27899,20 +28166,24 @@
28166 typedef struct ImportCtx ImportCtx;
28167 struct ImportCtx {
28168 const char *zFile; /* Name of the input file */
28169 FILE *in; /* Read the CSV text from this input stream */
28170 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
28171 char *zIn; /* Input text */
28172 char *z; /* Accumulated text for a field */
28173 i64 nUsed; /* Bytes of zIn[] used so far */
28174 i64 n; /* Number of bytes in z */
28175 i64 nAlloc; /* Space allocated for z[] */
28176 int nLine; /* Current line number */
28177 int nRow; /* Number of rows imported */
28178 int nErr; /* Number of errors encountered */
28179 int bNotFirst; /* True if one or more bytes already read */
28180 int cTerm; /* Character that terminated the most recent field */
28181 int cColSep; /* The column separator character. (Usually ",") */
28182 int cRowSep; /* The row separator character. (Usually "\n") */
28183 int cQEscape; /* Escape character with "...". 0 for none */
28184 int cUQEscape; /* Escape character not with "...". 0 for none */
28185 };
28186
28187 /* Clean up resourced used by an ImportCtx */
28188 static void import_cleanup(ImportCtx *p){
28189 if( p->in!=0 && p->xCloser!=0 ){
@@ -27919,13 +28190,32 @@
28190 p->xCloser(p->in);
28191 p->in = 0;
28192 }
28193 sqlite3_free(p->z);
28194 p->z = 0;
28195 if( p->zIn ){
28196 sqlite3_free(p->zIn);
28197 p->zIn = 0;
28198 }
28199 }
28200
28201 /* Read a single character of the .import input text. Return EOF
28202 ** at end-of-file.
28203 */
28204 static int import_getc(ImportCtx *p){
28205 if( p->in ){
28206 return fgetc(p->in);
28207 }else if( p->zIn && p->zIn[p->nUsed]!=0 ){
28208 return p->zIn[p->nUsed++];
28209 }else{
28210 return EOF;
28211 }
28212 }
28213
28214 /* Append a single byte to the field value begin constructed
28215 ** in the p->z[] buffer
28216 */
28217 static void import_append_char(ImportCtx *p, int c){
28218 if( p->n+1>=p->nAlloc ){
28219 p->nAlloc += p->nAlloc + 100;
28220 p->z = sqlite3_realloc64(p->z, p->nAlloc);
28221 shell_check_oom(p->z);
@@ -27937,12 +28227,12 @@
28227 ** with the option of having a separator other than ",".
28228 **
28229 ** + Input comes from p->in.
28230 ** + Store results in p->z of length p->n. Space to hold p->z comes
28231 ** from sqlite3_malloc64().
28232 ** + Use p->cColSep as the column separator. The default is ",".
28233 ** + Use p->cRowSep as the row separator. The default is "\n".
28234 ** + Keep track of the line number in p->nLine.
28235 ** + Store the character that terminates the field in p->cTerm. Store
28236 ** EOF on end-of-file.
28237 ** + Report syntax errors on stderr
28238 */
@@ -27949,23 +28239,30 @@
28239 static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
28240 int c;
28241 int cSep = (u8)p->cColSep;
28242 int rSep = (u8)p->cRowSep;
28243 p->n = 0;
28244 c = import_getc(p);
28245 if( c==EOF || seenInterrupt ){
28246 p->cTerm = EOF;
28247 return 0;
28248 }
28249 if( c=='"' ){
28250 int pc, ppc;
28251 int startLine = p->nLine;
28252 int cQuote = c;
28253 int cEsc = (u8)p->cQEscape;
28254 pc = ppc = 0;
28255 while( 1 ){
28256 c = import_getc(p);
28257 if( c==rSep ) p->nLine++;
28258 if( c==cEsc && cEsc!=0 ){
28259 c = import_getc(p);
28260 import_append_char(p, c);
28261 ppc = pc = 0;
28262 continue;
28263 }
28264 if( c==cQuote ){
28265 if( pc==cQuote ){
28266 pc = 0;
28267 continue;
28268 }
@@ -27979,11 +28276,11 @@
28276 p->cTerm = c;
28277 break;
28278 }
28279 if( pc==cQuote && c!='\r' ){
28280 cli_printf(stderr,"%s:%d: unescaped %c character\n",
28281 p->zFile, p->nLine, cQuote);
28282 }
28283 if( c==EOF ){
28284 cli_printf(stderr,"%s:%d: unterminated %c-quoted field\n",
28285 p->zFile, startLine, cQuote);
28286 p->cTerm = c;
@@ -27994,26 +28291,28 @@
28291 pc = c;
28292 }
28293 }else{
28294 /* If this is the first field being parsed and it begins with the
28295 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
28296 int cEsc = p->cUQEscape;
28297 if( (c&0xff)==0xef && p->bNotFirst==0 ){
28298 import_append_char(p, c);
28299 c = import_getc(p);
28300 if( (c&0xff)==0xbb ){
28301 import_append_char(p, c);
28302 c = import_getc(p);
28303 if( (c&0xff)==0xbf ){
28304 p->bNotFirst = 1;
28305 p->n = 0;
28306 return csv_read_one_field(p);
28307 }
28308 }
28309 }
28310 while( c!=EOF && c!=cSep && c!=rSep ){
28311 if( c==cEsc && cEsc!=0 ) c = import_getc(p);
28312 import_append_char(p, c);
28313 c = import_getc(p);
28314 }
28315 if( c==rSep ){
28316 p->nLine++;
28317 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
28318 }
@@ -28027,12 +28326,12 @@
28326 /* Read a single field of ASCII delimited text.
28327 **
28328 ** + Input comes from p->in.
28329 ** + Store results in p->z of length p->n. Space to hold p->z comes
28330 ** from sqlite3_malloc64().
28331 ** + Use p->cColSep as the column separator. The default is "\x1F".
28332 ** + Use p->cRowSep as the row separator. The default is "\x1E".
28333 ** + Keep track of the row number in p->nLine.
28334 ** + Store the character that terminates the field in p->cTerm. Store
28335 ** EOF on end-of-file.
28336 ** + Report syntax errors on stderr
28337 */
@@ -28039,18 +28338,18 @@
28338 static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
28339 int c;
28340 int cSep = (u8)p->cColSep;
28341 int rSep = (u8)p->cRowSep;
28342 p->n = 0;
28343 c = import_getc(p);
28344 if( c==EOF || seenInterrupt ){
28345 p->cTerm = EOF;
28346 return 0;
28347 }
28348 while( c!=EOF && c!=cSep && c!=rSep ){
28349 import_append_char(p, c);
28350 c = import_getc(p);
28351 }
28352 if( c==rSep ){
28353 p->nLine++;
28354 }
28355 p->cTerm = c;
@@ -30151,11 +30450,11 @@
30450 ;
30451 static const char * const zCollectVar = "\
30452 SELECT\
30453 '('||x'0a'\
30454 || group_concat(\
30455 cname||' ANY',\
30456 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
30457 ||')' AS ColsSpec \
30458 FROM (\
30459 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
30460 FROM ColNames ORDER BY cpos\
@@ -30351,19 +30650,33 @@
30650 ** USAGE: .import [OPTIONS] FILE TABLE
30651 **
30652 ** Import CSV or similar text from FILE into TABLE. If TABLE does
30653 ** not exist, it is created using the first row of FILE as the column
30654 ** names. If FILE begins with "|" then it is a command that is run
30655 ** and the output from the command is used as the input data. If
30656 ** FILE begins with "<<" followed by a label, then content is read from
30657 ** the script until the first line that matches the label.
30658 **
30659 ** The content of FILE is interpreted using RFC-4180 ("CSV") quoting
30660 ** rules unless the current mode is "ascii" or "tabs" or unless one
30661 ** the --ascii option is used.
30662 **
30663 ** The column and row separators must be single ASCII characters. If
30664 ** multiple characters or a Unicode character are specified for the
30665 ** separators, then only the first byte of the separator is used. Except,
30666 ** if the row separator is \n and the mode is not --ascii, then \r\n is
30667 ** understood as a row separator too.
30668 **
30669 ** Options:
30670 ** --ascii Do not use RFC-4180 quoting. Use \037 and \036
30671 ** as column and row separators on input, unless other
30672 ** delimiters are specified using --colsep and/or --rowsep
30673 ** --colsep CHAR Use CHAR as the column separator.
30674 ** --csv Input is standard RFC-4180 CSV.
30675 ** --esc CHAR Use CHAR as an escape character in unquoted CSV inputs.
30676 ** --qesc CHAR Use CHAR as an escape character in quoted CSV inputs.
30677 ** --rowsep CHAR Use CHAR as the row separator.
30678 ** --schema S When creating TABLE, put it in schema S
30679 ** --skip N Ignore the first N rows of input
30680 ** -v Verbose mode
30681 */
30682 static int dotCmdImport(ShellState *p){
@@ -30375,17 +30688,16 @@
30688 sqlite3_stmt *pStmt = NULL; /* A statement */
30689 int nCol; /* Number of columns in the table */
30690 i64 nByte; /* Number of bytes in an SQL string */
30691 int i, j; /* Loop counters */
30692 int needCommit; /* True to COMMIT or ROLLBACK at end */
 
30693 char *zSql = 0; /* An SQL statement */
30694 ImportCtx sCtx; /* Reader context */
30695 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
30696 int eVerbose = 0; /* Larger for more console output */
30697 i64 nSkip = 0; /* Initial lines to skip */
30698 i64 iLineOffset = 0; /* Offset to the first line of input */
30699 char *zCreate = 0; /* CREATE TABLE statement text */
30700 int rc; /* Result code */
30701
30702 failIfSafeMode(p, "cannot run .import in safe mode");
30703 memset(&sCtx, 0, sizeof(sCtx));
@@ -30411,70 +30723,71 @@
30723 }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
30724 zSchema = azArg[++i];
30725 }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
30726 nSkip = integerValue(azArg[++i]);
30727 }else if( cli_strcmp(z,"-ascii")==0 ){
30728 if( sCtx.cColSep==0 ) sCtx.cColSep = SEP_Unit[0];
30729 if( sCtx.cRowSep==0 ) sCtx.cRowSep = SEP_Record[0];
30730 xRead = ascii_read_one_field;
 
30731 }else if( cli_strcmp(z,"-csv")==0 ){
30732 if( sCtx.cColSep==0 ) sCtx.cColSep = ',';
30733 if( sCtx.cRowSep==0 ) sCtx.cRowSep = '\n';
30734 xRead = csv_read_one_field;
30735 }else if( cli_strcmp(z,"-esc")==0 ){
30736 sCtx.cUQEscape = azArg[++i][0];
30737 }else if( cli_strcmp(z,"-qesc")==0 ){
30738 sCtx.cQEscape = azArg[++i][0];
30739 }else if( cli_strcmp(z,"-colsep")==0 ){
30740 if( i==nArg-1 ){
30741 dotCmdError(p, i, "missing argument", 0);
30742 return 1;
30743 }
30744 i++;
30745 sCtx.cColSep = azArg[i][0];
30746 }else if( cli_strcmp(z,"-rowsep")==0 ){
30747 if( i==nArg-1 ){
30748 dotCmdError(p, i, "missing argument", 0);
30749 return 1;
30750 }
30751 i++;
30752 sCtx.cRowSep = azArg[i][0];
30753 }else{
30754 dotCmdError(p, i, "unknown option", 0);
30755 return 1;
30756 }
30757 }
30758 if( zTable==0 ){
30759 dotCmdError(p, nArg, 0, "Missing %s argument\n",
30760 zFile==0 ? "FILE" : "TABLE");
30761 return 1;
30762 }
30763 seenInterrupt = 0;
30764 open_db(p, 0);
30765 if( sCtx.cColSep==0 ){
30766 if( p->mode.spec.zColumnSep && p->mode.spec.zColumnSep[0]!=0 ){
30767 sCtx.cColSep = p->mode.spec.zColumnSep[0];
30768 }else{
30769 sCtx.cColSep = ',';
30770 }
30771 }
30772 if( (sCtx.cColSep & 0x80)!=0 ){
30773 eputz("Error: .import column separator must be ASCII\n");
30774 return 1;
30775 }
30776 if( sCtx.cRowSep==0 ){
30777 if( p->mode.spec.zRowSep && p->mode.spec.zRowSep[0]!=0 ){
30778 sCtx.cRowSep = p->mode.spec.zRowSep[0];
30779 }else{
30780 sCtx.cRowSep = '\n';
30781 }
30782 }
30783 if( sCtx.cRowSep=='\r' && xRead!=ascii_read_one_field ){
30784 sCtx.cRowSep = '\n';
30785 }
30786 if( (sCtx.cRowSep & 0x80)!=0 ){
30787 eputz("Error: .import row separator must be ASCII\n");
30788 return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30789 }
30790 sCtx.zFile = zFile;
30791 sCtx.nLine = 1;
30792 if( sCtx.zFile[0]=='|' ){
30793 #ifdef SQLITE_OMIT_POPEN
@@ -30483,19 +30796,58 @@
30796 #else
30797 sCtx.in = sqlite3_popen(sCtx.zFile+1, "r");
30798 sCtx.zFile = "<pipe>";
30799 sCtx.xCloser = pclose;
30800 #endif
30801 }else if( sCtx.zFile[0]=='<' && sCtx.zFile[1]=='<' && sCtx.zFile[2]!=0 ){
30802 /* Input text comes from subsequent lines of script until the zFile
30803 ** delimiter */
30804 int nEndMark = strlen30(zFile)-2;
30805 char *zEndMark = &zFile[2];
30806 sqlite3_str *pContent = sqlite3_str_new(p->db);
30807 int ckEnd = 1;
30808 i64 iStart = p->lineno;
30809 char zLine[2000];
30810 sCtx.zFile = p->zInFile;
30811 sCtx.nLine = p->lineno+1;
30812 iLineOffset = p->lineno;
30813 while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
30814 if( ckEnd && cli_strncmp(zLine,zEndMark,nEndMark)==0 ){
30815 ckEnd = 2;
30816 if( strchr(zLine,'\n') ) p->lineno++;
30817 break;
30818 }
30819 if( strchr(zLine,'\n') ){
30820 p->lineno++;
30821 ckEnd = 1;
30822 }else{
30823 ckEnd = 0;
30824 }
30825 sqlite3_str_appendall(pContent, zLine);
30826 }
30827 sCtx.zIn = sqlite3_str_finish(pContent);
30828 if( sCtx.zIn==0 ){
30829 sCtx.zIn = sqlite3_mprintf("");
30830 }
30831 if( ckEnd<2 ){
30832 i64 savedLn = p->lineno;
30833 p->lineno = iStart;
30834 dotCmdError(p, 0, 0,"Content terminator \"%s\" not found.",zEndMark);
30835 p->lineno = savedLn;
30836 import_cleanup(&sCtx);
30837 return 1;
30838 }
30839 }else{
30840 sCtx.in = sqlite3_fopen(sCtx.zFile, "rb");
30841 sCtx.xCloser = fclose;
30842 }
30843 if( sCtx.in==0 && sCtx.zIn==0 ){
30844 dotCmdError(p, 0, 0, "cannot open \"%s\"", zFile);
30845 import_cleanup(&sCtx);
30846 return 1;
30847 }
30848 if( eVerbose>=1 ){
30849 char zSep[2];
30850 zSep[1] = 0;
30851 zSep[0] = sCtx.cColSep;
30852 cli_puts("Column separator ", p->out);
30853 output_c_string(p->out, zSep);
@@ -30648,10 +31000,14 @@
31000 if( z==0 && (xRead==csv_read_one_field) && i==nCol-1 && i>0 ){
31001 z = "";
31002 }
31003 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
31004 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
31005 if( i==0 && (strcmp(z,"\n")==0 || strcmp(z,"\r\n")==0) ){
31006 /* Ignore trailing \n or \r\n when some other row separator */
31007 break;
31008 }
31009 cli_printf(stderr,"%s:%d: expected %d columns but found %d"
31010 " - filling the rest with NULL\n",
31011 sCtx.zFile, startLine, nCol, i+1);
31012 i += 2;
31013 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
@@ -30671,10 +31027,11 @@
31027 rc = sqlite3_reset(pStmt);
31028 if( rc!=SQLITE_OK ){
31029 cli_printf(stderr,"%s:%d: INSERT failed: %s\n",
31030 sCtx.zFile, startLine, sqlite3_errmsg(p->db));
31031 sCtx.nErr++;
31032 if( bail_on_error ) break;
31033 }else{
31034 sCtx.nRow++;
31035 }
31036 }
31037 }while( sCtx.cTerm!=EOF );
@@ -30683,13 +31040,13 @@
31040 sqlite3_finalize(pStmt);
31041 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
31042 if( eVerbose>0 ){
31043 cli_printf(p->out,
31044 "Added %d rows with %d errors using %d lines of input\n",
31045 sCtx.nRow, sCtx.nErr, sCtx.nLine-1-iLineOffset);
31046 }
31047 return sCtx.nErr ? 1 : 0;
31048 }
31049
31050
31051 /*
31052 ** This function computes what to show the user about the configured
@@ -31100,10 +31457,11 @@
31457 if( k<0 ){
31458 dotCmdError(p, i, "bad --titles value","%z", zErr);
31459 return 1;
31460 }
31461 p->mode.spec.bTitles = k>=1 ? QRF_Yes : QRF_No;
31462 p->mode.mFlags &= ~MFLG_HDR;
31463 p->mode.spec.eTitle = k>1 ? k-1 : aModeInfo[p->mode.eMode].eHdr;
31464 chng = 1;
31465 }else if( optionMatch(z,"widths") || optionMatch(z,"width") ){
31466 int nWidth = 0;
31467 short int *aWidth;
@@ -31328,23 +31686,17 @@
31686 ** --bom Prepend a byte-order mark to the output
31687 ** -e Accumulate output in a temporary text file then
31688 ** launch a text editor when the redirection ends.
31689 ** --error-prefix X Use X as the left-margin prefix for error messages.
31690 ** Set to an empty string to restore the default.
31691 ** --keep Keep redirecting output to its current destination.
31692 ** Use this option in combination with --show or
31693 ** with --error-prefix when you do not want to stop
31694 ** a current redirection.
 
 
 
31695 ** --plain Use plain text rather than HTML tables with -w
31696 ** --show Show output text captured by .testcase or by
31697 ** redirecting to "memory".
 
 
 
31698 ** -w Show the output in a web browser. Output is
31699 ** written into a temporary HTML file until the
31700 ** redirect ends, then the web browser is launched.
31701 ** Query results are shown as HTML tables, unless
31702 ** the --plain is used too.
@@ -31382,13 +31734,11 @@
31734 char *zFile = 0; /* The FILE argument */
31735 int i; /* Loop counter */
31736 int eMode = 0; /* 0: .outout/.once, 'x'=.excel, 'w'=.www */
31737 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel/.www */
31738 int bPlain = 0; /* --plain option */
31739 int bKeep = 0; /* Keep redirecting */
 
 
31740 static const char *zBomUtf8 = "\357\273\277";
31741 const char *zBom = 0;
31742 char c = azArg[0][0];
31743 int n = strlen30(azArg[0]);
31744
@@ -31410,36 +31760,21 @@
31760 zBom = zBomUtf8;
31761 }else if( cli_strcmp(z,"-plain")==0 ){
31762 bPlain = 1;
31763 }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
31764 && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
31765 if( bKeep || eMode ){
31766 dotCmdError(p, i, "incompatible with prior options",0);
31767 goto dotCmdOutput_error;
31768 }
31769 eMode = z[1];
 
 
31770 }else if( cli_strcmp(z,"-show")==0 ){
31771 if( cli_output_capture ){
31772 sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31773 }
31774 }else if( cli_strcmp(z,"-keep")==0 ){
31775 bKeep = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31776 }else if( optionMatch(z,"error-prefix") ){
31777 if( i+1>=nArg ){
31778 dotCmdError(p, i, "missing argument", 0);
31779 return 1;
31780 }
@@ -31450,11 +31785,11 @@
31785 dotCmdError(p, i, "unknown option", 0);
31786 sqlite3_free(zFile);
31787 return 1;
31788 }
31789 }else if( zFile==0 && eMode==0 ){
31790 if( bKeep ){
31791 dotCmdError(p, i, "incompatible with prior options",0);
31792 goto dotCmdOutput_error;
31793 }
31794 if( cli_strcmp(z, "memory")==0 && bOnce ){
31795 dotCmdError(p, 0, "cannot redirect to \"memory\"", 0);
@@ -31486,53 +31821,10 @@
31821 if( bOnce ){
31822 p->nPopOutput = 2;
31823 }else{
31824 p->nPopOutput = 0;
31825 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31826 if( !bKeep ) output_reset(p);
31827 #ifndef SQLITE_NOHAVE_SYSTEM
31828 if( eMode=='e' || eMode=='x' || eMode=='w' ){
31829 p->doXdgOpen = 1;
31830 modePush(p);
@@ -31609,10 +31901,199 @@
31901
31902 dotCmdOutput_error:
31903 sqlite3_free(zFile);
31904 return 1;
31905 }
31906
31907 /*
31908 ** DOT-COMMAND: .check
31909 ** USAGE: .check [OPTIONS] PATTERN
31910 **
31911 ** Verify results of commands since the most recent .testcase command.
31912 ** Restore output to the console, unless --keep is used.
31913 **
31914 ** If PATTERN starts with "<<ENDMARK" then the actual pattern is taken from
31915 ** subsequent lines of text up to the first line that begins with ENDMARK.
31916 ** All pattern lines and the ENDMARK are discarded.
31917 **
31918 ** Options:
31919 ** --exact Do an exact comparison including leading and
31920 ** trailing whitespace.
31921 ** --glob Treat PATTERN as a GLOB
31922 ** --keep Do not reset the testcase. More .check commands
31923 ** will follow.
31924 ** --notglob Output should not match PATTERN
31925 ** --show Write testcase output to the screen, for debugging.
31926 */
31927 static int dotCmdCheck(ShellState *p){
31928 int nArg = p->dot.nArg; /* Number of arguments */
31929 char **azArg = p->dot.azArg; /* Text of the arguments */
31930 int i; /* Loop counter */
31931 int k; /* Result of pickStr() */
31932 char *zTest; /* Textcase result */
31933 int bKeep = 0; /* --keep option */
31934 char *zCheck = 0; /* PATTERN argument */
31935 char *zPattern = 0; /* Actual test pattern */
31936 int eCheck = 0; /* 1: --glob, 2: --notglob, 3: --exact */
31937 int isOk; /* True if results are OK */
31938 sqlite3_int64 iStart = p->lineno; /* Line number of .check statement */
31939
31940 if( p->zTestcase[0]==0 ){
31941 dotCmdError(p, 0, "no .testcase is active", 0);
31942 return 1;
31943 }
31944 for(i=1; i<nArg; i++){
31945 char *z = azArg[i];
31946 if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
31947 if( cli_strcmp(z,"-keep")==0 ){
31948 bKeep = 1;
31949 }else if( cli_strcmp(z,"-show")==0 ){
31950 if( cli_output_capture ){
31951 sqlite3_fprintf(stdout, "%s", sqlite3_str_value(cli_output_capture));
31952 }
31953 bKeep = 1;
31954 }else if( z[0]=='-'
31955 && (k = pickStr(&z[1],0,"glob","notglob","exact",""))>=0
31956 ){
31957 if( eCheck && eCheck!=k+1 ){
31958 dotCmdError(p, i, "incompatible with prior options",0);
31959 return 1;
31960 }
31961 eCheck = k+1;
31962 }else if( zCheck ){
31963 dotCmdError(p, i, "unknown option", 0);
31964 return 1;
31965 }else{
31966 zCheck = azArg[i];
31967 }
31968 }
31969 if( zCheck==0 ){
31970 dotCmdError(p, 0, "no PATTERN specified", 0);
31971 return 1;
31972 }
31973 if( cli_output_capture && sqlite3_str_length(cli_output_capture) ){
31974 zTest = sqlite3_str_value(cli_output_capture);
31975 shell_check_oom(zTest);
31976 }else{
31977 zTest = "";
31978 }
31979 p->nTestRun++;
31980 if( zCheck[0]=='<' && zCheck[1]=='<' && zCheck[2]!=0 ){
31981 int nCheck = strlen30(zCheck);
31982 sqlite3_str *pPattern = sqlite3_str_new(p->db);
31983 char zLine[2000];
31984 while( sqlite3_fgets(zLine,sizeof(zLine),p->in) ){
31985 if( strchr(zLine,'\n') ) p->lineno++;
31986 if( cli_strncmp(&zCheck[2],zLine,nCheck-2)==0 ) break;
31987 sqlite3_str_appendall(pPattern, zLine);
31988 }
31989 zPattern = sqlite3_str_finish(pPattern);
31990 if( zPattern==0 ){
31991 zPattern = sqlite3_mprintf("");
31992 }
31993 }else{
31994 zPattern = zCheck;
31995 }
31996 shell_check_oom(zPattern);
31997 switch( eCheck ){
31998 case 1: {
31999 char *zGlob = sqlite3_mprintf("*%s*", zPattern);
32000 isOk = testcase_glob(zGlob, zTest)!=0;
32001 sqlite3_free(zGlob);
32002 break;
32003 }
32004 case 2: {
32005 char *zGlob = sqlite3_mprintf("*%s*", zPattern);
32006 isOk = testcase_glob(zGlob, zTest)==0;
32007 sqlite3_free(zGlob);
32008 break;
32009 }
32010 case 3: {
32011 isOk = cli_strcmp(zTest,zPattern)==0;
32012 break;
32013 }
32014 default: {
32015 /* Skip leading and trailing \n and \r on both pattern and test output */
32016 const char *z1 = zPattern;
32017 const char *z2 = zTest;
32018 size_t n1, n2;
32019 while( z1[0]=='\n' || z1[0]=='\r' ) z1++;
32020 n1 = strlen(z1);
32021 while( n1>0 && (z1[n1-1]=='\n' || z1[n1-1]=='\r') ) n1--;
32022 while( z2[0]=='\n' || z2[0]=='\r' ) z2++;
32023 n2 = strlen(z2);
32024 while( n2>0 && (z2[n2-1]=='\n' || z2[n2-1]=='\r') ) n2--;
32025 isOk = n1==n2 && memcmp(z1,z2,n1)==0;
32026 break;
32027 }
32028 }
32029 if( !isOk ){
32030 sqlite3_fprintf(stderr,
32031 "%s:%lld: .check failed for testcase %s\n",
32032 p->zInFile, iStart, p->zTestcase);
32033 p->nTestErr++;
32034 sqlite3_fprintf(stderr, "Expected: [%s]\n", zPattern);
32035 sqlite3_fprintf(stderr, "Got: [%s]\n", zTest);
32036 }
32037 if( zPattern!=zCheck ){
32038 sqlite3_free(zPattern);
32039 }
32040 if( !bKeep ){
32041 output_reset(p);
32042 p->zTestcase[0] = 0;
32043 }
32044 return 0;
32045 }
32046
32047 /*
32048 ** DOT-COMMAND: .testcase
32049 ** USAGE: .testcase [OPTIONS] NAME
32050 **
32051 ** Start a new test case identified by NAME. All output
32052 ** through the next ".check" command is captured for comparison. See the
32053 ** ".check" commandn for additional informatioon.
32054 **
32055 ** Options:
32056 ** --error-prefix TEXT Change error message prefix text to TEXT
32057 */
32058 static int dotCmdTestcase(ShellState *p){
32059 int nArg = p->dot.nArg; /* Number of arguments */
32060 char **azArg = p->dot.azArg; /* Text of the arguments */
32061 int i; /* Loop counter */
32062 const char *zName = 0; /* Testcase name */
32063
32064 for(i=1; i<nArg; i++){
32065 char *z = azArg[i];
32066 if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
32067 if( optionMatch(z,"error-prefix") ){
32068 if( i+1>=nArg ){
32069 dotCmdError(p, i, "missing argument", 0);
32070 return 1;
32071 }
32072 free(p->zErrPrefix);
32073 i++;
32074 p->zErrPrefix = azArg[i][0]==0 ? 0 : strdup(azArg[i]);
32075 }else if( zName ){
32076 dotCmdError(p, i, "unknown option", 0);
32077 return 1;
32078 }else{
32079 zName = azArg[i];
32080 }
32081 }
32082 output_reset(p);
32083 if( cli_output_capture ){
32084 sqlite3_str_free(cli_output_capture);
32085 }
32086 cli_output_capture = sqlite3_str_new(0);
32087 if( zName ){
32088 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", zName);
32089 }else{
32090 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s:%lld",
32091 p->zInFile, p->lineno);
32092 }
32093 return 0;
32094 }
32095
32096 /*
32097 ** Enlarge the space allocated in p->dot so that it can hold more
32098 ** than nArg parsed command-line arguments.
32099 */
@@ -31641,11 +32122,11 @@
32122 free(p->dot.zCopy);
32123 z = p->dot.zCopy = strdup(zLine);
32124 shell_check_oom(z);
32125 szLine = strlen(z);
32126 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
32127 if( szLine>0 && z[szLine-1]==';' ){
32128 szLine--;
32129 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
32130 }
32131 z[szLine] = 0;
32132 parseDotRealloc(p, 2);
@@ -31861,35 +32342,17 @@
32342 eputz("Usage: .changes on|off\n");
32343 rc = 1;
32344 }
32345 }else
32346
 
32347 /* Cancel output redirection, if it is currently set (by .testcase)
32348 ** Then read the content of the testcase-out.txt file and compare against
32349 ** azArg[1]. If there are differences, report an error and exit.
32350 */
32351 if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
32352 rc = dotCmdCheck(p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32353 }else
 
32354
32355 #ifndef SQLITE_SHELL_FIDDLE
32356 if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
32357 failIfSafeMode(p, "cannot run .clone in safe mode");
32358 if( nArg==2 ){
@@ -32468,10 +32931,11 @@
32931 }else
32932
32933 if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
32934 if( nArg==2 ){
32935 p->mode.spec.bTitles = booleanValue(azArg[1]) ? QRF_Yes : QRF_No;
32936 p->mode.mFlags |= MFLG_HDR;
32937 p->mode.spec.eTitle = aModeInfo[p->mode.eMode].eHdr;
32938 }else{
32939 eputz("Usage: .headers on|off\n");
32940 rc = 1;
32941 }
@@ -32521,14 +32985,14 @@
32985 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
32986 goto meta_command_exit;
32987 }
32988 zSql = sqlite3_mprintf(
32989 "SELECT rootpage, 0 FROM sqlite_schema"
32990 " WHERE type='index' AND lower(name)=lower('%q')"
32991 "UNION ALL "
32992 "SELECT rootpage, 1 FROM sqlite_schema"
32993 " WHERE type='table' AND lower(name)=lower('%q')"
32994 " AND sql LIKE '%%without%%rowid%%'",
32995 azArg[1], azArg[1]
32996 );
32997 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
32998 sqlite3_free(zSql);
@@ -32682,13 +33146,14 @@
33146 goto meta_command_exit;
33147 }
33148 if( nArg==3 ){
33149 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
33150 (int)integerValue(azArg[2]));
33151 }else{
33152 cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
33153 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
33154 }
 
 
33155 }
33156 }else
33157
33158 if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
33159 open_db(p, 0);
@@ -33027,10 +33492,23 @@
33492 continue;
33493 }
33494 if( cli_strcmp(z,"once")==0 ){
33495 p->flgProgress |= SHELL_PROGRESS_ONCE;
33496 continue;
33497 }
33498 if( cli_strcmp(z,"timeout")==0 ){
33499 if( i==nArg-1 ){
33500 dotCmdError(p, i, "missing argument", 0);
33501 return 1;
33502 }
33503 i++;
33504 p->tmProgress = atof(azArg[i]);
33505 if( p->tmProgress>0.0 ){
33506 p->flgProgress = SHELL_PROGRESS_QUIET|SHELL_PROGRESS_TMOUT;
33507 if( nn==0 ) nn = 100;
33508 }
33509 continue;
33510 }
33511 if( cli_strcmp(z,"limit")==0 ){
33512 if( i+1>=nArg ){
33513 eputz("Error: missing argument on --limit\n");
33514 rc = 1;
@@ -33233,21 +33711,22 @@
33711 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
33712 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
33713 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
33714 if( isSchema ){
33715 cli_printf(p->out,
33716 "CREATE TABLE %ssqlite_schema (\n"
33717 " type text,\n"
33718 " name text,\n"
33719 " tbl_name text,\n"
33720 " rootpage integer,\n"
33721 " sql text\n"
33722 ");\n",
33723 sqlite3_strlike("sqlite_t%",zName,0)==0 ? "temp." : ""
33724 );
33725 }
33726 }
33727 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
 
33728 if( rc ){
33729 shellDatabaseError(p->db);
33730 sqlite3_finalize(pStmt);
33731
33732 rc = 1;
@@ -33255,11 +33734,11 @@
33734 }
33735 pSql = sqlite3_str_new(p->db);
33736 sqlite3_str_appendf(pSql, "SELECT sql FROM", 0);
33737 iSchema = 0;
33738 while( sqlite3_step(pStmt)==SQLITE_ROW ){
33739 const char *zDb = (const char*)sqlite3_column_text(pStmt, 1);
33740 char zScNum[30];
33741 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
33742 sqlite3_str_appendall(pSql, zDiv);
33743 zDiv = " UNION ALL ";
33744 if( sqlite3_stricmp(zDb, "main")==0 ){
@@ -33275,11 +33754,12 @@
33754 " AS sql, type, tbl_name, name, rowid, %d AS snum, %Q as sname",
33755 ++iSchema, zDb);
33756 sqlite3_str_appendf(pSql," FROM \"%w\".sqlite_schema", zDb);
33757 }
33758 sqlite3_finalize(pStmt);
33759 #if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) \
33760 && !defined(SQLITE_OMIT_VIRTUALTABLE)
33761 if( zName ){
33762 sqlite3_str_appendall(pSql,
33763 " UNION ALL SELECT shell_module_schema(name),"
33764 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list");
33765 }
@@ -33299,11 +33779,11 @@
33779 }else{
33780 sqlite3_str_appendf(pSql, " LIKE %Q ESCAPE '\\' AND ", zName);
33781 }
33782 }
33783 if( bNoSystemTabs ){
33784 sqlite3_str_appendf(pSql, " name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ");
33785 }
33786 sqlite3_str_appendf(pSql, "sql IS NOT NULL ORDER BY snum, rowid");
33787 if( bDebug ){
33788 cli_printf(p->out, "SQL: %s;\n", sqlite3_str_value(pSql));
33789 }else{
@@ -34017,25 +34497,15 @@
34497 sqlite3_str_free(pSql);
34498 modePop(p);
34499 if( rc ) return shellDatabaseError(p->db);
34500 }else
34501
34502 /* Set the p->zTestcase name and begin redirecting output into
34503 ** the cli_output_capture sqlite3_str */
34504 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
34505 rc = dotCmdTestcase(p);
 
 
 
 
 
 
 
 
 
34506 }else
 
34507
34508 #ifndef SQLITE_UNTESTABLE
34509 if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
34510 static const struct {
34511 const char *zCtrlName; /* Name of a test-control option */
@@ -34527,17 +34997,21 @@
34997 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
34998 }else
34999
35000 if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
35001 if( nArg==2 ){
35002 if( cli_strcmp(azArg[1],"once")==0 ){
35003 p->enableTimer = 1;
35004 }else{
35005 p->enableTimer = 2*booleanValue(azArg[1]);
35006 }
35007 if( p->enableTimer && !HAS_TIMER ){
35008 eputz("Error: timer not available on this system.\n");
35009 p->enableTimer = 0;
35010 }
35011 }else{
35012 eputz("Usage: .timer on|off|once\n");
35013 rc = 1;
35014 }
35015 }else
35016
35017 #ifndef SQLITE_OMIT_TRACE
@@ -34708,10 +35182,11 @@
35182 if( p->nPopOutput ){
35183 p->nPopOutput--;
35184 if( p->nPopOutput==0 ) output_reset(p);
35185 }
35186 p->bSafeMode = p->bSafeModePersist;
35187 p->dot.nArg = 0;
35188 return rc;
35189 }
35190
35191 /* Line scan result and intermediate states (supporting scan resumption)
35192 */
@@ -34944,13 +35419,13 @@
35419 char *zErrMsg = 0;
35420
35421 open_db(p, 0);
35422 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
35423 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
35424 BEGIN_TIMER(p);
35425 rc = shell_exec(p, zSql, &zErrMsg);
35426 END_TIMER(p);
35427 if( rc || zErrMsg ){
35428 char zPrefix[100];
35429 const char *zErrorTail;
35430 const char *zErrorType;
35431 if( zErrMsg==0 ){
@@ -35351,11 +35826,10 @@
35826 " -bail stop after hitting an error\n"
35827 " -batch force batch I/O\n"
35828 " -box set output mode to 'box'\n"
35829 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
35830 " -column set output mode to 'column'\n"
 
35831 " -csv set output mode to 'csv'\n"
35832 #if !defined(SQLITE_OMIT_DESERIALIZE)
35833 " -deserialize open the database using sqlite3_deserialize()\n"
35834 #endif
35835 " -echo print inputs before execution\n"
@@ -35435,15 +35909,10 @@
35909 /*
35910 ** Initialize the state information in data
35911 */
35912 static void main_init(ShellState *p) {
35913 memset(p, 0, sizeof(*p));
 
 
 
 
 
35914 p->pAuxDb = &p->aAuxDb[0];
35915 p->shellFlgs = SHFLG_Lookaside;
35916 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, p);
35917 #if !defined(SQLITE_SHELL_FIDDLE)
35918 verify_uninitialized();
@@ -35498,29 +35967,65 @@
35967 cli_puts(z, p->out);
35968 fflush(p->out);
35969 return 1;
35970 }
35971
35972 /* Alternative name to the entry point for Fiddle */
 
 
 
 
 
 
 
 
35973 #ifdef SQLITE_SHELL_FIDDLE
35974 # define main fiddle_main
35975 #endif
35976
35977 /* Use the wmain() entry point on Windows. Translate arguments to
35978 ** UTF8, then invoke the traditional main() entry point which is
35979 ** renamed using a #define to utf8_main() .
35980 */
35981 #if defined(_WIN32) && !defined(main)
35982 # define main utf8_main /* Rename entry point to utf_main() */
35983 int SQLITE_CDECL utf8_main(int,char**); /* Forward declaration */
35984 int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
35985 int rc, i;
35986 char **argv = malloc( sizeof(char*) * (argc+1) );
35987 char **orig = argv;
35988 if( argv==0 ){
35989 fprintf(stderr, "malloc failed\n");
35990 exit(1);
35991 }
35992 for(i=0; i<argc; i++){
35993 int nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0);
35994 if( nByte==0 ){
35995 argv[i] = 0;
35996 }else{
35997 argv[i] = malloc( nByte );
35998 if( argv[i]==0 ){
35999 fprintf(stderr, "malloc failed\n");
36000 exit(1);
36001 }
36002 nByte = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i],nByte,0,0);
36003 if( nByte==0 ){
36004 free(argv[i]);
36005 argv[i] = 0;
36006 }
36007 }
36008 }
36009 argv[argc] = 0;
36010 rc = utf8_main(argc, argv);
36011 for(i=0; i<argc; i++) free(orig[i]);
36012 free(argv);
36013 return rc;
36014 }
36015 #endif /* WIN32 */
36016
36017 /*
36018 ** This is the main entry point for the process. Everything starts here.
36019 **
36020 ** The "main" identifier may have been #defined to something else:
36021 **
36022 ** utf8_main On Windows
36023 ** fiddle_main In Fiddle
36024 ** sqlite3_shell Other projects that use shell.c as a subroutine
36025 */
36026 int SQLITE_CDECL main(int argc, char **argv){
36027 #ifdef SQLITE_DEBUG
36028 sqlite3_int64 mem_main_enter = 0;
36029 #endif
36030 char *zErrMsg = 0;
36031 #ifdef SQLITE_SHELL_FIDDLE
@@ -35538,14 +36043,10 @@
36043 int nOptsEnd = argc;
36044 int bEnableVfstrace = 0;
36045 char **azCmd = 0;
36046 int *aiCmd = 0;
36047 const char *zVfs = 0; /* Value of -vfs command-line option */
 
 
 
 
36048 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
36049
36050 #ifdef SQLITE_SHELL_FIDDLE
36051 stdin_is_interactive = 0;
36052 stdout_is_console = 1;
@@ -35596,36 +36097,10 @@
36097 exit(1);
36098 }
36099 #endif
36100 main_init(&data);
36101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36102 assert( argc>=1 && argv && argv[0] );
36103 Argv0 = argv[0];
36104
36105 #ifdef SQLITE_SHELL_DBNAME_PROC
36106 {
@@ -35637,11 +36112,11 @@
36112 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
36113 warnInmemoryDb = 0;
36114 }
36115 #endif
36116
36117 /* Do an initial pass through the command-line arguments to locate
36118 ** the name of the database file, the name of the initialization file,
36119 ** the size of the alternative malloc heap, options affecting commands
36120 ** or SQL run from the command line, and the first command to execute.
36121 */
36122 #ifndef SQLITE_SHELL_FIDDLE
@@ -35649,11 +36124,11 @@
36124 #endif
36125 for(i=1; i<argc; i++){
36126 char *z;
36127 z = argv[i];
36128 if( z[0]!='-' || i>nOptsEnd ){
36129 if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){
36130 data.aAuxDb->zDbFilename = z;
36131 }else{
36132 /* Excess arguments are interpreted as SQL (or dot-commands) and
36133 ** mean that nothing is read from stdin */
36134 readStdin = 0;
@@ -35694,15 +36169,10 @@
36169 if( n<2 ){
36170 sqlite3_fprintf(stderr,"minimum --screenwidth is 2\n");
36171 exit(1);
36172 }
36173 stdout_tty_width = n;
 
 
 
 
 
36174 }else if( cli_strcmp(z,"-utf8")==0 ){
36175 }else if( cli_strcmp(z,"-no-utf8")==0 ){
36176 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
36177 int val = 0;
36178 sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW, &val);
@@ -35822,10 +36292,20 @@
36292 }else if( cli_strcmp(z,"-safe")==0 ){
36293 /* no-op - catch this on the second pass */
36294 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
36295 /* skip over the argument */
36296 i++;
36297 }else if( cli_strcmp(z,"-test-argv")==0 ){
36298 /* Undocumented test option. Print the values in argv[] and exit.
36299 ** Use this to verify that any translation of the argv[], for example
36300 ** on Windows that receives wargv[] from the OS and must convert
36301 ** to UTF8 prior to calling this routine. */
36302 int kk;
36303 for(kk=0; kk<argc; kk++){
36304 sqlite3_fprintf(stdout,"argv[%d] = \"%s\"\n", kk, argv[kk]);
36305 }
36306 return 0;
36307 }
36308 }
36309 #ifndef SQLITE_SHELL_FIDDLE
36310 if( !bEnableVfstrace ) verify_uninitialized();
36311 #endif
@@ -35848,11 +36328,30 @@
36328
36329 if( zVfs ){
36330 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
36331 if( pVfs ){
36332 sqlite3_vfs_register(pVfs, 1);
36333 }
36334 #if !defined(SQLITE_OMIT_LOAD_EXTENSION)
36335 else if( access(zVfs,0)==0 ){
36336 /* If the VFS name is not the name of an existing VFS, but it is
36337 ** the name of a file, then try to load that file as an extension.
36338 ** Presumably the extension implements the desired VFS. */
36339 sqlite3 *db = 0;
36340 char *zErr = 0;
36341 sqlite3_open(":memory:", &db);
36342 sqlite3_enable_load_extension(db, 1);
36343 rc = sqlite3_load_extension(db, zVfs, 0, &zErr);
36344 sqlite3_close(db);
36345 if( (rc&0xff)!=SQLITE_OK ){
36346 cli_printf(stderr, "could not load extension VFS \"%s\": %s\n",
36347 zVfs, zErr);
36348 exit(1);
36349 }
36350 }
36351 #endif
36352 else{
36353 cli_printf(stderr,"no such VFS: \"%s\"\n", zVfs);
36354 exit(1);
36355 }
36356 }
36357
@@ -35889,11 +36388,11 @@
36388 ** is given on the command line, look for a file named ~/.sqliterc and
36389 ** try to process it.
36390 */
36391 if( !noInit ) process_sqliterc(&data,zInitFile);
36392
36393 /* Make a second pass through the command-line arguments and set
36394 ** options. This second pass is delayed until after the initialization
36395 ** file is processed so that the command-line arguments will override
36396 ** settings in the initialization file.
36397 */
36398 for(i=1; i<argc; i++){
@@ -36015,12 +36514,10 @@
36514 stdin_is_interactive = 1;
36515 }else if( cli_strcmp(z,"-batch")==0 ){
36516 /* already handled */
36517 }else if( cli_strcmp(z,"-screenwidth")==0 ){
36518 i++;
 
 
36519 }else if( cli_strcmp(z,"-utf8")==0 ){
36520 /* already handled */
36521 }else if( cli_strcmp(z,"-no-utf8")==0 ){
36522 /* already handled */
36523 }else if( cli_strcmp(z,"-no-rowid-in-view")==0 ){
@@ -36116,11 +36613,22 @@
36613 ** command-line inputs, except for the argToSkip argument which contains
36614 ** the database filename.
36615 */
36616 for(i=0; i<nCmd; i++){
36617 echo_group_input(&data, azCmd[i]);
36618 if( isScriptFile(azCmd[i],0) ){
36619 FILE *inSaved = data.in;
36620 i64 savedLineno = data.lineno;
36621 int res = 1;
36622 if( (data.in = openChrSource(azCmd[i]))!=0 ){
36623 res = process_input(&data, azCmd[i]);
36624 fclose(data.in);
36625 }
36626 data.in = inSaved;
36627 data.lineno = savedLineno;
36628 if( res ) i = nCmd;
36629 }else if( azCmd[i][0]=='.' ){
36630 char *zErrCtx = malloc( 64 );
36631 shell_check_oom(zErrCtx);
36632 sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
36633 data.zInFile = "<cmdline>";
36634 data.zErrPrefix = zErrCtx;
@@ -36231,14 +36739,10 @@
36739 }
36740 find_home_dir(1);
36741 output_reset(&data);
36742 data.doXdgOpen = 0;
36743 clearTempFile(&data);
 
 
 
 
36744 modeFree(&data.mode);
36745 if( data.nSavedModes ){
36746 int ii;
36747 for(ii=0; ii<data.nSavedModes; ii++){
36748 modeFree(&data.aSavedModes[ii].mode);
36749
+1112 -736
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
1616
** if you want a wrapper to interface SQLite with your choice of programming
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
**
2020
** The content in this amalgamation comes from Fossil check-in
21
-** 01409738afc2c0d5bdaa248ffb508aa5f36a with changes in files:
21
+** c476d956d0bd3065cf894de6f9d393b999ff with changes in files:
2222
**
2323
**
2424
*/
2525
#ifndef SQLITE_AMALGAMATION
2626
#define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467467
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468468
** [sqlite_version()] and [sqlite_source_id()].
469469
*/
470470
#define SQLITE_VERSION "3.52.0"
471471
#define SQLITE_VERSION_NUMBER 3052000
472
-#define SQLITE_SOURCE_ID "2025-12-11 23:24:05 01409738afc2c0d5bdaa248ffb508aa5f36a66390f6b8e4834734529ee8ed2fa"
472
+#define SQLITE_SOURCE_ID "2026-02-04 20:51:27 c476d956d0bd3065cf894de6f9d393b999ff7d2268a35f01a6d88804789ab58f"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2025-12-11T23:24:05.667Z"
475
+#define SQLITE_SCM_DATETIME "2026-02-04T20:51:27.822Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -4752,16 +4752,32 @@
47524752
** compiles to see if some SQL syntax is well-formed, without generating
47534753
** messages on the global error log when it is not. If the test compile
47544754
** fails, the sqlite3_prepare_v3() call returns the same error indications
47554755
** with or without this flag; it just omits the call to [sqlite3_log()] that
47564756
** logs the error.
4757
+**
4758
+** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
4759
+** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
4760
+** the SQL statement is part of a database schema. This makes a difference
4761
+** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
4762
+** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
4763
+** SQL functions may not be called unless they are tagged with
4764
+** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
4765
+** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
4766
+** when preparing SQL that is derived from parts of the database
4767
+** schema. In particular, virtual table implementations that
4768
+** run SQL statements based on the arguments to their CREATE VIRTUAL
4769
+** TABLE statement should use [sqlite3_prepare_v3()] and set the
4770
+** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
4771
+** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
47574772
** </dl>
47584773
*/
47594774
#define SQLITE_PREPARE_PERSISTENT 0x01
47604775
#define SQLITE_PREPARE_NORMALIZE 0x02
47614776
#define SQLITE_PREPARE_NO_VTAB 0x04
47624777
#define SQLITE_PREPARE_DONT_LOG 0x10
4778
+#define SQLITE_PREPARE_FROM_DDL 0x20
47634779
47644780
/*
47654781
** CAPI3REF: Compiling An SQL Statement
47664782
** KEYWORDS: {SQL statement compiler}
47674783
** METHOD: sqlite3
@@ -4771,12 +4787,13 @@
47714787
** program using one of these routines. Or, in other words, these routines
47724788
** are constructors for the [prepared statement] object.
47734789
**
47744790
** The preferred routine to use is [sqlite3_prepare_v2()]. The
47754791
** [sqlite3_prepare()] interface is legacy and should be avoided.
4776
-** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
4777
-** for special purposes.
4792
+** [sqlite3_prepare_v3()] has an extra
4793
+** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times
4794
+** needed for special purpose or to pass along security restrictions.
47784795
**
47794796
** The use of the UTF-8 interfaces is preferred, as SQLite currently
47804797
** does all parsing using UTF-8. The UTF-16 interfaces are provided
47814798
** as a convenience. The UTF-16 interfaces work by converting the
47824799
** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -5177,12 +5194,12 @@
51775194
** it should be a pointer to well-formed UTF8 text.
51785195
** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
51795196
** it should be a pointer to well-formed UTF16 text.
51805197
** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
51815198
** it should be a pointer to a well-formed unicode string that is
5182
-** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
5183
-** otherwise.
5199
+** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT,
5200
+** or UTF16 otherwise.
51845201
**
51855202
** [[byte-order determination rules]] ^The byte-order of
51865203
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
51875204
** found in the first character, which is removed, or in the absence of a BOM
51885205
** the byte order is the native byte order of the host
@@ -5224,14 +5241,19 @@
52245241
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
52255242
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
52265243
** object and pointer to it must remain valid until then. ^SQLite will then
52275244
** manage the lifetime of its private copy.
52285245
**
5229
-** ^The sixth argument to sqlite3_bind_text64() must be one of
5230
-** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
5231
-** to specify the encoding of the text in the third parameter. If
5232
-** the sixth argument to sqlite3_bind_text64() is not one of the
5246
+** ^The sixth argument (the E argument)
5247
+** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of
5248
+** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
5249
+** or [SQLITE_UTF16LE] to specify the encoding of the text in the
5250
+** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the
5251
+** string argument is both UTF-8 encoded and is zero-terminated. In other
5252
+** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at
5253
+** least N+1 bytes and that the Z&#91;N&#93; byte is zero. If
5254
+** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the
52335255
** allowed values shown above, or if the text encoding is different
52345256
** from the encoding specified by the sixth parameter, then the behavior
52355257
** is undefined.
52365258
**
52375259
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
@@ -6094,17 +6116,63 @@
60946116
/*
60956117
** CAPI3REF: Text Encodings
60966118
**
60976119
** These constants define integer codes that represent the various
60986120
** text encodings supported by SQLite.
6121
+**
6122
+** <dl>
6123
+** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd>
6124
+**
6125
+** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16
6126
+** with each code point being expressed "little endian" - the least significant
6127
+** byte first. This is the usual encoding, for example on Windows.</dd>
6128
+**
6129
+** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16
6130
+** with each code point being expressed "big endian" - the most significant
6131
+** byte first. This encoding is less common, but is still sometimes seen,
6132
+** specially on older systems.
6133
+**
6134
+** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16
6135
+** with each code point being expressed either little endian or as big
6136
+** endian, according to the native endianness of the host computer.
6137
+**
6138
+** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used
6139
+** to declare the preferred text for [application-defined SQL functions]
6140
+** created using [sqlite3_create_function()] and similar. If the preferred
6141
+** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep
6142
+** parameter) is SQLITE_ANY, that indicates that the function does not have
6143
+** a preference regarding the text encoding of its parameters and can take
6144
+** any text encoding that the SQLite core find convenient to supply. This
6145
+** option is deprecated. Please do not use it in new applications.
6146
+**
6147
+** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding
6148
+** value may be used as the 3rd parameter (the eTextRep parameter) to
6149
+** [sqlite3_create_collation()] and similar. This encoding value means
6150
+** that the application-defined collating sequence created expects its
6151
+** input strings to be in UTF16 in native byte order, and that the start
6152
+** of the strings must be aligned to a 2-byte boundary.
6153
+**
6154
+** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be
6155
+** used to specify the text encoding to strings input to [sqlite3_result_text64()]
6156
+** and [sqlite3_bind_text64()]. It means that the input string (call it "z")
6157
+** is UTF-8 encoded and that it is zero-terminated. If the length parameter
6158
+** (call it "n") is non-negative, this encoding option means that the caller
6159
+** guarantees that z array contains at least n+1 bytes and that the z&#91;n&#93;
6160
+** byte has a value of zero.
6161
+** This option gives the same output as SQLITE_UTF8, but can be more efficient
6162
+** by avoiding the need to make a copy of the input string, in some cases.
6163
+** However, if z is allocated to hold fewer than n+1 bytes or if the
6164
+** z&#91;n&#93; byte is not zero, undefined behavior may result.
6165
+** </dl>
60996166
*/
61006167
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
61016168
#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
61026169
#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
61036170
#define SQLITE_UTF16 4 /* Use native byte order */
61046171
#define SQLITE_ANY 5 /* Deprecated */
61056172
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
6173
+#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */
61066174
61076175
/*
61086176
** CAPI3REF: Function Flags
61096177
**
61106178
** These constants may be ORed together with the
@@ -6606,14 +6674,18 @@
66066674
** use for client data is to provide a mechanism for wrapper libraries
66076675
** to store additional information about an SQLite database connection.
66086676
**
66096677
** There is no limit (other than available memory) on the number of different
66106678
** client data pointers (with different names) that can be attached to a
6611
-** single database connection. However, the implementation is optimized
6612
-** for the case of having only one or two different client data names.
6613
-** Applications and wrapper libraries are discouraged from using more than
6614
-** one client data name each.
6679
+** single database connection. However, the current implementation stores
6680
+** the content on a linked list. Insert and retrieval performance will
6681
+** be proportional to the number of entries. The design use case, and
6682
+** the use case for which the implementation is optimized, is
6683
+** that an application will store only small number of client data names,
6684
+** typically just one or two. This interface is not intended to be a
6685
+** generalized key/value store for thousands or millions of keys. It
6686
+** will work for that, but performance might be disappointing.
66156687
**
66166688
** There is no way to enumerate the client data pointers
66176689
** associated with a database connection. The N parameter can be thought
66186690
** of as a secret key such that only code that knows the secret key is able
66196691
** to access the associated data.
@@ -6717,14 +6789,18 @@
67176789
** ^The sqlite3_result_text(), sqlite3_result_text16(),
67186790
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
67196791
** set the return value of the application-defined function to be
67206792
** a text string which is represented as UTF-8, UTF-16 native byte order,
67216793
** UTF-16 little endian, or UTF-16 big endian, respectively.
6722
-** ^The sqlite3_result_text64() interface sets the return value of an
6794
+** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an
67236795
** application-defined function to be a text string in an encoding
6724
-** specified by the fifth (and last) parameter, which must be one
6725
-** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
6796
+** specified the E parameter, which must be one
6797
+** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
6798
+** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that
6799
+** the result text is both UTF-8 and zero-terminated. In other words,
6800
+** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that
6801
+** the Z&#91;N&#93; is zero.
67266802
** ^SQLite takes the text result from the application from
67276803
** the 2nd parameter of the sqlite3_result_text* interfaces.
67286804
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
67296805
** other than sqlite3_result_text64() is negative, then SQLite computes
67306806
** the string length itself by searching the 2nd parameter for the first
@@ -6807,11 +6883,11 @@
68076883
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
68086884
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
68096885
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
68106886
SQLITE_API void sqlite3_result_null(sqlite3_context*);
68116887
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
6812
-SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
6888
+SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n,
68136889
void(*)(void*), unsigned char encoding);
68146890
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
68156891
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
68166892
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
68176893
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
@@ -7746,22 +7822,22 @@
77467822
** ^This interface loads an SQLite extension library from the named file.
77477823
**
77487824
** ^The sqlite3_load_extension() interface attempts to load an
77497825
** [SQLite extension] library contained in the file zFile. If
77507826
** the file cannot be loaded directly, attempts are made to load
7751
-** with various operating-system specific extensions added.
7827
+** with various operating-system specific filename extensions added.
77527828
** So for example, if "samplelib" cannot be loaded, then names like
77537829
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
77547830
** be tried also.
77557831
**
77567832
** ^The entry point is zProc.
77577833
** ^(zProc may be 0, in which case SQLite will try to come up with an
77587834
** entry point name on its own. It first tries "sqlite3_extension_init".
7759
-** If that does not work, it constructs a name "sqlite3_X_init" where
7760
-** X consists of the lower-case equivalent of all ASCII alphabetic
7761
-** characters in the filename from the last "/" to the first following
7762
-** "." and omitting any initial "lib".)^
7835
+** If that does not work, it tries names of the form "sqlite3_X_init"
7836
+** where X consists of the lower-case equivalent of all ASCII alphabetic
7837
+** characters or all ASCII alphanumeric characters in the filename from
7838
+** the last "/" to the first following "." and omitting any initial "lib".)^
77637839
** ^The sqlite3_load_extension() interface returns
77647840
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
77657841
** ^If an error occurs and pzErrMsg is not 0, then the
77667842
** [sqlite3_load_extension()] interface shall attempt to
77677843
** fill *pzErrMsg with error message text stored in memory
@@ -11495,23 +11571,45 @@
1149511571
#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
1149611572
1149711573
/*
1149811574
** CAPI3REF: Bind array values to the CARRAY table-valued function
1149911575
**
11500
-** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
11501
-** one of the first argument of the [carray() table-valued function]. The
11502
-** S parameter is a pointer to the [prepared statement] that uses the carray()
11503
-** functions. I is the parameter index to be bound. P is a pointer to the
11504
-** array to be bound, and N is the number of eements in the array. The
11505
-** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
11506
-** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
11507
-** indicate the datatype of the array being bound. The X argument is not a
11508
-** NULL pointer, then SQLite will invoke the function X on the P parameter
11509
-** after it has finished using P, even if the call to
11510
-** sqlite3_carray_bind() fails. The special-case finalizer
11511
-** SQLITE_TRANSIENT has no effect here.
11576
+** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
11577
+** parameter that is the first argument of the [carray() table-valued function].
11578
+** The S parameter is a pointer to the [prepared statement] that uses the carray()
11579
+** functions. I is the parameter index to be bound. I must be the index of the
11580
+** parameter that is the first argument to the carray() table-valued function.
11581
+** P is a pointer to the array to be bound, and N is the number of elements in
11582
+** the array. The F argument is one of constants [SQLITE_CARRAY_INT32],
11583
+** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
11584
+** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
11585
+**
11586
+** If the X argument is not a NULL pointer or one of the special
11587
+** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
11588
+** the function X with argument D when it is finished using the data in P.
11589
+** The call to X(D) is a destructor for the array P. The destructor X(D)
11590
+** is invoked even if the call to sqlite3_carray_bind() fails. If the X
11591
+** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
11592
+** that the data static and the destructor is never invoked. If the X
11593
+** parameter is the special-case value [SQLITE_TRANSIENT], then
11594
+** sqlite3_carray_bind_v2() makes its own private copy of the data prior
11595
+** to returning and never invokes the destructor X.
11596
+**
11597
+** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2()
11598
+** with a D parameter set to P. In other words,
11599
+** sqlite3_carray_bind(S,I,P,N,F,X) is same as
11600
+** sqlite3_carray_bind(S,I,P,N,F,X,P).
1151211601
*/
11602
+SQLITE_API int sqlite3_carray_bind_v2(
11603
+ sqlite3_stmt *pStmt, /* Statement to be bound */
11604
+ int i, /* Parameter index */
11605
+ void *aData, /* Pointer to array data */
11606
+ int nData, /* Number of data elements */
11607
+ int mFlags, /* CARRAY flags */
11608
+ void (*xDel)(void*), /* Destructor for aData */
11609
+ void *pDel /* Optional argument to xDel() */
11610
+);
1151311611
SQLITE_API int sqlite3_carray_bind(
1151411612
sqlite3_stmt *pStmt, /* Statement to be bound */
1151511613
int i, /* Parameter index */
1151611614
void *aData, /* Pointer to array data */
1151711615
int nData, /* Number of data elements */
@@ -14352,10 +14450,31 @@
1435214450
#ifndef SQLITE_MAX_LENGTH
1435314451
# define SQLITE_MAX_LENGTH 1000000000
1435414452
#endif
1435514453
#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
1435614454
14455
+/*
14456
+** Maximum size of any single memory allocation.
14457
+**
14458
+** This is not a limit on the total amount of memory used. This is
14459
+** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
14460
+**
14461
+** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
14462
+** This provides a 256-byte safety margin for defense against 32-bit
14463
+** signed integer overflow bugs when computing memory allocation sizes.
14464
+** Paranoid applications might want to reduce the maximum allocation size
14465
+** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
14466
+** or even smaller would be reasonable upper bounds on the size of a memory
14467
+** allocations for most applications.
14468
+*/
14469
+#ifndef SQLITE_MAX_ALLOCATION_SIZE
14470
+# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
14471
+#endif
14472
+#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
14473
+# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
14474
+#endif
14475
+
1435714476
/*
1435814477
** This is the maximum number of
1435914478
**
1436014479
** * Columns in a table
1436114480
** * Columns in an index
@@ -17529,11 +17648,11 @@
1752917648
1753017649
/*
1753117650
** Additional non-public SQLITE_PREPARE_* flags
1753217651
*/
1753317652
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17534
-#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
17653
+#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */
1753517654
1753617655
/*
1753717656
** Prototypes for the VDBE interface. See comments on the implementation
1753817657
** for a description of what each of these routines does.
1753917658
*/
@@ -20202,31 +20321,17 @@
2020220321
};
2020320322
2020420323
/*
2020520324
** An instance of the following structure contains all information
2020620325
** needed to generate code for a single SELECT statement.
20207
-**
20208
-** See the header comment on the computeLimitRegisters() routine for a
20209
-** detailed description of the meaning of the iLimit and iOffset fields.
20210
-**
20211
-** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
20212
-** These addresses must be stored so that we can go back and fill in
20213
-** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
20214
-** the number of columns in P2 can be computed at the same time
20215
-** as the OP_OpenEphm instruction is coded because not
20216
-** enough information about the compound query is known at that point.
20217
-** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
20218
-** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
20219
-** sequences for the ORDER BY clause.
2022020326
*/
2022120327
struct Select {
2022220328
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
2022320329
LogEst nSelectRow; /* Estimated number of result rows */
2022420330
u32 selFlags; /* Various SF_* values */
2022520331
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
2022620332
u32 selId; /* Unique identifier number for this SELECT */
20227
- int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
2022820333
ExprList *pEList; /* The fields of the result */
2022920334
SrcList *pSrc; /* The FROM clause */
2023020335
Expr *pWhere; /* The WHERE clause */
2023120336
ExprList *pGroupBy; /* The GROUP BY clause */
2023220337
Expr *pHaving; /* The HAVING clause */
@@ -20254,28 +20359,28 @@
2025420359
#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
2025520360
#define SF_All 0x0000002 /* Includes the ALL keyword */
2025620361
#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
2025720362
#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
2025820363
#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
20259
-#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
20364
+/* 0x0000020 // available for reuse */
2026020365
#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
2026120366
#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
2026220367
#define SF_Compound 0x0000100 /* Part of a compound query */
2026320368
#define SF_Values 0x0000200 /* Synthesized from VALUES clause */
2026420369
#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
2026520370
#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
2026620371
#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
2026720372
#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
2026820373
#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
20269
-#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
20374
+/* 0x0008000 // available for reuse */
2027020375
#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
2027120376
#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
2027220377
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
2027320378
#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
2027420379
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
2027520380
#define SF_View 0x0200000 /* SELECT statement is a view */
20276
-#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
20381
+/* 0x0400000 // available for reuse */
2027720382
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
2027820383
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
2027920384
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
2028020385
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
2028120386
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
@@ -20291,15 +20396,10 @@
2029120396
/*
2029220397
** The results of a SELECT can be distributed in several ways, as defined
2029320398
** by one of the following macros. The "SRT" prefix means "SELECT Result
2029420399
** Type".
2029520400
**
20296
-** SRT_Union Store results as a key in a temporary index
20297
-** identified by pDest->iSDParm.
20298
-**
20299
-** SRT_Except Remove results from the temporary index pDest->iSDParm.
20300
-**
2030120401
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
2030220402
** set is not empty.
2030320403
**
2030420404
** SRT_Discard Throw the results away. This is used by SELECT
2030520405
** statements within triggers whose only purpose is
@@ -20359,34 +20459,32 @@
2035920459
** column returned by the SELECT is used as the integer
2036020460
** key. If (pDest->iSDParm>0), then the table is an index
2036120461
** table. (pDest->iSDParm) is the number of key columns in
2036220462
** each index record in this case.
2036320463
*/
20364
-#define SRT_Union 1 /* Store result as keys in an index */
20365
-#define SRT_Except 2 /* Remove result from a UNION index */
20366
-#define SRT_Exists 3 /* Store 1 if the result is not empty */
20367
-#define SRT_Discard 4 /* Do not save the results anywhere */
20368
-#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
20369
-#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
20464
+#define SRT_Exists 1 /* Store 1 if the result is not empty */
20465
+#define SRT_Discard 2 /* Do not save the results anywhere */
20466
+#define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */
20467
+#define SRT_DistQueue 4 /* Like SRT_Queue, but unique results only */
2037020468
2037120469
/* The DISTINCT clause is ignored for all of the above. Not that
2037220470
** IgnorableDistinct() implies IgnorableOrderby() */
2037320471
#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
2037420472
20375
-#define SRT_Queue 7 /* Store result in an queue */
20376
-#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
20473
+#define SRT_Queue 5 /* Store result in an queue */
20474
+#define SRT_Fifo 6 /* Store result as data with an automatic rowid */
2037720475
2037820476
/* The ORDER BY clause is ignored for all of the above */
2037920477
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
2038020478
20381
-#define SRT_Output 9 /* Output each row of result */
20382
-#define SRT_Mem 10 /* Store result in a memory cell */
20383
-#define SRT_Set 11 /* Store results as keys in an index */
20384
-#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
20385
-#define SRT_Coroutine 13 /* Generate a single row of result */
20386
-#define SRT_Table 14 /* Store result as data with an automatic rowid */
20387
-#define SRT_Upfrom 15 /* Store result as data with rowid */
20479
+#define SRT_Output 7 /* Output each row of result */
20480
+#define SRT_Mem 8 /* Store result in a memory cell */
20481
+#define SRT_Set 9 /* Store results as keys in an index */
20482
+#define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */
20483
+#define SRT_Coroutine 11 /* Generate a single row of result */
20484
+#define SRT_Table 12 /* Store result as data with an automatic rowid */
20485
+#define SRT_Upfrom 13 /* Store result as data with rowid */
2038820486
2038920487
/*
2039020488
** An instance of this object describes where to put of the results of
2039120489
** a SELECT statement.
2039220490
*/
@@ -21018,10 +21116,11 @@
2101821116
u16 mWFlags; /* Use-dependent flags */
2101921117
union { /* Extra data for callback */
2102021118
NameContext *pNC; /* Naming context */
2102121119
int n; /* A counter */
2102221120
int iCur; /* A cursor number */
21121
+ int sz; /* String literal length */
2102321122
SrcList *pSrcList; /* FROM clause */
2102421123
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
2102521124
struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
2102621125
int *aiCol; /* array of column indexes */
2102721126
struct IdxCover *pIdxCover; /* Check for index coverage */
@@ -21801,10 +21900,11 @@
2180121900
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
2180221901
#endif
2180321902
SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
2180421903
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
2180521904
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
21905
+SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*);
2180621906
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
2180721907
SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
2180821908
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
2180921909
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
2181021910
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -24489,10 +24589,11 @@
2448924589
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
2449024590
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
2449124591
SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
2449224592
SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
2449324593
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
24594
+SQLITE_PRIVATE int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*));
2449424595
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
2449524596
#ifdef SQLITE_OMIT_FLOATING_POINT
2449624597
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
2449724598
#else
2449824599
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
@@ -31335,31 +31436,10 @@
3133531436
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
3133631437
}
3133731438
*pp = p;
3133831439
}
3133931440
31340
-/*
31341
-** Maximum size of any single memory allocation.
31342
-**
31343
-** This is not a limit on the total amount of memory used. This is
31344
-** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
31345
-**
31346
-** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
31347
-** This provides a 256-byte safety margin for defense against 32-bit
31348
-** signed integer overflow bugs when computing memory allocation sizes.
31349
-** Paranoid applications might want to reduce the maximum allocation size
31350
-** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
31351
-** or even smaller would be reasonable upper bounds on the size of a memory
31352
-** allocations for most applications.
31353
-*/
31354
-#ifndef SQLITE_MAX_ALLOCATION_SIZE
31355
-# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
31356
-#endif
31357
-#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
31358
-# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
31359
-#endif
31360
-
3136131441
/*
3136231442
** Allocate memory. This routine is like sqlite3_malloc() except that it
3136331443
** assumes the memory subsystem has already been initialized.
3136431444
*/
3136531445
SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
@@ -31579,12 +31659,11 @@
3157931659
}
3158031660
if( nBytes==0 ){
3158131661
sqlite3_free(pOld); /* IMP: R-26507-47431 */
3158231662
return 0;
3158331663
}
31584
- if( nBytes>=0x7fffff00 ){
31585
- /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
31664
+ if( nBytes>SQLITE_MAX_ALLOCATION_SIZE ){
3158631665
return 0;
3158731666
}
3158831667
nOld = sqlite3MallocSize(pOld);
3158931668
/* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
3159031669
** argument to xRealloc is always a value returned by a prior call to
@@ -48881,78 +48960,54 @@
4888148960
{ "WriteFile", (SYSCALL)WriteFile, 0 },
4888248961
4888348962
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
4888448963
LPOVERLAPPED))aSyscall[61].pCurrent)
4888548964
48886
- { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
48887
-
48888
-#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
48889
- DWORD,DWORD))aSyscall[62].pCurrent)
48890
-
4889148965
/*
4889248966
** For WaitForSingleObject(), MSDN says:
4889348967
**
4889448968
** Minimum supported client: Windows XP [desktop apps | UWP apps]
4889548969
** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
4889648970
*/
4889748971
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
4889848972
4889948973
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
48900
- DWORD))aSyscall[63].pCurrent)
48974
+ DWORD))aSyscall[62].pCurrent)
4890148975
4890248976
#if !SQLITE_OS_WINCE
4890348977
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
4890448978
#else
4890548979
{ "WaitForSingleObjectEx", (SYSCALL)0, 0 },
4890648980
#endif
4890748981
4890848982
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
48909
- BOOL))aSyscall[64].pCurrent)
48910
-
48911
- { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
48912
-
48913
-#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
48914
- PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
48915
-
48916
- { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
48917
-
48918
-#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
48919
- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
48920
-
48921
- { "CreateFile2", (SYSCALL)CreateFile2, 0 },
48922
-
48923
-#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
48924
- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
48925
-
48926
- { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
48927
-
48928
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
48983
+ BOOL))aSyscall[63].pCurrent)
4892948984
4893048985
{ "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
4893148986
4893248987
#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
48933
- LPSYSTEM_INFO))aSyscall[71].pCurrent)
48988
+ LPSYSTEM_INFO))aSyscall[64].pCurrent)
4893448989
4893548990
#if defined(SQLITE_WIN32_HAS_ANSI)
4893648991
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
4893748992
#else
4893848993
{ "OutputDebugStringA", (SYSCALL)0, 0 },
4893948994
#endif
4894048995
48941
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
48996
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[65].pCurrent)
4894248997
4894348998
#if defined(SQLITE_WIN32_HAS_WIDE)
4894448999
{ "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
4894549000
#else
4894649001
{ "OutputDebugStringW", (SYSCALL)0, 0 },
4894749002
#endif
4894849003
48949
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
49004
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[66].pCurrent)
4895049005
4895149006
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
4895249007
48953
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
49008
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[67].pCurrent)
4895449009
4895549010
/*
4895649011
** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
4895749012
** is really just a macro that uses a compiler intrinsic (e.g. x64).
4895849013
** So do not try to make this is into a redefinable interface.
@@ -48963,38 +49018,38 @@
4896349018
#define osInterlockedCompareExchange InterlockedCompareExchange
4896449019
#else
4896549020
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
4896649021
4896749022
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
48968
- SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
49023
+ SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[68].pCurrent)
4896949024
#endif /* defined(InterlockedCompareExchange) */
4897049025
4897149026
#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
4897249027
{ "UuidCreate", (SYSCALL)UuidCreate, 0 },
4897349028
#else
4897449029
{ "UuidCreate", (SYSCALL)0, 0 },
4897549030
#endif
4897649031
48977
-#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
49032
+#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[69].pCurrent)
4897849033
4897949034
#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
4898049035
{ "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
4898149036
#else
4898249037
{ "UuidCreateSequential", (SYSCALL)0, 0 },
4898349038
#endif
4898449039
4898549040
#define osUuidCreateSequential \
48986
- ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
49041
+ ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[70].pCurrent)
4898749042
4898849043
#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
4898949044
{ "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
4899049045
#else
4899149046
{ "FlushViewOfFile", (SYSCALL)0, 0 },
4899249047
#endif
4899349048
4899449049
#define osFlushViewOfFile \
48995
- ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
49050
+ ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[71].pCurrent)
4899649051
4899749052
/*
4899849053
** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
4899949054
** to implement blocking locks with timeouts. MSDN says:
4900049055
**
@@ -49007,11 +49062,11 @@
4900749062
{ "CreateEvent", (SYSCALL)0, 0 },
4900849063
#endif
4900949064
4901049065
#define osCreateEvent ( \
4901149066
(HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
49012
- aSyscall[80].pCurrent \
49067
+ aSyscall[72].pCurrent \
4901349068
)
4901449069
4901549070
/*
4901649071
** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
4901749072
** for the case where a timeout expires and a lock request must be
@@ -49024,68 +49079,68 @@
4902449079
{ "CancelIo", (SYSCALL)CancelIo, 0 },
4902549080
#else
4902649081
{ "CancelIo", (SYSCALL)0, 0 },
4902749082
#endif
4902849083
49029
-#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent)
49084
+#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[73].pCurrent)
4903049085
4903149086
#if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32)
4903249087
{ "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 },
4903349088
#else
4903449089
{ "GetModuleHandleW", (SYSCALL)0, 0 },
4903549090
#endif
4903649091
49037
-#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent)
49092
+#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[74].pCurrent)
4903849093
4903949094
#ifndef _WIN32
4904049095
{ "getenv", (SYSCALL)getenv, 0 },
4904149096
#else
4904249097
{ "getenv", (SYSCALL)0, 0 },
4904349098
#endif
4904449099
49045
-#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent)
49100
+#define osGetenv ((const char *(*)(const char *))aSyscall[75].pCurrent)
4904649101
4904749102
#ifndef _WIN32
4904849103
{ "getcwd", (SYSCALL)getcwd, 0 },
4904949104
#else
4905049105
{ "getcwd", (SYSCALL)0, 0 },
4905149106
#endif
4905249107
49053
-#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent)
49108
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[76].pCurrent)
4905449109
4905549110
#ifndef _WIN32
4905649111
{ "readlink", (SYSCALL)readlink, 0 },
4905749112
#else
4905849113
{ "readlink", (SYSCALL)0, 0 },
4905949114
#endif
4906049115
49061
-#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent)
49116
+#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[77].pCurrent)
4906249117
4906349118
#ifndef _WIN32
4906449119
{ "lstat", (SYSCALL)lstat, 0 },
4906549120
#else
4906649121
{ "lstat", (SYSCALL)0, 0 },
4906749122
#endif
4906849123
49069
-#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent)
49124
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[78].pCurrent)
4907049125
4907149126
#ifndef _WIN32
4907249127
{ "__errno", (SYSCALL)__errno, 0 },
4907349128
#else
4907449129
{ "__errno", (SYSCALL)0, 0 },
4907549130
#endif
4907649131
49077
-#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)())
49132
+#define osErrno (*((int*(*)(void))aSyscall[79].pCurrent)())
4907849133
4907949134
#ifndef _WIN32
4908049135
{ "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
4908149136
#else
4908249137
{ "cygwin_conv_path", (SYSCALL)0, 0 },
4908349138
#endif
4908449139
4908549140
#define osCygwin_conv_path ((size_t(*)(unsigned int, \
49086
- const void *, void *, size_t))aSyscall[88].pCurrent)
49141
+ const void *, void *, size_t))aSyscall[80].pCurrent)
4908749142
4908849143
}; /* End of the overrideable system calls */
4908949144
4909049145
/*
4909149146
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -53659,10 +53714,11 @@
5365953714
attr = INVALID_FILE_ATTRIBUTES;
5366053715
}else{
5366153716
attr = sAttrData.dwFileAttributes;
5366253717
}
5366353718
}else{
53719
+ if( noRetry ) lastErrno = osGetLastError();
5366453720
winLogIoerr(cnt, __LINE__);
5366553721
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
5366653722
sqlite3_free(zConverted);
5366753723
return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
5366853724
zFilename);
@@ -54399,11 +54455,16 @@
5439954455
};
5440054456
#endif
5440154457
5440254458
/* Double-check that the aSyscall[] array has been constructed
5440354459
** correctly. See ticket [bb3a86e890c8e96ab] */
54404
- assert( ArraySize(aSyscall)==86 );
54460
+ assert( ArraySize(aSyscall)==81 );
54461
+ assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 );
54462
+ assert( strcmp(aSyscall[20].zName,"GetFileAttributesA")==0 );
54463
+ assert( strcmp(aSyscall[40].zName,"HeapReAlloc")==0 );
54464
+ assert( strcmp(aSyscall[60].zName,"WideCharToMultiByte")==0 );
54465
+ assert( strcmp(aSyscall[80].zName,"cygwin_conv_path")==0 );
5440554466
5440654467
/* get memory map allocation granularity */
5440754468
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
5440854469
osGetSystemInfo(&winSysInfo);
5440954470
assert( winSysInfo.dwAllocationGranularity>0 );
@@ -77426,11 +77487,11 @@
7742677487
}
7742777488
assert( cursorHoldsMutex(pCur) );
7742877489
7742977490
getCellInfo(pCur);
7743077491
aPayload = pCur->info.pPayload;
77431
- assert( offset+amt <= pCur->info.nPayload );
77492
+ assert( (u64)offset+(u64)amt <= (u64)pCur->info.nPayload );
7743277493
7743377494
assert( aPayload > pPage->aData );
7743477495
if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
7743577496
/* Trying to read or write past the end of the data is an error. The
7743677497
** conditional above is really:
@@ -77983,11 +78044,11 @@
7798378044
SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
7798478045
int rc;
7798578046
7798678047
assert( cursorOwnsBtShared(pCur) );
7798778048
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
77988
- if( pCur->eState==CURSOR_VALID ){
78049
+ if( NEVER(pCur->eState==CURSOR_VALID) ){
7798978050
*pRes = 0;
7799078051
return SQLITE_OK;
7799178052
}
7799278053
rc = moveToRoot(pCur);
7799378054
if( rc==SQLITE_EMPTY ){
@@ -85876,10 +85937,88 @@
8587685937
#endif
8587785938
8587885939
8587985940
return SQLITE_OK;
8588085941
}
85942
+
85943
+/* Like sqlite3VdbeMemSetStr() except:
85944
+**
85945
+** enc is always SQLITE_UTF8
85946
+** pMem->db is always non-NULL
85947
+*/
85948
+SQLITE_PRIVATE int sqlite3VdbeMemSetText(
85949
+ Mem *pMem, /* Memory cell to set to string value */
85950
+ const char *z, /* String pointer */
85951
+ i64 n, /* Bytes in string, or negative */
85952
+ void (*xDel)(void*) /* Destructor function */
85953
+){
85954
+ i64 nByte = n; /* New value for pMem->n */
85955
+ u16 flags;
85956
+
85957
+ assert( pMem!=0 );
85958
+ assert( pMem->db!=0 );
85959
+ assert( sqlite3_mutex_held(pMem->db->mutex) );
85960
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
85961
+
85962
+ /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
85963
+ if( !z ){
85964
+ sqlite3VdbeMemSetNull(pMem);
85965
+ return SQLITE_OK;
85966
+ }
85967
+
85968
+ if( nByte<0 ){
85969
+ nByte = strlen(z);
85970
+ flags = MEM_Str|MEM_Term;
85971
+ }else{
85972
+ flags = MEM_Str;
85973
+ }
85974
+ if( nByte>(i64)pMem->db->aLimit[SQLITE_LIMIT_LENGTH] ){
85975
+ if( xDel && xDel!=SQLITE_TRANSIENT ){
85976
+ if( xDel==SQLITE_DYNAMIC ){
85977
+ sqlite3DbFree(pMem->db, (void*)z);
85978
+ }else{
85979
+ xDel((void*)z);
85980
+ }
85981
+ }
85982
+ sqlite3VdbeMemSetNull(pMem);
85983
+ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
85984
+ }
85985
+
85986
+ /* The following block sets the new values of Mem.z and Mem.xDel. It
85987
+ ** also sets a flag in local variable "flags" to indicate the memory
85988
+ ** management (one of MEM_Dyn or MEM_Static).
85989
+ */
85990
+ if( xDel==SQLITE_TRANSIENT ){
85991
+ i64 nAlloc = nByte + 1;
85992
+ testcase( nAlloc==31 );
85993
+ testcase( nAlloc==32 );
85994
+ if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
85995
+ return SQLITE_NOMEM_BKPT;
85996
+ }
85997
+ assert( pMem->z!=0 );
85998
+ memcpy(pMem->z, z, nByte);
85999
+ pMem->z[nByte] = 0;
86000
+ }else{
86001
+ sqlite3VdbeMemRelease(pMem);
86002
+ pMem->z = (char *)z;
86003
+ if( xDel==SQLITE_DYNAMIC ){
86004
+ pMem->zMalloc = pMem->z;
86005
+ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
86006
+ pMem->xDel = 0;
86007
+ }else if( xDel==SQLITE_STATIC ){
86008
+ pMem->xDel = xDel;
86009
+ flags |= MEM_Static;
86010
+ }else{
86011
+ pMem->xDel = xDel;
86012
+ flags |= MEM_Dyn;
86013
+ }
86014
+ }
86015
+ pMem->flags = flags;
86016
+ pMem->n = (int)(nByte & 0x7fffffff);
86017
+ pMem->enc = SQLITE_UTF8;
86018
+ return SQLITE_OK;
86019
+}
8588186020
8588286021
/*
8588386022
** Move data out of a btree key or data field and into a Mem structure.
8588486023
** The data is payload from the entry that pCur is currently pointing
8588586024
** to. offset and amt determine what portion of the data or key to retrieve.
@@ -85900,11 +86039,16 @@
8590086039
u32 amt, /* Number of bytes to return. */
8590186040
Mem *pMem /* OUT: Return data in this Mem structure. */
8590286041
){
8590386042
int rc;
8590486043
pMem->flags = MEM_Null;
85905
- if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){
86044
+ testcase( amt==SQLITE_MAX_ALLOCATION_SIZE-1 );
86045
+ testcase( amt==SQLITE_MAX_ALLOCATION_SIZE );
86046
+ if( amt>=SQLITE_MAX_ALLOCATION_SIZE ){
86047
+ return SQLITE_NOMEM_BKPT;
86048
+ }
86049
+ if( (u64)amt + (u64)offset > (u64)sqlite3BtreeMaxRecordSize(pCur) ){
8590686050
return SQLITE_CORRUPT_BKPT;
8590786051
}
8590886052
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
8590986053
rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
8591086054
if( rc==SQLITE_OK ){
@@ -86568,10 +86712,15 @@
8656886712
** the column value into *ppVal. If *ppVal is initially NULL then a new
8656986713
** sqlite3_value object is allocated.
8657086714
**
8657186715
** If *ppVal is initially NULL then the caller is responsible for
8657286716
** ensuring that the value written into *ppVal is eventually freed.
86717
+**
86718
+** If the buffer does not contain a well-formed record, this routine may
86719
+** read several bytes past the end of the buffer. Callers must therefore
86720
+** ensure that any buffer which may contain a corrupt record is padded
86721
+** with at least 8 bytes of addressable memory.
8657386722
*/
8657486723
SQLITE_PRIVATE int sqlite3Stat4Column(
8657586724
sqlite3 *db, /* Database handle */
8657686725
const void *pRec, /* Pointer to buffer containing record */
8657786726
int nRec, /* Size of buffer pRec in bytes */
@@ -89584,11 +89733,11 @@
8958489733
assert( !zName || xDel!=SQLITE_DYNAMIC );
8958589734
return SQLITE_NOMEM_BKPT;
8958689735
}
8958789736
assert( p->aColName!=0 );
8958889737
pColName = &(p->aColName[idx+var*p->nResAlloc]);
89589
- rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
89738
+ rc = sqlite3VdbeMemSetText(pColName, zName, -1, xDel);
8959089739
assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
8959189740
return rc;
8959289741
}
8959389742
8959489743
/*
@@ -92662,11 +92811,27 @@
9266292811
int n, /* Bytes in string, or negative */
9266392812
u8 enc, /* Encoding of z. 0 for BLOBs */
9266492813
void (*xDel)(void*) /* Destructor function */
9266592814
){
9266692815
Mem *pOut = pCtx->pOut;
92667
- int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
92816
+ int rc;
92817
+ if( enc==SQLITE_UTF8 ){
92818
+ rc = sqlite3VdbeMemSetText(pOut, z, n, xDel);
92819
+ }else if( enc==SQLITE_UTF8_ZT ){
92820
+ /* It is usually considered improper to assert() on an input. However,
92821
+ ** the following assert() is checking for inputs that are documented
92822
+ ** to result in undefined behavior. */
92823
+ assert( z==0
92824
+ || n<0
92825
+ || n>pOut->db->aLimit[SQLITE_LIMIT_LENGTH]
92826
+ || z[n]==0
92827
+ );
92828
+ rc = sqlite3VdbeMemSetText(pOut, z, n, xDel);
92829
+ pOut->flags |= MEM_Term;
92830
+ }else{
92831
+ rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
92832
+ }
9266892833
if( rc ){
9266992834
if( rc==SQLITE_TOOBIG ){
9267092835
sqlite3_result_error_toobig(pCtx);
9267192836
}else{
9267292837
/* The only errors possible from sqlite3VdbeMemSetStr are
@@ -92855,11 +93020,11 @@
9285593020
return;
9285693021
}
9285793022
#endif
9285893023
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
9285993024
assert( xDel!=SQLITE_DYNAMIC );
92860
- if( enc!=SQLITE_UTF8 ){
93025
+ if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){
9286193026
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
9286293027
n &= ~(u64)1;
9286393028
}
9286493029
if( n>0x7fffffff ){
9286593030
(void)invokeValueDestructor(z, xDel, pCtx);
@@ -93315,11 +93480,11 @@
9331593480
if( rc==SQLITE_OK ){
9331693481
u32 sz; /* Size of current row in bytes */
9331793482
Mem sMem; /* Raw content of current row */
9331893483
memset(&sMem, 0, sizeof(sMem));
9331993484
sz = sqlite3BtreePayloadSize(pRhs->pCsr);
93320
- rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
93485
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,sz,&sMem);
9332193486
if( rc==SQLITE_OK ){
9332293487
u8 *zBuf = (u8*)sMem.z;
9332393488
u32 iSerial;
9332493489
sqlite3_value *pOut = pRhs->pOut;
9332593490
int iOff = 1 + getVarint32(&zBuf[1], iSerial);
@@ -93964,17 +94129,29 @@
9396494129
rc = vdbeUnbind(p, (u32)(i-1));
9396594130
if( rc==SQLITE_OK ){
9396694131
assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
9396794132
if( zData!=0 ){
9396894133
pVar = &p->aVar[i-1];
93969
- rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
93970
- if( rc==SQLITE_OK ){
93971
- if( encoding==0 ){
93972
- pVar->enc = ENC(p->db);
93973
- }else{
93974
- rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
93975
- }
94134
+ if( encoding==SQLITE_UTF8 ){
94135
+ rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel);
94136
+ }else if( encoding==SQLITE_UTF8_ZT ){
94137
+ /* It is usually consider improper to assert() on an input.
94138
+ ** However, the following assert() is checking for inputs
94139
+ ** that are documented to result in undefined behavior. */
94140
+ assert( zData==0
94141
+ || nData<0
94142
+ || nData>pVar->db->aLimit[SQLITE_LIMIT_LENGTH]
94143
+ || ((u8*)zData)[nData]==0
94144
+ );
94145
+ rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel);
94146
+ pVar->flags |= MEM_Term;
94147
+ }else{
94148
+ rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
94149
+ if( encoding==0 ) pVar->enc = ENC(p->db);
94150
+ }
94151
+ if( rc==SQLITE_OK && encoding!=0 ){
94152
+ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
9397694153
}
9397794154
if( rc ){
9397894155
sqlite3Error(p->db, rc);
9397994156
rc = sqlite3ApiExit(p->db, rc);
9398094157
}
@@ -94082,11 +94259,11 @@
9408294259
sqlite3_uint64 nData,
9408394260
void (*xDel)(void*),
9408494261
unsigned char enc
9408594262
){
9408694263
assert( xDel!=SQLITE_DYNAMIC );
94087
- if( enc!=SQLITE_UTF8 ){
94264
+ if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){
9408894265
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
9408994266
nData &= ~(u64)1;
9409094267
}
9409194268
return bindText(pStmt, i, zData, nData, xDel, enc);
9409294269
}
@@ -101780,24 +101957,19 @@
101780101957
rc = sqlite3VdbeSorterWrite(pC, pIn2);
101781101958
if( rc) goto abort_due_to_error;
101782101959
break;
101783101960
}
101784101961
101785
-/* Opcode: IdxDelete P1 P2 P3 * P5
101962
+/* Opcode: IdxDelete P1 P2 P3 * *
101786101963
** Synopsis: key=r[P2@P3]
101787101964
**
101788101965
** The content of P3 registers starting at register P2 form
101789101966
** an unpacked index key. This opcode removes that entry from the
101790101967
** index opened by cursor P1.
101791101968
**
101792
-** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
101793
-** if no matching index entry is found. This happens when running
101794
-** an UPDATE or DELETE statement and the index entry to be updated
101795
-** or deleted is not found. For some uses of IdxDelete
101796
-** (example: the EXCEPT operator) it does not matter that no matching
101797
-** entry is found. For those cases, P5 is zero. Also, do not raise
101798
-** this (self-correcting and non-critical) error if in writable_schema mode.
101969
+** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
101970
+** and not in writable_schema mode.
101799101971
*/
101800101972
case OP_IdxDelete: {
101801101973
VdbeCursor *pC;
101802101974
BtCursor *pCrsr;
101803101975
int res;
@@ -101819,11 +101991,11 @@
101819101991
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
101820101992
if( rc ) goto abort_due_to_error;
101821101993
if( res==0 ){
101822101994
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
101823101995
if( rc ) goto abort_due_to_error;
101824
- }else if( pOp->p5 && !sqlite3WritableSchema(db) ){
101996
+ }else if( !sqlite3WritableSchema(db) ){
101825101997
rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
101826101998
goto abort_due_to_error;
101827101999
}
101828102000
assert( pC->deferredMoveto==0 );
101829102001
pC->cacheStatus = CACHE_STALE;
@@ -110988,14 +111160,10 @@
110988111160
}
110989111161
}
110990111162
}
110991111163
#endif
110992111164
110993
- /* The ORDER BY and GROUP BY clauses may not refer to terms in
110994
- ** outer queries
110995
- */
110996
- sNC.pNext = 0;
110997111165
sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
110998111166
110999111167
/* If this is a converted compound query, move the ORDER BY clause from
111000111168
** the sub-query back to the parent query. At this point each term
111001111169
** within the ORDER BY clause has been transformed to an integer value.
@@ -112575,11 +112743,13 @@
112575112743
const Expr *pExpr, /* The function invocation */
112576112744
const FuncDef *pDef /* The function being invoked */
112577112745
){
112578112746
assert( !IN_RENAME_OBJECT );
112579112747
assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
112580
- if( ExprHasProperty(pExpr, EP_FromDDL) ){
112748
+ if( ExprHasProperty(pExpr, EP_FromDDL)
112749
+ || pParse->prepFlags & SQLITE_PREPARE_FROM_DDL
112750
+ ){
112581112751
if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
112582112752
|| (pParse->db->flags & SQLITE_TrustedSchema)==0
112583112753
){
112584112754
/* Functions prohibited in triggers and views if:
112585112755
** (1) tagged with SQLITE_DIRECTONLY
@@ -113271,13 +113441,11 @@
113271113441
pNew->pNext = pNext;
113272113442
pNew->pPrior = 0;
113273113443
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
113274113444
pNew->iLimit = 0;
113275113445
pNew->iOffset = 0;
113276
- pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
113277
- pNew->addrOpenEphm[0] = -1;
113278
- pNew->addrOpenEphm[1] = -1;
113446
+ pNew->selFlags = p->selFlags;
113279113447
pNew->nSelectRow = p->nSelectRow;
113280113448
pNew->pWith = sqlite3WithDup(db, p->pWith);
113281113449
#ifndef SQLITE_OMIT_WINDOWFUNC
113282113450
pNew->pWin = 0;
113283113451
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
@@ -115495,12 +115663,13 @@
115495115663
if( destIfFalse==destIfNull ){
115496115664
/* Combine Step 3 and Step 5 into a single opcode */
115497115665
if( ExprHasProperty(pExpr, EP_Subrtn) ){
115498115666
const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
115499115667
assert( pOp->opcode==OP_Once || pParse->nErr );
115500
- if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
115501
- assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
115668
+ if( pOp->p3>0 ){ /* tag-202407032019 */
115669
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter)
115670
+ || pParse->nErr );
115502115671
sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
115503115672
rLhs, nVector); VdbeCoverage(v);
115504115673
}
115505115674
}
115506115675
sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
@@ -118687,11 +118856,14 @@
118687118856
if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break;
118688118857
}
118689118858
if( pIEpr==0 ) break;
118690118859
if( NEVER(!ExprUseYTab(pExpr)) ) break;
118691118860
for(i=0; i<pSrcList->nSrc; i++){
118692
- if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break;
118861
+ if( pSrcList->a[i].iCursor==pIEpr->iDataCur ){
118862
+ testcase( i>0 );
118863
+ break;
118864
+ }
118693118865
}
118694118866
if( i>=pSrcList->nSrc ) break;
118695118867
if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */
118696118868
if( pParse->nErr ){ return WRC_Abort; }
118697118869
@@ -131401,11 +131573,11 @@
131401131573
** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
131402131574
** virtual tables
131403131575
** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
131404131576
** virtual tables if PRAGMA trusted_schema=ON.
131405131577
*/
131406
- if( pParse->pToplevel!=0
131578
+ if( (pParse->pToplevel!=0 || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL))
131407131579
&& pTab->u.vtab.p->eVtabRisk >
131408131580
((pParse->db->flags & SQLITE_TrustedSchema)!=0)
131409131581
){
131410131582
sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
131411131583
pTab->zName);
@@ -132239,11 +132411,10 @@
132239132411
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
132240132412
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
132241132413
&iPartIdxLabel, pPrior, r1);
132242132414
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
132243132415
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
132244
- sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
132245132416
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
132246132417
pPrior = pIdx;
132247132418
}
132248132419
}
132249132420
@@ -133586,11 +133757,11 @@
133586133757
}else{
133587133758
goto unistr_error;
133588133759
}
133589133760
}
133590133761
zOut[j] = 0;
133591
- sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8);
133762
+ sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8_ZT);
133592133763
return;
133593133764
133594133765
unistr_error:
133595133766
sqlite3_free(zOut);
133596133767
sqlite3_result_error(context, "invalid Unicode escape", -1);
@@ -133679,11 +133850,11 @@
133679133850
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
133680133851
*zOut++ = 0x80 + (u8)(c & 0x3F);
133681133852
} \
133682133853
}
133683133854
*zOut = 0;
133684
- sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
133855
+ sqlite3_result_text64(context, (char*)z, zOut-z,sqlite3_free,SQLITE_UTF8_ZT);
133685133856
}
133686133857
133687133858
/*
133688133859
** The hex() function. Interpret the argument as a blob. Return
133689133860
** a hexadecimal rendering as text.
@@ -133708,11 +133879,11 @@
133708133879
*(z++) = hexdigits[(c>>4)&0xf];
133709133880
*(z++) = hexdigits[c&0xf];
133710133881
}
133711133882
*z = 0;
133712133883
sqlite3_result_text64(context, zHex, (u64)(z-zHex),
133713
- sqlite3_free, SQLITE_UTF8);
133884
+ sqlite3_free, SQLITE_UTF8_ZT);
133714133885
}
133715133886
}
133716133887
133717133888
/*
133718133889
** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr
@@ -134046,11 +134217,11 @@
134046134217
}
134047134218
}
134048134219
}
134049134220
z[j] = 0;
134050134221
assert( j<=n );
134051
- sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8);
134222
+ sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8_ZT);
134052134223
}
134053134224
134054134225
/*
134055134226
** The CONCAT(...) function. Generate a string result that is the
134056134227
** concatentation of all non-null arguments.
@@ -141234,10 +141405,12 @@
141234141405
int (*set_errmsg)(sqlite3*,int,const char*);
141235141406
int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
141236141407
/* Version 3.52.0 and later */
141237141408
void (*str_truncate)(sqlite3_str*,int);
141238141409
void (*str_free)(sqlite3_str*);
141410
+ int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
141411
+ int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
141239141412
};
141240141413
141241141414
/*
141242141415
** This is the function signature used for all extension entry points. It
141243141416
** is also defined in the file "loadext.c".
@@ -141575,10 +141748,12 @@
141575141748
#define sqlite3_set_errmsg sqlite3_api->set_errmsg
141576141749
#define sqlite3_db_status64 sqlite3_api->db_status64
141577141750
/* Version 3.52.0 and later */
141578141751
#define sqlite3_str_truncate sqlite3_api->str_truncate
141579141752
#define sqlite3_str_free sqlite3_api->str_free
141753
+#define sqlite3_carray_bind sqlite3_api->carray_bind
141754
+#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
141580141755
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
141581141756
141582141757
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
141583141758
/* This case when the file really is being compiled as a loadable
141584141759
** extension */
@@ -142104,11 +142279,18 @@
142104142279
/* Version 3.51.0 and later */
142105142280
sqlite3_set_errmsg,
142106142281
sqlite3_db_status64,
142107142282
/* Version 3.52.0 and later */
142108142283
sqlite3_str_truncate,
142109
- sqlite3_str_free
142284
+ sqlite3_str_free,
142285
+#ifdef SQLITE_ENABLE_CARRAY
142286
+ sqlite3_carray_bind,
142287
+ sqlite3_carray_bind_v2
142288
+#else
142289
+ 0,
142290
+ 0
142291
+#endif
142110142292
};
142111142293
142112142294
/* True if x is the directory separator character
142113142295
*/
142114142296
#if SQLITE_OS_WIN
@@ -142206,37 +142388,46 @@
142206142388
142207142389
/* If no entry point was specified and the default legacy
142208142390
** entry point name "sqlite3_extension_init" was not found, then
142209142391
** construct an entry point name "sqlite3_X_init" where the X is
142210142392
** replaced by the lowercase value of every ASCII alphabetic
142211
- ** character in the filename after the last "/" upto the first ".",
142212
- ** and eliding the first three characters if they are "lib".
142393
+ ** character in the filename after the last "/" up to the first ".",
142394
+ ** and skipping the first three characters if they are "lib".
142213142395
** Examples:
142214142396
**
142215142397
** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
142216142398
** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init
142399
+ **
142400
+ ** If that still finds no entry point, repeat a second time but this
142401
+ ** time include both alphabetic and numeric characters up to the first
142402
+ ** ".". Example:
142403
+ **
142404
+ ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init
142217142405
*/
142218142406
if( xInit==0 && zProc==0 ){
142219142407
int iFile, iEntry, c;
142220142408
int ncFile = sqlite3Strlen30(zFile);
142409
+ int cnt = 0;
142221142410
zAltEntry = sqlite3_malloc64(ncFile+30);
142222142411
if( zAltEntry==0 ){
142223142412
sqlite3OsDlClose(pVfs, handle);
142224142413
return SQLITE_NOMEM_BKPT;
142225142414
}
142226
- memcpy(zAltEntry, "sqlite3_", 8);
142227
- for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
142228
- iFile++;
142229
- if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
142230
- for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
142231
- if( sqlite3Isalpha(c) ){
142232
- zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
142233
- }
142234
- }
142235
- memcpy(zAltEntry+iEntry, "_init", 6);
142236
- zEntry = zAltEntry;
142237
- xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
142415
+ do{
142416
+ memcpy(zAltEntry, "sqlite3_", 8);
142417
+ for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
142418
+ iFile++;
142419
+ if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
142420
+ for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
142421
+ if( sqlite3Isalpha(c) || (cnt && sqlite3Isdigit(c)) ){
142422
+ zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
142423
+ }
142424
+ }
142425
+ memcpy(zAltEntry+iEntry, "_init", 6);
142426
+ zEntry = zAltEntry;
142427
+ xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
142428
+ }while( xInit==0 && (++cnt)<2 );
142238142429
}
142239142430
if( xInit==0 ){
142240142431
if( pzErrMsg ){
142241142432
nMsg += strlen(zEntry) + 300;
142242142433
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
@@ -147518,12 +147709,10 @@
147518147709
pNew->op = TK_SELECT;
147519147710
pNew->selFlags = selFlags;
147520147711
pNew->iLimit = 0;
147521147712
pNew->iOffset = 0;
147522147713
pNew->selId = ++pParse->nSelect;
147523
- pNew->addrOpenEphm[0] = -1;
147524
- pNew->addrOpenEphm[1] = -1;
147525147714
pNew->nSelectRow = 0;
147526147715
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
147527147716
pNew->pSrc = pSrc;
147528147717
pNew->pWhere = pWhere;
147529147718
pNew->pGroupBy = pGroupBy;
@@ -148667,33 +148856,10 @@
148667148856
codeOffset(v, p->iOffset, iContinue);
148668148857
}
148669148858
}
148670148859
148671148860
switch( eDest ){
148672
- /* In this mode, write each query result to the key of the temporary
148673
- ** table iParm.
148674
- */
148675
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
148676
- case SRT_Union: {
148677
- int r1;
148678
- r1 = sqlite3GetTempReg(pParse);
148679
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
148680
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
148681
- sqlite3ReleaseTempReg(pParse, r1);
148682
- break;
148683
- }
148684
-
148685
- /* Construct a record from the query result, but instead of
148686
- ** saving that record, use it as a key to delete elements from
148687
- ** the temporary table iParm.
148688
- */
148689
- case SRT_Except: {
148690
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
148691
- break;
148692
- }
148693
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
148694
-
148695148861
/* Store the result as data using a unique key.
148696148862
*/
148697148863
case SRT_Fifo:
148698148864
case SRT_DistFifo:
148699148865
case SRT_Table:
@@ -149976,13 +150142,13 @@
149976150142
**
149977150143
** Space to hold the KeyInfo structure is obtained from malloc. The calling
149978150144
** function is responsible for ensuring that this structure is eventually
149979150145
** freed.
149980150146
*/
149981
-static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
150147
+static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){
149982150148
ExprList *pOrderBy = p->pOrderBy;
149983
- int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0;
150149
+ int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0;
149984150150
sqlite3 *db = pParse->db;
149985150151
KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
149986150152
if( pRet ){
149987150153
int i;
149988150154
for(i=0; i<nOrderBy; i++){
@@ -150111,21 +150277,41 @@
150111150277
150112150278
/* Allocate cursors for Current, Queue, and Distinct. */
150113150279
regCurrent = ++pParse->nMem;
150114150280
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
150115150281
if( pOrderBy ){
150116
- KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
150282
+ KeyInfo *pKeyInfo = multiSelectByMergeKeyInfo(pParse, p, 1);
150117150283
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
150118150284
(char*)pKeyInfo, P4_KEYINFO);
150119150285
destQueue.pOrderBy = pOrderBy;
150120150286
}else{
150121150287
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
150122150288
}
150123150289
VdbeComment((v, "Queue table"));
150124150290
if( iDistinct ){
150125
- p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
150126
- p->selFlags |= SF_UsesEphemeral;
150291
+ /* Generate an ephemeral table used to enforce distinctness on the
150292
+ ** output of the recursive part of the CTE.
150293
+ */
150294
+ KeyInfo *pKeyInfo; /* Collating sequence for the result set */
150295
+ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
150296
+
150297
+ assert( p->pNext==0 );
150298
+ assert( p->pEList!=0 );
150299
+ nCol = p->pEList->nExpr;
150300
+ pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nCol, 1);
150301
+ if( pKeyInfo ){
150302
+ for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
150303
+ *apColl = multiSelectCollSeq(pParse, p, i);
150304
+ if( 0==*apColl ){
150305
+ *apColl = pParse->db->pDfltColl;
150306
+ }
150307
+ }
150308
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iDistinct, nCol, 0,
150309
+ (void*)pKeyInfo, P4_KEYINFO);
150310
+ }else{
150311
+ assert( pParse->nErr>0 );
150312
+ }
150127150313
}
150128150314
150129150315
/* Detach the ORDER BY clause from the compound SELECT */
150130150316
p->pOrderBy = 0;
150131150317
@@ -150196,11 +150382,11 @@
150196150382
return;
150197150383
}
150198150384
#endif /* SQLITE_OMIT_CTE */
150199150385
150200150386
/* Forward references */
150201
-static int multiSelectOrderBy(
150387
+static int multiSelectByMerge(
150202150388
Parse *pParse, /* Parsing context */
150203150389
Select *p, /* The right-most of SELECTs to be coded */
150204150390
SelectDest *pDest /* What to do with query results */
150205150391
);
150206150392
@@ -150345,317 +150531,80 @@
150345150531
#ifndef SQLITE_OMIT_CTE
150346150532
if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
150347150533
generateWithRecursiveQuery(pParse, p, &dest);
150348150534
}else
150349150535
#endif
150350
-
150351
- /* Compound SELECTs that have an ORDER BY clause are handled separately.
150352
- */
150353150536
if( p->pOrderBy ){
150354
- return multiSelectOrderBy(pParse, p, pDest);
150537
+ /* If the compound has an ORDER BY clause, then always use the merge
150538
+ ** algorithm. */
150539
+ return multiSelectByMerge(pParse, p, pDest);
150540
+ }else if( p->op!=TK_ALL ){
150541
+ /* If the compound is EXCEPT, INTERSECT, or UNION (anything other than
150542
+ ** UNION ALL) then also always use the merge algorithm. However, the
150543
+ ** multiSelectByMerge() routine requires that the compound have an
150544
+ ** ORDER BY clause, and it doesn't right now. So invent one first. */
150545
+ Expr *pOne = sqlite3ExprInt32(db, 1);
150546
+ p->pOrderBy = sqlite3ExprListAppend(pParse, 0, pOne);
150547
+ if( pParse->nErr ) goto multi_select_end;
150548
+ assert( p->pOrderBy!=0 );
150549
+ p->pOrderBy->a[0].u.x.iOrderByCol = 1;
150550
+ return multiSelectByMerge(pParse, p, pDest);
150355150551
}else{
150552
+ /* For a UNION ALL compound without ORDER BY, simply run the left
150553
+ ** query, then run the right query */
150554
+ int addr = 0;
150555
+ int nLimit = 0; /* Initialize to suppress harmless compiler warning */
150356150556
150357150557
#ifndef SQLITE_OMIT_EXPLAIN
150358150558
if( pPrior->pPrior==0 ){
150359150559
ExplainQueryPlan((pParse, 1, "COMPOUND QUERY"));
150360150560
ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
150361150561
}
150362150562
#endif
150363
-
150364
- /* Generate code for the left and right SELECT statements.
150365
- */
150366
- switch( p->op ){
150367
- case TK_ALL: {
150368
- int addr = 0;
150369
- int nLimit = 0; /* Initialize to suppress harmless compiler warning */
150370
- assert( !pPrior->pLimit );
150371
- pPrior->iLimit = p->iLimit;
150372
- pPrior->iOffset = p->iOffset;
150373
- pPrior->pLimit = p->pLimit;
150374
- TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
150375
- rc = sqlite3Select(pParse, pPrior, &dest);
150376
- pPrior->pLimit = 0;
150377
- if( rc ){
150378
- goto multi_select_end;
150379
- }
150380
- p->pPrior = 0;
150381
- p->iLimit = pPrior->iLimit;
150382
- p->iOffset = pPrior->iOffset;
150383
- if( p->iLimit ){
150384
- addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
150385
- VdbeComment((v, "Jump ahead if LIMIT reached"));
150386
- if( p->iOffset ){
150387
- sqlite3VdbeAddOp3(v, OP_OffsetLimit,
150388
- p->iLimit, p->iOffset+1, p->iOffset);
150389
- }
150390
- }
150391
- ExplainQueryPlan((pParse, 1, "UNION ALL"));
150392
- TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
150393
- rc = sqlite3Select(pParse, p, &dest);
150394
- testcase( rc!=SQLITE_OK );
150395
- pDelete = p->pPrior;
150396
- p->pPrior = pPrior;
150397
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
150398
- if( p->pLimit
150399
- && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
150400
- && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
150401
- ){
150402
- p->nSelectRow = sqlite3LogEst((u64)nLimit);
150403
- }
150404
- if( addr ){
150405
- sqlite3VdbeJumpHere(v, addr);
150406
- }
150407
- break;
150408
- }
150409
- case TK_EXCEPT:
150410
- case TK_UNION: {
150411
- int unionTab; /* Cursor number of the temp table holding result */
150412
- u8 op = 0; /* One of the SRT_ operations to apply to self */
150413
- int priorOp; /* The SRT_ operation to apply to prior selects */
150414
- Expr *pLimit; /* Saved values of p->nLimit */
150415
- int addr;
150416
- int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */
150417
- SelectDest uniondest;
150418
-
150419
-
150420
- testcase( p->op==TK_EXCEPT );
150421
- testcase( p->op==TK_UNION );
150422
- priorOp = SRT_Union;
150423
- if( dest.eDest==priorOp ){
150424
- /* We can reuse a temporary table generated by a SELECT to our
150425
- ** right.
150426
- */
150427
- assert( p->pLimit==0 ); /* Not allowed on leftward elements */
150428
- unionTab = dest.iSDParm;
150429
- }else{
150430
- /* We will need to create our own temporary table to hold the
150431
- ** intermediate results.
150432
- */
150433
- unionTab = pParse->nTab++;
150434
- assert( p->pOrderBy==0 );
150435
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
150436
- assert( p->addrOpenEphm[0] == -1 );
150437
- p->addrOpenEphm[0] = addr;
150438
- findRightmost(p)->selFlags |= SF_UsesEphemeral;
150439
- assert( p->pEList );
150440
- }
150441
-
150442
-
150443
- /* Code the SELECT statements to our left
150444
- */
150445
- assert( !pPrior->pOrderBy );
150446
- sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
150447
- TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
150448
- rc = sqlite3Select(pParse, pPrior, &uniondest);
150449
- if( rc ){
150450
- goto multi_select_end;
150451
- }
150452
-
150453
- /* Code the current SELECT statement
150454
- */
150455
- if( p->op==TK_EXCEPT ){
150456
- op = SRT_Except;
150457
- emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab);
150458
- VdbeCoverage(v);
150459
- }else{
150460
- assert( p->op==TK_UNION );
150461
- op = SRT_Union;
150462
- }
150463
- p->pPrior = 0;
150464
- pLimit = p->pLimit;
150465
- p->pLimit = 0;
150466
- uniondest.eDest = op;
150467
- ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
150468
- sqlite3SelectOpName(p->op)));
150469
- TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
150470
- rc = sqlite3Select(pParse, p, &uniondest);
150471
- testcase( rc!=SQLITE_OK );
150472
- assert( p->pOrderBy==0 );
150473
- pDelete = p->pPrior;
150474
- p->pPrior = pPrior;
150475
- p->pOrderBy = 0;
150476
- if( p->op==TK_UNION ){
150477
- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
150478
- }
150479
- if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass);
150480
- sqlite3ExprDelete(db, p->pLimit);
150481
- p->pLimit = pLimit;
150482
- p->iLimit = 0;
150483
- p->iOffset = 0;
150484
-
150485
- /* Convert the data in the temporary table into whatever form
150486
- ** it is that we currently need.
150487
- */
150488
- assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
150489
- assert( p->pEList || db->mallocFailed );
150490
- if( dest.eDest!=priorOp && db->mallocFailed==0 ){
150491
- int iCont, iBreak, iStart;
150492
- iBreak = sqlite3VdbeMakeLabel(pParse);
150493
- iCont = sqlite3VdbeMakeLabel(pParse);
150494
- computeLimitRegisters(pParse, p, iBreak);
150495
- sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
150496
- iStart = sqlite3VdbeCurrentAddr(v);
150497
- selectInnerLoop(pParse, p, unionTab,
150498
- 0, 0, &dest, iCont, iBreak);
150499
- sqlite3VdbeResolveLabel(v, iCont);
150500
- sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
150501
- sqlite3VdbeResolveLabel(v, iBreak);
150502
- sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
150503
- }
150504
- break;
150505
- }
150506
- default: assert( p->op==TK_INTERSECT ); {
150507
- int tab1, tab2;
150508
- int iCont, iBreak, iStart;
150509
- Expr *pLimit;
150510
- int addr, iLimit, iOffset;
150511
- SelectDest intersectdest;
150512
- int r1;
150513
- int emptyBypass;
150514
-
150515
- /* INTERSECT is different from the others since it requires
150516
- ** two temporary tables. Hence it has its own case. Begin
150517
- ** by allocating the tables we will need.
150518
- */
150519
- tab1 = pParse->nTab++;
150520
- tab2 = pParse->nTab++;
150521
- assert( p->pOrderBy==0 );
150522
-
150523
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
150524
- assert( p->addrOpenEphm[0] == -1 );
150525
- p->addrOpenEphm[0] = addr;
150526
- findRightmost(p)->selFlags |= SF_UsesEphemeral;
150527
- assert( p->pEList );
150528
-
150529
- /* Code the SELECTs to our left into temporary table "tab1".
150530
- */
150531
- sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
150532
- TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n"));
150533
- rc = sqlite3Select(pParse, pPrior, &intersectdest);
150534
- if( rc ){
150535
- goto multi_select_end;
150536
- }
150537
-
150538
- /* Initialize LIMIT counters before checking to see if the LHS
150539
- ** is empty, in case the jump is taken */
150540
- iBreak = sqlite3VdbeMakeLabel(pParse);
150541
- computeLimitRegisters(pParse, p, iBreak);
150542
- emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v);
150543
-
150544
- /* Code the current SELECT into temporary table "tab2"
150545
- */
150546
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
150547
- assert( p->addrOpenEphm[1] == -1 );
150548
- p->addrOpenEphm[1] = addr;
150549
-
150550
- /* Disable prior SELECTs and the LIMIT counters during the computation
150551
- ** of the RHS select */
150552
- pLimit = p->pLimit;
150553
- iLimit = p->iLimit;
150554
- iOffset = p->iOffset;
150555
- p->pPrior = 0;
150556
- p->pLimit = 0;
150557
- p->iLimit = 0;
150558
- p->iOffset = 0;
150559
-
150560
- intersectdest.iSDParm = tab2;
150561
- ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
150562
- sqlite3SelectOpName(p->op)));
150563
- TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n"));
150564
- rc = sqlite3Select(pParse, p, &intersectdest);
150565
- testcase( rc!=SQLITE_OK );
150566
- pDelete = p->pPrior;
150567
- p->pPrior = pPrior;
150568
- if( p->nSelectRow>pPrior->nSelectRow ){
150569
- p->nSelectRow = pPrior->nSelectRow;
150570
- }
150571
- sqlite3ExprDelete(db, p->pLimit);
150572
-
150573
- /* Reinstate the LIMIT counters prior to running the final intersect */
150574
- p->pLimit = pLimit;
150575
- p->iLimit = iLimit;
150576
- p->iOffset = iOffset;
150577
-
150578
- /* Generate code to take the intersection of the two temporary
150579
- ** tables.
150580
- */
150581
- if( rc ) break;
150582
- assert( p->pEList );
150583
- sqlite3VdbeAddOp1(v, OP_Rewind, tab1);
150584
- r1 = sqlite3GetTempReg(pParse);
150585
- iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
150586
- iCont = sqlite3VdbeMakeLabel(pParse);
150587
- sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
150588
- VdbeCoverage(v);
150589
- sqlite3ReleaseTempReg(pParse, r1);
150590
- selectInnerLoop(pParse, p, tab1,
150591
- 0, 0, &dest, iCont, iBreak);
150592
- sqlite3VdbeResolveLabel(v, iCont);
150593
- sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
150594
- sqlite3VdbeResolveLabel(v, iBreak);
150595
- sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
150596
- sqlite3VdbeJumpHere(v, emptyBypass);
150597
- sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
150598
- break;
150599
- }
150600
- }
150601
-
150602
- #ifndef SQLITE_OMIT_EXPLAIN
150563
+ assert( !pPrior->pLimit );
150564
+ pPrior->iLimit = p->iLimit;
150565
+ pPrior->iOffset = p->iOffset;
150566
+ pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0);
150567
+ TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
150568
+ rc = sqlite3Select(pParse, pPrior, &dest);
150569
+ sqlite3ExprDelete(db, pPrior->pLimit);
150570
+ pPrior->pLimit = 0;
150571
+ if( rc ){
150572
+ goto multi_select_end;
150573
+ }
150574
+ p->pPrior = 0;
150575
+ p->iLimit = pPrior->iLimit;
150576
+ p->iOffset = pPrior->iOffset;
150577
+ if( p->iLimit ){
150578
+ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
150579
+ VdbeComment((v, "Jump ahead if LIMIT reached"));
150580
+ if( p->iOffset ){
150581
+ sqlite3VdbeAddOp3(v, OP_OffsetLimit,
150582
+ p->iLimit, p->iOffset+1, p->iOffset);
150583
+ }
150584
+ }
150585
+ ExplainQueryPlan((pParse, 1, "UNION ALL"));
150586
+ TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
150587
+ rc = sqlite3Select(pParse, p, &dest);
150588
+ testcase( rc!=SQLITE_OK );
150589
+ pDelete = p->pPrior;
150590
+ p->pPrior = pPrior;
150591
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
150592
+ if( p->pLimit
150593
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
150594
+ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
150595
+ ){
150596
+ p->nSelectRow = sqlite3LogEst((u64)nLimit);
150597
+ }
150598
+ if( addr ){
150599
+ sqlite3VdbeJumpHere(v, addr);
150600
+ }
150601
+#ifndef SQLITE_OMIT_EXPLAIN
150603150602
if( p->pNext==0 ){
150604150603
ExplainQueryPlanPop(pParse);
150605150604
}
150606
- #endif
150607
- }
150608
- if( pParse->nErr ) goto multi_select_end;
150609
-
150610
- /* Compute collating sequences used by
150611
- ** temporary tables needed to implement the compound select.
150612
- ** Attach the KeyInfo structure to all temporary tables.
150613
- **
150614
- ** This section is run by the right-most SELECT statement only.
150615
- ** SELECT statements to the left always skip this part. The right-most
150616
- ** SELECT might also skip this part if it has no ORDER BY clause and
150617
- ** no temp tables are required.
150618
- */
150619
- if( p->selFlags & SF_UsesEphemeral ){
150620
- int i; /* Loop counter */
150621
- KeyInfo *pKeyInfo; /* Collating sequence for the result set */
150622
- Select *pLoop; /* For looping through SELECT statements */
150623
- CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
150624
- int nCol; /* Number of columns in result set */
150625
-
150626
- assert( p->pNext==0 );
150627
- assert( p->pEList!=0 );
150628
- nCol = p->pEList->nExpr;
150629
- pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
150630
- if( !pKeyInfo ){
150631
- rc = SQLITE_NOMEM_BKPT;
150632
- goto multi_select_end;
150633
- }
150634
- for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
150635
- *apColl = multiSelectCollSeq(pParse, p, i);
150636
- if( 0==*apColl ){
150637
- *apColl = db->pDfltColl;
150638
- }
150639
- }
150640
-
150641
- for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
150642
- for(i=0; i<2; i++){
150643
- int addr = pLoop->addrOpenEphm[i];
150644
- if( addr<0 ){
150645
- /* If [0] is unused then [1] is also unused. So we can
150646
- ** always safely abort as soon as the first unused slot is found */
150647
- assert( pLoop->addrOpenEphm[1]<0 );
150648
- break;
150649
- }
150650
- sqlite3VdbeChangeP2(v, addr, nCol);
150651
- sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo),
150652
- P4_KEYINFO);
150653
- pLoop->addrOpenEphm[i] = -1;
150654
- }
150655
- }
150656
- sqlite3KeyInfoUnref(pKeyInfo);
150605
+#endif
150657150606
}
150658150607
150659150608
multi_select_end:
150660150609
pDest->iSdst = dest.iSdst;
150661150610
pDest->nSdst = dest.nSdst;
@@ -150683,12 +150632,12 @@
150683150632
150684150633
/*
150685150634
** Code an output subroutine for a coroutine implementation of a
150686150635
** SELECT statement.
150687150636
**
150688
-** The data to be output is contained in pIn->iSdst. There are
150689
-** pIn->nSdst columns to be output. pDest is where the output should
150637
+** The data to be output is contained in an array of pIn->nSdst registers
150638
+** starting at register pIn->iSdst. pDest is where the output should
150690150639
** be sent.
150691150640
**
150692150641
** regReturn is the number of the register holding the subroutine
150693150642
** return address.
150694150643
**
@@ -150713,10 +150662,12 @@
150713150662
){
150714150663
Vdbe *v = pParse->pVdbe;
150715150664
int iContinue;
150716150665
int addr;
150717150666
150667
+ assert( pIn->eDest==SRT_Coroutine );
150668
+
150718150669
addr = sqlite3VdbeCurrentAddr(v);
150719150670
iContinue = sqlite3VdbeMakeLabel(pParse);
150720150671
150721150672
/* Suppress duplicates for UNION, EXCEPT, and INTERSECT
150722150673
*/
@@ -150734,26 +150685,63 @@
150734150685
150735150686
/* Suppress the first OFFSET entries if there is an OFFSET clause
150736150687
*/
150737150688
codeOffset(v, p->iOffset, iContinue);
150738150689
150739
- assert( pDest->eDest!=SRT_Exists );
150740
- assert( pDest->eDest!=SRT_Table );
150741150690
switch( pDest->eDest ){
150742150691
/* Store the result as data using a unique key.
150743150692
*/
150693
+ case SRT_Fifo:
150694
+ case SRT_DistFifo:
150695
+ case SRT_Table:
150744150696
case SRT_EphemTab: {
150745150697
int r1 = sqlite3GetTempReg(pParse);
150746150698
int r2 = sqlite3GetTempReg(pParse);
150699
+ int iParm = pDest->iSDParm;
150700
+ testcase( pDest->eDest==SRT_Table );
150701
+ testcase( pDest->eDest==SRT_EphemTab );
150702
+ testcase( pDest->eDest==SRT_Fifo );
150703
+ testcase( pDest->eDest==SRT_DistFifo );
150747150704
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
150748
- sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
150749
- sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
150705
+#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG)
150706
+ /* A destination of SRT_Table and a non-zero iSDParm2 parameter means
150707
+ ** that this is an "UPDATE ... FROM" on a virtual table or view. In this
150708
+ ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC.
150709
+ ** This does not affect operation in any way - it just allows MakeRecord
150710
+ ** to process OPFLAG_NOCHANGE values without an assert() failing. */
150711
+ if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){
150712
+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
150713
+ }
150714
+#endif
150715
+#ifndef SQLITE_OMIT_CTE
150716
+ if( pDest->eDest==SRT_DistFifo ){
150717
+ /* If the destination is DistFifo, then cursor (iParm+1) is open
150718
+ ** on an ephemeral index that is used to enforce uniqueness on the
150719
+ ** total result. At this point, we are processing the setup portion
150720
+ ** of the recursive CTE using the merge algorithm, so the results are
150721
+ ** guaranteed to be unique anyhow. But we still need to populate the
150722
+ ** (iParm+1) cursor for use by the subsequent recursive phase.
150723
+ */
150724
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,
150725
+ pIn->iSdst, pIn->nSdst);
150726
+ }
150727
+#endif
150728
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
150729
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
150750150730
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
150751150731
sqlite3ReleaseTempReg(pParse, r2);
150752150732
sqlite3ReleaseTempReg(pParse, r1);
150753150733
break;
150754150734
}
150735
+
150736
+ /* If any row exist in the result set, record that fact and abort.
150737
+ */
150738
+ case SRT_Exists: {
150739
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
150740
+ /* The LIMIT clause will terminate the loop for us */
150741
+ break;
150742
+ }
150755150743
150756150744
#ifndef SQLITE_OMIT_SUBQUERY
150757150745
/* If we are creating a set for an "expr IN (SELECT ...)".
150758150746
*/
150759150747
case SRT_Set: {
@@ -150796,14 +150784,74 @@
150796150784
}
150797150785
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
150798150786
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
150799150787
break;
150800150788
}
150789
+
150790
+#ifndef SQLITE_OMIT_CTE
150791
+ /* Write the results into a priority queue that is order according to
150792
+ ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an
150793
+ ** index with pSO->nExpr+2 columns. Build a key using pSO for the first
150794
+ ** pSO->nExpr columns, then make sure all keys are unique by adding a
150795
+ ** final OP_Sequence column. The last column is the record as a blob.
150796
+ */
150797
+ case SRT_DistQueue:
150798
+ case SRT_Queue: {
150799
+ int nKey;
150800
+ int r1, r2, r3, ii;
150801
+ ExprList *pSO;
150802
+ int iParm = pDest->iSDParm;
150803
+ pSO = pDest->pOrderBy;
150804
+ assert( pSO );
150805
+ nKey = pSO->nExpr;
150806
+ r1 = sqlite3GetTempReg(pParse);
150807
+ r2 = sqlite3GetTempRange(pParse, nKey+2);
150808
+ r3 = r2+nKey+1;
150809
+
150810
+#if 0 /* <-- Why the next block of code is commented out: (tag-20260125-a)
150811
+ **
150812
+ ** If the destination is DistQueue, then cursor (iParm+1) is open
150813
+ ** on a second ephemeral index that holds all values previously
150814
+ ** added to the queue. This code only runs during the setup phase
150815
+ ** using the merge algorithm, and so the values here are already
150816
+ ** guaranteed to be unique.
150817
+ */
150818
+ if( pDest->eDest==SRT_DistQueue ){
150819
+ addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
150820
+ pIn->iSdst, pIn->nSdst);
150821
+ VdbeCoverage(v);
150822
+ }
150823
+#endif
150824
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r3);
150825
+ if( pDest->eDest==SRT_DistQueue ){
150826
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
150827
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
150828
+ }
150829
+ for(ii=0; ii<nKey; ii++){
150830
+ sqlite3VdbeAddOp2(v, OP_SCopy,
150831
+ pIn->iSdst + pSO->a[ii].u.x.iOrderByCol - 1,
150832
+ r2+ii);
150833
+ }
150834
+ sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
150835
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
150836
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
150837
+#if 0 /* tag-20260125-a */
150838
+ if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
150839
+#endif
150840
+ sqlite3ReleaseTempReg(pParse, r1);
150841
+ sqlite3ReleaseTempRange(pParse, r2, nKey+2);
150842
+ break;
150843
+ }
150844
+#endif /* SQLITE_OMIT_CTE */
150845
+
150846
+ /* Ignore the output */
150847
+ case SRT_Discard: {
150848
+ break;
150849
+ }
150801150850
150802150851
/* If none of the above, then the result destination must be
150803
- ** SRT_Output. This routine is never called with any other
150804
- ** destination other than the ones handled above or SRT_Output.
150852
+ ** SRT_Output.
150805150853
**
150806150854
** For SRT_Output, results are stored in a sequence of registers.
150807150855
** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
150808150856
** return the next row of result.
150809150857
*/
@@ -150827,12 +150875,13 @@
150827150875
150828150876
return addr;
150829150877
}
150830150878
150831150879
/*
150832
-** Alternative compound select code generator for cases when there
150833
-** is an ORDER BY clause.
150880
+** Generate code for a compound SELECT statement using a merge
150881
+** algorithm. The compound must have an ORDER BY clause for this
150882
+** to work.
150834150883
**
150835150884
** We assume a query of the following form:
150836150885
**
150837150886
** <selectA> <operator> <selectB> ORDER BY <orderbylist>
150838150887
**
@@ -150845,11 +150894,11 @@
150845150894
** outA: Move the output of the selectA coroutine into the output
150846150895
** of the compound query.
150847150896
**
150848150897
** outB: Move the output of the selectB coroutine into the output
150849150898
** of the compound query. (Only generated for UNION and
150850
-** UNION ALL. EXCEPT and INSERTSECT never output a row that
150899
+** UNION ALL. EXCEPT and INTERSECT never output a row that
150851150900
** appears only in B.)
150852150901
**
150853150902
** AltB: Called when there is data from both coroutines and A<B.
150854150903
**
150855150904
** AeqB: Called when there is data from both coroutines and A==B.
@@ -150898,25 +150947,23 @@
150898150947
** EofB: ...
150899150948
** AltB: ...
150900150949
** AeqB: ...
150901150950
** AgtB: ...
150902150951
** Init: initialize coroutine registers
150903
-** yield coA
150904
-** if eof(A) goto EofA
150905
-** yield coB
150906
-** if eof(B) goto EofB
150952
+** yield coA, on eof goto EofA
150953
+** yield coB, on eof goto EofB
150907150954
** Cmpr: Compare A, B
150908150955
** Jump AltB, AeqB, AgtB
150909150956
** End: ...
150910150957
**
150911150958
** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
150912150959
** actually called using Gosub and they do not Return. EofA and EofB loop
150913150960
** until all data is exhausted then jump to the "end" label. AltB, AeqB,
150914
-** and AgtB jump to either L2 or to one of EofA or EofB.
150961
+** and AgtB jump to either Cmpr or to one of EofA or EofB.
150915150962
*/
150916150963
#ifndef SQLITE_OMIT_COMPOUND_SELECT
150917
-static int multiSelectOrderBy(
150964
+static int multiSelectByMerge(
150918150965
Parse *pParse, /* Parsing context */
150919150966
Select *p, /* The right-most of SELECTs to be coded */
150920150967
SelectDest *pDest /* What to do with query results */
150921150968
){
150922150969
int i, j; /* Loop counters */
@@ -150993,30 +151040,33 @@
150993151040
}
150994151041
}
150995151042
}
150996151043
150997151044
/* Compute the comparison permutation and keyinfo that is used with
150998
- ** the permutation used to determine if the next
150999
- ** row of results comes from selectA or selectB. Also add explicit
151000
- ** collations to the ORDER BY clause terms so that when the subqueries
151001
- ** to the right and the left are evaluated, they use the correct
151002
- ** collation.
151045
+ ** the permutation to determine if the next row of results comes
151046
+ ** from selectA or selectB. Also add literal collations to the
151047
+ ** ORDER BY clause terms so that when selectA and selectB are
151048
+ ** evaluated, they use the correct collation.
151003151049
*/
151004151050
aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
151005151051
if( aPermute ){
151006151052
struct ExprList_item *pItem;
151053
+ int bKeep = 0;
151007151054
aPermute[0] = nOrderBy;
151008151055
for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
151009151056
assert( pItem!=0 );
151010151057
assert( pItem->u.x.iOrderByCol>0 );
151011151058
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
151012151059
aPermute[i] = pItem->u.x.iOrderByCol - 1;
151060
+ if( aPermute[i]!=(u32)i-1 ) bKeep = 1;
151013151061
}
151014
- pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
151015
- }else{
151016
- pKeyMerge = 0;
151062
+ if( bKeep==0 ){
151063
+ sqlite3DbFreeNN(db, aPermute);
151064
+ aPermute = 0;
151065
+ }
151017151066
}
151067
+ pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1);
151018151068
151019151069
/* Allocate a range of temporary registers and the KeyInfo needed
151020151070
** for the logic that removes duplicate result rows when the
151021151071
** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
151022151072
*/
@@ -151091,11 +151141,11 @@
151091151141
/* Generate a coroutine to evaluate the SELECT statement to the
151092151142
** left of the compound operator - the "A" select.
151093151143
*/
151094151144
addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
151095151145
addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
151096
- VdbeComment((v, "left SELECT"));
151146
+ VdbeComment((v, "SUBR: next-A"));
151097151147
pPrior->iLimit = regLimitA;
151098151148
ExplainQueryPlan((pParse, 1, "LEFT"));
151099151149
sqlite3Select(pParse, pPrior, &destA);
151100151150
sqlite3VdbeEndCoroutine(v, regAddrA);
151101151151
sqlite3VdbeJumpHere(v, addr1);
@@ -151103,11 +151153,11 @@
151103151153
/* Generate a coroutine to evaluate the SELECT statement on
151104151154
** the right - the "B" select
151105151155
*/
151106151156
addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
151107151157
addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
151108
- VdbeComment((v, "right SELECT"));
151158
+ VdbeComment((v, "SUBR: next-B"));
151109151159
savedLimit = p->iLimit;
151110151160
savedOffset = p->iOffset;
151111151161
p->iLimit = regLimitB;
151112151162
p->iOffset = 0;
151113151163
ExplainQueryPlan((pParse, 1, "RIGHT"));
@@ -151117,20 +151167,20 @@
151117151167
sqlite3VdbeEndCoroutine(v, regAddrB);
151118151168
151119151169
/* Generate a subroutine that outputs the current row of the A
151120151170
** select as the next output row of the compound select.
151121151171
*/
151122
- VdbeNoopComment((v, "Output routine for A"));
151172
+ VdbeNoopComment((v, "SUBR: out-A"));
151123151173
addrOutA = generateOutputSubroutine(pParse,
151124151174
p, &destA, pDest, regOutA,
151125151175
regPrev, pKeyDup, labelEnd);
151126151176
151127151177
/* Generate a subroutine that outputs the current row of the B
151128151178
** select as the next output row of the compound select.
151129151179
*/
151130151180
if( op==TK_ALL || op==TK_UNION ){
151131
- VdbeNoopComment((v, "Output routine for B"));
151181
+ VdbeNoopComment((v, "SUBR: out-B"));
151132151182
addrOutB = generateOutputSubroutine(pParse,
151133151183
p, &destB, pDest, regOutB,
151134151184
regPrev, pKeyDup, labelEnd);
151135151185
}
151136151186
sqlite3KeyInfoUnref(pKeyDup);
@@ -151139,14 +151189,16 @@
151139151189
** are exhausted and only data in select B remains.
151140151190
*/
151141151191
if( op==TK_EXCEPT || op==TK_INTERSECT ){
151142151192
addrEofA_noB = addrEofA = labelEnd;
151143151193
}else{
151144
- VdbeNoopComment((v, "eof-A subroutine"));
151194
+ VdbeNoopComment((v, "SUBR: eof-A"));
151145151195
addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
151196
+ VdbeComment((v, "out-B"));
151146151197
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
151147151198
VdbeCoverage(v);
151199
+ VdbeComment((v, "next-B"));
151148151200
sqlite3VdbeGoto(v, addrEofA);
151149151201
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
151150151202
}
151151151203
151152151204
/* Generate a subroutine to run when the results from select B
@@ -151154,21 +151206,24 @@
151154151206
*/
151155151207
if( op==TK_INTERSECT ){
151156151208
addrEofB = addrEofA;
151157151209
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
151158151210
}else{
151159
- VdbeNoopComment((v, "eof-B subroutine"));
151211
+ VdbeNoopComment((v, "SUBR: eof-B"));
151160151212
addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
151213
+ VdbeComment((v, "out-A"));
151161151214
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
151215
+ VdbeComment((v, "next-A"));
151162151216
sqlite3VdbeGoto(v, addrEofB);
151163151217
}
151164151218
151165151219
/* Generate code to handle the case of A<B
151166151220
*/
151167
- VdbeNoopComment((v, "A-lt-B subroutine"));
151168151221
addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
151222
+ VdbeComment((v, "out-A"));
151169151223
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
151224
+ VdbeComment((v, "next-A"));
151170151225
sqlite3VdbeGoto(v, labelCmpr);
151171151226
151172151227
/* Generate code to handle the case of A==B
151173151228
*/
151174151229
if( op==TK_ALL ){
@@ -151175,40 +151230,52 @@
151175151230
addrAeqB = addrAltB;
151176151231
}else if( op==TK_INTERSECT ){
151177151232
addrAeqB = addrAltB;
151178151233
addrAltB++;
151179151234
}else{
151180
- VdbeNoopComment((v, "A-eq-B subroutine"));
151181
- addrAeqB =
151182
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
151183
- sqlite3VdbeGoto(v, labelCmpr);
151235
+ addrAeqB = addrAltB + 1;
151184151236
}
151185151237
151186151238
/* Generate code to handle the case of A>B
151187151239
*/
151188
- VdbeNoopComment((v, "A-gt-B subroutine"));
151189151240
addrAgtB = sqlite3VdbeCurrentAddr(v);
151190151241
if( op==TK_ALL || op==TK_UNION ){
151191151242
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
151243
+ VdbeComment((v, "out-B"));
151244
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
151245
+ VdbeComment((v, "next-B"));
151246
+ sqlite3VdbeGoto(v, labelCmpr);
151247
+ }else{
151248
+ addrAgtB++; /* Just do next-B. Might as well use the next-B call
151249
+ ** in the next code block */
151192151250
}
151193
- sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
151194
- sqlite3VdbeGoto(v, labelCmpr);
151195151251
151196151252
/* This code runs once to initialize everything.
151197151253
*/
151198151254
sqlite3VdbeJumpHere(v, addr1);
151199151255
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
151256
+ VdbeComment((v, "next-A"));
151257
+ /* v--- Also the A>B case for EXCEPT and INTERSECT */
151200151258
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
151259
+ VdbeComment((v, "next-B"));
151201151260
151202151261
/* Implement the main merge loop
151203151262
*/
151263
+ if( aPermute!=0 ){
151264
+ sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
151265
+ }
151204151266
sqlite3VdbeResolveLabel(v, labelCmpr);
151205
- sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
151206151267
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
151207151268
(char*)pKeyMerge, P4_KEYINFO);
151208
- sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
151209
- sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
151269
+ if( aPermute!=0 ){
151270
+ sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
151271
+ }
151272
+ sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
151273
+ VdbeCoverageIf(v, op==TK_ALL);
151274
+ VdbeCoverageIf(v, op==TK_UNION);
151275
+ VdbeCoverageIf(v, op==TK_EXCEPT);
151276
+ VdbeCoverageIf(v, op==TK_INTERSECT);
151210151277
151211151278
/* Jump to the this point in order to terminate the query.
151212151279
*/
151213151280
sqlite3VdbeResolveLabel(v, labelEnd);
151214151281
@@ -152121,11 +152188,11 @@
152121152188
pItem->fg.jointype |= (jointype & JT_LTORJ);
152122152189
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
152123152190
}
152124152191
pSubitem->fg.jointype |= jointype;
152125152192
152126
- /* Now begin substituting subquery result set expressions for
152193
+ /* Begin substituting subquery result set expressions for
152127152194
** references to the iParent in the outer query.
152128152195
**
152129152196
** Example:
152130152197
**
152131152198
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
@@ -152133,21 +152200,21 @@
152133152200
** \_____________________ outer query ______________________________/
152134152201
**
152135152202
** We look at every expression in the outer query and every place we see
152136152203
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
152137152204
*/
152138
- if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){
152205
+ if( pSub->pOrderBy ){
152139152206
/* At this point, any non-zero iOrderByCol values indicate that the
152140152207
** ORDER BY column expression is identical to the iOrderByCol'th
152141152208
** expression returned by SELECT statement pSub. Since these values
152142152209
** do not necessarily correspond to columns in SELECT statement pParent,
152143152210
** zero them before transferring the ORDER BY clause.
152144152211
**
152145152212
** Not doing this may cause an error if a subsequent call to this
152146
- ** function attempts to flatten a compound sub-query into pParent
152147
- ** (the only way this can happen is if the compound sub-query is
152148
- ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
152213
+ ** function attempts to flatten a compound sub-query into pParent.
152214
+ ** See ticket [d11a6e908f].
152215
+ */
152149152216
ExprList *pOrderBy = pSub->pOrderBy;
152150152217
for(i=0; i<pOrderBy->nExpr; i++){
152151152218
pOrderBy->a[i].u.x.iOrderByCol = 0;
152152152219
}
152153152220
assert( pParent->pOrderBy==0 );
@@ -152995,18 +153062,18 @@
152995153062
** These are rewritten as a subquery:
152996153063
**
152997153064
** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2)
152998153065
** ORDER BY ... COLLATE ...
152999153066
**
153000
-** This transformation is necessary because the multiSelectOrderBy() routine
153067
+** This transformation is necessary because the multiSelectByMerge() routine
153001153068
** above that generates the code for a compound SELECT with an ORDER BY clause
153002153069
** uses a merge algorithm that requires the same collating sequence on the
153003153070
** result columns as on the ORDER BY clause. See ticket
153004153071
** http://sqlite.org/src/info/6709574d2a
153005153072
**
153006153073
** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
153007
-** The UNION ALL operator works fine with multiSelectOrderBy() even when
153074
+** The UNION ALL operator works fine with multiSelectByMerge() even when
153008153075
** there are COLLATE terms in the ORDER BY.
153009153076
*/
153010153077
static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
153011153078
int i;
153012153079
Select *pNew;
@@ -153548,11 +153615,11 @@
153548153615
}
153549153616
sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
153550153617
}
153551153618
#ifndef SQLITE_OMIT_VIRTUALTABLE
153552153619
else if( ALWAYS(IsVirtual(pTab))
153553
- && pFrom->fg.fromDDL
153620
+ && (pFrom->fg.fromDDL || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL))
153554153621
&& ALWAYS(pTab->u.vtab.p!=0)
153555153622
&& pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
153556153623
){
153557153624
sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
153558153625
pTab->zName);
@@ -154832,19 +154899,30 @@
154832154899
Expr *pSubWhere = pSub->pWhere;
154833154900
if( pSub->pSrc->nSrc==1
154834154901
&& (pSub->selFlags & SF_Aggregate)==0
154835154902
&& !pSub->pSrc->a[0].fg.isSubquery
154836154903
&& pSub->pLimit==0
154904
+ && pSub->pPrior==0
154837154905
){
154906
+ /* Before combining the sub-select with the parent, renumber the
154907
+ ** cursor used by the subselect. This is because the EXISTS expression
154908
+ ** might be a copy of another EXISTS expression from somewhere
154909
+ ** else in the tree, and in this case it is important that it use
154910
+ ** a unique cursor number. */
154911
+ sqlite3 *db = pParse->db;
154912
+ int *aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+2)*sizeof(int));
154913
+ if( aCsrMap==0 ) return;
154914
+ aCsrMap[0] = (pParse->nTab+1);
154915
+ renumberCursors(pParse, pSub, -1, aCsrMap);
154916
+ sqlite3DbFree(db, aCsrMap);
154917
+
154838154918
memset(pWhere, 0, sizeof(*pWhere));
154839154919
pWhere->op = TK_INTEGER;
154840154920
pWhere->u.iValue = 1;
154841154921
ExprSetProperty(pWhere, EP_IntValue);
154842
-
154843154922
assert( p->pWhere!=0 );
154844154923
pSub->pSrc->a[0].fg.fromExists = 1;
154845
- pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
154846154924
p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc);
154847154925
if( pSubWhere ){
154848154926
p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere);
154849154927
pSub->pWhere = 0;
154850154928
}
@@ -154969,10 +155047,34 @@
154969155047
memset(&sCtx, 0, sizeof(sCtx));
154970155048
sCtx.pSrc = pSelect->pSrc;
154971155049
sqlite3WalkExprNN(&w, pSelect->pWhere);
154972155050
pSelect->selFlags &= ~SF_OnToWhere;
154973155051
}
155052
+
155053
+/*
155054
+** If p2 exists and p1 and p2 have the same number of terms, then change
155055
+** every term of p1 to have the same sort order as p2 and return true.
155056
+**
155057
+** If p2 is NULL or p1 and p2 are different lengths, then make no changes
155058
+** and return false.
155059
+**
155060
+** p1 must be non-NULL.
155061
+*/
155062
+static int sqlite3CopySortOrder(ExprList *p1, ExprList *p2){
155063
+ assert( p1 );
155064
+ if( p2 && p1->nExpr==p2->nExpr ){
155065
+ int ii;
155066
+ for(ii=0; ii<p1->nExpr; ii++){
155067
+ u8 sortFlags;
155068
+ sortFlags = p2->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
155069
+ p1->a[ii].fg.sortFlags = sortFlags;
155070
+ }
155071
+ return 1;
155072
+ }else{
155073
+ return 0;
155074
+ }
155075
+}
154974155076
154975155077
/*
154976155078
** Generate byte-code for the SELECT statement given in the p argument.
154977155079
**
154978155080
** The results are returned according to the SelectDest structure.
@@ -155065,12 +155167,11 @@
155065155167
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
155066155168
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
155067155169
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
155068155170
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
155069155171
if( IgnorableDistinct(pDest) ){
155070
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
155071
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
155172
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Discard ||
155072155173
pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
155073155174
/* All of these destinations are also able to ignore the ORDER BY clause */
155074155175
if( p->pOrderBy ){
155075155176
#if TREETRACE_ENABLED
155076155177
TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n"));
@@ -155082,11 +155183,10 @@
155082155183
p->pOrderBy);
155083155184
testcase( pParse->earlyCleanup );
155084155185
p->pOrderBy = 0;
155085155186
}
155086155187
p->selFlags &= ~(u32)SF_Distinct;
155087
- p->selFlags |= SF_NoopOrderBy;
155088155188
}
155089155189
sqlite3SelectPrep(pParse, p, 0);
155090155190
if( pParse->nErr ){
155091155191
goto select_end;
155092155192
}
@@ -155622,11 +155722,12 @@
155622155722
** used for both the ORDER BY and DISTINCT processing. As originally
155623155723
** written the query must use a temp-table for at least one of the ORDER
155624155724
** BY and DISTINCT, and an index or separate temp-table for the other.
155625155725
*/
155626155726
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
155627
- && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
155727
+ && sqlite3CopySortOrder(pEList, sSort.pOrderBy)
155728
+ && sqlite3ExprListCompare(pEList, sSort.pOrderBy, -1)==0
155628155729
&& OptimizationEnabled(db, SQLITE_GroupByOrder)
155629155730
#ifndef SQLITE_OMIT_WINDOWFUNC
155630155731
&& p->pWin==0
155631155732
#endif
155632155733
){
@@ -155836,25 +155937,14 @@
155836155937
** in the correct order. It also may not - the GROUP BY might use a
155837155938
** database index that causes rows to be grouped together as required
155838155939
** but not actually sorted. Either way, record the fact that the
155839155940
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
155840155941
** variable. */
155841
- if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){
155842
- int ii;
155843
- /* The GROUP BY processing doesn't care whether rows are delivered in
155844
- ** ASC or DESC order - only that each group is returned contiguously.
155845
- ** So set the ASC/DESC flags in the GROUP BY to match those in the
155846
- ** ORDER BY to maximize the chances of rows being delivered in an
155847
- ** order that makes the ORDER BY redundant. */
155848
- for(ii=0; ii<pGroupBy->nExpr; ii++){
155849
- u8 sortFlags;
155850
- sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
155851
- pGroupBy->a[ii].fg.sortFlags = sortFlags;
155852
- }
155853
- if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
155854
- orderByGrp = 1;
155855
- }
155942
+ if( sqlite3CopySortOrder(pGroupBy, sSort.pOrderBy)
155943
+ && sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0
155944
+ ){
155945
+ orderByGrp = 1;
155856155946
}
155857155947
}else{
155858155948
assert( 0==sqlite3LogEst(1) );
155859155949
p->nSelectRow = 0;
155860155950
}
@@ -156849,15 +156939,20 @@
156849156939
}
156850156940
goto trigger_cleanup;
156851156941
}
156852156942
}
156853156943
156944
+ /* NB: The SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES compile-time option is
156945
+ ** experimental and unsupported. Do not use it unless understand the
156946
+ ** implications and you cannot get by without this capability. */
156947
+#if !defined(SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES) /* Experimental */
156854156948
/* Do not create a trigger on a system table */
156855156949
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
156856156950
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
156857156951
goto trigger_cleanup;
156858156952
}
156953
+#endif
156859156954
156860156955
/* INSTEAD of triggers are only for views and views only support INSTEAD
156861156956
** of triggers.
156862156957
*/
156863156958
if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
@@ -160118,13 +160213,15 @@
160118160213
if( rc!=SQLITE_OK ) goto end_of_vacuum;
160119160214
assert( (db->nDb-1)==nDb );
160120160215
pDb = &db->aDb[nDb];
160121160216
assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
160122160217
pTemp = pDb->pBt;
160218
+ nRes = sqlite3BtreeGetRequestedReserve(pMain);
160123160219
if( pOut ){
160124160220
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
160125160221
i64 sz = 0;
160222
+ const char *zFilename;
160126160223
if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
160127160224
rc = SQLITE_ERROR;
160128160225
sqlite3SetString(pzErrMsg, db, "output file already exists");
160129160226
goto end_of_vacuum;
160130160227
}
@@ -160132,12 +160229,20 @@
160132160229
160133160230
/* For a VACUUM INTO, the pager-flags are set to the same values as
160134160231
** they are for the database being vacuumed, except that PAGER_CACHESPILL
160135160232
** is always set. */
160136160233
pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK);
160234
+
160235
+ /* If the VACUUM INTO target file is a URI filename and if the
160236
+ ** "reserve=N" query parameter is present, reset the reserve to the
160237
+ ** amount specified, if the amount is within range */
160238
+ zFilename = sqlite3BtreeGetFilename(pTemp);
160239
+ if( ALWAYS(zFilename) ){
160240
+ int nNew = (int)sqlite3_uri_int64(zFilename, "reserve", nRes);
160241
+ if( nNew>=0 && nNew<=255 ) nRes = nNew;
160242
+ }
160137160243
}
160138
- nRes = sqlite3BtreeGetRequestedReserve(pMain);
160139160244
160140160245
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
160141160246
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
160142160247
sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL);
160143160248
@@ -165646,10 +165751,38 @@
165646165751
sqlite3ValueFree(pVal);
165647165752
return rc;
165648165753
}
165649165754
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
165650165755
165756
+/*
165757
+** If pExpr is one of "like", "glob", "match", or "regexp", then
165758
+** return the corresponding SQLITE_INDEX_CONSTRAINT_xxxx value.
165759
+** If not, return 0.
165760
+**
165761
+** pExpr is guaranteed to be a TK_FUNCTION.
165762
+*/
165763
+SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr *pExpr){
165764
+ static const struct {
165765
+ const char *zOp;
165766
+ unsigned char eOp;
165767
+ } aOp[] = {
165768
+ { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
165769
+ { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
165770
+ { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
165771
+ { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
165772
+ };
165773
+ int i;
165774
+ assert( pExpr->op==TK_FUNCTION );
165775
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
165776
+ for(i=0; i<ArraySize(aOp); i++){
165777
+ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
165778
+ return aOp[i].eOp;
165779
+ }
165780
+ }
165781
+ return 0;
165782
+}
165783
+
165651165784
165652165785
#ifndef SQLITE_OMIT_VIRTUALTABLE
165653165786
/*
165654165787
** Check to see if the pExpr expression is a form that needs to be passed
165655165788
** to the xBestIndex method of virtual tables. Forms of interest include:
@@ -165682,19 +165815,10 @@
165682165815
unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
165683165816
Expr **ppLeft, /* Column expression to left of MATCH/op2 */
165684165817
Expr **ppRight /* Expression to left of MATCH/op2 */
165685165818
){
165686165819
if( pExpr->op==TK_FUNCTION ){
165687
- static const struct Op2 {
165688
- const char *zOp;
165689
- unsigned char eOp2;
165690
- } aOp[] = {
165691
- { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
165692
- { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
165693
- { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
165694
- { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
165695
- };
165696165820
ExprList *pList;
165697165821
Expr *pCol; /* Column reference */
165698165822
int i;
165699165823
165700165824
assert( ExprUseXList(pExpr) );
@@ -165710,20 +165834,15 @@
165710165834
** vtab_column MATCH expression
165711165835
** MATCH(expression,vtab_column)
165712165836
*/
165713165837
pCol = pList->a[1].pExpr;
165714165838
assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
165715
- if( ExprIsVtab(pCol) ){
165716
- for(i=0; i<ArraySize(aOp); i++){
165717
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
165718
- if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
165719
- *peOp2 = aOp[i].eOp2;
165720
- *ppRight = pList->a[0].pExpr;
165721
- *ppLeft = pCol;
165722
- return 1;
165723
- }
165724
- }
165839
+ if( ExprIsVtab(pCol) && (i = sqlite3ExprIsLikeOperator(pExpr))!=0 ){
165840
+ *peOp2 = i;
165841
+ *ppRight = pList->a[0].pExpr;
165842
+ *ppLeft = pCol;
165843
+ return 1;
165725165844
}
165726165845
165727165846
/* We can also match against the first column of overloaded
165728165847
** functions where xFindFunction returns a value of at least
165729165848
** SQLITE_INDEX_CONSTRAINT_FUNCTION.
@@ -165853,20 +165972,26 @@
165853165972
u16 eOp = pOne->eOperator | pTwo->eOperator;
165854165973
sqlite3 *db; /* Database connection (for malloc) */
165855165974
Expr *pNew; /* New virtual expression */
165856165975
int op; /* Operator for the combined expression */
165857165976
int idxNew; /* Index in pWC of the next virtual term */
165977
+ Expr *pA, *pB; /* Expressions associated with pOne and pTwo */
165858165978
165859165979
if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
165860165980
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
165861165981
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
165862165982
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
165863165983
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
165864
- assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
165865
- assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
165866
- if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
165867
- if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
165984
+ pA = pOne->pExpr;
165985
+ pB = pTwo->pExpr;
165986
+ assert( pA->pLeft!=0 && pA->pRight!=0 );
165987
+ assert( pB->pLeft!=0 && pB->pRight!=0 );
165988
+ if( sqlite3ExprCompare(0,pA->pLeft, pB->pLeft, -1) ) return;
165989
+ if( sqlite3ExprCompare(0,pA->pRight, pB->pRight,-1) ) return;
165990
+ if( ExprHasProperty(pA,EP_Commuted)!=ExprHasProperty(pB,EP_Commuted) ){
165991
+ return;
165992
+ }
165868165993
/* If we reach this point, it means the two subterms can be combined */
165869165994
if( (eOp & (eOp-1))!=0 ){
165870165995
if( eOp & (WO_LT|WO_LE) ){
165871165996
eOp = WO_LE;
165872165997
}else{
@@ -165873,11 +165998,11 @@
165873165998
assert( eOp & (WO_GT|WO_GE) );
165874165999
eOp = WO_GE;
165875166000
}
165876166001
}
165877166002
db = pWC->pWInfo->pParse->db;
165878
- pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
166003
+ pNew = sqlite3ExprDup(db, pA, 0);
165879166004
if( pNew==0 ) return;
165880166005
for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
165881166006
pNew->op = op;
165882166007
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
165883166008
exprAnalyze(pSrc, pWC, idxNew);
@@ -168744,15 +168869,18 @@
168744168869
168745168870
/* No matches cause a break out of the loop */
168746168871
break;
168747168872
}
168748168873
if( i==n ){
168874
+ int bSortByGroup = (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0;
168749168875
nOrderBy = n;
168750168876
if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
168751
- eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
168877
+ eDistinct = 2 + bSortByGroup;
168752168878
}else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
168753
- eDistinct = 1;
168879
+ eDistinct = 1 - bSortByGroup;
168880
+ }else if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
168881
+ eDistinct = 3;
168754168882
}
168755168883
}
168756168884
}
168757168885
168758168886
/* Allocate the sqlite3_index_info structure
@@ -170158,10 +170286,71 @@
170158170286
p->u.btree.pIndex = 0;
170159170287
}
170160170288
}
170161170289
return rc;
170162170290
}
170291
+
170292
+/*
170293
+** Callback for estLikePatternLength().
170294
+**
170295
+** If this node is a string literal that is longer pWalker->sz, then set
170296
+** pWalker->sz to the byte length of that string literal.
170297
+**
170298
+** pWalker->eCode indicates how to count characters:
170299
+**
170300
+** eCode==0 Count as a GLOB pattern
170301
+** eCode==1 Count as a LIKE pattern
170302
+*/
170303
+static int exprNodePatternLengthEst(Walker *pWalker, Expr *pExpr){
170304
+ if( pExpr->op==TK_STRING ){
170305
+ int sz = 0; /* Pattern size in bytes */
170306
+ u8 *z = (u8*)pExpr->u.zToken; /* The pattern */
170307
+ u8 c; /* Next character of the pattern */
170308
+ u8 c1, c2, c3; /* Wildcards */
170309
+ if( pWalker->eCode ){
170310
+ c1 = '%';
170311
+ c2 = '_';
170312
+ c3 = 0;
170313
+ }else{
170314
+ c1 = '*';
170315
+ c2 = '?';
170316
+ c3 = '[';
170317
+ }
170318
+ while( (c = *(z++))!=0 ){
170319
+ if( c==c3 ){
170320
+ if( *z ) z++;
170321
+ while( *z && *z!=']' ) z++;
170322
+ }else if( c!=c1 && c!=c2 ){
170323
+ sz++;
170324
+ }
170325
+ }
170326
+ if( sz>pWalker->u.sz ) pWalker->u.sz = sz;
170327
+ }
170328
+ return WRC_Continue;
170329
+}
170330
+
170331
+/*
170332
+** Return the length of the longest string literal in the given
170333
+** expression.
170334
+**
170335
+** eCode indicates how to count characters:
170336
+**
170337
+** eCode==0 Count as a GLOB pattern
170338
+** eCode==1 Count as a LIKE pattern
170339
+*/
170340
+static int estLikePatternLength(Expr *p, u16 eCode){
170341
+ Walker w;
170342
+ w.u.sz = 0;
170343
+ w.eCode = eCode;
170344
+ w.xExprCallback = exprNodePatternLengthEst;
170345
+ w.xSelectCallback = sqlite3SelectWalkFail;
170346
+#ifdef SQLITE_DEBUG
170347
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
170348
+#endif
170349
+ sqlite3WalkExpr(&w, p);
170350
+ return w.u.sz;
170351
+}
170163170352
170164170353
/*
170165170354
** Adjust the WhereLoop.nOut value downward to account for terms of the
170166170355
** WHERE clause that reference the loop but which are not used by an
170167170356
** index.
@@ -170187,10 +170376,17 @@
170187170376
** of rows in the table. In other words, assume that x==EXPR will filter
170188170377
** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the
170189170378
** "x" column is boolean or else -1 or 0 or 1 is a common default value
170190170379
** on the "x" column and so in that case only cap the output row estimate
170191170380
** at 1/2 instead of 1/4.
170381
+**
170382
+** Heuristic 3: If there is a LIKE or GLOB (or REGEXP or MATCH) operator
170383
+** with a large constant pattern, then reduce the size of the search
170384
+** space according to the length of the pattern, under the theory that
170385
+** longer patterns are less likely to match. This heuristic was added
170386
+** to give better output-row count estimates when preparing queries for
170387
+** the Join-Order Benchmarks. See forum thread 2026-01-30T09:57:54z
170192170388
*/
170193170389
static void whereLoopOutputAdjust(
170194170390
WhereClause *pWC, /* The WHERE clause */
170195170391
WhereLoop *pLoop, /* The loop to adjust downward */
170196170392
LogEst nRow /* Number of rows in the entire table */
@@ -170236,25 +170432,43 @@
170236170432
** then use the probability provided by the application. */
170237170433
pLoop->nOut += pTerm->truthProb;
170238170434
}else{
170239170435
/* In the absence of explicit truth probabilities, use heuristics to
170240170436
** guess a reasonable truth probability. */
170437
+ Expr *pOpExpr = pTerm->pExpr;
170241170438
pLoop->nOut--;
170242170439
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
170243170440
&& (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
170244170441
){
170245
- Expr *pRight = pTerm->pExpr->pRight;
170442
+ Expr *pRight = pOpExpr->pRight;
170246170443
int k = 0;
170247
- testcase( pTerm->pExpr->op==TK_IS );
170444
+ testcase( pOpExpr->op==TK_IS );
170248170445
if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
170249170446
k = 10;
170250170447
}else{
170251170448
k = 20;
170252170449
}
170253170450
if( iReduce<k ){
170254170451
pTerm->wtFlags |= TERM_HEURTRUTH;
170255170452
iReduce = k;
170453
+ }
170454
+ }else
170455
+ if( ExprHasProperty(pOpExpr, EP_InfixFunc)
170456
+ && pOpExpr->op==TK_FUNCTION
170457
+ ){
170458
+ int eOp;
170459
+ assert( ExprUseXList(pOpExpr) );
170460
+ assert( pOpExpr->x.pList->nExpr>=2 );
170461
+ eOp = sqlite3ExprIsLikeOperator(pOpExpr);
170462
+ if( ALWAYS(eOp>0) ){
170463
+ int szPattern;
170464
+ Expr *pRHS = pOpExpr->x.pList->a[0].pExpr;
170465
+ eOp = eOp==SQLITE_INDEX_CONSTRAINT_LIKE;
170466
+ szPattern = estLikePatternLength(pRHS, eOp);
170467
+ if( szPattern>0 ){
170468
+ pLoop->nOut -= szPattern*2;
170469
+ }
170256170470
}
170257170471
}
170258170472
}
170259170473
}
170260170474
}
@@ -170712,10 +170926,11 @@
170712170926
170713170927
nOutUnadjusted = pNew->nOut;
170714170928
pNew->rRun += nInMul + nIn;
170715170929
pNew->nOut += nInMul + nIn;
170716170930
whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
170931
+ if( pSrc->fg.fromExists ) pNew->nOut = 0;
170717170932
rc = whereLoopInsert(pBuilder, pNew);
170718170933
170719170934
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
170720170935
pNew->nOut = saved_nOut;
170721170936
}else{
@@ -171308,10 +171523,12 @@
171308171523
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
171309171524
whereLoopOutputAdjust(pWC, pNew, rSize);
171310171525
if( pSrc->fg.isSubquery ){
171311171526
if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
171312171527
pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
171528
+ }else if( pSrc->fg.fromExists ){
171529
+ pNew->nOut = 0;
171313171530
}
171314171531
rc = whereLoopInsert(pBuilder, pNew);
171315171532
pNew->nOut = rSize;
171316171533
if( rc ) break;
171317171534
}else{
@@ -171410,10 +171627,11 @@
171410171627
/* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
171411171628
** because the cursor used to access the index might not be
171412171629
** positioned to the correct row during the right-join no-match
171413171630
** loop. */
171414171631
}else{
171632
+ if( pSrc->fg.fromExists ) pNew->nOut = 0;
171415171633
rc = whereLoopInsert(pBuilder, pNew);
171416171634
}
171417171635
pNew->nOut = rSize;
171418171636
if( rc ) break;
171419171637
}
@@ -172072,11 +172290,11 @@
172072172290
SrcItem *pItem;
172073172291
SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
172074172292
sqlite3 *db = pWInfo->pParse->db;
172075172293
int rc = SQLITE_OK;
172076172294
int bFirstPastRJ = 0;
172077
- int hasRightJoin = 0;
172295
+ int hasRightCrossJoin = 0;
172078172296
WhereLoop *pNew;
172079172297
172080172298
172081172299
/* Loop over the tables in the join, from left to right */
172082172300
pNew = pBuilder->pNew;
@@ -172099,19 +172317,38 @@
172099172317
/* Add prerequisites to prevent reordering of FROM clause terms
172100172318
** across CROSS joins and outer joins. The bFirstPastRJ boolean
172101172319
** prevents the right operand of a RIGHT JOIN from being swapped with
172102172320
** other elements even further to the right.
172103172321
**
172104
- ** The JT_LTORJ case and the hasRightJoin flag work together to
172105
- ** prevent FROM-clause terms from moving from the right side of
172106
- ** a LEFT JOIN over to the left side of that join if the LEFT JOIN
172107
- ** is itself on the left side of a RIGHT JOIN.
172322
+ ** The hasRightCrossJoin flag prevent FROM-clause terms from moving
172323
+ ** from the right side of a LEFT JOIN or CROSS JOIN over to the
172324
+ ** left side of that same join. This is a required restriction in
172325
+ ** the case of LEFT JOIN - an incorrect answer may results if it is
172326
+ ** not enforced. This restriction is not required for CROSS JOIN.
172327
+ ** It is provided merely as a means of controlling join order, under
172328
+ ** the theory that no real-world queries that care about performance
172329
+ ** actually use the CROSS JOIN syntax.
172108172330
*/
172109
- if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1;
172331
+ if( pItem->fg.jointype & (JT_LTORJ|JT_CROSS) ){
172332
+ testcase( pItem->fg.jointype & JT_LTORJ );
172333
+ testcase( pItem->fg.jointype & JT_CROSS );
172334
+ hasRightCrossJoin = 1;
172335
+ }
172110172336
mPrereq |= mPrior;
172111172337
bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
172112
- }else if( !hasRightJoin ){
172338
+ }else if( pItem->fg.fromExists ){
172339
+ /* joins that result from the EXISTS-to-JOIN optimization should not
172340
+ ** be moved to the left of any of their dependencies */
172341
+ WhereClause *pWC = &pWInfo->sWC;
172342
+ WhereTerm *pTerm;
172343
+ int i;
172344
+ for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
172345
+ if( (pNew->maskSelf & pTerm->prereqAll)!=0 ){
172346
+ mPrereq |= (pTerm->prereqAll & (pNew->maskSelf-1));
172347
+ }
172348
+ }
172349
+ }else if( !hasRightCrossJoin ){
172113172350
mPrereq = 0;
172114172351
}
172115172352
#ifndef SQLITE_OMIT_VIRTUALTABLE
172116172353
if( IsVirtual(pItem->pSTab) ){
172117172354
SrcItem *p;
@@ -172330,13 +172567,11 @@
172330172567
if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
172331172568
}else{
172332172569
pLoop = pLast;
172333172570
}
172334172571
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
172335
- if( pLoop->u.vtab.isOrdered
172336
- && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
172337
- ){
172572
+ if( pLoop->u.vtab.isOrdered && pWInfo->pOrderBy==pOrderBy ){
172338172573
obSat = obDone;
172339172574
}else{
172340172575
/* No further ORDER BY terms may be matched. So this call should
172341172576
** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
172342172577
isOrderDistinct = 0;
@@ -173673,10 +173908,11 @@
173673173908
pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
173674173909
notReady &= ~pLoop->maskSelf;
173675173910
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
173676173911
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
173677173912
pTerm->wtFlags |= TERM_CODED;
173913
+ pTerm->prereqAll = 0;
173678173914
}
173679173915
}
173680173916
if( i!=pWInfo->nLevel-1 ){
173681173917
int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
173682173918
memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
@@ -174660,26 +174896,31 @@
174660174896
VdbeCoverageIf(v, op==OP_SeekGT);
174661174897
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
174662174898
}
174663174899
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
174664174900
}
174665
- if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
174666
- /* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
174667
- ** loop(s) will be the inner-most loops of the join. There might be
174668
- ** multiple EXISTS loops, but they will all be nested, and the join
174669
- ** order will not have been changed by the query planner. If the
174670
- ** inner-most EXISTS loop sees a single successful row, it should
174671
- ** break out of *all* EXISTS loops. But only the inner-most of the
174672
- ** nested EXISTS loops should do this breakout. */
174901
+ if( pTabList->a[pLevel->iFrom].fg.fromExists
174902
+ && (i==pWInfo->nLevel-1
174903
+ || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
174904
+ ){
174905
+ /* This is an EXISTS-to-JOIN optimization which is either the
174906
+ ** inner-most loop, or the inner-most of a group of nested
174907
+ ** EXISTS-to-JOIN optimization loops. If this loop sees a successful
174908
+ ** row, it should break out of itself as well as other EXISTS-to-JOIN
174909
+ ** loops in which is is directly nested. */
174673174910
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
174674174911
while( nOuter<i ){
174675174912
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
174676174913
nOuter++;
174677174914
}
174678174915
testcase( nOuter>0 );
174679174916
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
174680
- VdbeComment((v, "EXISTS break"));
174917
+ if( nOuter ){
174918
+ VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
174919
+ }else{
174920
+ VdbeComment((v, "EXISTS break %d", i));
174921
+ }
174681174922
}
174682174923
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
174683174924
if( pLevel->op!=OP_Noop ){
174684174925
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
174685174926
sqlite3VdbeChangeP5(v, pLevel->p5);
@@ -184823,11 +185064,11 @@
184823185064
for(i=1; sqlite3Isdigit(z[i]); i++){}
184824185065
return i;
184825185066
}
184826185067
case CC_DOLLAR:
184827185068
case CC_VARALPHA: {
184828
- int n = 0;
185069
+ i64 n = 0;
184829185070
testcase( z[0]=='$' ); testcase( z[0]=='@' );
184830185071
testcase( z[0]==':' ); testcase( z[0]=='#' );
184831185072
*tokenType = TK_VARIABLE;
184832185073
for(i=1; (c=z[i])!=0; i++){
184833185074
if( IdChar(c) ){
@@ -189448,10 +189689,16 @@
189448189689
/*
189449189690
** Find existing client data.
189450189691
*/
189451189692
SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){
189452189693
DbClientData *p;
189694
+#ifdef SQLITE_ENABLE_API_ARMOR
189695
+ if( !zName || !sqlite3SafetyCheckOk(db) ){
189696
+ (void)SQLITE_MISUSE_BKPT;
189697
+ return 0;
189698
+ }
189699
+#endif
189453189700
sqlite3_mutex_enter(db->mutex);
189454189701
for(p=db->pDbData; p; p=p->pNext){
189455189702
if( strcmp(p->zName, zName)==0 ){
189456189703
void *pResult = p->pData;
189457189704
sqlite3_mutex_leave(db->mutex);
@@ -192292,10 +192539,19 @@
192292192539
SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
192293192540
192294192541
#define fts3GetVarint32(p, piVal) ( \
192295192542
(*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
192296192543
)
192544
+
192545
+SQLITE_PRIVATE int sqlite3Fts3PrepareStmt(
192546
+ Fts3Table *p, /* Prepare for this connection */
192547
+ const char *zSql, /* SQL to prepare */
192548
+ int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */
192549
+ int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */
192550
+ sqlite3_stmt **pp /* OUT: Prepared statement */
192551
+);
192552
+
192297192553
192298192554
/* fts3.c */
192299192555
SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
192300192556
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
192301192557
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
@@ -193900,13 +194156,11 @@
193900194156
p->pSeekStmt = 0;
193901194157
}else{
193902194158
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
193903194159
if( !zSql ) return SQLITE_NOMEM;
193904194160
p->bLock++;
193905
- rc = sqlite3_prepare_v3(
193906
- p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
193907
- );
194161
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt);
193908194162
p->bLock--;
193909194163
sqlite3_free(zSql);
193910194164
}
193911194165
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
193912194166
}
@@ -195477,13 +195731,11 @@
195477195731
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
195478195732
);
195479195733
}
195480195734
if( zSql ){
195481195735
p->bLock++;
195482
- rc = sqlite3_prepare_v3(
195483
- p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
195484
- );
195736
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt);
195485195737
p->bLock--;
195486195738
sqlite3_free(zSql);
195487195739
}else{
195488195740
rc = SQLITE_NOMEM;
195489195741
}
@@ -196102,10 +196354,11 @@
196102196354
int rc = SQLITE_OK;
196103196355
int bOk = 0;
196104196356
196105196357
UNUSED_PARAMETER(isQuick);
196106196358
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
196359
+ assert( pVtab->zErrMsg==0 || rc!=SQLITE_OK );
196107196360
assert( rc!=SQLITE_CORRUPT_VTAB );
196108196361
if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){
196109196362
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
196110196363
" FTS%d table %s.%s: %s",
196111196364
p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
@@ -202713,10 +202966,28 @@
202713202966
#define SQL_SELECT_MXLEVEL 36
202714202967
202715202968
#define SQL_SELECT_LEVEL_RANGE2 37
202716202969
#define SQL_UPDATE_LEVEL_IDX 38
202717202970
#define SQL_UPDATE_LEVEL 39
202971
+
202972
+/*
202973
+** Wrapper around sqlite3_prepare_v3() to ensure that SQLITE_PREPARE_FROM_DDL
202974
+** is always set.
202975
+*/
202976
+SQLITE_PRIVATE int sqlite3Fts3PrepareStmt(
202977
+ Fts3Table *p, /* Prepare for this connection */
202978
+ const char *zSql, /* SQL to prepare */
202979
+ int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */
202980
+ int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */
202981
+ sqlite3_stmt **pp /* OUT: Prepared statement */
202982
+){
202983
+ int f = SQLITE_PREPARE_FROM_DDL
202984
+ |((bAllowVtab==0) ? SQLITE_PREPARE_NO_VTAB : 0)
202985
+ |(bPersist ? SQLITE_PREPARE_PERSISTENT : 0);
202986
+
202987
+ return sqlite3_prepare_v3(p->db, zSql, -1, f, pp, NULL);
202988
+}
202718202989
202719202990
/*
202720202991
** This function is used to obtain an SQLite prepared statement handle
202721202992
** for the statement identified by the second argument. If successful,
202722202993
** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -202839,24 +203110,24 @@
202839203110
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
202840203111
assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
202841203112
202842203113
pStmt = p->aStmt[eStmt];
202843203114
if( !pStmt ){
202844
- int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
203115
+ int bAllowVtab = 0;
202845203116
char *zSql;
202846203117
if( eStmt==SQL_CONTENT_INSERT ){
202847203118
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
202848203119
}else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
202849
- f &= ~SQLITE_PREPARE_NO_VTAB;
203120
+ bAllowVtab = 1;
202850203121
zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
202851203122
}else{
202852203123
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
202853203124
}
202854203125
if( !zSql ){
202855203126
rc = SQLITE_NOMEM;
202856203127
}else{
202857
- rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
203128
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 1, bAllowVtab, &pStmt);
202858203129
sqlite3_free(zSql);
202859203130
assert( rc==SQLITE_OK || pStmt==0 );
202860203131
p->aStmt[eStmt] = pStmt;
202861203132
}
202862203133
}
@@ -206019,11 +206290,11 @@
206019206290
/* Compose and prepare an SQL statement to loop through the content table */
206020206291
char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
206021206292
if( !zSql ){
206022206293
rc = SQLITE_NOMEM;
206023206294
}else{
206024
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
206295
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt);
206025206296
sqlite3_free(zSql);
206026206297
}
206027206298
206028206299
if( rc==SQLITE_OK ){
206029206300
sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
@@ -207772,11 +208043,11 @@
207772208043
207773208044
zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
207774208045
if( !zSql ){
207775208046
rc = SQLITE_NOMEM;
207776208047
}else{
207777
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
208048
+ rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt);
207778208049
sqlite3_free(zSql);
207779208050
}
207780208051
207781208052
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
207782208053
i64 iDocid = sqlite3_column_int64(pStmt, 0);
@@ -211177,11 +211448,14 @@
211177211448
*/
211178211449
#define JSON_JSON 0x01 /* Result is always JSON */
211179211450
#define JSON_SQL 0x02 /* Result is always SQL */
211180211451
#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
211181211452
#define JSON_ISSET 0x04 /* json_set(), not json_insert() */
211182
-#define JSON_BLOB 0x08 /* Use the BLOB output format */
211453
+#define JSON_AINS 0x08 /* json_array_insert(), not json_insert() */
211454
+#define JSON_BLOB 0x10 /* Use the BLOB output format */
211455
+
211456
+#define JSON_INSERT_TYPE(X) (((X)&0xC)>>2)
211183211457
211184211458
211185211459
/* A parsed JSON value. Lifecycle:
211186211460
**
211187211461
** 1. JSON comes in and is parsed into a JSONB value in aBlob. The
@@ -211223,10 +211497,11 @@
211223211497
/* Allowed values for JsonParse.eEdit */
211224211498
#define JEDIT_DEL 1 /* Delete if exists */
211225211499
#define JEDIT_REPL 2 /* Overwrite if exists */
211226211500
#define JEDIT_INS 3 /* Insert if not exists */
211227211501
#define JEDIT_SET 4 /* Insert or overwrite */
211502
+#define JEDIT_AINS 5 /* array_insert() */
211228211503
211229211504
/*
211230211505
** Maximum nesting depth of JSON for this implementation.
211231211506
**
211232211507
** This limit is needed to avoid a stack overflow in the recursive
@@ -213719,11 +213994,12 @@
213719213994
/*
213720213995
** Error returns from jsonLookupStep()
213721213996
*/
213722213997
#define JSON_LOOKUP_ERROR 0xffffffff
213723213998
#define JSON_LOOKUP_NOTFOUND 0xfffffffe
213724
-#define JSON_LOOKUP_PATHERROR 0xfffffffd
213999
+#define JSON_LOOKUP_NOTARRAY 0xfffffffd
214000
+#define JSON_LOOKUP_PATHERROR 0xfffffffc
213725214001
#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR)
213726214002
213727214003
/* Forward declaration */
213728214004
static u32 jsonLookupStep(JsonParse*,u32,const char*,u32);
213729214005
@@ -213748,11 +214024,11 @@
213748214024
** using the substructure.
213749214025
*/
213750214026
static u32 jsonCreateEditSubstructure(
213751214027
JsonParse *pParse, /* The original JSONB that is being edited */
213752214028
JsonParse *pIns, /* Populate this with the blob data to insert */
213753
- const char *zTail /* Tail of the path that determins substructure */
214029
+ const char *zTail /* Tail of the path that determines substructure */
213754214030
){
213755214031
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
213756214032
int rc;
213757214033
memset(pIns, 0, sizeof(*pIns));
213758214034
pIns->db = pParse->db;
@@ -213783,13 +214059,13 @@
213783214059
** label, before returning.
213784214060
**
213785214061
** Return one of the JSON_LOOKUP error codes if problems are seen.
213786214062
**
213787214063
** This routine will also modify the blob. If pParse->eEdit is one of
213788
-** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be
213789
-** made to the selected value. If an edit is performed, then the return
213790
-** value does not necessarily point to the select element. If an edit
214064
+** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, JEDIT_SET, or JEDIT_AINS, then changes
214065
+** might be made to the selected value. If an edit is performed, then the
214066
+** return value does not necessarily point to the select element. If an edit
213791214067
** is performed, the return value is only useful for detecting error
213792214068
** conditions.
213793214069
*/
213794214070
static u32 jsonLookupStep(
213795214071
JsonParse *pParse, /* The JSON to search */
@@ -213811,10 +214087,17 @@
213811214087
iRoot = iLabel;
213812214088
}
213813214089
jsonBlobEdit(pParse, iRoot, sz, 0, 0);
213814214090
}else if( pParse->eEdit==JEDIT_INS ){
213815214091
/* Already exists, so json_insert() is a no-op */
214092
+ }else if( pParse->eEdit==JEDIT_AINS ){
214093
+ /* json_array_insert() */
214094
+ if( zPath[-1]!=']' ){
214095
+ return JSON_LOOKUP_NOTARRAY;
214096
+ }else{
214097
+ jsonBlobEdit(pParse, iRoot, 0, pParse->aIns, pParse->nIns);
214098
+ }
213816214099
}else{
213817214100
/* json_set() or json_replace() */
213818214101
jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns);
213819214102
}
213820214103
}
@@ -213882,10 +214165,14 @@
213882214165
u32 nIns; /* Total bytes to insert (label+value) */
213883214166
JsonParse v; /* BLOB encoding of the value to be inserted */
213884214167
JsonParse ix; /* Header of the label to be inserted */
213885214168
testcase( pParse->eEdit==JEDIT_INS );
213886214169
testcase( pParse->eEdit==JEDIT_SET );
214170
+ testcase( pParse->eEdit==JEDIT_AINS );
214171
+ if( pParse->eEdit==JEDIT_AINS && sqlite3_strglob("*]",&zPath[i])!=0 ){
214172
+ return JSON_LOOKUP_NOTARRAY;
214173
+ }
213887214174
memset(&ix, 0, sizeof(ix));
213888214175
ix.db = pParse->db;
213889214176
jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
213890214177
pParse->oom |= ix.oom;
213891214178
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
@@ -213909,32 +214196,36 @@
213909214196
jsonParseReset(&v);
213910214197
jsonParseReset(&ix);
213911214198
return rc;
213912214199
}
213913214200
}else if( zPath[0]=='[' ){
214201
+ u64 kk = 0;
213914214202
x = pParse->aBlob[iRoot] & 0x0f;
213915214203
if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND;
213916214204
n = jsonbPayloadSize(pParse, iRoot, &sz);
213917
- k = 0;
213918214205
i = 1;
213919214206
while( sqlite3Isdigit(zPath[i]) ){
213920
- k = k*10 + zPath[i] - '0';
214207
+ if( kk<0xffffffff ) kk = kk*10 + zPath[i] - '0';
214208
+ /* ^^^^^^^^^^--- Allow kk to be bigger than any JSON array so that
214209
+ ** we get NOTFOUND instead of PATHERROR, without overflowing kk. */
213921214210
i++;
213922214211
}
213923214212
if( i<2 || zPath[i]!=']' ){
213924214213
if( zPath[1]=='#' ){
213925
- k = jsonbArrayCount(pParse, iRoot);
214214
+ kk = jsonbArrayCount(pParse, iRoot);
213926214215
i = 2;
213927214216
if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
213928
- unsigned int nn = 0;
214217
+ u64 nn = 0;
213929214218
i = 3;
213930214219
do{
213931
- nn = nn*10 + zPath[i] - '0';
214220
+ if( nn<0xffffffff ) nn = nn*10 + zPath[i] - '0';
214221
+ /* ^^^^^^^^^^--- Allow nn to be bigger than any JSON array to
214222
+ ** get NOTFOUND instead of PATHERROR, without overflowing nn. */
213932214223
i++;
213933214224
}while( sqlite3Isdigit(zPath[i]) );
213934
- if( nn>k ) return JSON_LOOKUP_NOTFOUND;
213935
- k -= nn;
214225
+ if( nn>kk ) return JSON_LOOKUP_NOTFOUND;
214226
+ kk -= nn;
213936214227
}
213937214228
if( zPath[i]!=']' ){
213938214229
return JSON_LOOKUP_PATHERROR;
213939214230
}
213940214231
}else{
@@ -213942,25 +214233,26 @@
213942214233
}
213943214234
}
213944214235
j = iRoot+n;
213945214236
iEnd = j+sz;
213946214237
while( j<iEnd ){
213947
- if( k==0 ){
214238
+ if( kk==0 ){
213948214239
rc = jsonLookupStep(pParse, j, &zPath[i+1], 0);
213949214240
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
213950214241
return rc;
213951214242
}
213952
- k--;
214243
+ kk--;
213953214244
n = jsonbPayloadSize(pParse, j, &sz);
213954214245
if( n==0 ) return JSON_LOOKUP_ERROR;
213955214246
j += n+sz;
213956214247
}
213957214248
if( j>iEnd ) return JSON_LOOKUP_ERROR;
213958
- if( k>0 ) return JSON_LOOKUP_NOTFOUND;
214249
+ if( kk>0 ) return JSON_LOOKUP_NOTFOUND;
213959214250
if( pParse->eEdit>=JEDIT_INS ){
213960214251
JsonParse v;
213961214252
testcase( pParse->eEdit==JEDIT_INS );
214253
+ testcase( pParse->eEdit==JEDIT_AINS );
213962214254
testcase( pParse->eEdit==JEDIT_SET );
213963214255
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]);
213964214256
if( !JSON_LOOKUP_ISERROR(rc)
213965214257
&& jsonBlobMakeEditable(pParse, v.nBlob)
213966214258
){
@@ -214281,13 +214573,19 @@
214281214573
** If ctx is not NULL then push the error message into ctx and return NULL.
214282214574
** If ctx is NULL, then return the text of the error message.
214283214575
*/
214284214576
static char *jsonBadPathError(
214285214577
sqlite3_context *ctx, /* The function call containing the error */
214286
- const char *zPath /* The path with the problem */
214578
+ const char *zPath, /* The path with the problem */
214579
+ int rc /* Maybe JSON_LOOKUP_NOTARRAY */
214287214580
){
214288
- char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
214581
+ char *zMsg;
214582
+ if( rc==(int)JSON_LOOKUP_NOTARRAY ){
214583
+ zMsg = sqlite3_mprintf("not an array element: %Q", zPath);
214584
+ }else{
214585
+ zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
214586
+ }
214289214587
if( ctx==0 ) return zMsg;
214290214588
if( zMsg ){
214291214589
sqlite3_result_error(ctx, zMsg, -1);
214292214590
sqlite3_free(zMsg);
214293214591
}else{
@@ -214300,17 +214598,17 @@
214300214598
** arguments come in pairs where each pair contains a JSON path and
214301214599
** content to insert or set at that patch. Do the updates
214302214600
** and return the result.
214303214601
**
214304214602
** The specific operation is determined by eEdit, which can be one
214305
-** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET.
214603
+** of JEDIT_INS, JEDIT_REPL, JEDIT_SET, or JEDIT_AINS.
214306214604
*/
214307214605
static void jsonInsertIntoBlob(
214308214606
sqlite3_context *ctx,
214309214607
int argc,
214310214608
sqlite3_value **argv,
214311
- int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */
214609
+ int eEdit /* JEDIT_INS, JEDIT_REPL, JEDIT_SET, JEDIT_AINS */
214312214610
){
214313214611
int i;
214314214612
u32 rc = 0;
214315214613
const char *zPath = 0;
214316214614
int flgs;
@@ -214358,11 +214656,11 @@
214358214656
jsonInsertIntoBlob_patherror:
214359214657
jsonParseFree(p);
214360214658
if( rc==JSON_LOOKUP_ERROR ){
214361214659
sqlite3_result_error(ctx, "malformed JSON", -1);
214362214660
}else{
214363
- jsonBadPathError(ctx, zPath);
214661
+ jsonBadPathError(ctx, zPath, rc);
214364214662
}
214365214663
return;
214366214664
}
214367214665
214368214666
/*
@@ -214800,11 +215098,11 @@
214800215098
i = jsonLookupStep(p, 0, zPath[0]=='$' ? zPath+1 : "@", 0);
214801215099
if( JSON_LOOKUP_ISERROR(i) ){
214802215100
if( i==JSON_LOOKUP_NOTFOUND ){
214803215101
/* no-op */
214804215102
}else if( i==JSON_LOOKUP_PATHERROR ){
214805
- jsonBadPathError(ctx, zPath);
215103
+ jsonBadPathError(ctx, zPath, 0);
214806215104
}else{
214807215105
sqlite3_result_error(ctx, "malformed JSON", -1);
214808215106
}
214809215107
eErr = 1;
214810215108
i = 0;
@@ -214905,11 +215203,11 @@
214905215203
}
214906215204
jsonStringTerminate(&jx);
214907215205
j = jsonLookupStep(p, 0, jx.zBuf, 0);
214908215206
jsonStringReset(&jx);
214909215207
}else{
214910
- jsonBadPathError(ctx, zPath);
215208
+ jsonBadPathError(ctx, zPath, 0);
214911215209
goto json_extract_error;
214912215210
}
214913215211
if( j<p->nBlob ){
214914215212
if( argc==2 ){
214915215213
if( flags & JSON_JSON ){
@@ -214940,11 +215238,11 @@
214940215238
}
214941215239
}else if( j==JSON_LOOKUP_ERROR ){
214942215240
sqlite3_result_error(ctx, "malformed JSON", -1);
214943215241
goto json_extract_error;
214944215242
}else{
214945
- jsonBadPathError(ctx, zPath);
215243
+ jsonBadPathError(ctx, zPath, 0);
214946215244
goto json_extract_error;
214947215245
}
214948215246
}
214949215247
if( argc>2 ){
214950215248
jsonAppendChar(&jx, ']');
@@ -215269,11 +215567,11 @@
215269215567
rc = jsonLookupStep(p, 0, zPath+1, 0);
215270215568
if( JSON_LOOKUP_ISERROR(rc) ){
215271215569
if( rc==JSON_LOOKUP_NOTFOUND ){
215272215570
continue; /* No-op */
215273215571
}else if( rc==JSON_LOOKUP_PATHERROR ){
215274
- jsonBadPathError(ctx, zPath);
215572
+ jsonBadPathError(ctx, zPath, rc);
215275215573
}else{
215276215574
sqlite3_result_error(ctx, "malformed JSON", -1);
215277215575
}
215278215576
goto json_remove_done;
215279215577
}
@@ -215281,11 +215579,11 @@
215281215579
jsonReturnParse(ctx, p);
215282215580
jsonParseFree(p);
215283215581
return;
215284215582
215285215583
json_remove_patherror:
215286
- jsonBadPathError(ctx, zPath);
215584
+ jsonBadPathError(ctx, zPath, 0);
215287215585
215288215586
json_remove_done:
215289215587
jsonParseFree(p);
215290215588
return;
215291215589
}
@@ -215325,20 +215623,22 @@
215325215623
static void jsonSetFunc(
215326215624
sqlite3_context *ctx,
215327215625
int argc,
215328215626
sqlite3_value **argv
215329215627
){
215330
-
215331215628
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215332
- int bIsSet = (flags&JSON_ISSET)!=0;
215629
+ int eInsType = JSON_INSERT_TYPE(flags);
215630
+ static const char *azInsType[] = { "insert", "set", "array_insert" };
215631
+ static const u8 aEditType[] = { JEDIT_INS, JEDIT_SET, JEDIT_AINS };
215333215632
215334215633
if( argc<1 ) return;
215634
+ assert( eInsType>=0 && eInsType<=2 );
215335215635
if( (argc&1)==0 ) {
215336
- jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
215636
+ jsonWrongNumArgs(ctx, azInsType[eInsType]);
215337215637
return;
215338215638
}
215339
- jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS);
215639
+ jsonInsertIntoBlob(ctx, argc, argv, aEditType[eInsType]);
215340215640
}
215341215641
215342215642
/*
215343215643
** json_type(JSON)
215344215644
** json_type(JSON, PATH)
@@ -215359,19 +215659,19 @@
215359215659
if( p==0 ) return;
215360215660
if( argc==2 ){
215361215661
zPath = (const char*)sqlite3_value_text(argv[1]);
215362215662
if( zPath==0 ) goto json_type_done;
215363215663
if( zPath[0]!='$' ){
215364
- jsonBadPathError(ctx, zPath);
215664
+ jsonBadPathError(ctx, zPath, 0);
215365215665
goto json_type_done;
215366215666
}
215367215667
i = jsonLookupStep(p, 0, zPath+1, 0);
215368215668
if( JSON_LOOKUP_ISERROR(i) ){
215369215669
if( i==JSON_LOOKUP_NOTFOUND ){
215370215670
/* no-op */
215371215671
}else if( i==JSON_LOOKUP_PATHERROR ){
215372
- jsonBadPathError(ctx, zPath);
215672
+ jsonBadPathError(ctx, zPath, 0);
215373215673
}else{
215374215674
sqlite3_result_error(ctx, "malformed JSON", -1);
215375215675
}
215376215676
goto json_type_done;
215377215677
}
@@ -215623,16 +215923,15 @@
215623215923
jsonAppendSqlValue(pStr, argv[0]);
215624215924
}
215625215925
}
215626215926
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
215627215927
JsonString *pStr;
215928
+ int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215628215929
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
215629215930
if( pStr ){
215630
- int flags;
215631215931
pStr->pCtx = ctx;
215632215932
jsonAppendChar(pStr, ']');
215633
- flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215634215933
if( pStr->eErr ){
215635215934
jsonReturnString(pStr, 0, 0);
215636215935
return;
215637215936
}else if( flags & JSON_BLOB ){
215638215937
jsonReturnStringAsBlob(pStr);
@@ -215649,10 +215948,13 @@
215649215948
pStr->bStatic = 1;
215650215949
}else{
215651215950
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
215652215951
jsonStringTrimOneChar(pStr);
215653215952
}
215953
+ }else if( flags & JSON_BLOB ){
215954
+ static const u8 emptyArray = 0x0b;
215955
+ sqlite3_result_blob(ctx, &emptyArray, 1, SQLITE_STATIC);
215654215956
}else{
215655215957
sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
215656215958
}
215657215959
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
215658215960
}
@@ -215745,16 +216047,15 @@
215745216047
}
215746216048
}
215747216049
}
215748216050
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
215749216051
JsonString *pStr;
216052
+ int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215750216053
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
215751216054
if( pStr ){
215752
- int flags;
215753216055
jsonAppendChar(pStr, '}');
215754216056
pStr->pCtx = ctx;
215755
- flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215756216057
if( pStr->eErr ){
215757216058
jsonReturnString(pStr, 0, 0);
215758216059
return;
215759216060
}else if( flags & JSON_BLOB ){
215760216061
jsonReturnStringAsBlob(pStr);
@@ -215771,10 +216072,13 @@
215771216072
pStr->bStatic = 1;
215772216073
}else{
215773216074
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
215774216075
jsonStringTrimOneChar(pStr);
215775216076
}
216077
+ }else if( flags & JSON_BLOB ){
216078
+ static const unsigned char emptyObject = 0x0c;
216079
+ sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
215776216080
}else{
215777216081
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
215778216082
}
215779216083
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
215780216084
}
@@ -216271,11 +216575,11 @@
216271216575
if( idxNum==3 ){
216272216576
zRoot = (const char*)sqlite3_value_text(argv[1]);
216273216577
if( zRoot==0 ) return SQLITE_OK;
216274216578
if( zRoot[0]!='$' ){
216275216579
sqlite3_free(cur->pVtab->zErrMsg);
216276
- cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
216580
+ cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0);
216277216581
jsonEachCursorReset(p);
216278216582
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216279216583
}
216280216584
p->nRoot = sqlite3Strlen30(zRoot);
216281216585
if( zRoot[1]==0 ){
@@ -216289,11 +216593,11 @@
216289216593
p->eType = 0;
216290216594
p->iEnd = 0;
216291216595
return SQLITE_OK;
216292216596
}
216293216597
sqlite3_free(cur->pVtab->zErrMsg);
216294
- cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
216598
+ cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0);
216295216599
jsonEachCursorReset(p);
216296216600
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216297216601
}
216298216602
if( p->sParse.iLabel ){
216299216603
p->i = p->sParse.iLabel;
@@ -216379,10 +216683,12 @@
216379216683
/* | | | | | | */
216380216684
JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc),
216381216685
JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc),
216382216686
JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
216383216687
JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
216688
+ JFUNCTION(json_array_insert, -1,1,1, 1,0,JSON_AINS, jsonSetFunc),
216689
+ JFUNCTION(jsonb_array_insert,-1,1,0, 1,1,JSON_AINS, jsonSetFunc),
216384216690
JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
216385216691
JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
216386216692
JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
216387216693
JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc),
216388216694
JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc),
@@ -220226,11 +220532,11 @@
220226220532
tree.nBytesPerCell = 8 + 8 * tree.nDim;
220227220533
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
220228220534
if( node.zData==0 ) return;
220229220535
nData = sqlite3_value_bytes(apArg[1]);
220230220536
if( nData<4 ) return;
220231
- if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
220537
+ if( nData<4+NCELL(&node)*tree.nBytesPerCell ) return;
220232220538
220233220539
pOut = sqlite3_str_new(0);
220234220540
for(ii=0; ii<NCELL(&node); ii++){
220235220541
RtreeCell cell;
220236220542
int jj;
@@ -231218,10 +231524,11 @@
231218231524
struct carray_bind {
231219231525
void *aData; /* The data */
231220231526
int nData; /* Number of elements */
231221231527
int mFlags; /* Control flags */
231222231528
void (*xDel)(void*); /* Destructor for aData */
231529
+ void *pDel; /* Alternative argument to xDel() */
231223231530
};
231224231531
231225231532
231226231533
/* carray_cursor is a subclass of sqlite3_vtab_cursor which will
231227231534
** serve as the underlying representation of a cursor that scans
@@ -231550,26 +231857,38 @@
231550231857
** Destructor for the carray_bind object
231551231858
*/
231552231859
static void carrayBindDel(void *pPtr){
231553231860
carray_bind *p = (carray_bind*)pPtr;
231554231861
if( p->xDel!=SQLITE_STATIC ){
231555
- p->xDel(p->aData);
231862
+ p->xDel(p->pDel);
231556231863
}
231557231864
sqlite3_free(p);
231558231865
}
231559231866
231560231867
/*
231561231868
** Invoke this interface in order to bind to the single-argument
231562231869
** version of CARRAY().
231870
+**
231871
+** pStmt The prepared statement to which to bind
231872
+** idx The index of the parameter of pStmt to which to bind
231873
+** aData The data to be bound
231874
+** nData The number of elements in aData
231875
+** mFlags One of SQLITE_CARRAY_xxxx indicating datatype of aData
231876
+** xDestroy Destructor for pDestroy or aData if pDestroy==NULL.
231877
+** pDestroy Invoke xDestroy on this pointer if not NULL
231878
+**
231879
+** The destructor is called pDestroy if pDestroy!=NULL, or against
231880
+** aData if pDestroy==NULL.
231563231881
*/
231564
-SQLITE_API int sqlite3_carray_bind(
231882
+SQLITE_API int sqlite3_carray_bind_v2(
231565231883
sqlite3_stmt *pStmt,
231566231884
int idx,
231567231885
void *aData,
231568231886
int nData,
231569231887
int mFlags,
231570
- void (*xDestroy)(void*)
231888
+ void (*xDestroy)(void*),
231889
+ void *pDestroy
231571231890
){
231572231891
carray_bind *pNew = 0;
231573231892
int i;
231574231893
int rc = SQLITE_OK;
231575231894
@@ -231642,23 +231961,41 @@
231642231961
}
231643231962
}else{
231644231963
memcpy(pNew->aData, aData, sz);
231645231964
}
231646231965
pNew->xDel = sqlite3_free;
231966
+ pNew->pDel = pNew->aData;
231647231967
}else{
231648231968
pNew->aData = aData;
231649231969
pNew->xDel = xDestroy;
231970
+ pNew->pDel = pDestroy;
231650231971
}
231651231972
return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel);
231652231973
231653231974
carray_bind_error:
231654231975
if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){
231655
- xDestroy(aData);
231976
+ xDestroy(pDestroy);
231656231977
}
231657231978
sqlite3_free(pNew);
231658231979
return rc;
231659231980
}
231981
+
231982
+/*
231983
+** Invoke this interface in order to bind to the single-argument
231984
+** version of CARRAY(). Same as sqlite3_carray_bind_v2() with the
231985
+** pDestroy parameter set to NULL.
231986
+*/
231987
+SQLITE_API int sqlite3_carray_bind(
231988
+ sqlite3_stmt *pStmt,
231989
+ int idx,
231990
+ void *aData,
231991
+ int nData,
231992
+ int mFlags,
231993
+ void (*xDestroy)(void*)
231994
+){
231995
+ return sqlite3_carray_bind_v2(pStmt,idx,aData,nData,mFlags,xDestroy,aData);
231996
+}
231660231997
231661231998
/*
231662231999
** Invoke this routine to register the carray() function.
231663232000
*/
231664232001
SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3 *db){
@@ -232017,10 +232354,24 @@
232017232354
** bytes read.
232018232355
*/
232019232356
static int sessionVarintGet(const u8 *aBuf, int *piVal){
232020232357
return getVarint32(aBuf, *piVal);
232021232358
}
232359
+
232360
+/*
232361
+** Read a varint value from buffer aBuf[], size nBuf bytes, into *piVal.
232362
+** Return the number of bytes read.
232363
+*/
232364
+static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){
232365
+ u8 aCopy[5];
232366
+ const u8 *aRead = aBuf;
232367
+ if( nBuf<5 ){
232368
+ memcpy(aCopy, aBuf, nBuf);
232369
+ aRead = aCopy;
232370
+ }
232371
+ return getVarint32(aRead, *piVal);
232372
+}
232022232373
232023232374
/* Load an unaligned and unsigned 32-bit integer */
232024232375
#define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
232025232376
232026232377
/*
@@ -232312,31 +232663,31 @@
232312232663
for(i=0; i<pTab->nCol; i++){
232313232664
int eType = *a;
232314232665
int isPK = pTab->abPK[i];
232315232666
if( bPkOnly && isPK==0 ) continue;
232316232667
232317
- /* It is not possible for eType to be SQLITE_NULL here. The session
232318
- ** module does not record changes for rows with NULL values stored in
232319
- ** primary key columns. */
232320232668
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
232321232669
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
232322232670
|| eType==SQLITE_NULL || eType==0
232323232671
);
232324
- assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) );
232325232672
232326232673
if( isPK ){
232327232674
a++;
232328232675
h = sessionHashAppendType(h, eType);
232329232676
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
232330232677
h = sessionHashAppendI64(h, sessionGetI64(a));
232331232678
a += 8;
232332
- }else{
232679
+ }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
232333232680
int n;
232334232681
a += sessionVarintGet(a, &n);
232335232682
h = sessionHashAppendBlob(h, n, a);
232336232683
a += n;
232337232684
}
232685
+ /* It should not be possible for eType to be SQLITE_NULL or 0x00 here,
232686
+ ** as the session module does not record changes for rows with NULL
232687
+ ** values stored in primary key columns. But a corrupt changesets
232688
+ ** may contain such a value. */
232338232689
}else{
232339232690
a += sessionSerialLen(a);
232340232691
}
232341232692
}
232342232693
return (h % nBucket);
@@ -234741,14 +235092,17 @@
234741235092
*pnChangeset = 0;
234742235093
*ppChangeset = 0;
234743235094
}
234744235095
234745235096
if( pSession->rc ) return pSession->rc;
234746
- rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
234747
- if( rc!=SQLITE_OK ) return rc;
234748235097
234749235098
sqlite3_mutex_enter(sqlite3_db_mutex(db));
235099
+ rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
235100
+ if( rc!=SQLITE_OK ){
235101
+ sqlite3_mutex_leave(sqlite3_db_mutex(db));
235102
+ return rc;
235103
+ }
234750235104
234751235105
for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
234752235106
if( pTab->nEntry ){
234753235107
const char *zName = pTab->zName;
234754235108
int i; /* Used to iterate through hash buckets */
@@ -235227,11 +235581,12 @@
235227235581
235228235582
if( rc==SQLITE_OK ){
235229235583
u8 *aVal = &pIn->aData[pIn->iNext];
235230235584
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
235231235585
int nByte;
235232
- pIn->iNext += sessionVarintGet(aVal, &nByte);
235586
+ int nRem = pIn->nData - pIn->iNext;
235587
+ pIn->iNext += sessionVarintGetSafe(aVal, nRem, &nByte);
235233235588
rc = sessionInputBuffer(pIn, nByte);
235234235589
if( rc==SQLITE_OK ){
235235235590
if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
235236235591
rc = SQLITE_CORRUPT_BKPT;
235237235592
}else{
@@ -235280,11 +235635,12 @@
235280235635
int nCol = 0;
235281235636
int nRead = 0;
235282235637
235283235638
rc = sessionInputBuffer(pIn, 9);
235284235639
if( rc==SQLITE_OK ){
235285
- nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol);
235640
+ int nBuf = pIn->nData - pIn->iNext;
235641
+ nRead += sessionVarintGetSafe(&pIn->aData[pIn->iNext], nBuf, &nCol);
235286235642
/* The hard upper limit for the number of columns in an SQLite
235287235643
** database table is, according to sqliteLimit.h, 32676. So
235288235644
** consider any table-header that purports to have more than 65536
235289235645
** columns to be corrupt. This is convenient because otherwise,
235290235646
** if the (nCol>65536) condition below were omitted, a sufficiently
@@ -235300,12 +235656,19 @@
235300235656
235301235657
while( rc==SQLITE_OK ){
235302235658
while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){
235303235659
nRead++;
235304235660
}
235661
+
235662
+ /* Break out of the loop if if the nul-terminator byte has been found.
235663
+ ** Otherwise, read some more input data and keep seeking. If there is
235664
+ ** no more input data, consider the changeset corrupt. */
235305235665
if( (pIn->iNext + nRead)<pIn->nData ) break;
235306235666
rc = sessionInputBuffer(pIn, nRead + 100);
235667
+ if( rc==SQLITE_OK && (pIn->iNext + nRead)>=pIn->nData ){
235668
+ rc = SQLITE_CORRUPT_BKPT;
235669
+ }
235307235670
}
235308235671
*pnByte = nRead+1;
235309235672
return rc;
235310235673
}
235311235674
@@ -235433,14 +235796,14 @@
235433235796
sqlite3ValueFree(p->apValue[i]);
235434235797
}
235435235798
memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2);
235436235799
}
235437235800
235438
- /* Make sure the buffer contains at least 10 bytes of input data, or all
235439
- ** remaining data if there are less than 10 bytes available. This is
235440
- ** sufficient either for the 'T' or 'P' byte and the varint that follows
235441
- ** it, or for the two single byte values otherwise. */
235801
+ /* Make sure the buffer contains at least 2 bytes of input data, or all
235802
+ ** remaining data if there are less than 2 bytes available. This is
235803
+ ** sufficient either for the 'T' or 'P' byte that begins a new table,
235804
+ ** or for the "op" and "bIndirect" single bytes otherwise. */
235442235805
p->rc = sessionInputBuffer(&p->in, 2);
235443235806
if( p->rc!=SQLITE_OK ) return p->rc;
235444235807
235445235808
p->in.iCurrent = p->in.iNext;
235446235809
sessionDiscardData(&p->in);
@@ -235466,15 +235829,17 @@
235466235829
** corrupt changeset. */
235467235830
assert( p->in.iNext==1 || p->zTab );
235468235831
return (p->rc = SQLITE_CORRUPT_BKPT);
235469235832
}
235470235833
235471
- p->op = op;
235472
- p->bIndirect = p->in.aData[p->in.iNext++];
235473
- if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
235834
+ if( (op!=SQLITE_UPDATE && op!=SQLITE_DELETE && op!=SQLITE_INSERT)
235835
+ || (p->in.iNext>=p->in.nData)
235836
+ ){
235474235837
return (p->rc = SQLITE_CORRUPT_BKPT);
235475235838
}
235839
+ p->op = op;
235840
+ p->bIndirect = p->in.aData[p->in.iNext++];
235476235841
235477235842
if( paRec ){
235478235843
int nVal; /* Number of values to buffer */
235479235844
if( p->bPatchset==0 && op==SQLITE_UPDATE ){
235480235845
nVal = p->nCol * 2;
@@ -239307,11 +239672,17 @@
239307239672
# define FLEXARRAY
239308239673
#else
239309239674
# define FLEXARRAY 1
239310239675
#endif
239311239676
239312
-#endif
239677
+#endif /* SQLITE_AMALGAMATION */
239678
+
239679
+/*
239680
+** Constants for the largest and smallest possible 32-bit signed integers.
239681
+*/
239682
+# define LARGEST_INT32 ((int)(0x7fffffff))
239683
+# define SMALLEST_INT32 ((int)((-1) - LARGEST_INT32))
239313239684
239314239685
/* Truncate very long tokens to this many bytes. Hard limit is
239315239686
** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
239316239687
** field that occurs at the start of each leaf page (see fts5_index.c). */
239317239688
#define FTS5_MAX_TOKEN_SIZE 32768
@@ -253198,11 +253569,11 @@
253198253569
){
253199253570
const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE);
253200253571
int iSegid = pSeg->pSeg->iSegid;
253201253572
u8 *aPg = pSeg->pLeaf->p;
253202253573
int nPg = pSeg->pLeaf->nn;
253203
- int iPgIdx = pSeg->pLeaf->szLeaf;
253574
+ int iPgIdx = pSeg->pLeaf->szLeaf; /* Offset of page footer */
253204253575
253205253576
u64 iDelta = 0;
253206253577
int iNextOff = 0;
253207253578
int iOff = 0;
253208253579
int nIdx = 0;
@@ -253277,11 +253648,11 @@
253277253648
iStart = iSOP + (nPos/2);
253278253649
iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
253279253650
iSOP += fts5GetVarint32(&aPg[iSOP], nPos);
253280253651
}
253281253652
assert_nc( iSOP==pSeg->iLeafOffset );
253282
- iNextOff = pSeg->iLeafOffset + pSeg->nPos;
253653
+ iNextOff = iSOP + pSeg->nPos;
253283253654
}
253284253655
}
253285253656
253286253657
iOff = iStart;
253287253658
@@ -253357,35 +253728,35 @@
253357253728
if( iNextOff!=iPgIdx ){
253358253729
/* This is the only position-list associated with the term, and there
253359253730
** is another term following it on this page. So the subsequent term
253360253731
** needs to be moved to replace the term associated with the entry
253361253732
** being removed. */
253362
- int nPrefix = 0;
253363
- int nSuffix = 0;
253364
- int nPrefix2 = 0;
253365
- int nSuffix2 = 0;
253733
+ u64 nPrefix = 0;
253734
+ u64 nSuffix = 0;
253735
+ u64 nPrefix2 = 0;
253736
+ u64 nSuffix2 = 0;
253366253737
253367253738
iDelKeyOff = iNextOff;
253368
- iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2);
253369
- iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2);
253739
+ iNextOff += fts5GetVarint(&aPg[iNextOff], &nPrefix2);
253740
+ iNextOff += fts5GetVarint(&aPg[iNextOff], &nSuffix2);
253370253741
253371253742
if( iKey!=1 ){
253372
- iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix);
253743
+ iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nPrefix);
253373253744
}
253374
- iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix);
253745
+ iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nSuffix);
253375253746
253376253747
nPrefix = MIN(nPrefix, nPrefix2);
253377253748
nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
253378253749
253379
- if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
253750
+ if( (iKeyOff+nSuffix)>(u64)iPgIdx || (iNextOff+nSuffix2)>(u64)iPgIdx ){
253380253751
FTS5_CORRUPT_IDX(p);
253381253752
}else{
253382253753
if( iKey!=1 ){
253383253754
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
253384253755
}
253385253756
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
253386
- if( nPrefix2>pSeg->term.n ){
253757
+ if( nPrefix2>(u64)pSeg->term.n ){
253387253758
FTS5_CORRUPT_IDX(p);
253388253759
}else if( nPrefix2>nPrefix ){
253389253760
memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
253390253761
iOff += (nPrefix2-nPrefix);
253391253762
}
@@ -253412,11 +253783,11 @@
253412253783
Fts5Data *pTerm = fts5DataRead(p, iId);
253413253784
if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
253414253785
u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
253415253786
int nTermIdx = pTerm->nn - pTerm->szLeaf;
253416253787
int iTermIdx = 0;
253417
- int iTermOff = 0;
253788
+ i64 iTermOff = 0;
253418253789
253419253790
while( 1 ){
253420253791
u32 iVal = 0;
253421253792
int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal);
253422253793
iTermOff += iVal;
@@ -253423,16 +253794,19 @@
253423253794
if( (iTermIdx+nByte)>=nTermIdx ) break;
253424253795
iTermIdx += nByte;
253425253796
}
253426253797
nTermIdx = iTermIdx;
253427253798
253428
- memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
253429
- fts5PutU16(&pTerm->p[2], iTermOff);
253430
-
253431
- fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
253432
- if( nTermIdx==0 ){
253433
- fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
253799
+ if( iTermOff>pTerm->szLeaf ){
253800
+ FTS5_CORRUPT_IDX(p);
253801
+ }else{
253802
+ memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
253803
+ fts5PutU16(&pTerm->p[2], iTermOff);
253804
+ fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
253805
+ if( nTermIdx==0 ){
253806
+ fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
253807
+ }
253434253808
}
253435253809
}
253436253810
fts5DataRelease(pTerm);
253437253811
}
253438253812
}
@@ -253451,11 +253825,13 @@
253451253825
int nShift = iNextOff - iOff; /* Distance to move them */
253452253826
253453253827
int iPrevKeyOut = 0;
253454253828
int iKeyIn = 0;
253455253829
253456
- memmove(&aPg[iOff], &aPg[iNextOff], nMove);
253830
+ if( nMove>0 ){
253831
+ memmove(&aPg[iOff], &aPg[iNextOff], nMove);
253832
+ }
253457253833
iPgIdx -= nShift;
253458253834
nPg = iPgIdx;
253459253835
fts5PutU16(&aPg[2], iPgIdx);
253460253836
253461253837
for(iIdx=0; iIdx<nIdx; /* no-op */){
@@ -253889,11 +254265,11 @@
253889254265
if( nMerge<0 ){
253890254266
Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
253891254267
fts5StructureRelease(pStruct);
253892254268
pStruct = pNew;
253893254269
nMin = 1;
253894
- nMerge = nMerge*-1;
254270
+ nMerge = (nMerge==SMALLEST_INT32 ? LARGEST_INT32 : (nMerge*-1));
253895254271
}
253896254272
if( pStruct && pStruct->nLevel ){
253897254273
if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
253898254274
fts5StructureWrite(p, pStruct);
253899254275
}
@@ -261097,11 +261473,11 @@
261097261473
int nArg, /* Number of args */
261098261474
sqlite3_value **apUnused /* Function arguments */
261099261475
){
261100261476
assert( nArg==0 );
261101261477
UNUSED_PARAM2(nArg, apUnused);
261102
- sqlite3_result_text(pCtx, "fts5: 2025-12-11 18:16:39 e785a80e4100c368dca8d73cb662cff4d0fd76734fa0f3fa9b5754a380f7c746", -1, SQLITE_TRANSIENT);
261478
+ sqlite3_result_text(pCtx, "fts5: 2026-02-04 18:10:49 e6902937ecdbeb449986469859b46631272fb0a9e7e1c31adea14cff072b6d67", -1, SQLITE_TRANSIENT);
261103261479
}
261104261480
261105261481
/*
261106261482
** Implementation of fts5_locale(LOCALE, TEXT) function.
261107261483
**
261108261484
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** 01409738afc2c0d5bdaa248ffb508aa5f36a with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468 ** [sqlite_version()] and [sqlite_source_id()].
469 */
470 #define SQLITE_VERSION "3.52.0"
471 #define SQLITE_VERSION_NUMBER 3052000
472 #define SQLITE_SOURCE_ID "2025-12-11 23:24:05 01409738afc2c0d5bdaa248ffb508aa5f36a66390f6b8e4834734529ee8ed2fa"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2025-12-11T23:24:05.667Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -4752,16 +4752,32 @@
4752 ** compiles to see if some SQL syntax is well-formed, without generating
4753 ** messages on the global error log when it is not. If the test compile
4754 ** fails, the sqlite3_prepare_v3() call returns the same error indications
4755 ** with or without this flag; it just omits the call to [sqlite3_log()] that
4756 ** logs the error.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4757 ** </dl>
4758 */
4759 #define SQLITE_PREPARE_PERSISTENT 0x01
4760 #define SQLITE_PREPARE_NORMALIZE 0x02
4761 #define SQLITE_PREPARE_NO_VTAB 0x04
4762 #define SQLITE_PREPARE_DONT_LOG 0x10
 
4763
4764 /*
4765 ** CAPI3REF: Compiling An SQL Statement
4766 ** KEYWORDS: {SQL statement compiler}
4767 ** METHOD: sqlite3
@@ -4771,12 +4787,13 @@
4771 ** program using one of these routines. Or, in other words, these routines
4772 ** are constructors for the [prepared statement] object.
4773 **
4774 ** The preferred routine to use is [sqlite3_prepare_v2()]. The
4775 ** [sqlite3_prepare()] interface is legacy and should be avoided.
4776 ** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
4777 ** for special purposes.
 
4778 **
4779 ** The use of the UTF-8 interfaces is preferred, as SQLite currently
4780 ** does all parsing using UTF-8. The UTF-16 interfaces are provided
4781 ** as a convenience. The UTF-16 interfaces work by converting the
4782 ** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -5177,12 +5194,12 @@
5177 ** it should be a pointer to well-formed UTF8 text.
5178 ** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
5179 ** it should be a pointer to well-formed UTF16 text.
5180 ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
5181 ** it should be a pointer to a well-formed unicode string that is
5182 ** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
5183 ** otherwise.
5184 **
5185 ** [[byte-order determination rules]] ^The byte-order of
5186 ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
5187 ** found in the first character, which is removed, or in the absence of a BOM
5188 ** the byte order is the native byte order of the host
@@ -5224,14 +5241,19 @@
5224 ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
5225 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
5226 ** object and pointer to it must remain valid until then. ^SQLite will then
5227 ** manage the lifetime of its private copy.
5228 **
5229 ** ^The sixth argument to sqlite3_bind_text64() must be one of
5230 ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
5231 ** to specify the encoding of the text in the third parameter. If
5232 ** the sixth argument to sqlite3_bind_text64() is not one of the
 
 
 
 
 
5233 ** allowed values shown above, or if the text encoding is different
5234 ** from the encoding specified by the sixth parameter, then the behavior
5235 ** is undefined.
5236 **
5237 ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
@@ -6094,17 +6116,63 @@
6094 /*
6095 ** CAPI3REF: Text Encodings
6096 **
6097 ** These constants define integer codes that represent the various
6098 ** text encodings supported by SQLite.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6099 */
6100 #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
6101 #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
6102 #define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
6103 #define SQLITE_UTF16 4 /* Use native byte order */
6104 #define SQLITE_ANY 5 /* Deprecated */
6105 #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
 
6106
6107 /*
6108 ** CAPI3REF: Function Flags
6109 **
6110 ** These constants may be ORed together with the
@@ -6606,14 +6674,18 @@
6606 ** use for client data is to provide a mechanism for wrapper libraries
6607 ** to store additional information about an SQLite database connection.
6608 **
6609 ** There is no limit (other than available memory) on the number of different
6610 ** client data pointers (with different names) that can be attached to a
6611 ** single database connection. However, the implementation is optimized
6612 ** for the case of having only one or two different client data names.
6613 ** Applications and wrapper libraries are discouraged from using more than
6614 ** one client data name each.
 
 
 
 
6615 **
6616 ** There is no way to enumerate the client data pointers
6617 ** associated with a database connection. The N parameter can be thought
6618 ** of as a secret key such that only code that knows the secret key is able
6619 ** to access the associated data.
@@ -6717,14 +6789,18 @@
6717 ** ^The sqlite3_result_text(), sqlite3_result_text16(),
6718 ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
6719 ** set the return value of the application-defined function to be
6720 ** a text string which is represented as UTF-8, UTF-16 native byte order,
6721 ** UTF-16 little endian, or UTF-16 big endian, respectively.
6722 ** ^The sqlite3_result_text64() interface sets the return value of an
6723 ** application-defined function to be a text string in an encoding
6724 ** specified by the fifth (and last) parameter, which must be one
6725 ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
 
 
 
 
6726 ** ^SQLite takes the text result from the application from
6727 ** the 2nd parameter of the sqlite3_result_text* interfaces.
6728 ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
6729 ** other than sqlite3_result_text64() is negative, then SQLite computes
6730 ** the string length itself by searching the 2nd parameter for the first
@@ -6807,11 +6883,11 @@
6807 SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
6808 SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
6809 SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
6810 SQLITE_API void sqlite3_result_null(sqlite3_context*);
6811 SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
6812 SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
6813 void(*)(void*), unsigned char encoding);
6814 SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
6815 SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
6816 SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
6817 SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
@@ -7746,22 +7822,22 @@
7746 ** ^This interface loads an SQLite extension library from the named file.
7747 **
7748 ** ^The sqlite3_load_extension() interface attempts to load an
7749 ** [SQLite extension] library contained in the file zFile. If
7750 ** the file cannot be loaded directly, attempts are made to load
7751 ** with various operating-system specific extensions added.
7752 ** So for example, if "samplelib" cannot be loaded, then names like
7753 ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
7754 ** be tried also.
7755 **
7756 ** ^The entry point is zProc.
7757 ** ^(zProc may be 0, in which case SQLite will try to come up with an
7758 ** entry point name on its own. It first tries "sqlite3_extension_init".
7759 ** If that does not work, it constructs a name "sqlite3_X_init" where
7760 ** X consists of the lower-case equivalent of all ASCII alphabetic
7761 ** characters in the filename from the last "/" to the first following
7762 ** "." and omitting any initial "lib".)^
7763 ** ^The sqlite3_load_extension() interface returns
7764 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
7765 ** ^If an error occurs and pzErrMsg is not 0, then the
7766 ** [sqlite3_load_extension()] interface shall attempt to
7767 ** fill *pzErrMsg with error message text stored in memory
@@ -11495,23 +11571,45 @@
11495 #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
11496
11497 /*
11498 ** CAPI3REF: Bind array values to the CARRAY table-valued function
11499 **
11500 ** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
11501 ** one of the first argument of the [carray() table-valued function]. The
11502 ** S parameter is a pointer to the [prepared statement] that uses the carray()
11503 ** functions. I is the parameter index to be bound. P is a pointer to the
11504 ** array to be bound, and N is the number of eements in the array. The
11505 ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
11506 ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
11507 ** indicate the datatype of the array being bound. The X argument is not a
11508 ** NULL pointer, then SQLite will invoke the function X on the P parameter
11509 ** after it has finished using P, even if the call to
11510 ** sqlite3_carray_bind() fails. The special-case finalizer
11511 ** SQLITE_TRANSIENT has no effect here.
 
 
 
 
 
 
 
 
 
 
 
 
 
11512 */
 
 
 
 
 
 
 
 
 
11513 SQLITE_API int sqlite3_carray_bind(
11514 sqlite3_stmt *pStmt, /* Statement to be bound */
11515 int i, /* Parameter index */
11516 void *aData, /* Pointer to array data */
11517 int nData, /* Number of data elements */
@@ -14352,10 +14450,31 @@
14352 #ifndef SQLITE_MAX_LENGTH
14353 # define SQLITE_MAX_LENGTH 1000000000
14354 #endif
14355 #define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
14356
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14357 /*
14358 ** This is the maximum number of
14359 **
14360 ** * Columns in a table
14361 ** * Columns in an index
@@ -17529,11 +17648,11 @@
17529
17530 /*
17531 ** Additional non-public SQLITE_PREPARE_* flags
17532 */
17533 #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17534 #define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
17535
17536 /*
17537 ** Prototypes for the VDBE interface. See comments on the implementation
17538 ** for a description of what each of these routines does.
17539 */
@@ -20202,31 +20321,17 @@
20202 };
20203
20204 /*
20205 ** An instance of the following structure contains all information
20206 ** needed to generate code for a single SELECT statement.
20207 **
20208 ** See the header comment on the computeLimitRegisters() routine for a
20209 ** detailed description of the meaning of the iLimit and iOffset fields.
20210 **
20211 ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
20212 ** These addresses must be stored so that we can go back and fill in
20213 ** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
20214 ** the number of columns in P2 can be computed at the same time
20215 ** as the OP_OpenEphm instruction is coded because not
20216 ** enough information about the compound query is known at that point.
20217 ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
20218 ** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
20219 ** sequences for the ORDER BY clause.
20220 */
20221 struct Select {
20222 u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
20223 LogEst nSelectRow; /* Estimated number of result rows */
20224 u32 selFlags; /* Various SF_* values */
20225 int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
20226 u32 selId; /* Unique identifier number for this SELECT */
20227 int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
20228 ExprList *pEList; /* The fields of the result */
20229 SrcList *pSrc; /* The FROM clause */
20230 Expr *pWhere; /* The WHERE clause */
20231 ExprList *pGroupBy; /* The GROUP BY clause */
20232 Expr *pHaving; /* The HAVING clause */
@@ -20254,28 +20359,28 @@
20254 #define SF_Distinct 0x0000001 /* Output should be DISTINCT */
20255 #define SF_All 0x0000002 /* Includes the ALL keyword */
20256 #define SF_Resolved 0x0000004 /* Identifiers have been resolved */
20257 #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
20258 #define SF_HasAgg 0x0000010 /* Contains aggregate functions */
20259 #define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
20260 #define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
20261 #define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
20262 #define SF_Compound 0x0000100 /* Part of a compound query */
20263 #define SF_Values 0x0000200 /* Synthesized from VALUES clause */
20264 #define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
20265 #define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
20266 #define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
20267 #define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
20268 #define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
20269 #define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
20270 #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
20271 #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
20272 #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
20273 #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
20274 #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
20275 #define SF_View 0x0200000 /* SELECT statement is a view */
20276 #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
20277 #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
20278 #define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
20279 #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
20280 #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
20281 #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
@@ -20291,15 +20396,10 @@
20291 /*
20292 ** The results of a SELECT can be distributed in several ways, as defined
20293 ** by one of the following macros. The "SRT" prefix means "SELECT Result
20294 ** Type".
20295 **
20296 ** SRT_Union Store results as a key in a temporary index
20297 ** identified by pDest->iSDParm.
20298 **
20299 ** SRT_Except Remove results from the temporary index pDest->iSDParm.
20300 **
20301 ** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
20302 ** set is not empty.
20303 **
20304 ** SRT_Discard Throw the results away. This is used by SELECT
20305 ** statements within triggers whose only purpose is
@@ -20359,34 +20459,32 @@
20359 ** column returned by the SELECT is used as the integer
20360 ** key. If (pDest->iSDParm>0), then the table is an index
20361 ** table. (pDest->iSDParm) is the number of key columns in
20362 ** each index record in this case.
20363 */
20364 #define SRT_Union 1 /* Store result as keys in an index */
20365 #define SRT_Except 2 /* Remove result from a UNION index */
20366 #define SRT_Exists 3 /* Store 1 if the result is not empty */
20367 #define SRT_Discard 4 /* Do not save the results anywhere */
20368 #define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
20369 #define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
20370
20371 /* The DISTINCT clause is ignored for all of the above. Not that
20372 ** IgnorableDistinct() implies IgnorableOrderby() */
20373 #define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
20374
20375 #define SRT_Queue 7 /* Store result in an queue */
20376 #define SRT_Fifo 8 /* Store result as data with an automatic rowid */
20377
20378 /* The ORDER BY clause is ignored for all of the above */
20379 #define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
20380
20381 #define SRT_Output 9 /* Output each row of result */
20382 #define SRT_Mem 10 /* Store result in a memory cell */
20383 #define SRT_Set 11 /* Store results as keys in an index */
20384 #define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
20385 #define SRT_Coroutine 13 /* Generate a single row of result */
20386 #define SRT_Table 14 /* Store result as data with an automatic rowid */
20387 #define SRT_Upfrom 15 /* Store result as data with rowid */
20388
20389 /*
20390 ** An instance of this object describes where to put of the results of
20391 ** a SELECT statement.
20392 */
@@ -21018,10 +21116,11 @@
21018 u16 mWFlags; /* Use-dependent flags */
21019 union { /* Extra data for callback */
21020 NameContext *pNC; /* Naming context */
21021 int n; /* A counter */
21022 int iCur; /* A cursor number */
 
21023 SrcList *pSrcList; /* FROM clause */
21024 struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
21025 struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
21026 int *aiCol; /* array of column indexes */
21027 struct IdxCover *pIdxCover; /* Check for index coverage */
@@ -21801,10 +21900,11 @@
21801 SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
21802 #endif
21803 SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
21804 SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
21805 SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
 
21806 SQLITE_PRIVATE int sqlite3IsRowid(const char*);
21807 SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
21808 SQLITE_PRIVATE void sqlite3GenerateRowDelete(
21809 Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
21810 SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -24489,10 +24589,11 @@
24489 SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
24490 SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
24491 SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
24492 SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
24493 SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
 
24494 SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
24495 #ifdef SQLITE_OMIT_FLOATING_POINT
24496 # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
24497 #else
24498 SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
@@ -31335,31 +31436,10 @@
31335 sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
31336 }
31337 *pp = p;
31338 }
31339
31340 /*
31341 ** Maximum size of any single memory allocation.
31342 **
31343 ** This is not a limit on the total amount of memory used. This is
31344 ** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
31345 **
31346 ** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
31347 ** This provides a 256-byte safety margin for defense against 32-bit
31348 ** signed integer overflow bugs when computing memory allocation sizes.
31349 ** Paranoid applications might want to reduce the maximum allocation size
31350 ** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
31351 ** or even smaller would be reasonable upper bounds on the size of a memory
31352 ** allocations for most applications.
31353 */
31354 #ifndef SQLITE_MAX_ALLOCATION_SIZE
31355 # define SQLITE_MAX_ALLOCATION_SIZE 2147483391
31356 #endif
31357 #if SQLITE_MAX_ALLOCATION_SIZE>2147483391
31358 # error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
31359 #endif
31360
31361 /*
31362 ** Allocate memory. This routine is like sqlite3_malloc() except that it
31363 ** assumes the memory subsystem has already been initialized.
31364 */
31365 SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
@@ -31579,12 +31659,11 @@
31579 }
31580 if( nBytes==0 ){
31581 sqlite3_free(pOld); /* IMP: R-26507-47431 */
31582 return 0;
31583 }
31584 if( nBytes>=0x7fffff00 ){
31585 /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
31586 return 0;
31587 }
31588 nOld = sqlite3MallocSize(pOld);
31589 /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
31590 ** argument to xRealloc is always a value returned by a prior call to
@@ -48881,78 +48960,54 @@
48881 { "WriteFile", (SYSCALL)WriteFile, 0 },
48882
48883 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
48884 LPOVERLAPPED))aSyscall[61].pCurrent)
48885
48886 { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
48887
48888 #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
48889 DWORD,DWORD))aSyscall[62].pCurrent)
48890
48891 /*
48892 ** For WaitForSingleObject(), MSDN says:
48893 **
48894 ** Minimum supported client: Windows XP [desktop apps | UWP apps]
48895 ** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
48896 */
48897 { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
48898
48899 #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
48900 DWORD))aSyscall[63].pCurrent)
48901
48902 #if !SQLITE_OS_WINCE
48903 { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
48904 #else
48905 { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
48906 #endif
48907
48908 #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
48909 BOOL))aSyscall[64].pCurrent)
48910
48911 { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
48912
48913 #define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
48914 PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
48915
48916 { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
48917
48918 #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
48919 FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
48920
48921 { "CreateFile2", (SYSCALL)CreateFile2, 0 },
48922
48923 #define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
48924 LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
48925
48926 { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
48927
48928 #define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
48929
48930 { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
48931
48932 #define osGetNativeSystemInfo ((VOID(WINAPI*)( \
48933 LPSYSTEM_INFO))aSyscall[71].pCurrent)
48934
48935 #if defined(SQLITE_WIN32_HAS_ANSI)
48936 { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
48937 #else
48938 { "OutputDebugStringA", (SYSCALL)0, 0 },
48939 #endif
48940
48941 #define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
48942
48943 #if defined(SQLITE_WIN32_HAS_WIDE)
48944 { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
48945 #else
48946 { "OutputDebugStringW", (SYSCALL)0, 0 },
48947 #endif
48948
48949 #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
48950
48951 { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
48952
48953 #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
48954
48955 /*
48956 ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
48957 ** is really just a macro that uses a compiler intrinsic (e.g. x64).
48958 ** So do not try to make this is into a redefinable interface.
@@ -48963,38 +49018,38 @@
48963 #define osInterlockedCompareExchange InterlockedCompareExchange
48964 #else
48965 { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
48966
48967 #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
48968 SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
48969 #endif /* defined(InterlockedCompareExchange) */
48970
48971 #if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
48972 { "UuidCreate", (SYSCALL)UuidCreate, 0 },
48973 #else
48974 { "UuidCreate", (SYSCALL)0, 0 },
48975 #endif
48976
48977 #define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
48978
48979 #if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
48980 { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
48981 #else
48982 { "UuidCreateSequential", (SYSCALL)0, 0 },
48983 #endif
48984
48985 #define osUuidCreateSequential \
48986 ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
48987
48988 #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
48989 { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
48990 #else
48991 { "FlushViewOfFile", (SYSCALL)0, 0 },
48992 #endif
48993
48994 #define osFlushViewOfFile \
48995 ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
48996
48997 /*
48998 ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
48999 ** to implement blocking locks with timeouts. MSDN says:
49000 **
@@ -49007,11 +49062,11 @@
49007 { "CreateEvent", (SYSCALL)0, 0 },
49008 #endif
49009
49010 #define osCreateEvent ( \
49011 (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
49012 aSyscall[80].pCurrent \
49013 )
49014
49015 /*
49016 ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
49017 ** for the case where a timeout expires and a lock request must be
@@ -49024,68 +49079,68 @@
49024 { "CancelIo", (SYSCALL)CancelIo, 0 },
49025 #else
49026 { "CancelIo", (SYSCALL)0, 0 },
49027 #endif
49028
49029 #define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent)
49030
49031 #if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32)
49032 { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 },
49033 #else
49034 { "GetModuleHandleW", (SYSCALL)0, 0 },
49035 #endif
49036
49037 #define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent)
49038
49039 #ifndef _WIN32
49040 { "getenv", (SYSCALL)getenv, 0 },
49041 #else
49042 { "getenv", (SYSCALL)0, 0 },
49043 #endif
49044
49045 #define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent)
49046
49047 #ifndef _WIN32
49048 { "getcwd", (SYSCALL)getcwd, 0 },
49049 #else
49050 { "getcwd", (SYSCALL)0, 0 },
49051 #endif
49052
49053 #define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent)
49054
49055 #ifndef _WIN32
49056 { "readlink", (SYSCALL)readlink, 0 },
49057 #else
49058 { "readlink", (SYSCALL)0, 0 },
49059 #endif
49060
49061 #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent)
49062
49063 #ifndef _WIN32
49064 { "lstat", (SYSCALL)lstat, 0 },
49065 #else
49066 { "lstat", (SYSCALL)0, 0 },
49067 #endif
49068
49069 #define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent)
49070
49071 #ifndef _WIN32
49072 { "__errno", (SYSCALL)__errno, 0 },
49073 #else
49074 { "__errno", (SYSCALL)0, 0 },
49075 #endif
49076
49077 #define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)())
49078
49079 #ifndef _WIN32
49080 { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
49081 #else
49082 { "cygwin_conv_path", (SYSCALL)0, 0 },
49083 #endif
49084
49085 #define osCygwin_conv_path ((size_t(*)(unsigned int, \
49086 const void *, void *, size_t))aSyscall[88].pCurrent)
49087
49088 }; /* End of the overrideable system calls */
49089
49090 /*
49091 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -53659,10 +53714,11 @@
53659 attr = INVALID_FILE_ATTRIBUTES;
53660 }else{
53661 attr = sAttrData.dwFileAttributes;
53662 }
53663 }else{
 
53664 winLogIoerr(cnt, __LINE__);
53665 if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
53666 sqlite3_free(zConverted);
53667 return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
53668 zFilename);
@@ -54399,11 +54455,16 @@
54399 };
54400 #endif
54401
54402 /* Double-check that the aSyscall[] array has been constructed
54403 ** correctly. See ticket [bb3a86e890c8e96ab] */
54404 assert( ArraySize(aSyscall)==86 );
 
 
 
 
 
54405
54406 /* get memory map allocation granularity */
54407 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
54408 osGetSystemInfo(&winSysInfo);
54409 assert( winSysInfo.dwAllocationGranularity>0 );
@@ -77426,11 +77487,11 @@
77426 }
77427 assert( cursorHoldsMutex(pCur) );
77428
77429 getCellInfo(pCur);
77430 aPayload = pCur->info.pPayload;
77431 assert( offset+amt <= pCur->info.nPayload );
77432
77433 assert( aPayload > pPage->aData );
77434 if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
77435 /* Trying to read or write past the end of the data is an error. The
77436 ** conditional above is really:
@@ -77983,11 +78044,11 @@
77983 SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
77984 int rc;
77985
77986 assert( cursorOwnsBtShared(pCur) );
77987 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
77988 if( pCur->eState==CURSOR_VALID ){
77989 *pRes = 0;
77990 return SQLITE_OK;
77991 }
77992 rc = moveToRoot(pCur);
77993 if( rc==SQLITE_EMPTY ){
@@ -85876,10 +85937,88 @@
85876 #endif
85877
85878
85879 return SQLITE_OK;
85880 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85881
85882 /*
85883 ** Move data out of a btree key or data field and into a Mem structure.
85884 ** The data is payload from the entry that pCur is currently pointing
85885 ** to. offset and amt determine what portion of the data or key to retrieve.
@@ -85900,11 +86039,16 @@
85900 u32 amt, /* Number of bytes to return. */
85901 Mem *pMem /* OUT: Return data in this Mem structure. */
85902 ){
85903 int rc;
85904 pMem->flags = MEM_Null;
85905 if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){
 
 
 
 
 
85906 return SQLITE_CORRUPT_BKPT;
85907 }
85908 if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
85909 rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
85910 if( rc==SQLITE_OK ){
@@ -86568,10 +86712,15 @@
86568 ** the column value into *ppVal. If *ppVal is initially NULL then a new
86569 ** sqlite3_value object is allocated.
86570 **
86571 ** If *ppVal is initially NULL then the caller is responsible for
86572 ** ensuring that the value written into *ppVal is eventually freed.
 
 
 
 
 
86573 */
86574 SQLITE_PRIVATE int sqlite3Stat4Column(
86575 sqlite3 *db, /* Database handle */
86576 const void *pRec, /* Pointer to buffer containing record */
86577 int nRec, /* Size of buffer pRec in bytes */
@@ -89584,11 +89733,11 @@
89584 assert( !zName || xDel!=SQLITE_DYNAMIC );
89585 return SQLITE_NOMEM_BKPT;
89586 }
89587 assert( p->aColName!=0 );
89588 pColName = &(p->aColName[idx+var*p->nResAlloc]);
89589 rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
89590 assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
89591 return rc;
89592 }
89593
89594 /*
@@ -92662,11 +92811,27 @@
92662 int n, /* Bytes in string, or negative */
92663 u8 enc, /* Encoding of z. 0 for BLOBs */
92664 void (*xDel)(void*) /* Destructor function */
92665 ){
92666 Mem *pOut = pCtx->pOut;
92667 int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92668 if( rc ){
92669 if( rc==SQLITE_TOOBIG ){
92670 sqlite3_result_error_toobig(pCtx);
92671 }else{
92672 /* The only errors possible from sqlite3VdbeMemSetStr are
@@ -92855,11 +93020,11 @@
92855 return;
92856 }
92857 #endif
92858 assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
92859 assert( xDel!=SQLITE_DYNAMIC );
92860 if( enc!=SQLITE_UTF8 ){
92861 if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
92862 n &= ~(u64)1;
92863 }
92864 if( n>0x7fffffff ){
92865 (void)invokeValueDestructor(z, xDel, pCtx);
@@ -93315,11 +93480,11 @@
93315 if( rc==SQLITE_OK ){
93316 u32 sz; /* Size of current row in bytes */
93317 Mem sMem; /* Raw content of current row */
93318 memset(&sMem, 0, sizeof(sMem));
93319 sz = sqlite3BtreePayloadSize(pRhs->pCsr);
93320 rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
93321 if( rc==SQLITE_OK ){
93322 u8 *zBuf = (u8*)sMem.z;
93323 u32 iSerial;
93324 sqlite3_value *pOut = pRhs->pOut;
93325 int iOff = 1 + getVarint32(&zBuf[1], iSerial);
@@ -93964,17 +94129,29 @@
93964 rc = vdbeUnbind(p, (u32)(i-1));
93965 if( rc==SQLITE_OK ){
93966 assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
93967 if( zData!=0 ){
93968 pVar = &p->aVar[i-1];
93969 rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
93970 if( rc==SQLITE_OK ){
93971 if( encoding==0 ){
93972 pVar->enc = ENC(p->db);
93973 }else{
93974 rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
93975 }
 
 
 
 
 
 
 
 
 
 
 
 
93976 }
93977 if( rc ){
93978 sqlite3Error(p->db, rc);
93979 rc = sqlite3ApiExit(p->db, rc);
93980 }
@@ -94082,11 +94259,11 @@
94082 sqlite3_uint64 nData,
94083 void (*xDel)(void*),
94084 unsigned char enc
94085 ){
94086 assert( xDel!=SQLITE_DYNAMIC );
94087 if( enc!=SQLITE_UTF8 ){
94088 if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
94089 nData &= ~(u64)1;
94090 }
94091 return bindText(pStmt, i, zData, nData, xDel, enc);
94092 }
@@ -101780,24 +101957,19 @@
101780 rc = sqlite3VdbeSorterWrite(pC, pIn2);
101781 if( rc) goto abort_due_to_error;
101782 break;
101783 }
101784
101785 /* Opcode: IdxDelete P1 P2 P3 * P5
101786 ** Synopsis: key=r[P2@P3]
101787 **
101788 ** The content of P3 registers starting at register P2 form
101789 ** an unpacked index key. This opcode removes that entry from the
101790 ** index opened by cursor P1.
101791 **
101792 ** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
101793 ** if no matching index entry is found. This happens when running
101794 ** an UPDATE or DELETE statement and the index entry to be updated
101795 ** or deleted is not found. For some uses of IdxDelete
101796 ** (example: the EXCEPT operator) it does not matter that no matching
101797 ** entry is found. For those cases, P5 is zero. Also, do not raise
101798 ** this (self-correcting and non-critical) error if in writable_schema mode.
101799 */
101800 case OP_IdxDelete: {
101801 VdbeCursor *pC;
101802 BtCursor *pCrsr;
101803 int res;
@@ -101819,11 +101991,11 @@
101819 rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
101820 if( rc ) goto abort_due_to_error;
101821 if( res==0 ){
101822 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
101823 if( rc ) goto abort_due_to_error;
101824 }else if( pOp->p5 && !sqlite3WritableSchema(db) ){
101825 rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
101826 goto abort_due_to_error;
101827 }
101828 assert( pC->deferredMoveto==0 );
101829 pC->cacheStatus = CACHE_STALE;
@@ -110988,14 +111160,10 @@
110988 }
110989 }
110990 }
110991 #endif
110992
110993 /* The ORDER BY and GROUP BY clauses may not refer to terms in
110994 ** outer queries
110995 */
110996 sNC.pNext = 0;
110997 sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
110998
110999 /* If this is a converted compound query, move the ORDER BY clause from
111000 ** the sub-query back to the parent query. At this point each term
111001 ** within the ORDER BY clause has been transformed to an integer value.
@@ -112575,11 +112743,13 @@
112575 const Expr *pExpr, /* The function invocation */
112576 const FuncDef *pDef /* The function being invoked */
112577 ){
112578 assert( !IN_RENAME_OBJECT );
112579 assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
112580 if( ExprHasProperty(pExpr, EP_FromDDL) ){
 
 
112581 if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
112582 || (pParse->db->flags & SQLITE_TrustedSchema)==0
112583 ){
112584 /* Functions prohibited in triggers and views if:
112585 ** (1) tagged with SQLITE_DIRECTONLY
@@ -113271,13 +113441,11 @@
113271 pNew->pNext = pNext;
113272 pNew->pPrior = 0;
113273 pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
113274 pNew->iLimit = 0;
113275 pNew->iOffset = 0;
113276 pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
113277 pNew->addrOpenEphm[0] = -1;
113278 pNew->addrOpenEphm[1] = -1;
113279 pNew->nSelectRow = p->nSelectRow;
113280 pNew->pWith = sqlite3WithDup(db, p->pWith);
113281 #ifndef SQLITE_OMIT_WINDOWFUNC
113282 pNew->pWin = 0;
113283 pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
@@ -115495,12 +115663,13 @@
115495 if( destIfFalse==destIfNull ){
115496 /* Combine Step 3 and Step 5 into a single opcode */
115497 if( ExprHasProperty(pExpr, EP_Subrtn) ){
115498 const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
115499 assert( pOp->opcode==OP_Once || pParse->nErr );
115500 if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
115501 assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
 
115502 sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
115503 rLhs, nVector); VdbeCoverage(v);
115504 }
115505 }
115506 sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
@@ -118687,11 +118856,14 @@
118687 if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break;
118688 }
118689 if( pIEpr==0 ) break;
118690 if( NEVER(!ExprUseYTab(pExpr)) ) break;
118691 for(i=0; i<pSrcList->nSrc; i++){
118692 if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break;
 
 
 
118693 }
118694 if( i>=pSrcList->nSrc ) break;
118695 if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */
118696 if( pParse->nErr ){ return WRC_Abort; }
118697
@@ -131401,11 +131573,11 @@
131401 ** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
131402 ** virtual tables
131403 ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
131404 ** virtual tables if PRAGMA trusted_schema=ON.
131405 */
131406 if( pParse->pToplevel!=0
131407 && pTab->u.vtab.p->eVtabRisk >
131408 ((pParse->db->flags & SQLITE_TrustedSchema)!=0)
131409 ){
131410 sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
131411 pTab->zName);
@@ -132239,11 +132411,10 @@
132239 VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
132240 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
132241 &iPartIdxLabel, pPrior, r1);
132242 sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
132243 pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
132244 sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
132245 sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
132246 pPrior = pIdx;
132247 }
132248 }
132249
@@ -133586,11 +133757,11 @@
133586 }else{
133587 goto unistr_error;
133588 }
133589 }
133590 zOut[j] = 0;
133591 sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8);
133592 return;
133593
133594 unistr_error:
133595 sqlite3_free(zOut);
133596 sqlite3_result_error(context, "invalid Unicode escape", -1);
@@ -133679,11 +133850,11 @@
133679 *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
133680 *zOut++ = 0x80 + (u8)(c & 0x3F);
133681 } \
133682 }
133683 *zOut = 0;
133684 sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
133685 }
133686
133687 /*
133688 ** The hex() function. Interpret the argument as a blob. Return
133689 ** a hexadecimal rendering as text.
@@ -133708,11 +133879,11 @@
133708 *(z++) = hexdigits[(c>>4)&0xf];
133709 *(z++) = hexdigits[c&0xf];
133710 }
133711 *z = 0;
133712 sqlite3_result_text64(context, zHex, (u64)(z-zHex),
133713 sqlite3_free, SQLITE_UTF8);
133714 }
133715 }
133716
133717 /*
133718 ** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr
@@ -134046,11 +134217,11 @@
134046 }
134047 }
134048 }
134049 z[j] = 0;
134050 assert( j<=n );
134051 sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8);
134052 }
134053
134054 /*
134055 ** The CONCAT(...) function. Generate a string result that is the
134056 ** concatentation of all non-null arguments.
@@ -141234,10 +141405,12 @@
141234 int (*set_errmsg)(sqlite3*,int,const char*);
141235 int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
141236 /* Version 3.52.0 and later */
141237 void (*str_truncate)(sqlite3_str*,int);
141238 void (*str_free)(sqlite3_str*);
 
 
141239 };
141240
141241 /*
141242 ** This is the function signature used for all extension entry points. It
141243 ** is also defined in the file "loadext.c".
@@ -141575,10 +141748,12 @@
141575 #define sqlite3_set_errmsg sqlite3_api->set_errmsg
141576 #define sqlite3_db_status64 sqlite3_api->db_status64
141577 /* Version 3.52.0 and later */
141578 #define sqlite3_str_truncate sqlite3_api->str_truncate
141579 #define sqlite3_str_free sqlite3_api->str_free
 
 
141580 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
141581
141582 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
141583 /* This case when the file really is being compiled as a loadable
141584 ** extension */
@@ -142104,11 +142279,18 @@
142104 /* Version 3.51.0 and later */
142105 sqlite3_set_errmsg,
142106 sqlite3_db_status64,
142107 /* Version 3.52.0 and later */
142108 sqlite3_str_truncate,
142109 sqlite3_str_free
 
 
 
 
 
 
 
142110 };
142111
142112 /* True if x is the directory separator character
142113 */
142114 #if SQLITE_OS_WIN
@@ -142206,37 +142388,46 @@
142206
142207 /* If no entry point was specified and the default legacy
142208 ** entry point name "sqlite3_extension_init" was not found, then
142209 ** construct an entry point name "sqlite3_X_init" where the X is
142210 ** replaced by the lowercase value of every ASCII alphabetic
142211 ** character in the filename after the last "/" upto the first ".",
142212 ** and eliding the first three characters if they are "lib".
142213 ** Examples:
142214 **
142215 ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
142216 ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init
 
 
 
 
 
 
142217 */
142218 if( xInit==0 && zProc==0 ){
142219 int iFile, iEntry, c;
142220 int ncFile = sqlite3Strlen30(zFile);
 
142221 zAltEntry = sqlite3_malloc64(ncFile+30);
142222 if( zAltEntry==0 ){
142223 sqlite3OsDlClose(pVfs, handle);
142224 return SQLITE_NOMEM_BKPT;
142225 }
142226 memcpy(zAltEntry, "sqlite3_", 8);
142227 for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
142228 iFile++;
142229 if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
142230 for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
142231 if( sqlite3Isalpha(c) ){
142232 zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
142233 }
142234 }
142235 memcpy(zAltEntry+iEntry, "_init", 6);
142236 zEntry = zAltEntry;
142237 xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
 
 
142238 }
142239 if( xInit==0 ){
142240 if( pzErrMsg ){
142241 nMsg += strlen(zEntry) + 300;
142242 *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
@@ -147518,12 +147709,10 @@
147518 pNew->op = TK_SELECT;
147519 pNew->selFlags = selFlags;
147520 pNew->iLimit = 0;
147521 pNew->iOffset = 0;
147522 pNew->selId = ++pParse->nSelect;
147523 pNew->addrOpenEphm[0] = -1;
147524 pNew->addrOpenEphm[1] = -1;
147525 pNew->nSelectRow = 0;
147526 if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
147527 pNew->pSrc = pSrc;
147528 pNew->pWhere = pWhere;
147529 pNew->pGroupBy = pGroupBy;
@@ -148667,33 +148856,10 @@
148667 codeOffset(v, p->iOffset, iContinue);
148668 }
148669 }
148670
148671 switch( eDest ){
148672 /* In this mode, write each query result to the key of the temporary
148673 ** table iParm.
148674 */
148675 #ifndef SQLITE_OMIT_COMPOUND_SELECT
148676 case SRT_Union: {
148677 int r1;
148678 r1 = sqlite3GetTempReg(pParse);
148679 sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
148680 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
148681 sqlite3ReleaseTempReg(pParse, r1);
148682 break;
148683 }
148684
148685 /* Construct a record from the query result, but instead of
148686 ** saving that record, use it as a key to delete elements from
148687 ** the temporary table iParm.
148688 */
148689 case SRT_Except: {
148690 sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
148691 break;
148692 }
148693 #endif /* SQLITE_OMIT_COMPOUND_SELECT */
148694
148695 /* Store the result as data using a unique key.
148696 */
148697 case SRT_Fifo:
148698 case SRT_DistFifo:
148699 case SRT_Table:
@@ -149976,13 +150142,13 @@
149976 **
149977 ** Space to hold the KeyInfo structure is obtained from malloc. The calling
149978 ** function is responsible for ensuring that this structure is eventually
149979 ** freed.
149980 */
149981 static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
149982 ExprList *pOrderBy = p->pOrderBy;
149983 int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0;
149984 sqlite3 *db = pParse->db;
149985 KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
149986 if( pRet ){
149987 int i;
149988 for(i=0; i<nOrderBy; i++){
@@ -150111,21 +150277,41 @@
150111
150112 /* Allocate cursors for Current, Queue, and Distinct. */
150113 regCurrent = ++pParse->nMem;
150114 sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
150115 if( pOrderBy ){
150116 KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
150117 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
150118 (char*)pKeyInfo, P4_KEYINFO);
150119 destQueue.pOrderBy = pOrderBy;
150120 }else{
150121 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
150122 }
150123 VdbeComment((v, "Queue table"));
150124 if( iDistinct ){
150125 p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
150126 p->selFlags |= SF_UsesEphemeral;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150127 }
150128
150129 /* Detach the ORDER BY clause from the compound SELECT */
150130 p->pOrderBy = 0;
150131
@@ -150196,11 +150382,11 @@
150196 return;
150197 }
150198 #endif /* SQLITE_OMIT_CTE */
150199
150200 /* Forward references */
150201 static int multiSelectOrderBy(
150202 Parse *pParse, /* Parsing context */
150203 Select *p, /* The right-most of SELECTs to be coded */
150204 SelectDest *pDest /* What to do with query results */
150205 );
150206
@@ -150345,317 +150531,80 @@
150345 #ifndef SQLITE_OMIT_CTE
150346 if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
150347 generateWithRecursiveQuery(pParse, p, &dest);
150348 }else
150349 #endif
150350
150351 /* Compound SELECTs that have an ORDER BY clause are handled separately.
150352 */
150353 if( p->pOrderBy ){
150354 return multiSelectOrderBy(pParse, p, pDest);
 
 
 
 
 
 
 
 
 
 
 
 
 
150355 }else{
 
 
 
 
150356
150357 #ifndef SQLITE_OMIT_EXPLAIN
150358 if( pPrior->pPrior==0 ){
150359 ExplainQueryPlan((pParse, 1, "COMPOUND QUERY"));
150360 ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
150361 }
150362 #endif
150363
150364 /* Generate code for the left and right SELECT statements.
150365 */
150366 switch( p->op ){
150367 case TK_ALL: {
150368 int addr = 0;
150369 int nLimit = 0; /* Initialize to suppress harmless compiler warning */
150370 assert( !pPrior->pLimit );
150371 pPrior->iLimit = p->iLimit;
150372 pPrior->iOffset = p->iOffset;
150373 pPrior->pLimit = p->pLimit;
150374 TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
150375 rc = sqlite3Select(pParse, pPrior, &dest);
150376 pPrior->pLimit = 0;
150377 if( rc ){
150378 goto multi_select_end;
150379 }
150380 p->pPrior = 0;
150381 p->iLimit = pPrior->iLimit;
150382 p->iOffset = pPrior->iOffset;
150383 if( p->iLimit ){
150384 addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
150385 VdbeComment((v, "Jump ahead if LIMIT reached"));
150386 if( p->iOffset ){
150387 sqlite3VdbeAddOp3(v, OP_OffsetLimit,
150388 p->iLimit, p->iOffset+1, p->iOffset);
150389 }
150390 }
150391 ExplainQueryPlan((pParse, 1, "UNION ALL"));
150392 TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
150393 rc = sqlite3Select(pParse, p, &dest);
150394 testcase( rc!=SQLITE_OK );
150395 pDelete = p->pPrior;
150396 p->pPrior = pPrior;
150397 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
150398 if( p->pLimit
150399 && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
150400 && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
150401 ){
150402 p->nSelectRow = sqlite3LogEst((u64)nLimit);
150403 }
150404 if( addr ){
150405 sqlite3VdbeJumpHere(v, addr);
150406 }
150407 break;
150408 }
150409 case TK_EXCEPT:
150410 case TK_UNION: {
150411 int unionTab; /* Cursor number of the temp table holding result */
150412 u8 op = 0; /* One of the SRT_ operations to apply to self */
150413 int priorOp; /* The SRT_ operation to apply to prior selects */
150414 Expr *pLimit; /* Saved values of p->nLimit */
150415 int addr;
150416 int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */
150417 SelectDest uniondest;
150418
150419
150420 testcase( p->op==TK_EXCEPT );
150421 testcase( p->op==TK_UNION );
150422 priorOp = SRT_Union;
150423 if( dest.eDest==priorOp ){
150424 /* We can reuse a temporary table generated by a SELECT to our
150425 ** right.
150426 */
150427 assert( p->pLimit==0 ); /* Not allowed on leftward elements */
150428 unionTab = dest.iSDParm;
150429 }else{
150430 /* We will need to create our own temporary table to hold the
150431 ** intermediate results.
150432 */
150433 unionTab = pParse->nTab++;
150434 assert( p->pOrderBy==0 );
150435 addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
150436 assert( p->addrOpenEphm[0] == -1 );
150437 p->addrOpenEphm[0] = addr;
150438 findRightmost(p)->selFlags |= SF_UsesEphemeral;
150439 assert( p->pEList );
150440 }
150441
150442
150443 /* Code the SELECT statements to our left
150444 */
150445 assert( !pPrior->pOrderBy );
150446 sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
150447 TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
150448 rc = sqlite3Select(pParse, pPrior, &uniondest);
150449 if( rc ){
150450 goto multi_select_end;
150451 }
150452
150453 /* Code the current SELECT statement
150454 */
150455 if( p->op==TK_EXCEPT ){
150456 op = SRT_Except;
150457 emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab);
150458 VdbeCoverage(v);
150459 }else{
150460 assert( p->op==TK_UNION );
150461 op = SRT_Union;
150462 }
150463 p->pPrior = 0;
150464 pLimit = p->pLimit;
150465 p->pLimit = 0;
150466 uniondest.eDest = op;
150467 ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
150468 sqlite3SelectOpName(p->op)));
150469 TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
150470 rc = sqlite3Select(pParse, p, &uniondest);
150471 testcase( rc!=SQLITE_OK );
150472 assert( p->pOrderBy==0 );
150473 pDelete = p->pPrior;
150474 p->pPrior = pPrior;
150475 p->pOrderBy = 0;
150476 if( p->op==TK_UNION ){
150477 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
150478 }
150479 if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass);
150480 sqlite3ExprDelete(db, p->pLimit);
150481 p->pLimit = pLimit;
150482 p->iLimit = 0;
150483 p->iOffset = 0;
150484
150485 /* Convert the data in the temporary table into whatever form
150486 ** it is that we currently need.
150487 */
150488 assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
150489 assert( p->pEList || db->mallocFailed );
150490 if( dest.eDest!=priorOp && db->mallocFailed==0 ){
150491 int iCont, iBreak, iStart;
150492 iBreak = sqlite3VdbeMakeLabel(pParse);
150493 iCont = sqlite3VdbeMakeLabel(pParse);
150494 computeLimitRegisters(pParse, p, iBreak);
150495 sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
150496 iStart = sqlite3VdbeCurrentAddr(v);
150497 selectInnerLoop(pParse, p, unionTab,
150498 0, 0, &dest, iCont, iBreak);
150499 sqlite3VdbeResolveLabel(v, iCont);
150500 sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
150501 sqlite3VdbeResolveLabel(v, iBreak);
150502 sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
150503 }
150504 break;
150505 }
150506 default: assert( p->op==TK_INTERSECT ); {
150507 int tab1, tab2;
150508 int iCont, iBreak, iStart;
150509 Expr *pLimit;
150510 int addr, iLimit, iOffset;
150511 SelectDest intersectdest;
150512 int r1;
150513 int emptyBypass;
150514
150515 /* INTERSECT is different from the others since it requires
150516 ** two temporary tables. Hence it has its own case. Begin
150517 ** by allocating the tables we will need.
150518 */
150519 tab1 = pParse->nTab++;
150520 tab2 = pParse->nTab++;
150521 assert( p->pOrderBy==0 );
150522
150523 addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
150524 assert( p->addrOpenEphm[0] == -1 );
150525 p->addrOpenEphm[0] = addr;
150526 findRightmost(p)->selFlags |= SF_UsesEphemeral;
150527 assert( p->pEList );
150528
150529 /* Code the SELECTs to our left into temporary table "tab1".
150530 */
150531 sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
150532 TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n"));
150533 rc = sqlite3Select(pParse, pPrior, &intersectdest);
150534 if( rc ){
150535 goto multi_select_end;
150536 }
150537
150538 /* Initialize LIMIT counters before checking to see if the LHS
150539 ** is empty, in case the jump is taken */
150540 iBreak = sqlite3VdbeMakeLabel(pParse);
150541 computeLimitRegisters(pParse, p, iBreak);
150542 emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v);
150543
150544 /* Code the current SELECT into temporary table "tab2"
150545 */
150546 addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
150547 assert( p->addrOpenEphm[1] == -1 );
150548 p->addrOpenEphm[1] = addr;
150549
150550 /* Disable prior SELECTs and the LIMIT counters during the computation
150551 ** of the RHS select */
150552 pLimit = p->pLimit;
150553 iLimit = p->iLimit;
150554 iOffset = p->iOffset;
150555 p->pPrior = 0;
150556 p->pLimit = 0;
150557 p->iLimit = 0;
150558 p->iOffset = 0;
150559
150560 intersectdest.iSDParm = tab2;
150561 ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
150562 sqlite3SelectOpName(p->op)));
150563 TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n"));
150564 rc = sqlite3Select(pParse, p, &intersectdest);
150565 testcase( rc!=SQLITE_OK );
150566 pDelete = p->pPrior;
150567 p->pPrior = pPrior;
150568 if( p->nSelectRow>pPrior->nSelectRow ){
150569 p->nSelectRow = pPrior->nSelectRow;
150570 }
150571 sqlite3ExprDelete(db, p->pLimit);
150572
150573 /* Reinstate the LIMIT counters prior to running the final intersect */
150574 p->pLimit = pLimit;
150575 p->iLimit = iLimit;
150576 p->iOffset = iOffset;
150577
150578 /* Generate code to take the intersection of the two temporary
150579 ** tables.
150580 */
150581 if( rc ) break;
150582 assert( p->pEList );
150583 sqlite3VdbeAddOp1(v, OP_Rewind, tab1);
150584 r1 = sqlite3GetTempReg(pParse);
150585 iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
150586 iCont = sqlite3VdbeMakeLabel(pParse);
150587 sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
150588 VdbeCoverage(v);
150589 sqlite3ReleaseTempReg(pParse, r1);
150590 selectInnerLoop(pParse, p, tab1,
150591 0, 0, &dest, iCont, iBreak);
150592 sqlite3VdbeResolveLabel(v, iCont);
150593 sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
150594 sqlite3VdbeResolveLabel(v, iBreak);
150595 sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
150596 sqlite3VdbeJumpHere(v, emptyBypass);
150597 sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
150598 break;
150599 }
150600 }
150601
150602 #ifndef SQLITE_OMIT_EXPLAIN
150603 if( p->pNext==0 ){
150604 ExplainQueryPlanPop(pParse);
150605 }
150606 #endif
150607 }
150608 if( pParse->nErr ) goto multi_select_end;
150609
150610 /* Compute collating sequences used by
150611 ** temporary tables needed to implement the compound select.
150612 ** Attach the KeyInfo structure to all temporary tables.
150613 **
150614 ** This section is run by the right-most SELECT statement only.
150615 ** SELECT statements to the left always skip this part. The right-most
150616 ** SELECT might also skip this part if it has no ORDER BY clause and
150617 ** no temp tables are required.
150618 */
150619 if( p->selFlags & SF_UsesEphemeral ){
150620 int i; /* Loop counter */
150621 KeyInfo *pKeyInfo; /* Collating sequence for the result set */
150622 Select *pLoop; /* For looping through SELECT statements */
150623 CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
150624 int nCol; /* Number of columns in result set */
150625
150626 assert( p->pNext==0 );
150627 assert( p->pEList!=0 );
150628 nCol = p->pEList->nExpr;
150629 pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
150630 if( !pKeyInfo ){
150631 rc = SQLITE_NOMEM_BKPT;
150632 goto multi_select_end;
150633 }
150634 for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
150635 *apColl = multiSelectCollSeq(pParse, p, i);
150636 if( 0==*apColl ){
150637 *apColl = db->pDfltColl;
150638 }
150639 }
150640
150641 for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
150642 for(i=0; i<2; i++){
150643 int addr = pLoop->addrOpenEphm[i];
150644 if( addr<0 ){
150645 /* If [0] is unused then [1] is also unused. So we can
150646 ** always safely abort as soon as the first unused slot is found */
150647 assert( pLoop->addrOpenEphm[1]<0 );
150648 break;
150649 }
150650 sqlite3VdbeChangeP2(v, addr, nCol);
150651 sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo),
150652 P4_KEYINFO);
150653 pLoop->addrOpenEphm[i] = -1;
150654 }
150655 }
150656 sqlite3KeyInfoUnref(pKeyInfo);
150657 }
150658
150659 multi_select_end:
150660 pDest->iSdst = dest.iSdst;
150661 pDest->nSdst = dest.nSdst;
@@ -150683,12 +150632,12 @@
150683
150684 /*
150685 ** Code an output subroutine for a coroutine implementation of a
150686 ** SELECT statement.
150687 **
150688 ** The data to be output is contained in pIn->iSdst. There are
150689 ** pIn->nSdst columns to be output. pDest is where the output should
150690 ** be sent.
150691 **
150692 ** regReturn is the number of the register holding the subroutine
150693 ** return address.
150694 **
@@ -150713,10 +150662,12 @@
150713 ){
150714 Vdbe *v = pParse->pVdbe;
150715 int iContinue;
150716 int addr;
150717
 
 
150718 addr = sqlite3VdbeCurrentAddr(v);
150719 iContinue = sqlite3VdbeMakeLabel(pParse);
150720
150721 /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
150722 */
@@ -150734,26 +150685,63 @@
150734
150735 /* Suppress the first OFFSET entries if there is an OFFSET clause
150736 */
150737 codeOffset(v, p->iOffset, iContinue);
150738
150739 assert( pDest->eDest!=SRT_Exists );
150740 assert( pDest->eDest!=SRT_Table );
150741 switch( pDest->eDest ){
150742 /* Store the result as data using a unique key.
150743 */
 
 
 
150744 case SRT_EphemTab: {
150745 int r1 = sqlite3GetTempReg(pParse);
150746 int r2 = sqlite3GetTempReg(pParse);
 
 
 
 
 
150747 sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
150748 sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
150749 sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150750 sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
150751 sqlite3ReleaseTempReg(pParse, r2);
150752 sqlite3ReleaseTempReg(pParse, r1);
150753 break;
150754 }
 
 
 
 
 
 
 
 
150755
150756 #ifndef SQLITE_OMIT_SUBQUERY
150757 /* If we are creating a set for an "expr IN (SELECT ...)".
150758 */
150759 case SRT_Set: {
@@ -150796,14 +150784,74 @@
150796 }
150797 sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
150798 sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
150799 break;
150800 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150801
150802 /* If none of the above, then the result destination must be
150803 ** SRT_Output. This routine is never called with any other
150804 ** destination other than the ones handled above or SRT_Output.
150805 **
150806 ** For SRT_Output, results are stored in a sequence of registers.
150807 ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
150808 ** return the next row of result.
150809 */
@@ -150827,12 +150875,13 @@
150827
150828 return addr;
150829 }
150830
150831 /*
150832 ** Alternative compound select code generator for cases when there
150833 ** is an ORDER BY clause.
 
150834 **
150835 ** We assume a query of the following form:
150836 **
150837 ** <selectA> <operator> <selectB> ORDER BY <orderbylist>
150838 **
@@ -150845,11 +150894,11 @@
150845 ** outA: Move the output of the selectA coroutine into the output
150846 ** of the compound query.
150847 **
150848 ** outB: Move the output of the selectB coroutine into the output
150849 ** of the compound query. (Only generated for UNION and
150850 ** UNION ALL. EXCEPT and INSERTSECT never output a row that
150851 ** appears only in B.)
150852 **
150853 ** AltB: Called when there is data from both coroutines and A<B.
150854 **
150855 ** AeqB: Called when there is data from both coroutines and A==B.
@@ -150898,25 +150947,23 @@
150898 ** EofB: ...
150899 ** AltB: ...
150900 ** AeqB: ...
150901 ** AgtB: ...
150902 ** Init: initialize coroutine registers
150903 ** yield coA
150904 ** if eof(A) goto EofA
150905 ** yield coB
150906 ** if eof(B) goto EofB
150907 ** Cmpr: Compare A, B
150908 ** Jump AltB, AeqB, AgtB
150909 ** End: ...
150910 **
150911 ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
150912 ** actually called using Gosub and they do not Return. EofA and EofB loop
150913 ** until all data is exhausted then jump to the "end" label. AltB, AeqB,
150914 ** and AgtB jump to either L2 or to one of EofA or EofB.
150915 */
150916 #ifndef SQLITE_OMIT_COMPOUND_SELECT
150917 static int multiSelectOrderBy(
150918 Parse *pParse, /* Parsing context */
150919 Select *p, /* The right-most of SELECTs to be coded */
150920 SelectDest *pDest /* What to do with query results */
150921 ){
150922 int i, j; /* Loop counters */
@@ -150993,30 +151040,33 @@
150993 }
150994 }
150995 }
150996
150997 /* Compute the comparison permutation and keyinfo that is used with
150998 ** the permutation used to determine if the next
150999 ** row of results comes from selectA or selectB. Also add explicit
151000 ** collations to the ORDER BY clause terms so that when the subqueries
151001 ** to the right and the left are evaluated, they use the correct
151002 ** collation.
151003 */
151004 aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
151005 if( aPermute ){
151006 struct ExprList_item *pItem;
 
151007 aPermute[0] = nOrderBy;
151008 for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
151009 assert( pItem!=0 );
151010 assert( pItem->u.x.iOrderByCol>0 );
151011 assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
151012 aPermute[i] = pItem->u.x.iOrderByCol - 1;
 
151013 }
151014 pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
151015 }else{
151016 pKeyMerge = 0;
 
151017 }
 
151018
151019 /* Allocate a range of temporary registers and the KeyInfo needed
151020 ** for the logic that removes duplicate result rows when the
151021 ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
151022 */
@@ -151091,11 +151141,11 @@
151091 /* Generate a coroutine to evaluate the SELECT statement to the
151092 ** left of the compound operator - the "A" select.
151093 */
151094 addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
151095 addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
151096 VdbeComment((v, "left SELECT"));
151097 pPrior->iLimit = regLimitA;
151098 ExplainQueryPlan((pParse, 1, "LEFT"));
151099 sqlite3Select(pParse, pPrior, &destA);
151100 sqlite3VdbeEndCoroutine(v, regAddrA);
151101 sqlite3VdbeJumpHere(v, addr1);
@@ -151103,11 +151153,11 @@
151103 /* Generate a coroutine to evaluate the SELECT statement on
151104 ** the right - the "B" select
151105 */
151106 addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
151107 addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
151108 VdbeComment((v, "right SELECT"));
151109 savedLimit = p->iLimit;
151110 savedOffset = p->iOffset;
151111 p->iLimit = regLimitB;
151112 p->iOffset = 0;
151113 ExplainQueryPlan((pParse, 1, "RIGHT"));
@@ -151117,20 +151167,20 @@
151117 sqlite3VdbeEndCoroutine(v, regAddrB);
151118
151119 /* Generate a subroutine that outputs the current row of the A
151120 ** select as the next output row of the compound select.
151121 */
151122 VdbeNoopComment((v, "Output routine for A"));
151123 addrOutA = generateOutputSubroutine(pParse,
151124 p, &destA, pDest, regOutA,
151125 regPrev, pKeyDup, labelEnd);
151126
151127 /* Generate a subroutine that outputs the current row of the B
151128 ** select as the next output row of the compound select.
151129 */
151130 if( op==TK_ALL || op==TK_UNION ){
151131 VdbeNoopComment((v, "Output routine for B"));
151132 addrOutB = generateOutputSubroutine(pParse,
151133 p, &destB, pDest, regOutB,
151134 regPrev, pKeyDup, labelEnd);
151135 }
151136 sqlite3KeyInfoUnref(pKeyDup);
@@ -151139,14 +151189,16 @@
151139 ** are exhausted and only data in select B remains.
151140 */
151141 if( op==TK_EXCEPT || op==TK_INTERSECT ){
151142 addrEofA_noB = addrEofA = labelEnd;
151143 }else{
151144 VdbeNoopComment((v, "eof-A subroutine"));
151145 addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
 
151146 addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
151147 VdbeCoverage(v);
 
151148 sqlite3VdbeGoto(v, addrEofA);
151149 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
151150 }
151151
151152 /* Generate a subroutine to run when the results from select B
@@ -151154,21 +151206,24 @@
151154 */
151155 if( op==TK_INTERSECT ){
151156 addrEofB = addrEofA;
151157 if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
151158 }else{
151159 VdbeNoopComment((v, "eof-B subroutine"));
151160 addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
 
151161 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
 
151162 sqlite3VdbeGoto(v, addrEofB);
151163 }
151164
151165 /* Generate code to handle the case of A<B
151166 */
151167 VdbeNoopComment((v, "A-lt-B subroutine"));
151168 addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
 
151169 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
 
151170 sqlite3VdbeGoto(v, labelCmpr);
151171
151172 /* Generate code to handle the case of A==B
151173 */
151174 if( op==TK_ALL ){
@@ -151175,40 +151230,52 @@
151175 addrAeqB = addrAltB;
151176 }else if( op==TK_INTERSECT ){
151177 addrAeqB = addrAltB;
151178 addrAltB++;
151179 }else{
151180 VdbeNoopComment((v, "A-eq-B subroutine"));
151181 addrAeqB =
151182 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
151183 sqlite3VdbeGoto(v, labelCmpr);
151184 }
151185
151186 /* Generate code to handle the case of A>B
151187 */
151188 VdbeNoopComment((v, "A-gt-B subroutine"));
151189 addrAgtB = sqlite3VdbeCurrentAddr(v);
151190 if( op==TK_ALL || op==TK_UNION ){
151191 sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
 
 
 
 
 
 
 
151192 }
151193 sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
151194 sqlite3VdbeGoto(v, labelCmpr);
151195
151196 /* This code runs once to initialize everything.
151197 */
151198 sqlite3VdbeJumpHere(v, addr1);
151199 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
 
 
151200 sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
 
151201
151202 /* Implement the main merge loop
151203 */
 
 
 
151204 sqlite3VdbeResolveLabel(v, labelCmpr);
151205 sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
151206 sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
151207 (char*)pKeyMerge, P4_KEYINFO);
151208 sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
151209 sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
 
 
 
 
 
 
151210
151211 /* Jump to the this point in order to terminate the query.
151212 */
151213 sqlite3VdbeResolveLabel(v, labelEnd);
151214
@@ -152121,11 +152188,11 @@
152121 pItem->fg.jointype |= (jointype & JT_LTORJ);
152122 memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
152123 }
152124 pSubitem->fg.jointype |= jointype;
152125
152126 /* Now begin substituting subquery result set expressions for
152127 ** references to the iParent in the outer query.
152128 **
152129 ** Example:
152130 **
152131 ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
@@ -152133,21 +152200,21 @@
152133 ** \_____________________ outer query ______________________________/
152134 **
152135 ** We look at every expression in the outer query and every place we see
152136 ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
152137 */
152138 if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){
152139 /* At this point, any non-zero iOrderByCol values indicate that the
152140 ** ORDER BY column expression is identical to the iOrderByCol'th
152141 ** expression returned by SELECT statement pSub. Since these values
152142 ** do not necessarily correspond to columns in SELECT statement pParent,
152143 ** zero them before transferring the ORDER BY clause.
152144 **
152145 ** Not doing this may cause an error if a subsequent call to this
152146 ** function attempts to flatten a compound sub-query into pParent
152147 ** (the only way this can happen is if the compound sub-query is
152148 ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
152149 ExprList *pOrderBy = pSub->pOrderBy;
152150 for(i=0; i<pOrderBy->nExpr; i++){
152151 pOrderBy->a[i].u.x.iOrderByCol = 0;
152152 }
152153 assert( pParent->pOrderBy==0 );
@@ -152995,18 +153062,18 @@
152995 ** These are rewritten as a subquery:
152996 **
152997 ** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2)
152998 ** ORDER BY ... COLLATE ...
152999 **
153000 ** This transformation is necessary because the multiSelectOrderBy() routine
153001 ** above that generates the code for a compound SELECT with an ORDER BY clause
153002 ** uses a merge algorithm that requires the same collating sequence on the
153003 ** result columns as on the ORDER BY clause. See ticket
153004 ** http://sqlite.org/src/info/6709574d2a
153005 **
153006 ** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
153007 ** The UNION ALL operator works fine with multiSelectOrderBy() even when
153008 ** there are COLLATE terms in the ORDER BY.
153009 */
153010 static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
153011 int i;
153012 Select *pNew;
@@ -153548,11 +153615,11 @@
153548 }
153549 sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
153550 }
153551 #ifndef SQLITE_OMIT_VIRTUALTABLE
153552 else if( ALWAYS(IsVirtual(pTab))
153553 && pFrom->fg.fromDDL
153554 && ALWAYS(pTab->u.vtab.p!=0)
153555 && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
153556 ){
153557 sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
153558 pTab->zName);
@@ -154832,19 +154899,30 @@
154832 Expr *pSubWhere = pSub->pWhere;
154833 if( pSub->pSrc->nSrc==1
154834 && (pSub->selFlags & SF_Aggregate)==0
154835 && !pSub->pSrc->a[0].fg.isSubquery
154836 && pSub->pLimit==0
 
154837 ){
 
 
 
 
 
 
 
 
 
 
 
 
154838 memset(pWhere, 0, sizeof(*pWhere));
154839 pWhere->op = TK_INTEGER;
154840 pWhere->u.iValue = 1;
154841 ExprSetProperty(pWhere, EP_IntValue);
154842
154843 assert( p->pWhere!=0 );
154844 pSub->pSrc->a[0].fg.fromExists = 1;
154845 pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
154846 p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc);
154847 if( pSubWhere ){
154848 p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere);
154849 pSub->pWhere = 0;
154850 }
@@ -154969,10 +155047,34 @@
154969 memset(&sCtx, 0, sizeof(sCtx));
154970 sCtx.pSrc = pSelect->pSrc;
154971 sqlite3WalkExprNN(&w, pSelect->pWhere);
154972 pSelect->selFlags &= ~SF_OnToWhere;
154973 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154974
154975 /*
154976 ** Generate byte-code for the SELECT statement given in the p argument.
154977 **
154978 ** The results are returned according to the SelectDest structure.
@@ -155065,12 +155167,11 @@
155065 assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
155066 assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
155067 assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
155068 assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
155069 if( IgnorableDistinct(pDest) ){
155070 assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
155071 pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
155072 pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
155073 /* All of these destinations are also able to ignore the ORDER BY clause */
155074 if( p->pOrderBy ){
155075 #if TREETRACE_ENABLED
155076 TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n"));
@@ -155082,11 +155183,10 @@
155082 p->pOrderBy);
155083 testcase( pParse->earlyCleanup );
155084 p->pOrderBy = 0;
155085 }
155086 p->selFlags &= ~(u32)SF_Distinct;
155087 p->selFlags |= SF_NoopOrderBy;
155088 }
155089 sqlite3SelectPrep(pParse, p, 0);
155090 if( pParse->nErr ){
155091 goto select_end;
155092 }
@@ -155622,11 +155722,12 @@
155622 ** used for both the ORDER BY and DISTINCT processing. As originally
155623 ** written the query must use a temp-table for at least one of the ORDER
155624 ** BY and DISTINCT, and an index or separate temp-table for the other.
155625 */
155626 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
155627 && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
 
155628 && OptimizationEnabled(db, SQLITE_GroupByOrder)
155629 #ifndef SQLITE_OMIT_WINDOWFUNC
155630 && p->pWin==0
155631 #endif
155632 ){
@@ -155836,25 +155937,14 @@
155836 ** in the correct order. It also may not - the GROUP BY might use a
155837 ** database index that causes rows to be grouped together as required
155838 ** but not actually sorted. Either way, record the fact that the
155839 ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
155840 ** variable. */
155841 if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){
155842 int ii;
155843 /* The GROUP BY processing doesn't care whether rows are delivered in
155844 ** ASC or DESC order - only that each group is returned contiguously.
155845 ** So set the ASC/DESC flags in the GROUP BY to match those in the
155846 ** ORDER BY to maximize the chances of rows being delivered in an
155847 ** order that makes the ORDER BY redundant. */
155848 for(ii=0; ii<pGroupBy->nExpr; ii++){
155849 u8 sortFlags;
155850 sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
155851 pGroupBy->a[ii].fg.sortFlags = sortFlags;
155852 }
155853 if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
155854 orderByGrp = 1;
155855 }
155856 }
155857 }else{
155858 assert( 0==sqlite3LogEst(1) );
155859 p->nSelectRow = 0;
155860 }
@@ -156849,15 +156939,20 @@
156849 }
156850 goto trigger_cleanup;
156851 }
156852 }
156853
 
 
 
 
156854 /* Do not create a trigger on a system table */
156855 if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
156856 sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
156857 goto trigger_cleanup;
156858 }
 
156859
156860 /* INSTEAD of triggers are only for views and views only support INSTEAD
156861 ** of triggers.
156862 */
156863 if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
@@ -160118,13 +160213,15 @@
160118 if( rc!=SQLITE_OK ) goto end_of_vacuum;
160119 assert( (db->nDb-1)==nDb );
160120 pDb = &db->aDb[nDb];
160121 assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
160122 pTemp = pDb->pBt;
 
160123 if( pOut ){
160124 sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
160125 i64 sz = 0;
 
160126 if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
160127 rc = SQLITE_ERROR;
160128 sqlite3SetString(pzErrMsg, db, "output file already exists");
160129 goto end_of_vacuum;
160130 }
@@ -160132,12 +160229,20 @@
160132
160133 /* For a VACUUM INTO, the pager-flags are set to the same values as
160134 ** they are for the database being vacuumed, except that PAGER_CACHESPILL
160135 ** is always set. */
160136 pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK);
 
 
 
 
 
 
 
 
 
160137 }
160138 nRes = sqlite3BtreeGetRequestedReserve(pMain);
160139
160140 sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
160141 sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
160142 sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL);
160143
@@ -165646,10 +165751,38 @@
165646 sqlite3ValueFree(pVal);
165647 return rc;
165648 }
165649 #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
165650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165651
165652 #ifndef SQLITE_OMIT_VIRTUALTABLE
165653 /*
165654 ** Check to see if the pExpr expression is a form that needs to be passed
165655 ** to the xBestIndex method of virtual tables. Forms of interest include:
@@ -165682,19 +165815,10 @@
165682 unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
165683 Expr **ppLeft, /* Column expression to left of MATCH/op2 */
165684 Expr **ppRight /* Expression to left of MATCH/op2 */
165685 ){
165686 if( pExpr->op==TK_FUNCTION ){
165687 static const struct Op2 {
165688 const char *zOp;
165689 unsigned char eOp2;
165690 } aOp[] = {
165691 { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
165692 { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
165693 { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
165694 { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
165695 };
165696 ExprList *pList;
165697 Expr *pCol; /* Column reference */
165698 int i;
165699
165700 assert( ExprUseXList(pExpr) );
@@ -165710,20 +165834,15 @@
165710 ** vtab_column MATCH expression
165711 ** MATCH(expression,vtab_column)
165712 */
165713 pCol = pList->a[1].pExpr;
165714 assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
165715 if( ExprIsVtab(pCol) ){
165716 for(i=0; i<ArraySize(aOp); i++){
165717 assert( !ExprHasProperty(pExpr, EP_IntValue) );
165718 if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
165719 *peOp2 = aOp[i].eOp2;
165720 *ppRight = pList->a[0].pExpr;
165721 *ppLeft = pCol;
165722 return 1;
165723 }
165724 }
165725 }
165726
165727 /* We can also match against the first column of overloaded
165728 ** functions where xFindFunction returns a value of at least
165729 ** SQLITE_INDEX_CONSTRAINT_FUNCTION.
@@ -165853,20 +165972,26 @@
165853 u16 eOp = pOne->eOperator | pTwo->eOperator;
165854 sqlite3 *db; /* Database connection (for malloc) */
165855 Expr *pNew; /* New virtual expression */
165856 int op; /* Operator for the combined expression */
165857 int idxNew; /* Index in pWC of the next virtual term */
 
165858
165859 if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
165860 if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
165861 if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
165862 if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
165863 && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
165864 assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
165865 assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
165866 if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
165867 if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
 
 
 
 
 
165868 /* If we reach this point, it means the two subterms can be combined */
165869 if( (eOp & (eOp-1))!=0 ){
165870 if( eOp & (WO_LT|WO_LE) ){
165871 eOp = WO_LE;
165872 }else{
@@ -165873,11 +165998,11 @@
165873 assert( eOp & (WO_GT|WO_GE) );
165874 eOp = WO_GE;
165875 }
165876 }
165877 db = pWC->pWInfo->pParse->db;
165878 pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
165879 if( pNew==0 ) return;
165880 for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
165881 pNew->op = op;
165882 idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
165883 exprAnalyze(pSrc, pWC, idxNew);
@@ -168744,15 +168869,18 @@
168744
168745 /* No matches cause a break out of the loop */
168746 break;
168747 }
168748 if( i==n ){
 
168749 nOrderBy = n;
168750 if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
168751 eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
168752 }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
168753 eDistinct = 1;
 
 
168754 }
168755 }
168756 }
168757
168758 /* Allocate the sqlite3_index_info structure
@@ -170158,10 +170286,71 @@
170158 p->u.btree.pIndex = 0;
170159 }
170160 }
170161 return rc;
170162 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170163
170164 /*
170165 ** Adjust the WhereLoop.nOut value downward to account for terms of the
170166 ** WHERE clause that reference the loop but which are not used by an
170167 ** index.
@@ -170187,10 +170376,17 @@
170187 ** of rows in the table. In other words, assume that x==EXPR will filter
170188 ** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the
170189 ** "x" column is boolean or else -1 or 0 or 1 is a common default value
170190 ** on the "x" column and so in that case only cap the output row estimate
170191 ** at 1/2 instead of 1/4.
 
 
 
 
 
 
 
170192 */
170193 static void whereLoopOutputAdjust(
170194 WhereClause *pWC, /* The WHERE clause */
170195 WhereLoop *pLoop, /* The loop to adjust downward */
170196 LogEst nRow /* Number of rows in the entire table */
@@ -170236,25 +170432,43 @@
170236 ** then use the probability provided by the application. */
170237 pLoop->nOut += pTerm->truthProb;
170238 }else{
170239 /* In the absence of explicit truth probabilities, use heuristics to
170240 ** guess a reasonable truth probability. */
 
170241 pLoop->nOut--;
170242 if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
170243 && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
170244 ){
170245 Expr *pRight = pTerm->pExpr->pRight;
170246 int k = 0;
170247 testcase( pTerm->pExpr->op==TK_IS );
170248 if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
170249 k = 10;
170250 }else{
170251 k = 20;
170252 }
170253 if( iReduce<k ){
170254 pTerm->wtFlags |= TERM_HEURTRUTH;
170255 iReduce = k;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170256 }
170257 }
170258 }
170259 }
170260 }
@@ -170712,10 +170926,11 @@
170712
170713 nOutUnadjusted = pNew->nOut;
170714 pNew->rRun += nInMul + nIn;
170715 pNew->nOut += nInMul + nIn;
170716 whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
 
170717 rc = whereLoopInsert(pBuilder, pNew);
170718
170719 if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
170720 pNew->nOut = saved_nOut;
170721 }else{
@@ -171308,10 +171523,12 @@
171308 ApplyCostMultiplier(pNew->rRun, pTab->costMult);
171309 whereLoopOutputAdjust(pWC, pNew, rSize);
171310 if( pSrc->fg.isSubquery ){
171311 if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
171312 pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
 
 
171313 }
171314 rc = whereLoopInsert(pBuilder, pNew);
171315 pNew->nOut = rSize;
171316 if( rc ) break;
171317 }else{
@@ -171410,10 +171627,11 @@
171410 /* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
171411 ** because the cursor used to access the index might not be
171412 ** positioned to the correct row during the right-join no-match
171413 ** loop. */
171414 }else{
 
171415 rc = whereLoopInsert(pBuilder, pNew);
171416 }
171417 pNew->nOut = rSize;
171418 if( rc ) break;
171419 }
@@ -172072,11 +172290,11 @@
172072 SrcItem *pItem;
172073 SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
172074 sqlite3 *db = pWInfo->pParse->db;
172075 int rc = SQLITE_OK;
172076 int bFirstPastRJ = 0;
172077 int hasRightJoin = 0;
172078 WhereLoop *pNew;
172079
172080
172081 /* Loop over the tables in the join, from left to right */
172082 pNew = pBuilder->pNew;
@@ -172099,19 +172317,38 @@
172099 /* Add prerequisites to prevent reordering of FROM clause terms
172100 ** across CROSS joins and outer joins. The bFirstPastRJ boolean
172101 ** prevents the right operand of a RIGHT JOIN from being swapped with
172102 ** other elements even further to the right.
172103 **
172104 ** The JT_LTORJ case and the hasRightJoin flag work together to
172105 ** prevent FROM-clause terms from moving from the right side of
172106 ** a LEFT JOIN over to the left side of that join if the LEFT JOIN
172107 ** is itself on the left side of a RIGHT JOIN.
 
 
 
 
172108 */
172109 if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1;
 
 
 
 
172110 mPrereq |= mPrior;
172111 bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
172112 }else if( !hasRightJoin ){
 
 
 
 
 
 
 
 
 
 
 
172113 mPrereq = 0;
172114 }
172115 #ifndef SQLITE_OMIT_VIRTUALTABLE
172116 if( IsVirtual(pItem->pSTab) ){
172117 SrcItem *p;
@@ -172330,13 +172567,11 @@
172330 if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
172331 }else{
172332 pLoop = pLast;
172333 }
172334 if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
172335 if( pLoop->u.vtab.isOrdered
172336 && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
172337 ){
172338 obSat = obDone;
172339 }else{
172340 /* No further ORDER BY terms may be matched. So this call should
172341 ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
172342 isOrderDistinct = 0;
@@ -173673,10 +173908,11 @@
173673 pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
173674 notReady &= ~pLoop->maskSelf;
173675 for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
173676 if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
173677 pTerm->wtFlags |= TERM_CODED;
 
173678 }
173679 }
173680 if( i!=pWInfo->nLevel-1 ){
173681 int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
173682 memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
@@ -174660,26 +174896,31 @@
174660 VdbeCoverageIf(v, op==OP_SeekGT);
174661 sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
174662 }
174663 #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
174664 }
174665 if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
174666 /* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
174667 ** loop(s) will be the inner-most loops of the join. There might be
174668 ** multiple EXISTS loops, but they will all be nested, and the join
174669 ** order will not have been changed by the query planner. If the
174670 ** inner-most EXISTS loop sees a single successful row, it should
174671 ** break out of *all* EXISTS loops. But only the inner-most of the
174672 ** nested EXISTS loops should do this breakout. */
 
174673 int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
174674 while( nOuter<i ){
174675 if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
174676 nOuter++;
174677 }
174678 testcase( nOuter>0 );
174679 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
174680 VdbeComment((v, "EXISTS break"));
 
 
 
 
174681 }
174682 sqlite3VdbeResolveLabel(v, pLevel->addrCont);
174683 if( pLevel->op!=OP_Noop ){
174684 sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
174685 sqlite3VdbeChangeP5(v, pLevel->p5);
@@ -184823,11 +185064,11 @@
184823 for(i=1; sqlite3Isdigit(z[i]); i++){}
184824 return i;
184825 }
184826 case CC_DOLLAR:
184827 case CC_VARALPHA: {
184828 int n = 0;
184829 testcase( z[0]=='$' ); testcase( z[0]=='@' );
184830 testcase( z[0]==':' ); testcase( z[0]=='#' );
184831 *tokenType = TK_VARIABLE;
184832 for(i=1; (c=z[i])!=0; i++){
184833 if( IdChar(c) ){
@@ -189448,10 +189689,16 @@
189448 /*
189449 ** Find existing client data.
189450 */
189451 SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){
189452 DbClientData *p;
 
 
 
 
 
 
189453 sqlite3_mutex_enter(db->mutex);
189454 for(p=db->pDbData; p; p=p->pNext){
189455 if( strcmp(p->zName, zName)==0 ){
189456 void *pResult = p->pData;
189457 sqlite3_mutex_leave(db->mutex);
@@ -192292,10 +192539,19 @@
192292 SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
192293
192294 #define fts3GetVarint32(p, piVal) ( \
192295 (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
192296 )
 
 
 
 
 
 
 
 
 
192297
192298 /* fts3.c */
192299 SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
192300 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
192301 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
@@ -193900,13 +194156,11 @@
193900 p->pSeekStmt = 0;
193901 }else{
193902 zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
193903 if( !zSql ) return SQLITE_NOMEM;
193904 p->bLock++;
193905 rc = sqlite3_prepare_v3(
193906 p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
193907 );
193908 p->bLock--;
193909 sqlite3_free(zSql);
193910 }
193911 if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
193912 }
@@ -195477,13 +195731,11 @@
195477 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
195478 );
195479 }
195480 if( zSql ){
195481 p->bLock++;
195482 rc = sqlite3_prepare_v3(
195483 p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
195484 );
195485 p->bLock--;
195486 sqlite3_free(zSql);
195487 }else{
195488 rc = SQLITE_NOMEM;
195489 }
@@ -196102,10 +196354,11 @@
196102 int rc = SQLITE_OK;
196103 int bOk = 0;
196104
196105 UNUSED_PARAMETER(isQuick);
196106 rc = sqlite3Fts3IntegrityCheck(p, &bOk);
 
196107 assert( rc!=SQLITE_CORRUPT_VTAB );
196108 if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){
196109 *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
196110 " FTS%d table %s.%s: %s",
196111 p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
@@ -202713,10 +202966,28 @@
202713 #define SQL_SELECT_MXLEVEL 36
202714
202715 #define SQL_SELECT_LEVEL_RANGE2 37
202716 #define SQL_UPDATE_LEVEL_IDX 38
202717 #define SQL_UPDATE_LEVEL 39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202718
202719 /*
202720 ** This function is used to obtain an SQLite prepared statement handle
202721 ** for the statement identified by the second argument. If successful,
202722 ** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -202839,24 +203110,24 @@
202839 assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
202840 assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
202841
202842 pStmt = p->aStmt[eStmt];
202843 if( !pStmt ){
202844 int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
202845 char *zSql;
202846 if( eStmt==SQL_CONTENT_INSERT ){
202847 zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
202848 }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
202849 f &= ~SQLITE_PREPARE_NO_VTAB;
202850 zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
202851 }else{
202852 zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
202853 }
202854 if( !zSql ){
202855 rc = SQLITE_NOMEM;
202856 }else{
202857 rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
202858 sqlite3_free(zSql);
202859 assert( rc==SQLITE_OK || pStmt==0 );
202860 p->aStmt[eStmt] = pStmt;
202861 }
202862 }
@@ -206019,11 +206290,11 @@
206019 /* Compose and prepare an SQL statement to loop through the content table */
206020 char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
206021 if( !zSql ){
206022 rc = SQLITE_NOMEM;
206023 }else{
206024 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
206025 sqlite3_free(zSql);
206026 }
206027
206028 if( rc==SQLITE_OK ){
206029 sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
@@ -207772,11 +208043,11 @@
207772
207773 zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
207774 if( !zSql ){
207775 rc = SQLITE_NOMEM;
207776 }else{
207777 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
207778 sqlite3_free(zSql);
207779 }
207780
207781 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
207782 i64 iDocid = sqlite3_column_int64(pStmt, 0);
@@ -211177,11 +211448,14 @@
211177 */
211178 #define JSON_JSON 0x01 /* Result is always JSON */
211179 #define JSON_SQL 0x02 /* Result is always SQL */
211180 #define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
211181 #define JSON_ISSET 0x04 /* json_set(), not json_insert() */
211182 #define JSON_BLOB 0x08 /* Use the BLOB output format */
 
 
 
211183
211184
211185 /* A parsed JSON value. Lifecycle:
211186 **
211187 ** 1. JSON comes in and is parsed into a JSONB value in aBlob. The
@@ -211223,10 +211497,11 @@
211223 /* Allowed values for JsonParse.eEdit */
211224 #define JEDIT_DEL 1 /* Delete if exists */
211225 #define JEDIT_REPL 2 /* Overwrite if exists */
211226 #define JEDIT_INS 3 /* Insert if not exists */
211227 #define JEDIT_SET 4 /* Insert or overwrite */
 
211228
211229 /*
211230 ** Maximum nesting depth of JSON for this implementation.
211231 **
211232 ** This limit is needed to avoid a stack overflow in the recursive
@@ -213719,11 +213994,12 @@
213719 /*
213720 ** Error returns from jsonLookupStep()
213721 */
213722 #define JSON_LOOKUP_ERROR 0xffffffff
213723 #define JSON_LOOKUP_NOTFOUND 0xfffffffe
213724 #define JSON_LOOKUP_PATHERROR 0xfffffffd
 
213725 #define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR)
213726
213727 /* Forward declaration */
213728 static u32 jsonLookupStep(JsonParse*,u32,const char*,u32);
213729
@@ -213748,11 +214024,11 @@
213748 ** using the substructure.
213749 */
213750 static u32 jsonCreateEditSubstructure(
213751 JsonParse *pParse, /* The original JSONB that is being edited */
213752 JsonParse *pIns, /* Populate this with the blob data to insert */
213753 const char *zTail /* Tail of the path that determins substructure */
213754 ){
213755 static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
213756 int rc;
213757 memset(pIns, 0, sizeof(*pIns));
213758 pIns->db = pParse->db;
@@ -213783,13 +214059,13 @@
213783 ** label, before returning.
213784 **
213785 ** Return one of the JSON_LOOKUP error codes if problems are seen.
213786 **
213787 ** This routine will also modify the blob. If pParse->eEdit is one of
213788 ** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be
213789 ** made to the selected value. If an edit is performed, then the return
213790 ** value does not necessarily point to the select element. If an edit
213791 ** is performed, the return value is only useful for detecting error
213792 ** conditions.
213793 */
213794 static u32 jsonLookupStep(
213795 JsonParse *pParse, /* The JSON to search */
@@ -213811,10 +214087,17 @@
213811 iRoot = iLabel;
213812 }
213813 jsonBlobEdit(pParse, iRoot, sz, 0, 0);
213814 }else if( pParse->eEdit==JEDIT_INS ){
213815 /* Already exists, so json_insert() is a no-op */
 
 
 
 
 
 
 
213816 }else{
213817 /* json_set() or json_replace() */
213818 jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns);
213819 }
213820 }
@@ -213882,10 +214165,14 @@
213882 u32 nIns; /* Total bytes to insert (label+value) */
213883 JsonParse v; /* BLOB encoding of the value to be inserted */
213884 JsonParse ix; /* Header of the label to be inserted */
213885 testcase( pParse->eEdit==JEDIT_INS );
213886 testcase( pParse->eEdit==JEDIT_SET );
 
 
 
 
213887 memset(&ix, 0, sizeof(ix));
213888 ix.db = pParse->db;
213889 jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
213890 pParse->oom |= ix.oom;
213891 rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
@@ -213909,32 +214196,36 @@
213909 jsonParseReset(&v);
213910 jsonParseReset(&ix);
213911 return rc;
213912 }
213913 }else if( zPath[0]=='[' ){
 
213914 x = pParse->aBlob[iRoot] & 0x0f;
213915 if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND;
213916 n = jsonbPayloadSize(pParse, iRoot, &sz);
213917 k = 0;
213918 i = 1;
213919 while( sqlite3Isdigit(zPath[i]) ){
213920 k = k*10 + zPath[i] - '0';
 
 
213921 i++;
213922 }
213923 if( i<2 || zPath[i]!=']' ){
213924 if( zPath[1]=='#' ){
213925 k = jsonbArrayCount(pParse, iRoot);
213926 i = 2;
213927 if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
213928 unsigned int nn = 0;
213929 i = 3;
213930 do{
213931 nn = nn*10 + zPath[i] - '0';
 
 
213932 i++;
213933 }while( sqlite3Isdigit(zPath[i]) );
213934 if( nn>k ) return JSON_LOOKUP_NOTFOUND;
213935 k -= nn;
213936 }
213937 if( zPath[i]!=']' ){
213938 return JSON_LOOKUP_PATHERROR;
213939 }
213940 }else{
@@ -213942,25 +214233,26 @@
213942 }
213943 }
213944 j = iRoot+n;
213945 iEnd = j+sz;
213946 while( j<iEnd ){
213947 if( k==0 ){
213948 rc = jsonLookupStep(pParse, j, &zPath[i+1], 0);
213949 if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
213950 return rc;
213951 }
213952 k--;
213953 n = jsonbPayloadSize(pParse, j, &sz);
213954 if( n==0 ) return JSON_LOOKUP_ERROR;
213955 j += n+sz;
213956 }
213957 if( j>iEnd ) return JSON_LOOKUP_ERROR;
213958 if( k>0 ) return JSON_LOOKUP_NOTFOUND;
213959 if( pParse->eEdit>=JEDIT_INS ){
213960 JsonParse v;
213961 testcase( pParse->eEdit==JEDIT_INS );
 
213962 testcase( pParse->eEdit==JEDIT_SET );
213963 rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]);
213964 if( !JSON_LOOKUP_ISERROR(rc)
213965 && jsonBlobMakeEditable(pParse, v.nBlob)
213966 ){
@@ -214281,13 +214573,19 @@
214281 ** If ctx is not NULL then push the error message into ctx and return NULL.
214282 ** If ctx is NULL, then return the text of the error message.
214283 */
214284 static char *jsonBadPathError(
214285 sqlite3_context *ctx, /* The function call containing the error */
214286 const char *zPath /* The path with the problem */
 
214287 ){
214288 char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
 
 
 
 
 
214289 if( ctx==0 ) return zMsg;
214290 if( zMsg ){
214291 sqlite3_result_error(ctx, zMsg, -1);
214292 sqlite3_free(zMsg);
214293 }else{
@@ -214300,17 +214598,17 @@
214300 ** arguments come in pairs where each pair contains a JSON path and
214301 ** content to insert or set at that patch. Do the updates
214302 ** and return the result.
214303 **
214304 ** The specific operation is determined by eEdit, which can be one
214305 ** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET.
214306 */
214307 static void jsonInsertIntoBlob(
214308 sqlite3_context *ctx,
214309 int argc,
214310 sqlite3_value **argv,
214311 int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */
214312 ){
214313 int i;
214314 u32 rc = 0;
214315 const char *zPath = 0;
214316 int flgs;
@@ -214358,11 +214656,11 @@
214358 jsonInsertIntoBlob_patherror:
214359 jsonParseFree(p);
214360 if( rc==JSON_LOOKUP_ERROR ){
214361 sqlite3_result_error(ctx, "malformed JSON", -1);
214362 }else{
214363 jsonBadPathError(ctx, zPath);
214364 }
214365 return;
214366 }
214367
214368 /*
@@ -214800,11 +215098,11 @@
214800 i = jsonLookupStep(p, 0, zPath[0]=='$' ? zPath+1 : "@", 0);
214801 if( JSON_LOOKUP_ISERROR(i) ){
214802 if( i==JSON_LOOKUP_NOTFOUND ){
214803 /* no-op */
214804 }else if( i==JSON_LOOKUP_PATHERROR ){
214805 jsonBadPathError(ctx, zPath);
214806 }else{
214807 sqlite3_result_error(ctx, "malformed JSON", -1);
214808 }
214809 eErr = 1;
214810 i = 0;
@@ -214905,11 +215203,11 @@
214905 }
214906 jsonStringTerminate(&jx);
214907 j = jsonLookupStep(p, 0, jx.zBuf, 0);
214908 jsonStringReset(&jx);
214909 }else{
214910 jsonBadPathError(ctx, zPath);
214911 goto json_extract_error;
214912 }
214913 if( j<p->nBlob ){
214914 if( argc==2 ){
214915 if( flags & JSON_JSON ){
@@ -214940,11 +215238,11 @@
214940 }
214941 }else if( j==JSON_LOOKUP_ERROR ){
214942 sqlite3_result_error(ctx, "malformed JSON", -1);
214943 goto json_extract_error;
214944 }else{
214945 jsonBadPathError(ctx, zPath);
214946 goto json_extract_error;
214947 }
214948 }
214949 if( argc>2 ){
214950 jsonAppendChar(&jx, ']');
@@ -215269,11 +215567,11 @@
215269 rc = jsonLookupStep(p, 0, zPath+1, 0);
215270 if( JSON_LOOKUP_ISERROR(rc) ){
215271 if( rc==JSON_LOOKUP_NOTFOUND ){
215272 continue; /* No-op */
215273 }else if( rc==JSON_LOOKUP_PATHERROR ){
215274 jsonBadPathError(ctx, zPath);
215275 }else{
215276 sqlite3_result_error(ctx, "malformed JSON", -1);
215277 }
215278 goto json_remove_done;
215279 }
@@ -215281,11 +215579,11 @@
215281 jsonReturnParse(ctx, p);
215282 jsonParseFree(p);
215283 return;
215284
215285 json_remove_patherror:
215286 jsonBadPathError(ctx, zPath);
215287
215288 json_remove_done:
215289 jsonParseFree(p);
215290 return;
215291 }
@@ -215325,20 +215623,22 @@
215325 static void jsonSetFunc(
215326 sqlite3_context *ctx,
215327 int argc,
215328 sqlite3_value **argv
215329 ){
215330
215331 int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215332 int bIsSet = (flags&JSON_ISSET)!=0;
 
 
215333
215334 if( argc<1 ) return;
 
215335 if( (argc&1)==0 ) {
215336 jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
215337 return;
215338 }
215339 jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS);
215340 }
215341
215342 /*
215343 ** json_type(JSON)
215344 ** json_type(JSON, PATH)
@@ -215359,19 +215659,19 @@
215359 if( p==0 ) return;
215360 if( argc==2 ){
215361 zPath = (const char*)sqlite3_value_text(argv[1]);
215362 if( zPath==0 ) goto json_type_done;
215363 if( zPath[0]!='$' ){
215364 jsonBadPathError(ctx, zPath);
215365 goto json_type_done;
215366 }
215367 i = jsonLookupStep(p, 0, zPath+1, 0);
215368 if( JSON_LOOKUP_ISERROR(i) ){
215369 if( i==JSON_LOOKUP_NOTFOUND ){
215370 /* no-op */
215371 }else if( i==JSON_LOOKUP_PATHERROR ){
215372 jsonBadPathError(ctx, zPath);
215373 }else{
215374 sqlite3_result_error(ctx, "malformed JSON", -1);
215375 }
215376 goto json_type_done;
215377 }
@@ -215623,16 +215923,15 @@
215623 jsonAppendSqlValue(pStr, argv[0]);
215624 }
215625 }
215626 static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
215627 JsonString *pStr;
 
215628 pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
215629 if( pStr ){
215630 int flags;
215631 pStr->pCtx = ctx;
215632 jsonAppendChar(pStr, ']');
215633 flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215634 if( pStr->eErr ){
215635 jsonReturnString(pStr, 0, 0);
215636 return;
215637 }else if( flags & JSON_BLOB ){
215638 jsonReturnStringAsBlob(pStr);
@@ -215649,10 +215948,13 @@
215649 pStr->bStatic = 1;
215650 }else{
215651 sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
215652 jsonStringTrimOneChar(pStr);
215653 }
 
 
 
215654 }else{
215655 sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
215656 }
215657 sqlite3_result_subtype(ctx, JSON_SUBTYPE);
215658 }
@@ -215745,16 +216047,15 @@
215745 }
215746 }
215747 }
215748 static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
215749 JsonString *pStr;
 
215750 pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
215751 if( pStr ){
215752 int flags;
215753 jsonAppendChar(pStr, '}');
215754 pStr->pCtx = ctx;
215755 flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215756 if( pStr->eErr ){
215757 jsonReturnString(pStr, 0, 0);
215758 return;
215759 }else if( flags & JSON_BLOB ){
215760 jsonReturnStringAsBlob(pStr);
@@ -215771,10 +216072,13 @@
215771 pStr->bStatic = 1;
215772 }else{
215773 sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
215774 jsonStringTrimOneChar(pStr);
215775 }
 
 
 
215776 }else{
215777 sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
215778 }
215779 sqlite3_result_subtype(ctx, JSON_SUBTYPE);
215780 }
@@ -216271,11 +216575,11 @@
216271 if( idxNum==3 ){
216272 zRoot = (const char*)sqlite3_value_text(argv[1]);
216273 if( zRoot==0 ) return SQLITE_OK;
216274 if( zRoot[0]!='$' ){
216275 sqlite3_free(cur->pVtab->zErrMsg);
216276 cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
216277 jsonEachCursorReset(p);
216278 return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216279 }
216280 p->nRoot = sqlite3Strlen30(zRoot);
216281 if( zRoot[1]==0 ){
@@ -216289,11 +216593,11 @@
216289 p->eType = 0;
216290 p->iEnd = 0;
216291 return SQLITE_OK;
216292 }
216293 sqlite3_free(cur->pVtab->zErrMsg);
216294 cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
216295 jsonEachCursorReset(p);
216296 return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216297 }
216298 if( p->sParse.iLabel ){
216299 p->i = p->sParse.iLabel;
@@ -216379,10 +216683,12 @@
216379 /* | | | | | | */
216380 JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc),
216381 JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc),
216382 JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
216383 JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
 
 
216384 JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
216385 JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
216386 JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
216387 JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc),
216388 JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc),
@@ -220226,11 +220532,11 @@
220226 tree.nBytesPerCell = 8 + 8 * tree.nDim;
220227 node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
220228 if( node.zData==0 ) return;
220229 nData = sqlite3_value_bytes(apArg[1]);
220230 if( nData<4 ) return;
220231 if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
220232
220233 pOut = sqlite3_str_new(0);
220234 for(ii=0; ii<NCELL(&node); ii++){
220235 RtreeCell cell;
220236 int jj;
@@ -231218,10 +231524,11 @@
231218 struct carray_bind {
231219 void *aData; /* The data */
231220 int nData; /* Number of elements */
231221 int mFlags; /* Control flags */
231222 void (*xDel)(void*); /* Destructor for aData */
 
231223 };
231224
231225
231226 /* carray_cursor is a subclass of sqlite3_vtab_cursor which will
231227 ** serve as the underlying representation of a cursor that scans
@@ -231550,26 +231857,38 @@
231550 ** Destructor for the carray_bind object
231551 */
231552 static void carrayBindDel(void *pPtr){
231553 carray_bind *p = (carray_bind*)pPtr;
231554 if( p->xDel!=SQLITE_STATIC ){
231555 p->xDel(p->aData);
231556 }
231557 sqlite3_free(p);
231558 }
231559
231560 /*
231561 ** Invoke this interface in order to bind to the single-argument
231562 ** version of CARRAY().
 
 
 
 
 
 
 
 
 
 
 
231563 */
231564 SQLITE_API int sqlite3_carray_bind(
231565 sqlite3_stmt *pStmt,
231566 int idx,
231567 void *aData,
231568 int nData,
231569 int mFlags,
231570 void (*xDestroy)(void*)
 
231571 ){
231572 carray_bind *pNew = 0;
231573 int i;
231574 int rc = SQLITE_OK;
231575
@@ -231642,23 +231961,41 @@
231642 }
231643 }else{
231644 memcpy(pNew->aData, aData, sz);
231645 }
231646 pNew->xDel = sqlite3_free;
 
231647 }else{
231648 pNew->aData = aData;
231649 pNew->xDel = xDestroy;
 
231650 }
231651 return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel);
231652
231653 carray_bind_error:
231654 if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){
231655 xDestroy(aData);
231656 }
231657 sqlite3_free(pNew);
231658 return rc;
231659 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231660
231661 /*
231662 ** Invoke this routine to register the carray() function.
231663 */
231664 SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3 *db){
@@ -232017,10 +232354,24 @@
232017 ** bytes read.
232018 */
232019 static int sessionVarintGet(const u8 *aBuf, int *piVal){
232020 return getVarint32(aBuf, *piVal);
232021 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232022
232023 /* Load an unaligned and unsigned 32-bit integer */
232024 #define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
232025
232026 /*
@@ -232312,31 +232663,31 @@
232312 for(i=0; i<pTab->nCol; i++){
232313 int eType = *a;
232314 int isPK = pTab->abPK[i];
232315 if( bPkOnly && isPK==0 ) continue;
232316
232317 /* It is not possible for eType to be SQLITE_NULL here. The session
232318 ** module does not record changes for rows with NULL values stored in
232319 ** primary key columns. */
232320 assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
232321 || eType==SQLITE_TEXT || eType==SQLITE_BLOB
232322 || eType==SQLITE_NULL || eType==0
232323 );
232324 assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) );
232325
232326 if( isPK ){
232327 a++;
232328 h = sessionHashAppendType(h, eType);
232329 if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
232330 h = sessionHashAppendI64(h, sessionGetI64(a));
232331 a += 8;
232332 }else{
232333 int n;
232334 a += sessionVarintGet(a, &n);
232335 h = sessionHashAppendBlob(h, n, a);
232336 a += n;
232337 }
 
 
 
 
232338 }else{
232339 a += sessionSerialLen(a);
232340 }
232341 }
232342 return (h % nBucket);
@@ -234741,14 +235092,17 @@
234741 *pnChangeset = 0;
234742 *ppChangeset = 0;
234743 }
234744
234745 if( pSession->rc ) return pSession->rc;
234746 rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
234747 if( rc!=SQLITE_OK ) return rc;
234748
234749 sqlite3_mutex_enter(sqlite3_db_mutex(db));
 
 
 
 
 
234750
234751 for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
234752 if( pTab->nEntry ){
234753 const char *zName = pTab->zName;
234754 int i; /* Used to iterate through hash buckets */
@@ -235227,11 +235581,12 @@
235227
235228 if( rc==SQLITE_OK ){
235229 u8 *aVal = &pIn->aData[pIn->iNext];
235230 if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
235231 int nByte;
235232 pIn->iNext += sessionVarintGet(aVal, &nByte);
 
235233 rc = sessionInputBuffer(pIn, nByte);
235234 if( rc==SQLITE_OK ){
235235 if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
235236 rc = SQLITE_CORRUPT_BKPT;
235237 }else{
@@ -235280,11 +235635,12 @@
235280 int nCol = 0;
235281 int nRead = 0;
235282
235283 rc = sessionInputBuffer(pIn, 9);
235284 if( rc==SQLITE_OK ){
235285 nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol);
 
235286 /* The hard upper limit for the number of columns in an SQLite
235287 ** database table is, according to sqliteLimit.h, 32676. So
235288 ** consider any table-header that purports to have more than 65536
235289 ** columns to be corrupt. This is convenient because otherwise,
235290 ** if the (nCol>65536) condition below were omitted, a sufficiently
@@ -235300,12 +235656,19 @@
235300
235301 while( rc==SQLITE_OK ){
235302 while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){
235303 nRead++;
235304 }
 
 
 
 
235305 if( (pIn->iNext + nRead)<pIn->nData ) break;
235306 rc = sessionInputBuffer(pIn, nRead + 100);
 
 
 
235307 }
235308 *pnByte = nRead+1;
235309 return rc;
235310 }
235311
@@ -235433,14 +235796,14 @@
235433 sqlite3ValueFree(p->apValue[i]);
235434 }
235435 memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2);
235436 }
235437
235438 /* Make sure the buffer contains at least 10 bytes of input data, or all
235439 ** remaining data if there are less than 10 bytes available. This is
235440 ** sufficient either for the 'T' or 'P' byte and the varint that follows
235441 ** it, or for the two single byte values otherwise. */
235442 p->rc = sessionInputBuffer(&p->in, 2);
235443 if( p->rc!=SQLITE_OK ) return p->rc;
235444
235445 p->in.iCurrent = p->in.iNext;
235446 sessionDiscardData(&p->in);
@@ -235466,15 +235829,17 @@
235466 ** corrupt changeset. */
235467 assert( p->in.iNext==1 || p->zTab );
235468 return (p->rc = SQLITE_CORRUPT_BKPT);
235469 }
235470
235471 p->op = op;
235472 p->bIndirect = p->in.aData[p->in.iNext++];
235473 if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
235474 return (p->rc = SQLITE_CORRUPT_BKPT);
235475 }
 
 
235476
235477 if( paRec ){
235478 int nVal; /* Number of values to buffer */
235479 if( p->bPatchset==0 && op==SQLITE_UPDATE ){
235480 nVal = p->nCol * 2;
@@ -239307,11 +239672,17 @@
239307 # define FLEXARRAY
239308 #else
239309 # define FLEXARRAY 1
239310 #endif
239311
239312 #endif
 
 
 
 
 
 
239313
239314 /* Truncate very long tokens to this many bytes. Hard limit is
239315 ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
239316 ** field that occurs at the start of each leaf page (see fts5_index.c). */
239317 #define FTS5_MAX_TOKEN_SIZE 32768
@@ -253198,11 +253569,11 @@
253198 ){
253199 const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE);
253200 int iSegid = pSeg->pSeg->iSegid;
253201 u8 *aPg = pSeg->pLeaf->p;
253202 int nPg = pSeg->pLeaf->nn;
253203 int iPgIdx = pSeg->pLeaf->szLeaf;
253204
253205 u64 iDelta = 0;
253206 int iNextOff = 0;
253207 int iOff = 0;
253208 int nIdx = 0;
@@ -253277,11 +253648,11 @@
253277 iStart = iSOP + (nPos/2);
253278 iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
253279 iSOP += fts5GetVarint32(&aPg[iSOP], nPos);
253280 }
253281 assert_nc( iSOP==pSeg->iLeafOffset );
253282 iNextOff = pSeg->iLeafOffset + pSeg->nPos;
253283 }
253284 }
253285
253286 iOff = iStart;
253287
@@ -253357,35 +253728,35 @@
253357 if( iNextOff!=iPgIdx ){
253358 /* This is the only position-list associated with the term, and there
253359 ** is another term following it on this page. So the subsequent term
253360 ** needs to be moved to replace the term associated with the entry
253361 ** being removed. */
253362 int nPrefix = 0;
253363 int nSuffix = 0;
253364 int nPrefix2 = 0;
253365 int nSuffix2 = 0;
253366
253367 iDelKeyOff = iNextOff;
253368 iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2);
253369 iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2);
253370
253371 if( iKey!=1 ){
253372 iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix);
253373 }
253374 iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix);
253375
253376 nPrefix = MIN(nPrefix, nPrefix2);
253377 nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
253378
253379 if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
253380 FTS5_CORRUPT_IDX(p);
253381 }else{
253382 if( iKey!=1 ){
253383 iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
253384 }
253385 iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
253386 if( nPrefix2>pSeg->term.n ){
253387 FTS5_CORRUPT_IDX(p);
253388 }else if( nPrefix2>nPrefix ){
253389 memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
253390 iOff += (nPrefix2-nPrefix);
253391 }
@@ -253412,11 +253783,11 @@
253412 Fts5Data *pTerm = fts5DataRead(p, iId);
253413 if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
253414 u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
253415 int nTermIdx = pTerm->nn - pTerm->szLeaf;
253416 int iTermIdx = 0;
253417 int iTermOff = 0;
253418
253419 while( 1 ){
253420 u32 iVal = 0;
253421 int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal);
253422 iTermOff += iVal;
@@ -253423,16 +253794,19 @@
253423 if( (iTermIdx+nByte)>=nTermIdx ) break;
253424 iTermIdx += nByte;
253425 }
253426 nTermIdx = iTermIdx;
253427
253428 memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
253429 fts5PutU16(&pTerm->p[2], iTermOff);
253430
253431 fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
253432 if( nTermIdx==0 ){
253433 fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
 
 
 
253434 }
253435 }
253436 fts5DataRelease(pTerm);
253437 }
253438 }
@@ -253451,11 +253825,13 @@
253451 int nShift = iNextOff - iOff; /* Distance to move them */
253452
253453 int iPrevKeyOut = 0;
253454 int iKeyIn = 0;
253455
253456 memmove(&aPg[iOff], &aPg[iNextOff], nMove);
 
 
253457 iPgIdx -= nShift;
253458 nPg = iPgIdx;
253459 fts5PutU16(&aPg[2], iPgIdx);
253460
253461 for(iIdx=0; iIdx<nIdx; /* no-op */){
@@ -253889,11 +254265,11 @@
253889 if( nMerge<0 ){
253890 Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
253891 fts5StructureRelease(pStruct);
253892 pStruct = pNew;
253893 nMin = 1;
253894 nMerge = nMerge*-1;
253895 }
253896 if( pStruct && pStruct->nLevel ){
253897 if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
253898 fts5StructureWrite(p, pStruct);
253899 }
@@ -261097,11 +261473,11 @@
261097 int nArg, /* Number of args */
261098 sqlite3_value **apUnused /* Function arguments */
261099 ){
261100 assert( nArg==0 );
261101 UNUSED_PARAM2(nArg, apUnused);
261102 sqlite3_result_text(pCtx, "fts5: 2025-12-11 18:16:39 e785a80e4100c368dca8d73cb662cff4d0fd76734fa0f3fa9b5754a380f7c746", -1, SQLITE_TRANSIENT);
261103 }
261104
261105 /*
261106 ** Implementation of fts5_locale(LOCALE, TEXT) function.
261107 **
261108
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** c476d956d0bd3065cf894de6f9d393b999ff with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468 ** [sqlite_version()] and [sqlite_source_id()].
469 */
470 #define SQLITE_VERSION "3.52.0"
471 #define SQLITE_VERSION_NUMBER 3052000
472 #define SQLITE_SOURCE_ID "2026-02-04 20:51:27 c476d956d0bd3065cf894de6f9d393b999ff7d2268a35f01a6d88804789ab58f"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2026-02-04T20:51:27.822Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -4752,16 +4752,32 @@
4752 ** compiles to see if some SQL syntax is well-formed, without generating
4753 ** messages on the global error log when it is not. If the test compile
4754 ** fails, the sqlite3_prepare_v3() call returns the same error indications
4755 ** with or without this flag; it just omits the call to [sqlite3_log()] that
4756 ** logs the error.
4757 **
4758 ** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
4759 ** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
4760 ** the SQL statement is part of a database schema. This makes a difference
4761 ** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
4762 ** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
4763 ** SQL functions may not be called unless they are tagged with
4764 ** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
4765 ** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
4766 ** when preparing SQL that is derived from parts of the database
4767 ** schema. In particular, virtual table implementations that
4768 ** run SQL statements based on the arguments to their CREATE VIRTUAL
4769 ** TABLE statement should use [sqlite3_prepare_v3()] and set the
4770 ** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
4771 ** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
4772 ** </dl>
4773 */
4774 #define SQLITE_PREPARE_PERSISTENT 0x01
4775 #define SQLITE_PREPARE_NORMALIZE 0x02
4776 #define SQLITE_PREPARE_NO_VTAB 0x04
4777 #define SQLITE_PREPARE_DONT_LOG 0x10
4778 #define SQLITE_PREPARE_FROM_DDL 0x20
4779
4780 /*
4781 ** CAPI3REF: Compiling An SQL Statement
4782 ** KEYWORDS: {SQL statement compiler}
4783 ** METHOD: sqlite3
@@ -4771,12 +4787,13 @@
4787 ** program using one of these routines. Or, in other words, these routines
4788 ** are constructors for the [prepared statement] object.
4789 **
4790 ** The preferred routine to use is [sqlite3_prepare_v2()]. The
4791 ** [sqlite3_prepare()] interface is legacy and should be avoided.
4792 ** [sqlite3_prepare_v3()] has an extra
4793 ** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times
4794 ** needed for special purpose or to pass along security restrictions.
4795 **
4796 ** The use of the UTF-8 interfaces is preferred, as SQLite currently
4797 ** does all parsing using UTF-8. The UTF-16 interfaces are provided
4798 ** as a convenience. The UTF-16 interfaces work by converting the
4799 ** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -5177,12 +5194,12 @@
5194 ** it should be a pointer to well-formed UTF8 text.
5195 ** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
5196 ** it should be a pointer to well-formed UTF16 text.
5197 ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
5198 ** it should be a pointer to a well-formed unicode string that is
5199 ** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT,
5200 ** or UTF16 otherwise.
5201 **
5202 ** [[byte-order determination rules]] ^The byte-order of
5203 ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
5204 ** found in the first character, which is removed, or in the absence of a BOM
5205 ** the byte order is the native byte order of the host
@@ -5224,14 +5241,19 @@
5241 ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
5242 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
5243 ** object and pointer to it must remain valid until then. ^SQLite will then
5244 ** manage the lifetime of its private copy.
5245 **
5246 ** ^The sixth argument (the E argument)
5247 ** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of
5248 ** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
5249 ** or [SQLITE_UTF16LE] to specify the encoding of the text in the
5250 ** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the
5251 ** string argument is both UTF-8 encoded and is zero-terminated. In other
5252 ** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at
5253 ** least N+1 bytes and that the Z&#91;N&#93; byte is zero. If
5254 ** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the
5255 ** allowed values shown above, or if the text encoding is different
5256 ** from the encoding specified by the sixth parameter, then the behavior
5257 ** is undefined.
5258 **
5259 ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
@@ -6094,17 +6116,63 @@
6116 /*
6117 ** CAPI3REF: Text Encodings
6118 **
6119 ** These constants define integer codes that represent the various
6120 ** text encodings supported by SQLite.
6121 **
6122 ** <dl>
6123 ** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd>
6124 **
6125 ** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16
6126 ** with each code point being expressed "little endian" - the least significant
6127 ** byte first. This is the usual encoding, for example on Windows.</dd>
6128 **
6129 ** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16
6130 ** with each code point being expressed "big endian" - the most significant
6131 ** byte first. This encoding is less common, but is still sometimes seen,
6132 ** specially on older systems.
6133 **
6134 ** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16
6135 ** with each code point being expressed either little endian or as big
6136 ** endian, according to the native endianness of the host computer.
6137 **
6138 ** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used
6139 ** to declare the preferred text for [application-defined SQL functions]
6140 ** created using [sqlite3_create_function()] and similar. If the preferred
6141 ** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep
6142 ** parameter) is SQLITE_ANY, that indicates that the function does not have
6143 ** a preference regarding the text encoding of its parameters and can take
6144 ** any text encoding that the SQLite core find convenient to supply. This
6145 ** option is deprecated. Please do not use it in new applications.
6146 **
6147 ** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding
6148 ** value may be used as the 3rd parameter (the eTextRep parameter) to
6149 ** [sqlite3_create_collation()] and similar. This encoding value means
6150 ** that the application-defined collating sequence created expects its
6151 ** input strings to be in UTF16 in native byte order, and that the start
6152 ** of the strings must be aligned to a 2-byte boundary.
6153 **
6154 ** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be
6155 ** used to specify the text encoding to strings input to [sqlite3_result_text64()]
6156 ** and [sqlite3_bind_text64()]. It means that the input string (call it "z")
6157 ** is UTF-8 encoded and that it is zero-terminated. If the length parameter
6158 ** (call it "n") is non-negative, this encoding option means that the caller
6159 ** guarantees that z array contains at least n+1 bytes and that the z&#91;n&#93;
6160 ** byte has a value of zero.
6161 ** This option gives the same output as SQLITE_UTF8, but can be more efficient
6162 ** by avoiding the need to make a copy of the input string, in some cases.
6163 ** However, if z is allocated to hold fewer than n+1 bytes or if the
6164 ** z&#91;n&#93; byte is not zero, undefined behavior may result.
6165 ** </dl>
6166 */
6167 #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
6168 #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
6169 #define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
6170 #define SQLITE_UTF16 4 /* Use native byte order */
6171 #define SQLITE_ANY 5 /* Deprecated */
6172 #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
6173 #define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */
6174
6175 /*
6176 ** CAPI3REF: Function Flags
6177 **
6178 ** These constants may be ORed together with the
@@ -6606,14 +6674,18 @@
6674 ** use for client data is to provide a mechanism for wrapper libraries
6675 ** to store additional information about an SQLite database connection.
6676 **
6677 ** There is no limit (other than available memory) on the number of different
6678 ** client data pointers (with different names) that can be attached to a
6679 ** single database connection. However, the current implementation stores
6680 ** the content on a linked list. Insert and retrieval performance will
6681 ** be proportional to the number of entries. The design use case, and
6682 ** the use case for which the implementation is optimized, is
6683 ** that an application will store only small number of client data names,
6684 ** typically just one or two. This interface is not intended to be a
6685 ** generalized key/value store for thousands or millions of keys. It
6686 ** will work for that, but performance might be disappointing.
6687 **
6688 ** There is no way to enumerate the client data pointers
6689 ** associated with a database connection. The N parameter can be thought
6690 ** of as a secret key such that only code that knows the secret key is able
6691 ** to access the associated data.
@@ -6717,14 +6789,18 @@
6789 ** ^The sqlite3_result_text(), sqlite3_result_text16(),
6790 ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
6791 ** set the return value of the application-defined function to be
6792 ** a text string which is represented as UTF-8, UTF-16 native byte order,
6793 ** UTF-16 little endian, or UTF-16 big endian, respectively.
6794 ** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an
6795 ** application-defined function to be a text string in an encoding
6796 ** specified the E parameter, which must be one
6797 ** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
6798 ** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that
6799 ** the result text is both UTF-8 and zero-terminated. In other words,
6800 ** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that
6801 ** the Z&#91;N&#93; is zero.
6802 ** ^SQLite takes the text result from the application from
6803 ** the 2nd parameter of the sqlite3_result_text* interfaces.
6804 ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
6805 ** other than sqlite3_result_text64() is negative, then SQLite computes
6806 ** the string length itself by searching the 2nd parameter for the first
@@ -6807,11 +6883,11 @@
6883 SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
6884 SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
6885 SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
6886 SQLITE_API void sqlite3_result_null(sqlite3_context*);
6887 SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
6888 SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n,
6889 void(*)(void*), unsigned char encoding);
6890 SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
6891 SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
6892 SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
6893 SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
@@ -7746,22 +7822,22 @@
7822 ** ^This interface loads an SQLite extension library from the named file.
7823 **
7824 ** ^The sqlite3_load_extension() interface attempts to load an
7825 ** [SQLite extension] library contained in the file zFile. If
7826 ** the file cannot be loaded directly, attempts are made to load
7827 ** with various operating-system specific filename extensions added.
7828 ** So for example, if "samplelib" cannot be loaded, then names like
7829 ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
7830 ** be tried also.
7831 **
7832 ** ^The entry point is zProc.
7833 ** ^(zProc may be 0, in which case SQLite will try to come up with an
7834 ** entry point name on its own. It first tries "sqlite3_extension_init".
7835 ** If that does not work, it tries names of the form "sqlite3_X_init"
7836 ** where X consists of the lower-case equivalent of all ASCII alphabetic
7837 ** characters or all ASCII alphanumeric characters in the filename from
7838 ** the last "/" to the first following "." and omitting any initial "lib".)^
7839 ** ^The sqlite3_load_extension() interface returns
7840 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
7841 ** ^If an error occurs and pzErrMsg is not 0, then the
7842 ** [sqlite3_load_extension()] interface shall attempt to
7843 ** fill *pzErrMsg with error message text stored in memory
@@ -11495,23 +11571,45 @@
11571 #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
11572
11573 /*
11574 ** CAPI3REF: Bind array values to the CARRAY table-valued function
11575 **
11576 ** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
11577 ** parameter that is the first argument of the [carray() table-valued function].
11578 ** The S parameter is a pointer to the [prepared statement] that uses the carray()
11579 ** functions. I is the parameter index to be bound. I must be the index of the
11580 ** parameter that is the first argument to the carray() table-valued function.
11581 ** P is a pointer to the array to be bound, and N is the number of elements in
11582 ** the array. The F argument is one of constants [SQLITE_CARRAY_INT32],
11583 ** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
11584 ** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
11585 **
11586 ** If the X argument is not a NULL pointer or one of the special
11587 ** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
11588 ** the function X with argument D when it is finished using the data in P.
11589 ** The call to X(D) is a destructor for the array P. The destructor X(D)
11590 ** is invoked even if the call to sqlite3_carray_bind() fails. If the X
11591 ** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
11592 ** that the data static and the destructor is never invoked. If the X
11593 ** parameter is the special-case value [SQLITE_TRANSIENT], then
11594 ** sqlite3_carray_bind_v2() makes its own private copy of the data prior
11595 ** to returning and never invokes the destructor X.
11596 **
11597 ** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2()
11598 ** with a D parameter set to P. In other words,
11599 ** sqlite3_carray_bind(S,I,P,N,F,X) is same as
11600 ** sqlite3_carray_bind(S,I,P,N,F,X,P).
11601 */
11602 SQLITE_API int sqlite3_carray_bind_v2(
11603 sqlite3_stmt *pStmt, /* Statement to be bound */
11604 int i, /* Parameter index */
11605 void *aData, /* Pointer to array data */
11606 int nData, /* Number of data elements */
11607 int mFlags, /* CARRAY flags */
11608 void (*xDel)(void*), /* Destructor for aData */
11609 void *pDel /* Optional argument to xDel() */
11610 );
11611 SQLITE_API int sqlite3_carray_bind(
11612 sqlite3_stmt *pStmt, /* Statement to be bound */
11613 int i, /* Parameter index */
11614 void *aData, /* Pointer to array data */
11615 int nData, /* Number of data elements */
@@ -14352,10 +14450,31 @@
14450 #ifndef SQLITE_MAX_LENGTH
14451 # define SQLITE_MAX_LENGTH 1000000000
14452 #endif
14453 #define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
14454
14455 /*
14456 ** Maximum size of any single memory allocation.
14457 **
14458 ** This is not a limit on the total amount of memory used. This is
14459 ** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
14460 **
14461 ** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
14462 ** This provides a 256-byte safety margin for defense against 32-bit
14463 ** signed integer overflow bugs when computing memory allocation sizes.
14464 ** Paranoid applications might want to reduce the maximum allocation size
14465 ** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
14466 ** or even smaller would be reasonable upper bounds on the size of a memory
14467 ** allocations for most applications.
14468 */
14469 #ifndef SQLITE_MAX_ALLOCATION_SIZE
14470 # define SQLITE_MAX_ALLOCATION_SIZE 2147483391
14471 #endif
14472 #if SQLITE_MAX_ALLOCATION_SIZE>2147483391
14473 # error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
14474 #endif
14475
14476 /*
14477 ** This is the maximum number of
14478 **
14479 ** * Columns in a table
14480 ** * Columns in an index
@@ -17529,11 +17648,11 @@
17648
17649 /*
17650 ** Additional non-public SQLITE_PREPARE_* flags
17651 */
17652 #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
17653 #define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */
17654
17655 /*
17656 ** Prototypes for the VDBE interface. See comments on the implementation
17657 ** for a description of what each of these routines does.
17658 */
@@ -20202,31 +20321,17 @@
20321 };
20322
20323 /*
20324 ** An instance of the following structure contains all information
20325 ** needed to generate code for a single SELECT statement.
 
 
 
 
 
 
 
 
 
 
 
 
 
20326 */
20327 struct Select {
20328 u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
20329 LogEst nSelectRow; /* Estimated number of result rows */
20330 u32 selFlags; /* Various SF_* values */
20331 int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
20332 u32 selId; /* Unique identifier number for this SELECT */
 
20333 ExprList *pEList; /* The fields of the result */
20334 SrcList *pSrc; /* The FROM clause */
20335 Expr *pWhere; /* The WHERE clause */
20336 ExprList *pGroupBy; /* The GROUP BY clause */
20337 Expr *pHaving; /* The HAVING clause */
@@ -20254,28 +20359,28 @@
20359 #define SF_Distinct 0x0000001 /* Output should be DISTINCT */
20360 #define SF_All 0x0000002 /* Includes the ALL keyword */
20361 #define SF_Resolved 0x0000004 /* Identifiers have been resolved */
20362 #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
20363 #define SF_HasAgg 0x0000010 /* Contains aggregate functions */
20364 /* 0x0000020 // available for reuse */
20365 #define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
20366 #define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
20367 #define SF_Compound 0x0000100 /* Part of a compound query */
20368 #define SF_Values 0x0000200 /* Synthesized from VALUES clause */
20369 #define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
20370 #define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
20371 #define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
20372 #define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
20373 #define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
20374 /* 0x0008000 // available for reuse */
20375 #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
20376 #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
20377 #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
20378 #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
20379 #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
20380 #define SF_View 0x0200000 /* SELECT statement is a view */
20381 /* 0x0400000 // available for reuse */
20382 #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
20383 #define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
20384 #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
20385 #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
20386 #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
@@ -20291,15 +20396,10 @@
20396 /*
20397 ** The results of a SELECT can be distributed in several ways, as defined
20398 ** by one of the following macros. The "SRT" prefix means "SELECT Result
20399 ** Type".
20400 **
 
 
 
 
 
20401 ** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
20402 ** set is not empty.
20403 **
20404 ** SRT_Discard Throw the results away. This is used by SELECT
20405 ** statements within triggers whose only purpose is
@@ -20359,34 +20459,32 @@
20459 ** column returned by the SELECT is used as the integer
20460 ** key. If (pDest->iSDParm>0), then the table is an index
20461 ** table. (pDest->iSDParm) is the number of key columns in
20462 ** each index record in this case.
20463 */
20464 #define SRT_Exists 1 /* Store 1 if the result is not empty */
20465 #define SRT_Discard 2 /* Do not save the results anywhere */
20466 #define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */
20467 #define SRT_DistQueue 4 /* Like SRT_Queue, but unique results only */
 
 
20468
20469 /* The DISTINCT clause is ignored for all of the above. Not that
20470 ** IgnorableDistinct() implies IgnorableOrderby() */
20471 #define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
20472
20473 #define SRT_Queue 5 /* Store result in an queue */
20474 #define SRT_Fifo 6 /* Store result as data with an automatic rowid */
20475
20476 /* The ORDER BY clause is ignored for all of the above */
20477 #define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
20478
20479 #define SRT_Output 7 /* Output each row of result */
20480 #define SRT_Mem 8 /* Store result in a memory cell */
20481 #define SRT_Set 9 /* Store results as keys in an index */
20482 #define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */
20483 #define SRT_Coroutine 11 /* Generate a single row of result */
20484 #define SRT_Table 12 /* Store result as data with an automatic rowid */
20485 #define SRT_Upfrom 13 /* Store result as data with rowid */
20486
20487 /*
20488 ** An instance of this object describes where to put of the results of
20489 ** a SELECT statement.
20490 */
@@ -21018,10 +21116,11 @@
21116 u16 mWFlags; /* Use-dependent flags */
21117 union { /* Extra data for callback */
21118 NameContext *pNC; /* Naming context */
21119 int n; /* A counter */
21120 int iCur; /* A cursor number */
21121 int sz; /* String literal length */
21122 SrcList *pSrcList; /* FROM clause */
21123 struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
21124 struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
21125 int *aiCol; /* array of column indexes */
21126 struct IdxCover *pIdxCover; /* Check for index coverage */
@@ -21801,10 +21900,11 @@
21900 SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
21901 #endif
21902 SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
21903 SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
21904 SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
21905 SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*);
21906 SQLITE_PRIVATE int sqlite3IsRowid(const char*);
21907 SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
21908 SQLITE_PRIVATE void sqlite3GenerateRowDelete(
21909 Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
21910 SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -24489,10 +24589,11 @@
24589 SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
24590 SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
24591 SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
24592 SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
24593 SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
24594 SQLITE_PRIVATE int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*));
24595 SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
24596 #ifdef SQLITE_OMIT_FLOATING_POINT
24597 # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
24598 #else
24599 SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
@@ -31335,31 +31436,10 @@
31436 sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
31437 }
31438 *pp = p;
31439 }
31440
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31441 /*
31442 ** Allocate memory. This routine is like sqlite3_malloc() except that it
31443 ** assumes the memory subsystem has already been initialized.
31444 */
31445 SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
@@ -31579,12 +31659,11 @@
31659 }
31660 if( nBytes==0 ){
31661 sqlite3_free(pOld); /* IMP: R-26507-47431 */
31662 return 0;
31663 }
31664 if( nBytes>SQLITE_MAX_ALLOCATION_SIZE ){
 
31665 return 0;
31666 }
31667 nOld = sqlite3MallocSize(pOld);
31668 /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
31669 ** argument to xRealloc is always a value returned by a prior call to
@@ -48881,78 +48960,54 @@
48960 { "WriteFile", (SYSCALL)WriteFile, 0 },
48961
48962 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
48963 LPOVERLAPPED))aSyscall[61].pCurrent)
48964
 
 
 
 
 
48965 /*
48966 ** For WaitForSingleObject(), MSDN says:
48967 **
48968 ** Minimum supported client: Windows XP [desktop apps | UWP apps]
48969 ** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
48970 */
48971 { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
48972
48973 #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
48974 DWORD))aSyscall[62].pCurrent)
48975
48976 #if !SQLITE_OS_WINCE
48977 { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
48978 #else
48979 { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
48980 #endif
48981
48982 #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
48983 BOOL))aSyscall[63].pCurrent)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48984
48985 { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
48986
48987 #define osGetNativeSystemInfo ((VOID(WINAPI*)( \
48988 LPSYSTEM_INFO))aSyscall[64].pCurrent)
48989
48990 #if defined(SQLITE_WIN32_HAS_ANSI)
48991 { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
48992 #else
48993 { "OutputDebugStringA", (SYSCALL)0, 0 },
48994 #endif
48995
48996 #define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[65].pCurrent)
48997
48998 #if defined(SQLITE_WIN32_HAS_WIDE)
48999 { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
49000 #else
49001 { "OutputDebugStringW", (SYSCALL)0, 0 },
49002 #endif
49003
49004 #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[66].pCurrent)
49005
49006 { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
49007
49008 #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[67].pCurrent)
49009
49010 /*
49011 ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
49012 ** is really just a macro that uses a compiler intrinsic (e.g. x64).
49013 ** So do not try to make this is into a redefinable interface.
@@ -48963,38 +49018,38 @@
49018 #define osInterlockedCompareExchange InterlockedCompareExchange
49019 #else
49020 { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
49021
49022 #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
49023 SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[68].pCurrent)
49024 #endif /* defined(InterlockedCompareExchange) */
49025
49026 #if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
49027 { "UuidCreate", (SYSCALL)UuidCreate, 0 },
49028 #else
49029 { "UuidCreate", (SYSCALL)0, 0 },
49030 #endif
49031
49032 #define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[69].pCurrent)
49033
49034 #if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
49035 { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
49036 #else
49037 { "UuidCreateSequential", (SYSCALL)0, 0 },
49038 #endif
49039
49040 #define osUuidCreateSequential \
49041 ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[70].pCurrent)
49042
49043 #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
49044 { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
49045 #else
49046 { "FlushViewOfFile", (SYSCALL)0, 0 },
49047 #endif
49048
49049 #define osFlushViewOfFile \
49050 ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[71].pCurrent)
49051
49052 /*
49053 ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
49054 ** to implement blocking locks with timeouts. MSDN says:
49055 **
@@ -49007,11 +49062,11 @@
49062 { "CreateEvent", (SYSCALL)0, 0 },
49063 #endif
49064
49065 #define osCreateEvent ( \
49066 (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
49067 aSyscall[72].pCurrent \
49068 )
49069
49070 /*
49071 ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
49072 ** for the case where a timeout expires and a lock request must be
@@ -49024,68 +49079,68 @@
49079 { "CancelIo", (SYSCALL)CancelIo, 0 },
49080 #else
49081 { "CancelIo", (SYSCALL)0, 0 },
49082 #endif
49083
49084 #define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[73].pCurrent)
49085
49086 #if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32)
49087 { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 },
49088 #else
49089 { "GetModuleHandleW", (SYSCALL)0, 0 },
49090 #endif
49091
49092 #define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[74].pCurrent)
49093
49094 #ifndef _WIN32
49095 { "getenv", (SYSCALL)getenv, 0 },
49096 #else
49097 { "getenv", (SYSCALL)0, 0 },
49098 #endif
49099
49100 #define osGetenv ((const char *(*)(const char *))aSyscall[75].pCurrent)
49101
49102 #ifndef _WIN32
49103 { "getcwd", (SYSCALL)getcwd, 0 },
49104 #else
49105 { "getcwd", (SYSCALL)0, 0 },
49106 #endif
49107
49108 #define osGetcwd ((char*(*)(char*,size_t))aSyscall[76].pCurrent)
49109
49110 #ifndef _WIN32
49111 { "readlink", (SYSCALL)readlink, 0 },
49112 #else
49113 { "readlink", (SYSCALL)0, 0 },
49114 #endif
49115
49116 #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[77].pCurrent)
49117
49118 #ifndef _WIN32
49119 { "lstat", (SYSCALL)lstat, 0 },
49120 #else
49121 { "lstat", (SYSCALL)0, 0 },
49122 #endif
49123
49124 #define osLstat ((int(*)(const char*,struct stat*))aSyscall[78].pCurrent)
49125
49126 #ifndef _WIN32
49127 { "__errno", (SYSCALL)__errno, 0 },
49128 #else
49129 { "__errno", (SYSCALL)0, 0 },
49130 #endif
49131
49132 #define osErrno (*((int*(*)(void))aSyscall[79].pCurrent)())
49133
49134 #ifndef _WIN32
49135 { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
49136 #else
49137 { "cygwin_conv_path", (SYSCALL)0, 0 },
49138 #endif
49139
49140 #define osCygwin_conv_path ((size_t(*)(unsigned int, \
49141 const void *, void *, size_t))aSyscall[80].pCurrent)
49142
49143 }; /* End of the overrideable system calls */
49144
49145 /*
49146 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -53659,10 +53714,11 @@
53714 attr = INVALID_FILE_ATTRIBUTES;
53715 }else{
53716 attr = sAttrData.dwFileAttributes;
53717 }
53718 }else{
53719 if( noRetry ) lastErrno = osGetLastError();
53720 winLogIoerr(cnt, __LINE__);
53721 if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
53722 sqlite3_free(zConverted);
53723 return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
53724 zFilename);
@@ -54399,11 +54455,16 @@
54455 };
54456 #endif
54457
54458 /* Double-check that the aSyscall[] array has been constructed
54459 ** correctly. See ticket [bb3a86e890c8e96ab] */
54460 assert( ArraySize(aSyscall)==81 );
54461 assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 );
54462 assert( strcmp(aSyscall[20].zName,"GetFileAttributesA")==0 );
54463 assert( strcmp(aSyscall[40].zName,"HeapReAlloc")==0 );
54464 assert( strcmp(aSyscall[60].zName,"WideCharToMultiByte")==0 );
54465 assert( strcmp(aSyscall[80].zName,"cygwin_conv_path")==0 );
54466
54467 /* get memory map allocation granularity */
54468 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
54469 osGetSystemInfo(&winSysInfo);
54470 assert( winSysInfo.dwAllocationGranularity>0 );
@@ -77426,11 +77487,11 @@
77487 }
77488 assert( cursorHoldsMutex(pCur) );
77489
77490 getCellInfo(pCur);
77491 aPayload = pCur->info.pPayload;
77492 assert( (u64)offset+(u64)amt <= (u64)pCur->info.nPayload );
77493
77494 assert( aPayload > pPage->aData );
77495 if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
77496 /* Trying to read or write past the end of the data is an error. The
77497 ** conditional above is really:
@@ -77983,11 +78044,11 @@
78044 SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
78045 int rc;
78046
78047 assert( cursorOwnsBtShared(pCur) );
78048 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
78049 if( NEVER(pCur->eState==CURSOR_VALID) ){
78050 *pRes = 0;
78051 return SQLITE_OK;
78052 }
78053 rc = moveToRoot(pCur);
78054 if( rc==SQLITE_EMPTY ){
@@ -85876,10 +85937,88 @@
85937 #endif
85938
85939
85940 return SQLITE_OK;
85941 }
85942
85943 /* Like sqlite3VdbeMemSetStr() except:
85944 **
85945 ** enc is always SQLITE_UTF8
85946 ** pMem->db is always non-NULL
85947 */
85948 SQLITE_PRIVATE int sqlite3VdbeMemSetText(
85949 Mem *pMem, /* Memory cell to set to string value */
85950 const char *z, /* String pointer */
85951 i64 n, /* Bytes in string, or negative */
85952 void (*xDel)(void*) /* Destructor function */
85953 ){
85954 i64 nByte = n; /* New value for pMem->n */
85955 u16 flags;
85956
85957 assert( pMem!=0 );
85958 assert( pMem->db!=0 );
85959 assert( sqlite3_mutex_held(pMem->db->mutex) );
85960 assert( !sqlite3VdbeMemIsRowSet(pMem) );
85961
85962 /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
85963 if( !z ){
85964 sqlite3VdbeMemSetNull(pMem);
85965 return SQLITE_OK;
85966 }
85967
85968 if( nByte<0 ){
85969 nByte = strlen(z);
85970 flags = MEM_Str|MEM_Term;
85971 }else{
85972 flags = MEM_Str;
85973 }
85974 if( nByte>(i64)pMem->db->aLimit[SQLITE_LIMIT_LENGTH] ){
85975 if( xDel && xDel!=SQLITE_TRANSIENT ){
85976 if( xDel==SQLITE_DYNAMIC ){
85977 sqlite3DbFree(pMem->db, (void*)z);
85978 }else{
85979 xDel((void*)z);
85980 }
85981 }
85982 sqlite3VdbeMemSetNull(pMem);
85983 return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
85984 }
85985
85986 /* The following block sets the new values of Mem.z and Mem.xDel. It
85987 ** also sets a flag in local variable "flags" to indicate the memory
85988 ** management (one of MEM_Dyn or MEM_Static).
85989 */
85990 if( xDel==SQLITE_TRANSIENT ){
85991 i64 nAlloc = nByte + 1;
85992 testcase( nAlloc==31 );
85993 testcase( nAlloc==32 );
85994 if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
85995 return SQLITE_NOMEM_BKPT;
85996 }
85997 assert( pMem->z!=0 );
85998 memcpy(pMem->z, z, nByte);
85999 pMem->z[nByte] = 0;
86000 }else{
86001 sqlite3VdbeMemRelease(pMem);
86002 pMem->z = (char *)z;
86003 if( xDel==SQLITE_DYNAMIC ){
86004 pMem->zMalloc = pMem->z;
86005 pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
86006 pMem->xDel = 0;
86007 }else if( xDel==SQLITE_STATIC ){
86008 pMem->xDel = xDel;
86009 flags |= MEM_Static;
86010 }else{
86011 pMem->xDel = xDel;
86012 flags |= MEM_Dyn;
86013 }
86014 }
86015 pMem->flags = flags;
86016 pMem->n = (int)(nByte & 0x7fffffff);
86017 pMem->enc = SQLITE_UTF8;
86018 return SQLITE_OK;
86019 }
86020
86021 /*
86022 ** Move data out of a btree key or data field and into a Mem structure.
86023 ** The data is payload from the entry that pCur is currently pointing
86024 ** to. offset and amt determine what portion of the data or key to retrieve.
@@ -85900,11 +86039,16 @@
86039 u32 amt, /* Number of bytes to return. */
86040 Mem *pMem /* OUT: Return data in this Mem structure. */
86041 ){
86042 int rc;
86043 pMem->flags = MEM_Null;
86044 testcase( amt==SQLITE_MAX_ALLOCATION_SIZE-1 );
86045 testcase( amt==SQLITE_MAX_ALLOCATION_SIZE );
86046 if( amt>=SQLITE_MAX_ALLOCATION_SIZE ){
86047 return SQLITE_NOMEM_BKPT;
86048 }
86049 if( (u64)amt + (u64)offset > (u64)sqlite3BtreeMaxRecordSize(pCur) ){
86050 return SQLITE_CORRUPT_BKPT;
86051 }
86052 if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
86053 rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
86054 if( rc==SQLITE_OK ){
@@ -86568,10 +86712,15 @@
86712 ** the column value into *ppVal. If *ppVal is initially NULL then a new
86713 ** sqlite3_value object is allocated.
86714 **
86715 ** If *ppVal is initially NULL then the caller is responsible for
86716 ** ensuring that the value written into *ppVal is eventually freed.
86717 **
86718 ** If the buffer does not contain a well-formed record, this routine may
86719 ** read several bytes past the end of the buffer. Callers must therefore
86720 ** ensure that any buffer which may contain a corrupt record is padded
86721 ** with at least 8 bytes of addressable memory.
86722 */
86723 SQLITE_PRIVATE int sqlite3Stat4Column(
86724 sqlite3 *db, /* Database handle */
86725 const void *pRec, /* Pointer to buffer containing record */
86726 int nRec, /* Size of buffer pRec in bytes */
@@ -89584,11 +89733,11 @@
89733 assert( !zName || xDel!=SQLITE_DYNAMIC );
89734 return SQLITE_NOMEM_BKPT;
89735 }
89736 assert( p->aColName!=0 );
89737 pColName = &(p->aColName[idx+var*p->nResAlloc]);
89738 rc = sqlite3VdbeMemSetText(pColName, zName, -1, xDel);
89739 assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
89740 return rc;
89741 }
89742
89743 /*
@@ -92662,11 +92811,27 @@
92811 int n, /* Bytes in string, or negative */
92812 u8 enc, /* Encoding of z. 0 for BLOBs */
92813 void (*xDel)(void*) /* Destructor function */
92814 ){
92815 Mem *pOut = pCtx->pOut;
92816 int rc;
92817 if( enc==SQLITE_UTF8 ){
92818 rc = sqlite3VdbeMemSetText(pOut, z, n, xDel);
92819 }else if( enc==SQLITE_UTF8_ZT ){
92820 /* It is usually considered improper to assert() on an input. However,
92821 ** the following assert() is checking for inputs that are documented
92822 ** to result in undefined behavior. */
92823 assert( z==0
92824 || n<0
92825 || n>pOut->db->aLimit[SQLITE_LIMIT_LENGTH]
92826 || z[n]==0
92827 );
92828 rc = sqlite3VdbeMemSetText(pOut, z, n, xDel);
92829 pOut->flags |= MEM_Term;
92830 }else{
92831 rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
92832 }
92833 if( rc ){
92834 if( rc==SQLITE_TOOBIG ){
92835 sqlite3_result_error_toobig(pCtx);
92836 }else{
92837 /* The only errors possible from sqlite3VdbeMemSetStr are
@@ -92855,11 +93020,11 @@
93020 return;
93021 }
93022 #endif
93023 assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
93024 assert( xDel!=SQLITE_DYNAMIC );
93025 if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){
93026 if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
93027 n &= ~(u64)1;
93028 }
93029 if( n>0x7fffffff ){
93030 (void)invokeValueDestructor(z, xDel, pCtx);
@@ -93315,11 +93480,11 @@
93480 if( rc==SQLITE_OK ){
93481 u32 sz; /* Size of current row in bytes */
93482 Mem sMem; /* Raw content of current row */
93483 memset(&sMem, 0, sizeof(sMem));
93484 sz = sqlite3BtreePayloadSize(pRhs->pCsr);
93485 rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,sz,&sMem);
93486 if( rc==SQLITE_OK ){
93487 u8 *zBuf = (u8*)sMem.z;
93488 u32 iSerial;
93489 sqlite3_value *pOut = pRhs->pOut;
93490 int iOff = 1 + getVarint32(&zBuf[1], iSerial);
@@ -93964,17 +94129,29 @@
94129 rc = vdbeUnbind(p, (u32)(i-1));
94130 if( rc==SQLITE_OK ){
94131 assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
94132 if( zData!=0 ){
94133 pVar = &p->aVar[i-1];
94134 if( encoding==SQLITE_UTF8 ){
94135 rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel);
94136 }else if( encoding==SQLITE_UTF8_ZT ){
94137 /* It is usually consider improper to assert() on an input.
94138 ** However, the following assert() is checking for inputs
94139 ** that are documented to result in undefined behavior. */
94140 assert( zData==0
94141 || nData<0
94142 || nData>pVar->db->aLimit[SQLITE_LIMIT_LENGTH]
94143 || ((u8*)zData)[nData]==0
94144 );
94145 rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel);
94146 pVar->flags |= MEM_Term;
94147 }else{
94148 rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
94149 if( encoding==0 ) pVar->enc = ENC(p->db);
94150 }
94151 if( rc==SQLITE_OK && encoding!=0 ){
94152 rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
94153 }
94154 if( rc ){
94155 sqlite3Error(p->db, rc);
94156 rc = sqlite3ApiExit(p->db, rc);
94157 }
@@ -94082,11 +94259,11 @@
94259 sqlite3_uint64 nData,
94260 void (*xDel)(void*),
94261 unsigned char enc
94262 ){
94263 assert( xDel!=SQLITE_DYNAMIC );
94264 if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){
94265 if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
94266 nData &= ~(u64)1;
94267 }
94268 return bindText(pStmt, i, zData, nData, xDel, enc);
94269 }
@@ -101780,24 +101957,19 @@
101957 rc = sqlite3VdbeSorterWrite(pC, pIn2);
101958 if( rc) goto abort_due_to_error;
101959 break;
101960 }
101961
101962 /* Opcode: IdxDelete P1 P2 P3 * *
101963 ** Synopsis: key=r[P2@P3]
101964 **
101965 ** The content of P3 registers starting at register P2 form
101966 ** an unpacked index key. This opcode removes that entry from the
101967 ** index opened by cursor P1.
101968 **
101969 ** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
101970 ** and not in writable_schema mode.
 
 
 
 
 
101971 */
101972 case OP_IdxDelete: {
101973 VdbeCursor *pC;
101974 BtCursor *pCrsr;
101975 int res;
@@ -101819,11 +101991,11 @@
101991 rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
101992 if( rc ) goto abort_due_to_error;
101993 if( res==0 ){
101994 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
101995 if( rc ) goto abort_due_to_error;
101996 }else if( !sqlite3WritableSchema(db) ){
101997 rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
101998 goto abort_due_to_error;
101999 }
102000 assert( pC->deferredMoveto==0 );
102001 pC->cacheStatus = CACHE_STALE;
@@ -110988,14 +111160,10 @@
111160 }
111161 }
111162 }
111163 #endif
111164
 
 
 
 
111165 sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
111166
111167 /* If this is a converted compound query, move the ORDER BY clause from
111168 ** the sub-query back to the parent query. At this point each term
111169 ** within the ORDER BY clause has been transformed to an integer value.
@@ -112575,11 +112743,13 @@
112743 const Expr *pExpr, /* The function invocation */
112744 const FuncDef *pDef /* The function being invoked */
112745 ){
112746 assert( !IN_RENAME_OBJECT );
112747 assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
112748 if( ExprHasProperty(pExpr, EP_FromDDL)
112749 || pParse->prepFlags & SQLITE_PREPARE_FROM_DDL
112750 ){
112751 if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
112752 || (pParse->db->flags & SQLITE_TrustedSchema)==0
112753 ){
112754 /* Functions prohibited in triggers and views if:
112755 ** (1) tagged with SQLITE_DIRECTONLY
@@ -113271,13 +113441,11 @@
113441 pNew->pNext = pNext;
113442 pNew->pPrior = 0;
113443 pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
113444 pNew->iLimit = 0;
113445 pNew->iOffset = 0;
113446 pNew->selFlags = p->selFlags;
 
 
113447 pNew->nSelectRow = p->nSelectRow;
113448 pNew->pWith = sqlite3WithDup(db, p->pWith);
113449 #ifndef SQLITE_OMIT_WINDOWFUNC
113450 pNew->pWin = 0;
113451 pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
@@ -115495,12 +115663,13 @@
115663 if( destIfFalse==destIfNull ){
115664 /* Combine Step 3 and Step 5 into a single opcode */
115665 if( ExprHasProperty(pExpr, EP_Subrtn) ){
115666 const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
115667 assert( pOp->opcode==OP_Once || pParse->nErr );
115668 if( pOp->p3>0 ){ /* tag-202407032019 */
115669 assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter)
115670 || pParse->nErr );
115671 sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
115672 rLhs, nVector); VdbeCoverage(v);
115673 }
115674 }
115675 sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
@@ -118687,11 +118856,14 @@
118856 if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break;
118857 }
118858 if( pIEpr==0 ) break;
118859 if( NEVER(!ExprUseYTab(pExpr)) ) break;
118860 for(i=0; i<pSrcList->nSrc; i++){
118861 if( pSrcList->a[i].iCursor==pIEpr->iDataCur ){
118862 testcase( i>0 );
118863 break;
118864 }
118865 }
118866 if( i>=pSrcList->nSrc ) break;
118867 if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */
118868 if( pParse->nErr ){ return WRC_Abort; }
118869
@@ -131401,11 +131573,11 @@
131573 ** * Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
131574 ** virtual tables
131575 ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
131576 ** virtual tables if PRAGMA trusted_schema=ON.
131577 */
131578 if( (pParse->pToplevel!=0 || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL))
131579 && pTab->u.vtab.p->eVtabRisk >
131580 ((pParse->db->flags & SQLITE_TrustedSchema)!=0)
131581 ){
131582 sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
131583 pTab->zName);
@@ -132239,11 +132411,10 @@
132411 VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
132412 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
132413 &iPartIdxLabel, pPrior, r1);
132414 sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
132415 pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
 
132416 sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
132417 pPrior = pIdx;
132418 }
132419 }
132420
@@ -133586,11 +133757,11 @@
133757 }else{
133758 goto unistr_error;
133759 }
133760 }
133761 zOut[j] = 0;
133762 sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8_ZT);
133763 return;
133764
133765 unistr_error:
133766 sqlite3_free(zOut);
133767 sqlite3_result_error(context, "invalid Unicode escape", -1);
@@ -133679,11 +133850,11 @@
133850 *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
133851 *zOut++ = 0x80 + (u8)(c & 0x3F);
133852 } \
133853 }
133854 *zOut = 0;
133855 sqlite3_result_text64(context, (char*)z, zOut-z,sqlite3_free,SQLITE_UTF8_ZT);
133856 }
133857
133858 /*
133859 ** The hex() function. Interpret the argument as a blob. Return
133860 ** a hexadecimal rendering as text.
@@ -133708,11 +133879,11 @@
133879 *(z++) = hexdigits[(c>>4)&0xf];
133880 *(z++) = hexdigits[c&0xf];
133881 }
133882 *z = 0;
133883 sqlite3_result_text64(context, zHex, (u64)(z-zHex),
133884 sqlite3_free, SQLITE_UTF8_ZT);
133885 }
133886 }
133887
133888 /*
133889 ** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr
@@ -134046,11 +134217,11 @@
134217 }
134218 }
134219 }
134220 z[j] = 0;
134221 assert( j<=n );
134222 sqlite3_result_text64(context, z, j, sqlite3_free, SQLITE_UTF8_ZT);
134223 }
134224
134225 /*
134226 ** The CONCAT(...) function. Generate a string result that is the
134227 ** concatentation of all non-null arguments.
@@ -141234,10 +141405,12 @@
141405 int (*set_errmsg)(sqlite3*,int,const char*);
141406 int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
141407 /* Version 3.52.0 and later */
141408 void (*str_truncate)(sqlite3_str*,int);
141409 void (*str_free)(sqlite3_str*);
141410 int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
141411 int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
141412 };
141413
141414 /*
141415 ** This is the function signature used for all extension entry points. It
141416 ** is also defined in the file "loadext.c".
@@ -141575,10 +141748,12 @@
141748 #define sqlite3_set_errmsg sqlite3_api->set_errmsg
141749 #define sqlite3_db_status64 sqlite3_api->db_status64
141750 /* Version 3.52.0 and later */
141751 #define sqlite3_str_truncate sqlite3_api->str_truncate
141752 #define sqlite3_str_free sqlite3_api->str_free
141753 #define sqlite3_carray_bind sqlite3_api->carray_bind
141754 #define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
141755 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
141756
141757 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
141758 /* This case when the file really is being compiled as a loadable
141759 ** extension */
@@ -142104,11 +142279,18 @@
142279 /* Version 3.51.0 and later */
142280 sqlite3_set_errmsg,
142281 sqlite3_db_status64,
142282 /* Version 3.52.0 and later */
142283 sqlite3_str_truncate,
142284 sqlite3_str_free,
142285 #ifdef SQLITE_ENABLE_CARRAY
142286 sqlite3_carray_bind,
142287 sqlite3_carray_bind_v2
142288 #else
142289 0,
142290 0
142291 #endif
142292 };
142293
142294 /* True if x is the directory separator character
142295 */
142296 #if SQLITE_OS_WIN
@@ -142206,37 +142388,46 @@
142388
142389 /* If no entry point was specified and the default legacy
142390 ** entry point name "sqlite3_extension_init" was not found, then
142391 ** construct an entry point name "sqlite3_X_init" where the X is
142392 ** replaced by the lowercase value of every ASCII alphabetic
142393 ** character in the filename after the last "/" up to the first ".",
142394 ** and skipping the first three characters if they are "lib".
142395 ** Examples:
142396 **
142397 ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
142398 ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init
142399 **
142400 ** If that still finds no entry point, repeat a second time but this
142401 ** time include both alphabetic and numeric characters up to the first
142402 ** ".". Example:
142403 **
142404 ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init
142405 */
142406 if( xInit==0 && zProc==0 ){
142407 int iFile, iEntry, c;
142408 int ncFile = sqlite3Strlen30(zFile);
142409 int cnt = 0;
142410 zAltEntry = sqlite3_malloc64(ncFile+30);
142411 if( zAltEntry==0 ){
142412 sqlite3OsDlClose(pVfs, handle);
142413 return SQLITE_NOMEM_BKPT;
142414 }
142415 do{
142416 memcpy(zAltEntry, "sqlite3_", 8);
142417 for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
142418 iFile++;
142419 if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
142420 for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
142421 if( sqlite3Isalpha(c) || (cnt && sqlite3Isdigit(c)) ){
142422 zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
142423 }
142424 }
142425 memcpy(zAltEntry+iEntry, "_init", 6);
142426 zEntry = zAltEntry;
142427 xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
142428 }while( xInit==0 && (++cnt)<2 );
142429 }
142430 if( xInit==0 ){
142431 if( pzErrMsg ){
142432 nMsg += strlen(zEntry) + 300;
142433 *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
@@ -147518,12 +147709,10 @@
147709 pNew->op = TK_SELECT;
147710 pNew->selFlags = selFlags;
147711 pNew->iLimit = 0;
147712 pNew->iOffset = 0;
147713 pNew->selId = ++pParse->nSelect;
 
 
147714 pNew->nSelectRow = 0;
147715 if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
147716 pNew->pSrc = pSrc;
147717 pNew->pWhere = pWhere;
147718 pNew->pGroupBy = pGroupBy;
@@ -148667,33 +148856,10 @@
148856 codeOffset(v, p->iOffset, iContinue);
148857 }
148858 }
148859
148860 switch( eDest ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148861 /* Store the result as data using a unique key.
148862 */
148863 case SRT_Fifo:
148864 case SRT_DistFifo:
148865 case SRT_Table:
@@ -149976,13 +150142,13 @@
150142 **
150143 ** Space to hold the KeyInfo structure is obtained from malloc. The calling
150144 ** function is responsible for ensuring that this structure is eventually
150145 ** freed.
150146 */
150147 static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){
150148 ExprList *pOrderBy = p->pOrderBy;
150149 int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0;
150150 sqlite3 *db = pParse->db;
150151 KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
150152 if( pRet ){
150153 int i;
150154 for(i=0; i<nOrderBy; i++){
@@ -150111,21 +150277,41 @@
150277
150278 /* Allocate cursors for Current, Queue, and Distinct. */
150279 regCurrent = ++pParse->nMem;
150280 sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
150281 if( pOrderBy ){
150282 KeyInfo *pKeyInfo = multiSelectByMergeKeyInfo(pParse, p, 1);
150283 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
150284 (char*)pKeyInfo, P4_KEYINFO);
150285 destQueue.pOrderBy = pOrderBy;
150286 }else{
150287 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
150288 }
150289 VdbeComment((v, "Queue table"));
150290 if( iDistinct ){
150291 /* Generate an ephemeral table used to enforce distinctness on the
150292 ** output of the recursive part of the CTE.
150293 */
150294 KeyInfo *pKeyInfo; /* Collating sequence for the result set */
150295 CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
150296
150297 assert( p->pNext==0 );
150298 assert( p->pEList!=0 );
150299 nCol = p->pEList->nExpr;
150300 pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nCol, 1);
150301 if( pKeyInfo ){
150302 for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
150303 *apColl = multiSelectCollSeq(pParse, p, i);
150304 if( 0==*apColl ){
150305 *apColl = pParse->db->pDfltColl;
150306 }
150307 }
150308 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iDistinct, nCol, 0,
150309 (void*)pKeyInfo, P4_KEYINFO);
150310 }else{
150311 assert( pParse->nErr>0 );
150312 }
150313 }
150314
150315 /* Detach the ORDER BY clause from the compound SELECT */
150316 p->pOrderBy = 0;
150317
@@ -150196,11 +150382,11 @@
150382 return;
150383 }
150384 #endif /* SQLITE_OMIT_CTE */
150385
150386 /* Forward references */
150387 static int multiSelectByMerge(
150388 Parse *pParse, /* Parsing context */
150389 Select *p, /* The right-most of SELECTs to be coded */
150390 SelectDest *pDest /* What to do with query results */
150391 );
150392
@@ -150345,317 +150531,80 @@
150531 #ifndef SQLITE_OMIT_CTE
150532 if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
150533 generateWithRecursiveQuery(pParse, p, &dest);
150534 }else
150535 #endif
 
 
 
150536 if( p->pOrderBy ){
150537 /* If the compound has an ORDER BY clause, then always use the merge
150538 ** algorithm. */
150539 return multiSelectByMerge(pParse, p, pDest);
150540 }else if( p->op!=TK_ALL ){
150541 /* If the compound is EXCEPT, INTERSECT, or UNION (anything other than
150542 ** UNION ALL) then also always use the merge algorithm. However, the
150543 ** multiSelectByMerge() routine requires that the compound have an
150544 ** ORDER BY clause, and it doesn't right now. So invent one first. */
150545 Expr *pOne = sqlite3ExprInt32(db, 1);
150546 p->pOrderBy = sqlite3ExprListAppend(pParse, 0, pOne);
150547 if( pParse->nErr ) goto multi_select_end;
150548 assert( p->pOrderBy!=0 );
150549 p->pOrderBy->a[0].u.x.iOrderByCol = 1;
150550 return multiSelectByMerge(pParse, p, pDest);
150551 }else{
150552 /* For a UNION ALL compound without ORDER BY, simply run the left
150553 ** query, then run the right query */
150554 int addr = 0;
150555 int nLimit = 0; /* Initialize to suppress harmless compiler warning */
150556
150557 #ifndef SQLITE_OMIT_EXPLAIN
150558 if( pPrior->pPrior==0 ){
150559 ExplainQueryPlan((pParse, 1, "COMPOUND QUERY"));
150560 ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
150561 }
150562 #endif
150563 assert( !pPrior->pLimit );
150564 pPrior->iLimit = p->iLimit;
150565 pPrior->iOffset = p->iOffset;
150566 pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0);
150567 TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
150568 rc = sqlite3Select(pParse, pPrior, &dest);
150569 sqlite3ExprDelete(db, pPrior->pLimit);
150570 pPrior->pLimit = 0;
150571 if( rc ){
150572 goto multi_select_end;
150573 }
150574 p->pPrior = 0;
150575 p->iLimit = pPrior->iLimit;
150576 p->iOffset = pPrior->iOffset;
150577 if( p->iLimit ){
150578 addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
150579 VdbeComment((v, "Jump ahead if LIMIT reached"));
150580 if( p->iOffset ){
150581 sqlite3VdbeAddOp3(v, OP_OffsetLimit,
150582 p->iLimit, p->iOffset+1, p->iOffset);
150583 }
150584 }
150585 ExplainQueryPlan((pParse, 1, "UNION ALL"));
150586 TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n"));
150587 rc = sqlite3Select(pParse, p, &dest);
150588 testcase( rc!=SQLITE_OK );
150589 pDelete = p->pPrior;
150590 p->pPrior = pPrior;
150591 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
150592 if( p->pLimit
150593 && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
150594 && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
150595 ){
150596 p->nSelectRow = sqlite3LogEst((u64)nLimit);
150597 }
150598 if( addr ){
150599 sqlite3VdbeJumpHere(v, addr);
150600 }
150601 #ifndef SQLITE_OMIT_EXPLAIN
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150602 if( p->pNext==0 ){
150603 ExplainQueryPlanPop(pParse);
150604 }
150605 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150606 }
150607
150608 multi_select_end:
150609 pDest->iSdst = dest.iSdst;
150610 pDest->nSdst = dest.nSdst;
@@ -150683,12 +150632,12 @@
150632
150633 /*
150634 ** Code an output subroutine for a coroutine implementation of a
150635 ** SELECT statement.
150636 **
150637 ** The data to be output is contained in an array of pIn->nSdst registers
150638 ** starting at register pIn->iSdst. pDest is where the output should
150639 ** be sent.
150640 **
150641 ** regReturn is the number of the register holding the subroutine
150642 ** return address.
150643 **
@@ -150713,10 +150662,12 @@
150662 ){
150663 Vdbe *v = pParse->pVdbe;
150664 int iContinue;
150665 int addr;
150666
150667 assert( pIn->eDest==SRT_Coroutine );
150668
150669 addr = sqlite3VdbeCurrentAddr(v);
150670 iContinue = sqlite3VdbeMakeLabel(pParse);
150671
150672 /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
150673 */
@@ -150734,26 +150685,63 @@
150685
150686 /* Suppress the first OFFSET entries if there is an OFFSET clause
150687 */
150688 codeOffset(v, p->iOffset, iContinue);
150689
 
 
150690 switch( pDest->eDest ){
150691 /* Store the result as data using a unique key.
150692 */
150693 case SRT_Fifo:
150694 case SRT_DistFifo:
150695 case SRT_Table:
150696 case SRT_EphemTab: {
150697 int r1 = sqlite3GetTempReg(pParse);
150698 int r2 = sqlite3GetTempReg(pParse);
150699 int iParm = pDest->iSDParm;
150700 testcase( pDest->eDest==SRT_Table );
150701 testcase( pDest->eDest==SRT_EphemTab );
150702 testcase( pDest->eDest==SRT_Fifo );
150703 testcase( pDest->eDest==SRT_DistFifo );
150704 sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
150705 #if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG)
150706 /* A destination of SRT_Table and a non-zero iSDParm2 parameter means
150707 ** that this is an "UPDATE ... FROM" on a virtual table or view. In this
150708 ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC.
150709 ** This does not affect operation in any way - it just allows MakeRecord
150710 ** to process OPFLAG_NOCHANGE values without an assert() failing. */
150711 if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){
150712 sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
150713 }
150714 #endif
150715 #ifndef SQLITE_OMIT_CTE
150716 if( pDest->eDest==SRT_DistFifo ){
150717 /* If the destination is DistFifo, then cursor (iParm+1) is open
150718 ** on an ephemeral index that is used to enforce uniqueness on the
150719 ** total result. At this point, we are processing the setup portion
150720 ** of the recursive CTE using the merge algorithm, so the results are
150721 ** guaranteed to be unique anyhow. But we still need to populate the
150722 ** (iParm+1) cursor for use by the subsequent recursive phase.
150723 */
150724 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,
150725 pIn->iSdst, pIn->nSdst);
150726 }
150727 #endif
150728 sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
150729 sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
150730 sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
150731 sqlite3ReleaseTempReg(pParse, r2);
150732 sqlite3ReleaseTempReg(pParse, r1);
150733 break;
150734 }
150735
150736 /* If any row exist in the result set, record that fact and abort.
150737 */
150738 case SRT_Exists: {
150739 sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
150740 /* The LIMIT clause will terminate the loop for us */
150741 break;
150742 }
150743
150744 #ifndef SQLITE_OMIT_SUBQUERY
150745 /* If we are creating a set for an "expr IN (SELECT ...)".
150746 */
150747 case SRT_Set: {
@@ -150796,14 +150784,74 @@
150784 }
150785 sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
150786 sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
150787 break;
150788 }
150789
150790 #ifndef SQLITE_OMIT_CTE
150791 /* Write the results into a priority queue that is order according to
150792 ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an
150793 ** index with pSO->nExpr+2 columns. Build a key using pSO for the first
150794 ** pSO->nExpr columns, then make sure all keys are unique by adding a
150795 ** final OP_Sequence column. The last column is the record as a blob.
150796 */
150797 case SRT_DistQueue:
150798 case SRT_Queue: {
150799 int nKey;
150800 int r1, r2, r3, ii;
150801 ExprList *pSO;
150802 int iParm = pDest->iSDParm;
150803 pSO = pDest->pOrderBy;
150804 assert( pSO );
150805 nKey = pSO->nExpr;
150806 r1 = sqlite3GetTempReg(pParse);
150807 r2 = sqlite3GetTempRange(pParse, nKey+2);
150808 r3 = r2+nKey+1;
150809
150810 #if 0 /* <-- Why the next block of code is commented out: (tag-20260125-a)
150811 **
150812 ** If the destination is DistQueue, then cursor (iParm+1) is open
150813 ** on a second ephemeral index that holds all values previously
150814 ** added to the queue. This code only runs during the setup phase
150815 ** using the merge algorithm, and so the values here are already
150816 ** guaranteed to be unique.
150817 */
150818 if( pDest->eDest==SRT_DistQueue ){
150819 addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
150820 pIn->iSdst, pIn->nSdst);
150821 VdbeCoverage(v);
150822 }
150823 #endif
150824 sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r3);
150825 if( pDest->eDest==SRT_DistQueue ){
150826 sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
150827 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
150828 }
150829 for(ii=0; ii<nKey; ii++){
150830 sqlite3VdbeAddOp2(v, OP_SCopy,
150831 pIn->iSdst + pSO->a[ii].u.x.iOrderByCol - 1,
150832 r2+ii);
150833 }
150834 sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
150835 sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
150836 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
150837 #if 0 /* tag-20260125-a */
150838 if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
150839 #endif
150840 sqlite3ReleaseTempReg(pParse, r1);
150841 sqlite3ReleaseTempRange(pParse, r2, nKey+2);
150842 break;
150843 }
150844 #endif /* SQLITE_OMIT_CTE */
150845
150846 /* Ignore the output */
150847 case SRT_Discard: {
150848 break;
150849 }
150850
150851 /* If none of the above, then the result destination must be
150852 ** SRT_Output.
 
150853 **
150854 ** For SRT_Output, results are stored in a sequence of registers.
150855 ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
150856 ** return the next row of result.
150857 */
@@ -150827,12 +150875,13 @@
150875
150876 return addr;
150877 }
150878
150879 /*
150880 ** Generate code for a compound SELECT statement using a merge
150881 ** algorithm. The compound must have an ORDER BY clause for this
150882 ** to work.
150883 **
150884 ** We assume a query of the following form:
150885 **
150886 ** <selectA> <operator> <selectB> ORDER BY <orderbylist>
150887 **
@@ -150845,11 +150894,11 @@
150894 ** outA: Move the output of the selectA coroutine into the output
150895 ** of the compound query.
150896 **
150897 ** outB: Move the output of the selectB coroutine into the output
150898 ** of the compound query. (Only generated for UNION and
150899 ** UNION ALL. EXCEPT and INTERSECT never output a row that
150900 ** appears only in B.)
150901 **
150902 ** AltB: Called when there is data from both coroutines and A<B.
150903 **
150904 ** AeqB: Called when there is data from both coroutines and A==B.
@@ -150898,25 +150947,23 @@
150947 ** EofB: ...
150948 ** AltB: ...
150949 ** AeqB: ...
150950 ** AgtB: ...
150951 ** Init: initialize coroutine registers
150952 ** yield coA, on eof goto EofA
150953 ** yield coB, on eof goto EofB
 
 
150954 ** Cmpr: Compare A, B
150955 ** Jump AltB, AeqB, AgtB
150956 ** End: ...
150957 **
150958 ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
150959 ** actually called using Gosub and they do not Return. EofA and EofB loop
150960 ** until all data is exhausted then jump to the "end" label. AltB, AeqB,
150961 ** and AgtB jump to either Cmpr or to one of EofA or EofB.
150962 */
150963 #ifndef SQLITE_OMIT_COMPOUND_SELECT
150964 static int multiSelectByMerge(
150965 Parse *pParse, /* Parsing context */
150966 Select *p, /* The right-most of SELECTs to be coded */
150967 SelectDest *pDest /* What to do with query results */
150968 ){
150969 int i, j; /* Loop counters */
@@ -150993,30 +151040,33 @@
151040 }
151041 }
151042 }
151043
151044 /* Compute the comparison permutation and keyinfo that is used with
151045 ** the permutation to determine if the next row of results comes
151046 ** from selectA or selectB. Also add literal collations to the
151047 ** ORDER BY clause terms so that when selectA and selectB are
151048 ** evaluated, they use the correct collation.
 
151049 */
151050 aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
151051 if( aPermute ){
151052 struct ExprList_item *pItem;
151053 int bKeep = 0;
151054 aPermute[0] = nOrderBy;
151055 for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
151056 assert( pItem!=0 );
151057 assert( pItem->u.x.iOrderByCol>0 );
151058 assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
151059 aPermute[i] = pItem->u.x.iOrderByCol - 1;
151060 if( aPermute[i]!=(u32)i-1 ) bKeep = 1;
151061 }
151062 if( bKeep==0 ){
151063 sqlite3DbFreeNN(db, aPermute);
151064 aPermute = 0;
151065 }
151066 }
151067 pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1);
151068
151069 /* Allocate a range of temporary registers and the KeyInfo needed
151070 ** for the logic that removes duplicate result rows when the
151071 ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
151072 */
@@ -151091,11 +151141,11 @@
151141 /* Generate a coroutine to evaluate the SELECT statement to the
151142 ** left of the compound operator - the "A" select.
151143 */
151144 addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
151145 addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
151146 VdbeComment((v, "SUBR: next-A"));
151147 pPrior->iLimit = regLimitA;
151148 ExplainQueryPlan((pParse, 1, "LEFT"));
151149 sqlite3Select(pParse, pPrior, &destA);
151150 sqlite3VdbeEndCoroutine(v, regAddrA);
151151 sqlite3VdbeJumpHere(v, addr1);
@@ -151103,11 +151153,11 @@
151153 /* Generate a coroutine to evaluate the SELECT statement on
151154 ** the right - the "B" select
151155 */
151156 addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
151157 addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
151158 VdbeComment((v, "SUBR: next-B"));
151159 savedLimit = p->iLimit;
151160 savedOffset = p->iOffset;
151161 p->iLimit = regLimitB;
151162 p->iOffset = 0;
151163 ExplainQueryPlan((pParse, 1, "RIGHT"));
@@ -151117,20 +151167,20 @@
151167 sqlite3VdbeEndCoroutine(v, regAddrB);
151168
151169 /* Generate a subroutine that outputs the current row of the A
151170 ** select as the next output row of the compound select.
151171 */
151172 VdbeNoopComment((v, "SUBR: out-A"));
151173 addrOutA = generateOutputSubroutine(pParse,
151174 p, &destA, pDest, regOutA,
151175 regPrev, pKeyDup, labelEnd);
151176
151177 /* Generate a subroutine that outputs the current row of the B
151178 ** select as the next output row of the compound select.
151179 */
151180 if( op==TK_ALL || op==TK_UNION ){
151181 VdbeNoopComment((v, "SUBR: out-B"));
151182 addrOutB = generateOutputSubroutine(pParse,
151183 p, &destB, pDest, regOutB,
151184 regPrev, pKeyDup, labelEnd);
151185 }
151186 sqlite3KeyInfoUnref(pKeyDup);
@@ -151139,14 +151189,16 @@
151189 ** are exhausted and only data in select B remains.
151190 */
151191 if( op==TK_EXCEPT || op==TK_INTERSECT ){
151192 addrEofA_noB = addrEofA = labelEnd;
151193 }else{
151194 VdbeNoopComment((v, "SUBR: eof-A"));
151195 addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
151196 VdbeComment((v, "out-B"));
151197 addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
151198 VdbeCoverage(v);
151199 VdbeComment((v, "next-B"));
151200 sqlite3VdbeGoto(v, addrEofA);
151201 p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
151202 }
151203
151204 /* Generate a subroutine to run when the results from select B
@@ -151154,21 +151206,24 @@
151206 */
151207 if( op==TK_INTERSECT ){
151208 addrEofB = addrEofA;
151209 if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
151210 }else{
151211 VdbeNoopComment((v, "SUBR: eof-B"));
151212 addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
151213 VdbeComment((v, "out-A"));
151214 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
151215 VdbeComment((v, "next-A"));
151216 sqlite3VdbeGoto(v, addrEofB);
151217 }
151218
151219 /* Generate code to handle the case of A<B
151220 */
 
151221 addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
151222 VdbeComment((v, "out-A"));
151223 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
151224 VdbeComment((v, "next-A"));
151225 sqlite3VdbeGoto(v, labelCmpr);
151226
151227 /* Generate code to handle the case of A==B
151228 */
151229 if( op==TK_ALL ){
@@ -151175,40 +151230,52 @@
151230 addrAeqB = addrAltB;
151231 }else if( op==TK_INTERSECT ){
151232 addrAeqB = addrAltB;
151233 addrAltB++;
151234 }else{
151235 addrAeqB = addrAltB + 1;
 
 
 
151236 }
151237
151238 /* Generate code to handle the case of A>B
151239 */
 
151240 addrAgtB = sqlite3VdbeCurrentAddr(v);
151241 if( op==TK_ALL || op==TK_UNION ){
151242 sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
151243 VdbeComment((v, "out-B"));
151244 sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
151245 VdbeComment((v, "next-B"));
151246 sqlite3VdbeGoto(v, labelCmpr);
151247 }else{
151248 addrAgtB++; /* Just do next-B. Might as well use the next-B call
151249 ** in the next code block */
151250 }
 
 
151251
151252 /* This code runs once to initialize everything.
151253 */
151254 sqlite3VdbeJumpHere(v, addr1);
151255 sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
151256 VdbeComment((v, "next-A"));
151257 /* v--- Also the A>B case for EXCEPT and INTERSECT */
151258 sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
151259 VdbeComment((v, "next-B"));
151260
151261 /* Implement the main merge loop
151262 */
151263 if( aPermute!=0 ){
151264 sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
151265 }
151266 sqlite3VdbeResolveLabel(v, labelCmpr);
 
151267 sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
151268 (char*)pKeyMerge, P4_KEYINFO);
151269 if( aPermute!=0 ){
151270 sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
151271 }
151272 sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
151273 VdbeCoverageIf(v, op==TK_ALL);
151274 VdbeCoverageIf(v, op==TK_UNION);
151275 VdbeCoverageIf(v, op==TK_EXCEPT);
151276 VdbeCoverageIf(v, op==TK_INTERSECT);
151277
151278 /* Jump to the this point in order to terminate the query.
151279 */
151280 sqlite3VdbeResolveLabel(v, labelEnd);
151281
@@ -152121,11 +152188,11 @@
152188 pItem->fg.jointype |= (jointype & JT_LTORJ);
152189 memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
152190 }
152191 pSubitem->fg.jointype |= jointype;
152192
152193 /* Begin substituting subquery result set expressions for
152194 ** references to the iParent in the outer query.
152195 **
152196 ** Example:
152197 **
152198 ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
@@ -152133,21 +152200,21 @@
152200 ** \_____________________ outer query ______________________________/
152201 **
152202 ** We look at every expression in the outer query and every place we see
152203 ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
152204 */
152205 if( pSub->pOrderBy ){
152206 /* At this point, any non-zero iOrderByCol values indicate that the
152207 ** ORDER BY column expression is identical to the iOrderByCol'th
152208 ** expression returned by SELECT statement pSub. Since these values
152209 ** do not necessarily correspond to columns in SELECT statement pParent,
152210 ** zero them before transferring the ORDER BY clause.
152211 **
152212 ** Not doing this may cause an error if a subsequent call to this
152213 ** function attempts to flatten a compound sub-query into pParent.
152214 ** See ticket [d11a6e908f].
152215 */
152216 ExprList *pOrderBy = pSub->pOrderBy;
152217 for(i=0; i<pOrderBy->nExpr; i++){
152218 pOrderBy->a[i].u.x.iOrderByCol = 0;
152219 }
152220 assert( pParent->pOrderBy==0 );
@@ -152995,18 +153062,18 @@
153062 ** These are rewritten as a subquery:
153063 **
153064 ** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2)
153065 ** ORDER BY ... COLLATE ...
153066 **
153067 ** This transformation is necessary because the multiSelectByMerge() routine
153068 ** above that generates the code for a compound SELECT with an ORDER BY clause
153069 ** uses a merge algorithm that requires the same collating sequence on the
153070 ** result columns as on the ORDER BY clause. See ticket
153071 ** http://sqlite.org/src/info/6709574d2a
153072 **
153073 ** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
153074 ** The UNION ALL operator works fine with multiSelectByMerge() even when
153075 ** there are COLLATE terms in the ORDER BY.
153076 */
153077 static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
153078 int i;
153079 Select *pNew;
@@ -153548,11 +153615,11 @@
153615 }
153616 sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
153617 }
153618 #ifndef SQLITE_OMIT_VIRTUALTABLE
153619 else if( ALWAYS(IsVirtual(pTab))
153620 && (pFrom->fg.fromDDL || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL))
153621 && ALWAYS(pTab->u.vtab.p!=0)
153622 && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
153623 ){
153624 sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
153625 pTab->zName);
@@ -154832,19 +154899,30 @@
154899 Expr *pSubWhere = pSub->pWhere;
154900 if( pSub->pSrc->nSrc==1
154901 && (pSub->selFlags & SF_Aggregate)==0
154902 && !pSub->pSrc->a[0].fg.isSubquery
154903 && pSub->pLimit==0
154904 && pSub->pPrior==0
154905 ){
154906 /* Before combining the sub-select with the parent, renumber the
154907 ** cursor used by the subselect. This is because the EXISTS expression
154908 ** might be a copy of another EXISTS expression from somewhere
154909 ** else in the tree, and in this case it is important that it use
154910 ** a unique cursor number. */
154911 sqlite3 *db = pParse->db;
154912 int *aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+2)*sizeof(int));
154913 if( aCsrMap==0 ) return;
154914 aCsrMap[0] = (pParse->nTab+1);
154915 renumberCursors(pParse, pSub, -1, aCsrMap);
154916 sqlite3DbFree(db, aCsrMap);
154917
154918 memset(pWhere, 0, sizeof(*pWhere));
154919 pWhere->op = TK_INTEGER;
154920 pWhere->u.iValue = 1;
154921 ExprSetProperty(pWhere, EP_IntValue);
 
154922 assert( p->pWhere!=0 );
154923 pSub->pSrc->a[0].fg.fromExists = 1;
 
154924 p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc);
154925 if( pSubWhere ){
154926 p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere);
154927 pSub->pWhere = 0;
154928 }
@@ -154969,10 +155047,34 @@
155047 memset(&sCtx, 0, sizeof(sCtx));
155048 sCtx.pSrc = pSelect->pSrc;
155049 sqlite3WalkExprNN(&w, pSelect->pWhere);
155050 pSelect->selFlags &= ~SF_OnToWhere;
155051 }
155052
155053 /*
155054 ** If p2 exists and p1 and p2 have the same number of terms, then change
155055 ** every term of p1 to have the same sort order as p2 and return true.
155056 **
155057 ** If p2 is NULL or p1 and p2 are different lengths, then make no changes
155058 ** and return false.
155059 **
155060 ** p1 must be non-NULL.
155061 */
155062 static int sqlite3CopySortOrder(ExprList *p1, ExprList *p2){
155063 assert( p1 );
155064 if( p2 && p1->nExpr==p2->nExpr ){
155065 int ii;
155066 for(ii=0; ii<p1->nExpr; ii++){
155067 u8 sortFlags;
155068 sortFlags = p2->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
155069 p1->a[ii].fg.sortFlags = sortFlags;
155070 }
155071 return 1;
155072 }else{
155073 return 0;
155074 }
155075 }
155076
155077 /*
155078 ** Generate byte-code for the SELECT statement given in the p argument.
155079 **
155080 ** The results are returned according to the SelectDest structure.
@@ -155065,12 +155167,11 @@
155167 assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
155168 assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
155169 assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
155170 assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
155171 if( IgnorableDistinct(pDest) ){
155172 assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Discard ||
 
155173 pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
155174 /* All of these destinations are also able to ignore the ORDER BY clause */
155175 if( p->pOrderBy ){
155176 #if TREETRACE_ENABLED
155177 TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n"));
@@ -155082,11 +155183,10 @@
155183 p->pOrderBy);
155184 testcase( pParse->earlyCleanup );
155185 p->pOrderBy = 0;
155186 }
155187 p->selFlags &= ~(u32)SF_Distinct;
 
155188 }
155189 sqlite3SelectPrep(pParse, p, 0);
155190 if( pParse->nErr ){
155191 goto select_end;
155192 }
@@ -155622,11 +155722,12 @@
155722 ** used for both the ORDER BY and DISTINCT processing. As originally
155723 ** written the query must use a temp-table for at least one of the ORDER
155724 ** BY and DISTINCT, and an index or separate temp-table for the other.
155725 */
155726 if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
155727 && sqlite3CopySortOrder(pEList, sSort.pOrderBy)
155728 && sqlite3ExprListCompare(pEList, sSort.pOrderBy, -1)==0
155729 && OptimizationEnabled(db, SQLITE_GroupByOrder)
155730 #ifndef SQLITE_OMIT_WINDOWFUNC
155731 && p->pWin==0
155732 #endif
155733 ){
@@ -155836,25 +155937,14 @@
155937 ** in the correct order. It also may not - the GROUP BY might use a
155938 ** database index that causes rows to be grouped together as required
155939 ** but not actually sorted. Either way, record the fact that the
155940 ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
155941 ** variable. */
155942 if( sqlite3CopySortOrder(pGroupBy, sSort.pOrderBy)
155943 && sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0
155944 ){
155945 orderByGrp = 1;
 
 
 
 
 
 
 
 
 
 
 
155946 }
155947 }else{
155948 assert( 0==sqlite3LogEst(1) );
155949 p->nSelectRow = 0;
155950 }
@@ -156849,15 +156939,20 @@
156939 }
156940 goto trigger_cleanup;
156941 }
156942 }
156943
156944 /* NB: The SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES compile-time option is
156945 ** experimental and unsupported. Do not use it unless understand the
156946 ** implications and you cannot get by without this capability. */
156947 #if !defined(SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES) /* Experimental */
156948 /* Do not create a trigger on a system table */
156949 if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
156950 sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
156951 goto trigger_cleanup;
156952 }
156953 #endif
156954
156955 /* INSTEAD of triggers are only for views and views only support INSTEAD
156956 ** of triggers.
156957 */
156958 if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
@@ -160118,13 +160213,15 @@
160213 if( rc!=SQLITE_OK ) goto end_of_vacuum;
160214 assert( (db->nDb-1)==nDb );
160215 pDb = &db->aDb[nDb];
160216 assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
160217 pTemp = pDb->pBt;
160218 nRes = sqlite3BtreeGetRequestedReserve(pMain);
160219 if( pOut ){
160220 sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
160221 i64 sz = 0;
160222 const char *zFilename;
160223 if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
160224 rc = SQLITE_ERROR;
160225 sqlite3SetString(pzErrMsg, db, "output file already exists");
160226 goto end_of_vacuum;
160227 }
@@ -160132,12 +160229,20 @@
160229
160230 /* For a VACUUM INTO, the pager-flags are set to the same values as
160231 ** they are for the database being vacuumed, except that PAGER_CACHESPILL
160232 ** is always set. */
160233 pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK);
160234
160235 /* If the VACUUM INTO target file is a URI filename and if the
160236 ** "reserve=N" query parameter is present, reset the reserve to the
160237 ** amount specified, if the amount is within range */
160238 zFilename = sqlite3BtreeGetFilename(pTemp);
160239 if( ALWAYS(zFilename) ){
160240 int nNew = (int)sqlite3_uri_int64(zFilename, "reserve", nRes);
160241 if( nNew>=0 && nNew<=255 ) nRes = nNew;
160242 }
160243 }
 
160244
160245 sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
160246 sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
160247 sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL);
160248
@@ -165646,10 +165751,38 @@
165751 sqlite3ValueFree(pVal);
165752 return rc;
165753 }
165754 #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
165755
165756 /*
165757 ** If pExpr is one of "like", "glob", "match", or "regexp", then
165758 ** return the corresponding SQLITE_INDEX_CONSTRAINT_xxxx value.
165759 ** If not, return 0.
165760 **
165761 ** pExpr is guaranteed to be a TK_FUNCTION.
165762 */
165763 SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr *pExpr){
165764 static const struct {
165765 const char *zOp;
165766 unsigned char eOp;
165767 } aOp[] = {
165768 { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
165769 { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
165770 { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
165771 { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
165772 };
165773 int i;
165774 assert( pExpr->op==TK_FUNCTION );
165775 assert( !ExprHasProperty(pExpr, EP_IntValue) );
165776 for(i=0; i<ArraySize(aOp); i++){
165777 if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
165778 return aOp[i].eOp;
165779 }
165780 }
165781 return 0;
165782 }
165783
165784
165785 #ifndef SQLITE_OMIT_VIRTUALTABLE
165786 /*
165787 ** Check to see if the pExpr expression is a form that needs to be passed
165788 ** to the xBestIndex method of virtual tables. Forms of interest include:
@@ -165682,19 +165815,10 @@
165815 unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
165816 Expr **ppLeft, /* Column expression to left of MATCH/op2 */
165817 Expr **ppRight /* Expression to left of MATCH/op2 */
165818 ){
165819 if( pExpr->op==TK_FUNCTION ){
 
 
 
 
 
 
 
 
 
165820 ExprList *pList;
165821 Expr *pCol; /* Column reference */
165822 int i;
165823
165824 assert( ExprUseXList(pExpr) );
@@ -165710,20 +165834,15 @@
165834 ** vtab_column MATCH expression
165835 ** MATCH(expression,vtab_column)
165836 */
165837 pCol = pList->a[1].pExpr;
165838 assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
165839 if( ExprIsVtab(pCol) && (i = sqlite3ExprIsLikeOperator(pExpr))!=0 ){
165840 *peOp2 = i;
165841 *ppRight = pList->a[0].pExpr;
165842 *ppLeft = pCol;
165843 return 1;
 
 
 
 
 
165844 }
165845
165846 /* We can also match against the first column of overloaded
165847 ** functions where xFindFunction returns a value of at least
165848 ** SQLITE_INDEX_CONSTRAINT_FUNCTION.
@@ -165853,20 +165972,26 @@
165972 u16 eOp = pOne->eOperator | pTwo->eOperator;
165973 sqlite3 *db; /* Database connection (for malloc) */
165974 Expr *pNew; /* New virtual expression */
165975 int op; /* Operator for the combined expression */
165976 int idxNew; /* Index in pWC of the next virtual term */
165977 Expr *pA, *pB; /* Expressions associated with pOne and pTwo */
165978
165979 if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
165980 if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
165981 if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
165982 if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
165983 && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
165984 pA = pOne->pExpr;
165985 pB = pTwo->pExpr;
165986 assert( pA->pLeft!=0 && pA->pRight!=0 );
165987 assert( pB->pLeft!=0 && pB->pRight!=0 );
165988 if( sqlite3ExprCompare(0,pA->pLeft, pB->pLeft, -1) ) return;
165989 if( sqlite3ExprCompare(0,pA->pRight, pB->pRight,-1) ) return;
165990 if( ExprHasProperty(pA,EP_Commuted)!=ExprHasProperty(pB,EP_Commuted) ){
165991 return;
165992 }
165993 /* If we reach this point, it means the two subterms can be combined */
165994 if( (eOp & (eOp-1))!=0 ){
165995 if( eOp & (WO_LT|WO_LE) ){
165996 eOp = WO_LE;
165997 }else{
@@ -165873,11 +165998,11 @@
165998 assert( eOp & (WO_GT|WO_GE) );
165999 eOp = WO_GE;
166000 }
166001 }
166002 db = pWC->pWInfo->pParse->db;
166003 pNew = sqlite3ExprDup(db, pA, 0);
166004 if( pNew==0 ) return;
166005 for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
166006 pNew->op = op;
166007 idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
166008 exprAnalyze(pSrc, pWC, idxNew);
@@ -168744,15 +168869,18 @@
168869
168870 /* No matches cause a break out of the loop */
168871 break;
168872 }
168873 if( i==n ){
168874 int bSortByGroup = (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0;
168875 nOrderBy = n;
168876 if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){
168877 eDistinct = 2 + bSortByGroup;
168878 }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
168879 eDistinct = 1 - bSortByGroup;
168880 }else if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
168881 eDistinct = 3;
168882 }
168883 }
168884 }
168885
168886 /* Allocate the sqlite3_index_info structure
@@ -170158,10 +170286,71 @@
170286 p->u.btree.pIndex = 0;
170287 }
170288 }
170289 return rc;
170290 }
170291
170292 /*
170293 ** Callback for estLikePatternLength().
170294 **
170295 ** If this node is a string literal that is longer pWalker->sz, then set
170296 ** pWalker->sz to the byte length of that string literal.
170297 **
170298 ** pWalker->eCode indicates how to count characters:
170299 **
170300 ** eCode==0 Count as a GLOB pattern
170301 ** eCode==1 Count as a LIKE pattern
170302 */
170303 static int exprNodePatternLengthEst(Walker *pWalker, Expr *pExpr){
170304 if( pExpr->op==TK_STRING ){
170305 int sz = 0; /* Pattern size in bytes */
170306 u8 *z = (u8*)pExpr->u.zToken; /* The pattern */
170307 u8 c; /* Next character of the pattern */
170308 u8 c1, c2, c3; /* Wildcards */
170309 if( pWalker->eCode ){
170310 c1 = '%';
170311 c2 = '_';
170312 c3 = 0;
170313 }else{
170314 c1 = '*';
170315 c2 = '?';
170316 c3 = '[';
170317 }
170318 while( (c = *(z++))!=0 ){
170319 if( c==c3 ){
170320 if( *z ) z++;
170321 while( *z && *z!=']' ) z++;
170322 }else if( c!=c1 && c!=c2 ){
170323 sz++;
170324 }
170325 }
170326 if( sz>pWalker->u.sz ) pWalker->u.sz = sz;
170327 }
170328 return WRC_Continue;
170329 }
170330
170331 /*
170332 ** Return the length of the longest string literal in the given
170333 ** expression.
170334 **
170335 ** eCode indicates how to count characters:
170336 **
170337 ** eCode==0 Count as a GLOB pattern
170338 ** eCode==1 Count as a LIKE pattern
170339 */
170340 static int estLikePatternLength(Expr *p, u16 eCode){
170341 Walker w;
170342 w.u.sz = 0;
170343 w.eCode = eCode;
170344 w.xExprCallback = exprNodePatternLengthEst;
170345 w.xSelectCallback = sqlite3SelectWalkFail;
170346 #ifdef SQLITE_DEBUG
170347 w.xSelectCallback2 = sqlite3SelectWalkAssert2;
170348 #endif
170349 sqlite3WalkExpr(&w, p);
170350 return w.u.sz;
170351 }
170352
170353 /*
170354 ** Adjust the WhereLoop.nOut value downward to account for terms of the
170355 ** WHERE clause that reference the loop but which are not used by an
170356 ** index.
@@ -170187,10 +170376,17 @@
170376 ** of rows in the table. In other words, assume that x==EXPR will filter
170377 ** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the
170378 ** "x" column is boolean or else -1 or 0 or 1 is a common default value
170379 ** on the "x" column and so in that case only cap the output row estimate
170380 ** at 1/2 instead of 1/4.
170381 **
170382 ** Heuristic 3: If there is a LIKE or GLOB (or REGEXP or MATCH) operator
170383 ** with a large constant pattern, then reduce the size of the search
170384 ** space according to the length of the pattern, under the theory that
170385 ** longer patterns are less likely to match. This heuristic was added
170386 ** to give better output-row count estimates when preparing queries for
170387 ** the Join-Order Benchmarks. See forum thread 2026-01-30T09:57:54z
170388 */
170389 static void whereLoopOutputAdjust(
170390 WhereClause *pWC, /* The WHERE clause */
170391 WhereLoop *pLoop, /* The loop to adjust downward */
170392 LogEst nRow /* Number of rows in the entire table */
@@ -170236,25 +170432,43 @@
170432 ** then use the probability provided by the application. */
170433 pLoop->nOut += pTerm->truthProb;
170434 }else{
170435 /* In the absence of explicit truth probabilities, use heuristics to
170436 ** guess a reasonable truth probability. */
170437 Expr *pOpExpr = pTerm->pExpr;
170438 pLoop->nOut--;
170439 if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
170440 && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
170441 ){
170442 Expr *pRight = pOpExpr->pRight;
170443 int k = 0;
170444 testcase( pOpExpr->op==TK_IS );
170445 if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
170446 k = 10;
170447 }else{
170448 k = 20;
170449 }
170450 if( iReduce<k ){
170451 pTerm->wtFlags |= TERM_HEURTRUTH;
170452 iReduce = k;
170453 }
170454 }else
170455 if( ExprHasProperty(pOpExpr, EP_InfixFunc)
170456 && pOpExpr->op==TK_FUNCTION
170457 ){
170458 int eOp;
170459 assert( ExprUseXList(pOpExpr) );
170460 assert( pOpExpr->x.pList->nExpr>=2 );
170461 eOp = sqlite3ExprIsLikeOperator(pOpExpr);
170462 if( ALWAYS(eOp>0) ){
170463 int szPattern;
170464 Expr *pRHS = pOpExpr->x.pList->a[0].pExpr;
170465 eOp = eOp==SQLITE_INDEX_CONSTRAINT_LIKE;
170466 szPattern = estLikePatternLength(pRHS, eOp);
170467 if( szPattern>0 ){
170468 pLoop->nOut -= szPattern*2;
170469 }
170470 }
170471 }
170472 }
170473 }
170474 }
@@ -170712,10 +170926,11 @@
170926
170927 nOutUnadjusted = pNew->nOut;
170928 pNew->rRun += nInMul + nIn;
170929 pNew->nOut += nInMul + nIn;
170930 whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
170931 if( pSrc->fg.fromExists ) pNew->nOut = 0;
170932 rc = whereLoopInsert(pBuilder, pNew);
170933
170934 if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
170935 pNew->nOut = saved_nOut;
170936 }else{
@@ -171308,10 +171523,12 @@
171523 ApplyCostMultiplier(pNew->rRun, pTab->costMult);
171524 whereLoopOutputAdjust(pWC, pNew, rSize);
171525 if( pSrc->fg.isSubquery ){
171526 if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
171527 pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
171528 }else if( pSrc->fg.fromExists ){
171529 pNew->nOut = 0;
171530 }
171531 rc = whereLoopInsert(pBuilder, pNew);
171532 pNew->nOut = rSize;
171533 if( rc ) break;
171534 }else{
@@ -171410,10 +171627,11 @@
171627 /* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
171628 ** because the cursor used to access the index might not be
171629 ** positioned to the correct row during the right-join no-match
171630 ** loop. */
171631 }else{
171632 if( pSrc->fg.fromExists ) pNew->nOut = 0;
171633 rc = whereLoopInsert(pBuilder, pNew);
171634 }
171635 pNew->nOut = rSize;
171636 if( rc ) break;
171637 }
@@ -172072,11 +172290,11 @@
172290 SrcItem *pItem;
172291 SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
172292 sqlite3 *db = pWInfo->pParse->db;
172293 int rc = SQLITE_OK;
172294 int bFirstPastRJ = 0;
172295 int hasRightCrossJoin = 0;
172296 WhereLoop *pNew;
172297
172298
172299 /* Loop over the tables in the join, from left to right */
172300 pNew = pBuilder->pNew;
@@ -172099,19 +172317,38 @@
172317 /* Add prerequisites to prevent reordering of FROM clause terms
172318 ** across CROSS joins and outer joins. The bFirstPastRJ boolean
172319 ** prevents the right operand of a RIGHT JOIN from being swapped with
172320 ** other elements even further to the right.
172321 **
172322 ** The hasRightCrossJoin flag prevent FROM-clause terms from moving
172323 ** from the right side of a LEFT JOIN or CROSS JOIN over to the
172324 ** left side of that same join. This is a required restriction in
172325 ** the case of LEFT JOIN - an incorrect answer may results if it is
172326 ** not enforced. This restriction is not required for CROSS JOIN.
172327 ** It is provided merely as a means of controlling join order, under
172328 ** the theory that no real-world queries that care about performance
172329 ** actually use the CROSS JOIN syntax.
172330 */
172331 if( pItem->fg.jointype & (JT_LTORJ|JT_CROSS) ){
172332 testcase( pItem->fg.jointype & JT_LTORJ );
172333 testcase( pItem->fg.jointype & JT_CROSS );
172334 hasRightCrossJoin = 1;
172335 }
172336 mPrereq |= mPrior;
172337 bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
172338 }else if( pItem->fg.fromExists ){
172339 /* joins that result from the EXISTS-to-JOIN optimization should not
172340 ** be moved to the left of any of their dependencies */
172341 WhereClause *pWC = &pWInfo->sWC;
172342 WhereTerm *pTerm;
172343 int i;
172344 for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
172345 if( (pNew->maskSelf & pTerm->prereqAll)!=0 ){
172346 mPrereq |= (pTerm->prereqAll & (pNew->maskSelf-1));
172347 }
172348 }
172349 }else if( !hasRightCrossJoin ){
172350 mPrereq = 0;
172351 }
172352 #ifndef SQLITE_OMIT_VIRTUALTABLE
172353 if( IsVirtual(pItem->pSTab) ){
172354 SrcItem *p;
@@ -172330,13 +172567,11 @@
172567 if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
172568 }else{
172569 pLoop = pLast;
172570 }
172571 if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
172572 if( pLoop->u.vtab.isOrdered && pWInfo->pOrderBy==pOrderBy ){
 
 
172573 obSat = obDone;
172574 }else{
172575 /* No further ORDER BY terms may be matched. So this call should
172576 ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
172577 isOrderDistinct = 0;
@@ -173673,10 +173908,11 @@
173908 pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
173909 notReady &= ~pLoop->maskSelf;
173910 for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
173911 if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
173912 pTerm->wtFlags |= TERM_CODED;
173913 pTerm->prereqAll = 0;
173914 }
173915 }
173916 if( i!=pWInfo->nLevel-1 ){
173917 int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
173918 memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
@@ -174660,26 +174896,31 @@
174896 VdbeCoverageIf(v, op==OP_SeekGT);
174897 sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
174898 }
174899 #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
174900 }
174901 if( pTabList->a[pLevel->iFrom].fg.fromExists
174902 && (i==pWInfo->nLevel-1
174903 || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
174904 ){
174905 /* This is an EXISTS-to-JOIN optimization which is either the
174906 ** inner-most loop, or the inner-most of a group of nested
174907 ** EXISTS-to-JOIN optimization loops. If this loop sees a successful
174908 ** row, it should break out of itself as well as other EXISTS-to-JOIN
174909 ** loops in which is is directly nested. */
174910 int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
174911 while( nOuter<i ){
174912 if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
174913 nOuter++;
174914 }
174915 testcase( nOuter>0 );
174916 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
174917 if( nOuter ){
174918 VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
174919 }else{
174920 VdbeComment((v, "EXISTS break %d", i));
174921 }
174922 }
174923 sqlite3VdbeResolveLabel(v, pLevel->addrCont);
174924 if( pLevel->op!=OP_Noop ){
174925 sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
174926 sqlite3VdbeChangeP5(v, pLevel->p5);
@@ -184823,11 +185064,11 @@
185064 for(i=1; sqlite3Isdigit(z[i]); i++){}
185065 return i;
185066 }
185067 case CC_DOLLAR:
185068 case CC_VARALPHA: {
185069 i64 n = 0;
185070 testcase( z[0]=='$' ); testcase( z[0]=='@' );
185071 testcase( z[0]==':' ); testcase( z[0]=='#' );
185072 *tokenType = TK_VARIABLE;
185073 for(i=1; (c=z[i])!=0; i++){
185074 if( IdChar(c) ){
@@ -189448,10 +189689,16 @@
189689 /*
189690 ** Find existing client data.
189691 */
189692 SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){
189693 DbClientData *p;
189694 #ifdef SQLITE_ENABLE_API_ARMOR
189695 if( !zName || !sqlite3SafetyCheckOk(db) ){
189696 (void)SQLITE_MISUSE_BKPT;
189697 return 0;
189698 }
189699 #endif
189700 sqlite3_mutex_enter(db->mutex);
189701 for(p=db->pDbData; p; p=p->pNext){
189702 if( strcmp(p->zName, zName)==0 ){
189703 void *pResult = p->pData;
189704 sqlite3_mutex_leave(db->mutex);
@@ -192292,10 +192539,19 @@
192539 SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
192540
192541 #define fts3GetVarint32(p, piVal) ( \
192542 (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
192543 )
192544
192545 SQLITE_PRIVATE int sqlite3Fts3PrepareStmt(
192546 Fts3Table *p, /* Prepare for this connection */
192547 const char *zSql, /* SQL to prepare */
192548 int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */
192549 int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */
192550 sqlite3_stmt **pp /* OUT: Prepared statement */
192551 );
192552
192553
192554 /* fts3.c */
192555 SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
192556 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
192557 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
@@ -193900,13 +194156,11 @@
194156 p->pSeekStmt = 0;
194157 }else{
194158 zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
194159 if( !zSql ) return SQLITE_NOMEM;
194160 p->bLock++;
194161 rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt);
 
 
194162 p->bLock--;
194163 sqlite3_free(zSql);
194164 }
194165 if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
194166 }
@@ -195477,13 +195731,11 @@
195731 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
195732 );
195733 }
195734 if( zSql ){
195735 p->bLock++;
195736 rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt);
 
 
195737 p->bLock--;
195738 sqlite3_free(zSql);
195739 }else{
195740 rc = SQLITE_NOMEM;
195741 }
@@ -196102,10 +196354,11 @@
196354 int rc = SQLITE_OK;
196355 int bOk = 0;
196356
196357 UNUSED_PARAMETER(isQuick);
196358 rc = sqlite3Fts3IntegrityCheck(p, &bOk);
196359 assert( pVtab->zErrMsg==0 || rc!=SQLITE_OK );
196360 assert( rc!=SQLITE_CORRUPT_VTAB );
196361 if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){
196362 *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
196363 " FTS%d table %s.%s: %s",
196364 p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
@@ -202713,10 +202966,28 @@
202966 #define SQL_SELECT_MXLEVEL 36
202967
202968 #define SQL_SELECT_LEVEL_RANGE2 37
202969 #define SQL_UPDATE_LEVEL_IDX 38
202970 #define SQL_UPDATE_LEVEL 39
202971
202972 /*
202973 ** Wrapper around sqlite3_prepare_v3() to ensure that SQLITE_PREPARE_FROM_DDL
202974 ** is always set.
202975 */
202976 SQLITE_PRIVATE int sqlite3Fts3PrepareStmt(
202977 Fts3Table *p, /* Prepare for this connection */
202978 const char *zSql, /* SQL to prepare */
202979 int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */
202980 int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */
202981 sqlite3_stmt **pp /* OUT: Prepared statement */
202982 ){
202983 int f = SQLITE_PREPARE_FROM_DDL
202984 |((bAllowVtab==0) ? SQLITE_PREPARE_NO_VTAB : 0)
202985 |(bPersist ? SQLITE_PREPARE_PERSISTENT : 0);
202986
202987 return sqlite3_prepare_v3(p->db, zSql, -1, f, pp, NULL);
202988 }
202989
202990 /*
202991 ** This function is used to obtain an SQLite prepared statement handle
202992 ** for the statement identified by the second argument. If successful,
202993 ** *pp is set to the requested statement handle and SQLITE_OK returned.
@@ -202839,24 +203110,24 @@
203110 assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
203111 assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
203112
203113 pStmt = p->aStmt[eStmt];
203114 if( !pStmt ){
203115 int bAllowVtab = 0;
203116 char *zSql;
203117 if( eStmt==SQL_CONTENT_INSERT ){
203118 zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
203119 }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
203120 bAllowVtab = 1;
203121 zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
203122 }else{
203123 zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
203124 }
203125 if( !zSql ){
203126 rc = SQLITE_NOMEM;
203127 }else{
203128 rc = sqlite3Fts3PrepareStmt(p, zSql, 1, bAllowVtab, &pStmt);
203129 sqlite3_free(zSql);
203130 assert( rc==SQLITE_OK || pStmt==0 );
203131 p->aStmt[eStmt] = pStmt;
203132 }
203133 }
@@ -206019,11 +206290,11 @@
206290 /* Compose and prepare an SQL statement to loop through the content table */
206291 char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
206292 if( !zSql ){
206293 rc = SQLITE_NOMEM;
206294 }else{
206295 rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt);
206296 sqlite3_free(zSql);
206297 }
206298
206299 if( rc==SQLITE_OK ){
206300 sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
@@ -207772,11 +208043,11 @@
208043
208044 zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
208045 if( !zSql ){
208046 rc = SQLITE_NOMEM;
208047 }else{
208048 rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt);
208049 sqlite3_free(zSql);
208050 }
208051
208052 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
208053 i64 iDocid = sqlite3_column_int64(pStmt, 0);
@@ -211177,11 +211448,14 @@
211448 */
211449 #define JSON_JSON 0x01 /* Result is always JSON */
211450 #define JSON_SQL 0x02 /* Result is always SQL */
211451 #define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
211452 #define JSON_ISSET 0x04 /* json_set(), not json_insert() */
211453 #define JSON_AINS 0x08 /* json_array_insert(), not json_insert() */
211454 #define JSON_BLOB 0x10 /* Use the BLOB output format */
211455
211456 #define JSON_INSERT_TYPE(X) (((X)&0xC)>>2)
211457
211458
211459 /* A parsed JSON value. Lifecycle:
211460 **
211461 ** 1. JSON comes in and is parsed into a JSONB value in aBlob. The
@@ -211223,10 +211497,11 @@
211497 /* Allowed values for JsonParse.eEdit */
211498 #define JEDIT_DEL 1 /* Delete if exists */
211499 #define JEDIT_REPL 2 /* Overwrite if exists */
211500 #define JEDIT_INS 3 /* Insert if not exists */
211501 #define JEDIT_SET 4 /* Insert or overwrite */
211502 #define JEDIT_AINS 5 /* array_insert() */
211503
211504 /*
211505 ** Maximum nesting depth of JSON for this implementation.
211506 **
211507 ** This limit is needed to avoid a stack overflow in the recursive
@@ -213719,11 +213994,12 @@
213994 /*
213995 ** Error returns from jsonLookupStep()
213996 */
213997 #define JSON_LOOKUP_ERROR 0xffffffff
213998 #define JSON_LOOKUP_NOTFOUND 0xfffffffe
213999 #define JSON_LOOKUP_NOTARRAY 0xfffffffd
214000 #define JSON_LOOKUP_PATHERROR 0xfffffffc
214001 #define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR)
214002
214003 /* Forward declaration */
214004 static u32 jsonLookupStep(JsonParse*,u32,const char*,u32);
214005
@@ -213748,11 +214024,11 @@
214024 ** using the substructure.
214025 */
214026 static u32 jsonCreateEditSubstructure(
214027 JsonParse *pParse, /* The original JSONB that is being edited */
214028 JsonParse *pIns, /* Populate this with the blob data to insert */
214029 const char *zTail /* Tail of the path that determines substructure */
214030 ){
214031 static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
214032 int rc;
214033 memset(pIns, 0, sizeof(*pIns));
214034 pIns->db = pParse->db;
@@ -213783,13 +214059,13 @@
214059 ** label, before returning.
214060 **
214061 ** Return one of the JSON_LOOKUP error codes if problems are seen.
214062 **
214063 ** This routine will also modify the blob. If pParse->eEdit is one of
214064 ** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, JEDIT_SET, or JEDIT_AINS, then changes
214065 ** might be made to the selected value. If an edit is performed, then the
214066 ** return value does not necessarily point to the select element. If an edit
214067 ** is performed, the return value is only useful for detecting error
214068 ** conditions.
214069 */
214070 static u32 jsonLookupStep(
214071 JsonParse *pParse, /* The JSON to search */
@@ -213811,10 +214087,17 @@
214087 iRoot = iLabel;
214088 }
214089 jsonBlobEdit(pParse, iRoot, sz, 0, 0);
214090 }else if( pParse->eEdit==JEDIT_INS ){
214091 /* Already exists, so json_insert() is a no-op */
214092 }else if( pParse->eEdit==JEDIT_AINS ){
214093 /* json_array_insert() */
214094 if( zPath[-1]!=']' ){
214095 return JSON_LOOKUP_NOTARRAY;
214096 }else{
214097 jsonBlobEdit(pParse, iRoot, 0, pParse->aIns, pParse->nIns);
214098 }
214099 }else{
214100 /* json_set() or json_replace() */
214101 jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns);
214102 }
214103 }
@@ -213882,10 +214165,14 @@
214165 u32 nIns; /* Total bytes to insert (label+value) */
214166 JsonParse v; /* BLOB encoding of the value to be inserted */
214167 JsonParse ix; /* Header of the label to be inserted */
214168 testcase( pParse->eEdit==JEDIT_INS );
214169 testcase( pParse->eEdit==JEDIT_SET );
214170 testcase( pParse->eEdit==JEDIT_AINS );
214171 if( pParse->eEdit==JEDIT_AINS && sqlite3_strglob("*]",&zPath[i])!=0 ){
214172 return JSON_LOOKUP_NOTARRAY;
214173 }
214174 memset(&ix, 0, sizeof(ix));
214175 ix.db = pParse->db;
214176 jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
214177 pParse->oom |= ix.oom;
214178 rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
@@ -213909,32 +214196,36 @@
214196 jsonParseReset(&v);
214197 jsonParseReset(&ix);
214198 return rc;
214199 }
214200 }else if( zPath[0]=='[' ){
214201 u64 kk = 0;
214202 x = pParse->aBlob[iRoot] & 0x0f;
214203 if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND;
214204 n = jsonbPayloadSize(pParse, iRoot, &sz);
 
214205 i = 1;
214206 while( sqlite3Isdigit(zPath[i]) ){
214207 if( kk<0xffffffff ) kk = kk*10 + zPath[i] - '0';
214208 /* ^^^^^^^^^^--- Allow kk to be bigger than any JSON array so that
214209 ** we get NOTFOUND instead of PATHERROR, without overflowing kk. */
214210 i++;
214211 }
214212 if( i<2 || zPath[i]!=']' ){
214213 if( zPath[1]=='#' ){
214214 kk = jsonbArrayCount(pParse, iRoot);
214215 i = 2;
214216 if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
214217 u64 nn = 0;
214218 i = 3;
214219 do{
214220 if( nn<0xffffffff ) nn = nn*10 + zPath[i] - '0';
214221 /* ^^^^^^^^^^--- Allow nn to be bigger than any JSON array to
214222 ** get NOTFOUND instead of PATHERROR, without overflowing nn. */
214223 i++;
214224 }while( sqlite3Isdigit(zPath[i]) );
214225 if( nn>kk ) return JSON_LOOKUP_NOTFOUND;
214226 kk -= nn;
214227 }
214228 if( zPath[i]!=']' ){
214229 return JSON_LOOKUP_PATHERROR;
214230 }
214231 }else{
@@ -213942,25 +214233,26 @@
214233 }
214234 }
214235 j = iRoot+n;
214236 iEnd = j+sz;
214237 while( j<iEnd ){
214238 if( kk==0 ){
214239 rc = jsonLookupStep(pParse, j, &zPath[i+1], 0);
214240 if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
214241 return rc;
214242 }
214243 kk--;
214244 n = jsonbPayloadSize(pParse, j, &sz);
214245 if( n==0 ) return JSON_LOOKUP_ERROR;
214246 j += n+sz;
214247 }
214248 if( j>iEnd ) return JSON_LOOKUP_ERROR;
214249 if( kk>0 ) return JSON_LOOKUP_NOTFOUND;
214250 if( pParse->eEdit>=JEDIT_INS ){
214251 JsonParse v;
214252 testcase( pParse->eEdit==JEDIT_INS );
214253 testcase( pParse->eEdit==JEDIT_AINS );
214254 testcase( pParse->eEdit==JEDIT_SET );
214255 rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]);
214256 if( !JSON_LOOKUP_ISERROR(rc)
214257 && jsonBlobMakeEditable(pParse, v.nBlob)
214258 ){
@@ -214281,13 +214573,19 @@
214573 ** If ctx is not NULL then push the error message into ctx and return NULL.
214574 ** If ctx is NULL, then return the text of the error message.
214575 */
214576 static char *jsonBadPathError(
214577 sqlite3_context *ctx, /* The function call containing the error */
214578 const char *zPath, /* The path with the problem */
214579 int rc /* Maybe JSON_LOOKUP_NOTARRAY */
214580 ){
214581 char *zMsg;
214582 if( rc==(int)JSON_LOOKUP_NOTARRAY ){
214583 zMsg = sqlite3_mprintf("not an array element: %Q", zPath);
214584 }else{
214585 zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
214586 }
214587 if( ctx==0 ) return zMsg;
214588 if( zMsg ){
214589 sqlite3_result_error(ctx, zMsg, -1);
214590 sqlite3_free(zMsg);
214591 }else{
@@ -214300,17 +214598,17 @@
214598 ** arguments come in pairs where each pair contains a JSON path and
214599 ** content to insert or set at that patch. Do the updates
214600 ** and return the result.
214601 **
214602 ** The specific operation is determined by eEdit, which can be one
214603 ** of JEDIT_INS, JEDIT_REPL, JEDIT_SET, or JEDIT_AINS.
214604 */
214605 static void jsonInsertIntoBlob(
214606 sqlite3_context *ctx,
214607 int argc,
214608 sqlite3_value **argv,
214609 int eEdit /* JEDIT_INS, JEDIT_REPL, JEDIT_SET, JEDIT_AINS */
214610 ){
214611 int i;
214612 u32 rc = 0;
214613 const char *zPath = 0;
214614 int flgs;
@@ -214358,11 +214656,11 @@
214656 jsonInsertIntoBlob_patherror:
214657 jsonParseFree(p);
214658 if( rc==JSON_LOOKUP_ERROR ){
214659 sqlite3_result_error(ctx, "malformed JSON", -1);
214660 }else{
214661 jsonBadPathError(ctx, zPath, rc);
214662 }
214663 return;
214664 }
214665
214666 /*
@@ -214800,11 +215098,11 @@
215098 i = jsonLookupStep(p, 0, zPath[0]=='$' ? zPath+1 : "@", 0);
215099 if( JSON_LOOKUP_ISERROR(i) ){
215100 if( i==JSON_LOOKUP_NOTFOUND ){
215101 /* no-op */
215102 }else if( i==JSON_LOOKUP_PATHERROR ){
215103 jsonBadPathError(ctx, zPath, 0);
215104 }else{
215105 sqlite3_result_error(ctx, "malformed JSON", -1);
215106 }
215107 eErr = 1;
215108 i = 0;
@@ -214905,11 +215203,11 @@
215203 }
215204 jsonStringTerminate(&jx);
215205 j = jsonLookupStep(p, 0, jx.zBuf, 0);
215206 jsonStringReset(&jx);
215207 }else{
215208 jsonBadPathError(ctx, zPath, 0);
215209 goto json_extract_error;
215210 }
215211 if( j<p->nBlob ){
215212 if( argc==2 ){
215213 if( flags & JSON_JSON ){
@@ -214940,11 +215238,11 @@
215238 }
215239 }else if( j==JSON_LOOKUP_ERROR ){
215240 sqlite3_result_error(ctx, "malformed JSON", -1);
215241 goto json_extract_error;
215242 }else{
215243 jsonBadPathError(ctx, zPath, 0);
215244 goto json_extract_error;
215245 }
215246 }
215247 if( argc>2 ){
215248 jsonAppendChar(&jx, ']');
@@ -215269,11 +215567,11 @@
215567 rc = jsonLookupStep(p, 0, zPath+1, 0);
215568 if( JSON_LOOKUP_ISERROR(rc) ){
215569 if( rc==JSON_LOOKUP_NOTFOUND ){
215570 continue; /* No-op */
215571 }else if( rc==JSON_LOOKUP_PATHERROR ){
215572 jsonBadPathError(ctx, zPath, rc);
215573 }else{
215574 sqlite3_result_error(ctx, "malformed JSON", -1);
215575 }
215576 goto json_remove_done;
215577 }
@@ -215281,11 +215579,11 @@
215579 jsonReturnParse(ctx, p);
215580 jsonParseFree(p);
215581 return;
215582
215583 json_remove_patherror:
215584 jsonBadPathError(ctx, zPath, 0);
215585
215586 json_remove_done:
215587 jsonParseFree(p);
215588 return;
215589 }
@@ -215325,20 +215623,22 @@
215623 static void jsonSetFunc(
215624 sqlite3_context *ctx,
215625 int argc,
215626 sqlite3_value **argv
215627 ){
 
215628 int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215629 int eInsType = JSON_INSERT_TYPE(flags);
215630 static const char *azInsType[] = { "insert", "set", "array_insert" };
215631 static const u8 aEditType[] = { JEDIT_INS, JEDIT_SET, JEDIT_AINS };
215632
215633 if( argc<1 ) return;
215634 assert( eInsType>=0 && eInsType<=2 );
215635 if( (argc&1)==0 ) {
215636 jsonWrongNumArgs(ctx, azInsType[eInsType]);
215637 return;
215638 }
215639 jsonInsertIntoBlob(ctx, argc, argv, aEditType[eInsType]);
215640 }
215641
215642 /*
215643 ** json_type(JSON)
215644 ** json_type(JSON, PATH)
@@ -215359,19 +215659,19 @@
215659 if( p==0 ) return;
215660 if( argc==2 ){
215661 zPath = (const char*)sqlite3_value_text(argv[1]);
215662 if( zPath==0 ) goto json_type_done;
215663 if( zPath[0]!='$' ){
215664 jsonBadPathError(ctx, zPath, 0);
215665 goto json_type_done;
215666 }
215667 i = jsonLookupStep(p, 0, zPath+1, 0);
215668 if( JSON_LOOKUP_ISERROR(i) ){
215669 if( i==JSON_LOOKUP_NOTFOUND ){
215670 /* no-op */
215671 }else if( i==JSON_LOOKUP_PATHERROR ){
215672 jsonBadPathError(ctx, zPath, 0);
215673 }else{
215674 sqlite3_result_error(ctx, "malformed JSON", -1);
215675 }
215676 goto json_type_done;
215677 }
@@ -215623,16 +215923,15 @@
215923 jsonAppendSqlValue(pStr, argv[0]);
215924 }
215925 }
215926 static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
215927 JsonString *pStr;
215928 int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
215929 pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
215930 if( pStr ){
 
215931 pStr->pCtx = ctx;
215932 jsonAppendChar(pStr, ']');
 
215933 if( pStr->eErr ){
215934 jsonReturnString(pStr, 0, 0);
215935 return;
215936 }else if( flags & JSON_BLOB ){
215937 jsonReturnStringAsBlob(pStr);
@@ -215649,10 +215948,13 @@
215948 pStr->bStatic = 1;
215949 }else{
215950 sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
215951 jsonStringTrimOneChar(pStr);
215952 }
215953 }else if( flags & JSON_BLOB ){
215954 static const u8 emptyArray = 0x0b;
215955 sqlite3_result_blob(ctx, &emptyArray, 1, SQLITE_STATIC);
215956 }else{
215957 sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
215958 }
215959 sqlite3_result_subtype(ctx, JSON_SUBTYPE);
215960 }
@@ -215745,16 +216047,15 @@
216047 }
216048 }
216049 }
216050 static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
216051 JsonString *pStr;
216052 int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
216053 pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
216054 if( pStr ){
 
216055 jsonAppendChar(pStr, '}');
216056 pStr->pCtx = ctx;
 
216057 if( pStr->eErr ){
216058 jsonReturnString(pStr, 0, 0);
216059 return;
216060 }else if( flags & JSON_BLOB ){
216061 jsonReturnStringAsBlob(pStr);
@@ -215771,10 +216072,13 @@
216072 pStr->bStatic = 1;
216073 }else{
216074 sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
216075 jsonStringTrimOneChar(pStr);
216076 }
216077 }else if( flags & JSON_BLOB ){
216078 static const unsigned char emptyObject = 0x0c;
216079 sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
216080 }else{
216081 sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
216082 }
216083 sqlite3_result_subtype(ctx, JSON_SUBTYPE);
216084 }
@@ -216271,11 +216575,11 @@
216575 if( idxNum==3 ){
216576 zRoot = (const char*)sqlite3_value_text(argv[1]);
216577 if( zRoot==0 ) return SQLITE_OK;
216578 if( zRoot[0]!='$' ){
216579 sqlite3_free(cur->pVtab->zErrMsg);
216580 cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0);
216581 jsonEachCursorReset(p);
216582 return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216583 }
216584 p->nRoot = sqlite3Strlen30(zRoot);
216585 if( zRoot[1]==0 ){
@@ -216289,11 +216593,11 @@
216593 p->eType = 0;
216594 p->iEnd = 0;
216595 return SQLITE_OK;
216596 }
216597 sqlite3_free(cur->pVtab->zErrMsg);
216598 cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0);
216599 jsonEachCursorReset(p);
216600 return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216601 }
216602 if( p->sParse.iLabel ){
216603 p->i = p->sParse.iLabel;
@@ -216379,10 +216683,12 @@
216683 /* | | | | | | */
216684 JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc),
216685 JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc),
216686 JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
216687 JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
216688 JFUNCTION(json_array_insert, -1,1,1, 1,0,JSON_AINS, jsonSetFunc),
216689 JFUNCTION(jsonb_array_insert,-1,1,0, 1,1,JSON_AINS, jsonSetFunc),
216690 JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
216691 JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
216692 JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
216693 JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc),
216694 JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc),
@@ -220226,11 +220532,11 @@
220532 tree.nBytesPerCell = 8 + 8 * tree.nDim;
220533 node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
220534 if( node.zData==0 ) return;
220535 nData = sqlite3_value_bytes(apArg[1]);
220536 if( nData<4 ) return;
220537 if( nData<4+NCELL(&node)*tree.nBytesPerCell ) return;
220538
220539 pOut = sqlite3_str_new(0);
220540 for(ii=0; ii<NCELL(&node); ii++){
220541 RtreeCell cell;
220542 int jj;
@@ -231218,10 +231524,11 @@
231524 struct carray_bind {
231525 void *aData; /* The data */
231526 int nData; /* Number of elements */
231527 int mFlags; /* Control flags */
231528 void (*xDel)(void*); /* Destructor for aData */
231529 void *pDel; /* Alternative argument to xDel() */
231530 };
231531
231532
231533 /* carray_cursor is a subclass of sqlite3_vtab_cursor which will
231534 ** serve as the underlying representation of a cursor that scans
@@ -231550,26 +231857,38 @@
231857 ** Destructor for the carray_bind object
231858 */
231859 static void carrayBindDel(void *pPtr){
231860 carray_bind *p = (carray_bind*)pPtr;
231861 if( p->xDel!=SQLITE_STATIC ){
231862 p->xDel(p->pDel);
231863 }
231864 sqlite3_free(p);
231865 }
231866
231867 /*
231868 ** Invoke this interface in order to bind to the single-argument
231869 ** version of CARRAY().
231870 **
231871 ** pStmt The prepared statement to which to bind
231872 ** idx The index of the parameter of pStmt to which to bind
231873 ** aData The data to be bound
231874 ** nData The number of elements in aData
231875 ** mFlags One of SQLITE_CARRAY_xxxx indicating datatype of aData
231876 ** xDestroy Destructor for pDestroy or aData if pDestroy==NULL.
231877 ** pDestroy Invoke xDestroy on this pointer if not NULL
231878 **
231879 ** The destructor is called pDestroy if pDestroy!=NULL, or against
231880 ** aData if pDestroy==NULL.
231881 */
231882 SQLITE_API int sqlite3_carray_bind_v2(
231883 sqlite3_stmt *pStmt,
231884 int idx,
231885 void *aData,
231886 int nData,
231887 int mFlags,
231888 void (*xDestroy)(void*),
231889 void *pDestroy
231890 ){
231891 carray_bind *pNew = 0;
231892 int i;
231893 int rc = SQLITE_OK;
231894
@@ -231642,23 +231961,41 @@
231961 }
231962 }else{
231963 memcpy(pNew->aData, aData, sz);
231964 }
231965 pNew->xDel = sqlite3_free;
231966 pNew->pDel = pNew->aData;
231967 }else{
231968 pNew->aData = aData;
231969 pNew->xDel = xDestroy;
231970 pNew->pDel = pDestroy;
231971 }
231972 return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel);
231973
231974 carray_bind_error:
231975 if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){
231976 xDestroy(pDestroy);
231977 }
231978 sqlite3_free(pNew);
231979 return rc;
231980 }
231981
231982 /*
231983 ** Invoke this interface in order to bind to the single-argument
231984 ** version of CARRAY(). Same as sqlite3_carray_bind_v2() with the
231985 ** pDestroy parameter set to NULL.
231986 */
231987 SQLITE_API int sqlite3_carray_bind(
231988 sqlite3_stmt *pStmt,
231989 int idx,
231990 void *aData,
231991 int nData,
231992 int mFlags,
231993 void (*xDestroy)(void*)
231994 ){
231995 return sqlite3_carray_bind_v2(pStmt,idx,aData,nData,mFlags,xDestroy,aData);
231996 }
231997
231998 /*
231999 ** Invoke this routine to register the carray() function.
232000 */
232001 SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3 *db){
@@ -232017,10 +232354,24 @@
232354 ** bytes read.
232355 */
232356 static int sessionVarintGet(const u8 *aBuf, int *piVal){
232357 return getVarint32(aBuf, *piVal);
232358 }
232359
232360 /*
232361 ** Read a varint value from buffer aBuf[], size nBuf bytes, into *piVal.
232362 ** Return the number of bytes read.
232363 */
232364 static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){
232365 u8 aCopy[5];
232366 const u8 *aRead = aBuf;
232367 if( nBuf<5 ){
232368 memcpy(aCopy, aBuf, nBuf);
232369 aRead = aCopy;
232370 }
232371 return getVarint32(aRead, *piVal);
232372 }
232373
232374 /* Load an unaligned and unsigned 32-bit integer */
232375 #define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
232376
232377 /*
@@ -232312,31 +232663,31 @@
232663 for(i=0; i<pTab->nCol; i++){
232664 int eType = *a;
232665 int isPK = pTab->abPK[i];
232666 if( bPkOnly && isPK==0 ) continue;
232667
 
 
 
232668 assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
232669 || eType==SQLITE_TEXT || eType==SQLITE_BLOB
232670 || eType==SQLITE_NULL || eType==0
232671 );
 
232672
232673 if( isPK ){
232674 a++;
232675 h = sessionHashAppendType(h, eType);
232676 if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
232677 h = sessionHashAppendI64(h, sessionGetI64(a));
232678 a += 8;
232679 }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
232680 int n;
232681 a += sessionVarintGet(a, &n);
232682 h = sessionHashAppendBlob(h, n, a);
232683 a += n;
232684 }
232685 /* It should not be possible for eType to be SQLITE_NULL or 0x00 here,
232686 ** as the session module does not record changes for rows with NULL
232687 ** values stored in primary key columns. But a corrupt changesets
232688 ** may contain such a value. */
232689 }else{
232690 a += sessionSerialLen(a);
232691 }
232692 }
232693 return (h % nBucket);
@@ -234741,14 +235092,17 @@
235092 *pnChangeset = 0;
235093 *ppChangeset = 0;
235094 }
235095
235096 if( pSession->rc ) return pSession->rc;
 
 
235097
235098 sqlite3_mutex_enter(sqlite3_db_mutex(db));
235099 rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
235100 if( rc!=SQLITE_OK ){
235101 sqlite3_mutex_leave(sqlite3_db_mutex(db));
235102 return rc;
235103 }
235104
235105 for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
235106 if( pTab->nEntry ){
235107 const char *zName = pTab->zName;
235108 int i; /* Used to iterate through hash buckets */
@@ -235227,11 +235581,12 @@
235581
235582 if( rc==SQLITE_OK ){
235583 u8 *aVal = &pIn->aData[pIn->iNext];
235584 if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
235585 int nByte;
235586 int nRem = pIn->nData - pIn->iNext;
235587 pIn->iNext += sessionVarintGetSafe(aVal, nRem, &nByte);
235588 rc = sessionInputBuffer(pIn, nByte);
235589 if( rc==SQLITE_OK ){
235590 if( nByte<0 || nByte>pIn->nData-pIn->iNext ){
235591 rc = SQLITE_CORRUPT_BKPT;
235592 }else{
@@ -235280,11 +235635,12 @@
235635 int nCol = 0;
235636 int nRead = 0;
235637
235638 rc = sessionInputBuffer(pIn, 9);
235639 if( rc==SQLITE_OK ){
235640 int nBuf = pIn->nData - pIn->iNext;
235641 nRead += sessionVarintGetSafe(&pIn->aData[pIn->iNext], nBuf, &nCol);
235642 /* The hard upper limit for the number of columns in an SQLite
235643 ** database table is, according to sqliteLimit.h, 32676. So
235644 ** consider any table-header that purports to have more than 65536
235645 ** columns to be corrupt. This is convenient because otherwise,
235646 ** if the (nCol>65536) condition below were omitted, a sufficiently
@@ -235300,12 +235656,19 @@
235656
235657 while( rc==SQLITE_OK ){
235658 while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){
235659 nRead++;
235660 }
235661
235662 /* Break out of the loop if if the nul-terminator byte has been found.
235663 ** Otherwise, read some more input data and keep seeking. If there is
235664 ** no more input data, consider the changeset corrupt. */
235665 if( (pIn->iNext + nRead)<pIn->nData ) break;
235666 rc = sessionInputBuffer(pIn, nRead + 100);
235667 if( rc==SQLITE_OK && (pIn->iNext + nRead)>=pIn->nData ){
235668 rc = SQLITE_CORRUPT_BKPT;
235669 }
235670 }
235671 *pnByte = nRead+1;
235672 return rc;
235673 }
235674
@@ -235433,14 +235796,14 @@
235796 sqlite3ValueFree(p->apValue[i]);
235797 }
235798 memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2);
235799 }
235800
235801 /* Make sure the buffer contains at least 2 bytes of input data, or all
235802 ** remaining data if there are less than 2 bytes available. This is
235803 ** sufficient either for the 'T' or 'P' byte that begins a new table,
235804 ** or for the "op" and "bIndirect" single bytes otherwise. */
235805 p->rc = sessionInputBuffer(&p->in, 2);
235806 if( p->rc!=SQLITE_OK ) return p->rc;
235807
235808 p->in.iCurrent = p->in.iNext;
235809 sessionDiscardData(&p->in);
@@ -235466,15 +235829,17 @@
235829 ** corrupt changeset. */
235830 assert( p->in.iNext==1 || p->zTab );
235831 return (p->rc = SQLITE_CORRUPT_BKPT);
235832 }
235833
235834 if( (op!=SQLITE_UPDATE && op!=SQLITE_DELETE && op!=SQLITE_INSERT)
235835 || (p->in.iNext>=p->in.nData)
235836 ){
235837 return (p->rc = SQLITE_CORRUPT_BKPT);
235838 }
235839 p->op = op;
235840 p->bIndirect = p->in.aData[p->in.iNext++];
235841
235842 if( paRec ){
235843 int nVal; /* Number of values to buffer */
235844 if( p->bPatchset==0 && op==SQLITE_UPDATE ){
235845 nVal = p->nCol * 2;
@@ -239307,11 +239672,17 @@
239672 # define FLEXARRAY
239673 #else
239674 # define FLEXARRAY 1
239675 #endif
239676
239677 #endif /* SQLITE_AMALGAMATION */
239678
239679 /*
239680 ** Constants for the largest and smallest possible 32-bit signed integers.
239681 */
239682 # define LARGEST_INT32 ((int)(0x7fffffff))
239683 # define SMALLEST_INT32 ((int)((-1) - LARGEST_INT32))
239684
239685 /* Truncate very long tokens to this many bytes. Hard limit is
239686 ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
239687 ** field that occurs at the start of each leaf page (see fts5_index.c). */
239688 #define FTS5_MAX_TOKEN_SIZE 32768
@@ -253198,11 +253569,11 @@
253569 ){
253570 const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE);
253571 int iSegid = pSeg->pSeg->iSegid;
253572 u8 *aPg = pSeg->pLeaf->p;
253573 int nPg = pSeg->pLeaf->nn;
253574 int iPgIdx = pSeg->pLeaf->szLeaf; /* Offset of page footer */
253575
253576 u64 iDelta = 0;
253577 int iNextOff = 0;
253578 int iOff = 0;
253579 int nIdx = 0;
@@ -253277,11 +253648,11 @@
253648 iStart = iSOP + (nPos/2);
253649 iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
253650 iSOP += fts5GetVarint32(&aPg[iSOP], nPos);
253651 }
253652 assert_nc( iSOP==pSeg->iLeafOffset );
253653 iNextOff = iSOP + pSeg->nPos;
253654 }
253655 }
253656
253657 iOff = iStart;
253658
@@ -253357,35 +253728,35 @@
253728 if( iNextOff!=iPgIdx ){
253729 /* This is the only position-list associated with the term, and there
253730 ** is another term following it on this page. So the subsequent term
253731 ** needs to be moved to replace the term associated with the entry
253732 ** being removed. */
253733 u64 nPrefix = 0;
253734 u64 nSuffix = 0;
253735 u64 nPrefix2 = 0;
253736 u64 nSuffix2 = 0;
253737
253738 iDelKeyOff = iNextOff;
253739 iNextOff += fts5GetVarint(&aPg[iNextOff], &nPrefix2);
253740 iNextOff += fts5GetVarint(&aPg[iNextOff], &nSuffix2);
253741
253742 if( iKey!=1 ){
253743 iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nPrefix);
253744 }
253745 iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nSuffix);
253746
253747 nPrefix = MIN(nPrefix, nPrefix2);
253748 nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
253749
253750 if( (iKeyOff+nSuffix)>(u64)iPgIdx || (iNextOff+nSuffix2)>(u64)iPgIdx ){
253751 FTS5_CORRUPT_IDX(p);
253752 }else{
253753 if( iKey!=1 ){
253754 iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
253755 }
253756 iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
253757 if( nPrefix2>(u64)pSeg->term.n ){
253758 FTS5_CORRUPT_IDX(p);
253759 }else if( nPrefix2>nPrefix ){
253760 memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
253761 iOff += (nPrefix2-nPrefix);
253762 }
@@ -253412,11 +253783,11 @@
253783 Fts5Data *pTerm = fts5DataRead(p, iId);
253784 if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
253785 u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
253786 int nTermIdx = pTerm->nn - pTerm->szLeaf;
253787 int iTermIdx = 0;
253788 i64 iTermOff = 0;
253789
253790 while( 1 ){
253791 u32 iVal = 0;
253792 int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal);
253793 iTermOff += iVal;
@@ -253423,16 +253794,19 @@
253794 if( (iTermIdx+nByte)>=nTermIdx ) break;
253795 iTermIdx += nByte;
253796 }
253797 nTermIdx = iTermIdx;
253798
253799 if( iTermOff>pTerm->szLeaf ){
253800 FTS5_CORRUPT_IDX(p);
253801 }else{
253802 memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
253803 fts5PutU16(&pTerm->p[2], iTermOff);
253804 fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
253805 if( nTermIdx==0 ){
253806 fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
253807 }
253808 }
253809 }
253810 fts5DataRelease(pTerm);
253811 }
253812 }
@@ -253451,11 +253825,13 @@
253825 int nShift = iNextOff - iOff; /* Distance to move them */
253826
253827 int iPrevKeyOut = 0;
253828 int iKeyIn = 0;
253829
253830 if( nMove>0 ){
253831 memmove(&aPg[iOff], &aPg[iNextOff], nMove);
253832 }
253833 iPgIdx -= nShift;
253834 nPg = iPgIdx;
253835 fts5PutU16(&aPg[2], iPgIdx);
253836
253837 for(iIdx=0; iIdx<nIdx; /* no-op */){
@@ -253889,11 +254265,11 @@
254265 if( nMerge<0 ){
254266 Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
254267 fts5StructureRelease(pStruct);
254268 pStruct = pNew;
254269 nMin = 1;
254270 nMerge = (nMerge==SMALLEST_INT32 ? LARGEST_INT32 : (nMerge*-1));
254271 }
254272 if( pStruct && pStruct->nLevel ){
254273 if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
254274 fts5StructureWrite(p, pStruct);
254275 }
@@ -261097,11 +261473,11 @@
261473 int nArg, /* Number of args */
261474 sqlite3_value **apUnused /* Function arguments */
261475 ){
261476 assert( nArg==0 );
261477 UNUSED_PARAM2(nArg, apUnused);
261478 sqlite3_result_text(pCtx, "fts5: 2026-02-04 18:10:49 e6902937ecdbeb449986469859b46631272fb0a9e7e1c31adea14cff072b6d67", -1, SQLITE_TRANSIENT);
261479 }
261480
261481 /*
261482 ** Implementation of fts5_locale(LOCALE, TEXT) function.
261483 **
261484
+133 -35
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,14 +146,14 @@
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149149
#define SQLITE_VERSION "3.52.0"
150150
#define SQLITE_VERSION_NUMBER 3052000
151
-#define SQLITE_SOURCE_ID "2025-12-11 23:24:05 01409738afc2c0d5bdaa248ffb508aa5f36a66390f6b8e4834734529ee8ed2fa"
151
+#define SQLITE_SOURCE_ID "2026-02-04 20:51:27 c476d956d0bd3065cf894de6f9d393b999ff7d2268a35f01a6d88804789ab58f"
152152
#define SQLITE_SCM_BRANCH "trunk"
153153
#define SQLITE_SCM_TAGS ""
154
-#define SQLITE_SCM_DATETIME "2025-12-11T23:24:05.667Z"
154
+#define SQLITE_SCM_DATETIME "2026-02-04T20:51:27.822Z"
155155
156156
/*
157157
** CAPI3REF: Run-Time Library Version Numbers
158158
** KEYWORDS: sqlite3_version sqlite3_sourceid
159159
**
@@ -4431,16 +4431,32 @@
44314431
** compiles to see if some SQL syntax is well-formed, without generating
44324432
** messages on the global error log when it is not. If the test compile
44334433
** fails, the sqlite3_prepare_v3() call returns the same error indications
44344434
** with or without this flag; it just omits the call to [sqlite3_log()] that
44354435
** logs the error.
4436
+**
4437
+** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
4438
+** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
4439
+** the SQL statement is part of a database schema. This makes a difference
4440
+** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
4441
+** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
4442
+** SQL functions may not be called unless they are tagged with
4443
+** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
4444
+** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
4445
+** when preparing SQL that is derived from parts of the database
4446
+** schema. In particular, virtual table implementations that
4447
+** run SQL statements based on the arguments to their CREATE VIRTUAL
4448
+** TABLE statement should use [sqlite3_prepare_v3()] and set the
4449
+** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
4450
+** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
44364451
** </dl>
44374452
*/
44384453
#define SQLITE_PREPARE_PERSISTENT 0x01
44394454
#define SQLITE_PREPARE_NORMALIZE 0x02
44404455
#define SQLITE_PREPARE_NO_VTAB 0x04
44414456
#define SQLITE_PREPARE_DONT_LOG 0x10
4457
+#define SQLITE_PREPARE_FROM_DDL 0x20
44424458
44434459
/*
44444460
** CAPI3REF: Compiling An SQL Statement
44454461
** KEYWORDS: {SQL statement compiler}
44464462
** METHOD: sqlite3
@@ -4450,12 +4466,13 @@
44504466
** program using one of these routines. Or, in other words, these routines
44514467
** are constructors for the [prepared statement] object.
44524468
**
44534469
** The preferred routine to use is [sqlite3_prepare_v2()]. The
44544470
** [sqlite3_prepare()] interface is legacy and should be avoided.
4455
-** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
4456
-** for special purposes.
4471
+** [sqlite3_prepare_v3()] has an extra
4472
+** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times
4473
+** needed for special purpose or to pass along security restrictions.
44574474
**
44584475
** The use of the UTF-8 interfaces is preferred, as SQLite currently
44594476
** does all parsing using UTF-8. The UTF-16 interfaces are provided
44604477
** as a convenience. The UTF-16 interfaces work by converting the
44614478
** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -4856,12 +4873,12 @@
48564873
** it should be a pointer to well-formed UTF8 text.
48574874
** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
48584875
** it should be a pointer to well-formed UTF16 text.
48594876
** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
48604877
** it should be a pointer to a well-formed unicode string that is
4861
-** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
4862
-** otherwise.
4878
+** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT,
4879
+** or UTF16 otherwise.
48634880
**
48644881
** [[byte-order determination rules]] ^The byte-order of
48654882
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
48664883
** found in the first character, which is removed, or in the absence of a BOM
48674884
** the byte order is the native byte order of the host
@@ -4903,14 +4920,19 @@
49034920
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
49044921
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
49054922
** object and pointer to it must remain valid until then. ^SQLite will then
49064923
** manage the lifetime of its private copy.
49074924
**
4908
-** ^The sixth argument to sqlite3_bind_text64() must be one of
4909
-** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
4910
-** to specify the encoding of the text in the third parameter. If
4911
-** the sixth argument to sqlite3_bind_text64() is not one of the
4925
+** ^The sixth argument (the E argument)
4926
+** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of
4927
+** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
4928
+** or [SQLITE_UTF16LE] to specify the encoding of the text in the
4929
+** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the
4930
+** string argument is both UTF-8 encoded and is zero-terminated. In other
4931
+** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at
4932
+** least N+1 bytes and that the Z&#91;N&#93; byte is zero. If
4933
+** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the
49124934
** allowed values shown above, or if the text encoding is different
49134935
** from the encoding specified by the sixth parameter, then the behavior
49144936
** is undefined.
49154937
**
49164938
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
@@ -5773,17 +5795,63 @@
57735795
/*
57745796
** CAPI3REF: Text Encodings
57755797
**
57765798
** These constants define integer codes that represent the various
57775799
** text encodings supported by SQLite.
5800
+**
5801
+** <dl>
5802
+** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd>
5803
+**
5804
+** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16
5805
+** with each code point being expressed "little endian" - the least significant
5806
+** byte first. This is the usual encoding, for example on Windows.</dd>
5807
+**
5808
+** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16
5809
+** with each code point being expressed "big endian" - the most significant
5810
+** byte first. This encoding is less common, but is still sometimes seen,
5811
+** specially on older systems.
5812
+**
5813
+** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16
5814
+** with each code point being expressed either little endian or as big
5815
+** endian, according to the native endianness of the host computer.
5816
+**
5817
+** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used
5818
+** to declare the preferred text for [application-defined SQL functions]
5819
+** created using [sqlite3_create_function()] and similar. If the preferred
5820
+** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep
5821
+** parameter) is SQLITE_ANY, that indicates that the function does not have
5822
+** a preference regarding the text encoding of its parameters and can take
5823
+** any text encoding that the SQLite core find convenient to supply. This
5824
+** option is deprecated. Please do not use it in new applications.
5825
+**
5826
+** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding
5827
+** value may be used as the 3rd parameter (the eTextRep parameter) to
5828
+** [sqlite3_create_collation()] and similar. This encoding value means
5829
+** that the application-defined collating sequence created expects its
5830
+** input strings to be in UTF16 in native byte order, and that the start
5831
+** of the strings must be aligned to a 2-byte boundary.
5832
+**
5833
+** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be
5834
+** used to specify the text encoding to strings input to [sqlite3_result_text64()]
5835
+** and [sqlite3_bind_text64()]. It means that the input string (call it "z")
5836
+** is UTF-8 encoded and that it is zero-terminated. If the length parameter
5837
+** (call it "n") is non-negative, this encoding option means that the caller
5838
+** guarantees that z array contains at least n+1 bytes and that the z&#91;n&#93;
5839
+** byte has a value of zero.
5840
+** This option gives the same output as SQLITE_UTF8, but can be more efficient
5841
+** by avoiding the need to make a copy of the input string, in some cases.
5842
+** However, if z is allocated to hold fewer than n+1 bytes or if the
5843
+** z&#91;n&#93; byte is not zero, undefined behavior may result.
5844
+** </dl>
57785845
*/
57795846
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
57805847
#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
57815848
#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
57825849
#define SQLITE_UTF16 4 /* Use native byte order */
57835850
#define SQLITE_ANY 5 /* Deprecated */
57845851
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
5852
+#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */
57855853
57865854
/*
57875855
** CAPI3REF: Function Flags
57885856
**
57895857
** These constants may be ORed together with the
@@ -6285,14 +6353,18 @@
62856353
** use for client data is to provide a mechanism for wrapper libraries
62866354
** to store additional information about an SQLite database connection.
62876355
**
62886356
** There is no limit (other than available memory) on the number of different
62896357
** client data pointers (with different names) that can be attached to a
6290
-** single database connection. However, the implementation is optimized
6291
-** for the case of having only one or two different client data names.
6292
-** Applications and wrapper libraries are discouraged from using more than
6293
-** one client data name each.
6358
+** single database connection. However, the current implementation stores
6359
+** the content on a linked list. Insert and retrieval performance will
6360
+** be proportional to the number of entries. The design use case, and
6361
+** the use case for which the implementation is optimized, is
6362
+** that an application will store only small number of client data names,
6363
+** typically just one or two. This interface is not intended to be a
6364
+** generalized key/value store for thousands or millions of keys. It
6365
+** will work for that, but performance might be disappointing.
62946366
**
62956367
** There is no way to enumerate the client data pointers
62966368
** associated with a database connection. The N parameter can be thought
62976369
** of as a secret key such that only code that knows the secret key is able
62986370
** to access the associated data.
@@ -6396,14 +6468,18 @@
63966468
** ^The sqlite3_result_text(), sqlite3_result_text16(),
63976469
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
63986470
** set the return value of the application-defined function to be
63996471
** a text string which is represented as UTF-8, UTF-16 native byte order,
64006472
** UTF-16 little endian, or UTF-16 big endian, respectively.
6401
-** ^The sqlite3_result_text64() interface sets the return value of an
6473
+** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an
64026474
** application-defined function to be a text string in an encoding
6403
-** specified by the fifth (and last) parameter, which must be one
6404
-** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
6475
+** specified the E parameter, which must be one
6476
+** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
6477
+** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that
6478
+** the result text is both UTF-8 and zero-terminated. In other words,
6479
+** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that
6480
+** the Z&#91;N&#93; is zero.
64056481
** ^SQLite takes the text result from the application from
64066482
** the 2nd parameter of the sqlite3_result_text* interfaces.
64076483
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
64086484
** other than sqlite3_result_text64() is negative, then SQLite computes
64096485
** the string length itself by searching the 2nd parameter for the first
@@ -6486,11 +6562,11 @@
64866562
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
64876563
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
64886564
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
64896565
SQLITE_API void sqlite3_result_null(sqlite3_context*);
64906566
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
6491
-SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
6567
+SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n,
64926568
void(*)(void*), unsigned char encoding);
64936569
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
64946570
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
64956571
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
64966572
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
@@ -7425,22 +7501,22 @@
74257501
** ^This interface loads an SQLite extension library from the named file.
74267502
**
74277503
** ^The sqlite3_load_extension() interface attempts to load an
74287504
** [SQLite extension] library contained in the file zFile. If
74297505
** the file cannot be loaded directly, attempts are made to load
7430
-** with various operating-system specific extensions added.
7506
+** with various operating-system specific filename extensions added.
74317507
** So for example, if "samplelib" cannot be loaded, then names like
74327508
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
74337509
** be tried also.
74347510
**
74357511
** ^The entry point is zProc.
74367512
** ^(zProc may be 0, in which case SQLite will try to come up with an
74377513
** entry point name on its own. It first tries "sqlite3_extension_init".
7438
-** If that does not work, it constructs a name "sqlite3_X_init" where
7439
-** X consists of the lower-case equivalent of all ASCII alphabetic
7440
-** characters in the filename from the last "/" to the first following
7441
-** "." and omitting any initial "lib".)^
7514
+** If that does not work, it tries names of the form "sqlite3_X_init"
7515
+** where X consists of the lower-case equivalent of all ASCII alphabetic
7516
+** characters or all ASCII alphanumeric characters in the filename from
7517
+** the last "/" to the first following "." and omitting any initial "lib".)^
74427518
** ^The sqlite3_load_extension() interface returns
74437519
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
74447520
** ^If an error occurs and pzErrMsg is not 0, then the
74457521
** [sqlite3_load_extension()] interface shall attempt to
74467522
** fill *pzErrMsg with error message text stored in memory
@@ -11174,23 +11250,45 @@
1117411250
#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
1117511251
1117611252
/*
1117711253
** CAPI3REF: Bind array values to the CARRAY table-valued function
1117811254
**
11179
-** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
11180
-** one of the first argument of the [carray() table-valued function]. The
11181
-** S parameter is a pointer to the [prepared statement] that uses the carray()
11182
-** functions. I is the parameter index to be bound. P is a pointer to the
11183
-** array to be bound, and N is the number of eements in the array. The
11184
-** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
11185
-** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
11186
-** indicate the datatype of the array being bound. The X argument is not a
11187
-** NULL pointer, then SQLite will invoke the function X on the P parameter
11188
-** after it has finished using P, even if the call to
11189
-** sqlite3_carray_bind() fails. The special-case finalizer
11190
-** SQLITE_TRANSIENT has no effect here.
11255
+** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
11256
+** parameter that is the first argument of the [carray() table-valued function].
11257
+** The S parameter is a pointer to the [prepared statement] that uses the carray()
11258
+** functions. I is the parameter index to be bound. I must be the index of the
11259
+** parameter that is the first argument to the carray() table-valued function.
11260
+** P is a pointer to the array to be bound, and N is the number of elements in
11261
+** the array. The F argument is one of constants [SQLITE_CARRAY_INT32],
11262
+** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
11263
+** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
11264
+**
11265
+** If the X argument is not a NULL pointer or one of the special
11266
+** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
11267
+** the function X with argument D when it is finished using the data in P.
11268
+** The call to X(D) is a destructor for the array P. The destructor X(D)
11269
+** is invoked even if the call to sqlite3_carray_bind() fails. If the X
11270
+** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
11271
+** that the data static and the destructor is never invoked. If the X
11272
+** parameter is the special-case value [SQLITE_TRANSIENT], then
11273
+** sqlite3_carray_bind_v2() makes its own private copy of the data prior
11274
+** to returning and never invokes the destructor X.
11275
+**
11276
+** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2()
11277
+** with a D parameter set to P. In other words,
11278
+** sqlite3_carray_bind(S,I,P,N,F,X) is same as
11279
+** sqlite3_carray_bind(S,I,P,N,F,X,P).
1119111280
*/
11281
+SQLITE_API int sqlite3_carray_bind_v2(
11282
+ sqlite3_stmt *pStmt, /* Statement to be bound */
11283
+ int i, /* Parameter index */
11284
+ void *aData, /* Pointer to array data */
11285
+ int nData, /* Number of data elements */
11286
+ int mFlags, /* CARRAY flags */
11287
+ void (*xDel)(void*), /* Destructor for aData */
11288
+ void *pDel /* Optional argument to xDel() */
11289
+);
1119211290
SQLITE_API int sqlite3_carray_bind(
1119311291
sqlite3_stmt *pStmt, /* Statement to be bound */
1119411292
int i, /* Parameter index */
1119511293
void *aData, /* Pointer to array data */
1119611294
int nData, /* Number of data elements */
1119711295
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,14 +146,14 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.52.0"
150 #define SQLITE_VERSION_NUMBER 3052000
151 #define SQLITE_SOURCE_ID "2025-12-11 23:24:05 01409738afc2c0d5bdaa248ffb508aa5f36a66390f6b8e4834734529ee8ed2fa"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2025-12-11T23:24:05.667Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
@@ -4431,16 +4431,32 @@
4431 ** compiles to see if some SQL syntax is well-formed, without generating
4432 ** messages on the global error log when it is not. If the test compile
4433 ** fails, the sqlite3_prepare_v3() call returns the same error indications
4434 ** with or without this flag; it just omits the call to [sqlite3_log()] that
4435 ** logs the error.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4436 ** </dl>
4437 */
4438 #define SQLITE_PREPARE_PERSISTENT 0x01
4439 #define SQLITE_PREPARE_NORMALIZE 0x02
4440 #define SQLITE_PREPARE_NO_VTAB 0x04
4441 #define SQLITE_PREPARE_DONT_LOG 0x10
 
4442
4443 /*
4444 ** CAPI3REF: Compiling An SQL Statement
4445 ** KEYWORDS: {SQL statement compiler}
4446 ** METHOD: sqlite3
@@ -4450,12 +4466,13 @@
4450 ** program using one of these routines. Or, in other words, these routines
4451 ** are constructors for the [prepared statement] object.
4452 **
4453 ** The preferred routine to use is [sqlite3_prepare_v2()]. The
4454 ** [sqlite3_prepare()] interface is legacy and should be avoided.
4455 ** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
4456 ** for special purposes.
 
4457 **
4458 ** The use of the UTF-8 interfaces is preferred, as SQLite currently
4459 ** does all parsing using UTF-8. The UTF-16 interfaces are provided
4460 ** as a convenience. The UTF-16 interfaces work by converting the
4461 ** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -4856,12 +4873,12 @@
4856 ** it should be a pointer to well-formed UTF8 text.
4857 ** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
4858 ** it should be a pointer to well-formed UTF16 text.
4859 ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
4860 ** it should be a pointer to a well-formed unicode string that is
4861 ** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
4862 ** otherwise.
4863 **
4864 ** [[byte-order determination rules]] ^The byte-order of
4865 ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
4866 ** found in the first character, which is removed, or in the absence of a BOM
4867 ** the byte order is the native byte order of the host
@@ -4903,14 +4920,19 @@
4903 ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4904 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
4905 ** object and pointer to it must remain valid until then. ^SQLite will then
4906 ** manage the lifetime of its private copy.
4907 **
4908 ** ^The sixth argument to sqlite3_bind_text64() must be one of
4909 ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
4910 ** to specify the encoding of the text in the third parameter. If
4911 ** the sixth argument to sqlite3_bind_text64() is not one of the
 
 
 
 
 
4912 ** allowed values shown above, or if the text encoding is different
4913 ** from the encoding specified by the sixth parameter, then the behavior
4914 ** is undefined.
4915 **
4916 ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
@@ -5773,17 +5795,63 @@
5773 /*
5774 ** CAPI3REF: Text Encodings
5775 **
5776 ** These constants define integer codes that represent the various
5777 ** text encodings supported by SQLite.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5778 */
5779 #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
5780 #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
5781 #define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
5782 #define SQLITE_UTF16 4 /* Use native byte order */
5783 #define SQLITE_ANY 5 /* Deprecated */
5784 #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
 
5785
5786 /*
5787 ** CAPI3REF: Function Flags
5788 **
5789 ** These constants may be ORed together with the
@@ -6285,14 +6353,18 @@
6285 ** use for client data is to provide a mechanism for wrapper libraries
6286 ** to store additional information about an SQLite database connection.
6287 **
6288 ** There is no limit (other than available memory) on the number of different
6289 ** client data pointers (with different names) that can be attached to a
6290 ** single database connection. However, the implementation is optimized
6291 ** for the case of having only one or two different client data names.
6292 ** Applications and wrapper libraries are discouraged from using more than
6293 ** one client data name each.
 
 
 
 
6294 **
6295 ** There is no way to enumerate the client data pointers
6296 ** associated with a database connection. The N parameter can be thought
6297 ** of as a secret key such that only code that knows the secret key is able
6298 ** to access the associated data.
@@ -6396,14 +6468,18 @@
6396 ** ^The sqlite3_result_text(), sqlite3_result_text16(),
6397 ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
6398 ** set the return value of the application-defined function to be
6399 ** a text string which is represented as UTF-8, UTF-16 native byte order,
6400 ** UTF-16 little endian, or UTF-16 big endian, respectively.
6401 ** ^The sqlite3_result_text64() interface sets the return value of an
6402 ** application-defined function to be a text string in an encoding
6403 ** specified by the fifth (and last) parameter, which must be one
6404 ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
 
 
 
 
6405 ** ^SQLite takes the text result from the application from
6406 ** the 2nd parameter of the sqlite3_result_text* interfaces.
6407 ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
6408 ** other than sqlite3_result_text64() is negative, then SQLite computes
6409 ** the string length itself by searching the 2nd parameter for the first
@@ -6486,11 +6562,11 @@
6486 SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
6487 SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
6488 SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
6489 SQLITE_API void sqlite3_result_null(sqlite3_context*);
6490 SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
6491 SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
6492 void(*)(void*), unsigned char encoding);
6493 SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
6494 SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
6495 SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
6496 SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
@@ -7425,22 +7501,22 @@
7425 ** ^This interface loads an SQLite extension library from the named file.
7426 **
7427 ** ^The sqlite3_load_extension() interface attempts to load an
7428 ** [SQLite extension] library contained in the file zFile. If
7429 ** the file cannot be loaded directly, attempts are made to load
7430 ** with various operating-system specific extensions added.
7431 ** So for example, if "samplelib" cannot be loaded, then names like
7432 ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
7433 ** be tried also.
7434 **
7435 ** ^The entry point is zProc.
7436 ** ^(zProc may be 0, in which case SQLite will try to come up with an
7437 ** entry point name on its own. It first tries "sqlite3_extension_init".
7438 ** If that does not work, it constructs a name "sqlite3_X_init" where
7439 ** X consists of the lower-case equivalent of all ASCII alphabetic
7440 ** characters in the filename from the last "/" to the first following
7441 ** "." and omitting any initial "lib".)^
7442 ** ^The sqlite3_load_extension() interface returns
7443 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
7444 ** ^If an error occurs and pzErrMsg is not 0, then the
7445 ** [sqlite3_load_extension()] interface shall attempt to
7446 ** fill *pzErrMsg with error message text stored in memory
@@ -11174,23 +11250,45 @@
11174 #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
11175
11176 /*
11177 ** CAPI3REF: Bind array values to the CARRAY table-valued function
11178 **
11179 ** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
11180 ** one of the first argument of the [carray() table-valued function]. The
11181 ** S parameter is a pointer to the [prepared statement] that uses the carray()
11182 ** functions. I is the parameter index to be bound. P is a pointer to the
11183 ** array to be bound, and N is the number of eements in the array. The
11184 ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
11185 ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
11186 ** indicate the datatype of the array being bound. The X argument is not a
11187 ** NULL pointer, then SQLite will invoke the function X on the P parameter
11188 ** after it has finished using P, even if the call to
11189 ** sqlite3_carray_bind() fails. The special-case finalizer
11190 ** SQLITE_TRANSIENT has no effect here.
 
 
 
 
 
 
 
 
 
 
 
 
 
11191 */
 
 
 
 
 
 
 
 
 
11192 SQLITE_API int sqlite3_carray_bind(
11193 sqlite3_stmt *pStmt, /* Statement to be bound */
11194 int i, /* Parameter index */
11195 void *aData, /* Pointer to array data */
11196 int nData, /* Number of data elements */
11197
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,14 +146,14 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.52.0"
150 #define SQLITE_VERSION_NUMBER 3052000
151 #define SQLITE_SOURCE_ID "2026-02-04 20:51:27 c476d956d0bd3065cf894de6f9d393b999ff7d2268a35f01a6d88804789ab58f"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2026-02-04T20:51:27.822Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
@@ -4431,16 +4431,32 @@
4431 ** compiles to see if some SQL syntax is well-formed, without generating
4432 ** messages on the global error log when it is not. If the test compile
4433 ** fails, the sqlite3_prepare_v3() call returns the same error indications
4434 ** with or without this flag; it just omits the call to [sqlite3_log()] that
4435 ** logs the error.
4436 **
4437 ** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
4438 ** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
4439 ** the SQL statement is part of a database schema. This makes a difference
4440 ** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
4441 ** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
4442 ** SQL functions may not be called unless they are tagged with
4443 ** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
4444 ** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
4445 ** when preparing SQL that is derived from parts of the database
4446 ** schema. In particular, virtual table implementations that
4447 ** run SQL statements based on the arguments to their CREATE VIRTUAL
4448 ** TABLE statement should use [sqlite3_prepare_v3()] and set the
4449 ** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
4450 ** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
4451 ** </dl>
4452 */
4453 #define SQLITE_PREPARE_PERSISTENT 0x01
4454 #define SQLITE_PREPARE_NORMALIZE 0x02
4455 #define SQLITE_PREPARE_NO_VTAB 0x04
4456 #define SQLITE_PREPARE_DONT_LOG 0x10
4457 #define SQLITE_PREPARE_FROM_DDL 0x20
4458
4459 /*
4460 ** CAPI3REF: Compiling An SQL Statement
4461 ** KEYWORDS: {SQL statement compiler}
4462 ** METHOD: sqlite3
@@ -4450,12 +4466,13 @@
4466 ** program using one of these routines. Or, in other words, these routines
4467 ** are constructors for the [prepared statement] object.
4468 **
4469 ** The preferred routine to use is [sqlite3_prepare_v2()]. The
4470 ** [sqlite3_prepare()] interface is legacy and should be avoided.
4471 ** [sqlite3_prepare_v3()] has an extra
4472 ** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times
4473 ** needed for special purpose or to pass along security restrictions.
4474 **
4475 ** The use of the UTF-8 interfaces is preferred, as SQLite currently
4476 ** does all parsing using UTF-8. The UTF-16 interfaces are provided
4477 ** as a convenience. The UTF-16 interfaces work by converting the
4478 ** input text into UTF-8, then invoking the corresponding UTF-8 interface.
@@ -4856,12 +4873,12 @@
4873 ** it should be a pointer to well-formed UTF8 text.
4874 ** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
4875 ** it should be a pointer to well-formed UTF16 text.
4876 ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
4877 ** it should be a pointer to a well-formed unicode string that is
4878 ** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT,
4879 ** or UTF16 otherwise.
4880 **
4881 ** [[byte-order determination rules]] ^The byte-order of
4882 ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
4883 ** found in the first character, which is removed, or in the absence of a BOM
4884 ** the byte order is the native byte order of the host
@@ -4903,14 +4920,19 @@
4920 ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
4921 ** object is to be copied prior to the return from sqlite3_bind_*(). ^The
4922 ** object and pointer to it must remain valid until then. ^SQLite will then
4923 ** manage the lifetime of its private copy.
4924 **
4925 ** ^The sixth argument (the E argument)
4926 ** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of
4927 ** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
4928 ** or [SQLITE_UTF16LE] to specify the encoding of the text in the
4929 ** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the
4930 ** string argument is both UTF-8 encoded and is zero-terminated. In other
4931 ** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at
4932 ** least N+1 bytes and that the Z&#91;N&#93; byte is zero. If
4933 ** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the
4934 ** allowed values shown above, or if the text encoding is different
4935 ** from the encoding specified by the sixth parameter, then the behavior
4936 ** is undefined.
4937 **
4938 ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
@@ -5773,17 +5795,63 @@
5795 /*
5796 ** CAPI3REF: Text Encodings
5797 **
5798 ** These constants define integer codes that represent the various
5799 ** text encodings supported by SQLite.
5800 **
5801 ** <dl>
5802 ** [[SQLITE_UTF8]] <dt>SQLITE_UTF8</dt><dd>Text is encoding as UTF-8</dd>
5803 **
5804 ** [[SQLITE_UTF16LE]] <dt>SQLITE_UTF16LE</dt><dd>Text is encoding as UTF-16
5805 ** with each code point being expressed "little endian" - the least significant
5806 ** byte first. This is the usual encoding, for example on Windows.</dd>
5807 **
5808 ** [[SQLITE_UTF16BE]] <dt>SQLITE_UTF16BE</dt><dd>Text is encoding as UTF-16
5809 ** with each code point being expressed "big endian" - the most significant
5810 ** byte first. This encoding is less common, but is still sometimes seen,
5811 ** specially on older systems.
5812 **
5813 ** [[SQLITE_UTF16]] <dt>SQLITE_UTF16</dt><dd>Text is encoding as UTF-16
5814 ** with each code point being expressed either little endian or as big
5815 ** endian, according to the native endianness of the host computer.
5816 **
5817 ** [[SQLITE_ANY]] <dt>SQLITE_ANY</dt><dd>This encoding value may only be used
5818 ** to declare the preferred text for [application-defined SQL functions]
5819 ** created using [sqlite3_create_function()] and similar. If the preferred
5820 ** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep
5821 ** parameter) is SQLITE_ANY, that indicates that the function does not have
5822 ** a preference regarding the text encoding of its parameters and can take
5823 ** any text encoding that the SQLite core find convenient to supply. This
5824 ** option is deprecated. Please do not use it in new applications.
5825 **
5826 ** [[SQLITE_UTF16_ALIGNED]] <dt>SQLITE_UTF16_ALIGNED</dt><dd>This encoding
5827 ** value may be used as the 3rd parameter (the eTextRep parameter) to
5828 ** [sqlite3_create_collation()] and similar. This encoding value means
5829 ** that the application-defined collating sequence created expects its
5830 ** input strings to be in UTF16 in native byte order, and that the start
5831 ** of the strings must be aligned to a 2-byte boundary.
5832 **
5833 ** [[SQLITE_UTF8_ZT]] <dt>SQLITE_UTF8_ZT</dt><dd>This option can only be
5834 ** used to specify the text encoding to strings input to [sqlite3_result_text64()]
5835 ** and [sqlite3_bind_text64()]. It means that the input string (call it "z")
5836 ** is UTF-8 encoded and that it is zero-terminated. If the length parameter
5837 ** (call it "n") is non-negative, this encoding option means that the caller
5838 ** guarantees that z array contains at least n+1 bytes and that the z&#91;n&#93;
5839 ** byte has a value of zero.
5840 ** This option gives the same output as SQLITE_UTF8, but can be more efficient
5841 ** by avoiding the need to make a copy of the input string, in some cases.
5842 ** However, if z is allocated to hold fewer than n+1 bytes or if the
5843 ** z&#91;n&#93; byte is not zero, undefined behavior may result.
5844 ** </dl>
5845 */
5846 #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
5847 #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
5848 #define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
5849 #define SQLITE_UTF16 4 /* Use native byte order */
5850 #define SQLITE_ANY 5 /* Deprecated */
5851 #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
5852 #define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */
5853
5854 /*
5855 ** CAPI3REF: Function Flags
5856 **
5857 ** These constants may be ORed together with the
@@ -6285,14 +6353,18 @@
6353 ** use for client data is to provide a mechanism for wrapper libraries
6354 ** to store additional information about an SQLite database connection.
6355 **
6356 ** There is no limit (other than available memory) on the number of different
6357 ** client data pointers (with different names) that can be attached to a
6358 ** single database connection. However, the current implementation stores
6359 ** the content on a linked list. Insert and retrieval performance will
6360 ** be proportional to the number of entries. The design use case, and
6361 ** the use case for which the implementation is optimized, is
6362 ** that an application will store only small number of client data names,
6363 ** typically just one or two. This interface is not intended to be a
6364 ** generalized key/value store for thousands or millions of keys. It
6365 ** will work for that, but performance might be disappointing.
6366 **
6367 ** There is no way to enumerate the client data pointers
6368 ** associated with a database connection. The N parameter can be thought
6369 ** of as a secret key such that only code that knows the secret key is able
6370 ** to access the associated data.
@@ -6396,14 +6468,18 @@
6468 ** ^The sqlite3_result_text(), sqlite3_result_text16(),
6469 ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
6470 ** set the return value of the application-defined function to be
6471 ** a text string which is represented as UTF-8, UTF-16 native byte order,
6472 ** UTF-16 little endian, or UTF-16 big endian, respectively.
6473 ** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an
6474 ** application-defined function to be a text string in an encoding
6475 ** specified the E parameter, which must be one
6476 ** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
6477 ** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that
6478 ** the result text is both UTF-8 and zero-terminated. In other words,
6479 ** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that
6480 ** the Z&#91;N&#93; is zero.
6481 ** ^SQLite takes the text result from the application from
6482 ** the 2nd parameter of the sqlite3_result_text* interfaces.
6483 ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
6484 ** other than sqlite3_result_text64() is negative, then SQLite computes
6485 ** the string length itself by searching the 2nd parameter for the first
@@ -6486,11 +6562,11 @@
6562 SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
6563 SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
6564 SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
6565 SQLITE_API void sqlite3_result_null(sqlite3_context*);
6566 SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
6567 SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n,
6568 void(*)(void*), unsigned char encoding);
6569 SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
6570 SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
6571 SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
6572 SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
@@ -7425,22 +7501,22 @@
7501 ** ^This interface loads an SQLite extension library from the named file.
7502 **
7503 ** ^The sqlite3_load_extension() interface attempts to load an
7504 ** [SQLite extension] library contained in the file zFile. If
7505 ** the file cannot be loaded directly, attempts are made to load
7506 ** with various operating-system specific filename extensions added.
7507 ** So for example, if "samplelib" cannot be loaded, then names like
7508 ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
7509 ** be tried also.
7510 **
7511 ** ^The entry point is zProc.
7512 ** ^(zProc may be 0, in which case SQLite will try to come up with an
7513 ** entry point name on its own. It first tries "sqlite3_extension_init".
7514 ** If that does not work, it tries names of the form "sqlite3_X_init"
7515 ** where X consists of the lower-case equivalent of all ASCII alphabetic
7516 ** characters or all ASCII alphanumeric characters in the filename from
7517 ** the last "/" to the first following "." and omitting any initial "lib".)^
7518 ** ^The sqlite3_load_extension() interface returns
7519 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
7520 ** ^If an error occurs and pzErrMsg is not 0, then the
7521 ** [sqlite3_load_extension()] interface shall attempt to
7522 ** fill *pzErrMsg with error message text stored in memory
@@ -11174,23 +11250,45 @@
11250 #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
11251
11252 /*
11253 ** CAPI3REF: Bind array values to the CARRAY table-valued function
11254 **
11255 ** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
11256 ** parameter that is the first argument of the [carray() table-valued function].
11257 ** The S parameter is a pointer to the [prepared statement] that uses the carray()
11258 ** functions. I is the parameter index to be bound. I must be the index of the
11259 ** parameter that is the first argument to the carray() table-valued function.
11260 ** P is a pointer to the array to be bound, and N is the number of elements in
11261 ** the array. The F argument is one of constants [SQLITE_CARRAY_INT32],
11262 ** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
11263 ** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
11264 **
11265 ** If the X argument is not a NULL pointer or one of the special
11266 ** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
11267 ** the function X with argument D when it is finished using the data in P.
11268 ** The call to X(D) is a destructor for the array P. The destructor X(D)
11269 ** is invoked even if the call to sqlite3_carray_bind() fails. If the X
11270 ** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
11271 ** that the data static and the destructor is never invoked. If the X
11272 ** parameter is the special-case value [SQLITE_TRANSIENT], then
11273 ** sqlite3_carray_bind_v2() makes its own private copy of the data prior
11274 ** to returning and never invokes the destructor X.
11275 **
11276 ** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2()
11277 ** with a D parameter set to P. In other words,
11278 ** sqlite3_carray_bind(S,I,P,N,F,X) is same as
11279 ** sqlite3_carray_bind(S,I,P,N,F,X,P).
11280 */
11281 SQLITE_API int sqlite3_carray_bind_v2(
11282 sqlite3_stmt *pStmt, /* Statement to be bound */
11283 int i, /* Parameter index */
11284 void *aData, /* Pointer to array data */
11285 int nData, /* Number of data elements */
11286 int mFlags, /* CARRAY flags */
11287 void (*xDel)(void*), /* Destructor for aData */
11288 void *pDel /* Optional argument to xDel() */
11289 );
11290 SQLITE_API int sqlite3_carray_bind(
11291 sqlite3_stmt *pStmt, /* Statement to be bound */
11292 int i, /* Parameter index */
11293 void *aData, /* Pointer to array data */
11294 int nData, /* Number of data elements */
11295
--- src/accordion.js
+++ src/accordion.js
@@ -22,10 +22,27 @@
2222
** calculated. That's why setting `maxHeight' to `scrollHeight' is considered
2323
** "good enough" only during animation, but cleared afterwards.
2424
**
2525
** https://fossil-scm.org/forum/forumpost/66d7075f40
2626
** https://fossil-scm.org/home/timeline?r=accordion-fix
27
+**
28
+** To work around the missing support for `overflow-y: clip', this script uses a
29
+** fallback and sets `overflow-y: hidden' during the accordion panel animations.
30
+** That's because if `overflow-y: hidden' is set statically from the stylesheet,
31
+** the shadow of the selected or current timeline entries in the context section
32
+** of `/info' pages is still truncated on the right (which is strange, as that's
33
+** not the "y" direction) in all major browsers. Otherwise, the stylesheet might
34
+** define the fallback using the `@supports(…)' at-rule:
35
+**
36
+** .accordion_panel {
37
+** overflow-y: hidden;
38
+** }
39
+** @supports(overflow-y: clip) {
40
+** .accordion_panel {
41
+** overflow-y: clip;
42
+** }
43
+** }
2744
*/
2845
var acc_svgdata = ["data:image/svg+xml,"+
2946
"%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E"+
3047
"%3Cpath style='fill:black;opacity:0' d='M16,16H0V0h16v16z'/%3E"+
3148
"%3Cpath style='fill:rgb(240,240,240)' d='M14,14H2V2h12v12z'/%3E"+
@@ -52,15 +69,21 @@
5269
var x = this.nextElementSibling;
5370
if( this.classList.contains("accordion_closed") ){
5471
x.style.maxHeight = x.scrollHeight + "px";
5572
setTimeout(function(){
5673
x.style.maxHeight = "";
74
+ if( !window.CSS || !window.CSS.supports("overflow: clip") ){
75
+ x.style.overflowY = "";
76
+ }
5777
},250); // default.css: .accordion_panel { transition-duration }
5878
}else{
5979
x.style.maxHeight = x.scrollHeight + "px";
80
+ if( !window.CSS || !window.CSS.supports("overflow: clip") ){
81
+ x.style.overflowY = "hidden";
82
+ }
6083
setTimeout(function(){
6184
x.style.maxHeight = "0";
6285
},1);
6386
}
6487
this.classList.toggle("accordion_closed");
6588
});
6689
}
6790
--- src/accordion.js
+++ src/accordion.js
@@ -22,10 +22,27 @@
22 ** calculated. That's why setting `maxHeight' to `scrollHeight' is considered
23 ** "good enough" only during animation, but cleared afterwards.
24 **
25 ** https://fossil-scm.org/forum/forumpost/66d7075f40
26 ** https://fossil-scm.org/home/timeline?r=accordion-fix
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27 */
28 var acc_svgdata = ["data:image/svg+xml,"+
29 "%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E"+
30 "%3Cpath style='fill:black;opacity:0' d='M16,16H0V0h16v16z'/%3E"+
31 "%3Cpath style='fill:rgb(240,240,240)' d='M14,14H2V2h12v12z'/%3E"+
@@ -52,15 +69,21 @@
52 var x = this.nextElementSibling;
53 if( this.classList.contains("accordion_closed") ){
54 x.style.maxHeight = x.scrollHeight + "px";
55 setTimeout(function(){
56 x.style.maxHeight = "";
 
 
 
57 },250); // default.css: .accordion_panel { transition-duration }
58 }else{
59 x.style.maxHeight = x.scrollHeight + "px";
 
 
 
60 setTimeout(function(){
61 x.style.maxHeight = "0";
62 },1);
63 }
64 this.classList.toggle("accordion_closed");
65 });
66 }
67
--- src/accordion.js
+++ src/accordion.js
@@ -22,10 +22,27 @@
22 ** calculated. That's why setting `maxHeight' to `scrollHeight' is considered
23 ** "good enough" only during animation, but cleared afterwards.
24 **
25 ** https://fossil-scm.org/forum/forumpost/66d7075f40
26 ** https://fossil-scm.org/home/timeline?r=accordion-fix
27 **
28 ** To work around the missing support for `overflow-y: clip', this script uses a
29 ** fallback and sets `overflow-y: hidden' during the accordion panel animations.
30 ** That's because if `overflow-y: hidden' is set statically from the stylesheet,
31 ** the shadow of the selected or current timeline entries in the context section
32 ** of `/info' pages is still truncated on the right (which is strange, as that's
33 ** not the "y" direction) in all major browsers. Otherwise, the stylesheet might
34 ** define the fallback using the `@supports(…)' at-rule:
35 **
36 ** .accordion_panel {
37 ** overflow-y: hidden;
38 ** }
39 ** @supports(overflow-y: clip) {
40 ** .accordion_panel {
41 ** overflow-y: clip;
42 ** }
43 ** }
44 */
45 var acc_svgdata = ["data:image/svg+xml,"+
46 "%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E"+
47 "%3Cpath style='fill:black;opacity:0' d='M16,16H0V0h16v16z'/%3E"+
48 "%3Cpath style='fill:rgb(240,240,240)' d='M14,14H2V2h12v12z'/%3E"+
@@ -52,15 +69,21 @@
69 var x = this.nextElementSibling;
70 if( this.classList.contains("accordion_closed") ){
71 x.style.maxHeight = x.scrollHeight + "px";
72 setTimeout(function(){
73 x.style.maxHeight = "";
74 if( !window.CSS || !window.CSS.supports("overflow: clip") ){
75 x.style.overflowY = "";
76 }
77 },250); // default.css: .accordion_panel { transition-duration }
78 }else{
79 x.style.maxHeight = x.scrollHeight + "px";
80 if( !window.CSS || !window.CSS.supports("overflow: clip") ){
81 x.style.overflowY = "hidden";
82 }
83 setTimeout(function(){
84 x.style.maxHeight = "0";
85 },1);
86 }
87 this.classList.toggle("accordion_closed");
88 });
89 }
90
+2 -2
--- src/add.c
+++ src/add.c
@@ -353,11 +353,11 @@
353353
** for files to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore
354354
** option does not appear on the command line then the "ignore-glob" setting
355355
** is used. If the --clean option does not appear on the command line then
356356
** the "clean-glob" setting is used.
357357
**
358
-** When attempting to explicitly add files on the commandline, and if those
358
+** When attempting to explicitly add files on the command line, and if those
359359
** match "ignore-glob", a confirmation is asked first. This can be prevented
360360
** using the -f|--force option.
361361
**
362362
** The --case-sensitive option determines whether or not filenames should
363363
** be treated case sensitive or not. If the option is not given, the default
@@ -476,11 +476,11 @@
476476
}
477477
glob_free(pIgnore);
478478
glob_free(pClean);
479479
480480
/** Check for Windows-reserved names and warn or exit, as
481
- ** appopriate. Note that the 'add' internal machinery already
481
+ ** appropriate. Note that the 'add' internal machinery already
482482
** _silently_ skips over any names for which
483483
** file_is_reserved_name() returns true or which is in the
484484
** fossil_reserved_name() list. We do not need to warn for those,
485485
** as they're outright verboten. */
486486
if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
487487
--- src/add.c
+++ src/add.c
@@ -353,11 +353,11 @@
353 ** for files to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore
354 ** option does not appear on the command line then the "ignore-glob" setting
355 ** is used. If the --clean option does not appear on the command line then
356 ** the "clean-glob" setting is used.
357 **
358 ** When attempting to explicitly add files on the commandline, and if those
359 ** match "ignore-glob", a confirmation is asked first. This can be prevented
360 ** using the -f|--force option.
361 **
362 ** The --case-sensitive option determines whether or not filenames should
363 ** be treated case sensitive or not. If the option is not given, the default
@@ -476,11 +476,11 @@
476 }
477 glob_free(pIgnore);
478 glob_free(pClean);
479
480 /** Check for Windows-reserved names and warn or exit, as
481 ** appopriate. Note that the 'add' internal machinery already
482 ** _silently_ skips over any names for which
483 ** file_is_reserved_name() returns true or which is in the
484 ** fossil_reserved_name() list. We do not need to warn for those,
485 ** as they're outright verboten. */
486 if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
487
--- src/add.c
+++ src/add.c
@@ -353,11 +353,11 @@
353 ** for files to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore
354 ** option does not appear on the command line then the "ignore-glob" setting
355 ** is used. If the --clean option does not appear on the command line then
356 ** the "clean-glob" setting is used.
357 **
358 ** When attempting to explicitly add files on the command line, and if those
359 ** match "ignore-glob", a confirmation is asked first. This can be prevented
360 ** using the -f|--force option.
361 **
362 ** The --case-sensitive option determines whether or not filenames should
363 ** be treated case sensitive or not. If the option is not given, the default
@@ -476,11 +476,11 @@
476 }
477 glob_free(pIgnore);
478 glob_free(pClean);
479
480 /** Check for Windows-reserved names and warn or exit, as
481 ** appropriate. Note that the 'add' internal machinery already
482 ** _silently_ skips over any names for which
483 ** file_is_reserved_name() returns true or which is in the
484 ** fossil_reserved_name() list. We do not need to warn for those,
485 ** as they're outright verboten. */
486 if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
487
+1 -1
--- src/ajax.c
+++ src/ajax.c
@@ -395,11 +395,11 @@
395395
const AjaxRoute routes[] = {
396396
/* Keep these sorted by zName (for bsearch()) */
397397
{"preview-text", ajax_route_preview_text, 0, 1
398398
/* Note that this does not require write permissions in the repo.
399399
** It should arguably require write permissions but doing means
400
- ** that /chat does not work without checkin permissions:
400
+ ** that /chat does not work without check-in permissions:
401401
**
402402
** https://fossil-scm.org/forum/forumpost/ed4a762b3a557898
403403
**
404404
** This particular route is used by /fileedit and /chat, whereas
405405
** /wikiedit uses a simpler wiki-specific route.
406406
--- src/ajax.c
+++ src/ajax.c
@@ -395,11 +395,11 @@
395 const AjaxRoute routes[] = {
396 /* Keep these sorted by zName (for bsearch()) */
397 {"preview-text", ajax_route_preview_text, 0, 1
398 /* Note that this does not require write permissions in the repo.
399 ** It should arguably require write permissions but doing means
400 ** that /chat does not work without checkin permissions:
401 **
402 ** https://fossil-scm.org/forum/forumpost/ed4a762b3a557898
403 **
404 ** This particular route is used by /fileedit and /chat, whereas
405 ** /wikiedit uses a simpler wiki-specific route.
406
--- src/ajax.c
+++ src/ajax.c
@@ -395,11 +395,11 @@
395 const AjaxRoute routes[] = {
396 /* Keep these sorted by zName (for bsearch()) */
397 {"preview-text", ajax_route_preview_text, 0, 1
398 /* Note that this does not require write permissions in the repo.
399 ** It should arguably require write permissions but doing means
400 ** that /chat does not work without check-in permissions:
401 **
402 ** https://fossil-scm.org/forum/forumpost/ed4a762b3a557898
403 **
404 ** This particular route is used by /fileedit and /chat, whereas
405 ** /wikiedit uses a simpler wiki-specific route.
406
+7 -7
--- src/alerts.c
+++ src/alerts.c
@@ -664,11 +664,11 @@
664664
return p;
665665
}
666666
667667
/*
668668
** Scan the header of the email message in pMsg looking for the
669
-** (first) occurrance of zField. Fill pValue with the content of
669
+** (first) occurrence of zField. Fill pValue with the content of
670670
** that field.
671671
**
672672
** This routine initializes pValue. Any prior content of pValue is
673673
** discarded (leaked).
674674
**
@@ -710,11 +710,11 @@
710710
/*
711711
** Determine whether or not the input string is a valid email address.
712712
** Only look at character up to but not including the first \000 or
713713
** the first cTerm character, whichever comes first.
714714
**
715
-** Return the length of the email addresss string in bytes if the email
715
+** Return the length of the email address string in bytes if the email
716716
** address is valid. If the email address is misformed, return 0.
717717
*/
718718
int email_address_is_valid(const char *z, char cTerm){
719719
int i;
720720
int nAt = 0;
@@ -2259,11 +2259,11 @@
22592259
** Users visit this page to be delisted from email alerts.
22602260
**
22612261
** If a valid subscriber code is supplied in the name= query parameter,
22622262
** then that subscriber is delisted.
22632263
**
2264
-** Otherwise, If the users is logged in, then they are redirected
2264
+** Otherwise, if the users are logged in, then they are redirected
22652265
** to the /alerts page where they have an unsubscribe button.
22662266
**
22672267
** Non-logged-in users with no name= query parameter are invited to enter
22682268
** an email address to which will be sent the unsubscribe link that
22692269
** contains the correct subscriber code.
@@ -2606,11 +2606,11 @@
26062606
/*
26072607
** Compute a string that is appropriate for the EmailEvent.zPriors field
26082608
** for a particular forum post.
26092609
**
26102610
** This string is an encode list of sender names and rids for all ancestors
2611
-** of the fpdi post - the post that fpid answer, the post that that parent
2611
+** of the fpid post - the post that fpid answers, the post that parent
26122612
** post answers, and so forth back up to the root post. Duplicates sender
26132613
** names are omitted.
26142614
**
26152615
** The EmailEvent.zPriors field is used to screen events for people who
26162616
** only want to see replies to their own posts or to specific posts.
@@ -2955,12 +2955,12 @@
29552955
Blob *pBody, /* Write email body here */
29562956
const char *zCode, /* The subscriber code */
29572957
int lastContact, /* Last contact (days since 1970) */
29582958
const char *zEAddr, /* Subscriber email address. Send to this. */
29592959
const char *zSub, /* Subscription codes */
2960
- const char *zRepoName, /* Name of the sending Fossil repostory */
2961
- const char *zUrl /* URL for the sending Fossil repostory */
2960
+ const char *zRepoName, /* Name of the sending Fossil repository */
2961
+ const char *zUrl /* URL for the sending Fossil repository */
29622962
){
29632963
blob_appendf(pHdr,"To: <%s>\r\n", zEAddr);
29642964
blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon\r\n",
29652965
zRepoName, zUrl);
29662966
blob_appendf(pBody,
@@ -3466,11 +3466,11 @@
34663466
@ </form>
34673467
style_finish_page();
34683468
}
34693469
34703470
/*
3471
-** Send an annoucement message described by query parameter.
3471
+** Send an announcement message described by query parameter.
34723472
** Permission to do this has already been verified.
34733473
*/
34743474
static char *alert_send_announcement(void){
34753475
AlertSender *pSender;
34763476
char *zErr;
34773477
--- src/alerts.c
+++ src/alerts.c
@@ -664,11 +664,11 @@
664 return p;
665 }
666
667 /*
668 ** Scan the header of the email message in pMsg looking for the
669 ** (first) occurrance of zField. Fill pValue with the content of
670 ** that field.
671 **
672 ** This routine initializes pValue. Any prior content of pValue is
673 ** discarded (leaked).
674 **
@@ -710,11 +710,11 @@
710 /*
711 ** Determine whether or not the input string is a valid email address.
712 ** Only look at character up to but not including the first \000 or
713 ** the first cTerm character, whichever comes first.
714 **
715 ** Return the length of the email addresss string in bytes if the email
716 ** address is valid. If the email address is misformed, return 0.
717 */
718 int email_address_is_valid(const char *z, char cTerm){
719 int i;
720 int nAt = 0;
@@ -2259,11 +2259,11 @@
2259 ** Users visit this page to be delisted from email alerts.
2260 **
2261 ** If a valid subscriber code is supplied in the name= query parameter,
2262 ** then that subscriber is delisted.
2263 **
2264 ** Otherwise, If the users is logged in, then they are redirected
2265 ** to the /alerts page where they have an unsubscribe button.
2266 **
2267 ** Non-logged-in users with no name= query parameter are invited to enter
2268 ** an email address to which will be sent the unsubscribe link that
2269 ** contains the correct subscriber code.
@@ -2606,11 +2606,11 @@
2606 /*
2607 ** Compute a string that is appropriate for the EmailEvent.zPriors field
2608 ** for a particular forum post.
2609 **
2610 ** This string is an encode list of sender names and rids for all ancestors
2611 ** of the fpdi post - the post that fpid answer, the post that that parent
2612 ** post answers, and so forth back up to the root post. Duplicates sender
2613 ** names are omitted.
2614 **
2615 ** The EmailEvent.zPriors field is used to screen events for people who
2616 ** only want to see replies to their own posts or to specific posts.
@@ -2955,12 +2955,12 @@
2955 Blob *pBody, /* Write email body here */
2956 const char *zCode, /* The subscriber code */
2957 int lastContact, /* Last contact (days since 1970) */
2958 const char *zEAddr, /* Subscriber email address. Send to this. */
2959 const char *zSub, /* Subscription codes */
2960 const char *zRepoName, /* Name of the sending Fossil repostory */
2961 const char *zUrl /* URL for the sending Fossil repostory */
2962 ){
2963 blob_appendf(pHdr,"To: <%s>\r\n", zEAddr);
2964 blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon\r\n",
2965 zRepoName, zUrl);
2966 blob_appendf(pBody,
@@ -3466,11 +3466,11 @@
3466 @ </form>
3467 style_finish_page();
3468 }
3469
3470 /*
3471 ** Send an annoucement message described by query parameter.
3472 ** Permission to do this has already been verified.
3473 */
3474 static char *alert_send_announcement(void){
3475 AlertSender *pSender;
3476 char *zErr;
3477
--- src/alerts.c
+++ src/alerts.c
@@ -664,11 +664,11 @@
664 return p;
665 }
666
667 /*
668 ** Scan the header of the email message in pMsg looking for the
669 ** (first) occurrence of zField. Fill pValue with the content of
670 ** that field.
671 **
672 ** This routine initializes pValue. Any prior content of pValue is
673 ** discarded (leaked).
674 **
@@ -710,11 +710,11 @@
710 /*
711 ** Determine whether or not the input string is a valid email address.
712 ** Only look at character up to but not including the first \000 or
713 ** the first cTerm character, whichever comes first.
714 **
715 ** Return the length of the email address string in bytes if the email
716 ** address is valid. If the email address is misformed, return 0.
717 */
718 int email_address_is_valid(const char *z, char cTerm){
719 int i;
720 int nAt = 0;
@@ -2259,11 +2259,11 @@
2259 ** Users visit this page to be delisted from email alerts.
2260 **
2261 ** If a valid subscriber code is supplied in the name= query parameter,
2262 ** then that subscriber is delisted.
2263 **
2264 ** Otherwise, if the users are logged in, then they are redirected
2265 ** to the /alerts page where they have an unsubscribe button.
2266 **
2267 ** Non-logged-in users with no name= query parameter are invited to enter
2268 ** an email address to which will be sent the unsubscribe link that
2269 ** contains the correct subscriber code.
@@ -2606,11 +2606,11 @@
2606 /*
2607 ** Compute a string that is appropriate for the EmailEvent.zPriors field
2608 ** for a particular forum post.
2609 **
2610 ** This string is an encode list of sender names and rids for all ancestors
2611 ** of the fpid post - the post that fpid answers, the post that parent
2612 ** post answers, and so forth back up to the root post. Duplicates sender
2613 ** names are omitted.
2614 **
2615 ** The EmailEvent.zPriors field is used to screen events for people who
2616 ** only want to see replies to their own posts or to specific posts.
@@ -2955,12 +2955,12 @@
2955 Blob *pBody, /* Write email body here */
2956 const char *zCode, /* The subscriber code */
2957 int lastContact, /* Last contact (days since 1970) */
2958 const char *zEAddr, /* Subscriber email address. Send to this. */
2959 const char *zSub, /* Subscription codes */
2960 const char *zRepoName, /* Name of the sending Fossil repository */
2961 const char *zUrl /* URL for the sending Fossil repository */
2962 ){
2963 blob_appendf(pHdr,"To: <%s>\r\n", zEAddr);
2964 blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon\r\n",
2965 zRepoName, zUrl);
2966 blob_appendf(pBody,
@@ -3466,11 +3466,11 @@
3466 @ </form>
3467 style_finish_page();
3468 }
3469
3470 /*
3471 ** Send an announcement message described by query parameter.
3472 ** Permission to do this has already been verified.
3473 */
3474 static char *alert_send_announcement(void){
3475 AlertSender *pSender;
3476 char *zErr;
3477
+18 -5
--- src/allrepo.c
+++ src/allrepo.c
@@ -157,19 +157,22 @@
157157
** when one of the following commands are run against the repository:
158158
** clone, info, pull, push, or sync. Even previously ignored repositories
159159
** are added back to the list of repositories by these commands.
160160
**
161161
** Options:
162
-** --dry-run If given, display instead of run actions
162
+** --dry-run Just display commands that would have run
163163
** --showfile Show the repository or check-out being operated upon
164164
** --stop-on-error Halt immediately if any subprocess fails
165
+** -s|--stop Shorthand for "--stop-on-error"
165166
*/
166167
void all_cmd(void){
167168
Stmt q;
168169
const char *zCmd;
169
- char *zSyscmd;
170
+ char *zSyscmd = 0;
170171
Blob extra;
172
+ int bHalted = 0;
173
+ int rc = 0;
171174
int useCheckouts = 0;
172175
int quiet = 0;
173176
int dryRunFlag = 0;
174177
int showFile = find_option("showfile",0,0)!=0;
175178
int stopOnError;
@@ -176,10 +179,11 @@
176179
int nToDel = 0;
177180
int showLabel = 0;
178181
179182
(void)find_option("dontstop",0,0); /* Legacy. Now the default */
180183
stopOnError = find_option("stop-on-error",0,0)!=0;
184
+ if( find_option("stop","s",0)!=0 ) stopOnError = 1;
181185
dryRunFlag = find_option("dry-run","n",0)!=0;
182186
if( !dryRunFlag ){
183187
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
184188
}
185189
@@ -330,10 +334,12 @@
330334
zCmd = "sync -autourl -R";
331335
collect_argument(&extra, "share-links",0);
332336
collect_argument(&extra, "verbose","v");
333337
collect_argument(&extra, "unversioned","u");
334338
collect_argument(&extra, "all",0);
339
+ collect_argument(&extra, "quiet","q");
340
+ collect_argument(&extra, "ping",0);
335341
}else if( fossil_strcmp(zCmd, "test-integrity")==0 ){
336342
collect_argument(&extra, "db-only", "d");
337343
collect_argument(&extra, "parse", 0);
338344
collect_argument(&extra, "quick", "q");
339345
zCmd = "test-integrity";
@@ -465,11 +471,10 @@
465471
" ORDER BY 1"
466472
);
467473
}
468474
db_prepare(&q,"SELECT name, tag, inode FROM repolist ORDER BY 1");
469475
while( db_step(&q)==SQLITE_ROW ){
470
- int rc;
471476
const char *zFilename = db_column_text(&q, 0);
472477
const char *zInode = db_column_text(&q,2);
473478
#if !USE_SEE
474479
if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
475480
#endif
@@ -502,18 +507,21 @@
502507
if( !quiet || dryRunFlag ){
503508
fossil_print("%s\n", zSyscmd);
504509
fflush(stdout);
505510
}
506511
rc = dryRunFlag ? 0 : fossil_system(zSyscmd);
507
- free(zSyscmd);
508512
if( rc ){
509
- if( stopOnError ) break;
513
+ if( stopOnError ){
514
+ bHalted = 1;
515
+ break;
516
+ }
510517
/* If there is an error, pause briefly, but do not stop. The brief
511518
** pause is so that if the prior command failed with Ctrl-C then there
512519
** will be time to stop the whole thing with a second Ctrl-C. */
513520
sqlite3_sleep(330);
514521
}
522
+ fossil_free(zSyscmd);
515523
}
516524
db_finalize(&q);
517525
518526
blob_reset(&extra);
519527
@@ -528,6 +536,11 @@
528536
db_unprotect(PROTECT_CONFIG);
529537
db_multi_exec("%s", zSql /*safe-for-%s*/ );
530538
db_protect_pop();
531539
}
532540
}
541
+
542
+ if( stopOnError && bHalted ){
543
+ fossil_fatal("STOPPED: non-zero result code (%d) from\nSTOPPED: %s",
544
+ rc, zSyscmd);
545
+ }
533546
}
534547
--- src/allrepo.c
+++ src/allrepo.c
@@ -157,19 +157,22 @@
157 ** when one of the following commands are run against the repository:
158 ** clone, info, pull, push, or sync. Even previously ignored repositories
159 ** are added back to the list of repositories by these commands.
160 **
161 ** Options:
162 ** --dry-run If given, display instead of run actions
163 ** --showfile Show the repository or check-out being operated upon
164 ** --stop-on-error Halt immediately if any subprocess fails
 
165 */
166 void all_cmd(void){
167 Stmt q;
168 const char *zCmd;
169 char *zSyscmd;
170 Blob extra;
 
 
171 int useCheckouts = 0;
172 int quiet = 0;
173 int dryRunFlag = 0;
174 int showFile = find_option("showfile",0,0)!=0;
175 int stopOnError;
@@ -176,10 +179,11 @@
176 int nToDel = 0;
177 int showLabel = 0;
178
179 (void)find_option("dontstop",0,0); /* Legacy. Now the default */
180 stopOnError = find_option("stop-on-error",0,0)!=0;
 
181 dryRunFlag = find_option("dry-run","n",0)!=0;
182 if( !dryRunFlag ){
183 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
184 }
185
@@ -330,10 +334,12 @@
330 zCmd = "sync -autourl -R";
331 collect_argument(&extra, "share-links",0);
332 collect_argument(&extra, "verbose","v");
333 collect_argument(&extra, "unversioned","u");
334 collect_argument(&extra, "all",0);
 
 
335 }else if( fossil_strcmp(zCmd, "test-integrity")==0 ){
336 collect_argument(&extra, "db-only", "d");
337 collect_argument(&extra, "parse", 0);
338 collect_argument(&extra, "quick", "q");
339 zCmd = "test-integrity";
@@ -465,11 +471,10 @@
465 " ORDER BY 1"
466 );
467 }
468 db_prepare(&q,"SELECT name, tag, inode FROM repolist ORDER BY 1");
469 while( db_step(&q)==SQLITE_ROW ){
470 int rc;
471 const char *zFilename = db_column_text(&q, 0);
472 const char *zInode = db_column_text(&q,2);
473 #if !USE_SEE
474 if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
475 #endif
@@ -502,18 +507,21 @@
502 if( !quiet || dryRunFlag ){
503 fossil_print("%s\n", zSyscmd);
504 fflush(stdout);
505 }
506 rc = dryRunFlag ? 0 : fossil_system(zSyscmd);
507 free(zSyscmd);
508 if( rc ){
509 if( stopOnError ) break;
 
 
 
510 /* If there is an error, pause briefly, but do not stop. The brief
511 ** pause is so that if the prior command failed with Ctrl-C then there
512 ** will be time to stop the whole thing with a second Ctrl-C. */
513 sqlite3_sleep(330);
514 }
 
515 }
516 db_finalize(&q);
517
518 blob_reset(&extra);
519
@@ -528,6 +536,11 @@
528 db_unprotect(PROTECT_CONFIG);
529 db_multi_exec("%s", zSql /*safe-for-%s*/ );
530 db_protect_pop();
531 }
532 }
 
 
 
 
 
533 }
534
--- src/allrepo.c
+++ src/allrepo.c
@@ -157,19 +157,22 @@
157 ** when one of the following commands are run against the repository:
158 ** clone, info, pull, push, or sync. Even previously ignored repositories
159 ** are added back to the list of repositories by these commands.
160 **
161 ** Options:
162 ** --dry-run Just display commands that would have run
163 ** --showfile Show the repository or check-out being operated upon
164 ** --stop-on-error Halt immediately if any subprocess fails
165 ** -s|--stop Shorthand for "--stop-on-error"
166 */
167 void all_cmd(void){
168 Stmt q;
169 const char *zCmd;
170 char *zSyscmd = 0;
171 Blob extra;
172 int bHalted = 0;
173 int rc = 0;
174 int useCheckouts = 0;
175 int quiet = 0;
176 int dryRunFlag = 0;
177 int showFile = find_option("showfile",0,0)!=0;
178 int stopOnError;
@@ -176,10 +179,11 @@
179 int nToDel = 0;
180 int showLabel = 0;
181
182 (void)find_option("dontstop",0,0); /* Legacy. Now the default */
183 stopOnError = find_option("stop-on-error",0,0)!=0;
184 if( find_option("stop","s",0)!=0 ) stopOnError = 1;
185 dryRunFlag = find_option("dry-run","n",0)!=0;
186 if( !dryRunFlag ){
187 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
188 }
189
@@ -330,10 +334,12 @@
334 zCmd = "sync -autourl -R";
335 collect_argument(&extra, "share-links",0);
336 collect_argument(&extra, "verbose","v");
337 collect_argument(&extra, "unversioned","u");
338 collect_argument(&extra, "all",0);
339 collect_argument(&extra, "quiet","q");
340 collect_argument(&extra, "ping",0);
341 }else if( fossil_strcmp(zCmd, "test-integrity")==0 ){
342 collect_argument(&extra, "db-only", "d");
343 collect_argument(&extra, "parse", 0);
344 collect_argument(&extra, "quick", "q");
345 zCmd = "test-integrity";
@@ -465,11 +471,10 @@
471 " ORDER BY 1"
472 );
473 }
474 db_prepare(&q,"SELECT name, tag, inode FROM repolist ORDER BY 1");
475 while( db_step(&q)==SQLITE_ROW ){
 
476 const char *zFilename = db_column_text(&q, 0);
477 const char *zInode = db_column_text(&q,2);
478 #if !USE_SEE
479 if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
480 #endif
@@ -502,18 +507,21 @@
507 if( !quiet || dryRunFlag ){
508 fossil_print("%s\n", zSyscmd);
509 fflush(stdout);
510 }
511 rc = dryRunFlag ? 0 : fossil_system(zSyscmd);
 
512 if( rc ){
513 if( stopOnError ){
514 bHalted = 1;
515 break;
516 }
517 /* If there is an error, pause briefly, but do not stop. The brief
518 ** pause is so that if the prior command failed with Ctrl-C then there
519 ** will be time to stop the whole thing with a second Ctrl-C. */
520 sqlite3_sleep(330);
521 }
522 fossil_free(zSyscmd);
523 }
524 db_finalize(&q);
525
526 blob_reset(&extra);
527
@@ -528,6 +536,11 @@
536 db_unprotect(PROTECT_CONFIG);
537 db_multi_exec("%s", zSql /*safe-for-%s*/ );
538 db_protect_pop();
539 }
540 }
541
542 if( stopOnError && bHalted ){
543 fossil_fatal("STOPPED: non-zero result code (%d) from\nSTOPPED: %s",
544 rc, zSyscmd);
545 }
546 }
547
+1 -1
--- src/backlink.c
+++ src/backlink.c
@@ -338,11 +338,11 @@
338338
blob_reset(&in);
339339
}
340340
341341
/*
342342
** Transform mimetype string into an integer code.
343
-** NOTE: In the sake of compatability empty string is parsed as MT_UNKNOWN;
343
+** NOTE: In the sake of compatibility empty string is parsed as MT_UNKNOWN;
344344
** it is yet unclear whether it can safely be changed to MT_NONE.
345345
*/
346346
int parse_mimetype(const char* zMimetype){
347347
if( zMimetype==0 ) return MT_NONE;
348348
if( strstr(zMimetype,"wiki")!=0 ) return MT_WIKI;
349349
--- src/backlink.c
+++ src/backlink.c
@@ -338,11 +338,11 @@
338 blob_reset(&in);
339 }
340
341 /*
342 ** Transform mimetype string into an integer code.
343 ** NOTE: In the sake of compatability empty string is parsed as MT_UNKNOWN;
344 ** it is yet unclear whether it can safely be changed to MT_NONE.
345 */
346 int parse_mimetype(const char* zMimetype){
347 if( zMimetype==0 ) return MT_NONE;
348 if( strstr(zMimetype,"wiki")!=0 ) return MT_WIKI;
349
--- src/backlink.c
+++ src/backlink.c
@@ -338,11 +338,11 @@
338 blob_reset(&in);
339 }
340
341 /*
342 ** Transform mimetype string into an integer code.
343 ** NOTE: In the sake of compatibility empty string is parsed as MT_UNKNOWN;
344 ** it is yet unclear whether it can safely be changed to MT_NONE.
345 */
346 int parse_mimetype(const char* zMimetype){
347 if( zMimetype==0 ) return MT_NONE;
348 if( strstr(zMimetype,"wiki")!=0 ) return MT_WIKI;
349
+1 -1
--- src/bisect.c
+++ src/bisect.c
@@ -171,11 +171,11 @@
171171
172172
/*
173173
** Append a new entry to the bisect log. Update the bisect-good or
174174
** bisect-bad values as appropriate.
175175
**
176
-** The bisect-log consists of a list of token. Each token is an
176
+** The bisect-log consists of a list of tokens. Each token is an
177177
** integer RID of a check-in. The RID is negative for "bad" check-ins
178178
** and positive for "good" check-ins.
179179
*/
180180
static void bisect_append_log(int rid){
181181
if( rid<0 ){
182182
--- src/bisect.c
+++ src/bisect.c
@@ -171,11 +171,11 @@
171
172 /*
173 ** Append a new entry to the bisect log. Update the bisect-good or
174 ** bisect-bad values as appropriate.
175 **
176 ** The bisect-log consists of a list of token. Each token is an
177 ** integer RID of a check-in. The RID is negative for "bad" check-ins
178 ** and positive for "good" check-ins.
179 */
180 static void bisect_append_log(int rid){
181 if( rid<0 ){
182
--- src/bisect.c
+++ src/bisect.c
@@ -171,11 +171,11 @@
171
172 /*
173 ** Append a new entry to the bisect log. Update the bisect-good or
174 ** bisect-bad values as appropriate.
175 **
176 ** The bisect-log consists of a list of tokens. Each token is an
177 ** integer RID of a check-in. The RID is negative for "bad" check-ins
178 ** and positive for "good" check-ins.
179 */
180 static void bisect_append_log(int rid){
181 if( rid<0 ){
182
+18 -7
--- src/blob.c
+++ src/blob.c
@@ -744,15 +744,26 @@
744744
void blob_rewind(Blob *p){
745745
p->iCursor = 0;
746746
}
747747
748748
/*
749
-** Truncate a blob back to zero length
749
+** Truncate a blob to the specified length in bytes.
750750
*/
751751
void blob_truncate(Blob *p, int sz){
752752
if( sz>=0 && sz<(int)(p->nUsed) ) p->nUsed = sz;
753753
}
754
+
755
+/*
756
+** Truncate a blob to the specified length in bytes. If truncation
757
+** results in an incomplete UTF-8 sequence at the end, remove up
758
+** to three more bytes back to the last complete UTF-8 sequence.
759
+*/
760
+void blob_truncate_utf8(Blob *p, int sz){
761
+ if( sz>=0 && sz<(int)(p->nUsed) ){
762
+ p->nUsed = utf8_nearest_codepoint(p->aData,sz);
763
+ }
764
+}
754765
755766
/*
756767
** Seek the cursor in a blob to the indicated offset.
757768
*/
758769
int blob_seek(Blob *p, int offset, int whence){
@@ -782,11 +793,11 @@
782793
** end-of-file.
783794
**
784795
** The cursor of pFrom is left pointing at the first byte past the
785796
** \n that terminated the line.
786797
**
787
-** pTo will be an ephermeral blob. If pFrom changes, it might alter
798
+** pTo will be an ephemeral blob. If pFrom changes, it might alter
788799
** pTo as well.
789800
*/
790801
int blob_line(Blob *pFrom, Blob *pTo){
791802
char *aData = pFrom->aData;
792803
int n = pFrom->nUsed;
@@ -825,11 +836,11 @@
825836
** whitespace is ignored.
826837
**
827838
** The cursor of pFrom is left pointing at the first character past
828839
** the end of the token.
829840
**
830
-** pTo will be an ephermeral blob. If pFrom changes, it might alter
841
+** pTo will be an ephemeral blob. If pFrom changes, it might alter
831842
** pTo as well.
832843
*/
833844
int blob_token(Blob *pFrom, Blob *pTo){
834845
char *aData = pFrom->aData;
835846
int n = pFrom->nUsed;
@@ -853,11 +864,11 @@
853864
** (ignoring double '') or by the end of the string
854865
**
855866
** The cursor of pFrom is left pointing at the first character past
856867
** the end of the token.
857868
**
858
-** pTo will be an ephermeral blob. If pFrom changes, it might alter
869
+** pTo will be an ephemeral blob. If pFrom changes, it might alter
859870
** pTo as well.
860871
*/
861872
int blob_sqltoken(Blob *pFrom, Blob *pTo){
862873
char *aData = pFrom->aData;
863874
int n = pFrom->nUsed;
@@ -881,11 +892,11 @@
881892
return pTo->nUsed;
882893
}
883894
884895
/*
885896
** Extract everything from the current cursor to the end of the blob
886
-** into a new blob. The new blob is an ephemerial reference to the
897
+** into a new blob. The new blob is an ephemeral reference to the
887898
** original blob. The cursor of the original blob is unchanged.
888899
*/
889900
int blob_tail(Blob *pFrom, Blob *pTo){
890901
int iCursor = pFrom->iCursor;
891902
blob_extract(pFrom, pFrom->nUsed-pFrom->iCursor, pTo);
@@ -976,11 +987,11 @@
976987
** Options:
977988
** -y|--side-by-side Show diff of INPUTFILE and output side-by-side
978989
** -W|--width N Width of lines in side-by-side diff
979990
*/
980991
void test_strip_comment_lines_cmd(void){
981
- Blob f, h; /* unitialized */
992
+ Blob f, h; /* uninitialized */
982993
Blob out;
983994
DiffConfig dCfg;
984995
int sbs = 0;
985996
const char *z;
986997
int w = 0;
@@ -1806,11 +1817,11 @@
18061817
** unusual characters as an argument for testing.
18071818
**
18081819
** --compare HEX ASCII Verify that argument ASCII is identical to
18091820
** to decoded HEX.
18101821
**
1811
-** --fuzz N Run N fuzz cases. Each cases is a call
1822
+** --fuzz N Run N fuzz cases. Each case is a call
18121823
** to "fossil test-escaped-arg --compare HEX ARG"
18131824
** where HEX and ARG are the same argument.
18141825
** The argument is chosen at random.
18151826
*/
18161827
void test_escaped_arg_command(void){
18171828
--- src/blob.c
+++ src/blob.c
@@ -744,15 +744,26 @@
744 void blob_rewind(Blob *p){
745 p->iCursor = 0;
746 }
747
748 /*
749 ** Truncate a blob back to zero length
750 */
751 void blob_truncate(Blob *p, int sz){
752 if( sz>=0 && sz<(int)(p->nUsed) ) p->nUsed = sz;
753 }
 
 
 
 
 
 
 
 
 
 
 
754
755 /*
756 ** Seek the cursor in a blob to the indicated offset.
757 */
758 int blob_seek(Blob *p, int offset, int whence){
@@ -782,11 +793,11 @@
782 ** end-of-file.
783 **
784 ** The cursor of pFrom is left pointing at the first byte past the
785 ** \n that terminated the line.
786 **
787 ** pTo will be an ephermeral blob. If pFrom changes, it might alter
788 ** pTo as well.
789 */
790 int blob_line(Blob *pFrom, Blob *pTo){
791 char *aData = pFrom->aData;
792 int n = pFrom->nUsed;
@@ -825,11 +836,11 @@
825 ** whitespace is ignored.
826 **
827 ** The cursor of pFrom is left pointing at the first character past
828 ** the end of the token.
829 **
830 ** pTo will be an ephermeral blob. If pFrom changes, it might alter
831 ** pTo as well.
832 */
833 int blob_token(Blob *pFrom, Blob *pTo){
834 char *aData = pFrom->aData;
835 int n = pFrom->nUsed;
@@ -853,11 +864,11 @@
853 ** (ignoring double '') or by the end of the string
854 **
855 ** The cursor of pFrom is left pointing at the first character past
856 ** the end of the token.
857 **
858 ** pTo will be an ephermeral blob. If pFrom changes, it might alter
859 ** pTo as well.
860 */
861 int blob_sqltoken(Blob *pFrom, Blob *pTo){
862 char *aData = pFrom->aData;
863 int n = pFrom->nUsed;
@@ -881,11 +892,11 @@
881 return pTo->nUsed;
882 }
883
884 /*
885 ** Extract everything from the current cursor to the end of the blob
886 ** into a new blob. The new blob is an ephemerial reference to the
887 ** original blob. The cursor of the original blob is unchanged.
888 */
889 int blob_tail(Blob *pFrom, Blob *pTo){
890 int iCursor = pFrom->iCursor;
891 blob_extract(pFrom, pFrom->nUsed-pFrom->iCursor, pTo);
@@ -976,11 +987,11 @@
976 ** Options:
977 ** -y|--side-by-side Show diff of INPUTFILE and output side-by-side
978 ** -W|--width N Width of lines in side-by-side diff
979 */
980 void test_strip_comment_lines_cmd(void){
981 Blob f, h; /* unitialized */
982 Blob out;
983 DiffConfig dCfg;
984 int sbs = 0;
985 const char *z;
986 int w = 0;
@@ -1806,11 +1817,11 @@
1806 ** unusual characters as an argument for testing.
1807 **
1808 ** --compare HEX ASCII Verify that argument ASCII is identical to
1809 ** to decoded HEX.
1810 **
1811 ** --fuzz N Run N fuzz cases. Each cases is a call
1812 ** to "fossil test-escaped-arg --compare HEX ARG"
1813 ** where HEX and ARG are the same argument.
1814 ** The argument is chosen at random.
1815 */
1816 void test_escaped_arg_command(void){
1817
--- src/blob.c
+++ src/blob.c
@@ -744,15 +744,26 @@
744 void blob_rewind(Blob *p){
745 p->iCursor = 0;
746 }
747
748 /*
749 ** Truncate a blob to the specified length in bytes.
750 */
751 void blob_truncate(Blob *p, int sz){
752 if( sz>=0 && sz<(int)(p->nUsed) ) p->nUsed = sz;
753 }
754
755 /*
756 ** Truncate a blob to the specified length in bytes. If truncation
757 ** results in an incomplete UTF-8 sequence at the end, remove up
758 ** to three more bytes back to the last complete UTF-8 sequence.
759 */
760 void blob_truncate_utf8(Blob *p, int sz){
761 if( sz>=0 && sz<(int)(p->nUsed) ){
762 p->nUsed = utf8_nearest_codepoint(p->aData,sz);
763 }
764 }
765
766 /*
767 ** Seek the cursor in a blob to the indicated offset.
768 */
769 int blob_seek(Blob *p, int offset, int whence){
@@ -782,11 +793,11 @@
793 ** end-of-file.
794 **
795 ** The cursor of pFrom is left pointing at the first byte past the
796 ** \n that terminated the line.
797 **
798 ** pTo will be an ephemeral blob. If pFrom changes, it might alter
799 ** pTo as well.
800 */
801 int blob_line(Blob *pFrom, Blob *pTo){
802 char *aData = pFrom->aData;
803 int n = pFrom->nUsed;
@@ -825,11 +836,11 @@
836 ** whitespace is ignored.
837 **
838 ** The cursor of pFrom is left pointing at the first character past
839 ** the end of the token.
840 **
841 ** pTo will be an ephemeral blob. If pFrom changes, it might alter
842 ** pTo as well.
843 */
844 int blob_token(Blob *pFrom, Blob *pTo){
845 char *aData = pFrom->aData;
846 int n = pFrom->nUsed;
@@ -853,11 +864,11 @@
864 ** (ignoring double '') or by the end of the string
865 **
866 ** The cursor of pFrom is left pointing at the first character past
867 ** the end of the token.
868 **
869 ** pTo will be an ephemeral blob. If pFrom changes, it might alter
870 ** pTo as well.
871 */
872 int blob_sqltoken(Blob *pFrom, Blob *pTo){
873 char *aData = pFrom->aData;
874 int n = pFrom->nUsed;
@@ -881,11 +892,11 @@
892 return pTo->nUsed;
893 }
894
895 /*
896 ** Extract everything from the current cursor to the end of the blob
897 ** into a new blob. The new blob is an ephemeral reference to the
898 ** original blob. The cursor of the original blob is unchanged.
899 */
900 int blob_tail(Blob *pFrom, Blob *pTo){
901 int iCursor = pFrom->iCursor;
902 blob_extract(pFrom, pFrom->nUsed-pFrom->iCursor, pTo);
@@ -976,11 +987,11 @@
987 ** Options:
988 ** -y|--side-by-side Show diff of INPUTFILE and output side-by-side
989 ** -W|--width N Width of lines in side-by-side diff
990 */
991 void test_strip_comment_lines_cmd(void){
992 Blob f, h; /* uninitialized */
993 Blob out;
994 DiffConfig dCfg;
995 int sbs = 0;
996 const char *z;
997 int w = 0;
@@ -1806,11 +1817,11 @@
1817 ** unusual characters as an argument for testing.
1818 **
1819 ** --compare HEX ASCII Verify that argument ASCII is identical to
1820 ** to decoded HEX.
1821 **
1822 ** --fuzz N Run N fuzz cases. Each case is a call
1823 ** to "fossil test-escaped-arg --compare HEX ARG"
1824 ** where HEX and ARG are the same argument.
1825 ** The argument is chosen at random.
1826 */
1827 void test_escaped_arg_command(void){
1828
+7 -7
--- src/branch.c
+++ src/branch.c
@@ -232,11 +232,11 @@
232232
**
233233
** name Name of the branch
234234
** mtime Time of last check-in on this branch
235235
** isclosed True if the branch is closed
236236
** mergeto Another branch this branch was merged into
237
-** nckin Number of checkins on this branch
237
+** nckin Number of check-ins on this branch
238238
** ckin Hash of the last check-in on this branch
239239
** isprivate True if the branch is private
240240
** bgclr Background color for this branch
241241
*/
242242
static const char createBrlistQuery[] =
@@ -558,11 +558,11 @@
558558
}
559559
560560
/*
561561
** Implementation of (branch close|reopen) subcommands. nStartAtArg is
562562
** the g.argv index to start reading branch/check-in names. The given
563
-** checkins are closed if fClose is true, else their "closed" tag (if
563
+** check-ins are closed if fClose is true, else their "closed" tag (if
564564
** any) is cancelled. Fails fatally on error.
565565
*/
566566
static void branch_cmd_close(int nStartAtArg, int fClose){
567567
int argPos = nStartAtArg; /* g.argv pos with first branch name */
568568
char * zUuid = 0; /* Resolved branch UUID. */
@@ -1116,17 +1116,17 @@
11161116
style_finish_page();
11171117
}
11181118
11191119
/*
11201120
** Generate a multichoice submenu for the few recent active branches. zName is
1121
-** the query parameter used to select the current checkin. zCI is optional and
1122
-** represent the currently selected checkin, so if it is a checkin hash
1121
+** the query parameter used to select the current check-in. zCI is optional and
1122
+** represent the currently selected check-in, so if it is a check-in hash
11231123
** instead of a branch, it can be part of the multichoice menu.
11241124
*/
11251125
void generate_branch_submenu_multichoice(
11261126
const char* zName, /* Query parameter name */
1127
- const char* zCI /* Current checkin */
1127
+ const char* zCI /* Current check-in */
11281128
){
11291129
Stmt q;
11301130
const int brFlags = BRL_ORDERBY_MTIME | BRL_OPEN_ONLY;
11311131
static const char *zBranchMenuList[32*2]; /* 2 per entries */
11321132
const int nLimit = count(zBranchMenuList)/2;
@@ -1134,18 +1134,18 @@
11341134
11351135
if( zName == 0 ) zName = "ci";
11361136
11371137
branch_prepare_list_query(&q, brFlags, 0, nLimit, 0);
11381138
zBranchMenuList[i++] = "";
1139
- zBranchMenuList[i++] = "All Checkins";
1139
+ zBranchMenuList[i++] = "All Check-ins";
11401140
11411141
if( zCI ){
11421142
zCI = fossil_strdup(zCI);
11431143
zBranchMenuList[i++] = zCI;
11441144
zBranchMenuList[i++] = zCI;
11451145
}
1146
- /* If current checkin is not "tip", add it to the list */
1146
+ /* If current check-in is not "tip", add it to the list */
11471147
if( zCI==0 || strcmp(zCI, "tip") ){
11481148
zBranchMenuList[i++] = "tip";
11491149
zBranchMenuList[i++] = "tip";
11501150
}
11511151
while( i/2 < nLimit && db_step(&q)==SQLITE_ROW ){
11521152
--- src/branch.c
+++ src/branch.c
@@ -232,11 +232,11 @@
232 **
233 ** name Name of the branch
234 ** mtime Time of last check-in on this branch
235 ** isclosed True if the branch is closed
236 ** mergeto Another branch this branch was merged into
237 ** nckin Number of checkins on this branch
238 ** ckin Hash of the last check-in on this branch
239 ** isprivate True if the branch is private
240 ** bgclr Background color for this branch
241 */
242 static const char createBrlistQuery[] =
@@ -558,11 +558,11 @@
558 }
559
560 /*
561 ** Implementation of (branch close|reopen) subcommands. nStartAtArg is
562 ** the g.argv index to start reading branch/check-in names. The given
563 ** checkins are closed if fClose is true, else their "closed" tag (if
564 ** any) is cancelled. Fails fatally on error.
565 */
566 static void branch_cmd_close(int nStartAtArg, int fClose){
567 int argPos = nStartAtArg; /* g.argv pos with first branch name */
568 char * zUuid = 0; /* Resolved branch UUID. */
@@ -1116,17 +1116,17 @@
1116 style_finish_page();
1117 }
1118
1119 /*
1120 ** Generate a multichoice submenu for the few recent active branches. zName is
1121 ** the query parameter used to select the current checkin. zCI is optional and
1122 ** represent the currently selected checkin, so if it is a checkin hash
1123 ** instead of a branch, it can be part of the multichoice menu.
1124 */
1125 void generate_branch_submenu_multichoice(
1126 const char* zName, /* Query parameter name */
1127 const char* zCI /* Current checkin */
1128 ){
1129 Stmt q;
1130 const int brFlags = BRL_ORDERBY_MTIME | BRL_OPEN_ONLY;
1131 static const char *zBranchMenuList[32*2]; /* 2 per entries */
1132 const int nLimit = count(zBranchMenuList)/2;
@@ -1134,18 +1134,18 @@
1134
1135 if( zName == 0 ) zName = "ci";
1136
1137 branch_prepare_list_query(&q, brFlags, 0, nLimit, 0);
1138 zBranchMenuList[i++] = "";
1139 zBranchMenuList[i++] = "All Checkins";
1140
1141 if( zCI ){
1142 zCI = fossil_strdup(zCI);
1143 zBranchMenuList[i++] = zCI;
1144 zBranchMenuList[i++] = zCI;
1145 }
1146 /* If current checkin is not "tip", add it to the list */
1147 if( zCI==0 || strcmp(zCI, "tip") ){
1148 zBranchMenuList[i++] = "tip";
1149 zBranchMenuList[i++] = "tip";
1150 }
1151 while( i/2 < nLimit && db_step(&q)==SQLITE_ROW ){
1152
--- src/branch.c
+++ src/branch.c
@@ -232,11 +232,11 @@
232 **
233 ** name Name of the branch
234 ** mtime Time of last check-in on this branch
235 ** isclosed True if the branch is closed
236 ** mergeto Another branch this branch was merged into
237 ** nckin Number of check-ins on this branch
238 ** ckin Hash of the last check-in on this branch
239 ** isprivate True if the branch is private
240 ** bgclr Background color for this branch
241 */
242 static const char createBrlistQuery[] =
@@ -558,11 +558,11 @@
558 }
559
560 /*
561 ** Implementation of (branch close|reopen) subcommands. nStartAtArg is
562 ** the g.argv index to start reading branch/check-in names. The given
563 ** check-ins are closed if fClose is true, else their "closed" tag (if
564 ** any) is cancelled. Fails fatally on error.
565 */
566 static void branch_cmd_close(int nStartAtArg, int fClose){
567 int argPos = nStartAtArg; /* g.argv pos with first branch name */
568 char * zUuid = 0; /* Resolved branch UUID. */
@@ -1116,17 +1116,17 @@
1116 style_finish_page();
1117 }
1118
1119 /*
1120 ** Generate a multichoice submenu for the few recent active branches. zName is
1121 ** the query parameter used to select the current check-in. zCI is optional and
1122 ** represent the currently selected check-in, so if it is a check-in hash
1123 ** instead of a branch, it can be part of the multichoice menu.
1124 */
1125 void generate_branch_submenu_multichoice(
1126 const char* zName, /* Query parameter name */
1127 const char* zCI /* Current check-in */
1128 ){
1129 Stmt q;
1130 const int brFlags = BRL_ORDERBY_MTIME | BRL_OPEN_ONLY;
1131 static const char *zBranchMenuList[32*2]; /* 2 per entries */
1132 const int nLimit = count(zBranchMenuList)/2;
@@ -1134,18 +1134,18 @@
1134
1135 if( zName == 0 ) zName = "ci";
1136
1137 branch_prepare_list_query(&q, brFlags, 0, nLimit, 0);
1138 zBranchMenuList[i++] = "";
1139 zBranchMenuList[i++] = "All Check-ins";
1140
1141 if( zCI ){
1142 zCI = fossil_strdup(zCI);
1143 zBranchMenuList[i++] = zCI;
1144 zBranchMenuList[i++] = zCI;
1145 }
1146 /* If current check-in is not "tip", add it to the list */
1147 if( zCI==0 || strcmp(zCI, "tip") ){
1148 zBranchMenuList[i++] = "tip";
1149 zBranchMenuList[i++] = "tip";
1150 }
1151 while( i/2 < nLimit && db_step(&q)==SQLITE_ROW ){
1152
+1 -1
--- src/builtin.c
+++ src/builtin.c
@@ -735,11 +735,11 @@
735735
} fjs[] = {
736736
/* This list ordering isn't strictly important. */
737737
{"confirmer", 0, 0},
738738
{"copybutton", 0, "dom\0"},
739739
{"diff", 0, "dom\0fetch\0storage\0"
740
- /* maintenance note: "diff" needs "storage" for storing the the
740
+ /* maintenance note: "diff" needs "storage" for storing the
741741
** sbs-sync-scroll toggle. */},
742742
{"dom", 0, 0},
743743
{"fetch", 0, 0},
744744
{"numbered-lines", 0, "popupwidget\0copybutton\0"},
745745
{"pikchr", 0, "dom\0"},
746746
--- src/builtin.c
+++ src/builtin.c
@@ -735,11 +735,11 @@
735 } fjs[] = {
736 /* This list ordering isn't strictly important. */
737 {"confirmer", 0, 0},
738 {"copybutton", 0, "dom\0"},
739 {"diff", 0, "dom\0fetch\0storage\0"
740 /* maintenance note: "diff" needs "storage" for storing the the
741 ** sbs-sync-scroll toggle. */},
742 {"dom", 0, 0},
743 {"fetch", 0, 0},
744 {"numbered-lines", 0, "popupwidget\0copybutton\0"},
745 {"pikchr", 0, "dom\0"},
746
--- src/builtin.c
+++ src/builtin.c
@@ -735,11 +735,11 @@
735 } fjs[] = {
736 /* This list ordering isn't strictly important. */
737 {"confirmer", 0, 0},
738 {"copybutton", 0, "dom\0"},
739 {"diff", 0, "dom\0fetch\0storage\0"
740 /* maintenance note: "diff" needs "storage" for storing the
741 ** sbs-sync-scroll toggle. */},
742 {"dom", 0, 0},
743 {"fetch", 0, 0},
744 {"numbered-lines", 0, "popupwidget\0copybutton\0"},
745 {"pikchr", 0, "dom\0"},
746
+2 -2
--- src/cache.c
+++ src/cache.c
@@ -70,11 +70,11 @@
7070
"CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
7171
"CREATE TABLE IF NOT EXISTS cache("
7272
"key TEXT PRIMARY KEY," /* Key used to access the cache */
7373
"id INT REFERENCES blob," /* The cache content */
7474
"sz INT," /* Size of content in bytes */
75
- "tm INT," /* Last access time (unix timestampe) */
75
+ "tm INT," /* Last access time (unix timestamp) */
7676
"nref INT" /* Number of uses */
7777
");"
7878
"CREATE TRIGGER IF NOT EXISTS cacheDel AFTER DELETE ON cache BEGIN"
7979
" DELETE FROM blob WHERE id=OLD.id;"
8080
"END;",
@@ -437,11 +437,11 @@
437437
@ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br>
438438
@ size: %,lld(sqlite3_column_int64(pStmt,1)),
439439
@ hit-count: %d(sqlite3_column_int(pStmt,2)),
440440
@ last-access: %s(sqlite3_column_text(pStmt,3))Z \
441441
if( zHash ){
442
- @ &rarr; %z(href("%R/timeline?c=%S",zHash))checkin info</a>\
442
+ @ &rarr; %z(href("%R/timeline?c=%S",zHash))check-in info</a>\
443443
fossil_free(zHash);
444444
}
445445
@ </p></li>
446446
nEntry++;
447447
}
448448
--- src/cache.c
+++ src/cache.c
@@ -70,11 +70,11 @@
70 "CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
71 "CREATE TABLE IF NOT EXISTS cache("
72 "key TEXT PRIMARY KEY," /* Key used to access the cache */
73 "id INT REFERENCES blob," /* The cache content */
74 "sz INT," /* Size of content in bytes */
75 "tm INT," /* Last access time (unix timestampe) */
76 "nref INT" /* Number of uses */
77 ");"
78 "CREATE TRIGGER IF NOT EXISTS cacheDel AFTER DELETE ON cache BEGIN"
79 " DELETE FROM blob WHERE id=OLD.id;"
80 "END;",
@@ -437,11 +437,11 @@
437 @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br>
438 @ size: %,lld(sqlite3_column_int64(pStmt,1)),
439 @ hit-count: %d(sqlite3_column_int(pStmt,2)),
440 @ last-access: %s(sqlite3_column_text(pStmt,3))Z \
441 if( zHash ){
442 @ &rarr; %z(href("%R/timeline?c=%S",zHash))checkin info</a>\
443 fossil_free(zHash);
444 }
445 @ </p></li>
446 nEntry++;
447 }
448
--- src/cache.c
+++ src/cache.c
@@ -70,11 +70,11 @@
70 "CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
71 "CREATE TABLE IF NOT EXISTS cache("
72 "key TEXT PRIMARY KEY," /* Key used to access the cache */
73 "id INT REFERENCES blob," /* The cache content */
74 "sz INT," /* Size of content in bytes */
75 "tm INT," /* Last access time (unix timestamp) */
76 "nref INT" /* Number of uses */
77 ");"
78 "CREATE TRIGGER IF NOT EXISTS cacheDel AFTER DELETE ON cache BEGIN"
79 " DELETE FROM blob WHERE id=OLD.id;"
80 "END;",
@@ -437,11 +437,11 @@
437 @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br>
438 @ size: %,lld(sqlite3_column_int64(pStmt,1)),
439 @ hit-count: %d(sqlite3_column_int(pStmt,2)),
440 @ last-access: %s(sqlite3_column_text(pStmt,3))Z \
441 if( zHash ){
442 @ &rarr; %z(href("%R/timeline?c=%S",zHash))check-in info</a>\
443 fossil_free(zHash);
444 }
445 @ </p></li>
446 nEntry++;
447 }
448
+3 -3
--- src/captcha.c
+++ src/captcha.c
@@ -509,11 +509,11 @@
509509
sqlite3_randomness(sizeof(x), &x);
510510
x &= 0x7fffffff;
511511
return x;
512512
}
513513
514
-/* The SQL that will rotate the the captcha-secret. */
514
+/* The SQL that will rotate the captcha-secret. */
515515
static const char captchaSecretRotationSql[] =
516516
@ SAVEPOINT rotate;
517517
@ DELETE FROM config
518518
@ WHERE name GLOB 'captcha-secret-*'
519519
@ AND mtime<unixepoch('now','-6 hours');
@@ -529,11 +529,11 @@
529529
;
530530
531531
532532
/*
533533
** Create a new random captcha-secret. Rotate the old one into
534
-** the captcha-secret-N backups. Purge captch-secret-N backups
534
+** the captcha-secret-N backups. Purge captcha-secret-N backups
535535
** older than 6 hours.
536536
**
537537
** Do this on the current database and in all other databases of
538538
** the same login group.
539539
*/
@@ -559,11 +559,11 @@
559559
fossil_free(zSql);
560560
}
561561
562562
/*
563563
** Return the value of the N-th more recent captcha-secret. The
564
-** most recent captch-secret is 0. Others are prior captcha-secrets
564
+** most recent captcha-secret is 0. Others are prior captcha-secrets
565565
** that have expired, but are retained for a limited period of time
566566
** so that pending anonymous login cookies and/or captcha dialogs
567567
** don't malfunction when the captcha-secret changes.
568568
**
569569
** Clients should start by using the 0-th captcha-secret. Only if
570570
--- src/captcha.c
+++ src/captcha.c
@@ -509,11 +509,11 @@
509 sqlite3_randomness(sizeof(x), &x);
510 x &= 0x7fffffff;
511 return x;
512 }
513
514 /* The SQL that will rotate the the captcha-secret. */
515 static const char captchaSecretRotationSql[] =
516 @ SAVEPOINT rotate;
517 @ DELETE FROM config
518 @ WHERE name GLOB 'captcha-secret-*'
519 @ AND mtime<unixepoch('now','-6 hours');
@@ -529,11 +529,11 @@
529 ;
530
531
532 /*
533 ** Create a new random captcha-secret. Rotate the old one into
534 ** the captcha-secret-N backups. Purge captch-secret-N backups
535 ** older than 6 hours.
536 **
537 ** Do this on the current database and in all other databases of
538 ** the same login group.
539 */
@@ -559,11 +559,11 @@
559 fossil_free(zSql);
560 }
561
562 /*
563 ** Return the value of the N-th more recent captcha-secret. The
564 ** most recent captch-secret is 0. Others are prior captcha-secrets
565 ** that have expired, but are retained for a limited period of time
566 ** so that pending anonymous login cookies and/or captcha dialogs
567 ** don't malfunction when the captcha-secret changes.
568 **
569 ** Clients should start by using the 0-th captcha-secret. Only if
570
--- src/captcha.c
+++ src/captcha.c
@@ -509,11 +509,11 @@
509 sqlite3_randomness(sizeof(x), &x);
510 x &= 0x7fffffff;
511 return x;
512 }
513
514 /* The SQL that will rotate the captcha-secret. */
515 static const char captchaSecretRotationSql[] =
516 @ SAVEPOINT rotate;
517 @ DELETE FROM config
518 @ WHERE name GLOB 'captcha-secret-*'
519 @ AND mtime<unixepoch('now','-6 hours');
@@ -529,11 +529,11 @@
529 ;
530
531
532 /*
533 ** Create a new random captcha-secret. Rotate the old one into
534 ** the captcha-secret-N backups. Purge captcha-secret-N backups
535 ** older than 6 hours.
536 **
537 ** Do this on the current database and in all other databases of
538 ** the same login group.
539 */
@@ -559,11 +559,11 @@
559 fossil_free(zSql);
560 }
561
562 /*
563 ** Return the value of the N-th more recent captcha-secret. The
564 ** most recent captcha-secret is 0. Others are prior captcha-secrets
565 ** that have expired, but are retained for a limited period of time
566 ** so that pending anonymous login cookies and/or captcha dialogs
567 ** don't malfunction when the captcha-secret changes.
568 **
569 ** Clients should start by using the 0-th captcha-secret. Only if
570
+7 -7
--- src/cgi.c
+++ src/cgi.c
@@ -13,11 +13,11 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** This file began as a set of C functions and procedures used intepret
18
+** This file began as a set of C functions and procedures used to interpret
1919
** CGI environment variables for Fossil web pages that were invoked by
2020
** CGI. That's where the file name comes from. But over the years it
2121
** has grown to incorporate lots of related functionality, including:
2222
**
2323
** * Interpreting CGI environment variables when Fossil is run as
@@ -146,11 +146,11 @@
146146
**
147147
** Do not confuse the content header with the HTTP header. The content header
148148
** is generated by downstream code. The HTTP header is generated by the
149149
** cgi_reply() routine below.
150150
**
151
-** The content header and contenty body are *approximately* the <head>
151
+** The content header and content body are *approximately* the <head>
152152
** element and the <body> elements for HTML replies. However this is only
153153
** approximate. The content header also includes parts of <body> that
154154
** show the banner and menu bar at the top of each page. Also note that
155155
** not all replies are HTML, but there can still be separate header and
156156
** body sections of the content.
@@ -942,12 +942,12 @@
942942
}
943943
return cnt;
944944
}
945945
946946
/*
947
-** Add an environment varaible value to the parameter set. The zName
948
-** portion is fixed but a copy is be made of zValue.
947
+** Add an environment variable value to the parameter set. The zName
948
+** portion is fixed but a copy is made of zValue.
949949
*/
950950
void cgi_setenv(const char *zName, const char *zValue){
951951
cgi_set_parameter_nocopy(zName, fossil_strdup(zValue), 0);
952952
}
953953
@@ -968,11 +968,11 @@
968968
** Each parameter is of the form NAME=VALUE. Both the NAME and the
969969
** VALUE may be url-encoded ("+" for space, "%HH" for other special
970970
** characters). But this routine assumes that NAME contains no
971971
** special character and therefore does not decode it.
972972
**
973
-** If NAME begins with another other than a lower-case letter then
973
+** If NAME begins with something other than a lower-case letter then
974974
** the entire NAME=VALUE term is ignored. Hence:
975975
**
976976
** * cookies and query parameters that have uppercase names
977977
** are ignored.
978978
**
@@ -1682,11 +1682,11 @@
16821682
** be extended in the future.
16831683
**
16841684
** Checks are omitted for any logged-in user.
16851685
**
16861686
** This is the primary defense against attack. Fossil should easily be
1687
-** proof against SQL injection and XSS attacks even without without this
1687
+** proof against SQL injection and XSS attacks even without this
16881688
** routine. Rather, this is an attempt to avoid denial-of-service caused
16891689
** by persistent spiders that hammer the server with dozens or hundreds of
16901690
** probes per seconds as they look for vulnerabilities. In other
16911691
** words, this is an effort to reduce the CPU load imposed by malicious
16921692
** spiders. Though those routine might help make attacks harder, it is
@@ -2830,11 +2830,11 @@
28302830
if( fossil_system(zBrowser)<0 ){
28312831
fossil_warning("cannot start browser: %s\n", zBrowser);
28322832
}
28332833
}
28342834
2835
- /* What for incomming requests. For each request, fork() a child process
2835
+ /* What for incoming requests. For each request, fork() a child process
28362836
** to deal with that request. The child process returns. The parent
28372837
** keeps on listening and never returns.
28382838
*/
28392839
while( 1 ){
28402840
#if FOSSIL_MAX_CONNECTIONS>0
28412841
--- src/cgi.c
+++ src/cgi.c
@@ -13,11 +13,11 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file began as a set of C functions and procedures used intepret
19 ** CGI environment variables for Fossil web pages that were invoked by
20 ** CGI. That's where the file name comes from. But over the years it
21 ** has grown to incorporate lots of related functionality, including:
22 **
23 ** * Interpreting CGI environment variables when Fossil is run as
@@ -146,11 +146,11 @@
146 **
147 ** Do not confuse the content header with the HTTP header. The content header
148 ** is generated by downstream code. The HTTP header is generated by the
149 ** cgi_reply() routine below.
150 **
151 ** The content header and contenty body are *approximately* the <head>
152 ** element and the <body> elements for HTML replies. However this is only
153 ** approximate. The content header also includes parts of <body> that
154 ** show the banner and menu bar at the top of each page. Also note that
155 ** not all replies are HTML, but there can still be separate header and
156 ** body sections of the content.
@@ -942,12 +942,12 @@
942 }
943 return cnt;
944 }
945
946 /*
947 ** Add an environment varaible value to the parameter set. The zName
948 ** portion is fixed but a copy is be made of zValue.
949 */
950 void cgi_setenv(const char *zName, const char *zValue){
951 cgi_set_parameter_nocopy(zName, fossil_strdup(zValue), 0);
952 }
953
@@ -968,11 +968,11 @@
968 ** Each parameter is of the form NAME=VALUE. Both the NAME and the
969 ** VALUE may be url-encoded ("+" for space, "%HH" for other special
970 ** characters). But this routine assumes that NAME contains no
971 ** special character and therefore does not decode it.
972 **
973 ** If NAME begins with another other than a lower-case letter then
974 ** the entire NAME=VALUE term is ignored. Hence:
975 **
976 ** * cookies and query parameters that have uppercase names
977 ** are ignored.
978 **
@@ -1682,11 +1682,11 @@
1682 ** be extended in the future.
1683 **
1684 ** Checks are omitted for any logged-in user.
1685 **
1686 ** This is the primary defense against attack. Fossil should easily be
1687 ** proof against SQL injection and XSS attacks even without without this
1688 ** routine. Rather, this is an attempt to avoid denial-of-service caused
1689 ** by persistent spiders that hammer the server with dozens or hundreds of
1690 ** probes per seconds as they look for vulnerabilities. In other
1691 ** words, this is an effort to reduce the CPU load imposed by malicious
1692 ** spiders. Though those routine might help make attacks harder, it is
@@ -2830,11 +2830,11 @@
2830 if( fossil_system(zBrowser)<0 ){
2831 fossil_warning("cannot start browser: %s\n", zBrowser);
2832 }
2833 }
2834
2835 /* What for incomming requests. For each request, fork() a child process
2836 ** to deal with that request. The child process returns. The parent
2837 ** keeps on listening and never returns.
2838 */
2839 while( 1 ){
2840 #if FOSSIL_MAX_CONNECTIONS>0
2841
--- src/cgi.c
+++ src/cgi.c
@@ -13,11 +13,11 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file began as a set of C functions and procedures used to interpret
19 ** CGI environment variables for Fossil web pages that were invoked by
20 ** CGI. That's where the file name comes from. But over the years it
21 ** has grown to incorporate lots of related functionality, including:
22 **
23 ** * Interpreting CGI environment variables when Fossil is run as
@@ -146,11 +146,11 @@
146 **
147 ** Do not confuse the content header with the HTTP header. The content header
148 ** is generated by downstream code. The HTTP header is generated by the
149 ** cgi_reply() routine below.
150 **
151 ** The content header and content body are *approximately* the <head>
152 ** element and the <body> elements for HTML replies. However this is only
153 ** approximate. The content header also includes parts of <body> that
154 ** show the banner and menu bar at the top of each page. Also note that
155 ** not all replies are HTML, but there can still be separate header and
156 ** body sections of the content.
@@ -942,12 +942,12 @@
942 }
943 return cnt;
944 }
945
946 /*
947 ** Add an environment variable value to the parameter set. The zName
948 ** portion is fixed but a copy is made of zValue.
949 */
950 void cgi_setenv(const char *zName, const char *zValue){
951 cgi_set_parameter_nocopy(zName, fossil_strdup(zValue), 0);
952 }
953
@@ -968,11 +968,11 @@
968 ** Each parameter is of the form NAME=VALUE. Both the NAME and the
969 ** VALUE may be url-encoded ("+" for space, "%HH" for other special
970 ** characters). But this routine assumes that NAME contains no
971 ** special character and therefore does not decode it.
972 **
973 ** If NAME begins with something other than a lower-case letter then
974 ** the entire NAME=VALUE term is ignored. Hence:
975 **
976 ** * cookies and query parameters that have uppercase names
977 ** are ignored.
978 **
@@ -1682,11 +1682,11 @@
1682 ** be extended in the future.
1683 **
1684 ** Checks are omitted for any logged-in user.
1685 **
1686 ** This is the primary defense against attack. Fossil should easily be
1687 ** proof against SQL injection and XSS attacks even without this
1688 ** routine. Rather, this is an attempt to avoid denial-of-service caused
1689 ** by persistent spiders that hammer the server with dozens or hundreds of
1690 ** probes per seconds as they look for vulnerabilities. In other
1691 ** words, this is an effort to reduce the CPU load imposed by malicious
1692 ** spiders. Though those routine might help make attacks harder, it is
@@ -2830,11 +2830,11 @@
2830 if( fossil_system(zBrowser)<0 ){
2831 fossil_warning("cannot start browser: %s\n", zBrowser);
2832 }
2833 }
2834
2835 /* What for incoming requests. For each request, fork() a child process
2836 ** to deal with that request. The child process returns. The parent
2837 ** keeps on listening and never returns.
2838 */
2839 while( 1 ){
2840 #if FOSSIL_MAX_CONNECTIONS>0
2841
+1 -1
--- src/chat.c
+++ src/chat.c
@@ -443,11 +443,11 @@
443443
const char *zUserName;
444444
login_check_credentials();
445445
if( 0==g.perm.Chat ) {
446446
chat_emit_permissions_error(0);
447447
return;
448
- }else if( 0==cgi_csrf_safe(1) ){
448
+ }else if( g.eAuthMethod==AUTH_COOKIE && 0==cgi_csrf_safe(1) ){
449449
chat_emit_csrf_error();
450450
return;
451451
}
452452
zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
453453
nByte = atoi(PD("file:bytes","0"));
454454
--- src/chat.c
+++ src/chat.c
@@ -443,11 +443,11 @@
443 const char *zUserName;
444 login_check_credentials();
445 if( 0==g.perm.Chat ) {
446 chat_emit_permissions_error(0);
447 return;
448 }else if( 0==cgi_csrf_safe(1) ){
449 chat_emit_csrf_error();
450 return;
451 }
452 zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
453 nByte = atoi(PD("file:bytes","0"));
454
--- src/chat.c
+++ src/chat.c
@@ -443,11 +443,11 @@
443 const char *zUserName;
444 login_check_credentials();
445 if( 0==g.perm.Chat ) {
446 chat_emit_permissions_error(0);
447 return;
448 }else if( g.eAuthMethod==AUTH_COOKIE && 0==cgi_csrf_safe(1) ){
449 chat_emit_csrf_error();
450 return;
451 }
452 zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
453 nByte = atoi(PD("file:bytes","0"));
454
+32 -9
--- src/checkin.c
+++ src/checkin.c
@@ -484,11 +484,11 @@
484484
{"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY },
485485
};
486486
487487
Blob report = BLOB_INITIALIZER;
488488
enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES;
489
- /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
489
+ /* --sha1sum is an undocumented alias for --hash for backwards compatibility */
490490
int useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
491491
int showHdr = command==CHANGES && find_option("header", 0, 0);
492492
int verboseFlag = command==CHANGES && find_option("verbose", "v", 0);
493493
const char *zIgnoreFlag = find_option("ignore", 0, 1);
494494
unsigned scanFlags = 0;
@@ -714,16 +714,17 @@
714714
}
715715
716716
/*
717717
** Take care of -r version of ls command
718718
*/
719
-static void ls_cmd_rev(
719
+void ls_cmd_rev(
720720
const char *zRev, /* Revision string given */
721721
int verboseFlag, /* Verbose flag given */
722722
int showAge, /* Age flag given */
723723
int showFileHash, /* Show file hash flag given */
724724
int showCkinHash, /* Show check-in hash flag given */
725
+ int showCkinInfo, /* Show check-in infos */
725726
int timeOrder, /* Order by time flag given */
726727
int treeFmt /* Show output in the tree format */
727728
){
728729
Stmt q;
729730
char *zOrderBy = "pathname COLLATE nocase";
@@ -763,22 +764,36 @@
763764
if( timeOrder ){
764765
zOrderBy = "mtime DESC";
765766
}
766767
767768
compute_fileage(rid,0);
768
- db_prepare(&q,
769
+ if( showCkinInfo ){
770
+ db_prepare(&q,
771
+ "SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
772
+ " bfh.size, fileage.uuid, bch.uuid,\n"
773
+ " coalesce(e.ecomment, e.comment), coalesce(e.euser, e.user)\n"
774
+ " FROM fileage, blob bfh, blob bch, event e\n"
775
+ " WHERE bfh.rid=fileage.fid AND bch.rid=fileage.mid\n"
776
+ " AND e.objid = fileage.mid %s\n"
777
+ " ORDER BY %s;",
778
+ blob_sql_text(&where),
779
+ zOrderBy /*safe-for-%s*/
780
+ );
781
+ }else{
782
+ db_prepare(&q,
769783
"SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
770784
" bfh.size, fileage.uuid %s\n"
771785
" FROM fileage, blob bfh %s\n"
772786
" WHERE bfh.rid=fileage.fid %s %s\n"
773
- " ORDER BY %s;",
787
+ " ORDER BY %s;",
774788
showCkinHash ? ", bch.uuid" : "",
775789
showCkinHash ? ", blob bch" : "",
776790
showCkinHash ? "\n AND bch.rid=fileage.mid" : "",
777791
blob_sql_text(&where),
778792
zOrderBy /*safe-for-%s*/
779
- );
793
+ );
794
+ }
780795
blob_reset(&where);
781796
if( treeFmt ) blob_init(&out, 0, 0);
782797
783798
while( db_step(&q)==SQLITE_ROW ){
784799
const char *zTime = db_column_text(&q,0);
@@ -785,11 +800,18 @@
785800
const char *zFile = db_column_text(&q,1);
786801
int size = db_column_int(&q,2);
787802
if( treeFmt ){
788803
blob_appendf(&out, "%s\n", zFile);
789804
}else if( verboseFlag ){
790
- if( showFileHash ){
805
+ if( showCkinInfo ){
806
+ const char *zUuidC = db_column_text(&q,4);
807
+ const char *zComm = db_column_text(&q,5);
808
+ const char *zUser = db_column_text(&q,6);
809
+ fossil_print("%s [%S] %12s ", zTime, zUuidC, zUser);
810
+ if( showCkinInfo==2 ) fossil_print("%-20.20s ", zComm);
811
+ fossil_print("%s\n", zFile);
812
+ }else if( showFileHash ){
791813
const char *zUuidF = db_column_text(&q,3);
792814
fossil_print("%s %7d [%S] %s\n", zTime, size, zUuidF, zFile);
793815
}else if( showCkinHash ){
794816
const char *zUuidC = db_column_text(&q,4);
795817
fossil_print("%s %7d [%S] %s\n", zTime, size, zUuidC, zFile);
@@ -887,11 +909,12 @@
887909
}
888910
889911
if( zRev!=0 ){
890912
db_find_and_open_repository(0, 0);
891913
verify_all_options();
892
- ls_cmd_rev(zRev,verboseFlag,showAge,showFHash,showCHash,timeOrder,treeFmt);
914
+ ls_cmd_rev(zRev, verboseFlag, showAge, showFHash, showCHash, 0, timeOrder,
915
+ treeFmt);
893916
return;
894917
}else if( find_option("R",0,1)!=0 ){
895918
fossil_fatal("the -r is required in addition to -R");
896919
}
897920
@@ -1010,11 +1033,11 @@
10101033
10111034
zRev = find_option("r","r",1);
10121035
if( zRev==0 ) zRev = "current";
10131036
db_find_and_open_repository(0, 0);
10141037
verify_all_options();
1015
- ls_cmd_rev(zRev,0,0,0,0,0,1);
1038
+ ls_cmd_rev(zRev,0,0,0,0,0,0,1);
10161039
}
10171040
10181041
/*
10191042
** COMMAND: extras
10201043
**
@@ -2562,11 +2585,11 @@
25622585
char *zNewBranch = 0; /* The branch name after update */
25632586
int ckComFlgs; /* Flags passed to verify_comment() */
25642587
25652588
memset(&sCiInfo, 0, sizeof(sCiInfo));
25662589
url_proxy_options();
2567
- /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2590
+ /* --sha1sum is an undocumented alias for --hash for backwards compatibility */
25682591
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
25692592
noSign = find_option("nosign",0,0)!=0;
25702593
if( find_option("nosync",0,0) ) g.fNoSync = 1;
25712594
privateFlag = find_option("private",0,0)!=0;
25722595
forceDelta = find_option("delta",0,0)!=0;
25732596
--- src/checkin.c
+++ src/checkin.c
@@ -484,11 +484,11 @@
484 {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY },
485 };
486
487 Blob report = BLOB_INITIALIZER;
488 enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES;
489 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
490 int useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
491 int showHdr = command==CHANGES && find_option("header", 0, 0);
492 int verboseFlag = command==CHANGES && find_option("verbose", "v", 0);
493 const char *zIgnoreFlag = find_option("ignore", 0, 1);
494 unsigned scanFlags = 0;
@@ -714,16 +714,17 @@
714 }
715
716 /*
717 ** Take care of -r version of ls command
718 */
719 static void ls_cmd_rev(
720 const char *zRev, /* Revision string given */
721 int verboseFlag, /* Verbose flag given */
722 int showAge, /* Age flag given */
723 int showFileHash, /* Show file hash flag given */
724 int showCkinHash, /* Show check-in hash flag given */
 
725 int timeOrder, /* Order by time flag given */
726 int treeFmt /* Show output in the tree format */
727 ){
728 Stmt q;
729 char *zOrderBy = "pathname COLLATE nocase";
@@ -763,22 +764,36 @@
763 if( timeOrder ){
764 zOrderBy = "mtime DESC";
765 }
766
767 compute_fileage(rid,0);
768 db_prepare(&q,
 
 
 
 
 
 
 
 
 
 
 
 
 
769 "SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
770 " bfh.size, fileage.uuid %s\n"
771 " FROM fileage, blob bfh %s\n"
772 " WHERE bfh.rid=fileage.fid %s %s\n"
773 " ORDER BY %s;",
774 showCkinHash ? ", bch.uuid" : "",
775 showCkinHash ? ", blob bch" : "",
776 showCkinHash ? "\n AND bch.rid=fileage.mid" : "",
777 blob_sql_text(&where),
778 zOrderBy /*safe-for-%s*/
779 );
 
780 blob_reset(&where);
781 if( treeFmt ) blob_init(&out, 0, 0);
782
783 while( db_step(&q)==SQLITE_ROW ){
784 const char *zTime = db_column_text(&q,0);
@@ -785,11 +800,18 @@
785 const char *zFile = db_column_text(&q,1);
786 int size = db_column_int(&q,2);
787 if( treeFmt ){
788 blob_appendf(&out, "%s\n", zFile);
789 }else if( verboseFlag ){
790 if( showFileHash ){
 
 
 
 
 
 
 
791 const char *zUuidF = db_column_text(&q,3);
792 fossil_print("%s %7d [%S] %s\n", zTime, size, zUuidF, zFile);
793 }else if( showCkinHash ){
794 const char *zUuidC = db_column_text(&q,4);
795 fossil_print("%s %7d [%S] %s\n", zTime, size, zUuidC, zFile);
@@ -887,11 +909,12 @@
887 }
888
889 if( zRev!=0 ){
890 db_find_and_open_repository(0, 0);
891 verify_all_options();
892 ls_cmd_rev(zRev,verboseFlag,showAge,showFHash,showCHash,timeOrder,treeFmt);
 
893 return;
894 }else if( find_option("R",0,1)!=0 ){
895 fossil_fatal("the -r is required in addition to -R");
896 }
897
@@ -1010,11 +1033,11 @@
1010
1011 zRev = find_option("r","r",1);
1012 if( zRev==0 ) zRev = "current";
1013 db_find_and_open_repository(0, 0);
1014 verify_all_options();
1015 ls_cmd_rev(zRev,0,0,0,0,0,1);
1016 }
1017
1018 /*
1019 ** COMMAND: extras
1020 **
@@ -2562,11 +2585,11 @@
2562 char *zNewBranch = 0; /* The branch name after update */
2563 int ckComFlgs; /* Flags passed to verify_comment() */
2564
2565 memset(&sCiInfo, 0, sizeof(sCiInfo));
2566 url_proxy_options();
2567 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2568 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
2569 noSign = find_option("nosign",0,0)!=0;
2570 if( find_option("nosync",0,0) ) g.fNoSync = 1;
2571 privateFlag = find_option("private",0,0)!=0;
2572 forceDelta = find_option("delta",0,0)!=0;
2573
--- src/checkin.c
+++ src/checkin.c
@@ -484,11 +484,11 @@
484 {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY },
485 };
486
487 Blob report = BLOB_INITIALIZER;
488 enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES;
489 /* --sha1sum is an undocumented alias for --hash for backwards compatibility */
490 int useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
491 int showHdr = command==CHANGES && find_option("header", 0, 0);
492 int verboseFlag = command==CHANGES && find_option("verbose", "v", 0);
493 const char *zIgnoreFlag = find_option("ignore", 0, 1);
494 unsigned scanFlags = 0;
@@ -714,16 +714,17 @@
714 }
715
716 /*
717 ** Take care of -r version of ls command
718 */
719 void ls_cmd_rev(
720 const char *zRev, /* Revision string given */
721 int verboseFlag, /* Verbose flag given */
722 int showAge, /* Age flag given */
723 int showFileHash, /* Show file hash flag given */
724 int showCkinHash, /* Show check-in hash flag given */
725 int showCkinInfo, /* Show check-in infos */
726 int timeOrder, /* Order by time flag given */
727 int treeFmt /* Show output in the tree format */
728 ){
729 Stmt q;
730 char *zOrderBy = "pathname COLLATE nocase";
@@ -763,22 +764,36 @@
764 if( timeOrder ){
765 zOrderBy = "mtime DESC";
766 }
767
768 compute_fileage(rid,0);
769 if( showCkinInfo ){
770 db_prepare(&q,
771 "SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
772 " bfh.size, fileage.uuid, bch.uuid,\n"
773 " coalesce(e.ecomment, e.comment), coalesce(e.euser, e.user)\n"
774 " FROM fileage, blob bfh, blob bch, event e\n"
775 " WHERE bfh.rid=fileage.fid AND bch.rid=fileage.mid\n"
776 " AND e.objid = fileage.mid %s\n"
777 " ORDER BY %s;",
778 blob_sql_text(&where),
779 zOrderBy /*safe-for-%s*/
780 );
781 }else{
782 db_prepare(&q,
783 "SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
784 " bfh.size, fileage.uuid %s\n"
785 " FROM fileage, blob bfh %s\n"
786 " WHERE bfh.rid=fileage.fid %s %s\n"
787 " ORDER BY %s;",
788 showCkinHash ? ", bch.uuid" : "",
789 showCkinHash ? ", blob bch" : "",
790 showCkinHash ? "\n AND bch.rid=fileage.mid" : "",
791 blob_sql_text(&where),
792 zOrderBy /*safe-for-%s*/
793 );
794 }
795 blob_reset(&where);
796 if( treeFmt ) blob_init(&out, 0, 0);
797
798 while( db_step(&q)==SQLITE_ROW ){
799 const char *zTime = db_column_text(&q,0);
@@ -785,11 +800,18 @@
800 const char *zFile = db_column_text(&q,1);
801 int size = db_column_int(&q,2);
802 if( treeFmt ){
803 blob_appendf(&out, "%s\n", zFile);
804 }else if( verboseFlag ){
805 if( showCkinInfo ){
806 const char *zUuidC = db_column_text(&q,4);
807 const char *zComm = db_column_text(&q,5);
808 const char *zUser = db_column_text(&q,6);
809 fossil_print("%s [%S] %12s ", zTime, zUuidC, zUser);
810 if( showCkinInfo==2 ) fossil_print("%-20.20s ", zComm);
811 fossil_print("%s\n", zFile);
812 }else if( showFileHash ){
813 const char *zUuidF = db_column_text(&q,3);
814 fossil_print("%s %7d [%S] %s\n", zTime, size, zUuidF, zFile);
815 }else if( showCkinHash ){
816 const char *zUuidC = db_column_text(&q,4);
817 fossil_print("%s %7d [%S] %s\n", zTime, size, zUuidC, zFile);
@@ -887,11 +909,12 @@
909 }
910
911 if( zRev!=0 ){
912 db_find_and_open_repository(0, 0);
913 verify_all_options();
914 ls_cmd_rev(zRev, verboseFlag, showAge, showFHash, showCHash, 0, timeOrder,
915 treeFmt);
916 return;
917 }else if( find_option("R",0,1)!=0 ){
918 fossil_fatal("the -r is required in addition to -R");
919 }
920
@@ -1010,11 +1033,11 @@
1033
1034 zRev = find_option("r","r",1);
1035 if( zRev==0 ) zRev = "current";
1036 db_find_and_open_repository(0, 0);
1037 verify_all_options();
1038 ls_cmd_rev(zRev,0,0,0,0,0,0,1);
1039 }
1040
1041 /*
1042 ** COMMAND: extras
1043 **
@@ -2562,11 +2585,11 @@
2585 char *zNewBranch = 0; /* The branch name after update */
2586 int ckComFlgs; /* Flags passed to verify_comment() */
2587
2588 memset(&sCiInfo, 0, sizeof(sCiInfo));
2589 url_proxy_options();
2590 /* --sha1sum is an undocumented alias for --hash for backwards compatibility */
2591 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
2592 noSign = find_option("nosign",0,0)!=0;
2593 if( find_option("nosync",0,0) ) g.fNoSync = 1;
2594 privateFlag = find_option("private",0,0)!=0;
2595 forceDelta = find_option("delta",0,0)!=0;
2596
+19 -21
--- src/checkout.c
+++ src/checkout.c
@@ -438,43 +438,40 @@
438438
** COMMAND: get
439439
**
440440
** Usage: %fossil get URL ?VERSION? ?OPTIONS?
441441
**
442442
** Download a single check-in from a remote repository named URL and
443
-** unpack all of the files locally. The check-in is identified by VERSION.
444
-**
445
-** URL can be a traditional URL like one of:
443
+** unpack all of the files into a subdirectory. The specific check-in
444
+** to download is identified by VERSION. If VERSION is omitted, the
445
+** latest trunk check-in is used. The URL can be a traditional "https:",
446
+** "ssh:", or "file:" URL similar to the examples shown below, or it can
447
+** be the name of a local repository/
446448
**
447449
** * https://domain.com/project
448450
** * ssh://my-server/project.fossil
449451
** * file:/home/user/Fossils/project.fossil
450452
**
451
-** Or URL can be just the name of a local repository without the "file:"
452
-** prefix.
453
-**
454453
** This command works by downloading an SQL archive of the requested
455454
** check-in and then extracting all the files from the archive.
456455
**
457456
** Options:
458
-** --dest DIRECTORY Extract files into DIRECTORY. Use "--dest ."
459
-** to extract into the local directory.
460
-**
461
-** -f|--force Overwrite existing files
462
-**
463
-** --list List all the files that would have been checked
464
-** out but do not actually write anything to the
465
-** filesystem.
466
-**
467
-** --sqlar ARCHIVE Store the check-out in an SQL-archive rather
468
-** than unpacking them into separate files.
469
-**
470
-** -v|--verbose Show all files as they are extracted
457
+** --dest DIRECTORY Extract files into DIRECTORY. Use "--dest ." to
458
+** extract into the local directory. If this option is
459
+** omitted, Fossil invents a subdirectory name derived
460
+** from base filename in the URL and from the VERSION.
461
+** -f|--force Overwrite existing files
462
+** --list List all the files that would have been checked
463
+** out but do not actually write anything to the
464
+** filesystem.
465
+** --sqlar ARCHIVE Leave the check-out in an SQL-archive named ARCHIVE
466
+** rather than unpacking into separate files.
467
+** -v|--verbose Show all files as they are extracted
471468
*/
472469
void get_cmd(void){
473470
int forceFlag = find_option("force","f",0)!=0;
474471
int bVerbose = find_option("verbose","v",0)!=0;
475
- int bQuiet = find_option("quiet","q",0)!=0;
472
+ int bQuiet = g.fQuiet;
476473
int bDebug = find_option("debug",0,0)!=0;
477474
int bList = find_option("list",0,0)!=0;
478475
const char *zSqlArchive = find_option("sqlar",0,1);
479476
const char *z;
480477
char *zDest = 0; /* Where to store results */
@@ -596,11 +593,11 @@
596593
}
597594
if( rc!=SQLITE_OK ){
598595
fossil_fatal("Cannot create an in-memory database: %s",
599596
sqlite3_errmsg(db));
600597
}
601
- zSql = mprintf("SELECT name, mode, sz, data FROM sqlar"
598
+ zSql = mprintf("SELECT name, mode, sz, data, mtime FROM sqlar"
602599
" WHERE name GLOB '%q*'", zDest);
603600
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
604601
fossil_free(zSql);
605602
if( rc!=0 ){
606603
fossil_fatal("SQL error: %s\n", sqlite3_errmsg(db));
@@ -636,10 +633,11 @@
636633
blob_write_to_file(&file, zFilename);
637634
if( mode & 0x40 ){
638635
file_setexe(zFilename, 1);
639636
}
640637
blob_zero(&file);
638
+ file_set_mtime(zFilename, sqlite3_column_int64(pStmt,4));
641639
if( bVerbose ){
642640
fossil_print("%s\n", zFilename);
643641
}
644642
}
645643
}
646644
--- src/checkout.c
+++ src/checkout.c
@@ -438,43 +438,40 @@
438 ** COMMAND: get
439 **
440 ** Usage: %fossil get URL ?VERSION? ?OPTIONS?
441 **
442 ** Download a single check-in from a remote repository named URL and
443 ** unpack all of the files locally. The check-in is identified by VERSION.
444 **
445 ** URL can be a traditional URL like one of:
 
 
446 **
447 ** * https://domain.com/project
448 ** * ssh://my-server/project.fossil
449 ** * file:/home/user/Fossils/project.fossil
450 **
451 ** Or URL can be just the name of a local repository without the "file:"
452 ** prefix.
453 **
454 ** This command works by downloading an SQL archive of the requested
455 ** check-in and then extracting all the files from the archive.
456 **
457 ** Options:
458 ** --dest DIRECTORY Extract files into DIRECTORY. Use "--dest ."
459 ** to extract into the local directory.
460 **
461 ** -f|--force Overwrite existing files
462 **
463 ** --list List all the files that would have been checked
464 ** out but do not actually write anything to the
465 ** filesystem.
466 **
467 ** --sqlar ARCHIVE Store the check-out in an SQL-archive rather
468 ** than unpacking them into separate files.
469 **
470 ** -v|--verbose Show all files as they are extracted
471 */
472 void get_cmd(void){
473 int forceFlag = find_option("force","f",0)!=0;
474 int bVerbose = find_option("verbose","v",0)!=0;
475 int bQuiet = find_option("quiet","q",0)!=0;
476 int bDebug = find_option("debug",0,0)!=0;
477 int bList = find_option("list",0,0)!=0;
478 const char *zSqlArchive = find_option("sqlar",0,1);
479 const char *z;
480 char *zDest = 0; /* Where to store results */
@@ -596,11 +593,11 @@
596 }
597 if( rc!=SQLITE_OK ){
598 fossil_fatal("Cannot create an in-memory database: %s",
599 sqlite3_errmsg(db));
600 }
601 zSql = mprintf("SELECT name, mode, sz, data FROM sqlar"
602 " WHERE name GLOB '%q*'", zDest);
603 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
604 fossil_free(zSql);
605 if( rc!=0 ){
606 fossil_fatal("SQL error: %s\n", sqlite3_errmsg(db));
@@ -636,10 +633,11 @@
636 blob_write_to_file(&file, zFilename);
637 if( mode & 0x40 ){
638 file_setexe(zFilename, 1);
639 }
640 blob_zero(&file);
 
641 if( bVerbose ){
642 fossil_print("%s\n", zFilename);
643 }
644 }
645 }
646
--- src/checkout.c
+++ src/checkout.c
@@ -438,43 +438,40 @@
438 ** COMMAND: get
439 **
440 ** Usage: %fossil get URL ?VERSION? ?OPTIONS?
441 **
442 ** Download a single check-in from a remote repository named URL and
443 ** unpack all of the files into a subdirectory. The specific check-in
444 ** to download is identified by VERSION. If VERSION is omitted, the
445 ** latest trunk check-in is used. The URL can be a traditional "https:",
446 ** "ssh:", or "file:" URL similar to the examples shown below, or it can
447 ** be the name of a local repository/
448 **
449 ** * https://domain.com/project
450 ** * ssh://my-server/project.fossil
451 ** * file:/home/user/Fossils/project.fossil
452 **
 
 
 
453 ** This command works by downloading an SQL archive of the requested
454 ** check-in and then extracting all the files from the archive.
455 **
456 ** Options:
457 ** --dest DIRECTORY Extract files into DIRECTORY. Use "--dest ." to
458 ** extract into the local directory. If this option is
459 ** omitted, Fossil invents a subdirectory name derived
460 ** from base filename in the URL and from the VERSION.
461 ** -f|--force Overwrite existing files
462 ** --list List all the files that would have been checked
463 ** out but do not actually write anything to the
464 ** filesystem.
465 ** --sqlar ARCHIVE Leave the check-out in an SQL-archive named ARCHIVE
466 ** rather than unpacking into separate files.
467 ** -v|--verbose Show all files as they are extracted
 
 
468 */
469 void get_cmd(void){
470 int forceFlag = find_option("force","f",0)!=0;
471 int bVerbose = find_option("verbose","v",0)!=0;
472 int bQuiet = g.fQuiet;
473 int bDebug = find_option("debug",0,0)!=0;
474 int bList = find_option("list",0,0)!=0;
475 const char *zSqlArchive = find_option("sqlar",0,1);
476 const char *z;
477 char *zDest = 0; /* Where to store results */
@@ -596,11 +593,11 @@
593 }
594 if( rc!=SQLITE_OK ){
595 fossil_fatal("Cannot create an in-memory database: %s",
596 sqlite3_errmsg(db));
597 }
598 zSql = mprintf("SELECT name, mode, sz, data, mtime FROM sqlar"
599 " WHERE name GLOB '%q*'", zDest);
600 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
601 fossil_free(zSql);
602 if( rc!=0 ){
603 fossil_fatal("SQL error: %s\n", sqlite3_errmsg(db));
@@ -636,10 +633,11 @@
633 blob_write_to_file(&file, zFilename);
634 if( mode & 0x40 ){
635 file_setexe(zFilename, 1);
636 }
637 blob_zero(&file);
638 file_set_mtime(zFilename, sqlite3_column_int64(pStmt,4));
639 if( bVerbose ){
640 fossil_print("%s\n", zFilename);
641 }
642 }
643 }
644
+1 -1
--- src/color.c
+++ src/color.c
@@ -215,11 +215,11 @@
215215
216216
/*
217217
** SETTING: raw-bgcolor boolean default=off
218218
**
219219
** Fossil usually tries to adjust user-specified background colors
220
-** for checkins so that the text is readable and so that the color
220
+** for check-ins so that the text is readable and so that the color
221221
** is not too garish. This setting disables that filter. When
222222
** this setting is on, the user-selected background colors are shown
223223
** exactly as requested.
224224
*/
225225
226226
--- src/color.c
+++ src/color.c
@@ -215,11 +215,11 @@
215
216 /*
217 ** SETTING: raw-bgcolor boolean default=off
218 **
219 ** Fossil usually tries to adjust user-specified background colors
220 ** for checkins so that the text is readable and so that the color
221 ** is not too garish. This setting disables that filter. When
222 ** this setting is on, the user-selected background colors are shown
223 ** exactly as requested.
224 */
225
226
--- src/color.c
+++ src/color.c
@@ -215,11 +215,11 @@
215
216 /*
217 ** SETTING: raw-bgcolor boolean default=off
218 **
219 ** Fossil usually tries to adjust user-specified background colors
220 ** for check-ins so that the text is readable and so that the color
221 ** is not too garish. This setting disables that filter. When
222 ** this setting is on, the user-selected background colors are shown
223 ** exactly as requested.
224 */
225
226
+1 -1
--- src/comformat.c
+++ src/comformat.c
@@ -750,11 +750,11 @@
750750
** handling the value of a C-card from a manifest.
751751
** --file FILE Omit the TEXT argument and read the comment text
752752
** from FILE.
753753
** --indent Number of spaces to indent (default (-1) is to
754754
** auto-detect). Zero means no indent.
755
-** --orig FILE Take the value for the ORIGTEXT argumetn from FILE.
755
+** --orig FILE Take the value for the ORIGTEXT argument from FILE.
756756
** --origbreak Attempt to break when the original comment text
757757
** is detected.
758758
** --trimcrlf Enable trimming of leading/trailing CR/LF.
759759
** --trimspace Enable trimming of leading/trailing spaces.
760760
** --whitespace Keep all internal whitespace.
761761
--- src/comformat.c
+++ src/comformat.c
@@ -750,11 +750,11 @@
750 ** handling the value of a C-card from a manifest.
751 ** --file FILE Omit the TEXT argument and read the comment text
752 ** from FILE.
753 ** --indent Number of spaces to indent (default (-1) is to
754 ** auto-detect). Zero means no indent.
755 ** --orig FILE Take the value for the ORIGTEXT argumetn from FILE.
756 ** --origbreak Attempt to break when the original comment text
757 ** is detected.
758 ** --trimcrlf Enable trimming of leading/trailing CR/LF.
759 ** --trimspace Enable trimming of leading/trailing spaces.
760 ** --whitespace Keep all internal whitespace.
761
--- src/comformat.c
+++ src/comformat.c
@@ -750,11 +750,11 @@
750 ** handling the value of a C-card from a manifest.
751 ** --file FILE Omit the TEXT argument and read the comment text
752 ** from FILE.
753 ** --indent Number of spaces to indent (default (-1) is to
754 ** auto-detect). Zero means no indent.
755 ** --orig FILE Take the value for the ORIGTEXT argument from FILE.
756 ** --origbreak Attempt to break when the original comment text
757 ** is detected.
758 ** --trimcrlf Enable trimming of leading/trailing CR/LF.
759 ** --trimspace Enable trimming of leading/trailing spaces.
760 ** --whitespace Keep all internal whitespace.
761
+1 -1
--- src/config.h
+++ src/config.h
@@ -39,11 +39,11 @@
3939
4040
#ifdef HAVE_AUTOCONFIG_H
4141
#include "autoconfig.h"
4242
#endif
4343
44
-/* Enable the hardened SHA1 implemenation by default */
44
+/* Enable the hardened SHA1 implementation by default */
4545
#ifndef FOSSIL_HARDENED_SHA1
4646
# define FOSSIL_HARDENED_SHA1 1
4747
#endif
4848
4949
#ifndef _RC_COMPILE_
5050
--- src/config.h
+++ src/config.h
@@ -39,11 +39,11 @@
39
40 #ifdef HAVE_AUTOCONFIG_H
41 #include "autoconfig.h"
42 #endif
43
44 /* Enable the hardened SHA1 implemenation by default */
45 #ifndef FOSSIL_HARDENED_SHA1
46 # define FOSSIL_HARDENED_SHA1 1
47 #endif
48
49 #ifndef _RC_COMPILE_
50
--- src/config.h
+++ src/config.h
@@ -39,11 +39,11 @@
39
40 #ifdef HAVE_AUTOCONFIG_H
41 #include "autoconfig.h"
42 #endif
43
44 /* Enable the hardened SHA1 implementation by default */
45 #ifndef FOSSIL_HARDENED_SHA1
46 # define FOSSIL_HARDENED_SHA1 1
47 #endif
48
49 #ifndef _RC_COMPILE_
50
+1 -1
--- src/configure.c
+++ src/configure.c
@@ -376,11 +376,11 @@
376376
** NAME-specific notes:
377377
**
378378
** - /reportftm's $MTIME is in Julian, not the Unix epoch.
379379
*/
380380
void configure_receive(const char *zName, Blob *pContent, int groupMask){
381
- int checkMask; /* Masks for which we must first check existance of tables */
381
+ int checkMask; /* Masks for which we must first check existence of tables */
382382
383383
checkMask = CONFIGSET_SCRIBER;
384384
if( zName[0]=='/' ){
385385
/* The new format */
386386
char *azToken[24];
387387
--- src/configure.c
+++ src/configure.c
@@ -376,11 +376,11 @@
376 ** NAME-specific notes:
377 **
378 ** - /reportftm's $MTIME is in Julian, not the Unix epoch.
379 */
380 void configure_receive(const char *zName, Blob *pContent, int groupMask){
381 int checkMask; /* Masks for which we must first check existance of tables */
382
383 checkMask = CONFIGSET_SCRIBER;
384 if( zName[0]=='/' ){
385 /* The new format */
386 char *azToken[24];
387
--- src/configure.c
+++ src/configure.c
@@ -376,11 +376,11 @@
376 ** NAME-specific notes:
377 **
378 ** - /reportftm's $MTIME is in Julian, not the Unix epoch.
379 */
380 void configure_receive(const char *zName, Blob *pContent, int groupMask){
381 int checkMask; /* Masks for which we must first check existence of tables */
382
383 checkMask = CONFIGSET_SCRIBER;
384 if( zName[0]=='/' ){
385 /* The new format */
386 char *azToken[24];
387
+8 -8
--- src/content.c
+++ src/content.c
@@ -496,11 +496,11 @@
496496
** zUuid is the UUID of the artifact, if it is specified. When srcId is
497497
** specified then zUuid must always be specified. If srcId is zero,
498498
** and zUuid is zero then the correct zUuid is computed from pBlob.
499499
**
500500
** If the record already exists but is a phantom, the pBlob content
501
-** is inserted and the phatom becomes a real record.
501
+** is inserted and the phantom becomes a real record.
502502
**
503503
** The original content of pBlob is not disturbed. The caller continues
504504
** to be responsible for pBlob. This routine does *not* take over
505505
** responsibility for freeing pBlob.
506506
*/
@@ -651,11 +651,11 @@
651651
** pBlob is uncompressed and is not deltaed. It is exactly the content
652652
** to be inserted.
653653
**
654654
** The original content of pBlob is not disturbed. The caller continues
655655
** to be responsible for pBlob. This routine does *not* take over
656
-** responsiblity for freeing pBlob.
656
+** responsibility for freeing pBlob.
657657
*/
658658
int content_put(Blob *pBlob){
659659
return content_put_ex(pBlob, 0, 0, 0, 0);
660660
}
661661
@@ -793,11 +793,11 @@
793793
}
794794
795795
/*
796796
** Try to change the storage of rid so that it is a delta from one
797797
** of the artifacts given in aSrc[0]..aSrc[nSrc-1]. The aSrc[*] that
798
-** gives the smallest delta is choosen.
798
+** gives the smallest delta is chosen.
799799
**
800800
** If rid is already a delta from some other place then no
801801
** conversion occurs and this is a no-op unless force==1. If force==1,
802802
** then nSrc must also be 1.
803803
**
@@ -864,11 +864,11 @@
864864
int srcid = aSrc[i];
865865
if( srcid==rid ) continue;
866866
if( content_is_private(srcid) && !content_is_private(rid) ) continue;
867867
868868
/* Compute all ancestors of srcid and make sure rid is not one of them.
869
- ** If rid is an ancestor of srcid, then making rid a descendent of srcid
869
+ ** If rid is an ancestor of srcid, then making rid a descendant of srcid
870870
** would create a delta loop. */
871871
s = srcid;
872872
while( (s = delta_source_rid(s))>0 ){
873873
if( s==rid ){
874874
content_undelta(srcid);
@@ -965,11 +965,11 @@
965965
** Options:
966966
** -d|--db-only Run "PRAGMA integrity_check" on the database only.
967967
** No other validation is performed.
968968
** --parse Parse all manifests, wikis, tickets, events, and
969969
** so forth, reporting any errors found.
970
-** -q|--quick Run "PRAGMA quick_check" on the database only.
970
+** --quick Run "PRAGMA quick_check" on the database only.
971971
** No other validation is performed.
972972
*/
973973
void test_integrity(void){
974974
Stmt q;
975975
Blob content;
@@ -979,11 +979,11 @@
979979
int total;
980980
int nCA = 0;
981981
int anCA[10];
982982
int bParse = find_option("parse",0,0)!=0;
983983
int bDbOnly = find_option("db-only","d",0)!=0;
984
- int bQuick = find_option("quick","q",0)!=0;
984
+ int bQuick = find_option("quick",0,0)!=0;
985985
db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
986986
if( bDbOnly || bQuick ){
987987
const char *zType = bQuick ? "quick" : "integrity";
988988
char *zRes;
989989
zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
@@ -1199,11 +1199,11 @@
11991199
** all references are satisfied. Report any referenced artifacts
12001200
** that are missing or shunned.
12011201
**
12021202
** Options:
12031203
** --notshunned Do not report shunned artifacts
1204
-** --quiet Only show output if there are errors
1204
+** -q|--quiet Only show output if there are errors
12051205
*/
12061206
void test_missing(void){
12071207
Stmt q;
12081208
Blob content;
12091209
int nErr = 0;
@@ -1212,11 +1212,11 @@
12121212
Manifest *p;
12131213
unsigned flags = 0;
12141214
int quietFlag;
12151215
12161216
if( find_option("notshunned", 0, 0)!=0 ) flags |= MISSING_SHUNNED;
1217
- quietFlag = find_option("quiet","q",0)!=0;
1217
+ quietFlag = g.fQuiet;
12181218
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
12191219
db_prepare(&q,
12201220
"SELECT mid FROM mlink UNION "
12211221
"SELECT srcid FROM tagxref WHERE srcid>0 UNION "
12221222
"SELECT rid FROM tagxref UNION "
12231223
--- src/content.c
+++ src/content.c
@@ -496,11 +496,11 @@
496 ** zUuid is the UUID of the artifact, if it is specified. When srcId is
497 ** specified then zUuid must always be specified. If srcId is zero,
498 ** and zUuid is zero then the correct zUuid is computed from pBlob.
499 **
500 ** If the record already exists but is a phantom, the pBlob content
501 ** is inserted and the phatom becomes a real record.
502 **
503 ** The original content of pBlob is not disturbed. The caller continues
504 ** to be responsible for pBlob. This routine does *not* take over
505 ** responsibility for freeing pBlob.
506 */
@@ -651,11 +651,11 @@
651 ** pBlob is uncompressed and is not deltaed. It is exactly the content
652 ** to be inserted.
653 **
654 ** The original content of pBlob is not disturbed. The caller continues
655 ** to be responsible for pBlob. This routine does *not* take over
656 ** responsiblity for freeing pBlob.
657 */
658 int content_put(Blob *pBlob){
659 return content_put_ex(pBlob, 0, 0, 0, 0);
660 }
661
@@ -793,11 +793,11 @@
793 }
794
795 /*
796 ** Try to change the storage of rid so that it is a delta from one
797 ** of the artifacts given in aSrc[0]..aSrc[nSrc-1]. The aSrc[*] that
798 ** gives the smallest delta is choosen.
799 **
800 ** If rid is already a delta from some other place then no
801 ** conversion occurs and this is a no-op unless force==1. If force==1,
802 ** then nSrc must also be 1.
803 **
@@ -864,11 +864,11 @@
864 int srcid = aSrc[i];
865 if( srcid==rid ) continue;
866 if( content_is_private(srcid) && !content_is_private(rid) ) continue;
867
868 /* Compute all ancestors of srcid and make sure rid is not one of them.
869 ** If rid is an ancestor of srcid, then making rid a descendent of srcid
870 ** would create a delta loop. */
871 s = srcid;
872 while( (s = delta_source_rid(s))>0 ){
873 if( s==rid ){
874 content_undelta(srcid);
@@ -965,11 +965,11 @@
965 ** Options:
966 ** -d|--db-only Run "PRAGMA integrity_check" on the database only.
967 ** No other validation is performed.
968 ** --parse Parse all manifests, wikis, tickets, events, and
969 ** so forth, reporting any errors found.
970 ** -q|--quick Run "PRAGMA quick_check" on the database only.
971 ** No other validation is performed.
972 */
973 void test_integrity(void){
974 Stmt q;
975 Blob content;
@@ -979,11 +979,11 @@
979 int total;
980 int nCA = 0;
981 int anCA[10];
982 int bParse = find_option("parse",0,0)!=0;
983 int bDbOnly = find_option("db-only","d",0)!=0;
984 int bQuick = find_option("quick","q",0)!=0;
985 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
986 if( bDbOnly || bQuick ){
987 const char *zType = bQuick ? "quick" : "integrity";
988 char *zRes;
989 zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
@@ -1199,11 +1199,11 @@
1199 ** all references are satisfied. Report any referenced artifacts
1200 ** that are missing or shunned.
1201 **
1202 ** Options:
1203 ** --notshunned Do not report shunned artifacts
1204 ** --quiet Only show output if there are errors
1205 */
1206 void test_missing(void){
1207 Stmt q;
1208 Blob content;
1209 int nErr = 0;
@@ -1212,11 +1212,11 @@
1212 Manifest *p;
1213 unsigned flags = 0;
1214 int quietFlag;
1215
1216 if( find_option("notshunned", 0, 0)!=0 ) flags |= MISSING_SHUNNED;
1217 quietFlag = find_option("quiet","q",0)!=0;
1218 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1219 db_prepare(&q,
1220 "SELECT mid FROM mlink UNION "
1221 "SELECT srcid FROM tagxref WHERE srcid>0 UNION "
1222 "SELECT rid FROM tagxref UNION "
1223
--- src/content.c
+++ src/content.c
@@ -496,11 +496,11 @@
496 ** zUuid is the UUID of the artifact, if it is specified. When srcId is
497 ** specified then zUuid must always be specified. If srcId is zero,
498 ** and zUuid is zero then the correct zUuid is computed from pBlob.
499 **
500 ** If the record already exists but is a phantom, the pBlob content
501 ** is inserted and the phantom becomes a real record.
502 **
503 ** The original content of pBlob is not disturbed. The caller continues
504 ** to be responsible for pBlob. This routine does *not* take over
505 ** responsibility for freeing pBlob.
506 */
@@ -651,11 +651,11 @@
651 ** pBlob is uncompressed and is not deltaed. It is exactly the content
652 ** to be inserted.
653 **
654 ** The original content of pBlob is not disturbed. The caller continues
655 ** to be responsible for pBlob. This routine does *not* take over
656 ** responsibility for freeing pBlob.
657 */
658 int content_put(Blob *pBlob){
659 return content_put_ex(pBlob, 0, 0, 0, 0);
660 }
661
@@ -793,11 +793,11 @@
793 }
794
795 /*
796 ** Try to change the storage of rid so that it is a delta from one
797 ** of the artifacts given in aSrc[0]..aSrc[nSrc-1]. The aSrc[*] that
798 ** gives the smallest delta is chosen.
799 **
800 ** If rid is already a delta from some other place then no
801 ** conversion occurs and this is a no-op unless force==1. If force==1,
802 ** then nSrc must also be 1.
803 **
@@ -864,11 +864,11 @@
864 int srcid = aSrc[i];
865 if( srcid==rid ) continue;
866 if( content_is_private(srcid) && !content_is_private(rid) ) continue;
867
868 /* Compute all ancestors of srcid and make sure rid is not one of them.
869 ** If rid is an ancestor of srcid, then making rid a descendant of srcid
870 ** would create a delta loop. */
871 s = srcid;
872 while( (s = delta_source_rid(s))>0 ){
873 if( s==rid ){
874 content_undelta(srcid);
@@ -965,11 +965,11 @@
965 ** Options:
966 ** -d|--db-only Run "PRAGMA integrity_check" on the database only.
967 ** No other validation is performed.
968 ** --parse Parse all manifests, wikis, tickets, events, and
969 ** so forth, reporting any errors found.
970 ** --quick Run "PRAGMA quick_check" on the database only.
971 ** No other validation is performed.
972 */
973 void test_integrity(void){
974 Stmt q;
975 Blob content;
@@ -979,11 +979,11 @@
979 int total;
980 int nCA = 0;
981 int anCA[10];
982 int bParse = find_option("parse",0,0)!=0;
983 int bDbOnly = find_option("db-only","d",0)!=0;
984 int bQuick = find_option("quick",0,0)!=0;
985 db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
986 if( bDbOnly || bQuick ){
987 const char *zType = bQuick ? "quick" : "integrity";
988 char *zRes;
989 zRes = db_text(0,"PRAGMA repository.%s_check", zType/*safe-for-%s*/);
@@ -1199,11 +1199,11 @@
1199 ** all references are satisfied. Report any referenced artifacts
1200 ** that are missing or shunned.
1201 **
1202 ** Options:
1203 ** --notshunned Do not report shunned artifacts
1204 ** -q|--quiet Only show output if there are errors
1205 */
1206 void test_missing(void){
1207 Stmt q;
1208 Blob content;
1209 int nErr = 0;
@@ -1212,11 +1212,11 @@
1212 Manifest *p;
1213 unsigned flags = 0;
1214 int quietFlag;
1215
1216 if( find_option("notshunned", 0, 0)!=0 ) flags |= MISSING_SHUNNED;
1217 quietFlag = g.fQuiet;
1218 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1219 db_prepare(&q,
1220 "SELECT mid FROM mlink UNION "
1221 "SELECT srcid FROM tagxref WHERE srcid>0 UNION "
1222 "SELECT rid FROM tagxref UNION "
1223
+9 -9
--- src/db.c
+++ src/db.c
@@ -1718,11 +1718,11 @@
17181718
savedKeySize = n;
17191719
}
17201720
17211721
/*
17221722
** This function arranges for the database encryption key to be securely
1723
-** saved in non-pagable memory (on platforms where this is possible).
1723
+** saved in non-pageable memory (on platforms where this is possible).
17241724
*/
17251725
static void db_save_encryption_key(
17261726
Blob *pKey
17271727
){
17281728
void *p = NULL;
@@ -2531,11 +2531,11 @@
25312531
if( file_access(zDbName, F_OK) ) return 0;
25322532
lsize = file_size(zDbName, ExtFILE);
25332533
if( lsize%1024!=0 || lsize<4096 ) return 0;
25342534
db_open_or_attach(zDbName, "localdb");
25352535
2536
- /* Check to see if the check-out database has the lastest schema changes.
2536
+ /* Check to see if the check-out database has the latest schema changes.
25372537
** The most recent schema change (2019-01-19) is the addition of the
25382538
** vmerge.mhash and vfile.mhash fields. If the schema has the vmerge.mhash
25392539
** column, assume everything else is up-to-date.
25402540
*/
25412541
if( db_table_has_column("localdb","vmerge","mhash") ){
@@ -2784,11 +2784,11 @@
27842784
27852785
/* Additional checks that occur when opening the check-out database */
27862786
if( g.localOpen ){
27872787
27882788
/* If the repository database that was just opened has been
2789
- ** eplaced by a clone of the same project, with different RID
2789
+ ** replaced by a clone of the same project, with different RID
27902790
** values, then renumber the RID values stored in various tables
27912791
** of the check-out database, so that the repository and check-out
27922792
** databases align.
27932793
*/
27942794
if( !db_fingerprint_ok() ){
@@ -3655,12 +3655,12 @@
36553655
** non-versioned value exist and are not equal, then a warning message
36563656
** might be generated.
36573657
**
36583658
** zCkin is normally NULL. In that case, the versioned setting is
36593659
** take from the local check-out, if a local checkout exists, or from
3660
-** checkin named by the g.zOpenRevision global variable. If zCkin is
3661
-** not NULL, then zCkin is the name of the specific checkin from which
3660
+** check-in named by the g.zOpenRevision global variable. If zCkin is
3661
+** not NULL, then zCkin is the name of the specific check-in from which
36623662
** versioned setting value is taken. When zCkin is not NULL, the cache
36633663
** is bypassed.
36643664
*/
36653665
char *db_get_versioned(
36663666
const char *zName,
@@ -4569,11 +4569,11 @@
45694569
**
45704570
** var is the name of the internal configuration name for db_(un)set.
45714571
** If var is 0, the settings name is used.
45724572
**
45734573
** width is the length for the edit field on the behavior page, 0 is
4574
-** used for on/off checkboxes. A negative value indicates that that
4574
+** used for on/off checkboxes. A negative value indicates that the
45754575
** page should not render this setting. Such values may be rendered
45764576
** separately/manually on another page, e.g., /setup_access, and are
45774577
** exposed via the CLI settings command.
45784578
**
45794579
** The behaviour page doesn't use a special layout. It lists all
@@ -4855,11 +4855,11 @@
48554855
*/
48564856
/*
48574857
** SETTING: empty-dirs width=40 versionable block-text
48584858
** The value is a list of pathnames parsed according to the same rules as
48594859
** the *-glob settings. On update and checkout commands, if no directory
4860
-** exists with that name, an empty directory will be be created, even if
4860
+** exists with that name, an empty directory will be created, even if
48614861
** it must create one or more parent directories.
48624862
*/
48634863
/*
48644864
** SETTING: encoding-glob width=40 versionable block-text
48654865
** The VALUE of this setting is a list of GLOB patterns matching files that
@@ -5576,17 +5576,17 @@
55765576
fossil_print("Config database: %s\n", g.zConfigDbName);
55775577
}
55785578
55795579
/*
55805580
** Compute a "fingerprint" on the repository. A fingerprint is used
5581
-** to verify that that the repository has not been replaced by a clone
5581
+** to verify that the repository has not been replaced by a clone
55825582
** of the same repository. More precisely, a fingerprint is used to
55835583
** verify that the mapping between SHA3 hashes and RID values is unchanged.
55845584
**
55855585
** The check-out database ("localdb") stores RID values. When associating
55865586
** a check-out database against a repository database, it is useful to verify
5587
-** the fingerprint so that we know tha the RID values in the check-out
5587
+** the fingerprint so that we know that the RID values in the check-out
55885588
** database still correspond to the correct entries in the BLOB table of
55895589
** the repository.
55905590
**
55915591
** The fingerprint is based on the RCVFROM table. When constructing a
55925592
** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
55935593
--- src/db.c
+++ src/db.c
@@ -1718,11 +1718,11 @@
1718 savedKeySize = n;
1719 }
1720
1721 /*
1722 ** This function arranges for the database encryption key to be securely
1723 ** saved in non-pagable memory (on platforms where this is possible).
1724 */
1725 static void db_save_encryption_key(
1726 Blob *pKey
1727 ){
1728 void *p = NULL;
@@ -2531,11 +2531,11 @@
2531 if( file_access(zDbName, F_OK) ) return 0;
2532 lsize = file_size(zDbName, ExtFILE);
2533 if( lsize%1024!=0 || lsize<4096 ) return 0;
2534 db_open_or_attach(zDbName, "localdb");
2535
2536 /* Check to see if the check-out database has the lastest schema changes.
2537 ** The most recent schema change (2019-01-19) is the addition of the
2538 ** vmerge.mhash and vfile.mhash fields. If the schema has the vmerge.mhash
2539 ** column, assume everything else is up-to-date.
2540 */
2541 if( db_table_has_column("localdb","vmerge","mhash") ){
@@ -2784,11 +2784,11 @@
2784
2785 /* Additional checks that occur when opening the check-out database */
2786 if( g.localOpen ){
2787
2788 /* If the repository database that was just opened has been
2789 ** eplaced by a clone of the same project, with different RID
2790 ** values, then renumber the RID values stored in various tables
2791 ** of the check-out database, so that the repository and check-out
2792 ** databases align.
2793 */
2794 if( !db_fingerprint_ok() ){
@@ -3655,12 +3655,12 @@
3655 ** non-versioned value exist and are not equal, then a warning message
3656 ** might be generated.
3657 **
3658 ** zCkin is normally NULL. In that case, the versioned setting is
3659 ** take from the local check-out, if a local checkout exists, or from
3660 ** checkin named by the g.zOpenRevision global variable. If zCkin is
3661 ** not NULL, then zCkin is the name of the specific checkin from which
3662 ** versioned setting value is taken. When zCkin is not NULL, the cache
3663 ** is bypassed.
3664 */
3665 char *db_get_versioned(
3666 const char *zName,
@@ -4569,11 +4569,11 @@
4569 **
4570 ** var is the name of the internal configuration name for db_(un)set.
4571 ** If var is 0, the settings name is used.
4572 **
4573 ** width is the length for the edit field on the behavior page, 0 is
4574 ** used for on/off checkboxes. A negative value indicates that that
4575 ** page should not render this setting. Such values may be rendered
4576 ** separately/manually on another page, e.g., /setup_access, and are
4577 ** exposed via the CLI settings command.
4578 **
4579 ** The behaviour page doesn't use a special layout. It lists all
@@ -4855,11 +4855,11 @@
4855 */
4856 /*
4857 ** SETTING: empty-dirs width=40 versionable block-text
4858 ** The value is a list of pathnames parsed according to the same rules as
4859 ** the *-glob settings. On update and checkout commands, if no directory
4860 ** exists with that name, an empty directory will be be created, even if
4861 ** it must create one or more parent directories.
4862 */
4863 /*
4864 ** SETTING: encoding-glob width=40 versionable block-text
4865 ** The VALUE of this setting is a list of GLOB patterns matching files that
@@ -5576,17 +5576,17 @@
5576 fossil_print("Config database: %s\n", g.zConfigDbName);
5577 }
5578
5579 /*
5580 ** Compute a "fingerprint" on the repository. A fingerprint is used
5581 ** to verify that that the repository has not been replaced by a clone
5582 ** of the same repository. More precisely, a fingerprint is used to
5583 ** verify that the mapping between SHA3 hashes and RID values is unchanged.
5584 **
5585 ** The check-out database ("localdb") stores RID values. When associating
5586 ** a check-out database against a repository database, it is useful to verify
5587 ** the fingerprint so that we know tha the RID values in the check-out
5588 ** database still correspond to the correct entries in the BLOB table of
5589 ** the repository.
5590 **
5591 ** The fingerprint is based on the RCVFROM table. When constructing a
5592 ** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
5593
--- src/db.c
+++ src/db.c
@@ -1718,11 +1718,11 @@
1718 savedKeySize = n;
1719 }
1720
1721 /*
1722 ** This function arranges for the database encryption key to be securely
1723 ** saved in non-pageable memory (on platforms where this is possible).
1724 */
1725 static void db_save_encryption_key(
1726 Blob *pKey
1727 ){
1728 void *p = NULL;
@@ -2531,11 +2531,11 @@
2531 if( file_access(zDbName, F_OK) ) return 0;
2532 lsize = file_size(zDbName, ExtFILE);
2533 if( lsize%1024!=0 || lsize<4096 ) return 0;
2534 db_open_or_attach(zDbName, "localdb");
2535
2536 /* Check to see if the check-out database has the latest schema changes.
2537 ** The most recent schema change (2019-01-19) is the addition of the
2538 ** vmerge.mhash and vfile.mhash fields. If the schema has the vmerge.mhash
2539 ** column, assume everything else is up-to-date.
2540 */
2541 if( db_table_has_column("localdb","vmerge","mhash") ){
@@ -2784,11 +2784,11 @@
2784
2785 /* Additional checks that occur when opening the check-out database */
2786 if( g.localOpen ){
2787
2788 /* If the repository database that was just opened has been
2789 ** replaced by a clone of the same project, with different RID
2790 ** values, then renumber the RID values stored in various tables
2791 ** of the check-out database, so that the repository and check-out
2792 ** databases align.
2793 */
2794 if( !db_fingerprint_ok() ){
@@ -3655,12 +3655,12 @@
3655 ** non-versioned value exist and are not equal, then a warning message
3656 ** might be generated.
3657 **
3658 ** zCkin is normally NULL. In that case, the versioned setting is
3659 ** take from the local check-out, if a local checkout exists, or from
3660 ** check-in named by the g.zOpenRevision global variable. If zCkin is
3661 ** not NULL, then zCkin is the name of the specific check-in from which
3662 ** versioned setting value is taken. When zCkin is not NULL, the cache
3663 ** is bypassed.
3664 */
3665 char *db_get_versioned(
3666 const char *zName,
@@ -4569,11 +4569,11 @@
4569 **
4570 ** var is the name of the internal configuration name for db_(un)set.
4571 ** If var is 0, the settings name is used.
4572 **
4573 ** width is the length for the edit field on the behavior page, 0 is
4574 ** used for on/off checkboxes. A negative value indicates that the
4575 ** page should not render this setting. Such values may be rendered
4576 ** separately/manually on another page, e.g., /setup_access, and are
4577 ** exposed via the CLI settings command.
4578 **
4579 ** The behaviour page doesn't use a special layout. It lists all
@@ -4855,11 +4855,11 @@
4855 */
4856 /*
4857 ** SETTING: empty-dirs width=40 versionable block-text
4858 ** The value is a list of pathnames parsed according to the same rules as
4859 ** the *-glob settings. On update and checkout commands, if no directory
4860 ** exists with that name, an empty directory will be created, even if
4861 ** it must create one or more parent directories.
4862 */
4863 /*
4864 ** SETTING: encoding-glob width=40 versionable block-text
4865 ** The VALUE of this setting is a list of GLOB patterns matching files that
@@ -5576,17 +5576,17 @@
5576 fossil_print("Config database: %s\n", g.zConfigDbName);
5577 }
5578
5579 /*
5580 ** Compute a "fingerprint" on the repository. A fingerprint is used
5581 ** to verify that the repository has not been replaced by a clone
5582 ** of the same repository. More precisely, a fingerprint is used to
5583 ** verify that the mapping between SHA3 hashes and RID values is unchanged.
5584 **
5585 ** The check-out database ("localdb") stores RID values. When associating
5586 ** a check-out database against a repository database, it is useful to verify
5587 ** the fingerprint so that we know that the RID values in the check-out
5588 ** database still correspond to the correct entries in the BLOB table of
5589 ** the repository.
5590 **
5591 ** The fingerprint is based on the RCVFROM table. When constructing a
5592 ** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
5593
+19 -1
--- src/default.css
+++ src/default.css
@@ -1231,11 +1231,11 @@
12311231
}
12321232
.accordion_closed > .accordion_btn_plus {
12331233
display: inline-block;
12341234
}
12351235
.accordion_panel {
1236
- overflow: hidden;
1236
+ overflow-y: clip;
12371237
transition: max-height 0.25s ease-out;
12381238
}
12391239
.error {
12401240
color: darkred;
12411241
background: yellow;
@@ -1975,10 +1975,28 @@
19751975
}
19761976
div.markdown span.notescope:hover,
19771977
div.markdown span.notescope:target {
19781978
border-bottom: 2px solid gold;
19791979
}
1980
+
1981
+/* Cause <dd> elements to be aligned complete to the
1982
+** right of their <dt> on help pages. */
1983
+dl.helpOptions {
1984
+ display: grid;
1985
+ grid-template-columns: max-content 1fr;
1986
+ column-gap: 1rem;
1987
+}
1988
+dl.helpOptions > dt {
1989
+ grid-column: 1;
1990
+}
1991
+dl.helpOptions > dd {
1992
+ grid-column: 2;
1993
+ margin: 0;
1994
+}
1995
+div.helpPage blockquote {
1996
+ margin-left: 0.2em;
1997
+}
19801998
19811999
/* Objects in the "desktoponly" class are invisible on mobile */
19822000
@media screen and (max-width: 600px) {
19832001
.desktoponly {
19842002
display: none;
19852003
--- src/default.css
+++ src/default.css
@@ -1231,11 +1231,11 @@
1231 }
1232 .accordion_closed > .accordion_btn_plus {
1233 display: inline-block;
1234 }
1235 .accordion_panel {
1236 overflow: hidden;
1237 transition: max-height 0.25s ease-out;
1238 }
1239 .error {
1240 color: darkred;
1241 background: yellow;
@@ -1975,10 +1975,28 @@
1975 }
1976 div.markdown span.notescope:hover,
1977 div.markdown span.notescope:target {
1978 border-bottom: 2px solid gold;
1979 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1980
1981 /* Objects in the "desktoponly" class are invisible on mobile */
1982 @media screen and (max-width: 600px) {
1983 .desktoponly {
1984 display: none;
1985
--- src/default.css
+++ src/default.css
@@ -1231,11 +1231,11 @@
1231 }
1232 .accordion_closed > .accordion_btn_plus {
1233 display: inline-block;
1234 }
1235 .accordion_panel {
1236 overflow-y: clip;
1237 transition: max-height 0.25s ease-out;
1238 }
1239 .error {
1240 color: darkred;
1241 background: yellow;
@@ -1975,10 +1975,28 @@
1975 }
1976 div.markdown span.notescope:hover,
1977 div.markdown span.notescope:target {
1978 border-bottom: 2px solid gold;
1979 }
1980
1981 /* Cause <dd> elements to be aligned complete to the
1982 ** right of their <dt> on help pages. */
1983 dl.helpOptions {
1984 display: grid;
1985 grid-template-columns: max-content 1fr;
1986 column-gap: 1rem;
1987 }
1988 dl.helpOptions > dt {
1989 grid-column: 1;
1990 }
1991 dl.helpOptions > dd {
1992 grid-column: 2;
1993 margin: 0;
1994 }
1995 div.helpPage blockquote {
1996 margin-left: 0.2em;
1997 }
1998
1999 /* Objects in the "desktoponly" class are invisible on mobile */
2000 @media screen and (max-width: 600px) {
2001 .desktoponly {
2002 display: none;
2003
+3 -3
--- src/delta.c
+++ src/delta.c
@@ -316,11 +316,11 @@
316316
**
317317
** The last term is of the form
318318
**
319319
** NNN;
320320
**
321
-** In this case, NNN is a 32-bit bigendian checksum of the output file
321
+** In this case, NNN is a 32-bit big endian checksum of the output file
322322
** that can be used to verify that the delta applied correctly. All
323323
** numbers are in base-64.
324324
**
325325
** Pure text files generate a pure text delta. Binary files generate a
326326
** delta that may contain some binary data.
@@ -572,12 +572,12 @@
572572
int lenSrc, /* Length of the source file */
573573
const char *zDelta, /* Delta to apply to the pattern */
574574
int lenDelta, /* Length of the delta */
575575
char *zOut /* Write the output into this preallocated buffer */
576576
){
577
- unsigned int limit;
578
- unsigned int total = 0;
577
+ sqlite3_uint64 limit;
578
+ sqlite3_uint64 total = 0;
579579
#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
580580
char *zOrigOut = zOut;
581581
#endif
582582
583583
limit = getInt(&zDelta, &lenDelta);
584584
--- src/delta.c
+++ src/delta.c
@@ -316,11 +316,11 @@
316 **
317 ** The last term is of the form
318 **
319 ** NNN;
320 **
321 ** In this case, NNN is a 32-bit bigendian checksum of the output file
322 ** that can be used to verify that the delta applied correctly. All
323 ** numbers are in base-64.
324 **
325 ** Pure text files generate a pure text delta. Binary files generate a
326 ** delta that may contain some binary data.
@@ -572,12 +572,12 @@
572 int lenSrc, /* Length of the source file */
573 const char *zDelta, /* Delta to apply to the pattern */
574 int lenDelta, /* Length of the delta */
575 char *zOut /* Write the output into this preallocated buffer */
576 ){
577 unsigned int limit;
578 unsigned int total = 0;
579 #ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
580 char *zOrigOut = zOut;
581 #endif
582
583 limit = getInt(&zDelta, &lenDelta);
584
--- src/delta.c
+++ src/delta.c
@@ -316,11 +316,11 @@
316 **
317 ** The last term is of the form
318 **
319 ** NNN;
320 **
321 ** In this case, NNN is a 32-bit big endian checksum of the output file
322 ** that can be used to verify that the delta applied correctly. All
323 ** numbers are in base-64.
324 **
325 ** Pure text files generate a pure text delta. Binary files generate a
326 ** delta that may contain some binary data.
@@ -572,12 +572,12 @@
572 int lenSrc, /* Length of the source file */
573 const char *zDelta, /* Delta to apply to the pattern */
574 int lenDelta, /* Length of the delta */
575 char *zOut /* Write the output into this preallocated buffer */
576 ){
577 sqlite3_uint64 limit;
578 sqlite3_uint64 total = 0;
579 #ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
580 char *zOrigOut = zOut;
581 #endif
582
583 limit = getInt(&zDelta, &lenDelta);
584
--- src/descendants.c
+++ src/descendants.c
@@ -159,11 +159,11 @@
159159
}
160160
}
161161
162162
/*
163163
** If RID refers to a check-in, return the mtime of that check-in - the
164
-** julian day number of when the check-in occurred.
164
+** Julian day number of when the check-in occurred.
165165
*/
166166
double mtime_of_rid(int rid, double mtime){
167167
static Stmt q;
168168
db_static_prepare(&q,"SELECT mtime FROM event WHERE objid=:rid");
169169
db_bind_int(&q, ":rid", rid);
170170
--- src/descendants.c
+++ src/descendants.c
@@ -159,11 +159,11 @@
159 }
160 }
161
162 /*
163 ** If RID refers to a check-in, return the mtime of that check-in - the
164 ** julian day number of when the check-in occurred.
165 */
166 double mtime_of_rid(int rid, double mtime){
167 static Stmt q;
168 db_static_prepare(&q,"SELECT mtime FROM event WHERE objid=:rid");
169 db_bind_int(&q, ":rid", rid);
170
--- src/descendants.c
+++ src/descendants.c
@@ -159,11 +159,11 @@
159 }
160 }
161
162 /*
163 ** If RID refers to a check-in, return the mtime of that check-in - the
164 ** Julian day number of when the check-in occurred.
165 */
166 double mtime_of_rid(int rid, double mtime){
167 static Stmt q;
168 db_static_prepare(&q,"SELECT mtime FROM event WHERE objid=:rid");
169 db_bind_int(&q, ":rid", rid);
170
+22 -2
--- src/diff.c
+++ src/diff.c
@@ -1045,11 +1045,11 @@
10451045
10461046
/************************* DiffBuilderDebug ********************************/
10471047
/* This version of DiffBuilder is used for debugging the diff and diff
10481048
** diff formatter logic. It is accessed using the (undocumented) --debug
10491049
** option to the diff command. The output is human-readable text that
1050
-** describes the various method calls that are invoked agains the DiffBuilder
1050
+** describes the various method calls that are invoked against the DiffBuilder
10511051
** object.
10521052
*/
10531053
static void dfdebugSkip(DiffBuilder *p, unsigned int n, int isFinal){
10541054
blob_appendf(p->pOut, "SKIP %d (%d..%d left and %d..%d right)%s\n",
10551055
n, p->lnLeft+1, p->lnLeft+n, p->lnRight+1, p->lnRight+n,
@@ -3622,11 +3622,11 @@
36223622
iLimit = 0;
36233623
mxTime = current_time_in_milliseconds()+1000;
36243624
}
36253625
db_begin_transaction();
36263626
3627
- /* Get the artifact ID for the check-in begin analyzed */
3627
+ /* Get the artifact ID for the check-in being analyzed */
36283628
if( zRevision ){
36293629
cid = name_to_typed_rid(zRevision, "ci");
36303630
}else{
36313631
db_must_be_within_tree();
36323632
cid = db_lget_int("checkout", 0);
@@ -3939,10 +3939,15 @@
39393939
** (example: "-o trunk") then these commands show changes moving towards
39403940
** that alternative origin. Thus using "-o trunk" on an historical version
39413941
** of the file shows the first time each line in the file was changed or
39423942
** removed by any subsequent check-in.
39433943
**
3944
+** With -t or -T, the "blame" and "praise" commands show for each file the
3945
+** latest (relative to the revision given by -r) check-in that modified it and
3946
+** the check-in's author. If not given, the revision defaults to "current" for
3947
+** a check-out. Option -T additionally shows a comment snippet for the check-in.
3948
+**
39443949
** Options:
39453950
** --filevers Show file version numbers rather than
39463951
** check-in versions
39473952
** -r|--revision VERSION The specific check-in containing the file
39483953
** -l|--log List all versions analyzed
@@ -3954,10 +3959,13 @@
39543959
** root of the repository. Set to the name of
39553960
** the main branch (usually "trunk") or
39563961
** similar for a reverse annotation.
39573962
** -w|--ignore-all-space Ignore white space when comparing lines
39583963
** -Z|--ignore-trailing-space Ignore whitespace at line end
3964
+** -t Show latest check-in and its author for each
3965
+** tracked file in the tree as of VERSION
3966
+** -T Like -t, plus comment snippet
39593967
**
39603968
** See also: [[info]], [[finfo]], [[timeline]]
39613969
*/
39623970
void annotate_cmd(void){
39633971
const char *zRevision; /* Revision name, or NULL for current check-in */
@@ -3967,16 +3975,28 @@
39673975
const char *zOrig; /* The value for -o|--origin */
39683976
int showLog; /* True to show the log */
39693977
int fileVers; /* Show file version instead of check-in versions */
39703978
u64 annFlags = 0; /* Flags to control annotation properties */
39713979
int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
3980
+ int bTreeInfo = 0; /* Show for the entire tree: 1=checkin, 2=with comment */
39723981
int szHash; /* Display size of a version hash */
39733982
Blob treename; /* Name of file to be annotated */
39743983
char *zFilename; /* Name of file to be annotated */
39753984
39763985
bBlame = g.argv[1][0]!='a';
3986
+ if( find_option("t","t",0)!=0 ) bTreeInfo = 1;
3987
+ if( find_option("T","T",0)!=0 ) bTreeInfo = 2;
39773988
zRevision = find_option("revision","r",1);
3989
+ if( bBlame && bTreeInfo ){
3990
+ if( find_repository_option()!=0 && zRevision==0 ){
3991
+ fossil_fatal("the -r is required in addition to -R");
3992
+ }
3993
+ db_find_and_open_repository(0, 0);
3994
+ if( zRevision==0 ) zRevision = "current";
3995
+ ls_cmd_rev(zRevision,1,1,0,1,bTreeInfo,0,0);
3996
+ return;
3997
+ }
39783998
zLimit = find_option("limit","n",1);
39793999
zOrig = find_option("origin","o",1);
39804000
showLog = find_option("log","l",0)!=0;
39814001
if( find_option("ignore-trailing-space","Z",0)!=0 ){
39824002
annFlags = DIFF_IGNORE_EOLWS;
39834003
--- src/diff.c
+++ src/diff.c
@@ -1045,11 +1045,11 @@
1045
1046 /************************* DiffBuilderDebug ********************************/
1047 /* This version of DiffBuilder is used for debugging the diff and diff
1048 ** diff formatter logic. It is accessed using the (undocumented) --debug
1049 ** option to the diff command. The output is human-readable text that
1050 ** describes the various method calls that are invoked agains the DiffBuilder
1051 ** object.
1052 */
1053 static void dfdebugSkip(DiffBuilder *p, unsigned int n, int isFinal){
1054 blob_appendf(p->pOut, "SKIP %d (%d..%d left and %d..%d right)%s\n",
1055 n, p->lnLeft+1, p->lnLeft+n, p->lnRight+1, p->lnRight+n,
@@ -3622,11 +3622,11 @@
3622 iLimit = 0;
3623 mxTime = current_time_in_milliseconds()+1000;
3624 }
3625 db_begin_transaction();
3626
3627 /* Get the artifact ID for the check-in begin analyzed */
3628 if( zRevision ){
3629 cid = name_to_typed_rid(zRevision, "ci");
3630 }else{
3631 db_must_be_within_tree();
3632 cid = db_lget_int("checkout", 0);
@@ -3939,10 +3939,15 @@
3939 ** (example: "-o trunk") then these commands show changes moving towards
3940 ** that alternative origin. Thus using "-o trunk" on an historical version
3941 ** of the file shows the first time each line in the file was changed or
3942 ** removed by any subsequent check-in.
3943 **
 
 
 
 
 
3944 ** Options:
3945 ** --filevers Show file version numbers rather than
3946 ** check-in versions
3947 ** -r|--revision VERSION The specific check-in containing the file
3948 ** -l|--log List all versions analyzed
@@ -3954,10 +3959,13 @@
3954 ** root of the repository. Set to the name of
3955 ** the main branch (usually "trunk") or
3956 ** similar for a reverse annotation.
3957 ** -w|--ignore-all-space Ignore white space when comparing lines
3958 ** -Z|--ignore-trailing-space Ignore whitespace at line end
 
 
 
3959 **
3960 ** See also: [[info]], [[finfo]], [[timeline]]
3961 */
3962 void annotate_cmd(void){
3963 const char *zRevision; /* Revision name, or NULL for current check-in */
@@ -3967,16 +3975,28 @@
3967 const char *zOrig; /* The value for -o|--origin */
3968 int showLog; /* True to show the log */
3969 int fileVers; /* Show file version instead of check-in versions */
3970 u64 annFlags = 0; /* Flags to control annotation properties */
3971 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
 
3972 int szHash; /* Display size of a version hash */
3973 Blob treename; /* Name of file to be annotated */
3974 char *zFilename; /* Name of file to be annotated */
3975
3976 bBlame = g.argv[1][0]!='a';
 
 
3977 zRevision = find_option("revision","r",1);
 
 
 
 
 
 
 
 
 
3978 zLimit = find_option("limit","n",1);
3979 zOrig = find_option("origin","o",1);
3980 showLog = find_option("log","l",0)!=0;
3981 if( find_option("ignore-trailing-space","Z",0)!=0 ){
3982 annFlags = DIFF_IGNORE_EOLWS;
3983
--- src/diff.c
+++ src/diff.c
@@ -1045,11 +1045,11 @@
1045
1046 /************************* DiffBuilderDebug ********************************/
1047 /* This version of DiffBuilder is used for debugging the diff and diff
1048 ** diff formatter logic. It is accessed using the (undocumented) --debug
1049 ** option to the diff command. The output is human-readable text that
1050 ** describes the various method calls that are invoked against the DiffBuilder
1051 ** object.
1052 */
1053 static void dfdebugSkip(DiffBuilder *p, unsigned int n, int isFinal){
1054 blob_appendf(p->pOut, "SKIP %d (%d..%d left and %d..%d right)%s\n",
1055 n, p->lnLeft+1, p->lnLeft+n, p->lnRight+1, p->lnRight+n,
@@ -3622,11 +3622,11 @@
3622 iLimit = 0;
3623 mxTime = current_time_in_milliseconds()+1000;
3624 }
3625 db_begin_transaction();
3626
3627 /* Get the artifact ID for the check-in being analyzed */
3628 if( zRevision ){
3629 cid = name_to_typed_rid(zRevision, "ci");
3630 }else{
3631 db_must_be_within_tree();
3632 cid = db_lget_int("checkout", 0);
@@ -3939,10 +3939,15 @@
3939 ** (example: "-o trunk") then these commands show changes moving towards
3940 ** that alternative origin. Thus using "-o trunk" on an historical version
3941 ** of the file shows the first time each line in the file was changed or
3942 ** removed by any subsequent check-in.
3943 **
3944 ** With -t or -T, the "blame" and "praise" commands show for each file the
3945 ** latest (relative to the revision given by -r) check-in that modified it and
3946 ** the check-in's author. If not given, the revision defaults to "current" for
3947 ** a check-out. Option -T additionally shows a comment snippet for the check-in.
3948 **
3949 ** Options:
3950 ** --filevers Show file version numbers rather than
3951 ** check-in versions
3952 ** -r|--revision VERSION The specific check-in containing the file
3953 ** -l|--log List all versions analyzed
@@ -3954,10 +3959,13 @@
3959 ** root of the repository. Set to the name of
3960 ** the main branch (usually "trunk") or
3961 ** similar for a reverse annotation.
3962 ** -w|--ignore-all-space Ignore white space when comparing lines
3963 ** -Z|--ignore-trailing-space Ignore whitespace at line end
3964 ** -t Show latest check-in and its author for each
3965 ** tracked file in the tree as of VERSION
3966 ** -T Like -t, plus comment snippet
3967 **
3968 ** See also: [[info]], [[finfo]], [[timeline]]
3969 */
3970 void annotate_cmd(void){
3971 const char *zRevision; /* Revision name, or NULL for current check-in */
@@ -3967,16 +3975,28 @@
3975 const char *zOrig; /* The value for -o|--origin */
3976 int showLog; /* True to show the log */
3977 int fileVers; /* Show file version instead of check-in versions */
3978 u64 annFlags = 0; /* Flags to control annotation properties */
3979 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
3980 int bTreeInfo = 0; /* Show for the entire tree: 1=checkin, 2=with comment */
3981 int szHash; /* Display size of a version hash */
3982 Blob treename; /* Name of file to be annotated */
3983 char *zFilename; /* Name of file to be annotated */
3984
3985 bBlame = g.argv[1][0]!='a';
3986 if( find_option("t","t",0)!=0 ) bTreeInfo = 1;
3987 if( find_option("T","T",0)!=0 ) bTreeInfo = 2;
3988 zRevision = find_option("revision","r",1);
3989 if( bBlame && bTreeInfo ){
3990 if( find_repository_option()!=0 && zRevision==0 ){
3991 fossil_fatal("the -r is required in addition to -R");
3992 }
3993 db_find_and_open_repository(0, 0);
3994 if( zRevision==0 ) zRevision = "current";
3995 ls_cmd_rev(zRevision,1,1,0,1,bTreeInfo,0,0);
3996 return;
3997 }
3998 zLimit = find_option("limit","n",1);
3999 zOrig = find_option("origin","o",1);
4000 showLog = find_option("log","l",0)!=0;
4001 if( find_option("ignore-trailing-space","Z",0)!=0 ){
4002 annFlags = DIFF_IGNORE_EOLWS;
4003
+5 -5
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -212,11 +212,11 @@
212212
blob_appendf(pOut, "%.*c %.*s %.*c versus %.*c %.*s %.*c\n",
213213
(w-n1+10)/2, '=', n1, zLeft, (w-n1+1)/2, '=',
214214
(w-n2)/2, '=', n2, zRight, (w-n2+1)/2, '=');
215215
}
216216
}else{
217
- blob_appendf(pOut, "--- %s\n+++ %s\n", zLeft, zRight);
217
+ blob_appendf(pOut, "--- %s\t\n+++ %s\t\n", zLeft, zRight);
218218
}
219219
}
220220
221221
222222
/*
@@ -813,11 +813,11 @@
813813
Blob *pOut /* Blob to output diff instead of stdout */
814814
){
815815
int vid;
816816
Blob sql;
817817
Stmt q;
818
- int asNewFile; /* Treat non-existant files as empty files */
818
+ int asNewFile; /* Treat non-existent files as empty files */
819819
int isNumStat; /* True for --numstat */
820820
821821
asNewFile = (pCfg->diffFlags & (DIFF_VERBOSE|DIFF_NUMSTAT|DIFF_HTML))!=0;
822822
isNumStat = (pCfg->diffFlags & (DIFF_NUMSTAT|DIFF_TCL|DIFF_HTML))!=0;
823823
vid = db_lget_int("checkout", 0);
@@ -1329,11 +1329,11 @@
13291329
**
13301330
** The "--binary" option causes files matching the glob PATTERN to be treated
13311331
** as binary when considering if they should be used with the external diff
13321332
** program. This option overrides the "binary-glob" setting.
13331333
**
1334
-** These command show differences between managed files. Use the "fossil xdiff"
1334
+** These commands show differences between managed files. Use the "fossil xdiff"
13351335
** command to see differences in unmanaged files.
13361336
**
13371337
** Options:
13381338
** --binary PATTERN Treat files that match the glob PATTERN
13391339
** as binary
@@ -1357,12 +1357,12 @@
13571357
** --invert Invert the diff
13581358
** --json Output formatted as JSON
13591359
** -n|--linenum Show line numbers
13601360
** -N|--new-file Alias for --verbose
13611361
** -s|--numstat Show the number of added and deleted lines per
1362
-** file, omitting the diff. When combined with
1363
-** --brief, show only the total row.
1362
+** file, omitting the diff. When combined
1363
+** with --brief, show only the total row.
13641364
** -y|--side-by-side Side-by-side diff
13651365
** --strip-trailing-cr Strip trailing CR
13661366
** --tcl Tcl-formatted output used internally by --tk
13671367
** --tclsh PATH Tcl/Tk shell used for --tk (default: "tclsh")
13681368
** --tk Launch a Tcl/Tk GUI for display
13691369
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -212,11 +212,11 @@
212 blob_appendf(pOut, "%.*c %.*s %.*c versus %.*c %.*s %.*c\n",
213 (w-n1+10)/2, '=', n1, zLeft, (w-n1+1)/2, '=',
214 (w-n2)/2, '=', n2, zRight, (w-n2+1)/2, '=');
215 }
216 }else{
217 blob_appendf(pOut, "--- %s\n+++ %s\n", zLeft, zRight);
218 }
219 }
220
221
222 /*
@@ -813,11 +813,11 @@
813 Blob *pOut /* Blob to output diff instead of stdout */
814 ){
815 int vid;
816 Blob sql;
817 Stmt q;
818 int asNewFile; /* Treat non-existant files as empty files */
819 int isNumStat; /* True for --numstat */
820
821 asNewFile = (pCfg->diffFlags & (DIFF_VERBOSE|DIFF_NUMSTAT|DIFF_HTML))!=0;
822 isNumStat = (pCfg->diffFlags & (DIFF_NUMSTAT|DIFF_TCL|DIFF_HTML))!=0;
823 vid = db_lget_int("checkout", 0);
@@ -1329,11 +1329,11 @@
1329 **
1330 ** The "--binary" option causes files matching the glob PATTERN to be treated
1331 ** as binary when considering if they should be used with the external diff
1332 ** program. This option overrides the "binary-glob" setting.
1333 **
1334 ** These command show differences between managed files. Use the "fossil xdiff"
1335 ** command to see differences in unmanaged files.
1336 **
1337 ** Options:
1338 ** --binary PATTERN Treat files that match the glob PATTERN
1339 ** as binary
@@ -1357,12 +1357,12 @@
1357 ** --invert Invert the diff
1358 ** --json Output formatted as JSON
1359 ** -n|--linenum Show line numbers
1360 ** -N|--new-file Alias for --verbose
1361 ** -s|--numstat Show the number of added and deleted lines per
1362 ** file, omitting the diff. When combined with
1363 ** --brief, show only the total row.
1364 ** -y|--side-by-side Side-by-side diff
1365 ** --strip-trailing-cr Strip trailing CR
1366 ** --tcl Tcl-formatted output used internally by --tk
1367 ** --tclsh PATH Tcl/Tk shell used for --tk (default: "tclsh")
1368 ** --tk Launch a Tcl/Tk GUI for display
1369
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -212,11 +212,11 @@
212 blob_appendf(pOut, "%.*c %.*s %.*c versus %.*c %.*s %.*c\n",
213 (w-n1+10)/2, '=', n1, zLeft, (w-n1+1)/2, '=',
214 (w-n2)/2, '=', n2, zRight, (w-n2+1)/2, '=');
215 }
216 }else{
217 blob_appendf(pOut, "--- %s\t\n+++ %s\t\n", zLeft, zRight);
218 }
219 }
220
221
222 /*
@@ -813,11 +813,11 @@
813 Blob *pOut /* Blob to output diff instead of stdout */
814 ){
815 int vid;
816 Blob sql;
817 Stmt q;
818 int asNewFile; /* Treat non-existent files as empty files */
819 int isNumStat; /* True for --numstat */
820
821 asNewFile = (pCfg->diffFlags & (DIFF_VERBOSE|DIFF_NUMSTAT|DIFF_HTML))!=0;
822 isNumStat = (pCfg->diffFlags & (DIFF_NUMSTAT|DIFF_TCL|DIFF_HTML))!=0;
823 vid = db_lget_int("checkout", 0);
@@ -1329,11 +1329,11 @@
1329 **
1330 ** The "--binary" option causes files matching the glob PATTERN to be treated
1331 ** as binary when considering if they should be used with the external diff
1332 ** program. This option overrides the "binary-glob" setting.
1333 **
1334 ** These commands show differences between managed files. Use the "fossil xdiff"
1335 ** command to see differences in unmanaged files.
1336 **
1337 ** Options:
1338 ** --binary PATTERN Treat files that match the glob PATTERN
1339 ** as binary
@@ -1357,12 +1357,12 @@
1357 ** --invert Invert the diff
1358 ** --json Output formatted as JSON
1359 ** -n|--linenum Show line numbers
1360 ** -N|--new-file Alias for --verbose
1361 ** -s|--numstat Show the number of added and deleted lines per
1362 ** file, omitting the diff. When combined
1363 ** with --brief, show only the total row.
1364 ** -y|--side-by-side Side-by-side diff
1365 ** --strip-trailing-cr Strip trailing CR
1366 ** --tcl Tcl-formatted output used internally by --tk
1367 ** --tclsh PATH Tcl/Tk shell used for --tk (default: "tclsh")
1368 ** --tk Launch a Tcl/Tk GUI for display
1369
+115 -73
--- src/dispatch.c
+++ src/dispatch.c
@@ -25,11 +25,11 @@
2525
#include "dispatch.h"
2626
2727
#if INTERFACE
2828
/*
2929
** An instance of this object defines everything we need to know about an
30
-** individual command, webpage, or setting.
30
+** individual command, webpage, setting, or help topic.
3131
*/
3232
struct CmdOrPage {
3333
const char *zName; /* Name. Webpages start with "/". Commands do not */
3434
void (*xFunc)(void); /* Implementation function, or NULL for settings */
3535
const char *zHelp; /* Raw help text */
@@ -39,31 +39,32 @@
3939
4040
/***************************************************************************
4141
** These macros must match similar macros in mkindex.c
4242
** Allowed values for CmdOrPage.eCmdFlags.
4343
*/
44
-#define CMDFLAG_1ST_TIER 0x0001 /* Most important commands */
45
-#define CMDFLAG_2ND_TIER 0x0002 /* Obscure and seldom used commands */
46
-#define CMDFLAG_TEST 0x0004 /* Commands for testing only */
47
-#define CMDFLAG_WEBPAGE 0x0008 /* Web pages */
48
-#define CMDFLAG_COMMAND 0x0010 /* A command */
49
-#define CMDFLAG_SETTING 0x0020 /* A setting */
50
-#define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
51
-#define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
52
-#define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
53
-#define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret POST content */
54
-/* NOTE: 0x0400 = CMDFLAG_SENSITIVE in mkindex.c! */
55
-#define CMDFLAG_HIDDEN 0x0800 /* Elide from most listings */
56
-#define CMDFLAG_LDAVG_EXEMPT 0x1000 /* Exempt from load_control() */
57
-#define CMDFLAG_ALIAS 0x2000 /* Command aliases */
58
-#define CMDFLAG_KEEPEMPTY 0x4000 /* Do not unset empty settings */
59
-#define CMDFLAG_ABBREVSUBCMD 0x8000 /* Help text abbreviates subcommands */
44
+#define CMDFLAG_1ST_TIER 0x000001 /* Most important commands */
45
+#define CMDFLAG_2ND_TIER 0x000002 /* Obscure and seldom used commands */
46
+#define CMDFLAG_TEST 0x000004 /* Commands for testing only */
47
+#define CMDFLAG_WEBPAGE 0x000008 /* Web pages */
48
+#define CMDFLAG_COMMAND 0x000010 /* A command */
49
+#define CMDFLAG_SETTING 0x000020 /* A setting */
50
+#define CMDFLAG_VERSIONABLE 0x000040 /* A versionable setting */
51
+#define CMDFLAG_BLOCKTEXT 0x000080 /* Multi-line text setting */
52
+#define CMDFLAG_BOOLEAN 0x000100 /* A boolean setting */
53
+#define CMDFLAG_RAWCONTENT 0x000200 /* Do not interpret POST content */
54
+/* NOTE: 0x000400 = CMDFLAG_SENSITIVE in mkindex.c! */
55
+#define CMDFLAG_HIDDEN 0x000800 /* Elide from most listings */
56
+#define CMDFLAG_LDAVG_EXEMPT 0x001000 /* Exempt from load_control() */
57
+#define CMDFLAG_ALIAS 0x002000 /* Command aliases */
58
+#define CMDFLAG_KEEPEMPTY 0x004000 /* Do not unset empty settings */
59
+#define CMDFLAG_ABBREVSUBCMD 0x008000 /* Help text abbreviates subcommands */
60
+#define CMDFLAG_TOPIC 0x010000 /* A help topic */
6061
/**************************************************************************/
6162
6263
/* Values for the 2nd parameter to dispatch_name_search() */
63
-#define CMDFLAG_ANY 0x0038 /* Match anything */
64
-#define CMDFLAG_PREFIX 0x0200 /* Prefix match is OK */
64
+#define CMDFLAG_ANY 0x010038 /* Match anything */
65
+#define CMDFLAG_PREFIX 0x000200 /* Prefix match is OK */
6566
6667
#endif /* INTERFACE */
6768
6869
/*
6970
** The page_index.h file contains the definition for aCommand[] - an array
@@ -461,11 +462,15 @@
461462
|| hasGap(zHelp+nIndent,i-nIndent) ){
462463
iLevel++;
463464
aIndent[iLevel] = nIndent;
464465
azEnd[iLevel] = zEndDL;
465466
wantP = 0;
466
- blob_append(pHtml, "<blockquote><dl>\n", -1);
467
+ if( isDT ){
468
+ blob_append(pHtml, "<blockquote><dl>\n", -1);
469
+ }else{
470
+ blob_append(pHtml, "<blockquote><dl class=\"helpOptions\">\n", -1);
471
+ }
467472
}else if( azEnd[iLevel]==zEndDL ){
468473
iLevel++;
469474
aIndent[iLevel] = nIndent;
470475
azEnd[iLevel] = zEndDD;
471476
if( wantP ){
@@ -578,10 +583,11 @@
578583
if( mask & CMDFLAG_2ND_TIER ) fossil_print(" * Auxiliary commands\n");
579584
if( mask & CMDFLAG_ALIAS ) fossil_print(" * Aliases\n");
580585
if( mask & CMDFLAG_TEST ) fossil_print(" * Test commands\n");
581586
if( mask & CMDFLAG_WEBPAGE ) fossil_print(" * Web pages\n");
582587
if( mask & CMDFLAG_SETTING ) fossil_print(" * Settings\n");
588
+ if( mask & CMDFLAG_TOPIC ) fossil_print(" * Help Topic\n");
583589
if( useHtml ){
584590
fossil_print("-->\n");
585591
fossil_print("<!-- start_all_help -->\n");
586592
}else{
587593
fossil_print("---\n");
@@ -644,10 +650,11 @@
644650
** Defaults to just the CLI commands. Specify --www to see only the
645651
** web pages, or --everything to see both commands and pages.
646652
**
647653
** Options:
648654
** -a|--aliases Show aliases
655
+** -c|--topics Show help topics
649656
** -e|--everything Show all commands and pages. Omit aliases to
650657
** avoid duplicates.
651658
** -h|--html Transform output to HTML
652659
** -o|--options Show global options
653660
** -r|--raw No output formatting
@@ -663,20 +670,23 @@
663670
if( find_option("www","w",0) ){
664671
mask = CMDFLAG_WEBPAGE;
665672
}
666673
if( find_option("everything","e",0) ){
667674
mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
668
- CMDFLAG_ALIAS | CMDFLAG_SETTING | CMDFLAG_TEST;
675
+ CMDFLAG_ALIAS | CMDFLAG_SETTING | CMDFLAG_TEST | CMDFLAG_TOPIC;
669676
}
670677
if( find_option("settings","s",0) ){
671678
mask = CMDFLAG_SETTING;
672679
}
673680
if( find_option("aliases","a",0) ){
674681
mask = CMDFLAG_ALIAS;
675682
}
676683
if( find_option("test","t",0) ){
677684
mask |= CMDFLAG_TEST;
685
+ }
686
+ if( find_option("topics","c",0) ){
687
+ mask |= CMDFLAG_TOPIC;
678688
}
679689
display_all_help(mask, useHtml, rawOut);
680690
}
681691
682692
/*
@@ -710,10 +720,12 @@
710720
countCmds( CMDFLAG_TEST ));
711721
fossil_print("web-pages: %4d\n",
712722
countCmds( CMDFLAG_WEBPAGE ));
713723
fossil_print("settings: %4d\n",
714724
countCmds( CMDFLAG_SETTING ));
725
+ fossil_print("help-topics: %4d\n",
726
+ countCmds( CMDFLAG_TOPIC ));
715727
fossil_print("total entries: %4d\n", MX_COMMAND);
716728
}
717729
718730
/*
719731
** Compute an estimate of the edit-distance between to input strings.
@@ -892,10 +904,12 @@
892904
/* Some of the webpages require query parameters in order to work.
893905
** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */
894906
@ <h1>The "%h(pCmd->zName)" page:</h1>
895907
}else if( rc==0 && (pCmd->eCmdFlags & CMDFLAG_SETTING)!=0 ){
896908
@ <h1>The "%h(pCmd->zName)" setting:</h1>
909
+ }else if( rc==0 && (pCmd->eCmdFlags & CMDFLAG_TOPIC)!=0 ){
910
+ @ <h1>The "%h(pCmd->zName)" help topic:</h1>
897911
}else{
898912
@ <h1>The "%h(pCmd->zName)" command:</h1>
899913
}
900914
if( rc==1 || (rc==2 && zCmd[0]=='/') ){
901915
if( zCmd && help_is_platform_command(zCmd) ){
@@ -933,11 +947,11 @@
933947
int bktHelp[FOSSIL_MX_CMDIDX][MX_HELP_DUP] = {{0}};/* Help str->commands */
934948
style_header("Help");
935949
search_screen(SRCH_HELP, 0x02);
936950
937951
@ <a name='commands'></a>
938
- @ <h1>Available commands:</h1>
952
+ @ <h1>Commands:</h1>
939953
@ <div class="columns" style="column-width: %s(zWidth);">
940954
@ <ul>
941955
/* Fill in help string buckets */
942956
for(i=0; i<MX_COMMAND; i++){
943957
if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
@@ -946,11 +960,13 @@
946960
for(i=0; i<MX_COMMAND; i++){
947961
const char *z = aCommand[i].zName;
948962
const char *zBoldOn = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :"";
949963
const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":"";
950964
if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
951
- if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)!=0 ) continue;
965
+ if( (aCommand[i].eCmdFlags & (CMDFLAG_SETTING|CMDFLAG_TOPIC))!=0 ){
966
+ continue;
967
+ }
952968
else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
953969
else if( (aCommand[i].eCmdFlags & CMDFLAG_ALIAS)!=0 ) continue;
954970
@ <li><a href="%R/help/%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a>
955971
/* Output aliases */
956972
if( occHelp[aCommand[i].iHelp] > 1 ){
@@ -978,11 +994,11 @@
978994
}
979995
980996
@ </ul></div>
981997
982998
@ <a name='webpages'></a>
983
- @ <h1>Available web UI pages:</h1>
999
+ @ <h1>Web pages:</h1>
9841000
@ <div class="columns" style="column-width: %s(zWidth);">
9851001
@ <ul>
9861002
for(i=0; i<MX_COMMAND; i++){
9871003
const char *z = aCommand[i].zName;
9881004
if( '/'!=*z ) continue;
@@ -993,33 +1009,48 @@
9931009
@ <li>%s(z+1)</li>
9941010
}
9951011
}
9961012
@ </ul></div>
9971013
998
- @ <a name='unsupported'></a>
999
- @ <h1>Unsupported commands:</h1>
1014
+ @ <a name='settings'></a>
1015
+ @ <h1>Settings:</h1>
10001016
@ <div class="columns" style="column-width: %s(zWidth);">
10011017
@ <ul>
10021018
for(i=0; i<MX_COMMAND; i++){
10031019
const char *z = aCommand[i].zName;
1004
- if( strncmp(z,"test",4)!=0 ) continue;
1020
+ if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
10051021
else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
10061022
if( aCommand[i].zHelp[0] ){
10071023
@ <li><a href="%R/help/%s(z)">%s(z)</a></li>
10081024
}else{
10091025
@ <li>%s(z)</li>
10101026
}
10111027
}
10121028
@ </ul></div>
10131029
1014
- @ <a name='settings'></a>
1015
- @ <h1>Settings:</h1>
1030
+ @ <a name='topics'></a>
1031
+ @ <h1>Other Miscellaneous Help Topics:</h1>
1032
+ @ <div class="columns" style="column-width: %s(zWidth);">
1033
+ @ <ul>
1034
+ for(i=0; i<MX_COMMAND; i++){
1035
+ const char *z = aCommand[i].zName;
1036
+ if( (aCommand[i].eCmdFlags & CMDFLAG_TOPIC)==0 ) continue;
1037
+ if( aCommand[i].zHelp[0] ){
1038
+ @ <li><a href="%R/help/%s(z)">%s(z)</a></li>
1039
+ }else{
1040
+ @ <li>%s(z)</li>
1041
+ }
1042
+ }
1043
+ @ </ul></div>
1044
+
1045
+ @ <a name='unsupported'></a>
1046
+ @ <h1>Unsupported and Testing Commands:</h1>
10161047
@ <div class="columns" style="column-width: %s(zWidth);">
10171048
@ <ul>
10181049
for(i=0; i<MX_COMMAND; i++){
10191050
const char *z = aCommand[i].zName;
1020
- if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
1051
+ if( strncmp(z,"test",4)!=0 ) continue;
10211052
else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
10221053
if( aCommand[i].zHelp[0] ){
10231054
@ <li><a href="%R/help/%s(z)">%s(z)</a></li>
10241055
}else{
10251056
@ <li>%s(z)</li>
@@ -1059,10 +1090,12 @@
10591090
zDesc = "2nd tier command";
10601091
}else if( e & CMDFLAG_ALIAS ){
10611092
zDesc = "alias";
10621093
}else if( e & CMDFLAG_TEST ){
10631094
zDesc = "test command";
1095
+ }else if( e & CMDFLAG_TOPIC ){
1096
+ zDesc = "help-topic";
10641097
}else if( e & CMDFLAG_WEBPAGE ){
10651098
if( e & CMDFLAG_RAWCONTENT ){
10661099
zDesc = "raw-content web page";
10671100
}else{
10681101
zDesc = "web page";
@@ -1155,11 +1188,11 @@
11551188
Blob *pOut, /* Write simplified help text here */
11561189
const char *zTopic, /* TOPIC */
11571190
const char *zSubtopic, /* SUBTOPIC */
11581191
int bAbbrevSubcmd /* True if z[] contains abbreviated subcommands */
11591192
){
1160
- Blob in, line; //, subsection;
1193
+ Blob in, line;/*, subsection;*/
11611194
int n = 0;
11621195
char *zQTop = re_quote(zTopic);
11631196
char *zQSub = re_quote(zSubtopic);
11641197
char *zPattern;
11651198
ReCompiled *pRe = 0;
@@ -1392,46 +1425,44 @@
13921425
multi_column_list(aCmd, nCmd);
13931426
}
13941427
}
13951428
13961429
/*
1397
-** Documentation on universal command-line options.
1430
+** TOPIC: options
1431
+**
1432
+** Command-line options common to all commands:
1433
+**
1434
+** --args FILENAME Read additional arguments and options from FILENAME
1435
+** --case-sensitive BOOL Set case sensitivity for file names
1436
+** --cgitrace Active CGI tracing
1437
+** --chdir PATH Change to PATH before performing any operations
1438
+** --errorlog FILENAME Log errors to FILENAME
1439
+** -?|--help Show help on the command rather than running it
1440
+** --httptrace Trace outbound HTTP requests
1441
+** --localtime Display times using the local timezone
1442
+** --nocgi Do not act as CGI
1443
+** --no-th-hook Do not run TH1 hooks
1444
+** -q|--quiet Reduce the amount of output
1445
+** --sqlstats Show SQL usage statistics when done
1446
+** --sqltrace Trace all SQL commands
1447
+** --sshtrace Trace SSH activity
1448
+** --ssl-identity NAME Set the SSL identity to NAME
1449
+** --systemtrace Trace calls to system()
1450
+** -U|--user USER Make the default user be USER
1451
+** --utc Display times using UTC
1452
+** --vfs NAME Cause SQLite to use the NAME VFS
1453
+**
1454
+** Additional options available on most commands that use network I/O:
1455
+**
1456
+** --accept-any-cert Disable server SSL cdert validation. Accept any SSL
1457
+** cert that the server provides. WARNING: Unsafe!
1458
+** Testing and debugging use only!
1459
+** --ipv4 Use only IPv4. Disable IPv6 support.
1460
+** --ipv6 Use only IPv6. Disable IPv4 support.
1461
+** --nosync Disable autosync for the current command.
1462
+** --proxy URL Specify the HTTP proxy to use. URL can be "off".
13981463
*/
1399
-/* @-comment: # */
1400
-static const char zOptions[] =
1401
-@ Command-line options common to all commands:
1402
-@
1403
-@ --args FILENAME Read additional arguments and options from FILENAME
1404
-@ --case-sensitive BOOL Set case sensitivity for file names
1405
-@ --cgitrace Active CGI tracing
1406
-@ --chdir PATH Change to PATH before performing any operations
1407
-@ --errorlog FILENAME Log errors to FILENAME
1408
-@ -?|--help Show help on the command rather than running it
1409
-@ --httptrace Trace outbound HTTP requests
1410
-@ --localtime Display times using the local timezone
1411
-@ --nocgi Do not act as CGI
1412
-@ --no-th-hook Do not run TH1 hooks
1413
-@ --quiet Reduce the amount of output
1414
-@ --sqlstats Show SQL usage statistics when done
1415
-@ --sqltrace Trace all SQL commands
1416
-@ --sshtrace Trace SSH activity
1417
-@ --ssl-identity NAME Set the SSL identity to NAME
1418
-@ --systemtrace Trace calls to system()
1419
-@ -U|--user USER Make the default user be USER
1420
-@ --utc Display times using UTC
1421
-@ --vfs NAME Cause SQLite to use the NAME VFS
1422
-@
1423
-@ Additional options available on most commands that use network I/O:
1424
-@
1425
-@ --accept-any-cert Disable server SSL cdert validation. Accept any SSL
1426
-@ cert that the server provides. WARNING: Unsafe!
1427
-@ Testing and debugging use only!
1428
-@ --ipv4 Use only IPv4. Disable IPv6 support.
1429
-@ --ipv6 Use only IPv6. Disable IPv4 support.
1430
-@ --nosync Disable autosync for the current command.
1431
-@ --proxy URL Specify the HTTP proxy to use. URL can be "off".
1432
-;
14331464
14341465
/*
14351466
** COMMAND: help
14361467
**
14371468
** Usage: %fossil help [OPTIONS] [TOPIC] [SUBCOMMAND]
@@ -1508,21 +1539,26 @@
15081539
return;
15091540
}
15101541
else if( find_option("setting","s",0) ){
15111542
command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
15121543
return;
1544
+ }
1545
+ else if( find_option("topic","c",0) ){
1546
+ command_list(CMDFLAG_TOPIC, verboseFlag, useHtml);
1547
+ return;
15131548
}
15141549
else if( find_option("full","f",0) ){
15151550
fossil_print("fossil commands:\n\n");
15161551
command_list(CMDFLAG_1ST_TIER, verboseFlag, useHtml);
15171552
fossil_print("\nfossil auxiliary commands:\n\n");
15181553
command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1519
- fossil_print("\n%s", zOptions);
15201554
fossil_print("\nfossil settings:\n\n");
15211555
command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
15221556
fossil_print("\nfossil web pages:\n\n");
15231557
command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
1558
+ fossil_print("\nfossil miscellaneous help topics:\n\n");
1559
+ command_list(CMDFLAG_TOPIC, verboseFlag, useHtml);
15241560
fossil_print("\nfossil test commands (unsupported):\n\n");
15251561
command_list(CMDFLAG_TEST, verboseFlag, useHtml);
15261562
if ( !verboseFlag ) {
15271563
fossil_print("\n");
15281564
version_cmd();
@@ -1529,18 +1565,23 @@
15291565
}
15301566
return;
15311567
}
15321568
else if( find_option("everything","e",0) ){
15331569
display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1534
- CMDFLAG_SETTING | CMDFLAG_TEST, useHtml, 0);
1570
+ CMDFLAG_SETTING | CMDFLAG_TEST | CMDFLAG_TOPIC,
1571
+ useHtml, 0);
15351572
return;
15361573
}
15371574
verify_all_options();
1575
+ zCmdOrPage = "help topic";
15381576
if( g.argc<3 ){
15391577
if( bOptions ){
1540
- fossil_print("%s", zOptions);
1541
- return;
1578
+ zTopic = "options";
1579
+ zSubtopic = 0;
1580
+ mask = CMDFLAG_TOPIC;
1581
+ bOptions = 0;
1582
+ goto find_and_show_help;
15421583
}
15431584
z = g.argv[0];
15441585
fossil_print(
15451586
"Usage: %s help TOPIC\n"
15461587
"Things to try:\n\n"
@@ -1560,14 +1601,13 @@
15601601
if( isPage ){
15611602
zCmdOrPage = "page";
15621603
}else if( commandsFlag ){
15631604
mask = CMDFLAG_COMMAND;
15641605
zCmdOrPage = "command";
1565
- }else{
1566
- zCmdOrPage = "command or setting";
15671606
}
1568
- rc = dispatch_name_search(g.argv[2], mask|CMDFLAG_PREFIX, &pCmd);
1607
+find_and_show_help:
1608
+ rc = dispatch_name_search(zTopic, mask|CMDFLAG_PREFIX, &pCmd);
15691609
if( rc ){
15701610
int i, n;
15711611
const char *az[5];
15721612
if( rc==1 ){
15731613
if( help_is_platform_command(g.argv[2]) ){
@@ -1805,10 +1845,12 @@
18051845
zType = "command";
18061846
}else if( pPage->eCmdFlags & CMDFLAG_WEBPAGE ){
18071847
zType = "webpage";
18081848
}else if( pPage->eCmdFlags & CMDFLAG_SETTING ){
18091849
zType = "setting";
1850
+ }else if( pPage->eCmdFlags & CMDFLAG_TOPIC ){
1851
+ zType = "help-topic";
18101852
}
18111853
sqlite3_result_text(ctx, zType, -1, SQLITE_STATIC);
18121854
break;
18131855
}
18141856
case 2: /* flags */
18151857
--- src/dispatch.c
+++ src/dispatch.c
@@ -25,11 +25,11 @@
25 #include "dispatch.h"
26
27 #if INTERFACE
28 /*
29 ** An instance of this object defines everything we need to know about an
30 ** individual command, webpage, or setting.
31 */
32 struct CmdOrPage {
33 const char *zName; /* Name. Webpages start with "/". Commands do not */
34 void (*xFunc)(void); /* Implementation function, or NULL for settings */
35 const char *zHelp; /* Raw help text */
@@ -39,31 +39,32 @@
39
40 /***************************************************************************
41 ** These macros must match similar macros in mkindex.c
42 ** Allowed values for CmdOrPage.eCmdFlags.
43 */
44 #define CMDFLAG_1ST_TIER 0x0001 /* Most important commands */
45 #define CMDFLAG_2ND_TIER 0x0002 /* Obscure and seldom used commands */
46 #define CMDFLAG_TEST 0x0004 /* Commands for testing only */
47 #define CMDFLAG_WEBPAGE 0x0008 /* Web pages */
48 #define CMDFLAG_COMMAND 0x0010 /* A command */
49 #define CMDFLAG_SETTING 0x0020 /* A setting */
50 #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
51 #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
52 #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
53 #define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret POST content */
54 /* NOTE: 0x0400 = CMDFLAG_SENSITIVE in mkindex.c! */
55 #define CMDFLAG_HIDDEN 0x0800 /* Elide from most listings */
56 #define CMDFLAG_LDAVG_EXEMPT 0x1000 /* Exempt from load_control() */
57 #define CMDFLAG_ALIAS 0x2000 /* Command aliases */
58 #define CMDFLAG_KEEPEMPTY 0x4000 /* Do not unset empty settings */
59 #define CMDFLAG_ABBREVSUBCMD 0x8000 /* Help text abbreviates subcommands */
 
60 /**************************************************************************/
61
62 /* Values for the 2nd parameter to dispatch_name_search() */
63 #define CMDFLAG_ANY 0x0038 /* Match anything */
64 #define CMDFLAG_PREFIX 0x0200 /* Prefix match is OK */
65
66 #endif /* INTERFACE */
67
68 /*
69 ** The page_index.h file contains the definition for aCommand[] - an array
@@ -461,11 +462,15 @@
461 || hasGap(zHelp+nIndent,i-nIndent) ){
462 iLevel++;
463 aIndent[iLevel] = nIndent;
464 azEnd[iLevel] = zEndDL;
465 wantP = 0;
466 blob_append(pHtml, "<blockquote><dl>\n", -1);
 
 
 
 
467 }else if( azEnd[iLevel]==zEndDL ){
468 iLevel++;
469 aIndent[iLevel] = nIndent;
470 azEnd[iLevel] = zEndDD;
471 if( wantP ){
@@ -578,10 +583,11 @@
578 if( mask & CMDFLAG_2ND_TIER ) fossil_print(" * Auxiliary commands\n");
579 if( mask & CMDFLAG_ALIAS ) fossil_print(" * Aliases\n");
580 if( mask & CMDFLAG_TEST ) fossil_print(" * Test commands\n");
581 if( mask & CMDFLAG_WEBPAGE ) fossil_print(" * Web pages\n");
582 if( mask & CMDFLAG_SETTING ) fossil_print(" * Settings\n");
 
583 if( useHtml ){
584 fossil_print("-->\n");
585 fossil_print("<!-- start_all_help -->\n");
586 }else{
587 fossil_print("---\n");
@@ -644,10 +650,11 @@
644 ** Defaults to just the CLI commands. Specify --www to see only the
645 ** web pages, or --everything to see both commands and pages.
646 **
647 ** Options:
648 ** -a|--aliases Show aliases
 
649 ** -e|--everything Show all commands and pages. Omit aliases to
650 ** avoid duplicates.
651 ** -h|--html Transform output to HTML
652 ** -o|--options Show global options
653 ** -r|--raw No output formatting
@@ -663,20 +670,23 @@
663 if( find_option("www","w",0) ){
664 mask = CMDFLAG_WEBPAGE;
665 }
666 if( find_option("everything","e",0) ){
667 mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
668 CMDFLAG_ALIAS | CMDFLAG_SETTING | CMDFLAG_TEST;
669 }
670 if( find_option("settings","s",0) ){
671 mask = CMDFLAG_SETTING;
672 }
673 if( find_option("aliases","a",0) ){
674 mask = CMDFLAG_ALIAS;
675 }
676 if( find_option("test","t",0) ){
677 mask |= CMDFLAG_TEST;
 
 
 
678 }
679 display_all_help(mask, useHtml, rawOut);
680 }
681
682 /*
@@ -710,10 +720,12 @@
710 countCmds( CMDFLAG_TEST ));
711 fossil_print("web-pages: %4d\n",
712 countCmds( CMDFLAG_WEBPAGE ));
713 fossil_print("settings: %4d\n",
714 countCmds( CMDFLAG_SETTING ));
 
 
715 fossil_print("total entries: %4d\n", MX_COMMAND);
716 }
717
718 /*
719 ** Compute an estimate of the edit-distance between to input strings.
@@ -892,10 +904,12 @@
892 /* Some of the webpages require query parameters in order to work.
893 ** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */
894 @ <h1>The "%h(pCmd->zName)" page:</h1>
895 }else if( rc==0 && (pCmd->eCmdFlags & CMDFLAG_SETTING)!=0 ){
896 @ <h1>The "%h(pCmd->zName)" setting:</h1>
 
 
897 }else{
898 @ <h1>The "%h(pCmd->zName)" command:</h1>
899 }
900 if( rc==1 || (rc==2 && zCmd[0]=='/') ){
901 if( zCmd && help_is_platform_command(zCmd) ){
@@ -933,11 +947,11 @@
933 int bktHelp[FOSSIL_MX_CMDIDX][MX_HELP_DUP] = {{0}};/* Help str->commands */
934 style_header("Help");
935 search_screen(SRCH_HELP, 0x02);
936
937 @ <a name='commands'></a>
938 @ <h1>Available commands:</h1>
939 @ <div class="columns" style="column-width: %s(zWidth);">
940 @ <ul>
941 /* Fill in help string buckets */
942 for(i=0; i<MX_COMMAND; i++){
943 if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
@@ -946,11 +960,13 @@
946 for(i=0; i<MX_COMMAND; i++){
947 const char *z = aCommand[i].zName;
948 const char *zBoldOn = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :"";
949 const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":"";
950 if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
951 if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)!=0 ) continue;
 
 
952 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
953 else if( (aCommand[i].eCmdFlags & CMDFLAG_ALIAS)!=0 ) continue;
954 @ <li><a href="%R/help/%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a>
955 /* Output aliases */
956 if( occHelp[aCommand[i].iHelp] > 1 ){
@@ -978,11 +994,11 @@
978 }
979
980 @ </ul></div>
981
982 @ <a name='webpages'></a>
983 @ <h1>Available web UI pages:</h1>
984 @ <div class="columns" style="column-width: %s(zWidth);">
985 @ <ul>
986 for(i=0; i<MX_COMMAND; i++){
987 const char *z = aCommand[i].zName;
988 if( '/'!=*z ) continue;
@@ -993,33 +1009,48 @@
993 @ <li>%s(z+1)</li>
994 }
995 }
996 @ </ul></div>
997
998 @ <a name='unsupported'></a>
999 @ <h1>Unsupported commands:</h1>
1000 @ <div class="columns" style="column-width: %s(zWidth);">
1001 @ <ul>
1002 for(i=0; i<MX_COMMAND; i++){
1003 const char *z = aCommand[i].zName;
1004 if( strncmp(z,"test",4)!=0 ) continue;
1005 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
1006 if( aCommand[i].zHelp[0] ){
1007 @ <li><a href="%R/help/%s(z)">%s(z)</a></li>
1008 }else{
1009 @ <li>%s(z)</li>
1010 }
1011 }
1012 @ </ul></div>
1013
1014 @ <a name='settings'></a>
1015 @ <h1>Settings:</h1>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1016 @ <div class="columns" style="column-width: %s(zWidth);">
1017 @ <ul>
1018 for(i=0; i<MX_COMMAND; i++){
1019 const char *z = aCommand[i].zName;
1020 if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
1021 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
1022 if( aCommand[i].zHelp[0] ){
1023 @ <li><a href="%R/help/%s(z)">%s(z)</a></li>
1024 }else{
1025 @ <li>%s(z)</li>
@@ -1059,10 +1090,12 @@
1059 zDesc = "2nd tier command";
1060 }else if( e & CMDFLAG_ALIAS ){
1061 zDesc = "alias";
1062 }else if( e & CMDFLAG_TEST ){
1063 zDesc = "test command";
 
 
1064 }else if( e & CMDFLAG_WEBPAGE ){
1065 if( e & CMDFLAG_RAWCONTENT ){
1066 zDesc = "raw-content web page";
1067 }else{
1068 zDesc = "web page";
@@ -1155,11 +1188,11 @@
1155 Blob *pOut, /* Write simplified help text here */
1156 const char *zTopic, /* TOPIC */
1157 const char *zSubtopic, /* SUBTOPIC */
1158 int bAbbrevSubcmd /* True if z[] contains abbreviated subcommands */
1159 ){
1160 Blob in, line; //, subsection;
1161 int n = 0;
1162 char *zQTop = re_quote(zTopic);
1163 char *zQSub = re_quote(zSubtopic);
1164 char *zPattern;
1165 ReCompiled *pRe = 0;
@@ -1392,46 +1425,44 @@
1392 multi_column_list(aCmd, nCmd);
1393 }
1394 }
1395
1396 /*
1397 ** Documentation on universal command-line options.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1398 */
1399 /* @-comment: # */
1400 static const char zOptions[] =
1401 @ Command-line options common to all commands:
1402 @
1403 @ --args FILENAME Read additional arguments and options from FILENAME
1404 @ --case-sensitive BOOL Set case sensitivity for file names
1405 @ --cgitrace Active CGI tracing
1406 @ --chdir PATH Change to PATH before performing any operations
1407 @ --errorlog FILENAME Log errors to FILENAME
1408 @ -?|--help Show help on the command rather than running it
1409 @ --httptrace Trace outbound HTTP requests
1410 @ --localtime Display times using the local timezone
1411 @ --nocgi Do not act as CGI
1412 @ --no-th-hook Do not run TH1 hooks
1413 @ --quiet Reduce the amount of output
1414 @ --sqlstats Show SQL usage statistics when done
1415 @ --sqltrace Trace all SQL commands
1416 @ --sshtrace Trace SSH activity
1417 @ --ssl-identity NAME Set the SSL identity to NAME
1418 @ --systemtrace Trace calls to system()
1419 @ -U|--user USER Make the default user be USER
1420 @ --utc Display times using UTC
1421 @ --vfs NAME Cause SQLite to use the NAME VFS
1422 @
1423 @ Additional options available on most commands that use network I/O:
1424 @
1425 @ --accept-any-cert Disable server SSL cdert validation. Accept any SSL
1426 @ cert that the server provides. WARNING: Unsafe!
1427 @ Testing and debugging use only!
1428 @ --ipv4 Use only IPv4. Disable IPv6 support.
1429 @ --ipv6 Use only IPv6. Disable IPv4 support.
1430 @ --nosync Disable autosync for the current command.
1431 @ --proxy URL Specify the HTTP proxy to use. URL can be "off".
1432 ;
1433
1434 /*
1435 ** COMMAND: help
1436 **
1437 ** Usage: %fossil help [OPTIONS] [TOPIC] [SUBCOMMAND]
@@ -1508,21 +1539,26 @@
1508 return;
1509 }
1510 else if( find_option("setting","s",0) ){
1511 command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1512 return;
 
 
 
 
1513 }
1514 else if( find_option("full","f",0) ){
1515 fossil_print("fossil commands:\n\n");
1516 command_list(CMDFLAG_1ST_TIER, verboseFlag, useHtml);
1517 fossil_print("\nfossil auxiliary commands:\n\n");
1518 command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
1519 fossil_print("\n%s", zOptions);
1520 fossil_print("\nfossil settings:\n\n");
1521 command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1522 fossil_print("\nfossil web pages:\n\n");
1523 command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
 
 
1524 fossil_print("\nfossil test commands (unsupported):\n\n");
1525 command_list(CMDFLAG_TEST, verboseFlag, useHtml);
1526 if ( !verboseFlag ) {
1527 fossil_print("\n");
1528 version_cmd();
@@ -1529,18 +1565,23 @@
1529 }
1530 return;
1531 }
1532 else if( find_option("everything","e",0) ){
1533 display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1534 CMDFLAG_SETTING | CMDFLAG_TEST, useHtml, 0);
 
1535 return;
1536 }
1537 verify_all_options();
 
1538 if( g.argc<3 ){
1539 if( bOptions ){
1540 fossil_print("%s", zOptions);
1541 return;
 
 
 
1542 }
1543 z = g.argv[0];
1544 fossil_print(
1545 "Usage: %s help TOPIC\n"
1546 "Things to try:\n\n"
@@ -1560,14 +1601,13 @@
1560 if( isPage ){
1561 zCmdOrPage = "page";
1562 }else if( commandsFlag ){
1563 mask = CMDFLAG_COMMAND;
1564 zCmdOrPage = "command";
1565 }else{
1566 zCmdOrPage = "command or setting";
1567 }
1568 rc = dispatch_name_search(g.argv[2], mask|CMDFLAG_PREFIX, &pCmd);
 
1569 if( rc ){
1570 int i, n;
1571 const char *az[5];
1572 if( rc==1 ){
1573 if( help_is_platform_command(g.argv[2]) ){
@@ -1805,10 +1845,12 @@
1805 zType = "command";
1806 }else if( pPage->eCmdFlags & CMDFLAG_WEBPAGE ){
1807 zType = "webpage";
1808 }else if( pPage->eCmdFlags & CMDFLAG_SETTING ){
1809 zType = "setting";
 
 
1810 }
1811 sqlite3_result_text(ctx, zType, -1, SQLITE_STATIC);
1812 break;
1813 }
1814 case 2: /* flags */
1815
--- src/dispatch.c
+++ src/dispatch.c
@@ -25,11 +25,11 @@
25 #include "dispatch.h"
26
27 #if INTERFACE
28 /*
29 ** An instance of this object defines everything we need to know about an
30 ** individual command, webpage, setting, or help topic.
31 */
32 struct CmdOrPage {
33 const char *zName; /* Name. Webpages start with "/". Commands do not */
34 void (*xFunc)(void); /* Implementation function, or NULL for settings */
35 const char *zHelp; /* Raw help text */
@@ -39,31 +39,32 @@
39
40 /***************************************************************************
41 ** These macros must match similar macros in mkindex.c
42 ** Allowed values for CmdOrPage.eCmdFlags.
43 */
44 #define CMDFLAG_1ST_TIER 0x000001 /* Most important commands */
45 #define CMDFLAG_2ND_TIER 0x000002 /* Obscure and seldom used commands */
46 #define CMDFLAG_TEST 0x000004 /* Commands for testing only */
47 #define CMDFLAG_WEBPAGE 0x000008 /* Web pages */
48 #define CMDFLAG_COMMAND 0x000010 /* A command */
49 #define CMDFLAG_SETTING 0x000020 /* A setting */
50 #define CMDFLAG_VERSIONABLE 0x000040 /* A versionable setting */
51 #define CMDFLAG_BLOCKTEXT 0x000080 /* Multi-line text setting */
52 #define CMDFLAG_BOOLEAN 0x000100 /* A boolean setting */
53 #define CMDFLAG_RAWCONTENT 0x000200 /* Do not interpret POST content */
54 /* NOTE: 0x000400 = CMDFLAG_SENSITIVE in mkindex.c! */
55 #define CMDFLAG_HIDDEN 0x000800 /* Elide from most listings */
56 #define CMDFLAG_LDAVG_EXEMPT 0x001000 /* Exempt from load_control() */
57 #define CMDFLAG_ALIAS 0x002000 /* Command aliases */
58 #define CMDFLAG_KEEPEMPTY 0x004000 /* Do not unset empty settings */
59 #define CMDFLAG_ABBREVSUBCMD 0x008000 /* Help text abbreviates subcommands */
60 #define CMDFLAG_TOPIC 0x010000 /* A help topic */
61 /**************************************************************************/
62
63 /* Values for the 2nd parameter to dispatch_name_search() */
64 #define CMDFLAG_ANY 0x010038 /* Match anything */
65 #define CMDFLAG_PREFIX 0x000200 /* Prefix match is OK */
66
67 #endif /* INTERFACE */
68
69 /*
70 ** The page_index.h file contains the definition for aCommand[] - an array
@@ -461,11 +462,15 @@
462 || hasGap(zHelp+nIndent,i-nIndent) ){
463 iLevel++;
464 aIndent[iLevel] = nIndent;
465 azEnd[iLevel] = zEndDL;
466 wantP = 0;
467 if( isDT ){
468 blob_append(pHtml, "<blockquote><dl>\n", -1);
469 }else{
470 blob_append(pHtml, "<blockquote><dl class=\"helpOptions\">\n", -1);
471 }
472 }else if( azEnd[iLevel]==zEndDL ){
473 iLevel++;
474 aIndent[iLevel] = nIndent;
475 azEnd[iLevel] = zEndDD;
476 if( wantP ){
@@ -578,10 +583,11 @@
583 if( mask & CMDFLAG_2ND_TIER ) fossil_print(" * Auxiliary commands\n");
584 if( mask & CMDFLAG_ALIAS ) fossil_print(" * Aliases\n");
585 if( mask & CMDFLAG_TEST ) fossil_print(" * Test commands\n");
586 if( mask & CMDFLAG_WEBPAGE ) fossil_print(" * Web pages\n");
587 if( mask & CMDFLAG_SETTING ) fossil_print(" * Settings\n");
588 if( mask & CMDFLAG_TOPIC ) fossil_print(" * Help Topic\n");
589 if( useHtml ){
590 fossil_print("-->\n");
591 fossil_print("<!-- start_all_help -->\n");
592 }else{
593 fossil_print("---\n");
@@ -644,10 +650,11 @@
650 ** Defaults to just the CLI commands. Specify --www to see only the
651 ** web pages, or --everything to see both commands and pages.
652 **
653 ** Options:
654 ** -a|--aliases Show aliases
655 ** -c|--topics Show help topics
656 ** -e|--everything Show all commands and pages. Omit aliases to
657 ** avoid duplicates.
658 ** -h|--html Transform output to HTML
659 ** -o|--options Show global options
660 ** -r|--raw No output formatting
@@ -663,20 +670,23 @@
670 if( find_option("www","w",0) ){
671 mask = CMDFLAG_WEBPAGE;
672 }
673 if( find_option("everything","e",0) ){
674 mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
675 CMDFLAG_ALIAS | CMDFLAG_SETTING | CMDFLAG_TEST | CMDFLAG_TOPIC;
676 }
677 if( find_option("settings","s",0) ){
678 mask = CMDFLAG_SETTING;
679 }
680 if( find_option("aliases","a",0) ){
681 mask = CMDFLAG_ALIAS;
682 }
683 if( find_option("test","t",0) ){
684 mask |= CMDFLAG_TEST;
685 }
686 if( find_option("topics","c",0) ){
687 mask |= CMDFLAG_TOPIC;
688 }
689 display_all_help(mask, useHtml, rawOut);
690 }
691
692 /*
@@ -710,10 +720,12 @@
720 countCmds( CMDFLAG_TEST ));
721 fossil_print("web-pages: %4d\n",
722 countCmds( CMDFLAG_WEBPAGE ));
723 fossil_print("settings: %4d\n",
724 countCmds( CMDFLAG_SETTING ));
725 fossil_print("help-topics: %4d\n",
726 countCmds( CMDFLAG_TOPIC ));
727 fossil_print("total entries: %4d\n", MX_COMMAND);
728 }
729
730 /*
731 ** Compute an estimate of the edit-distance between to input strings.
@@ -892,10 +904,12 @@
904 /* Some of the webpages require query parameters in order to work.
905 ** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */
906 @ <h1>The "%h(pCmd->zName)" page:</h1>
907 }else if( rc==0 && (pCmd->eCmdFlags & CMDFLAG_SETTING)!=0 ){
908 @ <h1>The "%h(pCmd->zName)" setting:</h1>
909 }else if( rc==0 && (pCmd->eCmdFlags & CMDFLAG_TOPIC)!=0 ){
910 @ <h1>The "%h(pCmd->zName)" help topic:</h1>
911 }else{
912 @ <h1>The "%h(pCmd->zName)" command:</h1>
913 }
914 if( rc==1 || (rc==2 && zCmd[0]=='/') ){
915 if( zCmd && help_is_platform_command(zCmd) ){
@@ -933,11 +947,11 @@
947 int bktHelp[FOSSIL_MX_CMDIDX][MX_HELP_DUP] = {{0}};/* Help str->commands */
948 style_header("Help");
949 search_screen(SRCH_HELP, 0x02);
950
951 @ <a name='commands'></a>
952 @ <h1>Commands:</h1>
953 @ <div class="columns" style="column-width: %s(zWidth);">
954 @ <ul>
955 /* Fill in help string buckets */
956 for(i=0; i<MX_COMMAND; i++){
957 if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
@@ -946,11 +960,13 @@
960 for(i=0; i<MX_COMMAND; i++){
961 const char *z = aCommand[i].zName;
962 const char *zBoldOn = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :"";
963 const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":"";
964 if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
965 if( (aCommand[i].eCmdFlags & (CMDFLAG_SETTING|CMDFLAG_TOPIC))!=0 ){
966 continue;
967 }
968 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
969 else if( (aCommand[i].eCmdFlags & CMDFLAG_ALIAS)!=0 ) continue;
970 @ <li><a href="%R/help/%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a>
971 /* Output aliases */
972 if( occHelp[aCommand[i].iHelp] > 1 ){
@@ -978,11 +994,11 @@
994 }
995
996 @ </ul></div>
997
998 @ <a name='webpages'></a>
999 @ <h1>Web pages:</h1>
1000 @ <div class="columns" style="column-width: %s(zWidth);">
1001 @ <ul>
1002 for(i=0; i<MX_COMMAND; i++){
1003 const char *z = aCommand[i].zName;
1004 if( '/'!=*z ) continue;
@@ -993,33 +1009,48 @@
1009 @ <li>%s(z+1)</li>
1010 }
1011 }
1012 @ </ul></div>
1013
1014 @ <a name='settings'></a>
1015 @ <h1>Settings:</h1>
1016 @ <div class="columns" style="column-width: %s(zWidth);">
1017 @ <ul>
1018 for(i=0; i<MX_COMMAND; i++){
1019 const char *z = aCommand[i].zName;
1020 if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
1021 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
1022 if( aCommand[i].zHelp[0] ){
1023 @ <li><a href="%R/help/%s(z)">%s(z)</a></li>
1024 }else{
1025 @ <li>%s(z)</li>
1026 }
1027 }
1028 @ </ul></div>
1029
1030 @ <a name='topics'></a>
1031 @ <h1>Other Miscellaneous Help Topics:</h1>
1032 @ <div class="columns" style="column-width: %s(zWidth);">
1033 @ <ul>
1034 for(i=0; i<MX_COMMAND; i++){
1035 const char *z = aCommand[i].zName;
1036 if( (aCommand[i].eCmdFlags & CMDFLAG_TOPIC)==0 ) continue;
1037 if( aCommand[i].zHelp[0] ){
1038 @ <li><a href="%R/help/%s(z)">%s(z)</a></li>
1039 }else{
1040 @ <li>%s(z)</li>
1041 }
1042 }
1043 @ </ul></div>
1044
1045 @ <a name='unsupported'></a>
1046 @ <h1>Unsupported and Testing Commands:</h1>
1047 @ <div class="columns" style="column-width: %s(zWidth);">
1048 @ <ul>
1049 for(i=0; i<MX_COMMAND; i++){
1050 const char *z = aCommand[i].zName;
1051 if( strncmp(z,"test",4)!=0 ) continue;
1052 else if( (aCommand[i].eCmdFlags & CMDFLAG_HIDDEN)!=0 ) continue;
1053 if( aCommand[i].zHelp[0] ){
1054 @ <li><a href="%R/help/%s(z)">%s(z)</a></li>
1055 }else{
1056 @ <li>%s(z)</li>
@@ -1059,10 +1090,12 @@
1090 zDesc = "2nd tier command";
1091 }else if( e & CMDFLAG_ALIAS ){
1092 zDesc = "alias";
1093 }else if( e & CMDFLAG_TEST ){
1094 zDesc = "test command";
1095 }else if( e & CMDFLAG_TOPIC ){
1096 zDesc = "help-topic";
1097 }else if( e & CMDFLAG_WEBPAGE ){
1098 if( e & CMDFLAG_RAWCONTENT ){
1099 zDesc = "raw-content web page";
1100 }else{
1101 zDesc = "web page";
@@ -1155,11 +1188,11 @@
1188 Blob *pOut, /* Write simplified help text here */
1189 const char *zTopic, /* TOPIC */
1190 const char *zSubtopic, /* SUBTOPIC */
1191 int bAbbrevSubcmd /* True if z[] contains abbreviated subcommands */
1192 ){
1193 Blob in, line;/*, subsection;*/
1194 int n = 0;
1195 char *zQTop = re_quote(zTopic);
1196 char *zQSub = re_quote(zSubtopic);
1197 char *zPattern;
1198 ReCompiled *pRe = 0;
@@ -1392,46 +1425,44 @@
1425 multi_column_list(aCmd, nCmd);
1426 }
1427 }
1428
1429 /*
1430 ** TOPIC: options
1431 **
1432 ** Command-line options common to all commands:
1433 **
1434 ** --args FILENAME Read additional arguments and options from FILENAME
1435 ** --case-sensitive BOOL Set case sensitivity for file names
1436 ** --cgitrace Active CGI tracing
1437 ** --chdir PATH Change to PATH before performing any operations
1438 ** --errorlog FILENAME Log errors to FILENAME
1439 ** -?|--help Show help on the command rather than running it
1440 ** --httptrace Trace outbound HTTP requests
1441 ** --localtime Display times using the local timezone
1442 ** --nocgi Do not act as CGI
1443 ** --no-th-hook Do not run TH1 hooks
1444 ** -q|--quiet Reduce the amount of output
1445 ** --sqlstats Show SQL usage statistics when done
1446 ** --sqltrace Trace all SQL commands
1447 ** --sshtrace Trace SSH activity
1448 ** --ssl-identity NAME Set the SSL identity to NAME
1449 ** --systemtrace Trace calls to system()
1450 ** -U|--user USER Make the default user be USER
1451 ** --utc Display times using UTC
1452 ** --vfs NAME Cause SQLite to use the NAME VFS
1453 **
1454 ** Additional options available on most commands that use network I/O:
1455 **
1456 ** --accept-any-cert Disable server SSL cdert validation. Accept any SSL
1457 ** cert that the server provides. WARNING: Unsafe!
1458 ** Testing and debugging use only!
1459 ** --ipv4 Use only IPv4. Disable IPv6 support.
1460 ** --ipv6 Use only IPv6. Disable IPv4 support.
1461 ** --nosync Disable autosync for the current command.
1462 ** --proxy URL Specify the HTTP proxy to use. URL can be "off".
1463 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1464
1465 /*
1466 ** COMMAND: help
1467 **
1468 ** Usage: %fossil help [OPTIONS] [TOPIC] [SUBCOMMAND]
@@ -1508,21 +1539,26 @@
1539 return;
1540 }
1541 else if( find_option("setting","s",0) ){
1542 command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1543 return;
1544 }
1545 else if( find_option("topic","c",0) ){
1546 command_list(CMDFLAG_TOPIC, verboseFlag, useHtml);
1547 return;
1548 }
1549 else if( find_option("full","f",0) ){
1550 fossil_print("fossil commands:\n\n");
1551 command_list(CMDFLAG_1ST_TIER, verboseFlag, useHtml);
1552 fossil_print("\nfossil auxiliary commands:\n\n");
1553 command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml);
 
1554 fossil_print("\nfossil settings:\n\n");
1555 command_list(CMDFLAG_SETTING, verboseFlag, useHtml);
1556 fossil_print("\nfossil web pages:\n\n");
1557 command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml);
1558 fossil_print("\nfossil miscellaneous help topics:\n\n");
1559 command_list(CMDFLAG_TOPIC, verboseFlag, useHtml);
1560 fossil_print("\nfossil test commands (unsupported):\n\n");
1561 command_list(CMDFLAG_TEST, verboseFlag, useHtml);
1562 if ( !verboseFlag ) {
1563 fossil_print("\n");
1564 version_cmd();
@@ -1529,18 +1565,23 @@
1565 }
1566 return;
1567 }
1568 else if( find_option("everything","e",0) ){
1569 display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE |
1570 CMDFLAG_SETTING | CMDFLAG_TEST | CMDFLAG_TOPIC,
1571 useHtml, 0);
1572 return;
1573 }
1574 verify_all_options();
1575 zCmdOrPage = "help topic";
1576 if( g.argc<3 ){
1577 if( bOptions ){
1578 zTopic = "options";
1579 zSubtopic = 0;
1580 mask = CMDFLAG_TOPIC;
1581 bOptions = 0;
1582 goto find_and_show_help;
1583 }
1584 z = g.argv[0];
1585 fossil_print(
1586 "Usage: %s help TOPIC\n"
1587 "Things to try:\n\n"
@@ -1560,14 +1601,13 @@
1601 if( isPage ){
1602 zCmdOrPage = "page";
1603 }else if( commandsFlag ){
1604 mask = CMDFLAG_COMMAND;
1605 zCmdOrPage = "command";
 
 
1606 }
1607 find_and_show_help:
1608 rc = dispatch_name_search(zTopic, mask|CMDFLAG_PREFIX, &pCmd);
1609 if( rc ){
1610 int i, n;
1611 const char *az[5];
1612 if( rc==1 ){
1613 if( help_is_platform_command(g.argv[2]) ){
@@ -1805,10 +1845,12 @@
1845 zType = "command";
1846 }else if( pPage->eCmdFlags & CMDFLAG_WEBPAGE ){
1847 zType = "webpage";
1848 }else if( pPage->eCmdFlags & CMDFLAG_SETTING ){
1849 zType = "setting";
1850 }else if( pPage->eCmdFlags & CMDFLAG_TOPIC ){
1851 zType = "help-topic";
1852 }
1853 sqlite3_result_text(ctx, zType, -1, SQLITE_STATIC);
1854 break;
1855 }
1856 case 2: /* flags */
1857
+1 -1
--- src/event.c
+++ src/event.c
@@ -425,11 +425,11 @@
425425
if( rid ){
426426
zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
427427
if( zClr && zClr[0] ){
428428
const char * zRequestMethod = P("REQUEST_METHOD");
429429
if(zRequestMethod && 'G'==zRequestMethod[0]){
430
- /* Apply saved color by defaut for GET requests
430
+ /* Apply saved color by default for GET requests
431431
** (e.g., an Edit menu link).
432432
*/
433433
zClrFlag = " checked";
434434
}
435435
}
436436
--- src/event.c
+++ src/event.c
@@ -425,11 +425,11 @@
425 if( rid ){
426 zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
427 if( zClr && zClr[0] ){
428 const char * zRequestMethod = P("REQUEST_METHOD");
429 if(zRequestMethod && 'G'==zRequestMethod[0]){
430 /* Apply saved color by defaut for GET requests
431 ** (e.g., an Edit menu link).
432 */
433 zClrFlag = " checked";
434 }
435 }
436
--- src/event.c
+++ src/event.c
@@ -425,11 +425,11 @@
425 if( rid ){
426 zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
427 if( zClr && zClr[0] ){
428 const char * zRequestMethod = P("REQUEST_METHOD");
429 if(zRequestMethod && 'G'==zRequestMethod[0]){
430 /* Apply saved color by default for GET requests
431 ** (e.g., an Edit menu link).
432 */
433 zClrFlag = " checked";
434 }
435 }
436
+4 -3
--- src/export.c
+++ src/export.c
@@ -28,11 +28,11 @@
2828
const char *zTrunkName; /* Name of trunk branch */
2929
} gexport;
3030
3131
#if INTERFACE
3232
/*
33
-** Each line in a git-fast-export "marK" file is an instance of
33
+** Each line in a git-fast-export "mark" file is an instance of
3434
** this object.
3535
*/
3636
struct mark_t {
3737
char *name; /* Name of the mark. Also starts with ":" */
3838
int rid; /* Corresponding object in the BLOB table */
@@ -759,11 +759,11 @@
759759
**
760760
** This table contains all check-ins of the repository in topological
761761
** order. "Topological order" means that every parent check-in comes
762762
** before all of its children. Topological order is *almost* the same
763763
** thing as "ORDER BY event.mtime". Differences only arise when there
764
-** are timewarps. In as much as Git hates timewarps, we have to compute
764
+** are timewarps. Inasmuch as Git hates timewarps, we have to compute
765765
** a correct topological order when doing an export.
766766
**
767767
** Since mtime is a usually already nearly in topological order, the
768768
** algorithm is to start with mtime, then make adjustments as necessary
769769
** for timewarps. This is not a great algorithm for the general case,
@@ -1413,10 +1413,11 @@
14131413
zAutoPush = find_option("autopush",0,1);
14141414
zMainBr = (char*)find_option("mainbranch",0,1);
14151415
bForce = find_option("force","f",0)!=0;
14161416
bIfExists = find_option("if-mirrored",0,0)!=0;
14171417
gitmirror_verbosity = VERB_NORMAL;
1418
+ if( g.fQuiet ){ gitmirror_verbosity--; } /* Global option not repeatable. */
14181419
while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; }
14191420
while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; }
14201421
verify_all_options();
14211422
if( g.argc!=4 && g.argc!=3 ){ usage("export ?MIRROR?"); }
14221423
if( g.argc==4 ){
@@ -1752,11 +1753,11 @@
17521753
int bQuiet = 0;
17531754
int bByAll = 0; /* Undocumented option meaning this command was invoked
17541755
** from "fossil all" and should modify output accordingly */
17551756
17561757
db_find_and_open_repository(0, 0);
1757
- bQuiet = find_option("quiet","q",0)!=0;
1758
+ bQuiet = g.fQuiet;
17581759
bByAll = find_option("by-all",0,0)!=0;
17591760
verify_all_options();
17601761
zMirror = db_get("last-git-export-repo", 0);
17611762
if( zMirror==0 ){
17621763
if( bQuiet ) return;
17631764
--- src/export.c
+++ src/export.c
@@ -28,11 +28,11 @@
28 const char *zTrunkName; /* Name of trunk branch */
29 } gexport;
30
31 #if INTERFACE
32 /*
33 ** Each line in a git-fast-export "marK" file is an instance of
34 ** this object.
35 */
36 struct mark_t {
37 char *name; /* Name of the mark. Also starts with ":" */
38 int rid; /* Corresponding object in the BLOB table */
@@ -759,11 +759,11 @@
759 **
760 ** This table contains all check-ins of the repository in topological
761 ** order. "Topological order" means that every parent check-in comes
762 ** before all of its children. Topological order is *almost* the same
763 ** thing as "ORDER BY event.mtime". Differences only arise when there
764 ** are timewarps. In as much as Git hates timewarps, we have to compute
765 ** a correct topological order when doing an export.
766 **
767 ** Since mtime is a usually already nearly in topological order, the
768 ** algorithm is to start with mtime, then make adjustments as necessary
769 ** for timewarps. This is not a great algorithm for the general case,
@@ -1413,10 +1413,11 @@
1413 zAutoPush = find_option("autopush",0,1);
1414 zMainBr = (char*)find_option("mainbranch",0,1);
1415 bForce = find_option("force","f",0)!=0;
1416 bIfExists = find_option("if-mirrored",0,0)!=0;
1417 gitmirror_verbosity = VERB_NORMAL;
 
1418 while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; }
1419 while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; }
1420 verify_all_options();
1421 if( g.argc!=4 && g.argc!=3 ){ usage("export ?MIRROR?"); }
1422 if( g.argc==4 ){
@@ -1752,11 +1753,11 @@
1752 int bQuiet = 0;
1753 int bByAll = 0; /* Undocumented option meaning this command was invoked
1754 ** from "fossil all" and should modify output accordingly */
1755
1756 db_find_and_open_repository(0, 0);
1757 bQuiet = find_option("quiet","q",0)!=0;
1758 bByAll = find_option("by-all",0,0)!=0;
1759 verify_all_options();
1760 zMirror = db_get("last-git-export-repo", 0);
1761 if( zMirror==0 ){
1762 if( bQuiet ) return;
1763
--- src/export.c
+++ src/export.c
@@ -28,11 +28,11 @@
28 const char *zTrunkName; /* Name of trunk branch */
29 } gexport;
30
31 #if INTERFACE
32 /*
33 ** Each line in a git-fast-export "mark" file is an instance of
34 ** this object.
35 */
36 struct mark_t {
37 char *name; /* Name of the mark. Also starts with ":" */
38 int rid; /* Corresponding object in the BLOB table */
@@ -759,11 +759,11 @@
759 **
760 ** This table contains all check-ins of the repository in topological
761 ** order. "Topological order" means that every parent check-in comes
762 ** before all of its children. Topological order is *almost* the same
763 ** thing as "ORDER BY event.mtime". Differences only arise when there
764 ** are timewarps. Inasmuch as Git hates timewarps, we have to compute
765 ** a correct topological order when doing an export.
766 **
767 ** Since mtime is a usually already nearly in topological order, the
768 ** algorithm is to start with mtime, then make adjustments as necessary
769 ** for timewarps. This is not a great algorithm for the general case,
@@ -1413,10 +1413,11 @@
1413 zAutoPush = find_option("autopush",0,1);
1414 zMainBr = (char*)find_option("mainbranch",0,1);
1415 bForce = find_option("force","f",0)!=0;
1416 bIfExists = find_option("if-mirrored",0,0)!=0;
1417 gitmirror_verbosity = VERB_NORMAL;
1418 if( g.fQuiet ){ gitmirror_verbosity--; } /* Global option not repeatable. */
1419 while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; }
1420 while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; }
1421 verify_all_options();
1422 if( g.argc!=4 && g.argc!=3 ){ usage("export ?MIRROR?"); }
1423 if( g.argc==4 ){
@@ -1752,11 +1753,11 @@
1753 int bQuiet = 0;
1754 int bByAll = 0; /* Undocumented option meaning this command was invoked
1755 ** from "fossil all" and should modify output accordingly */
1756
1757 db_find_and_open_repository(0, 0);
1758 bQuiet = g.fQuiet;
1759 bByAll = find_option("by-all",0,0)!=0;
1760 verify_all_options();
1761 zMirror = db_get("last-git-export-repo", 0);
1762 if( zMirror==0 ){
1763 if( bQuiet ) return;
1764
+2 -2
--- src/file.c
+++ src/file.c
@@ -51,11 +51,11 @@
5151
** a few special cases such as the "fossil test-tarball" command when we never
5252
** want to follow symlinks.
5353
**
5454
** ExtFILE Symbolic links always refer to the object to which the
5555
** link points. Symlinks are never recognized as symlinks but
56
-** instead always appear to the the target object.
56
+** instead always appear to be the target object.
5757
**
5858
** SymFILE Symbolic links always appear to be files whose name is
5959
** the target pathname of the symbolic link.
6060
**
6161
** RepoFILE Like SymFILE if allow-symlinks is true, or like
@@ -2818,11 +2818,11 @@
28182818
i64 nowTime = 0; /* Timestamp of --now or --checkout */
28192819
Stmt q;
28202820
Blob absBuffer = empty_blob; /* Absolute filename buffer */
28212821
28222822
verboseFlag = find_option("verbose","v",0)!=0;
2823
- quietFlag = find_option("quiet","q",0)!=0 || g.fQuiet;
2823
+ quietFlag = g.fQuiet;
28242824
dryRunFlag = find_option("dry-run","n",0)!=0;
28252825
zGlobList = find_option("glob", "g",1);
28262826
zGlobFile = find_option("globfile", "G",1);
28272827
28282828
if(zGlobList && zGlobFile){
28292829
--- src/file.c
+++ src/file.c
@@ -51,11 +51,11 @@
51 ** a few special cases such as the "fossil test-tarball" command when we never
52 ** want to follow symlinks.
53 **
54 ** ExtFILE Symbolic links always refer to the object to which the
55 ** link points. Symlinks are never recognized as symlinks but
56 ** instead always appear to the the target object.
57 **
58 ** SymFILE Symbolic links always appear to be files whose name is
59 ** the target pathname of the symbolic link.
60 **
61 ** RepoFILE Like SymFILE if allow-symlinks is true, or like
@@ -2818,11 +2818,11 @@
2818 i64 nowTime = 0; /* Timestamp of --now or --checkout */
2819 Stmt q;
2820 Blob absBuffer = empty_blob; /* Absolute filename buffer */
2821
2822 verboseFlag = find_option("verbose","v",0)!=0;
2823 quietFlag = find_option("quiet","q",0)!=0 || g.fQuiet;
2824 dryRunFlag = find_option("dry-run","n",0)!=0;
2825 zGlobList = find_option("glob", "g",1);
2826 zGlobFile = find_option("globfile", "G",1);
2827
2828 if(zGlobList && zGlobFile){
2829
--- src/file.c
+++ src/file.c
@@ -51,11 +51,11 @@
51 ** a few special cases such as the "fossil test-tarball" command when we never
52 ** want to follow symlinks.
53 **
54 ** ExtFILE Symbolic links always refer to the object to which the
55 ** link points. Symlinks are never recognized as symlinks but
56 ** instead always appear to be the target object.
57 **
58 ** SymFILE Symbolic links always appear to be files whose name is
59 ** the target pathname of the symbolic link.
60 **
61 ** RepoFILE Like SymFILE if allow-symlinks is true, or like
@@ -2818,11 +2818,11 @@
2818 i64 nowTime = 0; /* Timestamp of --now or --checkout */
2819 Stmt q;
2820 Blob absBuffer = empty_blob; /* Absolute filename buffer */
2821
2822 verboseFlag = find_option("verbose","v",0)!=0;
2823 quietFlag = g.fQuiet;
2824 dryRunFlag = find_option("dry-run","n",0)!=0;
2825 zGlobList = find_option("glob", "g",1);
2826 zGlobFile = find_option("globfile", "G",1);
2827
2828 if(zGlobList && zGlobFile){
2829
+3 -3
--- src/fileedit.c
+++ src/fileedit.c
@@ -48,11 +48,11 @@
4848
Blob comment; /* Check-in comment text */
4949
char *zCommentMimetype; /* Mimetype of comment. May be NULL */
5050
char *zUser; /* User name */
5151
char *zDate; /* Optionally force this date string (anything
5252
supported by date_in_standard_format()).
53
- Maybe be NULL. */
53
+ May be NULL. */
5454
Blob *pMfOut; /* If not NULL, checkin_mini() will write a
5555
copy of the generated manifest here. This
5656
memory is NOT owned by CheckinMiniInfo. */
5757
int filePerm; /* Permissions (via file_perm()) of the input
5858
file. We need to store this before calling
@@ -123,11 +123,11 @@
123123
*/
124124
CIMINI_PREFER_DELTA = 1<<8,
125125
/*
126126
** A "stronger hint" to checkin_mini() to prefer creation of a delta
127127
** manifest if it at all can. It will decide not to only if creation
128
-** of a delta is not a realistic option or if it's forbitted by the
128
+** of a delta is not a realistic option or if it's forbidden by the
129129
** forbid-delta-manifests repo config option. For this to work, it
130130
** must be set together with the CIMINI_PREFER_DELTA flag, but the two
131131
** cannot be combined in this enum.
132132
**
133133
** This option is ONLY INTENDED FOR TESTING, used in bypassing
@@ -400,11 +400,11 @@
400400
** This routine uses the state from the given fully-populated pCI
401401
** argument to add pCI->fileContent to the database, and create and
402402
** save a manifest for that change. Ownership of pCI and its contents
403403
** are unchanged.
404404
**
405
-** This function may may modify pCI as follows:
405
+** This function may modify pCI as follows:
406406
**
407407
** - If one of Manifest pCI->pParent or pCI->zParentUuid are NULL,
408408
** then the other will be assigned based on its counterpart. Both
409409
** may not be NULL.
410410
**
411411
--- src/fileedit.c
+++ src/fileedit.c
@@ -48,11 +48,11 @@
48 Blob comment; /* Check-in comment text */
49 char *zCommentMimetype; /* Mimetype of comment. May be NULL */
50 char *zUser; /* User name */
51 char *zDate; /* Optionally force this date string (anything
52 supported by date_in_standard_format()).
53 Maybe be NULL. */
54 Blob *pMfOut; /* If not NULL, checkin_mini() will write a
55 copy of the generated manifest here. This
56 memory is NOT owned by CheckinMiniInfo. */
57 int filePerm; /* Permissions (via file_perm()) of the input
58 file. We need to store this before calling
@@ -123,11 +123,11 @@
123 */
124 CIMINI_PREFER_DELTA = 1<<8,
125 /*
126 ** A "stronger hint" to checkin_mini() to prefer creation of a delta
127 ** manifest if it at all can. It will decide not to only if creation
128 ** of a delta is not a realistic option or if it's forbitted by the
129 ** forbid-delta-manifests repo config option. For this to work, it
130 ** must be set together with the CIMINI_PREFER_DELTA flag, but the two
131 ** cannot be combined in this enum.
132 **
133 ** This option is ONLY INTENDED FOR TESTING, used in bypassing
@@ -400,11 +400,11 @@
400 ** This routine uses the state from the given fully-populated pCI
401 ** argument to add pCI->fileContent to the database, and create and
402 ** save a manifest for that change. Ownership of pCI and its contents
403 ** are unchanged.
404 **
405 ** This function may may modify pCI as follows:
406 **
407 ** - If one of Manifest pCI->pParent or pCI->zParentUuid are NULL,
408 ** then the other will be assigned based on its counterpart. Both
409 ** may not be NULL.
410 **
411
--- src/fileedit.c
+++ src/fileedit.c
@@ -48,11 +48,11 @@
48 Blob comment; /* Check-in comment text */
49 char *zCommentMimetype; /* Mimetype of comment. May be NULL */
50 char *zUser; /* User name */
51 char *zDate; /* Optionally force this date string (anything
52 supported by date_in_standard_format()).
53 May be NULL. */
54 Blob *pMfOut; /* If not NULL, checkin_mini() will write a
55 copy of the generated manifest here. This
56 memory is NOT owned by CheckinMiniInfo. */
57 int filePerm; /* Permissions (via file_perm()) of the input
58 file. We need to store this before calling
@@ -123,11 +123,11 @@
123 */
124 CIMINI_PREFER_DELTA = 1<<8,
125 /*
126 ** A "stronger hint" to checkin_mini() to prefer creation of a delta
127 ** manifest if it at all can. It will decide not to only if creation
128 ** of a delta is not a realistic option or if it's forbidden by the
129 ** forbid-delta-manifests repo config option. For this to work, it
130 ** must be set together with the CIMINI_PREFER_DELTA flag, but the two
131 ** cannot be combined in this enum.
132 **
133 ** This option is ONLY INTENDED FOR TESTING, used in bypassing
@@ -400,11 +400,11 @@
400 ** This routine uses the state from the given fully-populated pCI
401 ** argument to add pCI->fileContent to the database, and create and
402 ** save a manifest for that change. Ownership of pCI and its contents
403 ** are unchanged.
404 **
405 ** This function may modify pCI as follows:
406 **
407 ** - If one of Manifest pCI->pParent or pCI->zParentUuid are NULL,
408 ** then the other will be assigned based on its counterpart. Both
409 ** may not be NULL.
410 **
411
+1 -1
--- src/forum.c
+++ src/forum.c
@@ -133,11 +133,11 @@
133133
** (recursively), else they are not. When checking in-response-to
134134
** posts, the first one which is closed ends the search.
135135
**
136136
** Note that this function checks _exactly_ the given rid, whereas
137137
** forum post closure/re-opening is always applied to the head of an
138
-** edit chain so that we get consistent implied locking beheavior for
138
+** edit chain so that we get consistent implied locking behavior for
139139
** later versions and responses to arbitrary versions in the
140140
** chain. Even so, the "closed" tag is applied as a propagating tag
141141
** so will apply to all edits in a given chain.
142142
**
143143
** The return value is one of:
144144
--- src/forum.c
+++ src/forum.c
@@ -133,11 +133,11 @@
133 ** (recursively), else they are not. When checking in-response-to
134 ** posts, the first one which is closed ends the search.
135 **
136 ** Note that this function checks _exactly_ the given rid, whereas
137 ** forum post closure/re-opening is always applied to the head of an
138 ** edit chain so that we get consistent implied locking beheavior for
139 ** later versions and responses to arbitrary versions in the
140 ** chain. Even so, the "closed" tag is applied as a propagating tag
141 ** so will apply to all edits in a given chain.
142 **
143 ** The return value is one of:
144
--- src/forum.c
+++ src/forum.c
@@ -133,11 +133,11 @@
133 ** (recursively), else they are not. When checking in-response-to
134 ** posts, the first one which is closed ends the search.
135 **
136 ** Note that this function checks _exactly_ the given rid, whereas
137 ** forum post closure/re-opening is always applied to the head of an
138 ** edit chain so that we get consistent implied locking behavior for
139 ** later versions and responses to arbitrary versions in the
140 ** chain. Even so, the "closed" tag is applied as a propagating tag
141 ** so will apply to all edits in a given chain.
142 **
143 ** The return value is one of:
144
--- src/fossil.confirmer.js
+++ src/fossil.confirmer.js
@@ -168,11 +168,11 @@
168168
childs.forEach((e)=>target.appendChild(e));
169169
}
170170
}
171171
const formatCountdown = (txt, number) => txt + " ["+number+"]";
172172
if(opt.pinSize && opt.confirmText){
173
- /* Try to pin the element's width the the greater of its
173
+ /* Try to pin the element's width to the greater of its
174174
current width or its waiting-on-confirmation width
175175
to avoid layout reflow when it's activated. */
176176
const digits = (''+(opt.timeout/1000 || opt.ticks)).length;
177177
const lblLong = formatCountdown(opt.confirmText, "00000000".substr(0,digits+1));
178178
const w1 = parseInt(target.getBoundingClientRect().width);
179179
--- src/fossil.confirmer.js
+++ src/fossil.confirmer.js
@@ -168,11 +168,11 @@
168 childs.forEach((e)=>target.appendChild(e));
169 }
170 }
171 const formatCountdown = (txt, number) => txt + " ["+number+"]";
172 if(opt.pinSize && opt.confirmText){
173 /* Try to pin the element's width the the greater of its
174 current width or its waiting-on-confirmation width
175 to avoid layout reflow when it's activated. */
176 const digits = (''+(opt.timeout/1000 || opt.ticks)).length;
177 const lblLong = formatCountdown(opt.confirmText, "00000000".substr(0,digits+1));
178 const w1 = parseInt(target.getBoundingClientRect().width);
179
--- src/fossil.confirmer.js
+++ src/fossil.confirmer.js
@@ -168,11 +168,11 @@
168 childs.forEach((e)=>target.appendChild(e));
169 }
170 }
171 const formatCountdown = (txt, number) => txt + " ["+number+"]";
172 if(opt.pinSize && opt.confirmText){
173 /* Try to pin the element's width to the greater of its
174 current width or its waiting-on-confirmation width
175 to avoid layout reflow when it's activated. */
176 const digits = (''+(opt.timeout/1000 || opt.ticks)).length;
177 const lblLong = formatCountdown(opt.confirmText, "00000000".substr(0,digits+1));
178 const w1 = parseInt(target.getBoundingClientRect().width);
179
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -35,11 +35,11 @@
3535
}
3636
const D = window.fossil.dom;
3737
const allToggles = [/*collection of all diff-toggle checkboxes*/];
3838
let checkedCount =
3939
0 /* When showing more than one diff, keep track of how many
40
- "show/hide" checkboxes are are checked so we can update the
40
+ "show/hide" checkboxes are checked so we can update the
4141
"show/hide all" label dynamically. */;
4242
let btnAll /* UI control to show/hide all diffs */;
4343
/* Install a diff-toggle button for the given diff table element. */
4444
const addToggle = function(diffElem){
4545
const sib = diffElem.previousElementSibling,
@@ -106,11 +106,11 @@
106106
chunkLoadLines: (
107107
F.config.diffContextLines * 3
108108
/*per /chat discussion*/
109109
) || 20,
110110
chunkFetch: {
111
- /* Default callack handlers for Diff.fetchArtifactChunk(),
111
+ /* Default callback handlers for Diff.fetchArtifactChunk(),
112112
unless overridden by options passeed to that function. */
113113
beforesend: function(){},
114114
aftersend: function(){},
115115
onerror: function(e){
116116
console.error("XHR error: ",e);
@@ -368,11 +368,11 @@
368368
}
369369
return this;
370370
},
371371
372372
/**
373
- Callack for /jchunk responses.
373
+ Callback for /jchunk responses.
374374
*/
375375
injectResponse: function f(fetchType/*as for fetchChunk()*/,
376376
urlParam/*from fetchChunk()*/,
377377
lines/*response lines*/){
378378
if(!lines.length){
@@ -718,11 +718,11 @@
718718
: undefined;
719719
const keySbsScroll = 'sync-diff-scroll' /* F.storage key for persistent user preference */;
720720
if( eToggleParent ){
721721
/* Add a checkbox to toggle sbs scroll sync. Remember that in
722722
order to be UI-consistent in the /vdiff page we have to ensure
723
- that the checkbox is to the LEFT of of its label. We store the
723
+ that the checkbox is to the LEFT of its label. We store the
724724
sync-scroll preference in F.storage (not a cookie) so that it
725725
persists across page loads and different apps. */
726726
cbSync = D.checkbox(keySbsScroll, F.storage.getBool(keySbsScroll,true));
727727
D.append(eToggleParent, D.append(
728728
D.addClass(D.create('span'), 'input-with-label'),
729729
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -35,11 +35,11 @@
35 }
36 const D = window.fossil.dom;
37 const allToggles = [/*collection of all diff-toggle checkboxes*/];
38 let checkedCount =
39 0 /* When showing more than one diff, keep track of how many
40 "show/hide" checkboxes are are checked so we can update the
41 "show/hide all" label dynamically. */;
42 let btnAll /* UI control to show/hide all diffs */;
43 /* Install a diff-toggle button for the given diff table element. */
44 const addToggle = function(diffElem){
45 const sib = diffElem.previousElementSibling,
@@ -106,11 +106,11 @@
106 chunkLoadLines: (
107 F.config.diffContextLines * 3
108 /*per /chat discussion*/
109 ) || 20,
110 chunkFetch: {
111 /* Default callack handlers for Diff.fetchArtifactChunk(),
112 unless overridden by options passeed to that function. */
113 beforesend: function(){},
114 aftersend: function(){},
115 onerror: function(e){
116 console.error("XHR error: ",e);
@@ -368,11 +368,11 @@
368 }
369 return this;
370 },
371
372 /**
373 Callack for /jchunk responses.
374 */
375 injectResponse: function f(fetchType/*as for fetchChunk()*/,
376 urlParam/*from fetchChunk()*/,
377 lines/*response lines*/){
378 if(!lines.length){
@@ -718,11 +718,11 @@
718 : undefined;
719 const keySbsScroll = 'sync-diff-scroll' /* F.storage key for persistent user preference */;
720 if( eToggleParent ){
721 /* Add a checkbox to toggle sbs scroll sync. Remember that in
722 order to be UI-consistent in the /vdiff page we have to ensure
723 that the checkbox is to the LEFT of of its label. We store the
724 sync-scroll preference in F.storage (not a cookie) so that it
725 persists across page loads and different apps. */
726 cbSync = D.checkbox(keySbsScroll, F.storage.getBool(keySbsScroll,true));
727 D.append(eToggleParent, D.append(
728 D.addClass(D.create('span'), 'input-with-label'),
729
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -35,11 +35,11 @@
35 }
36 const D = window.fossil.dom;
37 const allToggles = [/*collection of all diff-toggle checkboxes*/];
38 let checkedCount =
39 0 /* When showing more than one diff, keep track of how many
40 "show/hide" checkboxes are checked so we can update the
41 "show/hide all" label dynamically. */;
42 let btnAll /* UI control to show/hide all diffs */;
43 /* Install a diff-toggle button for the given diff table element. */
44 const addToggle = function(diffElem){
45 const sib = diffElem.previousElementSibling,
@@ -106,11 +106,11 @@
106 chunkLoadLines: (
107 F.config.diffContextLines * 3
108 /*per /chat discussion*/
109 ) || 20,
110 chunkFetch: {
111 /* Default callback handlers for Diff.fetchArtifactChunk(),
112 unless overridden by options passeed to that function. */
113 beforesend: function(){},
114 aftersend: function(){},
115 onerror: function(e){
116 console.error("XHR error: ",e);
@@ -368,11 +368,11 @@
368 }
369 return this;
370 },
371
372 /**
373 Callback for /jchunk responses.
374 */
375 injectResponse: function f(fetchType/*as for fetchChunk()*/,
376 urlParam/*from fetchChunk()*/,
377 lines/*response lines*/){
378 if(!lines.length){
@@ -718,11 +718,11 @@
718 : undefined;
719 const keySbsScroll = 'sync-diff-scroll' /* F.storage key for persistent user preference */;
720 if( eToggleParent ){
721 /* Add a checkbox to toggle sbs scroll sync. Remember that in
722 order to be UI-consistent in the /vdiff page we have to ensure
723 that the checkbox is to the LEFT of its label. We store the
724 sync-scroll preference in F.storage (not a cookie) so that it
725 persists across page loads and different apps. */
726 cbSync = D.checkbox(keySbsScroll, F.storage.getBool(keySbsScroll,true));
727 D.append(eToggleParent, D.append(
728 D.addClass(D.create('span'), 'input-with-label'),
729
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -259,11 +259,11 @@
259259
dom.td = dom.createElemFactoryWithOptionalParent('td');
260260
dom.th = dom.createElemFactoryWithOptionalParent('th');
261261
262262
/**
263263
Creates and returns a FIELDSET element, optionaly with a LEGEND
264
- element added to it. If legendText is an HTMLElement then is is
264
+ element added to it. If legendText is an HTMLElement then it is
265265
assumed to be a LEGEND and is appended as-is, else it is assumed
266266
(if truthy) to be a value suitable for passing to
267267
dom.append(aLegendElement,...).
268268
*/
269269
dom.fieldset = function(legendText){
270270
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -259,11 +259,11 @@
259 dom.td = dom.createElemFactoryWithOptionalParent('td');
260 dom.th = dom.createElemFactoryWithOptionalParent('th');
261
262 /**
263 Creates and returns a FIELDSET element, optionaly with a LEGEND
264 element added to it. If legendText is an HTMLElement then is is
265 assumed to be a LEGEND and is appended as-is, else it is assumed
266 (if truthy) to be a value suitable for passing to
267 dom.append(aLegendElement,...).
268 */
269 dom.fieldset = function(legendText){
270
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -259,11 +259,11 @@
259 dom.td = dom.createElemFactoryWithOptionalParent('td');
260 dom.th = dom.createElemFactoryWithOptionalParent('th');
261
262 /**
263 Creates and returns a FIELDSET element, optionaly with a LEGEND
264 element added to it. If legendText is an HTMLElement then it is
265 assumed to be a LEGEND and is appended as-is, else it is assumed
266 (if truthy) to be a value suitable for passing to
267 dom.append(aLegendElement,...).
268 */
269 dom.fieldset = function(legendText){
270
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -61,11 +61,11 @@
6161
reported here, else they are reported through onerror().
6262
Unfortunately, XHR fires two events for a timeout: an
6363
onreadystatechange() and an ontimeout(), in that order. From the
6464
former, however, we cannot unambiguously identify the error as
6565
having been caused by a timeout, so clients which set ontimeout()
66
- will get _two_ callback calls: one with with an HTTP error response
66
+ will get _two_ callback calls: one with an HTTP error response
6767
followed immediately by an ontimeout() response. Error objects
6868
passed to this will have (.name='timeout', .status=xhr.HttpStatus).
6969
In the context of the callback, the options object is "this", Like
7070
onerror(), any exceptions thrown by the ontimeout() handler are
7171
suppressed, but may generate a console error message. The onerror()
7272
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -61,11 +61,11 @@
61 reported here, else they are reported through onerror().
62 Unfortunately, XHR fires two events for a timeout: an
63 onreadystatechange() and an ontimeout(), in that order. From the
64 former, however, we cannot unambiguously identify the error as
65 having been caused by a timeout, so clients which set ontimeout()
66 will get _two_ callback calls: one with with an HTTP error response
67 followed immediately by an ontimeout() response. Error objects
68 passed to this will have (.name='timeout', .status=xhr.HttpStatus).
69 In the context of the callback, the options object is "this", Like
70 onerror(), any exceptions thrown by the ontimeout() handler are
71 suppressed, but may generate a console error message. The onerror()
72
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -61,11 +61,11 @@
61 reported here, else they are reported through onerror().
62 Unfortunately, XHR fires two events for a timeout: an
63 onreadystatechange() and an ontimeout(), in that order. From the
64 former, however, we cannot unambiguously identify the error as
65 having been caused by a timeout, so clients which set ontimeout()
66 will get _two_ callback calls: one with an HTTP error response
67 followed immediately by an ontimeout() response. Error objects
68 passed to this will have (.name='timeout', .status=xhr.HttpStatus).
69 In the context of the callback, the options object is "this", Like
70 onerror(), any exceptions thrown by the ontimeout() handler are
71 suppressed, but may generate a console error message. The onerror()
72
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -357,11 +357,11 @@
357357
/** Either scrolls .message-widget element eMsg into view
358358
immediately or, if it represents an inlined image, delays
359359
the scroll until the image is loaded, at which point it will
360360
scroll to either the newest message, if one is set or to
361361
eMsg (the liklihood is good, at least on initial page load,
362
- that the the image won't be loaded until other messages have
362
+ that the image won't be loaded until other messages have
363363
been injected). */
364364
scheduleScrollOfMsg: function(eMsg){
365365
if(1===+eMsg.dataset.hasImage){
366366
eMsg.querySelector('img').addEventListener(
367367
'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false)
@@ -1050,11 +1050,11 @@
10501050
if(eUser==this || !eUser) return false;
10511051
const uname = eUser.dataset.uname;
10521052
let eLast;
10531053
cs.setCurrentView(cs.e.viewMessages);
10541054
if(eUser.classList.contains('selected')){
1055
- /* If curently selected, toggle filter off */
1055
+ /* If currently selected, toggle filter off */
10561056
eUser.classList.remove('selected');
10571057
cs.setUserFilter(false);
10581058
delete f.$eSelected;
10591059
}else{
10601060
if(f.$eSelected) f.$eSelected.classList.remove('selected');
@@ -2856,11 +2856,11 @@
28562856
beforesend: chatPollBeforeSend,
28572857
aftersend: function(){
28582858
poll.running = false;
28592859
},
28602860
ontimeout: function(err){
2861
- f.pendingOnError = undefined /*strip preceeding non-timeout error, if any*/;
2861
+ f.pendingOnError = undefined /*strip preceding non-timeout error, if any*/;
28622862
afterPollFetch(err);
28632863
},
28642864
onerror:function(err){
28652865
Chat._isBatchLoading = false;
28662866
if(Chat.beVerbose){
28672867
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -357,11 +357,11 @@
357 /** Either scrolls .message-widget element eMsg into view
358 immediately or, if it represents an inlined image, delays
359 the scroll until the image is loaded, at which point it will
360 scroll to either the newest message, if one is set or to
361 eMsg (the liklihood is good, at least on initial page load,
362 that the the image won't be loaded until other messages have
363 been injected). */
364 scheduleScrollOfMsg: function(eMsg){
365 if(1===+eMsg.dataset.hasImage){
366 eMsg.querySelector('img').addEventListener(
367 'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false)
@@ -1050,11 +1050,11 @@
1050 if(eUser==this || !eUser) return false;
1051 const uname = eUser.dataset.uname;
1052 let eLast;
1053 cs.setCurrentView(cs.e.viewMessages);
1054 if(eUser.classList.contains('selected')){
1055 /* If curently selected, toggle filter off */
1056 eUser.classList.remove('selected');
1057 cs.setUserFilter(false);
1058 delete f.$eSelected;
1059 }else{
1060 if(f.$eSelected) f.$eSelected.classList.remove('selected');
@@ -2856,11 +2856,11 @@
2856 beforesend: chatPollBeforeSend,
2857 aftersend: function(){
2858 poll.running = false;
2859 },
2860 ontimeout: function(err){
2861 f.pendingOnError = undefined /*strip preceeding non-timeout error, if any*/;
2862 afterPollFetch(err);
2863 },
2864 onerror:function(err){
2865 Chat._isBatchLoading = false;
2866 if(Chat.beVerbose){
2867
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -357,11 +357,11 @@
357 /** Either scrolls .message-widget element eMsg into view
358 immediately or, if it represents an inlined image, delays
359 the scroll until the image is loaded, at which point it will
360 scroll to either the newest message, if one is set or to
361 eMsg (the liklihood is good, at least on initial page load,
362 that the image won't be loaded until other messages have
363 been injected). */
364 scheduleScrollOfMsg: function(eMsg){
365 if(1===+eMsg.dataset.hasImage){
366 eMsg.querySelector('img').addEventListener(
367 'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false)
@@ -1050,11 +1050,11 @@
1050 if(eUser==this || !eUser) return false;
1051 const uname = eUser.dataset.uname;
1052 let eLast;
1053 cs.setCurrentView(cs.e.viewMessages);
1054 if(eUser.classList.contains('selected')){
1055 /* If currently selected, toggle filter off */
1056 eUser.classList.remove('selected');
1057 cs.setUserFilter(false);
1058 delete f.$eSelected;
1059 }else{
1060 if(f.$eSelected) f.$eSelected.classList.remove('selected');
@@ -2856,11 +2856,11 @@
2856 beforesend: chatPollBeforeSend,
2857 aftersend: function(){
2858 poll.running = false;
2859 },
2860 ontimeout: function(err){
2861 f.pendingOnError = undefined /*strip preceding non-timeout error, if any*/;
2862 afterPollFetch(err);
2863 },
2864 onerror:function(err){
2865 Chat._isBatchLoading = false;
2866 if(Chat.beVerbose){
2867
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -1149,11 +1149,11 @@
11491149
return this;
11501150
};
11511151
11521152
/**
11531153
Fetches the page preview based on the contents and settings of
1154
- this page's input fields, and updates the UI with with the
1154
+ this page's input fields, and updates the UI with the
11551155
preview.
11561156
11571157
Returns this object, noting that the operation is async.
11581158
*/
11591159
P.preview = function f(switchToTab){
11601160
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -1149,11 +1149,11 @@
1149 return this;
1150 };
1151
1152 /**
1153 Fetches the page preview based on the contents and settings of
1154 this page's input fields, and updates the UI with with the
1155 preview.
1156
1157 Returns this object, noting that the operation is async.
1158 */
1159 P.preview = function f(switchToTab){
1160
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -1149,11 +1149,11 @@
1149 return this;
1150 };
1151
1152 /**
1153 Fetches the page preview based on the contents and settings of
1154 this page's input fields, and updates the UI with the
1155 preview.
1156
1157 Returns this object, noting that the operation is async.
1158 */
1159 P.preview = function f(switchToTab){
1160
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -1457,11 +1457,11 @@
14571457
return this;
14581458
};
14591459
14601460
/**
14611461
Fetches the page preview based on the contents and settings of
1462
- this page's input fields, and updates the UI with with the
1462
+ this page's input fields, and updates the UI with the
14631463
preview.
14641464
14651465
Returns this object, noting that the operation is async.
14661466
*/
14671467
P.preview = function f(switchToTab){
14681468
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -1457,11 +1457,11 @@
1457 return this;
1458 };
1459
1460 /**
1461 Fetches the page preview based on the contents and settings of
1462 this page's input fields, and updates the UI with with the
1463 preview.
1464
1465 Returns this object, noting that the operation is async.
1466 */
1467 P.preview = function f(switchToTab){
1468
--- src/fossil.page.wikiedit.js
+++ src/fossil.page.wikiedit.js
@@ -1457,11 +1457,11 @@
1457 return this;
1458 };
1459
1460 /**
1461 Fetches the page preview based on the contents and settings of
1462 this page's input fields, and updates the UI with the
1463 preview.
1464
1465 Returns this object, noting that the operation is async.
1466 */
1467 P.preview = function f(switchToTab){
1468
--- src/fossil.pikchr.js
+++ src/fossil.pikchr.js
@@ -54,11 +54,11 @@
5454
meta) is handled differently everywhere. Shift is used
5555
by the browser, Ctrl doesn't work on an iMac, and Alt is
5656
intercepted by most Linux window managers to control
5757
window movement! So... we just listen for *any* of them
5858
(except Shift) and the user will need to find one which
59
- works on on their environment. */
59
+ works on their environment. */
6060
|| this.classList.contains('toggle')){
6161
this.classList.toggle('source');
6262
ev.stopPropagation();
6363
ev.preventDefault();
6464
}
6565
--- src/fossil.pikchr.js
+++ src/fossil.pikchr.js
@@ -54,11 +54,11 @@
54 meta) is handled differently everywhere. Shift is used
55 by the browser, Ctrl doesn't work on an iMac, and Alt is
56 intercepted by most Linux window managers to control
57 window movement! So... we just listen for *any* of them
58 (except Shift) and the user will need to find one which
59 works on on their environment. */
60 || this.classList.contains('toggle')){
61 this.classList.toggle('source');
62 ev.stopPropagation();
63 ev.preventDefault();
64 }
65
--- src/fossil.pikchr.js
+++ src/fossil.pikchr.js
@@ -54,11 +54,11 @@
54 meta) is handled differently everywhere. Shift is used
55 by the browser, Ctrl doesn't work on an iMac, and Alt is
56 intercepted by most Linux window managers to control
57 window movement! So... we just listen for *any* of them
58 (except Shift) and the user will need to find one which
59 works on their environment. */
60 || this.classList.contains('toggle')){
61 this.classList.toggle('source');
62 ev.stopPropagation();
63 ev.preventDefault();
64 }
65
--- src/fossil.wikiedit-wysiwyg.js
+++ src/fossil.wikiedit-wysiwyg.js
@@ -449,21 +449,21 @@
449449
oDoc.focus();
450450
}
451451
452452
////////////////////////////////////////////////////////////////////////
453453
// A hook which can be activated via a site skin to plug this editor
454
- // in to the wikiedit page.
454
+ // into the wikiedit page.
455455
F.page.wysiwyg = {
456456
// only for debugging: oDoc: oDoc,
457457
/*
458458
Replaces wikiedit's default editor widget with this wysiwyg
459459
editor.
460460
461461
Must either be called via an onPageLoad handler via the site
462462
skin's footer or else it can be called manually from the dev
463463
tools console. Calling it too early (e.g. in the page footer
464
- outside of an an onPageLoad handler) will crash because wikiedit
464
+ outside of an onPageLoad handler) will crash because wikiedit
465465
has not been initialized.
466466
*/
467467
init: function(){
468468
initDoc();
469469
const content = F.page.wikiContent() || '';
470470
--- src/fossil.wikiedit-wysiwyg.js
+++ src/fossil.wikiedit-wysiwyg.js
@@ -449,21 +449,21 @@
449 oDoc.focus();
450 }
451
452 ////////////////////////////////////////////////////////////////////////
453 // A hook which can be activated via a site skin to plug this editor
454 // in to the wikiedit page.
455 F.page.wysiwyg = {
456 // only for debugging: oDoc: oDoc,
457 /*
458 Replaces wikiedit's default editor widget with this wysiwyg
459 editor.
460
461 Must either be called via an onPageLoad handler via the site
462 skin's footer or else it can be called manually from the dev
463 tools console. Calling it too early (e.g. in the page footer
464 outside of an an onPageLoad handler) will crash because wikiedit
465 has not been initialized.
466 */
467 init: function(){
468 initDoc();
469 const content = F.page.wikiContent() || '';
470
--- src/fossil.wikiedit-wysiwyg.js
+++ src/fossil.wikiedit-wysiwyg.js
@@ -449,21 +449,21 @@
449 oDoc.focus();
450 }
451
452 ////////////////////////////////////////////////////////////////////////
453 // A hook which can be activated via a site skin to plug this editor
454 // into the wikiedit page.
455 F.page.wysiwyg = {
456 // only for debugging: oDoc: oDoc,
457 /*
458 Replaces wikiedit's default editor widget with this wysiwyg
459 editor.
460
461 Must either be called via an onPageLoad handler via the site
462 skin's footer or else it can be called manually from the dev
463 tools console. Calling it too early (e.g. in the page footer
464 outside of an onPageLoad handler) will crash because wikiedit
465 has not been initialized.
466 */
467 init: function(){
468 initDoc();
469 const content = F.page.wikiContent() || '';
470
+1 -1
--- src/fshell.c
+++ src/fshell.c
@@ -21,11 +21,11 @@
2121
** after the fashion of a standard Bourne shell and forks a child process
2222
** to run the corresponding Fossil command. This only works on Unix.
2323
**
2424
** The "fossil shell" command is intended for use with SEE-enabled fossil.
2525
** It allows multiple commands to be issued without having to reenter the
26
-** crypto phasephrase for each command.
26
+** crypto passphrase for each command.
2727
*/
2828
#include "config.h"
2929
#include "fshell.h"
3030
#include <ctype.h>
3131
3232
--- src/fshell.c
+++ src/fshell.c
@@ -21,11 +21,11 @@
21 ** after the fashion of a standard Bourne shell and forks a child process
22 ** to run the corresponding Fossil command. This only works on Unix.
23 **
24 ** The "fossil shell" command is intended for use with SEE-enabled fossil.
25 ** It allows multiple commands to be issued without having to reenter the
26 ** crypto phasephrase for each command.
27 */
28 #include "config.h"
29 #include "fshell.h"
30 #include <ctype.h>
31
32
--- src/fshell.c
+++ src/fshell.c
@@ -21,11 +21,11 @@
21 ** after the fashion of a standard Bourne shell and forks a child process
22 ** to run the corresponding Fossil command. This only works on Unix.
23 **
24 ** The "fossil shell" command is intended for use with SEE-enabled fossil.
25 ** It allows multiple commands to be issued without having to reenter the
26 ** crypto passphrase for each command.
27 */
28 #include "config.h"
29 #include "fshell.h"
30 #include <ctype.h>
31
32
+2 -2
--- src/glob.c
+++ src/glob.c
@@ -29,11 +29,11 @@
2929
** zVal: "x"
3030
** zGlobList: "*.o,*.obj"
3131
**
3232
** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
3333
**
34
-** Commas and whitespace are considered to be element delimters. Each
34
+** Commas and whitespace are considered to be element delimiters. Each
3535
** element of the GLOB list may optionally be enclosed in either '...' or
3636
** "...". This allows commas and/or whitespace to be used in the elements
3737
** themselves.
3838
**
3939
** The returned string is owned by the caller, who must fossil_free()
@@ -57,11 +57,11 @@
5757
cTerm = zGlobList[0];
5858
zGlobList++;
5959
}else{
6060
cTerm = ',';
6161
}
62
- /* Find the next delimter (or the end of the string). */
62
+ /* Find the next delimiter (or the end of the string). */
6363
for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){
6464
if( cTerm!=',' ) continue; /* If quoted, keep going. */
6565
if( fossil_isspace(zGlobList[i]) ) break; /* If space, stop. */
6666
}
6767
blob_appendf(&expr, "%s%s GLOB '%#q'", zSep, zVal, i, zGlobList);
6868
--- src/glob.c
+++ src/glob.c
@@ -29,11 +29,11 @@
29 ** zVal: "x"
30 ** zGlobList: "*.o,*.obj"
31 **
32 ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
33 **
34 ** Commas and whitespace are considered to be element delimters. Each
35 ** element of the GLOB list may optionally be enclosed in either '...' or
36 ** "...". This allows commas and/or whitespace to be used in the elements
37 ** themselves.
38 **
39 ** The returned string is owned by the caller, who must fossil_free()
@@ -57,11 +57,11 @@
57 cTerm = zGlobList[0];
58 zGlobList++;
59 }else{
60 cTerm = ',';
61 }
62 /* Find the next delimter (or the end of the string). */
63 for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){
64 if( cTerm!=',' ) continue; /* If quoted, keep going. */
65 if( fossil_isspace(zGlobList[i]) ) break; /* If space, stop. */
66 }
67 blob_appendf(&expr, "%s%s GLOB '%#q'", zSep, zVal, i, zGlobList);
68
--- src/glob.c
+++ src/glob.c
@@ -29,11 +29,11 @@
29 ** zVal: "x"
30 ** zGlobList: "*.o,*.obj"
31 **
32 ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
33 **
34 ** Commas and whitespace are considered to be element delimiters. Each
35 ** element of the GLOB list may optionally be enclosed in either '...' or
36 ** "...". This allows commas and/or whitespace to be used in the elements
37 ** themselves.
38 **
39 ** The returned string is owned by the caller, who must fossil_free()
@@ -57,11 +57,11 @@
57 cTerm = zGlobList[0];
58 zGlobList++;
59 }else{
60 cTerm = ',';
61 }
62 /* Find the next delimiter (or the end of the string). */
63 for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){
64 if( cTerm!=',' ) continue; /* If quoted, keep going. */
65 if( fossil_isspace(zGlobList[i]) ) break; /* If space, stop. */
66 }
67 blob_appendf(&expr, "%s%s GLOB '%#q'", zSep, zVal, i, zGlobList);
68
+1 -1
--- src/graph.c
+++ src/graph.c
@@ -51,11 +51,11 @@
5151
5252
/*
5353
** The type of integer identifiers for rows of the graph.
5454
**
5555
** For a normal /timeline graph, the identifiers are never that big
56
-** an an ordinary 32-bit int will work fine. But for the /finfo page,
56
+** an ordinary 32-bit int will work fine. But for the /finfo page,
5757
** the identifier is a combination of the BLOB.RID and the FILENAME.FNID
5858
** values, and so it can become quite large for repos that have both many
5959
** check-ins and many files. For this reason, we make the identifier
6060
** a 64-bit integer, to dramatically reduce the risk of an overflow.
6161
*/
6262
--- src/graph.c
+++ src/graph.c
@@ -51,11 +51,11 @@
51
52 /*
53 ** The type of integer identifiers for rows of the graph.
54 **
55 ** For a normal /timeline graph, the identifiers are never that big
56 ** an an ordinary 32-bit int will work fine. But for the /finfo page,
57 ** the identifier is a combination of the BLOB.RID and the FILENAME.FNID
58 ** values, and so it can become quite large for repos that have both many
59 ** check-ins and many files. For this reason, we make the identifier
60 ** a 64-bit integer, to dramatically reduce the risk of an overflow.
61 */
62
--- src/graph.c
+++ src/graph.c
@@ -51,11 +51,11 @@
51
52 /*
53 ** The type of integer identifiers for rows of the graph.
54 **
55 ** For a normal /timeline graph, the identifiers are never that big
56 ** an ordinary 32-bit int will work fine. But for the /finfo page,
57 ** the identifier is a combination of the BLOB.RID and the FILENAME.FNID
58 ** values, and so it can become quite large for repos that have both many
59 ** check-ins and many files. For this reason, we make the identifier
60 ** a 64-bit integer, to dramatically reduce the risk of an overflow.
61 */
62
+1 -1
--- src/hname.c
+++ src/hname.c
@@ -199,11 +199,11 @@
199199
200200
/*
201201
** Return the default hash policy for repositories that do not currently
202202
** have an assigned hash policy.
203203
**
204
-** Make the default HPOLICY_AUTO if there are SHA1 artficates but no SHA3
204
+** Make the default HPOLICY_AUTO if there are SHA1 artifacts but no SHA3
205205
** artifacts in the repository. Make the default HPOLICY_SHA3 if there
206206
** are one or more SHA3 artifacts or if the repository is initially empty.
207207
*/
208208
int hname_default_policy(void){
209209
if( db_exists("SELECT 1 FROM blob WHERE length(uuid)>40")
210210
--- src/hname.c
+++ src/hname.c
@@ -199,11 +199,11 @@
199
200 /*
201 ** Return the default hash policy for repositories that do not currently
202 ** have an assigned hash policy.
203 **
204 ** Make the default HPOLICY_AUTO if there are SHA1 artficates but no SHA3
205 ** artifacts in the repository. Make the default HPOLICY_SHA3 if there
206 ** are one or more SHA3 artifacts or if the repository is initially empty.
207 */
208 int hname_default_policy(void){
209 if( db_exists("SELECT 1 FROM blob WHERE length(uuid)>40")
210
--- src/hname.c
+++ src/hname.c
@@ -199,11 +199,11 @@
199
200 /*
201 ** Return the default hash policy for repositories that do not currently
202 ** have an assigned hash policy.
203 **
204 ** Make the default HPOLICY_AUTO if there are SHA1 artifacts but no SHA3
205 ** artifacts in the repository. Make the default HPOLICY_SHA3 if there
206 ** are one or more SHA3 artifacts or if the repository is initially empty.
207 */
208 int hname_default_policy(void){
209 if( db_exists("SELECT 1 FROM blob WHERE length(uuid)>40")
210
+1 -1
--- src/hook.c
+++ src/hook.c
@@ -29,11 +29,11 @@
2929
** }
3030
**
3131
** hook-last-rcvid The last rcvid for which post-receive hooks were
3232
** run.
3333
**
34
-** hook-embargo Do not run hooks again before this julianday.
34
+** hook-embargo Do not run hooks again before this Julian day.
3535
**
3636
** For "after-receive" hooks, a list of the received artifacts is sent
3737
** into the command via standard input. Each line of input begins with
3838
** the hash of the artifact and continues with a description of the
3939
** interpretation of the artifact.
4040
--- src/hook.c
+++ src/hook.c
@@ -29,11 +29,11 @@
29 ** }
30 **
31 ** hook-last-rcvid The last rcvid for which post-receive hooks were
32 ** run.
33 **
34 ** hook-embargo Do not run hooks again before this julianday.
35 **
36 ** For "after-receive" hooks, a list of the received artifacts is sent
37 ** into the command via standard input. Each line of input begins with
38 ** the hash of the artifact and continues with a description of the
39 ** interpretation of the artifact.
40
--- src/hook.c
+++ src/hook.c
@@ -29,11 +29,11 @@
29 ** }
30 **
31 ** hook-last-rcvid The last rcvid for which post-receive hooks were
32 ** run.
33 **
34 ** hook-embargo Do not run hooks again before this Julian day.
35 **
36 ** For "after-receive" hooks, a list of the received artifacts is sent
37 ** into the command via standard input. Each line of input begins with
38 ** the hash of the artifact and continues with a description of the
39 ** interpretation of the artifact.
40
+33 -14
--- src/http.c
+++ src/http.c
@@ -246,11 +246,11 @@
246246
}
247247
return zHttpAuth;
248248
}
249249
250250
/*
251
-** Send content pSend to the the server identified by g.url using the
251
+** Send content pSend to the server identified by g.url using the
252252
** external program given by g.zHttpCmd. Capture the reply from that
253253
** program and load it into pReply.
254254
**
255255
** This routine implements the --transport-command option for "fossil sync".
256256
*/
@@ -353,11 +353,11 @@
353353
db_finalize(&s);
354354
db_swap_connections();
355355
}
356356
}
357357
358
-/* Add an approprate PATH= argument to the SSH command under construction
358
+/* Add an appropriate PATH= argument to the SSH command under construction
359359
** in pCmd.
360360
**
361361
** About This Feature
362362
** ==================
363363
**
@@ -581,11 +581,13 @@
581581
}
582582
if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){
583583
int ii;
584584
for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
585585
while( zLine[ii]==' ' ) ii++;
586
- fossil_warning("server says: %s", &zLine[ii]);
586
+ if( (mHttpFlags & HTTP_QUIET)==0 ){
587
+ fossil_warning("server says: %s", &zLine[ii]);
588
+ }
587589
goto write_err;
588590
}
589591
if( iHttpVersion==0 ){
590592
closeConnection = 1;
591593
}else{
@@ -616,11 +618,13 @@
616618
int i, j;
617619
int wasHttps;
618620
int priorUrlFlags;
619621
620622
if ( --maxRedirect == 0){
621
- fossil_warning("redirect limit exceeded");
623
+ if( (mHttpFlags & HTTP_QUIET)==0 ){
624
+ fossil_warning("redirect limit exceeded");
625
+ }
622626
goto write_err;
623627
}
624628
for(i=9; zLine[i] && zLine[i]==' '; i++){}
625629
if( zLine[i]==0 ){
626630
fossil_warning("malformed redirect: %s", zLine);
@@ -633,23 +637,29 @@
633637
}
634638
if( (mHttpFlags & HTTP_QUIET)==0 ){
635639
fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
636640
}
637641
if( g.url.isFile || g.url.isSsh ){
638
- fossil_warning("cannot redirect from %s to %s", g.url.canonical,
639
- &zLine[i]);
642
+ if( (mHttpFlags & HTTP_QUIET)==0 ){
643
+ fossil_warning("cannot redirect from %s to %s", g.url.canonical,
644
+ &zLine[i]);
645
+ }
640646
goto write_err;
641647
}
642648
wasHttps = g.url.isHttps;
643649
priorUrlFlags = g.url.flags;
644650
url_parse(&zLine[i], 0);
645651
if( wasHttps && !g.url.isHttps ){
646
- fossil_warning("cannot redirect from HTTPS to HTTP");
652
+ if( (mHttpFlags & HTTP_QUIET)==0 ){
653
+ fossil_warning("cannot redirect from HTTPS to HTTP");
654
+ }
647655
goto write_err;
648656
}
649657
if( g.url.isSsh || g.url.isFile ){
650
- fossil_warning("cannot redirect to %s", &zLine[i]);
658
+ if( (mHttpFlags & HTTP_QUIET)==0 ){
659
+ fossil_warning("cannot redirect to %s", &zLine[i]);
660
+ }
651661
goto write_err;
652662
}
653663
transport_close(&g.url);
654664
transport_global_shutdown(&g.url);
655665
fSeenHttpAuth = 0;
@@ -704,20 +714,23 @@
704714
}
705715
return rc;
706716
}else{
707717
/* The problem could not be corrected by retrying. Report the
708718
** the error. */
709
- if( g.url.isSsh && !g.fSshTrace ){
719
+ if( mHttpFlags & HTTP_QUIET ){
720
+ /* no-op */
721
+ }else if( g.url.isSsh && !g.fSshTrace ){
710722
fossil_warning("server did not reply: "
711723
" rerun with --sshtrace for diagnostics");
712724
}else{
713725
fossil_warning("server did not reply");
714726
}
715727
goto write_err;
716728
}
717729
}
718730
if( rc!=200 ){
731
+ if( mHttpFlags & HTTP_QUIET ) goto write_err;
719732
fossil_warning("\"location:\" missing from %d redirect reply", rc);
720733
goto write_err;
721734
}
722735
723736
/*
@@ -733,19 +746,21 @@
733746
iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
734747
if( mHttpFlags & HTTP_VERBOSE ){
735748
fossil_print("Reply received: %d of %d bytes\n", iRecvLen, iLength);
736749
}
737750
if( iRecvLen != iLength ){
751
+ if( mHttpFlags & HTTP_QUIET ) goto write_err;
738752
fossil_warning("response truncated: got %d bytes of %d",
739753
iRecvLen, iLength);
740754
goto write_err;
741755
}
742
- }else if( closeConnection ){
756
+ }else{
743757
/* Read content until end-of-file */
744758
int iRecvLen; /* Received length of the reply payload */
745759
unsigned int nReq = 1000;
746760
unsigned int nPrior = 0;
761
+ closeConnection = 1;
747762
do{
748763
nReq *= 2;
749764
blob_resize(pReply, nPrior+nReq);
750765
iRecvLen = transport_receive(&g.url, &pReply->aData[nPrior], (int)nReq);
751766
nPrior += iRecvLen;
@@ -752,13 +767,10 @@
752767
pReply->nUsed = nPrior;
753768
}while( iRecvLen==nReq && nReq<0x20000000 );
754769
if( mHttpFlags & HTTP_VERBOSE ){
755770
fossil_print("Reply received: %u bytes (w/o content-length)\n", nPrior);
756771
}
757
- }else{
758
- assert( iLength<0 && !closeConnection );
759
- fossil_warning("\"content-length\" missing from %d keep-alive reply", rc);
760772
}
761773
if( isError ){
762774
char *z;
763775
int i, j;
764776
z = blob_str(pReply);
@@ -768,11 +780,17 @@
768780
if( z[i]==0 ) break;
769781
}
770782
z[j] = z[i];
771783
}
772784
z[j] = 0;
773
- fossil_warning("server sends error: %s", z);
785
+ if( mHttpFlags & HTTP_QUIET ){
786
+ /* no-op */
787
+ }else if( mHttpFlags & HTTP_VERBOSE ){
788
+ fossil_warning("server sends error: %s", z);
789
+ }else{
790
+ fossil_warning("server sends error");
791
+ }
774792
goto write_err;
775793
}
776794
if( isCompressed ) blob_uncompress(pReply, pReply);
777795
778796
/*
@@ -794,10 +812,11 @@
794812
795813
/*
796814
** Jump to here if an error is seen.
797815
*/
798816
write_err:
817
+ g.iResultCode = 1;
799818
transport_close(&g.url);
800819
return 1;
801820
}
802821
803822
/*
804823
--- src/http.c
+++ src/http.c
@@ -246,11 +246,11 @@
246 }
247 return zHttpAuth;
248 }
249
250 /*
251 ** Send content pSend to the the server identified by g.url using the
252 ** external program given by g.zHttpCmd. Capture the reply from that
253 ** program and load it into pReply.
254 **
255 ** This routine implements the --transport-command option for "fossil sync".
256 */
@@ -353,11 +353,11 @@
353 db_finalize(&s);
354 db_swap_connections();
355 }
356 }
357
358 /* Add an approprate PATH= argument to the SSH command under construction
359 ** in pCmd.
360 **
361 ** About This Feature
362 ** ==================
363 **
@@ -581,11 +581,13 @@
581 }
582 if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){
583 int ii;
584 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
585 while( zLine[ii]==' ' ) ii++;
586 fossil_warning("server says: %s", &zLine[ii]);
 
 
587 goto write_err;
588 }
589 if( iHttpVersion==0 ){
590 closeConnection = 1;
591 }else{
@@ -616,11 +618,13 @@
616 int i, j;
617 int wasHttps;
618 int priorUrlFlags;
619
620 if ( --maxRedirect == 0){
621 fossil_warning("redirect limit exceeded");
 
 
622 goto write_err;
623 }
624 for(i=9; zLine[i] && zLine[i]==' '; i++){}
625 if( zLine[i]==0 ){
626 fossil_warning("malformed redirect: %s", zLine);
@@ -633,23 +637,29 @@
633 }
634 if( (mHttpFlags & HTTP_QUIET)==0 ){
635 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
636 }
637 if( g.url.isFile || g.url.isSsh ){
638 fossil_warning("cannot redirect from %s to %s", g.url.canonical,
639 &zLine[i]);
 
 
640 goto write_err;
641 }
642 wasHttps = g.url.isHttps;
643 priorUrlFlags = g.url.flags;
644 url_parse(&zLine[i], 0);
645 if( wasHttps && !g.url.isHttps ){
646 fossil_warning("cannot redirect from HTTPS to HTTP");
 
 
647 goto write_err;
648 }
649 if( g.url.isSsh || g.url.isFile ){
650 fossil_warning("cannot redirect to %s", &zLine[i]);
 
 
651 goto write_err;
652 }
653 transport_close(&g.url);
654 transport_global_shutdown(&g.url);
655 fSeenHttpAuth = 0;
@@ -704,20 +714,23 @@
704 }
705 return rc;
706 }else{
707 /* The problem could not be corrected by retrying. Report the
708 ** the error. */
709 if( g.url.isSsh && !g.fSshTrace ){
 
 
710 fossil_warning("server did not reply: "
711 " rerun with --sshtrace for diagnostics");
712 }else{
713 fossil_warning("server did not reply");
714 }
715 goto write_err;
716 }
717 }
718 if( rc!=200 ){
 
719 fossil_warning("\"location:\" missing from %d redirect reply", rc);
720 goto write_err;
721 }
722
723 /*
@@ -733,19 +746,21 @@
733 iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
734 if( mHttpFlags & HTTP_VERBOSE ){
735 fossil_print("Reply received: %d of %d bytes\n", iRecvLen, iLength);
736 }
737 if( iRecvLen != iLength ){
 
738 fossil_warning("response truncated: got %d bytes of %d",
739 iRecvLen, iLength);
740 goto write_err;
741 }
742 }else if( closeConnection ){
743 /* Read content until end-of-file */
744 int iRecvLen; /* Received length of the reply payload */
745 unsigned int nReq = 1000;
746 unsigned int nPrior = 0;
 
747 do{
748 nReq *= 2;
749 blob_resize(pReply, nPrior+nReq);
750 iRecvLen = transport_receive(&g.url, &pReply->aData[nPrior], (int)nReq);
751 nPrior += iRecvLen;
@@ -752,13 +767,10 @@
752 pReply->nUsed = nPrior;
753 }while( iRecvLen==nReq && nReq<0x20000000 );
754 if( mHttpFlags & HTTP_VERBOSE ){
755 fossil_print("Reply received: %u bytes (w/o content-length)\n", nPrior);
756 }
757 }else{
758 assert( iLength<0 && !closeConnection );
759 fossil_warning("\"content-length\" missing from %d keep-alive reply", rc);
760 }
761 if( isError ){
762 char *z;
763 int i, j;
764 z = blob_str(pReply);
@@ -768,11 +780,17 @@
768 if( z[i]==0 ) break;
769 }
770 z[j] = z[i];
771 }
772 z[j] = 0;
773 fossil_warning("server sends error: %s", z);
 
 
 
 
 
 
774 goto write_err;
775 }
776 if( isCompressed ) blob_uncompress(pReply, pReply);
777
778 /*
@@ -794,10 +812,11 @@
794
795 /*
796 ** Jump to here if an error is seen.
797 */
798 write_err:
 
799 transport_close(&g.url);
800 return 1;
801 }
802
803 /*
804
--- src/http.c
+++ src/http.c
@@ -246,11 +246,11 @@
246 }
247 return zHttpAuth;
248 }
249
250 /*
251 ** Send content pSend to the server identified by g.url using the
252 ** external program given by g.zHttpCmd. Capture the reply from that
253 ** program and load it into pReply.
254 **
255 ** This routine implements the --transport-command option for "fossil sync".
256 */
@@ -353,11 +353,11 @@
353 db_finalize(&s);
354 db_swap_connections();
355 }
356 }
357
358 /* Add an appropriate PATH= argument to the SSH command under construction
359 ** in pCmd.
360 **
361 ** About This Feature
362 ** ==================
363 **
@@ -581,11 +581,13 @@
581 }
582 if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){
583 int ii;
584 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
585 while( zLine[ii]==' ' ) ii++;
586 if( (mHttpFlags & HTTP_QUIET)==0 ){
587 fossil_warning("server says: %s", &zLine[ii]);
588 }
589 goto write_err;
590 }
591 if( iHttpVersion==0 ){
592 closeConnection = 1;
593 }else{
@@ -616,11 +618,13 @@
618 int i, j;
619 int wasHttps;
620 int priorUrlFlags;
621
622 if ( --maxRedirect == 0){
623 if( (mHttpFlags & HTTP_QUIET)==0 ){
624 fossil_warning("redirect limit exceeded");
625 }
626 goto write_err;
627 }
628 for(i=9; zLine[i] && zLine[i]==' '; i++){}
629 if( zLine[i]==0 ){
630 fossil_warning("malformed redirect: %s", zLine);
@@ -633,23 +637,29 @@
637 }
638 if( (mHttpFlags & HTTP_QUIET)==0 ){
639 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
640 }
641 if( g.url.isFile || g.url.isSsh ){
642 if( (mHttpFlags & HTTP_QUIET)==0 ){
643 fossil_warning("cannot redirect from %s to %s", g.url.canonical,
644 &zLine[i]);
645 }
646 goto write_err;
647 }
648 wasHttps = g.url.isHttps;
649 priorUrlFlags = g.url.flags;
650 url_parse(&zLine[i], 0);
651 if( wasHttps && !g.url.isHttps ){
652 if( (mHttpFlags & HTTP_QUIET)==0 ){
653 fossil_warning("cannot redirect from HTTPS to HTTP");
654 }
655 goto write_err;
656 }
657 if( g.url.isSsh || g.url.isFile ){
658 if( (mHttpFlags & HTTP_QUIET)==0 ){
659 fossil_warning("cannot redirect to %s", &zLine[i]);
660 }
661 goto write_err;
662 }
663 transport_close(&g.url);
664 transport_global_shutdown(&g.url);
665 fSeenHttpAuth = 0;
@@ -704,20 +714,23 @@
714 }
715 return rc;
716 }else{
717 /* The problem could not be corrected by retrying. Report the
718 ** the error. */
719 if( mHttpFlags & HTTP_QUIET ){
720 /* no-op */
721 }else if( g.url.isSsh && !g.fSshTrace ){
722 fossil_warning("server did not reply: "
723 " rerun with --sshtrace for diagnostics");
724 }else{
725 fossil_warning("server did not reply");
726 }
727 goto write_err;
728 }
729 }
730 if( rc!=200 ){
731 if( mHttpFlags & HTTP_QUIET ) goto write_err;
732 fossil_warning("\"location:\" missing from %d redirect reply", rc);
733 goto write_err;
734 }
735
736 /*
@@ -733,19 +746,21 @@
746 iRecvLen = transport_receive(&g.url, blob_buffer(pReply), iLength);
747 if( mHttpFlags & HTTP_VERBOSE ){
748 fossil_print("Reply received: %d of %d bytes\n", iRecvLen, iLength);
749 }
750 if( iRecvLen != iLength ){
751 if( mHttpFlags & HTTP_QUIET ) goto write_err;
752 fossil_warning("response truncated: got %d bytes of %d",
753 iRecvLen, iLength);
754 goto write_err;
755 }
756 }else{
757 /* Read content until end-of-file */
758 int iRecvLen; /* Received length of the reply payload */
759 unsigned int nReq = 1000;
760 unsigned int nPrior = 0;
761 closeConnection = 1;
762 do{
763 nReq *= 2;
764 blob_resize(pReply, nPrior+nReq);
765 iRecvLen = transport_receive(&g.url, &pReply->aData[nPrior], (int)nReq);
766 nPrior += iRecvLen;
@@ -752,13 +767,10 @@
767 pReply->nUsed = nPrior;
768 }while( iRecvLen==nReq && nReq<0x20000000 );
769 if( mHttpFlags & HTTP_VERBOSE ){
770 fossil_print("Reply received: %u bytes (w/o content-length)\n", nPrior);
771 }
 
 
 
772 }
773 if( isError ){
774 char *z;
775 int i, j;
776 z = blob_str(pReply);
@@ -768,11 +780,17 @@
780 if( z[i]==0 ) break;
781 }
782 z[j] = z[i];
783 }
784 z[j] = 0;
785 if( mHttpFlags & HTTP_QUIET ){
786 /* no-op */
787 }else if( mHttpFlags & HTTP_VERBOSE ){
788 fossil_warning("server sends error: %s", z);
789 }else{
790 fossil_warning("server sends error");
791 }
792 goto write_err;
793 }
794 if( isCompressed ) blob_uncompress(pReply, pReply);
795
796 /*
@@ -794,10 +812,11 @@
812
813 /*
814 ** Jump to here if an error is seen.
815 */
816 write_err:
817 g.iResultCode = 1;
818 transport_close(&g.url);
819 return 1;
820 }
821
822 /*
823
--- src/http_socket.c
+++ src/http_socket.c
@@ -87,10 +87,17 @@
8787
char *socket_errmsg(void){
8888
char *zResult = socketErrMsg;
8989
socketErrMsg = 0;
9090
return zResult;
9191
}
92
+
93
+/*
94
+** Return the file descriptor for the open socket.
95
+*/
96
+int socket_get_fd(){
97
+ return iSocket;
98
+}
9299
93100
/*
94101
** Call this routine once before any other use of the socket interface.
95102
** This routine does initial configuration of the socket module.
96103
*/
97104
--- src/http_socket.c
+++ src/http_socket.c
@@ -87,10 +87,17 @@
87 char *socket_errmsg(void){
88 char *zResult = socketErrMsg;
89 socketErrMsg = 0;
90 return zResult;
91 }
 
 
 
 
 
 
 
92
93 /*
94 ** Call this routine once before any other use of the socket interface.
95 ** This routine does initial configuration of the socket module.
96 */
97
--- src/http_socket.c
+++ src/http_socket.c
@@ -87,10 +87,17 @@
87 char *socket_errmsg(void){
88 char *zResult = socketErrMsg;
89 socketErrMsg = 0;
90 return zResult;
91 }
92
93 /*
94 ** Return the file descriptor for the open socket.
95 */
96 int socket_get_fd(){
97 return iSocket;
98 }
99
100 /*
101 ** Call this routine once before any other use of the socket interface.
102 ** This routine does initial configuration of the socket module.
103 */
104
+21 -100
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -270,11 +270,11 @@
270270
271271
/* Find the trust store */
272272
zFile = 0;
273273
for(i=0; zFile==0 && i<5; i++){
274274
switch( i ){
275
- case 0: /* First priority is environmentn variables */
275
+ case 0: /* First priority is environment variables */
276276
zFile = fossil_getenv(X509_get_default_cert_file_env());
277277
break;
278278
case 1:
279279
zFile = fossil_getenv(X509_get_default_cert_dir_env());
280280
break;
@@ -363,10 +363,11 @@
363363
if( sslIsInit ){
364364
SSL_CTX_free(sslCtx);
365365
ssl_clear_errmsg();
366366
sslIsInit = 0;
367367
}
368
+ socket_global_shutdown();
368369
}
369370
370371
/*
371372
** Close the currently open client SSL connection. If no connection is open,
372373
** this routine is a no-op.
@@ -375,10 +376,11 @@
375376
if( iBio!=NULL ){
376377
(void)BIO_reset(iBio);
377378
BIO_free_all(iBio);
378379
iBio = NULL;
379380
}
381
+ socket_close();
380382
}
381383
382384
/* See RFC2817 for details */
383385
static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
384386
int rc, httpVerMin;
@@ -450,63 +452,35 @@
450452
** Return the number of errors.
451453
*/
452454
int ssl_open_client(UrlData *pUrlData){
453455
X509 *cert;
454456
const char *zRemoteHost;
457
+ BIO *sBio;
455458
456459
ssl_global_init_client();
460
+ if( socket_open(pUrlData) ){
461
+ ssl_set_errmsg("SSL: cannot open socket (%s)", socket_errmsg());
462
+ return 1;
463
+ }
464
+ sBio = BIO_new_socket(socket_get_fd(), 0);
457465
if( pUrlData->useProxy ){
458
- int rc;
459
- char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
460
- BIO *sBio = BIO_new_connect(connStr);
461
- switch( g.eIPvers ){
462
- default: /* Any available protocol */
463
- break;
464
- case 1: /* IPv4 only */
465
-#ifdef BIO_FAMILY_IPV4
466
- BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV4);
467
-#else
468
- fossil_warning("The --ipv4 option is not supported in this build\n");
469
-#endif
470
- break;
471
- case 2: /* IPv6 only */
472
-#ifdef BIO_FAMILY_IPV6
473
- BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV6);
474
-#else
475
- fossil_warning("The --ipv6 option is not supported in this build\n");
476
-#endif
477
- break;
478
- }
479
- fossil_free(connStr);
480
- if( BIO_do_connect(sBio)<=0 ){
481
- ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
482
- pUrlData->name, pUrlData->port,
483
- ERR_reason_error_string(ERR_get_error()));
484
- ssl_close_client();
485
- return 1;
486
- }
487
- rc = establish_proxy_tunnel(pUrlData, sBio);
466
+ int rc = establish_proxy_tunnel(pUrlData, sBio);
488467
if( rc<200||rc>299 ){
489468
ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
469
+ ssl_close_client();
490470
return 1;
491471
}
492472
493473
pUrlData->path = pUrlData->proxyUrlPath;
494
-
495
- iBio = BIO_new_ssl(sslCtx, 1);
496
- BIO_push(iBio, sBio);
497
- zRemoteHost = pUrlData->hostname;
498
- }else{
499
- iBio = BIO_new_ssl_connect(sslCtx);
500
- zRemoteHost = pUrlData->name;
501
- }
502
- if( iBio==NULL ) {
503
- ssl_set_errmsg("SSL: cannot open SSL (%s)",
504
- ERR_reason_error_string(ERR_get_error()));
505
- return 1;
506
- }
474
+ }
475
+ iBio = BIO_new_ssl(sslCtx, 1);
476
+ BIO_push(iBio, sBio);
477
+ BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
478
+ BIO_set_ssl_mode(iBio, 1);
507479
BIO_get_ssl(iBio, &ssl);
480
+
481
+ zRemoteHost = pUrlData->useProxy ? pUrlData->hostname : pUrlData->name;
508482
509483
#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
510484
if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){
511485
fossil_warning("WARNING: failed to set server name indication (SNI), "
512486
"continuing without it.\n");
@@ -523,45 +497,14 @@
523497
}
524498
/* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
525499
}
526500
#endif
527501
528
- if( !pUrlData->useProxy ){
529
- char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port);
530
- BIO_set_conn_hostname(iBio, connStr);
531
- fossil_free(connStr);
532
- switch( g.eIPvers ){
533
- default: /* Any available protocol */
534
- break;
535
- case 1: /* IPv4 only */
536
-#ifdef BIO_FAMILY_IPV4
537
- BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV4);
538
-#else
539
- fossil_warning("The --ipv4 option is not supported in this build\n");
540
-#endif
541
- break;
542
- case 2: /* IPv6 only */
543
-#ifdef BIO_FAMILY_IPV6
544
- BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV6);
545
-#else
546
- fossil_warning("The --ipv6 option is not supported in this build\n");
547
-#endif
548
- break;
549
- }
550
- if( BIO_do_connect(iBio)<=0 ){
551
- ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
552
- pUrlData->name, pUrlData->port,
553
- ERR_reason_error_string(ERR_get_error()));
554
- ssl_close_client();
555
- return 1;
556
- }
557
- }
558
-
559
- if( BIO_do_handshake(iBio)<=0 ) {
502
+ if( BIO_do_handshake(iBio)<=0 ){
560503
ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
561
- pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
562
- pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
504
+ zRemoteHost,
505
+ pUrlData->useProxy ? pUrlData->proxyOrigPort : pUrlData->port,
563506
ERR_reason_error_string(ERR_get_error()));
564507
ssl_close_client();
565508
return 1;
566509
}
567510
/* Check if certificate is valid */
@@ -651,32 +594,10 @@
651594
}
652595
blob_reset(&ans);
653596
}
654597
}
655598
656
- /* Set the Global.zIpAddr variable to the server we are talking to.
657
- ** This is used to populate the ipaddr column of the rcvfrom table,
658
- ** if any files are received from the server.
659
- */
660
- {
661
- /* As soon as libressl implements
662
- ** BIO_ADDR_hostname_string/BIO_get_conn_address.
663
- ** check here for the correct LIBRESSL_VERSION_NUMBER too. For now: disable
664
- */
665
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L \
666
- && !defined(LIBRESSL_VERSION_NUMBER)
667
- char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
668
- g.zIpAddr = fossil_strdup(ip);
669
- OPENSSL_free(ip);
670
-#else
671
- /* IPv4 only code */
672
- const unsigned char *ip;
673
- ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
674
- g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
675
-#endif
676
- }
677
-
678599
X509_free(cert);
679600
return 0;
680601
}
681602
682603
/*
683604
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -270,11 +270,11 @@
270
271 /* Find the trust store */
272 zFile = 0;
273 for(i=0; zFile==0 && i<5; i++){
274 switch( i ){
275 case 0: /* First priority is environmentn variables */
276 zFile = fossil_getenv(X509_get_default_cert_file_env());
277 break;
278 case 1:
279 zFile = fossil_getenv(X509_get_default_cert_dir_env());
280 break;
@@ -363,10 +363,11 @@
363 if( sslIsInit ){
364 SSL_CTX_free(sslCtx);
365 ssl_clear_errmsg();
366 sslIsInit = 0;
367 }
 
368 }
369
370 /*
371 ** Close the currently open client SSL connection. If no connection is open,
372 ** this routine is a no-op.
@@ -375,10 +376,11 @@
375 if( iBio!=NULL ){
376 (void)BIO_reset(iBio);
377 BIO_free_all(iBio);
378 iBio = NULL;
379 }
 
380 }
381
382 /* See RFC2817 for details */
383 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
384 int rc, httpVerMin;
@@ -450,63 +452,35 @@
450 ** Return the number of errors.
451 */
452 int ssl_open_client(UrlData *pUrlData){
453 X509 *cert;
454 const char *zRemoteHost;
 
455
456 ssl_global_init_client();
 
 
 
 
 
457 if( pUrlData->useProxy ){
458 int rc;
459 char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
460 BIO *sBio = BIO_new_connect(connStr);
461 switch( g.eIPvers ){
462 default: /* Any available protocol */
463 break;
464 case 1: /* IPv4 only */
465 #ifdef BIO_FAMILY_IPV4
466 BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV4);
467 #else
468 fossil_warning("The --ipv4 option is not supported in this build\n");
469 #endif
470 break;
471 case 2: /* IPv6 only */
472 #ifdef BIO_FAMILY_IPV6
473 BIO_set_conn_ip_family(sBio, BIO_FAMILY_IPV6);
474 #else
475 fossil_warning("The --ipv6 option is not supported in this build\n");
476 #endif
477 break;
478 }
479 fossil_free(connStr);
480 if( BIO_do_connect(sBio)<=0 ){
481 ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
482 pUrlData->name, pUrlData->port,
483 ERR_reason_error_string(ERR_get_error()));
484 ssl_close_client();
485 return 1;
486 }
487 rc = establish_proxy_tunnel(pUrlData, sBio);
488 if( rc<200||rc>299 ){
489 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
 
490 return 1;
491 }
492
493 pUrlData->path = pUrlData->proxyUrlPath;
494
495 iBio = BIO_new_ssl(sslCtx, 1);
496 BIO_push(iBio, sBio);
497 zRemoteHost = pUrlData->hostname;
498 }else{
499 iBio = BIO_new_ssl_connect(sslCtx);
500 zRemoteHost = pUrlData->name;
501 }
502 if( iBio==NULL ) {
503 ssl_set_errmsg("SSL: cannot open SSL (%s)",
504 ERR_reason_error_string(ERR_get_error()));
505 return 1;
506 }
507 BIO_get_ssl(iBio, &ssl);
 
 
508
509 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
510 if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){
511 fossil_warning("WARNING: failed to set server name indication (SNI), "
512 "continuing without it.\n");
@@ -523,45 +497,14 @@
523 }
524 /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
525 }
526 #endif
527
528 if( !pUrlData->useProxy ){
529 char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port);
530 BIO_set_conn_hostname(iBio, connStr);
531 fossil_free(connStr);
532 switch( g.eIPvers ){
533 default: /* Any available protocol */
534 break;
535 case 1: /* IPv4 only */
536 #ifdef BIO_FAMILY_IPV4
537 BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV4);
538 #else
539 fossil_warning("The --ipv4 option is not supported in this build\n");
540 #endif
541 break;
542 case 2: /* IPv6 only */
543 #ifdef BIO_FAMILY_IPV6
544 BIO_set_conn_ip_family(iBio, BIO_FAMILY_IPV6);
545 #else
546 fossil_warning("The --ipv6 option is not supported in this build\n");
547 #endif
548 break;
549 }
550 if( BIO_do_connect(iBio)<=0 ){
551 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
552 pUrlData->name, pUrlData->port,
553 ERR_reason_error_string(ERR_get_error()));
554 ssl_close_client();
555 return 1;
556 }
557 }
558
559 if( BIO_do_handshake(iBio)<=0 ) {
560 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
561 pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
562 pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
563 ERR_reason_error_string(ERR_get_error()));
564 ssl_close_client();
565 return 1;
566 }
567 /* Check if certificate is valid */
@@ -651,32 +594,10 @@
651 }
652 blob_reset(&ans);
653 }
654 }
655
656 /* Set the Global.zIpAddr variable to the server we are talking to.
657 ** This is used to populate the ipaddr column of the rcvfrom table,
658 ** if any files are received from the server.
659 */
660 {
661 /* As soon as libressl implements
662 ** BIO_ADDR_hostname_string/BIO_get_conn_address.
663 ** check here for the correct LIBRESSL_VERSION_NUMBER too. For now: disable
664 */
665 #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L \
666 && !defined(LIBRESSL_VERSION_NUMBER)
667 char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
668 g.zIpAddr = fossil_strdup(ip);
669 OPENSSL_free(ip);
670 #else
671 /* IPv4 only code */
672 const unsigned char *ip;
673 ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
674 g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
675 #endif
676 }
677
678 X509_free(cert);
679 return 0;
680 }
681
682 /*
683
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -270,11 +270,11 @@
270
271 /* Find the trust store */
272 zFile = 0;
273 for(i=0; zFile==0 && i<5; i++){
274 switch( i ){
275 case 0: /* First priority is environment variables */
276 zFile = fossil_getenv(X509_get_default_cert_file_env());
277 break;
278 case 1:
279 zFile = fossil_getenv(X509_get_default_cert_dir_env());
280 break;
@@ -363,10 +363,11 @@
363 if( sslIsInit ){
364 SSL_CTX_free(sslCtx);
365 ssl_clear_errmsg();
366 sslIsInit = 0;
367 }
368 socket_global_shutdown();
369 }
370
371 /*
372 ** Close the currently open client SSL connection. If no connection is open,
373 ** this routine is a no-op.
@@ -375,10 +376,11 @@
376 if( iBio!=NULL ){
377 (void)BIO_reset(iBio);
378 BIO_free_all(iBio);
379 iBio = NULL;
380 }
381 socket_close();
382 }
383
384 /* See RFC2817 for details */
385 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
386 int rc, httpVerMin;
@@ -450,63 +452,35 @@
452 ** Return the number of errors.
453 */
454 int ssl_open_client(UrlData *pUrlData){
455 X509 *cert;
456 const char *zRemoteHost;
457 BIO *sBio;
458
459 ssl_global_init_client();
460 if( socket_open(pUrlData) ){
461 ssl_set_errmsg("SSL: cannot open socket (%s)", socket_errmsg());
462 return 1;
463 }
464 sBio = BIO_new_socket(socket_get_fd(), 0);
465 if( pUrlData->useProxy ){
466 int rc = establish_proxy_tunnel(pUrlData, sBio);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
467 if( rc<200||rc>299 ){
468 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
469 ssl_close_client();
470 return 1;
471 }
472
473 pUrlData->path = pUrlData->proxyUrlPath;
474 }
475 iBio = BIO_new_ssl(sslCtx, 1);
476 BIO_push(iBio, sBio);
477 BIO_set_ssl(sBio, ssl, BIO_NOCLOSE);
478 BIO_set_ssl_mode(iBio, 1);
 
 
 
 
 
 
 
 
479 BIO_get_ssl(iBio, &ssl);
480
481 zRemoteHost = pUrlData->useProxy ? pUrlData->hostname : pUrlData->name;
482
483 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
484 if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){
485 fossil_warning("WARNING: failed to set server name indication (SNI), "
486 "continuing without it.\n");
@@ -523,45 +497,14 @@
497 }
498 /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */
499 }
500 #endif
501
502 if( BIO_do_handshake(iBio)<=0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
504 zRemoteHost,
505 pUrlData->useProxy ? pUrlData->proxyOrigPort : pUrlData->port,
506 ERR_reason_error_string(ERR_get_error()));
507 ssl_close_client();
508 return 1;
509 }
510 /* Check if certificate is valid */
@@ -651,32 +594,10 @@
594 }
595 blob_reset(&ans);
596 }
597 }
598
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599 X509_free(cert);
600 return 0;
601 }
602
603 /*
604
+4 -4
--- src/json.c
+++ src/json.c
@@ -240,11 +240,11 @@
240240
** - g.json.gc.a is NULL
241241
** - key is NULL or empty.
242242
**
243243
** Returns 0 on success.
244244
**
245
-** Ownership of v is transfered to (or shared with) g.json.gc, and v
245
+** Ownership of v is transferred to (or shared with) g.json.gc, and v
246246
** will be valid until that object is cleaned up or some internal code
247247
** incorrectly removes it from the gc (which we never do). If this
248248
** function fails, it is fatal to the app (as it indicates an
249249
** allocation error (more likely than not) or a serious internal error
250250
** such as numeric overflow).
@@ -271,11 +271,11 @@
271271
272272
273273
/*
274274
** Returns the value of json_rc_cstr(code) as a new JSON
275275
** string, which is owned by the caller and must eventually
276
-** be cson_value_free()d or transfered to a JSON container.
276
+** be cson_value_free()d or transferred to a JSON container.
277277
*/
278278
cson_value * json_rc_string( int code ){
279279
return cson_value_new_string( json_rc_cstr(code), 11 );
280280
}
281281
@@ -864,11 +864,11 @@
864864
/*
865865
** Splits zStr (which must not be NULL) into tokens separated by the
866866
** given separator character. If doDeHttp is true then each element
867867
** will be passed through dehttpize(), otherwise they are used
868868
** as-is. Note that tokenization happens before dehttpize(),
869
-** which is significant if the ENcoded tokens might contain the
869
+** which is significant if the encoded tokens might contain the
870870
** separator character.
871871
**
872872
** Each new element is appended to the given target array object,
873873
** which must not be NULL and ownership of it is not changed by this
874874
** call.
@@ -1437,11 +1437,11 @@
14371437
** If payload is not NULL and resultCode is 0 then it is set as the
14381438
** "payload" property of the returned object. If resultCode is 0 then
14391439
** it defaults to g.json.resultCode. If resultCode is (or defaults to)
14401440
** non-zero and payload is not NULL then this function calls
14411441
** cson_value_free(payload) and does not insert the payload into the
1442
-** response. In either case, ownership of payload is transfered to (or
1442
+** response. In either case, ownership of payload is transferred to (or
14431443
** shared with, if the caller holds a reference) this function.
14441444
**
14451445
** pMsg is an optional message string property (resultText) of the
14461446
** response. If resultCode is non-0 and pMsg is NULL then
14471447
** json_err_cstr() is used to get the error string. The caller may
14481448
--- src/json.c
+++ src/json.c
@@ -240,11 +240,11 @@
240 ** - g.json.gc.a is NULL
241 ** - key is NULL or empty.
242 **
243 ** Returns 0 on success.
244 **
245 ** Ownership of v is transfered to (or shared with) g.json.gc, and v
246 ** will be valid until that object is cleaned up or some internal code
247 ** incorrectly removes it from the gc (which we never do). If this
248 ** function fails, it is fatal to the app (as it indicates an
249 ** allocation error (more likely than not) or a serious internal error
250 ** such as numeric overflow).
@@ -271,11 +271,11 @@
271
272
273 /*
274 ** Returns the value of json_rc_cstr(code) as a new JSON
275 ** string, which is owned by the caller and must eventually
276 ** be cson_value_free()d or transfered to a JSON container.
277 */
278 cson_value * json_rc_string( int code ){
279 return cson_value_new_string( json_rc_cstr(code), 11 );
280 }
281
@@ -864,11 +864,11 @@
864 /*
865 ** Splits zStr (which must not be NULL) into tokens separated by the
866 ** given separator character. If doDeHttp is true then each element
867 ** will be passed through dehttpize(), otherwise they are used
868 ** as-is. Note that tokenization happens before dehttpize(),
869 ** which is significant if the ENcoded tokens might contain the
870 ** separator character.
871 **
872 ** Each new element is appended to the given target array object,
873 ** which must not be NULL and ownership of it is not changed by this
874 ** call.
@@ -1437,11 +1437,11 @@
1437 ** If payload is not NULL and resultCode is 0 then it is set as the
1438 ** "payload" property of the returned object. If resultCode is 0 then
1439 ** it defaults to g.json.resultCode. If resultCode is (or defaults to)
1440 ** non-zero and payload is not NULL then this function calls
1441 ** cson_value_free(payload) and does not insert the payload into the
1442 ** response. In either case, ownership of payload is transfered to (or
1443 ** shared with, if the caller holds a reference) this function.
1444 **
1445 ** pMsg is an optional message string property (resultText) of the
1446 ** response. If resultCode is non-0 and pMsg is NULL then
1447 ** json_err_cstr() is used to get the error string. The caller may
1448
--- src/json.c
+++ src/json.c
@@ -240,11 +240,11 @@
240 ** - g.json.gc.a is NULL
241 ** - key is NULL or empty.
242 **
243 ** Returns 0 on success.
244 **
245 ** Ownership of v is transferred to (or shared with) g.json.gc, and v
246 ** will be valid until that object is cleaned up or some internal code
247 ** incorrectly removes it from the gc (which we never do). If this
248 ** function fails, it is fatal to the app (as it indicates an
249 ** allocation error (more likely than not) or a serious internal error
250 ** such as numeric overflow).
@@ -271,11 +271,11 @@
271
272
273 /*
274 ** Returns the value of json_rc_cstr(code) as a new JSON
275 ** string, which is owned by the caller and must eventually
276 ** be cson_value_free()d or transferred to a JSON container.
277 */
278 cson_value * json_rc_string( int code ){
279 return cson_value_new_string( json_rc_cstr(code), 11 );
280 }
281
@@ -864,11 +864,11 @@
864 /*
865 ** Splits zStr (which must not be NULL) into tokens separated by the
866 ** given separator character. If doDeHttp is true then each element
867 ** will be passed through dehttpize(), otherwise they are used
868 ** as-is. Note that tokenization happens before dehttpize(),
869 ** which is significant if the encoded tokens might contain the
870 ** separator character.
871 **
872 ** Each new element is appended to the given target array object,
873 ** which must not be NULL and ownership of it is not changed by this
874 ** call.
@@ -1437,11 +1437,11 @@
1437 ** If payload is not NULL and resultCode is 0 then it is set as the
1438 ** "payload" property of the returned object. If resultCode is 0 then
1439 ** it defaults to g.json.resultCode. If resultCode is (or defaults to)
1440 ** non-zero and payload is not NULL then this function calls
1441 ** cson_value_free(payload) and does not insert the payload into the
1442 ** response. In either case, ownership of payload is transferred to (or
1443 ** shared with, if the caller holds a reference) this function.
1444 **
1445 ** pMsg is an optional message string property (resultText) of the
1446 ** response. If resultCode is non-0 and pMsg is NULL then
1447 ** json_err_cstr() is used to get the error string. The caller may
1448
--- src/json_report.c
+++ src/json_report.c
@@ -155,11 +155,11 @@
155155
**
156156
** report=int (CLI: -report # or -r #) is the report number to run.
157157
**
158158
** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
159159
**
160
-** format=a|o Specifies result format: a=each row is an arry, o=each
160
+** format=a|o Specifies result format: a=each row is an array, o=each
161161
** row is an object. Default=o.
162162
*/
163163
static cson_value * json_report_run(void){
164164
int nReport;
165165
Stmt q = empty_Stmt;
166166
--- src/json_report.c
+++ src/json_report.c
@@ -155,11 +155,11 @@
155 **
156 ** report=int (CLI: -report # or -r #) is the report number to run.
157 **
158 ** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
159 **
160 ** format=a|o Specifies result format: a=each row is an arry, o=each
161 ** row is an object. Default=o.
162 */
163 static cson_value * json_report_run(void){
164 int nReport;
165 Stmt q = empty_Stmt;
166
--- src/json_report.c
+++ src/json_report.c
@@ -155,11 +155,11 @@
155 **
156 ** report=int (CLI: -report # or -r #) is the report number to run.
157 **
158 ** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
159 **
160 ** format=a|o Specifies result format: a=each row is an array, o=each
161 ** row is an object. Default=o.
162 */
163 static cson_value * json_report_run(void){
164 int nReport;
165 Stmt q = empty_Stmt;
166
--- src/json_status.c
+++ src/json_status.c
@@ -126,11 +126,11 @@
126126
zStatus = "missing";
127127
++nErr;
128128
}
129129
}else if( isChnged ){
130130
switch( isChnged ){
131
- /* These numbers from from checkin.c: status_report() */
131
+ /* These numbers from checkin.c: status_report() */
132132
case 1:
133133
if( file_contains_merge_marker(zFullName) ){
134134
zStatus = "conflict";
135135
}else{
136136
zStatus = "edited";
137137
--- src/json_status.c
+++ src/json_status.c
@@ -126,11 +126,11 @@
126 zStatus = "missing";
127 ++nErr;
128 }
129 }else if( isChnged ){
130 switch( isChnged ){
131 /* These numbers from from checkin.c: status_report() */
132 case 1:
133 if( file_contains_merge_marker(zFullName) ){
134 zStatus = "conflict";
135 }else{
136 zStatus = "edited";
137
--- src/json_status.c
+++ src/json_status.c
@@ -126,11 +126,11 @@
126 zStatus = "missing";
127 ++nErr;
128 }
129 }else if( isChnged ){
130 switch( isChnged ){
131 /* These numbers from checkin.c: status_report() */
132 case 1:
133 if( file_contains_merge_marker(zFullName) ){
134 zStatus = "conflict";
135 }else{
136 zStatus = "edited";
137
+15 -9
--- src/login.c
+++ src/login.c
@@ -293,11 +293,11 @@
293293
**
294294
** This function also updates the user.cookie, user.ipaddr,
295295
** and user.cexpire fields for the given user.
296296
**
297297
** If zDest is not NULL then the generated cookie is copied to
298
-** *zDdest and ownership is transfered to the caller (who should
298
+** *zDdest and ownership is transferred to the caller (who should
299299
** eventually pass it to free()).
300300
**
301301
** If bSessionCookie is true, the cookie will be a session cookie,
302302
** else a persistent cookie. If it's a session cookie, the
303303
** [user].[cexpire] and [user].[cookie] entries will be modified as if
@@ -379,11 +379,11 @@
379379
** If bSessionCookie is true, the cookie will be a session cookie.
380380
**
381381
** Search for tag-20250817a to find the code that recognizes this cookie.
382382
*/
383383
void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){
384
- char *zNow; /* Current time (julian day number) */
384
+ char *zNow; /* Current time (Julian day number) */
385385
char *zCookie; /* The login cookie */
386386
const char *zUserAgent; /* The user agent */
387387
const char *zCookieName; /* Name of the login cookie */
388388
Blob b; /* Blob used during cookie construction */
389389
int expires = bSessionCookie ? 0 : anon_cookie_lifespan();
@@ -1371,10 +1371,11 @@
13711371
** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
13721372
** g.perm Permissions granted to this user
13731373
** g.anon Permissions that would be available to anonymous
13741374
** g.isRobot True if the client is known to be a spider or robot
13751375
** g.perm Populated based on user account's capabilities
1376
+** g.eAuthMethod The mechanism used for authentication
13761377
**
13771378
*/
13781379
void login_check_credentials(void){
13791380
int uid = 0; /* User id */
13801381
const char *zCookie; /* Text of the login cookie */
@@ -1411,10 +1412,11 @@
14111412
}
14121413
g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
14131414
zCap = "sxy";
14141415
g.noPswd = 1;
14151416
g.isRobot = 0;
1417
+ g.eAuthMethod = AUTH_LOCAL;
14161418
zSeed = db_text("??", "SELECT uid||quote(login)||quote(pw)||quote(cookie)"
14171419
" FROM user WHERE uid=%d", uid);
14181420
login_create_csrf_secret(zSeed);
14191421
fossil_free(zSeed);
14201422
}
@@ -1490,10 +1492,11 @@
14901492
" AND octet_length(cap)>0"
14911493
" AND octet_length(pw)>0");
14921494
}
14931495
}
14941496
}
1497
+ if( uid ) g.eAuthMethod = AUTH_COOKIE;
14951498
login_create_csrf_secret(zHash);
14961499
}
14971500
14981501
/* If no user found and the REMOTE_USER environment variable is set,
14991502
** then accept the value of REMOTE_USER as the user.
@@ -1502,19 +1505,21 @@
15021505
const char *zRemoteUser = P("REMOTE_USER");
15031506
if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
15041507
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
15051508
" AND octet_length(cap)>0 AND octet_length(pw)>0",
15061509
zRemoteUser);
1510
+ if( uid ) g.eAuthMethod = AUTH_ENV;
15071511
}
15081512
}
15091513
15101514
/* If the request didn't provide a login cookie or the login cookie didn't
15111515
** match a known valid user, check the HTTP "Authorization" header and
15121516
** see if those credentials are valid for a known user.
15131517
*/
15141518
if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
15151519
uid = login_basic_authentication(zIpAddr);
1520
+ if( uid ) g.eAuthMethod = AUTH_HTTP;
15161521
}
15171522
15181523
/* Check for magic query parameters "resid" (for the username) and
15191524
** "token" for the password. Both values (if they exist) will be
15201525
** obfuscated.
@@ -1529,10 +1534,11 @@
15291534
" WHERE login=%Q"
15301535
" AND (constant_time_cmp(pw,%Q)=0"
15311536
" OR constant_time_cmp(pw,%Q)=0)",
15321537
zUsr, zSha1Pw, zPW);
15331538
fossil_free(zSha1Pw);
1539
+ if( uid ) g.eAuthMethod = AUTH_PW;
15341540
}
15351541
}
15361542
15371543
/* If no user found yet, try to log in as "nobody" */
15381544
if( uid==0 ){
@@ -1925,11 +1931,11 @@
19251931
}
19261932
}
19271933
19281934
/*
19291935
** Call this routine if the user lacks g.perm.Hyperlink permission. If
1930
-** the anonymous user has Hyperlink permission, then paint a mesage
1936
+** the anonymous user has Hyperlink permission, then paint a message
19311937
** to inform the user that much more information is available by
19321938
** logging in as anonymous.
19331939
*/
19341940
void login_anonymous_available(void){
19351941
if( !g.perm.Hyperlink && g.anon.Hyperlink && anon_cookie_lifespan()>0 ){
@@ -1949,13 +1955,13 @@
19491955
}
19501956
19511957
/*
19521958
** Check to see if the candidate username zUserID is already used.
19531959
** Return 1 if it is already in use. Return 0 if the name is
1954
-** available for a self-registeration.
1960
+** available for a self-registration.
19551961
*/
1956
-static int login_self_choosen_userid_already_exists(const char *zUserID){
1962
+static int login_self_chosen_userid_already_exists(const char *zUserID){
19571963
int rc = db_exists(
19581964
"SELECT 1 FROM user WHERE login=%Q "
19591965
"UNION ALL "
19601966
"SELECT 1 FROM event WHERE user=%Q OR euser=%Q",
19611967
zUserID, zUserID, zUserID
@@ -2140,11 +2146,11 @@
21402146
iErrLine = 5;
21412147
zErr = "Passwords do not match";
21422148
}else if( (uid = email_address_in_use(zEAddr))!=0 ){
21432149
iErrLine = 3;
21442150
zErr = "This email address is already associated with a user";
2145
- }else if( login_self_choosen_userid_already_exists(zUserID) ){
2151
+ }else if( login_self_chosen_userid_already_exists(zUserID) ){
21462152
iErrLine = 1;
21472153
zErr = "This User ID is already taken. Choose something different.";
21482154
}else{
21492155
/* If all of the tests above have passed, that means that the submitted
21502156
** form contains valid data and we can proceed to create the new login */
@@ -2151,11 +2157,11 @@
21512157
Blob sql;
21522158
int uid;
21532159
char *zPass = sha1_shared_secret(zPasswd, zUserID, 0);
21542160
const char *zStartPerms = zPerms;
21552161
if( db_get_boolean("selfreg-verify",0) ){
2156
- /* If email verification is required for self-registration, initalize
2162
+ /* If email verification is required for self-registration, initialize
21572163
** the new user capabilities to just "7" (Sign up for email). The
21582164
** full "default-perms" permissions will be added when they click
21592165
** the verification link on the email they are sent. */
21602166
zStartPerms = "7";
21612167
}
@@ -2206,11 +2212,11 @@
22062212
);
22072213
if( db_exists("SELECT 1 FROM subscriber WHERE semail=%Q"
22082214
" AND sverified", zEAddr) ){
22092215
/* This the case where the user was formerly a verified subscriber
22102216
** and here they have also registered as a user as well. It is
2211
- ** not necessary to repeat the verfication step */
2217
+ ** not necessary to repeat the verification step */
22122218
login_redirect_to_g();
22132219
}
22142220
/* A verification email */
22152221
pSender = alert_sender_new(0,0);
22162222
blob_init(&hdr,0,0);
@@ -2377,11 +2383,11 @@
23772383
style_finish_page();
23782384
return;
23792385
}
23802386
zEAddr = PDT("ea","");
23812387
2382
- /* Verify user imputs */
2388
+ /* Verify user inputs */
23832389
if( !cgi_csrf_safe(1) || P("reqpwreset")==0 ){
23842390
/* This is the initial display of the form. No processing or error
23852391
** checking is to be done. Fall through into the form display
23862392
**
23872393
** cgi_csrf_safe(): Nothing interesting happens on this page without
23882394
--- src/login.c
+++ src/login.c
@@ -293,11 +293,11 @@
293 **
294 ** This function also updates the user.cookie, user.ipaddr,
295 ** and user.cexpire fields for the given user.
296 **
297 ** If zDest is not NULL then the generated cookie is copied to
298 ** *zDdest and ownership is transfered to the caller (who should
299 ** eventually pass it to free()).
300 **
301 ** If bSessionCookie is true, the cookie will be a session cookie,
302 ** else a persistent cookie. If it's a session cookie, the
303 ** [user].[cexpire] and [user].[cookie] entries will be modified as if
@@ -379,11 +379,11 @@
379 ** If bSessionCookie is true, the cookie will be a session cookie.
380 **
381 ** Search for tag-20250817a to find the code that recognizes this cookie.
382 */
383 void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){
384 char *zNow; /* Current time (julian day number) */
385 char *zCookie; /* The login cookie */
386 const char *zUserAgent; /* The user agent */
387 const char *zCookieName; /* Name of the login cookie */
388 Blob b; /* Blob used during cookie construction */
389 int expires = bSessionCookie ? 0 : anon_cookie_lifespan();
@@ -1371,10 +1371,11 @@
1371 ** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
1372 ** g.perm Permissions granted to this user
1373 ** g.anon Permissions that would be available to anonymous
1374 ** g.isRobot True if the client is known to be a spider or robot
1375 ** g.perm Populated based on user account's capabilities
 
1376 **
1377 */
1378 void login_check_credentials(void){
1379 int uid = 0; /* User id */
1380 const char *zCookie; /* Text of the login cookie */
@@ -1411,10 +1412,11 @@
1411 }
1412 g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
1413 zCap = "sxy";
1414 g.noPswd = 1;
1415 g.isRobot = 0;
 
1416 zSeed = db_text("??", "SELECT uid||quote(login)||quote(pw)||quote(cookie)"
1417 " FROM user WHERE uid=%d", uid);
1418 login_create_csrf_secret(zSeed);
1419 fossil_free(zSeed);
1420 }
@@ -1490,10 +1492,11 @@
1490 " AND octet_length(cap)>0"
1491 " AND octet_length(pw)>0");
1492 }
1493 }
1494 }
 
1495 login_create_csrf_secret(zHash);
1496 }
1497
1498 /* If no user found and the REMOTE_USER environment variable is set,
1499 ** then accept the value of REMOTE_USER as the user.
@@ -1502,19 +1505,21 @@
1502 const char *zRemoteUser = P("REMOTE_USER");
1503 if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
1504 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
1505 " AND octet_length(cap)>0 AND octet_length(pw)>0",
1506 zRemoteUser);
 
1507 }
1508 }
1509
1510 /* If the request didn't provide a login cookie or the login cookie didn't
1511 ** match a known valid user, check the HTTP "Authorization" header and
1512 ** see if those credentials are valid for a known user.
1513 */
1514 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1515 uid = login_basic_authentication(zIpAddr);
 
1516 }
1517
1518 /* Check for magic query parameters "resid" (for the username) and
1519 ** "token" for the password. Both values (if they exist) will be
1520 ** obfuscated.
@@ -1529,10 +1534,11 @@
1529 " WHERE login=%Q"
1530 " AND (constant_time_cmp(pw,%Q)=0"
1531 " OR constant_time_cmp(pw,%Q)=0)",
1532 zUsr, zSha1Pw, zPW);
1533 fossil_free(zSha1Pw);
 
1534 }
1535 }
1536
1537 /* If no user found yet, try to log in as "nobody" */
1538 if( uid==0 ){
@@ -1925,11 +1931,11 @@
1925 }
1926 }
1927
1928 /*
1929 ** Call this routine if the user lacks g.perm.Hyperlink permission. If
1930 ** the anonymous user has Hyperlink permission, then paint a mesage
1931 ** to inform the user that much more information is available by
1932 ** logging in as anonymous.
1933 */
1934 void login_anonymous_available(void){
1935 if( !g.perm.Hyperlink && g.anon.Hyperlink && anon_cookie_lifespan()>0 ){
@@ -1949,13 +1955,13 @@
1949 }
1950
1951 /*
1952 ** Check to see if the candidate username zUserID is already used.
1953 ** Return 1 if it is already in use. Return 0 if the name is
1954 ** available for a self-registeration.
1955 */
1956 static int login_self_choosen_userid_already_exists(const char *zUserID){
1957 int rc = db_exists(
1958 "SELECT 1 FROM user WHERE login=%Q "
1959 "UNION ALL "
1960 "SELECT 1 FROM event WHERE user=%Q OR euser=%Q",
1961 zUserID, zUserID, zUserID
@@ -2140,11 +2146,11 @@
2140 iErrLine = 5;
2141 zErr = "Passwords do not match";
2142 }else if( (uid = email_address_in_use(zEAddr))!=0 ){
2143 iErrLine = 3;
2144 zErr = "This email address is already associated with a user";
2145 }else if( login_self_choosen_userid_already_exists(zUserID) ){
2146 iErrLine = 1;
2147 zErr = "This User ID is already taken. Choose something different.";
2148 }else{
2149 /* If all of the tests above have passed, that means that the submitted
2150 ** form contains valid data and we can proceed to create the new login */
@@ -2151,11 +2157,11 @@
2151 Blob sql;
2152 int uid;
2153 char *zPass = sha1_shared_secret(zPasswd, zUserID, 0);
2154 const char *zStartPerms = zPerms;
2155 if( db_get_boolean("selfreg-verify",0) ){
2156 /* If email verification is required for self-registration, initalize
2157 ** the new user capabilities to just "7" (Sign up for email). The
2158 ** full "default-perms" permissions will be added when they click
2159 ** the verification link on the email they are sent. */
2160 zStartPerms = "7";
2161 }
@@ -2206,11 +2212,11 @@
2206 );
2207 if( db_exists("SELECT 1 FROM subscriber WHERE semail=%Q"
2208 " AND sverified", zEAddr) ){
2209 /* This the case where the user was formerly a verified subscriber
2210 ** and here they have also registered as a user as well. It is
2211 ** not necessary to repeat the verfication step */
2212 login_redirect_to_g();
2213 }
2214 /* A verification email */
2215 pSender = alert_sender_new(0,0);
2216 blob_init(&hdr,0,0);
@@ -2377,11 +2383,11 @@
2377 style_finish_page();
2378 return;
2379 }
2380 zEAddr = PDT("ea","");
2381
2382 /* Verify user imputs */
2383 if( !cgi_csrf_safe(1) || P("reqpwreset")==0 ){
2384 /* This is the initial display of the form. No processing or error
2385 ** checking is to be done. Fall through into the form display
2386 **
2387 ** cgi_csrf_safe(): Nothing interesting happens on this page without
2388
--- src/login.c
+++ src/login.c
@@ -293,11 +293,11 @@
293 **
294 ** This function also updates the user.cookie, user.ipaddr,
295 ** and user.cexpire fields for the given user.
296 **
297 ** If zDest is not NULL then the generated cookie is copied to
298 ** *zDdest and ownership is transferred to the caller (who should
299 ** eventually pass it to free()).
300 **
301 ** If bSessionCookie is true, the cookie will be a session cookie,
302 ** else a persistent cookie. If it's a session cookie, the
303 ** [user].[cexpire] and [user].[cookie] entries will be modified as if
@@ -379,11 +379,11 @@
379 ** If bSessionCookie is true, the cookie will be a session cookie.
380 **
381 ** Search for tag-20250817a to find the code that recognizes this cookie.
382 */
383 void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){
384 char *zNow; /* Current time (Julian day number) */
385 char *zCookie; /* The login cookie */
386 const char *zUserAgent; /* The user agent */
387 const char *zCookieName; /* Name of the login cookie */
388 Blob b; /* Blob used during cookie construction */
389 int expires = bSessionCookie ? 0 : anon_cookie_lifespan();
@@ -1371,10 +1371,11 @@
1371 ** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
1372 ** g.perm Permissions granted to this user
1373 ** g.anon Permissions that would be available to anonymous
1374 ** g.isRobot True if the client is known to be a spider or robot
1375 ** g.perm Populated based on user account's capabilities
1376 ** g.eAuthMethod The mechanism used for authentication
1377 **
1378 */
1379 void login_check_credentials(void){
1380 int uid = 0; /* User id */
1381 const char *zCookie; /* Text of the login cookie */
@@ -1411,10 +1412,11 @@
1412 }
1413 g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
1414 zCap = "sxy";
1415 g.noPswd = 1;
1416 g.isRobot = 0;
1417 g.eAuthMethod = AUTH_LOCAL;
1418 zSeed = db_text("??", "SELECT uid||quote(login)||quote(pw)||quote(cookie)"
1419 " FROM user WHERE uid=%d", uid);
1420 login_create_csrf_secret(zSeed);
1421 fossil_free(zSeed);
1422 }
@@ -1490,10 +1492,11 @@
1492 " AND octet_length(cap)>0"
1493 " AND octet_length(pw)>0");
1494 }
1495 }
1496 }
1497 if( uid ) g.eAuthMethod = AUTH_COOKIE;
1498 login_create_csrf_secret(zHash);
1499 }
1500
1501 /* If no user found and the REMOTE_USER environment variable is set,
1502 ** then accept the value of REMOTE_USER as the user.
@@ -1502,19 +1505,21 @@
1505 const char *zRemoteUser = P("REMOTE_USER");
1506 if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
1507 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
1508 " AND octet_length(cap)>0 AND octet_length(pw)>0",
1509 zRemoteUser);
1510 if( uid ) g.eAuthMethod = AUTH_ENV;
1511 }
1512 }
1513
1514 /* If the request didn't provide a login cookie or the login cookie didn't
1515 ** match a known valid user, check the HTTP "Authorization" header and
1516 ** see if those credentials are valid for a known user.
1517 */
1518 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1519 uid = login_basic_authentication(zIpAddr);
1520 if( uid ) g.eAuthMethod = AUTH_HTTP;
1521 }
1522
1523 /* Check for magic query parameters "resid" (for the username) and
1524 ** "token" for the password. Both values (if they exist) will be
1525 ** obfuscated.
@@ -1529,10 +1534,11 @@
1534 " WHERE login=%Q"
1535 " AND (constant_time_cmp(pw,%Q)=0"
1536 " OR constant_time_cmp(pw,%Q)=0)",
1537 zUsr, zSha1Pw, zPW);
1538 fossil_free(zSha1Pw);
1539 if( uid ) g.eAuthMethod = AUTH_PW;
1540 }
1541 }
1542
1543 /* If no user found yet, try to log in as "nobody" */
1544 if( uid==0 ){
@@ -1925,11 +1931,11 @@
1931 }
1932 }
1933
1934 /*
1935 ** Call this routine if the user lacks g.perm.Hyperlink permission. If
1936 ** the anonymous user has Hyperlink permission, then paint a message
1937 ** to inform the user that much more information is available by
1938 ** logging in as anonymous.
1939 */
1940 void login_anonymous_available(void){
1941 if( !g.perm.Hyperlink && g.anon.Hyperlink && anon_cookie_lifespan()>0 ){
@@ -1949,13 +1955,13 @@
1955 }
1956
1957 /*
1958 ** Check to see if the candidate username zUserID is already used.
1959 ** Return 1 if it is already in use. Return 0 if the name is
1960 ** available for a self-registration.
1961 */
1962 static int login_self_chosen_userid_already_exists(const char *zUserID){
1963 int rc = db_exists(
1964 "SELECT 1 FROM user WHERE login=%Q "
1965 "UNION ALL "
1966 "SELECT 1 FROM event WHERE user=%Q OR euser=%Q",
1967 zUserID, zUserID, zUserID
@@ -2140,11 +2146,11 @@
2146 iErrLine = 5;
2147 zErr = "Passwords do not match";
2148 }else if( (uid = email_address_in_use(zEAddr))!=0 ){
2149 iErrLine = 3;
2150 zErr = "This email address is already associated with a user";
2151 }else if( login_self_chosen_userid_already_exists(zUserID) ){
2152 iErrLine = 1;
2153 zErr = "This User ID is already taken. Choose something different.";
2154 }else{
2155 /* If all of the tests above have passed, that means that the submitted
2156 ** form contains valid data and we can proceed to create the new login */
@@ -2151,11 +2157,11 @@
2157 Blob sql;
2158 int uid;
2159 char *zPass = sha1_shared_secret(zPasswd, zUserID, 0);
2160 const char *zStartPerms = zPerms;
2161 if( db_get_boolean("selfreg-verify",0) ){
2162 /* If email verification is required for self-registration, initialize
2163 ** the new user capabilities to just "7" (Sign up for email). The
2164 ** full "default-perms" permissions will be added when they click
2165 ** the verification link on the email they are sent. */
2166 zStartPerms = "7";
2167 }
@@ -2206,11 +2212,11 @@
2212 );
2213 if( db_exists("SELECT 1 FROM subscriber WHERE semail=%Q"
2214 " AND sverified", zEAddr) ){
2215 /* This the case where the user was formerly a verified subscriber
2216 ** and here they have also registered as a user as well. It is
2217 ** not necessary to repeat the verification step */
2218 login_redirect_to_g();
2219 }
2220 /* A verification email */
2221 pSender = alert_sender_new(0,0);
2222 blob_init(&hdr,0,0);
@@ -2377,11 +2383,11 @@
2383 style_finish_page();
2384 return;
2385 }
2386 zEAddr = PDT("ea","");
2387
2388 /* Verify user inputs */
2389 if( !cgi_csrf_safe(1) || P("reqpwreset")==0 ){
2390 /* This is the initial display of the form. No processing or error
2391 ** checking is to be done. Fall through into the form display
2392 **
2393 ** cgi_csrf_safe(): Nothing interesting happens on this page without
2394
+16 -8
--- src/main.c
+++ src/main.c
@@ -63,11 +63,11 @@
6363
#ifdef HAVE_BACKTRACE
6464
# include <execinfo.h>
6565
#endif
6666
6767
/*
68
-** Default length of a timeout for serving an HTTP request. Changable
68
+** Default length of a timeout for serving an HTTP request. Changeable
6969
** using the "--timeout N" command-line option or via "timeout: N" in the
7070
** CGI script.
7171
*/
7272
#ifndef FOSSIL_DEFAULT_TIMEOUT
7373
# define FOSSIL_DEFAULT_TIMEOUT 600 /* 10 minutes */
@@ -153,10 +153,11 @@
153153
char *nameOfExe; /* Full path of executable. */
154154
const char *zErrlog; /* Log errors to this file, if not NULL */
155155
const char *zPhase; /* Phase of operation, for use by the error log
156156
** and for deriving $canonical_page TH1 variable */
157157
int isConst; /* True if the output is unchanging & cacheable */
158
+ int iResultCode; /* Process reply code for commands */
158159
const char *zVfsName; /* The VFS to use for database connections */
159160
sqlite3 *db; /* The connection to the databases */
160161
sqlite3 *dbConfig; /* Separate connection for global_config table */
161162
char *zAuxSchema; /* Main repository aux-schema */
162163
int dbIgnoreErrors; /* Ignore database errors if true */
@@ -236,10 +237,17 @@
236237
* applicable when using SEE on Windows or Linux. */
237238
#endif
238239
int useLocalauth; /* No login required if from 127.0.0.1 */
239240
int noPswd; /* Logged in without password (on 127.0.0.1) */
240241
int userUid; /* Integer user id */
242
+ int eAuthMethod; /* How the user authenticated to us */
243
+# define AUTH_NONE 0 /* Not authenticated */
244
+# define AUTH_COOKIE 1 /* Authentication by cookie */
245
+# define AUTH_LOCAL 2 /* Uses loopback */
246
+# define AUTH_PW 3 /* Authentication by password */
247
+# define AUTH_ENV 4 /* Authenticated by REMOTE_USER environment var */
248
+# define AUTH_HTTP 5 /* HTTP Basic Authentication */
241249
int isRobot; /* True if the client is definitely a robot. False
242250
** negatives are common for this flag */
243251
int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
244252
** accessed through get_comment_format(). */
245253
const char *zSockName; /* Name of the unix-domain socket file */
@@ -823,11 +831,11 @@
823831
fossil_exit(1);
824832
}else{
825833
const char *zChdir = find_option("chdir",0,1);
826834
g.isHTTP = 0;
827835
g.rcvid = 0;
828
- g.fQuiet = find_option("quiet", 0, 0)!=0;
836
+ g.fQuiet = find_option("quiet", "q", 0)!=0;
829837
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
830838
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
831839
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
832840
g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
833841
g.fCgiTrace = find_option("cgitrace", 0, 0)!=0;
@@ -1009,11 +1017,11 @@
10091017
if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
10101018
Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags);
10111019
}
10121020
}
10131021
#endif
1014
- fossil_exit(0);
1022
+ fossil_exit(g.iResultCode);
10151023
/*NOT_REACHED*/
10161024
return 0;
10171025
}
10181026
10191027
/*
@@ -1183,11 +1191,11 @@
11831191
** list and this function immediately returns. The effect is to treat
11841192
** all arguments after "--" as non-flags (conventionally used to
11851193
** enable passing-in of filenames which start with a dash).
11861194
**
11871195
** This function must normally only be called one time per app
1188
-** invokation. The exception is commands which process their
1196
+** invocation. The exception is commands which process their
11891197
** arguments, call this to confirm that there are no extraneous flags,
11901198
** then modify the arguments list for forwarding to another
11911199
** (sub)command (which itself will call this to confirm its own
11921200
** arguments).
11931201
*/
@@ -1395,11 +1403,11 @@
13951403
style_finish_page();
13961404
}
13971405
13981406
13991407
/*
1400
-** Set the g.zBaseURL value to the full URL for the toplevel of
1408
+** Set the g.zBaseURL value to the full URL for the top level of
14011409
** the fossil tree. Set g.zTop to g.zBaseURL without the
14021410
** leading "http://" and the host and port.
14031411
**
14041412
** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
14051413
** environment variables. However, if zAltBase is not NULL then it
@@ -2869,11 +2877,11 @@
28692877
** then the server redirects (HTTP code 302) to the URL of --notfound.
28702878
** When REPOSITORY is a directory, the pathname must contain only
28712879
** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
28722880
** and every "." must be surrounded on both sides by alphanumerics or else
28732881
** a 404 error is returned. Static content files in the directory are
2874
-** returned if they match comma-separate GLOB pattern specified by --files
2882
+** returned if they match comma-separated GLOB pattern specified by --files
28752883
** and do not match "*.fossil*" and have a well-known suffix.
28762884
**
28772885
** Options:
28782886
** --acme Deliver files from the ".well-known" subdirectory
28792887
** --baseurl URL Base URL (useful with reverse proxies)
@@ -2881,11 +2889,11 @@
28812889
** fullchain.pem) taken from FILE.
28822890
** --chroot DIR Use directory for chroot instead of repository path.
28832891
** --ckout-alias N Treat URIs of the form /doc/N/... as if they were
28842892
** /doc/ckout/...
28852893
** --extroot DIR Document root for the /ext extension mechanism
2886
-** --files GLOB Comma-separate glob patterns for static file to serve
2894
+** --files GLOB Comma-separated glob patterns for static files to serve
28872895
** --host NAME DNS Hostname of the server
28882896
** --https The HTTP request originated from https but has already
28892897
** been decoded by a reverse proxy. Hence, URLs created
28902898
** by Fossil should use "https:" rather than "http:".
28912899
** --in FILE Take input from FILE instead of standard input
@@ -3102,11 +3110,11 @@
31023110
** using this command interactively over SSH. A better solution would be
31033111
** to use a different command for "ssh" sync, but we cannot do that without
31043112
** breaking legacy.
31053113
**
31063114
** Options:
3107
-** --csrf-safe N Set cgi_csrf_safe() to to return N
3115
+** --csrf-safe N Set cgi_csrf_safe() to return N
31083116
** --nobody Pretend to be user "nobody"
31093117
** --ssh-sim Pretend to be over an SSH connection
31103118
** --test Do not do special "sync" processing when operating
31113119
** over an SSH link
31123120
** --th-trace Trace TH1 execution (for debugging purposes)
31133121
--- src/main.c
+++ src/main.c
@@ -63,11 +63,11 @@
63 #ifdef HAVE_BACKTRACE
64 # include <execinfo.h>
65 #endif
66
67 /*
68 ** Default length of a timeout for serving an HTTP request. Changable
69 ** using the "--timeout N" command-line option or via "timeout: N" in the
70 ** CGI script.
71 */
72 #ifndef FOSSIL_DEFAULT_TIMEOUT
73 # define FOSSIL_DEFAULT_TIMEOUT 600 /* 10 minutes */
@@ -153,10 +153,11 @@
153 char *nameOfExe; /* Full path of executable. */
154 const char *zErrlog; /* Log errors to this file, if not NULL */
155 const char *zPhase; /* Phase of operation, for use by the error log
156 ** and for deriving $canonical_page TH1 variable */
157 int isConst; /* True if the output is unchanging & cacheable */
 
158 const char *zVfsName; /* The VFS to use for database connections */
159 sqlite3 *db; /* The connection to the databases */
160 sqlite3 *dbConfig; /* Separate connection for global_config table */
161 char *zAuxSchema; /* Main repository aux-schema */
162 int dbIgnoreErrors; /* Ignore database errors if true */
@@ -236,10 +237,17 @@
236 * applicable when using SEE on Windows or Linux. */
237 #endif
238 int useLocalauth; /* No login required if from 127.0.0.1 */
239 int noPswd; /* Logged in without password (on 127.0.0.1) */
240 int userUid; /* Integer user id */
 
 
 
 
 
 
 
241 int isRobot; /* True if the client is definitely a robot. False
242 ** negatives are common for this flag */
243 int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
244 ** accessed through get_comment_format(). */
245 const char *zSockName; /* Name of the unix-domain socket file */
@@ -823,11 +831,11 @@
823 fossil_exit(1);
824 }else{
825 const char *zChdir = find_option("chdir",0,1);
826 g.isHTTP = 0;
827 g.rcvid = 0;
828 g.fQuiet = find_option("quiet", 0, 0)!=0;
829 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
830 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
831 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
832 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
833 g.fCgiTrace = find_option("cgitrace", 0, 0)!=0;
@@ -1009,11 +1017,11 @@
1009 if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
1010 Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags);
1011 }
1012 }
1013 #endif
1014 fossil_exit(0);
1015 /*NOT_REACHED*/
1016 return 0;
1017 }
1018
1019 /*
@@ -1183,11 +1191,11 @@
1183 ** list and this function immediately returns. The effect is to treat
1184 ** all arguments after "--" as non-flags (conventionally used to
1185 ** enable passing-in of filenames which start with a dash).
1186 **
1187 ** This function must normally only be called one time per app
1188 ** invokation. The exception is commands which process their
1189 ** arguments, call this to confirm that there are no extraneous flags,
1190 ** then modify the arguments list for forwarding to another
1191 ** (sub)command (which itself will call this to confirm its own
1192 ** arguments).
1193 */
@@ -1395,11 +1403,11 @@
1395 style_finish_page();
1396 }
1397
1398
1399 /*
1400 ** Set the g.zBaseURL value to the full URL for the toplevel of
1401 ** the fossil tree. Set g.zTop to g.zBaseURL without the
1402 ** leading "http://" and the host and port.
1403 **
1404 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1405 ** environment variables. However, if zAltBase is not NULL then it
@@ -2869,11 +2877,11 @@
2869 ** then the server redirects (HTTP code 302) to the URL of --notfound.
2870 ** When REPOSITORY is a directory, the pathname must contain only
2871 ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
2872 ** and every "." must be surrounded on both sides by alphanumerics or else
2873 ** a 404 error is returned. Static content files in the directory are
2874 ** returned if they match comma-separate GLOB pattern specified by --files
2875 ** and do not match "*.fossil*" and have a well-known suffix.
2876 **
2877 ** Options:
2878 ** --acme Deliver files from the ".well-known" subdirectory
2879 ** --baseurl URL Base URL (useful with reverse proxies)
@@ -2881,11 +2889,11 @@
2881 ** fullchain.pem) taken from FILE.
2882 ** --chroot DIR Use directory for chroot instead of repository path.
2883 ** --ckout-alias N Treat URIs of the form /doc/N/... as if they were
2884 ** /doc/ckout/...
2885 ** --extroot DIR Document root for the /ext extension mechanism
2886 ** --files GLOB Comma-separate glob patterns for static file to serve
2887 ** --host NAME DNS Hostname of the server
2888 ** --https The HTTP request originated from https but has already
2889 ** been decoded by a reverse proxy. Hence, URLs created
2890 ** by Fossil should use "https:" rather than "http:".
2891 ** --in FILE Take input from FILE instead of standard input
@@ -3102,11 +3110,11 @@
3102 ** using this command interactively over SSH. A better solution would be
3103 ** to use a different command for "ssh" sync, but we cannot do that without
3104 ** breaking legacy.
3105 **
3106 ** Options:
3107 ** --csrf-safe N Set cgi_csrf_safe() to to return N
3108 ** --nobody Pretend to be user "nobody"
3109 ** --ssh-sim Pretend to be over an SSH connection
3110 ** --test Do not do special "sync" processing when operating
3111 ** over an SSH link
3112 ** --th-trace Trace TH1 execution (for debugging purposes)
3113
--- src/main.c
+++ src/main.c
@@ -63,11 +63,11 @@
63 #ifdef HAVE_BACKTRACE
64 # include <execinfo.h>
65 #endif
66
67 /*
68 ** Default length of a timeout for serving an HTTP request. Changeable
69 ** using the "--timeout N" command-line option or via "timeout: N" in the
70 ** CGI script.
71 */
72 #ifndef FOSSIL_DEFAULT_TIMEOUT
73 # define FOSSIL_DEFAULT_TIMEOUT 600 /* 10 minutes */
@@ -153,10 +153,11 @@
153 char *nameOfExe; /* Full path of executable. */
154 const char *zErrlog; /* Log errors to this file, if not NULL */
155 const char *zPhase; /* Phase of operation, for use by the error log
156 ** and for deriving $canonical_page TH1 variable */
157 int isConst; /* True if the output is unchanging & cacheable */
158 int iResultCode; /* Process reply code for commands */
159 const char *zVfsName; /* The VFS to use for database connections */
160 sqlite3 *db; /* The connection to the databases */
161 sqlite3 *dbConfig; /* Separate connection for global_config table */
162 char *zAuxSchema; /* Main repository aux-schema */
163 int dbIgnoreErrors; /* Ignore database errors if true */
@@ -236,10 +237,17 @@
237 * applicable when using SEE on Windows or Linux. */
238 #endif
239 int useLocalauth; /* No login required if from 127.0.0.1 */
240 int noPswd; /* Logged in without password (on 127.0.0.1) */
241 int userUid; /* Integer user id */
242 int eAuthMethod; /* How the user authenticated to us */
243 # define AUTH_NONE 0 /* Not authenticated */
244 # define AUTH_COOKIE 1 /* Authentication by cookie */
245 # define AUTH_LOCAL 2 /* Uses loopback */
246 # define AUTH_PW 3 /* Authentication by password */
247 # define AUTH_ENV 4 /* Authenticated by REMOTE_USER environment var */
248 # define AUTH_HTTP 5 /* HTTP Basic Authentication */
249 int isRobot; /* True if the client is definitely a robot. False
250 ** negatives are common for this flag */
251 int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
252 ** accessed through get_comment_format(). */
253 const char *zSockName; /* Name of the unix-domain socket file */
@@ -823,11 +831,11 @@
831 fossil_exit(1);
832 }else{
833 const char *zChdir = find_option("chdir",0,1);
834 g.isHTTP = 0;
835 g.rcvid = 0;
836 g.fQuiet = find_option("quiet", "q", 0)!=0;
837 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
838 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
839 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
840 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
841 g.fCgiTrace = find_option("cgitrace", 0, 0)!=0;
@@ -1009,11 +1017,11 @@
1017 if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
1018 Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags);
1019 }
1020 }
1021 #endif
1022 fossil_exit(g.iResultCode);
1023 /*NOT_REACHED*/
1024 return 0;
1025 }
1026
1027 /*
@@ -1183,11 +1191,11 @@
1191 ** list and this function immediately returns. The effect is to treat
1192 ** all arguments after "--" as non-flags (conventionally used to
1193 ** enable passing-in of filenames which start with a dash).
1194 **
1195 ** This function must normally only be called one time per app
1196 ** invocation. The exception is commands which process their
1197 ** arguments, call this to confirm that there are no extraneous flags,
1198 ** then modify the arguments list for forwarding to another
1199 ** (sub)command (which itself will call this to confirm its own
1200 ** arguments).
1201 */
@@ -1395,11 +1403,11 @@
1403 style_finish_page();
1404 }
1405
1406
1407 /*
1408 ** Set the g.zBaseURL value to the full URL for the top level of
1409 ** the fossil tree. Set g.zTop to g.zBaseURL without the
1410 ** leading "http://" and the host and port.
1411 **
1412 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1413 ** environment variables. However, if zAltBase is not NULL then it
@@ -2869,11 +2877,11 @@
2877 ** then the server redirects (HTTP code 302) to the URL of --notfound.
2878 ** When REPOSITORY is a directory, the pathname must contain only
2879 ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
2880 ** and every "." must be surrounded on both sides by alphanumerics or else
2881 ** a 404 error is returned. Static content files in the directory are
2882 ** returned if they match comma-separated GLOB pattern specified by --files
2883 ** and do not match "*.fossil*" and have a well-known suffix.
2884 **
2885 ** Options:
2886 ** --acme Deliver files from the ".well-known" subdirectory
2887 ** --baseurl URL Base URL (useful with reverse proxies)
@@ -2881,11 +2889,11 @@
2889 ** fullchain.pem) taken from FILE.
2890 ** --chroot DIR Use directory for chroot instead of repository path.
2891 ** --ckout-alias N Treat URIs of the form /doc/N/... as if they were
2892 ** /doc/ckout/...
2893 ** --extroot DIR Document root for the /ext extension mechanism
2894 ** --files GLOB Comma-separated glob patterns for static files to serve
2895 ** --host NAME DNS Hostname of the server
2896 ** --https The HTTP request originated from https but has already
2897 ** been decoded by a reverse proxy. Hence, URLs created
2898 ** by Fossil should use "https:" rather than "http:".
2899 ** --in FILE Take input from FILE instead of standard input
@@ -3102,11 +3110,11 @@
3110 ** using this command interactively over SSH. A better solution would be
3111 ** to use a different command for "ssh" sync, but we cannot do that without
3112 ** breaking legacy.
3113 **
3114 ** Options:
3115 ** --csrf-safe N Set cgi_csrf_safe() to return N
3116 ** --nobody Pretend to be user "nobody"
3117 ** --ssh-sim Pretend to be over an SSH connection
3118 ** --test Do not do special "sync" processing when operating
3119 ** over an SSH link
3120 ** --th-trace Trace TH1 execution (for debugging purposes)
3121
+3 -4
--- src/manifest.c
+++ src/manifest.c
@@ -946,12 +946,11 @@
946946
** T (+|*|-)<tagname> <uuid> ?<value>?
947947
**
948948
** Create or cancel a tag or property. The tagname is fossil-encoded.
949949
** The first character of the name must be either "+" to create a
950950
** singleton tag, "*" to create a propagating tag, or "-" to create
951
- ** anti-tag that undoes a prior "+" or blocks propagation of of
952
- ** a "*".
951
+ ** anti-tag that undoes a prior "+" or blocks propagation of a "*".
953952
**
954953
** The tag is applied to <uuid>. If <uuid> is "*" then the tag is
955954
** applied to the current manifest. If <value> is provided then
956955
** the tag is really a property with the given value.
957956
**
@@ -2994,11 +2993,11 @@
29942993
KVP_STR(1, uuid, pF->zUuid);
29952994
KVP_STR(1, perm, pF->zPerm);
29962995
KVP_STR(1, rename, pF->zPrior);
29972996
blob_append_char(b, '}');
29982997
}
2999
- /* Special case: model checkins with no F-card as having an empty
2998
+ /* Special case: model check-ins with no F-card as having an empty
30002999
** array, rather than no F-cards, to hypothetically simplify
30013000
** handling in JSON queries. */
30023001
blob_append_char(b, ']');
30033002
}
30043003
CARD_STR2(G, p->zThreadRoot);
@@ -3038,11 +3037,11 @@
30383037
blob_append_char(b, '[');
30393038
for( i = 0; i < p->nParent; ++i ){
30403039
if( i>0 ) blob_append_char(b, ',');
30413040
blob_appendf(b, "%!j", p->azParent[i]);
30423041
}
3043
- /* Special case: model checkins with no P-card as having an empty
3042
+ /* Special case: model check-ins with no P-card as having an empty
30443043
** array, as per F-cards. */
30453044
blob_append_char(b, ']');
30463045
}
30473046
if( p->nCherrypick ){
30483047
CARD_LETTER(Q);
30493048
--- src/manifest.c
+++ src/manifest.c
@@ -946,12 +946,11 @@
946 ** T (+|*|-)<tagname> <uuid> ?<value>?
947 **
948 ** Create or cancel a tag or property. The tagname is fossil-encoded.
949 ** The first character of the name must be either "+" to create a
950 ** singleton tag, "*" to create a propagating tag, or "-" to create
951 ** anti-tag that undoes a prior "+" or blocks propagation of of
952 ** a "*".
953 **
954 ** The tag is applied to <uuid>. If <uuid> is "*" then the tag is
955 ** applied to the current manifest. If <value> is provided then
956 ** the tag is really a property with the given value.
957 **
@@ -2994,11 +2993,11 @@
2994 KVP_STR(1, uuid, pF->zUuid);
2995 KVP_STR(1, perm, pF->zPerm);
2996 KVP_STR(1, rename, pF->zPrior);
2997 blob_append_char(b, '}');
2998 }
2999 /* Special case: model checkins with no F-card as having an empty
3000 ** array, rather than no F-cards, to hypothetically simplify
3001 ** handling in JSON queries. */
3002 blob_append_char(b, ']');
3003 }
3004 CARD_STR2(G, p->zThreadRoot);
@@ -3038,11 +3037,11 @@
3038 blob_append_char(b, '[');
3039 for( i = 0; i < p->nParent; ++i ){
3040 if( i>0 ) blob_append_char(b, ',');
3041 blob_appendf(b, "%!j", p->azParent[i]);
3042 }
3043 /* Special case: model checkins with no P-card as having an empty
3044 ** array, as per F-cards. */
3045 blob_append_char(b, ']');
3046 }
3047 if( p->nCherrypick ){
3048 CARD_LETTER(Q);
3049
--- src/manifest.c
+++ src/manifest.c
@@ -946,12 +946,11 @@
946 ** T (+|*|-)<tagname> <uuid> ?<value>?
947 **
948 ** Create or cancel a tag or property. The tagname is fossil-encoded.
949 ** The first character of the name must be either "+" to create a
950 ** singleton tag, "*" to create a propagating tag, or "-" to create
951 ** anti-tag that undoes a prior "+" or blocks propagation of a "*".
 
952 **
953 ** The tag is applied to <uuid>. If <uuid> is "*" then the tag is
954 ** applied to the current manifest. If <value> is provided then
955 ** the tag is really a property with the given value.
956 **
@@ -2994,11 +2993,11 @@
2993 KVP_STR(1, uuid, pF->zUuid);
2994 KVP_STR(1, perm, pF->zPerm);
2995 KVP_STR(1, rename, pF->zPrior);
2996 blob_append_char(b, '}');
2997 }
2998 /* Special case: model check-ins with no F-card as having an empty
2999 ** array, rather than no F-cards, to hypothetically simplify
3000 ** handling in JSON queries. */
3001 blob_append_char(b, ']');
3002 }
3003 CARD_STR2(G, p->zThreadRoot);
@@ -3038,11 +3037,11 @@
3037 blob_append_char(b, '[');
3038 for( i = 0; i < p->nParent; ++i ){
3039 if( i>0 ) blob_append_char(b, ',');
3040 blob_appendf(b, "%!j", p->azParent[i]);
3041 }
3042 /* Special case: model check-ins with no P-card as having an empty
3043 ** array, as per F-cards. */
3044 blob_append_char(b, ']');
3045 }
3046 if( p->nCherrypick ){
3047 CARD_LETTER(Q);
3048
+4 -4
--- src/markdown.c
+++ src/markdown.c
@@ -530,12 +530,12 @@
530530
}
531531
}
532532
533533
/*
534534
** data[*pI] should be a "`" character that introduces a code-span.
535
-** The code-span boundry mark can be any number of one or more "`"
536
-** characters. We do not know the size of the boundry marker, only
535
+** The code-span boundary mark can be any number of one or more "`"
536
+** characters. We do not know the size of the boundary marker, only
537537
** that there is at least one "`" at data[*pI].
538538
**
539539
** This routine increases *pI to move it past the code-span, including
540540
** the closing boundary mark. Or, if the code-span is unterminated,
541541
** this routine moves *pI past the opening boundary mark only.
@@ -634,11 +634,11 @@
634634
** punct alnum (*x yes no
635635
** alnum space a* no yes
636636
** alnum punct a*( no yes
637637
** alnum alnum a*x yes yes
638638
**
639
-** The following routines determine whether a delimitor is left
639
+** The following routines determine whether a delimiter is left
640640
** or right flanking.
641641
*/
642642
static int left_flanking(char before, char after){
643643
if( fossil_isspace(after) ) return 0;
644644
if( fossil_isalnum(after) ) return 1;
@@ -2533,11 +2533,11 @@
25332533
25342534
/* failfast if data is too short */
25352535
if( beg+5>=end ) return 0;
25362536
i = beg;
25372537
2538
- /* footnote definition must start at the begining of a line */
2538
+ /* footnote definition must start at the beginning of a line */
25392539
if( data[i]!='[' ) return 0;
25402540
i++;
25412541
if( data[i]!='^' ) return 0;
25422542
id_offset = ++i;
25432543
25442544
--- src/markdown.c
+++ src/markdown.c
@@ -530,12 +530,12 @@
530 }
531 }
532
533 /*
534 ** data[*pI] should be a "`" character that introduces a code-span.
535 ** The code-span boundry mark can be any number of one or more "`"
536 ** characters. We do not know the size of the boundry marker, only
537 ** that there is at least one "`" at data[*pI].
538 **
539 ** This routine increases *pI to move it past the code-span, including
540 ** the closing boundary mark. Or, if the code-span is unterminated,
541 ** this routine moves *pI past the opening boundary mark only.
@@ -634,11 +634,11 @@
634 ** punct alnum (*x yes no
635 ** alnum space a* no yes
636 ** alnum punct a*( no yes
637 ** alnum alnum a*x yes yes
638 **
639 ** The following routines determine whether a delimitor is left
640 ** or right flanking.
641 */
642 static int left_flanking(char before, char after){
643 if( fossil_isspace(after) ) return 0;
644 if( fossil_isalnum(after) ) return 1;
@@ -2533,11 +2533,11 @@
2533
2534 /* failfast if data is too short */
2535 if( beg+5>=end ) return 0;
2536 i = beg;
2537
2538 /* footnote definition must start at the begining of a line */
2539 if( data[i]!='[' ) return 0;
2540 i++;
2541 if( data[i]!='^' ) return 0;
2542 id_offset = ++i;
2543
2544
--- src/markdown.c
+++ src/markdown.c
@@ -530,12 +530,12 @@
530 }
531 }
532
533 /*
534 ** data[*pI] should be a "`" character that introduces a code-span.
535 ** The code-span boundary mark can be any number of one or more "`"
536 ** characters. We do not know the size of the boundary marker, only
537 ** that there is at least one "`" at data[*pI].
538 **
539 ** This routine increases *pI to move it past the code-span, including
540 ** the closing boundary mark. Or, if the code-span is unterminated,
541 ** this routine moves *pI past the opening boundary mark only.
@@ -634,11 +634,11 @@
634 ** punct alnum (*x yes no
635 ** alnum space a* no yes
636 ** alnum punct a*( no yes
637 ** alnum alnum a*x yes yes
638 **
639 ** The following routines determine whether a delimiter is left
640 ** or right flanking.
641 */
642 static int left_flanking(char before, char after){
643 if( fossil_isspace(after) ) return 0;
644 if( fossil_isalnum(after) ) return 1;
@@ -2533,11 +2533,11 @@
2533
2534 /* failfast if data is too short */
2535 if( beg+5>=end ) return 0;
2536 i = beg;
2537
2538 /* footnote definition must start at the beginning of a line */
2539 if( data[i]!='[' ) return 0;
2540 i++;
2541 if( data[i]!='^' ) return 0;
2542 id_offset = ++i;
2543
2544
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -216,20 +216,61 @@
216216
struct Blob *text,
217217
int level,
218218
void *opaque
219219
){
220220
struct Blob *title = ((MarkdownToHtml*)opaque)->output_title;
221
+ char *z = 0;
222
+ int i,j;
221223
/* The first header at the beginning of a text is considered as
222224
* a title and not output. */
223225
if( blob_size(ob)<=PROLOG_SIZE && title!=0 && blob_size(title)==0 ){
224226
blob_appendb(title, text);
225227
return;
226228
}
227229
INTER_BLOCK(ob);
228
- blob_appendf(ob, "<h%d>", level);
230
+ z = fossil_strdup(blob_buffer(text));
231
+ if( z==0 ){
232
+ j = 0;
233
+ }else{
234
+ /*
235
+ ** The GitHub "slugify" algorithm converts the text of a markdown header
236
+ ** into a ID for that header. The algorithm is:
237
+ **
238
+ ** 1. ASCII alphanumerics -> convert to lower case
239
+ ** 2. Spaces, hyphens, underscores -> convert to '-'
240
+ ** 3. Non-ASCII -> preserve as-is
241
+ ** 4. Other punctuation -> remove
242
+ ** 5. Multiple consecutive dashes -> collapse to one
243
+ ** 6. Leading and trailing dashes -> remove
244
+ ** 7. Markup <...> and &...; -> remove
245
+ **
246
+ ** This implementation does the conversion in-place.
247
+ */
248
+ for(i=j=0; z[i]; i++){
249
+ if( fossil_isalnum(z[i]) ){
250
+ z[j++] = fossil_tolower(z[i]);
251
+ }else if( fossil_isspace(z[i]) || z[i]=='-' || z[i]=='_' ){
252
+ if( j>0 && z[j-1]!='-' ) z[j++] = '-';
253
+ }else if( z[i]=='<' ){
254
+ do{ i++; }while( z[i]!=0 && z[i]!='>' );
255
+ }else if( z[i]=='&' ){
256
+ do{ i++; }while( z[i]!=0 && z[i]!=';' );
257
+ }else if( (z[i]&0x80)!=0 ){
258
+ z[j++] = z[i];
259
+ }
260
+ }
261
+ if( j>0 && z[j-1]=='-' ) j--;
262
+ z[j] = 0;
263
+ }
264
+ if( j>0 ){
265
+ blob_appendf(ob, "<h%d id=\"%s\">", level, z);
266
+ }else{
267
+ blob_appendf(ob, "<h%d>", level);
268
+ }
229269
blob_appendb(ob, text);
230270
blob_appendf(ob, "</h%d>", level);
271
+ fossil_free(z);
231272
}
232273
233274
static void html_hrule(struct Blob *ob, void *opaque){
234275
INTER_BLOCK(ob);
235276
blob_append_literal(ob, "<hr>\n");
236277
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -216,20 +216,61 @@
216 struct Blob *text,
217 int level,
218 void *opaque
219 ){
220 struct Blob *title = ((MarkdownToHtml*)opaque)->output_title;
 
 
221 /* The first header at the beginning of a text is considered as
222 * a title and not output. */
223 if( blob_size(ob)<=PROLOG_SIZE && title!=0 && blob_size(title)==0 ){
224 blob_appendb(title, text);
225 return;
226 }
227 INTER_BLOCK(ob);
228 blob_appendf(ob, "<h%d>", level);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229 blob_appendb(ob, text);
230 blob_appendf(ob, "</h%d>", level);
 
231 }
232
233 static void html_hrule(struct Blob *ob, void *opaque){
234 INTER_BLOCK(ob);
235 blob_append_literal(ob, "<hr>\n");
236
--- src/markdown_html.c
+++ src/markdown_html.c
@@ -216,20 +216,61 @@
216 struct Blob *text,
217 int level,
218 void *opaque
219 ){
220 struct Blob *title = ((MarkdownToHtml*)opaque)->output_title;
221 char *z = 0;
222 int i,j;
223 /* The first header at the beginning of a text is considered as
224 * a title and not output. */
225 if( blob_size(ob)<=PROLOG_SIZE && title!=0 && blob_size(title)==0 ){
226 blob_appendb(title, text);
227 return;
228 }
229 INTER_BLOCK(ob);
230 z = fossil_strdup(blob_buffer(text));
231 if( z==0 ){
232 j = 0;
233 }else{
234 /*
235 ** The GitHub "slugify" algorithm converts the text of a markdown header
236 ** into a ID for that header. The algorithm is:
237 **
238 ** 1. ASCII alphanumerics -> convert to lower case
239 ** 2. Spaces, hyphens, underscores -> convert to '-'
240 ** 3. Non-ASCII -> preserve as-is
241 ** 4. Other punctuation -> remove
242 ** 5. Multiple consecutive dashes -> collapse to one
243 ** 6. Leading and trailing dashes -> remove
244 ** 7. Markup <...> and &...; -> remove
245 **
246 ** This implementation does the conversion in-place.
247 */
248 for(i=j=0; z[i]; i++){
249 if( fossil_isalnum(z[i]) ){
250 z[j++] = fossil_tolower(z[i]);
251 }else if( fossil_isspace(z[i]) || z[i]=='-' || z[i]=='_' ){
252 if( j>0 && z[j-1]!='-' ) z[j++] = '-';
253 }else if( z[i]=='<' ){
254 do{ i++; }while( z[i]!=0 && z[i]!='>' );
255 }else if( z[i]=='&' ){
256 do{ i++; }while( z[i]!=0 && z[i]!=';' );
257 }else if( (z[i]&0x80)!=0 ){
258 z[j++] = z[i];
259 }
260 }
261 if( j>0 && z[j-1]=='-' ) j--;
262 z[j] = 0;
263 }
264 if( j>0 ){
265 blob_appendf(ob, "<h%d id=\"%s\">", level, z);
266 }else{
267 blob_appendf(ob, "<h%d>", level);
268 }
269 blob_appendb(ob, text);
270 blob_appendf(ob, "</h%d>", level);
271 fossil_free(z);
272 }
273
274 static void html_hrule(struct Blob *ob, void *opaque){
275 INTER_BLOCK(ob);
276 blob_append_literal(ob, "<hr>\n");
277
+1 -1
--- src/match.c
+++ src/match.c
@@ -265,11 +265,11 @@
265265
** checks for integer match against the tag ID which is looked up directly by
266266
** this function. For the other modes, the returned SQL expression performs
267267
** string comparisons against the tag names, so it is necessary to join against
268268
** the tag table to access the "tagname" column.
269269
**
270
-** Each pattern is adjusted to to start with "sym-" and be anchored at end.
270
+** Each pattern is adjusted to start with "sym-" and be anchored at end.
271271
**
272272
** In MS_REGEXP mode, backslash can be used to protect delimiter characters.
273273
** The backslashes are not removed from the regular expression.
274274
**
275275
** In addition to assembling and returning an SQL expression, this function
276276
--- src/match.c
+++ src/match.c
@@ -265,11 +265,11 @@
265 ** checks for integer match against the tag ID which is looked up directly by
266 ** this function. For the other modes, the returned SQL expression performs
267 ** string comparisons against the tag names, so it is necessary to join against
268 ** the tag table to access the "tagname" column.
269 **
270 ** Each pattern is adjusted to to start with "sym-" and be anchored at end.
271 **
272 ** In MS_REGEXP mode, backslash can be used to protect delimiter characters.
273 ** The backslashes are not removed from the regular expression.
274 **
275 ** In addition to assembling and returning an SQL expression, this function
276
--- src/match.c
+++ src/match.c
@@ -265,11 +265,11 @@
265 ** checks for integer match against the tag ID which is looked up directly by
266 ** this function. For the other modes, the returned SQL expression performs
267 ** string comparisons against the tag names, so it is necessary to join against
268 ** the tag table to access the "tagname" column.
269 **
270 ** Each pattern is adjusted to start with "sym-" and be anchored at end.
271 **
272 ** In MS_REGEXP mode, backslash can be used to protect delimiter characters.
273 ** The backslashes are not removed from the regular expression.
274 **
275 ** In addition to assembling and returning an SQL expression, this function
276
+3 -3
--- src/merge.c
+++ src/merge.c
@@ -794,11 +794,11 @@
794794
char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
795795
const char *zVersion; /* The VERSION argument */
796796
int bMultiMerge = 0; /* True if there are two or more VERSION arguments */
797797
int nMerge = 0; /* Number of prior merges processed */
798798
int useUndo = 1; /* True to record changes in the undo log */
799
- Stmt q; /* SQL statment used for merge processing */
799
+ Stmt q; /* SQL statement used for merge processing */
800800
801801
802802
/* Notation:
803803
**
804804
** V The current check-out
@@ -1044,11 +1044,11 @@
10441044
}
10451045
if( showVfileFlag ) debug_show_vfile();
10461046
10471047
/*
10481048
** The vfile.pathname field is used to match files against each other. The
1049
- ** FV table contains one row for each each unique filename in
1049
+ ** FV table contains one row for each unique filename in
10501050
** in the current check-out, the pivot, and the version being merged.
10511051
*/
10521052
db_multi_exec(
10531053
"DROP TABLE IF EXISTS fv;"
10541054
"CREATE TEMP TABLE fv(\n"
@@ -1564,11 +1564,11 @@
15641564
zFullName = mprintf("%s%s", g.zLocalRoot, zName);
15651565
if( file_isfile_or_link(zFullName)
15661566
&& !db_exists("SELECT 1 FROM fv WHERE fn=%Q", zName) ){
15671567
/* Name of backup file with Original content */
15681568
char *zOrig = file_newname(zFullName, "original", 1);
1569
- /* Backup previously unanaged file before to be overwritten */
1569
+ /* Backup previously unmanaged file before being overwritten */
15701570
file_copy(zFullName, zOrig);
15711571
fossil_free(zOrig);
15721572
fossil_print("ADDED %s (overwrites an unmanaged file)", zName);
15731573
if( !dryRunFlag ) fossil_print(", original copy backed up locally");
15741574
fossil_print("\n");
15751575
--- src/merge.c
+++ src/merge.c
@@ -794,11 +794,11 @@
794 char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
795 const char *zVersion; /* The VERSION argument */
796 int bMultiMerge = 0; /* True if there are two or more VERSION arguments */
797 int nMerge = 0; /* Number of prior merges processed */
798 int useUndo = 1; /* True to record changes in the undo log */
799 Stmt q; /* SQL statment used for merge processing */
800
801
802 /* Notation:
803 **
804 ** V The current check-out
@@ -1044,11 +1044,11 @@
1044 }
1045 if( showVfileFlag ) debug_show_vfile();
1046
1047 /*
1048 ** The vfile.pathname field is used to match files against each other. The
1049 ** FV table contains one row for each each unique filename in
1050 ** in the current check-out, the pivot, and the version being merged.
1051 */
1052 db_multi_exec(
1053 "DROP TABLE IF EXISTS fv;"
1054 "CREATE TEMP TABLE fv(\n"
@@ -1564,11 +1564,11 @@
1564 zFullName = mprintf("%s%s", g.zLocalRoot, zName);
1565 if( file_isfile_or_link(zFullName)
1566 && !db_exists("SELECT 1 FROM fv WHERE fn=%Q", zName) ){
1567 /* Name of backup file with Original content */
1568 char *zOrig = file_newname(zFullName, "original", 1);
1569 /* Backup previously unanaged file before to be overwritten */
1570 file_copy(zFullName, zOrig);
1571 fossil_free(zOrig);
1572 fossil_print("ADDED %s (overwrites an unmanaged file)", zName);
1573 if( !dryRunFlag ) fossil_print(", original copy backed up locally");
1574 fossil_print("\n");
1575
--- src/merge.c
+++ src/merge.c
@@ -794,11 +794,11 @@
794 char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
795 const char *zVersion; /* The VERSION argument */
796 int bMultiMerge = 0; /* True if there are two or more VERSION arguments */
797 int nMerge = 0; /* Number of prior merges processed */
798 int useUndo = 1; /* True to record changes in the undo log */
799 Stmt q; /* SQL statement used for merge processing */
800
801
802 /* Notation:
803 **
804 ** V The current check-out
@@ -1044,11 +1044,11 @@
1044 }
1045 if( showVfileFlag ) debug_show_vfile();
1046
1047 /*
1048 ** The vfile.pathname field is used to match files against each other. The
1049 ** FV table contains one row for each unique filename in
1050 ** in the current check-out, the pivot, and the version being merged.
1051 */
1052 db_multi_exec(
1053 "DROP TABLE IF EXISTS fv;"
1054 "CREATE TEMP TABLE fv(\n"
@@ -1564,11 +1564,11 @@
1564 zFullName = mprintf("%s%s", g.zLocalRoot, zName);
1565 if( file_isfile_or_link(zFullName)
1566 && !db_exists("SELECT 1 FROM fv WHERE fn=%Q", zName) ){
1567 /* Name of backup file with Original content */
1568 char *zOrig = file_newname(zFullName, "original", 1);
1569 /* Backup previously unmanaged file before being overwritten */
1570 file_copy(zFullName, zOrig);
1571 fossil_free(zOrig);
1572 fossil_print("ADDED %s (overwrites an unmanaged file)", zName);
1573 if( !dryRunFlag ) fossil_print(", original copy backed up locally");
1574 fossil_print("\n");
1575
+2 -2
--- src/merge3.c
+++ src/merge3.c
@@ -175,11 +175,11 @@
175175
/* These are generic methods for MergeBuilder. They just output debugging
176176
** information. But some of them are useful as base methods for other useful
177177
** implementations of MergeBuilder.
178178
*/
179179
180
-/* xStart() and xEnd() are called to generate header and fotter information
180
+/* xStart() and xEnd() are called to generate header and footer information
181181
** in the output. This is a no-op in the generic implementation.
182182
*/
183183
static void dbgStartEnd(MergeBuilder *p){ (void)p; }
184184
185185
/* The next N lines of PIVOT are unchanged in both V1 and V2
@@ -716,11 +716,11 @@
716716
*/
717717
static int skip_conflict(
718718
int *aC, /* Array of integer triples describing the edit */
719719
int i, /* Index in aC[] of current location */
720720
int sz, /* Lines of A that have been skipped */
721
- unsigned int *pLn /* OUT: Lines of B to skip to keep aligment with A */
721
+ unsigned int *pLn /* OUT: Lines of B to skip to keep alignment with A */
722722
){
723723
*pLn = 0;
724724
while( sz>0 ){
725725
if( aC[i]==0 && aC[i+1]==0 && aC[i+2]==0 ) break;
726726
if( aC[i]>=sz ){
727727
--- src/merge3.c
+++ src/merge3.c
@@ -175,11 +175,11 @@
175 /* These are generic methods for MergeBuilder. They just output debugging
176 ** information. But some of them are useful as base methods for other useful
177 ** implementations of MergeBuilder.
178 */
179
180 /* xStart() and xEnd() are called to generate header and fotter information
181 ** in the output. This is a no-op in the generic implementation.
182 */
183 static void dbgStartEnd(MergeBuilder *p){ (void)p; }
184
185 /* The next N lines of PIVOT are unchanged in both V1 and V2
@@ -716,11 +716,11 @@
716 */
717 static int skip_conflict(
718 int *aC, /* Array of integer triples describing the edit */
719 int i, /* Index in aC[] of current location */
720 int sz, /* Lines of A that have been skipped */
721 unsigned int *pLn /* OUT: Lines of B to skip to keep aligment with A */
722 ){
723 *pLn = 0;
724 while( sz>0 ){
725 if( aC[i]==0 && aC[i+1]==0 && aC[i+2]==0 ) break;
726 if( aC[i]>=sz ){
727
--- src/merge3.c
+++ src/merge3.c
@@ -175,11 +175,11 @@
175 /* These are generic methods for MergeBuilder. They just output debugging
176 ** information. But some of them are useful as base methods for other useful
177 ** implementations of MergeBuilder.
178 */
179
180 /* xStart() and xEnd() are called to generate header and footer information
181 ** in the output. This is a no-op in the generic implementation.
182 */
183 static void dbgStartEnd(MergeBuilder *p){ (void)p; }
184
185 /* The next N lines of PIVOT are unchanged in both V1 and V2
@@ -716,11 +716,11 @@
716 */
717 static int skip_conflict(
718 int *aC, /* Array of integer triples describing the edit */
719 int i, /* Index in aC[] of current location */
720 int sz, /* Lines of A that have been skipped */
721 unsigned int *pLn /* OUT: Lines of B to skip to keep alignment with A */
722 ){
723 *pLn = 0;
724 while( sz>0 ){
725 if( aC[i]==0 && aC[i+1]==0 && aC[i+2]==0 ) break;
726 if( aC[i]>=sz ){
727
+17 -5
--- src/name.c
+++ src/name.c
@@ -1131,10 +1131,11 @@
11311131
#if INTERFACE
11321132
#define WHATIS_VERBOSE 0x01 /* Extra output */
11331133
#define WHATIS_BRIEF 0x02 /* Omit unnecessary output */
11341134
#define WHATIS_REPO 0x04 /* Show repository name */
11351135
#define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */
1136
+#define WHATIS_HASHONLY 0x10 /* Show only the hash */
11361137
#endif
11371138
11381139
/*
11391140
** Generate a description of artifact "rid"
11401141
*/
@@ -1148,11 +1149,13 @@
11481149
" FROM blob, rcvfrom"
11491150
" WHERE rid=%d"
11501151
" AND rcvfrom.rcvid=blob.rcvid",
11511152
rid);
11521153
if( db_step(&q)==SQLITE_ROW ){
1153
- if( flags & WHATIS_VERBOSE ){
1154
+ if( flags & WHATIS_HASHONLY ){
1155
+ fossil_print("%s\n", db_column_text(&q,0));
1156
+ }else if( flags & WHATIS_VERBOSE ){
11541157
fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
11551158
fossil_print("size: %d bytes\n", db_column_int(&q,1));
11561159
fossil_print("received: %s from %s\n",
11571160
db_column_text(&q, 2),
11581161
db_column_text(&q, 3));
@@ -1160,10 +1163,11 @@
11601163
fossil_print("artifact: %s\n", db_column_text(&q,0));
11611164
fossil_print("size: %d bytes\n", db_column_int(&q,1));
11621165
}
11631166
}
11641167
db_finalize(&q);
1168
+ if( flags & WHATIS_HASHONLY ) return;
11651169
11661170
/* Report any symbolic tags on this artifact */
11671171
db_prepare(&q,
11681172
"SELECT substr(tagname,5)"
11691173
" FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
@@ -1330,11 +1334,11 @@
13301334
if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
13311335
whatis_rid(db_column_int(&q, 0), mFlags);
13321336
}
13331337
db_finalize(&q);
13341338
}else if( rid==0 ){
1335
- if( (mFlags & WHATIS_OMIT_UNK)==0 ){
1339
+ if( (mFlags & (WHATIS_OMIT_UNK|WHATIS_HASHONLY))==0 ){
13361340
/* 0123456789 12 */
13371341
if( zFileName ){
13381342
fossil_print("%-12s%s\n", "name:", zFileName);
13391343
}
13401344
fossil_print("unknown: %s\n", zName);
@@ -1344,11 +1348,13 @@
13441348
fossil_print("\nrepository: %s\n", g.zRepositoryName);
13451349
}
13461350
if( zFileName ){
13471351
zName = zFileName;
13481352
}
1349
- fossil_print("%-12s%s\n", "name:", zName);
1353
+ if( (mFlags & WHATIS_HASHONLY)==0 ){
1354
+ fossil_print("%-12s%s\n", "name:", zName);
1355
+ }
13501356
whatis_rid(rid, mFlags);
13511357
}
13521358
}
13531359
13541360
/*
@@ -1361,11 +1367,14 @@
13611367
** plays.
13621368
**
13631369
** Options:
13641370
** -f|--file Find artifacts with the same hash as file NAME.
13651371
** If NAME is "-", read content from standard input.
1372
+** -h|--hash Show only the hash of matching artifacts.
13661373
** -q|--quiet Show nothing if NAME is not found
1374
+** -R REPO_FILE Specifies the repository db to use. Default is
1375
+** the current check-out's repository.
13671376
** --type TYPE Only find artifacts of TYPE (one of: 'ci', 't',
13681377
** 'w', 'g', or 'e')
13691378
** -v|--verbose Provide extra information (such as the RID)
13701379
*/
13711380
void whatis_cmd(void){
@@ -1375,11 +1384,14 @@
13751384
const char *zType = 0;
13761385
db_find_and_open_repository(0,0);
13771386
if( find_option("verbose","v",0)!=0 ){
13781387
mFlags |= WHATIS_VERBOSE;
13791388
}
1380
- if( find_option("quiet","q",0)!=0 ){
1389
+ if( find_option("hash","h",0)!=0 ){
1390
+ mFlags |= WHATIS_HASHONLY;
1391
+ }
1392
+ if( g.fQuiet ){
13811393
mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO;
13821394
}
13831395
fileFlag = find_option("file","f",0)!=0;
13841396
zType = find_option("type",0,1);
13851397
@@ -2215,11 +2227,11 @@
22152227
** --delta Show all delta-phantoms. A delta-phantom is a
22162228
** artifact for which there is a delta but the delta
22172229
** source is a phantom.
22182230
** --list Just list the phantoms. Do not try to describe them.
22192231
*/
2220
-void test_phatoms_cmd(void){
2232
+void test_phantoms_cmd(void){
22212233
int bDelta;
22222234
int bList;
22232235
int bCount;
22242236
unsigned nPhantom = 0;
22252237
unsigned nDeltaPhantom = 0;
22262238
--- src/name.c
+++ src/name.c
@@ -1131,10 +1131,11 @@
1131 #if INTERFACE
1132 #define WHATIS_VERBOSE 0x01 /* Extra output */
1133 #define WHATIS_BRIEF 0x02 /* Omit unnecessary output */
1134 #define WHATIS_REPO 0x04 /* Show repository name */
1135 #define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */
 
1136 #endif
1137
1138 /*
1139 ** Generate a description of artifact "rid"
1140 */
@@ -1148,11 +1149,13 @@
1148 " FROM blob, rcvfrom"
1149 " WHERE rid=%d"
1150 " AND rcvfrom.rcvid=blob.rcvid",
1151 rid);
1152 if( db_step(&q)==SQLITE_ROW ){
1153 if( flags & WHATIS_VERBOSE ){
 
 
1154 fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
1155 fossil_print("size: %d bytes\n", db_column_int(&q,1));
1156 fossil_print("received: %s from %s\n",
1157 db_column_text(&q, 2),
1158 db_column_text(&q, 3));
@@ -1160,10 +1163,11 @@
1160 fossil_print("artifact: %s\n", db_column_text(&q,0));
1161 fossil_print("size: %d bytes\n", db_column_int(&q,1));
1162 }
1163 }
1164 db_finalize(&q);
 
1165
1166 /* Report any symbolic tags on this artifact */
1167 db_prepare(&q,
1168 "SELECT substr(tagname,5)"
1169 " FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
@@ -1330,11 +1334,11 @@
1330 if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1331 whatis_rid(db_column_int(&q, 0), mFlags);
1332 }
1333 db_finalize(&q);
1334 }else if( rid==0 ){
1335 if( (mFlags & WHATIS_OMIT_UNK)==0 ){
1336 /* 0123456789 12 */
1337 if( zFileName ){
1338 fossil_print("%-12s%s\n", "name:", zFileName);
1339 }
1340 fossil_print("unknown: %s\n", zName);
@@ -1344,11 +1348,13 @@
1344 fossil_print("\nrepository: %s\n", g.zRepositoryName);
1345 }
1346 if( zFileName ){
1347 zName = zFileName;
1348 }
1349 fossil_print("%-12s%s\n", "name:", zName);
 
 
1350 whatis_rid(rid, mFlags);
1351 }
1352 }
1353
1354 /*
@@ -1361,11 +1367,14 @@
1361 ** plays.
1362 **
1363 ** Options:
1364 ** -f|--file Find artifacts with the same hash as file NAME.
1365 ** If NAME is "-", read content from standard input.
 
1366 ** -q|--quiet Show nothing if NAME is not found
 
 
1367 ** --type TYPE Only find artifacts of TYPE (one of: 'ci', 't',
1368 ** 'w', 'g', or 'e')
1369 ** -v|--verbose Provide extra information (such as the RID)
1370 */
1371 void whatis_cmd(void){
@@ -1375,11 +1384,14 @@
1375 const char *zType = 0;
1376 db_find_and_open_repository(0,0);
1377 if( find_option("verbose","v",0)!=0 ){
1378 mFlags |= WHATIS_VERBOSE;
1379 }
1380 if( find_option("quiet","q",0)!=0 ){
 
 
 
1381 mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO;
1382 }
1383 fileFlag = find_option("file","f",0)!=0;
1384 zType = find_option("type",0,1);
1385
@@ -2215,11 +2227,11 @@
2215 ** --delta Show all delta-phantoms. A delta-phantom is a
2216 ** artifact for which there is a delta but the delta
2217 ** source is a phantom.
2218 ** --list Just list the phantoms. Do not try to describe them.
2219 */
2220 void test_phatoms_cmd(void){
2221 int bDelta;
2222 int bList;
2223 int bCount;
2224 unsigned nPhantom = 0;
2225 unsigned nDeltaPhantom = 0;
2226
--- src/name.c
+++ src/name.c
@@ -1131,10 +1131,11 @@
1131 #if INTERFACE
1132 #define WHATIS_VERBOSE 0x01 /* Extra output */
1133 #define WHATIS_BRIEF 0x02 /* Omit unnecessary output */
1134 #define WHATIS_REPO 0x04 /* Show repository name */
1135 #define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */
1136 #define WHATIS_HASHONLY 0x10 /* Show only the hash */
1137 #endif
1138
1139 /*
1140 ** Generate a description of artifact "rid"
1141 */
@@ -1148,11 +1149,13 @@
1149 " FROM blob, rcvfrom"
1150 " WHERE rid=%d"
1151 " AND rcvfrom.rcvid=blob.rcvid",
1152 rid);
1153 if( db_step(&q)==SQLITE_ROW ){
1154 if( flags & WHATIS_HASHONLY ){
1155 fossil_print("%s\n", db_column_text(&q,0));
1156 }else if( flags & WHATIS_VERBOSE ){
1157 fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
1158 fossil_print("size: %d bytes\n", db_column_int(&q,1));
1159 fossil_print("received: %s from %s\n",
1160 db_column_text(&q, 2),
1161 db_column_text(&q, 3));
@@ -1160,10 +1163,11 @@
1163 fossil_print("artifact: %s\n", db_column_text(&q,0));
1164 fossil_print("size: %d bytes\n", db_column_int(&q,1));
1165 }
1166 }
1167 db_finalize(&q);
1168 if( flags & WHATIS_HASHONLY ) return;
1169
1170 /* Report any symbolic tags on this artifact */
1171 db_prepare(&q,
1172 "SELECT substr(tagname,5)"
1173 " FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
@@ -1330,11 +1334,11 @@
1334 if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1335 whatis_rid(db_column_int(&q, 0), mFlags);
1336 }
1337 db_finalize(&q);
1338 }else if( rid==0 ){
1339 if( (mFlags & (WHATIS_OMIT_UNK|WHATIS_HASHONLY))==0 ){
1340 /* 0123456789 12 */
1341 if( zFileName ){
1342 fossil_print("%-12s%s\n", "name:", zFileName);
1343 }
1344 fossil_print("unknown: %s\n", zName);
@@ -1344,11 +1348,13 @@
1348 fossil_print("\nrepository: %s\n", g.zRepositoryName);
1349 }
1350 if( zFileName ){
1351 zName = zFileName;
1352 }
1353 if( (mFlags & WHATIS_HASHONLY)==0 ){
1354 fossil_print("%-12s%s\n", "name:", zName);
1355 }
1356 whatis_rid(rid, mFlags);
1357 }
1358 }
1359
1360 /*
@@ -1361,11 +1367,14 @@
1367 ** plays.
1368 **
1369 ** Options:
1370 ** -f|--file Find artifacts with the same hash as file NAME.
1371 ** If NAME is "-", read content from standard input.
1372 ** -h|--hash Show only the hash of matching artifacts.
1373 ** -q|--quiet Show nothing if NAME is not found
1374 ** -R REPO_FILE Specifies the repository db to use. Default is
1375 ** the current check-out's repository.
1376 ** --type TYPE Only find artifacts of TYPE (one of: 'ci', 't',
1377 ** 'w', 'g', or 'e')
1378 ** -v|--verbose Provide extra information (such as the RID)
1379 */
1380 void whatis_cmd(void){
@@ -1375,11 +1384,14 @@
1384 const char *zType = 0;
1385 db_find_and_open_repository(0,0);
1386 if( find_option("verbose","v",0)!=0 ){
1387 mFlags |= WHATIS_VERBOSE;
1388 }
1389 if( find_option("hash","h",0)!=0 ){
1390 mFlags |= WHATIS_HASHONLY;
1391 }
1392 if( g.fQuiet ){
1393 mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO;
1394 }
1395 fileFlag = find_option("file","f",0)!=0;
1396 zType = find_option("type",0,1);
1397
@@ -2215,11 +2227,11 @@
2227 ** --delta Show all delta-phantoms. A delta-phantom is a
2228 ** artifact for which there is a delta but the delta
2229 ** source is a phantom.
2230 ** --list Just list the phantoms. Do not try to describe them.
2231 */
2232 void test_phantoms_cmd(void){
2233 int bDelta;
2234 int bList;
2235 int bCount;
2236 unsigned nPhantom = 0;
2237 unsigned nDeltaPhantom = 0;
2238
+1 -1
--- src/piechart.c
+++ src/piechart.c
@@ -26,11 +26,11 @@
2626
# define M_PI 3.1415926535897932385
2727
#endif
2828
2929
/*
3030
** Return an RGB color name given HSV values. The HSV values
31
-** must each be between between 0 and 255. The string
31
+** must each be between 0 and 255. The string
3232
** returned is held in a static buffer and is overwritten
3333
** on each call.
3434
*/
3535
const char *rgbName(unsigned char h, unsigned char s, unsigned char v){
3636
static char zColor[8];
3737
--- src/piechart.c
+++ src/piechart.c
@@ -26,11 +26,11 @@
26 # define M_PI 3.1415926535897932385
27 #endif
28
29 /*
30 ** Return an RGB color name given HSV values. The HSV values
31 ** must each be between between 0 and 255. The string
32 ** returned is held in a static buffer and is overwritten
33 ** on each call.
34 */
35 const char *rgbName(unsigned char h, unsigned char s, unsigned char v){
36 static char zColor[8];
37
--- src/piechart.c
+++ src/piechart.c
@@ -26,11 +26,11 @@
26 # define M_PI 3.1415926535897932385
27 #endif
28
29 /*
30 ** Return an RGB color name given HSV values. The HSV values
31 ** must each be between 0 and 255. The string
32 ** returned is held in a static buffer and is overwritten
33 ** on each call.
34 */
35 const char *rgbName(unsigned char h, unsigned char s, unsigned char v){
36 static char zColor[8];
37
+7 -7
--- src/printf.c
+++ src/printf.c
@@ -13,11 +13,11 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** This file contains implementions of routines for formatting output
18
+** This file contains implementations of routines for formatting output
1919
** (ex: mprintf()) and for output to the console.
2020
*/
2121
#include "config.h"
2222
#include "printf.h"
2323
#if defined(_WIN32)
@@ -89,11 +89,11 @@
8989
#define etBLOB 11 /* Blob objects. %b */
9090
#define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
9191
#define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
9292
#define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
9393
NULL pointers replaced by SQL NULL. %Q */
94
-#define etSQLESCAPE3 15 /* Double '"' characters within an indentifier. %w */
94
+#define etSQLESCAPE3 15 /* Double '"' characters within an identifier. %w */
9595
#define etPOINTER 16 /* The %p conversion */
9696
#define etHTMLIZE 17 /* Make text safe for HTML */
9797
#define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
9898
#define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
9999
#define etFOSSILIZE 20 /* The fossil header encoding format. */
@@ -265,12 +265,12 @@
265265
** configuration parameters.
266266
**
267267
** The altForm2 argument is true for "%!W" (with the "!" alternate-form-2
268268
** flags) and is false for plain "%W". The ! flag indicates that the
269269
** formatting is for display of a check-in comment on the timeline. Such
270
-** comments used to be renderedd differently, but ever since 2020, they
271
-** have been rendered identially, so the ! flag does not make any different
270
+** comments used to be rendered differently, but ever since 2020, they
271
+** have been rendered identically, so the ! flag does not make any different
272272
** in the output any more.
273273
*/
274274
int wiki_convert_flags(int altForm2){
275275
static int wikiFlags = 0;
276276
(void)altForm2;
@@ -456,11 +456,11 @@
456456
** flag_leftjustify TRUE if a '-' is present or if the
457457
** field width was negative.
458458
** flag_zeropad TRUE if the width began with 0.
459459
** flag_long TRUE if the letter 'l' (ell) prefixed
460460
** the conversion character.
461
- ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
461
+ ** flag_longlong TRUE if the letters 'll' (ell ell) prefixed
462462
** the conversion character.
463463
** flag_blanksign TRUE if a ' ' is present.
464464
** width The specified field width. This is
465465
** always non-negative. Zero is the default.
466466
** precision The specified precision. The default
@@ -1188,13 +1188,13 @@
11881188
**
11891189
** The main difference between fossil_fatal() and fossil_panic() is that
11901190
** fossil_panic() makes an entry in the error log whereas fossil_fatal()
11911191
** does not. On POSIX platforms, if there is not an error log, then both
11921192
** routines work similarly with respect to user-visible effects. Hence,
1193
-** the routines are interchangable for commands and only act differently
1193
+** the routines are interchangeable for commands and only act differently
11941194
** when processing web pages. On the Windows platform, fossil_panic()
1195
-** also displays a pop-up stating that an error has occured and allowing
1195
+** also displays a pop-up stating that an error has occurred and allowing
11961196
** just-in-time debugging to commence. On all platforms, fossil_panic()
11971197
** ends execution with a SIGABRT signal, bypassing atexit processing.
11981198
** This signal can also produce a core dump on POSIX platforms.
11991199
**
12001200
** Use fossil_fatal() for malformed inputs that should be reported back
12011201
--- src/printf.c
+++ src/printf.c
@@ -13,11 +13,11 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains implementions of routines for formatting output
19 ** (ex: mprintf()) and for output to the console.
20 */
21 #include "config.h"
22 #include "printf.h"
23 #if defined(_WIN32)
@@ -89,11 +89,11 @@
89 #define etBLOB 11 /* Blob objects. %b */
90 #define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
91 #define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
92 #define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
93 NULL pointers replaced by SQL NULL. %Q */
94 #define etSQLESCAPE3 15 /* Double '"' characters within an indentifier. %w */
95 #define etPOINTER 16 /* The %p conversion */
96 #define etHTMLIZE 17 /* Make text safe for HTML */
97 #define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
98 #define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
99 #define etFOSSILIZE 20 /* The fossil header encoding format. */
@@ -265,12 +265,12 @@
265 ** configuration parameters.
266 **
267 ** The altForm2 argument is true for "%!W" (with the "!" alternate-form-2
268 ** flags) and is false for plain "%W". The ! flag indicates that the
269 ** formatting is for display of a check-in comment on the timeline. Such
270 ** comments used to be renderedd differently, but ever since 2020, they
271 ** have been rendered identially, so the ! flag does not make any different
272 ** in the output any more.
273 */
274 int wiki_convert_flags(int altForm2){
275 static int wikiFlags = 0;
276 (void)altForm2;
@@ -456,11 +456,11 @@
456 ** flag_leftjustify TRUE if a '-' is present or if the
457 ** field width was negative.
458 ** flag_zeropad TRUE if the width began with 0.
459 ** flag_long TRUE if the letter 'l' (ell) prefixed
460 ** the conversion character.
461 ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
462 ** the conversion character.
463 ** flag_blanksign TRUE if a ' ' is present.
464 ** width The specified field width. This is
465 ** always non-negative. Zero is the default.
466 ** precision The specified precision. The default
@@ -1188,13 +1188,13 @@
1188 **
1189 ** The main difference between fossil_fatal() and fossil_panic() is that
1190 ** fossil_panic() makes an entry in the error log whereas fossil_fatal()
1191 ** does not. On POSIX platforms, if there is not an error log, then both
1192 ** routines work similarly with respect to user-visible effects. Hence,
1193 ** the routines are interchangable for commands and only act differently
1194 ** when processing web pages. On the Windows platform, fossil_panic()
1195 ** also displays a pop-up stating that an error has occured and allowing
1196 ** just-in-time debugging to commence. On all platforms, fossil_panic()
1197 ** ends execution with a SIGABRT signal, bypassing atexit processing.
1198 ** This signal can also produce a core dump on POSIX platforms.
1199 **
1200 ** Use fossil_fatal() for malformed inputs that should be reported back
1201
--- src/printf.c
+++ src/printf.c
@@ -13,11 +13,11 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains implementations of routines for formatting output
19 ** (ex: mprintf()) and for output to the console.
20 */
21 #include "config.h"
22 #include "printf.h"
23 #if defined(_WIN32)
@@ -89,11 +89,11 @@
89 #define etBLOB 11 /* Blob objects. %b */
90 #define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
91 #define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
92 #define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
93 NULL pointers replaced by SQL NULL. %Q */
94 #define etSQLESCAPE3 15 /* Double '"' characters within an identifier. %w */
95 #define etPOINTER 16 /* The %p conversion */
96 #define etHTMLIZE 17 /* Make text safe for HTML */
97 #define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
98 #define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
99 #define etFOSSILIZE 20 /* The fossil header encoding format. */
@@ -265,12 +265,12 @@
265 ** configuration parameters.
266 **
267 ** The altForm2 argument is true for "%!W" (with the "!" alternate-form-2
268 ** flags) and is false for plain "%W". The ! flag indicates that the
269 ** formatting is for display of a check-in comment on the timeline. Such
270 ** comments used to be rendered differently, but ever since 2020, they
271 ** have been rendered identically, so the ! flag does not make any different
272 ** in the output any more.
273 */
274 int wiki_convert_flags(int altForm2){
275 static int wikiFlags = 0;
276 (void)altForm2;
@@ -456,11 +456,11 @@
456 ** flag_leftjustify TRUE if a '-' is present or if the
457 ** field width was negative.
458 ** flag_zeropad TRUE if the width began with 0.
459 ** flag_long TRUE if the letter 'l' (ell) prefixed
460 ** the conversion character.
461 ** flag_longlong TRUE if the letters 'll' (ell ell) prefixed
462 ** the conversion character.
463 ** flag_blanksign TRUE if a ' ' is present.
464 ** width The specified field width. This is
465 ** always non-negative. Zero is the default.
466 ** precision The specified precision. The default
@@ -1188,13 +1188,13 @@
1188 **
1189 ** The main difference between fossil_fatal() and fossil_panic() is that
1190 ** fossil_panic() makes an entry in the error log whereas fossil_fatal()
1191 ** does not. On POSIX platforms, if there is not an error log, then both
1192 ** routines work similarly with respect to user-visible effects. Hence,
1193 ** the routines are interchangeable for commands and only act differently
1194 ** when processing web pages. On the Windows platform, fossil_panic()
1195 ** also displays a pop-up stating that an error has occurred and allowing
1196 ** just-in-time debugging to commence. On all platforms, fossil_panic()
1197 ** ends execution with a SIGABRT signal, bypassing atexit processing.
1198 ** This signal can also produce a core dump on POSIX platforms.
1199 **
1200 ** Use fossil_fatal() for malformed inputs that should be reported back
1201
+3 -3
--- src/purge.c
+++ src/purge.c
@@ -62,11 +62,11 @@
6262
#define PURGE_EXPLAIN_ONLY 0x0002 /* Show what would have happened */
6363
#define PURGE_PRINT_SUMMARY 0x0004 /* Print a summary report at end */
6464
#endif
6565
6666
/*
67
-** This routine purges multiple artifacts from the repository, transfering
67
+** This routine purges multiple artifacts from the repository, transferring
6868
** those artifacts into the PURGEITEM table.
6969
**
7070
** Prior to invoking this routine, the caller must create a (TEMP) table
7171
** named zTab that contains the RID of every artifact to be purged.
7272
**
@@ -120,11 +120,11 @@
120120
return 0;
121121
}
122122
123123
/* Make sure we are not removing a manifest that is the baseline of some
124124
** manifest that is being left behind. This step is not strictly necessary.
125
- ** is is just a safety check. */
125
+ ** It is just a safety check. */
126126
if( purge_baseline_out_from_under_delta(zTab) ){
127127
fossil_panic("attempt to purge a baseline manifest without also purging "
128128
"all of its deltas");
129129
}
130130
@@ -256,11 +256,11 @@
256256
** When bExclusive is false, then all artifacts used by the check-ins
257257
** are added even if those artifacts are also used by other check-ins
258258
** not in the set.
259259
**
260260
** The "fossil publish" command with the (undocumented) --test and
261
-** --exclusive options can be used for interactiving testing of this
261
+** --exclusive options can be used for interactive testing of this
262262
** function.
263263
*/
264264
void find_checkin_associates(const char *zTab, int bExclusive){
265265
db_begin_transaction();
266266
267267
--- src/purge.c
+++ src/purge.c
@@ -62,11 +62,11 @@
62 #define PURGE_EXPLAIN_ONLY 0x0002 /* Show what would have happened */
63 #define PURGE_PRINT_SUMMARY 0x0004 /* Print a summary report at end */
64 #endif
65
66 /*
67 ** This routine purges multiple artifacts from the repository, transfering
68 ** those artifacts into the PURGEITEM table.
69 **
70 ** Prior to invoking this routine, the caller must create a (TEMP) table
71 ** named zTab that contains the RID of every artifact to be purged.
72 **
@@ -120,11 +120,11 @@
120 return 0;
121 }
122
123 /* Make sure we are not removing a manifest that is the baseline of some
124 ** manifest that is being left behind. This step is not strictly necessary.
125 ** is is just a safety check. */
126 if( purge_baseline_out_from_under_delta(zTab) ){
127 fossil_panic("attempt to purge a baseline manifest without also purging "
128 "all of its deltas");
129 }
130
@@ -256,11 +256,11 @@
256 ** When bExclusive is false, then all artifacts used by the check-ins
257 ** are added even if those artifacts are also used by other check-ins
258 ** not in the set.
259 **
260 ** The "fossil publish" command with the (undocumented) --test and
261 ** --exclusive options can be used for interactiving testing of this
262 ** function.
263 */
264 void find_checkin_associates(const char *zTab, int bExclusive){
265 db_begin_transaction();
266
267
--- src/purge.c
+++ src/purge.c
@@ -62,11 +62,11 @@
62 #define PURGE_EXPLAIN_ONLY 0x0002 /* Show what would have happened */
63 #define PURGE_PRINT_SUMMARY 0x0004 /* Print a summary report at end */
64 #endif
65
66 /*
67 ** This routine purges multiple artifacts from the repository, transferring
68 ** those artifacts into the PURGEITEM table.
69 **
70 ** Prior to invoking this routine, the caller must create a (TEMP) table
71 ** named zTab that contains the RID of every artifact to be purged.
72 **
@@ -120,11 +120,11 @@
120 return 0;
121 }
122
123 /* Make sure we are not removing a manifest that is the baseline of some
124 ** manifest that is being left behind. This step is not strictly necessary.
125 ** It is just a safety check. */
126 if( purge_baseline_out_from_under_delta(zTab) ){
127 fossil_panic("attempt to purge a baseline manifest without also purging "
128 "all of its deltas");
129 }
130
@@ -256,11 +256,11 @@
256 ** When bExclusive is false, then all artifacts used by the check-ins
257 ** are added even if those artifacts are also used by other check-ins
258 ** not in the set.
259 **
260 ** The "fossil publish" command with the (undocumented) --test and
261 ** --exclusive options can be used for interactive testing of this
262 ** function.
263 */
264 void find_checkin_associates(const char *zTab, int bExclusive){
265 db_begin_transaction();
266
267
+1 -1
--- src/regexp.c
+++ src/regexp.c
@@ -993,11 +993,11 @@
993993
994994
995995
if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1;
996996
if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS;
997997
if( find_option("verbose",0,0)!=0 ) bVerbose = 1;
998
- if( find_option("quiet","q",0) ) flags |= GREP_QUIET|GREP_EXISTS;
998
+ if( g.fQuiet ) flags |= GREP_QUIET|GREP_EXISTS;
999999
bNoMsg = find_option("no-messages","s",0)!=0;
10001000
bOnce = find_option("once",0,0)!=0;
10011001
bInvert = find_option("invert-match","v",0)!=0;
10021002
if( bInvert ){
10031003
flags |= GREP_QUIET|GREP_EXISTS;
10041004
--- src/regexp.c
+++ src/regexp.c
@@ -993,11 +993,11 @@
993
994
995 if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1;
996 if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS;
997 if( find_option("verbose",0,0)!=0 ) bVerbose = 1;
998 if( find_option("quiet","q",0) ) flags |= GREP_QUIET|GREP_EXISTS;
999 bNoMsg = find_option("no-messages","s",0)!=0;
1000 bOnce = find_option("once",0,0)!=0;
1001 bInvert = find_option("invert-match","v",0)!=0;
1002 if( bInvert ){
1003 flags |= GREP_QUIET|GREP_EXISTS;
1004
--- src/regexp.c
+++ src/regexp.c
@@ -993,11 +993,11 @@
993
994
995 if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1;
996 if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS;
997 if( find_option("verbose",0,0)!=0 ) bVerbose = 1;
998 if( g.fQuiet ) flags |= GREP_QUIET|GREP_EXISTS;
999 bNoMsg = find_option("no-messages","s",0)!=0;
1000 bOnce = find_option("once",0,0)!=0;
1001 bInvert = find_option("invert-match","v",0)!=0;
1002 if( bInvert ){
1003 flags |= GREP_QUIET|GREP_EXISTS;
1004
+1 -1
--- src/report.c
+++ src/report.c
@@ -447,11 +447,11 @@
447447
int rn;
448448
const char *zTitle; /* Title of the report */
449449
const char *z;
450450
const char *zOwner; /* Owner of the report */
451451
const char *zClrKey; /* Color key - used to add colors to lines */
452
- char *zSQL; /* The SQL text that gnerates the report */
452
+ char *zSQL; /* The SQL text that generates the report */
453453
char *zErr = 0; /* An error message */
454454
const char *zDesc; /* Extra descriptive text about the report */
455455
const char *zMimetype; /* Mimetype for zDesc */
456456
const char *zTag; /* Symbolic name for this report */
457457
int dflt = P("dflt") ? 1 : 0;
458458
--- src/report.c
+++ src/report.c
@@ -447,11 +447,11 @@
447 int rn;
448 const char *zTitle; /* Title of the report */
449 const char *z;
450 const char *zOwner; /* Owner of the report */
451 const char *zClrKey; /* Color key - used to add colors to lines */
452 char *zSQL; /* The SQL text that gnerates the report */
453 char *zErr = 0; /* An error message */
454 const char *zDesc; /* Extra descriptive text about the report */
455 const char *zMimetype; /* Mimetype for zDesc */
456 const char *zTag; /* Symbolic name for this report */
457 int dflt = P("dflt") ? 1 : 0;
458
--- src/report.c
+++ src/report.c
@@ -447,11 +447,11 @@
447 int rn;
448 const char *zTitle; /* Title of the report */
449 const char *z;
450 const char *zOwner; /* Owner of the report */
451 const char *zClrKey; /* Color key - used to add colors to lines */
452 char *zSQL; /* The SQL text that generates the report */
453 char *zErr = 0; /* An error message */
454 const char *zDesc; /* Extra descriptive text about the report */
455 const char *zMimetype; /* Mimetype for zDesc */
456 const char *zTag; /* Symbolic name for this report */
457 int dflt = P("dflt") ? 1 : 0;
458
+3 -1
--- src/robot.c
+++ src/robot.c
@@ -263,11 +263,11 @@
263263
** The VALUE of this setting is a list of GLOB patterns that match
264264
** pages for which complex HTTP requests from unauthenticated clients
265265
** should be disallowed. "Unauthenticated" means the user is "nobody".
266266
** The recommended value for this setting is:
267267
**
268
-** timelineX,diff,annotate,fileage,file,finfo,reports,tree,download,hexdump
268
+** timelineX,diff,annotate,fileage,file,finfo,reports,tree,hexdump,download
269269
**
270270
** Usually the tag should exactly match the page name. The "diff" tag
271271
** covers all diffing pages such as /vdiff, /fdiff, and /vpatch. The
272272
** "annotate" tag also covers /blame and /praise. "zip" also covers
273273
** /tarball and /sqlar. If a tag has an "X" character appended then it
@@ -320,10 +320,12 @@
320320
321321
/*
322322
** Return the default restriction GLOB
323323
*/
324324
const char *robot_restrict_default(void){
325
+ /* NOTE: The default value is also mentioned in the online help screen of
326
+ ** the "robot-restrict" setting, and in the www/antibot.wiki document. */
325327
return "timelineX,diff,annotate,fileage,file,finfo,reports,"
326328
"tree,hexdump,download";
327329
}
328330
329331
/*
330332
--- src/robot.c
+++ src/robot.c
@@ -263,11 +263,11 @@
263 ** The VALUE of this setting is a list of GLOB patterns that match
264 ** pages for which complex HTTP requests from unauthenticated clients
265 ** should be disallowed. "Unauthenticated" means the user is "nobody".
266 ** The recommended value for this setting is:
267 **
268 ** timelineX,diff,annotate,fileage,file,finfo,reports,tree,download,hexdump
269 **
270 ** Usually the tag should exactly match the page name. The "diff" tag
271 ** covers all diffing pages such as /vdiff, /fdiff, and /vpatch. The
272 ** "annotate" tag also covers /blame and /praise. "zip" also covers
273 ** /tarball and /sqlar. If a tag has an "X" character appended then it
@@ -320,10 +320,12 @@
320
321 /*
322 ** Return the default restriction GLOB
323 */
324 const char *robot_restrict_default(void){
 
 
325 return "timelineX,diff,annotate,fileage,file,finfo,reports,"
326 "tree,hexdump,download";
327 }
328
329 /*
330
--- src/robot.c
+++ src/robot.c
@@ -263,11 +263,11 @@
263 ** The VALUE of this setting is a list of GLOB patterns that match
264 ** pages for which complex HTTP requests from unauthenticated clients
265 ** should be disallowed. "Unauthenticated" means the user is "nobody".
266 ** The recommended value for this setting is:
267 **
268 ** timelineX,diff,annotate,fileage,file,finfo,reports,tree,hexdump,download
269 **
270 ** Usually the tag should exactly match the page name. The "diff" tag
271 ** covers all diffing pages such as /vdiff, /fdiff, and /vpatch. The
272 ** "annotate" tag also covers /blame and /praise. "zip" also covers
273 ** /tarball and /sqlar. If a tag has an "X" character appended then it
@@ -320,10 +320,12 @@
320
321 /*
322 ** Return the default restriction GLOB
323 */
324 const char *robot_restrict_default(void){
325 /* NOTE: The default value is also mentioned in the online help screen of
326 ** the "robot-restrict" setting, and in the www/antibot.wiki document. */
327 return "timelineX,diff,annotate,fileage,file,finfo,reports,"
328 "tree,hexdump,download";
329 }
330
331 /*
332
+3 -3
--- src/schema.c
+++ src/schema.c
@@ -259,11 +259,11 @@
259259
@ -- pfnid = Parent File Name ID.
260260
@ -- isaux = pmid IS AUXiliary parent, not primary parent
261261
@ --
262262
@ -- pid==0 if the file is added by check-in mid.
263263
@ -- pid==(-1) if the file exists in a merge parents but not in the primary
264
-@ -- parent. In other words, if the file file was added by merge.
264
+@ -- parent. In other words, if the file was added by merge.
265265
@ -- fid==0 if the file is removed by check-in mid.
266266
@ --
267267
@ CREATE TABLE mlink(
268268
@ mid INTEGER, -- Check-in that contains fid
269269
@ fid INTEGER, -- New file content. 0 if deleted
@@ -365,11 +365,11 @@
365365
@ -- Each artifact can have one or more tags. A tag
366366
@ -- is defined by a row in the next table.
367367
@ --
368368
@ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
369369
@ -- the wiki page. Tickets changes are tagged with "ticket-HASH" where
370
-@ -- HASH is the indentifier of the ticket. Tags used to assign symbolic
370
+@ -- HASH is the identifier of the ticket. Tags used to assign symbolic
371371
@ -- names to baselines are branches are of the form "sym-NAME" where
372372
@ -- NAME is the symbolic name.
373373
@ --
374374
@ CREATE TABLE tag(
375375
@ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
@@ -500,11 +500,11 @@
500500
** Allowed values for MIMEtype codes
501501
*/
502502
#if INTERFACE
503503
# define MT_NONE 0 /* unspecified */
504504
# define MT_WIKI 1 /* Wiki */
505
-# define MT_MARKDOWN 2 /* Markdonw */
505
+# define MT_MARKDOWN 2 /* Markdown */
506506
# define MT_UNKNOWN 3 /* unknown */
507507
# define ValidMTC(X) ((X)>=0 && (X)<=3) /* True if MIMEtype code is valid */
508508
#endif
509509
510510
/*
511511
--- src/schema.c
+++ src/schema.c
@@ -259,11 +259,11 @@
259 @ -- pfnid = Parent File Name ID.
260 @ -- isaux = pmid IS AUXiliary parent, not primary parent
261 @ --
262 @ -- pid==0 if the file is added by check-in mid.
263 @ -- pid==(-1) if the file exists in a merge parents but not in the primary
264 @ -- parent. In other words, if the file file was added by merge.
265 @ -- fid==0 if the file is removed by check-in mid.
266 @ --
267 @ CREATE TABLE mlink(
268 @ mid INTEGER, -- Check-in that contains fid
269 @ fid INTEGER, -- New file content. 0 if deleted
@@ -365,11 +365,11 @@
365 @ -- Each artifact can have one or more tags. A tag
366 @ -- is defined by a row in the next table.
367 @ --
368 @ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
369 @ -- the wiki page. Tickets changes are tagged with "ticket-HASH" where
370 @ -- HASH is the indentifier of the ticket. Tags used to assign symbolic
371 @ -- names to baselines are branches are of the form "sym-NAME" where
372 @ -- NAME is the symbolic name.
373 @ --
374 @ CREATE TABLE tag(
375 @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
@@ -500,11 +500,11 @@
500 ** Allowed values for MIMEtype codes
501 */
502 #if INTERFACE
503 # define MT_NONE 0 /* unspecified */
504 # define MT_WIKI 1 /* Wiki */
505 # define MT_MARKDOWN 2 /* Markdonw */
506 # define MT_UNKNOWN 3 /* unknown */
507 # define ValidMTC(X) ((X)>=0 && (X)<=3) /* True if MIMEtype code is valid */
508 #endif
509
510 /*
511
--- src/schema.c
+++ src/schema.c
@@ -259,11 +259,11 @@
259 @ -- pfnid = Parent File Name ID.
260 @ -- isaux = pmid IS AUXiliary parent, not primary parent
261 @ --
262 @ -- pid==0 if the file is added by check-in mid.
263 @ -- pid==(-1) if the file exists in a merge parents but not in the primary
264 @ -- parent. In other words, if the file was added by merge.
265 @ -- fid==0 if the file is removed by check-in mid.
266 @ --
267 @ CREATE TABLE mlink(
268 @ mid INTEGER, -- Check-in that contains fid
269 @ fid INTEGER, -- New file content. 0 if deleted
@@ -365,11 +365,11 @@
365 @ -- Each artifact can have one or more tags. A tag
366 @ -- is defined by a row in the next table.
367 @ --
368 @ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
369 @ -- the wiki page. Tickets changes are tagged with "ticket-HASH" where
370 @ -- HASH is the identifier of the ticket. Tags used to assign symbolic
371 @ -- names to baselines are branches are of the form "sym-NAME" where
372 @ -- NAME is the symbolic name.
373 @ --
374 @ CREATE TABLE tag(
375 @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
@@ -500,11 +500,11 @@
500 ** Allowed values for MIMEtype codes
501 */
502 #if INTERFACE
503 # define MT_NONE 0 /* unspecified */
504 # define MT_WIKI 1 /* Wiki */
505 # define MT_MARKDOWN 2 /* Markdown */
506 # define MT_UNKNOWN 3 /* unknown */
507 # define ValidMTC(X) ((X)>=0 && (X)<=3) /* True if MIMEtype code is valid */
508 #endif
509
510 /*
511
+2 -2
--- src/search.c
+++ src/search.c
@@ -589,11 +589,11 @@
589589
** or use "--highlight 91" to force it on. Change the argument to --highlight
590590
** to change the color.
591591
**
592592
** Options:
593593
** -a|--all Search everything
594
-** -c|--checkins Search checkin comments
594
+** -c|--checkins Search check-in comments
595595
** --docs Search embedded documentation
596596
** --forum Search forum posts
597597
** -h|--bi-help Search built-in help
598598
** --highlight N Used VT100 color N for matching text. 0 means "off".
599599
** -n|--limit N Limit output to N matches
@@ -2865,11 +2865,11 @@
28652865
rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoLocalCb);
28662866
}
28672867
if( rc!=SQLITE_OK ){
28682868
sqlite3_result_error_code(pCtx, rc);
28692869
}else{
2870
- /* No errors has occured, so return a copy of the array of integers. */
2870
+ /* No error has occurred, so return a copy of the array of integers. */
28712871
int nByte = p->nRet * sizeof(u32);
28722872
sqlite3_result_blob(pCtx, (void*)p->aRet, nByte, SQLITE_TRANSIENT);
28732873
}
28742874
}
28752875
28762876
--- src/search.c
+++ src/search.c
@@ -589,11 +589,11 @@
589 ** or use "--highlight 91" to force it on. Change the argument to --highlight
590 ** to change the color.
591 **
592 ** Options:
593 ** -a|--all Search everything
594 ** -c|--checkins Search checkin comments
595 ** --docs Search embedded documentation
596 ** --forum Search forum posts
597 ** -h|--bi-help Search built-in help
598 ** --highlight N Used VT100 color N for matching text. 0 means "off".
599 ** -n|--limit N Limit output to N matches
@@ -2865,11 +2865,11 @@
2865 rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoLocalCb);
2866 }
2867 if( rc!=SQLITE_OK ){
2868 sqlite3_result_error_code(pCtx, rc);
2869 }else{
2870 /* No errors has occured, so return a copy of the array of integers. */
2871 int nByte = p->nRet * sizeof(u32);
2872 sqlite3_result_blob(pCtx, (void*)p->aRet, nByte, SQLITE_TRANSIENT);
2873 }
2874 }
2875
2876
--- src/search.c
+++ src/search.c
@@ -589,11 +589,11 @@
589 ** or use "--highlight 91" to force it on. Change the argument to --highlight
590 ** to change the color.
591 **
592 ** Options:
593 ** -a|--all Search everything
594 ** -c|--checkins Search check-in comments
595 ** --docs Search embedded documentation
596 ** --forum Search forum posts
597 ** -h|--bi-help Search built-in help
598 ** --highlight N Used VT100 color N for matching text. 0 means "off".
599 ** -n|--limit N Limit output to N matches
@@ -2865,11 +2865,11 @@
2865 rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoLocalCb);
2866 }
2867 if( rc!=SQLITE_OK ){
2868 sqlite3_result_error_code(pCtx, rc);
2869 }else{
2870 /* No error has occurred, so return a copy of the array of integers. */
2871 int nByte = p->nRet * sizeof(u32);
2872 sqlite3_result_blob(pCtx, (void*)p->aRet, nByte, SQLITE_TRANSIENT);
2873 }
2874 }
2875
2876
--- src/security_audit.c
+++ src/security_audit.c
@@ -351,11 +351,11 @@
351351
*/
352352
if( db_exists("SELECT 1 FROM config WHERE name GLOB 'xfer-*-script'"
353353
" AND length(value)>0") ){
354354
@ <li><p><b>WARNING:</b>
355355
@ TH1 scripts might be configured to run on any sync, push, pull, or
356
- @ clone operation. See the the <a href="%R/xfersetup">/xfersetup</a>
356
+ @ clone operation. See the <a href="%R/xfersetup">/xfersetup</a>
357357
@ page for more information. These TH1 scripts are a potential
358358
@ security concern and so should be carefully audited by a human.
359359
}
360360
361361
/* The strict-manifest-syntax setting should be on. */
@@ -389,11 +389,11 @@
389389
@ <a href="setup_ulist">User Configuration</a> page in case we
390390
@ ever reuse the letter for another purpose.
391391
}
392392
393393
/* If anonymous users are allowed to create new Wiki, then
394
- ** wiki moderation should be activated to pervent spam.
394
+ ** wiki moderation should be activated to prevent spam.
395395
*/
396396
if( hasAnyCap(zAnonCap, "fk") ){
397397
if( db_get_boolean("modreq-wiki",0)==0 ){
398398
@ <li><p><b>WARNING:</b>
399399
@ Anonymous users can create or edit wiki without moderation.
400400
--- src/security_audit.c
+++ src/security_audit.c
@@ -351,11 +351,11 @@
351 */
352 if( db_exists("SELECT 1 FROM config WHERE name GLOB 'xfer-*-script'"
353 " AND length(value)>0") ){
354 @ <li><p><b>WARNING:</b>
355 @ TH1 scripts might be configured to run on any sync, push, pull, or
356 @ clone operation. See the the <a href="%R/xfersetup">/xfersetup</a>
357 @ page for more information. These TH1 scripts are a potential
358 @ security concern and so should be carefully audited by a human.
359 }
360
361 /* The strict-manifest-syntax setting should be on. */
@@ -389,11 +389,11 @@
389 @ <a href="setup_ulist">User Configuration</a> page in case we
390 @ ever reuse the letter for another purpose.
391 }
392
393 /* If anonymous users are allowed to create new Wiki, then
394 ** wiki moderation should be activated to pervent spam.
395 */
396 if( hasAnyCap(zAnonCap, "fk") ){
397 if( db_get_boolean("modreq-wiki",0)==0 ){
398 @ <li><p><b>WARNING:</b>
399 @ Anonymous users can create or edit wiki without moderation.
400
--- src/security_audit.c
+++ src/security_audit.c
@@ -351,11 +351,11 @@
351 */
352 if( db_exists("SELECT 1 FROM config WHERE name GLOB 'xfer-*-script'"
353 " AND length(value)>0") ){
354 @ <li><p><b>WARNING:</b>
355 @ TH1 scripts might be configured to run on any sync, push, pull, or
356 @ clone operation. See the <a href="%R/xfersetup">/xfersetup</a>
357 @ page for more information. These TH1 scripts are a potential
358 @ security concern and so should be carefully audited by a human.
359 }
360
361 /* The strict-manifest-syntax setting should be on. */
@@ -389,11 +389,11 @@
389 @ <a href="setup_ulist">User Configuration</a> page in case we
390 @ ever reuse the letter for another purpose.
391 }
392
393 /* If anonymous users are allowed to create new Wiki, then
394 ** wiki moderation should be activated to prevent spam.
395 */
396 if( hasAnyCap(zAnonCap, "fk") ){
397 if( db_get_boolean("modreq-wiki",0)==0 ){
398 @ <li><p><b>WARNING:</b>
399 @ Anonymous users can create or edit wiki without moderation.
400
+1 -1
--- src/setup.c
+++ src/setup.c
@@ -485,11 +485,11 @@
485485
@ <hr>
486486
@ <p><b>Do not allow robots access to these pages.</b><br>
487487
@ If the page name matches the GLOB pattern of this setting, and the
488488
@ users is "nobody", and the client has not previously passed a captcha
489489
@ test to show that it is not a robot, then the page is not displayed.
490
- @ A captcha test is is rendered instead.
490
+ @ A captcha test is rendered instead.
491491
@ The default value for this setting is:
492492
@ <p>
493493
@ &emsp;&emsp;&emsp;<tt>%h(robot_restrict_default())</tt>
494494
@ <p>
495495
@ Usually the tag should exactly match the page name. Exceptions:
496496
--- src/setup.c
+++ src/setup.c
@@ -485,11 +485,11 @@
485 @ <hr>
486 @ <p><b>Do not allow robots access to these pages.</b><br>
487 @ If the page name matches the GLOB pattern of this setting, and the
488 @ users is "nobody", and the client has not previously passed a captcha
489 @ test to show that it is not a robot, then the page is not displayed.
490 @ A captcha test is is rendered instead.
491 @ The default value for this setting is:
492 @ <p>
493 @ &emsp;&emsp;&emsp;<tt>%h(robot_restrict_default())</tt>
494 @ <p>
495 @ Usually the tag should exactly match the page name. Exceptions:
496
--- src/setup.c
+++ src/setup.c
@@ -485,11 +485,11 @@
485 @ <hr>
486 @ <p><b>Do not allow robots access to these pages.</b><br>
487 @ If the page name matches the GLOB pattern of this setting, and the
488 @ users is "nobody", and the client has not previously passed a captcha
489 @ test to show that it is not a robot, then the page is not displayed.
490 @ A captcha test is rendered instead.
491 @ The default value for this setting is:
492 @ <p>
493 @ &emsp;&emsp;&emsp;<tt>%h(robot_restrict_default())</tt>
494 @ <p>
495 @ Usually the tag should exactly match the page name. Exceptions:
496
+1 -1
--- src/setupuser.c
+++ src/setupuser.c
@@ -617,11 +617,11 @@
617617
zLogin, zLogin
618618
);
619619
zOldLogin = zLogin;
620620
}
621621
#if 0
622
- /* Problem: when renaming a user we need to update the subcriber
622
+ /* Problem: when renaming a user we need to update the subscriber
623623
** names to match but we cannot know from here if each member of
624624
** the login group has the subscriber tables, so we cannot blindly
625625
** include this SQL. */
626626
else if( fossil_strcmp(zLogin, zOldLogin)!=0
627627
&& alert_tables_exist() ){
628628
--- src/setupuser.c
+++ src/setupuser.c
@@ -617,11 +617,11 @@
617 zLogin, zLogin
618 );
619 zOldLogin = zLogin;
620 }
621 #if 0
622 /* Problem: when renaming a user we need to update the subcriber
623 ** names to match but we cannot know from here if each member of
624 ** the login group has the subscriber tables, so we cannot blindly
625 ** include this SQL. */
626 else if( fossil_strcmp(zLogin, zOldLogin)!=0
627 && alert_tables_exist() ){
628
--- src/setupuser.c
+++ src/setupuser.c
@@ -617,11 +617,11 @@
617 zLogin, zLogin
618 );
619 zOldLogin = zLogin;
620 }
621 #if 0
622 /* Problem: when renaming a user we need to update the subscriber
623 ** names to match but we cannot know from here if each member of
624 ** the login group has the subscriber tables, so we cannot blindly
625 ** include this SQL. */
626 else if( fossil_strcmp(zLogin, zOldLogin)!=0
627 && alert_tables_exist() ){
628
+1 -1
--- src/sha1.c
+++ src/sha1.c
@@ -257,11 +257,11 @@
257257
for (i = 0; i < 20; i++)
258258
digest[i] = (unsigned char)
259259
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
260260
}
261261
}
262
-#endif /* Built-in SHA1 implemenation */
262
+#endif /* Built-in SHA1 implementation */
263263
264264
/*
265265
** Convert a digest into base-16. digest should be declared as
266266
** "unsigned char digest[20]" in the calling function. The SHA1
267267
** digest is stored in the first 20 bytes. zBuf should
268268
--- src/sha1.c
+++ src/sha1.c
@@ -257,11 +257,11 @@
257 for (i = 0; i < 20; i++)
258 digest[i] = (unsigned char)
259 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
260 }
261 }
262 #endif /* Built-in SHA1 implemenation */
263
264 /*
265 ** Convert a digest into base-16. digest should be declared as
266 ** "unsigned char digest[20]" in the calling function. The SHA1
267 ** digest is stored in the first 20 bytes. zBuf should
268
--- src/sha1.c
+++ src/sha1.c
@@ -257,11 +257,11 @@
257 for (i = 0; i < 20; i++)
258 digest[i] = (unsigned char)
259 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
260 }
261 }
262 #endif /* Built-in SHA1 implementation */
263
264 /*
265 ** Convert a digest into base-16. digest should be declared as
266 ** "unsigned char digest[20]" in the calling function. The SHA1
267 ** digest is stored in the first 20 bytes. zBuf should
268
+1 -1
--- src/skins.c
+++ src/skins.c
@@ -162,11 +162,11 @@
162162
** 2) The "skin" display setting cookie or URL argument, in that
163163
** order. If the "skin" URL argument is provided and refers to a legal
164164
** skin then that will update the display cookie. If the skin name is
165165
** illegal it is silently ignored.
166166
**
167
-** 3) The built-in skin identfied by the "default-skin" setting, if such
167
+** 3) The built-in skin identified by the "default-skin" setting, if such
168168
** a setting exists and matches one of the built-in skin names.
169169
**
170170
** 4) Skin properties (settings "css", "details", "footer", "header",
171171
** and "js") from the CONFIG db table
172172
**
173173
--- src/skins.c
+++ src/skins.c
@@ -162,11 +162,11 @@
162 ** 2) The "skin" display setting cookie or URL argument, in that
163 ** order. If the "skin" URL argument is provided and refers to a legal
164 ** skin then that will update the display cookie. If the skin name is
165 ** illegal it is silently ignored.
166 **
167 ** 3) The built-in skin identfied by the "default-skin" setting, if such
168 ** a setting exists and matches one of the built-in skin names.
169 **
170 ** 4) Skin properties (settings "css", "details", "footer", "header",
171 ** and "js") from the CONFIG db table
172 **
173
--- src/skins.c
+++ src/skins.c
@@ -162,11 +162,11 @@
162 ** 2) The "skin" display setting cookie or URL argument, in that
163 ** order. If the "skin" URL argument is provided and refers to a legal
164 ** skin then that will update the display cookie. If the skin name is
165 ** illegal it is silently ignored.
166 **
167 ** 3) The built-in skin identified by the "default-skin" setting, if such
168 ** a setting exists and matches one of the built-in skin names.
169 **
170 ** 4) Skin properties (settings "css", "details", "footer", "header",
171 ** and "js") from the CONFIG db table
172 **
173
+1 -1
--- src/smtp.c
+++ src/smtp.c
@@ -565,11 +565,11 @@
565565
** Return 0 on success. Otherwise an error code.
566566
*/
567567
int smtp_send_msg(
568568
SmtpSession *p, /* The SMTP server to which the message is sent */
569569
const char *zFrom, /* Who the message is from */
570
- int nTo, /* Number of receipients */
570
+ int nTo, /* Number of recipients */
571571
const char **azTo, /* Email address of each recipient */
572572
const char *zMsg /* Body of the message */
573573
){
574574
int i;
575575
int iCode = 0;
576576
--- src/smtp.c
+++ src/smtp.c
@@ -565,11 +565,11 @@
565 ** Return 0 on success. Otherwise an error code.
566 */
567 int smtp_send_msg(
568 SmtpSession *p, /* The SMTP server to which the message is sent */
569 const char *zFrom, /* Who the message is from */
570 int nTo, /* Number of receipients */
571 const char **azTo, /* Email address of each recipient */
572 const char *zMsg /* Body of the message */
573 ){
574 int i;
575 int iCode = 0;
576
--- src/smtp.c
+++ src/smtp.c
@@ -565,11 +565,11 @@
565 ** Return 0 on success. Otherwise an error code.
566 */
567 int smtp_send_msg(
568 SmtpSession *p, /* The SMTP server to which the message is sent */
569 const char *zFrom, /* Who the message is from */
570 int nTo, /* Number of recipients */
571 const char **azTo, /* Email address of each recipient */
572 const char *zMsg /* Body of the message */
573 ){
574 int i;
575 int iCode = 0;
576
+16 -12
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -168,11 +168,11 @@
168168
** WARNING:
169169
** Do not instantiate these functions for any Fossil webpage or command
170170
** method other than the "fossil sql" command. If an attacker gains access
171171
** to these functions, he will be able to disable other defense mechanisms.
172172
**
173
-** This routines are for interactiving testing only. They are experimental
173
+** This routines are for interactive testing only. They are experimental
174174
** and undocumented (apart from this comments) and might go away or change
175175
** in future releases.
176176
**
177177
** 2020-11-29: These functions are now only available if the "fossil sql"
178178
** command is started with the --test option.
@@ -221,12 +221,14 @@
221221
helptext_vtab_register(db);
222222
builtin_vtab_register(db);
223223
g.repositoryOpen = 1;
224224
g.db = db;
225225
sqlite3_busy_timeout(db, 10000);
226
- sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
227
- db_maybe_set_encryption_key(db, g.zRepositoryName);
226
+ if( g.zRepositoryName ){
227
+ sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
228
+ db_maybe_set_encryption_key(db, g.zRepositoryName);
229
+ }
228230
if( g.zLocalDbName ){
229231
char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
230232
g.zLocalDbName);
231233
sqlite3_exec(db, zSql, 0, 0, 0);
232234
sqlite3_free(zSql);
@@ -240,19 +242,21 @@
240242
(void)timeline_query_for_tty(); /* Registers wiki_to_text() as side-effect */
241243
/* Arrange to trace close operations so that static prepared statements
242244
** will get cleaned up when the shell closes the database connection */
243245
if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
244246
sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
245
- db_protect_only(PROTECT_NONE);
246
- sqlite3_set_authorizer(db, db_top_authorizer, db);
247
- if( local_bSqlCmdTest ){
248
- sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
249
- sqlcmd_db_protect, 0, 0);
250
- sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
251
- sqlcmd_db_protect_pop, 0, 0);
252
- sqlite3_create_function(db, "shared_secret", 2, SQLITE_UTF8, 0,
253
- sha1_shared_secret_sql_function, 0, 0);
247
+ if( g.zRepositoryName ){
248
+ db_protect_only(PROTECT_NONE);
249
+ sqlite3_set_authorizer(db, db_top_authorizer, db);
250
+ if( local_bSqlCmdTest ){
251
+ sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
252
+ sqlcmd_db_protect, 0, 0);
253
+ sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
254
+ sqlcmd_db_protect_pop, 0, 0);
255
+ sqlite3_create_function(db, "shared_secret", 2, SQLITE_UTF8, 0,
256
+ sha1_shared_secret_sql_function, 0, 0);
257
+ }
254258
}
255259
return SQLITE_OK;
256260
}
257261
258262
/*
259263
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -168,11 +168,11 @@
168 ** WARNING:
169 ** Do not instantiate these functions for any Fossil webpage or command
170 ** method other than the "fossil sql" command. If an attacker gains access
171 ** to these functions, he will be able to disable other defense mechanisms.
172 **
173 ** This routines are for interactiving testing only. They are experimental
174 ** and undocumented (apart from this comments) and might go away or change
175 ** in future releases.
176 **
177 ** 2020-11-29: These functions are now only available if the "fossil sql"
178 ** command is started with the --test option.
@@ -221,12 +221,14 @@
221 helptext_vtab_register(db);
222 builtin_vtab_register(db);
223 g.repositoryOpen = 1;
224 g.db = db;
225 sqlite3_busy_timeout(db, 10000);
226 sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
227 db_maybe_set_encryption_key(db, g.zRepositoryName);
 
 
228 if( g.zLocalDbName ){
229 char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
230 g.zLocalDbName);
231 sqlite3_exec(db, zSql, 0, 0, 0);
232 sqlite3_free(zSql);
@@ -240,19 +242,21 @@
240 (void)timeline_query_for_tty(); /* Registers wiki_to_text() as side-effect */
241 /* Arrange to trace close operations so that static prepared statements
242 ** will get cleaned up when the shell closes the database connection */
243 if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
244 sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
245 db_protect_only(PROTECT_NONE);
246 sqlite3_set_authorizer(db, db_top_authorizer, db);
247 if( local_bSqlCmdTest ){
248 sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
249 sqlcmd_db_protect, 0, 0);
250 sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
251 sqlcmd_db_protect_pop, 0, 0);
252 sqlite3_create_function(db, "shared_secret", 2, SQLITE_UTF8, 0,
253 sha1_shared_secret_sql_function, 0, 0);
 
 
254 }
255 return SQLITE_OK;
256 }
257
258 /*
259
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -168,11 +168,11 @@
168 ** WARNING:
169 ** Do not instantiate these functions for any Fossil webpage or command
170 ** method other than the "fossil sql" command. If an attacker gains access
171 ** to these functions, he will be able to disable other defense mechanisms.
172 **
173 ** This routines are for interactive testing only. They are experimental
174 ** and undocumented (apart from this comments) and might go away or change
175 ** in future releases.
176 **
177 ** 2020-11-29: These functions are now only available if the "fossil sql"
178 ** command is started with the --test option.
@@ -221,12 +221,14 @@
221 helptext_vtab_register(db);
222 builtin_vtab_register(db);
223 g.repositoryOpen = 1;
224 g.db = db;
225 sqlite3_busy_timeout(db, 10000);
226 if( g.zRepositoryName ){
227 sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
228 db_maybe_set_encryption_key(db, g.zRepositoryName);
229 }
230 if( g.zLocalDbName ){
231 char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
232 g.zLocalDbName);
233 sqlite3_exec(db, zSql, 0, 0, 0);
234 sqlite3_free(zSql);
@@ -240,19 +242,21 @@
242 (void)timeline_query_for_tty(); /* Registers wiki_to_text() as side-effect */
243 /* Arrange to trace close operations so that static prepared statements
244 ** will get cleaned up when the shell closes the database connection */
245 if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
246 sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
247 if( g.zRepositoryName ){
248 db_protect_only(PROTECT_NONE);
249 sqlite3_set_authorizer(db, db_top_authorizer, db);
250 if( local_bSqlCmdTest ){
251 sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
252 sqlcmd_db_protect, 0, 0);
253 sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
254 sqlcmd_db_protect_pop, 0, 0);
255 sqlite3_create_function(db, "shared_secret", 2, SQLITE_UTF8, 0,
256 sha1_shared_secret_sql_function, 0, 0);
257 }
258 }
259 return SQLITE_OK;
260 }
261
262 /*
263
+1 -1
--- src/stat.c
+++ src/stat.c
@@ -503,11 +503,11 @@
503503
** access URL.
504504
**
505505
** Algorithm:
506506
**
507507
** The public URL is given by the email-url property. But it is only
508
-** returned if there have been one more more accesses (as recorded by
508
+** returned if there have been one or more accesses (as recorded by
509509
** "baseurl:URL" entries in the CONFIG table).
510510
*/
511511
const char *public_url(void){
512512
const char *zUrl = db_get("email-url", 0);
513513
if( zUrl==0 ) return 0;
514514
--- src/stat.c
+++ src/stat.c
@@ -503,11 +503,11 @@
503 ** access URL.
504 **
505 ** Algorithm:
506 **
507 ** The public URL is given by the email-url property. But it is only
508 ** returned if there have been one more more accesses (as recorded by
509 ** "baseurl:URL" entries in the CONFIG table).
510 */
511 const char *public_url(void){
512 const char *zUrl = db_get("email-url", 0);
513 if( zUrl==0 ) return 0;
514
--- src/stat.c
+++ src/stat.c
@@ -503,11 +503,11 @@
503 ** access URL.
504 **
505 ** Algorithm:
506 **
507 ** The public URL is given by the email-url property. But it is only
508 ** returned if there have been one or more accesses (as recorded by
509 ** "baseurl:URL" entries in the CONFIG table).
510 */
511 const char *public_url(void){
512 const char *zUrl = db_get("email-url", 0);
513 if( zUrl==0 ) return 0;
514
+10 -5
--- src/style.c
+++ src/style.c
@@ -226,11 +226,11 @@
226226
**
227227
** As a defense against robots, the action=ARG might instead by data-action=ARG
228228
** and javascript (href.js) added to the page so that the data-action= is
229229
** changed into action= after the page loads. Whether or not this happens
230230
** depends on if the user has the "h" privilege and whether or not the
231
-** auto-hyperlink setting is on. These setings determine the values of
231
+** auto-hyperlink setting is on. These settings determine the values of
232232
** variables g.perm.Hyperlink and g.jsHref.
233233
**
234234
** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
235235
** ------------ -------------- ---------------- --------
236236
** 1: 0 0 0 0
@@ -913,14 +913,14 @@
913913
@ </script>
914914
builtin_fulfill_js_requests();
915915
}
916916
917917
/*
918
-** Transorm input string into a token that is safe for inclusion into
918
+** Transform input string into a token that is safe for inclusion into
919919
** class attribute. Digits and low-case letter are passed unchanged,
920920
** upper-case letters are transformed to low-case, everything else is
921
-** tranformed into hyphens; consequtive and pending hyphens are squeezed.
921
+** transformed into hyphens; consecutive and pending hyphens are squeezed.
922922
** If result does not fit into szOut chars then it is truncated.
923923
** Result is always terminated with null.
924924
*/
925925
void style_derive_classname(const char *zIn, char *zOut, int szOut){
926926
assert( zOut );
@@ -1219,11 +1219,11 @@
12191219
12201220
/*
12211221
** Check for "name" or "page" query parameters on an /style.css
12221222
** page request. If present, then page-specific CSS is requested,
12231223
** so add that CSS to pOut. If the "name" and "page" query parameters
1224
-** are omitted, then pOut is unchnaged.
1224
+** are omitted, then pOut is unchanged.
12251225
*/
12261226
static void page_style_css_append_page_style(Blob *pOut){
12271227
const char *zPage = PD("name",P("page"));
12281228
char * zFile;
12291229
int nFile = 0;
@@ -1252,11 +1252,11 @@
12521252
}
12531253
12541254
/*
12551255
** WEBPAGE: style.css loadavg-exempt
12561256
**
1257
-** Return the style sheet. The style sheet is assemblied from
1257
+** Return the style sheet. The style sheet is assembled from
12581258
** multiple sources, in order:
12591259
**
12601260
** (1) The built-in "default.css" style sheet containing basic defaults.
12611261
**
12621262
** (2) The page-specific style sheet taken from the built-in
@@ -1442,10 +1442,15 @@
14421442
@ g.zHttpsURL = %h(g.zHttpsURL)<br>
14431443
@ g.zTop = %h(g.zTop)<br>
14441444
@ g.zPath = %h(g.zPath)<br>
14451445
@ g.userUid = %d(g.userUid)<br>
14461446
@ g.zLogin = %h(g.zLogin)<br>
1447
+ if( g.eAuthMethod!=AUTH_NONE ){
1448
+ const char *zMethod[] = { "COOKIE", "LOCAL", "PW", "ENV", "HTTP" };
1449
+ @ g.eAuthMethod = %d(g.eAuthMethod) (%h(zMethod[g.eAuthMethod-1]))\
1450
+ @ <br>
1451
+ }
14471452
@ g.isRobot = %d(g.isRobot)<br>
14481453
@ g.jsHref = %d(g.jsHref)<br>
14491454
if( g.zLocalRoot ){
14501455
@ g.zLocalRoot = %h(g.zLocalRoot)<br>
14511456
}else{
14521457
--- src/style.c
+++ src/style.c
@@ -226,11 +226,11 @@
226 **
227 ** As a defense against robots, the action=ARG might instead by data-action=ARG
228 ** and javascript (href.js) added to the page so that the data-action= is
229 ** changed into action= after the page loads. Whether or not this happens
230 ** depends on if the user has the "h" privilege and whether or not the
231 ** auto-hyperlink setting is on. These setings determine the values of
232 ** variables g.perm.Hyperlink and g.jsHref.
233 **
234 ** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
235 ** ------------ -------------- ---------------- --------
236 ** 1: 0 0 0 0
@@ -913,14 +913,14 @@
913 @ </script>
914 builtin_fulfill_js_requests();
915 }
916
917 /*
918 ** Transorm input string into a token that is safe for inclusion into
919 ** class attribute. Digits and low-case letter are passed unchanged,
920 ** upper-case letters are transformed to low-case, everything else is
921 ** tranformed into hyphens; consequtive and pending hyphens are squeezed.
922 ** If result does not fit into szOut chars then it is truncated.
923 ** Result is always terminated with null.
924 */
925 void style_derive_classname(const char *zIn, char *zOut, int szOut){
926 assert( zOut );
@@ -1219,11 +1219,11 @@
1219
1220 /*
1221 ** Check for "name" or "page" query parameters on an /style.css
1222 ** page request. If present, then page-specific CSS is requested,
1223 ** so add that CSS to pOut. If the "name" and "page" query parameters
1224 ** are omitted, then pOut is unchnaged.
1225 */
1226 static void page_style_css_append_page_style(Blob *pOut){
1227 const char *zPage = PD("name",P("page"));
1228 char * zFile;
1229 int nFile = 0;
@@ -1252,11 +1252,11 @@
1252 }
1253
1254 /*
1255 ** WEBPAGE: style.css loadavg-exempt
1256 **
1257 ** Return the style sheet. The style sheet is assemblied from
1258 ** multiple sources, in order:
1259 **
1260 ** (1) The built-in "default.css" style sheet containing basic defaults.
1261 **
1262 ** (2) The page-specific style sheet taken from the built-in
@@ -1442,10 +1442,15 @@
1442 @ g.zHttpsURL = %h(g.zHttpsURL)<br>
1443 @ g.zTop = %h(g.zTop)<br>
1444 @ g.zPath = %h(g.zPath)<br>
1445 @ g.userUid = %d(g.userUid)<br>
1446 @ g.zLogin = %h(g.zLogin)<br>
 
 
 
 
 
1447 @ g.isRobot = %d(g.isRobot)<br>
1448 @ g.jsHref = %d(g.jsHref)<br>
1449 if( g.zLocalRoot ){
1450 @ g.zLocalRoot = %h(g.zLocalRoot)<br>
1451 }else{
1452
--- src/style.c
+++ src/style.c
@@ -226,11 +226,11 @@
226 **
227 ** As a defense against robots, the action=ARG might instead by data-action=ARG
228 ** and javascript (href.js) added to the page so that the data-action= is
229 ** changed into action= after the page loads. Whether or not this happens
230 ** depends on if the user has the "h" privilege and whether or not the
231 ** auto-hyperlink setting is on. These settings determine the values of
232 ** variables g.perm.Hyperlink and g.jsHref.
233 **
234 ** User has "h" auto-hyperlink g.perm.Hyperlink g.jsHref
235 ** ------------ -------------- ---------------- --------
236 ** 1: 0 0 0 0
@@ -913,14 +913,14 @@
913 @ </script>
914 builtin_fulfill_js_requests();
915 }
916
917 /*
918 ** Transform input string into a token that is safe for inclusion into
919 ** class attribute. Digits and low-case letter are passed unchanged,
920 ** upper-case letters are transformed to low-case, everything else is
921 ** transformed into hyphens; consecutive and pending hyphens are squeezed.
922 ** If result does not fit into szOut chars then it is truncated.
923 ** Result is always terminated with null.
924 */
925 void style_derive_classname(const char *zIn, char *zOut, int szOut){
926 assert( zOut );
@@ -1219,11 +1219,11 @@
1219
1220 /*
1221 ** Check for "name" or "page" query parameters on an /style.css
1222 ** page request. If present, then page-specific CSS is requested,
1223 ** so add that CSS to pOut. If the "name" and "page" query parameters
1224 ** are omitted, then pOut is unchanged.
1225 */
1226 static void page_style_css_append_page_style(Blob *pOut){
1227 const char *zPage = PD("name",P("page"));
1228 char * zFile;
1229 int nFile = 0;
@@ -1252,11 +1252,11 @@
1252 }
1253
1254 /*
1255 ** WEBPAGE: style.css loadavg-exempt
1256 **
1257 ** Return the style sheet. The style sheet is assembled from
1258 ** multiple sources, in order:
1259 **
1260 ** (1) The built-in "default.css" style sheet containing basic defaults.
1261 **
1262 ** (2) The page-specific style sheet taken from the built-in
@@ -1442,10 +1442,15 @@
1442 @ g.zHttpsURL = %h(g.zHttpsURL)<br>
1443 @ g.zTop = %h(g.zTop)<br>
1444 @ g.zPath = %h(g.zPath)<br>
1445 @ g.userUid = %d(g.userUid)<br>
1446 @ g.zLogin = %h(g.zLogin)<br>
1447 if( g.eAuthMethod!=AUTH_NONE ){
1448 const char *zMethod[] = { "COOKIE", "LOCAL", "PW", "ENV", "HTTP" };
1449 @ g.eAuthMethod = %d(g.eAuthMethod) (%h(zMethod[g.eAuthMethod-1]))\
1450 @ <br>
1451 }
1452 @ g.isRobot = %d(g.isRobot)<br>
1453 @ g.jsHref = %d(g.jsHref)<br>
1454 if( g.zLocalRoot ){
1455 @ g.zLocalRoot = %h(g.zLocalRoot)<br>
1456 }else{
1457
+17 -5
--- src/sync.c
+++ src/sync.c
@@ -23,11 +23,11 @@
2323
2424
/*
2525
** Explain what type of sync operation is about to occur
2626
*/
2727
static void sync_explain(unsigned syncFlags){
28
- if( g.url.isAlias ){
28
+ if( g.url.isAlias && (syncFlags & SYNC_QUIET)==0 ){
2929
const char *url;
3030
if( g.url.useProxy ){
3131
url = g.url.proxyUrlCanonical;
3232
}else{
3333
url = g.url.canonical;
@@ -36,10 +36,12 @@
3636
fossil_print("Sync with %s\n", url);
3737
}else if( syncFlags & SYNC_PUSH ){
3838
fossil_print("Push to %s\n", url);
3939
}else if( syncFlags & SYNC_PULL ){
4040
fossil_print("Pull from %s\n", url);
41
+ }else if( syncFlags & SYNC_PING ){
42
+ fossil_print("Ping %s\n", url);
4143
}
4244
}
4345
}
4446
4547
@@ -307,11 +309,11 @@
307309
** URL is the server name. PAYLOAD is the name of a temporary file
308310
** that will contain the xfer-protocol payload to send to the server.
309311
** REPLY is a temporary filename in which COMMAND should write the
310312
** content of the reply from the server.
311313
**
312
- ** CMD is reponsible for HTTP redirects. The following Fossil command
314
+ ** CMD is responsible for HTTP redirects. The following Fossil command
313315
** can be used for CMD to achieve a working sync:
314316
**
315317
** fossil test-httpmsg --xfer
316318
*/
317319
g.zHttpCmd = find_option("transport-command",0,1);
@@ -482,12 +484,14 @@
482484
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
483485
** if required by the remote website
484486
** --ipv4 Use only IPv4, not IPv6
485487
** --no-http-compression Do not compress HTTP traffic
486488
** --once Do not remember URL for subsequent syncs
489
+** --ping Just verify that the server is alive
487490
** --proxy PROXY Use the specified HTTP proxy
488491
** --private Sync private branches too
492
+** -q|--quiet Omit all output
489493
** -R|--repository REPO Local repository to sync with
490494
** --ssl-identity FILE Local SSL credentials, if requested by remote
491495
** --ssh-command SSH Use SSH as the "ssh" command
492496
** --transport-command CMD Use external command CMD to move message
493497
** between the client and the server
@@ -502,19 +506,27 @@
502506
void sync_cmd(void){
503507
unsigned configFlags = 0;
504508
unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
505509
if( find_option("unversioned","u",0)!=0 ){
506510
syncFlags |= SYNC_UNVERSIONED;
511
+ }
512
+ if( find_option("ping",0,0)!=0 ){
513
+ syncFlags = SYNC_PING;
514
+ }
515
+ if( g.fQuiet ){
516
+ syncFlags |= SYNC_QUIET;
507517
}
508518
process_sync_args(&configFlags, &syncFlags, 0, 0);
509519
510520
/* We should be done with options.. */
511521
verify_all_options();
512522
513
- if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
514
- if( (syncFlags & SYNC_PUSH)==0 ){
515
- fossil_warning("pull only: the 'dont-push' option is set");
523
+ if( (syncFlags & SYNC_PING)==0 ){
524
+ if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
525
+ if( (syncFlags & SYNC_PUSH)==0 ){
526
+ fossil_warning("pull only: the 'dont-push' option is set");
527
+ }
516528
}
517529
client_sync_all_urls(syncFlags, configFlags, 0, 0);
518530
}
519531
520532
/*
521533
--- src/sync.c
+++ src/sync.c
@@ -23,11 +23,11 @@
23
24 /*
25 ** Explain what type of sync operation is about to occur
26 */
27 static void sync_explain(unsigned syncFlags){
28 if( g.url.isAlias ){
29 const char *url;
30 if( g.url.useProxy ){
31 url = g.url.proxyUrlCanonical;
32 }else{
33 url = g.url.canonical;
@@ -36,10 +36,12 @@
36 fossil_print("Sync with %s\n", url);
37 }else if( syncFlags & SYNC_PUSH ){
38 fossil_print("Push to %s\n", url);
39 }else if( syncFlags & SYNC_PULL ){
40 fossil_print("Pull from %s\n", url);
 
 
41 }
42 }
43 }
44
45
@@ -307,11 +309,11 @@
307 ** URL is the server name. PAYLOAD is the name of a temporary file
308 ** that will contain the xfer-protocol payload to send to the server.
309 ** REPLY is a temporary filename in which COMMAND should write the
310 ** content of the reply from the server.
311 **
312 ** CMD is reponsible for HTTP redirects. The following Fossil command
313 ** can be used for CMD to achieve a working sync:
314 **
315 ** fossil test-httpmsg --xfer
316 */
317 g.zHttpCmd = find_option("transport-command",0,1);
@@ -482,12 +484,14 @@
482 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
483 ** if required by the remote website
484 ** --ipv4 Use only IPv4, not IPv6
485 ** --no-http-compression Do not compress HTTP traffic
486 ** --once Do not remember URL for subsequent syncs
 
487 ** --proxy PROXY Use the specified HTTP proxy
488 ** --private Sync private branches too
 
489 ** -R|--repository REPO Local repository to sync with
490 ** --ssl-identity FILE Local SSL credentials, if requested by remote
491 ** --ssh-command SSH Use SSH as the "ssh" command
492 ** --transport-command CMD Use external command CMD to move message
493 ** between the client and the server
@@ -502,19 +506,27 @@
502 void sync_cmd(void){
503 unsigned configFlags = 0;
504 unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
505 if( find_option("unversioned","u",0)!=0 ){
506 syncFlags |= SYNC_UNVERSIONED;
 
 
 
 
 
 
507 }
508 process_sync_args(&configFlags, &syncFlags, 0, 0);
509
510 /* We should be done with options.. */
511 verify_all_options();
512
513 if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
514 if( (syncFlags & SYNC_PUSH)==0 ){
515 fossil_warning("pull only: the 'dont-push' option is set");
 
 
516 }
517 client_sync_all_urls(syncFlags, configFlags, 0, 0);
518 }
519
520 /*
521
--- src/sync.c
+++ src/sync.c
@@ -23,11 +23,11 @@
23
24 /*
25 ** Explain what type of sync operation is about to occur
26 */
27 static void sync_explain(unsigned syncFlags){
28 if( g.url.isAlias && (syncFlags & SYNC_QUIET)==0 ){
29 const char *url;
30 if( g.url.useProxy ){
31 url = g.url.proxyUrlCanonical;
32 }else{
33 url = g.url.canonical;
@@ -36,10 +36,12 @@
36 fossil_print("Sync with %s\n", url);
37 }else if( syncFlags & SYNC_PUSH ){
38 fossil_print("Push to %s\n", url);
39 }else if( syncFlags & SYNC_PULL ){
40 fossil_print("Pull from %s\n", url);
41 }else if( syncFlags & SYNC_PING ){
42 fossil_print("Ping %s\n", url);
43 }
44 }
45 }
46
47
@@ -307,11 +309,11 @@
309 ** URL is the server name. PAYLOAD is the name of a temporary file
310 ** that will contain the xfer-protocol payload to send to the server.
311 ** REPLY is a temporary filename in which COMMAND should write the
312 ** content of the reply from the server.
313 **
314 ** CMD is responsible for HTTP redirects. The following Fossil command
315 ** can be used for CMD to achieve a working sync:
316 **
317 ** fossil test-httpmsg --xfer
318 */
319 g.zHttpCmd = find_option("transport-command",0,1);
@@ -482,12 +484,14 @@
484 ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
485 ** if required by the remote website
486 ** --ipv4 Use only IPv4, not IPv6
487 ** --no-http-compression Do not compress HTTP traffic
488 ** --once Do not remember URL for subsequent syncs
489 ** --ping Just verify that the server is alive
490 ** --proxy PROXY Use the specified HTTP proxy
491 ** --private Sync private branches too
492 ** -q|--quiet Omit all output
493 ** -R|--repository REPO Local repository to sync with
494 ** --ssl-identity FILE Local SSL credentials, if requested by remote
495 ** --ssh-command SSH Use SSH as the "ssh" command
496 ** --transport-command CMD Use external command CMD to move message
497 ** between the client and the server
@@ -502,19 +506,27 @@
506 void sync_cmd(void){
507 unsigned configFlags = 0;
508 unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
509 if( find_option("unversioned","u",0)!=0 ){
510 syncFlags |= SYNC_UNVERSIONED;
511 }
512 if( find_option("ping",0,0)!=0 ){
513 syncFlags = SYNC_PING;
514 }
515 if( g.fQuiet ){
516 syncFlags |= SYNC_QUIET;
517 }
518 process_sync_args(&configFlags, &syncFlags, 0, 0);
519
520 /* We should be done with options.. */
521 verify_all_options();
522
523 if( (syncFlags & SYNC_PING)==0 ){
524 if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
525 if( (syncFlags & SYNC_PUSH)==0 ){
526 fossil_warning("pull only: the 'dont-push' option is set");
527 }
528 }
529 client_sync_all_urls(syncFlags, configFlags, 0, 0);
530 }
531
532 /*
533
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -422,11 +422,11 @@
422422
**
423423
** > fossil tag cancel ?--raw? TAGNAME ARTIFACT-ID
424424
**
425425
** Remove the tag TAGNAME from the artifact referenced by
426426
** ARTIFACT-ID, and also remove the propagation of the tag to
427
-** any descendants. Use the the -n|--dry-run option to see
427
+** any descendants. Use the -n|--dry-run option to see
428428
** what would have happened. Certain tag name prefixes are
429429
** forbidden, as documented for the 'add' subcommand.
430430
**
431431
** Options:
432432
** --date-override DATETIME Set date and time deleted
433433
--- src/tag.c
+++ src/tag.c
@@ -422,11 +422,11 @@
422 **
423 ** > fossil tag cancel ?--raw? TAGNAME ARTIFACT-ID
424 **
425 ** Remove the tag TAGNAME from the artifact referenced by
426 ** ARTIFACT-ID, and also remove the propagation of the tag to
427 ** any descendants. Use the the -n|--dry-run option to see
428 ** what would have happened. Certain tag name prefixes are
429 ** forbidden, as documented for the 'add' subcommand.
430 **
431 ** Options:
432 ** --date-override DATETIME Set date and time deleted
433
--- src/tag.c
+++ src/tag.c
@@ -422,11 +422,11 @@
422 **
423 ** > fossil tag cancel ?--raw? TAGNAME ARTIFACT-ID
424 **
425 ** Remove the tag TAGNAME from the artifact referenced by
426 ** ARTIFACT-ID, and also remove the propagation of the tag to
427 ** any descendants. Use the -n|--dry-run option to see
428 ** what would have happened. Certain tag name prefixes are
429 ** forbidden, as documented for the 'add' subcommand.
430 **
431 ** Options:
432 ** --date-override DATETIME Set date and time deleted
433
+3 -3
--- src/tar.c
+++ src/tar.c
@@ -809,11 +809,11 @@
809809
** /tarball/fossil-20251018193920-d6c9aee97df.tar.gz
810810
**
811811
** In other words, filename itself contains sufficient information to
812812
** uniquely identify the check-in, including a timestamp of the form
813813
** YYYYMMDDHHMMSS and a prefix of the check-in hash. The timestamp
814
-** and hash must immediately preceed the first "." in the name.
814
+** and hash must immediately precede the first "." in the name.
815815
*/
816816
char *tar_uuid_from_name(char **pzName){
817817
char *zName = *pzName; /* Original input */
818818
int n1 = 0; /* Bytes in first prefix (tag-name) */
819819
int n2 = 0; /* Bytes in second prefix (check-in-name) */
@@ -915,11 +915,11 @@
915915
** part of the name= value after the / is the download
916916
** filename. If no check-in is specified by either
917917
** name= or r=, then the name of the main branch
918918
** (usually "trunk") is used.
919919
**
920
-** in=PATTERN Only include files that match the comma-separate
920
+** in=PATTERN Only include files that match the comma-separated
921921
** list of GLOB patterns in PATTERN, as with ex=
922922
**
923923
** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
924924
** comma-separated list of GLOB patterns, where each
925925
** pattern can optionally be quoted using ".." or '..'.
@@ -1167,11 +1167,11 @@
11671167
&azItem, &anItem, &nItem);
11681168
bPlainTextCom = db_get_boolean("timeline-plaintext",0);
11691169
for(i=0; i<nItem-3; i+=4){
11701170
int cnt; /* The number of instances of zLabel to use */
11711171
char *zLabel; /* The label to match */
1172
- double rStart; /* Starting time, julian day number */
1172
+ double rStart; /* Starting time, Julian day number */
11731173
char *zComment = 0; /* Comment to apply */
11741174
if( anItem[i]==1 && azItem[i][0]=='*' ){
11751175
cnt = -1;
11761176
}else if( anItem[i]<1 ){
11771177
cnt = 0;
11781178
--- src/tar.c
+++ src/tar.c
@@ -809,11 +809,11 @@
809 ** /tarball/fossil-20251018193920-d6c9aee97df.tar.gz
810 **
811 ** In other words, filename itself contains sufficient information to
812 ** uniquely identify the check-in, including a timestamp of the form
813 ** YYYYMMDDHHMMSS and a prefix of the check-in hash. The timestamp
814 ** and hash must immediately preceed the first "." in the name.
815 */
816 char *tar_uuid_from_name(char **pzName){
817 char *zName = *pzName; /* Original input */
818 int n1 = 0; /* Bytes in first prefix (tag-name) */
819 int n2 = 0; /* Bytes in second prefix (check-in-name) */
@@ -915,11 +915,11 @@
915 ** part of the name= value after the / is the download
916 ** filename. If no check-in is specified by either
917 ** name= or r=, then the name of the main branch
918 ** (usually "trunk") is used.
919 **
920 ** in=PATTERN Only include files that match the comma-separate
921 ** list of GLOB patterns in PATTERN, as with ex=
922 **
923 ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
924 ** comma-separated list of GLOB patterns, where each
925 ** pattern can optionally be quoted using ".." or '..'.
@@ -1167,11 +1167,11 @@
1167 &azItem, &anItem, &nItem);
1168 bPlainTextCom = db_get_boolean("timeline-plaintext",0);
1169 for(i=0; i<nItem-3; i+=4){
1170 int cnt; /* The number of instances of zLabel to use */
1171 char *zLabel; /* The label to match */
1172 double rStart; /* Starting time, julian day number */
1173 char *zComment = 0; /* Comment to apply */
1174 if( anItem[i]==1 && azItem[i][0]=='*' ){
1175 cnt = -1;
1176 }else if( anItem[i]<1 ){
1177 cnt = 0;
1178
--- src/tar.c
+++ src/tar.c
@@ -809,11 +809,11 @@
809 ** /tarball/fossil-20251018193920-d6c9aee97df.tar.gz
810 **
811 ** In other words, filename itself contains sufficient information to
812 ** uniquely identify the check-in, including a timestamp of the form
813 ** YYYYMMDDHHMMSS and a prefix of the check-in hash. The timestamp
814 ** and hash must immediately precede the first "." in the name.
815 */
816 char *tar_uuid_from_name(char **pzName){
817 char *zName = *pzName; /* Original input */
818 int n1 = 0; /* Bytes in first prefix (tag-name) */
819 int n2 = 0; /* Bytes in second prefix (check-in-name) */
@@ -915,11 +915,11 @@
915 ** part of the name= value after the / is the download
916 ** filename. If no check-in is specified by either
917 ** name= or r=, then the name of the main branch
918 ** (usually "trunk") is used.
919 **
920 ** in=PATTERN Only include files that match the comma-separated
921 ** list of GLOB patterns in PATTERN, as with ex=
922 **
923 ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
924 ** comma-separated list of GLOB patterns, where each
925 ** pattern can optionally be quoted using ".." or '..'.
@@ -1167,11 +1167,11 @@
1167 &azItem, &anItem, &nItem);
1168 bPlainTextCom = db_get_boolean("timeline-plaintext",0);
1169 for(i=0; i<nItem-3; i+=4){
1170 int cnt; /* The number of instances of zLabel to use */
1171 char *zLabel; /* The label to match */
1172 double rStart; /* Starting time, Julian day number */
1173 char *zComment = 0; /* Comment to apply */
1174 if( anItem[i]==1 && azItem[i][0]=='*' ){
1175 cnt = -1;
1176 }else if( anItem[i]<1 ){
1177 cnt = 0;
1178
+1 -1
--- src/terminal.c
+++ src/terminal.c
@@ -45,11 +45,11 @@
4545
#endif
4646
4747
4848
/* Get the current terminal size by calling a system service.
4949
**
50
-** Return 1 on success. This sets the size parameters to the values retured by
50
+** Return 1 on success. This sets the size parameters to the values returned by
5151
** the system call, when such is supported; set the size to zero otherwise.
5252
** Return 0 on the system service call failure.
5353
**
5454
** Under Linux/bash the size info is also available from env $LINES, $COLUMNS.
5555
** Or it can be queried using tput `echo -e "lines\ncols"|tput -S`.
5656
--- src/terminal.c
+++ src/terminal.c
@@ -45,11 +45,11 @@
45 #endif
46
47
48 /* Get the current terminal size by calling a system service.
49 **
50 ** Return 1 on success. This sets the size parameters to the values retured by
51 ** the system call, when such is supported; set the size to zero otherwise.
52 ** Return 0 on the system service call failure.
53 **
54 ** Under Linux/bash the size info is also available from env $LINES, $COLUMNS.
55 ** Or it can be queried using tput `echo -e "lines\ncols"|tput -S`.
56
--- src/terminal.c
+++ src/terminal.c
@@ -45,11 +45,11 @@
45 #endif
46
47
48 /* Get the current terminal size by calling a system service.
49 **
50 ** Return 1 on success. This sets the size parameters to the values returned by
51 ** the system call, when such is supported; set the size to zero otherwise.
52 ** Return 0 on the system service call failure.
53 **
54 ** Under Linux/bash the size info is also available from env $LINES, $COLUMNS.
55 ** Or it can be queried using tput `echo -e "lines\ncols"|tput -S`.
56
+1 -1
--- src/th.c
+++ src/th.c
@@ -1029,11 +1029,11 @@
10291029
** * If iFrame is negative, then the nth frame up the stack, where
10301030
** n is the absolute value of iFrame. A value of -1 means the
10311031
** calling procedure.
10321032
**
10331033
** * If iFrame is +ve, then the nth frame from the bottom of the
1034
-** stack. An iFrame value of 1 means the toplevel (global) frame.
1034
+** stack. An iFrame value of 1 means the top level (global) frame.
10351035
*/
10361036
static Th_Frame *getFrame(Th_Interp *interp, int iFrame){
10371037
Th_Frame *p = interp->pFrame;
10381038
int i;
10391039
if( iFrame>0 ){
10401040
--- src/th.c
+++ src/th.c
@@ -1029,11 +1029,11 @@
1029 ** * If iFrame is negative, then the nth frame up the stack, where
1030 ** n is the absolute value of iFrame. A value of -1 means the
1031 ** calling procedure.
1032 **
1033 ** * If iFrame is +ve, then the nth frame from the bottom of the
1034 ** stack. An iFrame value of 1 means the toplevel (global) frame.
1035 */
1036 static Th_Frame *getFrame(Th_Interp *interp, int iFrame){
1037 Th_Frame *p = interp->pFrame;
1038 int i;
1039 if( iFrame>0 ){
1040
--- src/th.c
+++ src/th.c
@@ -1029,11 +1029,11 @@
1029 ** * If iFrame is negative, then the nth frame up the stack, where
1030 ** n is the absolute value of iFrame. A value of -1 means the
1031 ** calling procedure.
1032 **
1033 ** * If iFrame is +ve, then the nth frame from the bottom of the
1034 ** stack. An iFrame value of 1 means the top level (global) frame.
1035 */
1036 static Th_Frame *getFrame(Th_Interp *interp, int iFrame){
1037 Th_Frame *p = interp->pFrame;
1038 int i;
1039 if( iFrame>0 ){
1040
+5 -5
--- src/th_main.c
+++ src/th_main.c
@@ -74,11 +74,11 @@
7474
*/
7575
#if defined(TH_MEMDEBUG)
7676
/*
7777
** Global variable counting the number of outstanding calls to malloc()
7878
** made by the th1 implementation. This is used to catch memory leaks
79
-** in the interpreter. Obviously, it also means th1 is not threadsafe.
79
+** in the interpreter. Obviously, it also means th1 is not thread-safe.
8080
*/
8181
static int nOutstandingMalloc = 0;
8282
8383
/*
8484
** Implementations of malloc() and free() to pass to the interpreter.
@@ -151,13 +151,13 @@
151151
fossil_print("\n------------------- END TRACE LOG -------------------\n");
152152
}
153153
}
154154
155155
/*
156
-** - adopted from ls_cmd_rev in checkin.c
157
-** - adopted commands/error handling for usage within th1
158
-** - interface adopted to allow result creation as TH1 List
156
+** - adapted from ls_cmd_rev in checkin.c
157
+** - adapted commands/error handling for usage within th1
158
+** - interface adapted to allow result creation as TH1 List
159159
**
160160
** Takes a check-in identifier in zRev and an optiona glob pattern in zGLOB
161161
** as parameter returns a TH list in pzList,pnList with filenames matching
162162
** glob pattern with the checking
163163
*/
@@ -1065,11 +1065,11 @@
10651065
10661066
10671067
/*
10681068
** TH1 command: anycap STRING
10691069
**
1070
-** Return true if the current user user
1070
+** Return true if the current user
10711071
** has any one of the capabilities listed in STRING.
10721072
*/
10731073
static int anycapCmd(
10741074
Th_Interp *interp,
10751075
void *p,
10761076
--- src/th_main.c
+++ src/th_main.c
@@ -74,11 +74,11 @@
74 */
75 #if defined(TH_MEMDEBUG)
76 /*
77 ** Global variable counting the number of outstanding calls to malloc()
78 ** made by the th1 implementation. This is used to catch memory leaks
79 ** in the interpreter. Obviously, it also means th1 is not threadsafe.
80 */
81 static int nOutstandingMalloc = 0;
82
83 /*
84 ** Implementations of malloc() and free() to pass to the interpreter.
@@ -151,13 +151,13 @@
151 fossil_print("\n------------------- END TRACE LOG -------------------\n");
152 }
153 }
154
155 /*
156 ** - adopted from ls_cmd_rev in checkin.c
157 ** - adopted commands/error handling for usage within th1
158 ** - interface adopted to allow result creation as TH1 List
159 **
160 ** Takes a check-in identifier in zRev and an optiona glob pattern in zGLOB
161 ** as parameter returns a TH list in pzList,pnList with filenames matching
162 ** glob pattern with the checking
163 */
@@ -1065,11 +1065,11 @@
1065
1066
1067 /*
1068 ** TH1 command: anycap STRING
1069 **
1070 ** Return true if the current user user
1071 ** has any one of the capabilities listed in STRING.
1072 */
1073 static int anycapCmd(
1074 Th_Interp *interp,
1075 void *p,
1076
--- src/th_main.c
+++ src/th_main.c
@@ -74,11 +74,11 @@
74 */
75 #if defined(TH_MEMDEBUG)
76 /*
77 ** Global variable counting the number of outstanding calls to malloc()
78 ** made by the th1 implementation. This is used to catch memory leaks
79 ** in the interpreter. Obviously, it also means th1 is not thread-safe.
80 */
81 static int nOutstandingMalloc = 0;
82
83 /*
84 ** Implementations of malloc() and free() to pass to the interpreter.
@@ -151,13 +151,13 @@
151 fossil_print("\n------------------- END TRACE LOG -------------------\n");
152 }
153 }
154
155 /*
156 ** - adapted from ls_cmd_rev in checkin.c
157 ** - adapted commands/error handling for usage within th1
158 ** - interface adapted to allow result creation as TH1 List
159 **
160 ** Takes a check-in identifier in zRev and an optiona glob pattern in zGLOB
161 ** as parameter returns a TH list in pzList,pnList with filenames matching
162 ** glob pattern with the checking
163 */
@@ -1065,11 +1065,11 @@
1065
1066
1067 /*
1068 ** TH1 command: anycap STRING
1069 **
1070 ** Return true if the current user
1071 ** has any one of the capabilities listed in STRING.
1072 */
1073 static int anycapCmd(
1074 Th_Interp *interp,
1075 void *p,
1076
+19 -18
--- src/timeline.c
+++ src/timeline.c
@@ -22,11 +22,11 @@
2222
#include <string.h>
2323
#include <time.h>
2424
#include "timeline.h"
2525
2626
/*
27
-** The value of one second in julianday notation
27
+** The value of one second in Julian day notation
2828
*/
2929
#define ONE_SECOND (1.0/86400.0)
3030
3131
/*
3232
** timeline mode options
@@ -730,10 +730,14 @@
730730
** will simply be rendered in the older format. */
731731
wiki_convert(&comment, 0, WIKI_INLINE);
732732
}
733733
wiki_hyperlink_override(0);
734734
}else{
735
+ if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
736
+ blob_truncate_utf8(&comment, mxWikiLen);
737
+ blob_append(&comment, "...", 3);
738
+ }
735739
wiki_convert(&comment, 0, WIKI_INLINE);
736740
}
737741
}else{
738742
if( bCommentGitStyle ){
739743
/* Truncate comment at first blank line */
@@ -747,16 +751,13 @@
747751
}
748752
}
749753
z[ii] = 0;
750754
cgi_printf("%W",z);
751755
}else if( mxWikiLen>0 && (int)blob_size(&comment)>mxWikiLen ){
752
- Blob truncated;
753
- blob_zero(&truncated);
754
- blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
755
- blob_append(&truncated, "...", 3);
756
- @ %W(blob_str(&truncated))
757
- blob_reset(&truncated);
756
+ blob_truncate_utf8(&comment, mxWikiLen);
757
+ blob_append(&comment, "...", 3);
758
+ @ %W(blob_str(&comment))
758759
drawDetailEllipsis = 0;
759760
}else{
760761
cgi_printf("%W",blob_str(&comment));
761762
}
762763
}
@@ -1045,11 +1046,11 @@
10451046
** Mnemonic: "Same Branch".
10461047
** f: 0x01: a leaf node, 0x02: a closed leaf node.
10471048
** au: An array of integers that define thick-line risers for branches.
10481049
** The integers are in pairs. For each pair, the first integer is
10491050
** is the rail on which the riser should run and the second integer
1050
- ** is the id of the node upto which the riser should run. If there
1051
+ ** is the id of the node up to which the riser should run. If there
10511052
** are no risers, this array does not exist.
10521053
** mi: "merge-in". An array of integer rail positions from which
10531054
** merge arrows should be drawn into this node. If the value is
10541055
** negative, then the rail position is -1-mi[] and a thin merge-arrow
10551056
** descender is drawn to the bottom of the screen. This array is
@@ -1483,11 +1484,11 @@
14831484
14841485
/*
14851486
** Find the first check-in encountered with a particular tag
14861487
** when moving either forwards are backwards in time from a
14871488
** particular starting point (iFrom). Return the rid of that
1488
-** first check-in. If there are no check-ins in the descendent
1489
+** first check-in. If there are no check-ins in the descendant
14891490
** or ancestor set of check-in iFrom that match the tag, then
14901491
** return 0.
14911492
*/
14921493
static int timeline_endpoint(
14931494
int iFrom, /* Starting point */
@@ -1623,12 +1624,12 @@
16231624
** COMMAND: test-endpoint
16241625
**
16251626
** Usage: fossil test-endpoint BASE TAG ?OPTIONS?
16261627
**
16271628
** Show the first check-in with TAG that is a descendant or ancestor
1628
-** of BASE. The first descendant checkin is shown by default. Use
1629
-** the --backto to see the first ancestor checkin.
1629
+** of BASE. The first descendant check-in is shown by default. Use
1630
+** the --backto to see the first ancestor check-in.
16301631
**
16311632
** Options:
16321633
**
16331634
** --backto Show ancestor. Others defaults to descendants.
16341635
*/
@@ -1681,14 +1682,14 @@
16811682
** d2=CKIN2 ... Use CKIN2 if CHECKIN is not found
16821683
** ft=DESCENDANT ... going forward to DESCENDANT
16831684
** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
16841685
** dp2=CKIN2 Same as 'd2=CKIN2&p2=CKIN2'
16851686
** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1686
-** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
1687
+** bt=CHECKIN "Back To". Show ancestors going back to CHECKIN
16871688
** p=CX ... from CX back to time of CHECKIN
16881689
** from=CX ... path from CX back to CHECKIN
1689
-** ft=CHECKIN "Forward To": Show descendents forward to CHECKIN
1690
+** ft=CHECKIN "Forward To": Show descendants forward to CHECKIN
16901691
** d=CX ... from CX up to the time of CHECKIN
16911692
** from=CX ... path from CX up to CHECKIN
16921693
** t=TAG Show only check-ins with the given TAG
16931694
** r=TAG Same as 't=TAG&rel'. Mnemonic: "Related"
16941695
** tl=TAGLIST Same as 't=TAGLIST&ms=brlist'. Mnemonic: "Tag List"
@@ -1726,11 +1727,11 @@
17261727
** rel ... also show related checkins
17271728
** uf=FILE_HASH Show only check-ins that contain the given file version
17281729
** All qualifying check-ins are shown unless there is
17291730
** also an n= or n1= query parameter.
17301731
** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1731
-** name matches one of the comma-separate GLOBLIST
1732
+** name matches one of the comma-separated GLOBLIST
17321733
** brbg Background color determined by branch name
17331734
** ubg Background color determined by user
17341735
** deltabg Background color red for delta manifests or green
17351736
** for baseline manifests
17361737
** namechng Show only check-ins that have filename changes
@@ -1800,11 +1801,11 @@
18001801
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
18011802
int renameOnly = P("namechng")!=0; /* Show only check-ins that rename files */
18021803
int forkOnly = PB("forks"); /* Show only forks and their children */
18031804
int bisectLocal = PB("bisect"); /* Show the check-ins of the bisect */
18041805
const char *zBisect = P("bid"); /* Bisect description */
1805
- int cpOnly = PB("cherrypicks"); /* Show all cherrypick checkins */
1806
+ int cpOnly = PB("cherrypicks"); /* Show all cherrypick check-ins */
18061807
int tmFlags = 0; /* Timeline flags */
18071808
const char *zThisTag = 0; /* Suppress links to this tag */
18081809
const char *zThisUser = 0; /* Suppress links to this user */
18091810
HQuery url; /* URL for various branch links */
18101811
int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
@@ -2003,11 +2004,11 @@
20032004
/* Finish preliminary processing of tag match queries. */
20042005
matchStyle = match_style(zMatchStyle, MS_EXACT);
20052006
if( zTagName ){
20062007
zType = "ci";
20072008
if( matchStyle==MS_EXACT ){
2008
- /* For exact maching, inhibit links to the selected tag. */
2009
+ /* For exact matching, inhibit links to the selected tag. */
20092010
zThisTag = zTagName;
20102011
Th_StoreUnsafe("current_checkin", zTagName);
20112012
}
20122013
20132014
/* Display a checkbox to enable/disable display of related check-ins. */
@@ -3670,11 +3671,11 @@
36703671
&& fossil_isdigit(z[0])
36713672
&& fossil_isdigit(z[5]);
36723673
}
36733674
36743675
/*
3675
-** Return true if the input string can be converted to a julianday.
3676
+** Return true if the input string can be converted to a Julian day.
36763677
*/
36773678
static int fossil_is_julianday(const char *zDate){
36783679
return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
36793680
" WHERE jd IS NOT NULL)", zDate);
36803681
}
@@ -3728,11 +3729,11 @@
37283729
** -n|--limit N If N is positive, output the first N entries. If
37293730
** N is negative, output the first -N lines. If N is
37303731
** zero, no limit. Default is -20 meaning 20 lines.
37313732
** --offset P Skip P changes
37323733
** -p|--path PATH Output items affecting PATH only.
3733
-** PATH can be a file or a sub directory.
3734
+** PATH can be a file or a subdirectory.
37343735
** -r|--reverse Show items in chronological order.
37353736
** -R REPO_FILE Specifies the repository db to use. Default is
37363737
** the current check-out's repository.
37373738
** --sql Show the SQL used to generate the timeline
37383739
** -t|--type TYPE Output items from the given types only, such as:
37393740
--- src/timeline.c
+++ src/timeline.c
@@ -22,11 +22,11 @@
22 #include <string.h>
23 #include <time.h>
24 #include "timeline.h"
25
26 /*
27 ** The value of one second in julianday notation
28 */
29 #define ONE_SECOND (1.0/86400.0)
30
31 /*
32 ** timeline mode options
@@ -730,10 +730,14 @@
730 ** will simply be rendered in the older format. */
731 wiki_convert(&comment, 0, WIKI_INLINE);
732 }
733 wiki_hyperlink_override(0);
734 }else{
 
 
 
 
735 wiki_convert(&comment, 0, WIKI_INLINE);
736 }
737 }else{
738 if( bCommentGitStyle ){
739 /* Truncate comment at first blank line */
@@ -747,16 +751,13 @@
747 }
748 }
749 z[ii] = 0;
750 cgi_printf("%W",z);
751 }else if( mxWikiLen>0 && (int)blob_size(&comment)>mxWikiLen ){
752 Blob truncated;
753 blob_zero(&truncated);
754 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
755 blob_append(&truncated, "...", 3);
756 @ %W(blob_str(&truncated))
757 blob_reset(&truncated);
758 drawDetailEllipsis = 0;
759 }else{
760 cgi_printf("%W",blob_str(&comment));
761 }
762 }
@@ -1045,11 +1046,11 @@
1045 ** Mnemonic: "Same Branch".
1046 ** f: 0x01: a leaf node, 0x02: a closed leaf node.
1047 ** au: An array of integers that define thick-line risers for branches.
1048 ** The integers are in pairs. For each pair, the first integer is
1049 ** is the rail on which the riser should run and the second integer
1050 ** is the id of the node upto which the riser should run. If there
1051 ** are no risers, this array does not exist.
1052 ** mi: "merge-in". An array of integer rail positions from which
1053 ** merge arrows should be drawn into this node. If the value is
1054 ** negative, then the rail position is -1-mi[] and a thin merge-arrow
1055 ** descender is drawn to the bottom of the screen. This array is
@@ -1483,11 +1484,11 @@
1483
1484 /*
1485 ** Find the first check-in encountered with a particular tag
1486 ** when moving either forwards are backwards in time from a
1487 ** particular starting point (iFrom). Return the rid of that
1488 ** first check-in. If there are no check-ins in the descendent
1489 ** or ancestor set of check-in iFrom that match the tag, then
1490 ** return 0.
1491 */
1492 static int timeline_endpoint(
1493 int iFrom, /* Starting point */
@@ -1623,12 +1624,12 @@
1623 ** COMMAND: test-endpoint
1624 **
1625 ** Usage: fossil test-endpoint BASE TAG ?OPTIONS?
1626 **
1627 ** Show the first check-in with TAG that is a descendant or ancestor
1628 ** of BASE. The first descendant checkin is shown by default. Use
1629 ** the --backto to see the first ancestor checkin.
1630 **
1631 ** Options:
1632 **
1633 ** --backto Show ancestor. Others defaults to descendants.
1634 */
@@ -1681,14 +1682,14 @@
1681 ** d2=CKIN2 ... Use CKIN2 if CHECKIN is not found
1682 ** ft=DESCENDANT ... going forward to DESCENDANT
1683 ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
1684 ** dp2=CKIN2 Same as 'd2=CKIN2&p2=CKIN2'
1685 ** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1686 ** bt=CHECKIN "Back To". Show ancenstors going back to CHECKIN
1687 ** p=CX ... from CX back to time of CHECKIN
1688 ** from=CX ... path from CX back to CHECKIN
1689 ** ft=CHECKIN "Forward To": Show descendents forward to CHECKIN
1690 ** d=CX ... from CX up to the time of CHECKIN
1691 ** from=CX ... path from CX up to CHECKIN
1692 ** t=TAG Show only check-ins with the given TAG
1693 ** r=TAG Same as 't=TAG&rel'. Mnemonic: "Related"
1694 ** tl=TAGLIST Same as 't=TAGLIST&ms=brlist'. Mnemonic: "Tag List"
@@ -1726,11 +1727,11 @@
1726 ** rel ... also show related checkins
1727 ** uf=FILE_HASH Show only check-ins that contain the given file version
1728 ** All qualifying check-ins are shown unless there is
1729 ** also an n= or n1= query parameter.
1730 ** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1731 ** name matches one of the comma-separate GLOBLIST
1732 ** brbg Background color determined by branch name
1733 ** ubg Background color determined by user
1734 ** deltabg Background color red for delta manifests or green
1735 ** for baseline manifests
1736 ** namechng Show only check-ins that have filename changes
@@ -1800,11 +1801,11 @@
1800 int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
1801 int renameOnly = P("namechng")!=0; /* Show only check-ins that rename files */
1802 int forkOnly = PB("forks"); /* Show only forks and their children */
1803 int bisectLocal = PB("bisect"); /* Show the check-ins of the bisect */
1804 const char *zBisect = P("bid"); /* Bisect description */
1805 int cpOnly = PB("cherrypicks"); /* Show all cherrypick checkins */
1806 int tmFlags = 0; /* Timeline flags */
1807 const char *zThisTag = 0; /* Suppress links to this tag */
1808 const char *zThisUser = 0; /* Suppress links to this user */
1809 HQuery url; /* URL for various branch links */
1810 int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
@@ -2003,11 +2004,11 @@
2003 /* Finish preliminary processing of tag match queries. */
2004 matchStyle = match_style(zMatchStyle, MS_EXACT);
2005 if( zTagName ){
2006 zType = "ci";
2007 if( matchStyle==MS_EXACT ){
2008 /* For exact maching, inhibit links to the selected tag. */
2009 zThisTag = zTagName;
2010 Th_StoreUnsafe("current_checkin", zTagName);
2011 }
2012
2013 /* Display a checkbox to enable/disable display of related check-ins. */
@@ -3670,11 +3671,11 @@
3670 && fossil_isdigit(z[0])
3671 && fossil_isdigit(z[5]);
3672 }
3673
3674 /*
3675 ** Return true if the input string can be converted to a julianday.
3676 */
3677 static int fossil_is_julianday(const char *zDate){
3678 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
3679 " WHERE jd IS NOT NULL)", zDate);
3680 }
@@ -3728,11 +3729,11 @@
3728 ** -n|--limit N If N is positive, output the first N entries. If
3729 ** N is negative, output the first -N lines. If N is
3730 ** zero, no limit. Default is -20 meaning 20 lines.
3731 ** --offset P Skip P changes
3732 ** -p|--path PATH Output items affecting PATH only.
3733 ** PATH can be a file or a sub directory.
3734 ** -r|--reverse Show items in chronological order.
3735 ** -R REPO_FILE Specifies the repository db to use. Default is
3736 ** the current check-out's repository.
3737 ** --sql Show the SQL used to generate the timeline
3738 ** -t|--type TYPE Output items from the given types only, such as:
3739
--- src/timeline.c
+++ src/timeline.c
@@ -22,11 +22,11 @@
22 #include <string.h>
23 #include <time.h>
24 #include "timeline.h"
25
26 /*
27 ** The value of one second in Julian day notation
28 */
29 #define ONE_SECOND (1.0/86400.0)
30
31 /*
32 ** timeline mode options
@@ -730,10 +730,14 @@
730 ** will simply be rendered in the older format. */
731 wiki_convert(&comment, 0, WIKI_INLINE);
732 }
733 wiki_hyperlink_override(0);
734 }else{
735 if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
736 blob_truncate_utf8(&comment, mxWikiLen);
737 blob_append(&comment, "...", 3);
738 }
739 wiki_convert(&comment, 0, WIKI_INLINE);
740 }
741 }else{
742 if( bCommentGitStyle ){
743 /* Truncate comment at first blank line */
@@ -747,16 +751,13 @@
751 }
752 }
753 z[ii] = 0;
754 cgi_printf("%W",z);
755 }else if( mxWikiLen>0 && (int)blob_size(&comment)>mxWikiLen ){
756 blob_truncate_utf8(&comment, mxWikiLen);
757 blob_append(&comment, "...", 3);
758 @ %W(blob_str(&comment))
 
 
 
759 drawDetailEllipsis = 0;
760 }else{
761 cgi_printf("%W",blob_str(&comment));
762 }
763 }
@@ -1045,11 +1046,11 @@
1046 ** Mnemonic: "Same Branch".
1047 ** f: 0x01: a leaf node, 0x02: a closed leaf node.
1048 ** au: An array of integers that define thick-line risers for branches.
1049 ** The integers are in pairs. For each pair, the first integer is
1050 ** is the rail on which the riser should run and the second integer
1051 ** is the id of the node up to which the riser should run. If there
1052 ** are no risers, this array does not exist.
1053 ** mi: "merge-in". An array of integer rail positions from which
1054 ** merge arrows should be drawn into this node. If the value is
1055 ** negative, then the rail position is -1-mi[] and a thin merge-arrow
1056 ** descender is drawn to the bottom of the screen. This array is
@@ -1483,11 +1484,11 @@
1484
1485 /*
1486 ** Find the first check-in encountered with a particular tag
1487 ** when moving either forwards are backwards in time from a
1488 ** particular starting point (iFrom). Return the rid of that
1489 ** first check-in. If there are no check-ins in the descendant
1490 ** or ancestor set of check-in iFrom that match the tag, then
1491 ** return 0.
1492 */
1493 static int timeline_endpoint(
1494 int iFrom, /* Starting point */
@@ -1623,12 +1624,12 @@
1624 ** COMMAND: test-endpoint
1625 **
1626 ** Usage: fossil test-endpoint BASE TAG ?OPTIONS?
1627 **
1628 ** Show the first check-in with TAG that is a descendant or ancestor
1629 ** of BASE. The first descendant check-in is shown by default. Use
1630 ** the --backto to see the first ancestor check-in.
1631 **
1632 ** Options:
1633 **
1634 ** --backto Show ancestor. Others defaults to descendants.
1635 */
@@ -1681,14 +1682,14 @@
1682 ** d2=CKIN2 ... Use CKIN2 if CHECKIN is not found
1683 ** ft=DESCENDANT ... going forward to DESCENDANT
1684 ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN'
1685 ** dp2=CKIN2 Same as 'd2=CKIN2&p2=CKIN2'
1686 ** df=CHECKIN Same as 'd=CHECKIN&n1=all&nd'. Mnemonic: "Derived From"
1687 ** bt=CHECKIN "Back To". Show ancestors going back to CHECKIN
1688 ** p=CX ... from CX back to time of CHECKIN
1689 ** from=CX ... path from CX back to CHECKIN
1690 ** ft=CHECKIN "Forward To": Show descendants forward to CHECKIN
1691 ** d=CX ... from CX up to the time of CHECKIN
1692 ** from=CX ... path from CX up to CHECKIN
1693 ** t=TAG Show only check-ins with the given TAG
1694 ** r=TAG Same as 't=TAG&rel'. Mnemonic: "Related"
1695 ** tl=TAGLIST Same as 't=TAGLIST&ms=brlist'. Mnemonic: "Tag List"
@@ -1726,11 +1727,11 @@
1727 ** rel ... also show related checkins
1728 ** uf=FILE_HASH Show only check-ins that contain the given file version
1729 ** All qualifying check-ins are shown unless there is
1730 ** also an n= or n1= query parameter.
1731 ** chng=GLOBLIST Show only check-ins that involve changes to a file whose
1732 ** name matches one of the comma-separated GLOBLIST
1733 ** brbg Background color determined by branch name
1734 ** ubg Background color determined by user
1735 ** deltabg Background color red for delta manifests or green
1736 ** for baseline manifests
1737 ** namechng Show only check-ins that have filename changes
@@ -1800,11 +1801,11 @@
1801 int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
1802 int renameOnly = P("namechng")!=0; /* Show only check-ins that rename files */
1803 int forkOnly = PB("forks"); /* Show only forks and their children */
1804 int bisectLocal = PB("bisect"); /* Show the check-ins of the bisect */
1805 const char *zBisect = P("bid"); /* Bisect description */
1806 int cpOnly = PB("cherrypicks"); /* Show all cherrypick check-ins */
1807 int tmFlags = 0; /* Timeline flags */
1808 const char *zThisTag = 0; /* Suppress links to this tag */
1809 const char *zThisUser = 0; /* Suppress links to this user */
1810 HQuery url; /* URL for various branch links */
1811 int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
@@ -2003,11 +2004,11 @@
2004 /* Finish preliminary processing of tag match queries. */
2005 matchStyle = match_style(zMatchStyle, MS_EXACT);
2006 if( zTagName ){
2007 zType = "ci";
2008 if( matchStyle==MS_EXACT ){
2009 /* For exact matching, inhibit links to the selected tag. */
2010 zThisTag = zTagName;
2011 Th_StoreUnsafe("current_checkin", zTagName);
2012 }
2013
2014 /* Display a checkbox to enable/disable display of related check-ins. */
@@ -3670,11 +3671,11 @@
3671 && fossil_isdigit(z[0])
3672 && fossil_isdigit(z[5]);
3673 }
3674
3675 /*
3676 ** Return true if the input string can be converted to a Julian day.
3677 */
3678 static int fossil_is_julianday(const char *zDate){
3679 return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd"
3680 " WHERE jd IS NOT NULL)", zDate);
3681 }
@@ -3728,11 +3729,11 @@
3729 ** -n|--limit N If N is positive, output the first N entries. If
3730 ** N is negative, output the first -N lines. If N is
3731 ** zero, no limit. Default is -20 meaning 20 lines.
3732 ** --offset P Skip P changes
3733 ** -p|--path PATH Output items affecting PATH only.
3734 ** PATH can be a file or a subdirectory.
3735 ** -r|--reverse Show items in chronological order.
3736 ** -R REPO_FILE Specifies the repository db to use. Default is
3737 ** the current check-out's repository.
3738 ** --sql Show the SQL used to generate the timeline
3739 ** -t|--type TYPE Output items from the given types only, such as:
3740
+7 -7
--- src/tkt.c
+++ src/tkt.c
@@ -1520,19 +1520,19 @@
15201520
**
15211521
** > fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?OPTIONS?
15221522
**
15231523
** Options:
15241524
** -l|--limit LIMITCHAR
1525
-** -q|--quote
1525
+** --quote
15261526
** -R|--repository REPO
15271527
**
15281528
** Run the ticket report, identified by the report format title
15291529
** used in the GUI. The data is written as flat file on stdout,
15301530
** using TAB as separator. The separator can be changed using
15311531
** the -l or --limit option.
15321532
**
1533
-** If TICKETFILTER is given on the commandline, the query is
1533
+** If TICKETFILTER is given on the command line, the query is
15341534
** limited with a new WHERE-condition.
15351535
** example: Report lists a column # with the uuid
15361536
** TICKETFILTER may be [#]='uuuuuuuuu'
15371537
** example: Report only lists rows with status not open
15381538
** TICKETFILTER: status != 'open'
@@ -1555,12 +1555,12 @@
15551555
** > fossil ticket list reports
15561556
** > fossil ticket ls reports
15571557
**
15581558
** List all ticket reports defined in the fossil repository.
15591559
**
1560
-** > fossil ticket set TICKETUUID (FIELD VALUE)+ ?-q|--quote?
1561
-** > fossil ticket change TICKETUUID (FIELD VALUE)+ ?-q|--quote?
1560
+** > fossil ticket set TICKETUUID (FIELD VALUE)+ ?--quote?
1561
+** > fossil ticket change TICKETUUID (FIELD VALUE)+ ?--quote?
15621562
**
15631563
** Change ticket identified by TICKETUUID to set the values of
15641564
** each field FIELD to VALUE.
15651565
**
15661566
** Field names as defined in the TICKET table. By default, these
@@ -1567,16 +1567,16 @@
15671567
** names include: type, status, subsystem, priority, severity, foundin,
15681568
** resolution, title, and comment, but other field names can be added
15691569
** or substituted in customized installations.
15701570
**
15711571
** If you use +FIELD, the VALUE is appended to the field FIELD. You
1572
-** can use more than one field/value pair on the commandline. Using
1572
+** can use more than one field/value pair on the command line. Using
15731573
** --quote enables the special character decoding as in "ticket
15741574
** show", which allows setting multiline text or text with special
15751575
** characters.
15761576
**
1577
-** > fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote?
1577
+** > fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?--quote?
15781578
**
15791579
** Like set, but create a new ticket with the given values.
15801580
**
15811581
** > fossil ticket history TICKETUUID
15821582
**
@@ -1642,11 +1642,11 @@
16421642
}
16431643
}else{
16441644
/* add a new ticket or set fields on existing tickets */
16451645
tTktShowEncoding tktEncoding;
16461646
1647
- tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab;
1647
+ tktEncoding = find_option("quote",0,0) ? tktFossilize : tktNoTab;
16481648
16491649
if( strncmp(g.argv[2],"show",n)==0 ){
16501650
if( g.argc==3 ){
16511651
usage("show REPORTNR");
16521652
}else{
16531653
--- src/tkt.c
+++ src/tkt.c
@@ -1520,19 +1520,19 @@
1520 **
1521 ** > fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?OPTIONS?
1522 **
1523 ** Options:
1524 ** -l|--limit LIMITCHAR
1525 ** -q|--quote
1526 ** -R|--repository REPO
1527 **
1528 ** Run the ticket report, identified by the report format title
1529 ** used in the GUI. The data is written as flat file on stdout,
1530 ** using TAB as separator. The separator can be changed using
1531 ** the -l or --limit option.
1532 **
1533 ** If TICKETFILTER is given on the commandline, the query is
1534 ** limited with a new WHERE-condition.
1535 ** example: Report lists a column # with the uuid
1536 ** TICKETFILTER may be [#]='uuuuuuuuu'
1537 ** example: Report only lists rows with status not open
1538 ** TICKETFILTER: status != 'open'
@@ -1555,12 +1555,12 @@
1555 ** > fossil ticket list reports
1556 ** > fossil ticket ls reports
1557 **
1558 ** List all ticket reports defined in the fossil repository.
1559 **
1560 ** > fossil ticket set TICKETUUID (FIELD VALUE)+ ?-q|--quote?
1561 ** > fossil ticket change TICKETUUID (FIELD VALUE)+ ?-q|--quote?
1562 **
1563 ** Change ticket identified by TICKETUUID to set the values of
1564 ** each field FIELD to VALUE.
1565 **
1566 ** Field names as defined in the TICKET table. By default, these
@@ -1567,16 +1567,16 @@
1567 ** names include: type, status, subsystem, priority, severity, foundin,
1568 ** resolution, title, and comment, but other field names can be added
1569 ** or substituted in customized installations.
1570 **
1571 ** If you use +FIELD, the VALUE is appended to the field FIELD. You
1572 ** can use more than one field/value pair on the commandline. Using
1573 ** --quote enables the special character decoding as in "ticket
1574 ** show", which allows setting multiline text or text with special
1575 ** characters.
1576 **
1577 ** > fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote?
1578 **
1579 ** Like set, but create a new ticket with the given values.
1580 **
1581 ** > fossil ticket history TICKETUUID
1582 **
@@ -1642,11 +1642,11 @@
1642 }
1643 }else{
1644 /* add a new ticket or set fields on existing tickets */
1645 tTktShowEncoding tktEncoding;
1646
1647 tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab;
1648
1649 if( strncmp(g.argv[2],"show",n)==0 ){
1650 if( g.argc==3 ){
1651 usage("show REPORTNR");
1652 }else{
1653
--- src/tkt.c
+++ src/tkt.c
@@ -1520,19 +1520,19 @@
1520 **
1521 ** > fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?OPTIONS?
1522 **
1523 ** Options:
1524 ** -l|--limit LIMITCHAR
1525 ** --quote
1526 ** -R|--repository REPO
1527 **
1528 ** Run the ticket report, identified by the report format title
1529 ** used in the GUI. The data is written as flat file on stdout,
1530 ** using TAB as separator. The separator can be changed using
1531 ** the -l or --limit option.
1532 **
1533 ** If TICKETFILTER is given on the command line, the query is
1534 ** limited with a new WHERE-condition.
1535 ** example: Report lists a column # with the uuid
1536 ** TICKETFILTER may be [#]='uuuuuuuuu'
1537 ** example: Report only lists rows with status not open
1538 ** TICKETFILTER: status != 'open'
@@ -1555,12 +1555,12 @@
1555 ** > fossil ticket list reports
1556 ** > fossil ticket ls reports
1557 **
1558 ** List all ticket reports defined in the fossil repository.
1559 **
1560 ** > fossil ticket set TICKETUUID (FIELD VALUE)+ ?--quote?
1561 ** > fossil ticket change TICKETUUID (FIELD VALUE)+ ?--quote?
1562 **
1563 ** Change ticket identified by TICKETUUID to set the values of
1564 ** each field FIELD to VALUE.
1565 **
1566 ** Field names as defined in the TICKET table. By default, these
@@ -1567,16 +1567,16 @@
1567 ** names include: type, status, subsystem, priority, severity, foundin,
1568 ** resolution, title, and comment, but other field names can be added
1569 ** or substituted in customized installations.
1570 **
1571 ** If you use +FIELD, the VALUE is appended to the field FIELD. You
1572 ** can use more than one field/value pair on the command line. Using
1573 ** --quote enables the special character decoding as in "ticket
1574 ** show", which allows setting multiline text or text with special
1575 ** characters.
1576 **
1577 ** > fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?--quote?
1578 **
1579 ** Like set, but create a new ticket with the given values.
1580 **
1581 ** > fossil ticket history TICKETUUID
1582 **
@@ -1642,11 +1642,11 @@
1642 }
1643 }else{
1644 /* add a new ticket or set fields on existing tickets */
1645 tTktShowEncoding tktEncoding;
1646
1647 tktEncoding = find_option("quote",0,0) ? tktFossilize : tktNoTab;
1648
1649 if( strncmp(g.argv[2],"show",n)==0 ){
1650 if( g.argc==3 ){
1651 usage("show REPORTNR");
1652 }else{
1653
+1 -1
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -1018,11 +1018,11 @@
10181018
}
10191019
10201020
/*
10211021
** WEBPAGE: tktsetup_timeline
10221022
**
1023
-** Administrative page used ot configure how tickets are
1023
+** Administrative page used to configure how tickets are
10241024
** rendered on timeline views.
10251025
*/
10261026
void tktsetup_timeline_page(void){
10271027
login_check_credentials();
10281028
if( !g.perm.Setup ){
10291029
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -1018,11 +1018,11 @@
1018 }
1019
1020 /*
1021 ** WEBPAGE: tktsetup_timeline
1022 **
1023 ** Administrative page used ot configure how tickets are
1024 ** rendered on timeline views.
1025 */
1026 void tktsetup_timeline_page(void){
1027 login_check_credentials();
1028 if( !g.perm.Setup ){
1029
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -1018,11 +1018,11 @@
1018 }
1019
1020 /*
1021 ** WEBPAGE: tktsetup_timeline
1022 **
1023 ** Administrative page used to configure how tickets are
1024 ** rendered on timeline views.
1025 */
1026 void tktsetup_timeline_page(void){
1027 login_check_credentials();
1028 if( !g.perm.Setup ){
1029
+2 -2
--- src/undo.c
+++ src/undo.c
@@ -23,11 +23,11 @@
2323
#if INTERFACE
2424
/*
2525
** Possible return values from the undo_maybe_save() routine.
2626
*/
2727
#define UNDO_NONE (0) /* Placeholder only used to initialize vars. */
28
-#define UNDO_SAVED_OK (1) /* The specified file was saved succesfully. */
28
+#define UNDO_SAVED_OK (1) /* The specified file was saved successfully. */
2929
#define UNDO_DISABLED (2) /* File not saved, subsystem is disabled. */
3030
#define UNDO_INACTIVE (3) /* File not saved, subsystem is not active. */
3131
#define UNDO_TOOBIG (4) /* File not saved, it exceeded a size limit. */
3232
#endif
3333
@@ -289,11 +289,11 @@
289289
** function instead.
290290
**
291291
** The return value of this function will always be one of the
292292
** following codes:
293293
**
294
-** UNDO_SAVED_OK: The specified file was saved succesfully.
294
+** UNDO_SAVED_OK: The specified file was saved successfully.
295295
**
296296
** UNDO_DISABLED: The specified file was NOT saved, because the
297297
** "undo subsystem" is disabled. This error may
298298
** indicate that a call to undo_disable() was
299299
** issued.
300300
--- src/undo.c
+++ src/undo.c
@@ -23,11 +23,11 @@
23 #if INTERFACE
24 /*
25 ** Possible return values from the undo_maybe_save() routine.
26 */
27 #define UNDO_NONE (0) /* Placeholder only used to initialize vars. */
28 #define UNDO_SAVED_OK (1) /* The specified file was saved succesfully. */
29 #define UNDO_DISABLED (2) /* File not saved, subsystem is disabled. */
30 #define UNDO_INACTIVE (3) /* File not saved, subsystem is not active. */
31 #define UNDO_TOOBIG (4) /* File not saved, it exceeded a size limit. */
32 #endif
33
@@ -289,11 +289,11 @@
289 ** function instead.
290 **
291 ** The return value of this function will always be one of the
292 ** following codes:
293 **
294 ** UNDO_SAVED_OK: The specified file was saved succesfully.
295 **
296 ** UNDO_DISABLED: The specified file was NOT saved, because the
297 ** "undo subsystem" is disabled. This error may
298 ** indicate that a call to undo_disable() was
299 ** issued.
300
--- src/undo.c
+++ src/undo.c
@@ -23,11 +23,11 @@
23 #if INTERFACE
24 /*
25 ** Possible return values from the undo_maybe_save() routine.
26 */
27 #define UNDO_NONE (0) /* Placeholder only used to initialize vars. */
28 #define UNDO_SAVED_OK (1) /* The specified file was saved successfully. */
29 #define UNDO_DISABLED (2) /* File not saved, subsystem is disabled. */
30 #define UNDO_INACTIVE (3) /* File not saved, subsystem is not active. */
31 #define UNDO_TOOBIG (4) /* File not saved, it exceeded a size limit. */
32 #endif
33
@@ -289,11 +289,11 @@
289 ** function instead.
290 **
291 ** The return value of this function will always be one of the
292 ** following codes:
293 **
294 ** UNDO_SAVED_OK: The specified file was saved successfully.
295 **
296 ** UNDO_DISABLED: The specified file was NOT saved, because the
297 ** "undo subsystem" is disabled. This error may
298 ** indicate that a call to undo_disable() was
299 ** issued.
300
+1 -1
--- src/unicode.c
+++ src/unicode.c
@@ -189,11 +189,11 @@
189189
/*
190190
** If the argument is a codepoint corresponding to a lowercase letter
191191
** in the ASCII range with a diacritic added, return the codepoint
192192
** of the ASCII letter only. For example, if passed 235 - "LATIN
193193
** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
194
-** E"). The resuls of passing a codepoint that corresponds to an
194
+** E"). The results of passing a codepoint that corresponds to an
195195
** uppercase letter are undefined.
196196
*/
197197
static int unicode_remove_diacritic(int c, int bComplex){
198198
static const unsigned short aDia[] = {
199199
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
200200
--- src/unicode.c
+++ src/unicode.c
@@ -189,11 +189,11 @@
189 /*
190 ** If the argument is a codepoint corresponding to a lowercase letter
191 ** in the ASCII range with a diacritic added, return the codepoint
192 ** of the ASCII letter only. For example, if passed 235 - "LATIN
193 ** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
194 ** E"). The resuls of passing a codepoint that corresponds to an
195 ** uppercase letter are undefined.
196 */
197 static int unicode_remove_diacritic(int c, int bComplex){
198 static const unsigned short aDia[] = {
199 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
200
--- src/unicode.c
+++ src/unicode.c
@@ -189,11 +189,11 @@
189 /*
190 ** If the argument is a codepoint corresponding to a lowercase letter
191 ** in the ASCII range with a diacritic added, return the codepoint
192 ** of the ASCII letter only. For example, if passed 235 - "LATIN
193 ** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
194 ** E"). The results of passing a codepoint that corresponds to an
195 ** uppercase letter are undefined.
196 */
197 static int unicode_remove_diacritic(int c, int bComplex){
198 static const unsigned short aDia[] = {
199 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
200
+3 -3
--- src/update.c
+++ src/update.c
@@ -88,11 +88,11 @@
8888
** The -n or --dry-run option causes this command to do a "dry run".
8989
** It prints out what would have happened but does not actually make
9090
** any changes to the current check-out or the repository.
9191
**
9292
** The -v or --verbose option prints status information about
93
-** unchanged files in addition to those file that actually do change.
93
+** unchanged files in addition to those files that actually do change.
9494
**
9595
** Options:
9696
** --case-sensitive BOOL Override case-sensitive setting
9797
** --debug Print debug information on stdout
9898
** -n|--dry-run If given, display instead of run actions
@@ -256,11 +256,11 @@
256256
fossil_fatal("missing content, unable to update");
257257
};
258258
259259
/*
260260
** The record.fn field is used to match files against each other. The
261
- ** FV table contains one row for each each unique filename in
261
+ ** FV table contains one row for each unique filename in
262262
** in the current check-out, the pivot, and the version being merged.
263263
*/
264264
db_multi_exec(
265265
"DROP TABLE IF EXISTS fv;"
266266
"CREATE TEMP TABLE fv("
@@ -451,11 +451,11 @@
451451
}else if( idt>0 && idv==0 ){
452452
/* File added in the target. */
453453
if( file_isfile_or_link(zFullPath) ){
454454
/* Name of backup file with Original content */
455455
char *zOrig = file_newname(zFullPath, "original", 1);
456
- /* Backup previously unanaged file before to be overwritten */
456
+ /* Backup previously unmanaged file before being overwritten */
457457
file_copy(zFullPath, zOrig);
458458
fossil_free(zOrig);
459459
fossil_print("ADD %s - overwrites an unmanaged file", zName);
460460
if( !dryRunFlag ) fossil_print(", original copy backed up locally");
461461
fossil_print("\n");
462462
--- src/update.c
+++ src/update.c
@@ -88,11 +88,11 @@
88 ** The -n or --dry-run option causes this command to do a "dry run".
89 ** It prints out what would have happened but does not actually make
90 ** any changes to the current check-out or the repository.
91 **
92 ** The -v or --verbose option prints status information about
93 ** unchanged files in addition to those file that actually do change.
94 **
95 ** Options:
96 ** --case-sensitive BOOL Override case-sensitive setting
97 ** --debug Print debug information on stdout
98 ** -n|--dry-run If given, display instead of run actions
@@ -256,11 +256,11 @@
256 fossil_fatal("missing content, unable to update");
257 };
258
259 /*
260 ** The record.fn field is used to match files against each other. The
261 ** FV table contains one row for each each unique filename in
262 ** in the current check-out, the pivot, and the version being merged.
263 */
264 db_multi_exec(
265 "DROP TABLE IF EXISTS fv;"
266 "CREATE TEMP TABLE fv("
@@ -451,11 +451,11 @@
451 }else if( idt>0 && idv==0 ){
452 /* File added in the target. */
453 if( file_isfile_or_link(zFullPath) ){
454 /* Name of backup file with Original content */
455 char *zOrig = file_newname(zFullPath, "original", 1);
456 /* Backup previously unanaged file before to be overwritten */
457 file_copy(zFullPath, zOrig);
458 fossil_free(zOrig);
459 fossil_print("ADD %s - overwrites an unmanaged file", zName);
460 if( !dryRunFlag ) fossil_print(", original copy backed up locally");
461 fossil_print("\n");
462
--- src/update.c
+++ src/update.c
@@ -88,11 +88,11 @@
88 ** The -n or --dry-run option causes this command to do a "dry run".
89 ** It prints out what would have happened but does not actually make
90 ** any changes to the current check-out or the repository.
91 **
92 ** The -v or --verbose option prints status information about
93 ** unchanged files in addition to those files that actually do change.
94 **
95 ** Options:
96 ** --case-sensitive BOOL Override case-sensitive setting
97 ** --debug Print debug information on stdout
98 ** -n|--dry-run If given, display instead of run actions
@@ -256,11 +256,11 @@
256 fossil_fatal("missing content, unable to update");
257 };
258
259 /*
260 ** The record.fn field is used to match files against each other. The
261 ** FV table contains one row for each unique filename in
262 ** in the current check-out, the pivot, and the version being merged.
263 */
264 db_multi_exec(
265 "DROP TABLE IF EXISTS fv;"
266 "CREATE TEMP TABLE fv("
@@ -451,11 +451,11 @@
451 }else if( idt>0 && idv==0 ){
452 /* File added in the target. */
453 if( file_isfile_or_link(zFullPath) ){
454 /* Name of backup file with Original content */
455 char *zOrig = file_newname(zFullPath, "original", 1);
456 /* Backup previously unmanaged file before being overwritten */
457 file_copy(zFullPath, zOrig);
458 fossil_free(zOrig);
459 fossil_print("ADD %s - overwrites an unmanaged file", zName);
460 if( !dryRunFlag ) fossil_print(", original copy backed up locally");
461 fossil_print("\n");
462
+8 -5
--- src/util.c
+++ src/util.c
@@ -234,11 +234,11 @@
234234
235235
/*
236236
** Check the input string to ensure that it is safe to pass into system().
237237
** A string is unsafe for system() on unix if it contains any of the following:
238238
**
239
-** * Any occurrance of '$' or '`' except single-quoted or after \
239
+** * Any occurrence of '$' or '`' except single-quoted or after \
240240
** * Any of the following characters, unquoted: ;|& or \n except
241241
** these characters are allowed as the very last character in the
242242
** string.
243243
** * Unbalanced single or double quotes
244244
**
@@ -671,20 +671,23 @@
671671
** (1) The value of the --editor command-line argument
672672
** (2) The local "editor" setting
673673
** (3) The global "editor" setting
674674
** (4) The VISUAL environment variable
675675
** (5) The EDITOR environment variable
676
-** (6) Any of the following programs that are available:
677
-** notepad, nano, pico, jove, edit, vi, vim, ed,
676
+** (6) Any of several common editors that might be available, such as:
677
+** notepad, nano, pico, jove, edit, vi, vim, ed
678678
**
679679
** The search only occurs once, the first time this routine is called.
680680
** Second and subsequent invocations always return the same value.
681681
*/
682682
const char *fossil_text_editor(void){
683683
static const char *zEditor = 0;
684684
const char *azStdEd[] = {
685
- "notepad", "nano", "pico", "jove", "edit", "vi", "vim", "ed"
685
+#ifdef _WIN32
686
+ "notepad",
687
+#endif
688
+ "nano", "pico", "jove", "edit", "vi", "vim", "ed"
686689
};
687690
int i = 0;
688691
if( zEditor==0 ){
689692
zEditor = find_option("editor",0,1);
690693
}
@@ -915,11 +918,11 @@
915918
unsigned char *p = zStr;
916919
int i, k;
917920
918921
sqlite3_randomness(16, aBlob);
919922
aBlob[6] = (aBlob[6]&0x0f) + 0x40; /* Version byte: 0100 xxxx */
920
- aBlob[8] = (aBlob[8]&0x3f) + 0x80; /* Variant byte: 1000 xxxx */
923
+ aBlob[8] = (aBlob[8]&0x3f) + 0x80; /* Variant byte: 10xx xxxx */
921924
922925
for(i=0, k=0x550; i<16; i++, k=k>>1){
923926
if( k&1 ){
924927
*p++ = '-'; /* Add a dash after byte 4, 6, 8, and 12 */
925928
}
926929
--- src/util.c
+++ src/util.c
@@ -234,11 +234,11 @@
234
235 /*
236 ** Check the input string to ensure that it is safe to pass into system().
237 ** A string is unsafe for system() on unix if it contains any of the following:
238 **
239 ** * Any occurrance of '$' or '`' except single-quoted or after \
240 ** * Any of the following characters, unquoted: ;|& or \n except
241 ** these characters are allowed as the very last character in the
242 ** string.
243 ** * Unbalanced single or double quotes
244 **
@@ -671,20 +671,23 @@
671 ** (1) The value of the --editor command-line argument
672 ** (2) The local "editor" setting
673 ** (3) The global "editor" setting
674 ** (4) The VISUAL environment variable
675 ** (5) The EDITOR environment variable
676 ** (6) Any of the following programs that are available:
677 ** notepad, nano, pico, jove, edit, vi, vim, ed,
678 **
679 ** The search only occurs once, the first time this routine is called.
680 ** Second and subsequent invocations always return the same value.
681 */
682 const char *fossil_text_editor(void){
683 static const char *zEditor = 0;
684 const char *azStdEd[] = {
685 "notepad", "nano", "pico", "jove", "edit", "vi", "vim", "ed"
 
 
 
686 };
687 int i = 0;
688 if( zEditor==0 ){
689 zEditor = find_option("editor",0,1);
690 }
@@ -915,11 +918,11 @@
915 unsigned char *p = zStr;
916 int i, k;
917
918 sqlite3_randomness(16, aBlob);
919 aBlob[6] = (aBlob[6]&0x0f) + 0x40; /* Version byte: 0100 xxxx */
920 aBlob[8] = (aBlob[8]&0x3f) + 0x80; /* Variant byte: 1000 xxxx */
921
922 for(i=0, k=0x550; i<16; i++, k=k>>1){
923 if( k&1 ){
924 *p++ = '-'; /* Add a dash after byte 4, 6, 8, and 12 */
925 }
926
--- src/util.c
+++ src/util.c
@@ -234,11 +234,11 @@
234
235 /*
236 ** Check the input string to ensure that it is safe to pass into system().
237 ** A string is unsafe for system() on unix if it contains any of the following:
238 **
239 ** * Any occurrence of '$' or '`' except single-quoted or after \
240 ** * Any of the following characters, unquoted: ;|& or \n except
241 ** these characters are allowed as the very last character in the
242 ** string.
243 ** * Unbalanced single or double quotes
244 **
@@ -671,20 +671,23 @@
671 ** (1) The value of the --editor command-line argument
672 ** (2) The local "editor" setting
673 ** (3) The global "editor" setting
674 ** (4) The VISUAL environment variable
675 ** (5) The EDITOR environment variable
676 ** (6) Any of several common editors that might be available, such as:
677 ** notepad, nano, pico, jove, edit, vi, vim, ed
678 **
679 ** The search only occurs once, the first time this routine is called.
680 ** Second and subsequent invocations always return the same value.
681 */
682 const char *fossil_text_editor(void){
683 static const char *zEditor = 0;
684 const char *azStdEd[] = {
685 #ifdef _WIN32
686 "notepad",
687 #endif
688 "nano", "pico", "jove", "edit", "vi", "vim", "ed"
689 };
690 int i = 0;
691 if( zEditor==0 ){
692 zEditor = find_option("editor",0,1);
693 }
@@ -915,11 +918,11 @@
918 unsigned char *p = zStr;
919 int i, k;
920
921 sqlite3_randomness(16, aBlob);
922 aBlob[6] = (aBlob[6]&0x0f) + 0x40; /* Version byte: 0100 xxxx */
923 aBlob[8] = (aBlob[8]&0x3f) + 0x80; /* Variant byte: 10xx xxxx */
924
925 for(i=0, k=0x550; i<16; i++, k=k>>1){
926 if( k&1 ){
927 *p++ = '-'; /* Add a dash after byte 4, 6, 8, and 12 */
928 }
929
+1 -1
--- src/vfile.c
+++ src/vfile.c
@@ -571,11 +571,11 @@
571571
}
572572
}
573573
574574
/*
575575
** Scans the specified base directory for any directories within it, while
576
-** keeping a count of how many files they each contains, either directly or
576
+** keeping a count of how many files they each contain, either directly or
577577
** indirectly.
578578
**
579579
** Subdirectories are scanned recursively.
580580
** Omit files named in VFILE.
581581
**
582582
--- src/vfile.c
+++ src/vfile.c
@@ -571,11 +571,11 @@
571 }
572 }
573
574 /*
575 ** Scans the specified base directory for any directories within it, while
576 ** keeping a count of how many files they each contains, either directly or
577 ** indirectly.
578 **
579 ** Subdirectories are scanned recursively.
580 ** Omit files named in VFILE.
581 **
582
--- src/vfile.c
+++ src/vfile.c
@@ -571,11 +571,11 @@
571 }
572 }
573
574 /*
575 ** Scans the specified base directory for any directories within it, while
576 ** keeping a count of how many files they each contain, either directly or
577 ** indirectly.
578 **
579 ** Subdirectories are scanned recursively.
580 ** Omit files named in VFILE.
581 **
582
+1 -1
--- src/wiki.c
+++ src/wiki.c
@@ -2273,11 +2273,11 @@
22732273
** of timestamp with the most recent
22742274
** first.
22752275
** -a|--show-associated Show wiki pages associated with
22762276
** check-ins and branches.
22772277
** -s|--show-technote-ids The id of the tech note will be listed
2278
-** along side the timestamp. The tech note
2278
+** alongside the timestamp. The tech note
22792279
** id will be the first word on each line.
22802280
** This option only applies if the
22812281
** --technote option is also specified.
22822282
**
22832283
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
22842284
--- src/wiki.c
+++ src/wiki.c
@@ -2273,11 +2273,11 @@
2273 ** of timestamp with the most recent
2274 ** first.
2275 ** -a|--show-associated Show wiki pages associated with
2276 ** check-ins and branches.
2277 ** -s|--show-technote-ids The id of the tech note will be listed
2278 ** along side the timestamp. The tech note
2279 ** id will be the first word on each line.
2280 ** This option only applies if the
2281 ** --technote option is also specified.
2282 **
2283 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
2284
--- src/wiki.c
+++ src/wiki.c
@@ -2273,11 +2273,11 @@
2273 ** of timestamp with the most recent
2274 ** first.
2275 ** -a|--show-associated Show wiki pages associated with
2276 ** check-ins and branches.
2277 ** -s|--show-technote-ids The id of the tech note will be listed
2278 ** alongside the timestamp. The tech note
2279 ** id will be the first word on each line.
2280 ** This option only applies if the
2281 ** --technote option is also specified.
2282 **
2283 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
2284
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -25,11 +25,11 @@
2525
/*
2626
** Allowed wiki transformation operations
2727
*/
2828
#define WIKI_HTMLONLY 0x0001 /* HTML markup only. No wiki */
2929
#define WIKI_INLINE 0x0002 /* Do not surround with <p>..</p> */
30
-/* avalable for reuse: 0x0004 --- formerly WIKI_NOBLOCK */
30
+/* available for reuse: 0x0004 --- formerly WIKI_NOBLOCK */
3131
#define WIKI_BUTTONS 0x0008 /* Allow sub-menu buttons */
3232
#define WIKI_NOBADLINKS 0x0010 /* Ignore broken hyperlinks */
3333
#define WIKI_LINKSONLY 0x0020 /* No markup. Only decorate links */
3434
#define WIKI_NEWLINE 0x0040 /* Honor \n - break lines at each \n */
3535
#define WIKI_MARKDOWNLINKS 0x0080 /* Resolve hyperlinks as in markdown */
@@ -566,11 +566,11 @@
566566
** &
567567
** \n
568568
** [
569569
**
570570
** The "[" is only considered if flags contain ALLOW_LINKS or ALLOW_WIKI.
571
-** The "\n" is only considered interesting if the flags constains ALLOW_WIKI.
571
+** The "\n" is only considered interesting if the flags contains ALLOW_WIKI.
572572
*/
573573
static int textLength(const char *z, int flags){
574574
const char *zReject;
575575
if( flags & ALLOW_WIKI ){
576576
zReject = "<&[\n";
@@ -1811,11 +1811,11 @@
18111811
/* Enter <verbatim> processing. With verbatim enabled, all other
18121812
** markup other than the corresponding end-tag with the same ID is
18131813
** ignored.
18141814
*/
18151815
if( markup.iCode==MARKUP_VERBATIM ){
1816
- int ii; //, vAttrDidAppend=0;
1816
+ int ii; /*, vAttrDidAppend=0;*/
18171817
const char *zClass = 0;
18181818
p->zVerbatimId = 0;
18191819
p->inVerbatim = 1;
18201820
p->preVerbState = p->state;
18211821
p->state &= ~ALLOW_WIKI;
@@ -2745,11 +2745,11 @@
27452745
p->nAlloc = 0;
27462746
p->aStack = p->aSpace;
27472747
}
27482748
27492749
/*
2750
-** Push a new element onto the tag statk
2750
+** Push a new element onto the tag stack
27512751
*/
27522752
static void html_tagstack_push(HtmlTagStack *p, int e){
27532753
if( p->n>=ArraySize(p->aSpace) && p->n>=p->nAlloc ){
27542754
if( p->nAlloc==0 ){
27552755
int *aNew;
@@ -2813,11 +2813,11 @@
28132813
**
28142814
** When safe_html() is asked to sanitize some HTML, it will ignore
28152815
** any text in between two consecutive instances of the nonce. The
28162816
** nonce itself is an HTML comment so it is harmless to keep the
28172817
** nonce in the middle of the HTML stream. A different nonce is
2818
-** choosen each time Fossil is run, using a lot of randomness, so
2818
+** chosen each time Fossil is run, using a lot of randomness, so
28192819
** an attacker will be unable to guess the nonce in advance.
28202820
**
28212821
** The original use-case for this mechanism is to allow Pikchr-generated
28222822
** SVG in the middle of HTML generated from Markdown. The Markdown
28232823
** output will normally be processed by safe_html() to prevent accidental
28242824
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -25,11 +25,11 @@
25 /*
26 ** Allowed wiki transformation operations
27 */
28 #define WIKI_HTMLONLY 0x0001 /* HTML markup only. No wiki */
29 #define WIKI_INLINE 0x0002 /* Do not surround with <p>..</p> */
30 /* avalable for reuse: 0x0004 --- formerly WIKI_NOBLOCK */
31 #define WIKI_BUTTONS 0x0008 /* Allow sub-menu buttons */
32 #define WIKI_NOBADLINKS 0x0010 /* Ignore broken hyperlinks */
33 #define WIKI_LINKSONLY 0x0020 /* No markup. Only decorate links */
34 #define WIKI_NEWLINE 0x0040 /* Honor \n - break lines at each \n */
35 #define WIKI_MARKDOWNLINKS 0x0080 /* Resolve hyperlinks as in markdown */
@@ -566,11 +566,11 @@
566 ** &
567 ** \n
568 ** [
569 **
570 ** The "[" is only considered if flags contain ALLOW_LINKS or ALLOW_WIKI.
571 ** The "\n" is only considered interesting if the flags constains ALLOW_WIKI.
572 */
573 static int textLength(const char *z, int flags){
574 const char *zReject;
575 if( flags & ALLOW_WIKI ){
576 zReject = "<&[\n";
@@ -1811,11 +1811,11 @@
1811 /* Enter <verbatim> processing. With verbatim enabled, all other
1812 ** markup other than the corresponding end-tag with the same ID is
1813 ** ignored.
1814 */
1815 if( markup.iCode==MARKUP_VERBATIM ){
1816 int ii; //, vAttrDidAppend=0;
1817 const char *zClass = 0;
1818 p->zVerbatimId = 0;
1819 p->inVerbatim = 1;
1820 p->preVerbState = p->state;
1821 p->state &= ~ALLOW_WIKI;
@@ -2745,11 +2745,11 @@
2745 p->nAlloc = 0;
2746 p->aStack = p->aSpace;
2747 }
2748
2749 /*
2750 ** Push a new element onto the tag statk
2751 */
2752 static void html_tagstack_push(HtmlTagStack *p, int e){
2753 if( p->n>=ArraySize(p->aSpace) && p->n>=p->nAlloc ){
2754 if( p->nAlloc==0 ){
2755 int *aNew;
@@ -2813,11 +2813,11 @@
2813 **
2814 ** When safe_html() is asked to sanitize some HTML, it will ignore
2815 ** any text in between two consecutive instances of the nonce. The
2816 ** nonce itself is an HTML comment so it is harmless to keep the
2817 ** nonce in the middle of the HTML stream. A different nonce is
2818 ** choosen each time Fossil is run, using a lot of randomness, so
2819 ** an attacker will be unable to guess the nonce in advance.
2820 **
2821 ** The original use-case for this mechanism is to allow Pikchr-generated
2822 ** SVG in the middle of HTML generated from Markdown. The Markdown
2823 ** output will normally be processed by safe_html() to prevent accidental
2824
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -25,11 +25,11 @@
25 /*
26 ** Allowed wiki transformation operations
27 */
28 #define WIKI_HTMLONLY 0x0001 /* HTML markup only. No wiki */
29 #define WIKI_INLINE 0x0002 /* Do not surround with <p>..</p> */
30 /* available for reuse: 0x0004 --- formerly WIKI_NOBLOCK */
31 #define WIKI_BUTTONS 0x0008 /* Allow sub-menu buttons */
32 #define WIKI_NOBADLINKS 0x0010 /* Ignore broken hyperlinks */
33 #define WIKI_LINKSONLY 0x0020 /* No markup. Only decorate links */
34 #define WIKI_NEWLINE 0x0040 /* Honor \n - break lines at each \n */
35 #define WIKI_MARKDOWNLINKS 0x0080 /* Resolve hyperlinks as in markdown */
@@ -566,11 +566,11 @@
566 ** &
567 ** \n
568 ** [
569 **
570 ** The "[" is only considered if flags contain ALLOW_LINKS or ALLOW_WIKI.
571 ** The "\n" is only considered interesting if the flags contains ALLOW_WIKI.
572 */
573 static int textLength(const char *z, int flags){
574 const char *zReject;
575 if( flags & ALLOW_WIKI ){
576 zReject = "<&[\n";
@@ -1811,11 +1811,11 @@
1811 /* Enter <verbatim> processing. With verbatim enabled, all other
1812 ** markup other than the corresponding end-tag with the same ID is
1813 ** ignored.
1814 */
1815 if( markup.iCode==MARKUP_VERBATIM ){
1816 int ii; /*, vAttrDidAppend=0;*/
1817 const char *zClass = 0;
1818 p->zVerbatimId = 0;
1819 p->inVerbatim = 1;
1820 p->preVerbState = p->state;
1821 p->state &= ~ALLOW_WIKI;
@@ -2745,11 +2745,11 @@
2745 p->nAlloc = 0;
2746 p->aStack = p->aSpace;
2747 }
2748
2749 /*
2750 ** Push a new element onto the tag stack
2751 */
2752 static void html_tagstack_push(HtmlTagStack *p, int e){
2753 if( p->n>=ArraySize(p->aSpace) && p->n>=p->nAlloc ){
2754 if( p->nAlloc==0 ){
2755 int *aNew;
@@ -2813,11 +2813,11 @@
2813 **
2814 ** When safe_html() is asked to sanitize some HTML, it will ignore
2815 ** any text in between two consecutive instances of the nonce. The
2816 ** nonce itself is an HTML comment so it is harmless to keep the
2817 ** nonce in the middle of the HTML stream. A different nonce is
2818 ** chosen each time Fossil is run, using a lot of randomness, so
2819 ** an attacker will be unable to guess the nonce in advance.
2820 **
2821 ** The original use-case for this mechanism is to allow Pikchr-generated
2822 ** SVG in the middle of HTML generated from Markdown. The Markdown
2823 ** output will normally be processed by safe_html() to prevent accidental
2824
+1 -1
--- src/winhttp.c
+++ src/winhttp.c
@@ -805,11 +805,11 @@
805805
(LPWSTR) &tmp,
806806
0,
807807
NULL
808808
);
809809
if( !nMsg ){
810
- /* No english, get what the system has available. */
810
+ /* No English, get what the system has available. */
811811
nMsg = FormatMessageW(
812812
FORMAT_MESSAGE_ALLOCATE_BUFFER |
813813
FORMAT_MESSAGE_FROM_SYSTEM |
814814
FORMAT_MESSAGE_IGNORE_INSERTS,
815815
NULL,
816816
--- src/winhttp.c
+++ src/winhttp.c
@@ -805,11 +805,11 @@
805 (LPWSTR) &tmp,
806 0,
807 NULL
808 );
809 if( !nMsg ){
810 /* No english, get what the system has available. */
811 nMsg = FormatMessageW(
812 FORMAT_MESSAGE_ALLOCATE_BUFFER |
813 FORMAT_MESSAGE_FROM_SYSTEM |
814 FORMAT_MESSAGE_IGNORE_INSERTS,
815 NULL,
816
--- src/winhttp.c
+++ src/winhttp.c
@@ -805,11 +805,11 @@
805 (LPWSTR) &tmp,
806 0,
807 NULL
808 );
809 if( !nMsg ){
810 /* No English, get what the system has available. */
811 nMsg = FormatMessageW(
812 FORMAT_MESSAGE_ALLOCATE_BUFFER |
813 FORMAT_MESSAGE_FROM_SYSTEM |
814 FORMAT_MESSAGE_IGNORE_INSERTS,
815 NULL,
816
+18 -6
--- src/xfer.c
+++ src/xfer.c
@@ -52,11 +52,11 @@
5252
int resync; /* Send igot cards for all holdings */
5353
u8 syncPrivate; /* True to enable syncing private content */
5454
u8 nextIsPrivate; /* If true, next "file" received is a private */
5555
u32 remoteVersion; /* Version of fossil running on the other side */
5656
u32 remoteDate; /* Date for specific client software edition */
57
- u32 remoteTime; /* Time of date correspoding on remoteDate */
57
+ u32 remoteTime; /* Time of date corresponding on remoteDate */
5858
time_t maxTime; /* Time when this transfer should be finished */
5959
};
6060
6161
6262
/*
@@ -1216,11 +1216,11 @@
12161216
return xfer_run_script(xfer_common_code(), 0, 0);
12171217
}
12181218
12191219
/*
12201220
** This routine makes a "syncwith:URL" entry in the CONFIG table to
1221
-** indicate that a sync is occuring with zUrl.
1221
+** indicate that a sync is occurring with zUrl.
12221222
**
12231223
** Add a "syncfrom:URL" entry instead of "syncwith:URL" if bSyncFrom is true.
12241224
*/
12251225
static void xfer_syncwith(const char *zUrl, int bSyncFrom){
12261226
UrlData x;
@@ -2049,10 +2049,12 @@
20492049
#define SYNC_CKIN_LOCK 0x02000 /* Lock the current check-in */
20502050
#define SYNC_NOHTTPCOMPRESS 0x04000 /* Do not compression HTTP messages */
20512051
#define SYNC_ALLURL 0x08000 /* The --all flag - sync to all URLs */
20522052
#define SYNC_SHARE_LINKS 0x10000 /* Request alternate repo links */
20532053
#define SYNC_XVERBOSE 0x20000 /* Extra verbose. Network traffic */
2054
+#define SYNC_PING 0x40000 /* Verify server is alive */
2055
+#define SYNC_QUIET 0x80000 /* No output */
20542056
#endif
20552057
20562058
/*
20572059
** Floating-point absolute value
20582060
*/
@@ -2115,11 +2117,12 @@
21152117
unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
21162118
const int bOutIsTty = fossil_isatty(fossil_fileno(stdout));
21172119
21182120
if( pnRcvd ) *pnRcvd = 0;
21192121
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
2120
- if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
2122
+ if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED|SYNC_PING))
2123
+ ==0
21212124
&& configRcvMask==0
21222125
&& configSendMask==0
21232126
){
21242127
return 0; /* Nothing to do */
21252128
}
@@ -2384,11 +2387,11 @@
23842387
zCkinLock = 0;
23852388
}else if( zClientId ){
23862389
blob_appendf(&send, "pragma ci-unlock %s\n", zClientId);
23872390
}
23882391
/* Append randomness to the end of the uplink message. This makes all
2389
- ** messages unique so that that the login-card nonce will always
2392
+ ** messages unique so that the login-card nonce will always
23902393
** be unique.
23912394
*/
23922395
zRandomness = db_text(0, "SELECT hex(randomblob(20))");
23932396
blob_appendf(&send, "# %s\n", zRandomness);
23942397
fossil_free(zRandomness);
@@ -2410,10 +2413,13 @@
24102413
mHttpFlags |= HTTP_NOCOMPRESS;
24112414
}
24122415
if( syncFlags & SYNC_XVERBOSE ){
24132416
mHttpFlags |= HTTP_VERBOSE;
24142417
}
2418
+ if( syncFlags & SYNC_QUIET ){
2419
+ mHttpFlags |= HTTP_QUIET;
2420
+ }
24152421
24162422
/* Do the round-trip to the server */
24172423
if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
24182424
nErr++;
24192425
go = 2;
@@ -2431,10 +2437,12 @@
24312437
nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
24322438
if( syncFlags & SYNC_VERBOSE ){
24332439
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
24342440
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
24352441
xfer.nFileSent, xfer.nDeltaSent);
2442
+ }else if( syncFlags & SYNC_QUIET ){
2443
+ /* No-op */
24362444
}else{
24372445
if( bOutIsTty!=0 ){
24382446
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
24392447
nRoundtrip, nArtifactSent, nArtifactRcvd);
24402448
}
@@ -2954,10 +2962,12 @@
29542962
origConfigRcvMask = 0;
29552963
if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){
29562964
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Received:",
29572965
blob_size(&recv), nCardRcvd,
29582966
xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
2967
+ }else if( syncFlags & SYNC_QUIET ){
2968
+ /* No-op */
29592969
}else{
29602970
if( bOutIsTty!=0 ){
29612971
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
29622972
nRoundtrip, nArtifactSent, nArtifactRcvd);
29632973
}
@@ -3016,18 +3026,20 @@
30163026
}else if( rSkew*24.0*3600.0 < -10.0 ){
30173027
fossil_warning("*** time skew *** server is slow by %s",
30183028
db_timespan_name(-rSkew));
30193029
g.clockSkewSeen = 1;
30203030
}
3021
- if( bOutIsTty==0 ){
3031
+ if( bOutIsTty==0 && (syncFlags & SYNC_QUIET)==0 ){
30223032
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
30233033
nRoundtrip, nArtifactSent, nArtifactRcvd);
30243034
fossil_force_newline();
30253035
}
30263036
fossil_force_newline();
30273037
if( g.zHttpCmd==0 ){
3028
- if( syncFlags & SYNC_VERBOSE ){
3038
+ if( syncFlags & SYNC_QUIET ){
3039
+ /* no-op */
3040
+ }else if( syncFlags & SYNC_VERBOSE ){
30293041
fossil_print(
30303042
"%s done, wire bytes sent: %lld received: %lld remote: %s%s\n",
30313043
zOpType, nSent, nRcvd,
30323044
(g.url.name && g.url.name[0]!='\0') ? g.url.name : "",
30333045
(g.zIpAddr && g.zIpAddr[0]!='\0'
30343046
--- src/xfer.c
+++ src/xfer.c
@@ -52,11 +52,11 @@
52 int resync; /* Send igot cards for all holdings */
53 u8 syncPrivate; /* True to enable syncing private content */
54 u8 nextIsPrivate; /* If true, next "file" received is a private */
55 u32 remoteVersion; /* Version of fossil running on the other side */
56 u32 remoteDate; /* Date for specific client software edition */
57 u32 remoteTime; /* Time of date correspoding on remoteDate */
58 time_t maxTime; /* Time when this transfer should be finished */
59 };
60
61
62 /*
@@ -1216,11 +1216,11 @@
1216 return xfer_run_script(xfer_common_code(), 0, 0);
1217 }
1218
1219 /*
1220 ** This routine makes a "syncwith:URL" entry in the CONFIG table to
1221 ** indicate that a sync is occuring with zUrl.
1222 **
1223 ** Add a "syncfrom:URL" entry instead of "syncwith:URL" if bSyncFrom is true.
1224 */
1225 static void xfer_syncwith(const char *zUrl, int bSyncFrom){
1226 UrlData x;
@@ -2049,10 +2049,12 @@
2049 #define SYNC_CKIN_LOCK 0x02000 /* Lock the current check-in */
2050 #define SYNC_NOHTTPCOMPRESS 0x04000 /* Do not compression HTTP messages */
2051 #define SYNC_ALLURL 0x08000 /* The --all flag - sync to all URLs */
2052 #define SYNC_SHARE_LINKS 0x10000 /* Request alternate repo links */
2053 #define SYNC_XVERBOSE 0x20000 /* Extra verbose. Network traffic */
 
 
2054 #endif
2055
2056 /*
2057 ** Floating-point absolute value
2058 */
@@ -2115,11 +2117,12 @@
2115 unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
2116 const int bOutIsTty = fossil_isatty(fossil_fileno(stdout));
2117
2118 if( pnRcvd ) *pnRcvd = 0;
2119 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
2120 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
 
2121 && configRcvMask==0
2122 && configSendMask==0
2123 ){
2124 return 0; /* Nothing to do */
2125 }
@@ -2384,11 +2387,11 @@
2384 zCkinLock = 0;
2385 }else if( zClientId ){
2386 blob_appendf(&send, "pragma ci-unlock %s\n", zClientId);
2387 }
2388 /* Append randomness to the end of the uplink message. This makes all
2389 ** messages unique so that that the login-card nonce will always
2390 ** be unique.
2391 */
2392 zRandomness = db_text(0, "SELECT hex(randomblob(20))");
2393 blob_appendf(&send, "# %s\n", zRandomness);
2394 fossil_free(zRandomness);
@@ -2410,10 +2413,13 @@
2410 mHttpFlags |= HTTP_NOCOMPRESS;
2411 }
2412 if( syncFlags & SYNC_XVERBOSE ){
2413 mHttpFlags |= HTTP_VERBOSE;
2414 }
 
 
 
2415
2416 /* Do the round-trip to the server */
2417 if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
2418 nErr++;
2419 go = 2;
@@ -2431,10 +2437,12 @@
2431 nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
2432 if( syncFlags & SYNC_VERBOSE ){
2433 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
2434 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
2435 xfer.nFileSent, xfer.nDeltaSent);
 
 
2436 }else{
2437 if( bOutIsTty!=0 ){
2438 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2439 nRoundtrip, nArtifactSent, nArtifactRcvd);
2440 }
@@ -2954,10 +2962,12 @@
2954 origConfigRcvMask = 0;
2955 if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){
2956 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Received:",
2957 blob_size(&recv), nCardRcvd,
2958 xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
 
 
2959 }else{
2960 if( bOutIsTty!=0 ){
2961 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2962 nRoundtrip, nArtifactSent, nArtifactRcvd);
2963 }
@@ -3016,18 +3026,20 @@
3016 }else if( rSkew*24.0*3600.0 < -10.0 ){
3017 fossil_warning("*** time skew *** server is slow by %s",
3018 db_timespan_name(-rSkew));
3019 g.clockSkewSeen = 1;
3020 }
3021 if( bOutIsTty==0 ){
3022 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
3023 nRoundtrip, nArtifactSent, nArtifactRcvd);
3024 fossil_force_newline();
3025 }
3026 fossil_force_newline();
3027 if( g.zHttpCmd==0 ){
3028 if( syncFlags & SYNC_VERBOSE ){
 
 
3029 fossil_print(
3030 "%s done, wire bytes sent: %lld received: %lld remote: %s%s\n",
3031 zOpType, nSent, nRcvd,
3032 (g.url.name && g.url.name[0]!='\0') ? g.url.name : "",
3033 (g.zIpAddr && g.zIpAddr[0]!='\0'
3034
--- src/xfer.c
+++ src/xfer.c
@@ -52,11 +52,11 @@
52 int resync; /* Send igot cards for all holdings */
53 u8 syncPrivate; /* True to enable syncing private content */
54 u8 nextIsPrivate; /* If true, next "file" received is a private */
55 u32 remoteVersion; /* Version of fossil running on the other side */
56 u32 remoteDate; /* Date for specific client software edition */
57 u32 remoteTime; /* Time of date corresponding on remoteDate */
58 time_t maxTime; /* Time when this transfer should be finished */
59 };
60
61
62 /*
@@ -1216,11 +1216,11 @@
1216 return xfer_run_script(xfer_common_code(), 0, 0);
1217 }
1218
1219 /*
1220 ** This routine makes a "syncwith:URL" entry in the CONFIG table to
1221 ** indicate that a sync is occurring with zUrl.
1222 **
1223 ** Add a "syncfrom:URL" entry instead of "syncwith:URL" if bSyncFrom is true.
1224 */
1225 static void xfer_syncwith(const char *zUrl, int bSyncFrom){
1226 UrlData x;
@@ -2049,10 +2049,12 @@
2049 #define SYNC_CKIN_LOCK 0x02000 /* Lock the current check-in */
2050 #define SYNC_NOHTTPCOMPRESS 0x04000 /* Do not compression HTTP messages */
2051 #define SYNC_ALLURL 0x08000 /* The --all flag - sync to all URLs */
2052 #define SYNC_SHARE_LINKS 0x10000 /* Request alternate repo links */
2053 #define SYNC_XVERBOSE 0x20000 /* Extra verbose. Network traffic */
2054 #define SYNC_PING 0x40000 /* Verify server is alive */
2055 #define SYNC_QUIET 0x80000 /* No output */
2056 #endif
2057
2058 /*
2059 ** Floating-point absolute value
2060 */
@@ -2115,11 +2117,12 @@
2117 unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
2118 const int bOutIsTty = fossil_isatty(fossil_fileno(stdout));
2119
2120 if( pnRcvd ) *pnRcvd = 0;
2121 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
2122 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED|SYNC_PING))
2123 ==0
2124 && configRcvMask==0
2125 && configSendMask==0
2126 ){
2127 return 0; /* Nothing to do */
2128 }
@@ -2384,11 +2387,11 @@
2387 zCkinLock = 0;
2388 }else if( zClientId ){
2389 blob_appendf(&send, "pragma ci-unlock %s\n", zClientId);
2390 }
2391 /* Append randomness to the end of the uplink message. This makes all
2392 ** messages unique so that the login-card nonce will always
2393 ** be unique.
2394 */
2395 zRandomness = db_text(0, "SELECT hex(randomblob(20))");
2396 blob_appendf(&send, "# %s\n", zRandomness);
2397 fossil_free(zRandomness);
@@ -2410,10 +2413,13 @@
2413 mHttpFlags |= HTTP_NOCOMPRESS;
2414 }
2415 if( syncFlags & SYNC_XVERBOSE ){
2416 mHttpFlags |= HTTP_VERBOSE;
2417 }
2418 if( syncFlags & SYNC_QUIET ){
2419 mHttpFlags |= HTTP_QUIET;
2420 }
2421
2422 /* Do the round-trip to the server */
2423 if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
2424 nErr++;
2425 go = 2;
@@ -2431,10 +2437,12 @@
2437 nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
2438 if( syncFlags & SYNC_VERBOSE ){
2439 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
2440 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
2441 xfer.nFileSent, xfer.nDeltaSent);
2442 }else if( syncFlags & SYNC_QUIET ){
2443 /* No-op */
2444 }else{
2445 if( bOutIsTty!=0 ){
2446 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2447 nRoundtrip, nArtifactSent, nArtifactRcvd);
2448 }
@@ -2954,10 +2962,12 @@
2962 origConfigRcvMask = 0;
2963 if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){
2964 fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Received:",
2965 blob_size(&recv), nCardRcvd,
2966 xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
2967 }else if( syncFlags & SYNC_QUIET ){
2968 /* No-op */
2969 }else{
2970 if( bOutIsTty!=0 ){
2971 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
2972 nRoundtrip, nArtifactSent, nArtifactRcvd);
2973 }
@@ -3016,18 +3026,20 @@
3026 }else if( rSkew*24.0*3600.0 < -10.0 ){
3027 fossil_warning("*** time skew *** server is slow by %s",
3028 db_timespan_name(-rSkew));
3029 g.clockSkewSeen = 1;
3030 }
3031 if( bOutIsTty==0 && (syncFlags & SYNC_QUIET)==0 ){
3032 fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
3033 nRoundtrip, nArtifactSent, nArtifactRcvd);
3034 fossil_force_newline();
3035 }
3036 fossil_force_newline();
3037 if( g.zHttpCmd==0 ){
3038 if( syncFlags & SYNC_QUIET ){
3039 /* no-op */
3040 }else if( syncFlags & SYNC_VERBOSE ){
3041 fossil_print(
3042 "%s done, wire bytes sent: %lld received: %lld remote: %s%s\n",
3043 zOpType, nSent, nRcvd,
3044 (g.url.name && g.url.name[0]!='\0') ? g.url.name : "",
3045 (g.zIpAddr && g.zIpAddr[0]!='\0'
3046
+81 -3
--- src/xsystem.c
+++ src/xsystem.c
@@ -31,10 +31,13 @@
3131
*/
3232
#include "config.h"
3333
#include "xsystem.h"
3434
#include "qrf.h"
3535
#include <time.h>
36
+#ifdef _WIN32
37
+# include <windows.h>
38
+#endif
3639
3740
3841
/* Date and time */
3942
void xsystem_date(int argc, char **argv){
4043
(void)argc;
@@ -41,11 +44,11 @@
4144
(void)argv;
4245
fossil_print("%z = ", cgi_iso8601_datestamp());
4346
fossil_print("%z\n", cgi_rfc822_datestamp(time(0)));
4447
}
4548
46
-/* Present working diretory */
49
+/* Present working directory */
4750
void xsystem_pwd(int argc, char **argv){
4851
char *zPwd = file_getcwd(0, 0);
4952
fossil_print("%z\n", zPwd);
5053
}
5154
@@ -168,11 +171,11 @@
168171
file_directory_list_free(azList);
169172
}
170173
}
171174
172175
/*
173
-** Return arguments to ORDER BY that will correctly sort the entires.
176
+** Return arguments to ORDER BY that will correctly sort the entries.
174177
*/
175178
static const char *xsystem_ls_orderby(int mFlags){
176179
static const char *zSortTypes[] = {
177180
"fn COLLATE NOCASE",
178181
"mtime DESC",
@@ -343,11 +346,11 @@
343346
344347
/* List files "ls"
345348
** Options:
346349
**
347350
** -a Show files that begin with "."
348
-** -C List by colums
351
+** -C List by columns
349352
** --color=WHEN Colorize output?
350353
** -d Show just directory names, not content
351354
** -l Long listing
352355
** -m Comma-separated list
353356
** -r Reverse sort
@@ -439,10 +442,76 @@
439442
}
440443
}
441444
sqlite3_finalize(pStmt);
442445
sqlite3_close(db);
443446
}
447
+
448
+/*
449
+** unzip [-l] ZIPFILE
450
+*/
451
+void xsystem_unzip(int argc, char **argv){
452
+ const char *zZipfile = 0;
453
+ int doList = 0;
454
+ int i;
455
+ char *a[5];
456
+ int n;
457
+ extern int sqlite3_shell(int, char**);
458
+
459
+ for(i=1; i<argc; i++){
460
+ const char *z = argv[i];
461
+ if( z[0]=='-' ){
462
+ if( z[1]=='-' && z[2]!=0 ) z++;
463
+ if( strcmp(z,"-l")==0 ){
464
+ doList = 1;
465
+ }else
466
+ {
467
+ fossil_fatal("unknown option: %s", argv[i]);
468
+ }
469
+ }else if( zZipfile!=0 ){
470
+ fossil_fatal("extra argument: %s", z);
471
+ }else{
472
+ zZipfile = z;
473
+ }
474
+ }
475
+ if( zZipfile==0 ){
476
+ fossil_fatal("Usage: fossil sys unzip [-l] ZIPFILE");
477
+ }else if( file_size(zZipfile, ExtFILE)<0 ){
478
+ fossil_fatal("No such file: %s\n", zZipfile);
479
+ }
480
+ g.zRepositoryName = 0;
481
+ g.zLocalDbName = 0;
482
+ g.zConfigDbName = 0;
483
+ sqlite3_shutdown();
484
+ a[0] = argv[0];
485
+ a[1] = (char*)zZipfile;
486
+ if( doList ){
487
+ a[2] = ".mode column";
488
+ a[3] = "SELECT sz AS Size, date(mtime,'unixepoch') AS Date,"
489
+ " time(mtime,'unixepoch') AS Time, name AS Name"
490
+ " FROM zip;";
491
+ n = 4;
492
+ }else{
493
+ a[2] = ".mode list";
494
+ a[3] = "SELECT if(writefile(name,data,mode,mtime) IS NULL,"
495
+ "'error: '||name,'extracting: '||name) FROM zip;";
496
+ n = 4;
497
+ }
498
+ a[n] = 0;
499
+ sqlite3_shell(n,a);
500
+}
501
+
502
+/*
503
+** zip [OPTIONS] ZIPFILE FILE ...
504
+*/
505
+void xsystem_zip(int argc, char **argv){
506
+ int i;
507
+ for(i=0; i<argc; i++){
508
+ g.argv[i+1] = argv[i];
509
+ }
510
+ g.argc = argc+1;
511
+ filezip_cmd();
512
+}
444513
445514
/*
446515
** Available system commands.
447516
*/
448517
typedef struct XSysCmd XSysCmd;
@@ -473,17 +542,26 @@
473542
"Show the Present Working Directory name\n"
474543
},
475544
{ "stty", xsystem_stty,
476545
"\n"
477546
"Show the size of the TTY\n"
547
+ },
548
+ { "unzip", xsystem_unzip,
549
+ "[-l] ZIPFILE\n\n"
550
+ "Extract content from ZIPFILE, or list the content if the -l option\n"
551
+ "is used.\n"
478552
},
479553
{ "which", xsystem_which,
480554
"EXE ...\n"
481555
"Show the location on PATH of executables EXE\n"
482556
"Options:\n"
483557
" -a Show all path locations rather than just the first\n"
484558
},
559
+ { "zip", xsystem_zip,
560
+ "ZIPFILE FILE ...\n\n"
561
+ "Create a new ZIP archive named ZIPFILE using listed files as content\n"
562
+ },
485563
};
486564
487565
/*
488566
** COMMAND: system
489567
**
490568
--- src/xsystem.c
+++ src/xsystem.c
@@ -31,10 +31,13 @@
31 */
32 #include "config.h"
33 #include "xsystem.h"
34 #include "qrf.h"
35 #include <time.h>
 
 
 
36
37
38 /* Date and time */
39 void xsystem_date(int argc, char **argv){
40 (void)argc;
@@ -41,11 +44,11 @@
41 (void)argv;
42 fossil_print("%z = ", cgi_iso8601_datestamp());
43 fossil_print("%z\n", cgi_rfc822_datestamp(time(0)));
44 }
45
46 /* Present working diretory */
47 void xsystem_pwd(int argc, char **argv){
48 char *zPwd = file_getcwd(0, 0);
49 fossil_print("%z\n", zPwd);
50 }
51
@@ -168,11 +171,11 @@
168 file_directory_list_free(azList);
169 }
170 }
171
172 /*
173 ** Return arguments to ORDER BY that will correctly sort the entires.
174 */
175 static const char *xsystem_ls_orderby(int mFlags){
176 static const char *zSortTypes[] = {
177 "fn COLLATE NOCASE",
178 "mtime DESC",
@@ -343,11 +346,11 @@
343
344 /* List files "ls"
345 ** Options:
346 **
347 ** -a Show files that begin with "."
348 ** -C List by colums
349 ** --color=WHEN Colorize output?
350 ** -d Show just directory names, not content
351 ** -l Long listing
352 ** -m Comma-separated list
353 ** -r Reverse sort
@@ -439,10 +442,76 @@
439 }
440 }
441 sqlite3_finalize(pStmt);
442 sqlite3_close(db);
443 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
445 /*
446 ** Available system commands.
447 */
448 typedef struct XSysCmd XSysCmd;
@@ -473,17 +542,26 @@
473 "Show the Present Working Directory name\n"
474 },
475 { "stty", xsystem_stty,
476 "\n"
477 "Show the size of the TTY\n"
 
 
 
 
 
478 },
479 { "which", xsystem_which,
480 "EXE ...\n"
481 "Show the location on PATH of executables EXE\n"
482 "Options:\n"
483 " -a Show all path locations rather than just the first\n"
484 },
 
 
 
 
485 };
486
487 /*
488 ** COMMAND: system
489 **
490
--- src/xsystem.c
+++ src/xsystem.c
@@ -31,10 +31,13 @@
31 */
32 #include "config.h"
33 #include "xsystem.h"
34 #include "qrf.h"
35 #include <time.h>
36 #ifdef _WIN32
37 # include <windows.h>
38 #endif
39
40
41 /* Date and time */
42 void xsystem_date(int argc, char **argv){
43 (void)argc;
@@ -41,11 +44,11 @@
44 (void)argv;
45 fossil_print("%z = ", cgi_iso8601_datestamp());
46 fossil_print("%z\n", cgi_rfc822_datestamp(time(0)));
47 }
48
49 /* Present working directory */
50 void xsystem_pwd(int argc, char **argv){
51 char *zPwd = file_getcwd(0, 0);
52 fossil_print("%z\n", zPwd);
53 }
54
@@ -168,11 +171,11 @@
171 file_directory_list_free(azList);
172 }
173 }
174
175 /*
176 ** Return arguments to ORDER BY that will correctly sort the entries.
177 */
178 static const char *xsystem_ls_orderby(int mFlags){
179 static const char *zSortTypes[] = {
180 "fn COLLATE NOCASE",
181 "mtime DESC",
@@ -343,11 +346,11 @@
346
347 /* List files "ls"
348 ** Options:
349 **
350 ** -a Show files that begin with "."
351 ** -C List by columns
352 ** --color=WHEN Colorize output?
353 ** -d Show just directory names, not content
354 ** -l Long listing
355 ** -m Comma-separated list
356 ** -r Reverse sort
@@ -439,10 +442,76 @@
442 }
443 }
444 sqlite3_finalize(pStmt);
445 sqlite3_close(db);
446 }
447
448 /*
449 ** unzip [-l] ZIPFILE
450 */
451 void xsystem_unzip(int argc, char **argv){
452 const char *zZipfile = 0;
453 int doList = 0;
454 int i;
455 char *a[5];
456 int n;
457 extern int sqlite3_shell(int, char**);
458
459 for(i=1; i<argc; i++){
460 const char *z = argv[i];
461 if( z[0]=='-' ){
462 if( z[1]=='-' && z[2]!=0 ) z++;
463 if( strcmp(z,"-l")==0 ){
464 doList = 1;
465 }else
466 {
467 fossil_fatal("unknown option: %s", argv[i]);
468 }
469 }else if( zZipfile!=0 ){
470 fossil_fatal("extra argument: %s", z);
471 }else{
472 zZipfile = z;
473 }
474 }
475 if( zZipfile==0 ){
476 fossil_fatal("Usage: fossil sys unzip [-l] ZIPFILE");
477 }else if( file_size(zZipfile, ExtFILE)<0 ){
478 fossil_fatal("No such file: %s\n", zZipfile);
479 }
480 g.zRepositoryName = 0;
481 g.zLocalDbName = 0;
482 g.zConfigDbName = 0;
483 sqlite3_shutdown();
484 a[0] = argv[0];
485 a[1] = (char*)zZipfile;
486 if( doList ){
487 a[2] = ".mode column";
488 a[3] = "SELECT sz AS Size, date(mtime,'unixepoch') AS Date,"
489 " time(mtime,'unixepoch') AS Time, name AS Name"
490 " FROM zip;";
491 n = 4;
492 }else{
493 a[2] = ".mode list";
494 a[3] = "SELECT if(writefile(name,data,mode,mtime) IS NULL,"
495 "'error: '||name,'extracting: '||name) FROM zip;";
496 n = 4;
497 }
498 a[n] = 0;
499 sqlite3_shell(n,a);
500 }
501
502 /*
503 ** zip [OPTIONS] ZIPFILE FILE ...
504 */
505 void xsystem_zip(int argc, char **argv){
506 int i;
507 for(i=0; i<argc; i++){
508 g.argv[i+1] = argv[i];
509 }
510 g.argc = argc+1;
511 filezip_cmd();
512 }
513
514 /*
515 ** Available system commands.
516 */
517 typedef struct XSysCmd XSysCmd;
@@ -473,17 +542,26 @@
542 "Show the Present Working Directory name\n"
543 },
544 { "stty", xsystem_stty,
545 "\n"
546 "Show the size of the TTY\n"
547 },
548 { "unzip", xsystem_unzip,
549 "[-l] ZIPFILE\n\n"
550 "Extract content from ZIPFILE, or list the content if the -l option\n"
551 "is used.\n"
552 },
553 { "which", xsystem_which,
554 "EXE ...\n"
555 "Show the location on PATH of executables EXE\n"
556 "Options:\n"
557 " -a Show all path locations rather than just the first\n"
558 },
559 { "zip", xsystem_zip,
560 "ZIPFILE FILE ...\n\n"
561 "Create a new ZIP archive named ZIPFILE using listed files as content\n"
562 },
563 };
564
565 /*
566 ** COMMAND: system
567 **
568
+3 -3
--- src/zip.c
+++ src/zip.c
@@ -230,11 +230,11 @@
230230
dosTime = (H<<11) + (M<<5) + (S>>1);
231231
dosDate = ((y-1980)<<9) + (m<<5) + d;
232232
}
233233
234234
/*
235
-** Set the date and time from a julian day number.
235
+** Set the date and time from a Julian day number.
236236
*/
237237
void zip_set_timedate(double rDate){
238238
char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate);
239239
zip_set_timedate_from_str(zDate);
240240
fossil_free(zDate);
@@ -267,11 +267,11 @@
267267
char zHdr[30];
268268
char zExTime[13];
269269
char zBuf[100];
270270
char zOutBuf[100000];
271271
272
- /* Fill in as much of the header as we know.
272
+ /* Fill inasmuch of the header as we know.
273273
*/
274274
nameLen = (int)strlen(zName);
275275
if( nameLen==0 ) return;
276276
nBlob = pFile ? blob_size(pFile) : 0;
277277
if( pFile ){ /* This is a file, possibly empty... */
@@ -984,11 +984,11 @@
984984
** part of the name= value after the / is the download
985985
** filename. If no check-in is specified by either
986986
** name= or r=, then the name of the main branch
987987
** (usually "trunk") is used.
988988
**
989
-** in=PATTERN Only include files that match the comma-separate
989
+** in=PATTERN Only include files that match the comma-separated
990990
** list of GLOB patterns in PATTERN, as with ex=
991991
**
992992
** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
993993
** comma-separated list of GLOB patterns, where each
994994
** pattern can optionally be quoted using ".." or '..'.
995995
--- src/zip.c
+++ src/zip.c
@@ -230,11 +230,11 @@
230 dosTime = (H<<11) + (M<<5) + (S>>1);
231 dosDate = ((y-1980)<<9) + (m<<5) + d;
232 }
233
234 /*
235 ** Set the date and time from a julian day number.
236 */
237 void zip_set_timedate(double rDate){
238 char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate);
239 zip_set_timedate_from_str(zDate);
240 fossil_free(zDate);
@@ -267,11 +267,11 @@
267 char zHdr[30];
268 char zExTime[13];
269 char zBuf[100];
270 char zOutBuf[100000];
271
272 /* Fill in as much of the header as we know.
273 */
274 nameLen = (int)strlen(zName);
275 if( nameLen==0 ) return;
276 nBlob = pFile ? blob_size(pFile) : 0;
277 if( pFile ){ /* This is a file, possibly empty... */
@@ -984,11 +984,11 @@
984 ** part of the name= value after the / is the download
985 ** filename. If no check-in is specified by either
986 ** name= or r=, then the name of the main branch
987 ** (usually "trunk") is used.
988 **
989 ** in=PATTERN Only include files that match the comma-separate
990 ** list of GLOB patterns in PATTERN, as with ex=
991 **
992 ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
993 ** comma-separated list of GLOB patterns, where each
994 ** pattern can optionally be quoted using ".." or '..'.
995
--- src/zip.c
+++ src/zip.c
@@ -230,11 +230,11 @@
230 dosTime = (H<<11) + (M<<5) + (S>>1);
231 dosDate = ((y-1980)<<9) + (m<<5) + d;
232 }
233
234 /*
235 ** Set the date and time from a Julian day number.
236 */
237 void zip_set_timedate(double rDate){
238 char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate);
239 zip_set_timedate_from_str(zDate);
240 fossil_free(zDate);
@@ -267,11 +267,11 @@
267 char zHdr[30];
268 char zExTime[13];
269 char zBuf[100];
270 char zOutBuf[100000];
271
272 /* Fill inasmuch of the header as we know.
273 */
274 nameLen = (int)strlen(zName);
275 if( nameLen==0 ) return;
276 nBlob = pFile ? blob_size(pFile) : 0;
277 if( pFile ){ /* This is a file, possibly empty... */
@@ -984,11 +984,11 @@
984 ** part of the name= value after the / is the download
985 ** filename. If no check-in is specified by either
986 ** name= or r=, then the name of the main branch
987 ** (usually "trunk") is used.
988 **
989 ** in=PATTERN Only include files that match the comma-separated
990 ** list of GLOB patterns in PATTERN, as with ex=
991 **
992 ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
993 ** comma-separated list of GLOB patterns, where each
994 ** pattern can optionally be quoted using ".." or '..'.
995
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -443,11 +443,11 @@
443443
const struct FmtFunc *pB = (const struct FmtFunc*)pBB;
444444
return strcmp(pA->zFName, pB->zFName);
445445
}
446446
447447
/*
448
-** Determine if the indentifier zIdent of length nIndent is a Fossil
448
+** Determine if the identifier zIdent of length nIndent is a Fossil
449449
** internal interface that uses a printf-style argument. Return zero if not.
450450
** Return the index of the format string if true with the left-most
451451
** argument having an index of 1.
452452
*/
453453
static int isFormatFunc(const char *zIdent, int nIdent, unsigned *pFlags){
454454
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -443,11 +443,11 @@
443 const struct FmtFunc *pB = (const struct FmtFunc*)pBB;
444 return strcmp(pA->zFName, pB->zFName);
445 }
446
447 /*
448 ** Determine if the indentifier zIdent of length nIndent is a Fossil
449 ** internal interface that uses a printf-style argument. Return zero if not.
450 ** Return the index of the format string if true with the left-most
451 ** argument having an index of 1.
452 */
453 static int isFormatFunc(const char *zIdent, int nIdent, unsigned *pFlags){
454
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -443,11 +443,11 @@
443 const struct FmtFunc *pB = (const struct FmtFunc*)pBB;
444 return strcmp(pA->zFName, pB->zFName);
445 }
446
447 /*
448 ** Determine if the identifier zIdent of length nIndent is a Fossil
449 ** internal interface that uses a printf-style argument. Return zero if not.
450 ** Return the index of the format string if true with the left-most
451 ** argument having an index of 1.
452 */
453 static int isFormatFunc(const char *zIdent, int nIdent, unsigned *pFlags){
454
+61 -23
--- tools/mkindex.c
+++ tools/mkindex.c
@@ -17,15 +17,38 @@
1717
**
1818
** This utility program scans Fossil source text looking for specially
1919
** formatted comments and generates C source code for constant tables
2020
** that define the behavior of commands, webpages, and settings.
2121
**
22
+** USAGE:
23
+**
24
+** mkindex *.c >page_index.h
25
+**
26
+** Run this command with arguments that are all input source files to
27
+** scan. Generated C code appears on standard output. The generated
28
+** C code includes structures that:
29
+**
30
+** * Map command names to the C-language functions that implement
31
+** those command.
32
+**
33
+** * Map webpage names to the C-language functions that implement
34
+** those web pages.
35
+**
36
+** * Map settings into attributes, such as they default value for
37
+** each setting, and the kind of value (boolean, multi-line, etc).
38
+**
39
+** * Provide help text for commands, webpages, settings, and other
40
+** miscellanous help topics.
41
+**
42
+** COMMENT TEXT THAT THIS PROGRAM LOOKS FOR:
43
+**
2244
** The source code is scanned for comment lines of the form:
2345
**
2446
** WEBPAGE: /abc/xyz
2547
** COMMAND: cmdname
2648
** SETTING: access-log
49
+** TOPIC: help-topic
2750
**
2851
** The WEBPAGE and COMMAND comments should be followed by a function that
2952
** implements the webpage or command. The form of this function is:
3053
**
3154
** void function_name(void){
@@ -75,10 +98,22 @@
7598
** SETTING: pgp-command
7699
** DEFAULT: gpg --clearsign -o
77100
**
78101
** If no default is supplied, the default is assumed to be an empty string
79102
** or "off" in the case of a boolean.
103
+**
104
+** A TOPIC: is followed by help text for the named topic.
105
+**
106
+** OUTPUTS:
107
+**
108
+** The output is C-language text to define and initialize a constant
109
+** array of CmdOrPage objects named "aCommand[]". That array is a global
110
+** variable. The dispatch.c source file defines the CmdOrPage object and
111
+** deals with the aCommand[] global variable.
112
+**
113
+** The output also contains a constant array of Setting objects named
114
+** aSetting[]. The Setting object is defined in db.c.
80115
*/
81116
#include <stdio.h>
82117
#include <stdlib.h>
83118
#include <assert.h>
84119
#include <string.h>
@@ -85,26 +120,27 @@
85120
86121
/***************************************************************************
87122
** These macros must match similar macros in dispatch.c.
88123
**
89124
** Allowed values for CmdOrPage.eCmdFlags. */
90
-#define CMDFLAG_1ST_TIER 0x00001 /* Most important commands */
91
-#define CMDFLAG_2ND_TIER 0x00002 /* Obscure and seldom used commands */
92
-#define CMDFLAG_TEST 0x00004 /* Commands for testing only */
93
-#define CMDFLAG_WEBPAGE 0x00008 /* Web pages */
94
-#define CMDFLAG_COMMAND 0x00010 /* A command */
95
-#define CMDFLAG_SETTING 0x00020 /* A setting */
96
-#define CMDFLAG_VERSIONABLE 0x00040 /* A versionable setting */
97
-#define CMDFLAG_BLOCKTEXT 0x00080 /* Multi-line text setting */
98
-#define CMDFLAG_BOOLEAN 0x00100 /* A boolean setting */
99
-#define CMDFLAG_RAWCONTENT 0x00200 /* Do not interpret webpage content */
100
-#define CMDFLAG_SENSITIVE 0x00400 /* Security-sensitive setting */
101
-#define CMDFLAG_HIDDEN 0x00800 /* Elide from most listings */
102
-#define CMDFLAG_LDAVG_EXEMPT 0x01000 /* Exempt from load_control() */
103
-#define CMDFLAG_ALIAS 0x02000 /* Command aliases */
104
-#define CMDFLAG_KEEPEMPTY 0x04000 /* Do not unset empty settings */
105
-#define CMDFLAG_ABBREVSUBCMD 0x08000 /* Abbreviated subcmd in help text */
125
+#define CMDFLAG_1ST_TIER 0x000001 /* Most important commands */
126
+#define CMDFLAG_2ND_TIER 0x000002 /* Obscure and seldom used commands */
127
+#define CMDFLAG_TEST 0x000004 /* Commands for testing only */
128
+#define CMDFLAG_WEBPAGE 0x000008 /* Web pages */
129
+#define CMDFLAG_COMMAND 0x000010 /* A command */
130
+#define CMDFLAG_SETTING 0x000020 /* A setting */
131
+#define CMDFLAG_VERSIONABLE 0x000040 /* A versionable setting */
132
+#define CMDFLAG_BLOCKTEXT 0x000080 /* Multi-line text setting */
133
+#define CMDFLAG_BOOLEAN 0x000100 /* A boolean setting */
134
+#define CMDFLAG_RAWCONTENT 0x000200 /* Do not interpret webpage content */
135
+#define CMDFLAG_SENSITIVE 0x000400 /* Security-sensitive setting */
136
+#define CMDFLAG_HIDDEN 0x000800 /* Elide from most listings */
137
+#define CMDFLAG_LDAVG_EXEMPT 0x001000 /* Exempt from load_control() */
138
+#define CMDFLAG_ALIAS 0x002000 /* Command aliases */
139
+#define CMDFLAG_KEEPEMPTY 0x004000 /* Do not unset empty settings */
140
+#define CMDFLAG_ABBREVSUBCMD 0x008000 /* Abbreviated subcmd in help text */
141
+#define CMDFLAG_TOPIC 0x010000 /* A help topic */
106142
/**************************************************************************/
107143
108144
/*
109145
** Each entry looks like this:
110146
*/
@@ -343,20 +379,21 @@
343379
** Scan a line for a function that implements a web page or command.
344380
*/
345381
void scan_for_func(char *zLine){
346382
int i,j,k;
347383
char *z;
348
- int isSetting;
384
+ int hasFunc;
349385
if( nUsed<=nFixed ) return;
350386
if( strncmp(zLine, "**", 2)==0
351387
&& fossil_isspace(zLine[2])
352388
&& strlen(zLine)<sizeof(zHelp)-nHelp-1
353389
&& nUsed>nFixed
354390
&& strncmp(zLine,"** COMMAND:",11)!=0
355391
&& strncmp(zLine,"** WEBPAGE:",11)!=0
356392
&& strncmp(zLine,"** SETTING:",11)!=0
357393
&& strncmp(zLine,"** DEFAULT:",11)!=0
394
+ && strncmp(zLine,"** TOPIC:",9)!=0
358395
){
359396
if( zLine[2]=='\n' ){
360397
zHelp[nHelp++] = '\n';
361398
}else{
362399
if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
@@ -365,12 +402,12 @@
365402
}
366403
return;
367404
}
368405
for(i=0; fossil_isspace(zLine[i]); i++){}
369406
if( zLine[i]==0 ) return;
370
- isSetting = (aEntry[nFixed].eType & CMDFLAG_SETTING)!=0;
371
- if( !isSetting ){
407
+ hasFunc = (aEntry[nFixed].eType & (CMDFLAG_SETTING|CMDFLAG_TOPIC))==0;
408
+ if( hasFunc ){
372409
if( strncmp(&zLine[i],"void",4)!=0 ){
373410
if( zLine[i]!='*' ) goto page_skip;
374411
return;
375412
}
376413
i += 4;
@@ -390,16 +427,16 @@
390427
}else{
391428
z = "";
392429
}
393430
for(k=nFixed; k<nUsed; k++){
394431
aEntry[k].zIf = zIf[0] ? string_dup(zIf, -1) : 0;
395
- aEntry[k].zFunc = isSetting ? "0" : string_dup(&zLine[i], j);
432
+ aEntry[k].zFunc = hasFunc ? string_dup(&zLine[i], j) : "0";
396433
aEntry[k].zHelp = z;
397434
z = 0;
398435
aEntry[k].iHelp = nFixed;
399436
}
400
- if( !isSetting ){
437
+ if( hasFunc ){
401438
i+=j;
402439
while( fossil_isspace(zLine[i]) ){ i++; }
403440
if( zLine[i]!='(' ) goto page_skip;
404441
}
405442
nFixed = nUsed;
@@ -442,11 +479,11 @@
442479
"*/\n"
443480
);
444481
445482
/* Output declarations for all the action functions */
446483
for(i=0; i<nFixed; i++){
447
- if( aEntry[i].eType & CMDFLAG_SETTING ) continue;
484
+ if( aEntry[i].eType & (CMDFLAG_SETTING|CMDFLAG_TOPIC) ) continue;
448485
if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
449486
printf("extern void %s(void);\n", aEntry[i].zFunc);
450487
if( aEntry[i].zIf ) printf("#endif\n");
451488
}
452489
@@ -479,11 +516,11 @@
479516
if( aEntry[i].zIf ){
480517
printf("%s", aEntry[i].zIf);
481518
}else if( (aEntry[i].eType & CMDFLAG_WEBPAGE)!=0 ){
482519
nWeb++;
483520
}
484
- printf(" { \"%.*s\",%*s%s,%*szHelp%03d, %3d, 0x%03x },\n",
521
+ printf(" { \"%.*s\",%*s%s,%*szHelp%03d, %3d, 0x%05x },\n",
485522
n, z,
486523
25-n, "",
487524
aEntry[i].zFunc,
488525
(int)(29-strlen(aEntry[i].zFunc)), "",
489526
aEntry[i].iHelp,
@@ -550,10 +587,11 @@
550587
scan_for_label("WEBPAGE:",zLine,CMDFLAG_WEBPAGE);
551588
scan_for_label("COMMAND:",zLine,CMDFLAG_COMMAND);
552589
scan_for_func(zLine);
553590
scan_for_label("SETTING:",zLine,CMDFLAG_SETTING);
554591
scan_for_default(zLine);
592
+ scan_for_label("TOPIC:",zLine,CMDFLAG_TOPIC);
555593
}
556594
fclose(in);
557595
nUsed = nFixed;
558596
}
559597
560598
--- tools/mkindex.c
+++ tools/mkindex.c
@@ -17,15 +17,38 @@
17 **
18 ** This utility program scans Fossil source text looking for specially
19 ** formatted comments and generates C source code for constant tables
20 ** that define the behavior of commands, webpages, and settings.
21 **
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22 ** The source code is scanned for comment lines of the form:
23 **
24 ** WEBPAGE: /abc/xyz
25 ** COMMAND: cmdname
26 ** SETTING: access-log
 
27 **
28 ** The WEBPAGE and COMMAND comments should be followed by a function that
29 ** implements the webpage or command. The form of this function is:
30 **
31 ** void function_name(void){
@@ -75,10 +98,22 @@
75 ** SETTING: pgp-command
76 ** DEFAULT: gpg --clearsign -o
77 **
78 ** If no default is supplied, the default is assumed to be an empty string
79 ** or "off" in the case of a boolean.
 
 
 
 
 
 
 
 
 
 
 
 
80 */
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <assert.h>
84 #include <string.h>
@@ -85,26 +120,27 @@
85
86 /***************************************************************************
87 ** These macros must match similar macros in dispatch.c.
88 **
89 ** Allowed values for CmdOrPage.eCmdFlags. */
90 #define CMDFLAG_1ST_TIER 0x00001 /* Most important commands */
91 #define CMDFLAG_2ND_TIER 0x00002 /* Obscure and seldom used commands */
92 #define CMDFLAG_TEST 0x00004 /* Commands for testing only */
93 #define CMDFLAG_WEBPAGE 0x00008 /* Web pages */
94 #define CMDFLAG_COMMAND 0x00010 /* A command */
95 #define CMDFLAG_SETTING 0x00020 /* A setting */
96 #define CMDFLAG_VERSIONABLE 0x00040 /* A versionable setting */
97 #define CMDFLAG_BLOCKTEXT 0x00080 /* Multi-line text setting */
98 #define CMDFLAG_BOOLEAN 0x00100 /* A boolean setting */
99 #define CMDFLAG_RAWCONTENT 0x00200 /* Do not interpret webpage content */
100 #define CMDFLAG_SENSITIVE 0x00400 /* Security-sensitive setting */
101 #define CMDFLAG_HIDDEN 0x00800 /* Elide from most listings */
102 #define CMDFLAG_LDAVG_EXEMPT 0x01000 /* Exempt from load_control() */
103 #define CMDFLAG_ALIAS 0x02000 /* Command aliases */
104 #define CMDFLAG_KEEPEMPTY 0x04000 /* Do not unset empty settings */
105 #define CMDFLAG_ABBREVSUBCMD 0x08000 /* Abbreviated subcmd in help text */
 
106 /**************************************************************************/
107
108 /*
109 ** Each entry looks like this:
110 */
@@ -343,20 +379,21 @@
343 ** Scan a line for a function that implements a web page or command.
344 */
345 void scan_for_func(char *zLine){
346 int i,j,k;
347 char *z;
348 int isSetting;
349 if( nUsed<=nFixed ) return;
350 if( strncmp(zLine, "**", 2)==0
351 && fossil_isspace(zLine[2])
352 && strlen(zLine)<sizeof(zHelp)-nHelp-1
353 && nUsed>nFixed
354 && strncmp(zLine,"** COMMAND:",11)!=0
355 && strncmp(zLine,"** WEBPAGE:",11)!=0
356 && strncmp(zLine,"** SETTING:",11)!=0
357 && strncmp(zLine,"** DEFAULT:",11)!=0
 
358 ){
359 if( zLine[2]=='\n' ){
360 zHelp[nHelp++] = '\n';
361 }else{
362 if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
@@ -365,12 +402,12 @@
365 }
366 return;
367 }
368 for(i=0; fossil_isspace(zLine[i]); i++){}
369 if( zLine[i]==0 ) return;
370 isSetting = (aEntry[nFixed].eType & CMDFLAG_SETTING)!=0;
371 if( !isSetting ){
372 if( strncmp(&zLine[i],"void",4)!=0 ){
373 if( zLine[i]!='*' ) goto page_skip;
374 return;
375 }
376 i += 4;
@@ -390,16 +427,16 @@
390 }else{
391 z = "";
392 }
393 for(k=nFixed; k<nUsed; k++){
394 aEntry[k].zIf = zIf[0] ? string_dup(zIf, -1) : 0;
395 aEntry[k].zFunc = isSetting ? "0" : string_dup(&zLine[i], j);
396 aEntry[k].zHelp = z;
397 z = 0;
398 aEntry[k].iHelp = nFixed;
399 }
400 if( !isSetting ){
401 i+=j;
402 while( fossil_isspace(zLine[i]) ){ i++; }
403 if( zLine[i]!='(' ) goto page_skip;
404 }
405 nFixed = nUsed;
@@ -442,11 +479,11 @@
442 "*/\n"
443 );
444
445 /* Output declarations for all the action functions */
446 for(i=0; i<nFixed; i++){
447 if( aEntry[i].eType & CMDFLAG_SETTING ) continue;
448 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
449 printf("extern void %s(void);\n", aEntry[i].zFunc);
450 if( aEntry[i].zIf ) printf("#endif\n");
451 }
452
@@ -479,11 +516,11 @@
479 if( aEntry[i].zIf ){
480 printf("%s", aEntry[i].zIf);
481 }else if( (aEntry[i].eType & CMDFLAG_WEBPAGE)!=0 ){
482 nWeb++;
483 }
484 printf(" { \"%.*s\",%*s%s,%*szHelp%03d, %3d, 0x%03x },\n",
485 n, z,
486 25-n, "",
487 aEntry[i].zFunc,
488 (int)(29-strlen(aEntry[i].zFunc)), "",
489 aEntry[i].iHelp,
@@ -550,10 +587,11 @@
550 scan_for_label("WEBPAGE:",zLine,CMDFLAG_WEBPAGE);
551 scan_for_label("COMMAND:",zLine,CMDFLAG_COMMAND);
552 scan_for_func(zLine);
553 scan_for_label("SETTING:",zLine,CMDFLAG_SETTING);
554 scan_for_default(zLine);
 
555 }
556 fclose(in);
557 nUsed = nFixed;
558 }
559
560
--- tools/mkindex.c
+++ tools/mkindex.c
@@ -17,15 +17,38 @@
17 **
18 ** This utility program scans Fossil source text looking for specially
19 ** formatted comments and generates C source code for constant tables
20 ** that define the behavior of commands, webpages, and settings.
21 **
22 ** USAGE:
23 **
24 ** mkindex *.c >page_index.h
25 **
26 ** Run this command with arguments that are all input source files to
27 ** scan. Generated C code appears on standard output. The generated
28 ** C code includes structures that:
29 **
30 ** * Map command names to the C-language functions that implement
31 ** those command.
32 **
33 ** * Map webpage names to the C-language functions that implement
34 ** those web pages.
35 **
36 ** * Map settings into attributes, such as they default value for
37 ** each setting, and the kind of value (boolean, multi-line, etc).
38 **
39 ** * Provide help text for commands, webpages, settings, and other
40 ** miscellanous help topics.
41 **
42 ** COMMENT TEXT THAT THIS PROGRAM LOOKS FOR:
43 **
44 ** The source code is scanned for comment lines of the form:
45 **
46 ** WEBPAGE: /abc/xyz
47 ** COMMAND: cmdname
48 ** SETTING: access-log
49 ** TOPIC: help-topic
50 **
51 ** The WEBPAGE and COMMAND comments should be followed by a function that
52 ** implements the webpage or command. The form of this function is:
53 **
54 ** void function_name(void){
@@ -75,10 +98,22 @@
98 ** SETTING: pgp-command
99 ** DEFAULT: gpg --clearsign -o
100 **
101 ** If no default is supplied, the default is assumed to be an empty string
102 ** or "off" in the case of a boolean.
103 **
104 ** A TOPIC: is followed by help text for the named topic.
105 **
106 ** OUTPUTS:
107 **
108 ** The output is C-language text to define and initialize a constant
109 ** array of CmdOrPage objects named "aCommand[]". That array is a global
110 ** variable. The dispatch.c source file defines the CmdOrPage object and
111 ** deals with the aCommand[] global variable.
112 **
113 ** The output also contains a constant array of Setting objects named
114 ** aSetting[]. The Setting object is defined in db.c.
115 */
116 #include <stdio.h>
117 #include <stdlib.h>
118 #include <assert.h>
119 #include <string.h>
@@ -85,26 +120,27 @@
120
121 /***************************************************************************
122 ** These macros must match similar macros in dispatch.c.
123 **
124 ** Allowed values for CmdOrPage.eCmdFlags. */
125 #define CMDFLAG_1ST_TIER 0x000001 /* Most important commands */
126 #define CMDFLAG_2ND_TIER 0x000002 /* Obscure and seldom used commands */
127 #define CMDFLAG_TEST 0x000004 /* Commands for testing only */
128 #define CMDFLAG_WEBPAGE 0x000008 /* Web pages */
129 #define CMDFLAG_COMMAND 0x000010 /* A command */
130 #define CMDFLAG_SETTING 0x000020 /* A setting */
131 #define CMDFLAG_VERSIONABLE 0x000040 /* A versionable setting */
132 #define CMDFLAG_BLOCKTEXT 0x000080 /* Multi-line text setting */
133 #define CMDFLAG_BOOLEAN 0x000100 /* A boolean setting */
134 #define CMDFLAG_RAWCONTENT 0x000200 /* Do not interpret webpage content */
135 #define CMDFLAG_SENSITIVE 0x000400 /* Security-sensitive setting */
136 #define CMDFLAG_HIDDEN 0x000800 /* Elide from most listings */
137 #define CMDFLAG_LDAVG_EXEMPT 0x001000 /* Exempt from load_control() */
138 #define CMDFLAG_ALIAS 0x002000 /* Command aliases */
139 #define CMDFLAG_KEEPEMPTY 0x004000 /* Do not unset empty settings */
140 #define CMDFLAG_ABBREVSUBCMD 0x008000 /* Abbreviated subcmd in help text */
141 #define CMDFLAG_TOPIC 0x010000 /* A help topic */
142 /**************************************************************************/
143
144 /*
145 ** Each entry looks like this:
146 */
@@ -343,20 +379,21 @@
379 ** Scan a line for a function that implements a web page or command.
380 */
381 void scan_for_func(char *zLine){
382 int i,j,k;
383 char *z;
384 int hasFunc;
385 if( nUsed<=nFixed ) return;
386 if( strncmp(zLine, "**", 2)==0
387 && fossil_isspace(zLine[2])
388 && strlen(zLine)<sizeof(zHelp)-nHelp-1
389 && nUsed>nFixed
390 && strncmp(zLine,"** COMMAND:",11)!=0
391 && strncmp(zLine,"** WEBPAGE:",11)!=0
392 && strncmp(zLine,"** SETTING:",11)!=0
393 && strncmp(zLine,"** DEFAULT:",11)!=0
394 && strncmp(zLine,"** TOPIC:",9)!=0
395 ){
396 if( zLine[2]=='\n' ){
397 zHelp[nHelp++] = '\n';
398 }else{
399 if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
@@ -365,12 +402,12 @@
402 }
403 return;
404 }
405 for(i=0; fossil_isspace(zLine[i]); i++){}
406 if( zLine[i]==0 ) return;
407 hasFunc = (aEntry[nFixed].eType & (CMDFLAG_SETTING|CMDFLAG_TOPIC))==0;
408 if( hasFunc ){
409 if( strncmp(&zLine[i],"void",4)!=0 ){
410 if( zLine[i]!='*' ) goto page_skip;
411 return;
412 }
413 i += 4;
@@ -390,16 +427,16 @@
427 }else{
428 z = "";
429 }
430 for(k=nFixed; k<nUsed; k++){
431 aEntry[k].zIf = zIf[0] ? string_dup(zIf, -1) : 0;
432 aEntry[k].zFunc = hasFunc ? string_dup(&zLine[i], j) : "0";
433 aEntry[k].zHelp = z;
434 z = 0;
435 aEntry[k].iHelp = nFixed;
436 }
437 if( hasFunc ){
438 i+=j;
439 while( fossil_isspace(zLine[i]) ){ i++; }
440 if( zLine[i]!='(' ) goto page_skip;
441 }
442 nFixed = nUsed;
@@ -442,11 +479,11 @@
479 "*/\n"
480 );
481
482 /* Output declarations for all the action functions */
483 for(i=0; i<nFixed; i++){
484 if( aEntry[i].eType & (CMDFLAG_SETTING|CMDFLAG_TOPIC) ) continue;
485 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
486 printf("extern void %s(void);\n", aEntry[i].zFunc);
487 if( aEntry[i].zIf ) printf("#endif\n");
488 }
489
@@ -479,11 +516,11 @@
516 if( aEntry[i].zIf ){
517 printf("%s", aEntry[i].zIf);
518 }else if( (aEntry[i].eType & CMDFLAG_WEBPAGE)!=0 ){
519 nWeb++;
520 }
521 printf(" { \"%.*s\",%*s%s,%*szHelp%03d, %3d, 0x%05x },\n",
522 n, z,
523 25-n, "",
524 aEntry[i].zFunc,
525 (int)(29-strlen(aEntry[i].zFunc)), "",
526 aEntry[i].iHelp,
@@ -550,10 +587,11 @@
587 scan_for_label("WEBPAGE:",zLine,CMDFLAG_WEBPAGE);
588 scan_for_label("COMMAND:",zLine,CMDFLAG_COMMAND);
589 scan_for_func(zLine);
590 scan_for_label("SETTING:",zLine,CMDFLAG_SETTING);
591 scan_for_default(zLine);
592 scan_for_label("TOPIC:",zLine,CMDFLAG_TOPIC);
593 }
594 fclose(in);
595 nUsed = nFixed;
596 }
597
598
--- www/antibot.wiki
+++ www/antibot.wiki
@@ -139,11 +139,11 @@
139139
The [/help/robot-restrict|robot-restrict setting] is a comma-separated
140140
list of GLOB patterns for pages for which robot access is prohibited.
141141
The default value is:
142142
143143
<blockquote><pre>
144
-timelineX,diff,annotate,fileage,file,finfo,reports
144
+timelineX,diff,annotate,fileage,file,finfo,reports,tree,hexdump,download
145145
</pre></blockquote>
146146
147147
Each entry corresponds to the first path element on the URI for a
148148
Fossil-generated page. If Fossil does not know for certain that the
149149
HTTP request is coming from a human, then any attempt to access one of
150150
--- www/antibot.wiki
+++ www/antibot.wiki
@@ -139,11 +139,11 @@
139 The [/help/robot-restrict|robot-restrict setting] is a comma-separated
140 list of GLOB patterns for pages for which robot access is prohibited.
141 The default value is:
142
143 <blockquote><pre>
144 timelineX,diff,annotate,fileage,file,finfo,reports
145 </pre></blockquote>
146
147 Each entry corresponds to the first path element on the URI for a
148 Fossil-generated page. If Fossil does not know for certain that the
149 HTTP request is coming from a human, then any attempt to access one of
150
--- www/antibot.wiki
+++ www/antibot.wiki
@@ -139,11 +139,11 @@
139 The [/help/robot-restrict|robot-restrict setting] is a comma-separated
140 list of GLOB patterns for pages for which robot access is prohibited.
141 The default value is:
142
143 <blockquote><pre>
144 timelineX,diff,annotate,fileage,file,finfo,reports,tree,hexdump,download
145 </pre></blockquote>
146
147 Each entry corresponds to the first path element on the URI for a
148 Fossil-generated page. If Fossil does not know for certain that the
149 HTTP request is coming from a human, then any attempt to access one of
150
--- www/changes.wiki
+++ www/changes.wiki
@@ -23,10 +23,12 @@
2323
[/help/suggested-downloads|suggested-downloads setting], a
2424
link to [/download] named "Tarballs and ZIPs" appears in the
2525
[/sitemap] and thus on the hamburger menu.
2626
<li> The filenames for tarballs and ZIPs are now standardized to
2727
include a timestamp and a hash prefix.
28
+ <li> New "[/help/get|fossil get]" command downloads and unpacks a specific
29
+ check-in without having to clone the repository.
2830
</ol>
2931
<li> Timeline enhancements:<ol type="a">
3032
<li> A new "Simple" view is available. This is compromise between "Verbose"
3133
and "Compact" that shows only the check-in hash rather than the full
3234
detail section. There is an ellipsis that one can click on to see the
@@ -42,10 +44,12 @@
4244
<li> "No-graph" timelines (using the "ng" query parameter) now show
4345
branch colors and bare check-in circles on the left. The check-in
4446
circles appear, but no lines connecting them.
4547
([/timeline?ng|example]).
4648
</ol>
49
+ <li> Labels in Markdown now have IDs generated using the GitHub "slugify"
50
+ algorithm.
4751
<li> The [/help/timeline|timeline command] is enhanced with the new options
4852
"<tt>-u|--for-user</tt>" to filter by user, and "<tt>-r</tt>" to display
4953
entries in chronological order.
5054
<li> The [/help/open|open command]'s new "<tt>--reopen REPOFILE</tt>" flag
5155
can be used to fix a checkout after moving its repository file.
5256
--- www/changes.wiki
+++ www/changes.wiki
@@ -23,10 +23,12 @@
23 [/help/suggested-downloads|suggested-downloads setting], a
24 link to [/download] named "Tarballs and ZIPs" appears in the
25 [/sitemap] and thus on the hamburger menu.
26 <li> The filenames for tarballs and ZIPs are now standardized to
27 include a timestamp and a hash prefix.
 
 
28 </ol>
29 <li> Timeline enhancements:<ol type="a">
30 <li> A new "Simple" view is available. This is compromise between "Verbose"
31 and "Compact" that shows only the check-in hash rather than the full
32 detail section. There is an ellipsis that one can click on to see the
@@ -42,10 +44,12 @@
42 <li> "No-graph" timelines (using the "ng" query parameter) now show
43 branch colors and bare check-in circles on the left. The check-in
44 circles appear, but no lines connecting them.
45 ([/timeline?ng|example]).
46 </ol>
 
 
47 <li> The [/help/timeline|timeline command] is enhanced with the new options
48 "<tt>-u|--for-user</tt>" to filter by user, and "<tt>-r</tt>" to display
49 entries in chronological order.
50 <li> The [/help/open|open command]'s new "<tt>--reopen REPOFILE</tt>" flag
51 can be used to fix a checkout after moving its repository file.
52
--- www/changes.wiki
+++ www/changes.wiki
@@ -23,10 +23,12 @@
23 [/help/suggested-downloads|suggested-downloads setting], a
24 link to [/download] named "Tarballs and ZIPs" appears in the
25 [/sitemap] and thus on the hamburger menu.
26 <li> The filenames for tarballs and ZIPs are now standardized to
27 include a timestamp and a hash prefix.
28 <li> New "[/help/get|fossil get]" command downloads and unpacks a specific
29 check-in without having to clone the repository.
30 </ol>
31 <li> Timeline enhancements:<ol type="a">
32 <li> A new "Simple" view is available. This is compromise between "Verbose"
33 and "Compact" that shows only the check-in hash rather than the full
34 detail section. There is an ellipsis that one can click on to see the
@@ -42,10 +44,12 @@
44 <li> "No-graph" timelines (using the "ng" query parameter) now show
45 branch colors and bare check-in circles on the left. The check-in
46 circles appear, but no lines connecting them.
47 ([/timeline?ng|example]).
48 </ol>
49 <li> Labels in Markdown now have IDs generated using the GitHub "slugify"
50 algorithm.
51 <li> The [/help/timeline|timeline command] is enhanced with the new options
52 "<tt>-u|--for-user</tt>" to filter by user, and "<tt>-r</tt>" to display
53 entries in chronological order.
54 <li> The [/help/open|open command]'s new "<tt>--reopen REPOFILE</tt>" flag
55 can be used to fix a checkout after moving its repository file.
56
--- www/customskin.md
+++ www/customskin.md
@@ -336,11 +336,12 @@
336336
output and is instead run as a TH1 script. That TH1
337337
script has the opportunity to insert new text in place of itself,
338338
or to inhibit or enable the output of subsequent text.
339339
340340
* Text of the form "$NAME" or "$&lt;NAME&gt;" is replaced with
341
- the value of the TH1 variable NAME.
341
+ the value of the TH1 variable NAME. See the [TH1 Variables](#vars)
342
+ section for more information on the two possible variable formats.
342343
343344
For example, first few lines of a typical Skin Header will look
344345
like this:
345346
346347
<div class="header">
@@ -424,18 +425,32 @@
424425
## <a id="vars"></a>TH1 Variables
425426
426427
Before expanding the TH1 within the header and footer, Fossil first
427428
initializes a number of TH1 variables to values that depend on
428429
repository settings and the specific page being generated.
430
+
431
+Variables holding text that is loaded from "external, potentially untrusted"
432
+sources (including the repository settings) are treated as [tainted strings]
433
+(./th1.md#taint) and must be noted in the `$<NAME>` form, instead of `$NAME`,
434
+or they may trigger an error (see the linked document for details). The
435
+`$<NAME>` form corresponds to the TH1 statement `puts [ htmlize "$NAME" ]`,
436
+where the [htmlize](./th1.md#htmlize) function escapes the tainted string,
437
+making it safe for output in HTML code.
438
+
429439
430440
* **`project_name`** - The project_name variable is filled with the
431441
name of the project as configured under the Admin/Configuration
432
- menu.
442
+ menu. This is a [tainted string](./th1.md#taint) variable and must
443
+ be used as `$<project_name>`.
433444
434445
* **`project_description`** - The project_description variable is
435446
filled with the description of the project as configured under
436
- the Admin/Configuration menu.
447
+ the Admin/Configuration menu. This is a [tainted string]
448
+ (./th1.md#taint) variable and must be used as `$<project_description>`.
449
+
450
+ * **`mainmenu`** - The mainmenu variable contains a TCL list with the main
451
+ menu entries. See the [mainmenu](/help/mainmenu) setting for details.
437452
438453
* **`title`** - The title variable holds the title of the page being
439454
generated.
440455
441456
The title variable is special in that it is deleted after
442457
--- www/customskin.md
+++ www/customskin.md
@@ -336,11 +336,12 @@
336 output and is instead run as a TH1 script. That TH1
337 script has the opportunity to insert new text in place of itself,
338 or to inhibit or enable the output of subsequent text.
339
340 * Text of the form "$NAME" or "$&lt;NAME&gt;" is replaced with
341 the value of the TH1 variable NAME.
 
342
343 For example, first few lines of a typical Skin Header will look
344 like this:
345
346 <div class="header">
@@ -424,18 +425,32 @@
424 ## <a id="vars"></a>TH1 Variables
425
426 Before expanding the TH1 within the header and footer, Fossil first
427 initializes a number of TH1 variables to values that depend on
428 repository settings and the specific page being generated.
 
 
 
 
 
 
 
 
 
429
430 * **`project_name`** - The project_name variable is filled with the
431 name of the project as configured under the Admin/Configuration
432 menu.
 
433
434 * **`project_description`** - The project_description variable is
435 filled with the description of the project as configured under
436 the Admin/Configuration menu.
 
 
 
 
437
438 * **`title`** - The title variable holds the title of the page being
439 generated.
440
441 The title variable is special in that it is deleted after
442
--- www/customskin.md
+++ www/customskin.md
@@ -336,11 +336,12 @@
336 output and is instead run as a TH1 script. That TH1
337 script has the opportunity to insert new text in place of itself,
338 or to inhibit or enable the output of subsequent text.
339
340 * Text of the form "$NAME" or "$&lt;NAME&gt;" is replaced with
341 the value of the TH1 variable NAME. See the [TH1 Variables](#vars)
342 section for more information on the two possible variable formats.
343
344 For example, first few lines of a typical Skin Header will look
345 like this:
346
347 <div class="header">
@@ -424,18 +425,32 @@
425 ## <a id="vars"></a>TH1 Variables
426
427 Before expanding the TH1 within the header and footer, Fossil first
428 initializes a number of TH1 variables to values that depend on
429 repository settings and the specific page being generated.
430
431 Variables holding text that is loaded from "external, potentially untrusted"
432 sources (including the repository settings) are treated as [tainted strings]
433 (./th1.md#taint) and must be noted in the `$<NAME>` form, instead of `$NAME`,
434 or they may trigger an error (see the linked document for details). The
435 `$<NAME>` form corresponds to the TH1 statement `puts [ htmlize "$NAME" ]`,
436 where the [htmlize](./th1.md#htmlize) function escapes the tainted string,
437 making it safe for output in HTML code.
438
439
440 * **`project_name`** - The project_name variable is filled with the
441 name of the project as configured under the Admin/Configuration
442 menu. This is a [tainted string](./th1.md#taint) variable and must
443 be used as `$<project_name>`.
444
445 * **`project_description`** - The project_description variable is
446 filled with the description of the project as configured under
447 the Admin/Configuration menu. This is a [tainted string]
448 (./th1.md#taint) variable and must be used as `$<project_description>`.
449
450 * **`mainmenu`** - The mainmenu variable contains a TCL list with the main
451 menu entries. See the [mainmenu](/help/mainmenu) setting for details.
452
453 * **`title`** - The title variable holds the title of the page being
454 generated.
455
456 The title variable is special in that it is deleted after
457
--- www/serverext.wiki
+++ www/serverext.wiki
@@ -139,11 +139,11 @@
139139
For example, the author of this documentation page is running
140140
"<tt>fossil ui --extpage www/serverext.wiki</tt>" while editing this
141141
very paragraph, and presses Reload from time to time to view his
142142
edits.
143143
144
-A same idea applies when developing new CGI applications using a script
144
+The same idea applies when developing new CGI applications using a script
145145
language (for example using [https://wapp.tcl.tk|Wapp]). Run the
146146
command "<tt>fossil ui --extpage SCRIPT</tt>" where SCRIPT is the name
147147
of the application script, while editing that script in a separate
148148
window, then press Reload periodically on the web browser to test the
149149
script.
150150
--- www/serverext.wiki
+++ www/serverext.wiki
@@ -139,11 +139,11 @@
139 For example, the author of this documentation page is running
140 "<tt>fossil ui --extpage www/serverext.wiki</tt>" while editing this
141 very paragraph, and presses Reload from time to time to view his
142 edits.
143
144 A same idea applies when developing new CGI applications using a script
145 language (for example using [https://wapp.tcl.tk|Wapp]). Run the
146 command "<tt>fossil ui --extpage SCRIPT</tt>" where SCRIPT is the name
147 of the application script, while editing that script in a separate
148 window, then press Reload periodically on the web browser to test the
149 script.
150
--- www/serverext.wiki
+++ www/serverext.wiki
@@ -139,11 +139,11 @@
139 For example, the author of this documentation page is running
140 "<tt>fossil ui --extpage www/serverext.wiki</tt>" while editing this
141 very paragraph, and presses Reload from time to time to view his
142 edits.
143
144 The same idea applies when developing new CGI applications using a script
145 language (for example using [https://wapp.tcl.tk|Wapp]). Run the
146 command "<tt>fossil ui --extpage SCRIPT</tt>" where SCRIPT is the name
147 of the application script, while editing that script in a separate
148 window, then press Reload periodically on the web browser to test the
149 script.
150

Keyboard Shortcuts

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