Fossil SCM

Merge trunk into rss-content.

vor0nwe 2026-06-23 18:37 UTC rss-content merge
Commit f118634c5caefd1fcae765b2298eb86e9a8378046e3e9db8e7c83c90d34c005b
74 files changed +1 -2 +440 -282 +1551 -532 +32 -8 +17 -41 +43 -73 +30 -37 +72 -10 +1 -1 +1199 -181 +20 -1 +1 -1 +2 +3 -2 +4 +2 +1 +37 -8 +2 -1 +177 -1 +26 -14 +12 -11 +16 -4 +1 -1 +14 -7 +1 -1 +1301 -214 +1301 -214 +663 +8 -5 +4 +1295 -35 +5 -6 +10 -10 +62 -7 +3 -2 +101 -38 +3 -1 +2 -1 +6 -1 +98 -53 +39 -3 +61 -21 +128 -1 +251 -58 +2 -2 +1 -1 +4 +4 +13 -3 +34 +17 -2 +22 -3 +33 +107 -27 +18 +11 -6 +2 -2 +11 -39 +11 -39 +16 -15 +115 -43 +4 -1 +2 +4 +45 -36 +26 +2 -2 +28 -10 +193 -1 +142 -119 +6 -6 +3 -1 +3 -3
+1 -2
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -68,12 +68,11 @@
6868
const sqlite3_qrf_spec *pSpec, /* Result format specification */
6969
char **pzErr /* OUT: Write error message here */
7070
);
7171
7272
/*
73
-** Range of values for sqlite3_qrf_spec.aWidth[] entries and for
74
-** sqlite3_qrf_spec.mxColWidth and .nScreenWidth
73
+** Range of values for sqlite3_qrf_spec.aWidth[] entries.
7574
*/
7675
#define QRF_MAX_WIDTH 10000
7776
#define QRF_MIN_WIDTH 0
7877
7978
/*
8079
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -68,12 +68,11 @@
68 const sqlite3_qrf_spec *pSpec, /* Result format specification */
69 char **pzErr /* OUT: Write error message here */
70 );
71
72 /*
73 ** Range of values for sqlite3_qrf_spec.aWidth[] entries and for
74 ** sqlite3_qrf_spec.mxColWidth and .nScreenWidth
75 */
76 #define QRF_MAX_WIDTH 10000
77 #define QRF_MIN_WIDTH 0
78
79 /*
80
--- extsrc/qrf.h
+++ extsrc/qrf.h
@@ -68,12 +68,11 @@
68 const sqlite3_qrf_spec *pSpec, /* Result format specification */
69 char **pzErr /* OUT: Write error message here */
70 );
71
72 /*
73 ** Range of values for sqlite3_qrf_spec.aWidth[] entries.
 
74 */
75 #define QRF_MAX_WIDTH 10000
76 #define QRF_MIN_WIDTH 0
77
78 /*
79
+440 -282
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,16 +5,16 @@
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
1110
** ext/misc/appendvfs.c
1211
** ext/misc/base64.c
1312
** ext/misc/base85.c
1413
** ext/misc/completion.c
1514
** ext/misc/decimal.c
15
+** ext/misc/diskused.c
1616
** ext/misc/fileio.c
1717
** ext/misc/ieee754.c
1818
** ext/misc/memtrace.c
1919
** ext/misc/pcachetrace.c
2020
** ext/misc/regexp.c
@@ -154,10 +154,11 @@
154154
#include <string.h>
155155
#include <stdio.h>
156156
#include <assert.h>
157157
#include <math.h>
158158
#include <stdint.h>
159
+#include <time.h>
159160
#include "sqlite3.h"
160161
typedef sqlite3_int64 i64;
161162
typedef sqlite3_uint64 u64;
162163
typedef unsigned char u8;
163164
#include <ctype.h>
@@ -190,13 +191,14 @@
190191
#include <sys/stat.h>
191192
192193
#if HAVE_READLINE
193194
# include <readline/readline.h>
194195
# include <readline/history.h>
195
-#endif
196
-
197
-#if HAVE_EDITLINE
196
+#elif HAVE_EDITLINE
197
+/* If both HAVE_READLINE and HAVE_EDITLINE are true, assume that this
198
+** libedit installation does not have its own headers, instead using
199
+** those from libreadline. */
198200
# include <editline/readline.h>
199201
#endif
200202
201203
#if HAVE_EDITLINE || HAVE_READLINE
202204
@@ -744,12 +746,11 @@
744746
const sqlite3_qrf_spec *pSpec, /* Result format specification */
745747
char **pzErr /* OUT: Write error message here */
746748
);
747749
748750
/*
749
-** Range of values for sqlite3_qrf_spec.aWidth[] entries and for
750
-** sqlite3_qrf_spec.mxColWidth and .nScreenWidth
751
+** Range of values for sqlite3_qrf_spec.aWidth[] entries.
751752
*/
752753
#define QRF_MAX_WIDTH 10000
753754
#define QRF_MIN_WIDTH 0
754755
755756
/*
@@ -1129,10 +1130,14 @@
11291130
sqlite3_str_append(pOut, "-", 1);
11301131
}
11311132
if( N<10000 ){
11321133
sqlite3_str_appendf(pOut, "%4lld ", N);
11331134
return;
1135
+ }
1136
+ if( N>=9223372036854775800LL ){
1137
+ sqlite3_str_appendf(pOut, "%.2fE", 1e-18*(double)N);
1138
+ return;
11341139
}
11351140
for(i=1; i<=18; i++){
11361141
N = (N+5)/10;
11371142
if( N<10000 ){
11381143
int n = (int)N;
@@ -1289,12 +1294,12 @@
12891294
if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
12901295
int nSp = 0;
12911296
sqlite3_str_reset(pStats);
12921297
if( nCycle>=0 && nTotal>0 ){
12931298
qrfApproxInt64(pStats, nCycle);
1294
- sqlite3_str_appendf(pStats, " %3d%%",
1295
- ((nCycle*100)+nTotal/2) / nTotal
1299
+ sqlite3_str_appendf(pStats, " %3.0f%%",
1300
+ ((100.0*(double)nCycle)+nTotal/2.0) / (double)nTotal
12961301
);
12971302
nSp = 2;
12981303
}
12991304
if( nLoop>=0 ){
13001305
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
@@ -1787,11 +1792,11 @@
17871792
}
17881793
if( i>0 ){
17891794
sqlite3_str_append(pOut, (const char*)z, i);
17901795
}
17911796
switch( z[i] ){
1792
- case '>': sqlite3_str_append(pOut, "&lt;", 4); break;
1797
+ case '>': sqlite3_str_append(pOut, "&gt;", 4); break;
17931798
case '&': sqlite3_str_append(pOut, "&amp;", 5); break;
17941799
case '<': sqlite3_str_append(pOut, "&lt;", 4); break;
17951800
case '"': sqlite3_str_append(pOut, "&quot;", 6); break;
17961801
case '\'': sqlite3_str_append(pOut, "&#39;", 5); break;
17971802
default: i--;
@@ -2281,11 +2286,11 @@
22812286
if( bWrap && z[i]!=0 && !qrfSpace(z[i]) && qrfAlnum(c)==qrfAlnum(z[i]) ){
22822287
/* Perhaps try to back up to a better place to break the line */
22832288
for(k=i-1; k>=i/2; k--){
22842289
if( qrfSpace(z[k]) ) break;
22852290
}
2286
- if( k<i/2 ){
2291
+ if( k<i/2 && i/2>0 ){
22872292
for(k=i; k>=i/2; k--){
22882293
if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
22892294
}
22902295
}
22912296
if( k>=i/2 ){
@@ -2532,16 +2537,16 @@
25322537
const char *azDash[2] = {
25332538
BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24,
25342539
DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
25352540
};/* 0 1 2 3 4 5 6 7 8 9 */
25362541
const int nDash = 30;
2537
- N *= 3;
2538
- while( N>nDash ){
2542
+ i64 nn = 3*(i64)N;
2543
+ while( nn>nDash ){
25392544
sqlite3_str_append(pOut, azDash[bDbl], nDash);
2540
- N -= nDash;
2545
+ nn -= nDash;
25412546
}
2542
- sqlite3_str_append(pOut, azDash[bDbl], N);
2547
+ sqlite3_str_append(pOut, azDash[bDbl], (int)nn);
25432548
}
25442549
25452550
/*
25462551
** Draw a horizontal separator for a QRF_STYLE_Box table.
25472552
*/
@@ -2610,11 +2615,11 @@
26102615
int nSW /* Screen width */
26112616
){
26122617
int i; /* Loop counter */
26132618
int nr; /* Number of rows */
26142619
int w = 0; /* Width of the current column */
2615
- int t; /* Total width of all columns */
2620
+ i64 t; /* Total width of all columns */
26162621
int *aw; /* Array of individual column widths */
26172622
26182623
aw = sqlite3_malloc64( sizeof(int)*nCol );
26192624
if( aw==0 ){
26202625
qrfOom(p);
@@ -2748,12 +2753,15 @@
27482753
}else{
27492754
sepW = pData->nCol*3 + 1;
27502755
if( p->spec.bBorder==QRF_No ) sepW -= 2;
27512756
}
27522757
nCol = pData->nCol;
2753
- for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
2754
- if( p->spec.nScreenWidth >= sumW+sepW ) return;
2758
+ for(i=0, sumW=0; i<nCol; i++){
2759
+ if( sumW > 2147483647 - pData->a[i].w ) return;
2760
+ sumW += pData->a[i].w;
2761
+ }
2762
+ if( p->spec.nScreenWidth >= (i64)sumW + sepW ) return;
27552763
27562764
/* First thing to do is reduce the separation between columns */
27572765
pData->nMargin = 0;
27582766
if( p->spec.eStyle==QRF_STYLE_Column ){
27592767
sepW = pData->nCol - 1;
@@ -3624,11 +3632,11 @@
36243632
p->nRow = 0;
36253633
sz = sizeof(sqlite3_qrf_spec);
36263634
memcpy(&p->spec, pSpec, sz);
36273635
if( p->spec.zNull==0 ) p->spec.zNull = "";
36283636
p->mxWidth = p->spec.nScreenWidth;
3629
- if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
3637
+ if( p->mxWidth<=0 ) p->mxWidth = 2147483647;
36303638
p->mxHeight = p->spec.nLineLimit;
36313639
if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
36323640
if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
36333641
if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
36343642
if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto;
@@ -5272,10 +5280,14 @@
52725280
#include <stdarg.h>
52735281
52745282
/******************************************************************************
52755283
** The Hash Engine
52765284
*/
5285
+#if defined(__GNUC__) && __GNUC__>=11
5286
+# pragma GCC diagnostic push
5287
+# pragma GCC diagnostic ignored "-Wstringop-overread"
5288
+#endif
52775289
/* Context for the SHA1 hash */
52785290
typedef struct SHA1Context SHA1Context;
52795291
struct SHA1Context {
52805292
unsigned int state[5];
52815293
unsigned int count[2];
@@ -5412,11 +5424,11 @@
54125424
}
54135425
j = 0;
54145426
}else{
54155427
i = 0;
54165428
}
5417
- (void)memcpy(&p->buffer[j], &data[i], len - i);
5429
+ if( len-i>0 ) (void)memcpy(&p->buffer[j], &data[i], len - i);
54185430
}
54195431
54205432
/* Compute a string using sqlite3_vsnprintf() and hash it */
54215433
static void hash_step_vformat(
54225434
SHA1Context *p, /* Add content to this context */
@@ -5467,10 +5479,13 @@
54675479
zOut[i*2+1] = zEncode[digest[i] & 0xf];
54685480
}
54695481
zOut[i*2]= 0;
54705482
}
54715483
}
5484
+#if defined(__GNUC__) && __GNUC__>=11
5485
+# pragma GCC diagnostic pop
5486
+#endif
54725487
/* End of the hashing logic
54735488
*****************************************************************************/
54745489
54755490
/*
54765491
** Two SQL functions: sha1(X) and sha1b(X).
@@ -6056,32 +6071,41 @@
60566071
}
60576072
z[i] = 0;
60586073
sqlite3_result_text(pCtx, z, i, sqlite3_free);
60596074
}
60606075
6076
+/* Forward declaration */
6077
+static void decimal_expand(Decimal *p, int nDigit, int nFrac);
6078
+
60616079
/*
60626080
** Round a decimal value to N significant digits. N must be positive.
60636081
*/
60646082
static void decimal_round(Decimal *p, int N){
60656083
int i;
6066
- int nZero;
6084
+ int nZero; /* Number of leading zeros */
60676085
if( N<1 ) return;
60686086
if( p==0 ) return;
60696087
if( p->nDigit<=N ) return;
60706088
for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
60716089
N += nZero;
60726090
if( p->nDigit<=N ) return;
6073
- if( p->a[N]>4 ){
6091
+ if( p->a[N]>=5 ){
6092
+ /* If all leading digits are 9, increase the number of digits
6093
+ ** by adding a new 0 to the front */
6094
+ for(i=0; i<N && p->a[i]==9; i++){}
6095
+ if( i==N ){
6096
+ decimal_expand(p, p->nDigit+1, 0);
6097
+ if( p->oom ) return;
6098
+ }
6099
+
6100
+ /* Do the rounding */
60746101
p->a[N-1]++;
60756102
for(i=N-1; i>0 && p->a[i]>9; i--){
60766103
p->a[i] = 0;
60776104
p->a[i-1]++;
60786105
}
6079
- if( p->a[0]>9 ){
6080
- p->a[0] = 1;
6081
- p->nFrac--;
6082
- }
6106
+ assert( p->a[0]<=9 );
60836107
}
60846108
memset(&p->a[N], 0, p->nDigit - N);
60856109
}
60866110
60876111
/*
@@ -8363,19 +8387,26 @@
83638387
}
83648388
}else{
83658389
iMin = iMax = sqlite3_value_int64(argv[iArg++]);
83668390
}
83678391
}else{
8368
- if( idxNum & 0x0300 ){ /* value>X or value>=X */
8392
+ if( idxNum & 0x0300 ){ /* value>X (0x200) or value>=X (0x100) */
83698393
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
83708394
double r = sqlite3_value_double(argv[iArg++]);
8371
- if( r<(double)SMALLEST_INT64 ){
8395
+ if( r<=(double)SMALLEST_INT64 ){
83728396
iMin = SMALLEST_INT64;
8373
- }else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
8374
- iMin = (sqlite3_int64)seriesCeil(r+1.0);
8397
+ }else if( r>(double)LARGEST_INT64 ){
8398
+ goto series_no_rows;
83758399
}else{
83768400
iMin = (sqlite3_int64)seriesCeil(r);
8401
+ if( iMin<0 && r>0.0 ){
8402
+ iMin = LARGEST_INT64;
8403
+ }
8404
+ if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
8405
+ if( iMin==LARGEST_INT64 ) goto series_no_rows;
8406
+ iMin++;
8407
+ }
83778408
}
83788409
}else{
83798410
iMin = sqlite3_value_int64(argv[iArg++]);
83808411
if( (idxNum & 0x0200)!=0 ){
83818412
if( iMin==LARGEST_INT64 ){
@@ -8384,19 +8415,25 @@
83848415
iMin++;
83858416
}
83868417
}
83878418
}
83888419
}
8389
- if( idxNum & 0x3000 ){ /* value<X or value<=X */
8420
+ if( idxNum & 0x3000 ){ /* value<X (0x2000) or value<=X (0x1000) */
83908421
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
83918422
double r = sqlite3_value_double(argv[iArg++]);
8392
- if( r>(double)LARGEST_INT64 ){
8423
+ if( r>=(double)LARGEST_INT64 ){
83938424
iMax = LARGEST_INT64;
8394
- }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
8395
- iMax = (sqlite3_int64)(r-1.0);
8425
+ }else if( r<=(double)SMALLEST_INT64 ){
8426
+ goto series_no_rows;
83968427
}else{
83978428
iMax = (sqlite3_int64)seriesFloor(r);
8429
+ if( iMax<0 && r>0.0 ){
8430
+ iMax = LARGEST_INT64;
8431
+ }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
8432
+ if( iMax==SMALLEST_INT64 ) goto series_no_rows;
8433
+ iMax--;
8434
+ }
83988435
}
83998436
}else{
84008437
iMax = sqlite3_value_int64(argv[iArg++]);
84018438
if( idxNum & 0x2000 ){
84028439
if( iMax==SMALLEST_INT64 ){
@@ -9638,11 +9675,10 @@
96389675
if( pRe==0 ){
96399676
sqlite3_result_error_nomem(context);
96409677
return;
96419678
}
96429679
pStr = sqlite3_str_new(0);
9643
- if( pStr==0 ) goto re_bytecode_func_err;
96449680
if( pRe->nInit>0 ){
96459681
sqlite3_str_appendf(pStr, "INIT ");
96469682
for(i=0; i<pRe->nInit; i++){
96479683
sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
96489684
}
@@ -9649,20 +9685,20 @@
96499685
sqlite3_str_appendf(pStr, "\n");
96509686
}
96519687
for(i=0; (unsigned)i<pRe->nState; i++){
96529688
sqlite3_str_appendf(pStr, "%-8s %4d\n",
96539689
ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
9690
+ }
9691
+ if( sqlite3_str_errcode(pStr)==SQLITE_NOMEM ){
9692
+ sqlite3_str_finish(pStr);
9693
+ re_free(pRe);
9694
+ sqlite3_result_error_nomem(context);
9695
+ return;
96549696
}
96559697
n = sqlite3_str_length(pStr);
96569698
z = sqlite3_str_finish(pStr);
9657
- if( n==0 ){
9658
- sqlite3_free(z);
9659
- }else{
9660
- sqlite3_result_text(context, z, n-1, sqlite3_free);
9661
- }
9662
-
9663
-re_bytecode_func_err:
9699
+ sqlite3_result_text(context, z, n-1, sqlite3_free);
96649700
re_free(pRe);
96659701
}
96669702
96679703
#endif /* SQLITE_DEBUG */
96689704
@@ -10870,10 +10906,13 @@
1087010906
** Return NULL if unable.
1087110907
**
1087210908
** The file or directory X is not required to exist. The answer is formed
1087310909
** by calling system realpath() on the prefix of X that does exist and
1087410910
** appending the tail of X that does not (yet) exist.
10911
+**
10912
+** FIXME: This routine sometimes returns NULL rather than raising
10913
+** an SQLITE_NOMEM error if an OOM is encountered.
1087510914
*/
1087610915
static void realpathFunc(
1087710916
sqlite3_context *context,
1087810917
int argc,
1087910918
sqlite3_value **argv
@@ -10892,10 +10931,11 @@
1089210931
(void)argc;
1089310932
zPath = (const char*)sqlite3_value_text(argv[0]);
1089410933
if( zPath==0 ) return;
1089510934
if( zPath[0]==0 ) zPath = ".";
1089610935
zCopy = sqlite3_mprintf("%s",zPath);
10936
+ if( zCopy==0 ) return;
1089710937
len = strlen(zCopy);
1089810938
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
1089910939
len--;
1090010940
}
1090110941
zCopy[len] = 0;
@@ -12685,10 +12725,11 @@
1268512725
1268612726
for(p=pCsr->pFreeEntry; p; p=pNext){
1268712727
pNext = p->pNext;
1268812728
zipfileEntryFree(p);
1268912729
}
12730
+ pCsr->pFreeEntry = 0;
1269012731
}
1269112732
1269212733
/*
1269312734
** Destructor for an ZipfileCsr.
1269412735
*/
@@ -13087,11 +13128,17 @@
1308713128
}
1308813129
}
1308913130
1309013131
if( rc==SQLITE_OK ){
1309113132
u32 *pt = &pNew->mUnixTime;
13092
- pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
13133
+ /* aRead[0..nFile-1] might contain embedded \000 characters
13134
+ ** See Bug 2026-05-31T11:43:05Z */
13135
+ pNew->cds.zFile = sqlite3_malloc64(nFile+1);
13136
+ if( pNew->cds.zFile!=0 ){
13137
+ memcpy(pNew->cds.zFile, aRead, nFile);
13138
+ pNew->cds.zFile[nFile] = 0;
13139
+ }
1309313140
pNew->aExtra = (u8*)&pNew[1];
1309413141
memcpy(pNew->aExtra, &aRead[nFile], nExtra);
1309513142
if( pNew->cds.zFile==0 ){
1309613143
rc = SQLITE_NOMEM;
1309713144
}else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
@@ -14191,14 +14238,14 @@
1419114238
ZipfileBuffer body;
1419214239
ZipfileBuffer cds;
1419314240
};
1419414241
1419514242
static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
14196
- if( pBuf->n+nByte>pBuf->nAlloc ){
14243
+ if( (pBuf->nAlloc-pBuf->n)<nByte ){
1419714244
u8 *aNew;
14198
- sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
14199
- int nReq = pBuf->n + nByte;
14245
+ i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512;
14246
+ i64 nReq = pBuf->n + nByte;
1420014247
1420114248
while( nNew<nReq ) nNew = nNew*2;
1420214249
aNew = sqlite3_realloc64(pBuf->a, nNew);
1420314250
if( aNew==0 ) return SQLITE_NOMEM;
1420414251
pBuf->a = aNew;
@@ -16296,11 +16343,11 @@
1629616343
p->pTable = pTab;
1629716344
1629816345
/* The statement the vtab will pass to sqlite3_declare_vtab() */
1629916346
zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
1630016347
for(i=0; i<pTab->nCol; i++){
16301
- zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
16348
+ zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %Q",
1630216349
(i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
1630316350
);
1630416351
}
1630516352
zInner = idxAppendText(&rc, zInner, ")");
1630616353
@@ -16496,11 +16543,11 @@
1649616543
sqlite3_free(zCols);
1649716544
sqlite3_free(zOrder);
1649816545
return sqlite3_reset(pIndexXInfo);
1649916546
}
1650016547
zCols = idxAppendText(&rc, zCols,
16501
- "%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
16548
+ "%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %Q",
1650216549
zComma, zName, nCol, zName, zColl
1650316550
);
1650416551
zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
1650516552
}
1650616553
sqlite3_reset(pIndexXInfo);
@@ -19464,11 +19511,11 @@
1946419511
sqlite3_vfs_unregister(pVfs);
1946519512
sqlite3_free(pVfs);
1946619513
}
1946719514
1946819515
/************************* End ext/misc/vfstrace.c ********************/
19469
-/************************* Begin ext/misc/analyze.c ******************/
19516
+/************************* Begin ext/misc/diskused.c ******************/
1947019517
/*
1947119518
** 2026-04-13
1947219519
**
1947319520
** The author disclaims copyright to this source code. In place of
1947419521
** a legal notice, here is a blessing:
@@ -19477,12 +19524,21 @@
1947719524
** May you find forgiveness for yourself and forgive others.
1947819525
** May you share freely, never taking more than you give.
1947919526
**
1948019527
******************************************************************************
1948119528
**
19482
-** Partial reimplement of the sqlite3_analyzer utility program as
19483
-** loadable SQL function.
19529
+** This extension implements an SQL function:
19530
+**
19531
+** diskused(X)
19532
+**
19533
+** Where X is the schema name (typically 'main'). The output is text
19534
+** that describes how much filesystem space the various tables and indexes
19535
+** of the database consume.
19536
+**
19537
+** This function is a replacement for the (now deprecated)
19538
+** "sqlite3_analyzer" utility program. This function is built
19539
+** into the CLI and is used to implement the ".diskused" command there.
1948419540
*/
1948519541
/* #include "sqlite3ext.h" */
1948619542
SQLITE_EXTENSION_INIT1
1948719543
#include <assert.h>
1948819544
#include <string.h>
@@ -19490,28 +19546,28 @@
1949019546
#include <math.h>
1949119547
1949219548
/*
1949319549
** State information for the analysis
1949419550
*/
19495
-typedef struct Analysis Analysis;
19496
-struct Analysis {
19551
+typedef struct DiskUsed DiskUsed;
19552
+struct DiskUsed {
1949719553
sqlite3 *db; /* Database connection */
1949819554
sqlite3_context *context; /* SQL function context */
1949919555
sqlite3_str *pOut; /* Write output here */
1950019556
char *zSU; /* Name of the temp.space_used table */
1950119557
const char *zSchema; /* Schema to be analyzed */
1950219558
};
1950319559
1950419560
/*
19505
-** Free all resources that the Analysis object references and
19506
-** reset the Analysis object.
19561
+** Free all resources that the DiskUsed object references and
19562
+** reset the DiskUsed object.
1950719563
**
19508
-** Call this routine multiple times on the same Analysis object
19564
+** Call this routine multiple times on the same DiskUsed object
1950919565
** is a harmless no-op, as long as the memory for the object itself
1951019566
** has not been freed.
1951119567
*/
19512
-static void analysisReset(Analysis *p){
19568
+static void diskusedReset(DiskUsed *p){
1951319569
if( p->zSU ){
1951419570
char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
1951519571
if( zSql ){
1951619572
sqlite3_exec(p->db, zSql, 0, 0, 0);
1951719573
sqlite3_free(zSql);
@@ -19524,11 +19580,11 @@
1952419580
1952519581
/*
1952619582
** Report an error using formatted text. If zFormat==NULL then report
1952719583
** an OOM error.
1952819584
*/
19529
-static void analysisError(Analysis *p, const char *zFormat, ...){
19585
+static void diskusedError(DiskUsed *p, const char *zFormat, ...){
1953019586
char *zErr;
1953119587
if( zFormat ){
1953219588
va_list ap;
1953319589
va_start(ap, zFormat);
1953419590
zErr = sqlite3_vmprintf(zFormat, ap);
@@ -19540,38 +19596,38 @@
1954019596
sqlite3_result_error_nomem(p->context);
1954119597
}else{
1954219598
sqlite3_result_error(p->context, zErr, -1);
1954319599
sqlite3_free(zErr);
1954419600
}
19545
- analysisReset(p);
19601
+ diskusedReset(p);
1954619602
}
1954719603
1954819604
/*
1954919605
** Prepare and return an SQL statement.
1955019606
*/
19551
-static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
19607
+static sqlite3_stmt *diskusedVPrep(DiskUsed *p, const char *zFmt, va_list ap){
1955219608
char *zSql;
1955319609
int rc;
1955419610
sqlite3_stmt *pStmt = 0;
1955519611
zSql = sqlite3_vmprintf(zFmt, ap);
19556
- if( zSql==0 ){ analysisError(p,0); return 0; }
19612
+ if( zSql==0 ){ diskusedError(p,0); return 0; }
1955719613
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
1955819614
if( rc ){
19559
- analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
19615
+ diskusedError(p, "SQL parse error: %s\nOriginal SQL: %s",
1956019616
sqlite3_errmsg(p->db), zSql);
1956119617
sqlite3_finalize(pStmt);
19562
- analysisReset(p);
19618
+ diskusedReset(p);
1956319619
pStmt = 0;
1956419620
}
1956519621
sqlite3_free(zSql);
1956619622
return pStmt;
1956719623
}
19568
-static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
19624
+static sqlite3_stmt *diskusedPrepare(DiskUsed *p, const char *zFormat, ...){
1956919625
va_list ap;
1957019626
sqlite3_stmt *pStmt = 0;
1957119627
va_start(ap, zFormat);
19572
- pStmt = analysisVPrep(p,zFormat,ap);
19628
+ pStmt = diskusedVPrep(p,zFormat,ap);
1957319629
va_end(ap);
1957419630
return pStmt;
1957519631
}
1957619632
1957719633
/*
@@ -19580,60 +19636,60 @@
1958019636
**
1958119637
** If rc is SQLITE_DONE or SQLITE_OK, then return false.
1958219638
**
1958319639
** The prepared statement is closed in either case.
1958419640
*/
19585
-static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
19641
+static int diskusedStmtFinish(DiskUsed *p, int rc, sqlite3_stmt *pStmt){
1958619642
if( rc==SQLITE_DONE ){
1958719643
rc = SQLITE_OK;
1958819644
}
1958919645
if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19590
- analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19646
+ diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
1959119647
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19592
- analysisReset(p);
19648
+ diskusedReset(p);
1959319649
}
1959419650
sqlite3_finalize(pStmt);
1959519651
return rc;
1959619652
}
1959719653
1959819654
/*
1959919655
** Run SQL. Return the number of errors.
1960019656
*/
19601
-static int analysisSql(Analysis *p, const char *zFormat, ...){
19657
+static int diskusedSql(DiskUsed *p, const char *zFormat, ...){
1960219658
va_list ap;
1960319659
int rc;
1960419660
sqlite3_stmt *pStmt = 0;
1960519661
va_start(ap, zFormat);
19606
- pStmt = analysisVPrep(p,zFormat,ap);
19662
+ pStmt = diskusedVPrep(p,zFormat,ap);
1960719663
va_end(ap);
1960819664
if( pStmt==0 ) return 1;
1960919665
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
1961019666
if( rc==SQLITE_DONE ){
1961119667
rc = SQLITE_OK;
1961219668
}else{
19613
- analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19669
+ diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
1961419670
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19615
- analysisReset(p);
19671
+ diskusedReset(p);
1961619672
}
1961719673
sqlite3_finalize(pStmt);
1961819674
return rc;
1961919675
}
1962019676
1962119677
/*
1962219678
** Run an SQL query that returns an integer. Write that integer
1962319679
** into *piRes. Return the number of errors.
1962419680
*/
19625
-static int analysisSqlInt(
19626
- Analysis *p,
19681
+static int diskusedSqlInt(
19682
+ DiskUsed *p,
1962719683
sqlite3_int64 *piRes,
1962819684
const char *zFormat, ...
1962919685
){
1963019686
va_list ap;
1963119687
int rc;
1963219688
sqlite3_stmt *pStmt = 0;
1963319689
va_start(ap, zFormat);
19634
- pStmt = analysisVPrep(p,zFormat,ap);
19690
+ pStmt = diskusedVPrep(p,zFormat,ap);
1963519691
va_end(ap);
1963619692
if( pStmt==0 ) return 1;
1963719693
rc = sqlite3_step(pStmt);
1963819694
if( rc==SQLITE_ROW ){
1963919695
*piRes = sqlite3_column_int64(pStmt, 0);
@@ -19641,14 +19697,14 @@
1964119697
}else if( rc==SQLITE_DONE ){
1964219698
rc = SQLITE_OK;
1964319699
}else{
1964419700
if( p->db ){
1964519701
/* p->db is NULL if there was some prior error */
19646
- analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19702
+ diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
1964719703
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
1964819704
}
19649
- analysisReset(p);
19705
+ diskusedReset(p);
1965019706
}
1965119707
sqlite3_finalize(pStmt);
1965219708
return rc;
1965319709
}
1965419710
@@ -19657,20 +19713,20 @@
1965719713
** by the format string. If the output is initially empty, begin
1965819714
** the title line with "/" so that it forms the beginning of a C-style
1965919715
** comment. Otherwise begin with a new-line. Always finish with a
1966019716
** newline.
1966119717
*/
19662
-static void analysisTitle(Analysis *p, const char *zFormat, ...){
19718
+static void diskusedTitle(DiskUsed *p, const char *zFormat, ...){
1966319719
char *zFirst;
1966419720
char *zTitle;
1966519721
size_t nTitle;
1966619722
va_list ap;
1966719723
va_start(ap, zFormat);
1966819724
zTitle = sqlite3_vmprintf(zFormat, ap);
1966919725
va_end(ap);
1967019726
if( zTitle==0 ){
19671
- analysisError(p, 0);
19727
+ diskusedError(p, 0);
1967219728
return;
1967319729
}
1967419730
zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
1967519731
nTitle = strlen(zTitle);
1967619732
if( nTitle>=75 ){
@@ -19685,12 +19741,12 @@
1968519741
/*
1968619742
** Add an output line that begins with the zDesc text extended out to
1968719743
** 50 columns with "." characters, and followed by whatever text is
1968819744
** described by zFormat.
1968919745
*/
19690
-static void analysisLine(
19691
- Analysis *p, /* Analysis context */
19746
+static void diskusedLine(
19747
+ DiskUsed *p, /* DiskUsed context */
1969219748
const char *zDesc, /* Description */
1969319749
const char *zFormat, /* Argument to the description */
1969419750
...
1969519751
){
1969619752
char *zTxt;
@@ -19698,14 +19754,14 @@
1969819754
va_list ap;
1969919755
va_start(ap, zFormat);
1970019756
zTxt = sqlite3_vmprintf(zFormat, ap);
1970119757
va_end(ap);
1970219758
if( zTxt==0 ){
19703
- analysisError(p, 0);
19759
+ diskusedError(p, 0);
1970419760
return;
1970519761
}
19706
- nDesc = strlen(zDesc);
19762
+ nDesc = zDesc ? strlen(zDesc) : 0;
1970719763
if( nDesc>=50 ){
1970819764
sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
1970919765
}else{
1971019766
int nExtra = 50 - (int)nDesc;
1971119767
sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
@@ -19715,11 +19771,11 @@
1971519771
/*
1971619772
** Write a percentage into the output. The number written should show
1971719773
** two or three significant digits, with the decimal point being the fourth
1971819774
** character.
1971919775
*/
19720
-static void analysisPercent(Analysis *p, double r){
19776
+static void diskusedPercent(DiskUsed *p, double r){
1972119777
char zNum[100];
1972219778
char *zDP;
1972319779
int nLeadingDigit;
1972419780
int sz;
1972519781
sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
@@ -19744,12 +19800,12 @@
1974419800
**
1974519801
** The title if the subreport is given by zTitle. zWhere is
1974619802
** a boolean expression that can go in the WHERE clause to select
1974719803
** the relevant rows of the s.zSU table.
1974819804
*/
19749
-static int analysisSubreport(
19750
- Analysis *p, /* Analysis context */
19805
+static int diskusedSubreport(
19806
+ DiskUsed *p, /* DiskUsed context */
1975119807
char *zTitle, /* Title for this subreport */
1975219808
char *zWhere, /* WHERE clause for this subreport */
1975319809
sqlite3_int64 pgsz, /* Database page size */
1975419810
sqlite3_int64 nPage /* Number of pages in entire database */
1975519811
){
@@ -19773,14 +19829,14 @@
1977319829
sqlite3_int64 total_unused; /* Total unused bytes */
1977419830
sqlite3_int64 total_meta; /* Total metadata */
1977519831
int rc;
1977619832
1977719833
if( zTitle==0 || zWhere==0 ){
19778
- analysisError(p, 0);
19834
+ diskusedError(p, 0);
1977919835
return SQLITE_NOMEM;
1978019836
}
19781
- pStmt = analysisPrepare(p,
19837
+ pStmt = diskusedPrepare(p,
1978219838
"SELECT\n"
1978319839
" sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
1978419840
" sum(payload),\n" /* 1 */
1978519841
" sum(ovfl_payload),\n" /* 2 */
1978619842
" max(mx_payload),\n" /* 3 */
@@ -19797,11 +19853,11 @@
1979719853
" FROM temp.%s WHERE %s",
1979819854
p->zSU, zWhere);
1979919855
if( pStmt==0 ) return 1;
1980019856
rc = sqlite3_step(pStmt);
1980119857
if( rc==SQLITE_ROW ){
19802
- analysisTitle(p, zTitle);
19858
+ diskusedTitle(p, "%s", zTitle);
1980319859
1980419860
nentry = sqlite3_column_int64(pStmt, 0);
1980519861
payload = sqlite3_column_int64(pStmt, 1);
1980619862
ovfl_payload = sqlite3_column_int64(pStmt, 2);
1980719863
mx_payload = sqlite3_column_int64(pStmt, 3);
@@ -19816,73 +19872,73 @@
1981619872
cnt = sqlite3_column_int64(pStmt, 12);
1981719873
int_cell = sqlite3_column_int64(pStmt, 13);
1981819874
rc = SQLITE_DONE;
1981919875
1982019876
total_pages = leaf_pages + int_pages + ovfl_pages;
19821
- analysisLine(p, "Percentage of total database", "%.3g%%\n",
19877
+ diskusedLine(p, "Percentage of total database", "%.3g%%\n",
1982219878
(total_pages*100.0)/(double)nPage);
19823
- analysisLine(p, "Number of entries", "%lld\n", nentry);
19879
+ diskusedLine(p, "Number of entries", "%lld\n", nentry);
1982419880
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);
19881
+ diskusedLine(p, "Bytes of storage consumed", "%lld\n", storage);
19882
+ diskusedLine(p, "Bytes of payload", "%-11lld ", payload);
19883
+ diskusedPercent(p, payload*100.0/(double)storage);
1982819884
if( ovfl_cnt>0 ){
19829
- analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19830
- analysisPercent(p, ovfl_payload*100.0/(double)payload);
19885
+ diskusedLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19886
+ diskusedPercent(p, ovfl_payload*100.0/(double)payload);
1983119887
}
1983219888
total_unused = leaf_unused + int_unused + ovfl_unused;
1983319889
total_meta = storage - payload - total_unused;
19834
- analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
19835
- analysisPercent(p, total_meta*100.0/(double)storage);
19890
+ diskusedLine(p, "Bytes of metadata","%-11lld ", total_meta);
19891
+ diskusedPercent(p, total_meta*100.0/(double)storage);
1983619892
if( cnt==1 ){
19837
- analysisLine(p, "B-tree depth", "%lld\n", depth);
19893
+ diskusedLine(p, "B-tree depth", "%lld\n", depth);
1983819894
if( int_cell>1 ){
19839
- analysisLine(p, "Average fanout", "%.1f\n",
19895
+ diskusedLine(p, "Average fanout", "%.1f\n",
1984019896
(double)(int_cell+int_pages)/(double)int_pages);
1984119897
}
1984219898
}
1984319899
if( nentry>0 ){
19844
- analysisLine(p, "Average payload per entry", "%.1f\n",
19900
+ diskusedLine(p, "Average payload per entry", "%.1f\n",
1984519901
(double)payload/(double)nentry);
19846
- analysisLine(p, "Average unused bytes per entry", "%.1f\n",
19902
+ diskusedLine(p, "Average unused bytes per entry", "%.1f\n",
1984719903
(double)total_unused/(double)nentry);
19848
- analysisLine(p, "Average metadata per entry", "%.1f\n",
19904
+ diskusedLine(p, "Average metadata per entry", "%.1f\n",
1984919905
(double)total_meta/(double)nentry);
1985019906
}
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)
19907
+ diskusedLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19908
+ if( nentry>0 ){
19909
+ diskusedLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19910
+ diskusedPercent(p, ovfl_cnt*100.0/(double)nentry);
19911
+ }
19912
+ if( int_pages>0 ){
19913
+ diskusedLine(p, "Index pages used", "%lld\n", int_pages);
19914
+ }
19915
+ diskusedLine(p, "Primary pages used", "%lld\n", leaf_pages);
19916
+ if( ovfl_cnt ){
19917
+ diskusedLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19918
+ }
19919
+ diskusedLine(p, "Total pages used", "%lld\n", total_pages);
19920
+ if( int_pages>0 ){
19921
+ diskusedLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19922
+ }
19923
+ diskusedLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19924
+ if( ovfl_cnt ){
19925
+ diskusedLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19926
+ }
19927
+ diskusedLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19928
+ diskusedPercent(p, total_unused*100.0/(double)storage);
19929
+ }
19930
+ return diskusedStmtFinish(p, rc, pStmt);
19931
+}
19932
+
19933
+/*
19934
+** SQL Function: diskused(SCHEMA)
1987919935
**
1988019936
** Analyze the database schema named in the argument. Return text
19881
-** containing the analysis.
19937
+** containing the space utilization stats.
1988219938
*/
19883
-static void analyzeFunc(
19939
+static void diskusedFunc(
1988419940
sqlite3_context *context,
1988519941
int argc,
1988619942
sqlite3_value **argv
1988719943
){
1988819944
int rc;
@@ -19893,47 +19949,47 @@
1989319949
sqlite3_int64 nPage;
1989419950
sqlite3_int64 nPageInUse;
1989519951
sqlite3_int64 nFreeList;
1989619952
sqlite3_int64 nIndex;
1989719953
sqlite3_int64 nWORowid;
19898
- Analysis s;
19954
+ DiskUsed s;
1989919955
sqlite3_uint64 r[2];
1990019956
1990119957
(void)argc;
1990219958
memset(&s, 0, sizeof(s));
1990319959
s.db = sqlite3_context_db_handle(context);
1990419960
s.context = context;
1990519961
s.pOut = sqlite3_str_new(0);
1990619962
if( sqlite3_str_errcode(s.pOut) ){
19907
- analysisError(&s, 0);
19963
+ diskusedError(&s, 0);
1990819964
return;
1990919965
}
1991019966
s.zSchema = (const char*)sqlite3_value_text(argv[0]);
1991119967
if( s.zSchema==0 ){
1991219968
s.zSchema = "main";
1991319969
}else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19914
- analysisReset(&s);
19970
+ diskusedReset(&s);
1991519971
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
1991619972
return;
1991719973
}
1991819974
ii = 0;
19919
- rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
19975
+ rc = diskusedSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
1992019976
" WHERE name=%Q COLLATE nocase",s.zSchema);
1992119977
if( rc || ii==0 ){
19922
- analysisReset(&s);
19978
+ diskusedReset(&s);
1992319979
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
1992419980
return;
1992519981
}
1992619982
sqlite3_randomness(sizeof(r), &r);
19927
- s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
19928
- if( s.zSU==0 ){ analysisError(&s, 0); return; }
19983
+ s.zSU = sqlite3_mprintf("diskused%016llx%016llx", r[0], r[1]);
19984
+ if( s.zSU==0 ){ diskusedError(&s, 0); return; }
1992919985
1993019986
/* The s.zSU table contains the data used for the analysis.
1993119987
** The table name contains 128-bits of randomness to avoid
1993219988
** collisions with preexisting tables in temp.
1993319989
*/
19934
- rc = analysisSql(&s,
19990
+ rc = diskusedSql(&s,
1993519991
"CREATE TABLE temp.%s(\n"
1993619992
" name text, -- A table or index\n"
1993719993
" tblname text, -- Table that owns name\n"
1993819994
" is_index boolean, -- TRUE if it is an index\n"
1993919995
" is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
@@ -19956,11 +20012,11 @@
1995620012
);
1995720013
if( rc ) return;
1995820014
1995920015
/* Populate the s.zSU table
1996020016
*/
19961
- rc = analysisSql(&s,
20017
+ rc = diskusedSql(&s,
1996220018
"WITH\n"
1996320019
" allidx(idxname) AS (\n"
1996420020
" SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
1996520021
" ),\n"
1996620022
" allobj(allname,tblname,isidx,isworowid) AS (\n"
@@ -20008,141 +20064,143 @@
2000820064
s.zSchema /* JOIN dbstat(%Q) */
2000920065
);
2001020066
if( rc ) return;
2001120067
2001220068
nPage = 0;
20013
- rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20069
+ rc = diskusedSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
2001420070
if( rc ) return;
2001520071
if( nPage<=0 ){
2001620072
/* Very brief reply for an empty database */
20017
- analysisReset(&s);
20073
+ diskusedReset(&s);
2001820074
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
2001920075
return;
2002020076
}
2002120077
2002220078
/* Begin generating the report */
20023
- analysisTitle(&s, "Database storage utilization report");
20079
+ diskusedTitle(&s, "Database storage utilization report");
2002420080
pgsz = 0;
20025
- rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20081
+ rc = diskusedSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
2002620082
if( rc ) return;
20027
- analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
20028
- analysisLine(&s, "Pages in the database", "%lld\n", nPage);
20083
+ diskusedLine(&s, "Page size in bytes","%lld\n",pgsz);
20084
+ diskusedLine(&s, "Pages in the database", "%lld\n", nPage);
2002920085
2003020086
nPageInUse = 0;
20031
- rc = analysisSqlInt(&s, &nPageInUse,
20087
+ rc = diskusedSqlInt(&s, &nPageInUse,
2003220088
"SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
2003320089
if( rc ) return;
20034
- analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20035
- analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
20090
+ diskusedLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20091
+ diskusedPercent(&s, (nPageInUse*100.0)/(double)nPage);
2003620092
2003720093
nFreeList = 0;
20038
- rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20094
+ rc = diskusedSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
2003920095
if( rc ) return;
20040
- analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20041
- analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
20096
+ diskusedLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20097
+ diskusedPercent(&s, (nFreeList*100.0)/(double)nPage);
2004220098
2004320099
ii = 0;
20044
- rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20100
+ rc = diskusedSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
2004520101
if( rc ) return;
2004620102
if( ii==0 || nPage<=1 ){
2004720103
ii = 0;
2004820104
}else{
2004920105
double rPtrsPerPage = pgsz/5;
2005020106
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
2005120107
ii = (sqlite3_int64)ceil(rAvPage);
2005220108
}
20053
- analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20054
- analysisPercent(&s, (ii*100.0)/(double)nPage);
20109
+ diskusedLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20110
+ diskusedPercent(&s, (ii*100.0)/(double)nPage);
2005520111
2005620112
ii = 0;
20057
- rc = analysisSqlInt(&s, &ii,
20113
+ rc = diskusedSqlInt(&s, &ii,
2005820114
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
2005920115
s.zSchema);
2006020116
if( rc ) return;
20061
- analysisLine(&s, "Number of tables", "%lld\n", ii);
20117
+ diskusedLine(&s, "Number of tables", "%lld\n", ii);
2006220118
nWORowid = 0;
20063
- rc = analysisSqlInt(&s, &nWORowid,
20119
+ rc = diskusedSqlInt(&s, &nWORowid,
2006420120
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
2006520121
s.zSchema);
2006620122
if( rc ) return;
2006720123
if( nWORowid>0 ){
20068
- analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20069
- analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
20124
+ diskusedLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20125
+ diskusedLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
2007020126
}
2007120127
nIndex = 0;
20072
- rc = analysisSqlInt(&s, &nIndex,
20128
+ rc = diskusedSqlInt(&s, &nIndex,
2007320129
"SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
2007420130
s.zSchema);
2007520131
if( rc ) return;
20076
- analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
20132
+ diskusedLine(&s, "Number of indexes", "%lld\n", nIndex);
2007720133
ii = 0;
20078
- rc = analysisSqlInt(&s, &ii,
20134
+ rc = diskusedSqlInt(&s, &ii,
2007920135
"SELECT count(*) FROM \"%w\".sqlite_schema"
2008020136
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
2008120137
s.zSchema);
2008220138
if( rc ) return;
20083
- analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20084
- analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
20085
- analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20139
+ diskusedLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20140
+ diskusedLine(&s, "Number of implied indexes", "%lld\n", ii);
20141
+ diskusedLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
2008620142
ii = 0;
20087
- rc = analysisSqlInt(&s, &ii,
20143
+ rc = diskusedSqlInt(&s, &ii,
2008820144
"SELECT sum(payload) FROM temp.%s"
2008920145
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
2009020146
s.zSU);
2009120147
if( rc ) return;
20092
- analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
20093
- analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
20148
+ diskusedLine(&s, "Bytes of payload", "%-11lld ", ii);
20149
+ diskusedPercent(&s, ii*100.0/(double)(pgsz*nPage));
2009420150
20095
- analysisTitle(&s, "Page counts for all tables with their indexes");
20096
- pStmt = analysisPrepare(&s,
20151
+ diskusedTitle(&s, "Page counts for all tables with their indexes");
20152
+ pStmt = diskusedPrepare(&s,
2009720153
"SELECT upper(tblname),\n"
2009820154
" sum(int_pages+leaf_pages+ovfl_pages)\n"
2009920155
" FROM temp.%s\n"
20156
+ " WHERE tblname IS NOT NULL\n"
20157
+ " GROUP BY 1\n"
20158
+ " ORDER BY 2 DESC, 1;",
20159
+ s.zSU);
20160
+ if( pStmt==0 ) return;
20161
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20162
+ sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20163
+ diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20164
+ diskusedPercent(&s, (nn*100.0)/(double)nPage);
20165
+ }
20166
+ if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20167
+
20168
+ diskusedTitle(&s, "Page counts for all tables and indexes separately");
20169
+ pStmt = diskusedPrepare(&s,
20170
+ "SELECT upper(name),\n"
20171
+ " sum(int_pages+leaf_pages+ovfl_pages)\n"
20172
+ " FROM temp.%s\n"
20173
+ " WHERE name IS NOT NULL\n"
2010020174
" GROUP BY 1\n"
2010120175
" ORDER BY 2 DESC, 1;",
2010220176
s.zSU);
2010320177
if( pStmt==0 ) return;
2010420178
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
2010520179
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20106
- analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20107
- analysisPercent(&s, (nn*100.0)/(double)nPage);
20108
- }
20109
- if( analysisStmtFinish(&s, rc, pStmt) ) return;
20110
-
20111
- analysisTitle(&s, "Page counts for all tables and indexes separately");
20112
- pStmt = analysisPrepare(&s,
20113
- "SELECT upper(name),\n"
20114
- " sum(int_pages+leaf_pages+ovfl_pages)\n"
20115
- " FROM temp.%s\n"
20116
- " GROUP BY 1\n"
20117
- " ORDER BY 2 DESC, 1;",
20118
- s.zSU);
20119
- if( pStmt==0 ) return;
20120
- while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20121
- sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20122
- analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20123
- analysisPercent(&s, (nn*100.0)/(double)nPage);
20124
- }
20125
- if( analysisStmtFinish(&s, rc, pStmt) ) return;
20126
-
20127
- rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
20180
+ diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20181
+ diskusedPercent(&s, (nn*100.0)/(double)nPage);
20182
+ }
20183
+ if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20184
+
20185
+ rc = diskusedSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
2012820186
if( rc ) return;
20129
- rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20187
+ rc = diskusedSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
2013020188
if( rc ) return;
2013120189
if( nWORowid>0 ){
20132
- rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20190
+ rc = diskusedSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
2013320191
pgsz, nPage);
2013420192
if( rc ) return;
20135
- rc = analysisSubreport(&s, "All rowid tables",
20193
+ rc = diskusedSubreport(&s, "All rowid tables",
2013620194
"NOT is_without_rowid AND NOT is_index",
2013720195
pgsz, nPage);
2013820196
if( rc ) return;
2013920197
}
20140
- rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20198
+ rc = diskusedSubreport(&s, "All indexes", "is_index", pgsz, nPage);
2014120199
if( rc ) return;
2014220200
20143
- pStmt = analysisPrepare(&s,
20201
+ pStmt = diskusedPrepare(&s,
2014420202
"SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
2014520203
" GROUP BY 1 ORDER BY 1",
2014620204
s.zSU);
2014720205
if( pStmt==0 ) return;
2014820206
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
@@ -20150,37 +20208,37 @@
2015020208
const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
2015120209
int nSubIndex = sqlite3_column_int(pStmt, 2);
2015220210
if( nSubIndex==0 ){
2015320211
char *zTitle = sqlite3_mprintf("Table %s", zUpper);
2015420212
char *zWhere = sqlite3_mprintf("name=%Q", zName);
20155
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20213
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2015620214
sqlite3_free(zTitle);
2015720215
sqlite3_free(zWhere);
2015820216
if( rc ) break;
2015920217
}else{
2016020218
sqlite3_stmt *pS2;
2016120219
char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
2016220220
char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20163
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20221
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2016420222
sqlite3_free(zTitle);
2016520223
sqlite3_free(zWhere);
2016620224
if( rc ) break;
2016720225
zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
2016820226
zWhere = sqlite3_mprintf("name=%Q", zName);
20169
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20227
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2017020228
sqlite3_free(zTitle);
2017120229
sqlite3_free(zWhere);
2017220230
if( rc ) break;
2017320231
if( nSubIndex>1 ){
2017420232
zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
2017520233
zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20176
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20234
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2017720235
sqlite3_free(zTitle);
2017820236
sqlite3_free(zWhere);
2017920237
if( rc ) break;
2018020238
}
20181
- pS2 = analysisPrepare(&s,
20239
+ pS2 = diskusedPrepare(&s,
2018220240
"SELECT name, upper(name) FROM temp.%s"
2018320241
" WHERE is_index AND tblname=%Q",
2018420242
s.zSU, zName);
2018520243
if( pS2==0 ){
2018620244
rc = SQLITE_NOMEM;
@@ -20189,25 +20247,25 @@
2018920247
while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
2019020248
const char *zU = (const char*)sqlite3_column_text(pS2, 1);
2019120249
const char *zN = (const char*)sqlite3_column_text(pS2, 0);
2019220250
zTitle = sqlite3_mprintf("Index %s", zU);
2019320251
zWhere = sqlite3_mprintf("name=%Q", zN);
20194
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20252
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2019520253
sqlite3_free(zTitle);
2019620254
sqlite3_free(zWhere);
2019720255
if( rc ) break;
2019820256
}
20199
- rc = analysisStmtFinish(&s, rc, pS2);
20257
+ rc = diskusedStmtFinish(&s, rc, pS2);
2020020258
if( rc ) break;
2020120259
}
2020220260
}
20203
- if( analysisStmtFinish(&s, rc, pStmt) ) return;
20261
+ if( diskusedStmtFinish(&s, rc, pStmt) ) return;
2020420262
2020520263
/* Append SQL statements that will recreate the raw data used for
2020620264
** the analysis.
2020720265
*/
20208
- analysisTitle(&s, "Raw data used to generate this report");
20266
+ diskusedTitle(&s, "Raw data used to generate this report");
2020920267
sqlite3_str_appendf(s.pOut,
2021020268
"The following SQL will create a table named \"space_used\" which\n"
2021120269
"contains most of the information used to generate the report above.\n"
2021220270
"*/\n"
2021320271
);
@@ -20233,11 +20291,11 @@
2023320291
" ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
2023420292
" int_entries int -- B-tree entries on internal pages\n"/* 17 */
2023520293
");\n"
2023620294
"INSERT INTO space_used VALUES\n"
2023720295
);
20238
- pStmt = analysisPrepare(&s,
20296
+ pStmt = diskusedPrepare(&s,
2023920297
"SELECT quote(name), quote(tblname),\n" /* 0..1 */
2024020298
" is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
2024120299
" depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
2024220300
" int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
2024320301
" leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
@@ -20268,11 +20326,11 @@
2026820326
sqlite3_column_int64(pStmt, 15),
2026920327
sqlite3_column_int64(pStmt, 16),
2027020328
sqlite3_column_int64(pStmt, 17));
2027120329
}
2027220330
if( rc!=SQLITE_DONE ){
20273
- analysisError(&s, "SQL run-time error: %s\nSQL: %s",
20331
+ diskusedError(&s, "SQL run-time error: %s\nSQL: %s",
2027420332
sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
2027520333
sqlite3_finalize(pStmt);
2027620334
return;
2027720335
}
2027820336
sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
@@ -20281,32 +20339,32 @@
2028120339
if( sqlite3_str_length(s.pOut) ){
2028220340
sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
2028320341
sqlite3_free);
2028420342
s.pOut = 0;
2028520343
}
20286
- analysisReset(&s);
20344
+ diskusedReset(&s);
2028720345
}
2028820346
2028920347
2029020348
#ifdef _WIN32
2029120349
2029220350
#endif
20293
-int sqlite3_analyze_init(
20351
+int sqlite3_diskused_init(
2029420352
sqlite3 *db,
2029520353
char **pzErrMsg,
2029620354
const sqlite3_api_routines *pApi
2029720355
){
2029820356
int rc = SQLITE_OK;
2029920357
SQLITE_EXTENSION_INIT2(pApi);
2030020358
(void)pzErrMsg; /* Unused parameter */
20301
- rc = sqlite3_create_function(db, "analyze", 1,
20359
+ rc = sqlite3_create_function(db, "diskused", 1,
2030220360
SQLITE_UTF8|SQLITE_INNOCUOUS,
20303
- 0, analyzeFunc, 0, 0);
20361
+ 0, diskusedFunc, 0, 0);
2030420362
return rc;
2030520363
}
2030620364
20307
-/************************* End ext/misc/analyze.c ********************/
20365
+/************************* End ext/misc/diskused.c ********************/
2030820366
2030920367
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
2031020368
#define SQLITE_SHELL_HAVE_RECOVER 1
2031120369
#else
2031220370
#define SQLITE_SHELL_HAVE_RECOVER 0
@@ -25138,11 +25196,11 @@
2513825196
/*
2513925197
** Return true if either the SQLITE_NO_COLOR compile-time option is used
2514025198
** or if the NO_COLOR environment variable exists
2514125199
*/
2514225200
static int shellNoColor(void){
25143
-#ifdef SQLITE_NO_COLOR
25201
+#if defined(SQLITE_NO_COLOR) || defined(SQLITE_SHELL_FIDDLE)
2514425202
return 1;
2514525203
#else
2514625204
return getenv("NO_COLOR")!=0;
2514725205
#endif
2514825206
}
@@ -25172,11 +25230,11 @@
2517225230
case 1:
2517325231
#if defined(SQLITE_PS1)
2517425232
return SQLITE_PS1;
2517525233
#else
2517625234
if( shellNoColor() ){
25177
- return "/A-/v /~> ";
25235
+ return "/A-/v /f-> ";
2517825236
}else{
2517925237
return "/e[1;32m/A-/v /e[1;/x33/:36/;m/m/e[3m/;/f/;/e[0m-> ";
2518025238
}
2518125239
#endif
2518225240
@@ -25184,11 +25242,11 @@
2518425242
case 2:
2518525243
#if defined(SQLITE_PS2)
2518625244
return SQLITE_PS2;
2518725245
#else
2518825246
if( shellNoColor() ){
25189
- return "/B/C> ";
25247
+ return "/B/C-> ";
2519025248
}else{
2519125249
return "/B/e[1;/x33/:36/;m/C/e[0m-> ";
2519225250
}
2519325251
#endif
2519425252
@@ -25196,11 +25254,15 @@
2519625254
** of cases 1 and 2 */
2519725255
case 3: return "SQLITE_PS1";
2519825256
case 4: return "SQLITE_PS2";
2519925257
2520025258
/* Name of the application */
25259
+#ifndef SQLITE_CLI_APPNAME
2520125260
case 'A': return "SQLite";
25261
+#else
25262
+ case 'A': return SHELL_STRINGIFY(SQLITE_CLI_APPNAME);
25263
+#endif
2520225264
2520325265
/* Full version number of the application, including patch level */
2520425266
case 'V': return sqlite3_libversion();
2520525267
2520625268
/* Version number without the patch level */
@@ -26303,10 +26365,47 @@
2630326365
if( *az ){
2630426366
memcpy(*az, zNew, n+1 );
2630526367
}
2630626368
}
2630726369
}
26370
+
26371
+/* Forward reference */
26372
+static int pickStr(const char *zArg, char **pzErr, ...);
26373
+
26374
+/*
26375
+** Change the limits on the display mode. Return 0 on
26376
+** success. Return non-zero if zArg is mis-formatted.
26377
+**
26378
+** Valid arguments:
26379
+**
26380
+** "on" Default limits
26381
+** "off" All limits turned off
26382
+** L,C Line and Characters limits set
26383
+** L,C,T Line, Character, and Title limits set
26384
+**
26385
+** Anything else returns non-zero
26386
+*/
26387
+static int modeSetLimit(ShellState *p, const char *zArg){
26388
+ int k = zArg==0 ? 1 : pickStr(zArg,0,"on","off","");
26389
+ if( k==0 ){
26390
+ p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
26391
+ p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
26392
+ p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
26393
+ }else if( k==1 ){
26394
+ p->mode.spec.nLineLimit = 0;
26395
+ p->mode.spec.nCharLimit = 0;
26396
+ p->mode.spec.nTitleLimit = 0;
26397
+ }else{
26398
+ int L, C, T = 0;
26399
+ int nNum = sscanf(zArg, "%d,%d,%d", &L, &C, &T);
26400
+ if( nNum<2 || L<0 || C<0 || T<0) return 1;
26401
+ p->mode.spec.nLineLimit = L;
26402
+ p->mode.spec.nCharLimit = C;
26403
+ if( nNum==3 ) p->mode.spec.nTitleLimit = T;
26404
+ }
26405
+ return 0;
26406
+}
2630826407
2630926408
/*
2631026409
** Change the mode to eMode
2631126410
*/
2631226411
static void modeChange(ShellState *p, unsigned char eMode){
@@ -26340,10 +26439,11 @@
2634026439
modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
2634126440
}else if( eMode==MODE_BATCH ){
2634226441
u8 mFlags = p->mode.mFlags;
2634326442
modeFree(&p->mode);
2634426443
modeChange(p, MODE_List);
26444
+ modeSetLimit(p, "off");
2634526445
p->mode.mFlags = mFlags;
2634626446
}else if( eMode==MODE_TTY ){
2634726447
u8 mFlags = p->mode.mFlags;
2634826448
modeFree(&p->mode);
2634926449
modeChange(p, MODE_QBox);
@@ -26976,11 +27076,11 @@
2697627076
return SQLITE_OK;
2697727077
}
2697827078
#endif
2697927079
2698027080
/*
26981
-** Print a schema statement. This is helper routine to dump_callbac().
27081
+** Print a schema statement. This is a helper routine to dump_callback().
2698227082
**
2698327083
** This routine converts some CREATE TABLE statements for shadow tables
2698427084
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
2698527085
**
2698627086
** If the schema statement in z[] contains a start-of-comment and if
@@ -28428,12 +28528,12 @@
2842828528
".databases List names and files of attached databases",
2842928529
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
2843028530
#if SQLITE_SHELL_HAVE_RECOVER
2843128531
".dbinfo ?DB? Show status information about the database",
2843228532
#endif
28433
- ".dbstat ?SCHEMA? Report database space and size stats",
2843428533
".dbtotxt Hex dump of the database file",
28534
+ ".diskused ?SCHEMA? Report database space and size stats",
2843528535
".dump ?OBJECTS? Render database content as SQL",
2843628536
" Options:",
2843728537
" --data-only Output only INSERT statements",
2843828538
" --newlines Allow unescaped newline characters in output",
2843928539
" --nosys Omit system tables (ex: \"sqlite_stat1\")",
@@ -28540,10 +28640,13 @@
2854028640
" --reset Reset the count for each input and interrupt",
2854128641
" --timeout S Halt after running for S seconds",
2854228642
#endif
2854328643
".prompt MAIN CONTINUE Replace the standard prompts",
2854428644
" --hard-reset Unset SQLITE_PS1/2 and then --reset",
28645
+#ifndef SQLITE_NO_COLOR
28646
+ " --no-color Disable color prompts. Use --color to re-enable",
28647
+#endif
2854528648
" --reset Revert to default prompts",
2854628649
" --show Show the current prompt strings",
2854728650
" -- No more options. Subsequent args are prompts",
2854828651
#ifndef SQLITE_SHELL_FIDDLE
2854928652
".quit Stop interpreting input stream, exit if primary.",
@@ -29440,11 +29543,11 @@
2944029543
sqlite3_base64_init(p->db, 0, 0);
2944129544
sqlite3_base85_init(p->db, 0, 0);
2944229545
sqlite3_regexp_init(p->db, 0, 0);
2944329546
sqlite3_ieee_init(p->db, 0, 0);
2944429547
sqlite3_series_init(p->db, 0, 0);
29445
- sqlite3_analyze_init(p->db, 0, 0);
29548
+ sqlite3_diskused_init(p->db, 0, 0);
2944629549
#ifndef SQLITE_SHELL_FIDDLE
2944729550
sqlite3_fileio_init(p->db, 0, 0);
2944829551
sqlite3_completion_init(p->db, 0, 0);
2944929552
#endif
2945029553
#ifdef SQLITE_HAVE_ZLIB
@@ -31246,11 +31349,11 @@
3124631349
typedef struct ArCommand ArCommand;
3124731350
struct ArCommand {
3124831351
u8 eCmd; /* An AR_CMD_* value */
3124931352
u8 bVerbose; /* True if --verbose */
3125031353
u8 bZip; /* True if the archive is a ZIP */
31251
- u8 bDryRun; /* True if --dry-run */
31354
+ u8 bDryRun; /* 1 for --dry-run, 2 for --debug */
3125231355
u8 bAppend; /* True if --append */
3125331356
u8 bGlob; /* True if --glob */
3125431357
u8 fromCmdLine; /* Run from -A instead of .archive */
3125531358
int nArg; /* Number of command arguments */
3125631359
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
@@ -31308,10 +31411,11 @@
3130831411
#define AR_SWITCH_FILE 9
3130931412
#define AR_SWITCH_DIRECTORY 10
3131031413
#define AR_SWITCH_APPEND 11
3131131414
#define AR_SWITCH_DRYRUN 12
3131231415
#define AR_SWITCH_GLOB 13
31416
+#define AR_SWITCH_DEBUG 14
3131331417
3131431418
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
3131531419
switch( eSwitch ){
3131631420
case AR_CMD_CREATE:
3131731421
case AR_CMD_EXTRACT:
@@ -31325,11 +31429,14 @@
3132531429
}
3132631430
pAr->eCmd = eSwitch;
3132731431
break;
3132831432
3132931433
case AR_SWITCH_DRYRUN:
31330
- pAr->bDryRun = 1;
31434
+ if( pAr->bDryRun<2 ) pAr->bDryRun = 1;
31435
+ break;
31436
+ case AR_SWITCH_DEBUG:
31437
+ pAr->bDryRun = 2;
3133131438
break;
3133231439
case AR_SWITCH_GLOB:
3133331440
pAr->bGlob = 1;
3133431441
break;
3133531442
case AR_SWITCH_VERBOSE:
@@ -31376,10 +31483,11 @@
3137631483
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
3137731484
{ "file", 'f', AR_SWITCH_FILE, 1 },
3137831485
{ "append", 'a', AR_SWITCH_APPEND, 1 },
3137931486
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
3138031487
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
31488
+ { "debug", 0, AR_SWITCH_DEBUG, 0 },
3138131489
{ "glob", 'g', AR_SWITCH_GLOB, 0 },
3138231490
};
3138331491
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
3138431492
struct ArSwitch *pEnd = &aSwitch[nSwitch];
3138531493
@@ -31676,18 +31784,41 @@
3167631784
3167731785
/*
3167831786
** Implementation of .ar "eXtract" command.
3167931787
*/
3168031788
static int arExtractCommand(ArCommand *pAr){
31789
+ /* The zSql1[] string is a template for the query that does the
31790
+ ** extraction. Notes:
31791
+ **
31792
+ ** * $dir is the directory into which the archive is to be extracted
31793
+ ** * $pass is the integer pass number: 0, 1, or 2
31794
+ ** * The dest CTE is created so that realpath($dir) only needs
31795
+ ** to be called once.
31796
+ */
3168131797
const char *zSql1 =
31682
- "WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n"
31683
- "SELECT ($dir || name),\n"
31684
- " CASE WHEN $dryrun THEN 0\n"
31685
- " ELSE writefile($dir||name, %s, mode, mtime) END\n"
31798
+ "WITH dest(dpath,dlen) AS (\n"
31799
+#ifdef _WIN32
31800
+ " SELECT realpath($dir) || '\\',\n"
31801
+#else
31802
+ " SELECT realpath($dir) || '/',\n"
31803
+#endif
31804
+ " 1+length(realpath($dir))\n"
31805
+ ")\n"
31806
+ "SELECT\n"
31807
+ " ($dir || name),\n"
31808
+ " CASE $dryrun\n" /* vv--- azExtraArg */
31809
+ " WHEN 0 THEN writefile($dir||name, %s, mode, mtime)\n"
31810
+ " WHEN 1 THEN 0\n"
31811
+ " ELSE shell_putsnl(format('writefile(%%Q,%%s,%%0o,%%d)',"
31812
+ "$dir||name,quote(%s),mode,mtime)) IS NULL\n"
31813
+ " END\n" /* ^^--- azExtraArg */
3168631814
" FROM dest CROSS JOIN %s\n"
31687
- " WHERE (%s)\n"
31688
- " AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */
31815
+ " WHERE (%s)\n" /* ^^-- pAr->zSrcTable */
31816
+ /* ^^--- zWhere */
31817
+ " AND (CASE $pass WHEN 0 THEN (mode&0xf000)<>0xa000\n"
31818
+ " WHEN 1 THEN (mode&0xf000)=0xa000\n"
31819
+ " ELSE data IS NULL END)\n"
3168931820
" AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
3169031821
" AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
3169131822
3169231823
const char *azExtraArg[] = {
3169331824
"sqlar_uncompress(data, sz)",
@@ -31714,39 +31845,48 @@
3171431845
}
3171531846
if( zDir==0 ) rc = SQLITE_NOMEM;
3171631847
}
3171731848
3171831849
shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
31719
- azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
31850
+ azExtraArg[pAr->bZip],
31851
+ azExtraArg[pAr->bZip],
31852
+ pAr->zSrcTable,
31853
+ zWhere
3172031854
);
3172131855
3172231856
if( rc==SQLITE_OK ){
3172331857
j = sqlite3_bind_parameter_index(pSql, "$dir");
3172431858
sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
3172531859
j = sqlite3_bind_parameter_index(pSql, "$dryrun");
3172631860
sqlite3_bind_int(pSql, j, pAr->bDryRun);
3172731861
3172831862
/* Run the SELECT statement twice
31729
- ** (0) writefile() all files and directories
31730
- ** (1) writefile() for directory again
31731
- ** The second pass is so that the timestamps for extracted directories
31863
+ ** (0) writefile() files and directories
31864
+ ** (1) writefile() symlinks
31865
+ ** (2) writefile() for directory again
31866
+ ** The third pass is so that the timestamps for extracted directories
3173231867
** will be reset to the value in the archive, since populating them
3173331868
** in the first pass will have changed the timestamp. */
31734
- for(i=0; i<2; i++){
31869
+ for(i=0; i<3; i++){
31870
+ if( pAr->bDryRun>=2 ){
31871
+ cli_printf(pAr->out, "*** BEGIN PASS %d ***\n", i+1);
31872
+ }
3173531873
j = sqlite3_bind_parameter_index(pSql, "$pass");
3173631874
sqlite3_bind_int(pSql, j, i);
31737
- if( pAr->bDryRun ){
31875
+ if( pAr->bDryRun && i==0 ){
3173831876
cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
31739
- if( pAr->bVerbose==0 ) break;
3174031877
}
3174131878
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
3174231879
if( i==0 && pAr->bVerbose ){
3174331880
cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
3174431881
}
3174531882
}
31746
- if( pAr->bDryRun ) break;
31883
+ if( pAr->bDryRun==1 ) break;
3174731884
shellReset(&rc, pSql);
31885
+ if( pAr->bDryRun>=2 ){
31886
+ cli_printf(pAr->out, "*** END PASS %d ***\n", i+1);
31887
+ }
3174831888
}
3174931889
shellFinalize(&rc, pSql);
3175031890
}
3175131891
3175231892
sqlite3_free(zDir);
@@ -32257,11 +32397,11 @@
3225732397
;
3225832398
static const char * const zCollectVar = "\
3225932399
SELECT\
3226032400
'('||x'0a'\
3226132401
|| group_concat(\
32262
- cname||' ANY',\
32402
+ cname,\
3226332403
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
3226432404
||')' AS ColsSpec \
3226532405
FROM (\
3226632406
SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
3226732407
FROM ColNames ORDER BY cpos\
@@ -33102,30 +33242,14 @@
3310233242
}else if( optionMatch(z,"limits") ){
3310333243
if( (++i)>=nArg ){
3310433244
dotCmdError(p, i-1, "missing argument", 0);
3310533245
return 1;
3310633246
}
33107
- k = pickStr(azArg[i],0,"on","off","");
33108
- if( k==0 ){
33109
- p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
33110
- p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
33111
- p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
33112
- }else if( k==1 ){
33113
- p->mode.spec.nLineLimit = 0;
33114
- p->mode.spec.nCharLimit = 0;
33115
- p->mode.spec.nTitleLimit = 0;
33116
- }else{
33117
- int L, C, T = 0;
33118
- int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
33119
- if( nNum<2 || L<0 || C<0 || T<0){
33120
- dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
33121
- " and T are unsigned integers");
33122
- return 1;
33123
- }
33124
- p->mode.spec.nLineLimit = L;
33125
- p->mode.spec.nCharLimit = C;
33126
- if( nNum==3 ) p->mode.spec.nTitleLimit = T;
33247
+ if( modeSetLimit(p, azArg[i]) ){
33248
+ dotCmdError(p, i, "bad argument", "Should be \"on\" or \"off\" or "
33249
+ "\"L,C,T\" where L, C, and T are unsigned integers");
33250
+ return 1;
3312733251
}
3312833252
chng = 1;
3312933253
}else if( optionMatch(z,"list") ){
3313033254
int ii;
3313133255
cli_puts("available modes:", p->out);
@@ -34339,11 +34463,16 @@
3433934463
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
3434034464
rc = shell_dbinfo_command(p, nArg, azArg);
3434134465
}else
3434234466
#endif /* SQLITE_SHELL_HAVE_RECOVER */
3434334467
34344
- if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
34468
+ if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34469
+ open_db(p, 0);
34470
+ rc = shell_dbtotxt_command(p, nArg, azArg);
34471
+ }else
34472
+
34473
+ if( c=='d' && n==8 && cli_strncmp(azArg[0], "diskused", n)==0 ){
3434534474
const char *zSchema = 0;
3434634475
int ii;
3434734476
char *zSql;
3434834477
open_db(p, 0);
3434934478
for(ii=1; ii<nArg; ii++){
@@ -34358,27 +34487,19 @@
3435834487
rc = 1;
3435934488
goto meta_command_exit;
3436034489
}
3436134490
zSchema = z;
3436234491
}
34363
- zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
34492
+ zSql = sqlite3_mprintf("SELECT diskused(%Q)", zSchema);
3436434493
shell_check_oom(zSql);
3436534494
modePush(p);
3436634495
modeChange(p, MODE_BATCH);
34367
- p->mode.spec.nLineLimit = 0;
34368
- p->mode.spec.nCharLimit = 0;
34369
- p->mode.spec.nTitleLimit = 0;
3437034496
shell_exec(p, zSql, 0);
3437134497
modePop(p);
3437234498
sqlite3_free(zSql);
3437334499
}else
3437434500
34375
- if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34376
- open_db(p, 0);
34377
- rc = shell_dbtotxt_command(p, nArg, azArg);
34378
- }else
34379
-
3438034501
if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
3438134502
char *zLike = 0;
3438234503
char *zSql;
3438334504
int i;
3438434505
int savedShellFlags = p->shellFlgs;
@@ -35491,10 +35612,26 @@
3549135612
}else
3549235613
if( strcmp(z,"-show")==0 ){
3549335614
cli_printf(stdout,"Main prompt: '%s'\n", prompt_string(p, 0));
3549435615
cli_printf(stdout,"Continuation: '%s'\n", prompt_string(p, 1));
3549535616
}else
35617
+#ifndef SQLITE_NO_COLOR
35618
+ if( strcmp(z,"-color")==0 ){
35619
+#ifdef _WIN32
35620
+ _putenv("NO_COLOR=");
35621
+#else
35622
+ unsetenv("NO_COLOR");
35623
+#endif
35624
+ }else
35625
+ if( strcmp(z,"-no-color")==0 ){
35626
+#ifdef _WIN32
35627
+ _putenv("NO_COLOR=1");
35628
+#else
35629
+ setenv("NO_COLOR","1",1);
35630
+#endif
35631
+ }else
35632
+#endif
3549635633
if( strcmp(z,"-")==0 ){
3549735634
noOpt = 1;
3549835635
}else
3549935636
{
3550035637
dotCmdError(p, i, "unknown option", 0);
@@ -35505,10 +35642,11 @@
3550535642
dotCmdError(p, i, "extra argument", 0);
3550635643
rc = 1;
3550735644
goto meta_command_exit;
3550835645
}else if( !p->dot.abQuot[i] && sqlite3_strglob("*[^a-z]*",z)!=0 ){
3550935646
dotCmdError(p, i, "use quotes around the prompt string", 0);
35647
+ rc = 1;
3551035648
}else{
3551135649
free(p->azPrompt[cnt]);
3551235650
p->azPrompt[cnt] = strdup(z);
3551335651
cnt++;
3551435652
}
@@ -37717,17 +37855,17 @@
3771737855
" -- treat no subsequent arguments as options\n"
3771837856
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
3771937857
" -A ARGS... run \".archive ARGS\" and exit\n"
3772037858
#endif
3772137859
" -append append the database to the end of the file\n"
37722
- " -ascii set output mode to 'ascii'\n"
37860
+ " -ascii set '.mode ascii'\n"
3772337861
" -bail stop after hitting an error\n"
3772437862
" -batch force batch I/O\n"
37725
- " -box set output mode to 'box'\n"
37863
+ " -box set '.mode box'\n"
3772637864
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
37727
- " -column set output mode to 'column'\n"
37728
- " -csv set output mode to 'csv'\n"
37865
+ " -column set '.mode column'\n"
37866
+ " -csv set '.mode csv -limits off'\n"
3772937867
#if !defined(SQLITE_OMIT_DESERIALIZE)
3773037868
" -deserialize open the database using sqlite3_deserialize()\n"
3773137869
#endif
3773237870
" -echo print inputs before execution\n"
3773337871
" -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
@@ -37735,18 +37873,18 @@
3773537873
" -[no]header turn headers on or off\n"
3773637874
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
3773737875
" -heap SIZE Size of heap for memsys3 or memsys5\n"
3773837876
#endif
3773937877
" -help show this message\n"
37740
- " -html set output mode to HTML\n"
37878
+ " -html set '.mode html'\n"
3774137879
" -ifexists only open if database already exists\n"
3774237880
" -interactive force interactive I/O\n"
37743
- " -json set output mode to 'json'\n"
37744
- " -line set output mode to 'line'\n"
37745
- " -list set output mode to 'list'\n"
37881
+ " -json set '.mode json'\n"
37882
+ " -line set '.mode line'\n"
37883
+ " -list set '.mode list'\n"
3774637884
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
37747
- " -markdown set output mode to 'markdown'\n"
37885
+ " -markdown set '.mode markdown'\n"
3774837886
#if !defined(SQLITE_OMIT_DESERIALIZE)
3774937887
" -maxsize N maximum size for a --deserialize database\n"
3775037888
#endif
3775137889
" -memtrace trace all memory allocations and deallocations\n"
3775237890
" -mmap N default mmap size set to N\n"
@@ -37759,21 +37897,21 @@
3775937897
" -nonce STRING set the safe-mode escape nonce\n"
3776037898
" -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
3776137899
" -nullvalue TEXT set text string for NULL values. Default ''\n"
3776237900
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
3776337901
" -pcachetrace trace all page cache operations\n"
37764
- " -quote set output mode to 'quote'\n"
37902
+ " -quote set '.mode quote'\n"
3776537903
" -readonly open the database read-only\n"
3776637904
" -safe enable safe-mode\n"
3776737905
" -screenwidth N use N as the default screenwidth \n"
3776837906
" -separator SEP set output column separator. Default: '|'\n"
3776937907
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
3777037908
" -sorterref SIZE sorter references threshold size\n"
3777137909
#endif
3777237910
" -stats print memory stats before each finalize\n"
37773
- " -table set output mode to 'table'\n"
37774
- " -tabs set output mode to 'tabs'\n"
37911
+ " -table set '.mode table'\n"
37912
+ " -tabs set '.mode tabs'\n"
3777537913
" -unsafe-testing allow unsafe commands and modes for testing\n"
3777637914
" -version show SQLite version\n"
3777737915
" -vfs NAME use NAME as the default VFS\n"
3777837916
" -vfstrace enable tracing of all VFS calls\n"
3777937917
#ifdef SQLITE_HAVE_ZLIB
@@ -37801,10 +37939,23 @@
3780137939
sputz(stdout, "WARNING: attempt to configure SQLite after"
3780237940
" initialization.\n");
3780337941
}
3780437942
}
3780537943
37944
+#if HAVE_EDITLINE
37945
+/*
37946
+** https://sqlite.org/forum/forumpost/aad7a634916ff050:
37947
+**
37948
+** Calling setlocale(LC_...,"") is required to get libedit to accept
37949
+** non-ASCII input.
37950
+*/
37951
+#define DO_SET_LOCALE 1
37952
+#include <locale.h>
37953
+#else
37954
+#define DO_SET_LOCALE 0
37955
+#endif
37956
+
3780637957
/*
3780737958
** Initialize the state information in data
3780837959
*/
3780937960
static void main_init(ShellState *p) {
3781037961
memset(p, 0, sizeof(*p));
@@ -37825,10 +37976,14 @@
3782537976
#else
3782637977
/* No \001...\002 escapes required for linenoise or when not using a
3782737978
** command-line editing library */
3782837979
p->bDelimitNonprint = 0;
3782937980
#endif
37981
+#if DO_SET_LOCALE
37982
+ setlocale(LC_CTYPE,"");
37983
+#endif
37984
+#undef DO_SET_LOCALE
3783037985
}
3783137986
3783237987
/*
3783337988
** Output text to the console in a font that attracts extra attention.
3783437989
*/
@@ -37854,11 +38009,11 @@
3785438009
}
3785538010
3785638011
/*
3785738012
** The callback from atexit().
3785838013
*/
37859
-static void abnormalExit(void){
38014
+static void SQLITE_CDECL abnormalExit(void){
3786038015
if( seenInterrupt ) eputz("Program interrupted.\n");
3786138016
if( globalShellState ){
3786238017
clearTempFile(globalShellState, 1, 1);
3786338018
}
3786438019
}
@@ -38065,11 +38220,11 @@
3806538220
stdin_is_interactive = 0;
3806638221
nCmd++;
3806738222
azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
3806838223
shell_check_oom(azCmd);
3806938224
aiCmd = realloc(aiCmd, sizeof(aiCmd[0])*nCmd);
38070
- shell_check_oom(azCmd);
38225
+ shell_check_oom(aiCmd);
3807138226
azCmd[nCmd-1] = z;
3807238227
aiCmd[nCmd-1] = i;
3807338228
}
3807438229
continue;
3807538230
}
@@ -38354,10 +38509,11 @@
3835438509
modeChange(&data, MODE_Psql);
3835538510
}else if( cli_strcmp(z,"-box")==0 ){
3835638511
modeChange(&data, MODE_Box);
3835738512
}else if( cli_strcmp(z,"-csv")==0 ){
3835838513
modeChange(&data, MODE_Csv);
38514
+ modeSetLimit(&data, "off");
3835938515
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
3836038516
/* See similar code at tag-20250224-1 */
3836138517
const char *zEsc = argv[++i];
3836238518
int k;
3836338519
for(k=0; k<ArraySize(qrfEscNames); k++){
@@ -38412,12 +38568,14 @@
3841238568
}else if( cli_strcmp(z,"-nullvalue")==0 ){
3841338569
modeSetStr(&data.mode.spec.zNull,
3841438570
cmdline_option_value(argc,argv,++i));
3841538571
}else if( cli_strcmp(z,"-header")==0 ){
3841638572
data.mode.spec.bTitles = QRF_Yes;
38573
+ data.mode.mFlags |= MFLG_HDR;
3841738574
}else if( cli_strcmp(z,"-noheader")==0 ){
3841838575
data.mode.spec.bTitles = QRF_No;
38576
+ data.mode.mFlags |= MFLG_HDR;
3841938577
}else if( cli_strcmp(z,"-echo")==0 ){
3842038578
data.mode.mFlags |= MFLG_ECHO;
3842138579
}else if( cli_strcmp(z,"-eqp")==0 ){
3842238580
data.mode.autoEQP = AUTOEQP_on;
3842338581
}else if( cli_strcmp(z,"-eqpfull")==0 ){
3842438582
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,16 +5,16 @@
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
 
16 ** ext/misc/fileio.c
17 ** ext/misc/ieee754.c
18 ** ext/misc/memtrace.c
19 ** ext/misc/pcachetrace.c
20 ** ext/misc/regexp.c
@@ -154,10 +154,11 @@
154 #include <string.h>
155 #include <stdio.h>
156 #include <assert.h>
157 #include <math.h>
158 #include <stdint.h>
 
159 #include "sqlite3.h"
160 typedef sqlite3_int64 i64;
161 typedef sqlite3_uint64 u64;
162 typedef unsigned char u8;
163 #include <ctype.h>
@@ -190,13 +191,14 @@
190 #include <sys/stat.h>
191
192 #if HAVE_READLINE
193 # include <readline/readline.h>
194 # include <readline/history.h>
195 #endif
196
197 #if HAVE_EDITLINE
 
198 # include <editline/readline.h>
199 #endif
200
201 #if HAVE_EDITLINE || HAVE_READLINE
202
@@ -744,12 +746,11 @@
744 const sqlite3_qrf_spec *pSpec, /* Result format specification */
745 char **pzErr /* OUT: Write error message here */
746 );
747
748 /*
749 ** Range of values for sqlite3_qrf_spec.aWidth[] entries and for
750 ** sqlite3_qrf_spec.mxColWidth and .nScreenWidth
751 */
752 #define QRF_MAX_WIDTH 10000
753 #define QRF_MIN_WIDTH 0
754
755 /*
@@ -1129,10 +1130,14 @@
1129 sqlite3_str_append(pOut, "-", 1);
1130 }
1131 if( N<10000 ){
1132 sqlite3_str_appendf(pOut, "%4lld ", N);
1133 return;
 
 
 
 
1134 }
1135 for(i=1; i<=18; i++){
1136 N = (N+5)/10;
1137 if( N<10000 ){
1138 int n = (int)N;
@@ -1289,12 +1294,12 @@
1289 if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
1290 int nSp = 0;
1291 sqlite3_str_reset(pStats);
1292 if( nCycle>=0 && nTotal>0 ){
1293 qrfApproxInt64(pStats, nCycle);
1294 sqlite3_str_appendf(pStats, " %3d%%",
1295 ((nCycle*100)+nTotal/2) / nTotal
1296 );
1297 nSp = 2;
1298 }
1299 if( nLoop>=0 ){
1300 if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
@@ -1787,11 +1792,11 @@
1787 }
1788 if( i>0 ){
1789 sqlite3_str_append(pOut, (const char*)z, i);
1790 }
1791 switch( z[i] ){
1792 case '>': sqlite3_str_append(pOut, "&lt;", 4); break;
1793 case '&': sqlite3_str_append(pOut, "&amp;", 5); break;
1794 case '<': sqlite3_str_append(pOut, "&lt;", 4); break;
1795 case '"': sqlite3_str_append(pOut, "&quot;", 6); break;
1796 case '\'': sqlite3_str_append(pOut, "&#39;", 5); break;
1797 default: i--;
@@ -2281,11 +2286,11 @@
2281 if( bWrap && z[i]!=0 && !qrfSpace(z[i]) && qrfAlnum(c)==qrfAlnum(z[i]) ){
2282 /* Perhaps try to back up to a better place to break the line */
2283 for(k=i-1; k>=i/2; k--){
2284 if( qrfSpace(z[k]) ) break;
2285 }
2286 if( k<i/2 ){
2287 for(k=i; k>=i/2; k--){
2288 if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
2289 }
2290 }
2291 if( k>=i/2 ){
@@ -2532,16 +2537,16 @@
2532 const char *azDash[2] = {
2533 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24,
2534 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
2535 };/* 0 1 2 3 4 5 6 7 8 9 */
2536 const int nDash = 30;
2537 N *= 3;
2538 while( N>nDash ){
2539 sqlite3_str_append(pOut, azDash[bDbl], nDash);
2540 N -= nDash;
2541 }
2542 sqlite3_str_append(pOut, azDash[bDbl], N);
2543 }
2544
2545 /*
2546 ** Draw a horizontal separator for a QRF_STYLE_Box table.
2547 */
@@ -2610,11 +2615,11 @@
2610 int nSW /* Screen width */
2611 ){
2612 int i; /* Loop counter */
2613 int nr; /* Number of rows */
2614 int w = 0; /* Width of the current column */
2615 int t; /* Total width of all columns */
2616 int *aw; /* Array of individual column widths */
2617
2618 aw = sqlite3_malloc64( sizeof(int)*nCol );
2619 if( aw==0 ){
2620 qrfOom(p);
@@ -2748,12 +2753,15 @@
2748 }else{
2749 sepW = pData->nCol*3 + 1;
2750 if( p->spec.bBorder==QRF_No ) sepW -= 2;
2751 }
2752 nCol = pData->nCol;
2753 for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
2754 if( p->spec.nScreenWidth >= sumW+sepW ) return;
 
 
 
2755
2756 /* First thing to do is reduce the separation between columns */
2757 pData->nMargin = 0;
2758 if( p->spec.eStyle==QRF_STYLE_Column ){
2759 sepW = pData->nCol - 1;
@@ -3624,11 +3632,11 @@
3624 p->nRow = 0;
3625 sz = sizeof(sqlite3_qrf_spec);
3626 memcpy(&p->spec, pSpec, sz);
3627 if( p->spec.zNull==0 ) p->spec.zNull = "";
3628 p->mxWidth = p->spec.nScreenWidth;
3629 if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
3630 p->mxHeight = p->spec.nLineLimit;
3631 if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
3632 if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
3633 if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
3634 if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto;
@@ -5272,10 +5280,14 @@
5272 #include <stdarg.h>
5273
5274 /******************************************************************************
5275 ** The Hash Engine
5276 */
 
 
 
 
5277 /* Context for the SHA1 hash */
5278 typedef struct SHA1Context SHA1Context;
5279 struct SHA1Context {
5280 unsigned int state[5];
5281 unsigned int count[2];
@@ -5412,11 +5424,11 @@
5412 }
5413 j = 0;
5414 }else{
5415 i = 0;
5416 }
5417 (void)memcpy(&p->buffer[j], &data[i], len - i);
5418 }
5419
5420 /* Compute a string using sqlite3_vsnprintf() and hash it */
5421 static void hash_step_vformat(
5422 SHA1Context *p, /* Add content to this context */
@@ -5467,10 +5479,13 @@
5467 zOut[i*2+1] = zEncode[digest[i] & 0xf];
5468 }
5469 zOut[i*2]= 0;
5470 }
5471 }
 
 
 
5472 /* End of the hashing logic
5473 *****************************************************************************/
5474
5475 /*
5476 ** Two SQL functions: sha1(X) and sha1b(X).
@@ -6056,32 +6071,41 @@
6056 }
6057 z[i] = 0;
6058 sqlite3_result_text(pCtx, z, i, sqlite3_free);
6059 }
6060
 
 
 
6061 /*
6062 ** Round a decimal value to N significant digits. N must be positive.
6063 */
6064 static void decimal_round(Decimal *p, int N){
6065 int i;
6066 int nZero;
6067 if( N<1 ) return;
6068 if( p==0 ) return;
6069 if( p->nDigit<=N ) return;
6070 for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
6071 N += nZero;
6072 if( p->nDigit<=N ) return;
6073 if( p->a[N]>4 ){
 
 
 
 
 
 
 
 
 
6074 p->a[N-1]++;
6075 for(i=N-1; i>0 && p->a[i]>9; i--){
6076 p->a[i] = 0;
6077 p->a[i-1]++;
6078 }
6079 if( p->a[0]>9 ){
6080 p->a[0] = 1;
6081 p->nFrac--;
6082 }
6083 }
6084 memset(&p->a[N], 0, p->nDigit - N);
6085 }
6086
6087 /*
@@ -8363,19 +8387,26 @@
8363 }
8364 }else{
8365 iMin = iMax = sqlite3_value_int64(argv[iArg++]);
8366 }
8367 }else{
8368 if( idxNum & 0x0300 ){ /* value>X or value>=X */
8369 if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
8370 double r = sqlite3_value_double(argv[iArg++]);
8371 if( r<(double)SMALLEST_INT64 ){
8372 iMin = SMALLEST_INT64;
8373 }else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
8374 iMin = (sqlite3_int64)seriesCeil(r+1.0);
8375 }else{
8376 iMin = (sqlite3_int64)seriesCeil(r);
 
 
 
 
 
 
 
8377 }
8378 }else{
8379 iMin = sqlite3_value_int64(argv[iArg++]);
8380 if( (idxNum & 0x0200)!=0 ){
8381 if( iMin==LARGEST_INT64 ){
@@ -8384,19 +8415,25 @@
8384 iMin++;
8385 }
8386 }
8387 }
8388 }
8389 if( idxNum & 0x3000 ){ /* value<X or value<=X */
8390 if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
8391 double r = sqlite3_value_double(argv[iArg++]);
8392 if( r>(double)LARGEST_INT64 ){
8393 iMax = LARGEST_INT64;
8394 }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
8395 iMax = (sqlite3_int64)(r-1.0);
8396 }else{
8397 iMax = (sqlite3_int64)seriesFloor(r);
 
 
 
 
 
 
8398 }
8399 }else{
8400 iMax = sqlite3_value_int64(argv[iArg++]);
8401 if( idxNum & 0x2000 ){
8402 if( iMax==SMALLEST_INT64 ){
@@ -9638,11 +9675,10 @@
9638 if( pRe==0 ){
9639 sqlite3_result_error_nomem(context);
9640 return;
9641 }
9642 pStr = sqlite3_str_new(0);
9643 if( pStr==0 ) goto re_bytecode_func_err;
9644 if( pRe->nInit>0 ){
9645 sqlite3_str_appendf(pStr, "INIT ");
9646 for(i=0; i<pRe->nInit; i++){
9647 sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
9648 }
@@ -9649,20 +9685,20 @@
9649 sqlite3_str_appendf(pStr, "\n");
9650 }
9651 for(i=0; (unsigned)i<pRe->nState; i++){
9652 sqlite3_str_appendf(pStr, "%-8s %4d\n",
9653 ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
 
 
 
 
 
 
9654 }
9655 n = sqlite3_str_length(pStr);
9656 z = sqlite3_str_finish(pStr);
9657 if( n==0 ){
9658 sqlite3_free(z);
9659 }else{
9660 sqlite3_result_text(context, z, n-1, sqlite3_free);
9661 }
9662
9663 re_bytecode_func_err:
9664 re_free(pRe);
9665 }
9666
9667 #endif /* SQLITE_DEBUG */
9668
@@ -10870,10 +10906,13 @@
10870 ** Return NULL if unable.
10871 **
10872 ** The file or directory X is not required to exist. The answer is formed
10873 ** by calling system realpath() on the prefix of X that does exist and
10874 ** appending the tail of X that does not (yet) exist.
 
 
 
10875 */
10876 static void realpathFunc(
10877 sqlite3_context *context,
10878 int argc,
10879 sqlite3_value **argv
@@ -10892,10 +10931,11 @@
10892 (void)argc;
10893 zPath = (const char*)sqlite3_value_text(argv[0]);
10894 if( zPath==0 ) return;
10895 if( zPath[0]==0 ) zPath = ".";
10896 zCopy = sqlite3_mprintf("%s",zPath);
 
10897 len = strlen(zCopy);
10898 while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
10899 len--;
10900 }
10901 zCopy[len] = 0;
@@ -12685,10 +12725,11 @@
12685
12686 for(p=pCsr->pFreeEntry; p; p=pNext){
12687 pNext = p->pNext;
12688 zipfileEntryFree(p);
12689 }
 
12690 }
12691
12692 /*
12693 ** Destructor for an ZipfileCsr.
12694 */
@@ -13087,11 +13128,17 @@
13087 }
13088 }
13089
13090 if( rc==SQLITE_OK ){
13091 u32 *pt = &pNew->mUnixTime;
13092 pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
 
 
 
 
 
 
13093 pNew->aExtra = (u8*)&pNew[1];
13094 memcpy(pNew->aExtra, &aRead[nFile], nExtra);
13095 if( pNew->cds.zFile==0 ){
13096 rc = SQLITE_NOMEM;
13097 }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
@@ -14191,14 +14238,14 @@
14191 ZipfileBuffer body;
14192 ZipfileBuffer cds;
14193 };
14194
14195 static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
14196 if( pBuf->n+nByte>pBuf->nAlloc ){
14197 u8 *aNew;
14198 sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
14199 int nReq = pBuf->n + nByte;
14200
14201 while( nNew<nReq ) nNew = nNew*2;
14202 aNew = sqlite3_realloc64(pBuf->a, nNew);
14203 if( aNew==0 ) return SQLITE_NOMEM;
14204 pBuf->a = aNew;
@@ -16296,11 +16343,11 @@
16296 p->pTable = pTab;
16297
16298 /* The statement the vtab will pass to sqlite3_declare_vtab() */
16299 zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
16300 for(i=0; i<pTab->nCol; i++){
16301 zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
16302 (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
16303 );
16304 }
16305 zInner = idxAppendText(&rc, zInner, ")");
16306
@@ -16496,11 +16543,11 @@
16496 sqlite3_free(zCols);
16497 sqlite3_free(zOrder);
16498 return sqlite3_reset(pIndexXInfo);
16499 }
16500 zCols = idxAppendText(&rc, zCols,
16501 "%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
16502 zComma, zName, nCol, zName, zColl
16503 );
16504 zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
16505 }
16506 sqlite3_reset(pIndexXInfo);
@@ -19464,11 +19511,11 @@
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:
@@ -19477,12 +19524,21 @@
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>
@@ -19490,28 +19546,28 @@
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);
@@ -19524,11 +19580,11 @@
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);
@@ -19540,38 +19596,38 @@
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 /*
@@ -19580,60 +19636,60 @@
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);
@@ -19641,14 +19697,14 @@
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
@@ -19657,20 +19713,20 @@
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 ){
@@ -19685,12 +19741,12 @@
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;
@@ -19698,14 +19754,14 @@
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);
@@ -19715,11 +19771,11 @@
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);
@@ -19744,12 +19800,12 @@
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 ){
@@ -19773,14 +19829,14 @@
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 */
@@ -19797,11 +19853,11 @@
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);
@@ -19816,73 +19872,73 @@
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;
@@ -19893,47 +19949,47 @@
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 (void)argc;
19902 memset(&s, 0, sizeof(s));
19903 s.db = sqlite3_context_db_handle(context);
19904 s.context = context;
19905 s.pOut = sqlite3_str_new(0);
19906 if( sqlite3_str_errcode(s.pOut) ){
19907 analysisError(&s, 0);
19908 return;
19909 }
19910 s.zSchema = (const char*)sqlite3_value_text(argv[0]);
19911 if( s.zSchema==0 ){
19912 s.zSchema = "main";
19913 }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19914 analysisReset(&s);
19915 sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
19916 return;
19917 }
19918 ii = 0;
19919 rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
19920 " WHERE name=%Q COLLATE nocase",s.zSchema);
19921 if( rc || ii==0 ){
19922 analysisReset(&s);
19923 sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
19924 return;
19925 }
19926 sqlite3_randomness(sizeof(r), &r);
19927 s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
19928 if( s.zSU==0 ){ analysisError(&s, 0); return; }
19929
19930 /* The s.zSU table contains the data used for the analysis.
19931 ** The table name contains 128-bits of randomness to avoid
19932 ** collisions with preexisting tables in temp.
19933 */
19934 rc = analysisSql(&s,
19935 "CREATE TABLE temp.%s(\n"
19936 " name text, -- A table or index\n"
19937 " tblname text, -- Table that owns name\n"
19938 " is_index boolean, -- TRUE if it is an index\n"
19939 " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
@@ -19956,11 +20012,11 @@
19956 );
19957 if( rc ) return;
19958
19959 /* Populate the s.zSU table
19960 */
19961 rc = analysisSql(&s,
19962 "WITH\n"
19963 " allidx(idxname) AS (\n"
19964 " SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
19965 " ),\n"
19966 " allobj(allname,tblname,isidx,isworowid) AS (\n"
@@ -20008,141 +20064,143 @@
20008 s.zSchema /* JOIN dbstat(%Q) */
20009 );
20010 if( rc ) return;
20011
20012 nPage = 0;
20013 rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20014 if( rc ) return;
20015 if( nPage<=0 ){
20016 /* Very brief reply for an empty database */
20017 analysisReset(&s);
20018 sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
20019 return;
20020 }
20021
20022 /* Begin generating the report */
20023 analysisTitle(&s, "Database storage utilization report");
20024 pgsz = 0;
20025 rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20026 if( rc ) return;
20027 analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
20028 analysisLine(&s, "Pages in the database", "%lld\n", nPage);
20029
20030 nPageInUse = 0;
20031 rc = analysisSqlInt(&s, &nPageInUse,
20032 "SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
20033 if( rc ) return;
20034 analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20035 analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
20036
20037 nFreeList = 0;
20038 rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20039 if( rc ) return;
20040 analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20041 analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
20042
20043 ii = 0;
20044 rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20045 if( rc ) return;
20046 if( ii==0 || nPage<=1 ){
20047 ii = 0;
20048 }else{
20049 double rPtrsPerPage = pgsz/5;
20050 double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
20051 ii = (sqlite3_int64)ceil(rAvPage);
20052 }
20053 analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20054 analysisPercent(&s, (ii*100.0)/(double)nPage);
20055
20056 ii = 0;
20057 rc = analysisSqlInt(&s, &ii,
20058 "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
20059 s.zSchema);
20060 if( rc ) return;
20061 analysisLine(&s, "Number of tables", "%lld\n", ii);
20062 nWORowid = 0;
20063 rc = analysisSqlInt(&s, &nWORowid,
20064 "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
20065 s.zSchema);
20066 if( rc ) return;
20067 if( nWORowid>0 ){
20068 analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20069 analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
20070 }
20071 nIndex = 0;
20072 rc = analysisSqlInt(&s, &nIndex,
20073 "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
20074 s.zSchema);
20075 if( rc ) return;
20076 analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
20077 ii = 0;
20078 rc = analysisSqlInt(&s, &ii,
20079 "SELECT count(*) FROM \"%w\".sqlite_schema"
20080 " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
20081 s.zSchema);
20082 if( rc ) return;
20083 analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20084 analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
20085 analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20086 ii = 0;
20087 rc = analysisSqlInt(&s, &ii,
20088 "SELECT sum(payload) FROM temp.%s"
20089 " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
20090 s.zSU);
20091 if( rc ) return;
20092 analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
20093 analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
20094
20095 analysisTitle(&s, "Page counts for all tables with their indexes");
20096 pStmt = analysisPrepare(&s,
20097 "SELECT upper(tblname),\n"
20098 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20099 " FROM temp.%s\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20100 " GROUP BY 1\n"
20101 " ORDER BY 2 DESC, 1;",
20102 s.zSU);
20103 if( pStmt==0 ) return;
20104 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20105 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20106 analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20107 analysisPercent(&s, (nn*100.0)/(double)nPage);
20108 }
20109 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20110
20111 analysisTitle(&s, "Page counts for all tables and indexes separately");
20112 pStmt = analysisPrepare(&s,
20113 "SELECT upper(name),\n"
20114 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20115 " FROM temp.%s\n"
20116 " GROUP BY 1\n"
20117 " ORDER BY 2 DESC, 1;",
20118 s.zSU);
20119 if( pStmt==0 ) return;
20120 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20121 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20122 analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20123 analysisPercent(&s, (nn*100.0)/(double)nPage);
20124 }
20125 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20126
20127 rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
20128 if( rc ) return;
20129 rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20130 if( rc ) return;
20131 if( nWORowid>0 ){
20132 rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20133 pgsz, nPage);
20134 if( rc ) return;
20135 rc = analysisSubreport(&s, "All rowid tables",
20136 "NOT is_without_rowid AND NOT is_index",
20137 pgsz, nPage);
20138 if( rc ) return;
20139 }
20140 rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20141 if( rc ) return;
20142
20143 pStmt = analysisPrepare(&s,
20144 "SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
20145 " GROUP BY 1 ORDER BY 1",
20146 s.zSU);
20147 if( pStmt==0 ) return;
20148 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
@@ -20150,37 +20208,37 @@
20150 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
20151 int nSubIndex = sqlite3_column_int(pStmt, 2);
20152 if( nSubIndex==0 ){
20153 char *zTitle = sqlite3_mprintf("Table %s", zUpper);
20154 char *zWhere = sqlite3_mprintf("name=%Q", zName);
20155 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20156 sqlite3_free(zTitle);
20157 sqlite3_free(zWhere);
20158 if( rc ) break;
20159 }else{
20160 sqlite3_stmt *pS2;
20161 char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
20162 char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20163 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20164 sqlite3_free(zTitle);
20165 sqlite3_free(zWhere);
20166 if( rc ) break;
20167 zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
20168 zWhere = sqlite3_mprintf("name=%Q", zName);
20169 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20170 sqlite3_free(zTitle);
20171 sqlite3_free(zWhere);
20172 if( rc ) break;
20173 if( nSubIndex>1 ){
20174 zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
20175 zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20176 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20177 sqlite3_free(zTitle);
20178 sqlite3_free(zWhere);
20179 if( rc ) break;
20180 }
20181 pS2 = analysisPrepare(&s,
20182 "SELECT name, upper(name) FROM temp.%s"
20183 " WHERE is_index AND tblname=%Q",
20184 s.zSU, zName);
20185 if( pS2==0 ){
20186 rc = SQLITE_NOMEM;
@@ -20189,25 +20247,25 @@
20189 while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
20190 const char *zU = (const char*)sqlite3_column_text(pS2, 1);
20191 const char *zN = (const char*)sqlite3_column_text(pS2, 0);
20192 zTitle = sqlite3_mprintf("Index %s", zU);
20193 zWhere = sqlite3_mprintf("name=%Q", zN);
20194 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20195 sqlite3_free(zTitle);
20196 sqlite3_free(zWhere);
20197 if( rc ) break;
20198 }
20199 rc = analysisStmtFinish(&s, rc, pS2);
20200 if( rc ) break;
20201 }
20202 }
20203 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20204
20205 /* Append SQL statements that will recreate the raw data used for
20206 ** the analysis.
20207 */
20208 analysisTitle(&s, "Raw data used to generate this report");
20209 sqlite3_str_appendf(s.pOut,
20210 "The following SQL will create a table named \"space_used\" which\n"
20211 "contains most of the information used to generate the report above.\n"
20212 "*/\n"
20213 );
@@ -20233,11 +20291,11 @@
20233 " ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
20234 " int_entries int -- B-tree entries on internal pages\n"/* 17 */
20235 ");\n"
20236 "INSERT INTO space_used VALUES\n"
20237 );
20238 pStmt = analysisPrepare(&s,
20239 "SELECT quote(name), quote(tblname),\n" /* 0..1 */
20240 " is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
20241 " depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
20242 " int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
20243 " leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
@@ -20268,11 +20326,11 @@
20268 sqlite3_column_int64(pStmt, 15),
20269 sqlite3_column_int64(pStmt, 16),
20270 sqlite3_column_int64(pStmt, 17));
20271 }
20272 if( rc!=SQLITE_DONE ){
20273 analysisError(&s, "SQL run-time error: %s\nSQL: %s",
20274 sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
20275 sqlite3_finalize(pStmt);
20276 return;
20277 }
20278 sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
@@ -20281,32 +20339,32 @@
20281 if( sqlite3_str_length(s.pOut) ){
20282 sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
20283 sqlite3_free);
20284 s.pOut = 0;
20285 }
20286 analysisReset(&s);
20287 }
20288
20289
20290 #ifdef _WIN32
20291
20292 #endif
20293 int sqlite3_analyze_init(
20294 sqlite3 *db,
20295 char **pzErrMsg,
20296 const sqlite3_api_routines *pApi
20297 ){
20298 int rc = SQLITE_OK;
20299 SQLITE_EXTENSION_INIT2(pApi);
20300 (void)pzErrMsg; /* Unused parameter */
20301 rc = sqlite3_create_function(db, "analyze", 1,
20302 SQLITE_UTF8|SQLITE_INNOCUOUS,
20303 0, analyzeFunc, 0, 0);
20304 return rc;
20305 }
20306
20307 /************************* End ext/misc/analyze.c ********************/
20308
20309 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
20310 #define SQLITE_SHELL_HAVE_RECOVER 1
20311 #else
20312 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -25138,11 +25196,11 @@
25138 /*
25139 ** Return true if either the SQLITE_NO_COLOR compile-time option is used
25140 ** or if the NO_COLOR environment variable exists
25141 */
25142 static int shellNoColor(void){
25143 #ifdef SQLITE_NO_COLOR
25144 return 1;
25145 #else
25146 return getenv("NO_COLOR")!=0;
25147 #endif
25148 }
@@ -25172,11 +25230,11 @@
25172 case 1:
25173 #if defined(SQLITE_PS1)
25174 return SQLITE_PS1;
25175 #else
25176 if( shellNoColor() ){
25177 return "/A-/v /~> ";
25178 }else{
25179 return "/e[1;32m/A-/v /e[1;/x33/:36/;m/m/e[3m/;/f/;/e[0m-> ";
25180 }
25181 #endif
25182
@@ -25184,11 +25242,11 @@
25184 case 2:
25185 #if defined(SQLITE_PS2)
25186 return SQLITE_PS2;
25187 #else
25188 if( shellNoColor() ){
25189 return "/B/C> ";
25190 }else{
25191 return "/B/e[1;/x33/:36/;m/C/e[0m-> ";
25192 }
25193 #endif
25194
@@ -25196,11 +25254,15 @@
25196 ** of cases 1 and 2 */
25197 case 3: return "SQLITE_PS1";
25198 case 4: return "SQLITE_PS2";
25199
25200 /* Name of the application */
 
25201 case 'A': return "SQLite";
 
 
 
25202
25203 /* Full version number of the application, including patch level */
25204 case 'V': return sqlite3_libversion();
25205
25206 /* Version number without the patch level */
@@ -26303,10 +26365,47 @@
26303 if( *az ){
26304 memcpy(*az, zNew, n+1 );
26305 }
26306 }
26307 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26308
26309 /*
26310 ** Change the mode to eMode
26311 */
26312 static void modeChange(ShellState *p, unsigned char eMode){
@@ -26340,10 +26439,11 @@
26340 modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
26341 }else if( eMode==MODE_BATCH ){
26342 u8 mFlags = p->mode.mFlags;
26343 modeFree(&p->mode);
26344 modeChange(p, MODE_List);
 
26345 p->mode.mFlags = mFlags;
26346 }else if( eMode==MODE_TTY ){
26347 u8 mFlags = p->mode.mFlags;
26348 modeFree(&p->mode);
26349 modeChange(p, MODE_QBox);
@@ -26976,11 +27076,11 @@
26976 return SQLITE_OK;
26977 }
26978 #endif
26979
26980 /*
26981 ** Print a schema statement. This is helper routine to dump_callbac().
26982 **
26983 ** This routine converts some CREATE TABLE statements for shadow tables
26984 ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
26985 **
26986 ** If the schema statement in z[] contains a start-of-comment and if
@@ -28428,12 +28528,12 @@
28428 ".databases List names and files of attached databases",
28429 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
28430 #if SQLITE_SHELL_HAVE_RECOVER
28431 ".dbinfo ?DB? Show status information about the database",
28432 #endif
28433 ".dbstat ?SCHEMA? Report database space and size stats",
28434 ".dbtotxt Hex dump of the database file",
 
28435 ".dump ?OBJECTS? Render database content as SQL",
28436 " Options:",
28437 " --data-only Output only INSERT statements",
28438 " --newlines Allow unescaped newline characters in output",
28439 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
@@ -28540,10 +28640,13 @@
28540 " --reset Reset the count for each input and interrupt",
28541 " --timeout S Halt after running for S seconds",
28542 #endif
28543 ".prompt MAIN CONTINUE Replace the standard prompts",
28544 " --hard-reset Unset SQLITE_PS1/2 and then --reset",
 
 
 
28545 " --reset Revert to default prompts",
28546 " --show Show the current prompt strings",
28547 " -- No more options. Subsequent args are prompts",
28548 #ifndef SQLITE_SHELL_FIDDLE
28549 ".quit Stop interpreting input stream, exit if primary.",
@@ -29440,11 +29543,11 @@
29440 sqlite3_base64_init(p->db, 0, 0);
29441 sqlite3_base85_init(p->db, 0, 0);
29442 sqlite3_regexp_init(p->db, 0, 0);
29443 sqlite3_ieee_init(p->db, 0, 0);
29444 sqlite3_series_init(p->db, 0, 0);
29445 sqlite3_analyze_init(p->db, 0, 0);
29446 #ifndef SQLITE_SHELL_FIDDLE
29447 sqlite3_fileio_init(p->db, 0, 0);
29448 sqlite3_completion_init(p->db, 0, 0);
29449 #endif
29450 #ifdef SQLITE_HAVE_ZLIB
@@ -31246,11 +31349,11 @@
31246 typedef struct ArCommand ArCommand;
31247 struct ArCommand {
31248 u8 eCmd; /* An AR_CMD_* value */
31249 u8 bVerbose; /* True if --verbose */
31250 u8 bZip; /* True if the archive is a ZIP */
31251 u8 bDryRun; /* True if --dry-run */
31252 u8 bAppend; /* True if --append */
31253 u8 bGlob; /* True if --glob */
31254 u8 fromCmdLine; /* Run from -A instead of .archive */
31255 int nArg; /* Number of command arguments */
31256 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
@@ -31308,10 +31411,11 @@
31308 #define AR_SWITCH_FILE 9
31309 #define AR_SWITCH_DIRECTORY 10
31310 #define AR_SWITCH_APPEND 11
31311 #define AR_SWITCH_DRYRUN 12
31312 #define AR_SWITCH_GLOB 13
 
31313
31314 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
31315 switch( eSwitch ){
31316 case AR_CMD_CREATE:
31317 case AR_CMD_EXTRACT:
@@ -31325,11 +31429,14 @@
31325 }
31326 pAr->eCmd = eSwitch;
31327 break;
31328
31329 case AR_SWITCH_DRYRUN:
31330 pAr->bDryRun = 1;
 
 
 
31331 break;
31332 case AR_SWITCH_GLOB:
31333 pAr->bGlob = 1;
31334 break;
31335 case AR_SWITCH_VERBOSE:
@@ -31376,10 +31483,11 @@
31376 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
31377 { "file", 'f', AR_SWITCH_FILE, 1 },
31378 { "append", 'a', AR_SWITCH_APPEND, 1 },
31379 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
31380 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
 
31381 { "glob", 'g', AR_SWITCH_GLOB, 0 },
31382 };
31383 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
31384 struct ArSwitch *pEnd = &aSwitch[nSwitch];
31385
@@ -31676,18 +31784,41 @@
31676
31677 /*
31678 ** Implementation of .ar "eXtract" command.
31679 */
31680 static int arExtractCommand(ArCommand *pAr){
 
 
 
 
 
 
 
 
31681 const char *zSql1 =
31682 "WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n"
31683 "SELECT ($dir || name),\n"
31684 " CASE WHEN $dryrun THEN 0\n"
31685 " ELSE writefile($dir||name, %s, mode, mtime) END\n"
 
 
 
 
 
 
 
 
 
 
 
 
31686 " FROM dest CROSS JOIN %s\n"
31687 " WHERE (%s)\n"
31688 " AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */
 
 
 
31689 " AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
31690 " AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
31691
31692 const char *azExtraArg[] = {
31693 "sqlar_uncompress(data, sz)",
@@ -31714,39 +31845,48 @@
31714 }
31715 if( zDir==0 ) rc = SQLITE_NOMEM;
31716 }
31717
31718 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
31719 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
 
 
 
31720 );
31721
31722 if( rc==SQLITE_OK ){
31723 j = sqlite3_bind_parameter_index(pSql, "$dir");
31724 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
31725 j = sqlite3_bind_parameter_index(pSql, "$dryrun");
31726 sqlite3_bind_int(pSql, j, pAr->bDryRun);
31727
31728 /* Run the SELECT statement twice
31729 ** (0) writefile() all files and directories
31730 ** (1) writefile() for directory again
31731 ** The second pass is so that the timestamps for extracted directories
 
31732 ** will be reset to the value in the archive, since populating them
31733 ** in the first pass will have changed the timestamp. */
31734 for(i=0; i<2; i++){
 
 
 
31735 j = sqlite3_bind_parameter_index(pSql, "$pass");
31736 sqlite3_bind_int(pSql, j, i);
31737 if( pAr->bDryRun ){
31738 cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
31739 if( pAr->bVerbose==0 ) break;
31740 }
31741 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
31742 if( i==0 && pAr->bVerbose ){
31743 cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
31744 }
31745 }
31746 if( pAr->bDryRun ) break;
31747 shellReset(&rc, pSql);
 
 
 
31748 }
31749 shellFinalize(&rc, pSql);
31750 }
31751
31752 sqlite3_free(zDir);
@@ -32257,11 +32397,11 @@
32257 ;
32258 static const char * const zCollectVar = "\
32259 SELECT\
32260 '('||x'0a'\
32261 || group_concat(\
32262 cname||' ANY',\
32263 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
32264 ||')' AS ColsSpec \
32265 FROM (\
32266 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
32267 FROM ColNames ORDER BY cpos\
@@ -33102,30 +33242,14 @@
33102 }else if( optionMatch(z,"limits") ){
33103 if( (++i)>=nArg ){
33104 dotCmdError(p, i-1, "missing argument", 0);
33105 return 1;
33106 }
33107 k = pickStr(azArg[i],0,"on","off","");
33108 if( k==0 ){
33109 p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
33110 p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
33111 p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
33112 }else if( k==1 ){
33113 p->mode.spec.nLineLimit = 0;
33114 p->mode.spec.nCharLimit = 0;
33115 p->mode.spec.nTitleLimit = 0;
33116 }else{
33117 int L, C, T = 0;
33118 int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
33119 if( nNum<2 || L<0 || C<0 || T<0){
33120 dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
33121 " and T are unsigned integers");
33122 return 1;
33123 }
33124 p->mode.spec.nLineLimit = L;
33125 p->mode.spec.nCharLimit = C;
33126 if( nNum==3 ) p->mode.spec.nTitleLimit = T;
33127 }
33128 chng = 1;
33129 }else if( optionMatch(z,"list") ){
33130 int ii;
33131 cli_puts("available modes:", p->out);
@@ -34339,11 +34463,16 @@
34339 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
34340 rc = shell_dbinfo_command(p, nArg, azArg);
34341 }else
34342 #endif /* SQLITE_SHELL_HAVE_RECOVER */
34343
34344 if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
 
 
 
 
 
34345 const char *zSchema = 0;
34346 int ii;
34347 char *zSql;
34348 open_db(p, 0);
34349 for(ii=1; ii<nArg; ii++){
@@ -34358,27 +34487,19 @@
34358 rc = 1;
34359 goto meta_command_exit;
34360 }
34361 zSchema = z;
34362 }
34363 zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
34364 shell_check_oom(zSql);
34365 modePush(p);
34366 modeChange(p, MODE_BATCH);
34367 p->mode.spec.nLineLimit = 0;
34368 p->mode.spec.nCharLimit = 0;
34369 p->mode.spec.nTitleLimit = 0;
34370 shell_exec(p, zSql, 0);
34371 modePop(p);
34372 sqlite3_free(zSql);
34373 }else
34374
34375 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34376 open_db(p, 0);
34377 rc = shell_dbtotxt_command(p, nArg, azArg);
34378 }else
34379
34380 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
34381 char *zLike = 0;
34382 char *zSql;
34383 int i;
34384 int savedShellFlags = p->shellFlgs;
@@ -35491,10 +35612,26 @@
35491 }else
35492 if( strcmp(z,"-show")==0 ){
35493 cli_printf(stdout,"Main prompt: '%s'\n", prompt_string(p, 0));
35494 cli_printf(stdout,"Continuation: '%s'\n", prompt_string(p, 1));
35495 }else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35496 if( strcmp(z,"-")==0 ){
35497 noOpt = 1;
35498 }else
35499 {
35500 dotCmdError(p, i, "unknown option", 0);
@@ -35505,10 +35642,11 @@
35505 dotCmdError(p, i, "extra argument", 0);
35506 rc = 1;
35507 goto meta_command_exit;
35508 }else if( !p->dot.abQuot[i] && sqlite3_strglob("*[^a-z]*",z)!=0 ){
35509 dotCmdError(p, i, "use quotes around the prompt string", 0);
 
35510 }else{
35511 free(p->azPrompt[cnt]);
35512 p->azPrompt[cnt] = strdup(z);
35513 cnt++;
35514 }
@@ -37717,17 +37855,17 @@
37717 " -- treat no subsequent arguments as options\n"
37718 #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
37719 " -A ARGS... run \".archive ARGS\" and exit\n"
37720 #endif
37721 " -append append the database to the end of the file\n"
37722 " -ascii set output mode to 'ascii'\n"
37723 " -bail stop after hitting an error\n"
37724 " -batch force batch I/O\n"
37725 " -box set output mode to 'box'\n"
37726 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
37727 " -column set output mode to 'column'\n"
37728 " -csv set output mode to 'csv'\n"
37729 #if !defined(SQLITE_OMIT_DESERIALIZE)
37730 " -deserialize open the database using sqlite3_deserialize()\n"
37731 #endif
37732 " -echo print inputs before execution\n"
37733 " -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
@@ -37735,18 +37873,18 @@
37735 " -[no]header turn headers on or off\n"
37736 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
37737 " -heap SIZE Size of heap for memsys3 or memsys5\n"
37738 #endif
37739 " -help show this message\n"
37740 " -html set output mode to HTML\n"
37741 " -ifexists only open if database already exists\n"
37742 " -interactive force interactive I/O\n"
37743 " -json set output mode to 'json'\n"
37744 " -line set output mode to 'line'\n"
37745 " -list set output mode to 'list'\n"
37746 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
37747 " -markdown set output mode to 'markdown'\n"
37748 #if !defined(SQLITE_OMIT_DESERIALIZE)
37749 " -maxsize N maximum size for a --deserialize database\n"
37750 #endif
37751 " -memtrace trace all memory allocations and deallocations\n"
37752 " -mmap N default mmap size set to N\n"
@@ -37759,21 +37897,21 @@
37759 " -nonce STRING set the safe-mode escape nonce\n"
37760 " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
37761 " -nullvalue TEXT set text string for NULL values. Default ''\n"
37762 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
37763 " -pcachetrace trace all page cache operations\n"
37764 " -quote set output mode to 'quote'\n"
37765 " -readonly open the database read-only\n"
37766 " -safe enable safe-mode\n"
37767 " -screenwidth N use N as the default screenwidth \n"
37768 " -separator SEP set output column separator. Default: '|'\n"
37769 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
37770 " -sorterref SIZE sorter references threshold size\n"
37771 #endif
37772 " -stats print memory stats before each finalize\n"
37773 " -table set output mode to 'table'\n"
37774 " -tabs set output mode to 'tabs'\n"
37775 " -unsafe-testing allow unsafe commands and modes for testing\n"
37776 " -version show SQLite version\n"
37777 " -vfs NAME use NAME as the default VFS\n"
37778 " -vfstrace enable tracing of all VFS calls\n"
37779 #ifdef SQLITE_HAVE_ZLIB
@@ -37801,10 +37939,23 @@
37801 sputz(stdout, "WARNING: attempt to configure SQLite after"
37802 " initialization.\n");
37803 }
37804 }
37805
 
 
 
 
 
 
 
 
 
 
 
 
 
37806 /*
37807 ** Initialize the state information in data
37808 */
37809 static void main_init(ShellState *p) {
37810 memset(p, 0, sizeof(*p));
@@ -37825,10 +37976,14 @@
37825 #else
37826 /* No \001...\002 escapes required for linenoise or when not using a
37827 ** command-line editing library */
37828 p->bDelimitNonprint = 0;
37829 #endif
 
 
 
 
37830 }
37831
37832 /*
37833 ** Output text to the console in a font that attracts extra attention.
37834 */
@@ -37854,11 +38009,11 @@
37854 }
37855
37856 /*
37857 ** The callback from atexit().
37858 */
37859 static void abnormalExit(void){
37860 if( seenInterrupt ) eputz("Program interrupted.\n");
37861 if( globalShellState ){
37862 clearTempFile(globalShellState, 1, 1);
37863 }
37864 }
@@ -38065,11 +38220,11 @@
38065 stdin_is_interactive = 0;
38066 nCmd++;
38067 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
38068 shell_check_oom(azCmd);
38069 aiCmd = realloc(aiCmd, sizeof(aiCmd[0])*nCmd);
38070 shell_check_oom(azCmd);
38071 azCmd[nCmd-1] = z;
38072 aiCmd[nCmd-1] = i;
38073 }
38074 continue;
38075 }
@@ -38354,10 +38509,11 @@
38354 modeChange(&data, MODE_Psql);
38355 }else if( cli_strcmp(z,"-box")==0 ){
38356 modeChange(&data, MODE_Box);
38357 }else if( cli_strcmp(z,"-csv")==0 ){
38358 modeChange(&data, MODE_Csv);
 
38359 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
38360 /* See similar code at tag-20250224-1 */
38361 const char *zEsc = argv[++i];
38362 int k;
38363 for(k=0; k<ArraySize(qrfEscNames); k++){
@@ -38412,12 +38568,14 @@
38412 }else if( cli_strcmp(z,"-nullvalue")==0 ){
38413 modeSetStr(&data.mode.spec.zNull,
38414 cmdline_option_value(argc,argv,++i));
38415 }else if( cli_strcmp(z,"-header")==0 ){
38416 data.mode.spec.bTitles = QRF_Yes;
 
38417 }else if( cli_strcmp(z,"-noheader")==0 ){
38418 data.mode.spec.bTitles = QRF_No;
 
38419 }else if( cli_strcmp(z,"-echo")==0 ){
38420 data.mode.mFlags |= MFLG_ECHO;
38421 }else if( cli_strcmp(z,"-eqp")==0 ){
38422 data.mode.autoEQP = AUTOEQP_on;
38423 }else if( cli_strcmp(z,"-eqpfull")==0 ){
38424
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,16 +5,16 @@
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
15 ** ext/misc/diskused.c
16 ** ext/misc/fileio.c
17 ** ext/misc/ieee754.c
18 ** ext/misc/memtrace.c
19 ** ext/misc/pcachetrace.c
20 ** ext/misc/regexp.c
@@ -154,10 +154,11 @@
154 #include <string.h>
155 #include <stdio.h>
156 #include <assert.h>
157 #include <math.h>
158 #include <stdint.h>
159 #include <time.h>
160 #include "sqlite3.h"
161 typedef sqlite3_int64 i64;
162 typedef sqlite3_uint64 u64;
163 typedef unsigned char u8;
164 #include <ctype.h>
@@ -190,13 +191,14 @@
191 #include <sys/stat.h>
192
193 #if HAVE_READLINE
194 # include <readline/readline.h>
195 # include <readline/history.h>
196 #elif HAVE_EDITLINE
197 /* If both HAVE_READLINE and HAVE_EDITLINE are true, assume that this
198 ** libedit installation does not have its own headers, instead using
199 ** those from libreadline. */
200 # include <editline/readline.h>
201 #endif
202
203 #if HAVE_EDITLINE || HAVE_READLINE
204
@@ -744,12 +746,11 @@
746 const sqlite3_qrf_spec *pSpec, /* Result format specification */
747 char **pzErr /* OUT: Write error message here */
748 );
749
750 /*
751 ** Range of values for sqlite3_qrf_spec.aWidth[] entries.
 
752 */
753 #define QRF_MAX_WIDTH 10000
754 #define QRF_MIN_WIDTH 0
755
756 /*
@@ -1129,10 +1130,14 @@
1130 sqlite3_str_append(pOut, "-", 1);
1131 }
1132 if( N<10000 ){
1133 sqlite3_str_appendf(pOut, "%4lld ", N);
1134 return;
1135 }
1136 if( N>=9223372036854775800LL ){
1137 sqlite3_str_appendf(pOut, "%.2fE", 1e-18*(double)N);
1138 return;
1139 }
1140 for(i=1; i<=18; i++){
1141 N = (N+5)/10;
1142 if( N<10000 ){
1143 int n = (int)N;
@@ -1289,12 +1294,12 @@
1294 if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
1295 int nSp = 0;
1296 sqlite3_str_reset(pStats);
1297 if( nCycle>=0 && nTotal>0 ){
1298 qrfApproxInt64(pStats, nCycle);
1299 sqlite3_str_appendf(pStats, " %3.0f%%",
1300 ((100.0*(double)nCycle)+nTotal/2.0) / (double)nTotal
1301 );
1302 nSp = 2;
1303 }
1304 if( nLoop>=0 ){
1305 if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
@@ -1787,11 +1792,11 @@
1792 }
1793 if( i>0 ){
1794 sqlite3_str_append(pOut, (const char*)z, i);
1795 }
1796 switch( z[i] ){
1797 case '>': sqlite3_str_append(pOut, "&gt;", 4); break;
1798 case '&': sqlite3_str_append(pOut, "&amp;", 5); break;
1799 case '<': sqlite3_str_append(pOut, "&lt;", 4); break;
1800 case '"': sqlite3_str_append(pOut, "&quot;", 6); break;
1801 case '\'': sqlite3_str_append(pOut, "&#39;", 5); break;
1802 default: i--;
@@ -2281,11 +2286,11 @@
2286 if( bWrap && z[i]!=0 && !qrfSpace(z[i]) && qrfAlnum(c)==qrfAlnum(z[i]) ){
2287 /* Perhaps try to back up to a better place to break the line */
2288 for(k=i-1; k>=i/2; k--){
2289 if( qrfSpace(z[k]) ) break;
2290 }
2291 if( k<i/2 && i/2>0 ){
2292 for(k=i; k>=i/2; k--){
2293 if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
2294 }
2295 }
2296 if( k>=i/2 ){
@@ -2532,16 +2537,16 @@
2537 const char *azDash[2] = {
2538 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24,
2539 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
2540 };/* 0 1 2 3 4 5 6 7 8 9 */
2541 const int nDash = 30;
2542 i64 nn = 3*(i64)N;
2543 while( nn>nDash ){
2544 sqlite3_str_append(pOut, azDash[bDbl], nDash);
2545 nn -= nDash;
2546 }
2547 sqlite3_str_append(pOut, azDash[bDbl], (int)nn);
2548 }
2549
2550 /*
2551 ** Draw a horizontal separator for a QRF_STYLE_Box table.
2552 */
@@ -2610,11 +2615,11 @@
2615 int nSW /* Screen width */
2616 ){
2617 int i; /* Loop counter */
2618 int nr; /* Number of rows */
2619 int w = 0; /* Width of the current column */
2620 i64 t; /* Total width of all columns */
2621 int *aw; /* Array of individual column widths */
2622
2623 aw = sqlite3_malloc64( sizeof(int)*nCol );
2624 if( aw==0 ){
2625 qrfOom(p);
@@ -2748,12 +2753,15 @@
2753 }else{
2754 sepW = pData->nCol*3 + 1;
2755 if( p->spec.bBorder==QRF_No ) sepW -= 2;
2756 }
2757 nCol = pData->nCol;
2758 for(i=0, sumW=0; i<nCol; i++){
2759 if( sumW > 2147483647 - pData->a[i].w ) return;
2760 sumW += pData->a[i].w;
2761 }
2762 if( p->spec.nScreenWidth >= (i64)sumW + sepW ) return;
2763
2764 /* First thing to do is reduce the separation between columns */
2765 pData->nMargin = 0;
2766 if( p->spec.eStyle==QRF_STYLE_Column ){
2767 sepW = pData->nCol - 1;
@@ -3624,11 +3632,11 @@
3632 p->nRow = 0;
3633 sz = sizeof(sqlite3_qrf_spec);
3634 memcpy(&p->spec, pSpec, sz);
3635 if( p->spec.zNull==0 ) p->spec.zNull = "";
3636 p->mxWidth = p->spec.nScreenWidth;
3637 if( p->mxWidth<=0 ) p->mxWidth = 2147483647;
3638 p->mxHeight = p->spec.nLineLimit;
3639 if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
3640 if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
3641 if( p->spec.eEsc>QRF_ESC_Symbol ) p->spec.eEsc = QRF_Auto;
3642 if( p->spec.eText>QRF_TEXT_Relaxed ) p->spec.eText = QRF_Auto;
@@ -5272,10 +5280,14 @@
5280 #include <stdarg.h>
5281
5282 /******************************************************************************
5283 ** The Hash Engine
5284 */
5285 #if defined(__GNUC__) && __GNUC__>=11
5286 # pragma GCC diagnostic push
5287 # pragma GCC diagnostic ignored "-Wstringop-overread"
5288 #endif
5289 /* Context for the SHA1 hash */
5290 typedef struct SHA1Context SHA1Context;
5291 struct SHA1Context {
5292 unsigned int state[5];
5293 unsigned int count[2];
@@ -5412,11 +5424,11 @@
5424 }
5425 j = 0;
5426 }else{
5427 i = 0;
5428 }
5429 if( len-i>0 ) (void)memcpy(&p->buffer[j], &data[i], len - i);
5430 }
5431
5432 /* Compute a string using sqlite3_vsnprintf() and hash it */
5433 static void hash_step_vformat(
5434 SHA1Context *p, /* Add content to this context */
@@ -5467,10 +5479,13 @@
5479 zOut[i*2+1] = zEncode[digest[i] & 0xf];
5480 }
5481 zOut[i*2]= 0;
5482 }
5483 }
5484 #if defined(__GNUC__) && __GNUC__>=11
5485 # pragma GCC diagnostic pop
5486 #endif
5487 /* End of the hashing logic
5488 *****************************************************************************/
5489
5490 /*
5491 ** Two SQL functions: sha1(X) and sha1b(X).
@@ -6056,32 +6071,41 @@
6071 }
6072 z[i] = 0;
6073 sqlite3_result_text(pCtx, z, i, sqlite3_free);
6074 }
6075
6076 /* Forward declaration */
6077 static void decimal_expand(Decimal *p, int nDigit, int nFrac);
6078
6079 /*
6080 ** Round a decimal value to N significant digits. N must be positive.
6081 */
6082 static void decimal_round(Decimal *p, int N){
6083 int i;
6084 int nZero; /* Number of leading zeros */
6085 if( N<1 ) return;
6086 if( p==0 ) return;
6087 if( p->nDigit<=N ) return;
6088 for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
6089 N += nZero;
6090 if( p->nDigit<=N ) return;
6091 if( p->a[N]>=5 ){
6092 /* If all leading digits are 9, increase the number of digits
6093 ** by adding a new 0 to the front */
6094 for(i=0; i<N && p->a[i]==9; i++){}
6095 if( i==N ){
6096 decimal_expand(p, p->nDigit+1, 0);
6097 if( p->oom ) return;
6098 }
6099
6100 /* Do the rounding */
6101 p->a[N-1]++;
6102 for(i=N-1; i>0 && p->a[i]>9; i--){
6103 p->a[i] = 0;
6104 p->a[i-1]++;
6105 }
6106 assert( p->a[0]<=9 );
 
 
 
6107 }
6108 memset(&p->a[N], 0, p->nDigit - N);
6109 }
6110
6111 /*
@@ -8363,19 +8387,26 @@
8387 }
8388 }else{
8389 iMin = iMax = sqlite3_value_int64(argv[iArg++]);
8390 }
8391 }else{
8392 if( idxNum & 0x0300 ){ /* value>X (0x200) or value>=X (0x100) */
8393 if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
8394 double r = sqlite3_value_double(argv[iArg++]);
8395 if( r<=(double)SMALLEST_INT64 ){
8396 iMin = SMALLEST_INT64;
8397 }else if( r>(double)LARGEST_INT64 ){
8398 goto series_no_rows;
8399 }else{
8400 iMin = (sqlite3_int64)seriesCeil(r);
8401 if( iMin<0 && r>0.0 ){
8402 iMin = LARGEST_INT64;
8403 }
8404 if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
8405 if( iMin==LARGEST_INT64 ) goto series_no_rows;
8406 iMin++;
8407 }
8408 }
8409 }else{
8410 iMin = sqlite3_value_int64(argv[iArg++]);
8411 if( (idxNum & 0x0200)!=0 ){
8412 if( iMin==LARGEST_INT64 ){
@@ -8384,19 +8415,25 @@
8415 iMin++;
8416 }
8417 }
8418 }
8419 }
8420 if( idxNum & 0x3000 ){ /* value<X (0x2000) or value<=X (0x1000) */
8421 if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
8422 double r = sqlite3_value_double(argv[iArg++]);
8423 if( r>=(double)LARGEST_INT64 ){
8424 iMax = LARGEST_INT64;
8425 }else if( r<=(double)SMALLEST_INT64 ){
8426 goto series_no_rows;
8427 }else{
8428 iMax = (sqlite3_int64)seriesFloor(r);
8429 if( iMax<0 && r>0.0 ){
8430 iMax = LARGEST_INT64;
8431 }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
8432 if( iMax==SMALLEST_INT64 ) goto series_no_rows;
8433 iMax--;
8434 }
8435 }
8436 }else{
8437 iMax = sqlite3_value_int64(argv[iArg++]);
8438 if( idxNum & 0x2000 ){
8439 if( iMax==SMALLEST_INT64 ){
@@ -9638,11 +9675,10 @@
9675 if( pRe==0 ){
9676 sqlite3_result_error_nomem(context);
9677 return;
9678 }
9679 pStr = sqlite3_str_new(0);
 
9680 if( pRe->nInit>0 ){
9681 sqlite3_str_appendf(pStr, "INIT ");
9682 for(i=0; i<pRe->nInit; i++){
9683 sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
9684 }
@@ -9649,20 +9685,20 @@
9685 sqlite3_str_appendf(pStr, "\n");
9686 }
9687 for(i=0; (unsigned)i<pRe->nState; i++){
9688 sqlite3_str_appendf(pStr, "%-8s %4d\n",
9689 ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
9690 }
9691 if( sqlite3_str_errcode(pStr)==SQLITE_NOMEM ){
9692 sqlite3_str_finish(pStr);
9693 re_free(pRe);
9694 sqlite3_result_error_nomem(context);
9695 return;
9696 }
9697 n = sqlite3_str_length(pStr);
9698 z = sqlite3_str_finish(pStr);
9699 sqlite3_result_text(context, z, n-1, sqlite3_free);
 
 
 
 
 
 
9700 re_free(pRe);
9701 }
9702
9703 #endif /* SQLITE_DEBUG */
9704
@@ -10870,10 +10906,13 @@
10906 ** Return NULL if unable.
10907 **
10908 ** The file or directory X is not required to exist. The answer is formed
10909 ** by calling system realpath() on the prefix of X that does exist and
10910 ** appending the tail of X that does not (yet) exist.
10911 **
10912 ** FIXME: This routine sometimes returns NULL rather than raising
10913 ** an SQLITE_NOMEM error if an OOM is encountered.
10914 */
10915 static void realpathFunc(
10916 sqlite3_context *context,
10917 int argc,
10918 sqlite3_value **argv
@@ -10892,10 +10931,11 @@
10931 (void)argc;
10932 zPath = (const char*)sqlite3_value_text(argv[0]);
10933 if( zPath==0 ) return;
10934 if( zPath[0]==0 ) zPath = ".";
10935 zCopy = sqlite3_mprintf("%s",zPath);
10936 if( zCopy==0 ) return;
10937 len = strlen(zCopy);
10938 while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
10939 len--;
10940 }
10941 zCopy[len] = 0;
@@ -12685,10 +12725,11 @@
12725
12726 for(p=pCsr->pFreeEntry; p; p=pNext){
12727 pNext = p->pNext;
12728 zipfileEntryFree(p);
12729 }
12730 pCsr->pFreeEntry = 0;
12731 }
12732
12733 /*
12734 ** Destructor for an ZipfileCsr.
12735 */
@@ -13087,11 +13128,17 @@
13128 }
13129 }
13130
13131 if( rc==SQLITE_OK ){
13132 u32 *pt = &pNew->mUnixTime;
13133 /* aRead[0..nFile-1] might contain embedded \000 characters
13134 ** See Bug 2026-05-31T11:43:05Z */
13135 pNew->cds.zFile = sqlite3_malloc64(nFile+1);
13136 if( pNew->cds.zFile!=0 ){
13137 memcpy(pNew->cds.zFile, aRead, nFile);
13138 pNew->cds.zFile[nFile] = 0;
13139 }
13140 pNew->aExtra = (u8*)&pNew[1];
13141 memcpy(pNew->aExtra, &aRead[nFile], nExtra);
13142 if( pNew->cds.zFile==0 ){
13143 rc = SQLITE_NOMEM;
13144 }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
@@ -14191,14 +14238,14 @@
14238 ZipfileBuffer body;
14239 ZipfileBuffer cds;
14240 };
14241
14242 static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
14243 if( (pBuf->nAlloc-pBuf->n)<nByte ){
14244 u8 *aNew;
14245 i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512;
14246 i64 nReq = pBuf->n + nByte;
14247
14248 while( nNew<nReq ) nNew = nNew*2;
14249 aNew = sqlite3_realloc64(pBuf->a, nNew);
14250 if( aNew==0 ) return SQLITE_NOMEM;
14251 pBuf->a = aNew;
@@ -16296,11 +16343,11 @@
16343 p->pTable = pTab;
16344
16345 /* The statement the vtab will pass to sqlite3_declare_vtab() */
16346 zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
16347 for(i=0; i<pTab->nCol; i++){
16348 zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %Q",
16349 (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
16350 );
16351 }
16352 zInner = idxAppendText(&rc, zInner, ")");
16353
@@ -16496,11 +16543,11 @@
16543 sqlite3_free(zCols);
16544 sqlite3_free(zOrder);
16545 return sqlite3_reset(pIndexXInfo);
16546 }
16547 zCols = idxAppendText(&rc, zCols,
16548 "%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %Q",
16549 zComma, zName, nCol, zName, zColl
16550 );
16551 zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
16552 }
16553 sqlite3_reset(pIndexXInfo);
@@ -19464,11 +19511,11 @@
19511 sqlite3_vfs_unregister(pVfs);
19512 sqlite3_free(pVfs);
19513 }
19514
19515 /************************* End ext/misc/vfstrace.c ********************/
19516 /************************* Begin ext/misc/diskused.c ******************/
19517 /*
19518 ** 2026-04-13
19519 **
19520 ** The author disclaims copyright to this source code. In place of
19521 ** a legal notice, here is a blessing:
@@ -19477,12 +19524,21 @@
19524 ** May you find forgiveness for yourself and forgive others.
19525 ** May you share freely, never taking more than you give.
19526 **
19527 ******************************************************************************
19528 **
19529 ** This extension implements an SQL function:
19530 **
19531 ** diskused(X)
19532 **
19533 ** Where X is the schema name (typically 'main'). The output is text
19534 ** that describes how much filesystem space the various tables and indexes
19535 ** of the database consume.
19536 **
19537 ** This function is a replacement for the (now deprecated)
19538 ** "sqlite3_analyzer" utility program. This function is built
19539 ** into the CLI and is used to implement the ".diskused" command there.
19540 */
19541 /* #include "sqlite3ext.h" */
19542 SQLITE_EXTENSION_INIT1
19543 #include <assert.h>
19544 #include <string.h>
@@ -19490,28 +19546,28 @@
19546 #include <math.h>
19547
19548 /*
19549 ** State information for the analysis
19550 */
19551 typedef struct DiskUsed DiskUsed;
19552 struct DiskUsed {
19553 sqlite3 *db; /* Database connection */
19554 sqlite3_context *context; /* SQL function context */
19555 sqlite3_str *pOut; /* Write output here */
19556 char *zSU; /* Name of the temp.space_used table */
19557 const char *zSchema; /* Schema to be analyzed */
19558 };
19559
19560 /*
19561 ** Free all resources that the DiskUsed object references and
19562 ** reset the DiskUsed object.
19563 **
19564 ** Call this routine multiple times on the same DiskUsed object
19565 ** is a harmless no-op, as long as the memory for the object itself
19566 ** has not been freed.
19567 */
19568 static void diskusedReset(DiskUsed *p){
19569 if( p->zSU ){
19570 char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
19571 if( zSql ){
19572 sqlite3_exec(p->db, zSql, 0, 0, 0);
19573 sqlite3_free(zSql);
@@ -19524,11 +19580,11 @@
19580
19581 /*
19582 ** Report an error using formatted text. If zFormat==NULL then report
19583 ** an OOM error.
19584 */
19585 static void diskusedError(DiskUsed *p, const char *zFormat, ...){
19586 char *zErr;
19587 if( zFormat ){
19588 va_list ap;
19589 va_start(ap, zFormat);
19590 zErr = sqlite3_vmprintf(zFormat, ap);
@@ -19540,38 +19596,38 @@
19596 sqlite3_result_error_nomem(p->context);
19597 }else{
19598 sqlite3_result_error(p->context, zErr, -1);
19599 sqlite3_free(zErr);
19600 }
19601 diskusedReset(p);
19602 }
19603
19604 /*
19605 ** Prepare and return an SQL statement.
19606 */
19607 static sqlite3_stmt *diskusedVPrep(DiskUsed *p, const char *zFmt, va_list ap){
19608 char *zSql;
19609 int rc;
19610 sqlite3_stmt *pStmt = 0;
19611 zSql = sqlite3_vmprintf(zFmt, ap);
19612 if( zSql==0 ){ diskusedError(p,0); return 0; }
19613 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19614 if( rc ){
19615 diskusedError(p, "SQL parse error: %s\nOriginal SQL: %s",
19616 sqlite3_errmsg(p->db), zSql);
19617 sqlite3_finalize(pStmt);
19618 diskusedReset(p);
19619 pStmt = 0;
19620 }
19621 sqlite3_free(zSql);
19622 return pStmt;
19623 }
19624 static sqlite3_stmt *diskusedPrepare(DiskUsed *p, const char *zFormat, ...){
19625 va_list ap;
19626 sqlite3_stmt *pStmt = 0;
19627 va_start(ap, zFormat);
19628 pStmt = diskusedVPrep(p,zFormat,ap);
19629 va_end(ap);
19630 return pStmt;
19631 }
19632
19633 /*
@@ -19580,60 +19636,60 @@
19636 **
19637 ** If rc is SQLITE_DONE or SQLITE_OK, then return false.
19638 **
19639 ** The prepared statement is closed in either case.
19640 */
19641 static int diskusedStmtFinish(DiskUsed *p, int rc, sqlite3_stmt *pStmt){
19642 if( rc==SQLITE_DONE ){
19643 rc = SQLITE_OK;
19644 }
19645 if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19646 diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19647 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19648 diskusedReset(p);
19649 }
19650 sqlite3_finalize(pStmt);
19651 return rc;
19652 }
19653
19654 /*
19655 ** Run SQL. Return the number of errors.
19656 */
19657 static int diskusedSql(DiskUsed *p, const char *zFormat, ...){
19658 va_list ap;
19659 int rc;
19660 sqlite3_stmt *pStmt = 0;
19661 va_start(ap, zFormat);
19662 pStmt = diskusedVPrep(p,zFormat,ap);
19663 va_end(ap);
19664 if( pStmt==0 ) return 1;
19665 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
19666 if( rc==SQLITE_DONE ){
19667 rc = SQLITE_OK;
19668 }else{
19669 diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19670 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19671 diskusedReset(p);
19672 }
19673 sqlite3_finalize(pStmt);
19674 return rc;
19675 }
19676
19677 /*
19678 ** Run an SQL query that returns an integer. Write that integer
19679 ** into *piRes. Return the number of errors.
19680 */
19681 static int diskusedSqlInt(
19682 DiskUsed *p,
19683 sqlite3_int64 *piRes,
19684 const char *zFormat, ...
19685 ){
19686 va_list ap;
19687 int rc;
19688 sqlite3_stmt *pStmt = 0;
19689 va_start(ap, zFormat);
19690 pStmt = diskusedVPrep(p,zFormat,ap);
19691 va_end(ap);
19692 if( pStmt==0 ) return 1;
19693 rc = sqlite3_step(pStmt);
19694 if( rc==SQLITE_ROW ){
19695 *piRes = sqlite3_column_int64(pStmt, 0);
@@ -19641,14 +19697,14 @@
19697 }else if( rc==SQLITE_DONE ){
19698 rc = SQLITE_OK;
19699 }else{
19700 if( p->db ){
19701 /* p->db is NULL if there was some prior error */
19702 diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19703 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19704 }
19705 diskusedReset(p);
19706 }
19707 sqlite3_finalize(pStmt);
19708 return rc;
19709 }
19710
@@ -19657,20 +19713,20 @@
19713 ** by the format string. If the output is initially empty, begin
19714 ** the title line with "/" so that it forms the beginning of a C-style
19715 ** comment. Otherwise begin with a new-line. Always finish with a
19716 ** newline.
19717 */
19718 static void diskusedTitle(DiskUsed *p, const char *zFormat, ...){
19719 char *zFirst;
19720 char *zTitle;
19721 size_t nTitle;
19722 va_list ap;
19723 va_start(ap, zFormat);
19724 zTitle = sqlite3_vmprintf(zFormat, ap);
19725 va_end(ap);
19726 if( zTitle==0 ){
19727 diskusedError(p, 0);
19728 return;
19729 }
19730 zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
19731 nTitle = strlen(zTitle);
19732 if( nTitle>=75 ){
@@ -19685,12 +19741,12 @@
19741 /*
19742 ** Add an output line that begins with the zDesc text extended out to
19743 ** 50 columns with "." characters, and followed by whatever text is
19744 ** described by zFormat.
19745 */
19746 static void diskusedLine(
19747 DiskUsed *p, /* DiskUsed context */
19748 const char *zDesc, /* Description */
19749 const char *zFormat, /* Argument to the description */
19750 ...
19751 ){
19752 char *zTxt;
@@ -19698,14 +19754,14 @@
19754 va_list ap;
19755 va_start(ap, zFormat);
19756 zTxt = sqlite3_vmprintf(zFormat, ap);
19757 va_end(ap);
19758 if( zTxt==0 ){
19759 diskusedError(p, 0);
19760 return;
19761 }
19762 nDesc = zDesc ? strlen(zDesc) : 0;
19763 if( nDesc>=50 ){
19764 sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
19765 }else{
19766 int nExtra = 50 - (int)nDesc;
19767 sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
@@ -19715,11 +19771,11 @@
19771 /*
19772 ** Write a percentage into the output. The number written should show
19773 ** two or three significant digits, with the decimal point being the fourth
19774 ** character.
19775 */
19776 static void diskusedPercent(DiskUsed *p, double r){
19777 char zNum[100];
19778 char *zDP;
19779 int nLeadingDigit;
19780 int sz;
19781 sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
@@ -19744,12 +19800,12 @@
19800 **
19801 ** The title if the subreport is given by zTitle. zWhere is
19802 ** a boolean expression that can go in the WHERE clause to select
19803 ** the relevant rows of the s.zSU table.
19804 */
19805 static int diskusedSubreport(
19806 DiskUsed *p, /* DiskUsed context */
19807 char *zTitle, /* Title for this subreport */
19808 char *zWhere, /* WHERE clause for this subreport */
19809 sqlite3_int64 pgsz, /* Database page size */
19810 sqlite3_int64 nPage /* Number of pages in entire database */
19811 ){
@@ -19773,14 +19829,14 @@
19829 sqlite3_int64 total_unused; /* Total unused bytes */
19830 sqlite3_int64 total_meta; /* Total metadata */
19831 int rc;
19832
19833 if( zTitle==0 || zWhere==0 ){
19834 diskusedError(p, 0);
19835 return SQLITE_NOMEM;
19836 }
19837 pStmt = diskusedPrepare(p,
19838 "SELECT\n"
19839 " sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
19840 " sum(payload),\n" /* 1 */
19841 " sum(ovfl_payload),\n" /* 2 */
19842 " max(mx_payload),\n" /* 3 */
@@ -19797,11 +19853,11 @@
19853 " FROM temp.%s WHERE %s",
19854 p->zSU, zWhere);
19855 if( pStmt==0 ) return 1;
19856 rc = sqlite3_step(pStmt);
19857 if( rc==SQLITE_ROW ){
19858 diskusedTitle(p, "%s", zTitle);
19859
19860 nentry = sqlite3_column_int64(pStmt, 0);
19861 payload = sqlite3_column_int64(pStmt, 1);
19862 ovfl_payload = sqlite3_column_int64(pStmt, 2);
19863 mx_payload = sqlite3_column_int64(pStmt, 3);
@@ -19816,73 +19872,73 @@
19872 cnt = sqlite3_column_int64(pStmt, 12);
19873 int_cell = sqlite3_column_int64(pStmt, 13);
19874 rc = SQLITE_DONE;
19875
19876 total_pages = leaf_pages + int_pages + ovfl_pages;
19877 diskusedLine(p, "Percentage of total database", "%.3g%%\n",
19878 (total_pages*100.0)/(double)nPage);
19879 diskusedLine(p, "Number of entries", "%lld\n", nentry);
19880 storage = total_pages*pgsz;
19881 diskusedLine(p, "Bytes of storage consumed", "%lld\n", storage);
19882 diskusedLine(p, "Bytes of payload", "%-11lld ", payload);
19883 diskusedPercent(p, payload*100.0/(double)storage);
19884 if( ovfl_cnt>0 ){
19885 diskusedLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19886 diskusedPercent(p, ovfl_payload*100.0/(double)payload);
19887 }
19888 total_unused = leaf_unused + int_unused + ovfl_unused;
19889 total_meta = storage - payload - total_unused;
19890 diskusedLine(p, "Bytes of metadata","%-11lld ", total_meta);
19891 diskusedPercent(p, total_meta*100.0/(double)storage);
19892 if( cnt==1 ){
19893 diskusedLine(p, "B-tree depth", "%lld\n", depth);
19894 if( int_cell>1 ){
19895 diskusedLine(p, "Average fanout", "%.1f\n",
19896 (double)(int_cell+int_pages)/(double)int_pages);
19897 }
19898 }
19899 if( nentry>0 ){
19900 diskusedLine(p, "Average payload per entry", "%.1f\n",
19901 (double)payload/(double)nentry);
19902 diskusedLine(p, "Average unused bytes per entry", "%.1f\n",
19903 (double)total_unused/(double)nentry);
19904 diskusedLine(p, "Average metadata per entry", "%.1f\n",
19905 (double)total_meta/(double)nentry);
19906 }
19907 diskusedLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19908 if( nentry>0 ){
19909 diskusedLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19910 diskusedPercent(p, ovfl_cnt*100.0/(double)nentry);
19911 }
19912 if( int_pages>0 ){
19913 diskusedLine(p, "Index pages used", "%lld\n", int_pages);
19914 }
19915 diskusedLine(p, "Primary pages used", "%lld\n", leaf_pages);
19916 if( ovfl_cnt ){
19917 diskusedLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19918 }
19919 diskusedLine(p, "Total pages used", "%lld\n", total_pages);
19920 if( int_pages>0 ){
19921 diskusedLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19922 }
19923 diskusedLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19924 if( ovfl_cnt ){
19925 diskusedLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19926 }
19927 diskusedLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19928 diskusedPercent(p, total_unused*100.0/(double)storage);
19929 }
19930 return diskusedStmtFinish(p, rc, pStmt);
19931 }
19932
19933 /*
19934 ** SQL Function: diskused(SCHEMA)
19935 **
19936 ** Analyze the database schema named in the argument. Return text
19937 ** containing the space utilization stats.
19938 */
19939 static void diskusedFunc(
19940 sqlite3_context *context,
19941 int argc,
19942 sqlite3_value **argv
19943 ){
19944 int rc;
@@ -19893,47 +19949,47 @@
19949 sqlite3_int64 nPage;
19950 sqlite3_int64 nPageInUse;
19951 sqlite3_int64 nFreeList;
19952 sqlite3_int64 nIndex;
19953 sqlite3_int64 nWORowid;
19954 DiskUsed s;
19955 sqlite3_uint64 r[2];
19956
19957 (void)argc;
19958 memset(&s, 0, sizeof(s));
19959 s.db = sqlite3_context_db_handle(context);
19960 s.context = context;
19961 s.pOut = sqlite3_str_new(0);
19962 if( sqlite3_str_errcode(s.pOut) ){
19963 diskusedError(&s, 0);
19964 return;
19965 }
19966 s.zSchema = (const char*)sqlite3_value_text(argv[0]);
19967 if( s.zSchema==0 ){
19968 s.zSchema = "main";
19969 }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19970 diskusedReset(&s);
19971 sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
19972 return;
19973 }
19974 ii = 0;
19975 rc = diskusedSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
19976 " WHERE name=%Q COLLATE nocase",s.zSchema);
19977 if( rc || ii==0 ){
19978 diskusedReset(&s);
19979 sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
19980 return;
19981 }
19982 sqlite3_randomness(sizeof(r), &r);
19983 s.zSU = sqlite3_mprintf("diskused%016llx%016llx", r[0], r[1]);
19984 if( s.zSU==0 ){ diskusedError(&s, 0); return; }
19985
19986 /* The s.zSU table contains the data used for the analysis.
19987 ** The table name contains 128-bits of randomness to avoid
19988 ** collisions with preexisting tables in temp.
19989 */
19990 rc = diskusedSql(&s,
19991 "CREATE TABLE temp.%s(\n"
19992 " name text, -- A table or index\n"
19993 " tblname text, -- Table that owns name\n"
19994 " is_index boolean, -- TRUE if it is an index\n"
19995 " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
@@ -19956,11 +20012,11 @@
20012 );
20013 if( rc ) return;
20014
20015 /* Populate the s.zSU table
20016 */
20017 rc = diskusedSql(&s,
20018 "WITH\n"
20019 " allidx(idxname) AS (\n"
20020 " SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
20021 " ),\n"
20022 " allobj(allname,tblname,isidx,isworowid) AS (\n"
@@ -20008,141 +20064,143 @@
20064 s.zSchema /* JOIN dbstat(%Q) */
20065 );
20066 if( rc ) return;
20067
20068 nPage = 0;
20069 rc = diskusedSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20070 if( rc ) return;
20071 if( nPage<=0 ){
20072 /* Very brief reply for an empty database */
20073 diskusedReset(&s);
20074 sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
20075 return;
20076 }
20077
20078 /* Begin generating the report */
20079 diskusedTitle(&s, "Database storage utilization report");
20080 pgsz = 0;
20081 rc = diskusedSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20082 if( rc ) return;
20083 diskusedLine(&s, "Page size in bytes","%lld\n",pgsz);
20084 diskusedLine(&s, "Pages in the database", "%lld\n", nPage);
20085
20086 nPageInUse = 0;
20087 rc = diskusedSqlInt(&s, &nPageInUse,
20088 "SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
20089 if( rc ) return;
20090 diskusedLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20091 diskusedPercent(&s, (nPageInUse*100.0)/(double)nPage);
20092
20093 nFreeList = 0;
20094 rc = diskusedSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20095 if( rc ) return;
20096 diskusedLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20097 diskusedPercent(&s, (nFreeList*100.0)/(double)nPage);
20098
20099 ii = 0;
20100 rc = diskusedSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20101 if( rc ) return;
20102 if( ii==0 || nPage<=1 ){
20103 ii = 0;
20104 }else{
20105 double rPtrsPerPage = pgsz/5;
20106 double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
20107 ii = (sqlite3_int64)ceil(rAvPage);
20108 }
20109 diskusedLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20110 diskusedPercent(&s, (ii*100.0)/(double)nPage);
20111
20112 ii = 0;
20113 rc = diskusedSqlInt(&s, &ii,
20114 "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
20115 s.zSchema);
20116 if( rc ) return;
20117 diskusedLine(&s, "Number of tables", "%lld\n", ii);
20118 nWORowid = 0;
20119 rc = diskusedSqlInt(&s, &nWORowid,
20120 "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
20121 s.zSchema);
20122 if( rc ) return;
20123 if( nWORowid>0 ){
20124 diskusedLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20125 diskusedLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
20126 }
20127 nIndex = 0;
20128 rc = diskusedSqlInt(&s, &nIndex,
20129 "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
20130 s.zSchema);
20131 if( rc ) return;
20132 diskusedLine(&s, "Number of indexes", "%lld\n", nIndex);
20133 ii = 0;
20134 rc = diskusedSqlInt(&s, &ii,
20135 "SELECT count(*) FROM \"%w\".sqlite_schema"
20136 " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
20137 s.zSchema);
20138 if( rc ) return;
20139 diskusedLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20140 diskusedLine(&s, "Number of implied indexes", "%lld\n", ii);
20141 diskusedLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20142 ii = 0;
20143 rc = diskusedSqlInt(&s, &ii,
20144 "SELECT sum(payload) FROM temp.%s"
20145 " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
20146 s.zSU);
20147 if( rc ) return;
20148 diskusedLine(&s, "Bytes of payload", "%-11lld ", ii);
20149 diskusedPercent(&s, ii*100.0/(double)(pgsz*nPage));
20150
20151 diskusedTitle(&s, "Page counts for all tables with their indexes");
20152 pStmt = diskusedPrepare(&s,
20153 "SELECT upper(tblname),\n"
20154 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20155 " FROM temp.%s\n"
20156 " WHERE tblname IS NOT NULL\n"
20157 " GROUP BY 1\n"
20158 " ORDER BY 2 DESC, 1;",
20159 s.zSU);
20160 if( pStmt==0 ) return;
20161 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20162 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20163 diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20164 diskusedPercent(&s, (nn*100.0)/(double)nPage);
20165 }
20166 if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20167
20168 diskusedTitle(&s, "Page counts for all tables and indexes separately");
20169 pStmt = diskusedPrepare(&s,
20170 "SELECT upper(name),\n"
20171 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20172 " FROM temp.%s\n"
20173 " WHERE name IS NOT NULL\n"
20174 " GROUP BY 1\n"
20175 " ORDER BY 2 DESC, 1;",
20176 s.zSU);
20177 if( pStmt==0 ) return;
20178 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20179 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20180 diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20181 diskusedPercent(&s, (nn*100.0)/(double)nPage);
20182 }
20183 if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20184
20185 rc = diskusedSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20186 if( rc ) return;
20187 rc = diskusedSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20188 if( rc ) return;
20189 if( nWORowid>0 ){
20190 rc = diskusedSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20191 pgsz, nPage);
20192 if( rc ) return;
20193 rc = diskusedSubreport(&s, "All rowid tables",
20194 "NOT is_without_rowid AND NOT is_index",
20195 pgsz, nPage);
20196 if( rc ) return;
20197 }
20198 rc = diskusedSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20199 if( rc ) return;
20200
20201 pStmt = diskusedPrepare(&s,
20202 "SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
20203 " GROUP BY 1 ORDER BY 1",
20204 s.zSU);
20205 if( pStmt==0 ) return;
20206 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
@@ -20150,37 +20208,37 @@
20208 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
20209 int nSubIndex = sqlite3_column_int(pStmt, 2);
20210 if( nSubIndex==0 ){
20211 char *zTitle = sqlite3_mprintf("Table %s", zUpper);
20212 char *zWhere = sqlite3_mprintf("name=%Q", zName);
20213 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20214 sqlite3_free(zTitle);
20215 sqlite3_free(zWhere);
20216 if( rc ) break;
20217 }else{
20218 sqlite3_stmt *pS2;
20219 char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
20220 char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20221 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20222 sqlite3_free(zTitle);
20223 sqlite3_free(zWhere);
20224 if( rc ) break;
20225 zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
20226 zWhere = sqlite3_mprintf("name=%Q", zName);
20227 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20228 sqlite3_free(zTitle);
20229 sqlite3_free(zWhere);
20230 if( rc ) break;
20231 if( nSubIndex>1 ){
20232 zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
20233 zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20234 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20235 sqlite3_free(zTitle);
20236 sqlite3_free(zWhere);
20237 if( rc ) break;
20238 }
20239 pS2 = diskusedPrepare(&s,
20240 "SELECT name, upper(name) FROM temp.%s"
20241 " WHERE is_index AND tblname=%Q",
20242 s.zSU, zName);
20243 if( pS2==0 ){
20244 rc = SQLITE_NOMEM;
@@ -20189,25 +20247,25 @@
20247 while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
20248 const char *zU = (const char*)sqlite3_column_text(pS2, 1);
20249 const char *zN = (const char*)sqlite3_column_text(pS2, 0);
20250 zTitle = sqlite3_mprintf("Index %s", zU);
20251 zWhere = sqlite3_mprintf("name=%Q", zN);
20252 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20253 sqlite3_free(zTitle);
20254 sqlite3_free(zWhere);
20255 if( rc ) break;
20256 }
20257 rc = diskusedStmtFinish(&s, rc, pS2);
20258 if( rc ) break;
20259 }
20260 }
20261 if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20262
20263 /* Append SQL statements that will recreate the raw data used for
20264 ** the analysis.
20265 */
20266 diskusedTitle(&s, "Raw data used to generate this report");
20267 sqlite3_str_appendf(s.pOut,
20268 "The following SQL will create a table named \"space_used\" which\n"
20269 "contains most of the information used to generate the report above.\n"
20270 "*/\n"
20271 );
@@ -20233,11 +20291,11 @@
20291 " ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
20292 " int_entries int -- B-tree entries on internal pages\n"/* 17 */
20293 ");\n"
20294 "INSERT INTO space_used VALUES\n"
20295 );
20296 pStmt = diskusedPrepare(&s,
20297 "SELECT quote(name), quote(tblname),\n" /* 0..1 */
20298 " is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
20299 " depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
20300 " int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
20301 " leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
@@ -20268,11 +20326,11 @@
20326 sqlite3_column_int64(pStmt, 15),
20327 sqlite3_column_int64(pStmt, 16),
20328 sqlite3_column_int64(pStmt, 17));
20329 }
20330 if( rc!=SQLITE_DONE ){
20331 diskusedError(&s, "SQL run-time error: %s\nSQL: %s",
20332 sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
20333 sqlite3_finalize(pStmt);
20334 return;
20335 }
20336 sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
@@ -20281,32 +20339,32 @@
20339 if( sqlite3_str_length(s.pOut) ){
20340 sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
20341 sqlite3_free);
20342 s.pOut = 0;
20343 }
20344 diskusedReset(&s);
20345 }
20346
20347
20348 #ifdef _WIN32
20349
20350 #endif
20351 int sqlite3_diskused_init(
20352 sqlite3 *db,
20353 char **pzErrMsg,
20354 const sqlite3_api_routines *pApi
20355 ){
20356 int rc = SQLITE_OK;
20357 SQLITE_EXTENSION_INIT2(pApi);
20358 (void)pzErrMsg; /* Unused parameter */
20359 rc = sqlite3_create_function(db, "diskused", 1,
20360 SQLITE_UTF8|SQLITE_INNOCUOUS,
20361 0, diskusedFunc, 0, 0);
20362 return rc;
20363 }
20364
20365 /************************* End ext/misc/diskused.c ********************/
20366
20367 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
20368 #define SQLITE_SHELL_HAVE_RECOVER 1
20369 #else
20370 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -25138,11 +25196,11 @@
25196 /*
25197 ** Return true if either the SQLITE_NO_COLOR compile-time option is used
25198 ** or if the NO_COLOR environment variable exists
25199 */
25200 static int shellNoColor(void){
25201 #if defined(SQLITE_NO_COLOR) || defined(SQLITE_SHELL_FIDDLE)
25202 return 1;
25203 #else
25204 return getenv("NO_COLOR")!=0;
25205 #endif
25206 }
@@ -25172,11 +25230,11 @@
25230 case 1:
25231 #if defined(SQLITE_PS1)
25232 return SQLITE_PS1;
25233 #else
25234 if( shellNoColor() ){
25235 return "/A-/v /f-> ";
25236 }else{
25237 return "/e[1;32m/A-/v /e[1;/x33/:36/;m/m/e[3m/;/f/;/e[0m-> ";
25238 }
25239 #endif
25240
@@ -25184,11 +25242,11 @@
25242 case 2:
25243 #if defined(SQLITE_PS2)
25244 return SQLITE_PS2;
25245 #else
25246 if( shellNoColor() ){
25247 return "/B/C-> ";
25248 }else{
25249 return "/B/e[1;/x33/:36/;m/C/e[0m-> ";
25250 }
25251 #endif
25252
@@ -25196,11 +25254,15 @@
25254 ** of cases 1 and 2 */
25255 case 3: return "SQLITE_PS1";
25256 case 4: return "SQLITE_PS2";
25257
25258 /* Name of the application */
25259 #ifndef SQLITE_CLI_APPNAME
25260 case 'A': return "SQLite";
25261 #else
25262 case 'A': return SHELL_STRINGIFY(SQLITE_CLI_APPNAME);
25263 #endif
25264
25265 /* Full version number of the application, including patch level */
25266 case 'V': return sqlite3_libversion();
25267
25268 /* Version number without the patch level */
@@ -26303,10 +26365,47 @@
26365 if( *az ){
26366 memcpy(*az, zNew, n+1 );
26367 }
26368 }
26369 }
26370
26371 /* Forward reference */
26372 static int pickStr(const char *zArg, char **pzErr, ...);
26373
26374 /*
26375 ** Change the limits on the display mode. Return 0 on
26376 ** success. Return non-zero if zArg is mis-formatted.
26377 **
26378 ** Valid arguments:
26379 **
26380 ** "on" Default limits
26381 ** "off" All limits turned off
26382 ** L,C Line and Characters limits set
26383 ** L,C,T Line, Character, and Title limits set
26384 **
26385 ** Anything else returns non-zero
26386 */
26387 static int modeSetLimit(ShellState *p, const char *zArg){
26388 int k = zArg==0 ? 1 : pickStr(zArg,0,"on","off","");
26389 if( k==0 ){
26390 p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
26391 p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
26392 p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
26393 }else if( k==1 ){
26394 p->mode.spec.nLineLimit = 0;
26395 p->mode.spec.nCharLimit = 0;
26396 p->mode.spec.nTitleLimit = 0;
26397 }else{
26398 int L, C, T = 0;
26399 int nNum = sscanf(zArg, "%d,%d,%d", &L, &C, &T);
26400 if( nNum<2 || L<0 || C<0 || T<0) return 1;
26401 p->mode.spec.nLineLimit = L;
26402 p->mode.spec.nCharLimit = C;
26403 if( nNum==3 ) p->mode.spec.nTitleLimit = T;
26404 }
26405 return 0;
26406 }
26407
26408 /*
26409 ** Change the mode to eMode
26410 */
26411 static void modeChange(ShellState *p, unsigned char eMode){
@@ -26340,10 +26439,11 @@
26439 modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
26440 }else if( eMode==MODE_BATCH ){
26441 u8 mFlags = p->mode.mFlags;
26442 modeFree(&p->mode);
26443 modeChange(p, MODE_List);
26444 modeSetLimit(p, "off");
26445 p->mode.mFlags = mFlags;
26446 }else if( eMode==MODE_TTY ){
26447 u8 mFlags = p->mode.mFlags;
26448 modeFree(&p->mode);
26449 modeChange(p, MODE_QBox);
@@ -26976,11 +27076,11 @@
27076 return SQLITE_OK;
27077 }
27078 #endif
27079
27080 /*
27081 ** Print a schema statement. This is a helper routine to dump_callback().
27082 **
27083 ** This routine converts some CREATE TABLE statements for shadow tables
27084 ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
27085 **
27086 ** If the schema statement in z[] contains a start-of-comment and if
@@ -28428,12 +28528,12 @@
28528 ".databases List names and files of attached databases",
28529 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
28530 #if SQLITE_SHELL_HAVE_RECOVER
28531 ".dbinfo ?DB? Show status information about the database",
28532 #endif
 
28533 ".dbtotxt Hex dump of the database file",
28534 ".diskused ?SCHEMA? Report database space and size stats",
28535 ".dump ?OBJECTS? Render database content as SQL",
28536 " Options:",
28537 " --data-only Output only INSERT statements",
28538 " --newlines Allow unescaped newline characters in output",
28539 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
@@ -28540,10 +28640,13 @@
28640 " --reset Reset the count for each input and interrupt",
28641 " --timeout S Halt after running for S seconds",
28642 #endif
28643 ".prompt MAIN CONTINUE Replace the standard prompts",
28644 " --hard-reset Unset SQLITE_PS1/2 and then --reset",
28645 #ifndef SQLITE_NO_COLOR
28646 " --no-color Disable color prompts. Use --color to re-enable",
28647 #endif
28648 " --reset Revert to default prompts",
28649 " --show Show the current prompt strings",
28650 " -- No more options. Subsequent args are prompts",
28651 #ifndef SQLITE_SHELL_FIDDLE
28652 ".quit Stop interpreting input stream, exit if primary.",
@@ -29440,11 +29543,11 @@
29543 sqlite3_base64_init(p->db, 0, 0);
29544 sqlite3_base85_init(p->db, 0, 0);
29545 sqlite3_regexp_init(p->db, 0, 0);
29546 sqlite3_ieee_init(p->db, 0, 0);
29547 sqlite3_series_init(p->db, 0, 0);
29548 sqlite3_diskused_init(p->db, 0, 0);
29549 #ifndef SQLITE_SHELL_FIDDLE
29550 sqlite3_fileio_init(p->db, 0, 0);
29551 sqlite3_completion_init(p->db, 0, 0);
29552 #endif
29553 #ifdef SQLITE_HAVE_ZLIB
@@ -31246,11 +31349,11 @@
31349 typedef struct ArCommand ArCommand;
31350 struct ArCommand {
31351 u8 eCmd; /* An AR_CMD_* value */
31352 u8 bVerbose; /* True if --verbose */
31353 u8 bZip; /* True if the archive is a ZIP */
31354 u8 bDryRun; /* 1 for --dry-run, 2 for --debug */
31355 u8 bAppend; /* True if --append */
31356 u8 bGlob; /* True if --glob */
31357 u8 fromCmdLine; /* Run from -A instead of .archive */
31358 int nArg; /* Number of command arguments */
31359 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
@@ -31308,10 +31411,11 @@
31411 #define AR_SWITCH_FILE 9
31412 #define AR_SWITCH_DIRECTORY 10
31413 #define AR_SWITCH_APPEND 11
31414 #define AR_SWITCH_DRYRUN 12
31415 #define AR_SWITCH_GLOB 13
31416 #define AR_SWITCH_DEBUG 14
31417
31418 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
31419 switch( eSwitch ){
31420 case AR_CMD_CREATE:
31421 case AR_CMD_EXTRACT:
@@ -31325,11 +31429,14 @@
31429 }
31430 pAr->eCmd = eSwitch;
31431 break;
31432
31433 case AR_SWITCH_DRYRUN:
31434 if( pAr->bDryRun<2 ) pAr->bDryRun = 1;
31435 break;
31436 case AR_SWITCH_DEBUG:
31437 pAr->bDryRun = 2;
31438 break;
31439 case AR_SWITCH_GLOB:
31440 pAr->bGlob = 1;
31441 break;
31442 case AR_SWITCH_VERBOSE:
@@ -31376,10 +31483,11 @@
31483 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
31484 { "file", 'f', AR_SWITCH_FILE, 1 },
31485 { "append", 'a', AR_SWITCH_APPEND, 1 },
31486 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
31487 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
31488 { "debug", 0, AR_SWITCH_DEBUG, 0 },
31489 { "glob", 'g', AR_SWITCH_GLOB, 0 },
31490 };
31491 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
31492 struct ArSwitch *pEnd = &aSwitch[nSwitch];
31493
@@ -31676,18 +31784,41 @@
31784
31785 /*
31786 ** Implementation of .ar "eXtract" command.
31787 */
31788 static int arExtractCommand(ArCommand *pAr){
31789 /* The zSql1[] string is a template for the query that does the
31790 ** extraction. Notes:
31791 **
31792 ** * $dir is the directory into which the archive is to be extracted
31793 ** * $pass is the integer pass number: 0, 1, or 2
31794 ** * The dest CTE is created so that realpath($dir) only needs
31795 ** to be called once.
31796 */
31797 const char *zSql1 =
31798 "WITH dest(dpath,dlen) AS (\n"
31799 #ifdef _WIN32
31800 " SELECT realpath($dir) || '\\',\n"
31801 #else
31802 " SELECT realpath($dir) || '/',\n"
31803 #endif
31804 " 1+length(realpath($dir))\n"
31805 ")\n"
31806 "SELECT\n"
31807 " ($dir || name),\n"
31808 " CASE $dryrun\n" /* vv--- azExtraArg */
31809 " WHEN 0 THEN writefile($dir||name, %s, mode, mtime)\n"
31810 " WHEN 1 THEN 0\n"
31811 " ELSE shell_putsnl(format('writefile(%%Q,%%s,%%0o,%%d)',"
31812 "$dir||name,quote(%s),mode,mtime)) IS NULL\n"
31813 " END\n" /* ^^--- azExtraArg */
31814 " FROM dest CROSS JOIN %s\n"
31815 " WHERE (%s)\n" /* ^^-- pAr->zSrcTable */
31816 /* ^^--- zWhere */
31817 " AND (CASE $pass WHEN 0 THEN (mode&0xf000)<>0xa000\n"
31818 " WHEN 1 THEN (mode&0xf000)=0xa000\n"
31819 " ELSE data IS NULL END)\n"
31820 " AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
31821 " AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
31822
31823 const char *azExtraArg[] = {
31824 "sqlar_uncompress(data, sz)",
@@ -31714,39 +31845,48 @@
31845 }
31846 if( zDir==0 ) rc = SQLITE_NOMEM;
31847 }
31848
31849 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
31850 azExtraArg[pAr->bZip],
31851 azExtraArg[pAr->bZip],
31852 pAr->zSrcTable,
31853 zWhere
31854 );
31855
31856 if( rc==SQLITE_OK ){
31857 j = sqlite3_bind_parameter_index(pSql, "$dir");
31858 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
31859 j = sqlite3_bind_parameter_index(pSql, "$dryrun");
31860 sqlite3_bind_int(pSql, j, pAr->bDryRun);
31861
31862 /* Run the SELECT statement twice
31863 ** (0) writefile() files and directories
31864 ** (1) writefile() symlinks
31865 ** (2) writefile() for directory again
31866 ** The third pass is so that the timestamps for extracted directories
31867 ** will be reset to the value in the archive, since populating them
31868 ** in the first pass will have changed the timestamp. */
31869 for(i=0; i<3; i++){
31870 if( pAr->bDryRun>=2 ){
31871 cli_printf(pAr->out, "*** BEGIN PASS %d ***\n", i+1);
31872 }
31873 j = sqlite3_bind_parameter_index(pSql, "$pass");
31874 sqlite3_bind_int(pSql, j, i);
31875 if( pAr->bDryRun && i==0 ){
31876 cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
 
31877 }
31878 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
31879 if( i==0 && pAr->bVerbose ){
31880 cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
31881 }
31882 }
31883 if( pAr->bDryRun==1 ) break;
31884 shellReset(&rc, pSql);
31885 if( pAr->bDryRun>=2 ){
31886 cli_printf(pAr->out, "*** END PASS %d ***\n", i+1);
31887 }
31888 }
31889 shellFinalize(&rc, pSql);
31890 }
31891
31892 sqlite3_free(zDir);
@@ -32257,11 +32397,11 @@
32397 ;
32398 static const char * const zCollectVar = "\
32399 SELECT\
32400 '('||x'0a'\
32401 || group_concat(\
32402 cname,\
32403 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
32404 ||')' AS ColsSpec \
32405 FROM (\
32406 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
32407 FROM ColNames ORDER BY cpos\
@@ -33102,30 +33242,14 @@
33242 }else if( optionMatch(z,"limits") ){
33243 if( (++i)>=nArg ){
33244 dotCmdError(p, i-1, "missing argument", 0);
33245 return 1;
33246 }
33247 if( modeSetLimit(p, azArg[i]) ){
33248 dotCmdError(p, i, "bad argument", "Should be \"on\" or \"off\" or "
33249 "\"L,C,T\" where L, C, and T are unsigned integers");
33250 return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33251 }
33252 chng = 1;
33253 }else if( optionMatch(z,"list") ){
33254 int ii;
33255 cli_puts("available modes:", p->out);
@@ -34339,11 +34463,16 @@
34463 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
34464 rc = shell_dbinfo_command(p, nArg, azArg);
34465 }else
34466 #endif /* SQLITE_SHELL_HAVE_RECOVER */
34467
34468 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34469 open_db(p, 0);
34470 rc = shell_dbtotxt_command(p, nArg, azArg);
34471 }else
34472
34473 if( c=='d' && n==8 && cli_strncmp(azArg[0], "diskused", n)==0 ){
34474 const char *zSchema = 0;
34475 int ii;
34476 char *zSql;
34477 open_db(p, 0);
34478 for(ii=1; ii<nArg; ii++){
@@ -34358,27 +34487,19 @@
34487 rc = 1;
34488 goto meta_command_exit;
34489 }
34490 zSchema = z;
34491 }
34492 zSql = sqlite3_mprintf("SELECT diskused(%Q)", zSchema);
34493 shell_check_oom(zSql);
34494 modePush(p);
34495 modeChange(p, MODE_BATCH);
 
 
 
34496 shell_exec(p, zSql, 0);
34497 modePop(p);
34498 sqlite3_free(zSql);
34499 }else
34500
 
 
 
 
 
34501 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
34502 char *zLike = 0;
34503 char *zSql;
34504 int i;
34505 int savedShellFlags = p->shellFlgs;
@@ -35491,10 +35612,26 @@
35612 }else
35613 if( strcmp(z,"-show")==0 ){
35614 cli_printf(stdout,"Main prompt: '%s'\n", prompt_string(p, 0));
35615 cli_printf(stdout,"Continuation: '%s'\n", prompt_string(p, 1));
35616 }else
35617 #ifndef SQLITE_NO_COLOR
35618 if( strcmp(z,"-color")==0 ){
35619 #ifdef _WIN32
35620 _putenv("NO_COLOR=");
35621 #else
35622 unsetenv("NO_COLOR");
35623 #endif
35624 }else
35625 if( strcmp(z,"-no-color")==0 ){
35626 #ifdef _WIN32
35627 _putenv("NO_COLOR=1");
35628 #else
35629 setenv("NO_COLOR","1",1);
35630 #endif
35631 }else
35632 #endif
35633 if( strcmp(z,"-")==0 ){
35634 noOpt = 1;
35635 }else
35636 {
35637 dotCmdError(p, i, "unknown option", 0);
@@ -35505,10 +35642,11 @@
35642 dotCmdError(p, i, "extra argument", 0);
35643 rc = 1;
35644 goto meta_command_exit;
35645 }else if( !p->dot.abQuot[i] && sqlite3_strglob("*[^a-z]*",z)!=0 ){
35646 dotCmdError(p, i, "use quotes around the prompt string", 0);
35647 rc = 1;
35648 }else{
35649 free(p->azPrompt[cnt]);
35650 p->azPrompt[cnt] = strdup(z);
35651 cnt++;
35652 }
@@ -37717,17 +37855,17 @@
37855 " -- treat no subsequent arguments as options\n"
37856 #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
37857 " -A ARGS... run \".archive ARGS\" and exit\n"
37858 #endif
37859 " -append append the database to the end of the file\n"
37860 " -ascii set '.mode ascii'\n"
37861 " -bail stop after hitting an error\n"
37862 " -batch force batch I/O\n"
37863 " -box set '.mode box'\n"
37864 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
37865 " -column set '.mode column'\n"
37866 " -csv set '.mode csv -limits off'\n"
37867 #if !defined(SQLITE_OMIT_DESERIALIZE)
37868 " -deserialize open the database using sqlite3_deserialize()\n"
37869 #endif
37870 " -echo print inputs before execution\n"
37871 " -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
@@ -37735,18 +37873,18 @@
37873 " -[no]header turn headers on or off\n"
37874 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
37875 " -heap SIZE Size of heap for memsys3 or memsys5\n"
37876 #endif
37877 " -help show this message\n"
37878 " -html set '.mode html'\n"
37879 " -ifexists only open if database already exists\n"
37880 " -interactive force interactive I/O\n"
37881 " -json set '.mode json'\n"
37882 " -line set '.mode line'\n"
37883 " -list set '.mode list'\n"
37884 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
37885 " -markdown set '.mode markdown'\n"
37886 #if !defined(SQLITE_OMIT_DESERIALIZE)
37887 " -maxsize N maximum size for a --deserialize database\n"
37888 #endif
37889 " -memtrace trace all memory allocations and deallocations\n"
37890 " -mmap N default mmap size set to N\n"
@@ -37759,21 +37897,21 @@
37897 " -nonce STRING set the safe-mode escape nonce\n"
37898 " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
37899 " -nullvalue TEXT set text string for NULL values. Default ''\n"
37900 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
37901 " -pcachetrace trace all page cache operations\n"
37902 " -quote set '.mode quote'\n"
37903 " -readonly open the database read-only\n"
37904 " -safe enable safe-mode\n"
37905 " -screenwidth N use N as the default screenwidth \n"
37906 " -separator SEP set output column separator. Default: '|'\n"
37907 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
37908 " -sorterref SIZE sorter references threshold size\n"
37909 #endif
37910 " -stats print memory stats before each finalize\n"
37911 " -table set '.mode table'\n"
37912 " -tabs set '.mode tabs'\n"
37913 " -unsafe-testing allow unsafe commands and modes for testing\n"
37914 " -version show SQLite version\n"
37915 " -vfs NAME use NAME as the default VFS\n"
37916 " -vfstrace enable tracing of all VFS calls\n"
37917 #ifdef SQLITE_HAVE_ZLIB
@@ -37801,10 +37939,23 @@
37939 sputz(stdout, "WARNING: attempt to configure SQLite after"
37940 " initialization.\n");
37941 }
37942 }
37943
37944 #if HAVE_EDITLINE
37945 /*
37946 ** https://sqlite.org/forum/forumpost/aad7a634916ff050:
37947 **
37948 ** Calling setlocale(LC_...,"") is required to get libedit to accept
37949 ** non-ASCII input.
37950 */
37951 #define DO_SET_LOCALE 1
37952 #include <locale.h>
37953 #else
37954 #define DO_SET_LOCALE 0
37955 #endif
37956
37957 /*
37958 ** Initialize the state information in data
37959 */
37960 static void main_init(ShellState *p) {
37961 memset(p, 0, sizeof(*p));
@@ -37825,10 +37976,14 @@
37976 #else
37977 /* No \001...\002 escapes required for linenoise or when not using a
37978 ** command-line editing library */
37979 p->bDelimitNonprint = 0;
37980 #endif
37981 #if DO_SET_LOCALE
37982 setlocale(LC_CTYPE,"");
37983 #endif
37984 #undef DO_SET_LOCALE
37985 }
37986
37987 /*
37988 ** Output text to the console in a font that attracts extra attention.
37989 */
@@ -37854,11 +38009,11 @@
38009 }
38010
38011 /*
38012 ** The callback from atexit().
38013 */
38014 static void SQLITE_CDECL abnormalExit(void){
38015 if( seenInterrupt ) eputz("Program interrupted.\n");
38016 if( globalShellState ){
38017 clearTempFile(globalShellState, 1, 1);
38018 }
38019 }
@@ -38065,11 +38220,11 @@
38220 stdin_is_interactive = 0;
38221 nCmd++;
38222 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
38223 shell_check_oom(azCmd);
38224 aiCmd = realloc(aiCmd, sizeof(aiCmd[0])*nCmd);
38225 shell_check_oom(aiCmd);
38226 azCmd[nCmd-1] = z;
38227 aiCmd[nCmd-1] = i;
38228 }
38229 continue;
38230 }
@@ -38354,10 +38509,11 @@
38509 modeChange(&data, MODE_Psql);
38510 }else if( cli_strcmp(z,"-box")==0 ){
38511 modeChange(&data, MODE_Box);
38512 }else if( cli_strcmp(z,"-csv")==0 ){
38513 modeChange(&data, MODE_Csv);
38514 modeSetLimit(&data, "off");
38515 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
38516 /* See similar code at tag-20250224-1 */
38517 const char *zEsc = argv[++i];
38518 int k;
38519 for(k=0; k<ArraySize(qrfEscNames); k++){
@@ -38412,12 +38568,14 @@
38568 }else if( cli_strcmp(z,"-nullvalue")==0 ){
38569 modeSetStr(&data.mode.spec.zNull,
38570 cmdline_option_value(argc,argv,++i));
38571 }else if( cli_strcmp(z,"-header")==0 ){
38572 data.mode.spec.bTitles = QRF_Yes;
38573 data.mode.mFlags |= MFLG_HDR;
38574 }else if( cli_strcmp(z,"-noheader")==0 ){
38575 data.mode.spec.bTitles = QRF_No;
38576 data.mode.mFlags |= MFLG_HDR;
38577 }else if( cli_strcmp(z,"-echo")==0 ){
38578 data.mode.mFlags |= MFLG_ECHO;
38579 }else if( cli_strcmp(z,"-eqp")==0 ){
38580 data.mode.autoEQP = AUTOEQP_on;
38581 }else if( cli_strcmp(z,"-eqpfull")==0 ){
38582
+1551 -532
--- 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
-** 7e4134e3ff1ca8712f5fc78fadae66554945 with changes in files:
21
+** 3f3fb9b638f59ad982beafb7c117f24ddd3d 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-05-04 10:14:13 7e4134e3ff1ca8712f5fc78fadae665549450988dc43af27c7fe0c77f10ce3fb"
472
+#define SQLITE_SOURCE_ID "2026-06-16 13:43:08 3f3fb9b638f59ad982beafb7c117f24ddd3da612e62c862510805fa672ffae06"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2026-05-04T10:14:13.819Z"
475
+#define SQLITE_SCM_DATETIME "2026-06-16T13:43:08.110Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -4373,12 +4373,11 @@
43734373
** parameter on F or if the value of P does not match any of the
43744374
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
43754375
**
43764376
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
43774377
** 64-bit signed integer and returns that integer, or D if P does not
4378
-** exist. If the value of P is something other than an integer, then
4379
-** zero is returned.
4378
+** exist or ff the value of P is something other than an integer.
43804379
**
43814380
** The sqlite3_uri_key(F,N) returns a pointer to the name (not
43824381
** the value) of the N-th query parameter for filename F, or a NULL
43834382
** pointer if N is less than zero or greater than the number of query
43844383
** parameters minus 1. The N value is zero-based so N should be 0 to obtain
@@ -4697,11 +4696,12 @@
46974696
** <dd>The maximum number of columns in a table definition or in the
46984697
** result set of a [SELECT] or the maximum number of columns in an index
46994698
** or in an ORDER BY or GROUP BY clause.</dd>)^
47004699
**
47014700
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
4702
-** <dd>The maximum depth of the parse tree on any expression.</dd>)^
4701
+** <dd>The maximum depth of the parse tree on any expression and
4702
+** the maximum nesting depth for subqueries and VIEWs</dd>)^
47034703
**
47044704
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt>
47054705
** <dd>The maximum depth of the LALR(1) parser stack used to analyze
47064706
** input SQL statements.</dd>)^
47074707
**
@@ -4728,11 +4728,12 @@
47284728
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
47294729
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
47304730
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
47314731
**
47324732
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
4733
-** <dd>The maximum depth of recursion for triggers.</dd>)^
4733
+** <dd>The maximum depth of recursion for triggers, and the maximum
4734
+** nesting depth for separate triggers.</dd>)^
47344735
**
47354736
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
47364737
** <dd>The maximum number of auxiliary worker threads that a single
47374738
** [prepared statement] may start.</dd>)^
47384739
** </dl>
@@ -11534,12 +11535,23 @@
1153411535
** reopen S as an in-memory database based on the serialization
1153511536
** contained in P. If S is a NULL pointer, the main database is
1153611537
** used. The serialized database P is N bytes in size. M is the size
1153711538
** of the buffer P, which might be larger than N. If M is larger than
1153811539
** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
11539
-** SQLite is permitted to add content to the in-memory database as
11540
-** long as the total size does not exceed M bytes.
11540
+** SQLite is permitted to add content to the in-memory database, in
11541
+** page-sized chunks, as long as the total size does not exceed M bytes.
11542
+**
11543
+** The parameter M must be greater than or equal to N. Ideally, M
11544
+** should have a value which is N+(512&times;K)+20 where K determines how
11545
+** must extra space is available to hold new content as the database
11546
+** grows. K can be 0 if the database is read-only.
11547
+**
11548
+** If the database content in P is malformed in a malicious way then
11549
+** it is possible that SQLite might try to read a few more than N bytes
11550
+** from P. If the veracity of the database content P is uncertain,
11551
+** then applications are advised to allocate about 20 extra bytes on
11552
+** the end of the P buffer to avoid a memory error.
1154111553
**
1154211554
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
1154311555
** invoke sqlite3_free() on the serialization buffer when the database
1154411556
** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
1154511557
** SQLite will try to increase the buffer size using sqlite3_realloc64()
@@ -13184,15 +13196,27 @@
1318413196
** <dt>SQLITE_CHANGESETAPPLY_FKNOACTION <dd>
1318513197
** If this flag it set, then all foreign key constraints in the target
1318613198
** database behave as if they were declared with "ON UPDATE NO ACTION ON
1318713199
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
1318813200
** or SET DEFAULT.
13201
+**
13202
+** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
13203
+** Sometimes, a changeset contains two or more update statements such that
13204
+** although after applying all updates the database will contain no
13205
+** constraint violations, no single update can be applied before the others.
13206
+** The simplest example of this is a pair of UPDATEs that have "swapped"
13207
+** two column values with a UNIQUE constraint.
13208
+** <p>
13209
+** Usually, sqlite3changeset_apply() and similar functions work hard to try
13210
+** to find a way to apply such a changeset. However, if this flag is set,
13211
+** then all such updates are considered CONSTRAINT conflicts.
1318913212
*/
1319013213
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
1319113214
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
1319213215
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
1319313216
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
13217
+#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
1319413218
1319513219
/*
1319613220
** CAPI3REF: Constants Passed To The Conflict Handler
1319713221
**
1319813222
** Values that may be passed as the second argument to a conflict-handler.
@@ -15798,10 +15822,17 @@
1579815822
*/
1579915823
#ifndef offsetof
1580015824
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
1580115825
#endif
1580215826
15827
+/*
15828
+** sizeof64() is like sizeof(), but always returns a 64-bit value, even
15829
+** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit
15830
+** arithmetic is used consistently in both 32-bit and 64-bit builds.
15831
+*/
15832
+#define sizeof64(X) ((sqlite3_int64)sizeof(X))
15833
+
1580315834
/*
1580415835
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
1580515836
** to avoid complaints from -fsanitize=strict-bounds.
1580615837
*/
1580715838
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
@@ -18705,11 +18736,11 @@
1870518736
int aLimit[SQLITE_N_LIMIT]; /* Limits */
1870618737
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
1870718738
struct sqlite3InitInfo { /* Information used during initialization */
1870818739
Pgno newTnum; /* Rootpage of table being initialized */
1870918740
u8 iDb; /* Which db file is being initialized */
18710
- u8 busy; /* TRUE if currently initializing */
18741
+ u8 busy; /* TRUE if initing. 2 if due to ADD COLUMN */
1871118742
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
1871218743
unsigned imposterTable : 2; /* Building an imposter table */
1871318744
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
1871418745
const char **azInit; /* "type", "name", and "tbl_name" columns */
1871518746
} init;
@@ -20917,10 +20948,11 @@
2091720948
int nTab; /* Number of previously allocated VDBE cursors */
2091820949
int nMem; /* Number of memory cells used so far */
2091920950
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
2092020951
int iSelfTab; /* Table associated with an index on expr, or negative
2092120952
** of the base register during check-constraint eval */
20953
+ int nNestSel; /* Number of nested SELECT statements and/or VIEWs */
2092220954
int nLabel; /* The *negative* of the number of labels used */
2092320955
int nLabelAlloc; /* Number of slots in aLabel */
2092420956
int *aLabel; /* Space to hold the labels */
2092520957
ExprList *pConstExpr;/* Constant expressions */
2092620958
IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
@@ -21256,11 +21288,11 @@
2125621288
*/
2125721289
#define INITFLAG_AlterMask 0x0007 /* Types of ALTER */
2125821290
#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
2125921291
#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
2126021292
#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */
21261
-#define INITFLAG_AlterDropCons 0x0004 /* Reparse after an ADD COLUMN */
21293
+#define INITFLAG_AlterDropCons 0x0004 /* Reparse after a DROP CONSTRAINT */
2126221294
2126321295
/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
2126421296
** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
2126521297
** parameters are for temporary use during development, to help find
2126621298
** optimal values for parameters in the query planner. The should not
@@ -22509,11 +22541,19 @@
2250922541
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
2251022542
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
2251122543
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
2251222544
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
2251322545
SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
22514
-SQLITE_PRIVATE void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
22546
+SQLITE_PRIVATE void sqlite3AlterAddConstraint(
22547
+ Parse *pParse, /* Parse context */
22548
+ SrcList *pSrc, /* Table to add constraint to */
22549
+ Token *pFirst, /* First token of new constraint */
22550
+ Token *pName, /* Name of new constraint. NULL if name omitted. */
22551
+ const char *zExpr, /* Text of CHECK expression */
22552
+ int nExpr, /* Size of pExpr in bytes */
22553
+ Expr *pExpr /* The parsed CHECK expression */
22554
+);
2251522555
SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
2251622556
SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
2251722557
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
2251822558
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
2251922559
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int);
@@ -32413,12 +32453,14 @@
3241332453
#define etSRCITEM 12 /* a pointer to a SrcItem */
3241432454
#define etPOINTER 13 /* The %p conversion */
3241532455
#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */
3241632456
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
3241732457
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
32458
+#define etESCAPE_j 17 /* %j -> JSON string literal w/o "..." */
32459
+#define etESCAPE_J 18 /* %J -> JSON string literal with "..." */
3241832460
32419
-#define etINVALID 17 /* Any unrecognized conversion type */
32461
+#define etINVALID 19 /* Any unrecognized conversion type */
3242032462
3242132463
3242232464
/*
3242332465
** An "etByte" is an 8-bit unsigned value.
3242432466
*/
@@ -32444,24 +32486,24 @@
3244432486
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
3244532487
#define FLAG_STRING 4 /* Allow infinite precision */
3244632488
3244732489
/*
3244832490
** The table is searched by hash. In the case of %C where C is the character
32449
-** and that character has ASCII value j, then the hash is j%23.
32491
+** and that character has ASCII value j, then the hash is j%25.
3245032492
**
3245132493
** The order of the entries in fmtinfo[] and the hash chain was entered
3245232494
** manually, but based on the output of the following TCL script:
3245332495
*/
3245432496
#if 0 /***** Beginning of script ******/
32455
-foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {
32497
+foreach c {d s g z q Q w c o u x X f e E G i n % p T S r J j} {
3245632498
scan $c %c x
3245732499
set n($c) $x
3245832500
}
3245932501
set mx [llength [array names n]]
3246032502
puts "count: $mx"
3246132503
32462
-set mx 27
32504
+set mx 25
3246332505
puts "*********** mx=$mx ************"
3246432506
for {set r 0} {$r<$mx} {incr r} {
3246532507
puts -nonewline [format %2d: $r]
3246632508
foreach c [array names n] {
3246732509
if {($n($c))%$mx==$r} {puts -nonewline " $c"}
@@ -32469,35 +32511,38 @@
3246932511
puts ""
3247032512
}
3247132513
#endif /***** End of script ********/
3247232514
3247332515
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
32516
+static const char aHex[] = "0123456789abcdef";
3247432517
static const char aPrefix[] = "-x0\000X0";
32475
-static const et_info fmtinfo[23] = {
32476
- /* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 },
32477
- /* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 */
32478
- /* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 },
32479
- /* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 */
32480
- /* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 },
32481
- /* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
32482
- /* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 */
32483
- /* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 },
32484
- /* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
32485
- /* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
32486
- /* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
32487
- /* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
32488
- /* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 },
32489
- /* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
32490
- /* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 },
32491
- /* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
32492
- /* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 */
32493
- /* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 */
32494
- /* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
32495
- /* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 },
32496
- /* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 },
32497
- /* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 },
32498
- /* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 }
32518
+static const et_info fmtinfo[25] = {
32519
+ /* 0 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
32520
+ /* 1 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
32521
+ /* 2 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
32522
+ /* 3 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
32523
+ /* 4 */ { 'j', 0, 0, etESCAPE_j, 0, 0, 0 }, /* Hash: 6 */
32524
+ /* 5 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
32525
+ /* 6 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 4 },
32526
+ /* 7 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 }, /* Hash: 12 */
32527
+ /* 8 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 },
32528
+ /* 9 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
32529
+ /* 10 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
32530
+ /* 11 */ { 'o', 8, 0, etRADIX, 0, 2, 0 },
32531
+ /* 12 */ { '%', 0, 0, etPERCENT, 0, 0, 7 },
32532
+ /* 13 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 16 },
32533
+ /* 14 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 },
32534
+ /* 15 */ { 's', 0, 4, etSTRING, 0, 0, 0 },
32535
+ /* 16 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 13 */
32536
+ /* 17 */ { 'u', 10, 0, etDECIMAL, 0, 0, 0 },
32537
+ /* 18 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 }, /* Hash: 19 */
32538
+ /* 19 */ { 'E', 0, 1, etEXP, 14, 0, 18 },
32539
+ /* 20 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
32540
+ /* 21 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 },
32541
+ /* 22 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 0 },
32542
+ /* 23 */ { 'J', 0, 0, etESCAPE_J, 0, 0, 0 }, /* Hash: 24 */
32543
+ /* 24 */ { 'c', 0, 0, etCHARX, 0, 0, 23 }
3249932544
};
3250032545
3250132546
/* Additional Notes:
3250232547
**
3250332548
** %S Takes a pointer to SrcItem. Shows name or database.name
@@ -32754,12 +32799,12 @@
3275432799
break;
3275532800
}
3275632801
}
3275732802
#else
3275832803
/* Fast hash-table lookup */
32759
- assert( ArraySize(fmtinfo)==23 );
32760
- idx = ((unsigned)c) % 23;
32804
+ assert( ArraySize(fmtinfo)==25 );
32805
+ idx = ((unsigned)c) % 25;
3276132806
if( fmtinfo[idx].fmttype==c
3276232807
|| fmtinfo[idx = fmtinfo[idx].iNxt].fmttype==c
3276332808
){
3276432809
infop = &fmtinfo[idx];
3276532810
xtype = infop->type;
@@ -33126,11 +33171,11 @@
3312633171
length = width;
3312733172
}
3312833173
3312933174
if( zExtra==0 ){
3313033175
/* The result is being rendered directory into pAccum. This
33131
- ** is the command and fast case */
33176
+ ** is the common and fast case */
3313233177
pAccum->nChar += length;
3313333178
zOut[length] = 0;
3313433179
continue;
3313533180
}else{
3313633181
/* We were unable to render directly into pAccum because we
@@ -33246,10 +33291,87 @@
3324633291
/* Adjust width to account for extra bytes in UTF-8 characters */
3324733292
int ii = length - 1;
3324833293
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
3324933294
}
3325033295
break;
33296
+ case etESCAPE_j: /* %j: JSON string literal w/o "..." */
33297
+ case etESCAPE_J: { /* %J: Generate a JSON string literal */
33298
+ char *escarg;
33299
+ i64 i, j, px, iStart;
33300
+ unsigned char ch;
33301
+
33302
+ if( bArgList ){
33303
+ escarg = getTextArg(pArgList);
33304
+ }else{
33305
+ escarg = va_arg(ap,char*);
33306
+ }
33307
+ iStart = sqlite3_str_length(pAccum);
33308
+ if( escarg==0 ){
33309
+ if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "null", 4);
33310
+ }else{
33311
+ if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1);
33312
+ px = precision;
33313
+ testcase( px==0 );
33314
+ if( px<0 ){
33315
+ px = 0x7fffffff;
33316
+ }else if( flag_altform2 ){
33317
+ /* Convert precision from code-points to bytes */
33318
+ for(i=0; i<px && escarg[i]; i++){
33319
+ if( (escarg[i]&0xc0)==0x80 ) px++;
33320
+ }
33321
+ if( i==px ){
33322
+ while( (escarg[px]&0xc0)==0x80 ) px++;
33323
+ }
33324
+ }
33325
+ for(i=j=0; i<px; i++){
33326
+ if( (ch = ((u8*)escarg)[i])<=0x1f || ch=='"' || ch=='\\' ){
33327
+ if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j);
33328
+ j = i+1;
33329
+ if( ch==0 ) break;
33330
+ sqlite3_str_appendchar(pAccum, 1, '\\');
33331
+ if( ch>0x1f ){
33332
+ sqlite3_str_appendchar(pAccum, 1, ch);
33333
+ }else if( ((1u<<ch)&0x3700)!=0 ){
33334
+ ch = "btn?fr"[ch-8];
33335
+ sqlite3_str_appendchar(pAccum, 1, ch);
33336
+ }else{
33337
+ sqlite3_str_append(pAccum, "u00", 3);
33338
+ sqlite3_str_appendchar(pAccum, 1, aHex[ch>>4]);
33339
+ sqlite3_str_appendchar(pAccum, 1, aHex[ch&0xf]);
33340
+ }
33341
+ }
33342
+ }
33343
+ if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j);
33344
+ if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1);
33345
+ }
33346
+ if( width>0 && sqlite3_str_errcode(pAccum)==SQLITE_OK ){
33347
+ sqlite3_int64 n = sqlite3_str_length(pAccum) - iStart;
33348
+ sqlite3_int64 len = n;
33349
+ char *zz;
33350
+ if( flag_altform2 && n>0 ){
33351
+ zz = sqlite3_str_value(pAccum);
33352
+ for(i=iStart; zz[i]; i++){
33353
+ if( (zz[i]&0xc0)==0x80 ) len--;
33354
+ }
33355
+ }
33356
+ if( width>len ){
33357
+ sqlite3_int64 sp = width-len;
33358
+ assert( sp>0 && sp<0x7fffffff );
33359
+ sqlite3_str_appendchar(pAccum, (int)sp, ' ');
33360
+ if( !flag_leftjustify
33361
+ && n>0
33362
+ && sqlite3_str_errcode(pAccum)==0
33363
+ ){
33364
+ zz = sqlite3_str_value(pAccum);
33365
+ zz += iStart;
33366
+ memmove(zz+sp, zz, n);
33367
+ memset(zz, ' ', sp);
33368
+ }
33369
+ }
33370
+ }
33371
+ continue;
33372
+ }
3325133373
case etESCAPE_q: /* %q: Escape ' characters */
3325233374
case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
3325333375
case etESCAPE_w: { /* %w: Escape " characters */
3325433376
i64 i, j, k, n;
3325533377
int needQuote = 0;
@@ -33288,12 +33410,12 @@
3328833410
if( flag_alternateform ){
3328933411
/* For %#q, do unistr()-style backslash escapes for
3329033412
** all control characters, and for backslash itself.
3329133413
** For %#Q, do the same but only if there is at least
3329233414
** one control character. */
33293
- u32 nBack = 0;
33294
- u32 nCtrl = 0;
33415
+ i64 nBack = 0;
33416
+ i64 nCtrl = 0;
3329533417
for(k=0; k<i; k++){
3329633418
if( escarg[k]=='\\' ){
3329733419
nBack++;
3329833420
}else if( ((u8*)escarg)[k]<=0x1f ){
3329933421
nCtrl++;
@@ -33337,11 +33459,11 @@
3333733459
bufpt[j-1] = '\\';
3333833460
bufpt[j++] = 'u';
3333933461
bufpt[j++] = '0';
3334033462
bufpt[j++] = '0';
3334133463
bufpt[j++] = ch>=0x10 ? '1' : '0';
33342
- bufpt[j++] = "0123456789abcdef"[ch&0xf];
33464
+ bufpt[j++] = aHex[ch&0xf];
3334333465
}
3334433466
}
3334533467
}else{
3334633468
for(i=0; i<k; i++){
3334733469
bufpt[j++] = ch = escarg[i];
@@ -39154,10 +39276,26 @@
3915439276
******************************************************************************
3915539277
**
3915639278
** This file contains an experimental VFS layer that operates on a
3915739279
** Key/Value storage engine where both keys and values must be pure
3915839280
** text.
39281
+**
39282
+** DEBUG AND TEST
39283
+**
39284
+** For testing on Unix, compile using:
39285
+**
39286
+** make clean sqlite3d CFLAGS='-DSQLITE_OS_KV_OPTIONAL'
39287
+**
39288
+** Then start up a shell using something like:
39289
+**
39290
+** ./sqlite3d 'file:dbname?vfs=kvvfs'
39291
+**
39292
+** Each K/V entry is stored in a separate file in the working
39293
+** directory that has a name like "kvvfs-dbname-*". Due to limitations
39294
+** on the key size, the name of the database must be very short - just
39295
+** a few characters. If the database name is too long, the VFS will
39296
+** malfunction and you will get SQLITE_CORRUPT errors.
3915939297
*/
3916039298
/* #include <sqliteInt.h> */
3916139299
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
3916239300
3916339301
/*****************************************************************************
@@ -39606,16 +39744,18 @@
3960639744
}
3960739745
if( j+n>nOut ) return -1;
3960839746
memset(&aOut[j], 0, n);
3960939747
j += n;
3961039748
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
39611
- }else{
39749
+ }else if( j<nOut ){
3961239750
aOut[j] = c<<4;
3961339751
c = kvvfsHexValue[aIn[++i]];
3961439752
if( c<0 ) return -1 /* hex bytes are always in pairs */;
3961539753
aOut[j++] += c;
3961639754
i++;
39755
+ }else{
39756
+ return -1;
3961739757
}
3961839758
}
3961939759
return j;
3962039760
}
3962139761
@@ -40037,10 +40177,22 @@
4003740177
}else{
4003840178
pFile->isJournal = 0;
4003940179
pFile->base.pMethods = &kvvfs_db_io_methods;
4004040180
}
4004140181
if( !pFile->zClass ){
40182
+#ifdef SQLITE_WASM
40183
+ if( strlen(zName) >= (KVRECORD_KEY_SZ
40184
+ - 6 /* "kvvfs-" */
40185
+ - 11 /* "-##########" */) ){
40186
+ return SQLITE_CANTOPEN;
40187
+ }
40188
+#else
40189
+ if( 0!=strcmp(zName, "local") && 0!=strcmp(zName, "session") ){
40190
+ /* Historical naming restriction which journaling depends on. */
40191
+ return SQLITE_CANTOPEN;
40192
+ }
40193
+#endif
4004240194
pFile->zClass = zName;
4004340195
}
4004440196
pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
4004540197
if( pFile->aData==0 ){
4004640198
return SQLITE_NOMEM;
@@ -45345,13 +45497,13 @@
4534545497
4534645498
/* Minimum number of regions required to be mapped. */
4534745499
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
4534845500
4534945501
if( pShmNode->nRegion<nReqRegion ){
45350
- char **apNew; /* New apRegion[] array */
45351
- int nByte = nReqRegion*szRegion; /* Minimum required file size */
45352
- struct stat sStat; /* Used by fstat() */
45502
+ char **apNew; /* New apRegion[] array */
45503
+ i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
45504
+ struct stat sStat; /* Used by fstat() */
4535345505
4535445506
pShmNode->szRegion = szRegion;
4535545507
4535645508
if( pShmNode->hShm>=0 ){
4535745509
/* The requested region is not mapped into this processes address space.
@@ -45378,11 +45530,11 @@
4537845530
** pages forces the OS to allocate them immediately, which reduces
4537945531
** the chances of SIGBUS while accessing the mapped region later on.
4538045532
*/
4538145533
else{
4538245534
static const int pgsz = 4096;
45383
- int iPg;
45535
+ i64 iPg;
4538445536
4538545537
/* Write to the last byte of each newly allocated or extended page */
4538645538
assert( (nByte % pgsz)==0 );
4538745539
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
4538845540
int x = 0;
@@ -45404,12 +45556,12 @@
4540445556
rc = SQLITE_IOERR_NOMEM_BKPT;
4540545557
goto shmpage_out;
4540645558
}
4540745559
pShmNode->apRegion = apNew;
4540845560
while( pShmNode->nRegion<nReqRegion ){
45409
- int nMap = szRegion*nShmPerMap;
45410
- int i;
45561
+ i64 nMap = (i64)szRegion*(i64)nShmPerMap;
45562
+ i64 i;
4541145563
void *pMem;
4541245564
if( pShmNode->hShm>=0 ){
4541345565
pMem = osMmap(0, nMap,
4541445566
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
4541545567
MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
@@ -49195,107 +49347,154 @@
4919549347
4919649348
{ "CreateFileW", (SYSCALL)CreateFileW, 0 },
4919749349
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
4919849350
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[2].pCurrent)
4919949351
49352
+#if defined(SQLITE_UWP)
49353
+ { "CreateFileMappingFromApp",(SYSCALL)CreateFileMappingFromApp,0 },
49354
+#else
49355
+ { "CreateFileMappingFromApp",(SYSCALL)0, 0 },
49356
+#endif
49357
+#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE,\
49358
+ PSECURITY_ATTRIBUTES, \
49359
+ ULONG,ULONG64,PCWSTR))aSyscall[3].pCurrent)
49360
+
49361
+#if !defined(SQLITE_UWP)
4920049362
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
49363
+#else
49364
+ { "CreateFileMappingW", (SYSCALL)0, 0 },
49365
+#endif
4920149366
#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
49202
- DWORD,DWORD,DWORD,LPCWSTR))aSyscall[3].pCurrent)
49367
+ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[4].pCurrent)
4920349368
4920449369
{ "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
49205
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[4].pCurrent)
49370
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[5].pCurrent)
4920649371
4920749372
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
49208
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[5].pCurrent)
49373
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[6].pCurrent)
4920949374
4921049375
{ "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
4921149376
#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
49212
- DWORD,va_list*))aSyscall[6].pCurrent)
49377
+ DWORD,va_list*))aSyscall[7].pCurrent)
4921349378
49214
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
49379
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_UWP)
4921549380
{ "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
4921649381
#else
4921749382
{ "FreeLibrary", (SYSCALL)0, 0 },
4921849383
#endif
4921949384
49220
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[7].pCurrent)
49385
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[8].pCurrent)
4922149386
4922249387
{ "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
49223
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[8].pCurrent)
49388
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[9].pCurrent)
4922449389
4922549390
{ "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
49226
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[9].pCurrent)
49391
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
4922749392
4922849393
{ "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
4922949394
#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
49230
- LPVOID))aSyscall[10].pCurrent)
49395
+ LPVOID))aSyscall[11].pCurrent)
4923149396
49232
- { "GetFileSize", (SYSCALL)GetFileSize, 0 },
49233
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[11].pCurrent)
49397
+ { "GetFileSizeEx", (SYSCALL)GetFileSizeEx, 0 },
49398
+#define osGetFileSizeEx ((BOOL(WINAPI*)(HANDLE, \
49399
+ PLARGE_INTEGER))aSyscall[12].pCurrent)
4923449400
4923549401
{ "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
4923649402
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
49237
- LPWSTR*))aSyscall[12].pCurrent)
49403
+ LPWSTR*))aSyscall[13].pCurrent)
4923849404
4923949405
{ "GetLastError", (SYSCALL)GetLastError, 0 },
49240
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[13].pCurrent)
49406
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[14].pCurrent)
4924149407
49242
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
49408
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_UWP)
4924349409
{ "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
4924449410
#else
4924549411
{ "GetProcAddressA", (SYSCALL)0, 0 },
4924649412
#endif
4924749413
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
49248
- LPCSTR))aSyscall[14].pCurrent)
49414
+ LPCSTR))aSyscall[15].pCurrent)
4924949415
4925049416
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
49251
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[15].pCurrent)
49252
-
49253
- { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
49254
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[16].pCurrent)
49417
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[16].pCurrent)
4925549418
4925649419
{ "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
4925749420
#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
4925849421
LPFILETIME))aSyscall[17].pCurrent)
4925949422
49423
+#ifdef SQLITE_UWP
49424
+ { "GetTempPathW", (SYSCALL)0, 0 },
49425
+#else
4926049426
{ "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
49427
+#endif
4926149428
#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[18].pCurrent)
4926249429
49263
- { "GetTickCount", (SYSCALL)GetTickCount, 0 },
49264
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[19].pCurrent)
49430
+ { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
49431
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[19].pCurrent)
4926549432
49433
+#ifdef SQLITE_UWP
49434
+ { "HeapAlloc", (SYSCALL)0, 0 },
49435
+#else
4926649436
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
49437
+#endif
4926749438
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
4926849439
SIZE_T))aSyscall[20].pCurrent)
4926949440
49441
+#ifdef SQLITE_UWP
49442
+ { "HeapCreate", (SYSCALL)0, 0 },
49443
+#else
4927049444
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
49445
+#endif
4927149446
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
4927249447
SIZE_T))aSyscall[21].pCurrent)
4927349448
49449
+#ifdef SQLITE_UWP
49450
+ { "HeapDestroy", (SYSCALL)0, 0 },
49451
+#else
4927449452
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
49453
+#endif
4927549454
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[22].pCurrent)
4927649455
49456
+#ifdef SQLITE_UWP
49457
+ { "HeapFree", (SYSCALL)0, 0 },
49458
+#else
4927749459
{ "HeapFree", (SYSCALL)HeapFree, 0 },
49460
+#endif
4927849461
#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[23].pCurrent)
4927949462
49463
+#ifdef SQLITE_UWP
49464
+ { "HeapReAlloc", (SYSCALL)0, 0 },
49465
+#else
4928049466
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
49467
+#endif
4928149468
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
4928249469
SIZE_T))aSyscall[24].pCurrent)
4928349470
49471
+#ifdef SQLITE_UWP
49472
+ { "HeapSize", (SYSCALL)0, 0 },
49473
+#else
4928449474
{ "HeapSize", (SYSCALL)HeapSize, 0 },
49475
+#endif
4928549476
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
4928649477
LPCVOID))aSyscall[25].pCurrent)
4928749478
49479
+#ifdef SQLITE_UWP
49480
+ { "HeapValidate", (SYSCALL)0, 0 },
49481
+#else
4928849482
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
49483
+#endif
4928949484
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
4929049485
LPCVOID))aSyscall[26].pCurrent)
4929149486
49487
+#ifdef SQLITE_UWP
49488
+ { "HeapCompact", (SYSCALL)0, 0 },
49489
+#else
4929249490
{ "HeapCompact", (SYSCALL)HeapCompact, 0 },
49491
+#endif
4929349492
#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[27].pCurrent)
4929449493
4929549494
49296
-#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
49495
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_UWP)
4929749496
{ "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
4929849497
#else
4929949498
{ "LoadLibraryW", (SYSCALL)0, 0 },
4930049499
#endif
4930149500
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[28].pCurrent)
@@ -49305,72 +49504,82 @@
4930549504
4930649505
{ "LockFileEx", (SYSCALL)LockFileEx, 0 },
4930749506
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
4930849507
LPOVERLAPPED))aSyscall[30].pCurrent)
4930949508
49310
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
49509
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
49510
+ && !defined(SQLITE_UWP)
4931149511
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
4931249512
#else
4931349513
{ "MapViewOfFile", (SYSCALL)0, 0 },
4931449514
#endif
4931549515
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
4931649516
SIZE_T))aSyscall[31].pCurrent)
49517
+
49518
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
49519
+ && defined(SQLITE_UWP)
49520
+ { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
49521
+#else
49522
+ { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
49523
+#endif
49524
+#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
49525
+ SIZE_T))aSyscall[32].pCurrent)
4931749526
4931849527
{ "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
4931949528
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
49320
- int))aSyscall[32].pCurrent)
49529
+ int))aSyscall[33].pCurrent)
4932149530
4932249531
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
4932349532
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
49324
- LARGE_INTEGER*))aSyscall[33].pCurrent)
49533
+ LARGE_INTEGER*))aSyscall[34].pCurrent)
4932549534
4932649535
{ "ReadFile", (SYSCALL)ReadFile, 0 },
4932749536
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
49328
- LPOVERLAPPED))aSyscall[34].pCurrent)
49537
+ LPOVERLAPPED))aSyscall[35].pCurrent)
4932949538
4933049539
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
49331
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[35].pCurrent)
49540
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent)
4933249541
49333
- { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
49334
-#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
49335
- DWORD))aSyscall[36].pCurrent)
49542
+ { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
49543
+#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER,\
49544
+ PLARGE_INTEGER,DWORD))aSyscall[37].pCurrent)
4933649545
4933749546
{ "Sleep", (SYSCALL)Sleep, 0 },
49338
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[37].pCurrent)
49547
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[38].pCurrent)
4933949548
4934049549
{ "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
4934149550
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
49342
- LPOVERLAPPED))aSyscall[38].pCurrent)
49551
+ LPOVERLAPPED))aSyscall[39].pCurrent)
4934349552
4934449553
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
4934549554
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
4934649555
#else
4934749556
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
4934849557
#endif
49349
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[39].pCurrent)
49558
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[40].pCurrent)
4935049559
4935149560
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
4935249561
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
49353
- LPCSTR,LPBOOL))aSyscall[40].pCurrent)
49562
+ LPCSTR,LPBOOL))aSyscall[41].pCurrent)
4935449563
4935549564
{ "WriteFile", (SYSCALL)WriteFile, 0 },
4935649565
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
49357
- LPOVERLAPPED))aSyscall[41].pCurrent)
49566
+ LPOVERLAPPED))aSyscall[42].pCurrent)
4935849567
4935949568
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
4936049569
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
49361
- DWORD))aSyscall[42].pCurrent)
49570
+ DWORD))aSyscall[43].pCurrent)
4936249571
4936349572
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
4936449573
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
49365
- BOOL))aSyscall[43].pCurrent)
49574
+ BOOL))aSyscall[44].pCurrent)
4936649575
4936749576
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
49368
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
49577
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[45].pCurrent)
4936949578
4937049579
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
49371
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[45].pCurrent)
49580
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[46].pCurrent)
4937249581
4937349582
/*
4937449583
** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
4937549584
** is really just a macro that uses a compiler intrinsic (e.g. x64).
4937649585
** So do not try to make this is into a redefinable interface.
@@ -49379,95 +49588,93 @@
4937949588
{ "InterlockedCompareExchange", (SYSCALL)0, 0 },
4938049589
#define osInterlockedCompareExchange InterlockedCompareExchange
4938149590
#else
4938249591
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
4938349592
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*,\
49384
- LONG,LONG))aSyscall[46].pCurrent)
49593
+ LONG,LONG))aSyscall[47].pCurrent)
4938549594
#endif /* defined(InterlockedCompareExchange) */
4938649595
4938749596
#if SQLITE_WIN32_USE_UUID
4938849597
{ "UuidCreate", (SYSCALL)UuidCreate, 0 },
4938949598
#else
4939049599
{ "UuidCreate", (SYSCALL)0, 0 },
4939149600
#endif
49392
-#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[47].pCurrent)
49601
+#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[48].pCurrent)
4939349602
4939449603
#if SQLITE_WIN32_USE_UUID
4939549604
{ "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
4939649605
#else
4939749606
{ "UuidCreateSequential", (SYSCALL)0, 0 },
4939849607
#endif
4939949608
#define osUuidCreateSequential \
49400
- ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[48].pCurrent)
49609
+ ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[49].pCurrent)
4940149610
4940249611
#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
4940349612
{ "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
4940449613
#else
4940549614
{ "FlushViewOfFile", (SYSCALL)0, 0 },
4940649615
#endif
4940749616
#define osFlushViewOfFile \
49408
- ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[49].pCurrent)
49617
+ ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[50].pCurrent)
4940949618
4941049619
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
4941149620
{ "CreateEvent", (SYSCALL)CreateEvent, 0 },
4941249621
#else
4941349622
{ "CreateEvent", (SYSCALL)0, 0 },
4941449623
#endif
49415
-#define osCreateEvent ( \
49416
- (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
49417
- aSyscall[50].pCurrent \
49418
-)
49624
+#define osCreateEvent ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
49625
+ BOOL,LPCSTR))aSyscall[51].pCurrent)
4941949626
4942049627
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
4942149628
{ "CancelIo", (SYSCALL)CancelIo, 0 },
4942249629
#else
4942349630
{ "CancelIo", (SYSCALL)0, 0 },
4942449631
#endif
49425
-#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
49632
+#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[52].pCurrent)
4942649633
4942749634
#ifndef _WIN32
4942849635
{ "getenv", (SYSCALL)getenv, 0 },
4942949636
#else
4943049637
{ "getenv", (SYSCALL)0, 0 },
4943149638
#endif
49432
-#define osGetenv ((const char *(*)(const char *))aSyscall[52].pCurrent)
49639
+#define osGetenv ((const char *(*)(const char *))aSyscall[53].pCurrent)
4943349640
4943449641
#ifndef _WIN32
4943549642
{ "getcwd", (SYSCALL)getcwd, 0 },
4943649643
#else
4943749644
{ "getcwd", (SYSCALL)0, 0 },
4943849645
#endif
49439
-#define osGetcwd ((char*(*)(char*,size_t))aSyscall[53].pCurrent)
49646
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[54].pCurrent)
4944049647
4944149648
#ifndef _WIN32
4944249649
{ "readlink", (SYSCALL)readlink, 0 },
4944349650
#else
4944449651
{ "readlink", (SYSCALL)0, 0 },
4944549652
#endif
49446
-#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[54].pCurrent)
49653
+#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[55].pCurrent)
4944749654
4944849655
#ifndef _WIN32
4944949656
{ "lstat", (SYSCALL)lstat, 0 },
4945049657
#else
4945149658
{ "lstat", (SYSCALL)0, 0 },
4945249659
#endif
49453
-#define osLstat ((int(*)(const char*,struct stat*))aSyscall[55].pCurrent)
49660
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[56].pCurrent)
4945449661
4945549662
#ifndef _WIN32
4945649663
{ "__errno", (SYSCALL)__errno, 0 },
4945749664
#else
4945849665
{ "__errno", (SYSCALL)0, 0 },
4945949666
#endif
49460
-#define osErrno (*((int*(*)(void))aSyscall[56].pCurrent)())
49667
+#define osErrno (*((int*(*)(void))aSyscall[57].pCurrent)())
4946149668
4946249669
#ifndef _WIN32
4946349670
{ "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
4946449671
#else
4946549672
{ "cygwin_conv_path", (SYSCALL)0, 0 },
4946649673
#endif
4946749674
#define osCygwin_conv_path ((size_t(*)(unsigned int, \
49468
- const void *, void *, size_t))aSyscall[57].pCurrent)
49675
+ const void *, void *, size_t))aSyscall[58].pCurrent)
4946949676
4947049677
}; /* End of the overrideable system calls */
4947149678
4947249679
/*
4947349680
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -49551,10 +49758,13 @@
4955149758
}
4955249759
return 0;
4955349760
}
4955449761
4955549762
#ifdef SQLITE_WIN32_MALLOC
49763
+#ifdef SQLITE_UWP
49764
+# error SQLITE_WIN32_MALLOC is incompatible with SQLITE_UWP
49765
+#endif
4955649766
/*
4955749767
** If a Win32 native heap has been configured, this function will attempt to
4955849768
** compact it. Upon success, SQLITE_OK will be returned. Upon failure, one
4955949769
** of SQLITE_NOMEM, SQLITE_ERROR, or SQLITE_NOTFOUND will be returned. The
4956049770
** "pnLargest" argument, if non-zero, will be used to return the size of the
@@ -50509,31 +50719,15 @@
5050950719
** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite
5051050720
** error code.
5051150721
*/
5051250722
static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){
5051350723
int rc = SQLITE_OK; /* Return value */
50514
-
50515
- LONG upperBits; /* Most sig. 32 bits of new offset */
50516
- LONG lowerBits; /* Least sig. 32 bits of new offset */
50517
- DWORD dwRet; /* Value returned by SetFilePointer() */
50518
-
50519
- upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
50520
- lowerBits = (LONG)(iOffset & 0xffffffff);
50521
-
50522
- dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN);
50523
-
50524
- /* API oddity: If successful, SetFilePointer() returns a dword
50525
- ** containing the lower 32-bits of the new file-offset. Or, if it fails,
50526
- ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
50527
- ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
50528
- ** whether an error has actually occurred, it is also necessary to call
50529
- ** GetLastError(). */
50530
- if( dwRet==INVALID_SET_FILE_POINTER ){
50531
- DWORD lastErrno = osGetLastError();
50532
- if( lastErrno!=NO_ERROR ){
50533
- rc = SQLITE_IOERR_SEEK;
50534
- }
50724
+ LARGE_INTEGER x; /* The offset */
50725
+
50726
+ x.QuadPart = iOffset;
50727
+ if( osSetFilePointerEx(h, x, 0, FILE_BEGIN)==0 ){
50728
+ rc = SQLITE_IOERR_SEEK;
5053550729
}
5053650730
OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset,sqlite3ErrName(rc)));
5053750731
return rc;
5053850732
}
5053950733
@@ -50812,18 +51006,17 @@
5081251006
** Determine the size in bytes of the file opened by the handle passed as
5081351007
** the first argument.
5081451008
*/
5081551009
static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){
5081651010
int rc = SQLITE_OK;
50817
- DWORD upperBits = 0;
50818
- DWORD lowerBits = 0;
50819
-
51011
+ LARGE_INTEGER x;
5082051012
assert( pnByte );
50821
- lowerBits = osGetFileSize(h, &upperBits);
50822
- *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
50823
- if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
51013
+ if( osGetFileSizeEx(h, &x)==0 ){
5082451014
rc = SQLITE_IOERR_FSTAT;
51015
+ *pnByte = 0;
51016
+ }else{
51017
+ *pnByte = x.QuadPart;
5082551018
}
5082651019
return rc;
5082751020
}
5082851021
5082951022
/*
@@ -51020,21 +51213,18 @@
5102051213
assert( id!=0 );
5102151214
assert( pSize!=0 );
5102251215
SimulateIOError(return SQLITE_IOERR_FSTAT);
5102351216
OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
5102451217
{
51025
- DWORD upperBits;
51026
- DWORD lowerBits;
51027
- DWORD lastErrno;
51028
-
51029
- lowerBits = osGetFileSize(pFile->h, &upperBits);
51030
- *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
51031
- if( (lowerBits == INVALID_FILE_SIZE)
51032
- && ((lastErrno = osGetLastError())!=NO_ERROR) ){
51033
- pFile->lastErrno = lastErrno;
51218
+ LARGE_INTEGER x;
51219
+ if( osGetFileSizeEx(pFile->h, &x)==0 ){
51220
+ *pSize = 0;
51221
+ pFile->lastErrno = osGetLastError();
5103451222
rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
5103551223
"winFileSize", pFile->zPath);
51224
+ }else{
51225
+ *pSize = x.QuadPart;
5103651226
}
5103751227
}
5103851228
OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
5103951229
pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
5104051230
return rc;
@@ -52031,15 +52221,33 @@
5203152221
# define sqlite3_win_test_unc_locking 0
5203252222
#endif
5203352223
5203452224
/*
5203552225
** Return true if the string passed as the only argument is likely
52036
-** to be a UNC path. In other words, if it starts with "\\".
52226
+** to be a UNC path. Return false if note.
52227
+**
52228
+** Return true if:
52229
+**
52230
+** (1) The name begins with "\\"
52231
+** (2) But does not begin with "\\?\C:\" where C can be any alphabetic
52232
+** character.
52233
+**
52234
+** For testing, also return true in all cases if the global variable
52235
+** sqlite3_win_test_unc_locking is true.
5203752236
*/
5203852237
static int winIsUNCPath(const char *zFile){
5203952238
if( zFile[0]=='\\' && zFile[1]=='\\' ){
52040
- return 1;
52239
+ if( zFile[2]=='?'
52240
+ && zFile[3]=='\\'
52241
+ && sqlite3Isalpha(zFile[4])
52242
+ && zFile[5]==':'
52243
+ && winIsDirSep(zFile[6])
52244
+ ){
52245
+ return sqlite3_win_test_unc_locking;
52246
+ }else{
52247
+ return 1;
52248
+ }
5204152249
}
5204252250
return sqlite3_win_test_unc_locking;
5204352251
}
5204452252
5204552253
/*
@@ -52373,11 +52581,11 @@
5237352581
5237452582
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
5237552583
if( pShmNode->nRegion<=iRegion ){
5237652584
HANDLE hShared = pShmNode->hSharedShm;
5237752585
struct ShmRegion *apNew; /* New aRegion[] array */
52378
- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
52586
+ i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
5237952587
sqlite3_int64 sz; /* Current size of wal-index file */
5238052588
5238152589
pShmNode->szRegion = szRegion;
5238252590
5238352591
/* The requested region is not mapped into this processes address space.
@@ -52404,11 +52612,11 @@
5240452612
}
5240552613
}
5240652614
5240752615
/* Map the requested memory region into this processes address space. */
5240852616
apNew = (struct ShmRegion*)sqlite3_realloc64(
52409
- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
52617
+ pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
5241052618
);
5241152619
if( !apNew ){
5241252620
rc = SQLITE_IOERR_NOMEM_BKPT;
5241352621
goto shmpage_out;
5241452622
}
@@ -52421,20 +52629,30 @@
5242152629
5242252630
while( pShmNode->nRegion<=iRegion ){
5242352631
HANDLE hMap = NULL; /* file-mapping handle */
5242452632
void *pMap = 0; /* Mapped memory region */
5242552633
52634
+#ifdef SQLITE_UWP
52635
+ hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL);
52636
+#else
5242652637
hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL);
52427
- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
52638
+#endif
52639
+ OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
5242852640
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
5242952641
hMap ? "ok" : "failed"));
5243052642
if( hMap ){
52431
- int iOffset = pShmNode->nRegion*szRegion;
52643
+ i64 iOffset = pShmNode->nRegion*szRegion;
5243252644
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
52645
+#ifdef SQLITE_UWP
52646
+ pMap = osMapViewOfFileFromApp(hMap, flags,
52647
+ iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
52648
+ );
52649
+#else
5243352650
pMap = osMapViewOfFile(hMap, flags,
52434
- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
52651
+ 0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
5243552652
);
52653
+#endif
5243652654
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
5243752655
osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
5243852656
szRegion, pMap ? "ok" : "failed"));
5243952657
}
5244052658
if( !pMap ){
@@ -52451,11 +52669,11 @@
5245152669
}
5245252670
}
5245352671
5245452672
shmpage_out:
5245552673
if( pShmNode->nRegion>iRegion ){
52456
- int iOffset = iRegion*szRegion;
52674
+ i64 iOffset = (i64)iRegion*(i64)szRegion;
5245752675
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
5245852676
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
5245952677
*pp = (void *)&p[iOffsetShift];
5246052678
}else{
5246152679
*pp = 0;
@@ -52563,13 +52781,17 @@
5256352781
if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
5256452782
protect = PAGE_READWRITE;
5256552783
flags |= FILE_MAP_WRITE;
5256652784
}
5256752785
#endif
52786
+#ifdef SQLITE_UWP
52787
+ pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
52788
+#else
5256852789
pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
5256952790
(DWORD)((nMap>>32) & 0xffffffff),
5257052791
(DWORD)(nMap & 0xffffffff), NULL);
52792
+#endif
5257152793
if( pFd->hMap==NULL ){
5257252794
pFd->lastErrno = osGetLastError();
5257352795
rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
5257452796
"winMapfile1", pFd->zPath);
5257552797
/* Log the error, but continue normal operation using xRead/xWrite */
@@ -52577,11 +52799,15 @@
5257752799
osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
5257852800
return SQLITE_OK;
5257952801
}
5258052802
assert( (nMap % winSysInfo.dwPageSize)==0 );
5258152803
assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
52804
+#ifdef SQLITE_UWP
52805
+ pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
52806
+#else
5258252807
pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
52808
+#endif
5258352809
if( pNew==NULL ){
5258452810
osCloseHandle(pFd->hMap);
5258552811
pFd->hMap = NULL;
5258652812
pFd->lastErrno = osGetLastError();
5258752813
rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
@@ -52920,11 +53146,11 @@
5292053146
if( !zWidePath ){
5292153147
sqlite3_free(zBuf);
5292253148
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
5292353149
return SQLITE_IOERR_NOMEM_BKPT;
5292453150
}
52925
- if( osGetTempPathW(nMax, zWidePath)==0 ){
53151
+ if( osGetTempPathW==0 || osGetTempPathW(nMax, zWidePath)==0 ){
5292653152
sqlite3_free(zWidePath);
5292753153
sqlite3_free(zBuf);
5292853154
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
5292953155
return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
5293053156
"winGetTempname2", 0);
@@ -53723,37 +53949,37 @@
5372353949
/*
5372453950
** Interfaces for opening a shared library, finding entry points
5372553951
** within the shared library, and closing the shared library.
5372653952
*/
5372753953
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
53728
- HANDLE h;
53954
+ HANDLE h = 0;
5372953955
void *zConverted = winConvertFromUtf8Filename(zFilename);
5373053956
UNUSED_PARAMETER(pVfs);
5373153957
if( zConverted==0 ){
5373253958
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
5373353959
return 0;
5373453960
}
53735
- h = osLoadLibraryW((LPCWSTR)zConverted);
53961
+ h = osLoadLibraryW ? osLoadLibraryW((LPCWSTR)zConverted) : 0;
5373653962
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
5373753963
sqlite3_free(zConverted);
5373853964
return (void*)h;
5373953965
}
5374053966
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
5374153967
UNUSED_PARAMETER(pVfs);
5374253968
winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
5374353969
}
5374453970
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
53745
- FARPROC proc;
53971
+ FARPROC proc = 0;
5374653972
UNUSED_PARAMETER(pVfs);
53747
- proc = osGetProcAddressA((HANDLE)pH, zSym);
53973
+ proc = osGetProcAddressA ? osGetProcAddressA((HANDLE)pH, zSym) : 0;
5374853974
OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
5374953975
(void*)pH, zSym, (void*)proc));
5375053976
return (void(*)(void))proc;
5375153977
}
5375253978
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
5375353979
UNUSED_PARAMETER(pVfs);
53754
- osFreeLibrary((HANDLE)pHandle);
53980
+ if( osFreeLibrary!=0 ) osFreeLibrary((HANDLE)pHandle);
5375553981
OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
5375653982
}
5375753983
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
5375853984
#define winDlOpen 0
5375953985
#define winDlError 0
@@ -53798,36 +54024,39 @@
5379854024
e.a = (unsigned char*)zBuf;
5379954025
e.na = nBuf;
5380054026
e.nXor = 0;
5380154027
e.i = 0;
5380254028
{
53803
- SYSTEMTIME x;
53804
- osGetSystemTime(&x);
53805
- xorMemory(&e, (unsigned char*)&x, sizeof(SYSTEMTIME));
54029
+ FILETIME x;
54030
+ osGetSystemTimeAsFileTime(&x);
54031
+ xorMemory(&e, (unsigned char*)&x, sizeof(x));
5380654032
}
5380754033
{
5380854034
DWORD pid = osGetCurrentProcessId();
53809
- xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD));
54035
+ xorMemory(&e, (unsigned char*)&pid, sizeof(pid));
5381054036
}
5381154037
{
53812
- DWORD cnt = osGetTickCount();
53813
- xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD));
54038
+ ULONGLONG cnt = osGetTickCount64();
54039
+ xorMemory(&e, (unsigned char*)&cnt, sizeof(cnt));
5381454040
}
5381554041
{
5381654042
LARGE_INTEGER i;
5381754043
osQueryPerformanceCounter(&i);
53818
- xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER));
54044
+ xorMemory(&e, (unsigned char*)&i, sizeof(i));
5381954045
}
5382054046
#if SQLITE_WIN32_USE_UUID
54047
+#ifdef SQLITE_UWP
54048
+# error SQLITE_WIN32_USE_UUID is incompatible with SQLITE_UWP
54049
+#endif
5382154050
{
5382254051
UUID id;
53823
- memset(&id, 0, sizeof(UUID));
54052
+ memset(&id, 0, sizeof(id));
5382454053
osUuidCreate(&id);
53825
- xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
54054
+ xorMemory(&e, (unsigned char*)&id, sizeof(id));
5382654055
memset(&id, 0, sizeof(UUID));
5382754056
osUuidCreateSequential(&id);
53828
- xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
54057
+ xorMemory(&e, (unsigned char*)&id, sizeof(id));
5382954058
}
5383054059
#endif /* SQLITE_WIN32_USE_UUID */
5383154060
return e.nXor>nBuf ? nBuf : e.nXor;
5383254061
#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */
5383354062
}
@@ -54042,15 +54271,19 @@
5404254271
winNextSystemCall, /* xNextSystemCall */
5404354272
};
5404454273
5404554274
/* Double-check that the aSyscall[] array has been constructed
5404654275
** correctly. See ticket [bb3a86e890c8e96ab] */
54047
- assert( ArraySize(aSyscall)==58 );
54276
+ assert( ArraySize(aSyscall)==59 );
5404854277
assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 );
54049
- assert( strcmp(aSyscall[20].zName,"HeapAlloc")==0 );
54050
- assert( strcmp(aSyscall[40].zName,"WideCharToMultiByte")==0 );
54051
- assert( strcmp(aSyscall[57].zName,"cygwin_conv_path")==0 );
54278
+ assert( strcmp(aSyscall[8].zName,"FreeLibrary")==0 );
54279
+ assert( strcmp(aSyscall[16].zName,"GetSystemInfo")==0 );
54280
+ assert( strcmp(aSyscall[24].zName,"HeapReAlloc")==0 );
54281
+ assert( strcmp(aSyscall[32].zName,"MapViewOfFileFromApp")==0 );
54282
+ assert( strcmp(aSyscall[40].zName,"UnmapViewOfFile")==0 );
54283
+ assert( strcmp(aSyscall[48].zName,"UuidCreate")==0 );
54284
+ assert( strcmp(aSyscall[56].zName,"lstat")==0 );
5405254285
5405354286
/* get memory map allocation granularity */
5405454287
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
5405554288
osGetSystemInfo(&winSysInfo);
5405654289
assert( winSysInfo.dwAllocationGranularity>0 );
@@ -56762,26 +56995,28 @@
5676256995
szBulk = -1024 * (i64)pcache1.nInitPage;
5676356996
}
5676456997
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
5676556998
szBulk = pCache->szAlloc*(i64)pCache->nMax;
5676656999
}
56767
- zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
56768
- sqlite3EndBenignMalloc();
56769
- if( zBulk ){
56770
- int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
56771
- do{
56772
- PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
56773
- pX->page.pBuf = zBulk;
56774
- pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
56775
- assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
56776
- pX->isBulkLocal = 1;
56777
- pX->isAnchor = 0;
56778
- pX->pNext = pCache->pFree;
56779
- pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
56780
- pCache->pFree = pX;
56781
- zBulk += pCache->szAlloc;
56782
- }while( --nBulk );
57000
+ if( szBulk>=pCache->szAlloc ){
57001
+ zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
57002
+ sqlite3EndBenignMalloc();
57003
+ if( zBulk ){
57004
+ int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
57005
+ do{
57006
+ PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
57007
+ pX->page.pBuf = zBulk;
57008
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
57009
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
57010
+ pX->isBulkLocal = 1;
57011
+ pX->isAnchor = 0;
57012
+ pX->pNext = pCache->pFree;
57013
+ pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
57014
+ pCache->pFree = pX;
57015
+ zBulk += pCache->szAlloc;
57016
+ }while( --nBulk );
57017
+ }
5678357018
}
5678457019
return pCache->pFree!=0;
5678557020
}
5678657021
5678757022
/*
@@ -59675,73 +59910,84 @@
5967559910
#define pager_set_pagehash(X)
5967659911
#define CHECK_PAGE(x)
5967759912
#endif /* SQLITE_CHECK_PAGES */
5967859913
5967959914
/*
59680
-** When this is called the journal file for pager pPager must be open.
59681
-** This function attempts to read a super-journal file name from the
59682
-** end of the file and, if successful, copies it into memory supplied
59683
-** by the caller. See comments above writeSuperJournal() for the format
59684
-** used to store a super-journal file name at the end of a journal file.
59685
-**
59686
-** zSuper must point to a buffer of at least nSuper bytes allocated by
59687
-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
59688
-** enough space to write the super-journal name). If the super-journal
59689
-** name in the journal is longer than nSuper bytes (including a
59690
-** nul-terminator), then this is handled as if no super-journal name
59691
-** were present in the journal.
59692
-**
59693
-** If a super-journal file name is present at the end of the journal
59694
-** file, then it is copied into the buffer pointed to by zSuper. A
59695
-** nul-terminator byte is appended to the buffer following the
59696
-** super-journal file name.
59697
-**
59698
-** If it is determined that no super-journal file name is present
59699
-** zSuper[0] is set to 0 and SQLITE_OK returned.
59700
-**
59701
-** If an error occurs while reading from the journal file, an SQLite
59702
-** error code is returned.
59703
-*/
59704
-static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
59915
+** Free a buffer allocated by the readSuperJournal() function.
59916
+*/
59917
+static void freeSuperJournal(char *zSuper){
59918
+ if( zSuper ){
59919
+ sqlite3_free(&zSuper[-4]);
59920
+ }
59921
+}
59922
+
59923
+/*
59924
+** Parameter pJrnl is a file-handle open on a journal file. This function
59925
+** attempts to read a super-journal file name from the end of the journal
59926
+** file. If successful, it sets output parameter (*pzSuper) to point to a
59927
+** buffer containing the super-journal name as a nul-terminated string.
59928
+** The caller is responsible for freeing the buffer using freeSuperJournal().
59929
+**
59930
+** Refer to comments above writeSuperJournal() for the format used to store
59931
+** a super-journal file name at the end of a journal file.
59932
+**
59933
+** Parameter nSuper is passed the maximum allowable size of the super journal
59934
+** name in bytes. If the super-journal name in the journal is longer than
59935
+** nSuper bytes (including a nul-terminator), then this is handled as if no
59936
+** super-journal name were present in the journal.
59937
+**
59938
+** If there is no super-journal name at the end of pJrnl, (*pzSuper) is
59939
+** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading
59940
+** the super-journal name, an SQLite error code is returned and (*pzSuper)
59941
+** is set to 0.
59942
+*/
59943
+static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){
5970559944
int rc; /* Return code */
5970659945
u32 len; /* Length in bytes of super-journal name */
5970759946
i64 szJ; /* Total size in bytes of journal file pJrnl */
5970859947
u32 cksum; /* MJ checksum value read from journal */
59709
- u32 u; /* Unsigned loop counter */
5971059948
unsigned char aMagic[8]; /* A buffer to hold the magic header */
59711
- zSuper[0] = '\0';
59949
+ char *zOut = 0;
5971259950
59951
+ *pzSuper = 0;
5971359952
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
5971459953
|| szJ<16
5971559954
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
5971659955
|| len>=nSuper
5971759956
|| len>szJ-16
5971859957
|| len==0
5971959958
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
5972059959
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
5972159960
|| memcmp(aMagic, aJournalMagic, 8)
59722
- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
5972359961
){
5972459962
return rc;
5972559963
}
5972659964
59727
- /* See if the checksum matches the super-journal name */
59728
- for(u=0; u<len; u++){
59729
- cksum -= zSuper[u];
59730
- }
59731
- if( cksum ){
59732
- /* If the checksum doesn't add up, then one or more of the disk sectors
59733
- ** containing the super-journal filename is corrupted. This means
59734
- ** definitely roll back, so just return SQLITE_OK and report a (nul)
59735
- ** super-journal filename.
59736
- */
59737
- len = 0;
59738
- }
59739
- zSuper[len] = '\0';
59740
- zSuper[len+1] = '\0';
59741
-
59742
- return SQLITE_OK;
59965
+ zOut = (char*)sqlite3MallocZero(4 + len + 2);
59966
+ if( !zOut ){
59967
+ rc = SQLITE_NOMEM_BKPT;
59968
+ }else{
59969
+ zOut = &zOut[4];
59970
+ if( SQLITE_OK==(rc = sqlite3OsRead(pJrnl, zOut, len, szJ-16-len)) ){
59971
+ u32 u; /* Unsigned loop counter */
59972
+ /* See if the checksum matches the super-journal name */
59973
+ for(u=0; u<len; u++){
59974
+ cksum -= zOut[u];
59975
+ }
59976
+ }
59977
+ if( rc!=SQLITE_OK || cksum ){
59978
+ /* If the checksum doesn't add up, then one or more of the disk sectors
59979
+ ** containing the super-journal filename is corrupted. This means
59980
+ ** definitely roll back, so just return SQLITE_OK and report a (nul)
59981
+ ** super-journal filename. */
59982
+ freeSuperJournal(zOut);
59983
+ zOut = 0;
59984
+ }
59985
+ }
59986
+
59987
+ *pzSuper = zOut;
59988
+ return rc;
5974359989
}
5974459990
5974559991
/*
5974659992
** Return the offset of the sector boundary at or immediately
5974759993
** following the value in pPager->journalOff, assuming a sector
@@ -60942,13 +61188,11 @@
6094261188
sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */
6094361189
sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
6094461190
char *zSuperJournal = 0; /* Contents of super-journal file */
6094561191
i64 nSuperJournal; /* Size of super-journal file */
6094661192
char *zJournal; /* Pointer to one journal within MJ file */
60947
- char *zSuperPtr; /* Space to hold super-journal filename */
6094861193
char *zFree = 0; /* Free this buffer */
60949
- i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
6095061194
6095161195
/* Allocate space for both the pJournal and pSuper file descriptors.
6095261196
** If successful, open the super-journal file for reading.
6095361197
*/
6095461198
pSuper = (sqlite3_file *)sqlite3MallocZero(2 * (i64)pVfs->szOsFile);
@@ -60967,22 +61211,20 @@
6096761211
** sufficient space (in zSuperPtr) to hold the names of super-journal
6096861212
** files extracted from regular rollback-journals.
6096961213
*/
6097061214
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
6097161215
if( rc!=SQLITE_OK ) goto delsuper_out;
60972
- nSuperPtr = 1 + (i64)pVfs->mxPathname;
60973
- assert( nSuperJournal>=0 && nSuperPtr>0 );
60974
- zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
61216
+ assert( nSuperJournal>=0 );
61217
+ zFree = sqlite3Malloc(4 + nSuperJournal + 2);
6097561218
if( !zFree ){
6097661219
rc = SQLITE_NOMEM_BKPT;
6097761220
goto delsuper_out;
6097861221
}else{
6097961222
assert( nSuperJournal<=0x7fffffff );
6098061223
}
6098161224
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
6098261225
zSuperJournal = &zFree[4];
60983
- zSuperPtr = &zSuperJournal[nSuperJournal+2];
6098461226
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
6098561227
if( rc!=SQLITE_OK ) goto delsuper_out;
6098661228
zSuperJournal[nSuperJournal] = 0;
6098761229
zSuperJournal[nSuperJournal+1] = 0;
6098861230
@@ -60992,10 +61234,12 @@
6099261234
rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
6099361235
if( rc!=SQLITE_OK ){
6099461236
goto delsuper_out;
6099561237
}
6099661238
if( exists ){
61239
+ char *zSuperPtr = 0;
61240
+
6099761241
/* One of the journals pointed to by the super-journal exists.
6099861242
** Open it and check if it points at the super-journal. If
6099961243
** so, return without deleting the super-journal file.
6100061244
** NB: zJournal is really a MAIN_JOURNAL. But call it a
6100161245
** SUPER_JOURNAL here so that the VFS will not send the zJournal
@@ -61006,17 +61250,19 @@
6100661250
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
6100761251
if( rc!=SQLITE_OK ){
6100861252
goto delsuper_out;
6100961253
}
6101061254
61011
- rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
61255
+ rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr);
6101261256
sqlite3OsClose(pJournal);
6101361257
if( rc!=SQLITE_OK ){
61258
+ assert( zSuperPtr==0 );
6101461259
goto delsuper_out;
6101561260
}
6101661261
61017
- c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
61262
+ c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0;
61263
+ freeSuperJournal(zSuperPtr);
6101861264
if( c ){
6101961265
/* We have a match. Do not delete the super-journal file. */
6102061266
goto delsuper_out;
6102161267
}
6102261268
}
@@ -61227,23 +61473,15 @@
6122761473
6122861474
/* Read the super-journal name from the journal, if it is present.
6122961475
** If a super-journal file name is specified, but the file is not
6123061476
** present on disk, then the journal is not hot and does not need to be
6123161477
** played back.
61232
- **
61233
- ** TODO: Technically the following is an error because it assumes that
61234
- ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
61235
- ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
61236
- ** mxPathname is 512, which is the same as the minimum allowable value
61237
- ** for pageSize.
6123861478
*/
61239
- zSuper = pPager->pTmpSpace;
61240
- rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
61241
- if( rc==SQLITE_OK && zSuper[0] ){
61479
+ rc = readSuperJournal(pPager->jfd, 1+(i64)pPager->pVfs->mxPathname, &zSuper);
61480
+ if( rc==SQLITE_OK && zSuper ){
6124261481
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
6124361482
}
61244
- zSuper = 0;
6124561483
if( rc!=SQLITE_OK || !res ){
6124661484
goto end_playback;
6124761485
}
6124861486
pPager->journalOff = 0;
6124961487
needPagerReset = isHot;
@@ -61368,34 +61606,24 @@
6136861606
** problems for other processes at some point in the future. So, just
6136961607
** in case this has happened, clear the changeCountDone flag now.
6137061608
*/
6137161609
pPager->changeCountDone = pPager->tempFile;
6137261610
61373
- if( rc==SQLITE_OK ){
61374
- /* Leave 4 bytes of space before the super-journal filename in memory.
61375
- ** This is because it may end up being passed to sqlite3OsOpen(), in
61376
- ** which case it requires 4 0x00 bytes in memory immediately before
61377
- ** the filename. */
61378
- zSuper = &pPager->pTmpSpace[4];
61379
- rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
61380
- testcase( rc!=SQLITE_OK );
61381
- }
6138261611
if( rc==SQLITE_OK
6138361612
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
6138461613
){
6138561614
rc = sqlite3PagerSync(pPager, 0);
6138661615
}
6138761616
if( rc==SQLITE_OK ){
61388
- rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
61617
+ rc = pager_end_transaction(pPager, zSuper!=0, 0);
6138961618
testcase( rc!=SQLITE_OK );
6139061619
}
61391
- if( rc==SQLITE_OK && zSuper[0] && res ){
61620
+ if( rc==SQLITE_OK && zSuper && res ){
6139261621
/* If there was a super-journal and this routine will return success,
6139361622
** see if it is possible to delete the super-journal.
6139461623
*/
61395
- assert( zSuper==&pPager->pTmpSpace[4] );
61396
- memset(pPager->pTmpSpace, 0, 4);
61624
+ assert( memcmp(&zSuper[-4], "\0\0\0\0", 4)==0 );
6139761625
rc = pager_delsuper(pPager, zSuper);
6139861626
testcase( rc!=SQLITE_OK );
6139961627
}
6140061628
if( isHot && nPlayback ){
6140161629
sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
@@ -61404,10 +61632,11 @@
6140461632
6140561633
/* The Pager.sectorSize variable may have been updated while rolling
6140661634
** back a journal created by a process with a different sector size
6140761635
** value. Reset it to the correct value for this process.
6140861636
*/
61637
+ freeSuperJournal(zSuper);
6140961638
setSectorSize(pPager);
6141061639
return rc;
6141161640
}
6141261641
6141361642
@@ -67262,10 +67491,16 @@
6726267491
*/
6726367492
pgno = sqlite3Get4byte(&aFrame[0]);
6726467493
if( pgno==0 ){
6726567494
return 0;
6726667495
}
67496
+
67497
+ /* Need a valid page size
67498
+ */
67499
+ if( !pWal->szPage ){
67500
+ return 0;
67501
+ }
6726767502
6726867503
/* A frame is only valid if a checksum of the WAL header,
6726967504
** all prior frames, the first 16 bytes of this frame-header,
6727067505
** and the frame-data matches the checksum in the last 8
6727167506
** bytes of this frame-header.
@@ -69117,11 +69352,11 @@
6911769352
goto begin_unreliable_shm_out;
6911869353
}
6911969354
6912069355
/* Allocate a buffer to read frames into */
6912169356
assert( (pWal->szPage & (pWal->szPage-1))==0 );
69122
- assert( pWal->szPage>=512 && pWal->szPage<=65536 );
69357
+ assert( (pWal->szPage>=512 && pWal->szPage<=65536) || pWal->szPage==0 );
6912369358
szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
6912469359
aFrame = (u8 *)sqlite3_malloc64(szFrame);
6912569360
if( aFrame==0 ){
6912669361
rc = SQLITE_NOMEM_BKPT;
6912769362
goto begin_unreliable_shm_out;
@@ -71953,10 +72188,20 @@
7195372188
** See the header comment on "btreeInt.h" for additional information.
7195472189
** Including a description of file format and an overview of operation.
7195572190
*/
7195672191
/* #include "btreeInt.h" */
7195772192
72193
+/*
72194
+** Suppress false-positive compiler warnings from GCC. Warnings are
72195
+** re-enabled at the bottom of this source file.
72196
+*/
72197
+#if defined(__GNUC__) && __GNUC__>=11
72198
+# pragma GCC diagnostic push
72199
+# pragma GCC diagnostic ignored "-Wstringop-overread"
72200
+# pragma GCC diagnostic ignored "-Wstringop-overflow"
72201
+#endif
72202
+
7195872203
/*
7195972204
** The header string that appears at the beginning of every
7196072205
** SQLite database.
7196172206
*/
7196272207
static const char zMagicHeader[] = SQLITE_FILE_HEADER;
@@ -77123,11 +77368,13 @@
7712377368
** in the overflow chain. The page number of the first overflow page is
7712477369
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
7712577370
** means "not yet known" (the cache is lazily populated).
7712677371
*/
7712777372
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
77128
- int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
77373
+ i64 nOvfl = pCur->info.nPayload;
77374
+ testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
77375
+ nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
7712977376
if( pCur->aOverflow==0
7713077377
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
7713177378
){
7713277379
Pgno *aNew;
7713377380
if( sqlite3FaultSim(413) ){
@@ -77228,10 +77475,18 @@
7722877475
DbPage *pDbPage;
7722977476
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
7723077477
(eOp==0 ? PAGER_GET_READONLY : 0)
7723177478
);
7723277479
if( rc==SQLITE_OK ){
77480
+ if( eOp!=0
77481
+ && (sqlite3PagerPageRefcount(pDbPage)!=1
77482
+ || NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit))
77483
+ && sqlite3FaultSim(411)==SQLITE_OK
77484
+ ){
77485
+ sqlite3PagerUnref(pDbPage);
77486
+ return SQLITE_CORRUPT_PAGE(pPage);
77487
+ }
7723377488
aPayload = sqlite3PagerGetData(pDbPage);
7723477489
nextPage = get4byte(aPayload);
7723577490
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
7723677491
sqlite3PagerUnref(pDbPage);
7723777492
offset = 0;
@@ -82902,10 +83157,15 @@
8290283157
if( pc+info.nSize>usableSize ){
8290383158
checkAppendMsg(pCheck, "Extends off end of page");
8290483159
doCoverageCheck = 0;
8290583160
continue;
8290683161
}
83162
+ if( info.nPayload && info.pPayload[0]<2 ){
83163
+ checkAppendMsg(pCheck, "Bad cell header size");
83164
+ doCoverageCheck = 0;
83165
+ continue;
83166
+ }
8290783167
8290883168
/* Check for integer primary key out of range */
8290983169
if( pPage->intKey ){
8291083170
if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){
8291183171
checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
@@ -83504,10 +83764,17 @@
8350483764
SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
8350583765
testcase( p->sharable );
8350683766
return p->pBt->nRef;
8350783767
}
8350883768
#endif
83769
+
83770
+/* Re-enable GCC compiler warnings that were suppressed at the top
83771
+** of this source file to prevent annoying false-positives.
83772
+*/
83773
+#if defined(__GNUC__) && __GNUC__>=11
83774
+# pragma GCC diagnostic pop
83775
+#endif
8350983776
8351083777
/************** End of btree.c ***********************************************/
8351183778
/************** Begin file backup.c ******************************************/
8351283779
/*
8351383780
** 2009 January 28
@@ -84405,12 +84672,12 @@
8440584672
/* Work-around for GCC bug or bugs:
8440684673
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270
8440784674
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
8440884675
** The problem appears to be fixed in GCC 15 */
8440984676
i64 x;
84410
- assert( (MEM_Str&~p->flags)*4==sizeof(x) );
84411
- memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4);
84677
+ assert( (sqlite3Config.bSmallMalloc!=0xee)*8==sizeof(x) );
84678
+ memcpy(&x, (char*)&p->u.i, (sqlite3Config.bSmallMalloc!=0xee)*8);
8441284679
p->n = sqlite3Int64ToText(x, zBuf);
8441384680
#else
8441484681
p->n = sqlite3Int64ToText(p->u.i, zBuf);
8441584682
#endif
8441684683
if( p->flags & MEM_IntReal ){
@@ -87107,15 +87374,25 @@
8710787374
/*
8710887375
** Add an OP_ParseSchema opcode. This routine is broken out from
8710987376
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
8711087377
** as having been used.
8711187378
**
87112
-** The zWhere string must have been obtained from sqlite3_malloc().
87379
+** zWhere is a WHERE clause that defines which entries of the schema
87380
+** to reparse. If zWhere==0, that means all entries. p5 is a mask
87381
+** of INITFLAG_* values for the parse.
87382
+**
87383
+** In the current usage, the following are always true:
87384
+**
87385
+** ALTER TABLE: zWhere==0, p5!=0
87386
+** Otherwise: zWhere!=0, p5==0
87387
+**
87388
+** The zWhere string must have been obtained from sqlite3DbMalloc().
8711387389
** This routine will take ownership of the allocated memory.
8711487390
*/
8711587391
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
8711687392
int j;
87393
+ assert( p5==0 || zWhere==0 );
8711787394
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
8711887395
sqlite3VdbeChangeP5(p, p5);
8711987396
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
8712087397
sqlite3MayAbort(p->pParse);
8712187398
}
@@ -95247,11 +95524,11 @@
9524795524
QueryPerformanceCounter(&tm);
9524895525
return (sqlite3_uint64)tm.QuadPart;
9524995526
}
9525095527
9525195528
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \
95252
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
95529
+ (defined(i586) || defined(__i586__) || defined(_M_IX86))
9525395530
9525495531
__inline__ sqlite_uint64 sqlite3Hwtime(void){
9525595532
unsigned int lo, hi;
9525695533
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
9525795534
return (sqlite_uint64)hi << 32 | lo;
@@ -95713,14 +95990,16 @@
9571395990
*/
9571495991
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
9571595992
int eType = sqlite3_value_type(pVal);
9571695993
if( eType==SQLITE_TEXT ){
9571795994
Mem *pMem = (Mem*)pVal;
95718
- assert( pMem->db!=0 );
95719
- sqlite3_mutex_enter(pMem->db->mutex);
95995
+#if SQLITE_THREADSAFE>0
95996
+ sqlite3_mutex *pMutex = pMem->db ? pMem->db->mutex : 0;
95997
+#endif
95998
+ sqlite3_mutex_enter(pMutex);
9572095999
applyNumericAffinity(pMem, 0);
95721
- sqlite3_mutex_leave(pMem->db->mutex);
96000
+ sqlite3_mutex_leave(pMutex);
9572296001
eType = sqlite3_value_type(pVal);
9572396002
}
9572496003
return eType;
9572596004
}
9572696005
@@ -102423,15 +102702,22 @@
102423102702
goto abort_due_to_error;
102424102703
}
102425102704
break;
102426102705
}
102427102706
102428
-/* Opcode: ParseSchema P1 * * P4 *
102707
+/* Opcode: ParseSchema P1 * * P4 P5
102429102708
**
102430102709
** Read and parse all entries from the schema table of database P1
102431102710
** that match the WHERE clause P4. If P4 is a NULL pointer, then the
102432102711
** entire schema for P1 is reparsed.
102712
+**
102713
+** When P4 is NULL, the P5 value is used as the mFlags argument
102714
+** to sqlite3InitOne(). In other words, P5 should be a mask composed
102715
+** of INITFLAG_* values.
102716
+**
102717
+** The P4==0 case is only used by ALTER TABLE and P5!=0 for all such
102718
+** cases. For uses other than ALTER TABLE, P4<>0 and P5==0.
102433102719
**
102434102720
** This opcode invokes the parser to create a new virtual machine,
102435102721
** then runs the new virtual machine. It is thus a re-entrant opcode.
102436102722
*/
102437102723
case OP_ParseSchema: {
@@ -102456,18 +102742,20 @@
102456102742
|| db->mallocFailed
102457102743
|| (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) );
102458102744
102459102745
#ifndef SQLITE_OMIT_ALTERTABLE
102460102746
if( pOp->p4.z==0 ){
102747
+ assert( pOp->p5!=0 );
102461102748
sqlite3SchemaClear(db->aDb[iDb].pSchema);
102462102749
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
102463102750
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
102464102751
db->mDbFlags |= DBFLAG_SchemaChange;
102465102752
p->expired = 0;
102466102753
}else
102467102754
#endif
102468102755
{
102756
+ assert( pOp->p5==0 );
102469102757
zSchema = LEGACY_SCHEMA_TABLE;
102470102758
initData.db = db;
102471102759
initData.iDb = iDb;
102472102760
initData.pzErrMsg = &p->zErrMsg;
102473102761
initData.mInitFlags = 0;
@@ -102825,11 +103113,11 @@
102825103113
if( pFrame ) break;
102826103114
}
102827103115
102828103116
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
102829103117
rc = SQLITE_ERROR;
102830
- sqlite3VdbeError(p, "too many levels of trigger recursion");
103118
+ sqlite3VdbeError(p, "triggers nested too deep");
102831103119
goto abort_due_to_error;
102832103120
}
102833103121
102834103122
/* Register pRt is used to store the memory required to save the state
102835103123
** of the current program, and the memory required at runtime to execute
@@ -109952,11 +110240,11 @@
109952110240
/*
109953110241
** cnt==0 means there was not match.
109954110242
** cnt>1 means there were two or more matches.
109955110243
**
109956110244
** cnt==0 is always an error. cnt>1 is often an error, but might
109957
- ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
110245
+ ** be multiple matches for a NATURAL OUTER JOIN or a OUTER JOIN USING.
109958110246
*/
109959110247
assert( pFJMatch==0 || cnt>0 );
109960110248
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
109961110249
if( cnt!=1 ){
109962110250
const char *zErr;
@@ -109972,10 +110260,11 @@
109972110260
}
109973110261
extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
109974110262
pExpr->op = TK_FUNCTION;
109975110263
pExpr->u.zToken = "coalesce";
109976110264
pExpr->x.pList = pFJMatch;
110265
+ pExpr->affExpr = SQLITE_AFF_DEFER;
109977110266
cnt = 1;
109978110267
goto lookupname_end;
109979110268
}else{
109980110269
sqlite3ExprListDelete(db, pFJMatch);
109981110270
pFJMatch = 0;
@@ -110034,12 +110323,21 @@
110034110323
pExpr->op = eNewExprOp;
110035110324
lookupname_end:
110036110325
if( cnt==1 ){
110037110326
assert( pNC!=0 );
110038110327
#ifndef SQLITE_OMIT_AUTHORIZATION
110039
- if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){
110040
- sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
110328
+ if( db->xAuth ){
110329
+ if( pFJMatch ){
110330
+ assert( pExpr->op==TK_FUNCTION );
110331
+ assert( sqlite3_stricmp(pExpr->u.zToken,"coalesce")==0 );
110332
+ assert( pExpr->x.pList==pFJMatch );
110333
+ assert( pFJMatch->nExpr>0 );
110334
+ pExpr = pFJMatch->a[0].pExpr;
110335
+ }
110336
+ if( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ){
110337
+ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
110338
+ }
110041110339
}
110042110340
#endif
110043110341
/* Increment the nRef value on all name contexts from TopNC up to
110044110342
** the point where the name matched. */
110045110343
for(;;){
@@ -110137,10 +110435,30 @@
110137110435
sqlite3AtoF(p->u.zToken, &r);
110138110436
assert( r>=0.0 );
110139110437
if( r>1.0 ) return -1;
110140110438
return (int)(r*134217728.0);
110141110439
}
110440
+
110441
+/*
110442
+** Set the EP_SubtArg property on every expression inside of
110443
+** pList. If any subexpression is actually a subquery, then
110444
+** also set the EP_SubtArg property on the first result-set
110445
+** column of that subquery.
110446
+*/
110447
+static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
110448
+ int nn, ii;
110449
+ nn = pList ? pList->nExpr : 0;
110450
+ for(ii=0; ii<nn; ii++){
110451
+ Expr *pExpr = pList->a[ii].pExpr;
110452
+ ExprSetProperty(pExpr, EP_SubtArg);
110453
+ if( pExpr->op==TK_SELECT ){
110454
+ assert( ExprUseXSelect(pExpr) );
110455
+ assert( pExpr->x.pSelect!=0 );
110456
+ resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
110457
+ }
110458
+ }
110459
+}
110142110460
110143110461
/*
110144110462
** This routine is callback for sqlite3WalkExpr().
110145110463
**
110146110464
** Resolve symbolic names into TK_COLUMN operators for the current
@@ -110382,14 +110700,11 @@
110382110700
** the function may return a value with a subtype back to its
110383110701
** caller using sqlite3_result_value(). */
110384110702
if( (pDef->funcFlags & SQLITE_SUBTYPE)
110385110703
|| ExprHasProperty(pExpr, EP_SubtArg)
110386110704
){
110387
- int ii;
110388
- for(ii=0; ii<n; ii++){
110389
- ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
110390
- }
110705
+ resolveSetExprSubtypeArg(pList);
110391110706
}
110392110707
110393110708
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
110394110709
/* For the purposes of the EP_ConstFunc flag, date and time
110395110710
** functions and other functions that change slowly are considered
@@ -110415,12 +110730,17 @@
110415110730
&& (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
110416110731
){
110417110732
/* Internal-use-only functions are disallowed unless the
110418110733
** SQL is being compiled using sqlite3NestedParse() or
110419110734
** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
110420
- ** used to activate internal functions for testing purposes */
110421
- no_such_func = 1;
110735
+ ** used to activate internal functions for testing purposes.
110736
+ **
110737
+ ** The 2 value for no_such_func means that the function is
110738
+ ** an internal-use-only function which should be treated as a
110739
+ ** non-existant function for name resolution purposes.
110740
+ */
110741
+ no_such_func = 2;
110422110742
pDef = 0;
110423110743
}else
110424110744
if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
110425110745
&& !IN_RENAME_OBJECT
110426110746
){
@@ -110460,13 +110780,20 @@
110460110780
sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr);
110461110781
pNC->nNcErr++;
110462110782
is_agg = 0;
110463110783
}
110464110784
#endif
110465
- else if( no_such_func && pParse->db->init.busy==0
110785
+ else if( no_such_func
110786
+ && (pParse->db->init.busy==0 ||
110787
+ (no_such_func==2 && pParse->db->init.busy==2))
110788
+ /* Suppress "no such function" errors when reading
110789
+ ** the sqlite_schema table. Except, do raise the error
110790
+ ** if init.busy is 2, meaning the schema parse is due
110791
+ ** to an ALTER TABLE ADD COLUMN statement, and the function
110792
+ ** is an internal-use-only function (no_such_func==2). */
110466110793
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
110467
- && pParse->explain==0
110794
+ && pParse->explain==0
110468110795
#endif
110469110796
){
110470110797
sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
110471110798
pNC->nNcErr++;
110472110799
}else if( wrong_num_args ){
@@ -111849,11 +112176,13 @@
111849112176
** Return TRUE if the two expressions have equivalent collating sequences.
111850112177
*/
111851112178
SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
111852112179
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
111853112180
CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
111854
- return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
112181
+ assert( (pColl1==pColl2) ==
112182
+ (sqlite3_stricmp(pColl1->zName,pColl2->zName)==0) );
112183
+ return pColl1==pColl2;
111855112184
}
111856112185
111857112186
/*
111858112187
** pExpr is an operand of a comparison operator. aff2 is the
111859112188
** type affinity of the other operand. This routine returns the
@@ -115686,10 +116015,11 @@
115686116015
if( i!=nVector ){
115687116016
/* Need to reorder the LHS fields according to aiMap */
115688116017
int rLhsOrig = rLhs;
115689116018
rLhs = sqlite3GetTempRange(pParse, nVector);
115690116019
for(i=0; i<nVector; i++){
116020
+ testcase( aiMap[i]!=i );
115691116021
sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
115692116022
}
115693116023
sqlite3ReleaseTempReg(pParse, rLhsOrig);
115694116024
}
115695116025
}
@@ -115706,11 +116036,12 @@
115706116036
}
115707116037
for(i=0; i<nVector; i++){
115708116038
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
115709116039
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
115710116040
if( sqlite3ExprCanBeNull(p) ){
115711
- sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
116041
+ testcase( aiMap[i]!=i );
116042
+ sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+aiMap[i], destStep2);
115712116043
VdbeCoverage(v);
115713116044
}
115714116045
}
115715116046
115716116047
/* Step 3. The LHS is now known to be non-NULL. Do the binary search
@@ -115780,13 +116111,23 @@
115780116111
for(i=0; i<nVector; i++){
115781116112
Expr *p;
115782116113
CollSeq *pColl;
115783116114
int r3 = sqlite3GetTempReg(pParse);
115784116115
p = sqlite3VectorFieldSubexpr(pLeft, i);
115785
- pColl = sqlite3ExprCollSeq(pParse, p);
115786
- sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
115787
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
116116
+ if( ExprUseXSelect(pExpr) ){
116117
+ Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
116118
+ pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
116119
+ }else{
116120
+ /* If the RHS of the IN(...) expression are scalar expressions, do
116121
+ ** not consider their collation sequences. The documentation says
116122
+ ** "The collating sequence used for expressions of the form "x IN (y, z,
116123
+ ** ...)" is the collating sequence of x.". */
116124
+ pColl = sqlite3ExprCollSeq(pParse, p);
116125
+ }
116126
+ testcase( aiMap[i]!=i );
116127
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, aiMap[i], r3);
116128
+ sqlite3VdbeAddOp4(v, OP_Ne, rLhs+aiMap[i], destNotNull, r3,
115788116129
(void*)pColl, P4_COLLSEQ);
115789116130
VdbeCoverage(v);
115790116131
sqlite3ReleaseTempReg(pParse, r3);
115791116132
}
115792116133
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
@@ -116203,40 +116544,51 @@
116203116544
}
116204116545
return target;
116205116546
}
116206116547
116207116548
/*
116208
-** Expression Node callback for sqlite3ExprCanReturnSubtype().
116209
-**
116210
-** Only a function call is able to return a subtype. So if the node
116211
-** is not a function call, return WRC_Prune immediately.
116212
-**
116213
-** A function call is able to return a subtype if it has the
116214
-** SQLITE_RESULT_SUBTYPE property.
116215
-**
116216
-** Assume that every function is able to pass-through a subtype from
116217
-** one of its argument (using sqlite3_result_value()). Most functions
116218
-** are not this way, but we don't have a mechanism to distinguish those
116219
-** that are from those that are not, so assume they all work this way.
116220
-** That means that if one of its arguments is another function and that
116221
-** other function is able to return a subtype, then this function is
116222
-** able to return a subtype.
116549
+** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
116550
+** pExpr is able to return a subtype, set pWalker->eCode and abort
116551
+** the search. If pExpr can never return a subtype, prune search.
116552
+**
116553
+** The only expressions that can return a subtype are:
116554
+**
116555
+** 1. A function
116556
+** 2. The no-op "+" operator
116557
+** 3. A CASE...END expression
116558
+** 4. A CAST() expression
116559
+** 5. A "expr COLLATE colseq" expression.
116560
+**
116561
+** For any other kind of expression, prune the search.
116562
+**
116563
+** For case 1, the expression can yield a subtype if the function has
116564
+** the SQLITE_RESULT_SUBTYPE property. Functions can also return
116565
+** a subtype (via sqlite3_result_value()) if any of the arguments can
116566
+** return a subtype.
116567
+**
116568
+** In all cases 1 through 5, the expression might also return a subtype
116569
+** if any operand can return a subtype.
116223116570
*/
116224116571
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
116225116572
int n;
116226116573
FuncDef *pDef;
116227116574
sqlite3 *db;
116575
+ if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
116576
+ || pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
116577
+ ){
116578
+ return WRC_Continue;
116579
+ }
116228116580
if( pExpr->op!=TK_FUNCTION ){
116229116581
return WRC_Prune;
116230116582
}
116231116583
assert( ExprUseXList(pExpr) );
116232116584
db = pWalker->pParse->db;
116233116585
n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
116234116586
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
116235116587
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
116236116588
pWalker->eCode = 1;
116237
- return WRC_Prune;
116589
+ return WRC_Abort;
116238116590
}
116239116591
return WRC_Continue;
116240116592
}
116241116593
116242116594
/*
@@ -122210,23 +122562,35 @@
122210122562
SQLITE_PRIVATE void sqlite3AlterAddConstraint(
122211122563
Parse *pParse, /* Parse context */
122212122564
SrcList *pSrc, /* Table to add constraint to */
122213122565
Token *pFirst, /* First token of new constraint */
122214122566
Token *pName, /* Name of new constraint. NULL if name omitted. */
122215
- const char *pExpr, /* Text of CHECK expression */
122216
- int nExpr /* Size of pExpr in bytes */
122567
+ const char *zExpr, /* Text of CHECK expression */
122568
+ int nExpr, /* Size of pExpr in bytes */
122569
+ Expr *pExpr /* The parsed CHECK expression */
122217122570
){
122218122571
Table *pTab = 0; /* Table identified by pSrc */
122219122572
int iDb = 0; /* Which schema does pTab live in */
122220122573
const char *zDb = 0; /* Name of the schema in which pTab lives */
122221122574
const char *pCons = 0; /* Text of the constraint */
122222122575
int nCons; /* Bytes of text to use from pCons[] */
122576
+ int rc; /* Result from error checking pExpr */
122223122577
122224122578
/* Look up the table being altered. */
122225122579
assert( pSrc->nSrc==1 );
122226122580
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
122227
- if( !pTab ) return;
122581
+ if( !pTab ){
122582
+ sqlite3ExprDelete(pParse->db, pExpr);
122583
+ return;
122584
+ }
122585
+
122586
+ /* Verify that the new CHECK constraint does not contain any
122587
+ ** internal-use-only function. Forum post 2026-05-10T01:11:28Z
122588
+ */
122589
+ rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
122590
+ sqlite3ExprDelete(pParse->db, pExpr);
122591
+ if( rc ) return;
122228122592
122229122593
/* If this new constraint has a name, check that it is not a duplicate of
122230122594
** an existing constraint. It is an error if it is. */
122231122595
if( pName ){
122232122596
char *zName = sqlite3NameFromToken(pParse->db, pName);
@@ -122243,11 +122607,11 @@
122243122607
122244122608
/* Search for a constraint violation. Throw an exception if one is found. */
122245122609
sqlite3NestedParse(pParse,
122246122610
"SELECT sqlite_fail('constraint failed', %d) "
122247122611
"FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
122248
- SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr
122612
+ SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
122249122613
);
122250122614
122251122615
/* Edit the SQL for the named table. */
122252122616
pCons = pFirst->z;
122253122617
nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons);
@@ -124098,21 +124462,21 @@
124098124462
}else{
124099124463
nIdxCol = pIdx->nColumn;
124100124464
}
124101124465
pIdx->nSampleCol = nIdxCol;
124102124466
pIdx->mxSample = nSample;
124103
- nByte = ROUND8(sizeof(IndexSample) * nSample);
124104
- nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
124105
- nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
124467
+ nByte = ROUND8(sizeof64(IndexSample) * nSample);
124468
+ nByte += sizeof64(tRowcnt) * nIdxCol * 3 * nSample;
124469
+ nByte += nIdxCol * sizeof64(tRowcnt); /* Space for Index.aAvgEq[] */
124106124470
124107124471
pIdx->aSample = sqlite3DbMallocZero(db, nByte);
124108124472
if( pIdx->aSample==0 ){
124109124473
sqlite3_finalize(pStmt);
124110124474
return SQLITE_NOMEM_BKPT;
124111124475
}
124112124476
pPtr = (u8*)pIdx->aSample;
124113
- pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
124477
+ pPtr += ROUND8(nSample*sizeof64(pIdx->aSample[0]));
124114124478
pSpace = (tRowcnt*)pPtr;
124115124479
assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
124116124480
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
124117124481
pIdx->pTable->tabFlags |= TF_HasStat4;
124118124482
for(i=0; i<nSample; i++){
@@ -125929,10 +126293,23 @@
125929126293
if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
125930126294
if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
125931126295
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
125932126296
}
125933126297
126298
+/*
126299
+** Suppress false-positive warning message generated with -O3 in GCC
126300
+** on the second call to sqlite3Strlen30() in the sqlite3ColumnSetColl()
126301
+** function below. See the forum thread beginning on 2026-05-10T01:11:22Z.
126302
+**
126303
+** See also the "pop" pragma to undo this warning suppression immediately
126304
+** after the function.
126305
+*/
126306
+#if defined(__GNUC__) && __GNUC__>=11
126307
+# pragma GCC diagnostic push
126308
+# pragma GCC diagnostic ignored "-Wstringop-overread"
126309
+#endif
126310
+
125934126311
/*
125935126312
** Set the collating sequence name for a column.
125936126313
*/
125937126314
SQLITE_PRIVATE void sqlite3ColumnSetColl(
125938126315
sqlite3 *db,
@@ -125953,10 +126330,15 @@
125953126330
pCol->zCnName = zNew;
125954126331
memcpy(pCol->zCnName + n, zColl, nColl);
125955126332
pCol->colFlags |= COLFLAG_HASCOLL;
125956126333
}
125957126334
}
126335
+
126336
+/* Undo the false-positive warning suppression above. */
126337
+#if defined(__GNUC__) && __GNUC__>=11
126338
+# pragma GCC diagnostic pop
126339
+#endif
125958126340
125959126341
/*
125960126342
** Return the collating sequence name for a column
125961126343
*/
125962126344
SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){
@@ -132946,13 +133328,22 @@
132946133328
x.nUsed = 0;
132947133329
x.apArg = argv+1;
132948133330
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
132949133331
str.printfFlags = SQLITE_PRINTF_SQLFUNC;
132950133332
sqlite3_str_appendf(&str, zFormat, &x);
132951
- n = str.nChar;
132952
- sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
132953
- SQLITE_DYNAMIC);
133333
+ if( str.accError==SQLITE_OK ){
133334
+ n = str.nChar;
133335
+ sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
133336
+ SQLITE_DYNAMIC);
133337
+ }else{
133338
+ if( str.accError==SQLITE_NOMEM ){
133339
+ sqlite3_result_error_nomem(context);
133340
+ }else{
133341
+ sqlite3_result_error_toobig(context);
133342
+ }
133343
+ sqlite3_str_reset(&str);
133344
+ }
132954133345
}
132955133346
}
132956133347
132957133348
/*
132958133349
** Implementation of the substr() function.
@@ -134120,11 +134511,11 @@
134120134511
int nStr; /* Size of zStr */
134121134512
int nPattern; /* Size of zPattern */
134122134513
int nRep; /* Size of zRep */
134123134514
i64 nOut; /* Maximum size of zOut */
134124134515
int loopLimit; /* Last zStr[] that might match zPattern[] */
134125
- int i, j; /* Loop counters */
134516
+ i64 i, j; /* Loop counters */
134126134517
unsigned cntExpand; /* Number zOut expansions */
134127134518
sqlite3 *db = sqlite3_context_db_handle(context);
134128134519
134129134520
assert( argc==3 );
134130134521
UNUSED_PARAMETER(argc);
@@ -134599,15 +134990,20 @@
134599134990
** to initialize it */
134600134991
if( ALWAYS(p) && type!=SQLITE_NULL ){
134601134992
assert( p->cnt>0 );
134602134993
p->cnt--;
134603134994
if( !p->approx ){
134604
- if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
134605
- p->ovrfl = 1;
134606
- p->approx = 1;
134995
+ i64 x = p->iSum;
134996
+ if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
134997
+ p->iSum = x;
134998
+ return;
134607134999
}
134608
- }else if( type==SQLITE_INTEGER ){
135000
+ p->ovrfl = 1;
135001
+ p->approx = 1;
135002
+ kahanBabuskaNeumaierInit(p, p->iSum);
135003
+ }
135004
+ if( type==SQLITE_INTEGER ){
134609135005
i64 iVal = sqlite3_value_int64(argv[0]);
134610135006
if( iVal!=SMALLEST_INT64 ){
134611135007
kahanBabuskaNeumaierStepInt64(p, -iVal);
134612135008
}else{
134613135009
kahanBabuskaNeumaierStepInt64(p, LARGEST_INT64);
@@ -135569,57 +135965,95 @@
135569135965
** from the standard library because:
135570135966
**
135571135967
** (1) To avoid a dependency on qsort()
135572135968
** (2) To avoid the function call to the comparison routine for each
135573135969
** comparison.
135970
+**
135971
+** If parameter iReq is non-negative, then the caller will only access
135972
+** elements a[iReq] and a[iReq+1] (if it exists) of the sorted array and
135973
+** so it is not necessary to position any other elements. Or if iReq is
135974
+** negative, then the final array must be fully sorted.
135574135975
*/
135575
-static void percentSort(double *a, unsigned int n){
135976
+static void percentSort(
135977
+ double *a, /* Array to sort */
135978
+ unsigned int n, /* Number of elements in array a[] */
135979
+ int iReq /* Element caller cares about (or -ve) */
135980
+){
135576135981
int iLt; /* Entries before a[iLt] are less than rPivot */
135577135982
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
135578135983
int i; /* Loop counter */
135579135984
double rPivot; /* The pivot value */
135580135985
135581135986
assert( n>=2 );
135582
- if( a[0]>a[n-1] ){
135583
- SWAP_DOUBLE(a[0],a[n-1])
135584
- }
135585
- if( n==2 ) return;
135586
- iGt = n-1;
135587
- i = n/2;
135588
- if( a[0]>a[i] ){
135589
- SWAP_DOUBLE(a[0],a[i])
135590
- }else if( a[i]>a[iGt] ){
135591
- SWAP_DOUBLE(a[i],a[iGt])
135592
- }
135593
- if( n==3 ) return;
135594
- rPivot = a[i];
135595
- iLt = i = 1;
135596
- do{
135597
- if( a[i]<rPivot ){
135598
- if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
135599
- iLt++;
135600
- i++;
135601
- }else if( a[i]>rPivot ){
135602
- do{
135603
- iGt--;
135604
- }while( iGt>i && a[iGt]>rPivot );
135605
- SWAP_DOUBLE(a[i],a[iGt])
135606
- }else{
135607
- i++;
135608
- }
135609
- }while( i<iGt );
135610
- if( iLt>=2 ) percentSort(a, iLt);
135611
- if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
135612
-
135613
-/* Uncomment for testing */
135614
-#if 0
135615
- for(i=0; i<n-1; i++){
135616
- assert( a[i]<=a[i+1] );
135617
- }
135618
-#endif
135619
-}
135620
-
135987
+ do{
135988
+ if( a[0]>a[n-1] ){
135989
+ SWAP_DOUBLE(a[0],a[n-1])
135990
+ }
135991
+ if( n==2 ) return;
135992
+ iGt = n-1;
135993
+ i = n/2;
135994
+ if( a[0]>a[i] ){
135995
+ SWAP_DOUBLE(a[0],a[i])
135996
+ }else if( a[i]>a[iGt] ){
135997
+ SWAP_DOUBLE(a[i],a[iGt])
135998
+ }
135999
+ if( n==3 ) return;
136000
+ rPivot = a[i];
136001
+ iLt = i = 1;
136002
+ do{
136003
+ if( a[i]<rPivot ){
136004
+ if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
136005
+ iLt++;
136006
+ i++;
136007
+ }else if( a[i]>rPivot ){
136008
+ do{
136009
+ iGt--;
136010
+ }while( iGt>i && a[iGt]>rPivot );
136011
+ SWAP_DOUBLE(a[i],a[iGt])
136012
+ }else{
136013
+ i++;
136014
+ }
136015
+ }while( i<iGt );
136016
+
136017
+ assert( a[iLt]==rPivot );
136018
+ assert( iGt>iLt );
136019
+
136020
+ if( iReq>=0 ){
136021
+ /* In this case, the only elements that the caller requires sorted into
136022
+ ** the correct positions are elements a[iReq] and a[iReq+1]. At this
136023
+ ** point we know that element a[iLt] is in the correct position and
136024
+ ** all elements smaller than a[iLt] are in the left-hand partition.
136025
+ ** So if (iReq<iLt), then it is only necessary to sort the left
136026
+ ** partition.
136027
+ **
136028
+ ** If (iReq>=iLt), then elements iReq and iReq+1 are either in the
136029
+ ** right partition or the equal partition (elements for which
136030
+ ** iLt<=iElem<iGt). Therefore it is always sufficient to sort only
136031
+ ** the right partition in this case. */
136032
+ if( iReq<iLt ){
136033
+ n = iLt;
136034
+ }else{
136035
+ a += iGt;
136036
+ n -= iGt;
136037
+ iReq = MAX(0, iReq-iGt);
136038
+ }
136039
+ }else{
136040
+ /* Recurse on the smaller partition only. The smaller partition
136041
+ ** will hold n/2 or fewer entries, which assures that the stack
136042
+ ** depth will not exceed O(log(n)), even for pathological cases.
136043
+ ** Loop without recursion for the larger partition. */
136044
+ if( iLt>(int)(n/2) ){
136045
+ if( n-iGt>=2 ) percentSort(a+iGt, n-iGt, -1);
136046
+ n = iLt;
136047
+ }else{
136048
+ if( iLt>=2 ) percentSort(a, iLt, -1);
136049
+ a += iGt;
136050
+ n -= iGt;
136051
+ }
136052
+ }
136053
+ }while( n>=2 );
136054
+}
135621136055
135622136056
/*
135623136057
** The "inverse" function for percentile(Y,P) is called to remove a
135624136058
** row that was previously inserted by "step".
135625136059
*/
@@ -135649,11 +136083,11 @@
135649136083
if( percentIsInfinity(y) ){
135650136084
return;
135651136085
}
135652136086
if( p->bSorted==0 ){
135653136087
assert( p->nUsed>1 );
135654
- percentSort(p->a, p->nUsed);
136088
+ percentSort(p->a, p->nUsed, -1);
135655136089
p->bSorted = 1;
135656136090
}
135657136091
p->bKeepSorted = 1;
135658136092
135659136093
/* Find and remove the row */
@@ -135678,17 +136112,21 @@
135678136112
double ix, vx;
135679136113
p = (Percentile*)sqlite3_aggregate_context(pCtx, 0);
135680136114
if( p==0 ) return;
135681136115
if( p->a==0 ) return;
135682136116
if( p->nUsed ){
136117
+ ix = p->rPct*(p->nUsed-1);
136118
+ i1 = (unsigned)ix;
135683136119
if( p->bSorted==0 ){
136120
+ /* In cases where bIsFinal is non-zero, setting Percentile.bSorted
136121
+ ** after the percentSort() call here is not technically correct, as
136122
+ ** the array is not fully sorted. But in this case the object will be
136123
+ ** freed below anyway, so it doesn't matter. */
135684136124
assert( p->nUsed>1 );
135685
- percentSort(p->a, p->nUsed);
136125
+ percentSort(p->a, p->nUsed, (bIsFinal ? (int)i1 : -1));
135686136126
p->bSorted = 1;
135687136127
}
135688
- ix = p->rPct*(p->nUsed-1);
135689
- i1 = (unsigned)ix;
135690136128
if( settings & 1 ){
135691136129
vx = p->a[i1];
135692136130
}else{
135693136131
i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
135694136132
v1 = p->a[i1];
@@ -140569,10 +141007,48 @@
140569141007
}
140570141008
140571141009
/* If no test above fails then the indices must be compatible */
140572141010
return 1;
140573141011
}
141012
+
141013
+/*
141014
+** Examine an expression node and abort if it references the ROWID.
141015
+** This is a Walker callback used by xferCompatibleCheck()
141016
+*/
141017
+static int xferCheckRowid(Walker *pWalk, Expr *pExpr){
141018
+ if( pExpr->op==TK_COLUMN && pExpr->iColumn<0 ){
141019
+ pWalk->eCode = 1;
141020
+ return WRC_Abort;
141021
+ }else{
141022
+ return WRC_Continue;
141023
+ }
141024
+}
141025
+
141026
+/*
141027
+** Analyze CHECK constraints on the source and destination tables and
141028
+** return true if those CHECK constraints are compatible with the
141029
+** xfer-optimization.
141030
+**
141031
+** * The pDest and pSrc tables must have identical CHECK constraints.
141032
+**
141033
+** * If the destination table, pDest, does not have an
141034
+** INTEGER PRIMARY KEY column, then no CHECK constraint may
141035
+** referenced the ROWID. (See forum post 2026-05-11T13:15:57Z)
141036
+*/
141037
+static int xferCompatibleCheck(Table *pDest, Table *pSrc){
141038
+ if( sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
141039
+ return 0;
141040
+ }
141041
+ if( pDest->iPKey<0 ){
141042
+ Walker w;
141043
+ memset(&w, 0, sizeof(w));
141044
+ w.xExprCallback = xferCheckRowid;
141045
+ sqlite3WalkExprList(&w,pDest->pCheck);
141046
+ if( w.eCode ) return 0;
141047
+ }
141048
+ return 1;
141049
+}
140574141050
140575141051
/*
140576141052
** Attempt the transfer optimization on INSERTs of the form
140577141053
**
140578141054
** INSERT INTO tab1 SELECT * FROM tab2;
@@ -140696,12 +141172,23 @@
140696141172
return 0; /* Number of columns must be the same in tab1 and tab2 */
140697141173
}
140698141174
if( pDest->iPKey!=pSrc->iPKey ){
140699141175
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
140700141176
}
140701
- if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){
140702
- return 0; /* Cannot feed from a non-strict into a strict table */
141177
+ if( (pDest->tabFlags & TF_Strict)!=0 ){
141178
+ if( (pSrc->tabFlags & TF_Strict)==0 ){
141179
+ return 0; /* Cannot feed from a non-strict into a strict table */
141180
+ }
141181
+ for(i=0; i<pDest->nCol; i++){
141182
+ unsigned eDestType = pDest->aCol[i].eCType;
141183
+ unsigned eSrcType = pSrc->aCol[i].eCType;
141184
+ if( eDestType==COLTYPE_ANY ) continue;
141185
+ if( eDestType==eSrcType ) continue;
141186
+ if( eDestType==COLTYPE_INT && eSrcType==COLTYPE_INTEGER ) continue;
141187
+ if( eDestType==COLTYPE_INTEGER && eSrcType==COLTYPE_INT ) continue;
141188
+ return 0; /* Incompatible types in source and destination */
141189
+ }
140703141190
}
140704141191
for(i=0; i<pDest->nCol; i++){
140705141192
Column *pDestCol = &pDest->aCol[i];
140706141193
Column *pSrcCol = &pSrc->aCol[i];
140707141194
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
@@ -140791,11 +141278,11 @@
140791141278
}
140792141279
}
140793141280
#ifndef SQLITE_OMIT_CHECK
140794141281
if( pDest->pCheck
140795141282
&& (db->mDbFlags & DBFLAG_Vacuum)==0
140796
- && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
141283
+ && !xferCompatibleCheck(pDest,pSrc)
140797141284
){
140798141285
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
140799141286
}
140800141287
#endif
140801141288
#ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -140812,10 +141299,22 @@
140812141299
}
140813141300
#endif
140814141301
if( (db->flags & SQLITE_CountRows)!=0 ){
140815141302
return 0; /* xfer opt does not play well with PRAGMA count_changes */
140816141303
}
141304
+#ifndef SQLITE_OMIT_AUTHORIZATION
141305
+ if( db->xAuth ){
141306
+ int iDb = sqlite3SchemaToIndex(db, pSrc->pSchema);
141307
+ if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 0;
141308
+ for(i=0; i<pSrc->nCol; i++){
141309
+ Column *pSrcCol = &pSrc->aCol[i];
141310
+ if( sqlite3AuthReadCol(pParse, pSrc->zName, pSrcCol->zCnName, iDb) ){
141311
+ return 0;
141312
+ }
141313
+ }
141314
+ }
141315
+#endif
140817141316
140818141317
/* If we get this far, it means that the xfer optimization is at
140819141318
** least a possibility, though it might only work if the destination
140820141319
** table (tab1) is initially empty.
140821141320
*/
@@ -146810,11 +147309,17 @@
146810147309
assert( iDb>=0 && iDb<db->nDb );
146811147310
assert( db->aDb[iDb].pSchema );
146812147311
assert( sqlite3_mutex_held(db->mutex) );
146813147312
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
146814147313
146815
- db->init.busy = 1;
147314
+ db->init.busy = 1 + ((mFlags & INITFLAG_AlterAdd)!=0);
147315
+ /* ^--- Any non-zero value for init.busy means that we are scanning
147316
+ ** the sqlite_schema table to build the internal schema representation,
147317
+ ** rather than running actual CREATE statements. init.busy==2 has the
147318
+ ** additional meaning that the scan is happening as part of
147319
+ ** ALTER TABLE ADD COLUMN, which is stricter in its enforcement of
147320
+ ** function name resolution. */
146816147321
146817147322
/* Construct the in-memory representation schema tables (sqlite_schema or
146818147323
** sqlite_temp_schema) by invoking the parser directly. The appropriate
146819147324
** table name will be inserted automatically by the parser so we can just
146820147325
** use the abbreviation "x" here. The parser will also automatically tag
@@ -150131,10 +150636,17 @@
150131150636
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
150132150637
Table *pTab;
150133150638
sqlite3 *db = pParse->db;
150134150639
u64 savedFlags;
150135150640
150641
+ pParse->nNestSel++;
150642
+#if SQLITE_MAX_EXPR_DEPTH>0
150643
+ if( pParse->nNestSel >= db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
150644
+ sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
150645
+ return 0;
150646
+ }
150647
+#endif
150136150648
savedFlags = db->flags;
150137150649
db->flags &= ~(u64)SQLITE_FullColNames;
150138150650
db->flags |= SQLITE_ShortColNames;
150139150651
sqlite3SelectPrep(pParse, pSelect, 0);
150140150652
db->flags = savedFlags;
@@ -150152,10 +150664,12 @@
150152150664
pTab->iPKey = -1;
150153150665
if( db->mallocFailed ){
150154150666
sqlite3DeleteTable(db, pTab);
150155150667
return 0;
150156150668
}
150669
+ pParse->nNestSel--;
150670
+ assert( pParse->nNestSel>=0 );
150157150671
return pTab;
150158150672
}
150159150673
150160150674
/*
150161150675
** Get a VDBE for the given parser context. Create a new one if necessary.
@@ -155122,12 +155636,15 @@
155122155636
** Then, if CheckOnCtx.iJoin indicates that this expression is part of an
155123155637
** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it
155124155638
** does not refer to a table to the right of CheckOnCtx.iJoin. */
155125155639
do {
155126155640
SrcList *pSrc = pCtx->pSrc;
155641
+ int nSrc = pSrc->nSrc;
155127155642
int iTab = pExpr->iTable;
155128
- if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
155643
+ int ii;
155644
+ for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){}
155645
+ if( ii<nSrc ){
155129155646
if( pCtx->iJoin && iTab>pCtx->iJoin ){
155130155647
sqlite3ErrorMsg(pWalker->pParse,
155131155648
"%s references tables to its right",
155132155649
(pCtx->bFuncArg ? "table-function argument" : "ON clause")
155133155650
);
@@ -158092,22 +158609,36 @@
158092158609
Parse *pParse, /* Current parse context */
158093158610
Trigger *pTrigger, /* Trigger to code */
158094158611
Table *pTab, /* The table pTrigger is attached to */
158095158612
int orconf /* ON CONFLICT policy to code trigger program with */
158096158613
){
158097
- Parse *pTop = sqlite3ParseToplevel(pParse);
158614
+ Parse *pTop; /* Top level Parse object */
158098158615
sqlite3 *db = pParse->db; /* Database handle */
158099158616
TriggerPrg *pPrg; /* Value to return */
158100158617
Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
158101158618
Vdbe *v; /* Temporary VM */
158102158619
NameContext sNC; /* Name context for sub-vdbe */
158103158620
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
158104158621
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
158105158622
Parse sSubParse; /* Parse context for sub-vdbe */
158623
+ int nDepth; /* Trigger depth */
158106158624
158625
+ /* Ensure that triggers are not chained too deep. This test is linear
158626
+ ** in the chaining depth, but sensible code ought not be chaining
158627
+ ** triggers excessively, so that shouldn't be a problem.
158628
+ */
158629
+ pTop = pParse;
158630
+ for(nDepth=0; pTop->pOuterParse; pTop = pTop->pOuterParse, nDepth++){}
158631
+ if( nDepth>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
158632
+ sqlite3ErrorMsg(pParse, "triggers nested too deep");
158633
+ return 0;
158634
+ }
158635
+
158636
+ pTop = sqlite3ParseToplevel(pParse);
158107158637
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
158108158638
assert( pTop->pVdbe );
158639
+
158109158640
158110158641
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
158111158642
** are freed if an error occurs, link them into the Parse.pTriggerPrg
158112158643
** list of the top-level Parse object sooner rather than later. */
158113158644
pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
@@ -160105,11 +160636,12 @@
160105160636
** So we have to make a copy before passing it down into sqlite3Update() */
160106160637
pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
160107160638
/* excluded.* columns of type REAL need to be converted to a hard real */
160108160639
for(i=0; i<pTab->nCol; i++){
160109160640
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
160110
- sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
160641
+ int iStorage = pTop->regData + sqlite3TableColumnToStorage(pTab, i);
160642
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iStorage);
160111160643
}
160112160644
}
160113160645
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
160114160646
sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
160115160647
VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
@@ -164903,11 +165435,11 @@
164903165435
164904165436
/* Set up a new SrcList in pOrTab containing the table being scanned
164905165437
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
164906165438
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
164907165439
*/
164908
- if( pWInfo->nLevel>1 ){
165440
+ if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
164909165441
int nNotReady; /* The number of notReady tables */
164910165442
SrcItem *origSrc; /* Original list of tables */
164911165443
nNotReady = pWInfo->nLevel - iLevel - 1;
164912165444
pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
164913165445
if( pOrTab==0 ) return notReady;
@@ -164916,10 +165448,17 @@
164916165448
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
164917165449
origSrc = pWInfo->pTabList->a;
164918165450
for(k=1; k<=nNotReady; k++){
164919165451
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
164920165452
}
165453
+
165454
+ /* Clear the fromExists flag on the OR-optimized table entry so that
165455
+ ** the calls to sqlite3WhereEnd() do not code early-exits after the
165456
+ ** first row is visited. The early exit applies to this table's
165457
+ ** overall loop - including the multiple OR branches and any WHERE
165458
+ ** conditions not passed to the sub-loops - not to the sub-loops. */
165459
+ pOrTab->a[0].fg.fromExists = 0;
164921165460
}else{
164922165461
pOrTab = pWInfo->pTabList;
164923165462
}
164924165463
164925165464
/* Initialize the rowset register to contain NULL. An SQL NULL is
@@ -165159,11 +165698,11 @@
165159165698
** indent everything in between the this point and the final OP_Return.
165160165699
** See tag-20220407a in vdbe.c and shell.c */
165161165700
assert( pLevel->op==OP_Return );
165162165701
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
165163165702
165164
- if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
165703
+ if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
165165165704
if( !untestedTerms ) disableTerm(pLevel, pTerm);
165166165705
}else
165167165706
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
165168165707
165169165708
{
@@ -165316,10 +165855,11 @@
165316165855
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
165317165856
pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
165318165857
WO_EQ|WO_IN|WO_IS, 0);
165319165858
if( pAlt==0 ) continue;
165320165859
if( pAlt->wtFlags & (TERM_CODED) ) continue;
165860
+ if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
165321165861
if( (pAlt->eOperator & WO_IN)
165322165862
&& ExprUseXSelect(pAlt->pExpr)
165323165863
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
165324165864
){
165325165865
continue;
@@ -166069,11 +166609,14 @@
166069166609
** Mark term iChild as being a child of term iParent
166070166610
*/
166071166611
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
166072166612
pWC->a[iChild].iParent = iParent;
166073166613
pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
166614
+ assert( pWC->a[iParent].nChild < UMXV(pWC->a[0].nChild) );
166074166615
pWC->a[iParent].nChild++;
166616
+ testcase( pWC->a[iParent].nChild == UMXV(pWC->a[0].nChild) );
166617
+
166075166618
}
166076166619
166077166620
/*
166078166621
** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not
166079166622
** a conjunction, then return just pTerm when N==0. If N is exceeds
@@ -166508,23 +167051,22 @@
166508167051
** 1. The SQLITE_Transitive optimization must be enabled
166509167052
** 2. Must be either an == or an IS operator
166510167053
** 3. Not originating in the ON clause of an OUTER JOIN
166511167054
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
166512167055
** 5. The affinities of A and B must be compatible
166513
-** 6a. Both operands use the same collating sequence OR
166514
-** 6b. The overall collating sequence is BINARY
167056
+** 6. Both operands use the same collating sequence, and they must not
167057
+** use explicit COLLATE clauses.
166515167058
** If this routine returns TRUE, that means that the RHS can be substituted
166516167059
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
166517167060
** This is an optimization. No harm comes from returning 0. But if 1 is
166518167061
** returned when it should not be, then incorrect answers might result.
166519167062
*/
166520167063
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
166521167064
char aff1, aff2;
166522
- CollSeq *pColl;
166523167065
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
166524167066
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
166525
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
167067
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
166526167068
assert( pSrc!=0 );
166527167069
if( pExpr->op==TK_IS
166528167070
&& pSrc->nSrc>=2
166529167071
&& (pSrc->a[0].fg.jointype & JT_LTORJ)!=0
166530167072
){
@@ -166535,14 +167077,11 @@
166535167077
if( aff1!=aff2
166536167078
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
166537167079
){
166538167080
return 0; /* (5) */
166539167081
}
166540
- pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
166541
- if( !sqlite3IsBinary(pColl)
166542
- && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
166543
- ){
167082
+ if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
166544167083
return 0; /* (6) */
166545167084
}
166546167085
return 1;
166547167086
}
166548167087
@@ -166850,10 +167389,11 @@
166850167389
static const u8 ops[] = {TK_GE, TK_LE};
166851167390
assert( ExprUseXList(pExpr) );
166852167391
pList = pExpr->x.pList;
166853167392
assert( pList!=0 );
166854167393
assert( pList->nExpr==2 );
167394
+ assert( pWC->a[idxTerm].nChild==0 );
166855167395
for(i=0; i<2; i++){
166856167396
Expr *pNewExpr;
166857167397
int idxNew;
166858167398
pNewExpr = sqlite3PExpr(pParse, ops[i],
166859167399
sqlite3ExprDup(db, pExpr->pLeft, 0),
@@ -166870,11 +167410,11 @@
166870167410
166871167411
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
166872167412
/* Analyze a term that is composed of two or more subterms connected by
166873167413
** an OR operator.
166874167414
*/
166875
- else if( pExpr->op==TK_OR ){
167415
+ else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
166876167416
assert( pWC->op==TK_AND );
166877167417
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
166878167418
pTerm = &pWC->a[idxTerm];
166879167419
}
166880167420
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
@@ -167060,12 +167600,15 @@
167060167600
&& (pExpr->x.pSelect->pPrior==0 || (pExpr->x.pSelect->selFlags & SF_Values))
167061167601
#ifndef SQLITE_OMIT_WINDOWFUNC
167062167602
&& pExpr->x.pSelect->pWin==0
167063167603
#endif
167064167604
&& pWC->op==TK_AND
167605
+ && pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild)
167606
+ /* ^-- See bug 2026-06-04T10:00:49Z */
167065167607
){
167066167608
int i;
167609
+ assert( pTerm->nChild==0 );
167067167610
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
167068167611
int idxNew;
167069167612
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
167070167613
pWC->a[idxNew].u.x.iField = i+1;
167071167614
exprAnalyze(pSrc, pWC, idxNew);
@@ -170589,13 +171132,14 @@
170589171132
pLoop->nOut--;
170590171133
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
170591171134
&& (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
170592171135
){
170593171136
Expr *pRight = pOpExpr->pRight;
171137
+ Parse *pParse = pWC->pWInfo->pParse;
170594171138
int k = 0;
170595171139
testcase( pOpExpr->op==TK_IS );
170596
- if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
171140
+ if( sqlite3ExprIsInteger(pRight, &k, pParse) && k>=(-1) && k<=1 ){
170597171141
k = 10;
170598171142
}else{
170599171143
k = 20;
170600171144
}
170601171145
if( iReduce<k ){
@@ -170688,11 +171232,12 @@
170688171232
testcase( pLhs->iColumn==XN_ROWID );
170689171233
aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs));
170690171234
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
170691171235
if( aff!=idxaff ) break;
170692171236
170693
- pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
171237
+ if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
171238
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
170694171239
if( pColl==0 ) break;
170695171240
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
170696171241
}
170697171242
return i;
170698171243
}
@@ -183162,13 +183707,15 @@
183162183707
case 196: /* expr ::= LP nexprlist COMMA expr RP */
183163183708
{
183164183709
ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454);
183165183710
yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
183166183711
if( yymsp[-4].minor.yy454 ){
183712
+ int i;
183167183713
yymsp[-4].minor.yy454->x.pList = pList;
183168
- if( ALWAYS(pList->nExpr) ){
183169
- yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate;
183714
+ for(i=0; i<pList->nExpr; i++){
183715
+ assert( pList->a[i].pExpr!=0 );
183716
+ yymsp[-4].minor.yy454->flags |= pList->a[i].pExpr->flags & EP_Propagate;
183170183717
}
183171183718
}else{
183172183719
sqlite3ExprListDelete(pParse->db, pList);
183173183720
}
183174183721
}
@@ -183632,19 +184179,17 @@
183632184179
sqlite3AlterSetNotNull(pParse, yymsp[-7].minor.yy203, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0);
183633184180
}
183634184181
break;
183635184182
case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
183636184183
{
183637
- sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1));
184184
+ sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
183638184185
}
183639
- yy_destructor(yypParser,219,&yymsp[-2].minor);
183640184186
break;
183641184187
case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
183642184188
{
183643
- sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1));
184189
+ sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
183644184190
}
183645
- yy_destructor(yypParser,219,&yymsp[-2].minor);
183646184191
break;
183647184192
case 302: /* cmd ::= create_vtab */
183648184193
{sqlite3VtabFinishParse(pParse,0);}
183649184194
break;
183650184195
case 303: /* cmd ::= create_vtab LP vtabarglist RP */
@@ -186617,11 +187162,11 @@
186617187162
** or disables the collection of memory allocation statistics. */
186618187163
sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
186619187164
break;
186620187165
}
186621187166
case SQLITE_CONFIG_SMALL_MALLOC: {
186622
- sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
187167
+ sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int)!=0;
186623187168
break;
186624187169
}
186625187170
case SQLITE_CONFIG_PAGECACHE: {
186626187171
/* EVIDENCE-OF: R-18761-36601 There are three arguments to
186627187172
** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem),
@@ -192926,10 +193471,16 @@
192926193471
#ifndef SQLITE_CORE
192927193472
/* # include "sqlite3ext.h" */
192928193473
SQLITE_EXTENSION_INIT1
192929193474
#endif
192930193475
193476
+
193477
+/*
193478
+** Assume any b-tree layer with more levels than this is corrupt.
193479
+*/
193480
+#define FTS3_MAX_BTREE_HEIGHT 48
193481
+
192931193482
typedef struct Fts3HashWrapper Fts3HashWrapper;
192932193483
struct Fts3HashWrapper {
192933193484
Fts3Hash hash; /* Hash table */
192934193485
int nRef; /* Number of pointers to this object */
192935193486
};
@@ -194642,11 +195193,15 @@
194642195193
int iHeight; /* Height of this node in tree */
194643195194
194644195195
assert( piLeaf || piLeaf2 );
194645195196
194646195197
fts3GetVarint32(zNode, &iHeight);
194647
- rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
195198
+ if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
195199
+ rc = FTS_CORRUPT_VTAB;
195200
+ }else{
195201
+ rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
195202
+ }
194648195203
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
194649195204
194650195205
if( rc==SQLITE_OK && iHeight>1 ){
194651195206
char *zBlob = 0; /* Blob read from %_segments table */
194652195207
int nBlob = 0; /* Size of zBlob in bytes */
@@ -194687,12 +195242,17 @@
194687195242
char **pp, /* IN/OUT: Output pointer */
194688195243
sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
194689195244
sqlite3_int64 iVal /* Write this value to the list */
194690195245
){
194691195246
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
194692
- *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
194693
- *piPrev = iVal;
195247
+ if( iVal-(*piPrev)>=0 ){
195248
+ /* Refuse to write a negative delta integer. This only happens with a
195249
+ ** corrupt db (see the assert above) and can cause buffer overwrites
195250
+ ** in some cases. */
195251
+ *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
195252
+ *piPrev = iVal;
195253
+ }
194694195254
}
194695195255
194696195256
/*
194697195257
** When this function is called, *ppPoslist is assumed to point to the
194698195258
** start of a position-list. After it returns, *ppPoslist points to the
@@ -199171,11 +199731,11 @@
199171199731
break;
199172199732
199173199733
/* State 3. The integer just read is a column number. */
199174199734
default: assert( eState==3 );
199175199735
iCol = (int)v;
199176
- if( iCol<1 ){
199736
+ if( iCol<1 || iCol>(pFts3->nColumn+1) ){
199177199737
rc = SQLITE_CORRUPT_VTAB;
199178199738
break;
199179199739
}
199180199740
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
199181199741
pCsr->aStat[iCol+1].nDoc++;
@@ -199861,10 +200421,11 @@
199861200421
/* If this is a "NEAR" keyword, check for an explicit nearness. */
199862200422
if( pKey->eType==FTSQUERY_NEAR ){
199863200423
assert( nKey==4 );
199864200424
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
199865200425
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
200426
+ if( nNear>=1000000000 ) nNear = 1000000000;
199866200427
}
199867200428
}
199868200429
199869200430
/* At this point this is probably a keyword. But for that to be true,
199870200431
** the next byte must contain either whitespace, an open or close
@@ -206107,10 +206668,14 @@
206107206668
iMul = -1;
206108206669
}
206109206670
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
206110206671
iVal = iVal*10 + (zText[i] - '0');
206111206672
}
206673
+
206674
+ /* This if() clause is just to avoid an integer overflow. The record is
206675
+ ** corrupt in this case. */
206676
+ if( (i64)iVal==SMALLEST_INT64 ) iMul = 1;
206112206677
*pnByte = ((i64)iVal * (i64)iMul);
206113206678
}
206114206679
}
206115206680
206116206681
@@ -208969,14 +209534,13 @@
208969209534
*/
208970209535
208971209536
/*
208972209537
** Allocate a two-slot MatchinfoBuffer object.
208973209538
*/
208974
-static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
209539
+static MatchinfoBuffer *fts3MIBufferNew(i64 nElem, const char *zMatchinfo){
208975209540
MatchinfoBuffer *pRet;
208976
- sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
208977
- + SZ_MATCHINFOBUFFER(1);
209541
+ sqlite3_int64 nByte = sizeof(u32) * (2*(i64)nElem+1) + SZ_MATCHINFOBUFFER(1);
208978209542
sqlite3_int64 nStr = strlen(zMatchinfo);
208979209543
208980209544
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
208981209545
if( pRet ){
208982209546
pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
@@ -209724,11 +210288,11 @@
209724210288
int nHit = fts3ColumnlistCount(&pIter);
209725210289
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
209726210290
if( p->flag==FTS3_MATCHINFO_LHITS ){
209727210291
p->aMatchinfo[iStart + iCol] = (u32)nHit;
209728210292
}else if( nHit ){
209729
- p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
210293
+ p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
209730210294
}
209731210295
}
209732210296
assert( *pIter==0x00 || *pIter==0x01 );
209733210297
if( *pIter!=0x01 ) break;
209734210298
pIter++;
@@ -209843,12 +210407,12 @@
209843210407
}
209844210408
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg);
209845210409
return SQLITE_ERROR;
209846210410
}
209847210411
209848
-static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
209849
- size_t nVal; /* Number of integers output by cArg */
210412
+static i64 fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
210413
+ i64 nVal; /* Number of integers output by cArg */
209850210414
209851210415
switch( cArg ){
209852210416
case FTS3_MATCHINFO_NDOC:
209853210417
case FTS3_MATCHINFO_NPHRASE:
209854210418
case FTS3_MATCHINFO_NCOL:
@@ -209860,20 +210424,20 @@
209860210424
case FTS3_MATCHINFO_LCS:
209861210425
nVal = pInfo->nCol;
209862210426
break;
209863210427
209864210428
case FTS3_MATCHINFO_LHITS:
209865
- nVal = (size_t)pInfo->nCol * pInfo->nPhrase;
210429
+ nVal = (i64)pInfo->nCol * pInfo->nPhrase;
209866210430
break;
209867210431
209868210432
case FTS3_MATCHINFO_LHITS_BM:
209869
- nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
210433
+ nVal = (i64)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
209870210434
break;
209871210435
209872210436
default:
209873210437
assert( cArg==FTS3_MATCHINFO_HITS );
209874
- nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3;
210438
+ nVal = (i64)pInfo->nCol * pInfo->nPhrase * 3;
209875210439
break;
209876210440
}
209877210441
209878210442
return nVal;
209879210443
}
@@ -210151,11 +210715,11 @@
210151210715
}
210152210716
break;
210153210717
210154210718
case FTS3_MATCHINFO_LHITS_BM:
210155210719
case FTS3_MATCHINFO_LHITS: {
210156
- size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
210720
+ i64 nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
210157210721
memset(pInfo->aMatchinfo, 0, nZero);
210158210722
rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
210159210723
break;
210160210724
}
210161210725
@@ -210220,11 +210784,11 @@
210220210784
** matchinfo function has been called for this query. In this case
210221210785
** allocate the array used to accumulate the matchinfo data and
210222210786
** initialize those elements that are constant for every row.
210223210787
*/
210224210788
if( pCsr->pMIBuffer==0 ){
210225
- size_t nMatchinfo = 0; /* Number of u32 elements in match-info */
210789
+ i64 nMatchinfo = 0; /* Number of u32 elements in match-info */
210226210790
int i; /* Used to iterate through zArg */
210227210791
210228210792
/* Determine the number of phrases in the query */
210229210793
pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr);
210230210794
sInfo.nPhrase = pCsr->nPhrase;
@@ -212214,11 +212778,11 @@
212214212778
case SQLITE_NULL: {
212215212779
jsonAppendRawNZ(p, "null", 4);
212216212780
break;
212217212781
}
212218212782
case SQLITE_FLOAT: {
212219
- jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
212783
+ jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
212220212784
break;
212221212785
}
212222212786
case SQLITE_INTEGER: {
212223212787
const char *z = (const char*)sqlite3_value_text(pValue);
212224212788
u32 n = (u32)sqlite3_value_bytes(pValue);
@@ -213528,13 +214092,14 @@
213528214092
*/
213529214093
static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
213530214094
u8 x;
213531214095
u32 sz;
213532214096
u32 n;
213533
- assert( i<=pParse->nBlob );
213534
- x = pParse->aBlob[i]>>4;
213535
- if( x<=11 ){
214097
+ if( i>=pParse->nBlob ){
214098
+ *pSz = 0;
214099
+ return 0;
214100
+ }else if( (x = pParse->aBlob[i]>>4)<=11 ){
213536214101
sz = x;
213537214102
n = 1;
213538214103
}else if( x==12 ){
213539214104
if( i+1>=pParse->nBlob ){
213540214105
*pSz = 0;
@@ -213744,11 +214309,11 @@
213744214309
break;
213745214310
case '\n':
213746214311
break;
213747214312
case 0xe2:
213748214313
/* '\' followed by either U+2028 or U+2029 is ignored as
213749
- ** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29.
214314
+ ** whitespace. Note that in UTF8, U+2028 is 0xe2 0x80 0x29.
213750214315
** U+2029 is the same except for the last byte */
213751214316
if( sz2<4
213752214317
|| 0x80!=(u8)zIn[2]
213753214318
|| (0xa8!=(u8)zIn[3] && 0xa9!=(u8)zIn[3])
213754214319
){
@@ -216313,15 +216878,13 @@
216313216878
char c;
216314216879
JsonString *pStr;
216315216880
UNUSED_PARAMETER(argc);
216316216881
UNUSED_PARAMETER(argv);
216317216882
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
216318
-#ifdef NEVER
216319216883
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
216320216884
** always have been called to initialize it */
216321216885
if( NEVER(!pStr) ) return;
216322
-#endif
216323216886
z = pStr->zBuf;
216324216887
for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
216325216888
if( c=='"' ){
216326216889
inStr = !inStr;
216327216890
}else if( c=='\\' ){
@@ -216346,10 +216909,17 @@
216346216909
216347216910
/*
216348216911
** json_group_obj(NAME,VALUE)
216349216912
**
216350216913
** Return a JSON object composed of all names and values in the aggregate.
216914
+**
216915
+** Rows for which NAME is NULL do not result in a new entry. However, we
216916
+** do initially insert a "@" entry into the growing string for each null entry
216917
+** and change the first character of the string to "@" to signal that the
216918
+** string contains null entries. The "@" markers are needed in order to
216919
+** correctly process xInverse() requests. The initial "@" is converted
216920
+** back into "{" and the "@" null values are removed by jsonObjectCompute().
216351216921
*/
216352216922
static void jsonObjectStep(
216353216923
sqlite3_context *ctx,
216354216924
int argc,
216355216925
sqlite3_value **argv
@@ -216363,49 +216933,97 @@
216363216933
z = (const char*)sqlite3_value_text(argv[0]);
216364216934
n = sqlite3Strlen30(z);
216365216935
if( pStr->zBuf==0 ){
216366216936
jsonStringInit(pStr, ctx);
216367216937
jsonAppendChar(pStr, '{');
216368
- }else if( pStr->nUsed>1 && z!=0 ){
216938
+ }else if( pStr->nUsed>1 ){
216369216939
jsonAppendChar(pStr, ',');
216370216940
}
216371216941
pStr->pCtx = ctx;
216372216942
if( z!=0 ){
216373216943
jsonAppendString(pStr, z, n);
216374216944
jsonAppendChar(pStr, ':');
216375216945
jsonAppendSqlValue(pStr, argv[1]);
216946
+ }else{
216947
+ pStr->zBuf[0] = '@';
216948
+ jsonAppendRawNZ(pStr, "@", 1);
216376216949
}
216377216950
}
216378216951
}
216379216952
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
216380216953
JsonString *pStr;
216381216954
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
216382216955
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
216383216956
if( pStr ){
216384
- jsonAppendRawNZ(pStr, "}", 2);
216385
- jsonStringTrimOneChar(pStr);
216957
+ JsonString *pOgStr = pStr;
216958
+ JsonString tmpStr;
216959
+ jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
216960
+ jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
216386216961
pStr->pCtx = ctx;
216387216962
if( pStr->eErr ){
216388216963
jsonReturnString(pStr, 0, 0);
216389216964
return;
216390
- }else if( flags & JSON_BLOB ){
216965
+ }
216966
+ if( pStr->zBuf[0]!='{' ){
216967
+ /* The string contains null entries that need to be removed */
216968
+ u64 i, j;
216969
+ int inStr = 0;
216970
+ if( !isFinal ){
216971
+ /* Work with a temporary copy of the string if this is not the
216972
+ ** final result */
216973
+ jsonStringInit(&tmpStr, ctx);
216974
+ jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
216975
+ pStr = &tmpStr;
216976
+ if( pStr->eErr ){
216977
+ jsonReturnString(pStr, 0, 0);
216978
+ return;
216979
+ }
216980
+ jsonStringTrimOneChar(pStr); /* Remove zero terminator */
216981
+ }
216982
+ /* Fix up the string by changing the initial "@" flag back to
216983
+ ** to "{" and removing all subsequence "@" entries, with their
216984
+ ** associated comma delimeters. */
216985
+ pStr->zBuf[0] = '{';
216986
+ for(i=j=1; i<pStr->nUsed; i++){
216987
+ char c = pStr->zBuf[i];
216988
+ if( c=='"' ){
216989
+ inStr = !inStr;
216990
+ pStr->zBuf[j++] = '"';
216991
+ }else if( c=='\\' ){
216992
+ pStr->zBuf[j++] = '\\';
216993
+ pStr->zBuf[j++] = pStr->zBuf[++i];
216994
+ }else if( c=='@' && !inStr ){
216995
+ assert( i+1<pStr->nUsed );
216996
+ if( pStr->zBuf[i+1]==',' ){
216997
+ i++;
216998
+ }else if( pStr->zBuf[j-1]==',' ){
216999
+ j--;
217000
+ }
217001
+ }else{
217002
+ pStr->zBuf[j++] = c;
217003
+ }
217004
+ }
217005
+ pStr->zBuf[j] = 0; /* Restore zero terminator */
217006
+ pStr->nUsed = j; /* Truncate the string */
217007
+ }
217008
+ if( flags & JSON_BLOB ){
216391217009
jsonReturnStringAsBlob(pStr);
216392217010
if( isFinal ){
216393217011
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
216394217012
}else{
216395
- jsonStringTrimOneChar(pStr);
217013
+ jsonStringTrimOneChar(pOgStr);
216396217014
}
216397
- return;
216398217015
}else if( isFinal ){
216399217016
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
216400217017
pStr->bStatic ? SQLITE_TRANSIENT :
216401217018
sqlite3RCStrUnref);
216402217019
pStr->bStatic = 1;
216403217020
}else{
216404217021
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
216405
- jsonStringTrimOneChar(pStr);
217022
+ jsonStringTrimOneChar(pOgStr);
216406217023
}
217024
+ if( pStr!=pOgStr ) jsonStringReset(pStr);
216407217025
}else if( flags & JSON_BLOB ){
216408217026
static const unsigned char emptyObject = 0x0c;
216409217027
sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
216410217028
}else{
216411217029
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
@@ -216604,10 +217222,19 @@
216604217222
}else{
216605217223
jsonPrintf(sz+2,&p->path,".%.*s", sz, z);
216606217224
}
216607217225
}
216608217226
}
217227
+
217228
+/* Report a "malformed JSON" or OOM error against the cursor.
217229
+*/
217230
+static int jsonEachMalformedInput(sqlite3_vtab_cursor *cur){
217231
+ sqlite3_free(cur->pVtab->zErrMsg);
217232
+ cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
217233
+ jsonEachCursorReset((JsonEachCursor*)cur);
217234
+ return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
217235
+}
216609217236
216610217237
/* Advance the cursor to the next element for json_tree() */
216611217238
static int jsonEachNext(sqlite3_vtab_cursor *cur){
216612217239
JsonEachCursor *p = (JsonEachCursor*)cur;
216613217240
int rc = SQLITE_OK;
@@ -216616,10 +217243,11 @@
216616217243
u8 levelChange = 0;
216617217244
u32 n, sz = 0;
216618217245
u32 i = jsonSkipLabel(p);
216619217246
x = p->sParse.aBlob[i] & 0x0f;
216620217247
n = jsonbPayloadSize(&p->sParse, i, &sz);
217248
+ if( n==0 )return jsonEachMalformedInput(cur);
216621217249
if( x==JSONB_OBJECT || x==JSONB_ARRAY ){
216622217250
JsonParent *pParent;
216623217251
if( p->nParent>=p->nParentAlloc ){
216624217252
JsonParent *pNew;
216625217253
u64 nNew;
@@ -216661,10 +217289,11 @@
216661217289
}
216662217290
}else{
216663217291
u32 n, sz = 0;
216664217292
u32 i = jsonSkipLabel(p);
216665217293
n = jsonbPayloadSize(&p->sParse, i, &sz);
217294
+ if( n==0 )return jsonEachMalformedInput(cur);
216666217295
p->i = i + n + sz;
216667217296
}
216668217297
if( p->eType==JSONB_ARRAY && p->nParent ){
216669217298
p->aParent[p->nParent-1].iKey++;
216670217299
}
@@ -216897,11 +217526,11 @@
216897217526
}
216898217527
if( jsonConvertTextToBlob(&p->sParse, 0) ){
216899217528
if( p->sParse.oom ){
216900217529
return SQLITE_NOMEM;
216901217530
}
216902
- goto json_each_malformed_input;
217531
+ return jsonEachMalformedInput(cur);
216903217532
}
216904217533
}
216905217534
if( idxNum==3 ){
216906217535
zRoot = (const char*)sqlite3_value_text(argv[1]);
216907217536
if( zRoot==0 ) return SQLITE_OK;
@@ -216958,16 +217587,10 @@
216958217587
p->aParent[0].iEnd = p->iEnd;
216959217588
p->aParent[0].iHead = p->i;
216960217589
p->aParent[0].iValue = i;
216961217590
}
216962217591
return SQLITE_OK;
216963
-
216964
-json_each_malformed_input:
216965
- sqlite3_free(cur->pVtab->zErrMsg);
216966
- cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
216967
- jsonEachCursorReset(p);
216968
- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
216969217592
}
216970217593
216971217594
/* The methods of the json_each virtual table */
216972217595
static sqlite3_module jsonEachModule = {
216973217596
0, /* iVersion */
@@ -217253,11 +217876,11 @@
217253217876
u8 nDim; /* Number of dimensions */
217254217877
u8 nDim2; /* Twice the number of dimensions */
217255217878
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
217256217879
u8 nBytesPerCell; /* Bytes consumed per cell */
217257217880
u8 inWrTrans; /* True if inside write transaction */
217258
- u8 nAux; /* # of auxiliary columns in %_rowid */
217881
+ u16 nAux; /* # of auxiliary columns in %_rowid */
217259217882
#ifdef SQLITE_ENABLE_GEOPOLY
217260217883
u8 nAuxNotNull; /* Number of initial not-null aux columns */
217261217884
#endif
217262217885
#ifdef SQLITE_DEBUG
217263217886
u8 bCorrupt; /* Shadow table corruption detected */
@@ -217848,10 +218471,13 @@
217848218471
** be because the shadow tables hold erroneous data. */
217849218472
if( rc==SQLITE_ERROR ){
217850218473
rc = SQLITE_CORRUPT_VTAB;
217851218474
RTREE_IS_CORRUPT(pRtree);
217852218475
}
218476
+ }else if( iNode<=0 ){
218477
+ RTREE_IS_CORRUPT(pRtree);
218478
+ rc = SQLITE_CORRUPT_VTAB;
217853218479
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
217854218480
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
217855218481
if( !pNode ){
217856218482
rc = SQLITE_NOMEM;
217857218483
}else{
@@ -218489,11 +219115,11 @@
218489219115
i64 iRowid,
218490219116
int *piIndex
218491219117
){
218492219118
int ii;
218493219119
int nCell = NCELL(pNode);
218494
- assert( nCell<200 );
219120
+ assert( nCell<65536 && nCell>=0 );
218495219121
for(ii=0; ii<nCell; ii++){
218496219122
if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
218497219123
*piIndex = ii;
218498219124
return SQLITE_OK;
218499219125
}
@@ -218751,11 +219377,14 @@
218751219377
while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
218752219378
u8 *pCellData;
218753219379
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
218754219380
if( rc ) return rc;
218755219381
nCell = NCELL(pNode);
218756
- assert( nCell<200 );
219382
+ if( nCell>RTREE_MAXCELLS ){
219383
+ RTREE_IS_CORRUPT(pRtree);
219384
+ return SQLITE_CORRUPT_VTAB;
219385
+ }
218757219386
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
218758219387
while( p->iCell<nCell ){
218759219388
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
218760219389
eWithin = FULLY_WITHIN;
218761219390
for(ii=0; ii<nConstraint; ii++){
@@ -220728,11 +221357,11 @@
220728221357
"Too few columns for an rtree table", /* 2 */
220729221358
"Too many columns for an rtree table", /* 3 */
220730221359
"Auxiliary rtree columns must be last" /* 4 */
220731221360
};
220732221361
220733
- assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
221362
+ assert( RTREE_MAX_AUX_COLUMN<256 );
220734221363
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
220735221364
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
220736221365
return SQLITE_ERROR;
220737221366
}
220738221367
@@ -222646,10 +223275,15 @@
222646223275
sqlite3_int64 nName; /* Length of string argv[2] */
222647223276
sqlite3_str *pSql;
222648223277
char *zSql;
222649223278
int ii;
222650223279
(void)pAux;
223280
+
223281
+ if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
223282
+ *pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
223283
+ return SQLITE_ERROR;
223284
+ }
222651223285
222652223286
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
222653223287
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
222654223288
222655223289
/* Allocate the sqlite3_vtab structure */
@@ -223524,10 +224158,13 @@
223524224158
if( c>=0xc0 ){ \
223525224159
c = icuUtf8Trans1[c-0xc0]; \
223526224160
while( (*zIn & 0xc0)==0x80 ){ \
223527224161
c = (c<<6) + (0x3f & *(zIn++)); \
223528224162
} \
224163
+ if( c<0x80 \
224164
+ || (c&0xFFFFF800)==0xD800 \
224165
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
223529224166
}
223530224167
223531224168
#define SQLITE_ICU_SKIP_UTF8(zIn) \
223532224169
assert( *zIn ); \
223533224170
if( *(zIn++)>=0xc0 ){ \
@@ -223781,11 +224418,11 @@
223781224418
*/
223782224419
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
223783224420
const UChar *zInput; /* Pointer to input string */
223784224421
UChar *zOutput = 0; /* Pointer to output buffer */
223785224422
int nInput; /* Size of utf-16 input string in bytes */
223786
- int nOut; /* Size of output buffer in bytes */
224423
+ sqlite3_int64 nOut; /* Size of output buffer in bytes */
223787224424
int cnt;
223788224425
int bToUpper; /* True for toupper(), false for tolower() */
223789224426
UErrorCode status;
223790224427
const char *zLocale = 0;
223791224428
@@ -223804,22 +224441,22 @@
223804224441
sqlite3_result_text16(p, "", 0, SQLITE_STATIC);
223805224442
return;
223806224443
}
223807224444
223808224445
for(cnt=0; cnt<2; cnt++){
223809
- UChar *zNew = sqlite3_realloc(zOutput, nOut);
224446
+ UChar *zNew = sqlite3_realloc64(zOutput, nOut);
223810224447
if( zNew==0 ){
223811224448
sqlite3_free(zOutput);
223812224449
sqlite3_result_error_nomem(p);
223813224450
return;
223814224451
}
223815224452
zOutput = zNew;
223816224453
status = U_ZERO_ERROR;
223817224454
if( bToUpper ){
223818
- nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
224455
+ nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
223819224456
}else{
223820
- nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
224457
+ nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
223821224458
}
223822224459
223823224460
if( U_SUCCESS(status) ){
223824224461
sqlite3_result_text16(p, zOutput, nOut, xFree);
223825224462
}else if( status==U_BUFFER_OVERFLOW_ERROR ){
@@ -223935,10 +224572,11 @@
223935224572
for(i=0; i<sizeof(aStrength)/sizeof(aStrength[0]); i++){
223936224573
sqlite3_str_appendf(pStr, " %s", aStrength[i].zName);
223937224574
}
223938224575
sqlite3_result_error(p, sqlite3_str_value(pStr), -1);
223939224576
sqlite3_free(sqlite3_str_finish(pStr));
224577
+ ucol_close(pUCollator);
223940224578
return;
223941224579
}
223942224580
}
223943224581
rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
223944224582
icuCollationColl, icuCollationDel
@@ -225428,20 +226066,30 @@
225428226066
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
225429226067
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
225430226068
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
225431226069
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
225432226070
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
226071
+
226072
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226073
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226074
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226075
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226076
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226077
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226078
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226079
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
225433226080
};
225434226081
unsigned int v = 0;
225435226082
int c;
225436226083
unsigned char *z = (unsigned char*)*pz;
225437
- unsigned char *zStart = z;
225438
- while( (c = zValue[0x7f&*(z++)])>=0 ){
225439
- v = (v<<6) + c;
226084
+ unsigned char *zEnd = z + (*pLen);
226085
+ while( z<zEnd && (c = zValue[*z])>=0 ){
226086
+ v = (v<<6) + c;
226087
+ z++;
225440226088
}
225441
- z--;
225442
- *pLen -= (int)(z - zStart);
226089
+
226090
+ *pLen -= (int)(z - (unsigned char*)*pz);
225443226091
*pz = (char*)z;
225444226092
return v;
225445226093
}
225446226094
225447226095
#if RBU_ENABLE_DELTA_CKSUM
@@ -225513,23 +226161,24 @@
225513226161
#if RBU_ENABLE_DELTA_CKSUM
225514226162
char *zOrigOut = zOut;
225515226163
#endif
225516226164
225517226165
limit = rbuDeltaGetInt(&zDelta, &lenDelta);
225518
- if( *zDelta!='\n' ){
226166
+ if( lenDelta<=0 || *zDelta!='\n' ){
225519226167
/* ERROR: size integer not terminated by "\n" */
225520226168
return -1;
225521226169
}
225522226170
zDelta++; lenDelta--;
225523226171
while( *zDelta && lenDelta>0 ){
225524226172
unsigned int cnt, ofst;
225525226173
cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
226174
+ if( lenDelta<=0 ) return -1;
225526226175
switch( zDelta[0] ){
225527226176
case '@': {
225528226177
zDelta++; lenDelta--;
225529226178
ofst = rbuDeltaGetInt(&zDelta, &lenDelta);
225530
- if( lenDelta>0 && zDelta[0]!=',' ){
226179
+ if( lenDelta>0 || zDelta[0]!=',' ){
225531226180
/* ERROR: copy command not terminated by ',' */
225532226181
return -1;
225533226182
}
225534226183
zDelta++; lenDelta--;
225535226184
total += cnt;
@@ -225550,11 +226199,11 @@
225550226199
total += cnt;
225551226200
if( total>limit ){
225552226201
/* ERROR: insert command gives an output larger than predicted */
225553226202
return -1;
225554226203
}
225555
- if( (int)cnt>lenDelta ){
226204
+ if( (i64)cnt>(i64)lenDelta ){
225556226205
/* ERROR: insert count exceeds size of delta */
225557226206
return -1;
225558226207
}
225559226208
memcpy(zOut, zDelta, cnt);
225560226209
zOut += cnt;
@@ -225588,11 +226237,11 @@
225588226237
}
225589226238
225590226239
static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){
225591226240
int size;
225592226241
size = rbuDeltaGetInt(&zDelta, &lenDelta);
225593
- if( *zDelta!='\n' ){
226242
+ if( lenDelta<=0 || *zDelta!='\n' ){
225594226243
/* ERROR: size integer not terminated by "\n" */
225595226244
return -1;
225596226245
}
225597226246
return size;
225598226247
}
@@ -225636,11 +226285,11 @@
225636226285
if( nOut<0 ){
225637226286
sqlite3_result_error(context, "corrupt fossil delta", -1);
225638226287
return;
225639226288
}
225640226289
225641
- aOut = sqlite3_malloc(nOut+1);
226290
+ aOut = sqlite3_malloc64((i64)nOut+1);
225642226291
if( aOut==0 ){
225643226292
sqlite3_result_error_nomem(context);
225644226293
}else{
225645226294
nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut);
225646226295
if( nOut2!=nOut ){
@@ -231535,16 +232184,17 @@
231535232184
if( NEVER(pBt==0) ) return SQLITE_OK;
231536232185
pCsr->pPager = sqlite3BtreePager(pBt);
231537232186
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
231538232187
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
231539232188
if( idxNum & 1 ){
232189
+ i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
231540232190
assert( argc>(idxNum>>1) );
231541
- pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
231542
- if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
232191
+ if( iPg<1 || iPg>pCsr->mxPgno ){
231543232192
pCsr->pgno = 1;
231544232193
pCsr->mxPgno = 0;
231545232194
}else{
232195
+ pCsr->pgno = (Pgno)iPg;
231546232196
pCsr->mxPgno = pCsr->pgno;
231547232197
}
231548232198
}else{
231549232199
assert( pCsr->pgno==1 );
231550232200
}
@@ -231620,10 +232270,11 @@
231620232270
sqlite3_value **argv,
231621232271
sqlite_int64 *pRowid
231622232272
){
231623232273
DbpageTable *pTab = (DbpageTable *)pVtab;
231624232274
Pgno pgno;
232275
+ sqlite3_int64 pgno64;
231625232276
DbPage *pDbPage = 0;
231626232277
int rc = SQLITE_OK;
231627232278
char *zErr = 0;
231628232279
int iDb;
231629232280
Btree *pBt;
@@ -231639,15 +232290,15 @@
231639232290
if( argc==1 ){
231640232291
zErr = "cannot delete";
231641232292
goto update_fail;
231642232293
}
231643232294
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
231644
- pgno = (Pgno)sqlite3_value_int64(argv[2]);
232295
+ pgno64 = sqlite3_value_int64(argv[2]);
231645232296
isInsert = 1;
231646232297
}else{
231647
- pgno = (Pgno)sqlite3_value_int64(argv[0]);
231648
- if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
232298
+ pgno64 = (Pgno)sqlite3_value_int64(argv[0]);
232299
+ if( sqlite3_value_int64(argv[1])!=pgno64 ){
231649232300
zErr = "cannot insert";
231650232301
goto update_fail;
231651232302
}
231652232303
isInsert = 0;
231653232304
}
@@ -231660,14 +232311,15 @@
231660232311
zErr = "no such schema";
231661232312
goto update_fail;
231662232313
}
231663232314
}
231664232315
pBt = pTab->db->aDb[iDb].pBt;
231665
- if( pgno<1 || NEVER(pBt==0) ){
232316
+ if( pgno64<1 || pgno64>4294967294 || NEVER(pBt==0) ){
231666232317
zErr = "bad page number";
231667232318
goto update_fail;
231668232319
}
232320
+ pgno = (Pgno)pgno64;
231669232321
szPage = sqlite3BtreeGetPageSize(pBt);
231670232322
if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
231671232323
|| sqlite3_value_bytes(argv[3])!=szPage
231672232324
){
231673232325
if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert && pgno>1 ){
@@ -232688,11 +233340,13 @@
232688233340
/*
232689233341
** Read a varint value from aBuf[] into *piVal. Return the number of
232690233342
** bytes read.
232691233343
*/
232692233344
static int sessionVarintGet(const u8 *aBuf, int *piVal){
232693
- return getVarint32(aBuf, *piVal);
233345
+ int ret = getVarint32(aBuf, *piVal);
233346
+ *piVal = (*piVal & 0x7FFFFFFF);
233347
+ return ret;
232694233348
}
232695233349
232696233350
/*
232697233351
** Read a varint value from buffer aBuf[], size nBuf bytes, into *piVal.
232698233352
** Return the number of bytes read.
@@ -232703,11 +233357,11 @@
232703233357
memset(aCopy, 0, sizeof(aCopy));
232704233358
if( nBuf<sizeof(aCopy) ){
232705233359
memcpy(aCopy, aBuf, nBuf);
232706233360
aRead = aCopy;
232707233361
}
232708
- return getVarint32(aRead, *piVal);
233362
+ return sessionVarintGet(aRead, piVal);
232709233363
}
232710233364
232711233365
/* Load an unaligned and unsigned 32-bit integer */
232712233366
#define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
232713233367
@@ -233886,10 +234540,20 @@
233886234540
}
233887234541
sqlite3_free(sql.aBuf);
233888234542
233889234543
return rc;
233890234544
}
234545
+
234546
+/*
234547
+** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
234548
+** called, set it to the results of the sqlite3_finalize() call. Or, if
234549
+** it is already set to an error code, leave it as is.
234550
+*/
234551
+static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
234552
+ int rc = sqlite3_finalize(pStmt);
234553
+ if( *pRc==SQLITE_OK ) *pRc = rc;
234554
+}
233891234555
233892234556
/*
233893234557
** Table pTab has one or more existing change-records with old.* records
233894234558
** with fewer than pTab->nCol columns. This function updates all such
233895234559
** change-records with the default values for the missing columns.
@@ -233909,13 +234573,12 @@
233909234573
}
233910234574
}
233911234575
}
233912234576
}
233913234577
234578
+ sessionFinalizeStmt(pStmt, &rc);
233914234579
pSession->rc = rc;
233915
- rc = sqlite3_finalize(pStmt);
233916
- if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
233917234580
return pSession->rc;
233918234581
}
233919234582
233920234583
/*
233921234584
** Versions of the four methods in object SessionHook for use with the
@@ -234479,11 +235142,11 @@
234479235142
234480235143
if( zStmt==0 ){
234481235144
rc = SQLITE_NOMEM;
234482235145
}else{
234483235146
sqlite3_stmt *pStmt;
234484
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
235147
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
234485235148
if( rc==SQLITE_OK ){
234486235149
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
234487235150
pDiffCtx->pStmt = pStmt;
234488235151
pDiffCtx->nOldOff = 0;
234489235152
pDiffCtx->bRowid = pTab->bRowid;
@@ -234542,11 +235205,11 @@
234542235205
);
234543235206
if( zStmt==0 || z1==0 || z2==0 ){
234544235207
rc = SQLITE_NOMEM;
234545235208
}else{
234546235209
sqlite3_stmt *pStmt;
234547
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
235210
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
234548235211
234549235212
if( rc==SQLITE_OK ){
234550235213
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
234551235214
pDiffCtx->pStmt = pStmt;
234552235215
pDiffCtx->nOldOff = pTab->nCol;
@@ -235237,15 +235900,15 @@
235237235900
sessionAppendStr(&pkvar,
235238235901
"?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc
235239235902
);
235240235903
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
235241235904
}else{
235242
- #if 0
235905
+#if 0
235243235906
if( bRowid ){
235244235907
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
235245235908
}
235246
- #endif
235909
+#endif
235247235910
for(i=0; i<nCol; i++){
235248235911
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
235249235912
sessionAppendIdent(&cols, azCol[i], &rc);
235250235913
if( abPK[i] ){
235251235914
sessionAppendStr(&pkfield, zSep, &rc);
@@ -236036,21 +236699,25 @@
236036236699
int i;
236037236700
for(i=0; rc==SQLITE_OK && i<nCol; i++){
236038236701
int eType;
236039236702
rc = sessionInputBuffer(pIn, nByte + 10);
236040236703
if( rc==SQLITE_OK ){
236041
- eType = pIn->aData[pIn->iNext + nByte++];
236042
- if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
236043
- int n;
236044
- int nRem = pIn->nData - (pIn->iNext + nByte);
236045
- nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem, &n);
236046
- nByte += n;
236047
- rc = sessionInputBuffer(pIn, nByte);
236048
- }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
236049
- nByte += 8;
236050
- }else if( eType!=0 && eType!=SQLITE_NULL ){
236704
+ if( pIn->iNext+nByte>=pIn->nData ){
236051236705
rc = SQLITE_CORRUPT_BKPT;
236706
+ }else{
236707
+ eType = pIn->aData[pIn->iNext + nByte++];
236708
+ if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
236709
+ int n;
236710
+ int nRem = pIn->nData - (pIn->iNext + nByte);
236711
+ nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem,&n);
236712
+ nByte += n;
236713
+ rc = sessionInputBuffer(pIn, nByte);
236714
+ }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
236715
+ nByte += 8;
236716
+ }else if( eType!=0 && eType!=SQLITE_NULL ){
236717
+ rc = SQLITE_CORRUPT_BKPT;
236718
+ }
236052236719
}
236053236720
}
236054236721
if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
236055236722
rc = SQLITE_CORRUPT_BKPT;
236056236723
}
@@ -236495,11 +237162,17 @@
236495237162
while( 1 ){
236496237163
u8 eType;
236497237164
236498237165
/* Test for EOF. */
236499237166
if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
236500
- if( pInput->iNext>=pInput->nData ) break;
237167
+ if( pInput->iNext+1>=pInput->nData ){
237168
+ if( pInput->iNext!=pInput->nData ){
237169
+ rc = SQLITE_CORRUPT_BKPT;
237170
+ goto finished_invert;
237171
+ }
237172
+ break;
237173
+ }
236501237174
eType = pInput->aData[pInput->iNext];
236502237175
236503237176
switch( eType ){
236504237177
case 'T': {
236505237178
/* A 'table' record consists of:
@@ -236691,10 +237364,11 @@
236691237364
SessionBuffer constraints; /* Deferred constraints are stored here */
236692237365
SessionBuffer rebase; /* Rebase information (if any) here */
236693237366
u8 bRebaseStarted; /* If table header is already in rebase */
236694237367
u8 bRebase; /* True to collect rebase information */
236695237368
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
237369
+ u8 bNoUpdateLoop; /* No update-loop processing */
236696237370
int bRowid;
236697237371
char *zErr; /* Error message, if any */
236698237372
};
236699237373
236700237374
/* Number of prepared UPDATE statements to cache. */
@@ -237264,11 +237938,11 @@
237264237938
/* Instead of invoking the conflict handler, append the change blob
237265237939
** to the SessionApplyCtx.constraints buffer. */
237266237940
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
237267237941
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
237268237942
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
237269
- return SQLITE_OK;
237943
+ return rc;
237270237944
}else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
237271237945
|| eType==SQLITE_CHANGESET_CONFLICT
237272237946
){
237273237947
/* No other row with the new.* primary key. */
237274237948
res = xConflict(pCtx, eType+1, pIter);
@@ -237386,11 +238060,11 @@
237386238060
237387238061
/* Bind values to the UPDATE statement. */
237388238062
for(i=0; rc==SQLITE_OK && i<nCol; i++){
237389238063
sqlite3_value *pOld = sessionChangesetOld(pIter, i);
237390238064
sqlite3_value *pNew = sessionChangesetNew(pIter, i);
237391
- if( p->abPK[i] || (bPatchset==0 && pOld) ){
238065
+ if( pOld && (p->abPK[i] || bPatchset==0) ){
237392238066
rc = sessionBindValue(pUp, i*2+2, pOld);
237393238067
}
237394238068
if( rc==SQLITE_OK && pNew ){
237395238069
rc = sessionBindValue(pUp, i*2+1, pNew);
237396238070
}
@@ -237512,11 +238186,268 @@
237512238186
237513238187
return rc;
237514238188
}
237515238189
237516238190
/*
237517
-** Retry the changes accumulated in the pApply->constraints buffer.
238191
+** Create an iterator to iterate through the retry buffer pRetry.
238192
+*/
238193
+static int sessionRetryIterInit(
238194
+ SessionBuffer *pRetry, /* Buffer to iterate through */
238195
+ int bPatchset, /* True for patchset, false for changeset */
238196
+ const char *zTab, /* Table name */
238197
+ SessionApplyCtx *pApply, /* Session apply context */
238198
+ sqlite3_changeset_iter **ppIter /* OUT: New iterator */
238199
+){
238200
+ sqlite3_changeset_iter *pRet = 0;
238201
+ int rc = SQLITE_OK;
238202
+
238203
+ rc = sessionChangesetStart(
238204
+ &pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply-