Fossil SCM

Bring in the latest SQLite sources from upstream for testing, especially the renovated CLI code.

drh 2025-11-28 19:25 trunk
Commit f4b3b598c055231ccb5662a5b9212fa365cfb1aab9ac676227e8fcbf406b3062
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -35,10 +35,11 @@
3535
unsigned char bWordWrap; /* Try to wrap on word boundaries */
3636
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
3737
unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
3838
unsigned char eTitleAlign; /* Alignment for column headers */
3939
unsigned char bSplitColumn; /* Wrap single-column output into many columns */
40
+ unsigned char bBorder; /* Show outer border in Box and Table styles */
4041
short int nWrap; /* Wrap columns wider than this */
4142
short int nScreenWidth; /* Maximum overall table width */
4243
short int nLineLimit; /* Maximum number of lines for any row */
4344
int nCharLimit; /* Maximum number of characters in a cell */
4445
int nWidth; /* Number of entries in aWidth[] */
4546
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -35,10 +35,11 @@
35 unsigned char bWordWrap; /* Try to wrap on word boundaries */
36 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
37 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
38 unsigned char eTitleAlign; /* Alignment for column headers */
39 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
 
40 short int nWrap; /* Wrap columns wider than this */
41 short int nScreenWidth; /* Maximum overall table width */
42 short int nLineLimit; /* Maximum number of lines for any row */
43 int nCharLimit; /* Maximum number of characters in a cell */
44 int nWidth; /* Number of entries in aWidth[] */
45
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -35,10 +35,11 @@
35 unsigned char bWordWrap; /* Try to wrap on word boundaries */
36 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
37 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
38 unsigned char eTitleAlign; /* Alignment for column headers */
39 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
40 unsigned char bBorder; /* Show outer border in Box and Table styles */
41 short int nWrap; /* Wrap columns wider than this */
42 short int nScreenWidth; /* Maximum overall table width */
43 short int nLineLimit; /* Maximum number of lines for any row */
44 int nCharLimit; /* Maximum number of characters in a cell */
45 int nWidth; /* Number of entries in aWidth[] */
46
+201 -96
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -704,10 +704,11 @@
704704
unsigned char bWordWrap; /* Try to wrap on word boundaries */
705705
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
706706
unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
707707
unsigned char eTitleAlign; /* Alignment for column headers */
708708
unsigned char bSplitColumn; /* Wrap single-column output into many columns */
709
+ unsigned char bBorder; /* Show outer border in Box and Table styles */
709710
short int nWrap; /* Wrap columns wider than this */
710711
short int nScreenWidth; /* Maximum overall table width */
711712
short int nLineLimit; /* Maximum number of lines for any row */
712713
int nCharLimit; /* Maximum number of characters in a cell */
713714
int nWidth; /* Number of entries in aWidth[] */
@@ -2124,40 +2125,10 @@
21242125
}
21252126
}
21262127
sqlite3_str_append(pOut, (const char*)z, i);
21272128
}
21282129
2129
-/*
2130
-** Output horizontally justified text into pOut. The text is the
2131
-** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2132
-** split between both sides, or on the left, or on the right, depending
2133
-** on eAlign.
2134
-*/
2135
-static void qrfPrintAligned(
2136
- sqlite3_str *pOut, /* Append text here */
2137
- const char *zVal, /* Text to append */
2138
- int nVal, /* Use only the first nVal bytes of zVal[] */
2139
- int nWS, /* Whitespace for horizonal alignment */
2140
- unsigned char eAlign /* Alignment type */
2141
-){
2142
- eAlign &= QRF_ALIGN_HMASK;
2143
- if( eAlign==QRF_ALIGN_Center ){
2144
- /* Center the text */
2145
- sqlite3_str_appendchar(pOut, nWS/2, ' ');
2146
- qrfAppendWithTabs(pOut, zVal, nVal);
2147
- sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2148
- }else if( eAlign==QRF_ALIGN_Right){
2149
- /* Right justify the text */
2150
- sqlite3_str_appendchar(pOut, nWS, ' ');
2151
- qrfAppendWithTabs(pOut, zVal, nVal);
2152
- }else{
2153
- /* Left justify the next */
2154
- qrfAppendWithTabs(pOut, zVal, nVal);
2155
- sqlite3_str_appendchar(pOut, nWS, ' ');
2156
- }
2157
-}
2158
-
21592130
/*
21602131
** GCC does not define the offsetof() macro so we'll have to do it
21612132
** ourselves.
21622133
*/
21632134
#ifndef offsetof
@@ -2177,27 +2148,60 @@
21772148
sqlite3_int64 nRow; /* Number of rows */
21782149
sqlite3_int64 nAlloc; /* Number of cells allocated */
21792150
sqlite3_int64 n; /* Number of cells. nCol*nRow */
21802151
char **az; /* Content of all cells */
21812152
int *aiWth; /* Width of each cell */
2153
+ unsigned char *abNum; /* True for each numeric cell */
21822154
struct qrfPerCol { /* Per-column data */
21832155
char *z; /* Cache of text for current row */
21842156
int w; /* Computed width of this column */
21852157
int mxW; /* Maximum natural (unwrapped) width */
21862158
unsigned char e; /* Alignment */
21872159
unsigned char fx; /* Width is fixed */
2160
+ unsigned char bNum; /* True if is numeric */
21882161
} *a; /* One per column */
21892162
};
2163
+
2164
+/*
2165
+** Output horizontally justified text into pOut. The text is the
2166
+** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2167
+** split between both sides, or on the left, or on the right, depending
2168
+** on eAlign.
2169
+*/
2170
+static void qrfPrintAligned(
2171
+ sqlite3_str *pOut, /* Append text here */
2172
+ struct qrfPerCol *pCol, /* Information about the text to print */
2173
+ int nVal, /* Use only the first nVal bytes of zVal[] */
2174
+ int nWS /* Whitespace for horizonal alignment */
2175
+){
2176
+ unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK;
2177
+ if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right;
2178
+ if( eAlign==QRF_ALIGN_Center ){
2179
+ /* Center the text */
2180
+ sqlite3_str_appendchar(pOut, nWS/2, ' ');
2181
+ qrfAppendWithTabs(pOut, pCol->z, nVal);
2182
+ sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2183
+ }else if( eAlign==QRF_ALIGN_Right ){
2184
+ /* Right justify the text */
2185
+ sqlite3_str_appendchar(pOut, nWS, ' ');
2186
+ qrfAppendWithTabs(pOut, pCol->z, nVal);
2187
+ }else{
2188
+ /* Left justify the text */
2189
+ qrfAppendWithTabs(pOut, pCol->z, nVal);
2190
+ sqlite3_str_appendchar(pOut, nWS, ' ');
2191
+ }
2192
+}
21902193
21912194
/*
21922195
** Free all the memory allocates in the qrfColData object
21932196
*/
21942197
static void qrfColDataFree(qrfColData *p){
21952198
sqlite3_int64 i;
21962199
for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
21972200
sqlite3_free(p->az);
21982201
sqlite3_free(p->aiWth);
2202
+ sqlite3_free(p->abNum);
21992203
sqlite3_free(p->a);
22002204
memset(p, 0, sizeof(*p));
22012205
}
22022206
22032207
/*
@@ -2205,10 +2209,11 @@
22052209
** Return non-zero if a memory allocation fails.
22062210
*/
22072211
static int qrfColDataEnlarge(qrfColData *p){
22082212
char **azData;
22092213
int *aiWth;
2214
+ unsigned char *abNum;
22102215
p->nAlloc = 2*p->nAlloc + 10*p->nCol;
22112216
azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
22122217
if( azData==0 ){
22132218
qrfOom(p->p);
22142219
qrfColDataFree(p);
@@ -2220,26 +2225,38 @@
22202225
qrfOom(p->p);
22212226
qrfColDataFree(p);
22222227
return 1;
22232228
}
22242229
p->aiWth = aiWth;
2230
+ abNum = sqlite3_realloc64(p->abNum, p->nAlloc);
2231
+ if( abNum==0 ){
2232
+ qrfOom(p->p);
2233
+ qrfColDataFree(p);
2234
+ return 1;
2235
+ }
2236
+ p->abNum = abNum;
22252237
return 0;
22262238
}
22272239
22282240
/*
22292241
** Print a markdown or table-style row separator using ascii-art
22302242
*/
22312243
static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
22322244
int i;
22332245
if( p->nCol>0 ){
2234
- sqlite3_str_append(pOut, &cSep, 1);
2246
+ int useBorder = p->p->spec.bBorder!=QRF_No;
2247
+ if( useBorder ){
2248
+ sqlite3_str_append(pOut, &cSep, 1);
2249
+ }
22352250
sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
22362251
for(i=1; i<p->nCol; i++){
22372252
sqlite3_str_append(pOut, &cSep, 1);
22382253
sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
22392254
}
2240
- sqlite3_str_append(pOut, &cSep, 1);
2255
+ if( useBorder ){
2256
+ sqlite3_str_append(pOut, &cSep, 1);
2257
+ }
22412258
}
22422259
sqlite3_str_append(pOut, "\n", 1);
22432260
}
22442261
22452262
/*
@@ -2293,17 +2310,22 @@
22932310
const char *zSep2,
22942311
const char *zSep3
22952312
){
22962313
int i;
22972314
if( p->nCol>0 ){
2298
- sqlite3_str_appendall(pOut, zSep1);
2315
+ int useBorder = p->p->spec.bBorder!=QRF_No;
2316
+ if( useBorder ){
2317
+ sqlite3_str_appendall(pOut, zSep1);
2318
+ }
22992319
qrfBoxLine(pOut, p->a[0].w+p->nMargin);
23002320
for(i=1; i<p->nCol; i++){
23012321
sqlite3_str_appendall(pOut, zSep2);
23022322
qrfBoxLine(pOut, p->a[i].w+p->nMargin);
23032323
}
2304
- sqlite3_str_appendall(pOut, zSep3);
2324
+ if( useBorder ){
2325
+ sqlite3_str_appendall(pOut, zSep3);
2326
+ }
23052327
}
23062328
sqlite3_str_append(pOut, "\n", 1);
23072329
}
23082330
23092331
/*
@@ -2382,10 +2404,11 @@
23822404
static void qrfSplitColumn(qrfColData *pData, Qrf *p){
23832405
int nCol = 1;
23842406
int *aw = 0;
23852407
char **az = 0;
23862408
int *aiWth = 0;
2409
+ unsigned char *abNum = 0;
23872410
int nColNext = 2;
23882411
int w;
23892412
struct qrfPerCol *a = 0;
23902413
sqlite3_int64 nRow = 1;
23912414
sqlite3_int64 i;
@@ -2419,35 +2442,47 @@
24192442
if( a==0 ){
24202443
sqlite3_free(az);
24212444
sqlite3_free(aiWth);
24222445
qrfOom(p);
24232446
return;
2447
+ }
2448
+ abNum = sqlite3_malloc64( nRow*nCol );
2449
+ if( abNum==0 ){
2450
+ sqlite3_free(az);
2451
+ sqlite3_free(aiWth);
2452
+ sqlite3_free(a);
2453
+ qrfOom(p);
2454
+ return;
24242455
}
24252456
for(i=0; i<pData->n; i++){
24262457
sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
24272458
az[j] = pData->az[i];
2459
+ abNum[j]= pData->abNum[i];
24282460
pData->az[i] = 0;
24292461
aiWth[j] = pData->aiWth[i];
24302462
}
24312463
while( i<nRow*nCol ){
24322464
sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
24332465
az[j] = sqlite3_mprintf("");
24342466
if( az[j]==0 ) qrfOom(p);
24352467
aiWth[j] = 0;
2468
+ abNum[j] = 0;
24362469
i++;
24372470
}
24382471
for(i=0; i<nCol; i++){
24392472
a[i].fx = a[i].mxW = a[i].w = aw[i];
24402473
a[i].e = pData->a[0].e;
24412474
}
24422475
sqlite3_free(pData->az);
24432476
sqlite3_free(pData->aiWth);
24442477
sqlite3_free(pData->a);
2478
+ sqlite3_free(pData->abNum);
24452479
sqlite3_free(aw);
24462480
pData->az = az;
24472481
pData->aiWth = aiWth;
24482482
pData->a = a;
2483
+ pData->abNum = abNum;
24492484
pData->nCol = nCol;
24502485
pData->n = pData->nAlloc = nRow*nCol;
24512486
for(i=w=0; i<nCol; i++) w += a[i].w;
24522487
pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
24532488
if( pData->nMargin>5 ) pData->nMargin = 5;
@@ -2467,10 +2502,11 @@
24672502
if( p->spec.nScreenWidth==0 ) return;
24682503
if( p->spec.eStyle==QRF_STYLE_Column ){
24692504
sepW = pData->nCol*2 - 2;
24702505
}else{
24712506
sepW = pData->nCol*3 + 1;
2507
+ if( p->spec.bBorder==QRF_No ) sepW -= 2;
24722508
}
24732509
nCol = pData->nCol;
24742510
for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
24752511
if( p->spec.nScreenWidth >= sumW+sepW ) return;
24762512
@@ -2478,10 +2514,11 @@
24782514
pData->nMargin = 0;
24792515
if( p->spec.eStyle==QRF_STYLE_Column ){
24802516
sepW = pData->nCol - 1;
24812517
}else{
24822518
sepW = pData->nCol + 1;
2519
+ if( p->spec.bBorder==QRF_No ) sepW -= 2;
24832520
}
24842521
targetW = p->spec.nScreenWidth - sepW;
24852522
24862523
#define MIN_SQUOZE 8
24872524
#define MIN_EX_SQUOZE 16
@@ -2550,10 +2587,11 @@
25502587
}
25512588
25522589
/* Initialize the data container */
25532590
memset(&data, 0, sizeof(data));
25542591
data.nCol = p->nCol;
2592
+ data.p = p;
25552593
data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
25562594
if( data.a==0 ){
25572595
qrfOom(p);
25582596
return;
25592597
}
@@ -2563,10 +2601,11 @@
25632601
25642602
/* Load the column header names and all cell content into data */
25652603
if( p->spec.bTitles==QRF_Yes ){
25662604
unsigned char saved_eText = p->spec.eText;
25672605
p->spec.eText = p->spec.eTitle;
2606
+ memset(data.abNum, 0, nColumn);
25682607
for(i=0; i<nColumn; i++){
25692608
const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
25702609
int nNL = 0;
25712610
int n, w;
25722611
pStr = sqlite3_str_new(p->db);
@@ -2587,14 +2626,16 @@
25872626
}
25882627
for(i=0; i<nColumn; i++){
25892628
char *z;
25902629
int nNL = 0;
25912630
int n, w;
2631
+ int eType = sqlite3_column_type(p->pStmt,i);
25922632
pStr = sqlite3_str_new(p->db);
25932633
qrfRenderValue(p, pStr, i);
25942634
n = sqlite3_str_length(pStr);
25952635
z = data.az[data.n] = sqlite3_str_finish(pStr);
2636
+ data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
25962637
data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
25972638
data.n++;
25982639
if( w>data.a[i].mxW ) data.a[i].mxW = w;
25992640
if( nNL ) data.bMultiRow = 1;
26002641
}
@@ -2680,11 +2721,16 @@
26802721
}else{
26812722
rowStart = BOX_13;
26822723
colSep = BOX_13;
26832724
rowSep = BOX_13 "\n";
26842725
}
2685
- qrfBoxSeparator(p->pOut, &data, BOX_23, BOX_234, BOX_34);
2726
+ if( p->spec.bBorder==QRF_No){
2727
+ rowStart += 3;
2728
+ rowSep = "\n";
2729
+ }else{
2730
+ qrfBoxSeparator(p->pOut, &data, BOX_23, BOX_234, BOX_34);
2731
+ }
26862732
break;
26872733
case QRF_STYLE_Table:
26882734
if( data.nMargin ){
26892735
rowStart = "| ";
26902736
colSep = " | ";
@@ -2692,11 +2738,16 @@
26922738
}else{
26932739
rowStart = "|";
26942740
colSep = "|";
26952741
rowSep = "|\n";
26962742
}
2697
- qrfRowSeparator(p->pOut, &data, '+');
2743
+ if( p->spec.bBorder==QRF_No ){
2744
+ rowStart += 1;
2745
+ rowSep = "\n";
2746
+ }else{
2747
+ qrfRowSeparator(p->pOut, &data, '+');
2748
+ }
26982749
break;
26992750
case QRF_STYLE_Column: {
27002751
static const char zSpace[] = " ";
27012752
rowStart = "";
27022753
if( data.nMargin<2 ){
@@ -2724,20 +2775,31 @@
27242775
szRowStart = (int)strlen(rowStart);
27252776
szRowSep = (int)strlen(rowSep);
27262777
szColSep = (int)strlen(colSep);
27272778
27282779
bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2729
- bRTrim = (p->spec.eStyle==QRF_STYLE_Column);
2780
+ if( p->spec.eStyle==QRF_STYLE_Column
2781
+ || (p->spec.bBorder==QRF_No
2782
+ && (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table)
2783
+ )
2784
+ ){
2785
+ bRTrim = 1;
2786
+ }else{
2787
+ bRTrim = 0;
2788
+ }
27302789
for(i=0; i<data.n; i+=nColumn){
27312790
int bMore;
27322791
int nRow = 0;
27332792
27342793
/* Draw a single row of the table. This might be the title line
27352794
** (if there is a title line) or a row in the body of the table.
27362795
** The column number will be j. The row number is i/nColumn.
27372796
*/
2738
- for(j=0; j<nColumn; j++){ data.a[j].z = data.az[i+j]; }
2797
+ for(j=0; j<nColumn; j++){
2798
+ data.a[j].z = data.az[i+j];
2799
+ data.a[j].bNum = data.abNum[i+j];
2800
+ }
27392801
do{
27402802
sqlite3_str_append(p->pOut, rowStart, szRowStart);
27412803
bMore = 0;
27422804
for(j=0; j<nColumn; j++){
27432805
int nThis = 0;
@@ -2744,11 +2806,11 @@
27442806
int nWide = 0;
27452807
int iNext = 0;
27462808
int nWS;
27472809
qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
27482810
nWS = data.a[j].w - nWide;
2749
- qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
2811
+ qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS);
27502812
data.a[j].z += iNext;
27512813
if( data.a[j].z[0]!=0 ){
27522814
bMore = 1;
27532815
}
27542816
if( j<nColumn-1 ){
@@ -2766,11 +2828,12 @@
27662828
if( data.a[j].z[0]==0 ){
27672829
sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
27682830
}else{
27692831
int nE = 3;
27702832
if( nE>data.a[j].w ) nE = data.a[j].w;
2771
- qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
2833
+ data.a[j].z = "...";
2834
+ qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE);
27722835
}
27732836
if( j<nColumn-1 ){
27742837
sqlite3_str_append(p->pOut, colSep, szColSep);
27752838
}else{
27762839
if( bRTrim ) qrfRTrim(p->pOut);
@@ -2827,17 +2890,19 @@
28272890
}
28282891
}
28292892
}
28302893
28312894
/* Draw the line across the bottom of the table */
2832
- switch( p->spec.eStyle ){
2833
- case QRF_STYLE_Box:
2834
- qrfBoxSeparator(p->pOut, &data, BOX_12, BOX_124, BOX_14);
2835
- break;
2836
- case QRF_STYLE_Table:
2837
- qrfRowSeparator(p->pOut, &data, '+');
2838
- break;
2895
+ if( p->spec.bBorder!=QRF_No ){
2896
+ switch( p->spec.eStyle ){
2897
+ case QRF_STYLE_Box:
2898
+ qrfBoxSeparator(p->pOut, &data, BOX_12, BOX_124, BOX_14);
2899
+ break;
2900
+ case QRF_STYLE_Table:
2901
+ qrfRowSeparator(p->pOut, &data, '+');
2902
+ break;
2903
+ }
28392904
}
28402905
qrfWrite(p);
28412906
28422907
qrfColDataFree(&data);
28432908
return;
@@ -6013,17 +6078,20 @@
60136078
}
60146079
/* End of the hashing logic
60156080
*****************************************************************************/
60166081
60176082
/*
6018
-** Implementation of the sha1(X) function.
6083
+** Two SQL functions: sha1(X) and sha1b(X).
60196084
**
6020
-** Return a lower-case hexadecimal rendering of the SHA1 hash of the
6021
-** argument X. If X is a BLOB, it is hashed as is. For all other
6085
+** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash
6086
+** of the argument X. If X is a BLOB, it is hashed as is. For all other
60226087
** types of input, X is converted into a UTF-8 string and the string
6023
-** is hash without the trailing 0x00 terminator. The hash of a NULL
6088
+** is hashed without the trailing 0x00 terminator. The hash of a NULL
60246089
** value is NULL.
6090
+**
6091
+** sha1b(X) is the same except that it returns a 20-byte BLOB containing
6092
+** the binary hash instead of a hexadecimal string.
60256093
*/
60266094
static void sha1Func(
60276095
sqlite3_context *context,
60286096
int argc,
60296097
sqlite3_value **argv
@@ -6040,15 +6108,17 @@
60406108
hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
60416109
}else{
60426110
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
60436111
}
60446112
if( sqlite3_user_data(context)!=0 ){
6113
+ /* sha1b() - binary result */
60456114
hash_finish(&cx, zOut, 1);
60466115
sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
60476116
}else{
6117
+ /* sha1() - hexadecimal text result */
60486118
hash_finish(&cx, zOut, 0);
6049
- sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT);
6119
+ sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
60506120
}
60516121
}
60526122
60536123
/*
60546124
** Implementation of the sha1_query(SQL) function.
@@ -24120,19 +24190,20 @@
2412024190
#define MODE_Json 10 /* Output JSON */
2412124191
#define MODE_Line 11 /* One column per line. Blank line between records */
2412224192
#define MODE_List 12 /* One record per line with a separator */
2412324193
#define MODE_Markdown 13 /* Markdown formatting */
2412424194
#define MODE_Off 14 /* No query output shown */
24125
-#define MODE_QBox 15 /* BOX with SQL-quoted content */
24126
-#define MODE_Quote 16 /* Quote values as for SQL */
24127
-#define MODE_Split 17 /* Split-column mode */
24128
-#define MODE_Table 18 /* MySQL-style table formatting */
24129
-#define MODE_Tabs 19 /* Tab-separated values */
24130
-#define MODE_Tcl 20 /* Space-separated list of TCL strings */
24131
-#define MODE_Www 21 /* Full web-page output */
24132
-
24133
-#define MODE_BUILTIN 21 /* Maximum built-in mode */
24195
+#define MODE_Psql 15 /* Similar to psql */
24196
+#define MODE_QBox 16 /* BOX with SQL-quoted content */
24197
+#define MODE_Quote 17 /* Quote values as for SQL */
24198
+#define MODE_Split 18 /* Split-column mode */
24199
+#define MODE_Table 19 /* MySQL-style table formatting */
24200
+#define MODE_Tabs 20 /* Tab-separated values */
24201
+#define MODE_Tcl 21 /* Space-separated list of TCL strings */
24202
+#define MODE_Www 22 /* Full web-page output */
24203
+
24204
+#define MODE_BUILTIN 22 /* Maximum built-in mode */
2413424205
#define MODE_BATCH 50 /* Default mode for batch processing */
2413524206
#define MODE_TTY 51 /* Default mode for interactive processing */
2413624207
#define MODE_USER 75 /* First user-defined mode */
2413724208
#define MODE_N_USER 25 /* Maximum number of user-defined modes */
2413824209
@@ -24149,10 +24220,11 @@
2414924220
unsigned char eHdr; /* Default header encoding. */
2415024221
unsigned char eBlob; /* Default blob encoding. */
2415124222
unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */
2415224223
unsigned char eStyle; /* Underlying QRF style */
2415324224
unsigned char eCx; /* 0: other, 1: line, 2: columnar */
24225
+ unsigned char mFlg; /* Flags. 1=border-off 2=split-column */
2415424226
};
2415524227
2415624228
/* String constants used by built-in modes */
2415724229
static const char *aModeStr[] =
2415824230
/* 0 1 2 3 4 5 6 7 8 */
@@ -24159,33 +24231,34 @@
2415924231
{ 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t",
2416024232
"", "NULL", "null", "\"\"" };
2416124233
/* 9 10 11 12 */
2416224234
2416324235
static const ModeInfo aModeInfo[] = {
24164
-/* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx */
24165
- { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0 },
24166
- { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2 },
24167
- { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0 },
24168
- { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2 },
24169
- { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0 },
24170
- { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0 },
24171
- { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0 },
24172
- { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0 },
24173
- { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0 },
24174
- { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0 },
24175
- { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0 },
24176
- { "line", 0, 1, 9, 1, 1, 0, 0, 11, 1 },
24177
- { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0 },
24178
- { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2 },
24179
- { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
24180
- { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2 },
24181
- { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0 },
24182
- { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2 },
24183
- { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2 },
24184
- { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0 },
24185
- { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
24186
- { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0 }
24236
+/* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
24237
+ { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 },
24238
+ { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 },
24239
+ { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 },
24240
+ { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 },
24241
+ { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
24242
+ { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 },
24243
+ { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 },
24244
+ { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 },
24245
+ { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 },
24246
+ { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 },
24247
+ { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 },
24248
+ { "line", 0, 1, 9, 1, 1, 0, 0, 11, 1, 0 },
24249
+ { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 },
24250
+ { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 },
24251
+ { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 },
24252
+ { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 },
24253
+ { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 },
24254
+ { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 },
24255
+ { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 },
24256
+ { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 },
24257
+ { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 },
24258
+ { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 },
24259
+ { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }
2418724260
}; /* | / / | / / | | \
2418824261
** | / / | / / | | \_ 2: columnar
2418924262
** Index into aModeStr[] | / / | | 1: line
2419024263
** | / / | | 0: other
2419124264
** | / / | \
@@ -24307,11 +24380,16 @@
2430724380
if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
2430824381
pM->spec.eText = pI->eText;
2430924382
pM->spec.eBlob = pI->eBlob;
2431024383
pM->spec.bTitles = pI->bHdr;
2431124384
pM->spec.eTitle = pI->eHdr;
24312
- if( eMode==MODE_Split ){
24385
+ if( pI->mFlg & 0x01 ){
24386
+ pM->spec.bBorder = QRF_No;
24387
+ }else{
24388
+ pM->spec.bBorder = QRF_Auto;
24389
+ }
24390
+ if( pI->mFlg & 0x02 ){
2431324391
pM->spec.bSplitColumn = QRF_Yes;
2431424392
pM->bAutoScreenWidth = 1;
2431524393
}else{
2431624394
pM->spec.bSplitColumn = QRF_No;
2431724395
}
@@ -26625,10 +26703,11 @@
2662526703
" meaning \"left\", \"centered\", and \"right\", with\n"
2662626704
" one letter per column starting from the left.\n"
2662726705
" Unspecified alignment defaults to 'L'.\n"
2662826706
" --blob-quote ARG ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
2662926707
" \"json\", or \"size\". Default is \"auto\".\n"
26708
+" --border on|off Show outer border on \"box\" and \"table\" modes.\n"
2663026709
" --charlimit N Set the maximum number of output characters to\n"
2663126710
" show for any single SQL value to N. Longer values\n"
2663226711
" truncated. Zero means \"no limit\".\n"
2663326712
" --colsep STRING Use STRING as the column separator\n"
2663426713
" --escape ESC Enable/disable escaping of control characters\n"
@@ -30508,10 +30587,11 @@
3050830587
** meaning "left", "centered", and "right", with
3050930588
** one letter per column starting from the left.
3051030589
** Unspecified alignment defaults to 'L'.
3051130590
** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl",
3051230591
** "json", or "size". Default is "auto".
30592
+** --border on|off Show outer border on "box" and "table" modes.
3051330593
** --charlimit N Set the maximum number of output characters to
3051430594
** show for any single SQL value to N. Longer values
3051530595
** truncated. Zero means "no limit".
3051630596
** --colsep STRING Use STRING as the column separator
3051730597
** --escape ESC Enable/disable escaping of control characters
@@ -30625,10 +30705,20 @@
3062530705
/* 0 1 2 3 4 5 6
3062630706
** Must match QRF_BLOB_xxxx values. See also tag-20251124a */
3062730707
if( k>=0 ){
3062830708
p->mode.spec.eBlob = k & 0xff;
3062930709
}
30710
+ chng = 1;
30711
+ }else if( optionMatch(z,"border") ){
30712
+ if( (++i)>=nArg ){
30713
+ dotCmdError(p, i-1, "missing argument", 0);
30714
+ return 1;
30715
+ }
30716
+ k = pickStr(azArg[i], 0, "auto", "off", "on", "");
30717
+ if( k>=0 ){
30718
+ p->mode.spec.bBorder = k & 0x3;
30719
+ }
3063030720
chng = 1;
3063130721
}else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
3063230722
int w; /* 0 1 */
3063330723
if( i+1>=nArg ){
3063430724
dotCmdError(p, i, "missing argument", 0);
@@ -30847,16 +30937,16 @@
3084730937
zW = azArg[++i];
3084830938
/* Every width value takes at least 2 bytes in the input string to
3084930939
** specify, so strlen(zW) bytes should be plenty of space to hold the
3085030940
** result. */
3085130941
aWidth = malloc( strlen(zW) );
30852
- while( isspace(zW[0]) ) zW++;
30942
+ while( IsSpace(zW[0]) ) zW++;
3085330943
while( zW[0] ){
3085430944
int w = 0;
3085530945
int nDigit = 0;
30856
- k = zW[0]=='-' && isdigit(zW[1]);
30857
- while( isdigit(zW[k]) ){
30946
+ k = zW[0]=='-' && IsDigit(zW[1]);
30947
+ while( IsDigit(zW[k]) ){
3085830948
w = w*10 + zW[k] - '0';
3085930949
if( w>QRF_MAX_WIDTH ){
3086030950
dotCmdError(p,i+1,"width too big",
3086130951
"Maximum column width is %d", QRF_MAX_WIDTH);
3086230952
free(aWidth);
@@ -30873,11 +30963,11 @@
3087330963
}
3087430964
if( zW[0]=='-' ) w = -w;
3087530965
aWidth[nWidth++] = w;
3087630966
zW += k;
3087730967
if( zW[0]==',' ) zW++;
30878
- while( isspace(zW[0]) ) zW++;
30968
+ while( IsSpace(zW[0]) ) zW++;
3087930969
}
3088030970
free(p->mode.spec.aWidth);
3088130971
p->mode.spec.aWidth = aWidth;
3088230972
p->mode.spec.nWidth = nWidth;
3088330973
chng = 1;
@@ -30928,10 +31018,16 @@
3092831018
unsigned char a = p->mode.spec.aAlign[ii];
3092931019
sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]);
3093031020
}
3093131021
sqlite3_str_append(pDesc, "\"", 1);
3093231022
}
31023
+ if( bAll
31024
+ || (p->mode.spec.bBorder==QRF_No) != ((pI->mFlg&1)!=0)
31025
+ ){
31026
+ sqlite3_str_appendf(pDesc," --border %s",
31027
+ p->mode.spec.bBorder==QRF_No ? "off" : "on");
31028
+ }
3093331029
if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
3093431030
const char *azBQuote[] =
3093531031
{ "auto", "text", "sql", "hex", "tcl", "json", "size" };
3093631032
/* 0 1 2 3 4 5 6
3093731033
** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */
@@ -35586,11 +35682,12 @@
3558635682
data.pAuxDb->zDbFilename = ":memory:";
3558735683
warnInmemoryDb = argc==1;
3558835684
#else
3558935685
cli_printf(stderr,
3559035686
"%s: Error: no database filename specified\n", Argv0);
35591
- return 1;
35687
+ rc = 1;
35688
+ goto shell_main_exit;
3559235689
#endif
3559335690
}
3559435691
data.out = stdout;
3559535692
if( bEnableVfstrace ){
3559635693
vfstrace_register("trace",0,vfstraceOut, &data, 1);
@@ -35640,10 +35737,12 @@
3564035737
modeChange(&data, MODE_Json);
3564135738
}else if( cli_strcmp(z,"-markdown")==0 ){
3564235739
modeChange(&data, MODE_Markdown);
3564335740
}else if( cli_strcmp(z,"-table")==0 ){
3564435741
modeChange(&data, MODE_Table);
35742
+ }else if( cli_strcmp(z,"-psql")==0 ){
35743
+ modeChange(&data, MODE_Psql);
3564535744
}else if( cli_strcmp(z,"-box")==0 ){
3564635745
modeChange(&data, MODE_Box);
3564735746
}else if( cli_strcmp(z,"-csv")==0 ){
3564835747
modeChange(&data, MODE_Csv);
3564935748
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
@@ -35726,11 +35825,12 @@
3572635825
}else if( cli_strcmp(z,"-bail")==0 ){
3572735826
/* No-op. The bail_on_error flag should already be set. */
3572835827
}else if( cli_strcmp(z,"-version")==0 ){
3572935828
cli_printf(stdout, "%s %s (%d-bit)\n",
3573035829
sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
35731
- return 0;
35830
+ rc = 0;
35831
+ goto shell_main_exit;
3573235832
}else if( cli_strcmp(z,"-interactive")==0 ){
3573335833
/* Need to check for interactive override here to so that it can
3573435834
** affect console setup (for Windows only) and testing thereof.
3573535835
*/
3573635836
stdin_is_interactive = 1;
@@ -35783,29 +35883,33 @@
3578335883
** we retain the goofy behavior for historical compatibility. */
3578435884
if( i==argc-1 ) break;
3578535885
z = cmdline_option_value(argc,argv,++i);
3578635886
if( z[0]=='.' ){
3578735887
rc = do_meta_command(z, &data);
35788
- if( rc && bail_on_error ) return rc==2 ? 0 : rc;
35888
+ if( rc && bail_on_error ){
35889
+ if( rc==2 ) rc = 0;
35890
+ goto shell_main_exit;
35891
+ }
3578935892
}else{
3579035893
open_db(&data, 0);
3579135894
rc = shell_exec(&data, z, &zErrMsg);
3579235895
if( zErrMsg!=0 ){
3579335896
shellEmitError(zErrMsg);
3579435897
sqlite3_free(zErrMsg);
35795
- if( bail_on_error ) return rc!=0 ? rc : 1;
35898
+ if( !rc ) rc = 1;
3579635899
}else if( rc!=0 ){
3579735900
cli_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
35798
- if( bail_on_error ) return rc;
3579935901
}
35902
+ if( bail_on_error ) goto shell_main_exit;
3580035903
}
3580135904
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
3580235905
}else if( cli_strncmp(z, "-A", 2)==0 ){
3580335906
if( nCmd>0 ){
3580435907
cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands"
3580535908
" with \"%s\"\n", z);
35806
- return 1;
35909
+ rc = 1;
35910
+ goto shell_main_exit;
3580735911
}
3580835912
open_db(&data, OPEN_DB_ZIPFILE);
3580935913
if( z[2] ){
3581035914
argv[i] = &z[2];
3581135915
arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
@@ -35821,11 +35925,12 @@
3582135925
}else if( cli_strcmp(z,"-unsafe-testing")==0 ){
3582235926
/* Acted upon in first pass. */
3582335927
}else{
3582435928
cli_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
3582535929
eputz("Use -help for a list of options.\n");
35826
- return 1;
35930
+ rc = 1;
35931
+ goto shell_main_exit;
3582735932
}
3582835933
}
3582935934
3583035935
if( !readStdin ){
3583135936
/* Run all arguments that do not begin with '-' as if they were separate
3583235937
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -704,10 +704,11 @@
704 unsigned char bWordWrap; /* Try to wrap on word boundaries */
705 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
706 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
707 unsigned char eTitleAlign; /* Alignment for column headers */
708 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
 
709 short int nWrap; /* Wrap columns wider than this */
710 short int nScreenWidth; /* Maximum overall table width */
711 short int nLineLimit; /* Maximum number of lines for any row */
712 int nCharLimit; /* Maximum number of characters in a cell */
713 int nWidth; /* Number of entries in aWidth[] */
@@ -2124,40 +2125,10 @@
2124 }
2125 }
2126 sqlite3_str_append(pOut, (const char*)z, i);
2127 }
2128
2129 /*
2130 ** Output horizontally justified text into pOut. The text is the
2131 ** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2132 ** split between both sides, or on the left, or on the right, depending
2133 ** on eAlign.
2134 */
2135 static void qrfPrintAligned(
2136 sqlite3_str *pOut, /* Append text here */
2137 const char *zVal, /* Text to append */
2138 int nVal, /* Use only the first nVal bytes of zVal[] */
2139 int nWS, /* Whitespace for horizonal alignment */
2140 unsigned char eAlign /* Alignment type */
2141 ){
2142 eAlign &= QRF_ALIGN_HMASK;
2143 if( eAlign==QRF_ALIGN_Center ){
2144 /* Center the text */
2145 sqlite3_str_appendchar(pOut, nWS/2, ' ');
2146 qrfAppendWithTabs(pOut, zVal, nVal);
2147 sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2148 }else if( eAlign==QRF_ALIGN_Right){
2149 /* Right justify the text */
2150 sqlite3_str_appendchar(pOut, nWS, ' ');
2151 qrfAppendWithTabs(pOut, zVal, nVal);
2152 }else{
2153 /* Left justify the next */
2154 qrfAppendWithTabs(pOut, zVal, nVal);
2155 sqlite3_str_appendchar(pOut, nWS, ' ');
2156 }
2157 }
2158
2159 /*
2160 ** GCC does not define the offsetof() macro so we'll have to do it
2161 ** ourselves.
2162 */
2163 #ifndef offsetof
@@ -2177,27 +2148,60 @@
2177 sqlite3_int64 nRow; /* Number of rows */
2178 sqlite3_int64 nAlloc; /* Number of cells allocated */
2179 sqlite3_int64 n; /* Number of cells. nCol*nRow */
2180 char **az; /* Content of all cells */
2181 int *aiWth; /* Width of each cell */
 
