Fossil SCM

Update to the latest SQLite, so as to gain access to the improved layout of the ".tables" and ".indexes" commands in the SQLite CLI.

drh 2025-11-23 11:06 trunk
Commit 9aee493cf3b97fe878d370eefe2c4331c74414171626cdcd431b9d415875502b
+266 -95
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -681,10 +681,13 @@
681681
** Header file for the Result-Format or "resfmt" utility library for SQLite.
682682
** See the resfmt.md documentation for additional information.
683683
*/
684684
#ifndef SQLITE_QRF_H
685685
#define SQLITE_QRF_H
686
+#ifdef __cplusplus
687
+extern "C" {
688
+#endif
686689
#include <stdlib.h>
687690
/* #include "sqlite3.h" */
688691
689692
/*
690693
** Specification used by clients to define the output format they want
@@ -701,10 +704,11 @@
701704
unsigned char bWordWrap; /* Try to wrap on word boundaries */
702705
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
703706
unsigned char bTextNull; /* Apply eText encoding to zNull[] */
704707
unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
705708
unsigned char eTitleAlign; /* Alignment for column headers */
709
+ unsigned char bSplitColumn; /* Wrap single-column output into many columns */
706710
short int nWrap; /* Wrap columns wider than this */
707711
short int nScreenWidth; /* Maximum overall table width */
708712
short int nLineLimit; /* Maximum number of lines for any row */
709713
int nCharLimit; /* Maximum number of characters in a cell */
710714
int nWidth; /* Number of entries in aWidth[] */
@@ -846,12 +850,13 @@
846850
** Unfortunately, there is nothing we can do about that.
847851
*/
848852
int sqlite3_qrf_wcwidth(int c);
849853
850854
851
-
852
-
855
+#ifdef __cplusplus
856
+}
857
+#endif
853858
#endif /* !defined(SQLITE_QRF_H) */
854859
855860
/************************* End ext/qrf/qrf.h ********************/
856861
/************************* Begin ext/qrf/qrf.c ******************/
857862
/*
@@ -1895,10 +1900,21 @@
18951900
sqlite3_str_append(pOut, "...", 3);
18961901
}
18971902
}
18981903
#endif
18991904
}
1905
+
1906
+/* Trim spaces of the end if pOut
1907
+*/
1908
+static void qrfRTrim(sqlite3_str *pOut){
1909
+#if SQLITE_VERSION_NUMBER>=3052000
1910
+ int nByte = sqlite3_str_length(pOut);
1911
+ const char *zOut = sqlite3_str_value(pOut);
1912
+ while( nByte>0 && zOut[nByte-1]==' ' ){ nByte--; }
1913
+ sqlite3_str_truncate(pOut, nByte);
1914
+#endif
1915
+}
19001916
19011917
/*
19021918
** Store string zUtf to pOut as w characters. If w is negative,
19031919
** then right-justify the text. W is the width in display characters, not
19041920
** in bytes. Double-width unicode characters count as two characters.
@@ -2305,10 +2321,135 @@
23052321
(pData->a[i].e & QRF_ALIGN_VMASK);
23062322
}
23072323
}
23082324
}
23092325
}
2326
+
2327
+/*
2328
+** If the single column in pData->a[] with pData->n entries can be
2329
+** laid out as nCol columns with a 2-space gap between each such
2330
+** that all columns fit within nSW, then return a pointer to an array
2331
+** of integers which is the width of each column from left to right.
2332
+**
2333
+** If the layout is not possible, return a NULL pointer.
2334
+**
2335
+** Space to hold the returned array is from sqlite_malloc64().
2336
+*/
2337
+static int *qrfValidLayout(
2338
+ qrfColData *pData, /* Collected query results */
2339
+ Qrf *p, /* On which to report an OOM */
2340
+ int nCol, /* Attempt this many columns */
2341
+ int nSW /* Screen width */
2342
+){
2343
+ int i; /* Loop counter */
2344
+ int nr; /* Number of rows */
2345
+ int w = 0; /* Width of the current column */
2346
+ int t; /* Total width of all columns */
2347
+ int *aw; /* Array of individual column widths */
2348
+
2349
+ aw = sqlite3_malloc64( sizeof(int)*nCol );
2350
+ if( aw==0 ){
2351
+ qrfOom(p);
2352
+ return 0;
2353
+ }
2354
+ nr = (pData->n + nCol - 1)/nCol;
2355
+ for(i=0; i<pData->n; i++){
2356
+ if( (i%nr)==0 ){
2357
+ if( i>0 ) aw[i/nr-1] = w;
2358
+ w = pData->aiWth[i];
2359
+ }else if( pData->aiWth[i]>w ){
2360
+ w = pData->aiWth[i];
2361
+ }
2362
+ }
2363
+ aw[nCol-1] = w;
2364
+ for(t=i=0; i<nCol; i++) t += aw[i];
2365
+ t += 2*(nCol-1);
2366
+ if( t>nSW ){
2367
+ sqlite3_free(aw);
2368
+ return 0;
2369
+ }
2370
+ return aw;
2371
+}
2372
+
2373
+/*
2374
+** The output is single-column and the bSplitColumn flag is set.
2375
+** Check to see if the single-column output can be split into multiple
2376
+** columns that appear side-by-side. Adjust pData appropriately.
2377
+*/
2378
+static void qrfSplitColumn(qrfColData *pData, Qrf *p){
2379
+ int nCol = 1;
2380
+ int *aw = 0;
2381
+ char **az = 0;
2382
+ int *aiWth = 0;
2383
+ int nColNext = 2;
2384
+ int w;
2385
+ struct qrfPerCol *a = 0;
2386
+ sqlite3_int64 nRow = 1;
2387
+ sqlite3_int64 i;
2388
+ while( 1/*exit-by-break*/ ){
2389
+ int *awNew = qrfValidLayout(pData, p, nColNext, p->spec.nScreenWidth);
2390
+ if( awNew==0 ) break;
2391
+ sqlite3_free(aw);
2392
+ aw = awNew;
2393
+ nCol = nColNext;
2394
+ nRow = (pData->n + nCol - 1)/nCol;
2395
+ if( nRow==1 ) break;
2396
+ nColNext++;
2397
+ while( (pData->n + nColNext - 1)/nColNext == nRow ) nColNext++;
2398
+ }
2399
+ if( nCol==1 ){
2400
+ sqlite3_free(aw);
2401
+ return; /* Cannot do better than 1 column */
2402
+ }
2403
+ az = sqlite3_malloc64( nRow*nCol*sizeof(char*) );
2404
+ if( az==0 ){
2405
+ qrfOom(p);
2406
+ return;
2407
+ }
2408
+ aiWth = sqlite3_malloc64( nRow*nCol*sizeof(int) );
2409
+ if( aiWth==0 ){
2410
+ sqlite3_free(az);
2411
+ qrfOom(p);
2412
+ return;
2413
+ }
2414
+ a = sqlite3_malloc64( nCol*sizeof(struct qrfPerCol) );
2415
+ if( a==0 ){
2416
+ sqlite3_free(az);
2417
+ sqlite3_free(aiWth);
2418
+ qrfOom(p);
2419
+ return;
2420
+ }
2421
+ for(i=0; i<pData->n; i++){
2422
+ sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2423
+ az[j] = pData->az[i];
2424
+ pData->az[i] = 0;
2425
+ aiWth[j] = pData->aiWth[i];
2426
+ }
2427
+ while( i<nRow*nCol ){
2428
+ sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2429
+ az[j] = sqlite3_mprintf("");
2430
+ if( az[j]==0 ) qrfOom(p);
2431
+ aiWth[j] = 0;
2432
+ i++;
2433
+ }
2434
+ for(i=0; i<nCol; i++){
2435
+ a[i].fx = a[i].mxW = a[i].w = aw[i];
2436
+ a[i].e = pData->a[0].e;
2437
+ }
2438
+ sqlite3_free(pData->az);
2439
+ sqlite3_free(pData->aiWth);
2440
+ sqlite3_free(pData->a);
2441
+ sqlite3_free(aw);
2442
+ pData->az = az;
2443
+ pData->aiWth = aiWth;
2444
+ pData->a = a;
2445
+ pData->nCol = nCol;
2446
+ pData->n = pData->nAlloc = nRow*nCol;
2447
+ for(i=w=0; i<nCol; i++) w += a[i].w;
2448
+ pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
2449
+ if( pData->nMargin>5 ) pData->nMargin = 5;
2450
+}
23102451
23112452
/*
23122453
** Adjust the layout for the screen width restriction
23132454
*/
23142455
static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){
@@ -2395,10 +2536,11 @@
23952536
int rc; /* Result code */
23962537
int nColumn = p->nCol; /* Number of columns */
23972538
int bWW; /* True to do word-wrap */
23982539
sqlite3_str *pStr; /* Temporary rendering */
23992540
qrfColData data; /* Columnar layout data */
2541
+ int bRTrim; /* Trim trailing space */
24002542
24012543
rc = sqlite3_step(p->pStmt);
24022544
if( rc!=SQLITE_ROW || nColumn==0 ){
24032545
return; /* No output */
24042546
}
@@ -2504,12 +2646,26 @@
25042646
}
25052647
}
25062648
data.a[i].w = w;
25072649
}
25082650
2509
- /* Adjust the column widths due to screen width restrictions */
2510
- qrfRestrictScreenWidth(&data, p);
2651
+ if( nColumn==1
2652
+ && data.n>1
2653
+ && p->spec.bSplitColumn==QRF_Yes
2654
+ && p->spec.eStyle==QRF_STYLE_Column
2655
+ && p->spec.bTitles==QRF_No
2656
+ && p->spec.nScreenWidth>data.a[0].w+3
2657
+ ){
2658
+ /* Attempt to convert single-column tables into multi-column by
2659
+ ** verticle wrapping, if the screen is wide enough and if the
2660
+ ** bSplitColumn flag is set. */
2661
+ qrfSplitColumn(&data, p);
2662
+ nColumn = data.nCol;
2663
+ }else{
2664
+ /* Adjust the column widths due to screen width restrictions */
2665
+ qrfRestrictScreenWidth(&data, p);
2666
+ }
25112667
25122668
/* Draw the line across the top of the table. Also initialize
25132669
** the row boundary and column separator texts. */
25142670
switch( p->spec.eStyle ){
25152671
case QRF_STYLE_Box:
@@ -2536,11 +2692,17 @@
25362692
}
25372693
qrfRowSeparator(p->pOut, &data, '+');
25382694
break;
25392695
case QRF_STYLE_Column:
25402696
rowStart = "";
2541
- colSep = data.nMargin ? " " : " ";
2697
+ if( data.nMargin<2 ){
2698
+ colSep = " ";
2699
+ }else if( data.nMargin<=5 ){
2700
+ colSep = " " + (5-data.nMargin);
2701
+ }else{
2702
+ colSep = " ";
2703
+ }
25422704
rowSep = "\n";
25432705
break;
25442706
default: /*case QRF_STYLE_Markdown:*/
25452707
if( data.nMargin ){
25462708
rowStart = "| ";
@@ -2556,10 +2718,11 @@
25562718
szRowStart = (int)strlen(rowStart);
25572719
szRowSep = (int)strlen(rowSep);
25582720
szColSep = (int)strlen(colSep);
25592721
25602722
bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2723
+ bRTrim = (p->spec.eStyle==QRF_STYLE_Column);
25612724
for(i=0; i<data.n; i+=nColumn){
25622725
int bMore;
25632726
int nRow = 0;
25642727
25652728
/* Draw a single row of the table. This might be the title line
@@ -2577,14 +2740,17 @@
25772740
int nWS;
25782741
qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
25792742
nWS = data.a[j].w - nWide;
25802743
qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
25812744
data.a[j].z += iNext;
2582
- if( data.a[j].z[0]!=0 ) bMore = 1;
2745
+ if( data.a[j].z[0]!=0 ){
2746
+ bMore = 1;
2747
+ }
25832748
if( j<nColumn-1 ){
25842749
sqlite3_str_append(p->pOut, colSep, szColSep);
25852750
}else{
2751
+ if( bRTrim ) qrfRTrim(p->pOut);
25862752
sqlite3_str_append(p->pOut, rowSep, szRowSep);
25872753
}
25882754
}
25892755
}while( bMore && ++nRow < p->mxHeight );
25902756
if( bMore ){
@@ -2599,10 +2765,11 @@
25992765
qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
26002766
}
26012767
if( j<nColumn-1 ){
26022768
sqlite3_str_append(p->pOut, colSep, szColSep);
26032769
}else{
2770
+ if( bRTrim ) qrfRTrim(p->pOut);
26042771
sqlite3_str_append(p->pOut, rowSep, szRowSep);
26052772
}
26062773
}
26072774
}
26082775
@@ -2639,14 +2806,16 @@
26392806
for(j=0; j<nColumn; j++){
26402807
sqlite3_str_appendchar(p->pOut, data.a[j].w, '-');
26412808
if( j<nColumn-1 ){
26422809
sqlite3_str_append(p->pOut, colSep, szColSep);
26432810
}else{
2811
+ qrfRTrim(p->pOut);
26442812
sqlite3_str_append(p->pOut, rowSep, szRowSep);
26452813
}
26462814
}
26472815
}else if( data.bMultiRow ){
2816
+ qrfRTrim(p->pOut);
26482817
sqlite3_str_append(p->pOut, "\n", 1);
26492818
}
26502819
break;
26512820
}
26522821
}
@@ -23946,16 +24115,17 @@
2394624115
#define MODE_List 12 /* One record per line with a separator */
2394724116
#define MODE_Markdown 13 /* Markdown formatting */
2394824117
#define MODE_Off 14 /* No query output shown */
2394924118
#define MODE_QBox 15 /* BOX with SQL-quoted content */
2395024119
#define MODE_Quote 16 /* Quote values as for SQL */
23951
-#define MODE_Table 17 /* MySQL-style table formatting */
23952
-#define MODE_Tabs 18 /* Tab-separated values */
23953
-#define MODE_Tcl 19 /* Space-separated list of TCL strings */
23954
-#define MODE_Www 20 /* Full web-page output */
24120
+#define MODE_Split 17 /* Split-column mode */
24121
+#define MODE_Table 18 /* MySQL-style table formatting */
24122
+#define MODE_Tabs 19 /* Tab-separated values */
24123
+#define MODE_Tcl 20 /* Space-separated list of TCL strings */
24124
+#define MODE_Www 21 /* Full web-page output */
2395524125
23956
-#define MODE_BUILTIN 20 /* Maximum built-in mode */
24126
+#define MODE_BUILTIN 21 /* Maximum built-in mode */
2395724127
#define MODE_BATCH 50 /* Default mode for batch processing */
2395824128
#define MODE_TTY 51 /* Default mode for interactive processing */
2395924129
#define MODE_USER 75 /* First user-defined mode */
2396024130
#define MODE_N_USER 25 /* Maximum number of user-defined modes */
2396124131
@@ -24000,10 +24170,11 @@
2400024170
{ "list", 2, 1, 9, 1, 1, 1, 1, 12, 0 },
2400124171
{ "markdown", 0, 0, 9, 1, 1, 1, 2, 13, 2 },
2400224172
{ "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
2400324173
{ "qbox", 0, 0, 9, 2, 1, 2, 2, 1, 2 },
2400424174
{ "quote", 4, 1, 10, 2, 2, 2, 1, 12, 0 },
24175
+ { "split", 0, 0, 9, 1, 1, 1, 1, 2, 2 },
2400524176
{ "table", 0, 0, 9, 1, 1, 1, 2, 19, 2 },
2400624177
{ "tabs", 8, 1, 9, 3, 3, 1, 1, 12, 0 },
2400724178
{ "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
2400824179
{ "www", 0, 0, 9, 4, 4, 1, 2, 7, 0 }
2400924180
}; /* | / / | / / | | \
@@ -24128,10 +24299,16 @@
2412824299
if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
2412924300
pM->spec.eText = pI->eText;
2413024301
pM->spec.eBlob = pI->eBlob;
2413124302
pM->spec.bTitles = pI->bHdr;
2413224303
pM->spec.eTitle = pI->eHdr;
24304
+ if( eMode==MODE_Split ){
24305
+ pM->spec.bSplitColumn = QRF_Yes;
24306
+ pM->bAutoScreenWidth = 1;
24307
+ }else{
24308
+ pM->spec.bSplitColumn = QRF_No;
24309
+ }
2413324310
}else if( eMode>=MODE_USER && eMode-MODE_USER<p->nSavedModes ){
2413424311
modeFree(&p->mode);
2413524312
modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
2413624313
}else if( eMode==MODE_BATCH ){
2413724314
u8 mFlags = p->mode.mFlags;
@@ -26441,10 +26618,12 @@
2644126618
" --linelimit N Set the maximum number of output lines to show for\n"
2644226619
" any single SQL value to N. Longer values are\n"
2644326620
" truncated. Zero means \"no limit\". Only works\n"
2644426621
" in \"line\" mode and in columnar modes.\n"
2644526622
" --list List available modes\n"
26623
+" --no-limits Shorthand to turn off --linelimit, --charlimit,\n"
26624
+" and --screenwidth.\n"
2644626625
" --null STRING Render SQL NULL values as the given string\n"
2644726626
" --once Setting changes to the right are reverted after\n"
2644826627
" the next SQL command.\n"
2644926628
" --quote ARG Enable/disable quoting of text. ARG can be\n"
2645026629
" \"off\", \"on\", \"sql\", \"csv\", \"html\", \"tcl\",\n"
@@ -30320,10 +30499,12 @@
3032030499
** --linelimit N Set the maximum number of output lines to show for
3032130500
** any single SQL value to N. Longer values are
3032230501
** truncated. Zero means "no limit". Only works
3032330502
** in "line" mode and in columnar modes.
3032430503
** --list List available modes
30504
+** --no-limits Shorthand to turn off --linelimit, --charlimit,
30505
+** and --screenwidth.
3032530506
** --null STRING Render SQL NULL values as the given string
3032630507
** --once Setting changes to the right are reverted after
3032730508
** the next SQL command.
3032830509
** --quote ARG Enable/disable quoting of text. ARG can be
3032930510
** "off", "on", "sql", "csv", "html", "tcl",
@@ -30465,10 +30646,25 @@
3046530646
}
3046630647
for(ii=0; ii<p->nSavedModes; ii++){
3046730648
cli_printf(p->out, " %s", p->aSavedModes[ii].zTag);
3046830649
}
3046930650
cli_puts(" batch tty\n", p->out);
30651
+ }else if( optionMatch(z,"once") ){
30652
+ p->nPopMode = 0;
30653
+ modePush(p);
30654
+ p->nPopMode = 1;
30655
+ }else if( optionMatch(z,"noquote") ){
30656
+ /* (undocumented legacy) --noquote always turns quoting off */
30657
+ p->mode.spec.eText = QRF_TEXT_Plain;
30658
+ p->mode.spec.eBlob = QRF_BLOB_Text;
30659
+ chng = 1;
30660
+ }else if( optionMatch(z,"no-limits") ){
30661
+ p->mode.spec.nLineLimit = 0;
30662
+ p->mode.spec.nCharLimit = 0;
30663
+ p->mode.spec.nScreenWidth = 0;
30664
+ p->mode.bAutoScreenWidth = 0;
30665
+ chng = 1;
3047030666
}else if( optionMatch(z,"quote") ){
3047130667
if( i+1<nArg
3047230668
&& azArg[i+1][0]!='-'
3047330669
&& (iMode>0 || strcmp(azArg[i+1],"off")==0 || modeFind(p, azArg[i+1])<0)
3047430670
){
@@ -30517,19 +30713,10 @@
3051730713
p->mode.spec.eText = QRF_TEXT_Plain;
3051830714
p->mode.spec.eBlob = QRF_BLOB_Text;
3051930715
break;
3052030716
}
3052130717
chng = 1;
30522
- }else if( optionMatch(z,"once") ){
30523
- p->nPopMode = 0;
30524
- modePush(p);
30525
- p->nPopMode = 1;
30526
- }else if( optionMatch(z,"noquote") ){
30527
- /* (undocumented legacy) --noquote always turns quoting off */
30528
- p->mode.spec.eText = QRF_TEXT_Plain;
30529
- p->mode.spec.eBlob = QRF_BLOB_Text;
30530
- chng = 1;
3053130718
}else if( optionMatch(z,"reset") ){
3053230719
int saved_eMode = p->mode.eMode;
3053330720
modeFree(&p->mode);
3053430721
modeChange(p, saved_eMode);
3053530722
}else if( optionMatch(z,"screenwidth") ){
@@ -31077,13 +31264,14 @@
3107731264
3107831265
dotCmdOutput_error:
3107931266
sqlite3_free(zFile);
3108031267
return 1;
3108131268
}
31269
+
3108231270
/*
31083
-** Parse input line zLine up into individual arguments. Retain the
31084
-** parse in the p->dot substructure.
31271
+** Enlarge the space allocated in p->dot so that it can hold more
31272
+** than nArg parsed command-line arguments.
3108531273
*/
3108631274
static void parseDotRealloc(ShellState *p, int nArg){
3108731275
p->dot.nAlloc = nArg+22;
3108831276
p->dot.azArg = realloc(p->dot.azArg,p->dot.nAlloc*sizeof(char*));
3108931277
shell_check_oom(p->dot.azArg);
@@ -31090,19 +31278,33 @@
3109031278
p->dot.aiOfst = realloc(p->dot.aiOfst,p->dot.nAlloc*sizeof(int));
3109131279
shell_check_oom(p->dot.aiOfst);
3109231280
p->dot.abQuot = realloc(p->dot.abQuot,p->dot.nAlloc);
3109331281
shell_check_oom(p->dot.abQuot);
3109431282
}
31283
+
31284
+
31285
+/*
31286
+** Parse input line zLine up into individual arguments. Retain the
31287
+** parse in the p->dot substructure.
31288
+*/
3109531289
static void parseDotCmdArgs(const char *zLine, ShellState *p){
3109631290
char *z;
3109731291
int h = 1;
3109831292
int nArg = 0;
31293
+ size_t szLine;
3109931294
3110031295
p->dot.zOrig = zLine;
3110131296
free(p->dot.zCopy);
3110231297
z = p->dot.zCopy = strdup(zLine);
3110331298
shell_check_oom(z);
31299
+ szLine = strlen(z);
31300
+ while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31301
+ if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){
31302
+ szLine--;
31303
+ while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31304
+ }
31305
+ z[szLine] = 0;
3110431306
parseDotRealloc(p, 2);
3110531307
while( z[h] ){
3110631308
while( IsSpace(z[h]) ){ h++; }
3110731309
if( z[h]==0 ) break;
3110831310
if( nArg+2>p->dot.nAlloc ){
@@ -33406,16 +33608,15 @@
3340633608
3340733609
if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
3340833610
|| (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
3340933611
|| cli_strncmp(azArg[0], "indexes", n)==0) )
3341033612
){
33411
- sqlite3_stmt *pStmt;
33412
- char **azResult;
33413
- int nRow, nAlloc;
3341433613
int ii;
33415
- ShellText s;
33416
- initText(&s);
33614
+ sqlite3_stmt *pStmt;
33615
+ sqlite3_str *pSql;
33616
+ const char *zPattern = nArg>1 ? azArg[1] : 0;
33617
+
3341733618
open_db(p, 0);
3341833619
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
3341933620
if( rc ){
3342033621
sqlite3_finalize(pStmt);
3342133622
return shellDatabaseError(p->db);
@@ -33428,90 +33629,50 @@
3342833629
eputz("Usage: .indexes ?LIKE-PATTERN?\n");
3342933630
rc = 1;
3343033631
sqlite3_finalize(pStmt);
3343133632
goto meta_command_exit;
3343233633
}
33634
+ pSql = sqlite3_str_new(p->db);
3343333635
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
3343433636
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
3343533637
if( zDbName==0 ) continue;
33436
- if( s.zTxt && s.zTxt[0] ) appendText(&s, " UNION ALL ", 0);
33638
+ if( sqlite3_str_length(pSql) ){
33639
+ sqlite3_str_appendall(pSql, " UNION ALL ");
33640
+ }
3343733641
if( sqlite3_stricmp(zDbName, "main")==0 ){
33438
- appendText(&s, "SELECT name FROM ", 0);
33642
+ sqlite3_str_appendall(pSql, "SELECT name FROM ");
3343933643
}else{
33440
- appendText(&s, "SELECT ", 0);
33441
- appendText(&s, zDbName, '\'');
33442
- appendText(&s, "||'.'||name FROM ", 0);
33644
+ sqlite3_str_appendf(pSql, "SELECT %Q||'.'||name FROM ", zDbName);
3344333645
}
33444
- appendText(&s, zDbName, '"');
33445
- appendText(&s, ".sqlite_schema ", 0);
33646
+ sqlite3_str_appendf(pSql, "\"%w\".sqlite_schema", zDbName);
3344633647
if( c=='t' ){
33447
- appendText(&s," WHERE type IN ('table','view')"
33448
- " AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
33449
- " AND name LIKE ?1", 0);
33648
+ sqlite3_str_appendf(pSql,
33649
+ " WHERE type IN ('table','view')"
33650
+ " AND name NOT LIKE 'sqlite__%%' ESCAPE '_'"
33651
+ );
33652
+ if( zPattern ){
33653
+ sqlite3_str_appendf(pSql," AND name LIKE %Q", zPattern);
33654
+ }
3345033655
}else{
33451
- appendText(&s," WHERE type='index'"
33452
- " AND tbl_name LIKE ?1", 0);
33656
+ sqlite3_str_appendf(pSql, " WHERE type='index'");
33657
+ if( zPattern ){
33658
+ sqlite3_str_appendf(pSql," AND tbl_name LIKE %Q", zPattern);
33659
+ }
3345333660
}
3345433661
}
3345533662
rc = sqlite3_finalize(pStmt);
3345633663
if( rc==SQLITE_OK ){
33457
- appendText(&s, " ORDER BY 1", 0);
33458
- rc = sqlite3_prepare_v2(p->db, s.zTxt, -1, &pStmt, 0);
33459
- }
33460
- freeText(&s);
33461
- if( rc ) return shellDatabaseError(p->db);
33462
-
33463
- /* Run the SQL statement prepared by the above block. Store the results
33464
- ** as an array of nul-terminated strings in azResult[]. */
33465
- nRow = nAlloc = 0;
33466
- azResult = 0;
33467
- if( nArg>1 ){
33468
- sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
33469
- }else{
33470
- sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
33471
- }
33472
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
33473
- if( nRow>=nAlloc ){
33474
- char **azNew;
33475
- sqlite3_int64 n2 = 2*(sqlite3_int64)nAlloc + 10;
33476
- azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
33477
- shell_check_oom(azNew);
33478
- nAlloc = (int)n2;
33479
- azResult = azNew;
33480
- }
33481
- azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
33482
- shell_check_oom(azResult[nRow]);
33483
- nRow++;
33484
- }
33485
- if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
33486
- rc = shellDatabaseError(p->db);
33487
- }
33488
-
33489
- /* Pretty-print the contents of array azResult[] to the output */
33490
- if( rc==0 && nRow>0 ){
33491
- int len, maxlen = 0;
33492
- int i, j;
33493
- int nPrintCol, nPrintRow;
33494
- for(i=0; i<nRow; i++){
33495
- len = strlen30(azResult[i]);
33496
- if( len>maxlen ) maxlen = len;
33497
- }
33498
- nPrintCol = shellScreenWidth()/(maxlen+2);
33499
- if( nPrintCol<1 ) nPrintCol = 1;
33500
- nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
33501
- for(i=0; i<nPrintRow; i++){
33502
- for(j=i; j<nRow; j+=nPrintRow){
33503
- char *zSp = j<nPrintRow ? "" : " ";
33504
- cli_printf(p->out,
33505
- "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
33506
- }
33507
- cli_puts("\n", p->out);
33508
- }
33509
- }
33510
-
33511
- for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
33512
- sqlite3_free(azResult);
33664
+ sqlite3_str_appendall(pSql, " ORDER BY 1");
33665
+ }
33666
+
33667
+ /* Run the SQL statement in "split" mode. */
33668
+ modePush(p);
33669
+ modeChange(p, MODE_Split);
33670
+ shell_exec(p, sqlite3_str_value(pSql), 0);
33671
+ sqlite3_str_free(pSql);
33672
+ modePop(p);
33673
+ if( rc ) return shellDatabaseError(p->db);
3351333674
}else
3351433675
3351533676
#ifndef SQLITE_SHELL_FIDDLE
3351633677
/* Begin redirecting output to the file "testcase-out.txt" */
3351733678
if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
@@ -35635,10 +35796,20 @@
3563535796
}
3563635797
sqlite3_free(zErrMsg);
3563735798
if( rc==0 ) rc = 1;
3563835799
goto shell_main_exit;
3563935800
}
35801
+ if( data.nPopMode ){
35802
+ modePop(&data);
35803
+ data.nPopMode = 0;
35804
+ }
35805
+ }
35806
+ if( data.nPopOutput ){
35807
+ output_reset(&data);
35808
+ data.nPopOutput = 0;
35809
+ }else{
35810
+ clearTempFile(&data);
3564035811
}
3564135812
}
3564235813
}else{
3564335814
/* Run commands received from standard input
3564435815
*/
3564535816
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -681,10 +681,13 @@
681 ** Header file for the Result-Format or "resfmt" utility library for SQLite.
682 ** See the resfmt.md documentation for additional information.
683 */
684 #ifndef SQLITE_QRF_H
685 #define SQLITE_QRF_H
 
 
 
686 #include <stdlib.h>
687 /* #include "sqlite3.h" */
688
689 /*
690 ** Specification used by clients to define the output format they want
@@ -701,10 +704,11 @@
701 unsigned char bWordWrap; /* Try to wrap on word boundaries */
702 unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
703 unsigned char bTextNull; /* Apply eText encoding to zNull[] */
704 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
705 unsigned char eTitleAlign; /* Alignment for column headers */
 
706 short int nWrap; /* Wrap columns wider than this */
707 short int nScreenWidth; /* Maximum overall table width */
708 short int nLineLimit; /* Maximum number of lines for any row */
709 int nCharLimit; /* Maximum number of characters in a cell */
710 int nWidth; /* Number of entries in aWidth[] */
@@ -846,12 +850,13 @@
846 ** Unfortunately, there is nothing we can do about that.
847 */
848 int sqlite3_qrf_wcwidth(int c);
849
850
851
852
 
853 #endif /* !defined(SQLITE_QRF_H) */
854
855 /************************* End ext/qrf/qrf.h ********************/
856 /************************* Begin ext/qrf/qrf.c ******************/
857 /*
@@ -1895,10 +1900,21 @@
1895 sqlite3_str_append(pOut, "...", 3);
1896 }
1897 }
1898 #endif
1899 }
 
 
 
 
 
 
 
 
 
 
 
1900
1901 /*
1902 ** Store string zUtf to pOut as w characters. If w is negative,
1903 ** then right-justify the text. W is the width in display characters, not
1904 ** in bytes. Double-width unicode characters count as two characters.
@@ -2305,10 +2321,135 @@
2305 (pData->a[i].e & QRF_ALIGN_VMASK);
2306 }
2307 }
2308 }
2309 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2310
2311 /*
2312 ** Adjust the layout for the screen width restriction
2313 */
2314 static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){
@@ -2395,10 +2536,11 @@
2395 int rc; /* Result code */
2396 int nColumn = p->nCol; /* Number of columns */
2397 int bWW; /* True to do word-wrap */
2398 sqlite3_str *pStr; /* Temporary rendering */
2399 qrfColData data; /* Columnar layout data */
 
2400
2401 rc = sqlite3_step(p->pStmt);
2402 if( rc!=SQLITE_ROW || nColumn==0 ){
2403 return; /* No output */
2404 }
@@ -2504,12 +2646,26 @@
2504 }
2505 }
2506 data.a[i].w = w;
2507 }
2508
2509 /* Adjust the column widths due to screen width restrictions */
2510 qrfRestrictScreenWidth(&data, p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2511
2512 /* Draw the line across the top of the table. Also initialize
2513 ** the row boundary and column separator texts. */
2514 switch( p->spec.eStyle ){
2515 case QRF_STYLE_Box:
@@ -2536,11 +2692,17 @@
2536 }
2537 qrfRowSeparator(p->pOut, &data, '+');
2538 break;
2539 case QRF_STYLE_Column:
2540 rowStart = "";
2541 colSep = data.nMargin ? " " : " ";
 
 
 
 
 
 
2542 rowSep = "\n";
2543 break;
2544 default: /*case QRF_STYLE_Markdown:*/
2545 if( data.nMargin ){
2546 rowStart = "| ";
@@ -2556,10 +2718,11 @@
2556 szRowStart = (int)strlen(rowStart);
2557 szRowSep = (int)strlen(rowSep);
2558 szColSep = (int)strlen(colSep);
2559
2560 bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
 
2561 for(i=0; i<data.n; i+=nColumn){
2562 int bMore;
2563 int nRow = 0;
2564
2565 /* Draw a single row of the table. This might be the title line
@@ -2577,14 +2740,17 @@
2577 int nWS;
2578 qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
2579 nWS = data.a[j].w - nWide;
2580 qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
2581 data.a[j].z += iNext;
2582 if( data.a[j].z[0]!=0 ) bMore = 1;
 
 
2583 if( j<nColumn-1 ){
2584 sqlite3_str_append(p->pOut, colSep, szColSep);
2585 }else{
 
2586 sqlite3_str_append(p->pOut, rowSep, szRowSep);
2587 }
2588 }
2589 }while( bMore && ++nRow < p->mxHeight );
2590 if( bMore ){
@@ -2599,10 +2765,11 @@
2599 qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
2600 }
2601 if( j<nColumn-1 ){
2602 sqlite3_str_append(p->pOut, colSep, szColSep);
2603 }else{
 
2604 sqlite3_str_append(p->pOut, rowSep, szRowSep);
2605 }
2606 }
2607 }
2608
@@ -2639,14 +2806,16 @@
2639 for(j=0; j<nColumn; j++){
2640 sqlite3_str_appendchar(p->pOut, data.a[j].w, '-');
2641 if( j<nColumn-1 ){
2642 sqlite3_str_append(p->pOut, colSep, szColSep);
2643 }else{
 
2644 sqlite3_str_append(p->pOut, rowSep, szRowSep);
2645 }
2646 }
2647 }else if( data.bMultiRow ){
 
2648 sqlite3_str_append(p->pOut, "\n", 1);
2649 }
2650 break;
2651 }
2652 }
@@ -23946,16 +24115,17 @@
23946 #define MODE_List 12 /* One record per line with a separator */
23947 #define MODE_Markdown 13 /* Markdown formatting */
23948 #define MODE_Off 14 /* No query output shown */
23949 #define MODE_QBox 15 /* BOX with SQL-quoted content */
23950 #define MODE_Quote 16 /* Quote values as for SQL */
23951 #define MODE_Table 17 /* MySQL-style table formatting */
23952 #define MODE_Tabs 18 /* Tab-separated values */
23953 #define MODE_Tcl 19 /* Space-separated list of TCL strings */
23954 #define MODE_Www 20 /* Full web-page output */
 
23955
23956 #define MODE_BUILTIN 20 /* Maximum built-in mode */
23957 #define MODE_BATCH 50 /* Default mode for batch processing */
23958 #define MODE_TTY 51 /* Default mode for interactive processing */
23959 #define MODE_USER 75 /* First user-defined mode */
23960 #define MODE_N_USER 25 /* Maximum number of user-defined modes */
23961
@@ -24000,10 +24170,11 @@
24000 { "list", 2, 1, 9, 1, 1, 1, 1, 12, 0 },
24001 { "markdown", 0, 0, 9, 1, 1, 1, 2, 13, 2 },
24002 { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
24003 { "qbox", 0, 0, 9, 2, 1, 2, 2, 1, 2 },
24004 { "quote", 4, 1, 10, 2, 2, 2, 1, 12, 0 },
 
24005 { "table", 0, 0, 9, 1, 1, 1, 2, 19, 2 },
24006 { "tabs", 8, 1, 9, 3, 3, 1, 1, 12, 0 },
24007 { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
24008 { "www", 0, 0, 9, 4, 4, 1, 2, 7, 0 }
24009 }; /* | / / | / / | | \
@@ -24128,10 +24299,16 @@
24128 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24129 pM->spec.eText = pI->eText;
24130 pM->spec.eBlob = pI->eBlob;
24131 pM->spec.bTitles = pI->bHdr;
24132 pM->spec.eTitle = pI->eHdr;
 
 
 
 
 
 
24133 }else if( eMode>=MODE_USER && eMode-MODE_USER<p->nSavedModes ){
24134 modeFree(&p->mode);
24135 modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
24136 }else if( eMode==MODE_BATCH ){
24137 u8 mFlags = p->mode.mFlags;
@@ -26441,10 +26618,12 @@
26441 " --linelimit N Set the maximum number of output lines to show for\n"
26442 " any single SQL value to N. Longer values are\n"
26443 " truncated. Zero means \"no limit\". Only works\n"
26444 " in \"line\" mode and in columnar modes.\n"
26445 " --list List available modes\n"
 
 
26446 " --null STRING Render SQL NULL values as the given string\n"
26447 " --once Setting changes to the right are reverted after\n"
26448 " the next SQL command.\n"
26449 " --quote ARG Enable/disable quoting of text. ARG can be\n"
26450 " \"off\", \"on\", \"sql\", \"csv\", \"html\", \"tcl\",\n"
@@ -30320,10 +30499,12 @@
30320 ** --linelimit N Set the maximum number of output lines to show for
30321 ** any single SQL value to N. Longer values are
30322 ** truncated. Zero means "no limit". Only works
30323 ** in "line" mode and in columnar modes.
30324 ** --list List available modes
 
 
30325 ** --null STRING Render SQL NULL values as the given string
30326 ** --once Setting changes to the right are reverted after
30327 ** the next SQL command.
30328 ** --quote ARG Enable/disable quoting of text. ARG can be
30329 ** "off", "on", "sql", "csv", "html", "tcl",
@@ -30465,10 +30646,25 @@
30465 }
30466 for(ii=0; ii<p->nSavedModes; ii++){
30467 cli_printf(p->out, " %s", p->aSavedModes[ii].zTag);
30468 }
30469 cli_puts(" batch tty\n", p->out);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30470 }else if( optionMatch(z,"quote") ){
30471 if( i+1<nArg
30472 && azArg[i+1][0]!='-'
30473 && (iMode>0 || strcmp(azArg[i+1],"off")==0 || modeFind(p, azArg[i+1])<0)
30474 ){
@@ -30517,19 +30713,10 @@
30517 p->mode.spec.eText = QRF_TEXT_Plain;
30518 p->mode.spec.eBlob = QRF_BLOB_Text;
30519 break;
30520 }
30521 chng = 1;
30522 }else if( optionMatch(z,"once") ){
30523 p->nPopMode = 0;
30524 modePush(p);
30525 p->nPopMode = 1;
30526 }else if( optionMatch(z,"noquote") ){
30527 /* (undocumented legacy) --noquote always turns quoting off */
30528 p->mode.spec.eText = QRF_TEXT_Plain;
30529 p->mode.spec.eBlob = QRF_BLOB_Text;
30530 chng = 1;
30531 }else if( optionMatch(z,"reset") ){
30532 int saved_eMode = p->mode.eMode;
30533 modeFree(&p->mode);
30534 modeChange(p, saved_eMode);
30535 }else if( optionMatch(z,"screenwidth") ){
@@ -31077,13 +31264,14 @@
31077
31078 dotCmdOutput_error:
31079 sqlite3_free(zFile);
31080 return 1;
31081 }
 
31082 /*
31083 ** Parse input line zLine up into individual arguments. Retain the
31084 ** parse in the p->dot substructure.
31085 */
31086 static void parseDotRealloc(ShellState *p, int nArg){
31087 p->dot.nAlloc = nArg+22;
31088 p->dot.azArg = realloc(p->dot.azArg,p->dot.nAlloc*sizeof(char*));
31089 shell_check_oom(p->dot.azArg);
@@ -31090,19 +31278,33 @@
31090 p->dot.aiOfst = realloc(p->dot.aiOfst,p->dot.nAlloc*sizeof(int));
31091 shell_check_oom(p->dot.aiOfst);
31092 p->dot.abQuot = realloc(p->dot.abQuot,p->dot.nAlloc);
31093 shell_check_oom(p->dot.abQuot);
31094 }
 
 
 
 
 
 
31095 static void parseDotCmdArgs(const char *zLine, ShellState *p){
31096 char *z;
31097 int h = 1;
31098 int nArg = 0;
 
31099
31100 p->dot.zOrig = zLine;
31101 free(p->dot.zCopy);
31102 z = p->dot.zCopy = strdup(zLine);
31103 shell_check_oom(z);
 
 
 
 
 
 
 
31104 parseDotRealloc(p, 2);
31105 while( z[h] ){
31106 while( IsSpace(z[h]) ){ h++; }
31107 if( z[h]==0 ) break;
31108 if( nArg+2>p->dot.nAlloc ){
@@ -33406,16 +33608,15 @@
33406
33407 if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
33408 || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
33409 || cli_strncmp(azArg[0], "indexes", n)==0) )
33410 ){
33411 sqlite3_stmt *pStmt;
33412 char **azResult;
33413 int nRow, nAlloc;
33414 int ii;
33415 ShellText s;
33416 initText(&s);
 
 
33417 open_db(p, 0);
33418 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
33419 if( rc ){
33420 sqlite3_finalize(pStmt);
33421 return shellDatabaseError(p->db);
@@ -33428,90 +33629,50 @@
33428 eputz("Usage: .indexes ?LIKE-PATTERN?\n");
33429 rc = 1;
33430 sqlite3_finalize(pStmt);
33431 goto meta_command_exit;
33432 }
 
33433 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
33434 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
33435 if( zDbName==0 ) continue;
33436 if( s.zTxt && s.zTxt[0] ) appendText(&s, " UNION ALL ", 0);
 
 
33437 if( sqlite3_stricmp(zDbName, "main")==0 ){
33438 appendText(&s, "SELECT name FROM ", 0);
33439 }else{
33440 appendText(&s, "SELECT ", 0);
33441 appendText(&s, zDbName, '\'');
33442 appendText(&s, "||'.'||name FROM ", 0);
33443 }
33444 appendText(&s, zDbName, '"');
33445 appendText(&s, ".sqlite_schema ", 0);
33446 if( c=='t' ){
33447 appendText(&s," WHERE type IN ('table','view')"
33448 " AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
33449 " AND name LIKE ?1", 0);
 
 
 
 
33450 }else{
33451 appendText(&s," WHERE type='index'"
33452 " AND tbl_name LIKE ?1", 0);
 
 
33453 }
33454 }
33455 rc = sqlite3_finalize(pStmt);
33456 if( rc==SQLITE_OK ){
33457 appendText(&s, " ORDER BY 1", 0);
33458 rc = sqlite3_prepare_v2(p->db, s.zTxt, -1, &pStmt, 0);
33459 }
33460 freeText(&s);
33461 if( rc ) return shellDatabaseError(p->db);
33462
33463 /* Run the SQL statement prepared by the above block. Store the results
33464 ** as an array of nul-terminated strings in azResult[]. */
33465 nRow = nAlloc = 0;
33466 azResult = 0;
33467 if( nArg>1 ){
33468 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
33469 }else{
33470 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
33471 }
33472 while( sqlite3_step(pStmt)==SQLITE_ROW ){
33473 if( nRow>=nAlloc ){
33474 char **azNew;
33475 sqlite3_int64 n2 = 2*(sqlite3_int64)nAlloc + 10;
33476 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
33477 shell_check_oom(azNew);
33478 nAlloc = (int)n2;
33479 azResult = azNew;
33480 }
33481 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
33482 shell_check_oom(azResult[nRow]);
33483 nRow++;
33484 }
33485 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
33486 rc = shellDatabaseError(p->db);
33487 }
33488
33489 /* Pretty-print the contents of array azResult[] to the output */
33490 if( rc==0 && nRow>0 ){
33491 int len, maxlen = 0;
33492 int i, j;
33493 int nPrintCol, nPrintRow;
33494 for(i=0; i<nRow; i++){
33495 len = strlen30(azResult[i]);
33496 if( len>maxlen ) maxlen = len;
33497 }
33498 nPrintCol = shellScreenWidth()/(maxlen+2);
33499 if( nPrintCol<1 ) nPrintCol = 1;
33500 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
33501 for(i=0; i<nPrintRow; i++){
33502 for(j=i; j<nRow; j+=nPrintRow){
33503 char *zSp = j<nPrintRow ? "" : " ";
33504 cli_printf(p->out,
33505 "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
33506 }
33507 cli_puts("\n", p->out);
33508 }
33509 }
33510
33511 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
33512 sqlite3_free(azResult);
33513 }else
33514
33515 #ifndef SQLITE_SHELL_FIDDLE
33516 /* Begin redirecting output to the file "testcase-out.txt" */
33517 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
@@ -35635,10 +35796,20 @@
35635 }
35636 sqlite3_free(zErrMsg);
35637 if( rc==0 ) rc = 1;
35638 goto shell_main_exit;
35639 }
 
 
 
 
 
 
 
 
 
 
35640 }
35641 }
35642 }else{
35643 /* Run commands received from standard input
35644 */
35645
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -681,10 +681,13 @@
681 ** Header file for the Result-Format or "resfmt" utility library for SQLite.
682 ** See the resfmt.md documentation for additional information.
683 */
684 #ifndef SQLITE_QRF_H
685 #define SQLITE_QRF_H
686 #ifdef __cplusplus
687 extern "C" {
688 #endif
689 #include <stdlib.h>
690 /* #include "sqlite3.h" */
691
692 /*
693 ** Specification used by clients to define the output format they want
@@ -701,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 bTextNull; /* Apply eText encoding to zNull[] */
707 unsigned char eDfltAlign; /* Default alignment, no covered by aAlignment */
708 unsigned char eTitleAlign; /* Alignment for column headers */
709 unsigned char bSplitColumn; /* Wrap single-column output into many columns */
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[] */
@@ -846,12 +850,13 @@
850 ** Unfortunately, there is nothing we can do about that.
851 */
852 int sqlite3_qrf_wcwidth(int c);
853
854
855 #ifdef __cplusplus
856 }
857 #endif
858 #endif /* !defined(SQLITE_QRF_H) */
859
860 /************************* End ext/qrf/qrf.h ********************/
861 /************************* Begin ext/qrf/qrf.c ******************/
862 /*
@@ -1895,10 +1900,21 @@
1900 sqlite3_str_append(pOut, "...", 3);
1901 }
1902 }
1903 #endif
1904 }
1905
1906 /* Trim spaces of the end if pOut
1907 */
1908 static void qrfRTrim(sqlite3_str *pOut){
1909 #if SQLITE_VERSION_NUMBER>=3052000
1910 int nByte = sqlite3_str_length(pOut);
1911 const char *zOut = sqlite3_str_value(pOut);
1912 while( nByte>0 && zOut[nByte-1]==' ' ){ nByte--; }
1913 sqlite3_str_truncate(pOut, nByte);
1914 #endif
1915 }
1916
1917 /*
1918 ** Store string zUtf to pOut as w characters. If w is negative,
1919 ** then right-justify the text. W is the width in display characters, not
1920 ** in bytes. Double-width unicode characters count as two characters.
@@ -2305,10 +2321,135 @@
2321 (pData->a[i].e & QRF_ALIGN_VMASK);
2322 }
2323 }
2324 }
2325 }
2326
2327 /*
2328 ** If the single column in pData->a[] with pData->n entries can be
2329 ** laid out as nCol columns with a 2-space gap between each such
2330 ** that all columns fit within nSW, then return a pointer to an array
2331 ** of integers which is the width of each column from left to right.
2332 **
2333 ** If the layout is not possible, return a NULL pointer.
2334 **
2335 ** Space to hold the returned array is from sqlite_malloc64().
2336 */
2337 static int *qrfValidLayout(
2338 qrfColData *pData, /* Collected query results */
2339 Qrf *p, /* On which to report an OOM */
2340 int nCol, /* Attempt this many columns */
2341 int nSW /* Screen width */
2342 ){
2343 int i; /* Loop counter */
2344 int nr; /* Number of rows */
2345 int w = 0; /* Width of the current column */
2346 int t; /* Total width of all columns */
2347 int *aw; /* Array of individual column widths */
2348
2349 aw = sqlite3_malloc64( sizeof(int)*nCol );
2350 if( aw==0 ){
2351 qrfOom(p);
2352 return 0;
2353 }
2354 nr = (pData->n + nCol - 1)/nCol;
2355 for(i=0; i<pData->n; i++){
2356 if( (i%nr)==0 ){
2357 if( i>0 ) aw[i/nr-1] = w;
2358 w = pData->aiWth[i];
2359 }else if( pData->aiWth[i]>w ){
2360 w = pData->aiWth[i];
2361 }
2362 }
2363 aw[nCol-1] = w;
2364 for(t=i=0; i<nCol; i++) t += aw[i];
2365 t += 2*(nCol-1);
2366 if( t>nSW ){
2367 sqlite3_free(aw);
2368 return 0;
2369 }
2370 return aw;
2371 }
2372
2373 /*
2374 ** The output is single-column and the bSplitColumn flag is set.
2375 ** Check to see if the single-column output can be split into multiple
2376 ** columns that appear side-by-side. Adjust pData appropriately.
2377 */
2378 static void qrfSplitColumn(qrfColData *pData, Qrf *p){
2379 int nCol = 1;
2380 int *aw = 0;
2381 char **az = 0;
2382 int *aiWth = 0;
2383 int nColNext = 2;
2384 int w;
2385 struct qrfPerCol *a = 0;
2386 sqlite3_int64 nRow = 1;
2387 sqlite3_int64 i;
2388 while( 1/*exit-by-break*/ ){
2389 int *awNew = qrfValidLayout(pData, p, nColNext, p->spec.nScreenWidth);
2390 if( awNew==0 ) break;
2391 sqlite3_free(aw);
2392 aw = awNew;
2393 nCol = nColNext;
2394 nRow = (pData->n + nCol - 1)/nCol;
2395 if( nRow==1 ) break;
2396 nColNext++;
2397 while( (pData->n + nColNext - 1)/nColNext == nRow ) nColNext++;
2398 }
2399 if( nCol==1 ){
2400 sqlite3_free(aw);
2401 return; /* Cannot do better than 1 column */
2402 }
2403 az = sqlite3_malloc64( nRow*nCol*sizeof(char*) );
2404 if( az==0 ){
2405 qrfOom(p);
2406 return;
2407 }
2408 aiWth = sqlite3_malloc64( nRow*nCol*sizeof(int) );
2409 if( aiWth==0 ){
2410 sqlite3_free(az);
2411 qrfOom(p);
2412 return;
2413 }
2414 a = sqlite3_malloc64( nCol*sizeof(struct qrfPerCol) );
2415 if( a==0 ){
2416 sqlite3_free(az);
2417 sqlite3_free(aiWth);
2418 qrfOom(p);
2419 return;
2420 }
2421 for(i=0; i<pData->n; i++){
2422 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2423 az[j] = pData->az[i];
2424 pData->az[i] = 0;
2425 aiWth[j] = pData->aiWth[i];
2426 }
2427 while( i<nRow*nCol ){
2428 sqlite3_int64 j = (i%nRow)*nCol + (i/nRow);
2429 az[j] = sqlite3_mprintf("");
2430 if( az[j]==0 ) qrfOom(p);
2431 aiWth[j] = 0;
2432 i++;
2433 }
2434 for(i=0; i<nCol; i++){
2435 a[i].fx = a[i].mxW = a[i].w = aw[i];
2436 a[i].e = pData->a[0].e;
2437 }
2438 sqlite3_free(pData->az);
2439 sqlite3_free(pData->aiWth);
2440 sqlite3_free(pData->a);
2441 sqlite3_free(aw);
2442 pData->az = az;
2443 pData->aiWth = aiWth;
2444 pData->a = a;
2445 pData->nCol = nCol;
2446 pData->n = pData->nAlloc = nRow*nCol;
2447 for(i=w=0; i<nCol; i++) w += a[i].w;
2448 pData->nMargin = (p->spec.nScreenWidth - w)/(nCol - 1);
2449 if( pData->nMargin>5 ) pData->nMargin = 5;
2450 }
2451
2452 /*
2453 ** Adjust the layout for the screen width restriction
2454 */
2455 static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){
@@ -2395,10 +2536,11 @@
2536 int rc; /* Result code */
2537 int nColumn = p->nCol; /* Number of columns */
2538 int bWW; /* True to do word-wrap */
2539 sqlite3_str *pStr; /* Temporary rendering */
2540 qrfColData data; /* Columnar layout data */
2541 int bRTrim; /* Trim trailing space */
2542
2543 rc = sqlite3_step(p->pStmt);
2544 if( rc!=SQLITE_ROW || nColumn==0 ){
2545 return; /* No output */
2546 }
@@ -2504,12 +2646,26 @@
2646 }
2647 }
2648 data.a[i].w = w;
2649 }
2650
2651 if( nColumn==1
2652 && data.n>1
2653 && p->spec.bSplitColumn==QRF_Yes
2654 && p->spec.eStyle==QRF_STYLE_Column
2655 && p->spec.bTitles==QRF_No
2656 && p->spec.nScreenWidth>data.a[0].w+3
2657 ){
2658 /* Attempt to convert single-column tables into multi-column by
2659 ** verticle wrapping, if the screen is wide enough and if the
2660 ** bSplitColumn flag is set. */
2661 qrfSplitColumn(&data, p);
2662 nColumn = data.nCol;
2663 }else{
2664 /* Adjust the column widths due to screen width restrictions */
2665 qrfRestrictScreenWidth(&data, p);
2666 }
2667
2668 /* Draw the line across the top of the table. Also initialize
2669 ** the row boundary and column separator texts. */
2670 switch( p->spec.eStyle ){
2671 case QRF_STYLE_Box:
@@ -2536,11 +2692,17 @@
2692 }
2693 qrfRowSeparator(p->pOut, &data, '+');
2694 break;
2695 case QRF_STYLE_Column:
2696 rowStart = "";
2697 if( data.nMargin<2 ){
2698 colSep = " ";
2699 }else if( data.nMargin<=5 ){
2700 colSep = " " + (5-data.nMargin);
2701 }else{
2702 colSep = " ";
2703 }
2704 rowSep = "\n";
2705 break;
2706 default: /*case QRF_STYLE_Markdown:*/
2707 if( data.nMargin ){
2708 rowStart = "| ";
@@ -2556,10 +2718,11 @@
2718 szRowStart = (int)strlen(rowStart);
2719 szRowSep = (int)strlen(rowSep);
2720 szColSep = (int)strlen(colSep);
2721
2722 bWW = (p->spec.bWordWrap==QRF_Yes && data.bMultiRow);
2723 bRTrim = (p->spec.eStyle==QRF_STYLE_Column);
2724 for(i=0; i<data.n; i+=nColumn){
2725 int bMore;
2726 int nRow = 0;
2727
2728 /* Draw a single row of the table. This might be the title line
@@ -2577,14 +2740,17 @@
2740 int nWS;
2741 qrfWrapLine(data.a[j].z, data.a[j].w, bWW, &nThis, &nWide, &iNext);
2742 nWS = data.a[j].w - nWide;
2743 qrfPrintAligned(p->pOut, data.a[j].z, nThis, nWS, data.a[j].e);
2744 data.a[j].z += iNext;
2745 if( data.a[j].z[0]!=0 ){
2746 bMore = 1;
2747 }
2748 if( j<nColumn-1 ){
2749 sqlite3_str_append(p->pOut, colSep, szColSep);
2750 }else{
2751 if( bRTrim ) qrfRTrim(p->pOut);
2752 sqlite3_str_append(p->pOut, rowSep, szRowSep);
2753 }
2754 }
2755 }while( bMore && ++nRow < p->mxHeight );
2756 if( bMore ){
@@ -2599,10 +2765,11 @@
2765 qrfPrintAligned(p->pOut, "...", nE, data.a[j].w-nE, data.a[j].e);
2766 }
2767 if( j<nColumn-1 ){
2768 sqlite3_str_append(p->pOut, colSep, szColSep);
2769 }else{
2770 if( bRTrim ) qrfRTrim(p->pOut);
2771 sqlite3_str_append(p->pOut, rowSep, szRowSep);
2772 }
2773 }
2774 }
2775
@@ -2639,14 +2806,16 @@
2806 for(j=0; j<nColumn; j++){
2807 sqlite3_str_appendchar(p->pOut, data.a[j].w, '-');
2808 if( j<nColumn-1 ){
2809 sqlite3_str_append(p->pOut, colSep, szColSep);
2810 }else{
2811 qrfRTrim(p->pOut);
2812 sqlite3_str_append(p->pOut, rowSep, szRowSep);
2813 }
2814 }
2815 }else if( data.bMultiRow ){
2816 qrfRTrim(p->pOut);
2817 sqlite3_str_append(p->pOut, "\n", 1);
2818 }
2819 break;
2820 }
2821 }
@@ -23946,16 +24115,17 @@
24115 #define MODE_List 12 /* One record per line with a separator */
24116 #define MODE_Markdown 13 /* Markdown formatting */
24117 #define MODE_Off 14 /* No query output shown */
24118 #define MODE_QBox 15 /* BOX with SQL-quoted content */
24119 #define MODE_Quote 16 /* Quote values as for SQL */
24120 #define MODE_Split 17 /* Split-column mode */
24121 #define MODE_Table 18 /* MySQL-style table formatting */
24122 #define MODE_Tabs 19 /* Tab-separated values */
24123 #define MODE_Tcl 20 /* Space-separated list of TCL strings */
24124 #define MODE_Www 21 /* Full web-page output */
24125
24126 #define MODE_BUILTIN 21 /* Maximum built-in mode */
24127 #define MODE_BATCH 50 /* Default mode for batch processing */
24128 #define MODE_TTY 51 /* Default mode for interactive processing */
24129 #define MODE_USER 75 /* First user-defined mode */
24130 #define MODE_N_USER 25 /* Maximum number of user-defined modes */
24131
@@ -24000,10 +24170,11 @@
24170 { "list", 2, 1, 9, 1, 1, 1, 1, 12, 0 },
24171 { "markdown", 0, 0, 9, 1, 1, 1, 2, 13, 2 },
24172 { "off", 0, 0, 0, 0, 0, 0, 0, 14, 0 },
24173 { "qbox", 0, 0, 9, 2, 1, 2, 2, 1, 2 },
24174 { "quote", 4, 1, 10, 2, 2, 2, 1, 12, 0 },
24175 { "split", 0, 0, 9, 1, 1, 1, 1, 2, 2 },
24176 { "table", 0, 0, 9, 1, 1, 1, 2, 19, 2 },
24177 { "tabs", 8, 1, 9, 3, 3, 1, 1, 12, 0 },
24178 { "tcl", 3, 1, 12, 5, 5, 4, 1, 12, 0 },
24179 { "www", 0, 0, 9, 4, 4, 1, 2, 7, 0 }
24180 }; /* | / / | / / | | \
@@ -24128,10 +24299,16 @@
24299 if( pI->eNull ) modeSetStr(&pM->spec.zNull, aModeStr[pI->eNull]);
24300 pM->spec.eText = pI->eText;
24301 pM->spec.eBlob = pI->eBlob;
24302 pM->spec.bTitles = pI->bHdr;
24303 pM->spec.eTitle = pI->eHdr;
24304 if( eMode==MODE_Split ){
24305 pM->spec.bSplitColumn = QRF_Yes;
24306 pM->bAutoScreenWidth = 1;
24307 }else{
24308 pM->spec.bSplitColumn = QRF_No;
24309 }
24310 }else if( eMode>=MODE_USER && eMode-MODE_USER<p->nSavedModes ){
24311 modeFree(&p->mode);
24312 modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
24313 }else if( eMode==MODE_BATCH ){
24314 u8 mFlags = p->mode.mFlags;
@@ -26441,10 +26618,12 @@
26618 " --linelimit N Set the maximum number of output lines to show for\n"
26619 " any single SQL value to N. Longer values are\n"
26620 " truncated. Zero means \"no limit\". Only works\n"
26621 " in \"line\" mode and in columnar modes.\n"
26622 " --list List available modes\n"
26623 " --no-limits Shorthand to turn off --linelimit, --charlimit,\n"
26624 " and --screenwidth.\n"
26625 " --null STRING Render SQL NULL values as the given string\n"
26626 " --once Setting changes to the right are reverted after\n"
26627 " the next SQL command.\n"
26628 " --quote ARG Enable/disable quoting of text. ARG can be\n"
26629 " \"off\", \"on\", \"sql\", \"csv\", \"html\", \"tcl\",\n"
@@ -30320,10 +30499,12 @@
30499 ** --linelimit N Set the maximum number of output lines to show for
30500 ** any single SQL value to N. Longer values are
30501 ** truncated. Zero means "no limit". Only works
30502 ** in "line" mode and in columnar modes.
30503 ** --list List available modes
30504 ** --no-limits Shorthand to turn off --linelimit, --charlimit,
30505 ** and --screenwidth.
30506 ** --null STRING Render SQL NULL values as the given string
30507 ** --once Setting changes to the right are reverted after
30508 ** the next SQL command.
30509 ** --quote ARG Enable/disable quoting of text. ARG can be
30510 ** "off", "on", "sql", "csv", "html", "tcl",
@@ -30465,10 +30646,25 @@
30646 }
30647 for(ii=0; ii<p->nSavedModes; ii++){
30648 cli_printf(p->out, " %s", p->aSavedModes[ii].zTag);
30649 }
30650 cli_puts(" batch tty\n", p->out);
30651 }else if( optionMatch(z,"once") ){
30652 p->nPopMode = 0;
30653 modePush(p);
30654 p->nPopMode = 1;
30655 }else if( optionMatch(z,"noquote") ){
30656 /* (undocumented legacy) --noquote always turns quoting off */
30657 p->mode.spec.eText = QRF_TEXT_Plain;
30658 p->mode.spec.eBlob = QRF_BLOB_Text;
30659 chng = 1;
30660 }else if( optionMatch(z,"no-limits") ){
30661 p->mode.spec.nLineLimit = 0;
30662 p->mode.spec.nCharLimit = 0;
30663 p->mode.spec.nScreenWidth = 0;
30664 p->mode.bAutoScreenWidth = 0;
30665 chng = 1;
30666 }else if( optionMatch(z,"quote") ){
30667 if( i+1<nArg
30668 && azArg[i+1][0]!='-'
30669 && (iMode>0 || strcmp(azArg[i+1],"off")==0 || modeFind(p, azArg[i+1])<0)
30670 ){
@@ -30517,19 +30713,10 @@
30713 p->mode.spec.eText = QRF_TEXT_Plain;
30714 p->mode.spec.eBlob = QRF_BLOB_Text;
30715 break;
30716 }
30717 chng = 1;
 
 
 
 
 
 
 
 
 
30718 }else if( optionMatch(z,"reset") ){
30719 int saved_eMode = p->mode.eMode;
30720 modeFree(&p->mode);
30721 modeChange(p, saved_eMode);
30722 }else if( optionMatch(z,"screenwidth") ){
@@ -31077,13 +31264,14 @@
31264
31265 dotCmdOutput_error:
31266 sqlite3_free(zFile);
31267 return 1;
31268 }
31269
31270 /*
31271 ** Enlarge the space allocated in p->dot so that it can hold more
31272 ** than nArg parsed command-line arguments.
31273 */
31274 static void parseDotRealloc(ShellState *p, int nArg){
31275 p->dot.nAlloc = nArg+22;
31276 p->dot.azArg = realloc(p->dot.azArg,p->dot.nAlloc*sizeof(char*));
31277 shell_check_oom(p->dot.azArg);
@@ -31090,19 +31278,33 @@
31278 p->dot.aiOfst = realloc(p->dot.aiOfst,p->dot.nAlloc*sizeof(int));
31279 shell_check_oom(p->dot.aiOfst);
31280 p->dot.abQuot = realloc(p->dot.abQuot,p->dot.nAlloc);
31281 shell_check_oom(p->dot.abQuot);
31282 }
31283
31284
31285 /*
31286 ** Parse input line zLine up into individual arguments. Retain the
31287 ** parse in the p->dot substructure.
31288 */
31289 static void parseDotCmdArgs(const char *zLine, ShellState *p){
31290 char *z;
31291 int h = 1;
31292 int nArg = 0;
31293 size_t szLine;
31294
31295 p->dot.zOrig = zLine;
31296 free(p->dot.zCopy);
31297 z = p->dot.zCopy = strdup(zLine);
31298 shell_check_oom(z);
31299 szLine = strlen(z);
31300 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31301 if( szLine>0 && z[szLine-1]==';' && p->iCompat>=20251115 ){
31302 szLine--;
31303 while( szLine>0 && IsSpace(z[szLine-1]) ) szLine--;
31304 }
31305 z[szLine] = 0;
31306 parseDotRealloc(p, 2);
31307 while( z[h] ){
31308 while( IsSpace(z[h]) ){ h++; }
31309 if( z[h]==0 ) break;
31310 if( nArg+2>p->dot.nAlloc ){
@@ -33406,16 +33608,15 @@
33608
33609 if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
33610 || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
33611 || cli_strncmp(azArg[0], "indexes", n)==0) )
33612 ){
 
 
 
33613 int ii;
33614 sqlite3_stmt *pStmt;
33615 sqlite3_str *pSql;
33616 const char *zPattern = nArg>1 ? azArg[1] : 0;
33617
33618 open_db(p, 0);
33619 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
33620 if( rc ){
33621 sqlite3_finalize(pStmt);
33622 return shellDatabaseError(p->db);
@@ -33428,90 +33629,50 @@
33629 eputz("Usage: .indexes ?LIKE-PATTERN?\n");
33630 rc = 1;
33631 sqlite3_finalize(pStmt);
33632 goto meta_command_exit;
33633 }
33634 pSql = sqlite3_str_new(p->db);
33635 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
33636 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
33637 if( zDbName==0 ) continue;
33638 if( sqlite3_str_length(pSql) ){
33639 sqlite3_str_appendall(pSql, " UNION ALL ");
33640 }
33641 if( sqlite3_stricmp(zDbName, "main")==0 ){
33642 sqlite3_str_appendall(pSql, "SELECT name FROM ");
33643 }else{
33644 sqlite3_str_appendf(pSql, "SELECT %Q||'.'||name FROM ", zDbName);
 
 
33645 }
33646 sqlite3_str_appendf(pSql, "\"%w\".sqlite_schema", zDbName);
 
33647 if( c=='t' ){
33648 sqlite3_str_appendf(pSql,
33649 " WHERE type IN ('table','view')"
33650 " AND name NOT LIKE 'sqlite__%%' ESCAPE '_'"
33651 );
33652 if( zPattern ){
33653 sqlite3_str_appendf(pSql," AND name LIKE %Q", zPattern);
33654 }
33655 }else{
33656 sqlite3_str_appendf(pSql, " WHERE type='index'");
33657 if( zPattern ){
33658 sqlite3_str_appendf(pSql," AND tbl_name LIKE %Q", zPattern);
33659 }
33660 }
33661 }
33662 rc = sqlite3_finalize(pStmt);
33663 if( rc==SQLITE_OK ){
33664 sqlite3_str_appendall(pSql, " ORDER BY 1");
33665 }
33666
33667 /* Run the SQL statement in "split" mode. */
33668 modePush(p);
33669 modeChange(p, MODE_Split);
33670 shell_exec(p, sqlite3_str_value(pSql), 0);
33671 sqlite3_str_free(pSql);
33672 modePop(p);
33673 if( rc ) return shellDatabaseError(p->db);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33674 }else
33675
33676 #ifndef SQLITE_SHELL_FIDDLE
33677 /* Begin redirecting output to the file "testcase-out.txt" */
33678 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
@@ -35635,10 +35796,20 @@
35796 }
35797 sqlite3_free(zErrMsg);
35798 if( rc==0 ) rc = 1;
35799 goto shell_main_exit;
35800 }
35801 if( data.nPopMode ){
35802 modePop(&data);
35803 data.nPopMode = 0;
35804 }
35805 }
35806 if( data.nPopOutput ){
35807 output_reset(&data);
35808 data.nPopOutput = 0;
35809 }else{
35810 clearTempFile(&data);
35811 }
35812 }
35813 }else{
35814 /* Run commands received from standard input
35815 */
35816
--- 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
-** 8a230e4da230a7b103749b069a99a58e4c22 with changes in files:
21
+** 6d01f9f49eef5f7d4bddadc458691b6ca36e 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-21 17:30:44 8a230e4da230a7b103749b069a99a58e4c220873c2f9576abdc928c3538d70b3"
472
+#define SQLITE_SOURCE_ID "2025-11-23 10:55:38 6d01f9f49eef5f7d4bddadc458691b6ca36e277bae1d4b43b60a128a44e3faca"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2025-11-21T17:30:44.138Z"
475
+#define SQLITE_SCM_DATETIME "2025-11-23T10:55:38.669Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -261263,11 +261263,11 @@
261263261263
int nArg, /* Number of args */
261264261264
sqlite3_value **apUnused /* Function arguments */
261265261265
){
261266261266
assert( nArg==0 );
261267261267
UNUSED_PARAM2(nArg, apUnused);
261268
- sqlite3_result_text(pCtx, "fts5: 2025-11-21 17:30:44 8a230e4da230a7b103749b069a99a58e4c220873c2f9576abdc928c3538d70b3", -1, SQLITE_TRANSIENT);
261268
+ sqlite3_result_text(pCtx, "fts5: 2025-11-23 10:55:38 6d01f9f49eef5f7d4bddadc458691b6ca36e277bae1d4b43b60a128a44e3faca", -1, SQLITE_TRANSIENT);
261269261269
}
261270261270
261271261271
/*
261272261272
** Implementation of fts5_locale(LOCALE, TEXT) function.
261273261273
**
261274261274
--- 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 ** 8a230e4da230a7b103749b069a99a58e4c22 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-21 17:30:44 8a230e4da230a7b103749b069a99a58e4c220873c2f9576abdc928c3538d70b3"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2025-11-21T17:30:44.138Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -261263,11 +261263,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-21 17:30:44 8a230e4da230a7b103749b069a99a58e4c220873c2f9576abdc928c3538d70b3", -1, SQLITE_TRANSIENT);
261269 }
261270
261271 /*
261272 ** Implementation of fts5_locale(LOCALE, TEXT) function.
261273 **
261274
--- 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 ** 6d01f9f49eef5f7d4bddadc458691b6ca36e 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-23 10:55:38 6d01f9f49eef5f7d4bddadc458691b6ca36e277bae1d4b43b60a128a44e3faca"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2025-11-23T10:55:38.669Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -261263,11 +261263,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-23 10:55:38 6d01f9f49eef5f7d4bddadc458691b6ca36e277bae1d4b43b60a128a44e3faca", -1, SQLITE_TRANSIENT);
261269 }
261270
261271 /*
261272 ** Implementation of fts5_locale(LOCALE, TEXT) function.
261273 **
261274
--- 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-21 17:30:44 8a230e4da230a7b103749b069a99a58e4c220873c2f9576abdc928c3538d70b3"
151
+#define SQLITE_SOURCE_ID "2025-11-23 10:55:38 6d01f9f49eef5f7d4bddadc458691b6ca36e277bae1d4b43b60a128a44e3faca"
152152
#define SQLITE_SCM_BRANCH "trunk"
153153
#define SQLITE_SCM_TAGS ""
154
-#define SQLITE_SCM_DATETIME "2025-11-21T17:30:44.138Z"
154
+#define SQLITE_SCM_DATETIME "2025-11-23T10:55:38.669Z"
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-21 17:30:44 8a230e4da230a7b103749b069a99a58e4c220873c2f9576abdc928c3538d70b3"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2025-11-21T17:30:44.138Z"
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-23 10:55:38 6d01f9f49eef5f7d4bddadc458691b6ca36e277bae1d4b43b60a128a44e3faca"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2025-11-23T10:55:38.669Z"
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