Fossil SCM

Incorporate the latest SQLite updates. Improvements to prompt expansion in the "fossil sql" command.

drh 2026-04-23 16:42 UTC trunk
Commit 9b67f462f1e8437789ea8dc449a505fb3590c0adaab20018db9ea207626af0b4
+1114 -70
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,10 +5,11 @@
55
**
66
** ext/expert/sqlite3expert.c
77
** ext/expert/sqlite3expert.h
88
** ext/intck/sqlite3intck.c
99
** ext/intck/sqlite3intck.h
10
+** ext/misc/analyze.c
1011
** ext/misc/appendvfs.c
1112
** ext/misc/base64.c
1213
** ext/misc/base85.c
1314
** ext/misc/completion.c
1415
** ext/misc/decimal.c
@@ -1305,11 +1306,10 @@
13051306
}
13061307
}
13071308
if( nRow>=0 ){
13081309
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
13091310
qrfApproxInt64(pStats, nRow);
1310
- nSp = 2;
13111311
if( p->spec.eStyle==QRF_STYLE_StatsEst ){
13121312
sqlite3_str_appendf(pStats, " ");
13131313
qrfApproxInt64(pStats, (i64)rEstCum);
13141314
}
13151315
}
@@ -1595,44 +1595,43 @@
15951595
if( pnNL ) *pnNL = nNL;
15961596
return n;
15971597
}
15981598
15991599
/*
1600
-** Escape the input string if it is needed and in accordance with
1601
-** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
1600
+** Escape the text starting at byte iStart of pStr, if needed, using the
1601
+** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
1602
+** The pStr string is modified appropriately.
16021603
**
16031604
** Escaping is needed if the string contains any control characters
16041605
** other than \t, \n, and \r\n
16051606
**
1606
-** If no escaping is needed (the common case) then set *ppOut to NULL
1607
-** and return 0. If escaping is needed, write the escaped string into
1608
-** memory obtained from sqlite3_malloc64() and make *ppOut point to that
1609
-** memory and return 0. If an error occurs, return non-zero.
1610
-**
1611
-** The caller is responsible for freeing *ppFree if it is non-NULL in order
1612
-** to reclaim memory.
1607
+** If no escaping is needed (the common case) then pStr is unchanged.
1608
+** If escaping is required, then pStr is expanded and modified to hold
1609
+** an escaped representation of the text.
16131610
*/
16141611
static void qrfEscape(
16151612
int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
16161613
sqlite3_str *pStr, /* String to be escaped */
16171614
int iStart /* Begin escapding on this byte of pStr */
16181615
){
16191616
sqlite3_int64 i, j; /* Loop counters */
1620
- sqlite3_int64 sz; /* Size of the string prior to escaping */
16211617
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
16221618
unsigned char *zIn; /* Text to be escaped */
1619
+ unsigned int nIn; /* Bytes of text to be escaped */
16231620
unsigned char c; /* A single character of the text */
16241621
unsigned char *zOut; /* Where to write the results */
16251622
16261623
/* Find the text to be escaped */
16271624
zIn = (unsigned char*)sqlite3_str_value(pStr);
1625
+ nIn = sqlite3_str_length(pStr);
16281626
if( zIn==0 ) return;
16291627
zIn += iStart;
1628
+ nIn -= iStart;
16301629
16311630
/* Count the control characters */
1632
- for(i=0; (c = zIn[i])!=0; i++){
1633
- if( c<=0x1f
1631
+ for(i=0; i<nIn; i++){
1632
+ if( (c = zIn[i])<=0x1f
16341633
&& c!='\t'
16351634
&& c!='\n'
16361635
&& (c!='\r' || zIn[i+1]!='\n')
16371636
){
16381637
nCtrl++;
@@ -1640,22 +1639,21 @@
16401639
}
16411640
if( nCtrl==0 ) return; /* Early out if no control characters */
16421641
16431642
/* Make space to hold the escapes. Copy the original text to the end
16441643
** of the available space. */
1645
- sz = sqlite3_str_length(pStr) - iStart;
16461644
if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
16471645
sqlite3_str_appendchar(pStr, nCtrl, ' ');
16481646
zOut = (unsigned char*)sqlite3_str_value(pStr);
16491647
if( zOut==0 ) return;
16501648
zOut += iStart;
16511649
zIn = zOut + nCtrl;
1652
- memmove(zIn,zOut,sz);
1650
+ memmove(zIn,zOut,nIn);
16531651
16541652
/* Convert the control characters */
1655
- for(i=j=0; (c = zIn[i])!=0; i++){
1656
- if( c>0x1f
1653
+ for(i=j=0; i<nIn; i++){
1654
+ if( (c = zIn[i])>0x1f
16571655
|| c=='\t'
16581656
|| c=='\n'
16591657
|| (c=='\r' && zIn[i+1]=='\n')
16601658
){
16611659
continue;
@@ -1663,10 +1661,11 @@
16631661
if( i>0 ){
16641662
memmove(&zOut[j], zIn, i);
16651663
j += i;
16661664
}
16671665
zIn += i+1;
1666
+ nIn -= i+1;
16681667
i = -1;
16691668
if( eEsc==QRF_ESC_Symbol ){
16701669
zOut[j++] = 0xe2;
16711670
zOut[j++] = 0x90;
16721671
zOut[j++] = 0x80+c;
@@ -2065,12 +2064,26 @@
20652064
int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
20662065
sqlite3_str_appendf(pOut, "(%d-byte blob)", nBlob);
20672066
break;
20682067
}
20692068
default: {
2070
- const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
2071
- qrfEncodeText(p, pOut, zTxt);
2069
+ const void *pBlob = sqlite3_column_blob(p->pStmt,iCol);
2070
+ int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
2071
+ int rc;
2072
+ qrfWrite(p);
2073
+ if( nBlob==0 ){
2074
+ /* no-op */
2075
+ }else if( p->spec.eEsc==QRF_ESC_Off ){
2076
+ rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob);
2077
+ if( rc ){
2078
+ qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob);
2079
+ }
2080
+ }else{
2081
+ sqlite3_str_append(pOut, pBlob, nBlob);
2082
+ qrfEscape(p->spec.eEsc, pOut, 0);
2083
+ qrfWrite(p);
2084
+ }
20722085
}
20732086
}
20742087
break;
20752088
}
20762089
case SQLITE_NULL: {
@@ -6005,11 +6018,11 @@
60056018
}
60066019
if( p->isNull ){
60076020
sqlite3_result_null(pCtx);
60086021
return;
60096022
}
6010
- z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
6023
+ z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+8 );
60116024
if( z==0 ){
60126025
sqlite3_result_error_nomem(pCtx);
60136026
return;
60146027
}
60156028
i = 0;
@@ -9789,12 +9802,10 @@
97899802
/* # include "windirent.h" */
97909803
# include <direct.h>
97919804
# define STRUCT_STAT struct _stat
97929805
# define chmod(path,mode) fileio_chmod(path,mode)
97939806
# define mkdir(path,mode) fileio_mkdir(path)
9794
- extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
9795
- extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
97969807
#endif
97979808
#include <time.h>
97989809
#include <errno.h>
97999810
98009811
/* When used as part of the CLI, the sqlite3_stdio.h module will have
@@ -9817,17 +9828,73 @@
98179828
#define FSDIR_COLUMN_DATA 3 /* File content */
98189829
#define FSDIR_COLUMN_LEVEL 4 /* Level. Topmost is 1 */
98199830
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
98209831
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
98219832
9833
+#ifdef _WIN32
9834
+/*
9835
+** Convert a UTF-8 string to Microsoft Unicode.
9836
+**
9837
+** Space to hold the returned string is obtained from sqlite3_malloc().
9838
+*/
9839
+static wchar_t *winUtf8To16(const char *zText){
9840
+ int nChar;
9841
+ wchar_t *zWideText;
9842
+
9843
+ nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
9844
+ if( nChar==0 ){
9845
+ return 0;
9846
+ }
9847
+ zWideText = sqlite3_malloc64(nChar*sizeof(WCHAR) );
9848
+ if( zWideText==0 ){
9849
+ return 0;
9850
+ }
9851
+ nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
9852
+ nChar);
9853
+ if( nChar==0 ){
9854
+ sqlite3_free(zWideText);
9855
+ zWideText = 0;
9856
+ }
9857
+ return zWideText;
9858
+}
9859
+#endif /* _WIN32 */
9860
+
9861
+#ifdef _WIN32
9862
+/*
9863
+** Convert a Microsoft Unicode string to UTF-8.
9864
+**
9865
+** Space to hold the returned string is obtained from sqlite3_malloc().
9866
+*/
9867
+static char *winUtf16To8(wchar_t *zWideText){
9868
+ int nByte;
9869
+ char *zText;
9870
+
9871
+ nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
9872
+ if( nByte == 0 ){
9873
+ return 0;
9874
+ }
9875
+ zText = sqlite3_malloc64( nByte );
9876
+ if( zText==0 ){
9877
+ return 0;
9878
+ }
9879
+ nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
9880
+ 0, 0);
9881
+ if( nByte == 0 ){
9882
+ sqlite3_free(zText);
9883
+ zText = 0;
9884
+ }
9885
+ return zText;
9886
+}
9887
+#endif /* _WIN32 */
9888
+
98229889
/*
98239890
** UTF8 chmod() function for Windows
98249891
*/
98259892
#if defined(_WIN32) || defined(WIN32)
98269893
static int fileio_chmod(const char *zPath, int pmode){
98279894
int rc;
9828
- wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
9895
+ wchar_t *b1 = winUtf8To16(zPath);
98299896
if( b1==0 ) return -1;
98309897
rc = _wchmod(b1, pmode);
98319898
sqlite3_free(b1);
98329899
return rc;
98339900
}
@@ -9837,11 +9904,11 @@
98379904
** UTF8 mkdir() function for Windows
98389905
*/
98399906
#if defined(_WIN32) || defined(WIN32)
98409907
static int fileio_mkdir(const char *zPath){
98419908
int rc;
9842
- wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
9909
+ wchar_t *b1 = winUtf8To16(zPath);
98439910
if( b1==0 ) return -1;
98449911
rc = _wmkdir(b1);
98459912
sqlite3_free(b1);
98469913
return rc;
98479914
}
@@ -9964,11 +10031,11 @@
996410031
const char *zPath,
996510032
STRUCT_STAT *pStatBuf
996610033
){
996710034
#if defined(_WIN32)
996810035
int rc;
9969
- wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
10036
+ wchar_t *b1 = winUtf8To16(zPath);
997010037
if( b1==0 ) return 1;
997110038
rc = _wstat(b1, pStatBuf);
997210039
if( rc==0 ){
997310040
HANDLE hFindFile;
997410041
WIN32_FIND_DATAW fd;
@@ -10117,18 +10184,17 @@
1011710184
FILETIME lastWrite;
1011810185
SYSTEMTIME currentTime;
1011910186
LONGLONG intervals;
1012010187
HANDLE hFile;
1012110188
LPWSTR zUnicodeName;
10122
- extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
1012310189
1012410190
GetSystemTime(&currentTime);
1012510191
SystemTimeToFileTime(&currentTime, &lastAccess);
1012610192
intervals = (mtime*10000000) + 116444736000000000;
1012710193
lastWrite.dwLowDateTime = (DWORD)intervals;
1012810194
lastWrite.dwHighDateTime = intervals >> 32;
10129
- zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
10195
+ zUnicodeName = winUtf8To16(zFile);
1013010196
if( zUnicodeName==0 ){
1013110197
return 1;
1013210198
}
1013310199
hFile = CreateFileW(
1013410200
zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
@@ -10782,16 +10848,16 @@
1078210848
char *zOut = 0; /* Result */
1078310849
wchar_t *z = 0; /* Temporary buffer */
1078410850
1078510851
if( zPath==0 ) return 0;
1078610852
10787
- zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
10853
+ zPath16 = winUtf8To16(zPath);
1078810854
if( zPath16==0 ) return 0;
1078910855
z = _wfullpath(NULL, zPath16, 0);
1079010856
sqlite3_free(zPath16);
1079110857
if( z ){
10792
- zOut = sqlite3_win32_unicode_to_utf8(z);
10858
+ zOut = winUtf16To8(z);
1079310859
free(z);
1079410860
}
1079510861
return zOut;
1079610862
1079710863
#endif /* End WINDOWS, Begin common code */
@@ -19398,10 +19464,848 @@
1939819464
sqlite3_vfs_unregister(pVfs);
1939919465
sqlite3_free(pVfs);
1940019466
}
1940119467
1940219468
/************************* End ext/misc/vfstrace.c ********************/
19469
+/************************* Begin ext/misc/analyze.c ******************/
19470
+/*
19471
+** 2026-04-13
19472
+**
19473
+** The author disclaims copyright to this source code. In place of
19474
+** a legal notice, here is a blessing:
19475
+**
19476
+** May you do good and not evil.
19477
+** May you find forgiveness for yourself and forgive others.
19478
+** May you share freely, never taking more than you give.
19479
+**
19480
+******************************************************************************
19481
+**
19482
+** Partial reimplement of the sqlite3_analyzer utility program as
19483
+** loadable SQL function.
19484
+*/
19485
+/* #include "sqlite3ext.h" */
19486
+SQLITE_EXTENSION_INIT1
19487
+#include <assert.h>
19488
+#include <string.h>
19489
+#include <ctype.h>
19490
+#include <math.h>
19491
+
19492
+/*
19493
+** State information for the analysis
19494
+*/
19495
+typedef struct Analysis Analysis;
19496
+struct Analysis {
19497
+ sqlite3 *db; /* Database connection */
19498
+ sqlite3_context *context; /* SQL function context */
19499
+ sqlite3_str *pOut; /* Write output here */
19500
+ char *zSU; /* Name of the temp.space_used table */
19501
+ const char *zSchema; /* Schema to be analyzed */
19502
+};
19503
+
19504
+/*
19505
+** Free all resources that the Analysis object references and
19506
+** reset the Analysis object.
19507
+**
19508
+** Call this routine multiple times on the same Analysis object
19509
+** is a harmless no-op, as long as the memory for the object itself
19510
+** has not been freed.
19511
+*/
19512
+static void analysisReset(Analysis *p){
19513
+ if( p->zSU ){
19514
+ char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
19515
+ if( zSql ){
19516
+ sqlite3_exec(p->db, zSql, 0, 0, 0);
19517
+ sqlite3_free(zSql);
19518
+ }
19519
+ }
19520
+ sqlite3_str_free(p->pOut);
19521
+ sqlite3_free(p->zSU);
19522
+ memset(p, 0, sizeof(*p));
19523
+}
19524
+
19525
+/*
19526
+** Report an error using formatted text. If zFormat==NULL then report
19527
+** an OOM error.
19528
+*/
19529
+static void analysisError(Analysis *p, const char *zFormat, ...){
19530
+ char *zErr;
19531
+ if( zFormat ){
19532
+ va_list ap;
19533
+ va_start(ap, zFormat);
19534
+ zErr = sqlite3_vmprintf(zFormat, ap);
19535
+ va_end(ap);
19536
+ }else{
19537
+ zErr = 0;
19538
+ }
19539
+ if( zErr==0 ){
19540
+ sqlite3_result_error_nomem(p->context);
19541
+ }else{
19542
+ sqlite3_result_error(p->context, zErr, -1);
19543
+ sqlite3_free(zErr);
19544
+ }
19545
+ analysisReset(p);
19546
+}
19547
+
19548
+/*
19549
+** Prepare and return an SQL statement.
19550
+*/
19551
+static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
19552
+ char *zSql;
19553
+ int rc;
19554
+ sqlite3_stmt *pStmt = 0;
19555
+ zSql = sqlite3_vmprintf(zFmt, ap);
19556
+ if( zSql==0 ){ analysisError(p,0); return 0; }
19557
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19558
+ if( rc ){
19559
+ analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
19560
+ sqlite3_errmsg(p->db), zSql);
19561
+ sqlite3_finalize(pStmt);
19562
+ analysisReset(p);
19563
+ pStmt = 0;
19564
+ }
19565
+ sqlite3_free(zSql);
19566
+ return pStmt;
19567
+}
19568
+static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
19569
+ va_list ap;
19570
+ sqlite3_stmt *pStmt = 0;
19571
+ va_start(ap, zFormat);
19572
+ pStmt = analysisVPrep(p,zFormat,ap);
19573
+ va_end(ap);
19574
+ return pStmt;
19575
+}
19576
+
19577
+/*
19578
+** If rc is something other than SQLITE_DONE or SQLITE_OK, then report
19579
+** an error and return true.
19580
+**
19581
+** If rc is SQLITE_DONE or SQLITE_OK, then return false.
19582
+**
19583
+** The prepared statement is closed in either case.
19584
+*/
19585
+static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
19586
+ if( rc==SQLITE_DONE ){
19587
+ rc = SQLITE_OK;
19588
+ }
19589
+ if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19590
+ analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19591
+ sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19592
+ analysisReset(p);
19593
+ }
19594
+ sqlite3_finalize(pStmt);
19595
+ return rc;
19596
+}
19597
+
19598
+/*
19599
+** Run SQL. Return the number of errors.
19600
+*/
19601
+static int analysisSql(Analysis *p, const char *zFormat, ...){
19602
+ va_list ap;
19603
+ int rc;
19604
+ sqlite3_stmt *pStmt = 0;
19605
+ va_start(ap, zFormat);
19606
+ pStmt = analysisVPrep(p,zFormat,ap);
19607
+ va_end(ap);
19608
+ if( pStmt==0 ) return 1;
19609
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
19610
+ if( rc==SQLITE_DONE ){
19611
+ rc = SQLITE_OK;
19612
+ }else{
19613
+ analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19614
+ sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19615
+ analysisReset(p);
19616
+ }
19617
+ sqlite3_finalize(pStmt);
19618
+ return rc;
19619
+}
19620
+
19621
+/*
19622
+** Run an SQL query that returns an integer. Write that integer
19623
+** into *piRes. Return the number of errors.
19624
+*/
19625
+static int analysisSqlInt(
19626
+ Analysis *p,
19627
+ sqlite3_int64 *piRes,
19628
+ const char *zFormat, ...
19629
+){
19630
+ va_list ap;
19631
+ int rc;
19632
+ sqlite3_stmt *pStmt = 0;
19633
+ va_start(ap, zFormat);
19634
+ pStmt = analysisVPrep(p,zFormat,ap);
19635
+ va_end(ap);
19636
+ if( pStmt==0 ) return 1;
19637
+ rc = sqlite3_step(pStmt);
19638
+ if( rc==SQLITE_ROW ){
19639
+ *piRes = sqlite3_column_int64(pStmt, 0);
19640
+ rc = SQLITE_OK;
19641
+ }else if( rc==SQLITE_DONE ){
19642
+ rc = SQLITE_OK;
19643
+ }else{
19644
+ if( p->db ){
19645
+ /* p->db is NULL if there was some prior error */
19646
+ analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19647
+ sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19648
+ }
19649
+ analysisReset(p);
19650
+ }
19651
+ sqlite3_finalize(pStmt);
19652
+ return rc;
19653
+}
19654
+
19655
+/*
19656
+** Add to the output a title line that contains the text determined
19657
+** by the format string. If the output is initially empty, begin
19658
+** the title line with "/" so that it forms the beginning of a C-style
19659
+** comment. Otherwise begin with a new-line. Always finish with a
19660
+** newline.
19661
+*/
19662
+static void analysisTitle(Analysis *p, const char *zFormat, ...){
19663
+ char *zFirst;
19664
+ char *zTitle;
19665
+ size_t nTitle;
19666
+ va_list ap;
19667
+ va_start(ap, zFormat);
19668
+ zTitle = sqlite3_vmprintf(zFormat, ap);
19669
+ va_end(ap);
19670
+ if( zTitle==0 ){
19671
+ analysisError(p, 0);
19672
+ return;
19673
+ }
19674
+ zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
19675
+ nTitle = strlen(zTitle);
19676
+ if( nTitle>=75 ){
19677
+ sqlite3_str_appendf(p->pOut, "%s** %z\n\n", zFirst, zTitle);
19678
+ }else{
19679
+ int nExtra = 74 - (int)nTitle;
19680
+ sqlite3_str_appendf(p->pOut, "%s** %z %.*c\n\n", zFirst, zTitle,
19681
+ nExtra, '*');
19682
+ }
19683
+}
19684
+
19685
+/*
19686
+** Add an output line that begins with the zDesc text extended out to
19687
+** 50 columns with "." characters, and followed by whatever text is
19688
+** described by zFormat.
19689
+*/
19690
+static void analysisLine(
19691
+ Analysis *p, /* Analysis context */
19692
+ const char *zDesc, /* Description */
19693
+ const char *zFormat, /* Argument to the description */
19694
+ ...
19695
+){
19696
+ char *zTxt;
19697
+ size_t nDesc;
19698
+ va_list ap;
19699
+ va_start(ap, zFormat);
19700
+ zTxt = sqlite3_vmprintf(zFormat, ap);
19701
+ va_end(ap);
19702
+ if( zTxt==0 ){
19703
+ analysisError(p, 0);
19704
+ return;
19705
+ }
19706
+ nDesc = strlen(zDesc);
19707
+ if( nDesc>=50 ){
19708
+ sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
19709
+ }else{
19710
+ int nExtra = 50 - (int)nDesc;
19711
+ sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
19712
+ }
19713
+}
19714
+
19715
+/*
19716
+** Write a percentage into the output. The number written should show
19717
+** two or three significant digits, with the decimal point being the fourth
19718
+** character.
19719
+*/
19720
+static void analysisPercent(Analysis *p, double r){
19721
+ char zNum[100];
19722
+ char *zDP;
19723
+ int nLeadingDigit;
19724
+ int sz;
19725
+ sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
19726
+ sz = (int)strlen(zNum);
19727
+ zDP = strchr(zNum, '.');
19728
+ if( zDP==0 ){
19729
+ memcpy(zNum+sz,".0",3);
19730
+ nLeadingDigit = sz;
19731
+ sz += 2;
19732
+ }else{
19733
+ nLeadingDigit = (int)(zDP - zNum);
19734
+ }
19735
+ if( nLeadingDigit<3 ){
19736
+ sqlite3_str_appendchar(p->pOut, 3-nLeadingDigit, ' ');
19737
+ }
19738
+ sqlite3_str_append(p->pOut, zNum, sz);
19739
+ sqlite3_str_append(p->pOut, "%\n", 2);
19740
+}
19741
+
19742
+/*
19743
+** Create a subreport on a subset of tables and/or indexes.
19744
+**
19745
+** The title if the subreport is given by zTitle. zWhere is
19746
+** a boolean expression that can go in the WHERE clause to select
19747
+** the relevant rows of the s.zSU table.
19748
+*/
19749
+static int analysisSubreport(
19750
+ Analysis *p, /* Analysis context */
19751
+ char *zTitle, /* Title for this subreport */
19752
+ char *zWhere, /* WHERE clause for this subreport */
19753
+ sqlite3_int64 pgsz, /* Database page size */
19754
+ sqlite3_int64 nPage /* Number of pages in entire database */
19755
+){
19756
+ sqlite3_stmt *pStmt; /* Statement to query p->zSU */
19757
+ sqlite3_int64 nentry; /* Number of btree entires */
19758
+ sqlite3_int64 payload; /* Payload in bytes */
19759
+ sqlite3_int64 ovfl_payload; /* overflow payload in bytes */
19760
+ sqlite3_int64 mx_payload; /* largest individual payload */
19761
+ sqlite3_int64 ovfl_cnt; /* Number entries using overflow */
19762
+ sqlite3_int64 leaf_pages; /* Leaf pages */
19763
+ sqlite3_int64 int_pages; /* internal pages */
19764
+ sqlite3_int64 ovfl_pages; /* overflow pages */
19765
+ sqlite3_int64 leaf_unused; /* unused bytes on leaf pages */
19766
+ sqlite3_int64 int_unused; /* unused bytes on internal pages */
19767
+ sqlite3_int64 ovfl_unused; /* unused bytes on overflow pages */
19768
+ sqlite3_int64 int_cell; /* B-tree entries on internal pages */
19769
+ sqlite3_int64 depth; /* btree depth */
19770
+ sqlite3_int64 cnt; /* Number of s.zSU entries that match */
19771
+ sqlite3_int64 storage; /* Total bytes */
19772
+ sqlite3_int64 total_pages; /* Total page count */
19773
+ sqlite3_int64 total_unused; /* Total unused bytes */
19774
+ sqlite3_int64 total_meta; /* Total metadata */
19775
+ int rc;
19776
+
19777
+ if( zTitle==0 || zWhere==0 ){
19778
+ analysisError(p, 0);
19779
+ return SQLITE_NOMEM;
19780
+ }
19781
+ pStmt = analysisPrepare(p,
19782
+ "SELECT\n"
19783
+ " sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
19784
+ " sum(payload),\n" /* 1 */
19785
+ " sum(ovfl_payload),\n" /* 2 */
19786
+ " max(mx_payload),\n" /* 3 */
19787
+ " sum(ovfl_cnt),\n" /* 4 */
19788
+ " sum(leaf_pages),\n" /* 5 */
19789
+ " sum(int_pages),\n" /* 6 */
19790
+ " sum(ovfl_pages),\n" /* 7 */
19791
+ " sum(leaf_unused),\n" /* 8 */
19792
+ " sum(int_unused),\n" /* 9 */
19793
+ " sum(ovfl_unused),\n" /* 10 */
19794
+ " max(depth),\n" /* 11 */
19795
+ " count(*),\n" /* 12 */
19796
+ " sum(int_entries)\n" /* 13 */
19797
+ " FROM temp.%s WHERE %s",
19798
+ p->zSU, zWhere);
19799
+ if( pStmt==0 ) return 1;
19800
+ rc = sqlite3_step(pStmt);
19801
+ if( rc==SQLITE_ROW ){
19802
+ analysisTitle(p, zTitle);
19803
+
19804
+ nentry = sqlite3_column_int64(pStmt, 0);
19805
+ payload = sqlite3_column_int64(pStmt, 1);
19806
+ ovfl_payload = sqlite3_column_int64(pStmt, 2);
19807
+ mx_payload = sqlite3_column_int64(pStmt, 3);
19808
+ ovfl_cnt = sqlite3_column_int64(pStmt, 4);
19809
+ leaf_pages = sqlite3_column_int64(pStmt, 5);
19810
+ int_pages = sqlite3_column_int64(pStmt, 6);
19811
+ ovfl_pages = sqlite3_column_int64(pStmt, 7);
19812
+ leaf_unused = sqlite3_column_int64(pStmt, 8);
19813
+ int_unused = sqlite3_column_int64(pStmt, 9);
19814
+ ovfl_unused = sqlite3_column_int64(pStmt, 10);
19815
+ depth = sqlite3_column_int64(pStmt, 11);
19816
+ cnt = sqlite3_column_int64(pStmt, 12);
19817
+ int_cell = sqlite3_column_int64(pStmt, 13);
19818
+ rc = SQLITE_DONE;
19819
+
19820
+ total_pages = leaf_pages + int_pages + ovfl_pages;
19821
+ analysisLine(p, "Percentage of total database", "%.3g%%\n",
19822
+ (total_pages*100.0)/(double)nPage);
19823
+ analysisLine(p, "Number of entries", "%lld\n", nentry);
19824
+ storage = total_pages*pgsz;
19825
+ analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
19826
+ analysisLine(p, "Bytes of payload", "%-11lld ", payload);
19827
+ analysisPercent(p, payload*100.0/(double)storage);
19828
+ if( ovfl_cnt>0 ){
19829
+ analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19830
+ analysisPercent(p, ovfl_payload*100.0/(double)payload);
19831
+ }
19832
+ total_unused = leaf_unused + int_unused + ovfl_unused;
19833
+ total_meta = storage - payload - total_unused;
19834
+ analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
19835
+ analysisPercent(p, total_meta*100.0/(double)storage);
19836
+ if( cnt==1 ){
19837
+ analysisLine(p, "B-tree depth", "%lld\n", depth);
19838
+ if( int_cell>1 ){
19839
+ analysisLine(p, "Average fanout", "%.1f\n",
19840
+ (double)(int_cell+int_pages)/(double)int_pages);
19841
+ }
19842
+ }
19843
+ if( nentry>0 ){
19844
+ analysisLine(p, "Average payload per entry", "%.1f\n",
19845
+ (double)payload/(double)nentry);
19846
+ analysisLine(p, "Average unused bytes per entry", "%.1f\n",
19847
+ (double)total_unused/(double)nentry);
19848
+ analysisLine(p, "Average metadata per entry", "%.1f\n",
19849
+ (double)total_meta/(double)nentry);
19850
+ }
19851
+ analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19852
+ if( nentry>0 ){
19853
+ analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19854
+ analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
19855
+ }
19856
+ if( int_pages>0 ){
19857
+ analysisLine(p, "Index pages used", "%lld\n", int_pages);
19858
+ }
19859
+ analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
19860
+ if( ovfl_cnt ){
19861
+ analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19862
+ }
19863
+ analysisLine(p, "Total pages used", "%lld\n", total_pages);
19864
+ if( int_pages>0 ){
19865
+ analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19866
+ }
19867
+ analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19868
+ if( ovfl_cnt ){
19869
+ analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19870
+ }
19871
+ analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19872
+ analysisPercent(p, total_unused*100.0/(double)storage);
19873
+ }
19874
+ return analysisStmtFinish(p, rc, pStmt);
19875
+}
19876
+
19877
+/*
19878
+** SQL Function: analyze(SCHEMA)
19879
+**
19880
+** Analyze the database schema named in the argument. Return text
19881
+** containing the analysis.
19882
+*/
19883
+static void analyzeFunc(
19884
+ sqlite3_context *context,
19885
+ int argc,
19886
+ sqlite3_value **argv
19887
+){
19888
+ int rc;
19889
+ sqlite3_stmt *pStmt;
19890
+ int n;
19891
+ sqlite3_int64 i64;
19892
+ sqlite3_int64 pgsz;
19893
+ sqlite3_int64 nPage;
19894
+ sqlite3_int64 nPageInUse;
19895
+ sqlite3_int64 nFreeList;
19896
+ sqlite3_int64 nIndex;
19897
+ sqlite3_int64 nWORowid;
19898
+ Analysis s;
19899
+ sqlite3_uint64 r[2];
19900
+
19901
+ memset(&s, 0, sizeof(s));
19902
+ s.db = sqlite3_context_db_handle(context);
19903
+ s.context = context;
19904
+ s.pOut = sqlite3_str_new(0);
19905
+ if( sqlite3_str_errcode(s.pOut) ){
19906
+ analysisError(&s, 0);
19907
+ return;
19908
+ }
19909
+ s.zSchema = (const char*)sqlite3_value_text(argv[0]);
19910
+ if( s.zSchema==0 ){
19911
+ s.zSchema = "main";
19912
+ }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19913
+ analysisReset(&s);
19914
+ sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
19915
+ return;
19916
+ }
19917
+ i64 = 0;
19918
+ rc = analysisSqlInt(&s,&i64,"SELECT 1 FROM pragma_database_list"
19919
+ " WHERE name=%Q COLLATE nocase",s.zSchema);
19920
+ if( rc || i64==0 ){
19921
+ analysisReset(&s);
19922
+ sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
19923
+ return;
19924
+ }
19925
+ sqlite3_randomness(sizeof(r), &r);
19926
+ s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
19927
+ if( s.zSU==0 ){ analysisError(&s, 0); return; }
19928
+
19929
+ /* The s.zSU table contains the data used for the analysis.
19930
+ ** The table name contains 128-bits of randomness to avoid
19931
+ ** collisions with preexisting tables in temp.
19932
+ */
19933
+ rc = analysisSql(&s,
19934
+ "CREATE TABLE temp.%s(\n"
19935
+ " name text, -- A table or index\n"
19936
+ " tblname text, -- Table that owns name\n"
19937
+ " is_index boolean, -- TRUE if it is an index\n"
19938
+ " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
19939
+ " nentry int, -- Number of entries in the BTree\n"
19940
+ " leaf_entries int, -- Number of leaf entries\n"
19941
+ " depth int, -- Depth of the b-tree\n"
19942
+ " payload int, -- Total data stored in this table/index\n"
19943
+ " ovfl_payload int, -- Total data stored on overflow pages\n"
19944
+ " ovfl_cnt int, -- Number of entries that use overflow\n"
19945
+ " mx_payload int, -- Maximum payload size\n"
19946
+ " int_pages int, -- Interior pages used\n"
19947
+ " leaf_pages int, -- Leaf pages used\n"
19948
+ " ovfl_pages int, -- Overflow pages used\n"
19949
+ " int_unused int, -- Unused bytes on interior pages\n"
19950
+ " leaf_unused int, -- Unused bytes on primary pages\n"
19951
+ " ovfl_unused int, -- Unused bytes on overflow pages\n"
19952
+ " int_entries int -- Btree cells on internal pages\n"
19953
+ ");",
19954
+ s.zSU
19955
+ );
19956
+ if( rc ) return;
19957
+
19958
+ /* Populate the s.zSU table
19959
+ */
19960
+ rc = analysisSql(&s,
19961
+ "WITH\n"
19962
+ " allidx(idxname) AS (\n"
19963
+ " SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
19964
+ " ),\n"
19965
+ " allobj(allname,tblname,isidx,isworowid) AS (\n"
19966
+ " SELECT 'sqlite_schema',\n"
19967
+ " 'sqlite_schema',\n"
19968
+ " 0,\n"
19969
+ " 0\n"
19970
+ " UNION ALL\n"
19971
+ " SELECT name,\n"
19972
+ " tbl_name,\n"
19973
+ " type='index',\n"
19974
+ " EXISTS(SELECT 1\n"
19975
+ " FROM pragma_index_list(sqlite_schema.name,%Q)\n"
19976
+ " WHERE pragma_index_list.origin='pk'\n"
19977
+ " AND pragma_index_list.name NOT IN allidx)\n"
19978
+ " FROM \"%w\".sqlite_schema\n"
19979
+ " )\n"
19980
+ "INSERT INTO temp.%s\n"
19981
+ " SELECT\n"
19982
+ " allname,\n"
19983
+ " tblname,\n"
19984
+ " isidx,\n"
19985
+ " isworowid,\n"
19986
+ " sum(ncell),\n"
19987
+ " sum((pagetype='leaf')*ncell),\n"
19988
+ " max((length(if(path GLOB '*+*','',path))+3)/4),\n"
19989
+ " sum(payload),\n"
19990
+ " sum((pagetype='overflow')*payload),\n"
19991
+ " sum(path GLOB '*+000000'),\n"
19992
+ " max(mx_payload),\n"
19993
+ " sum(pagetype='internal'),\n"
19994
+ " sum(pagetype='leaf'),\n"
19995
+ " sum(pagetype='overflow'),\n"
19996
+ " sum((pagetype='internal')*unused),\n"
19997
+ " sum((pagetype='leaf')*unused),\n"
19998
+ " sum((pagetype='overflow')*unused),\n"
19999
+ " sum(if(pagetype='internal',ncell))\n"
20000
+ " FROM allobj CROSS JOIN dbstat(%Q) \n"
20001
+ " WHERE dbstat.name=allobj.allname\n"
20002
+ " GROUP BY allname;\n",
20003
+ s.zSchema, /* %w.sqlite_schema -- in allidx */
20004
+ s.zSchema, /* pragma_index_list(...,%Q) */
20005
+ s.zSchema, /* %w.sqlite_schema */
20006
+ s.zSU, /* INTO temp.%s */
20007
+ s.zSchema /* JOIN dbstat(%Q) */
20008
+ );
20009
+ if( rc ) return;
20010
+
20011
+ nPage = 0;
20012
+ rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20013
+ if( rc ) return;
20014
+ if( nPage<=0 ){
20015
+ /* Very brief reply for an empty database */
20016
+ analysisReset(&s);
20017
+ sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
20018
+ return;
20019
+ }
20020
+
20021
+ /* Begin generating the report */
20022
+ analysisTitle(&s, "Database storage utilization report");
20023
+ pgsz = 0;
20024
+ rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20025
+ if( rc ) return;
20026
+ analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
20027
+ analysisLine(&s, "Pages in the database", "%lld\n", nPage);
20028
+
20029
+ nPageInUse = 0;
20030
+ rc = analysisSqlInt(&s, &nPageInUse,
20031
+ "SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
20032
+ if( rc ) return;
20033
+ analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20034
+ analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
20035
+
20036
+ nFreeList = 0;
20037
+ rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20038
+ if( rc ) return;
20039
+ analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20040
+ analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
20041
+
20042
+ i64 = 0;
20043
+ rc = analysisSqlInt(&s, &i64, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20044
+ if( rc ) return;
20045
+ if( i64==0 || nPage<=1 ){
20046
+ i64 = 0;
20047
+ }else{
20048
+ double rPtrsPerPage = pgsz/5;
20049
+ double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
20050
+ i64 = (sqlite3_int64)ceil(rAvPage);
20051
+ }
20052
+ analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", i64);
20053
+ analysisPercent(&s, (i64*100.0)/(double)nPage);
20054
+
20055
+ i64 = 0;
20056
+ rc = analysisSqlInt(&s, &i64,
20057
+ "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
20058
+ s.zSchema);
20059
+ if( rc ) return;
20060
+ analysisLine(&s, "Number of tables", "%lld\n", i64);
20061
+ nWORowid = 0;
20062
+ rc = analysisSqlInt(&s, &nWORowid,
20063
+ "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
20064
+ s.zSchema);
20065
+ if( rc ) return;
20066
+ if( nWORowid>0 ){
20067
+ analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20068
+ analysisLine(&s, "Number of rowid tables", "%lld\n", i64 - nWORowid);
20069
+ }
20070
+ nIndex = 0;
20071
+ rc = analysisSqlInt(&s, &nIndex,
20072
+ "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
20073
+ s.zSchema);
20074
+ if( rc ) return;
20075
+ analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
20076
+ i64 = 0;
20077
+ rc = analysisSqlInt(&s, &i64,
20078
+ "SELECT count(*) FROM \"%w\".sqlite_schema"
20079
+ " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
20080
+ s.zSchema);
20081
+ if( rc ) return;
20082
+ analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - i64);
20083
+ analysisLine(&s, "Number of implied indexes", "%lld\n", i64);
20084
+ analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20085
+ i64 = 0;
20086
+ rc = analysisSqlInt(&s, &i64,
20087
+ "SELECT sum(payload) FROM temp.%s"
20088
+ " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
20089
+ s.zSU);
20090
+ if( rc ) return;
20091
+ analysisLine(&s, "Bytes of payload", "%-11lld ", i64);
20092
+ analysisPercent(&s, i64*100.0/(double)(pgsz*nPage));
20093
+
20094
+ analysisTitle(&s, "Page counts for all tables with their indexes");
20095
+ pStmt = analysisPrepare(&s,
20096
+ "SELECT upper(tblname),\n"
20097
+ " sum(int_pages+leaf_pages+ovfl_pages)\n"
20098
+ " FROM temp.%s\n"
20099
+ " GROUP BY 1\n"
20100
+ " ORDER BY 2 DESC, 1;",
20101
+ s.zSU);
20102
+ if( pStmt==0 ) return;
20103
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20104
+ sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20105
+ analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20106
+ analysisPercent(&s, (nn*100.0)/(double)nPage);
20107
+ }
20108
+ if( analysisStmtFinish(&s, rc, pStmt) ) return;
20109
+
20110
+ analysisTitle(&s, "Page counts for all tables and indexes separately");
20111
+ pStmt = analysisPrepare(&s,
20112
+ "SELECT upper(name),\n"
20113
+ " sum(int_pages+leaf_pages+ovfl_pages)\n"
20114
+ " FROM temp.%s\n"
20115
+ " GROUP BY 1\n"
20116
+ " ORDER BY 2 DESC, 1;",
20117
+ s.zSU);
20118
+ if( pStmt==0 ) return;
20119
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20120
+ sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20121
+ analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20122
+ analysisPercent(&s, (nn*100.0)/(double)nPage);
20123
+ }
20124
+ if( analysisStmtFinish(&s, rc, pStmt) ) return;
20125
+
20126
+ rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
20127
+ if( rc ) return;
20128
+ rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20129
+ if( rc ) return;
20130
+ if( nWORowid>0 ){
20131
+ rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20132
+ pgsz, nPage);
20133
+ if( rc ) return;
20134
+ rc = analysisSubreport(&s, "All rowid tables",
20135
+ "NOT is_without_rowid AND NOT is_index",
20136
+ pgsz, nPage);
20137
+ if( rc ) return;
20138
+ }
20139
+ rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20140
+ if( rc ) return;
20141
+
20142
+ pStmt = analysisPrepare(&s,
20143
+ "SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
20144
+ " GROUP BY 1 ORDER BY 1",
20145
+ s.zSU);
20146
+ if( pStmt==0 ) return;
20147
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20148
+ const char *zUpper = (const char*)sqlite3_column_text(pStmt, 0);
20149
+ const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
20150
+ int nSubIndex = sqlite3_column_int(pStmt, 2);
20151
+ if( nSubIndex==0 ){
20152
+ char *zTitle = sqlite3_mprintf("Table %s", zUpper);
20153
+ char *zWhere = sqlite3_mprintf("name=%Q", zName);
20154
+ rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20155
+ sqlite3_free(zTitle);
20156
+ sqlite3_free(zWhere);
20157
+ if( rc ) break;
20158
+ }else{
20159
+ sqlite3_stmt *pS2;
20160
+ char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
20161
+ char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20162
+ rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20163
+ sqlite3_free(zTitle);
20164
+ sqlite3_free(zWhere);
20165
+ if( rc ) break;
20166
+ zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
20167
+ zWhere = sqlite3_mprintf("name=%Q", zName);
20168
+ rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20169
+ sqlite3_free(zTitle);
20170
+ sqlite3_free(zWhere);
20171
+ if( rc ) break;
20172
+ if( nSubIndex>1 ){
20173
+ zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
20174
+ zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20175
+ rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20176
+ sqlite3_free(zTitle);
20177
+ sqlite3_free(zWhere);
20178
+ if( rc ) break;
20179
+ }
20180
+ pS2 = analysisPrepare(&s,
20181
+ "SELECT name, upper(name) FROM temp.%s"
20182
+ " WHERE is_index AND tblname=%Q",
20183
+ s.zSU, zName);
20184
+ if( pS2==0 ){
20185
+ rc = SQLITE_NOMEM;
20186
+ break;
20187
+ }
20188
+ while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
20189
+ const char *zU = (const char*)sqlite3_column_text(pS2, 1);
20190
+ const char *zN = (const char*)sqlite3_column_text(pS2, 0);
20191
+ zTitle = sqlite3_mprintf("Index %s", zU);
20192
+ zWhere = sqlite3_mprintf("name=%Q", zN);
20193
+ rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20194
+ sqlite3_free(zTitle);
20195
+ sqlite3_free(zWhere);
20196
+ if( rc ) break;
20197
+ }
20198
+ rc = analysisStmtFinish(&s, rc, pS2);
20199
+ if( rc ) break;
20200
+ }
20201
+ }
20202
+ if( analysisStmtFinish(&s, rc, pStmt) ) return;
20203
+
20204
+ /* Append SQL statements that will recreate the raw data used for
20205
+ ** the analysis.
20206
+ */
20207
+ analysisTitle(&s, "Raw data used to generate this report");
20208
+ sqlite3_str_appendf(s.pOut,
20209
+ "The following SQL will create a table named \"space_used\" which\n"
20210
+ "contains most of the information used to generate the report above.\n"
20211
+ "*/\n"
20212
+ );
20213
+ sqlite3_str_appendf(s.pOut,
20214
+ "BEGIN;\n"
20215
+ "CREATE TABLE space_used(\n"
20216
+ " name text, -- A table or index\n" /* 0 */
20217
+ " tblname text, -- Table that owns name\n" /* 1 */
20218
+ " is_index boolean, -- TRUE if it is an index\n" /* 2 */
20219
+ " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n" /* 3 */
20220
+ " nentry int, -- Number of entries in the BTree\n" /* 4 */
20221
+ " leaf_entries int, -- Number of leaf entries\n" /* 5 */
20222
+ " depth int, -- Depth of the b-tree\n" /* 6 */
20223
+ " payload int, -- Total data in this table/index\n" /* 7 */
20224
+ " ovfl_payload int, -- Total data on overflow pages\n" /* 8 */
20225
+ " ovfl_cnt int, -- Entries that use overflow\n" /* 9 */
20226
+ " mx_payload int, -- Maximum payload size\n" /* 10 */
20227
+ " int_pages int, -- Interior pages used\n" /* 11 */
20228
+ " leaf_pages int, -- Leaf pages used\n" /* 12 */
20229
+ " ovfl_pages int, -- Overflow pages used\n" /* 13 */
20230
+ " int_unused int, -- Unused bytes on interior pages\n" /* 14 */
20231
+ " leaf_unused int, -- Unused bytes on primary pages\n" /* 15 */
20232
+ " ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
20233
+ " int_entries int -- B-tree entries on internal pages\n"/* 17 */
20234
+ ");\n"
20235
+ "INSERT INTO space_used VALUES\n"
20236
+ );
20237
+ pStmt = analysisPrepare(&s,
20238
+ "SELECT quote(name), quote(tblname),\n" /* 0..1 */
20239
+ " is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
20240
+ " depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
20241
+ " int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
20242
+ " leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
20243
+ " FROM temp.%s;",
20244
+ s.zSU);
20245
+ if( pStmt==0 ) return;
20246
+ n = 0;
20247
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20248
+ if( n++ ) sqlite3_str_appendf(s.pOut,",\n");
20249
+ sqlite3_str_appendf(s.pOut,
20250
+ " (%s,%s,%lld,%lld,%lld,%lld,%lld,%lld,%lld,"
20251
+ "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld)",
20252
+ sqlite3_column_text(pStmt, 0),
20253
+ sqlite3_column_text(pStmt, 1),
20254
+ sqlite3_column_int64(pStmt, 2),
20255
+ sqlite3_column_int64(pStmt, 3),
20256
+ sqlite3_column_int64(pStmt, 4),
20257
+ sqlite3_column_int64(pStmt, 5),
20258
+ sqlite3_column_int64(pStmt, 6),
20259
+ sqlite3_column_int64(pStmt, 7),
20260
+ sqlite3_column_int64(pStmt, 8),
20261
+ sqlite3_column_int64(pStmt, 9),
20262
+ sqlite3_column_int64(pStmt, 10),
20263
+ sqlite3_column_int64(pStmt, 11),
20264
+ sqlite3_column_int64(pStmt, 12),
20265
+ sqlite3_column_int64(pStmt, 13),
20266
+ sqlite3_column_int64(pStmt, 14),
20267
+ sqlite3_column_int64(pStmt, 15),
20268
+ sqlite3_column_int64(pStmt, 16),
20269
+ sqlite3_column_int64(pStmt, 17));
20270
+ }
20271
+ if( rc!=SQLITE_DONE ){
20272
+ analysisError(&s, "SQL run-time error: %s\nSQL: %s",
20273
+ sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
20274
+ sqlite3_finalize(pStmt);
20275
+ return;
20276
+ }
20277
+ sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
20278
+ sqlite3_finalize(pStmt);
20279
+
20280
+ if( sqlite3_str_length(s.pOut) ){
20281
+ sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
20282
+ sqlite3_free);
20283
+ s.pOut = 0;
20284
+ }
20285
+ analysisReset(&s);
20286
+}
20287
+
20288
+
20289
+#ifdef _WIN32
20290
+
20291
+#endif
20292
+int sqlite3_analyze_init(
20293
+ sqlite3 *db,
20294
+ char **pzErrMsg,
20295
+ const sqlite3_api_routines *pApi
20296
+){
20297
+ int rc = SQLITE_OK;
20298
+ SQLITE_EXTENSION_INIT2(pApi);
20299
+ (void)pzErrMsg; /* Unused parameter */
20300
+ rc = sqlite3_create_function(db, "analyze", 1,
20301
+ SQLITE_UTF8|SQLITE_INNOCUOUS,
20302
+ 0, analyzeFunc, 0, 0);
20303
+ return rc;
20304
+}
20305
+
20306
+/************************* End ext/misc/analyze.c ********************/
1940320307
1940420308
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
1940520309
#define SQLITE_SHELL_HAVE_RECOVER 1
1940620310
#else
1940720311
#define SQLITE_SHELL_HAVE_RECOVER 0
@@ -23966,10 +24870,11 @@
2396624870
** Output routines that are able to redirect to memory rather than
2396724871
** doing actually I/O.
2396824872
** Works like.
2396924873
** --------------
2397024874
** cli_printf(FILE*, const char*, ...); fprintf()
24875
+** cli_write(FILE*, const char*, int); write()
2397124876
** cli_puts(const char*, FILE*); fputs()
2397224877
** cli_vprintf(FILE*, const char*, va_list); vfprintf()
2397324878
**
2397424879
** These are just thin wrappers with the following added semantics:
2397524880
** If the file-scope variable cli_output_capture is not NULL, and
@@ -23991,10 +24896,18 @@
2399124896
}else{
2399224897
rc = sqlite3_vfprintf(out, zFormat, ap);
2399324898
}
2399424899
va_end(ap);
2399524900
return rc;
24901
+}
24902
+static int cli_write(FILE *out, const char *zData, int nData){
24903
+ if( cli_output_capture && (out==stdout || out==stderr) ){
24904
+ sqlite3_str_append(cli_output_capture, zData, nData);
24905
+ }else{
24906
+ nData = (int)fwrite(zData, 1, nData, out);
24907
+ }
24908
+ return nData;
2399624909
}
2399724910
static int cli_puts(const char *zText, FILE *out){
2399824911
if( cli_output_capture && (out==stdout || out==stderr) ){
2399924912
sqlite3_str_appendall(cli_output_capture, zText);
2400024913
return 1;
@@ -24189,15 +25102,47 @@
2418925102
2419025103
/*
2419125104
** The default prompts.
2419225105
*/
2419325106
#ifndef SQLITE_PS1
24194
-# define SQLITE_PS1 "SQLite /f> "
25107
+# define SQLITE_PS1 "/A /f> "
2419525108
#endif
2419625109
#ifndef SQLITE_PS2
2419725110
# define SQLITE_PS2 "/B.../H> "
2419825111
#endif
25112
+
25113
+/*
25114
+** Redefinable name of a function that is used to find the text for
25115
+** some prompt expansions: /A /V /v
25116
+*/
25117
+#ifndef SQLITE_PS_APPDEF
25118
+# define SQLITE_PS_APPDEF shellPromptAppDef
25119
+#else
25120
+extern const char *SQLITE_PS_APPDEF(int);
25121
+#endif
25122
+
25123
+/*
25124
+** Return a string appropriate for various prompt expansion characters.
25125
+** Return an empty string at least. Always return a valid string pointer.
25126
+*/
25127
+static const char *shellPromptAppDef(int c){
25128
+ if( c=='A' ) return "SQLite";
25129
+ if( c=='V' ) return sqlite3_libversion();
25130
+ if( c=='v' ){
25131
+ static char zRel[16];
25132
+ const char *zF = sqlite3_libversion();
25133
+ const char *zD = strrchr(zF,'.');
25134
+ if( zD && (size_t)(zD-zF)<sizeof(zRel)-1 ){
25135
+ memcpy(zRel,zF,(size_t)(zD-zF));
25136
+ zRel[(size_t)(zD-zF)] = 0;
25137
+ return zRel;
25138
+ }else{
25139
+ return zF;
25140
+ }
25141
+ }
25142
+ return "";
25143
+}
2419925144
2420025145
/*
2420125146
** Return the raw (unexpanded) prompt string. This will be the
2420225147
** first of the following that exist:
2420325148
**
@@ -24236,11 +25181,14 @@
2423625181
zFN = p->pAuxDb->zDbFilename;
2423725182
}else if( p->db && (pFN = sqlite3_db_filename(p->db,0))!=0 ){
2423825183
zFN = sqlite3_filename_database(pFN);
2423925184
}
2424025185
if( zFN==0 || zFN[0]==0 ){
24241
- zFN = "in-memory";
25186
+ zFN = p->pAuxDb->zDbFilename;
25187
+ if( zFN==0 || zFN[0]==0 || cli_strcmp(zFN,":memory:")==0 ){
25188
+ zFN = "in-memory";
25189
+ }
2424225190
}
2424325191
return zFN;
2424425192
}
2424525193
2424625194
/*
@@ -24262,16 +25210,17 @@
2426225210
const char *zPrompt /* Prompt string to be expanded */
2426325211
){
2426425212
sqlite3_str *pOut = sqlite3_str_new(0);
2426525213
int i;
2426625214
char c;
24267
- int onoff = 1;
25215
+ unsigned int mOff = 0; /* Bitmask of FALSE for if/then/else */
2426825216
int idxSpace = -1;
25217
+ int iDate = -1;
2426925218
for(i=0; zPrompt[i]; i++){
2427025219
if( zPrompt[i]!='/' ) continue;
2427125220
if( i>0 ){
24272
- if( onoff ) sqlite3_str_append(pOut, zPrompt, i);
25221
+ if( !mOff ) sqlite3_str_append(pOut, zPrompt, i);
2427325222
zPrompt += i;
2427425223
i = 0;
2427525224
}
2427625225
/* At this point zPrompt[0] is a / character and all prior
2427725226
** characters have already been loaded into pOut. Process the
@@ -24290,18 +25239,27 @@
2429025239
/* /nnn becomes a single byte given by octal nnn */
2429125240
int v = c - '0';
2429225241
while( i<=2 && zPrompt[i+1]>='0' && zPrompt[i+1]<='7' ){
2429325242
v = v*8 + zPrompt[++i] - '0';
2429425243
}
24295
- if( onoff ) sqlite3_str_appendchar(pOut, 1, v);
25244
+ if( !mOff ) sqlite3_str_appendchar(pOut, 1, v);
2429625245
zPrompt += i+1;
2429725246
i = -1;
2429825247
continue;
2429925248
}
2430025249
if( c=='e' ){
2430125250
/* /e is shorthand for /033 which is U+001B "Escape" */
24302
- if( onoff ) sqlite3_str_append(pOut, "\033", 1);
25251
+ if( !mOff ) sqlite3_str_append(pOut, "\033", 1);
25252
+ zPrompt += 2;
25253
+ i = -1;
25254
+ continue;
25255
+ }
25256
+ if( c=='A' || c=='V' || c=='v' ){
25257
+ /* /A expands to the application name */
25258
+ /* /V expands to the version number with patch level */
25259
+ /* /v expands to the version number without the patch level */
25260
+ if( !mOff ) sqlite3_str_appendall(pOut, SQLITE_PS_APPDEF(c));
2430325261
zPrompt += 2;
2430425262
i = -1;
2430525263
continue;
2430625264
}
2430725265
@@ -24317,36 +25275,43 @@
2431725275
** or red if within a transaction:
2431825276
**
2431925277
** .prompt '/e[1;/x31/:34/;m~f>/e[0m '
2432025278
*/
2432125279
if( c==':' ){
24322
- /* toggle display on/off */
24323
- onoff = !onoff;
25280
+ /* ELSE: toggle display on/off */
25281
+ mOff ^= 1;
2432425282
zPrompt += 2;
2432525283
i = -1;
2432625284
continue;
2432725285
}
2432825286
if( c==';' ){
24329
- /* Turn display on */
24330
- onoff = 1;
25287
+ /* ENDIF: Turn display on */
25288
+ mOff >>= 1;
2433125289
zPrompt += 2;
2433225290
i = -1;
2433325291
continue;
2433425292
}
2433525293
if( c=='x' ){
2433625294
/* /x turns display off not in a transaction, on if in txn */
24337
- onoff = p->db && !sqlite3_get_autocommit(p->db);
25295
+ mOff = (mOff<<1) | (p->db==0 || sqlite3_get_autocommit(p->db)!=0);
25296
+ zPrompt += 2;
25297
+ i = -1;
25298
+ continue;
25299
+ }
25300
+ if( c=='r' ){
25301
+ /* /r turns display off if database is read/write, on if read-only */
25302
+ mOff = (mOff<<1) | (p->db==0 || sqlite3_db_readonly(p->db,0)==0);
2433825303
zPrompt += 2;
2433925304
i = -1;
2434025305
continue;
2434125306
}
2434225307
2434325308
if( c=='f' || c=='F' || c=='~' ){
2434425309
/* /f becomes the tail of the database filename */
2434525310
/* /F becomes the full pathname */
2434625311
/* /~ becomes the full pathname relative to $HOME */
24347
- if( onoff ){
25312
+ if( !mOff ){
2434825313
const char *zFN = prompt_filename(p);
2434925314
if( c=='f' ){
2435025315
#ifdef _WIN32
2435125316
const char *zTail = strrchr(zFN,'\\');
2435225317
#else
@@ -24371,11 +25336,11 @@
2437125336
continue;
2437225337
}
2437325338
2437425339
if( c=='H' ){
2437525340
/* /H becomes text needed to terminate current input */
24376
- if( onoff ){
25341
+ if( !mOff ){
2437725342
sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0;
2437825343
int cc = (R>>16)&0xff;
2437925344
int nParen = R>>32;
2438025345
int eSemi = (R>>8)&0xff;
2438125346
if( cc==0 ){
@@ -24405,22 +25370,48 @@
2440525370
2440625371
if( c=='B' ){
2440725372
/* /B is a no-op for the main prompt. For the continuation prompt,
2440825373
** /B expands to zero or more spaces to make the continuation prompt
2440925374
** at least as wide as the main prompt. */
24410
- if( onoff ) idxSpace = sqlite3_str_length(pOut);
25375
+ if( !mOff ) idxSpace = sqlite3_str_length(pOut);
25376
+ zPrompt += 2;
25377
+ i = -1;
25378
+ continue;
25379
+ }
25380
+
25381
+ if( c=='D' ){
25382
+ /* /D.../D replaces all of the text between the two /D escapes with
25383
+ ** the result from strftime(). */
25384
+ if( iDate<0 ){
25385
+ iDate = sqlite3_str_length(pOut);
25386
+ }else{
25387
+ if( !mOff ){
25388
+ time_t now;
25389
+ char zBuf[200];
25390
+ zBuf[0] = 0;
25391
+ time(&now);
25392
+ strftime(zBuf, sizeof(zBuf)-1, sqlite3_str_value(pOut)+iDate,
25393
+ localtime(&now));
25394
+ zBuf[199] = 0;
25395
+ sqlite3_str_truncate(pOut, iDate);
25396
+ sqlite3_str_appendall(pOut, zBuf);
25397
+ }
25398
+ iDate = -1;
25399
+ }
2441125400
zPrompt += 2;
2441225401
i = -1;
2441325402
continue;
2441425403
}
2441525404
24416
- /* No match to a known escape. Generate an error. */
24417
- if( onoff ) sqlite3_str_appendf(pOut,"UNKNOWN(\"/%c\")",c);
25405
+ /* No match to a known escape. Generate an error. The mOff flag
25406
+ ** is ignored for this output, so that errors appear even if they
25407
+ ** are in an unused branch. */
25408
+ sqlite3_str_appendf(pOut,"UNKNOWN(\"/%c\")",c);
2441825409
zPrompt += 2;
2441925410
i = -1;
2442025411
}
24421
- if( i>0 && onoff ){
25412
+ if( i>0 && !mOff ){
2442225413
sqlite3_str_append(pOut, zPrompt, i);
2442325414
}
2442425415
2442525416
/* Expand the /B, if there is one and if this is a continuation prompt */
2442625417
if( idxSpace>=0 && zPrior!=0 && zPrior[0]!=0 ){
@@ -24440,11 +25431,15 @@
2444025431
memmove(z+idxSpace+nNew, z+idxSpace, len-nNew-idxSpace);
2444125432
memset(z+idxSpace, ' ', nNew);
2444225433
}
2444325434
}
2444425435
}
24445
-
25436
+
25437
+ if( 0==sqlite3_str_length(pOut) ){
25438
+ /* Avoid a bogus OOM */
25439
+ sqlite3_str_appendchar(pOut, 1, '\0');
25440
+ }
2444625441
return sqlite3_str_finish(pOut);
2444725442
}
2444825443
2444925444
/*
2445025445
** Retrieve a single line of input text.
@@ -25331,11 +26326,11 @@
2533126326
** (2) Run program EDITOR on that temporary file.
2533226327
** (3) Read the temporary file back and return its content as the result.
2533326328
** (4) Delete the temporary file
2533426329
**
2533526330
** If the EDITOR argument is omitted, use the value in the VISUAL
25336
-** environment variable. If still there is no EDITOR, through an error.
26331
+** environment variable. If still there is no EDITOR, throw an error.
2533726332
**
2533826333
** Also throw an error if the EDITOR program returns a non-zero exit code.
2533926334
*/
2534026335
#ifndef SQLITE_NOHAVE_SYSTEM
2534126336
static void editFunc(
@@ -26688,11 +27683,11 @@
2668827683
/*
2668927684
** QRF write callback
2669027685
*/
2669127686
static int shellWriteQR(void *pX, const char *z, sqlite3_int64 n){
2669227687
ShellState *pArg = (ShellState*)pX;
26693
- cli_printf(pArg->out, "%.*s", (int)n, z);
27688
+ cli_write(pArg->out, z, (int)n);
2669427689
return SQLITE_OK;
2669527690
}
2669627691
2669727692
/*
2669827693
** Execute a statement or set of statements. Print
@@ -27230,10 +28225,11 @@
2723028225
".databases List names and files of attached databases",
2723128226
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
2723228227
#if SQLITE_SHELL_HAVE_RECOVER
2723328228
".dbinfo ?DB? Show status information about the database",
2723428229
#endif
28230
+ ".dbstat ?SCHEMA? Report database space and size stats",
2723528231
".dbtotxt Hex dump of the database file",
2723628232
".dump ?OBJECTS? Render database content as SQL",
2723728233
" Options:",
2723828234
" --data-only Output only INSERT statements",
2723928235
" --newlines Allow unescaped newline characters in output",
@@ -27262,11 +28258,11 @@
2726228258
".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
2726328259
".filectrl CMD ... Run various sqlite3_file_control() operations",
2726428260
" --schema SCHEMA Use SCHEMA instead of \"main\"",
2726528261
" --help Show CMD details",
2726628262
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
27267
- ",headers on|off Turn display of headers on or off",
28263
+ ".headers on|off Turn display of headers on or off",
2726828264
".help ?-all? ?PATTERN? Show help text for PATTERN",
2726928265
#ifndef SQLITE_SHELL_FIDDLE
2727028266
".import FILE TABLE Import data from FILE into TABLE",
2727128267
#endif
2727228268
#ifndef SQLITE_OMIT_TEST_CONTROL
@@ -27274,11 +28270,11 @@
2727428270
#endif
2727528271
".indexes ?PATTERN? Show names of indexes matching PATTERN",
2727628272
" -a|--all Also show system-generated indexes",
2727728273
" --expr Show only expression indexes",
2727828274
" --sys Show only system-generated indexes",
27279
- ".intck ?STEPS_PER_UNLOCK? Run an incremental integrity check on the db",
28275
+ ".intck ?STEPS? Run an incremental integrity check on the db",
2728028276
#ifdef SQLITE_ENABLE_IOTRACE
2728128277
",iotrace FILE Enable I/O diagnostic logging to FILE",
2728228278
#endif
2728328279
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
2728428280
".lint OPTIONS Report potential schema issues.",
@@ -27339,14 +28335,15 @@
2733928335
" --once Do no more than one progress interrupt",
2734028336
" --quiet|-q No output except at interrupts",
2734128337
" --reset Reset the count for each input and interrupt",
2734228338
" --timeout S Halt after running for S seconds",
2734328339
#endif
27344
- ".prompt MAIN CONTINUE Replace the standard prompts",
27345
- " --reset Revert to default prompts",
27346
- " --show Show the current prompt strings",
27347
- " -- No more options. Subsequent args are prompts",
28340
+ ".prompt MAIN CONTINUE Replace the standard prompts",
28341
+ " --hard-reset Unset SQLITE_PS1/2 and then --reset",
28342
+ " --reset Revert to default prompts",
28343
+ " --show Show the current prompt strings",
28344
+ " -- No more options. Subsequent args are prompts",
2734828345
#ifndef SQLITE_SHELL_FIDDLE
2734928346
".quit Stop interpreting input stream, exit if primary.",
2735028347
".read FILE Read input from FILE or command output",
2735128348
" If FILE begins with \"|\", it is a command that generates the input.",
2735228349
#endif
@@ -27622,11 +28619,11 @@
2762228619
{ ".testcase",
2762328620
"USAGE: .testcase [OPTIONS] NAME\n"
2762428621
"\n"
2762528622
"Start a new test case identified by NAME. All output\n"
2762628623
"through the next \".check\" command is captured for comparison. See the\n"
27627
-"\".check\" commandn for additional informatioon.\n"
28624
+"\".check\" command for additional informatioon.\n"
2762828625
"\n"
2762928626
"Options:\n"
2763028627
" --error-prefix TEXT Change error message prefix text to TEXT\n"
2763128628
},
2763228629
};
@@ -28237,10 +29234,11 @@
2823729234
sqlite3_base64_init(p->db, 0, 0);
2823829235
sqlite3_base85_init(p->db, 0, 0);
2823929236
sqlite3_regexp_init(p->db, 0, 0);
2824029237
sqlite3_ieee_init(p->db, 0, 0);
2824129238
sqlite3_series_init(p->db, 0, 0);
29239
+ sqlite3_analyze_init(p->db, 0, 0);
2824229240
#ifndef SQLITE_SHELL_FIDDLE
2824329241
sqlite3_fileio_init(p->db, 0, 0);
2824429242
sqlite3_completion_init(p->db, 0, 0);
2824529243
#endif
2824629244
#ifdef SQLITE_HAVE_ZLIB
@@ -29116,11 +30114,11 @@
2911630114
zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
2911730115
if( system(zCmd) ){
2911830116
cli_printf(stderr,"Failed: [%s]\n", zCmd);
2911930117
}else{
2912030118
/* Give the start/open/xdg-open command some time to get
29121
- ** going before we continue, and potential delete the
30119
+ ** going before we continue and potentially delete the
2912230120
** p->zTempFile data file out from under it */
2912330121
sqlite3_sleep(2000);
2912430122
}
2912530123
sqlite3_free(zCmd);
2912630124
modePop(p);
@@ -32266,12 +33264,11 @@
3226633264
if( z[1]=='-' ) z++;
3226733265
if( cli_strcmp(z,"-bom")==0 ){
3226833266
zBom = zBomUtf8;
3226933267
}else if( cli_strcmp(z,"-plain")==0 ){
3227033268
bPlain = 1;
32271
- }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
32272
- && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
33269
+ }else if( c=='o' && sqlite3_strglob("-[ewx]",z)==0 ){
3227333270
if( bKeep || eMode ){
3227433271
dotCmdError(p, i, "incompatible with prior options",0);
3227533272
goto dotCmdOutput_error;
3227633273
}
3227733274
eMode = z[1];
@@ -32556,11 +33553,11 @@
3255633553
** DOT-COMMAND: .testcase
3255733554
** USAGE: .testcase [OPTIONS] NAME
3255833555
**
3255933556
** Start a new test case identified by NAME. All output
3256033557
** through the next ".check" command is captured for comparison. See the
32561
-** ".check" commandn for additional informatioon.
33558
+** ".check" command for additional informatioon.
3256233559
**
3256333560
** Options:
3256433561
** --error-prefix TEXT Change error message prefix text to TEXT
3256533562
*/
3256633563
static int dotCmdTestcase(ShellState *p){
@@ -33030,16 +34027,47 @@
3303034027
3303134028
#if SQLITE_SHELL_HAVE_RECOVER
3303234029
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
3303334030
rc = shell_dbinfo_command(p, nArg, azArg);
3303434031
}else
33035
-
33036
- if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
33037
- open_db(p, 0);
33038
- rc = recoverDatabaseCmd(p, nArg, azArg);
33039
- }else
3304034032
#endif /* SQLITE_SHELL_HAVE_RECOVER */
34033
+
34034
+ if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
34035
+ const char *zSchema = 0;
34036
+ int ii;
34037
+ char *zSql;
34038
+ open_db(p, 0);
34039
+ for(ii=1; ii<nArg; ii++){
34040
+ const char *z = azArg[ii];
34041
+ if( z[0]=='-' ){
34042
+ dotCmdError(p, ii, "unknown option", 0);
34043
+ rc = 1;
34044
+ goto meta_command_exit;
34045
+ }
34046
+ if( zSchema ){
34047
+ dotCmdError(p, ii, "unknown argument", 0);
34048
+ rc = 1;
34049
+ goto meta_command_exit;
34050
+ }
34051
+ zSchema = z;
34052
+ }
34053
+ zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
34054
+ shell_check_oom(zSql);
34055
+ modePush(p);
34056
+ modeChange(p, MODE_BATCH);
34057
+ p->mode.spec.nLineLimit = 0;
34058
+ p->mode.spec.nCharLimit = 0;
34059
+ p->mode.spec.nTitleLimit = 0;
34060
+ shell_exec(p, zSql, 0);
34061
+ modePop(p);
34062
+ sqlite3_free(zSql);
34063
+ }else
34064
+
34065
+ if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34066
+ open_db(p, 0);
34067
+ rc = shell_dbtotxt_command(p, nArg, azArg);
34068
+ }else
3304134069
3304234070
if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
3304334071
char *zLike = 0;
3304434072
char *zSql;
3304534073
int i;
@@ -33167,15 +34195,10 @@
3316734195
eputz("Usage: .echo on|off\n");
3316834196
rc = 1;
3316934197
}
3317034198
}else
3317134199
33172
- if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
33173
- open_db(p, 0);
33174
- rc = shell_dbtotxt_command(p, nArg, azArg);
33175
- }else
33176
-
3317734200
if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
3317834201
if( nArg==2 ){
3317934202
if( p->mode.autoEQPtrace ){
3318034203
if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
3318134204
p->mode.autoEQPtrace = 0;
@@ -34139,10 +35162,20 @@
3413935162
int noOpt = 0;
3414035163
for(i=1; i<nArg; i++){
3414135164
const char *z = azArg[i];
3414235165
if( z[0]=='-' && !noOpt ){
3414335166
if( z[1]=='-' ) z++;
35167
+ if( strcmp(z,"-hard-reset")==0 ){
35168
+#ifdef _WIN32
35169
+ _putenv("SQLITE_PS1=");
35170
+ _putenv("SQLITE_PS2=");
35171
+#else
35172
+ unsetenv("SQLITE_PS1");
35173
+ unsetenv("SQLITE_PS2");
35174
+#endif
35175
+ z += 5;
35176
+ }
3414435177
if( strcmp(z,"-reset")==0 ){
3414535178
free(p->azPrompt[0]);
3414635179
free(p->azPrompt[1]);
3414735180
memset(p->azPrompt, 0, sizeof(p->azPrompt));
3414835181
}else
@@ -34160,13 +35193,16 @@
3416035193
}
3416135194
}else if( cnt>1 ){
3416235195
dotCmdError(p, i, "extra argument", 0);
3416335196
rc = 1;
3416435197
goto meta_command_exit;
35198
+ }else if( !p->dot.abQuot[i] && sqlite3_strglob("*[^a-z]*",z)!=0 ){
35199
+ dotCmdError(p, i, "use quotes around the prompt string", 0);
3416535200
}else{
3416635201
free(p->azPrompt[cnt]);
3416735202
p->azPrompt[cnt] = strdup(z);
35203
+ cnt++;
3416835204
}
3416935205
}
3417035206
}else
3417135207
3417235208
#ifndef SQLITE_SHELL_FIDDLE
@@ -34211,10 +35247,17 @@
3421135247
p->in = inSaved;
3421235248
p->lineno = savedLineno;
3421335249
}else
3421435250
#endif /* !defined(SQLITE_SHELL_FIDDLE) */
3421535251
35252
+#if SQLITE_SHELL_HAVE_RECOVER
35253
+ if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
35254
+ open_db(p, 0);
35255
+ rc = recoverDatabaseCmd(p, nArg, azArg);
35256
+ }else
35257
+#endif /* SQLITE_SHELL_HAVE_RECOVER */
35258
+
3421635259
#ifndef SQLITE_SHELL_FIDDLE
3421735260
if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
3421835261
const char *zSrcFile;
3421935262
const char *zDb;
3422035263
sqlite3 *pSrc;
@@ -37245,10 +38288,11 @@
3724538288
linenoiseSetCompletionCallback(linenoise_completion);
3724638289
#elif HAVE_LINENOISE==2
3724738290
linenoiseSetCompletionCallback(linenoise_completion, NULL);
3724838291
#endif
3724938292
data.in = 0;
38293
+ open_db(&data, 0);
3725038294
rc = process_input(&data, "<stdin>");
3725138295
if( zHistory ){
3725238296
shell_stifle_history(2000);
3725338297
shell_write_history(zHistory);
3725438298
sqlite3_free(zHistory);
3725538299
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,10 +5,11 @@
5 **
6 ** ext/expert/sqlite3expert.c
7 ** ext/expert/sqlite3expert.h
8 ** ext/intck/sqlite3intck.c
9 ** ext/intck/sqlite3intck.h
 
10 ** ext/misc/appendvfs.c
11 ** ext/misc/base64.c
12 ** ext/misc/base85.c
13 ** ext/misc/completion.c
14 ** ext/misc/decimal.c
@@ -1305,11 +1306,10 @@
1305 }
1306 }
1307 if( nRow>=0 ){
1308 if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
1309 qrfApproxInt64(pStats, nRow);
1310 nSp = 2;
1311 if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1312 sqlite3_str_appendf(pStats, " ");
1313 qrfApproxInt64(pStats, (i64)rEstCum);
1314 }
1315 }
@@ -1595,44 +1595,43 @@
1595 if( pnNL ) *pnNL = nNL;
1596 return n;
1597 }
1598
1599 /*
1600 ** Escape the input string if it is needed and in accordance with
1601 ** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
 
1602 **
1603 ** Escaping is needed if the string contains any control characters
1604 ** other than \t, \n, and \r\n
1605 **
1606 ** If no escaping is needed (the common case) then set *ppOut to NULL
1607 ** and return 0. If escaping is needed, write the escaped string into
1608 ** memory obtained from sqlite3_malloc64() and make *ppOut point to that
1609 ** memory and return 0. If an error occurs, return non-zero.
1610 **
1611 ** The caller is responsible for freeing *ppFree if it is non-NULL in order
1612 ** to reclaim memory.
1613 */
1614 static void qrfEscape(
1615 int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
1616 sqlite3_str *pStr, /* String to be escaped */
1617 int iStart /* Begin escapding on this byte of pStr */
1618 ){
1619 sqlite3_int64 i, j; /* Loop counters */
1620 sqlite3_int64 sz; /* Size of the string prior to escaping */
1621 sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
1622 unsigned char *zIn; /* Text to be escaped */
 
1623 unsigned char c; /* A single character of the text */
1624 unsigned char *zOut; /* Where to write the results */
1625
1626 /* Find the text to be escaped */
1627 zIn = (unsigned char*)sqlite3_str_value(pStr);
 
1628 if( zIn==0 ) return;
1629 zIn += iStart;
 
1630
1631 /* Count the control characters */
1632 for(i=0; (c = zIn[i])!=0; i++){
1633 if( c<=0x1f
1634 && c!='\t'
1635 && c!='\n'
1636 && (c!='\r' || zIn[i+1]!='\n')
1637 ){
1638 nCtrl++;
@@ -1640,22 +1639,21 @@
1640 }
1641 if( nCtrl==0 ) return; /* Early out if no control characters */
1642
1643 /* Make space to hold the escapes. Copy the original text to the end
1644 ** of the available space. */
1645 sz = sqlite3_str_length(pStr) - iStart;
1646 if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
1647 sqlite3_str_appendchar(pStr, nCtrl, ' ');
1648 zOut = (unsigned char*)sqlite3_str_value(pStr);
1649 if( zOut==0 ) return;
1650 zOut += iStart;
1651 zIn = zOut + nCtrl;
1652 memmove(zIn,zOut,sz);
1653
1654 /* Convert the control characters */
1655 for(i=j=0; (c = zIn[i])!=0; i++){
1656 if( c>0x1f
1657 || c=='\t'
1658 || c=='\n'
1659 || (c=='\r' && zIn[i+1]=='\n')
1660 ){
1661 continue;
@@ -1663,10 +1661,11 @@
1663 if( i>0 ){
1664 memmove(&zOut[j], zIn, i);
1665 j += i;
1666 }
1667 zIn += i+1;
 
1668 i = -1;
1669 if( eEsc==QRF_ESC_Symbol ){
1670 zOut[j++] = 0xe2;
1671 zOut[j++] = 0x90;
1672 zOut[j++] = 0x80+c;
@@ -2065,12 +2064,26 @@
2065 int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
2066 sqlite3_str_appendf(pOut, "(%d-byte blob)", nBlob);
2067 break;
2068 }
2069 default: {
2070 const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
2071 qrfEncodeText(p, pOut, zTxt);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2072 }
2073 }
2074 break;
2075 }
2076 case SQLITE_NULL: {
@@ -6005,11 +6018,11 @@
6005 }
6006 if( p->isNull ){
6007 sqlite3_result_null(pCtx);
6008 return;
6009 }
6010 z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
6011 if( z==0 ){
6012 sqlite3_result_error_nomem(pCtx);
6013 return;
6014 }
6015 i = 0;
@@ -9789,12 +9802,10 @@
9789 /* # include "windirent.h" */
9790 # include <direct.h>
9791 # define STRUCT_STAT struct _stat
9792 # define chmod(path,mode) fileio_chmod(path,mode)
9793 # define mkdir(path,mode) fileio_mkdir(path)
9794 extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
9795 extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
9796 #endif
9797 #include <time.h>
9798 #include <errno.h>
9799
9800 /* When used as part of the CLI, the sqlite3_stdio.h module will have
@@ -9817,17 +9828,73 @@
9817 #define FSDIR_COLUMN_DATA 3 /* File content */
9818 #define FSDIR_COLUMN_LEVEL 4 /* Level. Topmost is 1 */
9819 #define FSDIR_COLUMN_PATH 5 /* Path to top of search */
9820 #define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
9821
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9822 /*
9823 ** UTF8 chmod() function for Windows
9824 */
9825 #if defined(_WIN32) || defined(WIN32)
9826 static int fileio_chmod(const char *zPath, int pmode){
9827 int rc;
9828 wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
9829 if( b1==0 ) return -1;
9830 rc = _wchmod(b1, pmode);
9831 sqlite3_free(b1);
9832 return rc;
9833 }
@@ -9837,11 +9904,11 @@
9837 ** UTF8 mkdir() function for Windows
9838 */
9839 #if defined(_WIN32) || defined(WIN32)
9840 static int fileio_mkdir(const char *zPath){
9841 int rc;
9842 wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
9843 if( b1==0 ) return -1;
9844 rc = _wmkdir(b1);
9845 sqlite3_free(b1);
9846 return rc;
9847 }
@@ -9964,11 +10031,11 @@
9964 const char *zPath,
9965 STRUCT_STAT *pStatBuf
9966 ){
9967 #if defined(_WIN32)
9968 int rc;
9969 wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
9970 if( b1==0 ) return 1;
9971 rc = _wstat(b1, pStatBuf);
9972 if( rc==0 ){
9973 HANDLE hFindFile;
9974 WIN32_FIND_DATAW fd;
@@ -10117,18 +10184,17 @@
10117 FILETIME lastWrite;
10118 SYSTEMTIME currentTime;
10119 LONGLONG intervals;
10120 HANDLE hFile;
10121 LPWSTR zUnicodeName;
10122 extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
10123
10124 GetSystemTime(&currentTime);
10125 SystemTimeToFileTime(&currentTime, &lastAccess);
10126 intervals = (mtime*10000000) + 116444736000000000;
10127 lastWrite.dwLowDateTime = (DWORD)intervals;
10128 lastWrite.dwHighDateTime = intervals >> 32;
10129 zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
10130 if( zUnicodeName==0 ){
10131 return 1;
10132 }
10133 hFile = CreateFileW(
10134 zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
@@ -10782,16 +10848,16 @@
10782 char *zOut = 0; /* Result */
10783 wchar_t *z = 0; /* Temporary buffer */
10784
10785 if( zPath==0 ) return 0;
10786
10787 zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
10788 if( zPath16==0 ) return 0;
10789 z = _wfullpath(NULL, zPath16, 0);
10790 sqlite3_free(zPath16);
10791 if( z ){
10792 zOut = sqlite3_win32_unicode_to_utf8(z);
10793 free(z);
10794 }
10795 return zOut;
10796
10797 #endif /* End WINDOWS, Begin common code */
@@ -19398,10 +19464,848 @@
19398 sqlite3_vfs_unregister(pVfs);
19399 sqlite3_free(pVfs);
19400 }
19401
19402 /************************* End ext/misc/vfstrace.c ********************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19403
19404 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
19405 #define SQLITE_SHELL_HAVE_RECOVER 1
19406 #else
19407 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -23966,10 +24870,11 @@
23966 ** Output routines that are able to redirect to memory rather than
23967 ** doing actually I/O.
23968 ** Works like.
23969 ** --------------
23970 ** cli_printf(FILE*, const char*, ...); fprintf()
 
23971 ** cli_puts(const char*, FILE*); fputs()
23972 ** cli_vprintf(FILE*, const char*, va_list); vfprintf()
23973 **
23974 ** These are just thin wrappers with the following added semantics:
23975 ** If the file-scope variable cli_output_capture is not NULL, and
@@ -23991,10 +24896,18 @@
23991 }else{
23992 rc = sqlite3_vfprintf(out, zFormat, ap);
23993 }
23994 va_end(ap);
23995 return rc;
 
 
 
 
 
 
 
 
23996 }
23997 static int cli_puts(const char *zText, FILE *out){
23998 if( cli_output_capture && (out==stdout || out==stderr) ){
23999 sqlite3_str_appendall(cli_output_capture, zText);
24000 return 1;
@@ -24189,15 +25102,47 @@
24189
24190 /*
24191 ** The default prompts.
24192 */
24193 #ifndef SQLITE_PS1
24194 # define SQLITE_PS1 "SQLite /f> "
24195 #endif
24196 #ifndef SQLITE_PS2
24197 # define SQLITE_PS2 "/B.../H> "
24198 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24199
24200 /*
24201 ** Return the raw (unexpanded) prompt string. This will be the
24202 ** first of the following that exist:
24203 **
@@ -24236,11 +25181,14 @@
24236 zFN = p->pAuxDb->zDbFilename;
24237 }else if( p->db && (pFN = sqlite3_db_filename(p->db,0))!=0 ){
24238 zFN = sqlite3_filename_database(pFN);
24239 }
24240 if( zFN==0 || zFN[0]==0 ){
24241 zFN = "in-memory";
 
 
 
24242 }
24243 return zFN;
24244 }
24245
24246 /*
@@ -24262,16 +25210,17 @@
24262 const char *zPrompt /* Prompt string to be expanded */
24263 ){
24264 sqlite3_str *pOut = sqlite3_str_new(0);
24265 int i;
24266 char c;
24267 int onoff = 1;
24268 int idxSpace = -1;
 
24269 for(i=0; zPrompt[i]; i++){
24270 if( zPrompt[i]!='/' ) continue;
24271 if( i>0 ){
24272 if( onoff ) sqlite3_str_append(pOut, zPrompt, i);
24273 zPrompt += i;
24274 i = 0;
24275 }
24276 /* At this point zPrompt[0] is a / character and all prior
24277 ** characters have already been loaded into pOut. Process the
@@ -24290,18 +25239,27 @@
24290 /* /nnn becomes a single byte given by octal nnn */
24291 int v = c - '0';
24292 while( i<=2 && zPrompt[i+1]>='0' && zPrompt[i+1]<='7' ){
24293 v = v*8 + zPrompt[++i] - '0';
24294 }
24295 if( onoff ) sqlite3_str_appendchar(pOut, 1, v);
24296 zPrompt += i+1;
24297 i = -1;
24298 continue;
24299 }
24300 if( c=='e' ){
24301 /* /e is shorthand for /033 which is U+001B "Escape" */
24302 if( onoff ) sqlite3_str_append(pOut, "\033", 1);
 
 
 
 
 
 
 
 
 
24303 zPrompt += 2;
24304 i = -1;
24305 continue;
24306 }
24307
@@ -24317,36 +25275,43 @@
24317 ** or red if within a transaction:
24318 **
24319 ** .prompt '/e[1;/x31/:34/;m~f>/e[0m '
24320 */
24321 if( c==':' ){
24322 /* toggle display on/off */
24323 onoff = !onoff;
24324 zPrompt += 2;
24325 i = -1;
24326 continue;
24327 }
24328 if( c==';' ){
24329 /* Turn display on */
24330 onoff = 1;
24331 zPrompt += 2;
24332 i = -1;
24333 continue;
24334 }
24335 if( c=='x' ){
24336 /* /x turns display off not in a transaction, on if in txn */
24337 onoff = p->db && !sqlite3_get_autocommit(p->db);
 
 
 
 
 
 
 
24338 zPrompt += 2;
24339 i = -1;
24340 continue;
24341 }
24342
24343 if( c=='f' || c=='F' || c=='~' ){
24344 /* /f becomes the tail of the database filename */
24345 /* /F becomes the full pathname */
24346 /* /~ becomes the full pathname relative to $HOME */
24347 if( onoff ){
24348 const char *zFN = prompt_filename(p);
24349 if( c=='f' ){
24350 #ifdef _WIN32
24351 const char *zTail = strrchr(zFN,'\\');
24352 #else
@@ -24371,11 +25336,11 @@
24371 continue;
24372 }
24373
24374 if( c=='H' ){
24375 /* /H becomes text needed to terminate current input */
24376 if( onoff ){
24377 sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0;
24378 int cc = (R>>16)&0xff;
24379 int nParen = R>>32;
24380 int eSemi = (R>>8)&0xff;
24381 if( cc==0 ){
@@ -24405,22 +25370,48 @@
24405
24406 if( c=='B' ){
24407 /* /B is a no-op for the main prompt. For the continuation prompt,
24408 ** /B expands to zero or more spaces to make the continuation prompt
24409 ** at least as wide as the main prompt. */
24410 if( onoff ) idxSpace = sqlite3_str_length(pOut);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24411 zPrompt += 2;
24412 i = -1;
24413 continue;
24414 }
24415
24416 /* No match to a known escape. Generate an error. */
24417 if( onoff ) sqlite3_str_appendf(pOut,"UNKNOWN(\"/%c\")",c);
 
 
24418 zPrompt += 2;
24419 i = -1;
24420 }
24421 if( i>0 && onoff ){
24422 sqlite3_str_append(pOut, zPrompt, i);
24423 }
24424
24425 /* Expand the /B, if there is one and if this is a continuation prompt */
24426 if( idxSpace>=0 && zPrior!=0 && zPrior[0]!=0 ){
@@ -24440,11 +25431,15 @@
24440 memmove(z+idxSpace+nNew, z+idxSpace, len-nNew-idxSpace);
24441 memset(z+idxSpace, ' ', nNew);
24442 }
24443 }
24444 }
24445
 
 
 
 
24446 return sqlite3_str_finish(pOut);
24447 }
24448
24449 /*
24450 ** Retrieve a single line of input text.
@@ -25331,11 +26326,11 @@
25331 ** (2) Run program EDITOR on that temporary file.
25332 ** (3) Read the temporary file back and return its content as the result.
25333 ** (4) Delete the temporary file
25334 **
25335 ** If the EDITOR argument is omitted, use the value in the VISUAL
25336 ** environment variable. If still there is no EDITOR, through an error.
25337 **
25338 ** Also throw an error if the EDITOR program returns a non-zero exit code.
25339 */
25340 #ifndef SQLITE_NOHAVE_SYSTEM
25341 static void editFunc(
@@ -26688,11 +27683,11 @@
26688 /*
26689 ** QRF write callback
26690 */
26691 static int shellWriteQR(void *pX, const char *z, sqlite3_int64 n){
26692 ShellState *pArg = (ShellState*)pX;
26693 cli_printf(pArg->out, "%.*s", (int)n, z);
26694 return SQLITE_OK;
26695 }
26696
26697 /*
26698 ** Execute a statement or set of statements. Print
@@ -27230,10 +28225,11 @@
27230 ".databases List names and files of attached databases",
27231 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
27232 #if SQLITE_SHELL_HAVE_RECOVER
27233 ".dbinfo ?DB? Show status information about the database",
27234 #endif
 
27235 ".dbtotxt Hex dump of the database file",
27236 ".dump ?OBJECTS? Render database content as SQL",
27237 " Options:",
27238 " --data-only Output only INSERT statements",
27239 " --newlines Allow unescaped newline characters in output",
@@ -27262,11 +28258,11 @@
27262 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
27263 ".filectrl CMD ... Run various sqlite3_file_control() operations",
27264 " --schema SCHEMA Use SCHEMA instead of \"main\"",
27265 " --help Show CMD details",
27266 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
27267 ",headers on|off Turn display of headers on or off",
27268 ".help ?-all? ?PATTERN? Show help text for PATTERN",
27269 #ifndef SQLITE_SHELL_FIDDLE
27270 ".import FILE TABLE Import data from FILE into TABLE",
27271 #endif
27272 #ifndef SQLITE_OMIT_TEST_CONTROL
@@ -27274,11 +28270,11 @@
27274 #endif
27275 ".indexes ?PATTERN? Show names of indexes matching PATTERN",
27276 " -a|--all Also show system-generated indexes",
27277 " --expr Show only expression indexes",
27278 " --sys Show only system-generated indexes",
27279 ".intck ?STEPS_PER_UNLOCK? Run an incremental integrity check on the db",
27280 #ifdef SQLITE_ENABLE_IOTRACE
27281 ",iotrace FILE Enable I/O diagnostic logging to FILE",
27282 #endif
27283 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
27284 ".lint OPTIONS Report potential schema issues.",
@@ -27339,14 +28335,15 @@
27339 " --once Do no more than one progress interrupt",
27340 " --quiet|-q No output except at interrupts",
27341 " --reset Reset the count for each input and interrupt",
27342 " --timeout S Halt after running for S seconds",
27343 #endif
27344 ".prompt MAIN CONTINUE Replace the standard prompts",
27345 " --reset Revert to default prompts",
27346 " --show Show the current prompt strings",
27347 " -- No more options. Subsequent args are prompts",
 
27348 #ifndef SQLITE_SHELL_FIDDLE
27349 ".quit Stop interpreting input stream, exit if primary.",
27350 ".read FILE Read input from FILE or command output",
27351 " If FILE begins with \"|\", it is a command that generates the input.",
27352 #endif
@@ -27622,11 +28619,11 @@
27622 { ".testcase",
27623 "USAGE: .testcase [OPTIONS] NAME\n"
27624 "\n"
27625 "Start a new test case identified by NAME. All output\n"
27626 "through the next \".check\" command is captured for comparison. See the\n"
27627 "\".check\" commandn for additional informatioon.\n"
27628 "\n"
27629 "Options:\n"
27630 " --error-prefix TEXT Change error message prefix text to TEXT\n"
27631 },
27632 };
@@ -28237,10 +29234,11 @@
28237 sqlite3_base64_init(p->db, 0, 0);
28238 sqlite3_base85_init(p->db, 0, 0);
28239 sqlite3_regexp_init(p->db, 0, 0);
28240 sqlite3_ieee_init(p->db, 0, 0);
28241 sqlite3_series_init(p->db, 0, 0);
 
28242 #ifndef SQLITE_SHELL_FIDDLE
28243 sqlite3_fileio_init(p->db, 0, 0);
28244 sqlite3_completion_init(p->db, 0, 0);
28245 #endif
28246 #ifdef SQLITE_HAVE_ZLIB
@@ -29116,11 +30114,11 @@
29116 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
29117 if( system(zCmd) ){
29118 cli_printf(stderr,"Failed: [%s]\n", zCmd);
29119 }else{
29120 /* Give the start/open/xdg-open command some time to get
29121 ** going before we continue, and potential delete the
29122 ** p->zTempFile data file out from under it */
29123 sqlite3_sleep(2000);
29124 }
29125 sqlite3_free(zCmd);
29126 modePop(p);
@@ -32266,12 +33264,11 @@
32266 if( z[1]=='-' ) z++;
32267 if( cli_strcmp(z,"-bom")==0 ){
32268 zBom = zBomUtf8;
32269 }else if( cli_strcmp(z,"-plain")==0 ){
32270 bPlain = 1;
32271 }else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
32272 && (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
32273 if( bKeep || eMode ){
32274 dotCmdError(p, i, "incompatible with prior options",0);
32275 goto dotCmdOutput_error;
32276 }
32277 eMode = z[1];
@@ -32556,11 +33553,11 @@
32556 ** DOT-COMMAND: .testcase
32557 ** USAGE: .testcase [OPTIONS] NAME
32558 **
32559 ** Start a new test case identified by NAME. All output
32560 ** through the next ".check" command is captured for comparison. See the
32561 ** ".check" commandn for additional informatioon.
32562 **
32563 ** Options:
32564 ** --error-prefix TEXT Change error message prefix text to TEXT
32565 */
32566 static int dotCmdTestcase(ShellState *p){
@@ -33030,16 +34027,47 @@
33030
33031 #if SQLITE_SHELL_HAVE_RECOVER
33032 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
33033 rc = shell_dbinfo_command(p, nArg, azArg);
33034 }else
33035
33036 if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
33037 open_db(p, 0);
33038 rc = recoverDatabaseCmd(p, nArg, azArg);
33039 }else
33040 #endif /* SQLITE_SHELL_HAVE_RECOVER */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33041
33042 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
33043 char *zLike = 0;
33044 char *zSql;
33045 int i;
@@ -33167,15 +34195,10 @@
33167 eputz("Usage: .echo on|off\n");
33168 rc = 1;
33169 }
33170 }else
33171
33172 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
33173 open_db(p, 0);
33174 rc = shell_dbtotxt_command(p, nArg, azArg);
33175 }else
33176
33177 if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
33178 if( nArg==2 ){
33179 if( p->mode.autoEQPtrace ){
33180 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
33181 p->mode.autoEQPtrace = 0;
@@ -34139,10 +35162,20 @@
34139 int noOpt = 0;
34140 for(i=1; i<nArg; i++){
34141 const char *z = azArg[i];
34142 if( z[0]=='-' && !noOpt ){
34143 if( z[1]=='-' ) z++;
 
 
 
 
 
 
 
 
 
 
34144 if( strcmp(z,"-reset")==0 ){
34145 free(p->azPrompt[0]);
34146 free(p->azPrompt[1]);
34147 memset(p->azPrompt, 0, sizeof(p->azPrompt));
34148 }else
@@ -34160,13 +35193,16 @@
34160 }
34161 }else if( cnt>1 ){
34162 dotCmdError(p, i, "extra argument", 0);
34163 rc = 1;
34164 goto meta_command_exit;
 
 
34165 }else{
34166 free(p->azPrompt[cnt]);
34167 p->azPrompt[cnt] = strdup(z);
 
34168 }
34169 }
34170 }else
34171
34172 #ifndef SQLITE_SHELL_FIDDLE
@@ -34211,10 +35247,17 @@
34211 p->in = inSaved;
34212 p->lineno = savedLineno;
34213 }else
34214 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
34215
 
 
 
 
 
 
 