2182 struct qrfPerCol { /* Per-column data */
2183 char *z; /* Cache of text for current row */
2184 int w; /* Computed width of this column */
2185 int mxW; /* Maximum natural (unwrapped) width */
2186 unsigned char e; /* Alignment */
2187 unsigned char fx; /* Width is fixed */
 
2188 } *a; /* One per column */
2189 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2190
2191 /*
2192 ** Free all the memory allocates in the qrfColData object
2193 */
2194 static void qrfColDataFree(qrfColData *p){
2195 sqlite3_int64 i;
2196 for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
2197 sqlite3_free(p->az);
2198 sqlite3_free(p->aiWth);
 
2199 sqlite3_free(p->a);
2200 memset(p, 0, sizeof(*p));
2201 }
2202
2203 /*
@@ -2205,10 +2209,11 @@
2205 ** Return non-zero if a memory allocation fails.
2206 */
2207 static int qrfColDataEnlarge(qrfColData *p){
2208 char **azData;
2209 int *aiWth;
 
2210 p->nAlloc = 2*p->nAlloc + 10*p->nCol;
2211 azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
2212 if( azData==0 ){
2213 qrfOom(p->p);
2214 qrfColDataFree(p);
@@ -2220,26 +2225,38 @@
2220 qrfOom(p->p);
2221 qrfColDataFree(p);
2222 return 1;
2223 }
2224 p->aiWth = aiWth;
 
 
 
 
 
 
 
2225 return 0;
2226 }
2227
2228 /*
2229 ** Print a markdown or table-style row separator using ascii-art
2230 */
2231 static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
2232 int i;
2233 if( p->nCol>0 ){
2234 sqlite3_str_append(pOut, &cSep, 1);
 
 
 
2235 sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
2236 for(i=1; i<p->nCol; i++){
2237 sqlite3_str_append(pOut, &cSep, 1);
2238 sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
2239 }
2240 sqlite3_str_append(pOut, &cSep, 1);
 
 
2241 }
2242 sqlite3_str_append(pOut, "\n", 1);
2243 }
2244
2245 /*
@@ -2293,17 +2310,22 @@
2293 const char *zSep2,
2294 const char *zSep3
2295 ){
2296 int i;
2297 if( p->nCol>0 ){
2298 sqlite3_str_appendall(pOut, zSep1);
 
 
 
2299 qrfBoxLine(pOut, p->a[0].w+p->nMargin);
2300 for(i=1; i<p->nCol; i++){
2301 sqlite3_str_appendall(pOut, zSep2);
2302 qrfBoxLine(pOut, p->a[i].w+p->nMargin);
2303 }
2304 sqlite3_str_appendall(pOut, zSep3);
 
 
2305 }
2306 sqlite3_str_append(pOut, "\n", 1);
2307 }
2308
2309 /*
@@ -2382,10 +2404,11 @@
2382 static void qrfSplitColumn(qrfColData *pData, Qrf *p){
2383 int nCol = 1;
2384 int *aw = 0;
2385 char **az = 0;
2386 int *aiWth = 0;
 
2387 int nColNext = 2;
2388 int w;
2389 struct qrfPerCol *a = 0;
2390 sqlite3_int64 nRow = 1;
2391 sqlite3_int64 i;
@@ -2419,35 +2442,47 @@
2419 if( a==0 ){
2420 sqlite3_free(az);
2421 sqlite3_free(aiWth);
2422 qrfOom(p);
2423 return;
 
 
 
 
 
 
 
 
2424 }
2425 for(i=0; i<pData->n; i++){
2426 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2427 az[j] = pData->az[i];
 
2428 pData->az[i] = 0;
2429 aiWth[j] = pData->aiWth[i];
2430 }
2431 while( i<nRow*nCol ){
2432 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2433 az[j] = sqlite3_mprintf("");
2434 if( az[j]==0 ) qrfOom(p);
2435 aiWth[j] = 0;
 
2436 i++;
2437 }
2438 for(i=0; i<nCol; i++){
2439 a[i].fx = a[i].mxW = a[i].w = aw[i];
2440 a[i].e = pData->a[0].e;
2441 }
2442 sqlite3_free(pData->az);
2443 sqlite3_free(pData->aiWth);
2444 sqlite3_free(pData->a);
 
2445 sqlite3_free(aw);
2446 pData->az = az;
2447 pData->aiWth = aiWth;
2448 pData->a = a;
 
2449 pData->nCol = nCol;
2450 pData->n = pData->nAlloc = nRow*nCol;
2451 for(i=w=0; i<nCol; i++) w += a[i].w;
2452 pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
2453 if( pData->nMargin>5 ) pData->nMargin = 5;
@@ -2467,10 +2502,11 @@
2467 if( p->spec.nScreenWidth==0 ) return;
2468 if( p->spec.eStyle==QRF_STYLE_Column ){
2469 sepW = pData->nCol*2 - 2;
2470 }else{
2471 sepW = pData->nCol*3 + 1;
 
2472 }
2473 nCol = pData->nCol;
2474 for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
2475 if( p->spec.nScreenWidth >= sumW+sepW ) return;
2476
@@ -2478,10 +2514,11 @@
2478 pData->nMargin = 0;
2479 if( p->spec.eStyle==QRF_STYLE_Column ){
2480 sepW = pData->nCol - 1;
2481 }else{
2482 sepW = pData->nCol + 1;
 
2483 }
2484 targetW = p->spec.nScreenWidth - sepW;
2485
2486 #define MIN_SQUOZE 8
2487 #define MIN_EX_SQUOZE 16
@@ -2550,10 +2587,11 @@
2550 }
2551
2552 /* Initialize the data container */
2553 memset(&data, 0, sizeof(data));
2554 data.nCol = p->nCol;
 