34216 #ifndef SQLITE_SHELL_FIDDLE
34217 if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
34218 const char *zSrcFile;
34219 const char *zDb;
34220 sqlite3 *pSrc;
@@ -37245,10 +38288,11 @@
37245 linenoiseSetCompletionCallback(linenoise_completion);
37246 #elif HAVE_LINENOISE==2
37247 linenoiseSetCompletionCallback(linenoise_completion, NULL);
37248 #endif
37249 data.in = 0;
 
37250 rc = process_input(&data, "<stdin>");
37251 if( zHistory ){
37252 shell_stifle_history(2000);
37253 shell_write_history(zHistory);
37254 sqlite3_free(zHistory);
37255
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,10 +5,11 @@
5 **
6 ** ext/expert/sqlite3expert.c
7 ** ext/expert/sqlite3expert.h
8 ** ext/intck/sqlite3intck.c
9 ** ext/intck/sqlite3intck.h
10 ** ext/misc/analyze.c
11 ** ext/misc/appendvfs.c
12 ** ext/misc/base64.c
13 ** ext/misc/base85.c
14 ** ext/misc/completion.c
15 ** ext/misc/decimal.c
@@ -1305,11 +1306,10 @@
1306 }
1307 }
1308 if( nRow>=0 ){
1309 if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
1310 qrfApproxInt64(pStats, nRow);
 
1311 if( p->spec.eStyle==QRF_STYLE_StatsEst ){
1312 sqlite3_str_appendf(pStats, " ");
1313 qrfApproxInt64(pStats, (i64)rEstCum);
1314 }
1315 }
@@ -1595,44 +1595,43 @@
1595 if( pnNL ) *pnNL = nNL;
1596 return n;
1597 }
1598
1599 /*
1600 ** Escape the text starting at byte iStart of pStr, if needed, using the
1601 ** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
1602 ** The pStr string is modified appropriately.
1603 **
1604 ** Escaping is needed if the string contains any control characters
1605 ** other than \t, \n, and \r\n
1606 **
1607 ** If no escaping is needed (the common case) then pStr is unchanged.
1608 ** If escaping is required, then pStr is expanded and modified to hold
1609 ** an escaped representation of the text.
 
 
 
 
1610 */
1611 static void qrfEscape(
1612 int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
1613 sqlite3_str *pStr, /* String to be escaped */
1614 int iStart /* Begin escapding on this byte of pStr */
1615 ){
1616 sqlite3_int64 i, j; /* Loop counters */
 
1617 sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
1618 unsigned char *zIn; /* Text to be escaped */
1619 unsigned int nIn; /* Bytes of text to be escaped */
1620 unsigned char c; /* A single character of the text */
1621 unsigned char *zOut; /* Where to write the results */
1622
1623 /* Find the text to be escaped */
1624 zIn = (unsigned char*)sqlite3_str_value(pStr);
1625 nIn = sqlite3_str_length(pStr);
1626 if( zIn==0 ) return;
1627 zIn += iStart;
1628 nIn -= iStart;
1629
1630 /* Count the control characters */
1631 for(i=0; i<nIn; i++){
1632 if( (c = zIn[i])<=0x1f
1633 && c!='\t'
1634 && c!='\n'
1635 && (c!='\r' || zIn[i+1]!='\n')
1636 ){
1637 nCtrl++;
@@ -1640,22 +1639,21 @@
1639 }
1640 if( nCtrl==0 ) return; /* Early out if no control characters */
1641
1642 /* Make space to hold the escapes. Copy the original text to the end
1643 ** of the available space. */
 
1644 if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
1645 sqlite3_str_appendchar(pStr, nCtrl, ' ');
1646 zOut = (unsigned char*)sqlite3_str_value(pStr);
1647 if( zOut==0 ) return;
1648 zOut += iStart;
1649 zIn = zOut + nCtrl;
1650 memmove(zIn,zOut,nIn);
1651
1652 /* Convert the control characters */
1653 for(i=j=0; i<nIn; i++){
1654 if( (c = zIn[i])>0x1f
1655 || c=='\t'
1656 || c=='\n'
1657 || (c=='\r' && zIn[i+1]=='\n')
1658 ){
1659 continue;
@@ -1663,10 +1661,11 @@
1661 if( i>0 ){
1662 memmove(&zOut[j], zIn, i);
1663 j += i;
1664 }
1665 zIn += i+1;
1666 nIn -= i+1;
1667 i = -1;
1668 if( eEsc==QRF_ESC_Symbol ){
1669 zOut[j++] = 0xe2;
1670 zOut[j++] = 0x90;
1671 zOut[j++] = 0x80+c;
@@ -2065,12 +2064,26 @@
2064 int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
2065 sqlite3_str_appendf(pOut, "(%d-byte blob)", nBlob);
2066 break;
2067 }
2068 default: {
2069 const void *pBlob = sqlite3_column_blob(p->pStmt,iCol);
2070 int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
2071 int rc;
2072 qrfWrite(p);
2073 if( nBlob==0 ){
2074 /* no-op */
2075 }else if( p->spec.eEsc==QRF_ESC_Off ){
2076 rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob);
2077 if( rc ){
2078 qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob);
2079 }
2080 }else{
2081 sqlite3_str_append(pOut, pBlob, nBlob);
2082 qrfEscape(p->spec.eEsc, pOut, 0);
2083 qrfWrite(p);
2084 }
2085 }
2086 }
2087 break;
2088 }
2089 case SQLITE_NULL: {
@@ -6005,11 +6018,11 @@
6018 }
6019 if( p->isNull ){
6020 sqlite3_result_null(pCtx);
6021 return;
6022 }
6023 z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+8 );
6024 if( z==0 ){
6025 sqlite3_result_error_nomem(pCtx);
6026 return;
6027 }
6028 i = 0;
@@ -9789,12 +9802,10 @@
9802 /* # include "windirent.h" */
9803 # include <direct.h>
9804 # define STRUCT_STAT struct _stat
9805 # define chmod(path,mode) fileio_chmod(path,mode)
9806 # define mkdir(path,mode) fileio_mkdir(path)
 
 
9807 #endif
9808 #include <time.h>
9809 #include <errno.h>
9810
9811 /* When used as part of the CLI, the sqlite3_stdio.h module will have
@@ -9817,17 +9828,73 @@
9828 #define FSDIR_COLUMN_DATA 3 /* File content */
9829 #define FSDIR_COLUMN_LEVEL 4 /* Level. Topmost is 1 */
9830 #define FSDIR_COLUMN_PATH 5 /* Path to top of search */
9831 #define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
9832
9833 #ifdef _WIN32
9834 /*
9835 ** Convert a UTF-8 string to Microsoft Unicode.
9836 **
9837 ** Space to hold the returned string is obtained from sqlite3_malloc().
9838 */
9839 static wchar_t *winUtf8To16(const char *zText){
9840 int nChar;
9841 wchar_t *zWideText;
9842
9843 nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
9844 if( nChar==0 ){
9845 return 0;
9846 }
9847 zWideText = sqlite3_malloc64(nChar*sizeof(WCHAR) );
9848 if( zWideText==0 ){
9849 return 0;
9850 }
9851 nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
9852 nChar);
9853 if( nChar==0 ){
9854 sqlite3_free(zWideText);
9855 zWideText = 0;
9856 }
9857 return zWideText;
9858 }
9859 #endif /* _WIN32 */
9860
9861 #ifdef _WIN32
9862 /*
9863 ** Convert a Microsoft Unicode string to UTF-8.
9864 **
9865 ** Space to hold the returned string is obtained from sqlite3_malloc().
9866 */
9867 static char *winUtf16To8(wchar_t *zWideText){
9868 int nByte;
9869 char *zText;
9870
9871 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
9872 if( nByte == 0 ){
9873 return 0;
9874 }
9875 zText = sqlite3_malloc64( nByte );
9876 if( zText==0 ){
9877 return 0;
9878 }
9879 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
9880 0, 0);
9881 if( nByte == 0 ){
9882 sqlite3_free(zText);
9883 zText = 0;
9884 }
9885 return zText;
9886 }
9887 #endif /* _WIN32 */
9888
9889 /*
9890 ** UTF8 chmod() function for Windows
9891 */
9892 #if defined(_WIN32) || defined(WIN32)
9893 static int fileio_chmod(const char *zPath, int pmode){
9894 int rc;
9895 wchar_t *b1 = winUtf8To16(zPath);
9896 if( b1==0 ) return -1;
9897 rc = _wchmod(b1, pmode);
9898 sqlite3_free(b1);
9899 return rc;
9900 }
@@ -9837,11 +9904,11 @@
9904 ** UTF8 mkdir() function for Windows
9905 */
9906 #if defined(_WIN32) || defined(WIN32)
9907 static int fileio_mkdir(const char *zPath){
9908 int rc;
9909 wchar_t *b1 = winUtf8To16(zPath);
9910 if( b1==0 ) return -1;
9911 rc = _wmkdir(b1);
9912 sqlite3_free(b1);
9913 return rc;
9914 }
@@ -9964,11 +10031,11 @@
10031 const char *zPath,
10032 STRUCT_STAT *pStatBuf
10033 ){
10034 #if defined(_WIN32)
10035 int rc;
10036 wchar_t *b1 = winUtf8To16(zPath);
10037 if( b1==0 ) return 1;
10038 rc = _wstat(b1, pStatBuf);
10039 if( rc==0 ){
10040 HANDLE hFindFile;
10041 WIN32_FIND_DATAW fd;
@@ -10117,18 +10184,17 @@
10184 FILETIME lastWrite;
10185 SYSTEMTIME currentTime;
10186 LONGLONG intervals;
10187 HANDLE hFile;
10188 LPWSTR zUnicodeName;
 
10189
10190 GetSystemTime(&currentTime);
10191 SystemTimeToFileTime(&currentTime, &lastAccess);
10192 intervals = (mtime*10000000) + 116444736000000000;
10193 lastWrite.dwLowDateTime = (DWORD)intervals;
10194 lastWrite.dwHighDateTime = intervals >> 32;
10195 zUnicodeName = winUtf8To16(zFile);
10196 if( zUnicodeName==0 ){
10197 return 1;
10198 }
10199 hFile = CreateFileW(
10200 zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
@@ -10782,16 +10848,16 @@
10848 char *zOut = 0; /* Result */
10849 wchar_t *z = 0; /* Temporary buffer */
10850
10851 if( zPath==0 ) return 0;
10852
10853 zPath16 = winUtf8To16(zPath);
10854 if( zPath16==0 ) return 0;
10855 z = _wfullpath(NULL, zPath16, 0);
10856 sqlite3_free(zPath16);
10857 if( z ){
10858 zOut = winUtf16To8(z);
10859 free(z);
10860 }
10861 return zOut;
10862
10863 #endif /* End WINDOWS, Begin common code */
@@ -19398,10 +19464,848 @@
19464 sqlite3_vfs_unregister(pVfs);
19465 sqlite3_free(pVfs);
19466 }
19467
19468 /************************* End ext/misc/vfstrace.c ********************/
19469 /************************* Begin ext/misc/analyze.c ******************/
19470 /*
19471 ** 2026-04-13
19472 **
19473 ** The author disclaims copyright to this source code. In place of
19474 ** a legal notice, here is a blessing:
19475 **
19476 ** May you do good and not evil.
19477 ** May you find forgiveness for yourself and forgive others.
19478 ** May you share freely, never taking more than you give.
19479 **
19480 ******************************************************************************
19481 **
19482 ** Partial reimplement of the sqlite3_analyzer utility program as
19483 ** loadable SQL function.
19484 */
19485 /* #include "sqlite3ext.h" */
19486 SQLITE_EXTENSION_INIT1
19487 #include <assert.h>
19488 #include <string.h>
19489 #include <ctype.h>
19490 #include <math.h>
19491
19492 /*
19493 ** State information for the analysis
19494 */
19495 typedef struct Analysis Analysis;
19496 struct Analysis {
19497 sqlite3 *db; /* Database connection */
19498 sqlite3_context *context; /* SQL function context */
19499 sqlite3_str *pOut; /* Write output here */
19500 char *zSU; /* Name of the temp.space_used table */
19501 const char *zSchema; /* Schema to be analyzed */
19502 };
19503
19504 /*
19505 ** Free all resources that the Analysis object references and
19506 ** reset the Analysis object.
19507 **
19508 ** Call this routine multiple times on the same Analysis object
19509 ** is a harmless no-op, as long as the memory for the object itself
19510 ** has not been freed.
19511 */
19512 static void analysisReset(Analysis *p){
19513 if( p->zSU ){
19514 char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
19515 if( zSql ){
19516 sqlite3_exec(p->db, zSql, 0, 0, 0);
19517 sqlite3_free(zSql);
19518 }
19519 }
19520 sqlite3_str_free(p->pOut);
19521 sqlite3_free(p->zSU);
19522 memset(p, 0, sizeof(*p));
19523 }
19524
19525 /*
19526 ** Report an error using formatted text. If zFormat==NULL then report
19527 ** an OOM error.
19528 */
19529 static void analysisError(Analysis *p, const char *zFormat, ...){
19530 char *zErr;
19531 if( zFormat ){
19532 va_list ap;
19533 va_start(ap, zFormat);
19534 zErr = sqlite3_vmprintf(zFormat, ap);
19535 va_end(ap);
19536 }else{
19537 zErr = 0;
19538 }
19539 if( zErr==0 ){
19540 sqlite3_result_error_nomem(p->context);
19541 }else{
19542 sqlite3_result_error(p->context, zErr, -1);
19543 sqlite3_free(zErr);
19544 }
19545 analysisReset(p);
19546 }
19547
19548 /*
19549 ** Prepare and return an SQL statement.
19550 */
19551 static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
19552 char *zSql;
19553 int rc;
19554 sqlite3_stmt *pStmt = 0;
19555 zSql = sqlite3_vmprintf(zFmt, ap);
19556 if( zSql==0 ){ analysisError(p,0); return 0; }
19557 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19558 if( rc ){
19559 analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
19560 sqlite3_errmsg(p->db), zSql);
19561 sqlite3_finalize(pStmt);
19562 analysisReset(p);
19563 pStmt = 0;
19564 }
19565 sqlite3_free(zSql);
19566 return pStmt;
19567 }
19568 static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
19569 va_list ap;
19570 sqlite3_stmt *pStmt = 0;
19571 va_start(ap, zFormat);
19572 pStmt = analysisVPrep(p,zFormat,ap);
19573 va_end(ap);
19574 return pStmt;
19575 }
19576
19577 /*
19578 ** If rc is something other than SQLITE_DONE or SQLITE_OK, then report
19579 ** an error and return true.
19580 **
19581 ** If rc is SQLITE_DONE or SQLITE_OK, then return false.
19582 **
19583 ** The prepared statement is closed in either case.
19584 */
19585 static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
19586 if( rc==SQLITE_DONE ){
19587 rc = SQLITE_OK;
19588 }
19589 if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19590 analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19591 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19592 analysisReset(p);
19593 }
19594 sqlite3_finalize(pStmt);
19595 return rc;
19596 }
19597
19598 /*
19599 ** Run SQL. Return the number of errors.
19600 */
19601 static int analysisSql(Analysis *p, const char *zFormat, ...){
19602 va_list ap;
19603 int rc;
19604 sqlite3_stmt *pStmt = 0;
19605 va_start(ap, zFormat);
19606 pStmt = analysisVPrep(p,zFormat,ap);
19607 va_end(ap);
19608 if( pStmt==0 ) return 1;
19609 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
19610 if( rc==SQLITE_DONE ){
19611 rc = SQLITE_OK;
19612 }else{
19613 analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19614 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19615 analysisReset(p);
19616 }
19617 sqlite3_finalize(pStmt);
19618 return rc;
19619 }
19620
19621 /*
19622 ** Run an SQL query that returns an integer. Write that integer
19623 ** into *piRes. Return the number of errors.
19624 */
19625 static int analysisSqlInt(
19626 Analysis *p,
19627 sqlite3_int64 *piRes,
19628 const char *zFormat, ...
19629 ){
19630 va_list ap;
19631 int rc;
19632 sqlite3_stmt *pStmt = 0;
19633 va_start(ap, zFormat);
19634 pStmt = analysisVPrep(p,zFormat,ap);
19635 va_end(ap);
19636 if( pStmt==0 ) return 1;
19637 rc = sqlite3_step(pStmt);
19638 if( rc==SQLITE_ROW ){
19639 *piRes = sqlite3_column_int64(pStmt, 0);
19640 rc = SQLITE_OK;
19641 }else if( rc==SQLITE_DONE ){
19642 rc = SQLITE_OK;
19643 }else{
19644 if( p->db ){
19645 /* p->db is NULL if there was some prior error */
19646 analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19647 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19648 }
19649 analysisReset(p);
19650 }
19651 sqlite3_finalize(pStmt);
19652 return rc;
19653 }
19654
19655 /*
19656 ** Add to the output a title line that contains the text determined
19657 ** by the format string. If the output is initially empty, begin
19658 ** the title line with "/" so that it forms the beginning of a C-style
19659 ** comment. Otherwise begin with a new-line. Always finish with a
19660 ** newline.
19661 */
19662 static void analysisTitle(Analysis *p, const char *zFormat, ...){
19663 char *zFirst;
19664 char *zTitle;
19665 size_t nTitle;
19666 va_list ap;
19667 va_start(ap, zFormat);
19668 zTitle = sqlite3_vmprintf(zFormat, ap);
19669 va_end(ap);
19670 if( zTitle==0 ){
19671 analysisError(p, 0);
19672 return;
19673 }
19674 zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
19675 nTitle = strlen(zTitle);
19676 if( nTitle>=75 ){
19677 sqlite3_str_appendf(p->pOut, "%s** %z\n\n", zFirst, zTitle);
19678 }else{
19679 int nExtra = 74 - (int)nTitle;
19680 sqlite3_str_appendf(p->pOut, "%s** %z %.*c\n\n", zFirst, zTitle,
19681 nExtra, '*');
19682 }
19683 }
19684
19685 /*
19686 ** Add an output line that begins with the zDesc text extended out to
19687 ** 50 columns with "." characters, and followed by whatever text is
19688 ** described by zFormat.
19689 */
19690 static void analysisLine(
19691 Analysis *p, /* Analysis context */
19692 const char *zDesc, /* Description */
19693 const char *zFormat, /* Argument to the description */
19694 ...
19695 ){
19696 char *zTxt;
19697 size_t nDesc;
19698 va_list ap;
19699 va_start(ap, zFormat);
19700 zTxt = sqlite3_vmprintf(zFormat, ap);
19701 va_end(ap);
19702 if( zTxt==0 ){
19703 analysisError(p, 0);
19704 return;
19705 }
19706 nDesc = strlen(zDesc);
19707 if( nDesc>=50 ){
19708 sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
19709 }else{
19710 int nExtra = 50 - (int)nDesc;
19711 sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
19712 }
19713 }
19714
19715 /*
19716 ** Write a percentage into the output. The number written should show
19717 ** two or three significant digits, with the decimal point being the fourth
19718 ** character.
19719 */
19720 static void analysisPercent(Analysis *p, double r){
19721 char zNum[100];
19722 char *zDP;
19723 int nLeadingDigit;
19724 int sz;
19725 sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
19726 sz = (int)strlen(zNum);
19727 zDP = strchr(zNum, '.');
19728 if( zDP==0 ){
19729 memcpy(zNum+sz,".0",3);
19730 nLeadingDigit = sz;
19731 sz += 2;
19732 }else{
19733 nLeadingDigit = (int)(zDP - zNum);
19734 }
19735 if( nLeadingDigit<3 ){
19736 sqlite3_str_appendchar(p->pOut, 3-nLeadingDigit, ' ');
19737 }
19738 sqlite3_str_append(p->pOut, zNum, sz);
19739 sqlite3_str_append(p->pOut, "%\n", 2);
19740 }
19741
19742 /*
19743 ** Create a subreport on a subset of tables and/or indexes.
19744 **
19745 ** The title if the subreport is given by zTitle. zWhere is
19746 ** a boolean expression that can go in the WHERE clause to select
19747 ** the relevant rows of the s.zSU table.
19748 */
19749 static int analysisSubreport(
19750 Analysis *p, /* Analysis context */
19751 char *zTitle, /* Title for this subreport */
19752 char *zWhere, /* WHERE clause for this subreport */
19753 sqlite3_int64 pgsz, /* Database page size */
19754 sqlite3_int64 nPage /* Number of pages in entire database */
19755 ){
19756 sqlite3_stmt *pStmt; /* Statement to query p->zSU */
19757 sqlite3_int64 nentry; /* Number of btree entires */
19758 sqlite3_int64 payload; /* Payload in bytes */
19759 sqlite3_int64 ovfl_payload; /* overflow payload in bytes */
19760 sqlite3_int64 mx_payload; /* largest individual payload */
19761 sqlite3_int64 ovfl_cnt; /* Number entries using overflow */
19762 sqlite3_int64 leaf_pages; /* Leaf pages */
19763 sqlite3_int64 int_pages; /* internal pages */
19764 sqlite3_int64 ovfl_pages; /* overflow pages */
19765 sqlite3_int64 leaf_unused; /* unused bytes on leaf pages */
19766 sqlite3_int64 int_unused; /* unused bytes on internal pages */
19767 sqlite3_int64 ovfl_unused; /* unused bytes on overflow pages */
19768 sqlite3_int64 int_cell; /* B-tree entries on internal pages */
19769 sqlite3_int64 depth; /* btree depth */
19770 sqlite3_int64 cnt; /* Number of s.zSU entries that match */
19771 sqlite3_int64 storage; /* Total bytes */
19772 sqlite3_int64 total_pages; /* Total page count */
19773 sqlite3_int64 total_unused; /* Total unused bytes */
19774 sqlite3_int64 total_meta; /* Total metadata */
19775 int rc;
19776
19777 if( zTitle==0 || zWhere==0 ){
19778 analysisError(p, 0);
19779 return SQLITE_NOMEM;
19780 }
19781 pStmt = analysisPrepare(p,
19782 "SELECT\n"
19783 " sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
19784 " sum(payload),\n" /* 1 */
19785 " sum(ovfl_payload),\n" /* 2 */
19786 " max(mx_payload),\n" /* 3 */
19787 " sum(ovfl_cnt),\n" /* 4 */
19788 " sum(leaf_pages),\n" /* 5 */
19789 " sum(int_pages),\n" /* 6 */
19790 " sum(ovfl_pages),\n" /* 7 */
19791 " sum(leaf_unused),\n" /* 8 */
19792 " sum(int_unused),\n" /* 9 */
19793 " sum(ovfl_unused),\n" /* 10 */
19794 " max(depth),\n" /* 11 */
19795 " count(*),\n" /* 12 */
19796 " sum(int_entries)\n" /* 13 */
19797 " FROM temp.%s WHERE %s",
19798 p->zSU, zWhere);
19799 if( pStmt==0 ) return 1;
19800 rc = sqlite3_step(pStmt);
19801 if( rc==SQLITE_ROW ){
19802 analysisTitle(p, zTitle);
19803
19804 nentry = sqlite3_column_int64(pStmt, 0);
19805 payload = sqlite3_column_int64(pStmt, 1);
19806 ovfl_payload = sqlite3_column_int64(pStmt, 2);
19807 mx_payload = sqlite3_column_int64(pStmt, 3);
19808 ovfl_cnt = sqlite3_column_int64(pStmt, 4);
19809 leaf_pages = sqlite3_column_int64(pStmt, 5);
19810 int_pages = sqlite3_column_int64(pStmt, 6);
19811 ovfl_pages = sqlite3_column_int64(pStmt, 7);
19812 leaf_unused = sqlite3_column_int64(pStmt, 8);
19813 int_unused = sqlite3_column_int64(pStmt, 9);
19814 ovfl_unused = sqlite3_column_int64(pStmt, 10);
19815 depth = sqlite3_column_int64(pStmt, 11);
19816 cnt = sqlite3_column_int64(pStmt, 12);
19817 int_cell = sqlite3_column_int64(pStmt, 13);
19818 rc = SQLITE_DONE;
19819
19820 total_pages = leaf_pages + int_pages + ovfl_pages;
19821 analysisLine(p, "Percentage of total database", "%.3g%%\n",
19822 (total_pages*100.0)/(double)nPage);
19823 analysisLine(p, "Number of entries", "%lld\n", nentry);
19824 storage = total_pages*pgsz;
19825 analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
19826 analysisLine(p, "Bytes of payload", "%-11lld ", payload);
19827 analysisPercent(p, payload*100.0/(double)storage);
19828 if( ovfl_cnt>0 ){
19829 analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19830 analysisPercent(p, ovfl_payload*100.0/(double)payload);
19831 }
19832 total_unused = leaf_unused + int_unused + ovfl_unused;
19833 total_meta = storage - payload - total_unused;
19834 analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
19835 analysisPercent(p, total_meta*100.0/(double)storage);
19836 if( cnt==1 ){
19837 analysisLine(p, "B-tree depth", "%lld\n", depth);
19838 if( int_cell>1 ){
19839 analysisLine(p, "Average fanout", "%.1f\n",
19840 (double)(int_cell+int_pages)/(double)int_pages);
19841 }
19842 }
19843 if( nentry>0 ){
19844 analysisLine(p, "Average payload per entry", "%.1f\n",
19845 (double)payload/(double)nentry);
19846 analysisLine(p, "Average unused bytes per entry", "%.1f\n",
19847 (double)total_unused/(double)nentry);
19848 analysisLine(p, "Average metadata per entry", "%.1f\n",
19849 (double)total_meta/(double)nentry);
19850 }
19851 analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19852 if( nentry>0 ){
19853 analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19854 analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
19855 }
19856 if( int_pages>0 ){
19857 analysisLine(p, "Index pages used", "%lld\n", int_pages);
19858 }
19859 analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
19860 if( ovfl_cnt ){
19861 analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19862 }
19863 analysisLine(p, "Total pages used", "%lld\n", total_pages);
19864 if( int_pages>0 ){
19865 analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19866 }
19867 analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19868 if( ovfl_cnt ){
19869 analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19870 }
19871 analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19872 analysisPercent(p, total_unused*100.0/(double)storage);
19873 }
19874 return analysisStmtFinish(p, rc, pStmt);
19875 }
19876
19877 /*
19878 ** SQL Function: analyze(SCHEMA)
19879 **
19880 ** Analyze the database schema named in the argument. Return text
19881 ** containing the analysis.
19882 */
19883 static void analyzeFunc(
19884 sqlite3_context *context,
19885 int argc,
19886 sqlite3_value **argv
19887 ){
19888 int rc;
19889 sqlite3_stmt *pStmt;
19890 int n;
19891 sqlite3_int64 i64;
19892 sqlite3_int64 pgsz;
19893 sqlite3_int64 nPage;
19894 sqlite3_int64 nPageInUse;
19895 sqlite3_int64 nFreeList;
19896 sqlite3_int64 nIndex;
19897 sqlite3_int64 nWORowid;
19898 Analysis s;
19899 sqlite3_uint64 r[2];
19900
19901 memset(&s, 0, sizeof(s));
19902 s.db = sqlite3_context_db_handle(context);
19903 s.context = context;
19904 s.pOut = sqlite3_str_new(0);
19905 if( sqlite3_str_errcode(s.pOut) ){
19906 analysisError(&s, 0);
19907 return;
19908 }
19909 s.zSchema = (const char*)sqlite3_value_text(argv[0]);
19910 if( s.zSchema==0 ){
19911 s.zSchema = "main";
19912 }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19913 analysisReset(&s);
19914 sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
19915 return;
19916 }
19917 i64 = 0;
19918 rc = analysisSqlInt(&s,&i64,"SELECT 1 FROM pragma_database_list"
19919 " WHERE name=%Q COLLATE nocase",s.zSchema);
19920 if( rc || i64==0 ){
19921 analysisReset(&s);
19922 sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
19923 return;
19924 }
19925 sqlite3_randomness(sizeof(r), &r);
19926 s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
19927 if( s.zSU==0 ){ analysisError(&s, 0); return; }
19928
19929 /* The s.zSU table contains the data used for the analysis.
19930 ** The table name contains 128-bits of randomness to avoid
19931 ** collisions with preexisting tables in temp.
19932 */
19933 rc = analysisSql(&s,
19934 "CREATE TABLE temp.%s(\n"
19935 " name text, -- A table or index\n"
19936 " tblname text, -- Table that owns name\n"
19937 " is_index boolean, -- TRUE if it is an index\n"
19938 " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
19939 " nentry int, -- Number of entries in the BTree\n"
19940 " leaf_entries int, -- Number of leaf entries\n"
19941 " depth int, -- Depth of the b-tree\n"
19942 " payload int, -- Total data stored in this table/index\n"
19943 " ovfl_payload int, -- Total data stored on overflow pages\n"
19944 " ovfl_cnt int, -- Number of entries that use overflow\n"
19945 " mx_payload int, -- Maximum payload size\n"
19946 " int_pages int, -- Interior pages used\n"
19947 " leaf_pages int, -- Leaf pages used\n"
19948 " ovfl_pages int, -- Overflow pages used\n"
19949 " int_unused int, -- Unused bytes on interior pages\n"
19950 " leaf_unused int, -- Unused bytes on primary pages\n"
19951 " ovfl_unused int, -- Unused bytes on overflow pages\n"
19952 " int_entries int -- Btree cells on internal pages\n"
19953 ");",
19954 s.zSU
19955 );
19956 if( rc ) return;
19957
19958 /* Populate the s.zSU table
19959 */
19960 rc = analysisSql(&s,
19961 "WITH\n"
19962 " allidx(idxname) AS (\n"
19963 " SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
19964 " ),\n"
19965 " allobj(allname,tblname,isidx,isworowid) AS (\n"
19966 " SELECT 'sqlite_schema',\n"
19967 " 'sqlite_schema',\n"
19968 " 0,\n"
19969 " 0\n"
19970 " UNION ALL\n"
19971 " SELECT name,\n"
19972 " tbl_name,\n"
19973 " type='index',\n"
19974 " EXISTS(SELECT 1\n"
19975 " FROM pragma_index_list(sqlite_schema.name,%Q)\n"
19976 " WHERE pragma_index_list.origin='pk'\n"
19977 " AND pragma_index_list.name NOT IN allidx)\n"
19978 " FROM \"%w\".sqlite_schema\n"
19979 " )\n"
19980 "INSERT INTO temp.%s\n"
19981 " SELECT\n"
19982 " allname,\n"
19983 " tblname,\n"
19984 " isidx,\n"
19985 " isworowid,\n"
19986 " sum(ncell),\n"
19987 " sum((pagetype='leaf')*ncell),\n"
19988 " max((length(if(path GLOB '*+*','',path))+3)/4),\n"
19989 " sum(payload),\n"
19990 " sum((pagetype='overflow')*payload),\n"
19991 " sum(path GLOB '*+000000'),\n"
19992 " max(mx_payload),\n"
19993 " sum(pagetype='internal'),\n"
19994 " sum(pagetype='leaf'),\n"
19995 " sum(pagetype='overflow'),\n"
19996 " sum((pagetype='internal')*unused),\n"
19997 " sum((pagetype='leaf')*unused),\n"
19998 " sum((pagetype='overflow')*unused),\n"
19999 " sum(if(pagetype='internal',ncell))\n"
20000 " FROM allobj CROSS JOIN dbstat(%Q) \n"
20001 " WHERE dbstat.name=allobj.allname\n"
20002 " GROUP BY allname;\n",
20003 s.zSchema, /* %w.sqlite_schema -- in allidx */
20004 s.zSchema, /* pragma_index_list(...,%Q) */
20005 s.zSchema, /* %w.sqlite_schema */
20006 s.zSU, /* INTO temp.%s */
20007 s.zSchema /* JOIN dbstat(%Q) */
20008 );
20009 if( rc ) return;
20010
20011 nPage = 0;
20012 rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20013 if( rc ) return;
20014 if( nPage<=0 ){
20015 /* Very brief reply for an empty database */
20016 analysisReset(&s);
20017 sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
20018 return;
20019 }
20020
20021 /* Begin generating the report */
20022 analysisTitle(&s, "Database storage utilization report");
20023 pgsz = 0;
20024 rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20025 if( rc ) return;
20026 analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
20027 analysisLine(&s, "Pages in the database", "%lld\n", nPage);
20028
20029 nPageInUse = 0;
20030 rc = analysisSqlInt(&s, &nPageInUse,
20031 "SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
20032 if( rc ) return;
20033 analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20034 analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
20035
20036 nFreeList = 0;
20037 rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20038 if( rc ) return;
20039 analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20040 analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
20041
20042 i64 = 0;
20043 rc = analysisSqlInt(&s, &i64, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20044 if( rc ) return;
20045 if( i64==0 || nPage<=1 ){
20046 i64 = 0;
20047 }else{
20048 double rPtrsPerPage = pgsz/5;
20049 double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
20050 i64 = (sqlite3_int64)ceil(rAvPage);
20051 }
20052 analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", i64);
20053 analysisPercent(&s, (i64*100.0)/(double)nPage);
20054
20055 i64 = 0;
20056 rc = analysisSqlInt(&s, &i64,
20057 "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
20058 s.zSchema);
20059 if( rc ) return;
20060 analysisLine(&s, "Number of tables", "%lld\n", i64);
20061 nWORowid = 0;
20062 rc = analysisSqlInt(&s, &nWORowid,
20063 "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
20064 s.zSchema);
20065 if( rc ) return;
20066 if( nWORowid>0 ){
20067 analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20068 analysisLine(&s, "Number of rowid tables", "%lld\n", i64 - nWORowid);
20069 }
20070 nIndex = 0;
20071 rc = analysisSqlInt(&s, &nIndex,
20072 "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
20073 s.zSchema);
20074 if( rc ) return;
20075 analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
20076 i64 = 0;
20077 rc = analysisSqlInt(&s, &i64,
20078 "SELECT count(*) FROM \"%w\".sqlite_schema"
20079 " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
20080 s.zSchema);
20081 if( rc ) return;
20082 analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - i64);
20083 analysisLine(&s, "Number of implied indexes", "%lld\n", i64);
20084 analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20085 i64 = 0;
20086 rc = analysisSqlInt(&s, &i64,
20087 "SELECT sum(payload) FROM temp.%s"
20088 " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
20089 s.zSU);
20090 if( rc ) return;
20091 analysisLine(&s, "Bytes of payload", "%-11lld ", i64);
20092 analysisPercent(&s, i64*100.0/(double)(pgsz*nPage));
20093
20094 analysisTitle(&s, "Page counts for all tables with their indexes");
20095 pStmt = analysisPrepare(&s,
20096 "SELECT upper(tblname),\n"
20097 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20098 " FROM temp.%s\n"
20099 " GROUP BY 1\n"
20100 " ORDER BY 2 DESC, 1;",
20101 s.zSU);
20102 if( pStmt==0 ) return;
20103 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20104 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20105 analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20106 analysisPercent(&s, (nn*100.0)/(double)nPage);
20107 }
20108 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20109
20110 analysisTitle(&s, "Page counts for all tables and indexes separately");
20111 pStmt = analysisPrepare(&s,
20112 "SELECT upper(name),\n"
20113 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20114 " FROM temp.%s\n"
20115 " GROUP BY 1\n"
20116 " ORDER BY 2 DESC, 1;",
20117 s.zSU);
20118 if( pStmt==0 ) return;
20119 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20120 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20121 analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20122 analysisPercent(&s, (nn*100.0)/(double)nPage);
20123 }
20124 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20125
20126 rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
20127 if( rc ) return;
20128 rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20129 if( rc ) return;
20130 if( nWORowid>0 ){
20131 rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20132 pgsz, nPage);
20133 if( rc ) return;
20134 rc = analysisSubreport(&s, "All rowid tables",
20135 "NOT is_without_rowid AND NOT is_index",
20136 pgsz, nPage);
20137 if( rc ) return;
20138 }
20139 rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20140 if( rc ) return;
20141
20142 pStmt = analysisPrepare(&s,
20143 "SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
20144 " GROUP BY 1 ORDER BY 1",
20145 s.zSU);
20146 if( pStmt==0 ) return;
20147 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20148 const char *zUpper = (const char*)sqlite3_column_text(pStmt, 0);
20149 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
20150 int nSubIndex = sqlite3_column_int(pStmt, 2);
20151 if( nSubIndex==0 ){
20152 char *zTitle = sqlite3_mprintf("Table %s", zUpper);
20153 char *zWhere = sqlite3_mprintf("name=%Q", zName);
20154 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20155 sqlite3_free(zTitle);
20156 sqlite3_free(zWhere);
20157 if( rc ) break;
20158 }else{
20159 sqlite3_stmt *pS2;
20160 char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
20161 char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20162 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20163 sqlite3_free(zTitle);
20164 sqlite3_free(zWhere);
20165 if( rc ) break;
20166 zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
20167 zWhere = sqlite3_mprintf("name=%Q", zName);
20168 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20169 sqlite3_free(zTitle);
20170 sqlite3_free(zWhere);
20171 if( rc ) break;
20172 if( nSubIndex>1 ){
20173 zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
20174 zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20175 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20176 sqlite3_free(zTitle);
20177 sqlite3_free(zWhere);
20178 if( rc ) break;
20179 }
20180 pS2 = analysisPrepare(&s,
20181 "SELECT name, upper(name) FROM temp.%s"
20182 " WHERE is_index AND tblname=%Q",
20183 s.zSU, zName);
20184 if( pS2==0 ){
20185 rc = SQLITE_NOMEM;
20186 break;
20187 }
20188 while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
20189 const char *zU = (const char*)sqlite3_column_text(pS2, 1);
20190 const char *zN = (const char*)sqlite3_column_text(pS2, 0);
20191 zTitle = sqlite3_mprintf("Index %s", zU);
20192 zWhere = sqlite3_mprintf("name=%Q", zN);
20193 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20194 sqlite3_free(zTitle);
20195 sqlite3_free(zWhere);
20196 if( rc ) break;
20197 }
20198 rc = analysisStmtFinish(&s, rc, pS2);
20199 if( rc ) break;
20200 }
20201 }
20202 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20203
20204 /* Append SQL statements that will recreate the raw data used for
20205 ** the analysis.
20206 */
20207 analysisTitle(&s, "Raw data used to generate this report");
20208 sqlite3_str_appendf(s.pOut,
20209 "The following SQL will create a table named \"space_used\" which\n"
20210 "contains most of the information used to generate the report above.\n"
20211 "*/\n"
20212 );
20213 sqlite3_str_appendf(s.pOut,
20214 "BEGIN;\n"
20215 "CREATE TABLE space_used(\n"
20216 " name text, -- A table or index\n" /* 0 */
20217 " tblname text, -- Table that owns name\n" /* 1 */
20218 " is_index boolean, -- TRUE if it is an index\n" /* 2 */
20219 " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n" /* 3 */
20220 " nentry int, -- Number of entries in the BTree\n" /* 4 */
20221 " leaf_entries int, -- Number of leaf entries\n" /* 5 */
20222 " depth int, -- Depth of the b-tree\n" /* 6 */
20223 " payload int, -- Total data in this table/index\n" /* 7 */
20224 " ovfl_payload int, -- Total data on overflow pages\n" /* 8 */
20225 " ovfl_cnt int, -- Entries that use overflow\n" /* 9 */
20226 " mx_payload int, -- Maximum payload size\n" /* 10 */
20227 " int_pages int, -- Interior pages used\n" /* 11 */
20228 " leaf_pages int, -- Leaf pages used\n" /* 12 */
20229 " ovfl_pages int, -- Overflow pages used\n" /* 13 */
20230 " int_unused int, -- Unused bytes on interior pages\n" /* 14 */
20231 " leaf_unused int, -- Unused bytes on primary pages\n" /* 15 */
20232 " ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
20233 " int_entries int -- B-tree entries on internal pages\n"/* 17 */
20234 ");\n"
20235 "INSERT INTO space_used VALUES\n"
20236 );
20237 pStmt = analysisPrepare(&s,
20238 "SELECT quote(name), quote(tblname),\n" /* 0..1 */
20239 " is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
20240 " depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
20241 " int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
20242 " leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
20243 " FROM temp.%s;",
20244 s.zSU);
20245 if( pStmt==0 ) return;
20246 n = 0;
20247 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20248 if( n++ ) sqlite3_str_appendf(s.pOut,",\n");
20249 sqlite3_str_appendf(s.pOut,
20250 " (%s,%s,%lld,%lld,%lld,%lld,%lld,%lld,%lld,"
20251 "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld)",
20252 sqlite3_column_text(pStmt, 0),
20253 sqlite3_column_text(pStmt, 1),
20254 sqlite3_column_int64(pStmt, 2),
20255 sqlite3_column_int64(pStmt, 3),
20256 sqlite3_column_int64(pStmt, 4),
20257 sqlite3_column_int64(pStmt, 5),
20258 sqlite3_column_int64(pStmt, 6),
20259 sqlite3_column_int64(pStmt, 7),
20260 sqlite3_column_int64(pStmt, 8),
20261 sqlite3_column_int64(pStmt, 9),
20262 sqlite3_column_int64(pStmt, 10),
20263 sqlite3_column_int64(pStmt, 11),
20264 sqlite3_column_int64(pStmt, 12),
20265 sqlite3_column_int64(pStmt, 13),
20266 sqlite3_column_int64(pStmt, 14),
20267 sqlite3_column_int64(pStmt, 15),
20268 sqlite3_column_int64(pStmt, 16),
20269 sqlite3_column_int64(pStmt, 17));
20270 }
20271 if( rc!=SQLITE_DONE ){
20272 analysisError(&s, "SQL run-time error: %s\nSQL: %s",
20273 sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
20274 sqlite3_finalize(pStmt);
20275 return;
20276 }
20277 sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
20278 sqlite3_finalize(pStmt);
20279
20280 if( sqlite3_str_length(s.pOut) ){
20281 sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
20282 sqlite3_free);
20283 s.pOut = 0;
20284 }
20285 analysisReset(&s);
20286 }
20287
20288
20289 #ifdef _WIN32
20290
20291 #endif
20292 int sqlite3_analyze_init(
20293 sqlite3 *db,
20294 char **pzErrMsg,
20295 const sqlite3_api_routines *pApi
20296 ){
20297 int rc = SQLITE_OK;
20298 SQLITE_EXTENSION_INIT2(pApi);
20299 (void)pzErrMsg; /* Unused parameter */
20300 rc = sqlite3_create_function(db, "analyze", 1,
20301 SQLITE_UTF8|SQLITE_INNOCUOUS,
20302 0, analyzeFunc, 0, 0);
20303 return rc;
20304 }
20305
20306 /************************* End ext/misc/analyze.c ********************/
20307
20308 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
20309 #define SQLITE_SHELL_HAVE_RECOVER 1
20310 #else
20311 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -23966,10 +24870,11 @@
24870 ** Output routines that are able to redirect to memory rather than
24871 ** doing actually I/O.
24872 ** Works like.
24873 ** --------------
24874 ** cli_printf(FILE*, const char*, ...); fprintf()
24875 ** cli_write(FILE*, const char*, int); write()
24876 ** cli_puts(const char*, FILE*); fputs()
24877 ** cli_vprintf(FILE*, const char*, va_list); vfprintf()
24878 **
24879 ** These are just thin wrappers with the following added semantics:
24880 ** If the file-scope variable cli_output_capture is not NULL, and
@@ -23991,10 +24896,18 @@
24896 }else{
24897 rc = sqlite3_vfprintf(out, zFormat, ap);
24898 }
24899 va_end(ap);
24900 return rc;
24901 }
24902 static int cli_write(FILE *out, const char *zData, int nData){
24903 if( cli_output_capture && (out==stdout || out==stderr) ){
24904 sqlite3_str_append(cli_output_capture, zData, nData);
24905 }else{
24906 nData = (int)fwrite(zData, 1, nData, out);
24907 }
24908 return nData;
24909 }
24910 static int cli_puts(const char *zText, FILE *out){
24911 if( cli_output_capture && (out==stdout || out==stderr) ){
24912 sqlite3_str_appendall(cli_output_capture, zText);
24913 return 1;
@@ -24189,15 +25102,47 @@
25102
25103 /*
25104 ** The default prompts.
25105 */
25106 #ifndef SQLITE_PS1
25107 # define SQLITE_PS1 "/A /f> "
25108 #endif
25109 #ifndef SQLITE_PS2
25110 # define SQLITE_PS2 "/B.../H> "
25111 #endif
25112
25113 /*
25114 ** Redefinable name of a function that is used to find the text for
25115 ** some prompt expansions: /A /V /v
25116 */
25117 #ifndef SQLITE_PS_APPDEF
25118 # define SQLITE_PS_APPDEF shellPromptAppDef
25119 #else
25120 extern const char *SQLITE_PS_APPDEF(int);
25121 #endif
25122
25123 /*
25124 ** Return a string appropriate for various prompt expansion characters.
25125 ** Return an empty string at least. Always return a valid string pointer.
25126 */
25127 static const char *shellPromptAppDef(int c){
25128 if( c=='A' ) return "SQLite";
25129 if( c=='V' ) return sqlite3_libversion();
25130 if( c=='v' ){
25131 static char zRel[16];
25132 const char *zF = sqlite3_libversion();
25133 const char *zD = strrchr(zF,'.');
25134 if( zD && (size_t)(zD-zF)<sizeof(zRel)-1 ){
25135 memcpy(zRel,zF,(size_t)(zD-zF));
25136 zRel[(size_t)(zD-zF)] = 0;
25137 return zRel;
25138 }else{
25139 return zF;
25140 }
25141 }
25142 return "";
25143 }
25144
25145 /*
25146 ** Return the raw (unexpanded) prompt string. This will be the
25147 ** first of the following that exist:
25148 **
@@ -24236,11 +25181,14 @@
25181 zFN = p->pAuxDb->zDbFilename;
25182 }else if( p->db && (pFN = sqlite3_db_filename(p->db,0))!=0 ){
25183 zFN = sqlite3_filename_database(pFN);
25184 }
25185 if( zFN==0 || zFN[0]==0 ){
25186 zFN = p->pAuxDb->zDbFilename;
25187 if( zFN==0 || zFN[0]==0 || cli_strcmp(zFN,":memory:")==0 ){
25188 zFN = "in-memory";
25189 }
25190 }
25191 return zFN;
25192 }
25193
25194 /*
@@ -24262,16 +25210,17 @@
25210 const char *zPrompt /* Prompt string to be expanded */
25211 ){
25212 sqlite3_str *pOut = sqlite3_str_new(0);
25213 int i;
25214 char c;
25215 unsigned int mOff = 0; /* Bitmask of FALSE for if/then/else */
25216 int idxSpace = -1;
25217 int iDate = -1;
25218 for(i=0; zPrompt[i]; i++){
25219 if( zPrompt[i]!='/' ) continue;
25220 if( i>0 ){
25221 if( !mOff ) sqlite3_str_append(pOut, zPrompt, i);
25222 zPrompt += i;
25223 i = 0;
25224 }
25225 /* At this point zPrompt[0] is a / character and all prior
25226 ** characters have already been loaded into pOut. Process the
@@ -24290,18 +25239,27 @@
25239 /* /nnn becomes a single byte given by octal nnn */
25240 int v = c - '0';
25241 while( i<=2 && zPrompt[i+1]>='0' && zPrompt[i+1]<='7' ){
25242 v = v*8 + zPrompt[++i] - '0';
25243 }
25244 if( !mOff ) sqlite3_str_appendchar(pOut, 1, v);
25245 zPrompt += i+1;
25246 i = -1;
25247 continue;
25248 }
25249 if( c=='e' ){
25250 /* /e is shorthand for /033 which is U+001B "Escape" */
25251 if( !mOff ) sqlite3_str_append(pOut, "\033", 1);
25252 zPrompt += 2;
25253 i = -1;
25254 continue;
25255 }
25256 if( c=='A' || c=='V' || c=='v' ){
25257 /* /A expands to the application name */
25258 /* /V expands to the version number with patch level */
25259 /* /v expands to the version number without the patch level */
25260 if( !mOff ) sqlite3_str_appendall(pOut, SQLITE_PS_APPDEF(c));
25261 zPrompt += 2;
25262 i = -1;
25263 continue;
25264 }
25265
@@ -24317,36 +25275,43 @@
25275 ** or red if within a transaction:
25276 **
25277 ** .prompt '/e[1;/x31/:34/;m~f>/e[0m '
25278 */
25279 if( c==':' ){
25280 /* ELSE: toggle display on/off */
25281 mOff ^= 1;
25282 zPrompt += 2;
25283 i = -1;
25284 continue;
25285 }
25286 if( c==';' ){
25287 /* ENDIF: Turn display on */
25288 mOff >>= 1;
25289 zPrompt += 2;
25290 i = -1;
25291 continue;
25292 }
25293 if( c=='x' ){
25294 /* /x turns display off not in a transaction, on if in txn */
25295 mOff = (mOff<<1) | (p->db==0 || sqlite3_get_autocommit(p->db)!=0);
25296 zPrompt += 2;
25297 i = -1;
25298 continue;
25299 }
25300 if( c=='r' ){
25301 /* /r turns display off if database is read/write, on if read-only */
25302 mOff = (mOff<<1) | (p->db==0 || sqlite3_db_readonly(p->db,0)==0);
25303 zPrompt += 2;
25304 i = -1;
25305 continue;
25306 }
25307
25308 if( c=='f' || c=='F' || c=='~' ){
25309 /* /f becomes the tail of the database filename */
25310 /* /F becomes the full pathname */
25311 /* /~ becomes the full pathname relative to $HOME */
25312 if( !mOff ){
25313 const char *zFN = prompt_filename(p);
25314 if( c=='f' ){
25315 #ifdef _WIN32
25316 const char *zTail = strrchr(zFN,'\\');
25317 #else
@@ -24371,11 +25336,11 @@
25336 continue;
25337 }
25338
25339 if( c=='H' ){
25340 /* /H becomes text needed to terminate current input */
25341 if( !mOff ){
25342 sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0;
25343 int cc = (R>>16)&0xff;
25344 int nParen = R>>32;
25345 int eSemi = (R>>8)&0xff;
25346 if( cc==0 ){
@@ -24405,22 +25370,48 @@
25370
25371 if( c=='B' ){
25372 /* /B is a no-op for the main prompt. For the continuation prompt,
25373 ** /B expands to zero or more spaces to make the continuation prompt
25374 ** at least as wide as the main prompt. */
25375 if( !mOff ) idxSpace = sqlite3_str_length(pOut);
25376 zPrompt += 2;
25377 i = -1;
25378 continue;
25379 }
25380
25381 if( c=='D' ){
25382 /* /D.../D replaces all of the text between the two /D escapes with
25383 ** the result from strftime(). */
25384 if( iDate<0 ){
25385 iDate = sqlite3_str_length(pOut);
25386 }else{
25387 if( !mOff ){
25388 time_t now;
25389 char zBuf[200];
25390 zBuf[0] = 0;
25391 time(&now);
25392 strftime(zBuf, sizeof(zBuf)-1, sqlite3_str_value(pOut)+iDate,
25393 localtime(&now));
25394 zBuf[199] = 0;
25395 sqlite3_str_truncate(pOut, iDate);
25396 sqlite3_str_appendall(pOut, zBuf);
25397 }
25398 iDate = -1;
25399 }
25400 zPrompt += 2;
25401 i = -1;
25402 continue;
25403 }
25404
25405 /* No match to a known escape. Generate an error. The mOff flag
25406 ** is ignored for this output, so that errors appear even if they
25407 ** are in an unused branch. */
25408 sqlite3_str_appendf(pOut,"UNKNOWN(\"/%c\")",c);
25409 zPrompt += 2;
25410 i = -1;
25411 }
25412 if( i>0 && !mOff ){
25413 sqlite3_str_append(pOut, zPrompt, i);
25414 }
25415
25416 /* Expand the /B, if there is one and if this is a continuation prompt */
25417 if( idxSpace>=0 && zPrior!=0 && zPrior[0]!=0 ){
@@ -24440,11 +25431,15 @@
25431 memmove(z+idxSpace+nNew, z+idxSpace, len-nNew-idxSpace);
25432 memset(z+idxSpace, ' ', nNew);
25433 }
25434 }
25435 }
25436
25437 if( 0==sqlite3_str_length(pOut) ){
25438 /* Avoid a bogus OOM */
25439 sqlite3_str_appendchar(pOut, 1, '\0');
25440 }
25441 return sqlite3_str_finish(pOut);
25442 }
25443
25444 /*
25445 ** Retrieve a single line of input text.
@@ -25331,11 +26326,11 @@
26326 ** (2) Run program EDITOR on that temporary file.
26327 ** (3) Read the temporary file back and return its content as the result.
26328 ** (4) Delete the temporary file
26329 **
26330 ** If the EDITOR argument is omitted, use the value in the VISUAL
26331 ** environment variable. If still there is no EDITOR, throw an error.
26332 **
26333 ** Also throw an error if the EDITOR program returns a non-zero exit code.
26334 */
26335 #ifndef SQLITE_NOHAVE_SYSTEM
26336 static void editFunc(
@@ -26688,11 +27683,11 @@
27683 /*
27684 ** QRF write callback
27685 */
27686 static int shellWriteQR(void *pX, const char *z, sqlite3_int64 n){
27687 ShellState *pArg = (ShellState*)pX;
27688 cli_write(pArg->out, z, (int)n);
27689 return SQLITE_OK;
27690 }
27691
27692 /*
27693 ** Execute a statement or set of statements. Print
@@ -27230,10 +28225,11 @@
28225 ".databases List names and files of attached databases",
28226 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
28227 #if SQLITE_SHELL_HAVE_RECOVER
28228 ".dbinfo ?DB? Show status information about the database",
28229 #endif
28230 ".dbstat ?SCHEMA? Report database space and size stats",
28231 ".dbtotxt Hex dump of the database file",
28232 ".dump ?OBJECTS? Render database content as SQL",
28233 " Options:",
28234 " --data-only Output only INSERT statements",
28235 " --newlines Allow unescaped newline characters in output",
@@ -27262,11 +28258,11 @@
28258 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
28259 ".filectrl CMD ... Run various sqlite3_file_control() operations",
28260 " --schema SCHEMA Use SCHEMA instead of \"main\"",
28261 " --help Show CMD details",
28262 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
28263 ".headers on|off Turn display of headers on or off",
28264 ".help ?-all? ?PATTERN? Show help text for PATTERN",
28265 #ifndef SQLITE_SHELL_FIDDLE
28266 ".import FILE TABLE Import data from FILE into TABLE",
28267 #endif
28268 #ifndef SQLITE_OMIT_TEST_CONTROL
@@ -27274,11 +28270,11 @@
28270 #endif
28271 ".indexes ?PATTERN? Show names of indexes matching PATTERN",
28272 " -a|--all Also show system-generated indexes",
28273 " --expr Show only expression indexes",
28274 " --sys Show only system-generated indexes",
28275 ".intck ?STEPS? Run an incremental integrity check on the db",
28276 #ifdef SQLITE_ENABLE_IOTRACE
28277 ",iotrace FILE Enable I/O diagnostic logging to FILE",
28278 #endif
28279 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
28280 ".lint OPTIONS Report potential schema issues.",
@@ -27339,14 +28335,15 @@
28335 " --once Do no more than one progress interrupt",
28336 " --quiet|-q No output except at interrupts",
28337 " --reset Reset the count for each input and interrupt",
28338 " --timeout S Halt after running for S seconds",
28339 #endif
28340 ".prompt MAIN CONTINUE Replace the standard prompts",
28341 " --hard-reset Unset SQLITE_PS1/2 and then --reset",
28342 " --reset Revert to default prompts",
28343 " --show Show the current prompt strings",
28344 " -- No more options. Subsequent args are prompts",
28345 #ifndef SQLITE_SHELL_FIDDLE
28346 ".quit Stop interpreting input stream, exit if primary.",
28347 ".read FILE Read input from FILE or command output",
28348 " If FILE begins with \"|\", it is a command that generates the input.",
28349 #endif
@@ -27622,11 +28619,11 @@
28619 { ".testcase",
28620 "USAGE: .testcase [OPTIONS] NAME\n"
28621 "\n"
28622 "Start a new test case identified by NAME. All output\n"
28623 "through the next \".check\" command is captured for comparison. See the\n"
28624 "\".check\" command for additional informatioon.\n"
28625 "\n"
28626 "Options:\n"
28627 " --error-prefix TEXT Change error message prefix text to TEXT\n"
28628 },
28629 };
@@ -28237,10 +29234,11 @@
29234 sqlite3_base64_init(p->db, 0, 0);
29235 sqlite3_base85_init(p->db, 0, 0);
29236 sqlite3_regexp_init(p->db, 0, 0);
29237 sqlite3_ieee_init(p->db, 0, 0);
29238 sqlite3_series_init(p->db, 0, 0);
29239 sqlite3_analyze_init(p->db, 0, 0);
29240 #ifndef SQLITE_SHELL_FIDDLE
29241 sqlite3_fileio_init(p->db, 0, 0);
29242 sqlite3_completion_init(p->db, 0, 0);
29243 #endif
29244 #ifdef SQLITE_HAVE_ZLIB
@@ -29116,11 +30114,11 @@
30114 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
30115 if( system(zCmd) ){
30116 cli_printf(stderr,"Failed: [%s]\n", zCmd);
30117 }else{
30118 /* Give the start/open/xdg-open command some time to get
30119 ** going before we continue and potentially delete the
30120 ** p->zTempFile data file out from under it */
30121 sqlite3_sleep(2000);
30122 }
30123 sqlite3_free(zCmd);
30124 modePop(p);
@@ -32266,12 +33264,11 @@
33264 if( z[1]=='-' ) z++;
33265 if( cli_strcmp(z,"-bom")==0 ){
33266 zBom = zBomUtf8;
33267 }else if( cli_strcmp(z,"-plain")==0 ){
33268 bPlain = 1;
33269 }else if( c=='o' && sqlite3_strglob("-[ewx]",z)==0 ){
 
33270 if( bKeep || eMode ){
33271 dotCmdError(p, i, "incompatible with prior options",0);
33272 goto dotCmdOutput_error;
33273 }
33274 eMode = z[1];
@@ -32556,11 +33553,11 @@
33553 ** DOT-COMMAND: .testcase
33554 ** USAGE: .testcase [OPTIONS] NAME
33555 **
33556 ** Start a new test case identified by NAME. All output
33557 ** through the next ".check" command is captured for comparison. See the
33558 ** ".check" command for additional informatioon.
33559 **
33560 ** Options:
33561 ** --error-prefix TEXT Change error message prefix text to TEXT
33562 */
33563 static int dotCmdTestcase(ShellState *p){
@@ -33030,16 +34027,47 @@
34027
34028 #if SQLITE_SHELL_HAVE_RECOVER
34029 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
34030 rc = shell_dbinfo_command(p, nArg, azArg);
34031 }else
 
 
 
 
 
34032 #endif /* SQLITE_SHELL_HAVE_RECOVER */
34033
34034 if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
34035 const char *zSchema = 0;
34036 int ii;
34037 char *zSql;
34038 open_db(p, 0);
34039 for(ii=1; ii<nArg; ii++){
34040 const char *z = azArg[ii];
34041 if( z[0]=='-' ){
34042 dotCmdError(p, ii, "unknown option", 0);
34043 rc = 1;
34044 goto meta_command_exit;
34045 }
34046 if( zSchema ){
34047 dotCmdError(p, ii, "unknown argument", 0);
34048 rc = 1;
34049 goto meta_command_exit;
34050 }
34051 zSchema = z;
34052 }
34053 zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
34054 shell_check_oom(zSql);
34055 modePush(p);
34056 modeChange(p, MODE_BATCH);
34057 p->mode.spec.nLineLimit = 0;
34058 p->mode.spec.nCharLimit = 0;
34059 p->mode.spec.nTitleLimit = 0;
34060 shell_exec(p, zSql, 0);
34061 modePop(p);
34062 sqlite3_free(zSql);
34063 }else
34064
34065 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34066 open_db(p, 0);
34067 rc = shell_dbtotxt_command(p, nArg, azArg);
34068 }else
34069
34070 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
34071 char *zLike = 0;
34072 char *zSql;
34073 int i;
@@ -33167,15 +34195,10 @@
34195 eputz("Usage: .echo on|off\n");
34196 rc = 1;
34197 }
34198 }else
34199
 
 
 
 
 
34200 if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
34201 if( nArg==2 ){
34202 if( p->mode.autoEQPtrace ){
34203 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
34204 p->mode.autoEQPtrace = 0;
@@ -34139,10 +35162,20 @@
35162 int noOpt = 0;
35163 for(i=1; i<nArg; i++){
35164 const char *z = azArg[i];
35165 if( z[0]=='-' && !noOpt ){
35166 if( z[1]=='-' ) z++;
35167 if( strcmp(z,"-hard-reset")==0 ){
35168 #ifdef _WIN32
35169 _putenv("SQLITE_PS1=");
35170 _putenv("SQLITE_PS2=");
35171 #else
35172 unsetenv("SQLITE_PS1");
35173 unsetenv("SQLITE_PS2");
35174 #endif
35175 z += 5;
35176 }
35177 if( strcmp(z,"-reset")==0 ){
35178 free(p->azPrompt[0]);
35179 free(p->azPrompt[1]);
35180 memset(p->azPrompt, 0, sizeof(p->azPrompt));
35181 }else
@@ -34160,13 +35193,16 @@
35193 }
35194 }else if( cnt>1 ){
35195 dotCmdError(p, i, "extra argument", 0);
35196 rc = 1;
35197 goto meta_command_exit;
35198 }else if( !p->dot.abQuot[i] && sqlite3_strglob("*[^a-z]*",z)!=0 ){
35199 dotCmdError(p, i, "use quotes around the prompt string", 0);
35200 }else{
35201 free(p->azPrompt[cnt]);
35202 p->azPrompt[cnt] = strdup(z);
35203 cnt++;
35204 }
35205 }
35206 }else
35207
35208 #ifndef SQLITE_SHELL_FIDDLE
@@ -34211,10 +35247,17 @@
35247 p->in = inSaved;
35248 p->lineno = savedLineno;
35249 }else
35250 #endif /* !defined(SQLITE_SHELL_FIDDLE) */
35251
35252 #if SQLITE_SHELL_HAVE_RECOVER
35253 if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
35254 open_db(p, 0);
35255 rc = recoverDatabaseCmd(p, nArg, azArg);
35256 }else
35257 #endif /* SQLITE_SHELL_HAVE_RECOVER */
35258
35259 #ifndef SQLITE_SHELL_FIDDLE
35260 if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
35261 const char *zSrcFile;
35262 const char *zDb;
35263 sqlite3 *pSrc;
@@ -37245,10 +38288,11 @@
38288 linenoiseSetCompletionCallback(linenoise_completion);
38289 #elif HAVE_LINENOISE==2
38290 linenoiseSetCompletionCallback(linenoise_completion, NULL);
38291 #endif
38292 data.in = 0;
38293 open_db(&data, 0);
38294 rc = process_input(&data, "<stdin>");
38295 if( zHistory ){
38296 shell_stifle_history(2000);
38297 shell_write_history(zHistory);
38298 sqlite3_free(zHistory);
38299
+187 -73
--- 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
-** 79a8d3edf8207d72f0c4650272ee239a1c77 with changes in files:
21
+** e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6 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.54.0"
471471
#define SQLITE_VERSION_NUMBER 3054000
472
-#define SQLITE_SOURCE_ID "2026-04-11 23:58:15 79a8d3edf8207d72f0c4650272ee239a1c7783a07f907fbf0cf5a7ad99b27a2a"
472
+#define SQLITE_SOURCE_ID "2026-04-23 16:40:34 e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6ca6ecb7ff1a3a9a237715eed5d30"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2026-04-11T23:58:15.898Z"
475
+#define SQLITE_SCM_DATETIME "2026-04-23T16:40:34.462Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -3311,11 +3311,11 @@
33113311
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
33123312
** automatically by sqlite3_complete16(). If that initialization fails,
33133313
** then the return value from sqlite3_complete16() will be non-zero
33143314
** regardless of whether or not the input SQL is complete.)^
33153315
**
3316
-** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)
3316
+** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
33173317
** must be a zero-terminated UTF-8 string.
33183318
**
33193319
** The input to [sqlite3_complete16()] must be a zero-terminated
33203320
** UTF-16 string in native byte order.
33213321
*/
@@ -17812,11 +17812,11 @@
1781217812
#define OP_Rowid 137 /* synopsis: r[P2]=PX rowid of P1 */
1781317813
#define OP_NullRow 138
1781417814
#define OP_SeekEnd 139
1781517815
#define OP_IdxInsert 140 /* synopsis: key=r[P2] */
1781617816
#define OP_SorterInsert 141 /* synopsis: key=r[P2] */
17817
-#define OP_IdxDelete 142 /* synopsis: key=r[P2@P3] */
17817
+#define OP_IdxDelete 142 /* synopsis: key=r[P2@P5] */
1781817818
#define OP_DeferredSeek 143 /* synopsis: Move P3 to P1.rowid if needed */
1781917819
#define OP_IdxRowid 144 /* synopsis: r[P2]=rowid */
1782017820
#define OP_FinishSeek 145
1782117821
#define OP_Destroy 146
1782217822
#define OP_Clear 147
@@ -21617,10 +21617,61 @@
2161721617
#endif
2161821618
2161921619
/*
2162021620
** Assuming zIn points to the first byte of a UTF-8 character,
2162121621
** advance zIn to point to the first byte of the next UTF-8 character.
21622
+**
21623
+** # Dividing malformed UTF-8 into characters (tag-20260418-01)
21624
+**
21625
+** If a text input is malformed UTF-8, SQLite does not make any guarantees
21626
+** about how the bytes are divided up into characters. The system promises
21627
+** to not overflow an array or cause other memory errors when presented
21628
+** with malformed UTF-8. And it promises to preserve the specific
21629
+** sequence of bytes as long as no conversion occur. But beyond that,
21630
+** there are no guarantees. Results can vary from one version to the
21631
+** next.
21632
+**
21633
+** The SQLITE_SKIP_UTF8 macro below is one technique for dividing UTF-8
21634
+** into characters. The length() and substr() SQL functions use a
21635
+** different technique when searching across multiple characters, a
21636
+** technique that exchanges a subtraction for comparison of z and results
21637
+** in faster machine code on some compilers and architectures. The code
21638
+** in substr() to skip over p1 characters goes something like this:
21639
+**
21640
+** for( ; p1>0; p1--){
21641
+** // vvvv--- tag-20260418-01
21642
+** if( (u8)(z[0]-1)<(0x80-1) ){
21643
+** z++;
21644
+** }else if( z[0]==0 ){
21645
+** break;
21646
+** }else{
21647
+** do{ z++; }while( (z[0]&0xc0)==0x80 );
21648
+** }
21649
+** }
21650
+**
21651
+** In valid UTF-8, multibyte characters always begin with a byte with the
21652
+** two most significant bits set and that is followed by one or more bytes
21653
+** for which the two most significant bits are 10. In other words:
21654
+**
21655
+** First byte: (BYTE & 0xc0)==0xc0
21656
+** Following bytes: (BYTE & 0xc0)==0x80
21657
+**
21658
+** What to do if the input byte sequence contain a "following byte" that
21659
+** is not preceded by a "first byte"? How many characters are in the
21660
+** byte sequence: 0x61 0x81 0x82 0x7a? 3 or 4 or something else?
21661
+**
21662
+** If you use the macro below, the answer will be 4. If you use the code
21663
+** snippet demonstrated at tag-20260418-01, then answer is 3. If you
21664
+** use a variant of tag-20260418-01 where the constant of comparison is
21665
+** 0xc0-1 instead of 0x80-1 then the answer is again 4. The key point is
21666
+** that because the input is malformed UTF-8, so is no "correct" answer.
21667
+** SQLite is free to use either value.
21668
+**
21669
+** It turns out that GCC 13.3.0 is able to generate faster code (at least
21670
+** on x86-64) if the constant at tag-20260418-01 is (0x80-1). If you make
21671
+** that constant (0xc0-1) instead, gcc 13.3.0 generates code that runs slower.
21672
+** So the (0x80-1) constant is used for substr() and length().
2162221673
*/
2162321674
#define SQLITE_SKIP_UTF8(zIn) { \
2162421675
if( (*(zIn++))>=0xc0 ){ \
2162521676
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
2162621677
} \
@@ -33680,11 +33731,11 @@
3368033731
/*
3368133732
** Destroy a dynamically allocate sqlite3_str object and all
3368233733
** of its content, all in one call.
3368333734
*/
3368433735
SQLITE_API void sqlite3_str_free(sqlite3_str *p){
33685
- if( p ){
33736
+ if( p!=0 && p!=&sqlite3OomStr ){
3368633737
sqlite3_str_reset(p);
3368733738
sqlite3_free(p);
3368833739
}
3368933740
}
3369033741
@@ -39056,11 +39107,11 @@
3905639107
/* 137 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
3905739108
/* 138 */ "NullRow" OpHelp(""),
3905839109
/* 139 */ "SeekEnd" OpHelp(""),
3905939110
/* 140 */ "IdxInsert" OpHelp("key=r[P2]"),
3906039111
/* 141 */ "SorterInsert" OpHelp("key=r[P2]"),
39061
- /* 142 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
39112
+ /* 142 */ "IdxDelete" OpHelp("key=r[P2@P5]"),
3906239113
/* 143 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
3906339114
/* 144 */ "IdxRowid" OpHelp("r[P2]=rowid"),
3906439115
/* 145 */ "FinishSeek" OpHelp(""),
3906539116
/* 146 */ "Destroy" OpHelp(""),
3906639117
/* 147 */ "Clear" OpHelp(""),
@@ -61607,11 +61658,11 @@
6160761658
** after rollback of a hot-journal, or if an error occurs while opening
6160861659
** the journal file or writing the very first journal-header of a
6160961660
** database transaction.
6161061661
**
6161161662
** This routine is never called in PAGER_ERROR state. If it is called
61612
-** in PAGER_NONE or PAGER_SHARED state and the lock held is less
61663
+** in PAGER_OPEN or PAGER_READER state and the lock held is less
6161361664
** exclusive than a RESERVED lock, it is a no-op.
6161461665
**
6161561666
** Otherwise, any active savepoints are released.
6161661667
**
6161761668
** If the journal file is open, then it is "finalized". Once a journal
@@ -63368,11 +63419,11 @@
6336863419
** * the database is either not an in-memory database or it is
6336963420
** an in-memory database that currently consists of zero pages.
6337063421
**
6337163422
** then the pager object page size is set to *pPageSize.
6337263423
**
63373
-** If the page size is changed, then this function uses sqlite3PagerMalloc()
63424
+** If the page size is changed, then this function uses sqlite3PageMalloc()
6337463425
** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
6337563426
** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
6337663427
** In all other cases, SQLITE_OK is returned.
6337763428
**
6337863429
** If the page size is not changed, either because one of the enumerated
@@ -64715,12 +64766,12 @@
6471564766
return pPager->fd;
6471664767
}
6471764768
6471864769
6471964770
/*
64720
-** This function is called after transitioning from PAGER_UNLOCK to
64721
-** PAGER_SHARED state. It tests if there is a hot journal present in
64771
+** This function is called while transitioning from PAGER_OPEN to a
64772
+** higher state. It tests if there is a hot journal present in
6472264773
** the file-system for the given pager. A hot journal is one that
6472364774
** needs to be played back. According to this function, a hot-journal
6472464775
** file exists if the following criteria are met:
6472564776
**
6472664777
** * The journal file exists in the file system, and
@@ -79088,16 +79139,16 @@
7908879139
** Compare the "idx"-th cell on the page pPage against the key
7908979140
** pointing to by pIdxKey using xRecordCompare. Return negative or
7909079141
** zero if the cell is less than or equal pIdxKey. Return positive
7909179142
** if unknown.
7909279143
**
79093
-** Return value negative: Cell at pCur[idx] less than pIdxKey
79144
+** Return value negative: Cell at pPage[idx] less than pIdxKey
7909479145
**
79095
-** Return value is zero: Cell at pCur[idx] equals pIdxKey
79146
+** Return value is zero: Cell at pPage[idx] equals pIdxKey
7909679147
**
7909779148
** Return value positive: Nothing is known about the relationship
79098
-** of the cell at pCur[idx] and pIdxKey.
79149
+** of the cell at pPage[idx] and pIdxKey.
7909979150
**
7910079151
** This routine is part of an optimization. It is always safe to return
7910179152
** a positive value as that will cause the optimization to be skipped.
7910279153
*/
7910379154
static int indexCellCompare(
@@ -89650,11 +89701,10 @@
8965089701
8965189702
8965289703
#if VDBE_DISPLAY_P4
8965389704
/*
8965489705
** Compute a string that describes the P4 parameter for an opcode.
89655
-** Use zTemp for any required temporary buffer space.
8965689706
*/
8965789707
SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
8965889708
char *zP4 = 0;
8965989709
StrAccum x;
8966089710
@@ -97184,11 +97234,10 @@
9718497234
}
9718597235
}
9718697236
return h;
9718797237
}
9718897238
97189
-
9719097239
/*
9719197240
** For OP_Column, factor out the case where content is loaded from
9719297241
** overflow pages, so that the code to implement this case is separate
9719397242
** the common case where all content fits on the page. Factoring out
9719497243
** the code reduces register pressure and helps the common case
@@ -97269,10 +97318,44 @@
9726997318
}
9727097319
}
9727197320
pDest->flags &= ~MEM_Ephem;
9727297321
return rc;
9727397322
}
97323
+
97324
+/*
97325
+** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
97326
+** open on an index. If the current index entry matches the blob value in
97327
+** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
97328
+**
97329
+** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
97330
+** case as well.
97331
+*/
97332
+static SQLITE_NOINLINE int vdbeIndexKeyCompare(
97333
+ BtCursor *pCsr, /* Cursor to compare key to */
97334
+ Mem *pMem,
97335
+ int *pRc
97336
+){
97337
+ int ret = 0;
97338
+ u32 nKey = 0;
97339
+
97340
+ assert( pMem->flags & (MEM_Blob|MEM_Null) );
97341
+ nKey = sqlite3BtreePayloadSize(pCsr);
97342
+ if( nKey==(u32)pMem->n && ALWAYS((pMem->flags & MEM_Blob)!=0) ){
97343
+ /* This code could just use sqlite3BtreePayloadFetch(). But calling that
97344
+ ** function here apparently prevents compilers from inlining it in other,
97345
+ ** more performance critical, places. So this code uses
97346
+ ** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
97347
+ ** handles the case where the index record uses overflow pages. */
97348
+ Mem m;
97349
+ memset(&m, 0, sizeof(m));
97350
+ *pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
97351
+ ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
97352
+ sqlite3VdbeMemReleaseMalloc(&m);
97353
+ }
97354
+
97355
+ return ret;
97356
+}
9727497357
9727597358
/*
9727697359
** Send a "statement aborts" message to the error log.
9727797360
*/
9727897361
static SQLITE_NOINLINE void sqlite3VdbeLogAbort(
@@ -103098,18 +103181,23 @@
103098103181
rc = sqlite3VdbeSorterWrite(pC, pIn2);
103099103182
if( rc) goto abort_due_to_error;
103100103183
break;
103101103184
}
103102103185
103103
-/* Opcode: IdxDelete P1 P2 P3 P4 *
103104
-** Synopsis: key=r[P2@P3]
103186
+/* Opcode: IdxDelete P1 P2 P3 P4 P5
103187
+** Synopsis: key=r[P2@P5]
103105103188
**
103106
-** The content of P3 registers starting at register P2 form
103189
+** The content of P5 registers starting at register P2 form
103107103190
** an unpacked index key. This opcode removes that entry from the
103108103191
** index opened by cursor P1.
103109103192
**
103110103193
** P4 is a pointer to an Index structure.
103194
+**
103195
+** If P3 is non-zero, it is the register number of a register holding
103196
+** a record that will be inserted into this index. If that record is
103197
+** identical to the one that would be deleted by this instruction,
103198
+** skip the delete and set register P3 to NULL.
103111103199
**
103112103200
** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
103113103201
** and not in writable_schema mode.
103114103202
*/
103115103203
case OP_IdxDelete: {
@@ -103116,21 +103204,21 @@
103116103204
VdbeCursor *pC;
103117103205
BtCursor *pCrsr;
103118103206
int res;
103119103207
UnpackedRecord r;
103120103208
103121
- assert( pOp->p3>0 );
103122
- assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
103209
+ assert( pOp->p5>0 );
103210
+ assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
103123103211
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
103124103212
pC = p->apCsr[pOp->p1];
103125103213
assert( pC!=0 );
103126103214
assert( pC->eCurType==CURTYPE_BTREE );
103127103215
sqlite3VdbeIncrWriteCounter(p, pC);
103128103216
pCrsr = pC->uc.pCursor;
103129103217
assert( pCrsr!=0 );
103130103218
r.pKeyInfo = pC->pKeyInfo;
103131
- r.nField = (u16)pOp->p3;
103219
+ r.nField = pOp->p5;
103132103220
r.default_rc = 0;
103133103221
r.aMem = &aMem[pOp->p2];
103134103222
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
103135103223
if( rc ) goto abort_due_to_error;
103136103224
if( res!=0 ){
@@ -103145,10 +103233,17 @@
103145103233
pC->cacheStatus = CACHE_STALE;
103146103234
pC->seekResult = 0;
103147103235
break;
103148103236
}
103149103237
}
103238
+
103239
+ if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
103240
+ if( rc ) goto abort_due_to_error;
103241
+ sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
103242
+ break;
103243
+ }
103244
+
103150103245
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
103151103246
if( rc ) goto abort_due_to_error;
103152103247
assert( pC->deferredMoveto==0 );
103153103248
pC->cacheStatus = CACHE_STALE;
103154103249
pC->seekResult = 0;
@@ -115325,11 +115420,11 @@
115325115420
115326115421
/*
115327115422
** Walk an expression tree. Return non-zero if
115328115423
**
115329115424
** (1) the expression is constant, and
115330
-** (2) the expression does originate in the ON or USING clause
115425
+** (2) the expression does not originate in the ON or USING clause
115331115426
** of a LEFT JOIN, and
115332115427
** (3) the expression does not contain any EP_FixedCol TK_COLUMN
115333115428
** operands created by the constant propagation optimization.
115334115429
**
115335115430
** When this routine returns true, it indicates that the expression
@@ -123178,11 +123273,13 @@
123178123273
assert( pSrc->nSrc==1 );
123179123274
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0);
123180123275
if( !pTab ) return;
123181123276
123182123277
if( pCons ){
123183
- zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
123278
+ char *z = sqlite3NameFromToken(db, pCons);
123279
+ zArg = sqlite3MPrintf(db, "%Q", z);
123280
+ sqlite3DbFree(db, z);
123184123281
}else{
123185123282
int iCol;
123186123283
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
123187123284
zArg = sqlite3MPrintf(db, "%d", iCol);
123188123285
}
@@ -133621,21 +133718,24 @@
133621133718
Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
133622133719
133623133720
v = pParse->pVdbe;
133624133721
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
133625133722
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
133723
+ int p3 = 0;
133626133724
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
133627133725
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
133628133726
if( pIdx==pPk ) continue;
133629133727
if( iIdxCur+i==iIdxNoSeek ) continue;
133630133728
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
133631133729
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
133632133730
&iPartIdxLabel, pPrior, r1);
133633
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
133634
- pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn
133635
- );
133731
+ if( pIdx->bHasExpr && aRegIdx ){
133732
+ p3 = aRegIdx[i];
133733
+ }
133734
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, p3);
133636133735
sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
133736
+ sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
133637133737
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
133638133738
pPrior = pIdx;
133639133739
}
133640133740
}
133641133741
@@ -133870,17 +133970,21 @@
133870133970
break;
133871133971
}
133872133972
case SQLITE_TEXT: {
133873133973
const unsigned char *z = sqlite3_value_text(argv[0]);
133874133974
const unsigned char *z0;
133875
- unsigned char c;
133876133975
if( z==0 ) return;
133877133976
z0 = z;
133878
- while( (c = *z)!=0 ){
133879
- z++;
133880
- if( c>=0xc0 ){
133881
- while( (*z & 0xc0)==0x80 ){ z++; z0++; }
133977
+ while( 1 /*exit-by-break*/ ){
133978
+ /* vvvvvv---- See tag-20260418-01 */
133979
+ if( (u8)(z[0]-1)<(0x80-1) ){
133980
+ z++;
133981
+ }else if( z[0]==0 ){
133982
+ break;
133983
+ }else{
133984
+ z++;
133985
+ while( (z[0]&0xc0)==0x80 ){ z++; z0++; }
133882133986
}
133883133987
}
133884133988
sqlite3_result_int(context, (int)(z-z0));
133885133989
break;
133886133990
}
@@ -134155,16 +134259,29 @@
134155134259
}
134156134260
p1 -= p2;
134157134261
}
134158134262
assert( p1>=0 && p2>=0 );
134159134263
if( p0type!=SQLITE_BLOB ){
134160
- while( *z && p1 ){
134161
- SQLITE_SKIP_UTF8(z);
134162
- p1--;
134264
+ for( ; p1>0; p1--){
134265
+ /* vvvvvv---- See tag-20260418-01 */
134266
+ if( (u8)(z[0]-1)<(0x80-1) ){
134267
+ z++;
134268
+ }else if( z[0]==0 ){
134269
+ break;
134270
+ }else{
134271
+ do{ z++; }while( (z[0]&0xc0)==0x80 );
134272
+ }
134163134273
}
134164
- for(z2=z; *z2 && p2; p2--){
134165
- SQLITE_SKIP_UTF8(z2);
134274
+ for(z2=z; p2>0; p2--){
134275
+ /* vvvvvv---- See tag-20260418-01 */
134276
+ if( (u8)(z2[0]-1)<(0x80-1) ){
134277
+ z2++;
134278
+ }else if( z2[0]==0 ){
134279
+ break;
134280
+ }else{
134281
+ do{ z2++; }while( (z2[0]&0xc0)==0x80 );
134282
+ }
134166134283
}
134167134284
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
134168134285
SQLITE_UTF8);
134169134286
}else{
134170134287
if( p1>=len ){
@@ -136846,11 +136963,11 @@
136846136963
sqlite3BtreeEnter(pBtree);
136847136964
pPager = sqlite3BtreePager(pBtree);
136848136965
assert( pPager!=0 );
136849136966
fd = sqlite3PagerFile(pPager);
136850136967
pStr = sqlite3_str_new(db);
136851
- if( pStr==0 ){
136968
+ if( sqlite3_str_errcode(pStr) ){
136852136969
sqlite3_result_error_nomem(context);
136853136970
}else{
136854136971
sqlite3_str_append(pStr, "{\"db\":", 6);
136855136972
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
136856136973
if( rc ) sqlite3_str_append(pStr, "null", 4);
@@ -136949,11 +137066,11 @@
136949137066
zUri = (const char*)sqlite3_value_text(argv[0]);
136950137067
if( zUri==0 ) return;
136951137068
flgs = (unsigned int)sqlite3_value_int(argv[1]);
136952137069
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
136953137070
pResult = sqlite3_str_new(0);
136954
- if( pResult ){
137071
+ if( !sqlite3_str_errcode(pResult) ){
136955137072
int i;
136956137073
sqlite3_str_appendf(pResult, "rc=%d", rc);
136957137074
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
136958137075
sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
136959137076
sqlite3_str_appendf(pResult, ", err=%Q", zErr);
@@ -141499,11 +141616,14 @@
141499141616
/* All REPLACE indexes are at the end of the list */
141500141617
assert( pIdx->onError!=OE_Replace
141501141618
|| pIdx->pNext==0
141502141619
|| pIdx->pNext->onError==OE_Replace );
141503141620
if( aRegIdx[i]==0 ) continue;
141504
- if( pIdx->pPartIdxWhere ){
141621
+ if( pIdx->pPartIdxWhere || (update_flags && pIdx->bHasExpr) ){
141622
+ /* If this is a partial index, or an UPDATE of an index on an
141623
+ ** expression, then the record register may be set to NULL to indicate
141624
+ ** that no record should be inserted into this index. */
141505141625
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
141506141626
VdbeCoverage(v);
141507141627
}
141508141628
pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
141509141629
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
@@ -156118,10 +156238,11 @@
156118156238
if( pParse->nErr==0
156119156239
&& pWhere!=0
156120156240
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
156121156241
&& ALWAYS(p->pSrc!=0)
156122156242
&& p->pSrc->nSrc<BMS
156243
+ && (p->pLimit==0 || p->pLimit->pRight==0)
156123156244
){
156124156245
if( pWhere->op==TK_AND ){
156125156246
Expr *pRight = pWhere->pRight;
156126156247
existsToJoin(pParse, p, pWhere->pLeft);
156127156248
existsToJoin(pParse, p, pRight);
@@ -156165,11 +156286,10 @@
156165156286
TREETRACE(0x100000,pParse,p,
156166156287
("After EXISTS-to-JOIN optimization:\n"));
156167156288
sqlite3TreeViewSelect(0, p, 0);
156168156289
}
156169156290
#endif
156170
- existsToJoin(pParse, p, pSubWhere);
156171156291
}
156172156292
}
156173156293
}
156174156294
}
156175156295
@@ -168768,11 +168888,11 @@
168768168888
** optimization can be used on multiple
168769168889
**
168770168890
** If the ONEPASS optimization is used (if this routine returns true)
168771168891
** then also write the indices of open cursors used by ONEPASS
168772168892
** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
168773
-** table and iaCur[1] gets the cursor used by an auxiliary index.
168893
+** table and aiCur[1] gets the cursor used by an auxiliary index.
168774168894
** Either value may be -1, indicating that cursor is not used.
168775168895
** Any cursors returned will have been opened for writing.
168776168896
**
168777168897
** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
168778168898
** unable to use the ONEPASS optimization.
@@ -176188,31 +176308,15 @@
176188176308
sqlite3VdbeJumpHere(v, addrIfNull);
176189176309
}
176190176310
}
176191176311
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
176192176312
}
176193
- if( pTabList->a[pLevel->iFrom].fg.fromExists
176194
- && (i==pWInfo->nLevel-1
176195
- || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
176196
- ){
176197
- /* This is an EXISTS-to-JOIN optimization which is either the
176198
- ** inner-most loop, or the inner-most of a group of nested
176199
- ** EXISTS-to-JOIN optimization loops. If this loop sees a successful
176200
- ** row, it should break out of itself as well as other EXISTS-to-JOIN
176201
- ** loops in which is is directly nested. */
176202
- int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
176203
- while( nOuter<i ){
176204
- if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
176205
- nOuter++;
176206
- }
176207
- testcase( nOuter>0 );
176208
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
176209
- if( nOuter ){
176210
- VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
176211
- }else{
176212
- VdbeComment((v, "EXISTS break %d", i));
176213
- }
176313
+ if( pTabList->a[pLevel->iFrom].fg.fromExists ){
176314
+ /* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
176315
+ ** successful row, it should break out of itself. */
176316
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
176317
+ VdbeComment((v, "EXISTS break %d", i));
176214176318
}
176215176319
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
176216176320
if( pLevel->op!=OP_Noop ){
176217176321
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
176218176322
sqlite3VdbeChangeP5(v, pLevel->p5);
@@ -184395,10 +184499,11 @@
184395184499
ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
184396184500
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
184397184501
yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0);
184398184502
if( yymsp[-4].minor.yy454 ){
184399184503
yymsp[-4].minor.yy454->x.pList = pList;
184504
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
184400184505
}else{
184401184506
sqlite3ExprListDelete(pParse->db, pList);
184402184507
}
184403184508
if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
184404184509
}
@@ -188354,11 +188459,12 @@
188354188459
db->lastRowid = iRowid;
188355188460
sqlite3_mutex_leave(db->mutex);
188356188461
}
188357188462
188358188463
/*
188359
-** Return the number of changes in the most recent call to sqlite3_exec().
188464
+** Return the number of changes in the most recently executed DML
188465
+** statement.
188360188466
*/
188361188467
SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
188362188468
#ifdef SQLITE_ENABLE_API_ARMOR
188363188469
if( !sqlite3SafetyCheckOk(db) ){
188364188470
(void)SQLITE_MISUSE_BKPT;
@@ -229685,11 +229791,16 @@
229685229791
);
229686229792
}
229687229793
229688229794
while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
229689229795
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
229690
- p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
229796
+ sqlite3_stmt *pStmt = 0;
229797
+ p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, zSql);
229798
+ if( p->rc==SQLITE_OK ){
229799
+ sqlite3_step(pStmt);
229800
+ rbuFinalize(p, pStmt);
229801
+ }
229691229802
}
229692229803
rbuFinalize(p, pSql);
229693229804
if( p->rc!=SQLITE_OK ) return;
229694229805
229695229806
if( p->rc==SQLITE_OK ){
@@ -234093,14 +234204,15 @@
234093234204
static int sessionSerialLen(const u8 *a){
234094234205
int e;
234095234206
int n;
234096234207
assert( a!=0 );
234097234208
e = *a;
234098
- if( e==0 || e==0xFF ) return 1;
234099
- if( e==SQLITE_NULL ) return 1;
234100234209
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
234101
- return sessionVarintGet(&a[1], &n) + 1 + n;
234210
+ if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
234211
+ return sessionVarintGet(&a[1], &n) + 1 + n;
234212
+ }
234213
+ return 1;
234102234214
}
234103234215
234104234216
/*
234105234217
** Based on the primary key values stored in change aRecord, calculate a
234106234218
** hash key. Assume the has table has nBucket buckets. The hash keys
@@ -237157,13 +237269,15 @@
237157237269
nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem, &n);
237158237270
nByte += n;
237159237271
rc = sessionInputBuffer(pIn, nByte);
237160237272
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
237161237273
nByte += 8;
237274
+ }else if( eType!=0 && eType!=SQLITE_NULL ){
237275
+ rc = SQLITE_CORRUPT_BKPT;
237162237276
}
237163237277
}
237164
- if( (pIn->iNext+nByte)>pIn->nData ){
237278
+ if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
237165237279
rc = SQLITE_CORRUPT_BKPT;
237166237280
}
237167237281
}
237168237282
*pnByte = nByte;
237169237283
return rc;
@@ -242453,11 +242567,11 @@
242453242567
** The "lemon" program processes an LALR(1) input grammar file, then uses
242454242568
** this template to construct a parser. The "lemon" program inserts text
242455242569
** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
242456242570
** interstitial "-" characters) contained in this template is changed into
242457242571
** the value of the %name directive from the grammar. Otherwise, the content
242458
-** of this template is copied straight through into the generate parser
242572
+** of this template is copied straight through into the generated parser
242459242573
** source file.
242460242574
**
242461242575
** The following is the concatenation of all %include directives from the
242462242576
** input grammar file:
242463242577
*/
@@ -263364,11 +263478,11 @@
263364263478
int nArg, /* Number of args */
263365263479
sqlite3_value **apUnused /* Function arguments */
263366263480
){
263367263481
assert( nArg==0 );
263368263482
UNUSED_PARAM2(nArg, apUnused);
263369
- sqlite3_result_text(pCtx, "fts5: 2026-04-11 22:18:05 6fa0216a19c2f165110121227d3f9b9119369f8cd61f9c6d13eaa1ae42a60d60", -1, SQLITE_TRANSIENT);
263483
+ sqlite3_result_text(pCtx, "fts5: 2026-04-22 19:38:04 f0fc4e5ec334da3a1db8b0334e23d1911874c96675690da94210b2afb45f7307", -1, SQLITE_TRANSIENT);
263370263484
}
263371263485
263372263486
/*
263373263487
** Implementation of fts5_locale(LOCALE, TEXT) function.
263374263488
**
@@ -265884,13 +265998,13 @@
265884265998
int mask = 0;
265885265999
int bCons = 0;
265886266000
for(i=0; i<nStem; i++){
265887266001
bCons = !fts5PorterIsVowel(zStem[i], bCons);
265888266002
assert( bCons==0 || bCons==1 );
265889
- mask = (mask << 1) + bCons;
266003
+ mask = ((mask << 1) + bCons) & 0x0007;
265890266004
}
265891
- return ((mask & 0x0007)==0x0005);
266005
+ return (mask==0x0005);
265892266006
}
265893266007
}
265894266008
265895266009
/* porter rule condition: (m > 1 and (*S or *T)) */
265896266010
static int fts5Porter_MGt1_and_S_or_T(char *zStem, int nStem){
265897266011
--- 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 ** 79a8d3edf8207d72f0c4650272ee239a1c77 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.54.0"
471 #define SQLITE_VERSION_NUMBER 3054000
472 #define SQLITE_SOURCE_ID "2026-04-11 23:58:15 79a8d3edf8207d72f0c4650272ee239a1c7783a07f907fbf0cf5a7ad99b27a2a"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2026-04-11T23:58:15.898Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -3311,11 +3311,11 @@
3311 ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
3312 ** automatically by sqlite3_complete16(). If that initialization fails,
3313 ** then the return value from sqlite3_complete16() will be non-zero
3314 ** regardless of whether or not the input SQL is complete.)^
3315 **
3316 ** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)
3317 ** must be a zero-terminated UTF-8 string.
3318 **
3319 ** The input to [sqlite3_complete16()] must be a zero-terminated
3320 ** UTF-16 string in native byte order.
3321 */
@@ -17812,11 +17812,11 @@
17812 #define OP_Rowid 137 /* synopsis: r[P2]=PX rowid of P1 */
17813 #define OP_NullRow 138
17814 #define OP_SeekEnd 139
17815 #define OP_IdxInsert 140 /* synopsis: key=r[P2] */
17816 #define OP_SorterInsert 141 /* synopsis: key=r[P2] */
17817 #define OP_IdxDelete 142 /* synopsis: key=r[P2@P3] */
17818 #define OP_DeferredSeek 143 /* synopsis: Move P3 to P1.rowid if needed */
17819 #define OP_IdxRowid 144 /* synopsis: r[P2]=rowid */
17820 #define OP_FinishSeek 145
17821 #define OP_Destroy 146
17822 #define OP_Clear 147
@@ -21617,10 +21617,61 @@
21617 #endif
21618
21619 /*
21620 ** Assuming zIn points to the first byte of a UTF-8 character,
21621 ** advance zIn to point to the first byte of the next UTF-8 character.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21622 */
21623 #define SQLITE_SKIP_UTF8(zIn) { \
21624 if( (*(zIn++))>=0xc0 ){ \
21625 while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
21626 } \
@@ -33680,11 +33731,11 @@
33680 /*
33681 ** Destroy a dynamically allocate sqlite3_str object and all
33682 ** of its content, all in one call.
33683 */
33684 SQLITE_API void sqlite3_str_free(sqlite3_str *p){
33685 if( p ){
33686 sqlite3_str_reset(p);
33687 sqlite3_free(p);
33688 }
33689 }
33690
@@ -39056,11 +39107,11 @@
39056 /* 137 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
39057 /* 138 */ "NullRow" OpHelp(""),
39058 /* 139 */ "SeekEnd" OpHelp(""),
39059 /* 140 */ "IdxInsert" OpHelp("key=r[P2]"),
39060 /* 141 */ "SorterInsert" OpHelp("key=r[P2]"),
39061 /* 142 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
39062 /* 143 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
39063 /* 144 */ "IdxRowid" OpHelp("r[P2]=rowid"),
39064 /* 145 */ "FinishSeek" OpHelp(""),
39065 /* 146 */ "Destroy" OpHelp(""),
39066 /* 147 */ "Clear" OpHelp(""),
@@ -61607,11 +61658,11 @@
61607 ** after rollback of a hot-journal, or if an error occurs while opening
61608 ** the journal file or writing the very first journal-header of a
61609 ** database transaction.
61610 **
61611 ** This routine is never called in PAGER_ERROR state. If it is called
61612 ** in PAGER_NONE or PAGER_SHARED state and the lock held is less
61613 ** exclusive than a RESERVED lock, it is a no-op.
61614 **
61615 ** Otherwise, any active savepoints are released.
61616 **
61617 ** If the journal file is open, then it is "finalized". Once a journal
@@ -63368,11 +63419,11 @@
63368 ** * the database is either not an in-memory database or it is
63369 ** an in-memory database that currently consists of zero pages.
63370 **
63371 ** then the pager object page size is set to *pPageSize.
63372 **
63373 ** If the page size is changed, then this function uses sqlite3PagerMalloc()
63374 ** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
63375 ** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
63376 ** In all other cases, SQLITE_OK is returned.
63377 **
63378 ** If the page size is not changed, either because one of the enumerated
@@ -64715,12 +64766,12 @@
64715 return pPager->fd;
64716 }
64717
64718
64719 /*
64720 ** This function is called after transitioning from PAGER_UNLOCK to
64721 ** PAGER_SHARED state. It tests if there is a hot journal present in
64722 ** the file-system for the given pager. A hot journal is one that
64723 ** needs to be played back. According to this function, a hot-journal
64724 ** file exists if the following criteria are met:
64725 **
64726 ** * The journal file exists in the file system, and
@@ -79088,16 +79139,16 @@
79088 ** Compare the "idx"-th cell on the page pPage against the key
79089 ** pointing to by pIdxKey using xRecordCompare. Return negative or
79090 ** zero if the cell is less than or equal pIdxKey. Return positive
79091 ** if unknown.
79092 **
79093 ** Return value negative: Cell at pCur[idx] less than pIdxKey
79094 **
79095 ** Return value is zero: Cell at pCur[idx] equals pIdxKey
79096 **
79097 ** Return value positive: Nothing is known about the relationship
79098 ** of the cell at pCur[idx] and pIdxKey.
79099 **
79100 ** This routine is part of an optimization. It is always safe to return
79101 ** a positive value as that will cause the optimization to be skipped.
79102 */
79103 static int indexCellCompare(
@@ -89650,11 +89701,10 @@
89650
89651
89652 #if VDBE_DISPLAY_P4
89653 /*
89654 ** Compute a string that describes the P4 parameter for an opcode.
89655 ** Use zTemp for any required temporary buffer space.
89656 */
89657 SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
89658 char *zP4 = 0;
89659 StrAccum x;
89660
@@ -97184,11 +97234,10 @@
97184 }
97185 }
97186 return h;
97187 }
97188
97189
97190 /*
97191 ** For OP_Column, factor out the case where content is loaded from
97192 ** overflow pages, so that the code to implement this case is separate
97193 ** the common case where all content fits on the page. Factoring out
97194 ** the code reduces register pressure and helps the common case
@@ -97269,10 +97318,44 @@
97269 }
97270 }
97271 pDest->flags &= ~MEM_Ephem;
97272 return rc;
97273 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97274
97275 /*
97276 ** Send a "statement aborts" message to the error log.
97277 */
97278 static SQLITE_NOINLINE void sqlite3VdbeLogAbort(
@@ -103098,18 +103181,23 @@
103098 rc = sqlite3VdbeSorterWrite(pC, pIn2);
103099 if( rc) goto abort_due_to_error;
103100 break;
103101 }
103102
103103 /* Opcode: IdxDelete P1 P2 P3 P4 *
103104 ** Synopsis: key=r[P2@P3]
103105 **
103106 ** The content of P3 registers starting at register P2 form
103107 ** an unpacked index key. This opcode removes that entry from the
103108 ** index opened by cursor P1.
103109 **
103110 ** P4 is a pointer to an Index structure.
 
 
 
 
 
103111 **
103112 ** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
103113 ** and not in writable_schema mode.
103114 */
103115 case OP_IdxDelete: {
@@ -103116,21 +103204,21 @@
103116 VdbeCursor *pC;
103117 BtCursor *pCrsr;
103118 int res;
103119 UnpackedRecord r;
103120
103121 assert( pOp->p3>0 );
103122 assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
103123 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
103124 pC = p->apCsr[pOp->p1];
103125 assert( pC!=0 );
103126 assert( pC->eCurType==CURTYPE_BTREE );
103127 sqlite3VdbeIncrWriteCounter(p, pC);
103128 pCrsr = pC->uc.pCursor;
103129 assert( pCrsr!=0 );
103130 r.pKeyInfo = pC->pKeyInfo;
103131 r.nField = (u16)pOp->p3;
103132 r.default_rc = 0;
103133 r.aMem = &aMem[pOp->p2];
103134 rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
103135 if( rc ) goto abort_due_to_error;
103136 if( res!=0 ){
@@ -103145,10 +103233,17 @@
103145 pC->cacheStatus = CACHE_STALE;
103146 pC->seekResult = 0;
103147 break;
103148 }
103149 }
 
 
 
 
 
 
 