2555 data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
2556 if( data.a==0 ){
2557 qrfOom(p);
2558 return;
2559 }
@@ -2563,10 +2601,11 @@
2563
2564 /* Load the column header names and all cell content into data */
2565 if( p->spec.bTitles==QRF_Yes ){
2566 unsigned char saved_eText = p->spec.eText;
2567 p->spec.eText = p->spec.eTitle;
 
2568 for(i=0; i<nColumn; i++){
2569 const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
2570 int nNL = 0;
2571 int n, w;
2572 pStr = sqlite3_str_new(p->db);
@@ -2587,14 +2626,16 @@
2587 }
2588 for(i=0; i<nColumn; i++){
2589 char *z;
2590 int nNL = 0;
2591 int n, w;
 
2592 pStr = sqlite3_str_new(p->db);
2593 qrfRenderValue(p, pStr, i);
2594 n = sqlite3_str_length(pStr);
2595 z = data.az[data.n] = sqlite3_str_finish(pStr);
 
2596 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2597 data.n++;
2598 if( w>data.a[i].mxW ) data.a[i].mxW = w;
2599 if( nNL ) data.bMultiRow = 1;
2600 }
@@ -2680,11 +2721,16 @@
2680 }else{
2681 rowStart = BOX_13;
2682 colSep = BOX_13;
2683 rowSep = BOX_13 "\n";
2684 }
2685 qrfBoxSeparator(p->pOut, &data, BOX_23, BOX_234, BOX_34);
 
 
 
 
 