103150 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
103151 if( rc ) goto abort_due_to_error;
103152 assert( pC->deferredMoveto==0 );
103153 pC->cacheStatus = CACHE_STALE;
103154 pC->seekResult = 0;
@@ -115325,11 +115420,11 @@
115325
115326 /*
115327 ** Walk an expression tree. Return non-zero if
115328 **
115329 ** (1) the expression is constant, and
115330 ** (2) the expression does originate in the ON or USING clause
115331 ** of a LEFT JOIN, and
115332 ** (3) the expression does not contain any EP_FixedCol TK_COLUMN
115333 ** operands created by the constant propagation optimization.
115334 **
115335 ** When this routine returns true, it indicates that the expression
@@ -123178,11 +123273,13 @@
123178 assert( pSrc->nSrc==1 );
123179 pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0);
123180 if( !pTab ) return;
123181
123182 if( pCons ){
123183 zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
 
 
123184 }else{
123185 int iCol;
123186 if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
123187 zArg = sqlite3MPrintf(db, "%d", iCol);
123188 }
@@ -133621,21 +133718,24 @@
133621 Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
133622
133623 v = pParse->pVdbe;
133624 pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
133625 for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
 
133626 assert( iIdxCur+i!=iDataCur || pPk==pIdx );
133627 if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
133628 if( pIdx==pPk ) continue;
133629 if( iIdxCur+i==iIdxNoSeek ) continue;
133630 VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
133631 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
133632 &iPartIdxLabel, pPrior, r1);
133633 sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
133634 pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn
133635 );
 
133636 sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
 
133637 sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
133638 pPrior = pIdx;
133639 }
133640 }
133641
@@ -133870,17 +133970,21 @@
133870 break;
133871 }
133872 case SQLITE_TEXT: {
133873 const unsigned char *z = sqlite3_value_text(argv[0]);
133874 const unsigned char *z0;
133875 unsigned char c;
133876 if( z==0 ) return;
133877 z0 = z;
133878 while( (c = *z)!=0 ){
133879 z++;
133880 if( c>=0xc0 ){
133881 while( (*z & 0xc0)==0x80 ){ z++; z0++; }
 
 
 
 
 
133882 }
133883 }
133884 sqlite3_result_int(context, (int)(z-z0));
133885 break;
133886 }
@@ -134155,16 +134259,29 @@
134155 }
134156 p1 -= p2;
134157 }
134158 assert( p1>=0 && p2>=0 );
134159 if( p0type!=SQLITE_BLOB ){
134160 while( *z && p1 ){
134161 SQLITE_SKIP_UTF8(z);
134162 p1--;
 
 
 
 
 
 
134163 }
134164 for(z2=z; *z2 && p2; p2--){
134165 SQLITE_SKIP_UTF8(z2);
 
 
 
 
 
 
 
134166 }
134167 sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
134168 SQLITE_UTF8);
134169 }else{
134170 if( p1>=len ){
@@ -136846,11 +136963,11 @@
136846 sqlite3BtreeEnter(pBtree);
136847 pPager = sqlite3BtreePager(pBtree);
136848 assert( pPager!=0 );
136849 fd = sqlite3PagerFile(pPager);
136850 pStr = sqlite3_str_new(db);
136851 if( pStr==0 ){
136852 sqlite3_result_error_nomem(context);
136853 }else{
136854 sqlite3_str_append(pStr, "{\"db\":", 6);
136855 rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
136856 if( rc ) sqlite3_str_append(pStr, "null", 4);
@@ -136949,11 +137066,11 @@
136949 zUri = (const char*)sqlite3_value_text(argv[0]);
136950 if( zUri==0 ) return;
136951 flgs = (unsigned int)sqlite3_value_int(argv[1]);
136952 rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
136953 pResult = sqlite3_str_new(0);
136954 if( pResult ){
136955 int i;
136956 sqlite3_str_appendf(pResult, "rc=%d", rc);
136957 sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
136958 sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
136959 sqlite3_str_appendf(pResult, ", err=%Q", zErr);
@@ -141499,11 +141616,14 @@
141499 /* All REPLACE indexes are at the end of the list */
141500 assert( pIdx->onError!=OE_Replace
141501 || pIdx->pNext==0
141502 || pIdx->pNext->onError==OE_Replace );
141503 if( aRegIdx[i]==0 ) continue;
141504 if( pIdx->pPartIdxWhere ){
 
 
 
141505 sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
141506 VdbeCoverage(v);
141507 }
141508 pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
141509 if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
@@ -156118,10 +156238,11 @@
156118 if( pParse->nErr==0
156119 && pWhere!=0
156120 && !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
156121 && ALWAYS(p->pSrc!=0)
156122 && p->pSrc->nSrc<BMS
 
156123 ){
156124 if( pWhere->op==TK_AND ){
156125 Expr *pRight = pWhere->pRight;
156126 existsToJoin(pParse, p, pWhere->pLeft);
156127 existsToJoin(pParse, p, pRight);
@@ -156165,11 +156286,10 @@
156165 TREETRACE(0x100000,pParse,p,
156166 ("After EXISTS-to-JOIN optimization:\n"));
156167 sqlite3TreeViewSelect(0, p, 0);
156168 }
156169 #endif
156170 existsToJoin(pParse, p, pSubWhere);
156171 }
156172 }
156173 }
156174 }
156175
@@ -168768,11 +168888,11 @@
168768 ** optimization can be used on multiple
168769 **
168770 ** If the ONEPASS optimization is used (if this routine returns true)
168771 ** then also write the indices of open cursors used by ONEPASS
168772 ** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
168773 ** table and iaCur[1] gets the cursor used by an auxiliary index.
168774 ** Either value may be -1, indicating that cursor is not used.
168775 ** Any cursors returned will have been opened for writing.
168776 **
168777 ** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
168778 ** unable to use the ONEPASS optimization.
@@ -176188,31 +176308,15 @@
176188 sqlite3VdbeJumpHere(v, addrIfNull);
176189 }
176190 }
176191 #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
176192 }
176193 if( pTabList->a[pLevel->iFrom].fg.fromExists
176194 && (i==pWInfo->nLevel-1
176195 || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
176196 ){
176197 /* This is an EXISTS-to-JOIN optimization which is either the
176198 ** inner-most loop, or the inner-most of a group of nested
176199 ** EXISTS-to-JOIN optimization loops. If this loop sees a successful
176200 ** row, it should break out of itself as well as other EXISTS-to-JOIN
176201 ** loops in which is is directly nested. */
176202 int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
176203 while( nOuter<i ){
176204 if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
176205 nOuter++;
176206 }
176207 testcase( nOuter>0 );
176208 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
176209 if( nOuter ){
176210 VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
176211 }else{
176212 VdbeComment((v, "EXISTS break %d", i));
176213 }
176214 }
176215 sqlite3VdbeResolveLabel(v, pLevel->addrCont);
176216 if( pLevel->op!=OP_Noop ){
176217 sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
176218 sqlite3VdbeChangeP5(v, pLevel->p5);
@@ -184395,10 +184499,11 @@
184395 ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
184396 pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
184397 yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0);
184398 if( yymsp[-4].minor.yy454 ){
184399 yymsp[-4].minor.yy454->x.pList = pList;
 
184400 }else{
184401 sqlite3ExprListDelete(pParse->db, pList);
184402 }
184403 if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
184404 }
@@ -188354,11 +188459,12 @@
188354 db->lastRowid = iRowid;
188355 sqlite3_mutex_leave(db->mutex);
188356 }
188357
188358 /*
188359 ** Return the number of changes in the most recent call to sqlite3_exec().
 
188360 */
188361 SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
188362 #ifdef SQLITE_ENABLE_API_ARMOR
188363 if( !sqlite3SafetyCheckOk(db) ){
188364 (void)SQLITE_MISUSE_BKPT;
@@ -229685,11 +229791,16 @@
229685 );
229686 }
229687
229688 while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
229689 const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
229690 p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
 
 
 
 
 
229691 }
229692 rbuFinalize(p, pSql);
229693 if( p->rc!=SQLITE_OK ) return;
229694
229695 if( p->rc==SQLITE_OK ){
@@ -234093,14 +234204,15 @@
234093 static int sessionSerialLen(const u8 *a){
234094 int e;
234095 int n;
234096 assert( a!=0 );
234097 e = *a;
234098 if( e==0 || e==0xFF ) return 1;
234099 if( e==SQLITE_NULL ) return 1;
234100 if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
234101 return sessionVarintGet(&a[1], &n) + 1 + n;
 
 
 
234102 }
234103
234104 /*
234105 ** Based on the primary key values stored in change aRecord, calculate a
234106 ** hash key. Assume the has table has nBucket buckets. The hash keys
@@ -237157,13 +237269,15 @@
237157 nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem, &n);
237158 nByte += n;
237159 rc = sessionInputBuffer(pIn, nByte);
237160 }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
237161 nByte += 8;
 
 
237162 }
237163 }
237164 if( (pIn->iNext+nByte)>pIn->nData ){
237165 rc = SQLITE_CORRUPT_BKPT;
237166 }
237167 }
237168 *pnByte = nByte;
237169 return rc;
@@ -242453,11 +242567,11 @@
242453 ** The "lemon" program processes an LALR(1) input grammar file, then uses
242454 ** this template to construct a parser. The "lemon" program inserts text
242455 ** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
242456 ** interstitial "-" characters) contained in this template is changed into
242457 ** the value of the %name directive from the grammar. Otherwise, the content
242458 ** of this template is copied straight through into the generate parser
242459 ** source file.
242460 **
242461 ** The following is the concatenation of all %include directives from the
242462 ** input grammar file:
242463 */
@@ -263364,11 +263478,11 @@
263364 int nArg, /* Number of args */
263365 sqlite3_value **apUnused /* Function arguments */
263366 ){
263367 assert( nArg==0 );
263368 UNUSED_PARAM2(nArg, apUnused);
263369 sqlite3_result_text(pCtx, "fts5: 2026-04-11 22:18:05 6fa0216a19c2f165110121227d3f9b9119369f8cd61f9c6d13eaa1ae42a60d60", -1, SQLITE_TRANSIENT);
263370 }
263371
263372 /*
263373 ** Implementation of fts5_locale(LOCALE, TEXT) function.
263374 **
@@ -265884,13 +265998,13 @@
265884 int mask = 0;
265885 int bCons = 0;
265886 for(i=0; i<nStem; i++){
265887 bCons = !fts5PorterIsVowel(zStem[i], bCons);
265888 assert( bCons==0 || bCons==1 );
265889 mask = (mask << 1) + bCons;
265890 }
265891 return ((mask & 0x0007)==0x0005);
265892 }
265893 }
265894
265895 /* porter rule condition: (m > 1 and (*S or *T)) */
265896 static int fts5Porter_MGt1_and_S_or_T(char *zStem, int nStem){
265897
--- 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 ** e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6 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.54.0"
471 #define SQLITE_VERSION_NUMBER 3054000
472 #define SQLITE_SOURCE_ID "2026-04-23 16:40:34 e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6ca6ecb7ff1a3a9a237715eed5d30"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2026-04-23T16:40:34.462Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -3311,11 +3311,11 @@
3311 ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
3312 ** automatically by sqlite3_complete16(). If that initialization fails,
3313 ** then the return value from sqlite3_complete16() will be non-zero
3314 ** regardless of whether or not the input SQL is complete.)^
3315 **
3316 ** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
3317 ** must be a zero-terminated UTF-8 string.
3318 **
3319 ** The input to [sqlite3_complete16()] must be a zero-terminated
3320 ** UTF-16 string in native byte order.
3321 */
@@ -17812,11 +17812,11 @@
17812 #define OP_Rowid 137 /* synopsis: r[P2]=PX rowid of P1 */
17813 #define OP_NullRow 138
17814 #define OP_SeekEnd 139
17815 #define OP_IdxInsert 140 /* synopsis: key=r[P2] */
17816 #define OP_SorterInsert 141 /* synopsis: key=r[P2] */
17817 #define OP_IdxDelete 142 /* synopsis: key=r[P2@P5] */
17818 #define OP_DeferredSeek 143 /* synopsis: Move P3 to P1.rowid if needed */
17819 #define OP_IdxRowid 144 /* synopsis: r[P2]=rowid */
17820 #define OP_FinishSeek 145
17821 #define OP_Destroy 146
17822 #define OP_Clear 147
@@ -21617,10 +21617,61 @@
21617 #endif
21618
21619 /*
21620 ** Assuming zIn points to the first byte of a UTF-8 character,
21621 ** advance zIn to point to the first byte of the next UTF-8 character.
21622 **
21623 ** # Dividing malformed UTF-8 into characters (tag-20260418-01)
21624 **
21625 ** If a text input is malformed UTF-8, SQLite does not make any guarantees
21626 ** about how the bytes are divided up into characters. The system promises
21627 ** to not overflow an array or cause other memory errors when presented
21628 ** with malformed UTF-8. And it promises to preserve the specific
21629 ** sequence of bytes as long as no conversion occur. But beyond that,
21630 ** there are no guarantees. Results can vary from one version to the
21631 ** next.
21632 **
21633 ** The SQLITE_SKIP_UTF8 macro below is one technique for dividing UTF-8
21634 ** into characters. The length() and substr() SQL functions use a
21635 ** different technique when searching across multiple characters, a
21636 ** technique that exchanges a subtraction for comparison of z and results
21637 ** in faster machine code on some compilers and architectures. The code
21638 ** in substr() to skip over p1 characters goes something like this:
21639 **
21640 ** for( ; p1>0; p1--){
21641 ** // vvvv--- tag-20260418-01
21642 ** if( (u8)(z[0]-1)<(0x80-1) ){
21643 ** z++;
21644 ** }else if( z[0]==0 ){
21645 ** break;
21646 ** }else{
21647 ** do{ z++; }while( (z[0]&0xc0)==0x80 );
21648 ** }
21649 ** }
21650 **
21651 ** In valid UTF-8, multibyte characters always begin with a byte with the
21652 ** two most significant bits set and that is followed by one or more bytes
21653 ** for which the two most significant bits are 10. In other words:
21654 **
21655 ** First byte: (BYTE & 0xc0)==0xc0
21656 ** Following bytes: (BYTE & 0xc0)==0x80
21657 **
21658 ** What to do if the input byte sequence contain a "following byte" that
21659 ** is not preceded by a "first byte"? How many characters are in the
21660 ** byte sequence: 0x61 0x81 0x82 0x7a? 3 or 4 or something else?
21661 **
21662 ** If you use the macro below, the answer will be 4. If you use the code
21663 ** snippet demonstrated at tag-20260418-01, then answer is 3. If you
21664 ** use a variant of tag-20260418-01 where the constant of comparison is
21665 ** 0xc0-1 instead of 0x80-1 then the answer is again 4. The key point is
21666 ** that because the input is malformed UTF-8, so is no "correct" answer.
21667 ** SQLite is free to use either value.
21668 **
21669 ** It turns out that GCC 13.3.0 is able to generate faster code (at least
21670 ** on x86-64) if the constant at tag-20260418-01 is (0x80-1). If you make
21671 ** that constant (0xc0-1) instead, gcc 13.3.0 generates code that runs slower.
21672 ** So the (0x80-1) constant is used for substr() and length().
21673 */
21674 #define SQLITE_SKIP_UTF8(zIn) { \
21675 if( (*(zIn++))>=0xc0 ){ \
21676 while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
21677 } \
@@ -33680,11 +33731,11 @@
33731 /*
33732 ** Destroy a dynamically allocate sqlite3_str object and all
33733 ** of its content, all in one call.
33734 */
33735 SQLITE_API void sqlite3_str_free(sqlite3_str *p){
33736 if( p!=0 && p!=&sqlite3OomStr ){
33737 sqlite3_str_reset(p);
33738 sqlite3_free(p);
33739 }
33740 }
33741
@@ -39056,11 +39107,11 @@
39107 /* 137 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
39108 /* 138 */ "NullRow" OpHelp(""),
39109 /* 139 */ "SeekEnd" OpHelp(""),
39110 /* 140 */ "IdxInsert" OpHelp("key=r[P2]"),
39111 /* 141 */ "SorterInsert" OpHelp("key=r[P2]"),
39112 /* 142 */ "IdxDelete" OpHelp("key=r[P2@P5]"),
39113 /* 143 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
39114 /* 144 */ "IdxRowid" OpHelp("r[P2]=rowid"),
39115 /* 145 */ "FinishSeek" OpHelp(""),
39116 /* 146 */ "Destroy" OpHelp(""),
39117 /* 147 */ "Clear" OpHelp(""),
@@ -61607,11 +61658,11 @@
61658 ** after rollback of a hot-journal, or if an error occurs while opening
61659 ** the journal file or writing the very first journal-header of a
61660 ** database transaction.
61661 **
61662 ** This routine is never called in PAGER_ERROR state. If it is called
61663 ** in PAGER_OPEN or PAGER_READER state and the lock held is less
61664 ** exclusive than a RESERVED lock, it is a no-op.
61665 **
61666 ** Otherwise, any active savepoints are released.
61667 **
61668 ** If the journal file is open, then it is "finalized". Once a journal
@@ -63368,11 +63419,11 @@
63419 ** * the database is either not an in-memory database or it is
63420 ** an in-memory database that currently consists of zero pages.
63421 **
63422 ** then the pager object page size is set to *pPageSize.
63423 **
63424 ** If the page size is changed, then this function uses sqlite3PageMalloc()
63425 ** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
63426 ** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
63427 ** In all other cases, SQLITE_OK is returned.
63428 **
63429 ** If the page size is not changed, either because one of the enumerated
@@ -64715,12 +64766,12 @@
64766 return pPager->fd;
64767 }
64768
64769
64770 /*
64771 ** This function is called while transitioning from PAGER_OPEN to a
64772 ** higher state. It tests if there is a hot journal present in
64773 ** the file-system for the given pager. A hot journal is one that
64774 ** needs to be played back. According to this function, a hot-journal
64775 ** file exists if the following criteria are met:
64776 **
64777 ** * The journal file exists in the file system, and
@@ -79088,16 +79139,16 @@
79139 ** Compare the "idx"-th cell on the page pPage against the key
79140 ** pointing to by pIdxKey using xRecordCompare. Return negative or
79141 ** zero if the cell is less than or equal pIdxKey. Return positive
79142 ** if unknown.
79143 **
79144 ** Return value negative: Cell at pPage[idx] less than pIdxKey
79145 **
79146 ** Return value is zero: Cell at pPage[idx] equals pIdxKey
79147 **
79148 ** Return value positive: Nothing is known about the relationship
79149 ** of the cell at pPage[idx] and pIdxKey.
79150 **
79151 ** This routine is part of an optimization. It is always safe to return
79152 ** a positive value as that will cause the optimization to be skipped.
79153 */
79154 static int indexCellCompare(
@@ -89650,11 +89701,10 @@
89701
89702
89703 #if VDBE_DISPLAY_P4
89704 /*
89705 ** Compute a string that describes the P4 parameter for an opcode.
 
89706 */
89707 SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
89708 char *zP4 = 0;
89709 StrAccum x;
89710
@@ -97184,11 +97234,10 @@
97234 }
97235 }
97236 return h;
97237 }
97238
 