2686 break;
2687 case QRF_STYLE_Table:
2688 if( data.nMargin ){
2689 rowStart = "| ";
2690 colSep = " | ";
@@ -2692,11 +2738,16 @@
2692 }else{
2693 rowStart = "|";
2694 colSep = "|";
2695 rowSep = "|\n";
2696 }
2697 qrfRowSeparator(p->pOut, &data, '+');
 
 
 
 
 
2698 break;
2699 case QRF_STYLE_Column: {
2700 static const char zSpace[] = " ";
2701 rowStart = "";
2702 if( data.nMargin<2 ){
@@ -2724,20 +2775,31 @@
2724 szRowStart = (int)strlen(rowStart);
2725 szRowSep = (int)strlen(rowSep);
2726 szColSep = (int)strlen(colSep);
2727
2728 bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2729 bRTrim = (p->spec.eStyle==QRF_STYLE_Column);
 
 
 
 
 
 
 
 
2730 for(i=0; i<data.n; i+=nColumn){
2731 int bMore;
2732 int nRow = 0;
2733
2734 /* Draw a single row of the table. This might be the title line
2735 ** (if there is a title line) or a row in the body of the table.
2736 ** The column number will be j. The row number is i/nColumn.
2737 */
2738 for(j=0; j<nColumn; j++){ data.a[j].z = data.az[i+j]; }
 
 
 
2739 do{
2740 sqlite3_str_append(p->pOut, rowStart, szRowStart);
2741 bMore = 0;
2742 for(j=0; j<nColumn; j++){
2743 int nThis = 0;
@@ -2744,11 +2806,11 @@
2744 int nWide = 0;
2745 int iNext = 0;
2746 int nWS;
2747 qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
2748 nWS = data.a[j].w - nWide;
2749 qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
2750 data.a[j].z += iNext;
2751 if( data.a[j].z[0]!=0 ){
2752 bMore = 1;
2753 }
2754 if( j<nColumn-1 ){
@@ -2766,11 +2828,12 @@
2766 if( data.a[j].z[0]==0 ){
2767 sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
2768 }else{
2769 int nE = 3;
2770 if( nE>data.a[j].w ) nE = data.a[j].w;
2771 qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
 
2772 }
2773 if( j<nColumn-1 ){
2774 sqlite3_str_append(p->pOut, colSep, szColSep);
2775 }else{
2776 if( bRTrim ) qrfRTrim(p->pOut);
@@ -2827,17 +2890,19 @@
2827 }
2828 }
2829 }
2830
2831 /* Draw the line across the bottom of the table */
2832 switch( p->spec.eStyle ){
2833 case QRF_STYLE_Box:
2834 qrfBoxSeparator(p->pOut, &data, BOX_12, BOX_124, BOX_14);
2835 break;
2836 case QRF_STYLE_Table:
2837 qrfRowSeparator(p->pOut, &data, '+');
2838 break;
 
 
2839 }
2840 qrfWrite(p);
2841
2842 qrfColDataFree(&data);
2843 return;
@@ -6013,17 +6078,20 @@
6013 }
6014 /* End of the hashing logic
6015 *****************************************************************************/
6016
6017 /*
6018 ** Implementation of the sha1(X) function.
6019 **
6020 ** Return a lower-case hexadecimal rendering of the SHA1 hash of the
6021 ** argument X. If X is a BLOB, it is hashed as is. For all other
6022 ** types of input, X is converted into a UTF-8 string and the string
6023 ** is hash without the trailing 0x00 terminator. The hash of a NULL
6024 ** value is NULL.
 
 
 
6025 */
6026 static void sha1Func(
6027 sqlite3_context *context,
6028 int argc,
6029 sqlite3_value **argv
@@ -6040,15 +6108,17 @@
6040 hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
6041 }else{
6042 hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
6043 }
6044 if( sqlite3_user_data(context)!=0 ){
 
6045 hash_finish(&cx, zOut, 1);
6046 sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
6047 }else{
 
6048 hash_finish(&cx, zOut, 0);
6049 sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT);
6050 }
6051 }
6052
6053 /*
6054 ** Implementation of the sha1_query(SQL) function.
@@ -24120,19 +24190,20 @@
24120 #define MODE_Json 10 /* Output JSON */
24121 #define MODE_Line 11 /* One column per line. Blank line between records */
24122 #define MODE_List 12 /* One record per line with a separator */
24123 #define MODE_Markdown 13 /* Markdown formatting */
24124 #define MODE_Off 14 /* No query output shown */
24125 #define MODE_QBox 15 /* BOX with SQL-quoted content */
24126 #define MODE_Quote 16 /* Quote values as for SQL */
24127 #define MODE_Split 17 /* Split-column mode */
24128 #define MODE_Table 18 /* MySQL-style table formatting */
24129 #define MODE_Tabs 19 /* Tab-separated values */
24130 #define MODE_Tcl 20 /* Space-separated list of TCL strings */
24131 #define MODE_Www 21 /* Full web-page output */
24132
24133 #define MODE_BUILTIN 21 /* Maximum built-in mode */
 
24134 #define MODE_BATCH 50 /* Default mode for batch processing */
24135 #define MODE_TTY 51 /* Default mode for interactive processing */
24136 #define MODE_USER 75 /* First user-defined mode */
24137 #define MODE_N_USER 25 /* Maximum number of user-defined modes */
24138
@@ -24149,10 +24220,11 @@
24149 unsigned char eHdr; /* Default header encoding. */
24150 unsigned char eBlob; /* Default blob encoding. */
24151 unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */
24152 unsigned char eStyle; /* Underlying QRF style */
24153 unsigned char eCx; /* 0: other, 1: line, 2: columnar */
 
24154 };
24155
24156 /* String constants used by built-in modes */
24157 static const char *aModeStr[] =
24158 /* 0 1 2 3 4 5 6 7 8 */
@@ -24159,33 +24231,34 @@
24159 { 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t",
24160 "", "NULL", "null", "\"\"" };
24161 /* 9 10 11 12 */
24162
24163 static const ModeInfo aModeInfo[] = {
24164 /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx */
24165 { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0 },
24166 { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2 },
24167 { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0 },
24168 { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2 },
24169 { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0 },
24170 { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0 },
24171 { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0 },
24172 { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0 },
24173 { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0 },
24174 { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0 },
24175 { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0 },
24176 { "line", 0, 1, 9, 1, 1, 0, 0, 11, 1 },
24177 { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0 },
24178 { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2 },
24179 { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
24180 { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2 },
24181 { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0 },
24182 { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2 },
24183 { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2 },
24184 { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0 },
24185 { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
24186 { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0 }
 
24187 }; /* | / / | / / | | \
24188 ** | / / | / / | | \_ 2: columnar
24189 ** Index into aModeStr[] | / / | | 1: line
24190 ** | / / | | 0: other
24191 ** | / / | \
@@ -24307,11 +24380,16 @@
24307 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24308 pM->spec.eText = pI->eText;
24309 pM->spec.eBlob = pI->eBlob;
24310 pM->spec.bTitles = pI->bHdr;
24311 pM->spec.eTitle = pI->eHdr;
24312 if( eMode==MODE_Split ){
 
 
 
 
 
24313 pM->spec.bSplitColumn = QRF_Yes;
24314 pM->bAutoScreenWidth = 1;
24315 }else{
24316 pM->spec.bSplitColumn = QRF_No;
24317 }
@@ -26625,10 +26703,11 @@
26625 " meaning \"left\", \"centered\", and \"right\", with\n"
26626 " one letter per column starting from the left.\n"
26627 " Unspecified alignment defaults to 'L'.\n"
26628 " --blob-quote ARG ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
26629 " \"json\", or \"size\". Default is \"auto\".\n"
 
26630 " --charlimit N Set the maximum number of output characters to\n"
26631 " show for any single SQL value to N. Longer values\n"
26632 " truncated. Zero means \"no limit\".\n"
26633 " --colsep STRING Use STRING as the column separator\n"
26634 " --escape ESC Enable/disable escaping of control characters\n"
@@ -30508,10 +30587,11 @@
30508 ** meaning "left", "centered", and "right", with
30509 ** one letter per column starting from the left.
30510 ** Unspecified alignment defaults to 'L'.
30511 ** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl",
30512 ** "json", or "size". Default is "auto".
 
30513 ** --charlimit N Set the maximum number of output characters to
30514 ** show for any single SQL value to N. Longer values
30515 ** truncated. Zero means "no limit".
30516 ** --colsep STRING Use STRING as the column separator
30517 ** --escape ESC Enable/disable escaping of control characters
@@ -30625,10 +30705,20 @@
30625 /* 0 1 2 3 4 5 6
30626 ** Must match QRF_BLOB_xxxx values. See also tag-20251124a */
30627 if( k>=0 ){
30628 p->mode.spec.eBlob = k & 0xff;
30629 }
 
 
 
 
 
 
 
 
 
 
30630 chng = 1;
30631 }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
30632 int w; /* 0 1 */
30633 if( i+1>=nArg ){
30634 dotCmdError(p, i, "missing argument", 0);
@@ -30847,16 +30937,16 @@
30847 zW = azArg[++i];
30848 /* Every width value takes at least 2 bytes in the input string to
30849 ** specify, so strlen(zW) bytes should be plenty of space to hold the
30850 ** result. */
30851 aWidth = malloc( strlen(zW) );
30852 while( isspace(zW[0]) ) zW++;
30853 while( zW[0] ){
30854 int w = 0;
30855 int nDigit = 0;
30856 k = zW[0]=='-' && isdigit(zW[1]);
30857 while( isdigit(zW[k]) ){
30858 w = w*10 + zW[k] - '0';
30859 if( w>QRF_MAX_WIDTH ){
30860 dotCmdError(p,i+1,"width too big",
30861 "Maximum column width is %d", QRF_MAX_WIDTH);
30862 free(aWidth);
@@ -30873,11 +30963,11 @@
30873 }
30874 if( zW[0]=='-' ) w = -w;
30875 aWidth[nWidth++] = w;
30876 zW += k;
30877 if( zW[0]==',' ) zW++;
30878 while( isspace(zW[0]) ) zW++;
30879 }
30880 free(p->mode.spec.aWidth);
30881 p->mode.spec.aWidth = aWidth;
30882 p->mode.spec.nWidth = nWidth;
30883 chng = 1;
@@ -30928,10 +31018,16 @@
30928 unsigned char a = p->mode.spec.aAlign[ii];
30929 sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]);
30930 }
30931 sqlite3_str_append(pDesc, "\"", 1);
30932 }
 
 
 
 
 
 
30933 if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
30934 const char *azBQuote[] =
30935 { "auto", "text", "sql", "hex", "tcl", "json", "size" };
30936 /* 0 1 2 3 4 5 6
30937 ** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */
@@ -35586,11 +35682,12 @@
35586 data.pAuxDb->zDbFilename = ":memory:";
35587 warnInmemoryDb = argc==1;
35588 #else
35589 cli_printf(stderr,
35590 "%s: Error: no database filename specified\n", Argv0);
35591 return 1;
 