97239 /*
97240 ** For OP_Column, factor out the case where content is loaded from
97241 ** overflow pages, so that the code to implement this case is separate
97242 ** the common case where all content fits on the page. Factoring out
97243 ** the code reduces register pressure and helps the common case
@@ -97269,10 +97318,44 @@
97318 }
97319 }
97320 pDest->flags &= ~MEM_Ephem;
97321 return rc;
97322 }
97323
97324 /*
97325 ** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
97326 ** open on an index. If the current index entry matches the blob value in
97327 ** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
97328 **
97329 ** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
97330 ** case as well.
97331 */
97332 static SQLITE_NOINLINE int vdbeIndexKeyCompare(
97333 BtCursor *pCsr, /* Cursor to compare key to */
97334 Mem *pMem,
97335 int *pRc
97336 ){
97337 int ret = 0;
97338 u32 nKey = 0;
97339
97340 assert( pMem->flags & (MEM_Blob|MEM_Null) );
97341 nKey = sqlite3BtreePayloadSize(pCsr);
97342 if( nKey==(u32)pMem->n && ALWAYS((pMem->flags & MEM_Blob)!=0) ){
97343 /* This code could just use sqlite3BtreePayloadFetch(). But calling that
97344 ** function here apparently prevents compilers from inlining it in other,
97345 ** more performance critical, places. So this code uses
97346 ** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
97347 ** handles the case where the index record uses overflow pages. */
97348 Mem m;
97349 memset(&m, 0, sizeof(m));
97350 *pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
97351 ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
97352 sqlite3VdbeMemReleaseMalloc(&m);
97353 }
97354
97355 return ret;
97356 }
97357
97358 /*
97359 ** Send a "statement aborts" message to the error log.
97360 */
97361 static SQLITE_NOINLINE void sqlite3VdbeLogAbort(
@@ -103098,18 +103181,23 @@
103181 rc = sqlite3VdbeSorterWrite(pC, pIn2);
103182 if( rc) goto abort_due_to_error;
103183 break;
103184 }
103185
103186 /* Opcode: IdxDelete P1 P2 P3 P4 P5
103187 ** Synopsis: key=r[P2@P5]
103188 **
103189 ** The content of P5 registers starting at register P2 form
103190 ** an unpacked index key. This opcode removes that entry from the
103191 ** index opened by cursor P1.
103192 **
103193 ** P4 is a pointer to an Index structure.
103194 **
103195 ** If P3 is non-zero, it is the register number of a register holding
103196 ** a record that will be inserted into this index. If that record is
103197 ** identical to the one that would be deleted by this instruction,
103198 ** skip the delete and set register P3 to NULL.
103199 **
103200 ** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
103201 ** and not in writable_schema mode.
103202 */
103203 case OP_IdxDelete: {
@@ -103116,21 +103204,21 @@
103204 VdbeCursor *pC;
103205 BtCursor *pCrsr;
103206 int res;
103207 UnpackedRecord r;
103208
103209 assert( pOp->p5>0 );
103210 assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
103211 assert( pOp->p1>=0 && pOp->p1<p->nCursor );
103212 pC = p->apCsr[pOp->p1];
103213 assert( pC!=0 );
103214 assert( pC->eCurType==CURTYPE_BTREE );
103215 sqlite3VdbeIncrWriteCounter(p, pC);
103216 pCrsr = pC->uc.pCursor;
103217 assert( pCrsr!=0 );
103218 r.pKeyInfo = pC->pKeyInfo;
103219 r.nField = pOp->p5;
103220 r.default_rc = 0;
103221 r.aMem = &aMem[pOp->p2];
103222 rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
103223 if( rc ) goto abort_due_to_error;
103224 if( res!=0 ){
@@ -103145,10 +103233,17 @@
103233 pC->cacheStatus = CACHE_STALE;
103234 pC->seekResult = 0;
103235 break;
103236 }
103237 }
103238
103239 if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
103240 if( rc ) goto abort_due_to_error;
103241 sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
103242 break;
103243 }
103244
103245 rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
103246 if( rc ) goto abort_due_to_error;
103247 assert( pC->deferredMoveto==0 );
103248 pC->cacheStatus = CACHE_STALE;
103249 pC->seekResult = 0;
@@ -115325,11 +115420,11 @@
115420
115421 /*
115422 ** Walk an expression tree. Return non-zero if
115423 **
115424 ** (1) the expression is constant, and
115425 ** (2) the expression does not originate in the ON or USING clause
115426 ** of a LEFT JOIN, and
115427 ** (3) the expression does not contain any EP_FixedCol TK_COLUMN
115428 ** operands created by the constant propagation optimization.
115429 **
115430 ** When this routine returns true, it indicates that the expression
@@ -123178,11 +123273,13 @@
123273 assert( pSrc->nSrc==1 );
123274 pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0);
123275 if( !pTab ) return;
123276
123277 if( pCons ){
123278 char *z = sqlite3NameFromToken(db, pCons);
123279 zArg = sqlite3MPrintf(db, "%Q", z);
123280 sqlite3DbFree(db, z);
123281 }else{
123282 int iCol;
123283 if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
123284 zArg = sqlite3MPrintf(db, "%d", iCol);
123285 }
@@ -133621,21 +133718,24 @@
133718 Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
133719
133720 v = pParse->pVdbe;
133721 pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
133722 for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
133723 int p3 = 0;
133724 assert( iIdxCur+i!=iDataCur || pPk==pIdx );
133725 if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
133726 if( pIdx==pPk ) continue;
133727 if( iIdxCur+i==iIdxNoSeek ) continue;
133728 VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
133729 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
133730 &iPartIdxLabel, pPrior, r1);
133731 if( pIdx->bHasExpr && aRegIdx ){
133732 p3 = aRegIdx[i];
133733 }
133734 sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, p3);
133735 sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
133736 sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
133737 sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
133738 pPrior = pIdx;
133739 }
133740 }
133741
@@ -133870,17 +133970,21 @@
133970 break;
133971 }
133972 case SQLITE_TEXT: {
133973 const unsigned char *z = sqlite3_value_text(argv[0]);
133974 const unsigned char *z0;
 
133975 if( z==0 ) return;
133976 z0 = z;
133977 while( 1 /*exit-by-break*/ ){
133978 /* vvvvvv---- See tag-20260418-01 */
133979 if( (u8)(z[0]-1)<(0x80-1) ){
133980 z++;
133981 }else if( z[0]==0 ){
133982 break;
133983 }else{
133984 z++;
133985 while( (z[0]&0xc0)==0x80 ){ z++; z0++; }
133986 }
133987 }
133988 sqlite3_result_int(context, (int)(z-z0));
133989 break;
133990 }
@@ -134155,16 +134259,29 @@
134259 }
134260 p1 -= p2;
134261 }
134262 assert( p1>=0 && p2>=0 );
134263 if( p0type!=SQLITE_BLOB ){
134264 for( ; p1>0; p1--){
134265 /* vvvvvv---- See tag-20260418-01 */
134266 if( (u8)(z[0]-1)<(0x80-1) ){
134267 z++;
134268 }else if( z[0]==0 ){
134269 break;
134270 }else{
134271 do{ z++; }while( (z[0]&0xc0)==0x80 );
134272 }
134273 }
134274 for(z2=z; p2>0; p2--){
134275 /* vvvvvv---- See tag-20260418-01 */
134276 if( (u8)(z2[0]-1)<(0x80-1) ){
134277 z2++;
134278 }else if( z2[0]==0 ){
134279 break;
134280 }else{
134281 do{ z2++; }while( (z2[0]&0xc0)==0x80 );
134282 }
134283 }
134284 sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
134285 SQLITE_UTF8);
134286 }else{
134287 if( p1>=len ){
@@ -136846,11 +136963,11 @@
136963 sqlite3BtreeEnter(pBtree);
136964 pPager = sqlite3BtreePager(pBtree);
136965 assert( pPager!=0 );
136966 fd = sqlite3PagerFile(pPager);
136967 pStr = sqlite3_str_new(db);
136968 if( sqlite3_str_errcode(pStr) ){
136969 sqlite3_result_error_nomem(context);
136970 }else{
136971 sqlite3_str_append(pStr, "{\"db\":", 6);
136972 rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
136973 if( rc ) sqlite3_str_append(pStr, "null", 4);
@@ -136949,11 +137066,11 @@
137066 zUri = (const char*)sqlite3_value_text(argv[0]);
137067 if( zUri==0 ) return;
137068 flgs = (unsigned int)sqlite3_value_int(argv[1]);
137069 rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
137070 pResult = sqlite3_str_new(0);
137071 if( !sqlite3_str_errcode(pResult) ){
137072 int i;
137073 sqlite3_str_appendf(pResult, "rc=%d", rc);
137074 sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
137075 sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
137076 sqlite3_str_appendf(pResult, ", err=%Q", zErr);
@@ -141499,11 +141616,14 @@
141616 /* All REPLACE indexes are at the end of the list */
141617 assert( pIdx->onError!=OE_Replace
141618 || pIdx->pNext==0
141619 || pIdx->pNext->onError==OE_Replace );
141620 if( aRegIdx[i]==0 ) continue;
141621 if( pIdx->pPartIdxWhere || (update_flags && pIdx->bHasExpr) ){
141622 /* If this is a partial index, or an UPDATE of an index on an
141623 ** expression, then the record register may be set to NULL to indicate
141624 ** that no record should be inserted into this index. */
141625 sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
141626 VdbeCoverage(v);
141627 }
141628 pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
141629 if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
@@ -156118,10 +156238,11 @@
156238 if( pParse->nErr==0
156239 && pWhere!=0
156240 && !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
156241 && ALWAYS(p->pSrc!=0)
156242 && p->pSrc->nSrc<BMS
156243 && (p->pLimit==0 || p->pLimit->pRight==0)
156244 ){
156245 if( pWhere->op==TK_AND ){
156246 Expr *pRight = pWhere->pRight;
156247 existsToJoin(pParse, p, pWhere->pLeft);
156248 existsToJoin(pParse, p, pRight);
@@ -156165,11 +156286,10 @@
156286 TREETRACE(0x100000,pParse,p,
156287 ("After EXISTS-to-JOIN optimization:\n"));
156288 sqlite3TreeViewSelect(0, p, 0);
156289 }
156290 #endif
 
156291 }
156292 }
156293 }
156294 }
156295
@@ -168768,11 +168888,11 @@
168888 ** optimization can be used on multiple
168889 **
168890 ** If the ONEPASS optimization is used (if this routine returns true)
168891 ** then also write the indices of open cursors used by ONEPASS
168892 ** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
168893 ** table and aiCur[1] gets the cursor used by an auxiliary index.
168894 ** Either value may be -1, indicating that cursor is not used.
168895 ** Any cursors returned will have been opened for writing.
168896 **
168897 ** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
168898 ** unable to use the ONEPASS optimization.
@@ -176188,31 +176308,15 @@
176308 sqlite3VdbeJumpHere(v, addrIfNull);
176309 }
176310 }
176311 #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
176312 }
176313 if( pTabList->a[pLevel->iFrom].fg.fromExists ){
176314 /* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
176315 ** successful row, it should break out of itself. */
176316 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
176317 VdbeComment((v, "EXISTS break %d", i));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176318 }
176319 sqlite3VdbeResolveLabel(v, pLevel->addrCont);
176320 if( pLevel->op!=OP_Noop ){
176321 sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
176322 sqlite3VdbeChangeP5(v, pLevel->p5);
@@ -184395,10 +184499,11 @@
184499 ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454);
184500 pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454);
184501 yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0);
184502 if( yymsp[-4].minor.yy454 ){
184503 yymsp[-4].minor.yy454->x.pList = pList;
184504 sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454);
184505 }else{
184506 sqlite3ExprListDelete(pParse->db, pList);
184507 }
184508 if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0);
184509 }
@@ -188354,11 +188459,12 @@
188459 db->lastRowid = iRowid;
188460 sqlite3_mutex_leave(db->mutex);
188461 }
188462
188463 /*
188464 ** Return the number of changes in the most recently executed DML
188465 ** statement.
188466 */
188467 SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
188468 #ifdef SQLITE_ENABLE_API_ARMOR
188469 if( !sqlite3SafetyCheckOk(db) ){
188470 (void)SQLITE_MISUSE_BKPT;
@@ -229685,11 +229791,16 @@
229791 );
229792 }
229793
229794 while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
229795 const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
229796 sqlite3_stmt *pStmt = 0;
229797 p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, zSql);
229798 if( p->rc==SQLITE_OK ){
229799 sqlite3_step(pStmt);
229800 rbuFinalize(p, pStmt);
229801 }
229802 }
229803 rbuFinalize(p, pSql);
229804 if( p->rc!=SQLITE_OK ) return;
229805
229806 if( p->rc==SQLITE_OK ){
@@ -234093,14 +234204,15 @@
234204 static int sessionSerialLen(const u8 *a){
234205 int e;
234206 int n;
234207 assert( a!=0 );
234208 e = *a;
 
 
234209 if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
234210 if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
234211 return sessionVarintGet(&a[1], &n) + 1 + n;
234212 }
234213 return 1;
234214 }
234215
234216 /*
234217 ** Based on the primary key values stored in change aRecord, calculate a
234218 ** hash key. Assume the has table has nBucket buckets. The hash keys
@@ -237157,13 +237269,15 @@
237269 nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem, &n);
237270 nByte += n;
237271 rc = sessionInputBuffer(pIn, nByte);
237272 }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
237273 nByte += 8;
237274 }else if( eType!=0 && eType!=SQLITE_NULL ){
237275 rc = SQLITE_CORRUPT_BKPT;
237276 }
237277 }
237278 if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
237279 rc = SQLITE_CORRUPT_BKPT;
237280 }
237281 }
237282 *pnByte = nByte;
237283 return rc;
@@ -242453,11 +242567,11 @@
242567 ** The "lemon" program processes an LALR(1) input grammar file, then uses
242568 ** this template to construct a parser. The "lemon" program inserts text
242569 ** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
242570 ** interstitial "-" characters) contained in this template is changed into
242571 ** the value of the %name directive from the grammar. Otherwise, the content
242572 ** of this template is copied straight through into the generated parser
242573 ** source file.
242574 **
242575 ** The following is the concatenation of all %include directives from the
242576 ** input grammar file:
242577 */
@@ -263364,11 +263478,11 @@
263478 int nArg, /* Number of args */
263479 sqlite3_value **apUnused /* Function arguments */
263480 ){
263481 assert( nArg==0 );
263482 UNUSED_PARAM2(nArg, apUnused);
263483 sqlite3_result_text(pCtx, "fts5: 2026-04-22 19:38:04 f0fc4e5ec334da3a1db8b0334e23d1911874c96675690da94210b2afb45f7307", -1, SQLITE_TRANSIENT);
263484 }
263485
263486 /*
263487 ** Implementation of fts5_locale(LOCALE, TEXT) function.
263488 **
@@ -265884,13 +265998,13 @@
265998 int mask = 0;
265999 int bCons = 0;
266000 for(i=0; i<nStem; i++){
266001 bCons = !fts5PorterIsVowel(zStem[i], bCons);
266002 assert( bCons==0 || bCons==1 );
266003 mask = ((mask << 1) + bCons) & 0x0007;
266004 }
266005 return (mask==0x0005);
266006 }
266007 }
266008
266009 /* porter rule condition: (m > 1 and (*S or *T)) */
266010 static int fts5Porter_MGt1_and_S_or_T(char *zStem, int nStem){
266011
--- 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.54.0"
150150
#define SQLITE_VERSION_NUMBER 3054000
151
-#define SQLITE_SOURCE_ID "2026-04-11 23:58:15 79a8d3edf8207d72f0c4650272ee239a1c7783a07f907fbf0cf5a7ad99b27a2a"
151
+#define SQLITE_SOURCE_ID "2026-04-23 16:40:34 e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6ca6ecb7ff1a3a9a237715eed5d30"
152152
#define SQLITE_SCM_BRANCH "trunk"
153153
#define SQLITE_SCM_TAGS ""
154
-#define SQLITE_SCM_DATETIME "2026-04-11T23:58:15.898Z"
154
+#define SQLITE_SCM_DATETIME "2026-04-23T16:40:34.462Z"
155155
156156
/*
157157
** CAPI3REF: Run-Time Library Version Numbers
158158
** KEYWORDS: sqlite3_version sqlite3_sourceid
159159
**
@@ -2990,11 +2990,11 @@
29902990
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
29912991
** automatically by sqlite3_complete16(). If that initialization fails,
29922992
** then the return value from sqlite3_complete16() will be non-zero
29932993
** regardless of whether or not the input SQL is complete.)^
29942994
**
2995
-** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)
2995
+** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
29962996
** must be a zero-terminated UTF-8 string.
29972997
**
29982998
** The input to [sqlite3_complete16()] must be a zero-terminated
29992999
** UTF-16 string in native byte order.
30003000
*/
30013001
--- 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.54.0"
150 #define SQLITE_VERSION_NUMBER 3054000
151 #define SQLITE_SOURCE_ID "2026-04-11 23:58:15 79a8d3edf8207d72f0c4650272ee239a1c7783a07f907fbf0cf5a7ad99b27a2a"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2026-04-11T23:58:15.898Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
@@ -2990,11 +2990,11 @@
2990 ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
2991 ** automatically by sqlite3_complete16(). If that initialization fails,
2992 ** then the return value from sqlite3_complete16() will be non-zero
2993 ** regardless of whether or not the input SQL is complete.)^
2994 **
2995 ** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)
2996 ** must be a zero-terminated UTF-8 string.
2997 **
2998 ** The input to [sqlite3_complete16()] must be a zero-terminated
2999 ** UTF-16 string in native byte order.
3000 */
3001
--- 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.54.0"
150 #define SQLITE_VERSION_NUMBER 3054000
151 #define SQLITE_SOURCE_ID "2026-04-23 16:40:34 e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6ca6ecb7ff1a3a9a237715eed5d30"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2026-04-23T16:40:34.462Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
@@ -2990,11 +2990,11 @@
2990 ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
2991 ** automatically by sqlite3_complete16(). If that initialization fails,
2992 ** then the return value from sqlite3_complete16() will be non-zero
2993 ** regardless of whether or not the input SQL is complete.)^
2994 **
2995 ** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
2996 ** must be a zero-terminated UTF-8 string.
2997 **
2998 ** The input to [sqlite3_complete16()] must be a zero-terminated
2999 ** UTF-16 string in native byte order.
3000 */
3001
+1 -1
--- src/main.mk
+++ src/main.mk
@@ -703,11 +703,11 @@
703703
-DSQLITE_SHELL_IS_UTF8=1 \
704704
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
705705
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
706706
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
707707
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
708
- -DSQLITE_PS1=\"FossilSQL/040/~/076/040\"
708
+ -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef
709709
710710
# Setup the options used to compile the included Pikchr formatter.
711711
PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
712712
713713
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
714714
--- src/main.mk
+++ src/main.mk
@@ -703,11 +703,11 @@
703 -DSQLITE_SHELL_IS_UTF8=1 \
704 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
705 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
706 -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
707 -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
708 -DSQLITE_PS1=\"FossilSQL/040/~/076/040\"
709
710 # Setup the options used to compile the included Pikchr formatter.
711 PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
712
713 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
714
--- src/main.mk
+++ src/main.mk
@@ -703,11 +703,11 @@
703 -DSQLITE_SHELL_IS_UTF8=1 \
704 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
705 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
706 -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
707 -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
708 -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef
709
710 # Setup the options used to compile the included Pikchr formatter.
711 PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
712
713 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
714
+37
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -319,10 +319,35 @@
319319
if( noRepository ) g.zRepositoryName = 0;
320320
g.db = 0;
321321
g.repositoryOpen = 0;
322322
g.localOpen = 0;
323323
}
324
+
325
+/*
326
+** Return text for /A, /V, or /v prompt excapes.
327
+*/
328
+const char *sqlcmd_ps_appdef(int c){
329
+ if( c=='A' ) return "Fossil";
330
+ if( c=='V' ) return RELEASE_VERSION;
331
+ if( c=='v' ){
332
+ const char *zFull = RELEASE_VERSION;
333
+ const char *zD1, *zD2;
334
+ size_t i;
335
+ static char zRelease[16];
336
+ zD2 = strrchr(zFull,'.');
337
+ zD1 = strchr(zFull,'.');
338
+ if( zD2==0 || zD2==zD1 ){
339
+ return zFull;
340
+ }
341
+ i = zD2 - zFull;
342
+ if( i>sizeof(zRelease)-1 ) return zFull;
343
+ memcpy(zRelease, zFull, i);
344
+ zRelease[i] = 0;
345
+ return zRelease;
346
+ }
347
+ return "";
348
+}
324349
325350
/*
326351
** COMMAND: sql
327352
** COMMAND: sqlite3*
328353
**
@@ -407,10 +432,12 @@
407432
** name X.
408433
*/
409434
void cmd_sqlite3(void){
410435
int noRepository;
411436
char *zConfigDb;
437
+ char *zPrompt;
438
+ char zRelease[16];
412439
extern int sqlite3_shell(int, char**);
413440
#ifdef FOSSIL_ENABLE_TH1_HOOKS
414441
g.fNoThHook = 1;
415442
#endif
416443
noRepository = find_option("no-repository", 0, 0)!=0;
@@ -426,9 +453,19 @@
426453
linenoiseSetMultiLine(1);
427454
#endif
428455
atexit(sqlcmd_atexit);
429456
g.zConfigDbName = zConfigDb;
430457
g.argv[1] = "--noinit";
458
+ zPrompt = fossil_getenv("FOSSIL_PS1");
459
+ if( zPrompt ){
460
+ fossil_setenv("SQLITE_PS1",zPrompt);
461
+ }else{
462
+ fossil_setenv("SQLITE_PS1","/A-/V /~> ");
463
+ }
464
+ zPrompt = fossil_getenv("FOSSIL_PS2");
465
+ if( zPrompt ){
466
+ fossil_setenv("SQLITE_PS2",zPrompt);
467
+ }
431468
sqlite3_shell(g.argc, g.argv);
432469
sqlite3_cancel_auto_extension((void(*)(void))sqlcmd_autoinit);
433470
fossil_close(0, noRepository);
434471
}
435472
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -319,10 +319,35 @@
319 if( noRepository ) g.zRepositoryName = 0;
320 g.db = 0;
321 g.repositoryOpen = 0;
322 g.localOpen = 0;
323 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
325 /*
326 ** COMMAND: sql
327 ** COMMAND: sqlite3*
328 **
@@ -407,10 +432,12 @@
407 ** name X.
408 */
409 void cmd_sqlite3(void){
410 int noRepository;
411 char *zConfigDb;
 
 
412 extern int sqlite3_shell(int, char**);
413 #ifdef FOSSIL_ENABLE_TH1_HOOKS
414 g.fNoThHook = 1;
415 #endif
416 noRepository = find_option("no-repository", 0, 0)!=0;
@@ -426,9 +453,19 @@
426 linenoiseSetMultiLine(1);
427 #endif
428 atexit(sqlcmd_atexit);
429 g.zConfigDbName = zConfigDb;
430 g.argv[1] = "--noinit";
 
 
 
 
 
 
 
 
 
 
431 sqlite3_shell(g.argc, g.argv);
432 sqlite3_cancel_auto_extension((void(*)(void))sqlcmd_autoinit);
433 fossil_close(0, noRepository);
434 }
435
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -319,10 +319,35 @@
319 if( noRepository ) g.zRepositoryName = 0;
320 g.db = 0;
321 g.repositoryOpen = 0;
322 g.localOpen = 0;
323 }
324
325 /*
326 ** Return text for /A, /V, or /v prompt excapes.
327 */
328 const char *sqlcmd_ps_appdef(int c){
329 if( c=='A' ) return "Fossil";
330 if( c=='V' ) return RELEASE_VERSION;
331 if( c=='v' ){
332 const char *zFull = RELEASE_VERSION;
333 const char *zD1, *zD2;
334 size_t i;
335 static char zRelease[16];
336 zD2 = strrchr(zFull,'.');
337 zD1 = strchr(zFull,'.');
338 if( zD2==0 || zD2==zD1 ){
339 return zFull;
340 }
341 i = zD2 - zFull;
342 if( i>sizeof(zRelease)-1 ) return zFull;
343 memcpy(zRelease, zFull, i);
344 zRelease[i] = 0;
345 return zRelease;
346 }
347 return "";
348 }
349
350 /*
351 ** COMMAND: sql
352 ** COMMAND: sqlite3*
353 **
@@ -407,10 +432,12 @@
432 ** name X.
433 */
434 void cmd_sqlite3(void){
435 int noRepository;
436 char *zConfigDb;
437 char *zPrompt;
438 char zRelease[16];
439 extern int sqlite3_shell(int, char**);
440 #ifdef FOSSIL_ENABLE_TH1_HOOKS
441 g.fNoThHook = 1;
442 #endif
443 noRepository = find_option("no-repository", 0, 0)!=0;
@@ -426,9 +453,19 @@
453 linenoiseSetMultiLine(1);
454 #endif
455 atexit(sqlcmd_atexit);
456 g.zConfigDbName = zConfigDb;
457 g.argv[1] = "--noinit";
458 zPrompt = fossil_getenv("FOSSIL_PS1");
459 if( zPrompt ){
460 fossil_setenv("SQLITE_PS1",zPrompt);
461 }else{
462 fossil_setenv("SQLITE_PS1","/A-/V /~> ");
463 }
464 zPrompt = fossil_getenv("FOSSIL_PS2");
465 if( zPrompt ){
466 fossil_setenv("SQLITE_PS2",zPrompt);
467 }
468 sqlite3_shell(g.argc, g.argv);
469 sqlite3_cancel_auto_extension((void(*)(void))sqlcmd_autoinit);
470 fossil_close(0, noRepository);
471 }
472
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -275,11 +275,11 @@
275275
-DSQLITE_SHELL_IS_UTF8=1
276276
-DSQLITE_OMIT_LOAD_EXTENSION=1
277277
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
278278
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname
279279
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
280
- -DSQLITE_PS1=\\\"FossilSQL/040/~/076/040\\\"
280
+ -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef
281281
}]
282282
283283
# Options used to compile the included SQLite shell on Windows.
284284
#
285285
set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
286286
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -275,11 +275,11 @@
275 -DSQLITE_SHELL_IS_UTF8=1
276 -DSQLITE_OMIT_LOAD_EXTENSION=1
277 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
278 -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname
279 -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
280 -DSQLITE_PS1=\\\"FossilSQL/040/~/076/040\\\"
281 }]
282
283 # Options used to compile the included SQLite shell on Windows.
284 #
285 set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
286
--- tools/makemake.tcl
+++ tools/makemake.tcl
@@ -275,11 +275,11 @@
275 -DSQLITE_SHELL_IS_UTF8=1
276 -DSQLITE_OMIT_LOAD_EXTENSION=1
277 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
278 -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname
279 -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
280 -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef
281 }]
282
283 # Options used to compile the included SQLite shell on Windows.
284 #
285 set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
286
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,11 +28,11 @@
2828
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2929
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
3030
3131
SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP
3232
33
-SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -DSQLITE_PS1=\"FossilSQL/040/~/076/040\" -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
33
+SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3434
3535
PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
3636
3737
SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c match_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c robot_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c xsystem_.c zip_.c
3838
3939
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,11 +28,11 @@
28 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
29 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
30
31 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP
32
33 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -DSQLITE_PS1=\"FossilSQL/040/~/076/040\" -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
34
35 PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
36
37 SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c match_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c robot_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c xsystem_.c zip_.c
38
39
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,11 +28,11 @@
28 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
29 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
30
31 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP
32
33 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_ENABLE_PERCENTILE -DSQLITE_ENABLE_SETLK_TIMEOUT -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DHAVE_USLEEP -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
34
35 PIKCHR_OPTIONS = -DPIKCHR_TOKEN_LIMIT=10000
36
37 SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c match_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c robot_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c xsystem_.c zip_.c
38
39
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2602,11 +2602,11 @@
26022602
-DSQLITE_SHELL_IS_UTF8=1 \
26032603
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
26042604
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
26052605
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
26062606
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
2607
- -DSQLITE_PS1=\"FossilSQL/040/~/076/040\" \
2607
+ -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef \
26082608
-Daccess=file_access \
26092609
-Dsystem=fossil_system \
26102610
-Dgetenv=fossil_getenv \
26112611
-Dfopen=fossil_fopen
26122612
26132613
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2602,11 +2602,11 @@
2602 -DSQLITE_SHELL_IS_UTF8=1 \
2603 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
2604 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
2605 -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
2606 -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
2607 -DSQLITE_PS1=\"FossilSQL/040/~/076/040\" \
2608 -Daccess=file_access \
2609 -Dsystem=fossil_system \
2610 -Dgetenv=fossil_getenv \
2611 -Dfopen=fossil_fopen
2612
2613
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2602,11 +2602,11 @@
2602 -DSQLITE_SHELL_IS_UTF8=1 \
2603 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
2604 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
2605 -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
2606 -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
2607 -DSQLITE_PS_APPDEF=sqlcmd_ps_appdef \
2608 -Daccess=file_access \
2609 -Dsystem=fossil_system \
2610 -Dgetenv=fossil_getenv \
2611 -Dfopen=fossil_fopen
2612
2613
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -357,11 +357,11 @@
357357
/DSQLITE_SHELL_IS_UTF8=1 \
358358
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
359359
/DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
360360
/DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
361361
/DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
362
- /DSQLITE_PS1=\"FossilSQL/040/~/076/040\" \
362
+ /DSQLITE_PS_APPDEF=sqlcmd_ps_appdef \
363363
/Daccess=file_access \
364364
/Dsystem=fossil_system \
365365
/Dgetenv=fossil_getenv \
366366
/Dfopen=fossil_fopen
367367
368368
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -357,11 +357,11 @@
357 /DSQLITE_SHELL_IS_UTF8=1 \
358 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
359 /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
360 /DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
361 /DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
362 /DSQLITE_PS1=\"FossilSQL/040/~/076/040\" \
363 /Daccess=file_access \
364 /Dsystem=fossil_system \
365 /Dgetenv=fossil_getenv \
366 /Dfopen=fossil_fopen
367
368
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -357,11 +357,11 @@
357 /DSQLITE_SHELL_IS_UTF8=1 \
358 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
359 /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
360 /DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
361 /DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
362 /DSQLITE_PS_APPDEF=sqlcmd_ps_appdef \
363 /Daccess=file_access \
364 /Dsystem=fossil_system \
365 /Dgetenv=fossil_getenv \
366 /Dfopen=fossil_fopen
367
368

Keyboard Shortcuts

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