35592 #endif
35593 }
35594 data.out = stdout;
35595 if( bEnableVfstrace ){
35596 vfstrace_register("trace",0,vfstraceOut, &data, 1);
@@ -35640,10 +35737,12 @@
35640 modeChange(&data, MODE_Json);
35641 }else if( cli_strcmp(z,"-markdown")==0 ){
35642 modeChange(&data, MODE_Markdown);
35643 }else if( cli_strcmp(z,"-table")==0 ){
35644 modeChange(&data, MODE_Table);
 
 
35645 }else if( cli_strcmp(z,"-box")==0 ){
35646 modeChange(&data, MODE_Box);
35647 }else if( cli_strcmp(z,"-csv")==0 ){
35648 modeChange(&data, MODE_Csv);
35649 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
@@ -35726,11 +35825,12 @@
35726 }else if( cli_strcmp(z,"-bail")==0 ){
35727 /* No-op. The bail_on_error flag should already be set. */
35728 }else if( cli_strcmp(z,"-version")==0 ){
35729 cli_printf(stdout, "%s %s (%d-bit)\n",
35730 sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
35731 return 0;
 
35732 }else if( cli_strcmp(z,"-interactive")==0 ){
35733 /* Need to check for interactive override here to so that it can
35734 ** affect console setup (for Windows only) and testing thereof.
35735 */
35736 stdin_is_interactive = 1;
@@ -35783,29 +35883,33 @@
35783 ** we retain the goofy behavior for historical compatibility. */
35784 if( i==argc-1 ) break;
35785 z = cmdline_option_value(argc,argv,++i);
35786 if( z[0]=='.' ){
35787 rc = do_meta_command(z, &data);
35788 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
 
 
 
35789 }else{
35790 open_db(&data, 0);
35791 rc = shell_exec(&data, z, &zErrMsg);
35792 if( zErrMsg!=0 ){
35793 shellEmitError(zErrMsg);
35794 sqlite3_free(zErrMsg);
35795 if( bail_on_error ) return rc!=0 ? rc : 1;
35796 }else if( rc!=0 ){
35797 cli_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
35798 if( bail_on_error ) return rc;
35799 }
 
35800 }
35801 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
35802 }else if( cli_strncmp(z, "-A", 2)==0 ){
35803 if( nCmd>0 ){
35804 cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands"
35805 " with \"%s\"\n", z);
35806 return 1;
 
35807 }
35808 open_db(&data, OPEN_DB_ZIPFILE);
35809 if( z[2] ){
35810 argv[i] = &z[2];
35811 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
@@ -35821,11 +35925,12 @@
35821 }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
35822 /* Acted upon in first pass. */
35823 }else{
35824 cli_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
35825 eputz("Use -help for a list of options.\n");
35826 return 1;
 
35827 }
35828 }
35829
35830 if( !readStdin ){
35831 /* Run all arguments that do not begin with '-' as if they were separate
35832
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -704,10 +704,11 @@
704 unsigned char bWordWrap; /* Try to wrap on word boundaries */
705 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
706 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
707 unsigned char eTitleAlign; /* Alignment for column headers */
708 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
709 unsigned char bBorder; /* Show outer border in Box and Table styles */
710 short int nWrap; /* Wrap columns wider than this */
711 short int nScreenWidth; /* Maximum overall table width */
712 short int nLineLimit; /* Maximum number of lines for any row */
713 int nCharLimit; /* Maximum number of characters in a cell */
714 int nWidth; /* Number of entries in aWidth[] */
@@ -2124,40 +2125,10 @@
2125 }
2126 }
2127 sqlite3_str_append(pOut, (const char*)z, i);
2128 }
2129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2130 /*
2131 ** GCC does not define the offsetof() macro so we'll have to do it
2132 ** ourselves.
2133 */
2134 #ifndef offsetof
@@ -2177,27 +2148,60 @@
2148 sqlite3_int64 nRow; /* Number of rows */
2149 sqlite3_int64 nAlloc; /* Number of cells allocated */
2150 sqlite3_int64 n; /* Number of cells. nCol*nRow */
2151 char **az; /* Content of all cells */
2152 int *aiWth; /* Width of each cell */
2153 unsigned char *abNum; /* True for each numeric cell */
2154 struct qrfPerCol { /* Per-column data */
2155 char *z; /* Cache of text for current row */
2156 int w; /* Computed width of this column */
2157 int mxW; /* Maximum natural (unwrapped) width */
2158 unsigned char e; /* Alignment */
2159 unsigned char fx; /* Width is fixed */
2160 unsigned char bNum; /* True if is numeric */
2161 } *a; /* One per column */
2162 };
2163
2164 /*
2165 ** Output horizontally justified text into pOut. The text is the
2166 ** first nVal bytes of zVal. Include nWS bytes of whitespace, either
2167 ** split between both sides, or on the left, or on the right, depending
2168 ** on eAlign.
2169 */
2170 static void qrfPrintAligned(
2171 sqlite3_str *pOut, /* Append text here */
2172 struct qrfPerCol *pCol, /* Information about the text to print */
2173 int nVal, /* Use only the first nVal bytes of zVal[] */
2174 int nWS /* Whitespace for horizonal alignment */
2175 ){
2176 unsigned char eAlign = pCol->e & QRF_ALIGN_HMASK;
2177 if( eAlign==QRF_Auto && pCol->bNum ) eAlign = QRF_ALIGN_Right;
2178 if( eAlign==QRF_ALIGN_Center ){
2179 /* Center the text */
2180 sqlite3_str_appendchar(pOut, nWS/2, ' ');
2181 qrfAppendWithTabs(pOut, pCol->z, nVal);
2182 sqlite3_str_appendchar(pOut, nWS - nWS/2, ' ');
2183 }else if( eAlign==QRF_ALIGN_Right ){
2184 /* Right justify the text */
2185 sqlite3_str_appendchar(pOut, nWS, ' ');
2186 qrfAppendWithTabs(pOut, pCol->z, nVal);
2187 }else{
2188 /* Left justify the text */
2189 qrfAppendWithTabs(pOut, pCol->z, nVal);
2190 sqlite3_str_appendchar(pOut, nWS, ' ');
2191 }
2192 }
2193
2194 /*
2195 ** Free all the memory allocates in the qrfColData object
2196 */
2197 static void qrfColDataFree(qrfColData *p){
2198 sqlite3_int64 i;
2199 for(i=0; i<p->n; i++) sqlite3_free(p->az[i]);
2200 sqlite3_free(p->az);
2201 sqlite3_free(p->aiWth);
2202 sqlite3_free(p->abNum);
2203 sqlite3_free(p->a);
2204 memset(p, 0, sizeof(*p));
2205 }
2206
2207 /*
@@ -2205,10 +2209,11 @@
2209 ** Return non-zero if a memory allocation fails.
2210 */
2211 static int qrfColDataEnlarge(qrfColData *p){
2212 char **azData;
2213 int *aiWth;
2214 unsigned char *abNum;
2215 p->nAlloc = 2*p->nAlloc + 10*p->nCol;
2216 azData = sqlite3_realloc64(p->az, p->nAlloc*sizeof(char*));
2217 if( azData==0 ){
2218 qrfOom(p->p);
2219 qrfColDataFree(p);
@@ -2220,26 +2225,38 @@
2225 qrfOom(p->p);
2226 qrfColDataFree(p);
2227 return 1;
2228 }
2229 p->aiWth = aiWth;
2230 abNum = sqlite3_realloc64(p->abNum, p->nAlloc);
2231 if( abNum==0 ){
2232 qrfOom(p->p);
2233 qrfColDataFree(p);
2234 return 1;
2235 }
2236 p->abNum = abNum;
2237 return 0;
2238 }
2239
2240 /*
2241 ** Print a markdown or table-style row separator using ascii-art
2242 */
2243 static void qrfRowSeparator(sqlite3_str *pOut, qrfColData *p, char cSep){
2244 int i;
2245 if( p->nCol>0 ){
2246 int useBorder = p->p->spec.bBorder!=QRF_No;
2247 if( useBorder ){
2248 sqlite3_str_append(pOut, &cSep, 1);
2249 }
2250 sqlite3_str_appendchar(pOut, p->a[0].w+p->nMargin, '-');
2251 for(i=1; i<p->nCol; i++){
2252 sqlite3_str_append(pOut, &cSep, 1);
2253 sqlite3_str_appendchar(pOut, p->a[i].w+p->nMargin, '-');
2254 }
2255 if( useBorder ){
2256 sqlite3_str_append(pOut, &cSep, 1);
2257 }
2258 }
2259 sqlite3_str_append(pOut, "\n", 1);
2260 }
2261
2262 /*
@@ -2293,17 +2310,22 @@
2310 const char *zSep2,
2311 const char *zSep3
2312 ){
2313 int i;
2314 if( p->nCol>0 ){
2315 int useBorder = p->p->spec.bBorder!=QRF_No;
2316 if( useBorder ){
2317 sqlite3_str_appendall(pOut, zSep1);
2318 }
2319 qrfBoxLine(pOut, p->a[0].w+p->nMargin);
2320 for(i=1; i<p->nCol; i++){
2321 sqlite3_str_appendall(pOut, zSep2);
2322 qrfBoxLine(pOut, p->a[i].w+p->nMargin);
2323 }
2324 if( useBorder ){
2325 sqlite3_str_appendall(pOut, zSep3);
2326 }
2327 }
2328 sqlite3_str_append(pOut, "\n", 1);
2329 }
2330
2331 /*
@@ -2382,10 +2404,11 @@
2404 static void qrfSplitColumn(qrfColData *pData, Qrf *p){
2405 int nCol = 1;
2406 int *aw = 0;
2407 char **az = 0;
2408 int *aiWth = 0;
2409 unsigned char *abNum = 0;
2410 int nColNext = 2;
2411 int w;
2412 struct qrfPerCol *a = 0;
2413 sqlite3_int64 nRow = 1;
2414 sqlite3_int64 i;
@@ -2419,35 +2442,47 @@
2442 if( a==0 ){
2443 sqlite3_free(az);
2444 sqlite3_free(aiWth);
2445 qrfOom(p);
2446 return;
2447 }
2448 abNum = sqlite3_malloc64( nRow*nCol );
2449 if( abNum==0 ){
2450 sqlite3_free(az);
2451 sqlite3_free(aiWth);
2452 sqlite3_free(a);
2453 qrfOom(p);
2454 return;
2455 }
2456 for(i=0; i<pData->n; i++){
2457 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2458 az[j] = pData->az[i];
2459 abNum[j]= pData->abNum[i];
2460 pData->az[i] = 0;
2461 aiWth[j] = pData->aiWth[i];
2462 }
2463 while( i<nRow*nCol ){
2464 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2465 az[j] = sqlite3_mprintf("");
2466 if( az[j]==0 ) qrfOom(p);
2467 aiWth[j] = 0;
2468 abNum[j] = 0;
2469 i++;
2470 }
2471 for(i=0; i<nCol; i++){
2472 a[i].fx = a[i].mxW = a[i].w = aw[i];
2473 a[i].e = pData->a[0].e;
2474 }
2475 sqlite3_free(pData->az);
2476 sqlite3_free(pData->aiWth);
2477 sqlite3_free(pData->a);
2478 sqlite3_free(pData->abNum);
2479 sqlite3_free(aw);
2480 pData->az = az;
2481 pData->aiWth = aiWth;
2482 pData->a = a;
2483 pData->abNum = abNum;
2484 pData->nCol = nCol;
2485 pData->n = pData->nAlloc = nRow*nCol;
2486 for(i=w=0; i<nCol; i++) w += a[i].w;
2487 pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
2488 if( pData->nMargin>5 ) pData->nMargin = 5;
@@ -2467,10 +2502,11 @@
2502 if( p->spec.nScreenWidth==0 ) return;
2503 if( p->spec.eStyle==QRF_STYLE_Column ){
2504 sepW = pData->nCol*2 - 2;
2505 }else{
2506 sepW = pData->nCol*3 + 1;
2507 if( p->spec.bBorder==QRF_No ) sepW -= 2;
2508 }
2509 nCol = pData->nCol;
2510 for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
2511 if( p->spec.nScreenWidth >= sumW+sepW ) return;
2512
@@ -2478,10 +2514,11 @@
2514 pData->nMargin = 0;
2515 if( p->spec.eStyle==QRF_STYLE_Column ){
2516 sepW = pData->nCol - 1;
2517 }else{
2518 sepW = pData->nCol + 1;
2519 if( p->spec.bBorder==QRF_No ) sepW -= 2;
2520 }
2521 targetW = p->spec.nScreenWidth - sepW;
2522
2523 #define MIN_SQUOZE 8
2524 #define MIN_EX_SQUOZE 16
@@ -2550,10 +2587,11 @@
2587 }
2588
2589 /* Initialize the data container */
2590 memset(&data, 0, sizeof(data));
2591 data.nCol = p->nCol;
2592 data.p = p;
2593 data.a = sqlite3_malloc64( nColumn*sizeof(struct qrfPerCol) );
2594 if( data.a==0 ){
2595 qrfOom(p);
2596 return;
2597 }
@@ -2563,10 +2601,11 @@
2601
2602 /* Load the column header names and all cell content into data */
2603 if( p->spec.bTitles==QRF_Yes ){
2604 unsigned char saved_eText = p->spec.eText;
2605 p->spec.eText = p->spec.eTitle;
2606 memset(data.abNum, 0, nColumn);
2607 for(i=0; i<nColumn; i++){
2608 const char *z = (const char*)sqlite3_column_name(p->pStmt,i);
2609 int nNL = 0;
2610 int n, w;
2611 pStr = sqlite3_str_new(p->db);
@@ -2587,14 +2626,16 @@
2626 }
2627 for(i=0; i<nColumn; i++){
2628 char *z;
2629 int nNL = 0;
2630 int n, w;
2631 int eType = sqlite3_column_type(p->pStmt,i);
2632 pStr = sqlite3_str_new(p->db);
2633 qrfRenderValue(p, pStr, i);
2634 n = sqlite3_str_length(pStr);
2635 z = data.az[data.n] = sqlite3_str_finish(pStr);
2636 data.abNum[data.n] = eType==SQLITE_INTEGER || eType==SQLITE_FLOAT;
2637 data.aiWth[data.n] = w = qrfDisplayWidth(z, n, &nNL);
2638 data.n++;
2639 if( w>data.a[i].mxW ) data.a[i].mxW = w;
2640 if( nNL ) data.bMultiRow = 1;
2641 }
@@ -2680,11 +2721,16 @@
2721 }else{
2722 rowStart = BOX_13;
2723 colSep = BOX_13;
2724 rowSep = BOX_13 "\n";
2725 }
2726 if( p->spec.bBorder==QRF_No){
2727 rowStart += 3;
2728 rowSep = "\n";
2729 }else{
2730 qrfBoxSeparator(p->pOut, &data, BOX_23, BOX_234, BOX_34);
2731 }
2732 break;
2733 case QRF_STYLE_Table:
2734 if( data.nMargin ){
2735 rowStart = "| ";
2736 colSep = " | ";
@@ -2692,11 +2738,16 @@
2738 }else{
2739 rowStart = "|";
2740 colSep = "|";
2741 rowSep = "|\n";
2742 }
2743 if( p->spec.bBorder==QRF_No ){
2744 rowStart += 1;
2745 rowSep = "\n";
2746 }else{
2747 qrfRowSeparator(p->pOut, &data, '+');
2748 }
2749 break;
2750 case QRF_STYLE_Column: {
2751 static const char zSpace[] = " ";
2752 rowStart = "";
2753 if( data.nMargin<2 ){
@@ -2724,20 +2775,31 @@
2775 szRowStart = (int)strlen(rowStart);
2776 szRowSep = (int)strlen(rowSep);
2777 szColSep = (int)strlen(colSep);
2778
2779 bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2780 if( p->spec.eStyle==QRF_STYLE_Column
2781 || (p->spec.bBorder==QRF_No
2782 && (p->spec.eStyle==QRF_STYLE_Box || p->spec.eStyle==QRF_STYLE_Table)
2783 )
2784 ){
2785 bRTrim = 1;
2786 }else{
2787 bRTrim = 0;
2788 }
2789 for(i=0; i<data.n; i+=nColumn){
2790 int bMore;
2791 int nRow = 0;
2792
2793 /* Draw a single row of the table. This might be the title line
2794 ** (if there is a title line) or a row in the body of the table.
2795 ** The column number will be j. The row number is i/nColumn.
2796 */
2797 for(j=0; j<nColumn; j++){
2798 data.a[j].z = data.az[i+j];
2799 data.a[j].bNum = data.abNum[i+j];
2800 }
2801 do{
2802 sqlite3_str_append(p->pOut, rowStart, szRowStart);
2803 bMore = 0;
2804 for(j=0; j<nColumn; j++){
2805 int nThis = 0;
@@ -2744,11 +2806,11 @@
2806 int nWide = 0;
2807 int iNext = 0;
2808 int nWS;
2809 qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
2810 nWS = data.a[j].w - nWide;
2811 qrfPrintAligned(p->pOut, &data.a[j], nThis, nWS);
2812 data.a[j].z += iNext;
2813 if( data.a[j].z[0]!=0 ){
2814 bMore = 1;
2815 }
2816 if( j<nColumn-1 ){
@@ -2766,11 +2828,12 @@
2828 if( data.a[j].z[0]==0 ){
2829 sqlite3_str_appendchar(p->pOut, data.a[j].w, ' ');
2830 }else{
2831 int nE = 3;
2832 if( nE>data.a[j].w ) nE = data.a[j].w;
2833 data.a[j].z = "...";
2834 qrfPrintAligned(p->pOut, &data.a[j], nE, data.a[j].w-nE);
2835 }
2836 if( j<nColumn-1 ){
2837 sqlite3_str_append(p->pOut, colSep, szColSep);
2838 }else{
2839 if( bRTrim ) qrfRTrim(p->pOut);
@@ -2827,17 +2890,19 @@
2890 }
2891 }
2892 }
2893
2894 /* Draw the line across the bottom of the table */
2895 if( p->spec.bBorder!=QRF_No ){
2896 switch( p->spec.eStyle ){
2897 case QRF_STYLE_Box:
2898 qrfBoxSeparator(p->pOut, &data, BOX_12, BOX_124, BOX_14);
2899 break;
2900 case QRF_STYLE_Table:
2901 qrfRowSeparator(p->pOut, &data, '+');
2902 break;
2903 }
2904 }
2905 qrfWrite(p);
2906
2907 qrfColDataFree(&data);
2908 return;
@@ -6013,17 +6078,20 @@
6078 }
6079 /* End of the hashing logic
6080 *****************************************************************************/
6081
6082 /*
6083 ** Two SQL functions: sha1(X) and sha1b(X).
6084 **
6085 ** sha1(X) returns a lower-case hexadecimal rendering of the SHA1 hash
6086 ** of the argument X. If X is a BLOB, it is hashed as is. For all other
6087 ** types of input, X is converted into a UTF-8 string and the string
6088 ** is hashed without the trailing 0x00 terminator. The hash of a NULL
6089 ** value is NULL.
6090 **
6091 ** sha1b(X) is the same except that it returns a 20-byte BLOB containing
6092 ** the binary hash instead of a hexadecimal string.
6093 */
6094 static void sha1Func(
6095 sqlite3_context *context,
6096 int argc,
6097 sqlite3_value **argv
@@ -6040,15 +6108,17 @@
6108 hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
6109 }else{
6110 hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
6111 }
6112 if( sqlite3_user_data(context)!=0 ){
6113 /* sha1b() - binary result */
6114 hash_finish(&cx, zOut, 1);
6115 sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
6116 }else{
6117 /* sha1() - hexadecimal text result */
6118 hash_finish(&cx, zOut, 0);
6119 sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
6120 }
6121 }
6122
6123 /*
6124 ** Implementation of the sha1_query(SQL) function.
@@ -24120,19 +24190,20 @@
24190 #define MODE_Json 10 /* Output JSON */
24191 #define MODE_Line 11 /* One column per line. Blank line between records */
24192 #define MODE_List 12 /* One record per line with a separator */
24193 #define MODE_Markdown 13 /* Markdown formatting */
24194 #define MODE_Off 14 /* No query output shown */
24195 #define MODE_Psql 15 /* Similar to psql */
24196 #define MODE_QBox 16 /* BOX with SQL-quoted content */
24197 #define MODE_Quote 17 /* Quote values as for SQL */
24198 #define MODE_Split 18 /* Split-column mode */
24199 #define MODE_Table 19 /* MySQL-style table formatting */
24200 #define MODE_Tabs 20 /* Tab-separated values */
24201 #define MODE_Tcl 21 /* Space-separated list of TCL strings */
24202 #define MODE_Www 22 /* Full web-page output */
24203
24204 #define MODE_BUILTIN 22 /* Maximum built-in mode */
24205 #define MODE_BATCH 50 /* Default mode for batch processing */
24206 #define MODE_TTY 51 /* Default mode for interactive processing */
24207 #define MODE_USER 75 /* First user-defined mode */
24208 #define MODE_N_USER 25 /* Maximum number of user-defined modes */
24209
@@ -24149,10 +24220,11 @@
24220 unsigned char eHdr; /* Default header encoding. */
24221 unsigned char eBlob; /* Default blob encoding. */
24222 unsigned char bHdr; /* Show headers by default. 0: n/a, 1: no 2: yes */
24223 unsigned char eStyle; /* Underlying QRF style */
24224 unsigned char eCx; /* 0: other, 1: line, 2: columnar */
24225 unsigned char mFlg; /* Flags. 1=border-off 2=split-column */
24226 };
24227
24228 /* String constants used by built-in modes */
24229 static const char *aModeStr[] =
24230 /* 0 1 2 3 4 5 6 7 8 */
@@ -24159,33 +24231,34 @@
24231 { 0, "\n", "|", " ", ",", "\r\n", "\036", "\037", "\t",
24232 "", "NULL", "null", "\"\"" };
24233 /* 9 10 11 12 */
24234
24235 static const ModeInfo aModeInfo[] = {
24236 /* zName eCSep eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
24237 { "ascii", 7, 6, 9, 1, 1, 0, 1, 12, 0, 0 },
24238 { "box", 0, 0, 9, 1, 1, 0, 2, 1, 2, 0 },
24239 { "c", 4, 1, 10, 5, 5, 4, 1, 12, 0, 0 },
24240 { "column", 0, 0, 9, 1, 1, 0, 2, 2, 2, 0 },
24241 { "count", 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
24242 { "csv", 4, 5, 9, 3, 3, 0, 1, 12, 0, 0 },
24243 { "html", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 },
24244 { "insert", 0, 0, 10, 2, 2, 0, 1, 8, 0, 0 },
24245 { "jatom", 4, 1, 11, 6, 6, 0, 1, 12, 0, 0 },
24246 { "jobject", 0, 1, 11, 6, 6, 0, 0, 10, 0, 0 },
24247 { "json", 0, 0, 11, 6, 6, 0, 0, 9, 0, 0 },
24248 { "line", 0, 1, 9, 1, 1, 0, 0, 11, 1, 0 },
24249 { "list", 2, 1, 9, 1, 1, 0, 1, 12, 0, 0 },
24250 { "markdown", 0, 0, 9, 1, 1, 0, 2, 13, 2, 0 },
24251 { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0, 0 },
24252 { "psql", 0, 0, 9, 1, 1, 0, 2, 19, 2, 1 },
24253 { "qbox", 0, 0, 10, 2, 1, 0, 2, 1, 2, 0 },
24254 { "quote", 4, 1, 10, 2, 2, 0, 1, 12, 0, 0 },
24255 { "split", 0, 0, 9, 1, 1, 0, 1, 2, 2, 2 },
24256 { "table", 0, 0, 9, 1, 1, 0, 2, 19, 2, 0 },
24257 { "tabs", 8, 1, 9, 3, 3, 0, 1, 12, 0, 0 },
24258 { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0, 0 },
24259 { "www", 0, 0, 9, 4, 4, 0, 2, 7, 0, 0 }
24260 }; /* | / / | / / | | \
24261 ** | / / | / / | | \_ 2: columnar
24262 ** Index into aModeStr[] | / / | | 1: line
24263 ** | / / | | 0: other
24264 ** | / / | \
@@ -24307,11 +24380,16 @@
24380 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24381 pM->spec.eText = pI->eText;
24382 pM->spec.eBlob = pI->eBlob;
24383 pM->spec.bTitles = pI->bHdr;
24384 pM->spec.eTitle = pI->eHdr;
24385 if( pI->mFlg & 0x01 ){
24386 pM->spec.bBorder = QRF_No;
24387 }else{
24388 pM->spec.bBorder = QRF_Auto;
24389 }
24390 if( pI->mFlg & 0x02 ){
24391 pM->spec.bSplitColumn = QRF_Yes;
24392 pM->bAutoScreenWidth = 1;
24393 }else{
24394 pM->spec.bSplitColumn = QRF_No;
24395 }
@@ -26625,10 +26703,11 @@
26703 " meaning \"left\", \"centered\", and \"right\", with\n"
26704 " one letter per column starting from the left.\n"
26705 " Unspecified alignment defaults to 'L'.\n"
26706 " --blob-quote ARG ARG can be \"auto\", \"text\", \"sql\", \"hex\", \"tcl\",\n"
26707 " \"json\", or \"size\". Default is \"auto\".\n"
26708 " --border on|off Show outer border on \"box\" and \"table\" modes.\n"
26709 " --charlimit N Set the maximum number of output characters to\n"
26710 " show for any single SQL value to N. Longer values\n"
26711 " truncated. Zero means \"no limit\".\n"
26712 " --colsep STRING Use STRING as the column separator\n"
26713 " --escape ESC Enable/disable escaping of control characters\n"
@@ -30508,10 +30587,11 @@
30587 ** meaning "left", "centered", and "right", with
30588 ** one letter per column starting from the left.
30589 ** Unspecified alignment defaults to 'L'.
30590 ** --blob-quote ARG ARG can be "auto", "text", "sql", "hex", "tcl",
30591 ** "json", or "size". Default is "auto".
30592 ** --border on|off Show outer border on "box" and "table" modes.
30593 ** --charlimit N Set the maximum number of output characters to
30594 ** show for any single SQL value to N. Longer values
30595 ** truncated. Zero means "no limit".
30596 ** --colsep STRING Use STRING as the column separator
30597 ** --escape ESC Enable/disable escaping of control characters
@@ -30625,10 +30705,20 @@
30705 /* 0 1 2 3 4 5 6
30706 ** Must match QRF_BLOB_xxxx values. See also tag-20251124a */
30707 if( k>=0 ){
30708 p->mode.spec.eBlob = k & 0xff;
30709 }
30710 chng = 1;
30711 }else if( optionMatch(z,"border") ){
30712 if( (++i)>=nArg ){
30713 dotCmdError(p, i-1, "missing argument", 0);
30714 return 1;
30715 }
30716 k = pickStr(azArg[i], 0, "auto", "off", "on", "");
30717 if( k>=0 ){
30718 p->mode.spec.bBorder = k & 0x3;
30719 }
30720 chng = 1;
30721 }else if( 0<=(k=pickStr(z,0,"-charlimit","-linelimit","")) ){
30722 int w; /* 0 1 */
30723 if( i+1>=nArg ){
30724 dotCmdError(p, i, "missing argument", 0);
@@ -30847,16 +30937,16 @@
30937 zW = azArg[++i];
30938 /* Every width value takes at least 2 bytes in the input string to
30939 ** specify, so strlen(zW) bytes should be plenty of space to hold the
30940 ** result. */
30941 aWidth = malloc( strlen(zW) );
30942 while( IsSpace(zW[0]) ) zW++;
30943 while( zW[0] ){
30944 int w = 0;
30945 int nDigit = 0;
30946 k = zW[0]=='-' && IsDigit(zW[1]);
30947 while( IsDigit(zW[k]) ){
30948 w = w*10 + zW[k] - '0';
30949 if( w>QRF_MAX_WIDTH ){
30950 dotCmdError(p,i+1,"width too big",
30951 "Maximum column width is %d", QRF_MAX_WIDTH);
30952 free(aWidth);
@@ -30873,11 +30963,11 @@
30963 }
30964 if( zW[0]=='-' ) w = -w;
30965 aWidth[nWidth++] = w;
30966 zW += k;
30967 if( zW[0]==',' ) zW++;
30968 while( IsSpace(zW[0]) ) zW++;
30969 }
30970 free(p->mode.spec.aWidth);
30971 p->mode.spec.aWidth = aWidth;
30972 p->mode.spec.nWidth = nWidth;
30973 chng = 1;
@@ -30928,10 +31018,16 @@
31018 unsigned char a = p->mode.spec.aAlign[ii];
31019 sqlite3_str_appendchar(pDesc, 1, "LLCR"[a&3]);
31020 }
31021 sqlite3_str_append(pDesc, "\"", 1);
31022 }
31023 if( bAll
31024 || (p->mode.spec.bBorder==QRF_No) != ((pI->mFlg&1)!=0)
31025 ){
31026 sqlite3_str_appendf(pDesc," --border %s",
31027 p->mode.spec.bBorder==QRF_No ? "off" : "on");
31028 }
31029 if( bAll || p->mode.spec.eBlob!=QRF_BLOB_Auto ){
31030 const char *azBQuote[] =
31031 { "auto", "text", "sql", "hex", "tcl", "json", "size" };
31032 /* 0 1 2 3 4 5 6
31033 ** Must match QRF_BLOB_xxxx values. See all instances of tag-20251124a */
@@ -35586,11 +35682,12 @@
35682 data.pAuxDb->zDbFilename = ":memory:";
35683 warnInmemoryDb = argc==1;
35684 #else
35685 cli_printf(stderr,
35686 "%s: Error: no database filename specified\n", Argv0);
35687 rc = 1;
35688 goto shell_main_exit;
35689 #endif
35690 }
35691 data.out = stdout;
35692 if( bEnableVfstrace ){
35693 vfstrace_register("trace",0,vfstraceOut, &data, 1);
@@ -35640,10 +35737,12 @@
35737 modeChange(&data, MODE_Json);
35738 }else if( cli_strcmp(z,"-markdown")==0 ){
35739 modeChange(&data, MODE_Markdown);
35740 }else if( cli_strcmp(z,"-table")==0 ){
35741 modeChange(&data, MODE_Table);
35742 }else if( cli_strcmp(z,"-psql")==0 ){
35743 modeChange(&data, MODE_Psql);
35744 }else if( cli_strcmp(z,"-box")==0 ){
35745 modeChange(&data, MODE_Box);
35746 }else if( cli_strcmp(z,"-csv")==0 ){
35747 modeChange(&data, MODE_Csv);
35748 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
@@ -35726,11 +35825,12 @@
35825 }else if( cli_strcmp(z,"-bail")==0 ){
35826 /* No-op. The bail_on_error flag should already be set. */
35827 }else if( cli_strcmp(z,"-version")==0 ){
35828 cli_printf(stdout, "%s %s (%d-bit)\n",
35829 sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
35830 rc = 0;
35831 goto shell_main_exit;
35832 }else if( cli_strcmp(z,"-interactive")==0 ){
35833 /* Need to check for interactive override here to so that it can
35834 ** affect console setup (for Windows only) and testing thereof.
35835 */
35836 stdin_is_interactive = 1;
@@ -35783,29 +35883,33 @@
35883 ** we retain the goofy behavior for historical compatibility. */
35884 if( i==argc-1 ) break;
35885 z = cmdline_option_value(argc,argv,++i);
35886 if( z[0]=='.' ){
35887 rc = do_meta_command(z, &data);
35888 if( rc && bail_on_error ){
35889 if( rc==2 ) rc = 0;
35890 goto shell_main_exit;
35891 }
35892 }else{
35893 open_db(&data, 0);
35894 rc = shell_exec(&data, z, &zErrMsg);
35895 if( zErrMsg!=0 ){
35896 shellEmitError(zErrMsg);
35897 sqlite3_free(zErrMsg);
35898 if( !rc ) rc = 1;
35899 }else if( rc!=0 ){
35900 cli_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
 
35901 }
35902 if( bail_on_error ) goto shell_main_exit;
35903 }
35904 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
35905 }else if( cli_strncmp(z, "-A", 2)==0 ){
35906 if( nCmd>0 ){
35907 cli_printf(stderr,"Error: cannot mix regular SQL or dot-commands"
35908 " with \"%s\"\n", z);
35909 rc = 1;
35910 goto shell_main_exit;
35911 }
35912 open_db(&data, OPEN_DB_ZIPFILE);
35913 if( z[2] ){
35914 argv[i] = &z[2];
35915 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
@@ -35821,11 +35925,12 @@
35925 }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
35926 /* Acted upon in first pass. */
35927 }else{
35928 cli_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
35929 eputz("Use -help for a list of options.\n");
35930 rc = 1;
35931 goto shell_main_exit;
35932 }
35933 }
35934
35935 if( !readStdin ){
35936 /* Run all arguments that do not begin with '-' as if they were separate
35937
+21 -6
--- 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
-** 5804ba4874cc41b11e8bb559d5533283c289 with changes in files:
21
+** 4384c9a108b58a0b8c38c51678aad871f088 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-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911"
472
+#define SQLITE_SOURCE_ID "2025-11-28 17:56:22 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2025-11-25T18:20:33.534Z"
475
+#define SQLITE_SCM_DATETIME "2025-11-28T17:56:22.595Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -203373,11 +203373,12 @@
203373203373
PendingList *pList;
203374203374
int rc = SQLITE_OK;
203375203375
203376203376
pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
203377203377
if( pList ){
203378
- p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
203378
+ assert( pList->nData+nToken+sizeof(Fts3HashElem) <= (i64)p->nPendingData );
203379
+ p->nPendingData -= (int)(pList->nData + nToken + sizeof(Fts3HashElem));
203379203380
}
203380203381
if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
203381203382
if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
203382203383
/* Malloc failed while inserting the new entry. This can only
203383203384
** happen if there was no previous entry for this token.
@@ -203386,11 +203387,13 @@
203386203387
sqlite3_free(pList);
203387203388
rc = SQLITE_NOMEM;
203388203389
}
203389203390
}
203390203391
if( rc==SQLITE_OK ){
203391
- p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
203392
+ assert( (i64)p->nPendingData + pList->nData + nToken
203393
+ + sizeof(Fts3HashElem) <= 0x3fffffff );
203394
+ p->nPendingData += (int)(pList->nData + nToken + sizeof(Fts3HashElem));
203392203395
}
203393203396
return rc;
203394203397
}
203395203398
203396203399
/*
@@ -250200,10 +250203,11 @@
250200250203
250201250204
ASSERT_SZLEAF_OK(pIter->pLeaf);
250202250205
while( 1 ){
250203250206
u64 iDelta = 0;
250204250207
250208
+ if( i>=n ) break;
250205250209
if( eDetail==FTS5_DETAIL_NONE ){
250206250210
/* todo */
250207250211
if( i<n && a[i]==0 ){
250208250212
i++;
250209250213
if( i<n && a[i]==0 ) i++;
@@ -261263,11 +261267,11 @@
261263261267
int nArg, /* Number of args */
261264261268
sqlite3_value **apUnused /* Function arguments */
261265261269
){
261266261270
assert( nArg==0 );
261267261271
UNUSED_PARAM2(nArg, apUnused);
261268
- sqlite3_result_text(pCtx, "fts5: 2025-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911", -1, SQLITE_TRANSIENT);
261272
+ sqlite3_result_text(pCtx, "fts5: 2025-11-28 17:56:22 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce", -1, SQLITE_TRANSIENT);
261269261273
}
261270261274
261271261275
/*
261272261276
** Implementation of fts5_locale(LOCALE, TEXT) function.
261273261277
**
@@ -266084,20 +266088,31 @@
266084266088
266085266089
*ppCsr = (sqlite3_vtab_cursor*)pCsr;
266086266090
return rc;
266087266091
}
266088266092
266093
+/*
266094
+** Restore cursor pCsr to the state it was in immediately after being
266095
+** created by the xOpen() method.
266096
+*/
266089266097
static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
266098
+ int nCol = pCsr->pFts5->pConfig->nCol;
266090266099
pCsr->rowid = 0;
266091266100
sqlite3Fts5IterClose(pCsr->pIter);
266092266101
sqlite3Fts5StructureRelease(pCsr->pStruct);
266093266102
pCsr->pStruct = 0;
266094266103
pCsr->pIter = 0;
266095266104
sqlite3_free(pCsr->zLeTerm);
266096266105
pCsr->nLeTerm = -1;
266097266106
pCsr->zLeTerm = 0;
266098266107
pCsr->bEof = 0;
266108
+ pCsr->iCol = 0;
266109
+ pCsr->iInstPos = 0;
266110
+ pCsr->iInstOff = 0;
266111
+ pCsr->colUsed = 0;
266112
+ memset(pCsr->aCnt, 0, sizeof(i64)*nCol);
266113
+ memset(pCsr->aDoc, 0, sizeof(i64)*nCol);
266099266114
}
266100266115
266101266116
/*
266102266117
** Close the cursor. For additional information see the documentation
266103266118
** on the xClose method of the virtual table interface.
266104266119
--- 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 ** 5804ba4874cc41b11e8bb559d5533283c289 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-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2025-11-25T18:20:33.534Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -203373,11 +203373,12 @@
203373 PendingList *pList;
203374 int rc = SQLITE_OK;
203375
203376 pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
203377 if( pList ){
203378 p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
 
203379 }
203380 if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
203381 if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
203382 /* Malloc failed while inserting the new entry. This can only
203383 ** happen if there was no previous entry for this token.
@@ -203386,11 +203387,13 @@
203386 sqlite3_free(pList);
203387 rc = SQLITE_NOMEM;
203388 }
203389 }
203390 if( rc==SQLITE_OK ){
203391 p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
 
 
203392 }
203393 return rc;
203394 }
203395
203396 /*
@@ -250200,10 +250203,11 @@
250200
250201 ASSERT_SZLEAF_OK(pIter->pLeaf);
250202 while( 1 ){
250203 u64 iDelta = 0;
250204
 
250205 if( eDetail==FTS5_DETAIL_NONE ){
250206 /* todo */
250207 if( i<n && a[i]==0 ){
250208 i++;
250209 if( i<n && a[i]==0 ) i++;
@@ -261263,11 +261267,11 @@
261263 int nArg, /* Number of args */
261264 sqlite3_value **apUnused /* Function arguments */
261265 ){
261266 assert( nArg==0 );
261267 UNUSED_PARAM2(nArg, apUnused);
261268 sqlite3_result_text(pCtx, "fts5: 2025-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911", -1, SQLITE_TRANSIENT);
261269 }
261270
261271 /*
261272 ** Implementation of fts5_locale(LOCALE, TEXT) function.
261273 **
@@ -266084,20 +266088,31 @@
266084
266085 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
266086 return rc;
266087 }
266088
 
 
 
 
266089 static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
 
266090 pCsr->rowid = 0;
266091 sqlite3Fts5IterClose(pCsr->pIter);
266092 sqlite3Fts5StructureRelease(pCsr->pStruct);
266093 pCsr->pStruct = 0;
266094 pCsr->pIter = 0;
266095 sqlite3_free(pCsr->zLeTerm);
266096 pCsr->nLeTerm = -1;
266097 pCsr->zLeTerm = 0;
266098 pCsr->bEof = 0;
 
 
 
 
 
 
266099 }
266100
266101 /*
266102 ** Close the cursor. For additional information see the documentation
266103 ** on the xClose method of the virtual table interface.
266104
--- 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 ** 4384c9a108b58a0b8c38c51678aad871f088 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-11-28 17:56:22 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2025-11-28T17:56:22.595Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -203373,11 +203373,12 @@
203373 PendingList *pList;
203374 int rc = SQLITE_OK;
203375
203376 pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
203377 if( pList ){
203378 assert( pList->nData+nToken+sizeof(Fts3HashElem) <= (i64)p->nPendingData );
203379 p->nPendingData -= (int)(pList->nData + nToken + sizeof(Fts3HashElem));
203380 }
203381 if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
203382 if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
203383 /* Malloc failed while inserting the new entry. This can only
203384 ** happen if there was no previous entry for this token.
@@ -203386,11 +203387,13 @@
203387 sqlite3_free(pList);
203388 rc = SQLITE_NOMEM;
203389 }
203390 }
203391 if( rc==SQLITE_OK ){
203392 assert( (i64)p->nPendingData + pList->nData + nToken
203393 + sizeof(Fts3HashElem) <= 0x3fffffff );
203394 p->nPendingData += (int)(pList->nData + nToken + sizeof(Fts3HashElem));
203395 }
203396 return rc;
203397 }
203398
203399 /*
@@ -250200,10 +250203,11 @@
250203
250204 ASSERT_SZLEAF_OK(pIter->pLeaf);
250205 while( 1 ){
250206 u64 iDelta = 0;
250207
250208 if( i>=n ) break;
250209 if( eDetail==FTS5_DETAIL_NONE ){
250210 /* todo */
250211 if( i<n && a[i]==0 ){
250212 i++;
250213 if( i<n && a[i]==0 ) i++;
@@ -261263,11 +261267,11 @@
261267 int nArg, /* Number of args */
261268 sqlite3_value **apUnused /* Function arguments */
261269 ){
261270 assert( nArg==0 );
261271 UNUSED_PARAM2(nArg, apUnused);
261272 sqlite3_result_text(pCtx, "fts5: 2025-11-28 17:56:22 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce", -1, SQLITE_TRANSIENT);
261273 }
261274
261275 /*
261276 ** Implementation of fts5_locale(LOCALE, TEXT) function.
261277 **
@@ -266084,20 +266088,31 @@
266088
266089 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
266090 return rc;
266091 }
266092
266093 /*
266094 ** Restore cursor pCsr to the state it was in immediately after being
266095 ** created by the xOpen() method.
266096 */
266097 static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
266098 int nCol = pCsr->pFts5->pConfig->nCol;
266099 pCsr->rowid = 0;
266100 sqlite3Fts5IterClose(pCsr->pIter);
266101 sqlite3Fts5StructureRelease(pCsr->pStruct);
266102 pCsr->pStruct = 0;
266103 pCsr->pIter = 0;
266104 sqlite3_free(pCsr->zLeTerm);
266105 pCsr->nLeTerm = -1;
266106 pCsr->zLeTerm = 0;
266107 pCsr->bEof = 0;
266108 pCsr->iCol = 0;
266109 pCsr->iInstPos = 0;
266110 pCsr->iInstOff = 0;
266111 pCsr->colUsed = 0;
266112 memset(pCsr->aCnt, 0, sizeof(i64)*nCol);
266113 memset(pCsr->aDoc, 0, sizeof(i64)*nCol);
266114 }
266115
266116 /*
266117 ** Close the cursor. For additional information see the documentation
266118 ** on the xClose method of the virtual table interface.
266119
--- 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-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911"
151
+#define SQLITE_SOURCE_ID "2025-11-28 17:56:22 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce"
152152
#define SQLITE_SCM_BRANCH "trunk"
153153
#define SQLITE_SCM_TAGS ""
154
-#define SQLITE_SCM_DATETIME "2025-11-25T18:20:33.534Z"
154
+#define SQLITE_SCM_DATETIME "2025-11-28T17:56:22.595Z"
155155
156156
/*
157157
** CAPI3REF: Run-Time Library Version Numbers
158158
** KEYWORDS: sqlite3_version sqlite3_sourceid
159159
**
160160
--- 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-11-25 18:20:33 5804ba4874cc41b11e8bb559d5533283c2895d2b13316830955663575567f911"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2025-11-25T18:20:33.534Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
160
--- 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-11-28 17:56:22 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2025-11-28T17:56:22.595Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
160

Keyboard Shortcuts

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