Fossil SCM

Merge from trunk.

brickviking 2025-03-20 21:13 UTC bv-infotool merge
Commit 3eac814daa37e7dc3c0521b00cc6bf8167d7a4cf1644b67b35b62dfed19928b8
--- .fossil-settings/crlf-glob
+++ .fossil-settings/crlf-glob
@@ -1,5 +1,7 @@
11
compat/zlib/*
22
setup/fossil.iss
33
test/th1-docs-input.txt
44
test/th1-hooks-input.txt
5
+win/build32.bat
6
+win/build64.bat
57
win/buildmsvc.bat
68
--- .fossil-settings/crlf-glob
+++ .fossil-settings/crlf-glob
@@ -1,5 +1,7 @@
1 compat/zlib/*
2 setup/fossil.iss
3 test/th1-docs-input.txt
4 test/th1-hooks-input.txt
 
 
5 win/buildmsvc.bat
6
--- .fossil-settings/crlf-glob
+++ .fossil-settings/crlf-glob
@@ -1,5 +1,7 @@
1 compat/zlib/*
2 setup/fossil.iss
3 test/th1-docs-input.txt
4 test/th1-hooks-input.txt
5 win/build32.bat
6 win/build64.bat
7 win/buildmsvc.bat
8
--- extsrc/pikchr-worker.js
+++ extsrc/pikchr-worker.js
@@ -206,11 +206,11 @@
206206
data:{step: ++f.last.step, text: text||null}
207207
});
208208
}
209209
};
210210
211
- importScripts('pikchr-v7583078860.js');
211
+ importScripts('pikchr-v2813665466.js');
212212
/**
213213
initPikchrModule() is installed via pikchr.js due to
214214
building with:
215215
216216
emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initPikchrModule
217217
--- extsrc/pikchr-worker.js
+++ extsrc/pikchr-worker.js
@@ -206,11 +206,11 @@
206 data:{step: ++f.last.step, text: text||null}
207 });
208 }
209 };
210
211 importScripts('pikchr-v7583078860.js');
212 /**
213 initPikchrModule() is installed via pikchr.js due to
214 building with:
215
216 emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initPikchrModule
217
--- extsrc/pikchr-worker.js
+++ extsrc/pikchr-worker.js
@@ -206,11 +206,11 @@
206 data:{step: ++f.last.step, text: text||null}
207 });
208 }
209 };
210
211 importScripts('pikchr-v2813665466.js');
212 /**
213 initPikchrModule() is installed via pikchr.js due to
214 building with:
215
216 emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initPikchrModule
217
+31 -16
--- extsrc/pikchr.c
+++ extsrc/pikchr.c
@@ -25,17 +25,17 @@
2525
** The following is the concatenation of all %include directives from the
2626
** input grammar file:
2727
*/
2828
/************ Begin %include sections from the grammar ************************/
2929
#line 1 "VERSION.h"
30
-#define MANIFEST_UUID "052f07296e76ab2312caf2a4bf6237e574b3e533c7a36ee8f34db833baa3efb4"
31
-#define MANIFEST_VERSION "[052f07296e]"
32
-#define MANIFEST_DATE "2025-03-05 10:54:16"
30
+#define MANIFEST_UUID "8a43b020141f772a0ac45291a7fd73041d2efba5e3665c6bd2f334ad9b2e9845"
31
+#define MANIFEST_VERSION "[8a43b02014]"
32
+#define MANIFEST_DATE "2025-03-19 16:19:43"
3333
#define MANIFEST_YEAR "2025"
34
-#define MANIFEST_ISODATE "20250305105416"
35
-#define MANIFEST_NUMERIC_DATE 20250305
36
-#define MANIFEST_NUMERIC_TIME 105416
34
+#define MANIFEST_ISODATE "20250319161943"
35
+#define MANIFEST_NUMERIC_DATE 20250319
36
+#define MANIFEST_NUMERIC_TIME 161943
3737
#define RELEASE_VERSION "1.0"
3838
#define RELEASE_VERSION_NUMBER 10000
3939
#define RELEASE_RESOURCE_VERSION 1,0,0,0
4040
#define COMPILER "gcc-13.3.0"
4141
#line 2 "pikchr.y"
@@ -3687,42 +3687,57 @@
36873687
** than true arcs. Multiple reasons: (1) the legacy-PIC parameters
36883688
** that control arcs are obscure and I could not figure out what they
36893689
** mean based on available documentation. (2) Arcs are rarely used,
36903690
** and so do not seem that important.
36913691
*/
3692
-static PPoint arcControlPoint(int cw, PPoint f, PPoint t, PNum rScale){
3692
+static PPoint arcControlPoint(int cw, PPoint f, PPoint t){
36933693
PPoint m;
36943694
PNum dx, dy;
36953695
m.x = 0.5*(f.x+t.x);
36963696
m.y = 0.5*(f.y+t.y);
36973697
dx = t.x - f.x;
36983698
dy = t.y - f.y;
36993699
if( cw ){
3700
- m.x -= 0.5*rScale*dy;
3701
- m.y += 0.5*rScale*dx;
3700
+ m.x -= 0.5*dy;
3701
+ m.y += 0.5*dx;
37023702
}else{
3703
- m.x += 0.5*rScale*dy;
3704
- m.y -= 0.5*rScale*dx;
3703
+ m.x += 0.5*dy;
3704
+ m.y -= 0.5*dx;
37053705
}
37063706
return m;
37073707
}
37083708
static void arcCheck(Pik *p, PObj *pObj){
3709
- PPoint m;
3709
+ PPoint f, m, t;
3710
+ PNum sw;
3711
+ int i;
37103712
if( p->nTPath>2 ){
37113713
pik_error(p, &pObj->errTok, "arc geometry error");
37123714
return;
37133715
}
3714
- m = arcControlPoint(pObj->cw, p->aTPath[0], p->aTPath[1], 0.5);
3715
- pik_bbox_add_xy(&pObj->bbox, m.x, m.y);
3716
+ f = p->aTPath[0];
3717
+ t = p->aTPath[1];
3718
+ m = arcControlPoint(pObj->cw, f, t);
3719
+ sw = pObj->sw;
3720
+ for(i=1; i<16; i++){
3721
+ PNum t1, t2, a, b, c, x, y;
3722
+ t1 = 0.0625*i;
3723
+ t2 = 1.0 - t1;
3724
+ a = t2*t2;
3725
+ b = 2*t1*t2;
3726
+ c = t1*t1;
3727
+ x = a*f.x + b*m.x + c*t.x;
3728
+ y = a*f.y + b*m.y + c*t.y;
3729
+ pik_bbox_addellipse(&pObj->bbox, x, y, sw, sw);
3730
+ }
37163731
}
37173732
static void arcRender(Pik *p, PObj *pObj){
37183733
PPoint f, m, t;
37193734
if( pObj->nPath<2 ) return;
37203735
if( pObj->sw<0.0 ) return;
37213736
f = pObj->aPath[0];
37223737
t = pObj->aPath[1];
3723
- m = arcControlPoint(pObj->cw,f,t,1.0);
3738
+ m = arcControlPoint(pObj->cw,f,t);
37243739
if( pObj->larrow ){
37253740
pik_draw_arrowhead(p,&m,&f,pObj);
37263741
}
37273742
if( pObj->rarrow ){
37283743
pik_draw_arrowhead(p,&m,&t,pObj);
@@ -8315,6 +8330,6 @@
83158330
83168331
83178332
#endif /* PIKCHR_TCL */
83188333
83198334
8320
-#line 8320 "pikchr.c"
8335
+#line 8335 "pikchr.c"
83218336
--- extsrc/pikchr.c
+++ extsrc/pikchr.c
@@ -25,17 +25,17 @@
25 ** The following is the concatenation of all %include directives from the
26 ** input grammar file:
27 */
28 /************ Begin %include sections from the grammar ************************/
29 #line 1 "VERSION.h"
30 #define MANIFEST_UUID "052f07296e76ab2312caf2a4bf6237e574b3e533c7a36ee8f34db833baa3efb4"
31 #define MANIFEST_VERSION "[052f07296e]"
32 #define MANIFEST_DATE "2025-03-05 10:54:16"
33 #define MANIFEST_YEAR "2025"
34 #define MANIFEST_ISODATE "20250305105416"
35 #define MANIFEST_NUMERIC_DATE 20250305
36 #define MANIFEST_NUMERIC_TIME 105416
37 #define RELEASE_VERSION "1.0"
38 #define RELEASE_VERSION_NUMBER 10000
39 #define RELEASE_RESOURCE_VERSION 1,0,0,0
40 #define COMPILER "gcc-13.3.0"
41 #line 2 "pikchr.y"
@@ -3687,42 +3687,57 @@
3687 ** than true arcs. Multiple reasons: (1) the legacy-PIC parameters
3688 ** that control arcs are obscure and I could not figure out what they
3689 ** mean based on available documentation. (2) Arcs are rarely used,
3690 ** and so do not seem that important.
3691 */
3692 static PPoint arcControlPoint(int cw, PPoint f, PPoint t, PNum rScale){
3693 PPoint m;
3694 PNum dx, dy;
3695 m.x = 0.5*(f.x+t.x);
3696 m.y = 0.5*(f.y+t.y);
3697 dx = t.x - f.x;
3698 dy = t.y - f.y;
3699 if( cw ){
3700 m.x -= 0.5*rScale*dy;
3701 m.y += 0.5*rScale*dx;
3702 }else{
3703 m.x += 0.5*rScale*dy;
3704 m.y -= 0.5*rScale*dx;
3705 }
3706 return m;
3707 }
3708 static void arcCheck(Pik *p, PObj *pObj){
3709 PPoint m;
 
 
3710 if( p->nTPath>2 ){
3711 pik_error(p, &pObj->errTok, "arc geometry error");
3712 return;
3713 }
3714 m = arcControlPoint(pObj->cw, p->aTPath[0], p->aTPath[1], 0.5);
3715 pik_bbox_add_xy(&pObj->bbox, m.x, m.y);
 
 
 
 
 
 
 
 
 
 
 
 
 
3716 }
3717 static void arcRender(Pik *p, PObj *pObj){
3718 PPoint f, m, t;
3719 if( pObj->nPath<2 ) return;
3720 if( pObj->sw<0.0 ) return;
3721 f = pObj->aPath[0];
3722 t = pObj->aPath[1];
3723 m = arcControlPoint(pObj->cw,f,t,1.0);
3724 if( pObj->larrow ){
3725 pik_draw_arrowhead(p,&m,&f,pObj);
3726 }
3727 if( pObj->rarrow ){
3728 pik_draw_arrowhead(p,&m,&t,pObj);
@@ -8315,6 +8330,6 @@
8315
8316
8317 #endif /* PIKCHR_TCL */
8318
8319
8320 #line 8320 "pikchr.c"
8321
--- extsrc/pikchr.c
+++ extsrc/pikchr.c
@@ -25,17 +25,17 @@
25 ** The following is the concatenation of all %include directives from the
26 ** input grammar file:
27 */
28 /************ Begin %include sections from the grammar ************************/
29 #line 1 "VERSION.h"
30 #define MANIFEST_UUID "8a43b020141f772a0ac45291a7fd73041d2efba5e3665c6bd2f334ad9b2e9845"
31 #define MANIFEST_VERSION "[8a43b02014]"
32 #define MANIFEST_DATE "2025-03-19 16:19:43"
33 #define MANIFEST_YEAR "2025"
34 #define MANIFEST_ISODATE "20250319161943"
35 #define MANIFEST_NUMERIC_DATE 20250319
36 #define MANIFEST_NUMERIC_TIME 161943
37 #define RELEASE_VERSION "1.0"
38 #define RELEASE_VERSION_NUMBER 10000
39 #define RELEASE_RESOURCE_VERSION 1,0,0,0
40 #define COMPILER "gcc-13.3.0"
41 #line 2 "pikchr.y"
@@ -3687,42 +3687,57 @@
3687 ** than true arcs. Multiple reasons: (1) the legacy-PIC parameters
3688 ** that control arcs are obscure and I could not figure out what they
3689 ** mean based on available documentation. (2) Arcs are rarely used,
3690 ** and so do not seem that important.
3691 */
3692 static PPoint arcControlPoint(int cw, PPoint f, PPoint t){
3693 PPoint m;
3694 PNum dx, dy;
3695 m.x = 0.5*(f.x+t.x);
3696 m.y = 0.5*(f.y+t.y);
3697 dx = t.x - f.x;
3698 dy = t.y - f.y;
3699 if( cw ){
3700 m.x -= 0.5*dy;
3701 m.y += 0.5*dx;
3702 }else{
3703 m.x += 0.5*dy;
3704 m.y -= 0.5*dx;
3705 }
3706 return m;
3707 }
3708 static void arcCheck(Pik *p, PObj *pObj){
3709 PPoint f, m, t;
3710 PNum sw;
3711 int i;
3712 if( p->nTPath>2 ){
3713 pik_error(p, &pObj->errTok, "arc geometry error");
3714 return;
3715 }
3716 f = p->aTPath[0];
3717 t = p->aTPath[1];
3718 m = arcControlPoint(pObj->cw, f, t);
3719 sw = pObj->sw;
3720 for(i=1; i<16; i++){
3721 PNum t1, t2, a, b, c, x, y;
3722 t1 = 0.0625*i;
3723 t2 = 1.0 - t1;
3724 a = t2*t2;
3725 b = 2*t1*t2;
3726 c = t1*t1;
3727 x = a*f.x + b*m.x + c*t.x;
3728 y = a*f.y + b*m.y + c*t.y;
3729 pik_bbox_addellipse(&pObj->bbox, x, y, sw, sw);
3730 }
3731 }
3732 static void arcRender(Pik *p, PObj *pObj){
3733 PPoint f, m, t;
3734 if( pObj->nPath<2 ) return;
3735 if( pObj->sw<0.0 ) return;
3736 f = pObj->aPath[0];
3737 t = pObj->aPath[1];
3738 m = arcControlPoint(pObj->cw,f,t);
3739 if( pObj->larrow ){
3740 pik_draw_arrowhead(p,&m,&f,pObj);
3741 }
3742 if( pObj->rarrow ){
3743 pik_draw_arrowhead(p,&m,&t,pObj);
@@ -8315,6 +8330,6 @@
8330
8331
8332 #endif /* PIKCHR_TCL */
8333
8334
8335 #line 8335 "pikchr.c"
8336
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -300,11 +300,11 @@
300300
301301
// end include: URIUtils.js
302302
// include: runtime_exceptions.js
303303
// end include: runtime_exceptions.js
304304
function findWasmBinary() {
305
- var f = "pikchr-v7583078860.wasm";
305
+ var f = "pikchr-v2813665466.wasm";
306306
if (!isDataURI(f)) {
307307
return locateFile(f);
308308
}
309309
return f;
310310
}
311311
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -300,11 +300,11 @@
300
301 // end include: URIUtils.js
302 // include: runtime_exceptions.js
303 // end include: runtime_exceptions.js
304 function findWasmBinary() {
305 var f = "pikchr-v7583078860.wasm";
306 if (!isDataURI(f)) {
307 return locateFile(f);
308 }
309 return f;
310 }
311
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -300,11 +300,11 @@
300
301 // end include: URIUtils.js
302 // include: runtime_exceptions.js
303 // end include: runtime_exceptions.js
304 function findWasmBinary() {
305 var f = "pikchr-v2813665466.wasm";
306 if (!isDataURI(f)) {
307 return locateFile(f);
308 }
309 return f;
310 }
311
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
cannot compute difference between binary files
11
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
0 annot compute difference between binary files
1
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
0 annot compute difference between binary files
1
+19 -8
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -6729,23 +6729,21 @@
67296729
if( pCur->ss.iBase<iMin ){
67306730
sqlite3_uint64 d = iMin - pCur->ss.iBase;
67316731
pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
67326732
}
67336733
if( pCur->ss.iTerm>iMax ){
6734
- sqlite3_uint64 d = pCur->ss.iTerm - iMax;
6735
- pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
6734
+ pCur->ss.iTerm = iMax;
67366735
}
67376736
}else{
67386737
sqlite3_int64 szStep = -pCur->ss.iStep;
67396738
assert( szStep>0 );
67406739
if( pCur->ss.iBase>iMax ){
67416740
sqlite3_uint64 d = pCur->ss.iBase - iMax;
67426741
pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
67436742
}
67446743
if( pCur->ss.iTerm<iMin ){
6745
- sqlite3_uint64 d = iMin - pCur->ss.iTerm;
6746
- pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
6744
+ pCur->ss.iTerm = iMin;
67476745
}
67486746
}
67496747
}
67506748
67516749
/* Apply LIMIT and OFFSET constraints, if any */
@@ -18710,10 +18708,20 @@
1871018708
1871118709
/* typedef unsigned int u32; */
1871218710
/* typedef unsigned char u8; */
1871318711
/* typedef sqlite3_int64 i64; */
1871418712
18713
+/*
18714
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
18715
+** to avoid complaints from -fsanitize=strict-bounds.
18716
+*/
18717
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
18718
+# define FLEXARRAY
18719
+#else
18720
+# define FLEXARRAY 1
18721
+#endif
18722
+
1871518723
typedef struct RecoverTable RecoverTable;
1871618724
typedef struct RecoverColumn RecoverColumn;
1871718725
1871818726
/*
1871918727
** When recovering rows of data that can be associated with table
@@ -18817,12 +18825,15 @@
1881718825
** (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
1881818826
*/
1881918827
typedef struct RecoverBitmap RecoverBitmap;
1882018828
struct RecoverBitmap {
1882118829
i64 nPg; /* Size of bitmap */
18822
- u32 aElem[1]; /* Array of 32-bit bitmasks */
18830
+ u32 aElem[FLEXARRAY]; /* Array of 32-bit bitmasks */
1882318831
};
18832
+
18833
+/* Size in bytes of a RecoverBitmap object sufficient to cover 32 pages */
18834
+#define SZ_RECOVERBITMAP_32 (16)
1882418835
1882518836
/*
1882618837
** State variables (part of the sqlite3_recover structure) used while
1882718838
** recovering data for tables identified in the recovered schema (state
1882818839
** RECOVER_STATE_WRITING).
@@ -19059,11 +19070,11 @@
1905919070
** large enough to store a bit for all page numbers between 1 and nPg,
1906019071
** inclusive. The bitmap is initially zeroed.
1906119072
*/
1906219073
static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
1906319074
int nElem = (nPg+1+31) / 32;
19064
- int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
19075
+ int nByte = SZ_RECOVERBITMAP_32 + nElem*sizeof(u32);
1906519076
RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
1906619077
1906719078
if( pRet ){
1906819079
pRet->nPg = nPg;
1906919080
}
@@ -32463,11 +32474,11 @@
3246332474
/*
3246432475
** The CLI needs a working sqlite3_complete() to work properly. So error
3246532476
** out of the build if compiling with SQLITE_OMIT_COMPLETE.
3246632477
*/
3246732478
#ifdef SQLITE_OMIT_COMPLETE
32468
-# error the CLI application is incompatable with SQLITE_OMIT_COMPLETE.
32479
+# error the CLI application is incompatible with SQLITE_OMIT_COMPLETE.
3246932480
#endif
3247032481
3247132482
/*
3247232483
** Return true if zSql is a complete SQL statement. Return false if it
3247332484
** ends in the middle of a string literal or C-style comment.
@@ -33663,19 +33674,19 @@
3366333674
/* Run all arguments that do not begin with '-' as if they were separate
3366433675
** command-line inputs, except for the argToSkip argument which contains
3366533676
** the database filename.
3366633677
*/
3366733678
for(i=0; i<nCmd; i++){
33679
+ echo_group_input(&data, azCmd[i]);
3366833680
if( azCmd[i][0]=='.' ){
3366933681
rc = do_meta_command(azCmd[i], &data);
3367033682
if( rc ){
3367133683
if( rc==2 ) rc = 0;
3367233684
goto shell_main_exit;
3367333685
}
3367433686
}else{
3367533687
open_db(&data, 0);
33676
- echo_group_input(&data, azCmd[i]);
3367733688
rc = shell_exec(&data, azCmd[i], &zErrMsg);
3367833689
if( zErrMsg || rc ){
3367933690
if( zErrMsg!=0 ){
3368033691
shellEmitError(zErrMsg);
3368133692
}else{
3368233693
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -6729,23 +6729,21 @@
6729 if( pCur->ss.iBase<iMin ){
6730 sqlite3_uint64 d = iMin - pCur->ss.iBase;
6731 pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
6732 }
6733 if( pCur->ss.iTerm>iMax ){
6734 sqlite3_uint64 d = pCur->ss.iTerm - iMax;
6735 pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
6736 }
6737 }else{
6738 sqlite3_int64 szStep = -pCur->ss.iStep;
6739 assert( szStep>0 );
6740 if( pCur->ss.iBase>iMax ){
6741 sqlite3_uint64 d = pCur->ss.iBase - iMax;
6742 pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
6743 }
6744 if( pCur->ss.iTerm<iMin ){
6745 sqlite3_uint64 d = iMin - pCur->ss.iTerm;
6746 pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
6747 }
6748 }
6749 }
6750
6751 /* Apply LIMIT and OFFSET constraints, if any */
@@ -18710,10 +18708,20 @@
18710
18711 /* typedef unsigned int u32; */
18712 /* typedef unsigned char u8; */
18713 /* typedef sqlite3_int64 i64; */
18714
 
 
 
 
 
 
 
 
 
 
18715 typedef struct RecoverTable RecoverTable;
18716 typedef struct RecoverColumn RecoverColumn;
18717
18718 /*
18719 ** When recovering rows of data that can be associated with table
@@ -18817,12 +18825,15 @@
18817 ** (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
18818 */
18819 typedef struct RecoverBitmap RecoverBitmap;
18820 struct RecoverBitmap {
18821 i64 nPg; /* Size of bitmap */
18822 u32 aElem[1]; /* Array of 32-bit bitmasks */
18823 };
 
 
 
18824
18825 /*
18826 ** State variables (part of the sqlite3_recover structure) used while
18827 ** recovering data for tables identified in the recovered schema (state
18828 ** RECOVER_STATE_WRITING).
@@ -19059,11 +19070,11 @@
19059 ** large enough to store a bit for all page numbers between 1 and nPg,
19060 ** inclusive. The bitmap is initially zeroed.
19061 */
19062 static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
19063 int nElem = (nPg+1+31) / 32;
19064 int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
19065 RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
19066
19067 if( pRet ){
19068 pRet->nPg = nPg;
19069 }
@@ -32463,11 +32474,11 @@
32463 /*
32464 ** The CLI needs a working sqlite3_complete() to work properly. So error
32465 ** out of the build if compiling with SQLITE_OMIT_COMPLETE.
32466 */
32467 #ifdef SQLITE_OMIT_COMPLETE
32468 # error the CLI application is incompatable with SQLITE_OMIT_COMPLETE.
32469 #endif
32470
32471 /*
32472 ** Return true if zSql is a complete SQL statement. Return false if it
32473 ** ends in the middle of a string literal or C-style comment.
@@ -33663,19 +33674,19 @@
33663 /* Run all arguments that do not begin with '-' as if they were separate
33664 ** command-line inputs, except for the argToSkip argument which contains
33665 ** the database filename.
33666 */
33667 for(i=0; i<nCmd; i++){
 
33668 if( azCmd[i][0]=='.' ){
33669 rc = do_meta_command(azCmd[i], &data);
33670 if( rc ){
33671 if( rc==2 ) rc = 0;
33672 goto shell_main_exit;
33673 }
33674 }else{
33675 open_db(&data, 0);
33676 echo_group_input(&data, azCmd[i]);
33677 rc = shell_exec(&data, azCmd[i], &zErrMsg);
33678 if( zErrMsg || rc ){
33679 if( zErrMsg!=0 ){
33680 shellEmitError(zErrMsg);
33681 }else{
33682
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -6729,23 +6729,21 @@
6729 if( pCur->ss.iBase<iMin ){
6730 sqlite3_uint64 d = iMin - pCur->ss.iBase;
6731 pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
6732 }
6733 if( pCur->ss.iTerm>iMax ){
6734 pCur->ss.iTerm = iMax;
 
6735 }
6736 }else{
6737 sqlite3_int64 szStep = -pCur->ss.iStep;
6738 assert( szStep>0 );
6739 if( pCur->ss.iBase>iMax ){
6740 sqlite3_uint64 d = pCur->ss.iBase - iMax;
6741 pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
6742 }
6743 if( pCur->ss.iTerm<iMin ){
6744 pCur->ss.iTerm = iMin;
 
6745 }
6746 }
6747 }
6748
6749 /* Apply LIMIT and OFFSET constraints, if any */
@@ -18710,10 +18708,20 @@
18708
18709 /* typedef unsigned int u32; */
18710 /* typedef unsigned char u8; */
18711 /* typedef sqlite3_int64 i64; */
18712
18713 /*
18714 ** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
18715 ** to avoid complaints from -fsanitize=strict-bounds.
18716 */
18717 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
18718 # define FLEXARRAY
18719 #else
18720 # define FLEXARRAY 1
18721 #endif
18722
18723 typedef struct RecoverTable RecoverTable;
18724 typedef struct RecoverColumn RecoverColumn;
18725
18726 /*
18727 ** When recovering rows of data that can be associated with table
@@ -18817,12 +18825,15 @@
18825 ** (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
18826 */
18827 typedef struct RecoverBitmap RecoverBitmap;
18828 struct RecoverBitmap {
18829 i64 nPg; /* Size of bitmap */
18830 u32 aElem[FLEXARRAY]; /* Array of 32-bit bitmasks */
18831 };
18832
18833 /* Size in bytes of a RecoverBitmap object sufficient to cover 32 pages */
18834 #define SZ_RECOVERBITMAP_32 (16)
18835
18836 /*
18837 ** State variables (part of the sqlite3_recover structure) used while
18838 ** recovering data for tables identified in the recovered schema (state
18839 ** RECOVER_STATE_WRITING).
@@ -19059,11 +19070,11 @@
19070 ** large enough to store a bit for all page numbers between 1 and nPg,
19071 ** inclusive. The bitmap is initially zeroed.
19072 */
19073 static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
19074 int nElem = (nPg+1+31) / 32;
19075 int nByte = SZ_RECOVERBITMAP_32 + nElem*sizeof(u32);
19076 RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
19077
19078 if( pRet ){
19079 pRet->nPg = nPg;
19080 }
@@ -32463,11 +32474,11 @@
32474 /*
32475 ** The CLI needs a working sqlite3_complete() to work properly. So error
32476 ** out of the build if compiling with SQLITE_OMIT_COMPLETE.
32477 */
32478 #ifdef SQLITE_OMIT_COMPLETE
32479 # error the CLI application is incompatible with SQLITE_OMIT_COMPLETE.
32480 #endif
32481
32482 /*
32483 ** Return true if zSql is a complete SQL statement. Return false if it
32484 ** ends in the middle of a string literal or C-style comment.
@@ -33663,19 +33674,19 @@
33674 /* Run all arguments that do not begin with '-' as if they were separate
33675 ** command-line inputs, except for the argToSkip argument which contains
33676 ** the database filename.
33677 */
33678 for(i=0; i<nCmd; i++){
33679 echo_group_input(&data, azCmd[i]);
33680 if( azCmd[i][0]=='.' ){
33681 rc = do_meta_command(azCmd[i], &data);
33682 if( rc ){
33683 if( rc==2 ) rc = 0;
33684 goto shell_main_exit;
33685 }
33686 }else{
33687 open_db(&data, 0);
 
33688 rc = shell_exec(&data, azCmd[i], &zErrMsg);
33689 if( zErrMsg || rc ){
33690 if( zErrMsg!=0 ){
33691 shellEmitError(zErrMsg);
33692 }else{
33693
+486 -287
--- 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
-** e6784af6d50f715338ae3218fc8ba1b89488 with changes in files:
21
+** 18bda13e197e4b4ec7464b3e70012f71edc0 with changes in files:
2222
**
2323
**
2424
*/
2525
#ifndef SQLITE_AMALGAMATION
2626
#define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465465
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466466
** [sqlite_version()] and [sqlite_source_id()].
467467
*/
468468
#define SQLITE_VERSION "3.50.0"
469469
#define SQLITE_VERSION_NUMBER 3050000
470
-#define SQLITE_SOURCE_ID "2025-02-25 18:10:47 e6784af6d50f715338ae3218fc8ba1b894883c27d797f0b7fd2625cac17d9cd7"
470
+#define SQLITE_SOURCE_ID "2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185"
471471
472472
/*
473473
** CAPI3REF: Run-Time Library Version Numbers
474474
** KEYWORDS: sqlite3_version sqlite3_sourceid
475475
**
@@ -5492,11 +5492,11 @@
54925492
** For all versions of SQLite up to and including 3.6.23.1, a call to
54935493
** [sqlite3_reset()] was required after sqlite3_step() returned anything
54945494
** other than [SQLITE_ROW] before any subsequent invocation of
54955495
** sqlite3_step(). Failure to reset the prepared statement using
54965496
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
5497
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
5497
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
54985498
** sqlite3_step() began
54995499
** calling [sqlite3_reset()] automatically in this circumstance rather
55005500
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
55015501
** break because any application that ever receives an SQLITE_MISUSE error
55025502
** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
@@ -7388,10 +7388,12 @@
73887388
** ^Any callback set by a previous call to this function
73897389
** for the same database connection is overridden.
73907390
**
73917391
** ^The second argument is a pointer to the function to invoke when a
73927392
** row is updated, inserted or deleted in a rowid table.
7393
+** ^The update hook is disabled by invoking sqlite3_update_hook()
7394
+** with a NULL pointer as the second parameter.
73937395
** ^The first argument to the callback is a copy of the third argument
73947396
** to sqlite3_update_hook().
73957397
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
73967398
** or [SQLITE_UPDATE], depending on the operation that caused the callback
73977399
** to be invoked.
@@ -15170,11 +15172,21 @@
1517015172
/*
1517115173
** GCC does not define the offsetof() macro so we'll have to do it
1517215174
** ourselves.
1517315175
*/
1517415176
#ifndef offsetof
15175
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
15177
+#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
15178
+#endif
15179
+
15180
+/*
15181
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
15182
+** to avoid complaints from -fsanitize=strict-bounds.
15183
+*/
15184
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
15185
+# define FLEXARRAY
15186
+#else
15187
+# define FLEXARRAY 1
1517615188
#endif
1517715189
1517815190
/*
1517915191
** Macros to compute minimum and maximum of two numbers.
1518015192
*/
@@ -17405,12 +17417,12 @@
1740517417
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
1740617418
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
1740717419
SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
1740817420
#endif
1740917421
17410
-/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
17411
-** each VDBE opcode.
17422
+/* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra
17423
+** comments on each VDBE opcode.
1741217424
**
1741317425
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
1741417426
** comments in VDBE programs that show key decision points in the code
1741517427
** generator.
1741617428
*/
@@ -18945,12 +18957,16 @@
1894518957
u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
1894618958
Trigger *apTrigger[2];/* Triggers for aAction[] actions */
1894718959
struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
1894818960
int iFrom; /* Index of column in pFrom */
1894918961
char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
18950
- } aCol[1]; /* One entry for each of nCol columns */
18962
+ } aCol[FLEXARRAY]; /* One entry for each of nCol columns */
1895118963
};
18964
+
18965
+/* The size (in bytes) of an FKey object holding N columns. The answer
18966
+** does NOT include space to hold the zTo name. */
18967
+#define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap))
1895218968
1895318969
/*
1895418970
** SQLite supports many different ways to resolve a constraint
1895518971
** error. ROLLBACK processing means that a constraint violation
1895618972
** causes the operation in process to fail and for the current transaction
@@ -19009,13 +19025,16 @@
1900919025
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
1901019026
u16 nKeyField; /* Number of key columns in the index */
1901119027
u16 nAllField; /* Total columns, including key plus others */
1901219028
sqlite3 *db; /* The database connection */
1901319029
u8 *aSortFlags; /* Sort order for each column. */
19014
- CollSeq *aColl[1]; /* Collating sequence for each term of the key */
19030
+ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
1901519031
};
1901619032
19033
+/* The size (in bytes) of a KeyInfo object with up to N fields */
19034
+#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
19035
+
1901719036
/*
1901819037
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
1901919038
*/
1902019039
#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
1902119040
#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
@@ -19584,12 +19603,17 @@
1958419603
u16 iAlias; /* Index into Parse.aAlias[] for zName */
1958519604
} x;
1958619605
int iConstExprReg; /* Register in which Expr value is cached. Used only
1958719606
** by Parse.pConstExpr */
1958819607
} u;
19589
- } a[1]; /* One slot for each expression in the list */
19608
+ } a[FLEXARRAY]; /* One slot for each expression in the list */
1959019609
};
19610
+
19611
+/* The size (in bytes) of an ExprList object that is big enough to hold
19612
+** as many as N expressions. */
19613
+#define SZ_EXPRLIST(N) \
19614
+ (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item))
1959119615
1959219616
/*
1959319617
** Allowed values for Expr.a.eEName
1959419618
*/
1959519619
#define ENAME_NAME 0 /* The AS clause of a result set */
@@ -19614,13 +19638,16 @@
1961419638
*/
1961519639
struct IdList {
1961619640
int nId; /* Number of identifiers on the list */
1961719641
struct IdList_item {
1961819642
char *zName; /* Name of the identifier */
19619
- } a[1];
19643
+ } a[FLEXARRAY];
1962019644
};
1962119645
19646
+/* The size (in bytes) of an IdList object that can hold up to N IDs. */
19647
+#define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item))
19648
+
1962219649
/*
1962319650
** Allowed values for IdList.eType, which determines which value of the a.u4
1962419651
** is valid.
1962519652
*/
1962619653
#define EU4_NONE 0 /* Does not use IdList.a.u4 */
@@ -19736,14 +19763,22 @@
1973619763
** is used to hold the FROM clause of a SELECT statement. SrcList also
1973719764
** represents the target tables for DELETE, INSERT, and UPDATE statements.
1973819765
**
1973919766
*/
1974019767
struct SrcList {
19741
- int nSrc; /* Number of tables or subqueries in the FROM clause */
19742
- u32 nAlloc; /* Number of entries allocated in a[] below */
19743
- SrcItem a[1]; /* One entry for each identifier on the list */
19768
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
19769
+ u32 nAlloc; /* Number of entries allocated in a[] below */
19770
+ SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
1974419771
};
19772
+
19773
+/* Size (in bytes) of a SrcList object that can hold as many as N
19774
+** SrcItem objects. */
19775
+#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
19776
+
19777
+/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
19778
+** special case of SZ_SRCITEM(1) that comes up often. */
19779
+#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
1974519780
1974619781
/*
1974719782
** Permitted values of the SrcList.a.jointype field
1974819783
*/
1974919784
#define JT_INNER 0x01 /* Any kind of inner or cross join */
@@ -20804,12 +20839,16 @@
2080420839
*/
2080520840
struct With {
2080620841
int nCte; /* Number of CTEs in the WITH clause */
2080720842
int bView; /* Belongs to the outermost Select of a view */
2080820843
With *pOuter; /* Containing WITH clause, or NULL */
20809
- Cte a[1]; /* For each CTE in the WITH clause.... */
20844
+ Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */
2081020845
};
20846
+
20847
+/* The size (in bytes) of a With object that can hold as many
20848
+** as N different CTEs. */
20849
+#define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte))
2081120850
2081220851
/*
2081320852
** The Cte object is not guaranteed to persist for the entire duration
2081420853
** of code generation. (The query flattener or other parser tree
2081520854
** edits might delete it.) The following object records information
@@ -20835,12 +20874,16 @@
2083520874
*/
2083620875
struct DbClientData {
2083720876
DbClientData *pNext; /* Next in a linked list */
2083820877
void *pData; /* The data */
2083920878
void (*xDestructor)(void*); /* Destructor. Might be NULL */
20840
- char zName[1]; /* Name of this client data. MUST BE LAST */
20879
+ char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
2084120880
};
20881
+
20882
+/* The size (in bytes) of a DbClientData object that can has a name
20883
+** that is N bytes long, including the zero-terminator. */
20884
+#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
2084220885
2084320886
#ifdef SQLITE_DEBUG
2084420887
/*
2084520888
** An instance of the TreeView object is used for printing the content of
2084620889
** data structures on sqlite3DebugPrintf() using a tree-like view.
@@ -22673,10 +22716,13 @@
2267322716
"EXTRA_IFNULLROW",
2267422717
#endif
2267522718
#ifdef SQLITE_EXTRA_INIT
2267622719
"EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
2267722720
#endif
22721
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
22722
+ "EXTRA_INIT_MUTEXED=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT_MUTEXED),
22723
+#endif
2267822724
#ifdef SQLITE_EXTRA_SHUTDOWN
2267922725
"EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
2268022726
#endif
2268122727
#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
2268222728
"FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
@@ -23657,16 +23703,23 @@
2365723703
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
2365823704
u64 maskUsed; /* Mask of columns used by this cursor */
2365923705
#endif
2366023706
VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
2366123707
23662
- /* 2*nField extra array elements allocated for aType[], beyond the one
23663
- ** static element declared in the structure. nField total array slots for
23664
- ** aType[] and nField+1 array slots for aOffset[] */
23665
- u32 aType[1]; /* Type values record decode. MUST BE LAST */
23708
+ /* Space is allocated for aType to hold at least 2*nField+1 entries:
23709
+ ** nField slots for aType[] and nField+1 array slots for aOffset[] */
23710
+ u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
2366623711
};
2366723712
23713
+/*
23714
+** The size (in bytes) of a VdbeCursor object that has an nField value of N
23715
+** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
23716
+** of 8.
23717
+*/
23718
+#define SZ_VDBECURSOR(N) \
23719
+ (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
23720
+
2366823721
/* Return true if P is a null-only cursor
2366923722
*/
2367023723
#define IsNullCursor(P) \
2367123724
((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
2367223725
@@ -23919,13 +23972,20 @@
2391923972
int iOp; /* Instruction number of OP_Function */
2392023973
int isError; /* Error code returned by the function. */
2392123974
u8 enc; /* Encoding to use for results */
2392223975
u8 skipFlag; /* Skip accumulator loading if true */
2392323976
u16 argc; /* Number of arguments */
23924
- sqlite3_value *argv[1]; /* Argument set */
23977
+ sqlite3_value *argv[FLEXARRAY]; /* Argument set */
2392523978
};
2392623979
23980
+/*
23981
+** The size (in bytes) of an sqlite3_context object that holds N
23982
+** argv[] arguments.
23983
+*/
23984
+#define SZ_CONTEXT(N) \
23985
+ (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*))
23986
+
2392723987
2392823988
/* The ScanStatus object holds a single value for the
2392923989
** sqlite3_stmt_scanstatus() interface.
2393023990
**
2393123991
** aAddrRange[]:
@@ -24055,11 +24115,11 @@
2405524115
struct PreUpdate {
2405624116
Vdbe *v;
2405724117
VdbeCursor *pCsr; /* Cursor to read old values from */
2405824118
int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
2405924119
u8 *aRecord; /* old.* database record */
24060
- KeyInfo keyinfo;
24120
+ KeyInfo *pKeyinfo; /* Key information */
2406124121
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
2406224122
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
2406324123
int iNewReg; /* Register for new.* values */
2406424124
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
2406524125
i64 iKey1; /* First key value passed to hook */
@@ -24067,10 +24127,11 @@
2406724127
Mem oldipk; /* Memory cell holding "old" IPK value */
2406824128
Mem *aNew; /* Array of new.* values */
2406924129
Table *pTab; /* Schema object being updated */
2407024130
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
2407124131
sqlite3_value **apDflt; /* Array of default values, if required */
24132
+ u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */
2407224133
};
2407324134
2407424135
/*
2407524136
** An instance of this object is used to pass an vector of values into
2407624137
** OP_VFilter, the xFilter method of a virtual table. The vector is the
@@ -26000,11 +26061,11 @@
2600026061
** Return the number of days after the most recent Sunday.
2600126062
**
2600226063
** In other words, return the day of the week according
2600326064
** to this code:
2600426065
**
26005
-** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday
26066
+** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday
2600626067
*/
2600726068
static int daysAfterSunday(DateTime *pDate){
2600826069
assert( pDate->validJD );
2600926070
return (int)((pDate->iJD+129600000)/86400000) % 7;
2601026071
}
@@ -32378,11 +32439,11 @@
3237832439
u32 nBack = 0;
3237932440
u32 nCtrl = 0;
3238032441
for(k=0; k<i; k++){
3238132442
if( escarg[k]=='\\' ){
3238232443
nBack++;
32383
- }else if( escarg[k]<=0x1f ){
32444
+ }else if( ((u8*)escarg)[k]<=0x1f ){
3238432445
nCtrl++;
3238532446
}
3238632447
}
3238732448
if( nCtrl || xtype==etESCAPE_q ){
3238832449
n += nBack + 5*nCtrl;
@@ -32416,11 +32477,11 @@
3241632477
bufpt[j++] = ch = escarg[i];
3241732478
if( ch==q ){
3241832479
bufpt[j++] = ch;
3241932480
}else if( ch=='\\' ){
3242032481
bufpt[j++] = '\\';
32421
- }else if( ch<=0x1f ){
32482
+ }else if( ((unsigned char)ch)<=0x1f ){
3242232483
bufpt[j-1] = '\\';
3242332484
bufpt[j++] = 'u';
3242432485
bufpt[j++] = '0';
3242532486
bufpt[j++] = '0';
3242632487
bufpt[j++] = ch>=0x10 ? '1' : '0';
@@ -37067,11 +37128,11 @@
3706737128
return 0;
3706837129
#endif
3706937130
}
3707037131
3707137132
/*
37072
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
37133
+** Compute the absolute value of a 32-bit signed integer, if possible. Or
3707337134
** if the integer has a value of -2147483648, return +2147483647
3707437135
*/
3707537136
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
3707637137
if( x>=0 ) return x;
3707737138
if( x==(int)0x80000000 ) return 0x7fffffff;
@@ -45614,11 +45675,11 @@
4561445675
sp.tv_sec = microseconds / 1000000;
4561545676
sp.tv_nsec = (microseconds % 1000000) * 1000;
4561645677
4561745678
/* Almost all modern unix systems support nanosleep(). But if you are
4561845679
** compiling for one of the rare exceptions, you can use
45619
- ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
45680
+ ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if
4562045681
** usleep() is available) in order to bypass the use of nanosleep() */
4562145682
nanosleep(&sp, NULL);
4562245683
4562345684
UNUSED_PARAMETER(NotUsed);
4562445685
return microseconds;
@@ -56047,14 +56108,10 @@
5604756108
void *pStart, *pEnd; /* Bounds of global page cache memory */
5604856109
/* Above requires no mutex. Use mutex below for variable that follow. */
5604956110
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
5605056111
PgFreeslot *pFree; /* Free page blocks */
5605156112
int nFreeSlot; /* Number of unused pcache slots */
56052
- /* The following value requires a mutex to change. We skip the mutex on
56053
- ** reading because (1) most platforms read a 32-bit integer atomically and
56054
- ** (2) even if an incorrect value is read, no great harm is done since this
56055
- ** is really just an optimization. */
5605656113
int bUnderPressure; /* True if low on PAGECACHE memory */
5605756114
} pcache1_g;
5605856115
5605956116
/*
5606056117
** All code in this file should access the global structure above via the
@@ -56098,11 +56155,11 @@
5609856155
pcache1.szSlot = sz;
5609956156
pcache1.nSlot = pcache1.nFreeSlot = n;
5610056157
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
5610156158
pcache1.pStart = pBuf;
5610256159
pcache1.pFree = 0;
56103
- pcache1.bUnderPressure = 0;
56160
+ AtomicStore(&pcache1.bUnderPressure,0);
5610456161
while( n-- ){
5610556162
p = (PgFreeslot*)pBuf;
5610656163
p->pNext = pcache1.pFree;
5610756164
pcache1.pFree = p;
5610856165
pBuf = (void*)&((char*)pBuf)[sz];
@@ -56166,11 +56223,11 @@
5616656223
sqlite3_mutex_enter(pcache1.mutex);
5616756224
p = (PgHdr1 *)pcache1.pFree;
5616856225
if( p ){
5616956226
pcache1.pFree = pcache1.pFree->pNext;
5617056227
pcache1.nFreeSlot--;
56171
- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
56228
+ AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
5617256229
assert( pcache1.nFreeSlot>=0 );
5617356230
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
5617456231
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
5617556232
}
5617656233
sqlite3_mutex_leave(pcache1.mutex);
@@ -56205,11 +56262,11 @@
5620556262
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
5620656263
pSlot = (PgFreeslot*)p;
5620756264
pSlot->pNext = pcache1.pFree;
5620856265
pcache1.pFree = pSlot;
5620956266
pcache1.nFreeSlot++;
56210
- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
56267
+ AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
5621156268
assert( pcache1.nFreeSlot<=pcache1.nSlot );
5621256269
sqlite3_mutex_leave(pcache1.mutex);
5621356270
}else{
5621456271
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
5621556272
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
@@ -56336,11 +56393,11 @@
5633656393
** allocating a new page cache entry in order to avoid stressing
5633756394
** the heap even further.
5633856395
*/
5633956396
static int pcache1UnderMemoryPressure(PCache1 *pCache){
5634056397
if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
56341
- return pcache1.bUnderPressure;
56398
+ return AtomicLoad(&pcache1.bUnderPressure);
5634256399
}else{
5634356400
return sqlite3HeapNearlyFull();
5634456401
}
5634556402
}
5634656403
@@ -66177,12 +66234,16 @@
6617766234
int iNext; /* Next slot in aIndex[] not yet returned */
6617866235
ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
6617966236
u32 *aPgno; /* Array of page numbers. */
6618066237
int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
6618166238
int iZero; /* Frame number associated with aPgno[0] */
66182
- } aSegment[1]; /* One for every 32KB page in the wal-index */
66239
+ } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */
6618366240
};
66241
+
66242
+/* Size (in bytes) of a WalIterator object suitable for N or fewer segments */
66243
+#define SZ_WALITERATOR(N) \
66244
+ (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment))
6618466245
6618566246
/*
6618666247
** Define the parameters of the hash tables in the wal-index file. There
6618766248
** is a hash-table following every HASHTABLE_NPAGE page numbers in the
6618866249
** wal-index.
@@ -67540,12 +67601,11 @@
6754067601
assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
6754167602
iLast = pWal->hdr.mxFrame;
6754267603
6754367604
/* Allocate space for the WalIterator object. */
6754467605
nSegment = walFramePage(iLast) + 1;
67545
- nByte = sizeof(WalIterator)
67546
- + (nSegment-1)*sizeof(struct WalSegment)
67606
+ nByte = SZ_WALITERATOR(nSegment)
6754767607
+ iLast*sizeof(ht_slot);
6754867608
p = (WalIterator *)sqlite3_malloc64(nByte
6754967609
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
6755067610
);
6755167611
if( !p ){
@@ -86029,16 +86089,14 @@
8602986089
int nArg, /* Number of argument */
8603086090
const FuncDef *pFunc, /* The function to be invoked */
8603186091
int eCallCtx /* Calling context */
8603286092
){
8603386093
Vdbe *v = pParse->pVdbe;
86034
- int nByte;
8603586094
int addr;
8603686095
sqlite3_context *pCtx;
8603786096
assert( v );
86038
- nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
86039
- pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
86097
+ pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg));
8604086098
if( pCtx==0 ){
8604186099
assert( pParse->db->mallocFailed );
8604286100
freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
8604386101
return 0;
8604486102
}
@@ -91110,25 +91168,26 @@
9111091168
9111191169
preupdate.v = v;
9111291170
preupdate.pCsr = pCsr;
9111391171
preupdate.op = op;
9111491172
preupdate.iNewReg = iReg;
91115
- preupdate.keyinfo.db = db;
91116
- preupdate.keyinfo.enc = ENC(db);
91117
- preupdate.keyinfo.nKeyField = pTab->nCol;
91118
- preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
91173
+ preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace;
91174
+ preupdate.pKeyinfo->db = db;
91175
+ preupdate.pKeyinfo->enc = ENC(db);
91176
+ preupdate.pKeyinfo->nKeyField = pTab->nCol;
91177
+ preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
9111991178
preupdate.iKey1 = iKey1;
9112091179
preupdate.iKey2 = iKey2;
9112191180
preupdate.pTab = pTab;
9112291181
preupdate.iBlobWrite = iBlobWrite;
9112391182
9112491183
db->pPreUpdate = &preupdate;
9112591184
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
9112691185
db->pPreUpdate = 0;
9112791186
sqlite3DbFree(db, preupdate.aRecord);
91128
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
91129
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
91187
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked);
91188
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked);
9113091189
sqlite3VdbeMemRelease(&preupdate.oldipk);
9113191190
if( preupdate.aNew ){
9113291191
int i;
9113391192
for(i=0; i<pCsr->nField; i++){
9113491193
sqlite3VdbeMemRelease(&preupdate.aNew[i]);
@@ -93363,11 +93422,11 @@
9336393422
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
9336493423
aRec = sqlite3DbMallocRaw(db, nRec);
9336593424
if( !aRec ) goto preupdate_old_out;
9336693425
rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
9336793426
if( rc==SQLITE_OK ){
93368
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
93427
+ p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec);
9336993428
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
9337093429
}
9337193430
if( rc!=SQLITE_OK ){
9337293431
sqlite3DbFree(db, aRec);
9337393432
goto preupdate_old_out;
@@ -93428,11 +93487,11 @@
9342893487
#ifdef SQLITE_ENABLE_API_ARMOR
9342993488
p = db!=0 ? db->pPreUpdate : 0;
9343093489
#else
9343193490
p = db->pPreUpdate;
9343293491
#endif
93433
- return (p ? p->keyinfo.nKeyField : 0);
93492
+ return (p ? p->pKeyinfo->nKeyField : 0);
9343493493
}
9343593494
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
9343693495
9343793496
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
9343893497
/*
@@ -93511,11 +93570,11 @@
9351193570
UnpackedRecord *pUnpack = p->pNewUnpacked;
9351293571
if( !pUnpack ){
9351393572
Mem *pData = &p->v->aMem[p->iNewReg];
9351493573
rc = ExpandBlob(pData);
9351593574
if( rc!=SQLITE_OK ) goto preupdate_new_out;
93516
- pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
93575
+ pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z);
9351793576
if( !pUnpack ){
9351893577
rc = SQLITE_NOMEM;
9351993578
goto preupdate_new_out;
9352093579
}
9352193580
p->pNewUnpacked = pUnpack;
@@ -94305,13 +94364,13 @@
9430594364
*/
9430694365
Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
9430794366
9430894367
i64 nByte;
9430994368
VdbeCursor *pCx = 0;
94310
- nByte =
94311
- ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
94312
- (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
94369
+ nByte = SZ_VDBECURSOR(nField);
94370
+ assert( ROUND8(nByte)==nByte );
94371
+ if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize();
9431394372
9431494373
assert( iCur>=0 && iCur<p->nCursor );
9431594374
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
9431694375
sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
9431794376
p->apCsr[iCur] = 0;
@@ -94340,12 +94399,12 @@
9434094399
memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
9434194400
pCx->eCurType = eCurType;
9434294401
pCx->nField = nField;
9434394402
pCx->aOffset = &pCx->aType[nField];
9434494403
if( eCurType==CURTYPE_BTREE ){
94345
- pCx->uc.pCursor = (BtCursor*)
94346
- &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
94404
+ assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) );
94405
+ pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)];
9434794406
sqlite3BtreeCursorZero(pCx->uc.pCursor);
9434894407
}
9434994408
return pCx;
9435094409
}
9435194410
@@ -100083,11 +100142,11 @@
100083100142
pCrsr = pC->uc.pCursor;
100084100143
100085100144
/* The OP_RowData opcodes always follow OP_NotExists or
100086100145
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
100087100146
** that might invalidate the cursor.
100088
- ** If this where not the case, on of the following assert()s
100147
+ ** If this were not the case, one of the following assert()s
100089100148
** would fail. Should this ever change (because of changes in the code
100090100149
** generator) then the fix would be to insert a call to
100091100150
** sqlite3VdbeCursorMoveto().
100092100151
*/
100093100152
assert( pC->deferredMoveto==0 );
@@ -101732,11 +101791,11 @@
101732101791
** cell in which to store the accumulation. Be careful that the memory
101733101792
** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
101734101793
**
101735101794
** Note: We could avoid this by using a regular memory cell from aMem[] for
101736101795
** the accumulator, instead of allocating one here. */
101737
- nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) );
101796
+ nAlloc = ROUND8P( SZ_CONTEXT(n) );
101738101797
pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
101739101798
if( pCtx==0 ) goto no_mem;
101740101799
pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
101741101800
assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
101742101801
@@ -103390,10 +103449,11 @@
103390103449
int iCol; /* Index of zColumn in row-record */
103391103450
int rc = SQLITE_OK;
103392103451
char *zErr = 0;
103393103452
Table *pTab;
103394103453
Incrblob *pBlob = 0;
103454
+ int iDb;
103395103455
Parse sParse;
103396103456
103397103457
#ifdef SQLITE_ENABLE_API_ARMOR
103398103458
if( ppBlob==0 ){
103399103459
return SQLITE_MISUSE_BKPT;
@@ -103435,11 +103495,14 @@
103435103495
if( pTab && IsView(pTab) ){
103436103496
pTab = 0;
103437103497
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
103438103498
}
103439103499
#endif
103440
- if( !pTab ){
103500
+ if( pTab==0
103501
+ || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 &&
103502
+ sqlite3OpenTempDatabase(&sParse))
103503
+ ){
103441103504
if( sParse.zErrMsg ){
103442103505
sqlite3DbFree(db, zErr);
103443103506
zErr = sParse.zErrMsg;
103444103507
sParse.zErrMsg = 0;
103445103508
}
@@ -103446,11 +103509,11 @@
103446103509
rc = SQLITE_ERROR;
103447103510
sqlite3BtreeLeaveAll(db);
103448103511
goto blob_open_out;
103449103512
}
103450103513
pBlob->pTab = pTab;
103451
- pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
103514
+ pBlob->zDb = db->aDb[iDb].zDbSName;
103452103515
103453103516
/* Now search pTab for the exact column. */
103454103517
iCol = sqlite3ColumnIndex(pTab, zColumn);
103455103518
if( iCol<0 ){
103456103519
sqlite3DbFree(db, zErr);
@@ -103530,11 +103593,10 @@
103530103593
{OP_Column, 0, 0, 1}, /* 3 */
103531103594
{OP_ResultRow, 1, 0, 0}, /* 4 */
103532103595
{OP_Halt, 0, 0, 0}, /* 5 */
103533103596
};
103534103597
Vdbe *v = (Vdbe *)pBlob->pStmt;
103535
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
103536103598
VdbeOp *aOp;
103537103599
103538103600
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
103539103601
pTab->pSchema->schema_cookie,
103540103602
pTab->pSchema->iGeneration);
@@ -104108,12 +104170,15 @@
104108104170
u8 bUsePMA; /* True if one or more PMAs created */
104109104171
u8 bUseThreads; /* True to use background threads */
104110104172
u8 iPrev; /* Previous thread used to flush PMA */
104111104173
u8 nTask; /* Size of aTask[] array */
104112104174
u8 typeMask;
104113
- SortSubtask aTask[1]; /* One or more subtasks */
104175
+ SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */
104114104176
};
104177
+
104178
+/* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */
104179
+#define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask))
104115104180
104116104181
#define SORTER_TYPE_INTEGER 0x01
104117104182
#define SORTER_TYPE_TEXT 0x02
104118104183
104119104184
/*
@@ -104742,12 +104807,12 @@
104742104807
assert( pCsr->pKeyInfo );
104743104808
assert( !pCsr->isEphemeral );
104744104809
assert( pCsr->eCurType==CURTYPE_SORTER );
104745104810
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
104746104811
< 0x7fffffff );
104747
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
104748
- sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
104812
+ szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
104813
+ sz = SZ_VDBESORTER(nWorker+1);
104749104814
104750104815
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
104751104816
pCsr->uc.pSorter = pSorter;
104752104817
if( pSorter==0 ){
104753104818
rc = SQLITE_NOMEM_BKPT;
@@ -105207,10 +105272,14 @@
105207105272
}
105208105273
105209105274
p->u.pNext = 0;
105210105275
for(i=0; aSlot[i]; i++){
105211105276
p = vdbeSorterMerge(pTask, p, aSlot[i]);
105277
+ /* ,--Each aSlot[] holds twice as much as the previous. So we cannot use
105278
+ ** | up all 64 aSlots[] with only a 64-bit address space.
105279
+ ** v */
105280
+ assert( i<ArraySize(aSlot) );
105212105281
aSlot[i] = 0;
105213105282
}
105214105283
aSlot[i] = p;
105215105284
p = pNext;
105216105285
}
@@ -109981,32 +110050,34 @@
109981110050
Table *pTab, /* The table being referenced, or NULL */
109982110051
int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
109983110052
Expr *pExpr, /* Expression to resolve. May be NULL. */
109984110053
ExprList *pList /* Expression list to resolve. May be NULL. */
109985110054
){
109986
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
110055
+ SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */
109987110056
NameContext sNC; /* Name context for pParse->pNewTable */
109988110057
int rc;
110058
+ u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */
109989110059
109990110060
assert( type==0 || pTab!=0 );
109991110061
assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
109992110062
|| type==NC_GenCol || pTab==0 );
109993110063
memset(&sNC, 0, sizeof(sNC));
109994
- memset(&sSrc, 0, sizeof(sSrc));
110064
+ pSrc = (SrcList*)srcSpace;
110065
+ memset(pSrc, 0, SZ_SRCLIST_1);
109995110066
if( pTab ){
109996
- sSrc.nSrc = 1;
109997
- sSrc.a[0].zName = pTab->zName;
109998
- sSrc.a[0].pSTab = pTab;
109999
- sSrc.a[0].iCursor = -1;
110067
+ pSrc->nSrc = 1;
110068
+ pSrc->a[0].zName = pTab->zName;
110069
+ pSrc->a[0].pSTab = pTab;
110070
+ pSrc->a[0].iCursor = -1;
110000110071
if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
110001110072
/* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
110002110073
** schema elements */
110003110074
type |= NC_FromDDL;
110004110075
}
110005110076
}
110006110077
sNC.pParse = pParse;
110007
- sNC.pSrcList = &sSrc;
110078
+ sNC.pSrcList = pSrc;
110008110079
sNC.ncFlags = type | NC_IsDDL;
110009110080
if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
110010110081
if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
110011110082
return rc;
110012110083
}
@@ -111751,11 +111822,11 @@
111751111822
*/
111752111823
#ifndef SQLITE_OMIT_CTE
111753111824
SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){
111754111825
With *pRet = 0;
111755111826
if( p ){
111756
- sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
111827
+ sqlite3_int64 nByte = SZ_WITH(p->nCte);
111757111828
pRet = sqlite3DbMallocZero(db, nByte);
111758111829
if( pRet ){
111759111830
int i;
111760111831
pRet->nCte = p->nCte;
111761111832
for(i=0; i<p->nCte; i++){
@@ -111878,15 +111949,13 @@
111878111949
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
111879111950
|| !defined(SQLITE_OMIT_SUBQUERY)
111880111951
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
111881111952
SrcList *pNew;
111882111953
int i;
111883
- int nByte;
111884111954
assert( db!=0 );
111885111955
if( p==0 ) return 0;
111886
- nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
111887
- pNew = sqlite3DbMallocRawNN(db, nByte );
111956
+ pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) );
111888111957
if( pNew==0 ) return 0;
111889111958
pNew->nSrc = pNew->nAlloc = p->nSrc;
111890111959
for(i=0; i<p->nSrc; i++){
111891111960
SrcItem *pNewItem = &pNew->a[i];
111892111961
const SrcItem *pOldItem = &p->a[i];
@@ -111944,11 +112013,11 @@
111944112013
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
111945112014
IdList *pNew;
111946112015
int i;
111947112016
assert( db!=0 );
111948112017
if( p==0 ) return 0;
111949
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
112018
+ pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId));
111950112019
if( pNew==0 ) return 0;
111951112020
pNew->nId = p->nId;
111952112021
for(i=0; i<p->nId; i++){
111953112022
struct IdList_item *pNewItem = &pNew->a[i];
111954112023
const struct IdList_item *pOldItem = &p->a[i];
@@ -112028,11 +112097,11 @@
112028112097
Expr *pExpr /* Expression to be appended. Might be NULL */
112029112098
){
112030112099
struct ExprList_item *pItem;
112031112100
ExprList *pList;
112032112101
112033
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
112102
+ pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4));
112034112103
if( pList==0 ){
112035112104
sqlite3ExprDelete(db, pExpr);
112036112105
return 0;
112037112106
}
112038112107
pList->nAlloc = 4;
@@ -112048,12 +112117,11 @@
112048112117
Expr *pExpr /* Expression to be appended. Might be NULL */
112049112118
){
112050112119
struct ExprList_item *pItem;
112051112120
ExprList *pNew;
112052112121
pList->nAlloc *= 2;
112053
- pNew = sqlite3DbRealloc(db, pList,
112054
- sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
112122
+ pNew = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc));
112055112123
if( pNew==0 ){
112056112124
sqlite3ExprListDelete(db, pList);
112057112125
sqlite3ExprDelete(db, pExpr);
112058112126
return 0;
112059112127
}else{
@@ -114685,11 +114753,11 @@
114685114753
return -1; /* Not found */
114686114754
}
114687114755
114688114756
114689114757
/*
114690
-** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This
114758
+** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This
114691114759
** function checks the Parse.pIdxPartExpr list to see if this column
114692114760
** can be replaced with a constant value. If so, it generates code to
114693114761
** put the constant value in a register (ideally, but not necessarily,
114694114762
** register iTarget) and returns the register number.
114695114763
**
@@ -118531,10 +118599,11 @@
118531118599
sqlite3 *db, /* Database handle */
118532118600
const char *zSql, /* SQL to parse */
118533118601
int bTemp /* True if SQL is from temp schema */
118534118602
){
118535118603
int rc;
118604
+ u64 flags;
118536118605
118537118606
sqlite3ParseObjectInit(p, db);
118538118607
if( zSql==0 ){
118539118608
return SQLITE_NOMEM;
118540118609
}
@@ -118549,11 +118618,15 @@
118549118618
db->init.iDb = (u8)iDb;
118550118619
}
118551118620
p->eParseMode = PARSE_MODE_RENAME;
118552118621
p->db = db;
118553118622
p->nQueryLoop = 1;
118623
+ flags = db->flags;
118624
+ testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );
118625
+ db->flags |= SQLITE_Comments;
118554118626
rc = sqlite3RunParser(p, zSql);
118627
+ db->flags = flags;
118555118628
if( db->mallocFailed ) rc = SQLITE_NOMEM;
118556118629
if( rc==SQLITE_OK
118557118630
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
118558118631
){
118559118632
rc = SQLITE_CORRUPT_BKPT;
@@ -119445,11 +119518,11 @@
119445119518
int rc;
119446119519
Parse sParse;
119447119520
u64 flags = db->flags;
119448119521
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
119449119522
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
119450
- db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
119523
+ db->flags = flags;
119451119524
if( rc==SQLITE_OK ){
119452119525
if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
119453119526
NameContext sNC;
119454119527
memset(&sNC, 0, sizeof(sNC));
119455119528
sNC.pParse = &sParse;
@@ -126268,11 +126341,11 @@
126268126341
"columns in the referenced table");
126269126342
goto fk_end;
126270126343
}else{
126271126344
nCol = pFromCol->nExpr;
126272126345
}
126273
- nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
126346
+ nByte = SZ_FKEY(nCol) + pTo->n + 1;
126274126347
if( pToCol ){
126275126348
for(i=0; i<pToCol->nExpr; i++){
126276126349
nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
126277126350
}
126278126351
}
@@ -127327,16 +127400,15 @@
127327127400
*/
127328127401
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
127329127402
sqlite3 *db = pParse->db;
127330127403
int i;
127331127404
if( pList==0 ){
127332
- pList = sqlite3DbMallocZero(db, sizeof(IdList) );
127405
+ pList = sqlite3DbMallocZero(db, SZ_IDLIST(1));
127333127406
if( pList==0 ) return 0;
127334127407
}else{
127335127408
IdList *pNew;
127336
- pNew = sqlite3DbRealloc(db, pList,
127337
- sizeof(IdList) + pList->nId*sizeof(pList->a));
127409
+ pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1));
127338127410
if( pNew==0 ){
127339127411
sqlite3IdListDelete(db, pList);
127340127412
return 0;
127341127413
}
127342127414
pList = pNew;
@@ -127431,12 +127503,11 @@
127431127503
sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
127432127504
SQLITE_MAX_SRCLIST);
127433127505
return 0;
127434127506
}
127435127507
if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
127436
- pNew = sqlite3DbRealloc(db, pSrc,
127437
- sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
127508
+ pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc));
127438127509
if( pNew==0 ){
127439127510
assert( db->mallocFailed );
127440127511
return 0;
127441127512
}
127442127513
pSrc = pNew;
@@ -127507,11 +127578,11 @@
127507127578
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
127508127579
assert( pParse!=0 );
127509127580
assert( pParse->db!=0 );
127510127581
db = pParse->db;
127511127582
if( pList==0 ){
127512
- pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
127583
+ pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1));
127513127584
if( pList==0 ) return 0;
127514127585
pList->nAlloc = 1;
127515127586
pList->nSrc = 1;
127516127587
memset(&pList->a[0], 0, sizeof(pList->a[0]));
127517127588
pList->a[0].iCursor = -1;
@@ -128393,14 +128464,13 @@
128393128464
}
128394128465
}
128395128466
}
128396128467
128397128468
if( pWith ){
128398
- sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
128399
- pNew = sqlite3DbRealloc(db, pWith, nByte);
128469
+ pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1));
128400128470
}else{
128401
- pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
128471
+ pNew = sqlite3DbMallocZero(db, SZ_WITH(1));
128402128472
}
128403128473
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
128404128474
128405128475
if( db->mallocFailed ){
128406128476
sqlite3CteDelete(db, pCte);
@@ -131933,11 +132003,11 @@
131933132003
**
131934132004
** The SUM() function follows the (broken) SQL standard which means
131935132005
** that it returns NULL if it sums over no inputs. TOTAL returns
131936132006
** 0.0 in that case. In addition, TOTAL always returns a float where
131937132007
** SUM might return an integer if it never encounters a floating point
131938
-** value. TOTAL never fails, but SUM might through an exception if
132008
+** value. TOTAL never fails, but SUM might throw an exception if
131939132009
** it overflows an integer.
131940132010
*/
131941132011
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
131942132012
SumCtx *p;
131943132013
int type;
@@ -139748,52 +139818,52 @@
139748139818
/* 11 */ "notnull",
139749139819
/* 12 */ "dflt_value",
139750139820
/* 13 */ "pk",
139751139821
/* 14 */ "hidden",
139752139822
/* table_info reuses 8 */
139753
- /* 15 */ "schema", /* Used by: table_list */
139754
- /* 16 */ "name",
139823
+ /* 15 */ "name", /* Used by: function_list */
139824
+ /* 16 */ "builtin",
139755139825
/* 17 */ "type",
139756
- /* 18 */ "ncol",
139757
- /* 19 */ "wr",
139758
- /* 20 */ "strict",
139759
- /* 21 */ "seqno", /* Used by: index_xinfo */
139760
- /* 22 */ "cid",
139761
- /* 23 */ "name",
139762
- /* 24 */ "desc",
139763
- /* 25 */ "coll",
139764
- /* 26 */ "key",
139765
- /* 27 */ "name", /* Used by: function_list */
139766
- /* 28 */ "builtin",
139767
- /* 29 */ "type",
139768
- /* 30 */ "enc",
139769
- /* 31 */ "narg",
139770
- /* 32 */ "flags",
139771
- /* 33 */ "tbl", /* Used by: stats */
139772
- /* 34 */ "idx",
139773
- /* 35 */ "wdth",
139774
- /* 36 */ "hght",
139775
- /* 37 */ "flgs",
139776
- /* 38 */ "seq", /* Used by: index_list */
139777
- /* 39 */ "name",
139778
- /* 40 */ "unique",
139779
- /* 41 */ "origin",
139780
- /* 42 */ "partial",
139826
+ /* 18 */ "enc",
139827
+ /* 19 */ "narg",
139828
+ /* 20 */ "flags",
139829
+ /* 21 */ "schema", /* Used by: table_list */
139830
+ /* 22 */ "name",
139831
+ /* 23 */ "type",
139832
+ /* 24 */ "ncol",
139833
+ /* 25 */ "wr",
139834
+ /* 26 */ "strict",
139835
+ /* 27 */ "seqno", /* Used by: index_xinfo */
139836
+ /* 28 */ "cid",
139837
+ /* 29 */ "name",
139838
+ /* 30 */ "desc",
139839
+ /* 31 */ "coll",
139840
+ /* 32 */ "key",
139841
+ /* 33 */ "seq", /* Used by: index_list */
139842
+ /* 34 */ "name",
139843
+ /* 35 */ "unique",
139844
+ /* 36 */ "origin",
139845
+ /* 37 */ "partial",
139846
+ /* 38 */ "tbl", /* Used by: stats */
139847
+ /* 39 */ "idx",
139848
+ /* 40 */ "wdth",
139849
+ /* 41 */ "hght",
139850
+ /* 42 */ "flgs",
139781139851
/* 43 */ "table", /* Used by: foreign_key_check */
139782139852
/* 44 */ "rowid",
139783139853
/* 45 */ "parent",
139784139854
/* 46 */ "fkid",
139785
- /* index_info reuses 21 */
139786
- /* 47 */ "seq", /* Used by: database_list */
139787
- /* 48 */ "name",
139788
- /* 49 */ "file",
139789
- /* 50 */ "busy", /* Used by: wal_checkpoint */
139790
- /* 51 */ "log",
139791
- /* 52 */ "checkpointed",
139792
- /* collation_list reuses 38 */
139855
+ /* 47 */ "busy", /* Used by: wal_checkpoint */
139856
+ /* 48 */ "log",
139857
+ /* 49 */ "checkpointed",
139858
+ /* 50 */ "seq", /* Used by: database_list */
139859
+ /* 51 */ "name",
139860
+ /* 52 */ "file",
139861
+ /* index_info reuses 27 */
139793139862
/* 53 */ "database", /* Used by: lock_status */
139794139863
/* 54 */ "status",
139864
+ /* collation_list reuses 33 */
139795139865
/* 55 */ "cache_size", /* Used by: default_cache_size */
139796139866
/* module_list pragma_list reuses 9 */
139797139867
/* 56 */ "timeout", /* Used by: busy_timeout */
139798139868
};
139799139869
@@ -139882,11 +139952,11 @@
139882139952
#endif
139883139953
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139884139954
{/* zName: */ "collation_list",
139885139955
/* ePragTyp: */ PragTyp_COLLATION_LIST,
139886139956
/* ePragFlg: */ PragFlg_Result0,
139887
- /* ColNames: */ 38, 2,
139957
+ /* ColNames: */ 33, 2,
139888139958
/* iArg: */ 0 },
139889139959
#endif
139890139960
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
139891139961
{/* zName: */ "compile_options",
139892139962
/* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
@@ -139917,11 +139987,11 @@
139917139987
#endif
139918139988
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139919139989
{/* zName: */ "database_list",
139920139990
/* ePragTyp: */ PragTyp_DATABASE_LIST,
139921139991
/* ePragFlg: */ PragFlg_Result0,
139922
- /* ColNames: */ 47, 3,
139992
+ /* ColNames: */ 50, 3,
139923139993
/* iArg: */ 0 },
139924139994
#endif
139925139995
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
139926139996
{/* zName: */ "default_cache_size",
139927139997
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
@@ -139997,11 +140067,11 @@
139997140067
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139998140068
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
139999140069
{/* zName: */ "function_list",
140000140070
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
140001140071
/* ePragFlg: */ PragFlg_Result0,
140002
- /* ColNames: */ 27, 6,
140072
+ /* ColNames: */ 15, 6,
140003140073
/* iArg: */ 0 },
140004140074
#endif
140005140075
#endif
140006140076
{/* zName: */ "hard_heap_limit",
140007140077
/* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT,
@@ -140026,21 +140096,21 @@
140026140096
#endif
140027140097
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
140028140098
{/* zName: */ "index_info",
140029140099
/* ePragTyp: */ PragTyp_INDEX_INFO,
140030140100
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140031
- /* ColNames: */ 21, 3,
140101
+ /* ColNames: */ 27, 3,
140032140102
/* iArg: */ 0 },
140033140103
{/* zName: */ "index_list",
140034140104
/* ePragTyp: */ PragTyp_INDEX_LIST,
140035140105
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140036
- /* ColNames: */ 38, 5,
140106
+ /* ColNames: */ 33, 5,
140037140107
/* iArg: */ 0 },
140038140108
{/* zName: */ "index_xinfo",
140039140109
/* ePragTyp: */ PragTyp_INDEX_INFO,
140040140110
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140041
- /* ColNames: */ 21, 6,
140111
+ /* ColNames: */ 27, 6,
140042140112
/* iArg: */ 1 },
140043140113
#endif
140044140114
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
140045140115
{/* zName: */ "integrity_check",
140046140116
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
@@ -140215,11 +140285,11 @@
140215140285
#endif
140216140286
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
140217140287
{/* zName: */ "stats",
140218140288
/* ePragTyp: */ PragTyp_STATS,
140219140289
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
140220
- /* ColNames: */ 33, 5,
140290
+ /* ColNames: */ 38, 5,
140221140291
/* iArg: */ 0 },
140222140292
#endif
140223140293
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
140224140294
{/* zName: */ "synchronous",
140225140295
/* ePragTyp: */ PragTyp_SYNCHRONOUS,
@@ -140234,11 +140304,11 @@
140234140304
/* ColNames: */ 8, 6,
140235140305
/* iArg: */ 0 },
140236140306
{/* zName: */ "table_list",
140237140307
/* ePragTyp: */ PragTyp_TABLE_LIST,
140238140308
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
140239
- /* ColNames: */ 15, 6,
140309
+ /* ColNames: */ 21, 6,
140240140310
/* iArg: */ 0 },
140241140311
{/* zName: */ "table_xinfo",
140242140312
/* ePragTyp: */ PragTyp_TABLE_INFO,
140243140313
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140244140314
/* ColNames: */ 8, 7,
@@ -140311,11 +140381,11 @@
140311140381
/* ColNames: */ 0, 0,
140312140382
/* iArg: */ 0 },
140313140383
{/* zName: */ "wal_checkpoint",
140314140384
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
140315140385
/* ePragFlg: */ PragFlg_NeedSchema,
140316
- /* ColNames: */ 50, 3,
140386
+ /* ColNames: */ 47, 3,
140317140387
/* iArg: */ 0 },
140318140388
#endif
140319140389
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
140320140390
{/* zName: */ "writable_schema",
140321140391
/* ePragTyp: */ PragTyp_FLAG,
@@ -140333,11 +140403,11 @@
140333140403
** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands
140334140404
** will be run with an analysis_limit set to the lessor of the value of
140335140405
** the following macro or to the actual analysis_limit if it is non-zero,
140336140406
** in order to prevent PRAGMA optimize from running for too long.
140337140407
**
140338
-** The value of 2000 is chosen emperically so that the worst-case run-time
140408
+** The value of 2000 is chosen empirically so that the worst-case run-time
140339140409
** for PRAGMA optimize does not exceed 100 milliseconds against a variety
140340140410
** of test databases on a RaspberryPI-4 compiled using -Os and without
140341140411
** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
140342140412
** this paragraph, "worst-case" means that ANALYZE ends up being
140343140413
** run on every table in the database. The worst case typically only
@@ -144622,11 +144692,11 @@
144622144692
pNew->iOffset = 0;
144623144693
pNew->selId = ++pParse->nSelect;
144624144694
pNew->addrOpenEphm[0] = -1;
144625144695
pNew->addrOpenEphm[1] = -1;
144626144696
pNew->nSelectRow = 0;
144627
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
144697
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
144628144698
pNew->pSrc = pSrc;
144629144699
pNew->pWhere = pWhere;
144630144700
pNew->pGroupBy = pGroupBy;
144631144701
pNew->pHaving = pHaving;
144632144702
pNew->pOrderBy = pOrderBy;
@@ -146005,20 +146075,20 @@
146005146075
/*
146006146076
** Allocate a KeyInfo object sufficient for an index of N key columns and
146007146077
** X extra columns.
146008146078
*/
146009146079
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
146010
- int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
146011
- KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
146080
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1);
146081
+ KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
146012146082
if( p ){
146013146083
p->aSortFlags = (u8*)&p->aColl[N+X];
146014146084
p->nKeyField = (u16)N;
146015146085
p->nAllField = (u16)(N+X);
146016146086
p->enc = ENC(db);
146017146087
p->db = db;
146018146088
p->nRef = 1;
146019
- memset(&p[1], 0, nExtra);
146089
+ memset(p->aColl, 0, nExtra);
146020146090
}else{
146021146091
return (KeyInfo*)sqlite3OomFault(db);
146022146092
}
146023146093
return p;
146024146094
}
@@ -150530,11 +150600,11 @@
150530150600
}
150531150601
pTabList = p->pSrc;
150532150602
pEList = p->pEList;
150533150603
if( pParse->pWith && (p->selFlags & SF_View) ){
150534150604
if( p->pWith==0 ){
150535
- p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
150605
+ p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) );
150536150606
if( p->pWith==0 ){
150537150607
return WRC_Abort;
150538150608
}
150539150609
}
150540150610
p->pWith->bView = 1;
@@ -151669,10 +151739,11 @@
151669151739
** * The subquery is a UNION ALL of two or more terms
151670151740
** * The subquery does not have a LIMIT clause
151671151741
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
151672151742
** * The outer query is a simple count(*) with no WHERE clause or other
151673151743
** extraneous syntax.
151744
+** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10)
151674151745
**
151675151746
** Return TRUE if the optimization is undertaken.
151676151747
*/
151677151748
static int countOfViewOptimization(Parse *pParse, Select *p){
151678151749
Select *pSub, *pPrior;
@@ -151701,11 +151772,15 @@
151701151772
if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */
151702151773
do{
151703151774
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
151704151775
if( pSub->pWhere ) return 0; /* No WHERE clause */
151705151776
if( pSub->pLimit ) return 0; /* No LIMIT clause */
151706
- if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
151777
+ if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){
151778
+ testcase( pSub->selFlags & SF_Aggregate );
151779
+ testcase( pSub->selFlags & SF_Distinct );
151780
+ return 0; /* Not an aggregate nor DISTINCT */
151781
+ }
151707151782
assert( pSub->pHaving==0 ); /* Due to the previous */
151708151783
pSub = pSub->pPrior; /* Repeat over compound */
151709151784
}while( pSub );
151710151785
151711151786
/* If we reach this point then it is OK to perform the transformation */
@@ -151713,11 +151788,11 @@
151713151788
db = pParse->db;
151714151789
pCount = pExpr;
151715151790
pExpr = 0;
151716151791
pSub = sqlite3SubqueryDetach(db, pFrom);
151717151792
sqlite3SrcListDelete(db, p->pSrc);
151718
- p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
151793
+ p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
151719151794
while( pSub ){
151720151795
Expr *pTerm;
151721151796
pPrior = pSub->pPrior;
151722151797
pSub->pPrior = 0;
151723151798
pSub->pNext = 0;
@@ -154504,11 +154579,12 @@
154504154579
Vdbe *v = pParse->pVdbe;
154505154580
sqlite3 *db = pParse->db;
154506154581
ExprList *pNew;
154507154582
Returning *pReturning;
154508154583
Select sSelect;
154509
- SrcList sFrom;
154584
+ SrcList *pFrom;
154585
+ u8 fromSpace[SZ_SRCLIST_1];
154510154586
154511154587
assert( v!=0 );
154512154588
if( !pParse->bReturning ){
154513154589
/* This RETURNING trigger must be for a different statement as
154514154590
** this statement lacks a RETURNING clause. */
@@ -154520,17 +154596,18 @@
154520154596
if( pTrigger != &(pReturning->retTrig) ){
154521154597
/* This RETURNING trigger is for a different statement */
154522154598
return;
154523154599
}
154524154600
memset(&sSelect, 0, sizeof(sSelect));
154525
- memset(&sFrom, 0, sizeof(sFrom));
154601
+ pFrom = (SrcList*)fromSpace;
154602
+ memset(pFrom, 0, SZ_SRCLIST_1);
154526154603
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
154527
- sSelect.pSrc = &sFrom;
154528
- sFrom.nSrc = 1;
154529
- sFrom.a[0].pSTab = pTab;
154530
- sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
154531
- sFrom.a[0].iCursor = -1;
154604
+ sSelect.pSrc = pFrom;
154605
+ pFrom->nSrc = 1;
154606
+ pFrom->a[0].pSTab = pTab;
154607
+ pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
154608
+ pFrom->a[0].iCursor = -1;
154532154609
sqlite3SelectPrep(pParse, &sSelect, 0);
154533154610
if( pParse->nErr==0 ){
154534154611
assert( db->mallocFailed==0 );
154535154612
sqlite3GenerateColumnNames(pParse, &sSelect);
154536154613
}
@@ -156927,11 +157004,11 @@
156927157004
saved_flags = db->flags;
156928157005
saved_mDbFlags = db->mDbFlags;
156929157006
saved_nChange = db->nChange;
156930157007
saved_nTotalChange = db->nTotalChange;
156931157008
saved_mTrace = db->mTrace;
156932
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
157009
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
156933157010
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
156934157011
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
156935157012
| SQLITE_Defensive | SQLITE_CountRows);
156936157013
db->mTrace = 0;
156937157014
@@ -159056,13 +159133,18 @@
159056159133
WhereLoop *pLoops; /* List of all WhereLoop objects */
159057159134
WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
159058159135
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
159059159136
WhereClause sWC; /* Decomposition of the WHERE clause */
159060159137
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
159061
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
159138
+ WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */
159062159139
};
159063159140
159141
+/*
159142
+** The size (in bytes) of a WhereInfo object that holds N WhereLevels.
159143
+*/
159144
+#define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel))
159145
+
159064159146
/*
159065159147
** Private interfaces - callable only by other where.c routines.
159066159148
**
159067159149
** where.c:
159068159150
*/
@@ -161509,12 +161591,11 @@
161509161591
*/
161510161592
if( pWInfo->nLevel>1 ){
161511161593
int nNotReady; /* The number of notReady tables */
161512161594
SrcItem *origSrc; /* Original list of tables */
161513161595
nNotReady = pWInfo->nLevel - iLevel - 1;
161514
- pOrTab = sqlite3DbMallocRawNN(db,
161515
- sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
161596
+ pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
161516161597
if( pOrTab==0 ) return notReady;
161517161598
pOrTab->nAlloc = (u8)(nNotReady + 1);
161518161599
pOrTab->nSrc = pOrTab->nAlloc;
161519161600
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
161520161601
origSrc = pWInfo->pTabList->a;
@@ -162053,11 +162134,12 @@
162053162134
Expr *pSubWhere = 0;
162054162135
WhereClause *pWC = &pWInfo->sWC;
162055162136
WhereInfo *pSubWInfo;
162056162137
WhereLoop *pLoop = pLevel->pWLoop;
162057162138
SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
162058
- SrcList sFrom;
162139
+ SrcList *pFrom;
162140
+ u8 fromSpace[SZ_SRCLIST_1];
162059162141
Bitmask mAll = 0;
162060162142
int k;
162061162143
162062162144
ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
162063162145
sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
@@ -162097,17 +162179,18 @@
162097162179
if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
162098162180
pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
162099162181
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
162100162182
}
162101162183
}
162102
- sFrom.nSrc = 1;
162103
- sFrom.nAlloc = 1;
162104
- memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
162105
- sFrom.a[0].fg.jointype = 0;
162184
+ pFrom = (SrcList*)fromSpace;
162185
+ pFrom->nSrc = 1;
162186
+ pFrom->nAlloc = 1;
162187
+ memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
162188
+ pFrom->a[0].fg.jointype = 0;
162106162189
assert( pParse->withinRJSubrtn < 100 );
162107162190
pParse->withinRJSubrtn++;
162108
- pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
162191
+ pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
162109162192
WHERE_RIGHT_JOIN, 0);
162110162193
if( pSubWInfo ){
162111162194
int iCur = pLevel->iTabCur;
162112162195
int r = ++pParse->nMem;
162113162196
int nPk;
@@ -164091,15 +164174,20 @@
164091164174
WhereClause *pWC; /* The Where clause being analyzed */
164092164175
Parse *pParse; /* The parsing context */
164093164176
int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
164094164177
u32 mIn; /* Mask of terms that are <col> IN (...) */
164095164178
u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */
164096
- sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
164097
- ** because extra space is allocated to hold up
164098
- ** to nTerm such values */
164179
+ sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST
164180
+ ** Extra space is allocated to hold up
164181
+ ** to nTerm such values */
164099164182
};
164100164183
164184
+/* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as
164185
+** many as N constraints */
164186
+#define SZ_HIDDENINDEXINFO(N) \
164187
+ (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*))
164188
+
164101164189
/* Forward declaration of methods */
164102164190
static int whereLoopResize(sqlite3*, WhereLoop*, int);
164103164191
164104164192
/*
164105164193
** Return the estimated number of output rows from a WHERE clause
@@ -165573,12 +165661,12 @@
165573165661
165574165662
/* Allocate the sqlite3_index_info structure
165575165663
*/
165576165664
pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
165577165665
+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
165578
- + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
165579
- + sizeof(sqlite3_value*)*nTerm );
165666
+ + sizeof(*pIdxOrderBy)*nOrderBy
165667
+ + SZ_HIDDENINDEXINFO(nTerm) );
165580165668
if( pIdxInfo==0 ){
165581165669
sqlite3ErrorMsg(pParse, "out of memory");
165582165670
return 0;
165583165671
}
165584165672
pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
@@ -170768,14 +170856,11 @@
170768170856
** struct, the contents of WhereInfo.a[], the WhereClause structure
170769170857
** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
170770170858
** field (type Bitmask) it must be aligned on an 8-byte boundary on
170771170859
** some architectures. Hence the ROUND8() below.
170772170860
*/
170773
- nByteWInfo = ROUND8P(sizeof(WhereInfo));
170774
- if( nTabList>1 ){
170775
- nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel));
170776
- }
170861
+ nByteWInfo = SZ_WHEREINFO(nTabList);
170777170862
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
170778170863
if( db->mallocFailed ){
170779170864
sqlite3DbFree(db, pWInfo);
170780170865
pWInfo = 0;
170781170866
goto whereBeginError;
@@ -181607,11 +181692,15 @@
181607181692
tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
181608181693
}else if( tokenType==TK_FILTER ){
181609181694
assert( n==6 );
181610181695
tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
181611181696
#endif /* SQLITE_OMIT_WINDOWFUNC */
181612
- }else if( tokenType==TK_COMMENT && (db->flags & SQLITE_Comments)!=0 ){
181697
+ }else if( tokenType==TK_COMMENT
181698
+ && (db->init.busy || (db->flags & SQLITE_Comments)!=0)
181699
+ ){
181700
+ /* Ignore SQL comments if either (1) we are reparsing the schema or
181701
+ ** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */
181613181702
zSql += n;
181614181703
continue;
181615181704
}else if( tokenType!=TK_QNUMBER ){
181616181705
Token x;
181617181706
x.z = zSql;
@@ -182502,10 +182591,18 @@
182502182591
}
182503182592
#endif
182504182593
if( rc==SQLITE_OK ){
182505182594
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
182506182595
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
182596
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
182597
+ {
182598
+ int SQLITE_EXTRA_INIT_MUTEXED(const char*);
182599
+ rc = SQLITE_EXTRA_INIT_MUTEXED(0);
182600
+ }
182601
+#endif
182602
+ }
182603
+ if( rc==SQLITE_OK ){
182507182604
sqlite3MemoryBarrier();
182508182605
sqlite3GlobalConfig.isInit = 1;
182509182606
#ifdef SQLITE_EXTRA_INIT
182510182607
bRunExtraInit = 1;
182511182608
#endif
@@ -184063,10 +184160,14 @@
184063184160
sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt));
184064184161
sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC);
184065184162
}
184066184163
}
184067184164
sqlite3BtreeLeaveAll(db);
184165
+#endif
184166
+#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
184167
+ UNUSED_PARAMETER(db);
184168
+ UNUSED_PARAMETER(flags);
184068184169
#endif
184069184170
return SQLITE_OK;
184070184171
}
184071184172
184072184173
/*
@@ -186032,11 +186133,11 @@
186032186133
}else if( pData==0 ){
186033186134
sqlite3_mutex_leave(db->mutex);
186034186135
return SQLITE_OK;
186035186136
}else{
186036186137
size_t n = strlen(zName);
186037
- p = sqlite3_malloc64( sizeof(DbClientData)+n+1 );
186138
+ p = sqlite3_malloc64( SZ_DBCLIENTDATA(n+1) );
186038186139
if( p==0 ){
186039186140
if( xDestructor ) xDestructor(pData);
186040186141
sqlite3_mutex_leave(db->mutex);
186041186142
return SQLITE_NOMEM;
186042186143
}
@@ -186398,12 +186499,12 @@
186398186499
#endif
186399186500
186400186501
/* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b);
186401186502
**
186402186503
** If b is true, then activate the SQLITE_FkNoAction setting. If b is
186403
- ** false then clearn that setting. If the SQLITE_FkNoAction setting is
186404
- ** abled, all foreign key ON DELETE and ON UPDATE actions behave as if
186504
+ ** false then clear that setting. If the SQLITE_FkNoAction setting is
186505
+ ** enabled, all foreign key ON DELETE and ON UPDATE actions behave as if
186405186506
** they were NO ACTION, regardless of how they are defined.
186406186507
**
186407186508
** NB: One must usually run "PRAGMA writable_schema=RESET" after
186408186509
** using this test-control, before it will take full effect. failing
186409186510
** to reset the schema can result in some unexpected behavior.
@@ -187746,11 +187847,11 @@
187746187847
** }
187747187848
**
187748187849
** Here, array { X } means zero or more occurrences of X, adjacent in
187749187850
** memory. A "position" is an index of a token in the token stream
187750187851
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
187751
-** in the same logical place as the position element, and act as sentinals
187852
+** in the same logical place as the position element, and act as sentinels
187752187853
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
187753187854
** The positions numbers are not stored literally but rather as two more
187754187855
** than the difference from the prior position, or the just the position plus
187755187856
** 2 for the first position. Example:
187756187857
**
@@ -188433,10 +188534,23 @@
188433188534
188434188535
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
188435188536
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
188436188537
188437188538
#define deliberate_fall_through
188539
+
188540
+/*
188541
+** Macros needed to provide flexible arrays in a portable way
188542
+*/
188543
+#ifndef offsetof
188544
+# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
188545
+#endif
188546
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
188547
+# define FLEXARRAY
188548
+#else
188549
+# define FLEXARRAY 1
188550
+#endif
188551
+
188438188552
188439188553
#endif /* SQLITE_AMALGAMATION */
188440188554
188441188555
#ifdef SQLITE_DEBUG
188442188556
SQLITE_PRIVATE int sqlite3Fts3Corrupt(void);
@@ -188538,11 +188652,11 @@
188538188652
int inTransaction; /* True after xBegin but before xCommit/xRollback */
188539188653
int mxSavepoint; /* Largest valid xSavepoint integer */
188540188654
#endif
188541188655
188542188656
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
188543
- /* True to disable the incremental doclist optimization. This is controled
188657
+ /* True to disable the incremental doclist optimization. This is controlled
188544188658
** by special insert command 'test-no-incr-doclist'. */
188545188659
int bNoIncrDoclist;
188546188660
188547188661
/* Number of segments in a level */
188548188662
int nMergeCount;
@@ -188590,11 +188704,11 @@
188590188704
#define FTS3_EVAL_NEXT 1
188591188705
#define FTS3_EVAL_MATCHINFO 2
188592188706
188593188707
/*
188594188708
** The Fts3Cursor.eSearch member is always set to one of the following.
188595
-** Actualy, Fts3Cursor.eSearch can be greater than or equal to
188709
+** Actually, Fts3Cursor.eSearch can be greater than or equal to
188596188710
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
188597188711
** of the column to be searched. For example, in
188598188712
**
188599188713
** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
188600188714
** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
@@ -188663,12 +188777,16 @@
188663188777
/* Variables below this point are populated by fts3_expr.c when parsing
188664188778
** a MATCH expression. Everything above is part of the evaluation phase.
188665188779
*/
188666188780
int nToken; /* Number of tokens in the phrase */
188667188781
int iColumn; /* Index of column this phrase must match */
188668
- Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
188782
+ Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */
188669188783
};
188784
+
188785
+/* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */
188786
+#define SZ_FTS3PHRASE(N) \
188787
+ (offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken))
188670188788
188671188789
/*
188672188790
** A tree of these objects forms the RHS of a MATCH operator.
188673188791
**
188674188792
** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
@@ -191243,11 +191361,11 @@
191243191361
**
191244191362
** The space required to store the output is therefore the sum of the
191245191363
** sizes of the two inputs, plus enough space for exactly one of the input
191246191364
** docids to grow.
191247191365
**
191248
- ** A symetric argument may be made if the doclists are in descending
191366
+ ** A symmetric argument may be made if the doclists are in descending
191249191367
** order.
191250191368
*/
191251191369
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
191252191370
if( !aOut ) return SQLITE_NOMEM;
191253191371
@@ -193341,11 +193459,11 @@
193341193459
**
193342193460
** * features at least one token that uses an incremental doclist, and
193343193461
**
193344193462
** * does not contain any deferred tokens.
193345193463
**
193346
-** Advance it to the next matching documnent in the database and populate
193464
+** Advance it to the next matching document in the database and populate
193347193465
** the Fts3Doclist.pList and nList fields.
193348193466
**
193349193467
** If there is no "next" entry and no error occurs, then *pbEof is set to
193350193468
** 1 before returning. Otherwise, if no error occurs and the iterator is
193351193469
** successfully advanced, *pbEof is set to 0.
@@ -194348,11 +194466,11 @@
194348194466
194349194467
return rc;
194350194468
}
194351194469
194352194470
/*
194353
-** Restart interation for expression pExpr so that the next call to
194471
+** Restart iteration for expression pExpr so that the next call to
194354194472
** fts3EvalNext() visits the first row. Do not allow incremental
194355194473
** loading or merging of phrase doclists for this iteration.
194356194474
**
194357194475
** If *pRc is other than SQLITE_OK when this function is called, it is
194358194476
** a no-op. If an error occurs within this function, *pRc is set to an
@@ -195539,10 +195657,27 @@
195539195657
/*
195540195658
** Function getNextNode(), which is called by fts3ExprParse(), may itself
195541195659
** call fts3ExprParse(). So this forward declaration is required.
195542195660
*/
195543195661
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
195662
+
195663
+/*
195664
+** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
195665
+** is defined, search for '(' and ')' as well. Return the index of the first
195666
+** such character in the buffer. If there is no such character, return -1.
195667
+*/
195668
+static int findBarredChar(const char *z, int n){
195669
+ int ii;
195670
+ for(ii=0; ii<n; ii++){
195671
+ if( (z[ii]=='"')
195672
+ || (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')'))
195673
+ ){
195674
+ return ii;
195675
+ }
195676
+ }
195677
+ return -1;
195678
+}
195544195679
195545195680
/*
195546195681
** Extract the next token from buffer z (length n) using the tokenizer
195547195682
** and other information (column names etc.) in pParse. Create an Fts3Expr
195548195683
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -195564,38 +195699,42 @@
195564195699
sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
195565195700
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
195566195701
int rc;
195567195702
sqlite3_tokenizer_cursor *pCursor;
195568195703
Fts3Expr *pRet = 0;
195569
- int i = 0;
195570
-
195571
- /* Set variable i to the maximum number of bytes of input to tokenize. */
195572
- for(i=0; i<n; i++){
195573
- if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
195574
- if( z[i]=='"' ) break;
195575
- }
195576
-
195577
- *pnConsumed = i;
195578
- rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
195704
+
195705
+ *pnConsumed = n;
195706
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
195579195707
if( rc==SQLITE_OK ){
195580195708
const char *zToken;
195581195709
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
195582195710
sqlite3_int64 nByte; /* total space to allocate */
195583195711
195584195712
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
195585195713
if( rc==SQLITE_OK ){
195586
- nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
195714
+ /* Check that this tokenization did not gobble up any " characters. Or,
195715
+ ** if enable_parenthesis is true, that it did not gobble up any
195716
+ ** open or close parenthesis characters either. If it did, call
195717
+ ** getNextToken() again, but pass only that part of the input buffer
195718
+ ** up to the first such character. */
195719
+ int iBarred = findBarredChar(z, iEnd);
195720
+ if( iBarred>=0 ){
195721
+ pModule->xClose(pCursor);
195722
+ return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
195723
+ }
195724
+
195725
+ nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
195587195726
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
195588195727
if( !pRet ){
195589195728
rc = SQLITE_NOMEM;
195590195729
}else{
195591195730
pRet->eType = FTSQUERY_PHRASE;
195592195731
pRet->pPhrase = (Fts3Phrase *)&pRet[1];
195593195732
pRet->pPhrase->nToken = 1;
195594195733
pRet->pPhrase->iColumn = iCol;
195595195734
pRet->pPhrase->aToken[0].n = nToken;
195596
- pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
195735
+ pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
195597195736
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
195598195737
195599195738
if( iEnd<n && z[iEnd]=='*' ){
195600195739
pRet->pPhrase->aToken[0].isPrefix = 1;
195601195740
iEnd++;
@@ -195615,11 +195754,15 @@
195615195754
}
195616195755
}
195617195756
195618195757
}
195619195758
*pnConsumed = iEnd;
195620
- }else if( i && rc==SQLITE_DONE ){
195759
+ }else if( n && rc==SQLITE_DONE ){
195760
+ int iBarred = findBarredChar(z, n);
195761
+ if( iBarred>=0 ){
195762
+ *pnConsumed = iBarred;
195763
+ }
195621195764
rc = SQLITE_OK;
195622195765
}
195623195766
195624195767
pModule->xClose(pCursor);
195625195768
}
@@ -195664,11 +195807,11 @@
195664195807
Fts3Expr *p = 0;
195665195808
sqlite3_tokenizer_cursor *pCursor = 0;
195666195809
char *zTemp = 0;
195667195810
i64 nTemp = 0;
195668195811
195669
- const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
195812
+ const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
195670195813
int nToken = 0;
195671195814
195672195815
/* The final Fts3Expr data structure, including the Fts3Phrase,
195673195816
** Fts3PhraseToken structures token buffers are all stored as a single
195674195817
** allocation so that the expression can be freed with a single call to
@@ -196036,11 +196179,11 @@
196036196179
int eType = p->eType;
196037196180
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
196038196181
196039196182
/* The isRequirePhrase variable is set to true if a phrase or
196040196183
** an expression contained in parenthesis is required. If a
196041
- ** binary operator (AND, OR, NOT or NEAR) is encounted when
196184
+ ** binary operator (AND, OR, NOT or NEAR) is encountered when
196042196185
** isRequirePhrase is set, this is a syntax error.
196043196186
*/
196044196187
if( !isPhrase && isRequirePhrase ){
196045196188
sqlite3Fts3ExprFree(p);
196046196189
rc = SQLITE_ERROR;
@@ -196618,11 +196761,10 @@
196618196761
pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
196619196762
);
196620196763
}
196621196764
196622196765
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
196623
- sqlite3Fts3ExprFree(pExpr);
196624196766
sqlite3_result_error(context, "Error parsing expression", -1);
196625196767
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
196626196768
sqlite3_result_error_nomem(context);
196627196769
}else{
196628196770
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
@@ -196861,11 +197003,11 @@
196861197003
pEntry->count++;
196862197004
pEntry->chain = pNew;
196863197005
}
196864197006
196865197007
196866
-/* Resize the hash table so that it cantains "new_size" buckets.
197008
+/* Resize the hash table so that it contains "new_size" buckets.
196867197009
** "new_size" must be a power of 2. The hash table might fail
196868197010
** to resize if sqliteMalloc() fails.
196869197011
**
196870197012
** Return non-zero if a memory allocation error occurs.
196871197013
*/
@@ -197316,11 +197458,11 @@
197316197458
isConsonant(z+2);
197317197459
}
197318197460
197319197461
/*
197320197462
** If the word ends with zFrom and xCond() is true for the stem
197321
-** of the word that preceeds the zFrom ending, then change the
197463
+** of the word that precedes the zFrom ending, then change the
197322197464
** ending to zTo.
197323197465
**
197324197466
** The input word *pz and zFrom are both in reverse order. zTo
197325197467
** is in normal order.
197326197468
**
@@ -202899,11 +203041,11 @@
202899203041
** previous term. Before this function returns, it is updated to contain a
202900203042
** copy of zTerm/nTerm.
202901203043
**
202902203044
** It is assumed that the buffer associated with pNode is already large
202903203045
** enough to accommodate the new entry. The buffer associated with pPrev
202904
-** is extended by this function if requrired.
203046
+** is extended by this function if required.
202905203047
**
202906203048
** If an error (i.e. OOM condition) occurs, an SQLite error code is
202907203049
** returned. Otherwise, SQLITE_OK.
202908203050
*/
202909203051
static int fts3AppendToNode(
@@ -204562,11 +204704,11 @@
204562204704
#endif
204563204705
204564204706
/*
204565204707
** SQLite value pRowid contains the rowid of a row that may or may not be
204566204708
** present in the FTS3 table. If it is, delete it and adjust the contents
204567
-** of subsiduary data structures accordingly.
204709
+** of subsidiary data structures accordingly.
204568204710
*/
204569204711
static int fts3DeleteByRowid(
204570204712
Fts3Table *p,
204571204713
sqlite3_value *pRowid,
204572204714
int *pnChng, /* IN/OUT: Decrement if row is deleted */
@@ -204888,12 +205030,16 @@
204888205030
struct MatchinfoBuffer {
204889205031
u8 aRef[3];
204890205032
int nElem;
204891205033
int bGlobal; /* Set if global data is loaded */
204892205034
char *zMatchinfo;
204893
- u32 aMatchinfo[1];
205035
+ u32 aMI[FLEXARRAY];
204894205036
};
205037
+
205038
+/* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */
205039
+#define SZ_MATCHINFOBUFFER(N) \
205040
+ (offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64))
204895205041
204896205042
204897205043
/*
204898205044
** The snippet() and offsets() functions both return text values. An instance
204899205045
** of the following structure is used to accumulate those values while the
@@ -204915,17 +205061,17 @@
204915205061
** Allocate a two-slot MatchinfoBuffer object.
204916205062
*/
204917205063
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
204918205064
MatchinfoBuffer *pRet;
204919205065
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
204920
- + sizeof(MatchinfoBuffer);
205066
+ + SZ_MATCHINFOBUFFER(1);
204921205067
sqlite3_int64 nStr = strlen(zMatchinfo);
204922205068
204923205069
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
204924205070
if( pRet ){
204925
- pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
204926
- pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
205071
+ pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
205072
+ pRet->aMI[1+nElem] = pRet->aMI[0]
204927205073
+ sizeof(u32)*((int)nElem+1);
204928205074
pRet->nElem = (int)nElem;
204929205075
pRet->zMatchinfo = ((char*)pRet) + nByte;
204930205076
memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
204931205077
pRet->aRef[0] = 1;
@@ -204935,14 +205081,14 @@
204935205081
}
204936205082
204937205083
static void fts3MIBufferFree(void *p){
204938205084
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
204939205085
204940
- assert( (u32*)p==&pBuf->aMatchinfo[1]
204941
- || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
205086
+ assert( (u32*)p==&pBuf->aMI[1]
205087
+ || (u32*)p==&pBuf->aMI[pBuf->nElem+2]
204942205088
);
204943
- if( (u32*)p==&pBuf->aMatchinfo[1] ){
205089
+ if( (u32*)p==&pBuf->aMI[1] ){
204944205090
pBuf->aRef[1] = 0;
204945205091
}else{
204946205092
pBuf->aRef[2] = 0;
204947205093
}
204948205094
@@ -204955,32 +205101,32 @@
204955205101
void (*xRet)(void*) = 0;
204956205102
u32 *aOut = 0;
204957205103
204958205104
if( p->aRef[1]==0 ){
204959205105
p->aRef[1] = 1;
204960
- aOut = &p->aMatchinfo[1];
205106
+ aOut = &p->aMI[1];
204961205107
xRet = fts3MIBufferFree;
204962205108
}
204963205109
else if( p->aRef[2]==0 ){
204964205110
p->aRef[2] = 1;
204965
- aOut = &p->aMatchinfo[p->nElem+2];
205111
+ aOut = &p->aMI[p->nElem+2];
204966205112
xRet = fts3MIBufferFree;
204967205113
}else{
204968205114
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
204969205115
if( aOut ){
204970205116
xRet = sqlite3_free;
204971
- if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
205117
+ if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32));
204972205118
}
204973205119
}
204974205120
204975205121
*paOut = aOut;
204976205122
return xRet;
204977205123
}
204978205124
204979205125
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
204980205126
p->bGlobal = 1;
204981
- memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
205127
+ memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32));
204982205128
}
204983205129
204984205130
/*
204985205131
** Free a MatchinfoBuffer object allocated using fts3MIBufferNew()
204986205132
*/
@@ -205391,11 +205537,11 @@
205391205537
if( nAppend<0 ){
205392205538
nAppend = (int)strlen(zAppend);
205393205539
}
205394205540
205395205541
/* If there is insufficient space allocated at StrBuffer.z, use realloc()
205396
- ** to grow the buffer until so that it is big enough to accomadate the
205542
+ ** to grow the buffer until so that it is big enough to accommodate the
205397205543
** appended data.
205398205544
*/
205399205545
if( pStr->n+nAppend+1>=pStr->nAlloc ){
205400205546
sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
205401205547
char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
@@ -207766,11 +207912,11 @@
207766207912
**
207767207913
** When a match if found, the matching entry is moved to become the
207768207914
** most-recently used entry if it isn't so already.
207769207915
**
207770207916
** The JsonParse object returned still belongs to the Cache and might
207771
-** be deleted at any moment. If the caller whants the JsonParse to
207917
+** be deleted at any moment. If the caller wants the JsonParse to
207772207918
** linger, it needs to increment the nPJRef reference counter.
207773207919
*/
207774207920
static JsonParse *jsonCacheSearch(
207775207921
sqlite3_context *ctx, /* The SQL statement context holding the cache */
207776207922
sqlite3_value *pArg /* Function argument containing SQL text */
@@ -210811,11 +210957,11 @@
210811210957
**
210812210958
** This goes against all historical documentation about how the SQLite
210813210959
** JSON functions were suppose to work. From the beginning, blob was
210814210960
** reserved for expansion and a blob value should have raised an error.
210815210961
** But it did not, due to a bug. And many applications came to depend
210816
- ** upon this buggy behavior, espeically when using the CLI and reading
210962
+ ** upon this buggy behavior, especially when using the CLI and reading
210817210963
** JSON text using readfile(), which returns a blob. For this reason
210818210964
** we will continue to support the bug moving forward.
210819210965
** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
210820210966
*/
210821210967
}
@@ -212911,10 +213057,18 @@
212911213057
# define NEVER(X) ((X)?(assert(0),1):0)
212912213058
#else
212913213059
# define ALWAYS(X) (X)
212914213060
# define NEVER(X) (X)
212915213061
#endif
213062
+#ifndef offsetof
213063
+#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
213064
+#endif
213065
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
213066
+# define FLEXARRAY
213067
+#else
213068
+# define FLEXARRAY 1
213069
+#endif
212916213070
#endif /* !defined(SQLITE_AMALGAMATION) */
212917213071
212918213072
/* Macro to check for 4-byte alignment. Only used inside of assert() */
212919213073
#ifdef SQLITE_DEBUG
212920213074
# define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0)
@@ -213231,13 +213385,17 @@
213231213385
struct RtreeMatchArg {
213232213386
u32 iSize; /* Size of this object */
213233213387
RtreeGeomCallback cb; /* Info about the callback functions */
213234213388
int nParam; /* Number of parameters to the SQL function */
213235213389
sqlite3_value **apSqlParam; /* Original SQL parameter values */
213236
- RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
213390
+ RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */
213237213391
};
213238213392
213393
+/* Size of an RtreeMatchArg object with N parameters */
213394
+#define SZ_RTREEMATCHARG(N) \
213395
+ (offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue))
213396
+
213239213397
#ifndef MAX
213240213398
# define MAX(x,y) ((x) < (y) ? (y) : (x))
213241213399
#endif
213242213400
#ifndef MIN
213243213401
# define MIN(x,y) ((x) > (y) ? (y) : (x))
@@ -214922,11 +215080,11 @@
214922215080
214923215081
return rc;
214924215082
}
214925215083
214926215084
/*
214927
-** Return the N-dimensional volumn of the cell stored in *p.
215085
+** Return the N-dimensional volume of the cell stored in *p.
214928215086
*/
214929215087
static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
214930215088
RtreeDValue area = (RtreeDValue)1;
214931215089
assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
214932215090
#ifndef SQLITE_RTREE_INT_ONLY
@@ -216688,11 +216846,11 @@
216688216846
}
216689216847
216690216848
/*
216691216849
** The second and subsequent arguments to this function are a printf()
216692216850
** style format string and arguments. This function formats the string and
216693
-** appends it to the report being accumuated in pCheck.
216851
+** appends it to the report being accumulated in pCheck.
216694216852
*/
216695216853
static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
216696216854
va_list ap;
216697216855
va_start(ap, zFmt);
216698216856
if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){
@@ -217876,11 +218034,11 @@
217876218034
217877218035
/*
217878218036
** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
217879218037
** Returns:
217880218038
**
217881
-** +2 x0,y0 is on the line segement
218039
+** +2 x0,y0 is on the line segment
217882218040
**
217883218041
** +1 x0,y0 is beneath line segment
217884218042
**
217885218043
** 0 x0,y0 is not on or beneath the line segment or the line segment
217886218044
** is vertical and x0,y0 is not on the line segment
@@ -217982,11 +218140,11 @@
217982218140
}
217983218141
sqlite3_free(p1);
217984218142
sqlite3_free(p2);
217985218143
}
217986218144
217987
-/* Objects used by the overlap algorihm. */
218145
+/* Objects used by the overlap algorithm. */
217988218146
typedef struct GeoEvent GeoEvent;
217989218147
typedef struct GeoSegment GeoSegment;
217990218148
typedef struct GeoOverlap GeoOverlap;
217991218149
struct GeoEvent {
217992218150
double x; /* X coordinate at which event occurs */
@@ -219029,12 +219187,11 @@
219029219187
RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
219030219188
RtreeMatchArg *pBlob;
219031219189
sqlite3_int64 nBlob;
219032219190
int memErr = 0;
219033219191
219034
- nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
219035
- + nArg*sizeof(sqlite3_value*);
219192
+ nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*);
219036219193
pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
219037219194
if( !pBlob ){
219038219195
sqlite3_result_error_nomem(ctx);
219039219196
}else{
219040219197
int i;
@@ -220125,11 +220282,11 @@
220125220282
** to read from the original database snapshot. In other words, partially
220126220283
** applied transactions are not visible to other clients.
220127220284
**
220128220285
** "RBU" stands for "Resumable Bulk Update". As in a large database update
220129220286
** transmitted via a wireless network to a mobile device. A transaction
220130
-** applied using this extension is hence refered to as an "RBU update".
220287
+** applied using this extension is hence referred to as an "RBU update".
220131220288
**
220132220289
**
220133220290
** LIMITATIONS
220134220291
**
220135220292
** An "RBU update" transaction is subject to the following limitations:
@@ -220422,11 +220579,11 @@
220422220579
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
220423220580
** of the state tables within the state database are zeroed. This way,
220424220581
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
220425220582
** new RBU vacuum operation.
220426220583
**
220427
-** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
220584
+** As with sqlite3rbu_open(), Zipvfs users should refer to the comment
220428220585
** describing the sqlite3rbu_create_vfs() API function below for
220429220586
** a description of the complications associated with using RBU with
220430220587
** zipvfs databases.
220431220588
*/
220432220589
SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
@@ -220518,11 +220675,11 @@
220518220675
/*
220519220676
** Close an RBU handle.
220520220677
**
220521220678
** If the RBU update has been completely applied, mark the RBU database
220522220679
** as fully applied. Otherwise, assuming no error has occurred, save the
220523
-** current state of the RBU update appliation to the RBU database.
220680
+** current state of the RBU update application to the RBU database.
220524220681
**
220525220682
** If an error has already occurred as part of an sqlite3rbu_step()
220526220683
** or sqlite3rbu_open() call, or if one occurs within this function, an
220527220684
** SQLite error code is returned. Additionally, if pzErrmsg is not NULL,
220528220685
** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted
@@ -225444,11 +225601,11 @@
225444225601
int rc;
225445225602
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
225446225603
225447225604
/* If this is an RBU vacuum operation and this is the target database,
225448225605
** pretend that it has at least one page. Otherwise, SQLite will not
225449
- ** check for the existance of a *-wal file. rbuVfsRead() contains
225606
+ ** check for the existence of a *-wal file. rbuVfsRead() contains
225450225607
** similar logic. */
225451225608
if( rc==SQLITE_OK && *pSize==0
225452225609
&& p->pRbu && rbuIsVacuum(p->pRbu)
225453225610
&& (p->openFlags & SQLITE_OPEN_MAIN_DB)
225454225611
){
@@ -228674,11 +228831,11 @@
228674228831
}
228675228832
228676228833
/*
228677228834
** This function is called to initialize the SessionTable.nCol, azCol[]
228678228835
** abPK[] and azDflt[] members of SessionTable object pTab. If these
228679
-** fields are already initilialized, this function is a no-op.
228836
+** fields are already initialized, this function is a no-op.
228680228837
**
228681228838
** If an error occurs, an error code is stored in sqlite3_session.rc and
228682228839
** non-zero returned. Or, if no error occurs but the table has no primary
228683228840
** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to
228684228841
** indicate that updates on this table should be ignored. SessionTable.abPK
@@ -230497,11 +230654,11 @@
230497230654
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
230498230655
void **ppChangeset /* OUT: Buffer containing changeset */
230499230656
){
230500230657
sqlite3 *db = pSession->db; /* Source database handle */
230501230658
SessionTable *pTab; /* Used to iterate through attached tables */
230502
- SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
230659
+ SessionBuffer buf = {0,0,0}; /* Buffer in which to accumulate changeset */
230503230660
int rc; /* Return code */
230504230661
230505230662
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
230506230663
assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );
230507230664
@@ -234931,10 +235088,22 @@
234931235088
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
234932235089
#else
234933235090
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
234934235091
#endif
234935235092
235093
+/*
235094
+** Macros needed to provide flexible arrays in a portable way
235095
+*/
235096
+#ifndef offsetof
235097
+# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
235098
+#endif
235099
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
235100
+# define FLEXARRAY
235101
+#else
235102
+# define FLEXARRAY 1
235103
+#endif
235104
+
234936235105
#endif
234937235106
234938235107
/* Truncate very long tokens to this many bytes. Hard limit is
234939235108
** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
234940235109
** field that occurs at the start of each leaf page (see fts5_index.c). */
@@ -235003,14 +235172,15 @@
235003235172
**
235004235173
** This object is used by fts5_expr.c and fts5_index.c.
235005235174
*/
235006235175
struct Fts5Colset {
235007235176
int nCol;
235008
- int aiCol[1];
235177
+ int aiCol[FLEXARRAY];
235009235178
};
235010235179
235011
-
235180
+/* Size (int bytes) of a complete Fts5Colset object with N columns. */
235181
+#define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2))
235012235182
235013235183
/**************************************************************************
235014235184
** Interface to code in fts5_config.c. fts5_config.c contains contains code
235015235185
** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
235016235186
*/
@@ -235835,11 +236005,11 @@
235835236005
*************************************************************************
235836236006
** Driver template for the LEMON parser generator.
235837236007
**
235838236008
** The "lemon" program processes an LALR(1) input grammar file, then uses
235839236009
** this template to construct a parser. The "lemon" program inserts text
235840
-** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
236010
+** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
235841236011
** interstitial "-" characters) contained in this template is changed into
235842236012
** the value of the %name directive from the grammar. Otherwise, the content
235843236013
** of this template is copied straight through into the generate parser
235844236014
** source file.
235845236015
**
@@ -237989,11 +238159,11 @@
237989238159
** where "N" is the total number of documents in the set and nHit
237990238160
** is the number that contain at least one instance of the phrase
237991238161
** under consideration.
237992238162
**
237993238163
** The problem with this is that if (N < 2*nHit), the IDF is
237994
- ** negative. Which is undesirable. So the mimimum allowable IDF is
238164
+ ** negative. Which is undesirable. So the minimum allowable IDF is
237995238165
** (1e-6) - roughly the same as a term that appears in just over
237996238166
** half of set of 5,000,000 documents. */
237997238167
double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
237998238168
if( idf<=0.0 ) idf = 1e-6;
237999238169
p->aIDF[i] = idf;
@@ -238452,11 +238622,11 @@
238452238622
**
238453238623
** * All non-ASCII characters,
238454238624
** * The 52 upper and lower case ASCII characters, and
238455238625
** * The 10 integer ASCII characters.
238456238626
** * The underscore character "_" (0x5F).
238457
-** * The unicode "subsitute" character (0x1A).
238627
+** * The unicode "substitute" character (0x1A).
238458238628
*/
238459238629
static int sqlite3Fts5IsBareword(char t){
238460238630
u8 aBareword[128] = {
238461238631
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 .. 0x0F */
238462238632
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */
@@ -239770,12 +239940,16 @@
239770239940
Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
239771239941
239772239942
/* Child nodes. For a NOT node, this array always contains 2 entries. For
239773239943
** AND or OR nodes, it contains 2 or more entries. */
239774239944
int nChild; /* Number of child nodes */
239775
- Fts5ExprNode *apChild[1]; /* Array of child nodes */
239945
+ Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */
239776239946
};
239947
+
239948
+/* Size (in bytes) of an Fts5ExprNode object that holds up to N children */
239949
+#define SZ_FTS5EXPRNODE(N) \
239950
+ (offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*))
239777239951
239778239952
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
239779239953
239780239954
/*
239781239955
** Invoke the xNext method of an Fts5ExprNode object. This macro should be
@@ -239803,24 +239977,31 @@
239803239977
*/
239804239978
struct Fts5ExprPhrase {
239805239979
Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
239806239980
Fts5Buffer poslist; /* Current position list */
239807239981
int nTerm; /* Number of entries in aTerm[] */
239808
- Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
239982
+ Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */
239809239983
};
239984
+
239985
+/* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */
239986
+#define SZ_FTS5EXPRPHRASE(N) \
239987
+ (offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm))
239810239988
239811239989
/*
239812239990
** One or more phrases that must appear within a certain token distance of
239813239991
** each other within each matching document.
239814239992
*/
239815239993
struct Fts5ExprNearset {
239816239994
int nNear; /* NEAR parameter */
239817239995
Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
239818239996
int nPhrase; /* Number of entries in aPhrase[] array */
239819
- Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
239997
+ Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */
239820239998
};
239821239999
240000
+/* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */
240001
+#define SZ_FTS5EXPRNEARSET(N) \
240002
+ (offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*))
239822240003
239823240004
/*
239824240005
** Parse context.
239825240006
*/
239826240007
struct Fts5Parse {
@@ -239976,11 +240157,11 @@
239976240157
assert_expr_depth_ok(sParse.rc, sParse.pExpr);
239977240158
239978240159
/* If the LHS of the MATCH expression was a user column, apply the
239979240160
** implicit column-filter. */
239980240161
if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
239981
- int n = sizeof(Fts5Colset);
240162
+ int n = SZ_FTS5COLSET(1);
239982240163
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
239983240164
if( pColset ){
239984240165
pColset->nCol = 1;
239985240166
pColset->aiCol[0] = iCol;
239986240167
sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
@@ -241334,11 +241515,11 @@
241334241515
Fts5ExprNearset *pRet = 0;
241335241516
241336241517
if( pParse->rc==SQLITE_OK ){
241337241518
if( pNear==0 ){
241338241519
sqlite3_int64 nByte;
241339
- nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
241520
+ nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1);
241340241521
pRet = sqlite3_malloc64(nByte);
241341241522
if( pRet==0 ){
241342241523
pParse->rc = SQLITE_NOMEM;
241343241524
}else{
241344241525
memset(pRet, 0, (size_t)nByte);
@@ -241345,11 +241526,11 @@
241345241526
}
241346241527
}else if( (pNear->nPhrase % SZALLOC)==0 ){
241347241528
int nNew = pNear->nPhrase + SZALLOC;
241348241529
sqlite3_int64 nByte;
241349241530
241350
- nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
241531
+ nByte = SZ_FTS5EXPRNEARSET(nNew+1);
241351241532
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
241352241533
if( pRet==0 ){
241353241534
pParse->rc = SQLITE_NOMEM;
241354241535
}
241355241536
}else{
@@ -241436,16 +241617,16 @@
241436241617
if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){
241437241618
Fts5ExprPhrase *pNew;
241438241619
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
241439241620
241440241621
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
241441
- sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
241622
+ SZ_FTS5EXPRPHRASE(nNew+1)
241442241623
);
241443241624
if( pNew==0 ){
241444241625
rc = SQLITE_NOMEM;
241445241626
}else{
241446
- if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
241627
+ if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1));
241447241628
pCtx->pPhrase = pPhrase = pNew;
241448241629
pNew->nTerm = nNew - SZALLOC;
241449241630
}
241450241631
}
241451241632
@@ -241549,11 +241730,11 @@
241549241730
}
241550241731
241551241732
if( sCtx.pPhrase==0 ){
241552241733
/* This happens when parsing a token or quoted phrase that contains
241553241734
** no token characters at all. (e.g ... MATCH '""'). */
241554
- sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
241735
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1));
241555241736
}else if( sCtx.pPhrase->nTerm ){
241556241737
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
241557241738
}
241558241739
assert( pParse->apPhrase!=0 );
241559241740
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
@@ -241584,23 +241765,22 @@
241584241765
if( rc==SQLITE_OK ){
241585241766
pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
241586241767
sizeof(Fts5ExprPhrase*));
241587241768
}
241588241769
if( rc==SQLITE_OK ){
241589
- pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
241590
- sizeof(Fts5ExprNode));
241770
+ pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1));
241591241771
}
241592241772
if( rc==SQLITE_OK ){
241593241773
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
241594
- sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
241774
+ SZ_FTS5EXPRNEARSET(2));
241595241775
}
241596241776
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
241597241777
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
241598241778
if( pColsetOrig ){
241599241779
sqlite3_int64 nByte;
241600241780
Fts5Colset *pColset;
241601
- nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
241781
+ nByte = SZ_FTS5COLSET(pColsetOrig->nCol);
241602241782
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
241603241783
if( pColset ){
241604241784
memcpy(pColset, pColsetOrig, (size_t)nByte);
241605241785
}
241606241786
pNew->pRoot->pNear->pColset = pColset;
@@ -241624,11 +241804,11 @@
241624241804
}
241625241805
}
241626241806
}else{
241627241807
/* This happens when parsing a token or quoted phrase that contains
241628241808
** no token characters at all. (e.g ... MATCH '""'). */
241629
- sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
241809
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1));
241630241810
}
241631241811
}
241632241812
241633241813
if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
241634241814
/* All the allocations succeeded. Put the expression object together. */
@@ -241718,11 +241898,11 @@
241718241898
Fts5Colset *pNew; /* New colset object to return */
241719241899
241720241900
assert( pParse->rc==SQLITE_OK );
241721241901
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
241722241902
241723
- pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
241903
+ pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1));
241724241904
if( pNew==0 ){
241725241905
pParse->rc = SQLITE_NOMEM;
241726241906
}else{
241727241907
int *aiCol = pNew->aiCol;
241728241908
int i, j;
@@ -241753,11 +241933,11 @@
241753241933
static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
241754241934
Fts5Colset *pRet;
241755241935
int nCol = pParse->pConfig->nCol;
241756241936
241757241937
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
241758
- sizeof(Fts5Colset) + sizeof(int)*nCol
241938
+ SZ_FTS5COLSET(nCol+1)
241759241939
);
241760241940
if( pRet ){
241761241941
int i;
241762241942
int iOld = 0;
241763241943
for(i=0; i<nCol; i++){
@@ -241814,11 +241994,11 @@
241814241994
** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
241815241995
*/
241816241996
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
241817241997
Fts5Colset *pRet;
241818241998
if( pOrig ){
241819
- sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
241999
+ sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol);
241820242000
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
241821242001
if( pRet ){
241822242002
memcpy(pRet, pOrig, (size_t)nByte);
241823242003
}
241824242004
}else{
@@ -241982,21 +242162,21 @@
241982242162
Fts5ExprNode *pRet;
241983242163
241984242164
assert( pNear->nPhrase==1 );
241985242165
assert( pParse->bPhraseToAnd );
241986242166
241987
- nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
242167
+ nByte = SZ_FTS5EXPRNODE(nTerm+1);
241988242168
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
241989242169
if( pRet ){
241990242170
pRet->eType = FTS5_AND;
241991242171
pRet->nChild = nTerm;
241992242172
pRet->iHeight = 1;
241993242173
fts5ExprAssignXNext(pRet);
241994242174
pParse->nPhrase--;
241995242175
for(ii=0; ii<nTerm; ii++){
241996242176
Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
241997
- &pParse->rc, sizeof(Fts5ExprPhrase)
242177
+ &pParse->rc, SZ_FTS5EXPRPHRASE(1)
241998242178
);
241999242179
if( pPhrase ){
242000242180
if( parseGrowPhraseArray(pParse) ){
242001242181
fts5ExprPhraseFree(pPhrase);
242002242182
}else{
@@ -242061,11 +242241,11 @@
242061242241
nChild = 2;
242062242242
if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
242063242243
if( pRight->eType==eType ) nChild += pRight->nChild-1;
242064242244
}
242065242245
242066
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
242246
+ nByte = SZ_FTS5EXPRNODE(nChild);
242067242247
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
242068242248
242069242249
if( pRet ){
242070242250
pRet->eType = eType;
242071242251
pRet->pNear = pNear;
@@ -242936,11 +243116,11 @@
242936243116
}
242937243117
return rc;
242938243118
}
242939243119
242940243120
/*
242941
-** Clear the token mappings for all Fts5IndexIter objects mannaged by
243121
+** Clear the token mappings for all Fts5IndexIter objects managed by
242942243122
** the expression passed as the only argument.
242943243123
*/
242944243124
static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
242945243125
int ii;
242946243126
for(ii=0; ii<pExpr->nPhrase; ii++){
@@ -242971,11 +243151,11 @@
242971243151
242972243152
typedef struct Fts5HashEntry Fts5HashEntry;
242973243153
242974243154
/*
242975243155
** This file contains the implementation of an in-memory hash table used
242976
-** to accumuluate "term -> doclist" content before it is flused to a level-0
243156
+** to accumulate "term -> doclist" content before it is flushed to a level-0
242977243157
** segment.
242978243158
*/
242979243159
242980243160
242981243161
struct Fts5Hash {
@@ -243028,11 +243208,11 @@
243028243208
int iPos; /* Position of last value written */
243029243209
i64 iRowid; /* Rowid of last value written */
243030243210
};
243031243211
243032243212
/*
243033
-** Eqivalent to:
243213
+** Equivalent to:
243034243214
**
243035243215
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
243036243216
*/
243037243217
#define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
243038243218
@@ -243964,13 +244144,17 @@
243964244144
int nRef; /* Object reference count */
243965244145
u64 nWriteCounter; /* Total leaves written to level 0 */
243966244146
u64 nOriginCntr; /* Origin value for next top-level segment */
243967244147
int nSegment; /* Total segments in this structure */
243968244148
int nLevel; /* Number of levels in this index */
243969
- Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
244149
+ Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */
243970244150
};
243971244151
244152
+/* Size (in bytes) of an Fts5Structure object holding up to N levels */
244153
+#define SZ_FTS5STRUCTURE(N) \
244154
+ (offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel))
244155
+
243972244156
/*
243973244157
** An object of type Fts5SegWriter is used to write to segments.
243974244158
*/
243975244159
struct Fts5PageWriter {
243976244160
int pgno; /* Page number for this page */
@@ -244096,14 +244280,18 @@
244096244280
244097244281
/*
244098244282
** Array of tombstone pages. Reference counted.
244099244283
*/
244100244284
struct Fts5TombstoneArray {
244101
- int nRef; /* Number of pointers to this object */
244285
+ int nRef; /* Number of pointers to this object */
244102244286
int nTombstone;
244103
- Fts5Data *apTombstone[1]; /* Array of tombstone pages */
244287
+ Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */
244104244288
};
244289
+
244290
+/* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */
244291
+#define SZ_FTS5TOMBSTONEARRAY(N) \
244292
+ (offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*))
244105244293
244106244294
/*
244107244295
** Argument is a pointer to an Fts5Data structure that contains a
244108244296
** leaf page.
244109244297
*/
@@ -244169,12 +244357,15 @@
244169244357
int bRev; /* True to iterate in reverse order */
244170244358
u8 bSkipEmpty; /* True to skip deleted entries */
244171244359
244172244360
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
244173244361
Fts5CResult *aFirst; /* Current merge state (see above) */
244174
- Fts5SegIter aSeg[1]; /* Array of segment iterators */
244362
+ Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */
244175244363
};
244364
+
244365
+/* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */
244366
+#define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter))
244176244367
244177244368
/*
244178244369
** An instance of the following type is used to iterate through the contents
244179244370
** of a doclist-index record.
244180244371
**
@@ -244198,12 +244389,16 @@
244198244389
i64 iRowid; /* First rowid on leaf iLeafPgno */
244199244390
};
244200244391
struct Fts5DlidxIter {
244201244392
int nLvl;
244202244393
int iSegid;
244203
- Fts5DlidxLvl aLvl[1];
244394
+ Fts5DlidxLvl aLvl[FLEXARRAY];
244204244395
};
244396
+
244397
+/* Size (in bytes) of an Fts5DlidxIter object with up to N levels */
244398
+#define SZ_FTS5DLIDXITER(N) \
244399
+ (offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl))
244205244400
244206244401
static void fts5PutU16(u8 *aOut, u16 iVal){
244207244402
aOut[0] = (iVal>>8);
244208244403
aOut[1] = (iVal&0xFF);
244209244404
}
@@ -244568,11 +244763,11 @@
244568244763
** an error occurs, (*pRc) is set to an SQLite error code before returning.
244569244764
*/
244570244765
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
244571244766
Fts5Structure *p = *pp;
244572244767
if( *pRc==SQLITE_OK && p->nRef>1 ){
244573
- i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
244768
+ i64 nByte = SZ_FTS5STRUCTURE(p->nLevel);
244574244769
Fts5Structure *pNew;
244575244770
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
244576244771
if( pNew ){
244577244772
int i;
244578244773
memcpy(pNew, p, nByte);
@@ -244642,14 +244837,11 @@
244642244837
if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
244643244838
|| nSegment>FTS5_MAX_SEGMENT || nSegment<0
244644244839
){
244645244840
return FTS5_CORRUPT;
244646244841
}
244647
- nByte = (
244648
- sizeof(Fts5Structure) + /* Main structure */
244649
- sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
244650
- );
244842
+ nByte = SZ_FTS5STRUCTURE(nLevel);
244651244843
pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
244652244844
244653244845
if( pRet ){
244654244846
pRet->nRef = 1;
244655244847
pRet->nLevel = nLevel;
@@ -244725,14 +244917,11 @@
244725244917
fts5StructureMakeWritable(pRc, ppStruct);
244726244918
assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK );
244727244919
if( *pRc==SQLITE_OK ){
244728244920
Fts5Structure *pStruct = *ppStruct;
244729244921
int nLevel = pStruct->nLevel;
244730
- sqlite3_int64 nByte = (
244731
- sizeof(Fts5Structure) + /* Main structure */
244732
- sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
244733
- );
244922
+ sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2);
244734244923
244735244924
pStruct = sqlite3_realloc64(pStruct, nByte);
244736244925
if( pStruct ){
244737244926
memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
244738244927
pStruct->nLevel++;
@@ -245267,11 +245456,11 @@
245267245456
Fts5DlidxIter *pIter = 0;
245268245457
int i;
245269245458
int bDone = 0;
245270245459
245271245460
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
245272
- sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
245461
+ sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1);
245273245462
Fts5DlidxIter *pNew;
245274245463
245275245464
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
245276245465
if( pNew==0 ){
245277245466
p->rc = SQLITE_NOMEM;
@@ -245485,11 +245674,11 @@
245485245674
** leave an error in the Fts5Index object.
245486245675
*/
245487245676
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
245488245677
const int nTomb = pIter->pSeg->nPgTombstone;
245489245678
if( nTomb>0 ){
245490
- int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
245679
+ int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
245491245680
Fts5TombstoneArray *pNew;
245492245681
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
245493245682
if( pNew ){
245494245683
pNew->nTombstone = nTomb;
245495245684
pNew->nRef = 1;
@@ -246946,12 +247135,11 @@
246946247135
Fts5Iter *pNew;
246947247136
i64 nSlot; /* Power of two >= nSeg */
246948247137
246949247138
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
246950247139
pNew = fts5IdxMalloc(p,
246951
- sizeof(Fts5Iter) + /* pNew */
246952
- sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
247140
+ SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */
246953247141
sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
246954247142
);
246955247143
if( pNew ){
246956247144
pNew->nSeg = nSlot;
246957247145
pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
@@ -249313,11 +249501,11 @@
249313249501
static Fts5Structure *fts5IndexOptimizeStruct(
249314249502
Fts5Index *p,
249315249503
Fts5Structure *pStruct
249316249504
){
249317249505
Fts5Structure *pNew = 0;
249318
- sqlite3_int64 nByte = sizeof(Fts5Structure);
249506
+ sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1);
249319249507
int nSeg = pStruct->nSegment;
249320249508
int i;
249321249509
249322249510
/* Figure out if this structure requires optimization. A structure does
249323249511
** not require optimization if either:
@@ -249343,10 +249531,11 @@
249343249531
}
249344249532
assert( pStruct->aLevel[i].nMerge<=nThis );
249345249533
}
249346249534
249347249535
nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
249536
+ assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
249348249537
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
249349249538
249350249539
if( pNew ){
249351249540
Fts5StructureLevel *pLvl;
249352249541
nByte = nSeg * sizeof(Fts5StructureSegment);
@@ -249919,12 +250108,16 @@
249919250108
/* The following are used for other full-token tokendata queries only. */
249920250109
int nIter;
249921250110
int nIterAlloc;
249922250111
Fts5PoslistReader *aPoslistReader;
249923250112
int *aPoslistToIter;
249924
- Fts5Iter *apIter[1];
250113
+ Fts5Iter *apIter[FLEXARRAY];
249925250114
};
250115
+
250116
+/* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */
250117
+#define SZ_FTS5TOKENDATAITER(N) \
250118
+ (offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter))
249926250119
249927250120
/*
249928250121
** The two input arrays - a1[] and a2[] - are in sorted order. This function
249929250122
** merges the two arrays together and writes the result to output array
249930250123
** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
@@ -249993,11 +250186,11 @@
249993250186
}
249994250187
249995250188
/*
249996250189
** Sort the contents of the pT->aMap[] array.
249997250190
**
249998
-** The sorting algorithm requries a malloc(). If this fails, an error code
250191
+** The sorting algorithm requires a malloc(). If this fails, an error code
249999250192
** is left in Fts5Index.rc before returning.
250000250193
*/
250001250194
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
250002250195
Fts5TokenDataMap *aTmp = 0;
250003250196
int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
@@ -250184,11 +250377,11 @@
250184250377
if( iIdx==0
250185250378
&& p->pConfig->eDetail==FTS5_DETAIL_FULL
250186250379
&& p->pConfig->bPrefixInsttoken
250187250380
){
250188250381
s.pTokendata = &s2;
250189
- s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
250382
+ s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1));
250190250383
}
250191250384
250192250385
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
250193250386
s.xMerge = fts5MergeRowidLists;
250194250387
s.xAppend = fts5AppendRowid;
@@ -250312,19 +250505,21 @@
250312250505
** The %_data table is completely empty when this function is called. This
250313250506
** function populates it with the initial structure objects for each index,
250314250507
** and the initial version of the "averages" record (a zero-byte blob).
250315250508
*/
250316250509
static int sqlite3Fts5IndexReinit(Fts5Index *p){
250317
- Fts5Structure s;
250510
+ Fts5Structure *pTmp;
250511
+ u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
250318250512
fts5StructureInvalidate(p);
250319250513
fts5IndexDiscardData(p);
250320
- memset(&s, 0, sizeof(Fts5Structure));
250514
+ pTmp = (Fts5Structure*)tmpSpace;
250515
+ memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
250321250516
if( p->pConfig->bContentlessDelete ){
250322
- s.nOriginCntr = 1;
250517
+ pTmp->nOriginCntr = 1;
250323250518
}
250324250519
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
250325
- fts5StructureWrite(p, &s);
250520
+ fts5StructureWrite(p, pTmp);
250326250521
return fts5IndexReturn(p);
250327250522
}
250328250523
250329250524
/*
250330250525
** Open a new Fts5Index handle. If the bCreate argument is true, create
@@ -250528,11 +250723,11 @@
250528250723
Fts5TokenDataIter *pRet = pIn;
250529250724
250530250725
if( p->rc==SQLITE_OK ){
250531250726
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
250532250727
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
250533
- int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
250728
+ int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
250534250729
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
250535250730
250536250731
if( pNew==0 ){
250537250732
p->rc = SQLITE_NOMEM;
250538250733
}else{
@@ -251044,11 +251239,12 @@
251044251239
251045251240
memset(&ctx, 0, sizeof(ctx));
251046251241
251047251242
fts5BufferGrow(&p->rc, &token, nToken+1);
251048251243
assert( token.p!=0 || p->rc!=SQLITE_OK );
251049
- ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
251244
+ ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
251245
+ SZ_FTS5TOKENDATAITER(1));
251050251246
251051251247
if( p->rc==SQLITE_OK ){
251052251248
251053251249
/* Fill in the token prefix to search for */
251054251250
token.p[0] = FTS5_MAIN_PREFIX;
@@ -251175,11 +251371,12 @@
251175251371
assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
251176251372
assert( pIter->pTokenDataIter || pIter->nSeg>0 );
251177251373
if( pIter->nSeg>0 ){
251178251374
/* This is a prefix term iterator. */
251179251375
if( pT==0 ){
251180
- pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
251376
+ pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
251377
+ SZ_FTS5TOKENDATAITER(1));
251181251378
pIter->pTokenDataIter = pT;
251182251379
}
251183251380
if( pT ){
251184251381
fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
251185251382
fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
@@ -252209,11 +252406,11 @@
252209252406
}
252210252407
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
252211252408
252212252409
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
252213252410
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
252214
- int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
252411
+ int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid components */
252215252412
fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
252216252413
252217252414
if( iSegid==0 ){
252218252415
if( iKey==FTS5_AVERAGES_ROWID ){
252219252416
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
@@ -253170,13 +253367,15 @@
253170253367
struct Fts5Sorter {
253171253368
sqlite3_stmt *pStmt;
253172253369
i64 iRowid; /* Current rowid */
253173253370
const u8 *aPoslist; /* Position lists for current row */
253174253371
int nIdx; /* Number of entries in aIdx[] */
253175
- int aIdx[1]; /* Offsets into aPoslist for current row */
253372
+ int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
253176253373
};
253177253374
253375
+/* Size (int bytes) of an Fts5Sorter object with N indexes */
253376
+#define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
253178253377
253179253378
/*
253180253379
** Virtual-table cursor object.
253181253380
**
253182253381
** iSpecial:
@@ -254050,11 +254249,11 @@
254050254249
int rc;
254051254250
const char *zRank = pCsr->zRank;
254052254251
const char *zRankArgs = pCsr->zRankArgs;
254053254252
254054254253
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
254055
- nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
254254
+ nByte = SZ_FTS5SORTER(nPhrase);
254056254255
pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
254057254256
if( pSorter==0 ) return SQLITE_NOMEM;
254058254257
memset(pSorter, 0, (size_t)nByte);
254059254258
pSorter->nIdx = nPhrase;
254060254259
@@ -256576,11 +256775,11 @@
256576256775
int nArg, /* Number of args */
256577256776
sqlite3_value **apUnused /* Function arguments */
256578256777
){
256579256778
assert( nArg==0 );
256580256779
UNUSED_PARAM2(nArg, apUnused);
256581
- sqlite3_result_text(pCtx, "fts5: 2025-02-25 16:39:51 6f0b6d95db17e69ac7e46a39f52770291ac4cfe43eea09add224946a6e11f04e", -1, SQLITE_TRANSIENT);
256780
+ sqlite3_result_text(pCtx, "fts5: 2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185", -1, SQLITE_TRANSIENT);
256582256781
}
256583256782
256584256783
/*
256585256784
** Implementation of fts5_locale(LOCALE, TEXT) function.
256586256785
**
256587256786
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** e6784af6d50f715338ae3218fc8ba1b89488 with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466 ** [sqlite_version()] and [sqlite_source_id()].
467 */
468 #define SQLITE_VERSION "3.50.0"
469 #define SQLITE_VERSION_NUMBER 3050000
470 #define SQLITE_SOURCE_ID "2025-02-25 18:10:47 e6784af6d50f715338ae3218fc8ba1b894883c27d797f0b7fd2625cac17d9cd7"
471
472 /*
473 ** CAPI3REF: Run-Time Library Version Numbers
474 ** KEYWORDS: sqlite3_version sqlite3_sourceid
475 **
@@ -5492,11 +5492,11 @@
5492 ** For all versions of SQLite up to and including 3.6.23.1, a call to
5493 ** [sqlite3_reset()] was required after sqlite3_step() returned anything
5494 ** other than [SQLITE_ROW] before any subsequent invocation of
5495 ** sqlite3_step(). Failure to reset the prepared statement using
5496 ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
5497 ** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
5498 ** sqlite3_step() began
5499 ** calling [sqlite3_reset()] automatically in this circumstance rather
5500 ** than returning [SQLITE_MISUSE]. This is not considered a compatibility
5501 ** break because any application that ever receives an SQLITE_MISUSE error
5502 ** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
@@ -7388,10 +7388,12 @@
7388 ** ^Any callback set by a previous call to this function
7389 ** for the same database connection is overridden.
7390 **
7391 ** ^The second argument is a pointer to the function to invoke when a
7392 ** row is updated, inserted or deleted in a rowid table.
 
 
7393 ** ^The first argument to the callback is a copy of the third argument
7394 ** to sqlite3_update_hook().
7395 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
7396 ** or [SQLITE_UPDATE], depending on the operation that caused the callback
7397 ** to be invoked.
@@ -15170,11 +15172,21 @@
15170 /*
15171 ** GCC does not define the offsetof() macro so we'll have to do it
15172 ** ourselves.
15173 */
15174 #ifndef offsetof
15175 #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
 
 
 
 
 
 
 
 
 
 
15176 #endif
15177
15178 /*
15179 ** Macros to compute minimum and maximum of two numbers.
15180 */
@@ -17405,12 +17417,12 @@
17405 SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
17406 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
17407 SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
17408 #endif
17409
17410 /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
17411 ** each VDBE opcode.
17412 **
17413 ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
17414 ** comments in VDBE programs that show key decision points in the code
17415 ** generator.
17416 */
@@ -18945,12 +18957,16 @@
18945 u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
18946 Trigger *apTrigger[2];/* Triggers for aAction[] actions */
18947 struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
18948 int iFrom; /* Index of column in pFrom */
18949 char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
18950 } aCol[1]; /* One entry for each of nCol columns */
18951 };
 
 
 
 
18952
18953 /*
18954 ** SQLite supports many different ways to resolve a constraint
18955 ** error. ROLLBACK processing means that a constraint violation
18956 ** causes the operation in process to fail and for the current transaction
@@ -19009,13 +19025,16 @@
19009 u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
19010 u16 nKeyField; /* Number of key columns in the index */
19011 u16 nAllField; /* Total columns, including key plus others */
19012 sqlite3 *db; /* The database connection */
19013 u8 *aSortFlags; /* Sort order for each column. */
19014 CollSeq *aColl[1]; /* Collating sequence for each term of the key */
19015 };
19016
 
 
 
19017 /*
19018 ** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
19019 */
19020 #define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
19021 #define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
@@ -19584,12 +19603,17 @@
19584 u16 iAlias; /* Index into Parse.aAlias[] for zName */
19585 } x;
19586 int iConstExprReg; /* Register in which Expr value is cached. Used only
19587 ** by Parse.pConstExpr */
19588 } u;
19589 } a[1]; /* One slot for each expression in the list */
19590 };
 
 
 
 
 
19591
19592 /*
19593 ** Allowed values for Expr.a.eEName
19594 */
19595 #define ENAME_NAME 0 /* The AS clause of a result set */
@@ -19614,13 +19638,16 @@
19614 */
19615 struct IdList {
19616 int nId; /* Number of identifiers on the list */
19617 struct IdList_item {
19618 char *zName; /* Name of the identifier */
19619 } a[1];
19620 };
19621
 
 
 
19622 /*
19623 ** Allowed values for IdList.eType, which determines which value of the a.u4
19624 ** is valid.
19625 */
19626 #define EU4_NONE 0 /* Does not use IdList.a.u4 */
@@ -19736,14 +19763,22 @@
19736 ** is used to hold the FROM clause of a SELECT statement. SrcList also
19737 ** represents the target tables for DELETE, INSERT, and UPDATE statements.
19738 **
19739 */
19740 struct SrcList {
19741 int nSrc; /* Number of tables or subqueries in the FROM clause */
19742 u32 nAlloc; /* Number of entries allocated in a[] below */
19743 SrcItem a[1]; /* One entry for each identifier on the list */
19744 };
 
 
 
 
 
 
 
 
19745
19746 /*
19747 ** Permitted values of the SrcList.a.jointype field
19748 */
19749 #define JT_INNER 0x01 /* Any kind of inner or cross join */
@@ -20804,12 +20839,16 @@
20804 */
20805 struct With {
20806 int nCte; /* Number of CTEs in the WITH clause */
20807 int bView; /* Belongs to the outermost Select of a view */
20808 With *pOuter; /* Containing WITH clause, or NULL */
20809 Cte a[1]; /* For each CTE in the WITH clause.... */
20810 };
 
 
 
 
20811
20812 /*
20813 ** The Cte object is not guaranteed to persist for the entire duration
20814 ** of code generation. (The query flattener or other parser tree
20815 ** edits might delete it.) The following object records information
@@ -20835,12 +20874,16 @@
20835 */
20836 struct DbClientData {
20837 DbClientData *pNext; /* Next in a linked list */
20838 void *pData; /* The data */
20839 void (*xDestructor)(void*); /* Destructor. Might be NULL */
20840 char zName[1]; /* Name of this client data. MUST BE LAST */
20841 };
 
 
 
 
20842
20843 #ifdef SQLITE_DEBUG
20844 /*
20845 ** An instance of the TreeView object is used for printing the content of
20846 ** data structures on sqlite3DebugPrintf() using a tree-like view.
@@ -22673,10 +22716,13 @@
22673 "EXTRA_IFNULLROW",
22674 #endif
22675 #ifdef SQLITE_EXTRA_INIT
22676 "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
22677 #endif
 
 
 
22678 #ifdef SQLITE_EXTRA_SHUTDOWN
22679 "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
22680 #endif
22681 #ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
22682 "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
@@ -23657,16 +23703,23 @@
23657 #ifdef SQLITE_ENABLE_COLUMN_USED_MASK
23658 u64 maskUsed; /* Mask of columns used by this cursor */
23659 #endif
23660 VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
23661
23662 /* 2*nField extra array elements allocated for aType[], beyond the one
23663 ** static element declared in the structure. nField total array slots for
23664 ** aType[] and nField+1 array slots for aOffset[] */
23665 u32 aType[1]; /* Type values record decode. MUST BE LAST */
23666 };
23667
 
 
 
 
 
 
 
 
23668 /* Return true if P is a null-only cursor
23669 */
23670 #define IsNullCursor(P) \
23671 ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
23672
@@ -23919,13 +23972,20 @@
23919 int iOp; /* Instruction number of OP_Function */
23920 int isError; /* Error code returned by the function. */
23921 u8 enc; /* Encoding to use for results */
23922 u8 skipFlag; /* Skip accumulator loading if true */
23923 u16 argc; /* Number of arguments */
23924 sqlite3_value *argv[1]; /* Argument set */
23925 };
23926
 
 
 
 
 
 
 
23927
23928 /* The ScanStatus object holds a single value for the
23929 ** sqlite3_stmt_scanstatus() interface.
23930 **
23931 ** aAddrRange[]:
@@ -24055,11 +24115,11 @@
24055 struct PreUpdate {
24056 Vdbe *v;
24057 VdbeCursor *pCsr; /* Cursor to read old values from */
24058 int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
24059 u8 *aRecord; /* old.* database record */
24060 KeyInfo keyinfo;
24061 UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
24062 UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
24063 int iNewReg; /* Register for new.* values */
24064 int iBlobWrite; /* Value returned by preupdate_blobwrite() */
24065 i64 iKey1; /* First key value passed to hook */
@@ -24067,10 +24127,11 @@
24067 Mem oldipk; /* Memory cell holding "old" IPK value */
24068 Mem *aNew; /* Array of new.* values */
24069 Table *pTab; /* Schema object being updated */
24070 Index *pPk; /* PK index if pTab is WITHOUT ROWID */
24071 sqlite3_value **apDflt; /* Array of default values, if required */
 
24072 };
24073
24074 /*
24075 ** An instance of this object is used to pass an vector of values into
24076 ** OP_VFilter, the xFilter method of a virtual table. The vector is the
@@ -26000,11 +26061,11 @@
26000 ** Return the number of days after the most recent Sunday.
26001 **
26002 ** In other words, return the day of the week according
26003 ** to this code:
26004 **
26005 ** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday
26006 */
26007 static int daysAfterSunday(DateTime *pDate){
26008 assert( pDate->validJD );
26009 return (int)((pDate->iJD+129600000)/86400000) % 7;
26010 }
@@ -32378,11 +32439,11 @@
32378 u32 nBack = 0;
32379 u32 nCtrl = 0;
32380 for(k=0; k<i; k++){
32381 if( escarg[k]=='\\' ){
32382 nBack++;
32383 }else if( escarg[k]<=0x1f ){
32384 nCtrl++;
32385 }
32386 }
32387 if( nCtrl || xtype==etESCAPE_q ){
32388 n += nBack + 5*nCtrl;
@@ -32416,11 +32477,11 @@
32416 bufpt[j++] = ch = escarg[i];
32417 if( ch==q ){
32418 bufpt[j++] = ch;
32419 }else if( ch=='\\' ){
32420 bufpt[j++] = '\\';
32421 }else if( ch<=0x1f ){
32422 bufpt[j-1] = '\\';
32423 bufpt[j++] = 'u';
32424 bufpt[j++] = '0';
32425 bufpt[j++] = '0';
32426 bufpt[j++] = ch>=0x10 ? '1' : '0';
@@ -37067,11 +37128,11 @@
37067 return 0;
37068 #endif
37069 }
37070
37071 /*
37072 ** Compute the absolute value of a 32-bit signed integer, of possible. Or
37073 ** if the integer has a value of -2147483648, return +2147483647
37074 */
37075 SQLITE_PRIVATE int sqlite3AbsInt32(int x){
37076 if( x>=0 ) return x;
37077 if( x==(int)0x80000000 ) return 0x7fffffff;
@@ -45614,11 +45675,11 @@
45614 sp.tv_sec = microseconds / 1000000;
45615 sp.tv_nsec = (microseconds % 1000000) * 1000;
45616
45617 /* Almost all modern unix systems support nanosleep(). But if you are
45618 ** compiling for one of the rare exceptions, you can use
45619 ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
45620 ** usleep() is available) in order to bypass the use of nanosleep() */
45621 nanosleep(&sp, NULL);
45622
45623 UNUSED_PARAMETER(NotUsed);
45624 return microseconds;
@@ -56047,14 +56108,10 @@
56047 void *pStart, *pEnd; /* Bounds of global page cache memory */
56048 /* Above requires no mutex. Use mutex below for variable that follow. */
56049 sqlite3_mutex *mutex; /* Mutex for accessing the following: */
56050 PgFreeslot *pFree; /* Free page blocks */
56051 int nFreeSlot; /* Number of unused pcache slots */
56052 /* The following value requires a mutex to change. We skip the mutex on
56053 ** reading because (1) most platforms read a 32-bit integer atomically and
56054 ** (2) even if an incorrect value is read, no great harm is done since this
56055 ** is really just an optimization. */
56056 int bUnderPressure; /* True if low on PAGECACHE memory */
56057 } pcache1_g;
56058
56059 /*
56060 ** All code in this file should access the global structure above via the
@@ -56098,11 +56155,11 @@
56098 pcache1.szSlot = sz;
56099 pcache1.nSlot = pcache1.nFreeSlot = n;
56100 pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
56101 pcache1.pStart = pBuf;
56102 pcache1.pFree = 0;
56103 pcache1.bUnderPressure = 0;
56104 while( n-- ){
56105 p = (PgFreeslot*)pBuf;
56106 p->pNext = pcache1.pFree;
56107 pcache1.pFree = p;
56108 pBuf = (void*)&((char*)pBuf)[sz];
@@ -56166,11 +56223,11 @@
56166 sqlite3_mutex_enter(pcache1.mutex);
56167 p = (PgHdr1 *)pcache1.pFree;
56168 if( p ){
56169 pcache1.pFree = pcache1.pFree->pNext;
56170 pcache1.nFreeSlot--;
56171 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
56172 assert( pcache1.nFreeSlot>=0 );
56173 sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
56174 sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
56175 }
56176 sqlite3_mutex_leave(pcache1.mutex);
@@ -56205,11 +56262,11 @@
56205 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
56206 pSlot = (PgFreeslot*)p;
56207 pSlot->pNext = pcache1.pFree;
56208 pcache1.pFree = pSlot;
56209 pcache1.nFreeSlot++;
56210 pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
56211 assert( pcache1.nFreeSlot<=pcache1.nSlot );
56212 sqlite3_mutex_leave(pcache1.mutex);
56213 }else{
56214 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
56215 sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
@@ -56336,11 +56393,11 @@
56336 ** allocating a new page cache entry in order to avoid stressing
56337 ** the heap even further.
56338 */
56339 static int pcache1UnderMemoryPressure(PCache1 *pCache){
56340 if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
56341 return pcache1.bUnderPressure;
56342 }else{
56343 return sqlite3HeapNearlyFull();
56344 }
56345 }
56346
@@ -66177,12 +66234,16 @@
66177 int iNext; /* Next slot in aIndex[] not yet returned */
66178 ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
66179 u32 *aPgno; /* Array of page numbers. */
66180 int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
66181 int iZero; /* Frame number associated with aPgno[0] */
66182 } aSegment[1]; /* One for every 32KB page in the wal-index */
66183 };
 
 
 
 
66184
66185 /*
66186 ** Define the parameters of the hash tables in the wal-index file. There
66187 ** is a hash-table following every HASHTABLE_NPAGE page numbers in the
66188 ** wal-index.
@@ -67540,12 +67601,11 @@
67540 assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
67541 iLast = pWal->hdr.mxFrame;
67542
67543 /* Allocate space for the WalIterator object. */
67544 nSegment = walFramePage(iLast) + 1;
67545 nByte = sizeof(WalIterator)
67546 + (nSegment-1)*sizeof(struct WalSegment)
67547 + iLast*sizeof(ht_slot);
67548 p = (WalIterator *)sqlite3_malloc64(nByte
67549 + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
67550 );
67551 if( !p ){
@@ -86029,16 +86089,14 @@
86029 int nArg, /* Number of argument */
86030 const FuncDef *pFunc, /* The function to be invoked */
86031 int eCallCtx /* Calling context */
86032 ){
86033 Vdbe *v = pParse->pVdbe;
86034 int nByte;
86035 int addr;
86036 sqlite3_context *pCtx;
86037 assert( v );
86038 nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
86039 pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
86040 if( pCtx==0 ){
86041 assert( pParse->db->mallocFailed );
86042 freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
86043 return 0;
86044 }
@@ -91110,25 +91168,26 @@
91110
91111 preupdate.v = v;
91112 preupdate.pCsr = pCsr;
91113 preupdate.op = op;
91114 preupdate.iNewReg = iReg;
91115 preupdate.keyinfo.db = db;
91116 preupdate.keyinfo.enc = ENC(db);
91117 preupdate.keyinfo.nKeyField = pTab->nCol;
91118 preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
 
91119 preupdate.iKey1 = iKey1;
91120 preupdate.iKey2 = iKey2;
91121 preupdate.pTab = pTab;
91122 preupdate.iBlobWrite = iBlobWrite;
91123
91124 db->pPreUpdate = &preupdate;
91125 db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
91126 db->pPreUpdate = 0;
91127 sqlite3DbFree(db, preupdate.aRecord);
91128 vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
91129 vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
91130 sqlite3VdbeMemRelease(&preupdate.oldipk);
91131 if( preupdate.aNew ){
91132 int i;
91133 for(i=0; i<pCsr->nField; i++){
91134 sqlite3VdbeMemRelease(&preupdate.aNew[i]);
@@ -93363,11 +93422,11 @@
93363 nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
93364 aRec = sqlite3DbMallocRaw(db, nRec);
93365 if( !aRec ) goto preupdate_old_out;
93366 rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
93367 if( rc==SQLITE_OK ){
93368 p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
93369 if( !p->pUnpacked ) rc = SQLITE_NOMEM;
93370 }
93371 if( rc!=SQLITE_OK ){
93372 sqlite3DbFree(db, aRec);
93373 goto preupdate_old_out;
@@ -93428,11 +93487,11 @@
93428 #ifdef SQLITE_ENABLE_API_ARMOR
93429 p = db!=0 ? db->pPreUpdate : 0;
93430 #else
93431 p = db->pPreUpdate;
93432 #endif
93433 return (p ? p->keyinfo.nKeyField : 0);
93434 }
93435 #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
93436
93437 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
93438 /*
@@ -93511,11 +93570,11 @@
93511 UnpackedRecord *pUnpack = p->pNewUnpacked;
93512 if( !pUnpack ){
93513 Mem *pData = &p->v->aMem[p->iNewReg];
93514 rc = ExpandBlob(pData);
93515 if( rc!=SQLITE_OK ) goto preupdate_new_out;
93516 pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
93517 if( !pUnpack ){
93518 rc = SQLITE_NOMEM;
93519 goto preupdate_new_out;
93520 }
93521 p->pNewUnpacked = pUnpack;
@@ -94305,13 +94364,13 @@
94305 */
94306 Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
94307
94308 i64 nByte;
94309 VdbeCursor *pCx = 0;
94310 nByte =
94311 ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
94312 (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
94313
94314 assert( iCur>=0 && iCur<p->nCursor );
94315 if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
94316 sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
94317 p->apCsr[iCur] = 0;
@@ -94340,12 +94399,12 @@
94340 memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
94341 pCx->eCurType = eCurType;
94342 pCx->nField = nField;
94343 pCx->aOffset = &pCx->aType[nField];
94344 if( eCurType==CURTYPE_BTREE ){
94345 pCx->uc.pCursor = (BtCursor*)
94346 &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
94347 sqlite3BtreeCursorZero(pCx->uc.pCursor);
94348 }
94349 return pCx;
94350 }
94351
@@ -100083,11 +100142,11 @@
100083 pCrsr = pC->uc.pCursor;
100084
100085 /* The OP_RowData opcodes always follow OP_NotExists or
100086 ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
100087 ** that might invalidate the cursor.
100088 ** If this where not the case, on of the following assert()s
100089 ** would fail. Should this ever change (because of changes in the code
100090 ** generator) then the fix would be to insert a call to
100091 ** sqlite3VdbeCursorMoveto().
100092 */
100093 assert( pC->deferredMoveto==0 );
@@ -101732,11 +101791,11 @@
101732 ** cell in which to store the accumulation. Be careful that the memory
101733 ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
101734 **
101735 ** Note: We could avoid this by using a regular memory cell from aMem[] for
101736 ** the accumulator, instead of allocating one here. */
101737 nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) );
101738 pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
101739 if( pCtx==0 ) goto no_mem;
101740 pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
101741 assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
101742
@@ -103390,10 +103449,11 @@
103390 int iCol; /* Index of zColumn in row-record */
103391 int rc = SQLITE_OK;
103392 char *zErr = 0;
103393 Table *pTab;
103394 Incrblob *pBlob = 0;
 
103395 Parse sParse;
103396
103397 #ifdef SQLITE_ENABLE_API_ARMOR
103398 if( ppBlob==0 ){
103399 return SQLITE_MISUSE_BKPT;
@@ -103435,11 +103495,14 @@
103435 if( pTab && IsView(pTab) ){
103436 pTab = 0;
103437 sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
103438 }
103439 #endif
103440 if( !pTab ){
 
 
 
103441 if( sParse.zErrMsg ){
103442 sqlite3DbFree(db, zErr);
103443 zErr = sParse.zErrMsg;
103444 sParse.zErrMsg = 0;
103445 }
@@ -103446,11 +103509,11 @@
103446 rc = SQLITE_ERROR;
103447 sqlite3BtreeLeaveAll(db);
103448 goto blob_open_out;
103449 }
103450 pBlob->pTab = pTab;
103451 pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
103452
103453 /* Now search pTab for the exact column. */
103454 iCol = sqlite3ColumnIndex(pTab, zColumn);
103455 if( iCol<0 ){
103456 sqlite3DbFree(db, zErr);
@@ -103530,11 +103593,10 @@
103530 {OP_Column, 0, 0, 1}, /* 3 */
103531 {OP_ResultRow, 1, 0, 0}, /* 4 */
103532 {OP_Halt, 0, 0, 0}, /* 5 */
103533 };
103534 Vdbe *v = (Vdbe *)pBlob->pStmt;
103535 int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
103536 VdbeOp *aOp;
103537
103538 sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
103539 pTab->pSchema->schema_cookie,
103540 pTab->pSchema->iGeneration);
@@ -104108,12 +104170,15 @@
104108 u8 bUsePMA; /* True if one or more PMAs created */
104109 u8 bUseThreads; /* True to use background threads */
104110 u8 iPrev; /* Previous thread used to flush PMA */
104111 u8 nTask; /* Size of aTask[] array */
104112 u8 typeMask;
104113 SortSubtask aTask[1]; /* One or more subtasks */
104114 };
 
 
 
104115
104116 #define SORTER_TYPE_INTEGER 0x01
104117 #define SORTER_TYPE_TEXT 0x02
104118
104119 /*
@@ -104742,12 +104807,12 @@
104742 assert( pCsr->pKeyInfo );
104743 assert( !pCsr->isEphemeral );
104744 assert( pCsr->eCurType==CURTYPE_SORTER );
104745 assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
104746 < 0x7fffffff );
104747 szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
104748 sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
104749
104750 pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
104751 pCsr->uc.pSorter = pSorter;
104752 if( pSorter==0 ){
104753 rc = SQLITE_NOMEM_BKPT;
@@ -105207,10 +105272,14 @@
105207 }
105208
105209 p->u.pNext = 0;
105210 for(i=0; aSlot[i]; i++){
105211 p = vdbeSorterMerge(pTask, p, aSlot[i]);
 
 
 
 
105212 aSlot[i] = 0;
105213 }
105214 aSlot[i] = p;
105215 p = pNext;
105216 }
@@ -109981,32 +110050,34 @@
109981 Table *pTab, /* The table being referenced, or NULL */
109982 int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
109983 Expr *pExpr, /* Expression to resolve. May be NULL. */
109984 ExprList *pList /* Expression list to resolve. May be NULL. */
109985 ){
109986 SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
109987 NameContext sNC; /* Name context for pParse->pNewTable */
109988 int rc;
 
109989
109990 assert( type==0 || pTab!=0 );
109991 assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
109992 || type==NC_GenCol || pTab==0 );
109993 memset(&sNC, 0, sizeof(sNC));
109994 memset(&sSrc, 0, sizeof(sSrc));
 
109995 if( pTab ){
109996 sSrc.nSrc = 1;
109997 sSrc.a[0].zName = pTab->zName;
109998 sSrc.a[0].pSTab = pTab;
109999 sSrc.a[0].iCursor = -1;
110000 if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
110001 /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
110002 ** schema elements */
110003 type |= NC_FromDDL;
110004 }
110005 }
110006 sNC.pParse = pParse;
110007 sNC.pSrcList = &sSrc;
110008 sNC.ncFlags = type | NC_IsDDL;
110009 if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
110010 if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
110011 return rc;
110012 }
@@ -111751,11 +111822,11 @@
111751 */
111752 #ifndef SQLITE_OMIT_CTE
111753 SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){
111754 With *pRet = 0;
111755 if( p ){
111756 sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
111757 pRet = sqlite3DbMallocZero(db, nByte);
111758 if( pRet ){
111759 int i;
111760 pRet->nCte = p->nCte;
111761 for(i=0; i<p->nCte; i++){
@@ -111878,15 +111949,13 @@
111878 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
111879 || !defined(SQLITE_OMIT_SUBQUERY)
111880 SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
111881 SrcList *pNew;
111882 int i;
111883 int nByte;
111884 assert( db!=0 );
111885 if( p==0 ) return 0;
111886 nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
111887 pNew = sqlite3DbMallocRawNN(db, nByte );
111888 if( pNew==0 ) return 0;
111889 pNew->nSrc = pNew->nAlloc = p->nSrc;
111890 for(i=0; i<p->nSrc; i++){
111891 SrcItem *pNewItem = &pNew->a[i];
111892 const SrcItem *pOldItem = &p->a[i];
@@ -111944,11 +112013,11 @@
111944 SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
111945 IdList *pNew;
111946 int i;
111947 assert( db!=0 );
111948 if( p==0 ) return 0;
111949 pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
111950 if( pNew==0 ) return 0;
111951 pNew->nId = p->nId;
111952 for(i=0; i<p->nId; i++){
111953 struct IdList_item *pNewItem = &pNew->a[i];
111954 const struct IdList_item *pOldItem = &p->a[i];
@@ -112028,11 +112097,11 @@
112028 Expr *pExpr /* Expression to be appended. Might be NULL */
112029 ){
112030 struct ExprList_item *pItem;
112031 ExprList *pList;
112032
112033 pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
112034 if( pList==0 ){
112035 sqlite3ExprDelete(db, pExpr);
112036 return 0;
112037 }
112038 pList->nAlloc = 4;
@@ -112048,12 +112117,11 @@
112048 Expr *pExpr /* Expression to be appended. Might be NULL */
112049 ){
112050 struct ExprList_item *pItem;
112051 ExprList *pNew;
112052 pList->nAlloc *= 2;
112053 pNew = sqlite3DbRealloc(db, pList,
112054 sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
112055 if( pNew==0 ){
112056 sqlite3ExprListDelete(db, pList);
112057 sqlite3ExprDelete(db, pExpr);
112058 return 0;
112059 }else{
@@ -114685,11 +114753,11 @@
114685 return -1; /* Not found */
114686 }
114687
114688
114689 /*
114690 ** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This
114691 ** function checks the Parse.pIdxPartExpr list to see if this column
114692 ** can be replaced with a constant value. If so, it generates code to
114693 ** put the constant value in a register (ideally, but not necessarily,
114694 ** register iTarget) and returns the register number.
114695 **
@@ -118531,10 +118599,11 @@
118531 sqlite3 *db, /* Database handle */
118532 const char *zSql, /* SQL to parse */
118533 int bTemp /* True if SQL is from temp schema */
118534 ){
118535 int rc;
 
118536
118537 sqlite3ParseObjectInit(p, db);
118538 if( zSql==0 ){
118539 return SQLITE_NOMEM;
118540 }
@@ -118549,11 +118618,15 @@
118549 db->init.iDb = (u8)iDb;
118550 }
118551 p->eParseMode = PARSE_MODE_RENAME;
118552 p->db = db;
118553 p->nQueryLoop = 1;
 
 
 
118554 rc = sqlite3RunParser(p, zSql);
 
118555 if( db->mallocFailed ) rc = SQLITE_NOMEM;
118556 if( rc==SQLITE_OK
118557 && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
118558 ){
118559 rc = SQLITE_CORRUPT_BKPT;
@@ -119445,11 +119518,11 @@
119445 int rc;
119446 Parse sParse;
119447 u64 flags = db->flags;
119448 if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
119449 rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
119450 db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
119451 if( rc==SQLITE_OK ){
119452 if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
119453 NameContext sNC;
119454 memset(&sNC, 0, sizeof(sNC));
119455 sNC.pParse = &sParse;
@@ -126268,11 +126341,11 @@
126268 "columns in the referenced table");
126269 goto fk_end;
126270 }else{
126271 nCol = pFromCol->nExpr;
126272 }
126273 nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
126274 if( pToCol ){
126275 for(i=0; i<pToCol->nExpr; i++){
126276 nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
126277 }
126278 }
@@ -127327,16 +127400,15 @@
127327 */
127328 SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
127329 sqlite3 *db = pParse->db;
127330 int i;
127331 if( pList==0 ){
127332 pList = sqlite3DbMallocZero(db, sizeof(IdList) );
127333 if( pList==0 ) return 0;
127334 }else{
127335 IdList *pNew;
127336 pNew = sqlite3DbRealloc(db, pList,
127337 sizeof(IdList) + pList->nId*sizeof(pList->a));
127338 if( pNew==0 ){
127339 sqlite3IdListDelete(db, pList);
127340 return 0;
127341 }
127342 pList = pNew;
@@ -127431,12 +127503,11 @@
127431 sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
127432 SQLITE_MAX_SRCLIST);
127433 return 0;
127434 }
127435 if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
127436 pNew = sqlite3DbRealloc(db, pSrc,
127437 sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
127438 if( pNew==0 ){
127439 assert( db->mallocFailed );
127440 return 0;
127441 }
127442 pSrc = pNew;
@@ -127507,11 +127578,11 @@
127507 assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
127508 assert( pParse!=0 );
127509 assert( pParse->db!=0 );
127510 db = pParse->db;
127511 if( pList==0 ){
127512 pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
127513 if( pList==0 ) return 0;
127514 pList->nAlloc = 1;
127515 pList->nSrc = 1;
127516 memset(&pList->a[0], 0, sizeof(pList->a[0]));
127517 pList->a[0].iCursor = -1;
@@ -128393,14 +128464,13 @@
128393 }
128394 }
128395 }
128396
128397 if( pWith ){
128398 sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
128399 pNew = sqlite3DbRealloc(db, pWith, nByte);
128400 }else{
128401 pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
128402 }
128403 assert( (pNew!=0 && zName!=0) || db->mallocFailed );
128404
128405 if( db->mallocFailed ){
128406 sqlite3CteDelete(db, pCte);
@@ -131933,11 +132003,11 @@
131933 **
131934 ** The SUM() function follows the (broken) SQL standard which means
131935 ** that it returns NULL if it sums over no inputs. TOTAL returns
131936 ** 0.0 in that case. In addition, TOTAL always returns a float where
131937 ** SUM might return an integer if it never encounters a floating point
131938 ** value. TOTAL never fails, but SUM might through an exception if
131939 ** it overflows an integer.
131940 */
131941 static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
131942 SumCtx *p;
131943 int type;
@@ -139748,52 +139818,52 @@
139748 /* 11 */ "notnull",
139749 /* 12 */ "dflt_value",
139750 /* 13 */ "pk",
139751 /* 14 */ "hidden",
139752 /* table_info reuses 8 */
139753 /* 15 */ "schema", /* Used by: table_list */
139754 /* 16 */ "name",
139755 /* 17 */ "type",
139756 /* 18 */ "ncol",
139757 /* 19 */ "wr",
139758 /* 20 */ "strict",
139759 /* 21 */ "seqno", /* Used by: index_xinfo */
139760 /* 22 */ "cid",
139761 /* 23 */ "name",
139762 /* 24 */ "desc",
139763 /* 25 */ "coll",
139764 /* 26 */ "key",
139765 /* 27 */ "name", /* Used by: function_list */
139766 /* 28 */ "builtin",
139767 /* 29 */ "type",
139768 /* 30 */ "enc",
139769 /* 31 */ "narg",
139770 /* 32 */ "flags",
139771 /* 33 */ "tbl", /* Used by: stats */
139772 /* 34 */ "idx",
139773 /* 35 */ "wdth",
139774 /* 36 */ "hght",
139775 /* 37 */ "flgs",
139776 /* 38 */ "seq", /* Used by: index_list */
139777 /* 39 */ "name",
139778 /* 40 */ "unique",
139779 /* 41 */ "origin",
139780 /* 42 */ "partial",
139781 /* 43 */ "table", /* Used by: foreign_key_check */
139782 /* 44 */ "rowid",
139783 /* 45 */ "parent",
139784 /* 46 */ "fkid",
139785 /* index_info reuses 21 */
139786 /* 47 */ "seq", /* Used by: database_list */
139787 /* 48 */ "name",
139788 /* 49 */ "file",
139789 /* 50 */ "busy", /* Used by: wal_checkpoint */
139790 /* 51 */ "log",
139791 /* 52 */ "checkpointed",
139792 /* collation_list reuses 38 */
139793 /* 53 */ "database", /* Used by: lock_status */
139794 /* 54 */ "status",
 
139795 /* 55 */ "cache_size", /* Used by: default_cache_size */
139796 /* module_list pragma_list reuses 9 */
139797 /* 56 */ "timeout", /* Used by: busy_timeout */
139798 };
139799
@@ -139882,11 +139952,11 @@
139882 #endif
139883 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139884 {/* zName: */ "collation_list",
139885 /* ePragTyp: */ PragTyp_COLLATION_LIST,
139886 /* ePragFlg: */ PragFlg_Result0,
139887 /* ColNames: */ 38, 2,
139888 /* iArg: */ 0 },
139889 #endif
139890 #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
139891 {/* zName: */ "compile_options",
139892 /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
@@ -139917,11 +139987,11 @@
139917 #endif
139918 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139919 {/* zName: */ "database_list",
139920 /* ePragTyp: */ PragTyp_DATABASE_LIST,
139921 /* ePragFlg: */ PragFlg_Result0,
139922 /* ColNames: */ 47, 3,
139923 /* iArg: */ 0 },
139924 #endif
139925 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
139926 {/* zName: */ "default_cache_size",
139927 /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
@@ -139997,11 +140067,11 @@
139997 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139998 #if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
139999 {/* zName: */ "function_list",
140000 /* ePragTyp: */ PragTyp_FUNCTION_LIST,
140001 /* ePragFlg: */ PragFlg_Result0,
140002 /* ColNames: */ 27, 6,
140003 /* iArg: */ 0 },
140004 #endif
140005 #endif
140006 {/* zName: */ "hard_heap_limit",
140007 /* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT,
@@ -140026,21 +140096,21 @@
140026 #endif
140027 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
140028 {/* zName: */ "index_info",
140029 /* ePragTyp: */ PragTyp_INDEX_INFO,
140030 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140031 /* ColNames: */ 21, 3,
140032 /* iArg: */ 0 },
140033 {/* zName: */ "index_list",
140034 /* ePragTyp: */ PragTyp_INDEX_LIST,
140035 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140036 /* ColNames: */ 38, 5,
140037 /* iArg: */ 0 },
140038 {/* zName: */ "index_xinfo",
140039 /* ePragTyp: */ PragTyp_INDEX_INFO,
140040 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140041 /* ColNames: */ 21, 6,
140042 /* iArg: */ 1 },
140043 #endif
140044 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
140045 {/* zName: */ "integrity_check",
140046 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
@@ -140215,11 +140285,11 @@
140215 #endif
140216 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
140217 {/* zName: */ "stats",
140218 /* ePragTyp: */ PragTyp_STATS,
140219 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
140220 /* ColNames: */ 33, 5,
140221 /* iArg: */ 0 },
140222 #endif
140223 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
140224 {/* zName: */ "synchronous",
140225 /* ePragTyp: */ PragTyp_SYNCHRONOUS,
@@ -140234,11 +140304,11 @@
140234 /* ColNames: */ 8, 6,
140235 /* iArg: */ 0 },
140236 {/* zName: */ "table_list",
140237 /* ePragTyp: */ PragTyp_TABLE_LIST,
140238 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
140239 /* ColNames: */ 15, 6,
140240 /* iArg: */ 0 },
140241 {/* zName: */ "table_xinfo",
140242 /* ePragTyp: */ PragTyp_TABLE_INFO,
140243 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140244 /* ColNames: */ 8, 7,
@@ -140311,11 +140381,11 @@
140311 /* ColNames: */ 0, 0,
140312 /* iArg: */ 0 },
140313 {/* zName: */ "wal_checkpoint",
140314 /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
140315 /* ePragFlg: */ PragFlg_NeedSchema,
140316 /* ColNames: */ 50, 3,
140317 /* iArg: */ 0 },
140318 #endif
140319 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
140320 {/* zName: */ "writable_schema",
140321 /* ePragTyp: */ PragTyp_FLAG,
@@ -140333,11 +140403,11 @@
140333 ** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands
140334 ** will be run with an analysis_limit set to the lessor of the value of
140335 ** the following macro or to the actual analysis_limit if it is non-zero,
140336 ** in order to prevent PRAGMA optimize from running for too long.
140337 **
140338 ** The value of 2000 is chosen emperically so that the worst-case run-time
140339 ** for PRAGMA optimize does not exceed 100 milliseconds against a variety
140340 ** of test databases on a RaspberryPI-4 compiled using -Os and without
140341 ** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
140342 ** this paragraph, "worst-case" means that ANALYZE ends up being
140343 ** run on every table in the database. The worst case typically only
@@ -144622,11 +144692,11 @@
144622 pNew->iOffset = 0;
144623 pNew->selId = ++pParse->nSelect;
144624 pNew->addrOpenEphm[0] = -1;
144625 pNew->addrOpenEphm[1] = -1;
144626 pNew->nSelectRow = 0;
144627 if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
144628 pNew->pSrc = pSrc;
144629 pNew->pWhere = pWhere;
144630 pNew->pGroupBy = pGroupBy;
144631 pNew->pHaving = pHaving;
144632 pNew->pOrderBy = pOrderBy;
@@ -146005,20 +146075,20 @@
146005 /*
146006 ** Allocate a KeyInfo object sufficient for an index of N key columns and
146007 ** X extra columns.
146008 */
146009 SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
146010 int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
146011 KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
146012 if( p ){
146013 p->aSortFlags = (u8*)&p->aColl[N+X];
146014 p->nKeyField = (u16)N;
146015 p->nAllField = (u16)(N+X);
146016 p->enc = ENC(db);
146017 p->db = db;
146018 p->nRef = 1;
146019 memset(&p[1], 0, nExtra);
146020 }else{
146021 return (KeyInfo*)sqlite3OomFault(db);
146022 }
146023 return p;
146024 }
@@ -150530,11 +150600,11 @@
150530 }
150531 pTabList = p->pSrc;
150532 pEList = p->pEList;
150533 if( pParse->pWith && (p->selFlags & SF_View) ){
150534 if( p->pWith==0 ){
150535 p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
150536 if( p->pWith==0 ){
150537 return WRC_Abort;
150538 }
150539 }
150540 p->pWith->bView = 1;
@@ -151669,10 +151739,11 @@
151669 ** * The subquery is a UNION ALL of two or more terms
151670 ** * The subquery does not have a LIMIT clause
151671 ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
151672 ** * The outer query is a simple count(*) with no WHERE clause or other
151673 ** extraneous syntax.
 
151674 **
151675 ** Return TRUE if the optimization is undertaken.
151676 */
151677 static int countOfViewOptimization(Parse *pParse, Select *p){
151678 Select *pSub, *pPrior;
@@ -151701,11 +151772,15 @@
151701 if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */
151702 do{
151703 if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
151704 if( pSub->pWhere ) return 0; /* No WHERE clause */
151705 if( pSub->pLimit ) return 0; /* No LIMIT clause */
151706 if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
 
 
 
 
151707 assert( pSub->pHaving==0 ); /* Due to the previous */
151708 pSub = pSub->pPrior; /* Repeat over compound */
151709 }while( pSub );
151710
151711 /* If we reach this point then it is OK to perform the transformation */
@@ -151713,11 +151788,11 @@
151713 db = pParse->db;
151714 pCount = pExpr;
151715 pExpr = 0;
151716 pSub = sqlite3SubqueryDetach(db, pFrom);
151717 sqlite3SrcListDelete(db, p->pSrc);
151718 p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
151719 while( pSub ){
151720 Expr *pTerm;
151721 pPrior = pSub->pPrior;
151722 pSub->pPrior = 0;
151723 pSub->pNext = 0;
@@ -154504,11 +154579,12 @@
154504 Vdbe *v = pParse->pVdbe;
154505 sqlite3 *db = pParse->db;
154506 ExprList *pNew;
154507 Returning *pReturning;
154508 Select sSelect;
154509 SrcList sFrom;
 
154510
154511 assert( v!=0 );
154512 if( !pParse->bReturning ){
154513 /* This RETURNING trigger must be for a different statement as
154514 ** this statement lacks a RETURNING clause. */
@@ -154520,17 +154596,18 @@
154520 if( pTrigger != &(pReturning->retTrig) ){
154521 /* This RETURNING trigger is for a different statement */
154522 return;
154523 }
154524 memset(&sSelect, 0, sizeof(sSelect));
154525 memset(&sFrom, 0, sizeof(sFrom));
 
154526 sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
154527 sSelect.pSrc = &sFrom;
154528 sFrom.nSrc = 1;
154529 sFrom.a[0].pSTab = pTab;
154530 sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
154531 sFrom.a[0].iCursor = -1;
154532 sqlite3SelectPrep(pParse, &sSelect, 0);
154533 if( pParse->nErr==0 ){
154534 assert( db->mallocFailed==0 );
154535 sqlite3GenerateColumnNames(pParse, &sSelect);
154536 }
@@ -156927,11 +157004,11 @@
156927 saved_flags = db->flags;
156928 saved_mDbFlags = db->mDbFlags;
156929 saved_nChange = db->nChange;
156930 saved_nTotalChange = db->nTotalChange;
156931 saved_mTrace = db->mTrace;
156932 db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
156933 db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
156934 db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
156935 | SQLITE_Defensive | SQLITE_CountRows);
156936 db->mTrace = 0;
156937
@@ -159056,13 +159133,18 @@
159056 WhereLoop *pLoops; /* List of all WhereLoop objects */
159057 WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
159058 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
159059 WhereClause sWC; /* Decomposition of the WHERE clause */
159060 WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
159061 WhereLevel a[1]; /* Information about each nest loop in WHERE */
159062 };
159063
 
 
 
 
 
159064 /*
159065 ** Private interfaces - callable only by other where.c routines.
159066 **
159067 ** where.c:
159068 */
@@ -161509,12 +161591,11 @@
161509 */
161510 if( pWInfo->nLevel>1 ){
161511 int nNotReady; /* The number of notReady tables */
161512 SrcItem *origSrc; /* Original list of tables */
161513 nNotReady = pWInfo->nLevel - iLevel - 1;
161514 pOrTab = sqlite3DbMallocRawNN(db,
161515 sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
161516 if( pOrTab==0 ) return notReady;
161517 pOrTab->nAlloc = (u8)(nNotReady + 1);
161518 pOrTab->nSrc = pOrTab->nAlloc;
161519 memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
161520 origSrc = pWInfo->pTabList->a;
@@ -162053,11 +162134,12 @@
162053 Expr *pSubWhere = 0;
162054 WhereClause *pWC = &pWInfo->sWC;
162055 WhereInfo *pSubWInfo;
162056 WhereLoop *pLoop = pLevel->pWLoop;
162057 SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
162058 SrcList sFrom;
 
162059 Bitmask mAll = 0;
162060 int k;
162061
162062 ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
162063 sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
@@ -162097,17 +162179,18 @@
162097 if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
162098 pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
162099 sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
162100 }
162101 }
162102 sFrom.nSrc = 1;
162103 sFrom.nAlloc = 1;
162104 memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
162105 sFrom.a[0].fg.jointype = 0;
 
162106 assert( pParse->withinRJSubrtn < 100 );
162107 pParse->withinRJSubrtn++;
162108 pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
162109 WHERE_RIGHT_JOIN, 0);
162110 if( pSubWInfo ){
162111 int iCur = pLevel->iTabCur;
162112 int r = ++pParse->nMem;
162113 int nPk;
@@ -164091,15 +164174,20 @@
164091 WhereClause *pWC; /* The Where clause being analyzed */
164092 Parse *pParse; /* The parsing context */
164093 int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
164094 u32 mIn; /* Mask of terms that are <col> IN (...) */
164095 u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */
164096 sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
164097 ** because extra space is allocated to hold up
164098 ** to nTerm such values */
164099 };
164100
 
 
 
 
 
164101 /* Forward declaration of methods */
164102 static int whereLoopResize(sqlite3*, WhereLoop*, int);
164103
164104 /*
164105 ** Return the estimated number of output rows from a WHERE clause
@@ -165573,12 +165661,12 @@
165573
165574 /* Allocate the sqlite3_index_info structure
165575 */
165576 pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
165577 + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
165578 + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
165579 + sizeof(sqlite3_value*)*nTerm );
165580 if( pIdxInfo==0 ){
165581 sqlite3ErrorMsg(pParse, "out of memory");
165582 return 0;
165583 }
165584 pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
@@ -170768,14 +170856,11 @@
170768 ** struct, the contents of WhereInfo.a[], the WhereClause structure
170769 ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
170770 ** field (type Bitmask) it must be aligned on an 8-byte boundary on
170771 ** some architectures. Hence the ROUND8() below.
170772 */
170773 nByteWInfo = ROUND8P(sizeof(WhereInfo));
170774 if( nTabList>1 ){
170775 nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel));
170776 }
170777 pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
170778 if( db->mallocFailed ){
170779 sqlite3DbFree(db, pWInfo);
170780 pWInfo = 0;
170781 goto whereBeginError;
@@ -181607,11 +181692,15 @@
181607 tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
181608 }else if( tokenType==TK_FILTER ){
181609 assert( n==6 );
181610 tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
181611 #endif /* SQLITE_OMIT_WINDOWFUNC */
181612 }else if( tokenType==TK_COMMENT && (db->flags & SQLITE_Comments)!=0 ){
 
 
 
 
181613 zSql += n;
181614 continue;
181615 }else if( tokenType!=TK_QNUMBER ){
181616 Token x;
181617 x.z = zSql;
@@ -182502,10 +182591,18 @@
182502 }
182503 #endif
182504 if( rc==SQLITE_OK ){
182505 sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
182506 sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
 
 
 
 
 
 
 
 
182507 sqlite3MemoryBarrier();
182508 sqlite3GlobalConfig.isInit = 1;
182509 #ifdef SQLITE_EXTRA_INIT
182510 bRunExtraInit = 1;
182511 #endif
@@ -184063,10 +184160,14 @@
184063 sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt));
184064 sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC);
184065 }
184066 }
184067 sqlite3BtreeLeaveAll(db);
 
 
 
 
184068 #endif
184069 return SQLITE_OK;
184070 }
184071
184072 /*
@@ -186032,11 +186133,11 @@
186032 }else if( pData==0 ){
186033 sqlite3_mutex_leave(db->mutex);
186034 return SQLITE_OK;
186035 }else{
186036 size_t n = strlen(zName);
186037 p = sqlite3_malloc64( sizeof(DbClientData)+n+1 );
186038 if( p==0 ){
186039 if( xDestructor ) xDestructor(pData);
186040 sqlite3_mutex_leave(db->mutex);
186041 return SQLITE_NOMEM;
186042 }
@@ -186398,12 +186499,12 @@
186398 #endif
186399
186400 /* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b);
186401 **
186402 ** If b is true, then activate the SQLITE_FkNoAction setting. If b is
186403 ** false then clearn that setting. If the SQLITE_FkNoAction setting is
186404 ** abled, all foreign key ON DELETE and ON UPDATE actions behave as if
186405 ** they were NO ACTION, regardless of how they are defined.
186406 **
186407 ** NB: One must usually run "PRAGMA writable_schema=RESET" after
186408 ** using this test-control, before it will take full effect. failing
186409 ** to reset the schema can result in some unexpected behavior.
@@ -187746,11 +187847,11 @@
187746 ** }
187747 **
187748 ** Here, array { X } means zero or more occurrences of X, adjacent in
187749 ** memory. A "position" is an index of a token in the token stream
187750 ** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
187751 ** in the same logical place as the position element, and act as sentinals
187752 ** ending a position list array. POS_END is 0. POS_COLUMN is 1.
187753 ** The positions numbers are not stored literally but rather as two more
187754 ** than the difference from the prior position, or the just the position plus
187755 ** 2 for the first position. Example:
187756 **
@@ -188433,10 +188534,23 @@
188433
188434 #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
188435 #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
188436
188437 #define deliberate_fall_through
 
 
 
 
 
 
 
 
 
 
 
 
 
188438
188439 #endif /* SQLITE_AMALGAMATION */
188440
188441 #ifdef SQLITE_DEBUG
188442 SQLITE_PRIVATE int sqlite3Fts3Corrupt(void);
@@ -188538,11 +188652,11 @@
188538 int inTransaction; /* True after xBegin but before xCommit/xRollback */
188539 int mxSavepoint; /* Largest valid xSavepoint integer */
188540 #endif
188541
188542 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
188543 /* True to disable the incremental doclist optimization. This is controled
188544 ** by special insert command 'test-no-incr-doclist'. */
188545 int bNoIncrDoclist;
188546
188547 /* Number of segments in a level */
188548 int nMergeCount;
@@ -188590,11 +188704,11 @@
188590 #define FTS3_EVAL_NEXT 1
188591 #define FTS3_EVAL_MATCHINFO 2
188592
188593 /*
188594 ** The Fts3Cursor.eSearch member is always set to one of the following.
188595 ** Actualy, Fts3Cursor.eSearch can be greater than or equal to
188596 ** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
188597 ** of the column to be searched. For example, in
188598 **
188599 ** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
188600 ** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
@@ -188663,12 +188777,16 @@
188663 /* Variables below this point are populated by fts3_expr.c when parsing
188664 ** a MATCH expression. Everything above is part of the evaluation phase.
188665 */
188666 int nToken; /* Number of tokens in the phrase */
188667 int iColumn; /* Index of column this phrase must match */
188668 Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
188669 };
 
 
 
 
188670
188671 /*
188672 ** A tree of these objects forms the RHS of a MATCH operator.
188673 **
188674 ** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
@@ -191243,11 +191361,11 @@
191243 **
191244 ** The space required to store the output is therefore the sum of the
191245 ** sizes of the two inputs, plus enough space for exactly one of the input
191246 ** docids to grow.
191247 **
191248 ** A symetric argument may be made if the doclists are in descending
191249 ** order.
191250 */
191251 aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
191252 if( !aOut ) return SQLITE_NOMEM;
191253
@@ -193341,11 +193459,11 @@
193341 **
193342 ** * features at least one token that uses an incremental doclist, and
193343 **
193344 ** * does not contain any deferred tokens.
193345 **
193346 ** Advance it to the next matching documnent in the database and populate
193347 ** the Fts3Doclist.pList and nList fields.
193348 **
193349 ** If there is no "next" entry and no error occurs, then *pbEof is set to
193350 ** 1 before returning. Otherwise, if no error occurs and the iterator is
193351 ** successfully advanced, *pbEof is set to 0.
@@ -194348,11 +194466,11 @@
194348
194349 return rc;
194350 }
194351
194352 /*
194353 ** Restart interation for expression pExpr so that the next call to
194354 ** fts3EvalNext() visits the first row. Do not allow incremental
194355 ** loading or merging of phrase doclists for this iteration.
194356 **
194357 ** If *pRc is other than SQLITE_OK when this function is called, it is
194358 ** a no-op. If an error occurs within this function, *pRc is set to an
@@ -195539,10 +195657,27 @@
195539 /*
195540 ** Function getNextNode(), which is called by fts3ExprParse(), may itself
195541 ** call fts3ExprParse(). So this forward declaration is required.
195542 */
195543 static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195544
195545 /*
195546 ** Extract the next token from buffer z (length n) using the tokenizer
195547 ** and other information (column names etc.) in pParse. Create an Fts3Expr
195548 ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -195564,38 +195699,42 @@
195564 sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
195565 sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
195566 int rc;
195567 sqlite3_tokenizer_cursor *pCursor;
195568 Fts3Expr *pRet = 0;
195569 int i = 0;
195570
195571 /* Set variable i to the maximum number of bytes of input to tokenize. */
195572 for(i=0; i<n; i++){
195573 if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
195574 if( z[i]=='"' ) break;
195575 }
195576
195577 *pnConsumed = i;
195578 rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
195579 if( rc==SQLITE_OK ){
195580 const char *zToken;
195581 int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
195582 sqlite3_int64 nByte; /* total space to allocate */
195583
195584 rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
195585 if( rc==SQLITE_OK ){
195586 nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
 
 
 
 
 
 
 
 
 
 
 
195587 pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
195588 if( !pRet ){
195589 rc = SQLITE_NOMEM;
195590 }else{
195591 pRet->eType = FTSQUERY_PHRASE;
195592 pRet->pPhrase = (Fts3Phrase *)&pRet[1];
195593 pRet->pPhrase->nToken = 1;
195594 pRet->pPhrase->iColumn = iCol;
195595 pRet->pPhrase->aToken[0].n = nToken;
195596 pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
195597 memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
195598
195599 if( iEnd<n && z[iEnd]=='*' ){
195600 pRet->pPhrase->aToken[0].isPrefix = 1;
195601 iEnd++;
@@ -195615,11 +195754,15 @@
195615 }
195616 }
195617
195618 }
195619 *pnConsumed = iEnd;
195620 }else if( i && rc==SQLITE_DONE ){
 
 
 
 
195621 rc = SQLITE_OK;
195622 }
195623
195624 pModule->xClose(pCursor);
195625 }
@@ -195664,11 +195807,11 @@
195664 Fts3Expr *p = 0;
195665 sqlite3_tokenizer_cursor *pCursor = 0;
195666 char *zTemp = 0;
195667 i64 nTemp = 0;
195668
195669 const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
195670 int nToken = 0;
195671
195672 /* The final Fts3Expr data structure, including the Fts3Phrase,
195673 ** Fts3PhraseToken structures token buffers are all stored as a single
195674 ** allocation so that the expression can be freed with a single call to
@@ -196036,11 +196179,11 @@
196036 int eType = p->eType;
196037 isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
196038
196039 /* The isRequirePhrase variable is set to true if a phrase or
196040 ** an expression contained in parenthesis is required. If a
196041 ** binary operator (AND, OR, NOT or NEAR) is encounted when
196042 ** isRequirePhrase is set, this is a syntax error.
196043 */
196044 if( !isPhrase && isRequirePhrase ){
196045 sqlite3Fts3ExprFree(p);
196046 rc = SQLITE_ERROR;
@@ -196618,11 +196761,10 @@
196618 pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
196619 );
196620 }
196621
196622 if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
196623 sqlite3Fts3ExprFree(pExpr);
196624 sqlite3_result_error(context, "Error parsing expression", -1);
196625 }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
196626 sqlite3_result_error_nomem(context);
196627 }else{
196628 sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
@@ -196861,11 +197003,11 @@
196861 pEntry->count++;
196862 pEntry->chain = pNew;
196863 }
196864
196865
196866 /* Resize the hash table so that it cantains "new_size" buckets.
196867 ** "new_size" must be a power of 2. The hash table might fail
196868 ** to resize if sqliteMalloc() fails.
196869 **
196870 ** Return non-zero if a memory allocation error occurs.
196871 */
@@ -197316,11 +197458,11 @@
197316 isConsonant(z+2);
197317 }
197318
197319 /*
197320 ** If the word ends with zFrom and xCond() is true for the stem
197321 ** of the word that preceeds the zFrom ending, then change the
197322 ** ending to zTo.
197323 **
197324 ** The input word *pz and zFrom are both in reverse order. zTo
197325 ** is in normal order.
197326 **
@@ -202899,11 +203041,11 @@
202899 ** previous term. Before this function returns, it is updated to contain a
202900 ** copy of zTerm/nTerm.
202901 **
202902 ** It is assumed that the buffer associated with pNode is already large
202903 ** enough to accommodate the new entry. The buffer associated with pPrev
202904 ** is extended by this function if requrired.
202905 **
202906 ** If an error (i.e. OOM condition) occurs, an SQLite error code is
202907 ** returned. Otherwise, SQLITE_OK.
202908 */
202909 static int fts3AppendToNode(
@@ -204562,11 +204704,11 @@
204562 #endif
204563
204564 /*
204565 ** SQLite value pRowid contains the rowid of a row that may or may not be
204566 ** present in the FTS3 table. If it is, delete it and adjust the contents
204567 ** of subsiduary data structures accordingly.
204568 */
204569 static int fts3DeleteByRowid(
204570 Fts3Table *p,
204571 sqlite3_value *pRowid,
204572 int *pnChng, /* IN/OUT: Decrement if row is deleted */
@@ -204888,12 +205030,16 @@
204888 struct MatchinfoBuffer {
204889 u8 aRef[3];
204890 int nElem;
204891 int bGlobal; /* Set if global data is loaded */
204892 char *zMatchinfo;
204893 u32 aMatchinfo[1];
204894 };
 
 
 
 
204895
204896
204897 /*
204898 ** The snippet() and offsets() functions both return text values. An instance
204899 ** of the following structure is used to accumulate those values while the
@@ -204915,17 +205061,17 @@
204915 ** Allocate a two-slot MatchinfoBuffer object.
204916 */
204917 static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
204918 MatchinfoBuffer *pRet;
204919 sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
204920 + sizeof(MatchinfoBuffer);
204921 sqlite3_int64 nStr = strlen(zMatchinfo);
204922
204923 pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
204924 if( pRet ){
204925 pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
204926 pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
204927 + sizeof(u32)*((int)nElem+1);
204928 pRet->nElem = (int)nElem;
204929 pRet->zMatchinfo = ((char*)pRet) + nByte;
204930 memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
204931 pRet->aRef[0] = 1;
@@ -204935,14 +205081,14 @@
204935 }
204936
204937 static void fts3MIBufferFree(void *p){
204938 MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
204939
204940 assert( (u32*)p==&pBuf->aMatchinfo[1]
204941 || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
204942 );
204943 if( (u32*)p==&pBuf->aMatchinfo[1] ){
204944 pBuf->aRef[1] = 0;
204945 }else{
204946 pBuf->aRef[2] = 0;
204947 }
204948
@@ -204955,32 +205101,32 @@
204955 void (*xRet)(void*) = 0;
204956 u32 *aOut = 0;
204957
204958 if( p->aRef[1]==0 ){
204959 p->aRef[1] = 1;
204960 aOut = &p->aMatchinfo[1];
204961 xRet = fts3MIBufferFree;
204962 }
204963 else if( p->aRef[2]==0 ){
204964 p->aRef[2] = 1;
204965 aOut = &p->aMatchinfo[p->nElem+2];
204966 xRet = fts3MIBufferFree;
204967 }else{
204968 aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
204969 if( aOut ){
204970 xRet = sqlite3_free;
204971 if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
204972 }
204973 }
204974
204975 *paOut = aOut;
204976 return xRet;
204977 }
204978
204979 static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
204980 p->bGlobal = 1;
204981 memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
204982 }
204983
204984 /*
204985 ** Free a MatchinfoBuffer object allocated using fts3MIBufferNew()
204986 */
@@ -205391,11 +205537,11 @@
205391 if( nAppend<0 ){
205392 nAppend = (int)strlen(zAppend);
205393 }
205394
205395 /* If there is insufficient space allocated at StrBuffer.z, use realloc()
205396 ** to grow the buffer until so that it is big enough to accomadate the
205397 ** appended data.
205398 */
205399 if( pStr->n+nAppend+1>=pStr->nAlloc ){
205400 sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
205401 char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
@@ -207766,11 +207912,11 @@
207766 **
207767 ** When a match if found, the matching entry is moved to become the
207768 ** most-recently used entry if it isn't so already.
207769 **
207770 ** The JsonParse object returned still belongs to the Cache and might
207771 ** be deleted at any moment. If the caller whants the JsonParse to
207772 ** linger, it needs to increment the nPJRef reference counter.
207773 */
207774 static JsonParse *jsonCacheSearch(
207775 sqlite3_context *ctx, /* The SQL statement context holding the cache */
207776 sqlite3_value *pArg /* Function argument containing SQL text */
@@ -210811,11 +210957,11 @@
210811 **
210812 ** This goes against all historical documentation about how the SQLite
210813 ** JSON functions were suppose to work. From the beginning, blob was
210814 ** reserved for expansion and a blob value should have raised an error.
210815 ** But it did not, due to a bug. And many applications came to depend
210816 ** upon this buggy behavior, espeically when using the CLI and reading
210817 ** JSON text using readfile(), which returns a blob. For this reason
210818 ** we will continue to support the bug moving forward.
210819 ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
210820 */
210821 }
@@ -212911,10 +213057,18 @@
212911 # define NEVER(X) ((X)?(assert(0),1):0)
212912 #else
212913 # define ALWAYS(X) (X)
212914 # define NEVER(X) (X)
212915 #endif
 
 
 
 
 
 
 
 
212916 #endif /* !defined(SQLITE_AMALGAMATION) */
212917
212918 /* Macro to check for 4-byte alignment. Only used inside of assert() */
212919 #ifdef SQLITE_DEBUG
212920 # define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0)
@@ -213231,13 +213385,17 @@
213231 struct RtreeMatchArg {
213232 u32 iSize; /* Size of this object */
213233 RtreeGeomCallback cb; /* Info about the callback functions */
213234 int nParam; /* Number of parameters to the SQL function */
213235 sqlite3_value **apSqlParam; /* Original SQL parameter values */
213236 RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
213237 };
213238
 
 
 
 
213239 #ifndef MAX
213240 # define MAX(x,y) ((x) < (y) ? (y) : (x))
213241 #endif
213242 #ifndef MIN
213243 # define MIN(x,y) ((x) > (y) ? (y) : (x))
@@ -214922,11 +215080,11 @@
214922
214923 return rc;
214924 }
214925
214926 /*
214927 ** Return the N-dimensional volumn of the cell stored in *p.
214928 */
214929 static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
214930 RtreeDValue area = (RtreeDValue)1;
214931 assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
214932 #ifndef SQLITE_RTREE_INT_ONLY
@@ -216688,11 +216846,11 @@
216688 }
216689
216690 /*
216691 ** The second and subsequent arguments to this function are a printf()
216692 ** style format string and arguments. This function formats the string and
216693 ** appends it to the report being accumuated in pCheck.
216694 */
216695 static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
216696 va_list ap;
216697 va_start(ap, zFmt);
216698 if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){
@@ -217876,11 +218034,11 @@
217876
217877 /*
217878 ** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
217879 ** Returns:
217880 **
217881 ** +2 x0,y0 is on the line segement
217882 **
217883 ** +1 x0,y0 is beneath line segment
217884 **
217885 ** 0 x0,y0 is not on or beneath the line segment or the line segment
217886 ** is vertical and x0,y0 is not on the line segment
@@ -217982,11 +218140,11 @@
217982 }
217983 sqlite3_free(p1);
217984 sqlite3_free(p2);
217985 }
217986
217987 /* Objects used by the overlap algorihm. */
217988 typedef struct GeoEvent GeoEvent;
217989 typedef struct GeoSegment GeoSegment;
217990 typedef struct GeoOverlap GeoOverlap;
217991 struct GeoEvent {
217992 double x; /* X coordinate at which event occurs */
@@ -219029,12 +219187,11 @@
219029 RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
219030 RtreeMatchArg *pBlob;
219031 sqlite3_int64 nBlob;
219032 int memErr = 0;
219033
219034 nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
219035 + nArg*sizeof(sqlite3_value*);
219036 pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
219037 if( !pBlob ){
219038 sqlite3_result_error_nomem(ctx);
219039 }else{
219040 int i;
@@ -220125,11 +220282,11 @@
220125 ** to read from the original database snapshot. In other words, partially
220126 ** applied transactions are not visible to other clients.
220127 **
220128 ** "RBU" stands for "Resumable Bulk Update". As in a large database update
220129 ** transmitted via a wireless network to a mobile device. A transaction
220130 ** applied using this extension is hence refered to as an "RBU update".
220131 **
220132 **
220133 ** LIMITATIONS
220134 **
220135 ** An "RBU update" transaction is subject to the following limitations:
@@ -220422,11 +220579,11 @@
220422 ** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
220423 ** of the state tables within the state database are zeroed. This way,
220424 ** the next call to sqlite3rbu_vacuum() opens a handle that starts a
220425 ** new RBU vacuum operation.
220426 **
220427 ** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
220428 ** describing the sqlite3rbu_create_vfs() API function below for
220429 ** a description of the complications associated with using RBU with
220430 ** zipvfs databases.
220431 */
220432 SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
@@ -220518,11 +220675,11 @@
220518 /*
220519 ** Close an RBU handle.
220520 **
220521 ** If the RBU update has been completely applied, mark the RBU database
220522 ** as fully applied. Otherwise, assuming no error has occurred, save the
220523 ** current state of the RBU update appliation to the RBU database.
220524 **
220525 ** If an error has already occurred as part of an sqlite3rbu_step()
220526 ** or sqlite3rbu_open() call, or if one occurs within this function, an
220527 ** SQLite error code is returned. Additionally, if pzErrmsg is not NULL,
220528 ** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted
@@ -225444,11 +225601,11 @@
225444 int rc;
225445 rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
225446
225447 /* If this is an RBU vacuum operation and this is the target database,
225448 ** pretend that it has at least one page. Otherwise, SQLite will not
225449 ** check for the existance of a *-wal file. rbuVfsRead() contains
225450 ** similar logic. */
225451 if( rc==SQLITE_OK && *pSize==0
225452 && p->pRbu && rbuIsVacuum(p->pRbu)
225453 && (p->openFlags & SQLITE_OPEN_MAIN_DB)
225454 ){
@@ -228674,11 +228831,11 @@
228674 }
228675
228676 /*
228677 ** This function is called to initialize the SessionTable.nCol, azCol[]
228678 ** abPK[] and azDflt[] members of SessionTable object pTab. If these
228679 ** fields are already initilialized, this function is a no-op.
228680 **
228681 ** If an error occurs, an error code is stored in sqlite3_session.rc and
228682 ** non-zero returned. Or, if no error occurs but the table has no primary
228683 ** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to
228684 ** indicate that updates on this table should be ignored. SessionTable.abPK
@@ -230497,11 +230654,11 @@
230497 int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
230498 void **ppChangeset /* OUT: Buffer containing changeset */
230499 ){
230500 sqlite3 *db = pSession->db; /* Source database handle */
230501 SessionTable *pTab; /* Used to iterate through attached tables */
230502 SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
230503 int rc; /* Return code */
230504
230505 assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
230506 assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );
230507
@@ -234931,10 +235088,22 @@
234931 # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
234932 #else
234933 # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
234934 #endif
234935
 
 
 
 
 
 
 
 
 
 
 
 
234936 #endif
234937
234938 /* Truncate very long tokens to this many bytes. Hard limit is
234939 ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
234940 ** field that occurs at the start of each leaf page (see fts5_index.c). */
@@ -235003,14 +235172,15 @@
235003 **
235004 ** This object is used by fts5_expr.c and fts5_index.c.
235005 */
235006 struct Fts5Colset {
235007 int nCol;
235008 int aiCol[1];
235009 };
235010
235011
 
235012
235013 /**************************************************************************
235014 ** Interface to code in fts5_config.c. fts5_config.c contains contains code
235015 ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
235016 */
@@ -235835,11 +236005,11 @@
235835 *************************************************************************
235836 ** Driver template for the LEMON parser generator.
235837 **
235838 ** The "lemon" program processes an LALR(1) input grammar file, then uses
235839 ** this template to construct a parser. The "lemon" program inserts text
235840 ** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
235841 ** interstitial "-" characters) contained in this template is changed into
235842 ** the value of the %name directive from the grammar. Otherwise, the content
235843 ** of this template is copied straight through into the generate parser
235844 ** source file.
235845 **
@@ -237989,11 +238159,11 @@
237989 ** where "N" is the total number of documents in the set and nHit
237990 ** is the number that contain at least one instance of the phrase
237991 ** under consideration.
237992 **
237993 ** The problem with this is that if (N < 2*nHit), the IDF is
237994 ** negative. Which is undesirable. So the mimimum allowable IDF is
237995 ** (1e-6) - roughly the same as a term that appears in just over
237996 ** half of set of 5,000,000 documents. */
237997 double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
237998 if( idf<=0.0 ) idf = 1e-6;
237999 p->aIDF[i] = idf;
@@ -238452,11 +238622,11 @@
238452 **
238453 ** * All non-ASCII characters,
238454 ** * The 52 upper and lower case ASCII characters, and
238455 ** * The 10 integer ASCII characters.
238456 ** * The underscore character "_" (0x5F).
238457 ** * The unicode "subsitute" character (0x1A).
238458 */
238459 static int sqlite3Fts5IsBareword(char t){
238460 u8 aBareword[128] = {
238461 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 .. 0x0F */
238462 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */
@@ -239770,12 +239940,16 @@
239770 Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
239771
239772 /* Child nodes. For a NOT node, this array always contains 2 entries. For
239773 ** AND or OR nodes, it contains 2 or more entries. */
239774 int nChild; /* Number of child nodes */
239775 Fts5ExprNode *apChild[1]; /* Array of child nodes */
239776 };
 
 
 
 
239777
239778 #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
239779
239780 /*
239781 ** Invoke the xNext method of an Fts5ExprNode object. This macro should be
@@ -239803,24 +239977,31 @@
239803 */
239804 struct Fts5ExprPhrase {
239805 Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
239806 Fts5Buffer poslist; /* Current position list */
239807 int nTerm; /* Number of entries in aTerm[] */
239808 Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
239809 };
 
 
 
 
239810
239811 /*
239812 ** One or more phrases that must appear within a certain token distance of
239813 ** each other within each matching document.
239814 */
239815 struct Fts5ExprNearset {
239816 int nNear; /* NEAR parameter */
239817 Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
239818 int nPhrase; /* Number of entries in aPhrase[] array */
239819 Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
239820 };
239821
 
 
 
239822
239823 /*
239824 ** Parse context.
239825 */
239826 struct Fts5Parse {
@@ -239976,11 +240157,11 @@
239976 assert_expr_depth_ok(sParse.rc, sParse.pExpr);
239977
239978 /* If the LHS of the MATCH expression was a user column, apply the
239979 ** implicit column-filter. */
239980 if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
239981 int n = sizeof(Fts5Colset);
239982 Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
239983 if( pColset ){
239984 pColset->nCol = 1;
239985 pColset->aiCol[0] = iCol;
239986 sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
@@ -241334,11 +241515,11 @@
241334 Fts5ExprNearset *pRet = 0;
241335
241336 if( pParse->rc==SQLITE_OK ){
241337 if( pNear==0 ){
241338 sqlite3_int64 nByte;
241339 nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
241340 pRet = sqlite3_malloc64(nByte);
241341 if( pRet==0 ){
241342 pParse->rc = SQLITE_NOMEM;
241343 }else{
241344 memset(pRet, 0, (size_t)nByte);
@@ -241345,11 +241526,11 @@
241345 }
241346 }else if( (pNear->nPhrase % SZALLOC)==0 ){
241347 int nNew = pNear->nPhrase + SZALLOC;
241348 sqlite3_int64 nByte;
241349
241350 nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
241351 pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
241352 if( pRet==0 ){
241353 pParse->rc = SQLITE_NOMEM;
241354 }
241355 }else{
@@ -241436,16 +241617,16 @@
241436 if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){
241437 Fts5ExprPhrase *pNew;
241438 int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
241439
241440 pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
241441 sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
241442 );
241443 if( pNew==0 ){
241444 rc = SQLITE_NOMEM;
241445 }else{
241446 if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
241447 pCtx->pPhrase = pPhrase = pNew;
241448 pNew->nTerm = nNew - SZALLOC;
241449 }
241450 }
241451
@@ -241549,11 +241730,11 @@
241549 }
241550
241551 if( sCtx.pPhrase==0 ){
241552 /* This happens when parsing a token or quoted phrase that contains
241553 ** no token characters at all. (e.g ... MATCH '""'). */
241554 sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
241555 }else if( sCtx.pPhrase->nTerm ){
241556 sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
241557 }
241558 assert( pParse->apPhrase!=0 );
241559 pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
@@ -241584,23 +241765,22 @@
241584 if( rc==SQLITE_OK ){
241585 pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
241586 sizeof(Fts5ExprPhrase*));
241587 }
241588 if( rc==SQLITE_OK ){
241589 pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
241590 sizeof(Fts5ExprNode));
241591 }
241592 if( rc==SQLITE_OK ){
241593 pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
241594 sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
241595 }
241596 if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
241597 Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
241598 if( pColsetOrig ){
241599 sqlite3_int64 nByte;
241600 Fts5Colset *pColset;
241601 nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
241602 pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
241603 if( pColset ){
241604 memcpy(pColset, pColsetOrig, (size_t)nByte);
241605 }
241606 pNew->pRoot->pNear->pColset = pColset;
@@ -241624,11 +241804,11 @@
241624 }
241625 }
241626 }else{
241627 /* This happens when parsing a token or quoted phrase that contains
241628 ** no token characters at all. (e.g ... MATCH '""'). */
241629 sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
241630 }
241631 }
241632
241633 if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
241634 /* All the allocations succeeded. Put the expression object together. */
@@ -241718,11 +241898,11 @@
241718 Fts5Colset *pNew; /* New colset object to return */
241719
241720 assert( pParse->rc==SQLITE_OK );
241721 assert( iCol>=0 && iCol<pParse->pConfig->nCol );
241722
241723 pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
241724 if( pNew==0 ){
241725 pParse->rc = SQLITE_NOMEM;
241726 }else{
241727 int *aiCol = pNew->aiCol;
241728 int i, j;
@@ -241753,11 +241933,11 @@
241753 static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
241754 Fts5Colset *pRet;
241755 int nCol = pParse->pConfig->nCol;
241756
241757 pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
241758 sizeof(Fts5Colset) + sizeof(int)*nCol
241759 );
241760 if( pRet ){
241761 int i;
241762 int iOld = 0;
241763 for(i=0; i<nCol; i++){
@@ -241814,11 +241994,11 @@
241814 ** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
241815 */
241816 static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
241817 Fts5Colset *pRet;
241818 if( pOrig ){
241819 sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
241820 pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
241821 if( pRet ){
241822 memcpy(pRet, pOrig, (size_t)nByte);
241823 }
241824 }else{
@@ -241982,21 +242162,21 @@
241982 Fts5ExprNode *pRet;
241983
241984 assert( pNear->nPhrase==1 );
241985 assert( pParse->bPhraseToAnd );
241986
241987 nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
241988 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
241989 if( pRet ){
241990 pRet->eType = FTS5_AND;
241991 pRet->nChild = nTerm;
241992 pRet->iHeight = 1;
241993 fts5ExprAssignXNext(pRet);
241994 pParse->nPhrase--;
241995 for(ii=0; ii<nTerm; ii++){
241996 Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
241997 &pParse->rc, sizeof(Fts5ExprPhrase)
241998 );
241999 if( pPhrase ){
242000 if( parseGrowPhraseArray(pParse) ){
242001 fts5ExprPhraseFree(pPhrase);
242002 }else{
@@ -242061,11 +242241,11 @@
242061 nChild = 2;
242062 if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
242063 if( pRight->eType==eType ) nChild += pRight->nChild-1;
242064 }
242065
242066 nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
242067 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
242068
242069 if( pRet ){
242070 pRet->eType = eType;
242071 pRet->pNear = pNear;
@@ -242936,11 +243116,11 @@
242936 }
242937 return rc;
242938 }
242939
242940 /*
242941 ** Clear the token mappings for all Fts5IndexIter objects mannaged by
242942 ** the expression passed as the only argument.
242943 */
242944 static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
242945 int ii;
242946 for(ii=0; ii<pExpr->nPhrase; ii++){
@@ -242971,11 +243151,11 @@
242971
242972 typedef struct Fts5HashEntry Fts5HashEntry;
242973
242974 /*
242975 ** This file contains the implementation of an in-memory hash table used
242976 ** to accumuluate "term -> doclist" content before it is flused to a level-0
242977 ** segment.
242978 */
242979
242980
242981 struct Fts5Hash {
@@ -243028,11 +243208,11 @@
243028 int iPos; /* Position of last value written */
243029 i64 iRowid; /* Rowid of last value written */
243030 };
243031
243032 /*
243033 ** Eqivalent to:
243034 **
243035 ** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
243036 */
243037 #define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
243038
@@ -243964,13 +244144,17 @@
243964 int nRef; /* Object reference count */
243965 u64 nWriteCounter; /* Total leaves written to level 0 */
243966 u64 nOriginCntr; /* Origin value for next top-level segment */
243967 int nSegment; /* Total segments in this structure */
243968 int nLevel; /* Number of levels in this index */
243969 Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
243970 };
243971
 
 
 
 
243972 /*
243973 ** An object of type Fts5SegWriter is used to write to segments.
243974 */
243975 struct Fts5PageWriter {
243976 int pgno; /* Page number for this page */
@@ -244096,14 +244280,18 @@
244096
244097 /*
244098 ** Array of tombstone pages. Reference counted.
244099 */
244100 struct Fts5TombstoneArray {
244101 int nRef; /* Number of pointers to this object */
244102 int nTombstone;
244103 Fts5Data *apTombstone[1]; /* Array of tombstone pages */
244104 };
 
 
 
 
244105
244106 /*
244107 ** Argument is a pointer to an Fts5Data structure that contains a
244108 ** leaf page.
244109 */
@@ -244169,12 +244357,15 @@
244169 int bRev; /* True to iterate in reverse order */
244170 u8 bSkipEmpty; /* True to skip deleted entries */
244171
244172 i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
244173 Fts5CResult *aFirst; /* Current merge state (see above) */
244174 Fts5SegIter aSeg[1]; /* Array of segment iterators */
244175 };
 
 
 
244176
244177 /*
244178 ** An instance of the following type is used to iterate through the contents
244179 ** of a doclist-index record.
244180 **
@@ -244198,12 +244389,16 @@
244198 i64 iRowid; /* First rowid on leaf iLeafPgno */
244199 };
244200 struct Fts5DlidxIter {
244201 int nLvl;
244202 int iSegid;
244203 Fts5DlidxLvl aLvl[1];
244204 };
 
 
 
 
244205
244206 static void fts5PutU16(u8 *aOut, u16 iVal){
244207 aOut[0] = (iVal>>8);
244208 aOut[1] = (iVal&0xFF);
244209 }
@@ -244568,11 +244763,11 @@
244568 ** an error occurs, (*pRc) is set to an SQLite error code before returning.
244569 */
244570 static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
244571 Fts5Structure *p = *pp;
244572 if( *pRc==SQLITE_OK && p->nRef>1 ){
244573 i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
244574 Fts5Structure *pNew;
244575 pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
244576 if( pNew ){
244577 int i;
244578 memcpy(pNew, p, nByte);
@@ -244642,14 +244837,11 @@
244642 if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
244643 || nSegment>FTS5_MAX_SEGMENT || nSegment<0
244644 ){
244645 return FTS5_CORRUPT;
244646 }
244647 nByte = (
244648 sizeof(Fts5Structure) + /* Main structure */
244649 sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
244650 );
244651 pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
244652
244653 if( pRet ){
244654 pRet->nRef = 1;
244655 pRet->nLevel = nLevel;
@@ -244725,14 +244917,11 @@
244725 fts5StructureMakeWritable(pRc, ppStruct);
244726 assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK );
244727 if( *pRc==SQLITE_OK ){
244728 Fts5Structure *pStruct = *ppStruct;
244729 int nLevel = pStruct->nLevel;
244730 sqlite3_int64 nByte = (
244731 sizeof(Fts5Structure) + /* Main structure */
244732 sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
244733 );
244734
244735 pStruct = sqlite3_realloc64(pStruct, nByte);
244736 if( pStruct ){
244737 memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
244738 pStruct->nLevel++;
@@ -245267,11 +245456,11 @@
245267 Fts5DlidxIter *pIter = 0;
245268 int i;
245269 int bDone = 0;
245270
245271 for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
245272 sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
245273 Fts5DlidxIter *pNew;
245274
245275 pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
245276 if( pNew==0 ){
245277 p->rc = SQLITE_NOMEM;
@@ -245485,11 +245674,11 @@
245485 ** leave an error in the Fts5Index object.
245486 */
245487 static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
245488 const int nTomb = pIter->pSeg->nPgTombstone;
245489 if( nTomb>0 ){
245490 int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
245491 Fts5TombstoneArray *pNew;
245492 pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
245493 if( pNew ){
245494 pNew->nTombstone = nTomb;
245495 pNew->nRef = 1;
@@ -246946,12 +247135,11 @@
246946 Fts5Iter *pNew;
246947 i64 nSlot; /* Power of two >= nSeg */
246948
246949 for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
246950 pNew = fts5IdxMalloc(p,
246951 sizeof(Fts5Iter) + /* pNew */
246952 sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
246953 sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
246954 );
246955 if( pNew ){
246956 pNew->nSeg = nSlot;
246957 pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
@@ -249313,11 +249501,11 @@
249313 static Fts5Structure *fts5IndexOptimizeStruct(
249314 Fts5Index *p,
249315 Fts5Structure *pStruct
249316 ){
249317 Fts5Structure *pNew = 0;
249318 sqlite3_int64 nByte = sizeof(Fts5Structure);
249319 int nSeg = pStruct->nSegment;
249320 int i;
249321
249322 /* Figure out if this structure requires optimization. A structure does
249323 ** not require optimization if either:
@@ -249343,10 +249531,11 @@
249343 }
249344 assert( pStruct->aLevel[i].nMerge<=nThis );
249345 }
249346
249347 nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
 
249348 pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
249349
249350 if( pNew ){
249351 Fts5StructureLevel *pLvl;
249352 nByte = nSeg * sizeof(Fts5StructureSegment);
@@ -249919,12 +250108,16 @@
249919 /* The following are used for other full-token tokendata queries only. */
249920 int nIter;
249921 int nIterAlloc;
249922 Fts5PoslistReader *aPoslistReader;
249923 int *aPoslistToIter;
249924 Fts5Iter *apIter[1];
249925 };
 
 
 
 
249926
249927 /*
249928 ** The two input arrays - a1[] and a2[] - are in sorted order. This function
249929 ** merges the two arrays together and writes the result to output array
249930 ** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
@@ -249993,11 +250186,11 @@
249993 }
249994
249995 /*
249996 ** Sort the contents of the pT->aMap[] array.
249997 **
249998 ** The sorting algorithm requries a malloc(). If this fails, an error code
249999 ** is left in Fts5Index.rc before returning.
250000 */
250001 static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
250002 Fts5TokenDataMap *aTmp = 0;
250003 int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
@@ -250184,11 +250377,11 @@
250184 if( iIdx==0
250185 && p->pConfig->eDetail==FTS5_DETAIL_FULL
250186 && p->pConfig->bPrefixInsttoken
250187 ){
250188 s.pTokendata = &s2;
250189 s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
250190 }
250191
250192 if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
250193 s.xMerge = fts5MergeRowidLists;
250194 s.xAppend = fts5AppendRowid;
@@ -250312,19 +250505,21 @@
250312 ** The %_data table is completely empty when this function is called. This
250313 ** function populates it with the initial structure objects for each index,
250314 ** and the initial version of the "averages" record (a zero-byte blob).
250315 */
250316 static int sqlite3Fts5IndexReinit(Fts5Index *p){
250317 Fts5Structure s;
 
250318 fts5StructureInvalidate(p);
250319 fts5IndexDiscardData(p);
250320 memset(&s, 0, sizeof(Fts5Structure));
 
250321 if( p->pConfig->bContentlessDelete ){
250322 s.nOriginCntr = 1;
250323 }
250324 fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
250325 fts5StructureWrite(p, &s);
250326 return fts5IndexReturn(p);
250327 }
250328
250329 /*
250330 ** Open a new Fts5Index handle. If the bCreate argument is true, create
@@ -250528,11 +250723,11 @@
250528 Fts5TokenDataIter *pRet = pIn;
250529
250530 if( p->rc==SQLITE_OK ){
250531 if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
250532 int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
250533 int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
250534 Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
250535
250536 if( pNew==0 ){
250537 p->rc = SQLITE_NOMEM;
250538 }else{
@@ -251044,11 +251239,12 @@
251044
251045 memset(&ctx, 0, sizeof(ctx));
251046
251047 fts5BufferGrow(&p->rc, &token, nToken+1);
251048 assert( token.p!=0 || p->rc!=SQLITE_OK );
251049 ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
 
251050
251051 if( p->rc==SQLITE_OK ){
251052
251053 /* Fill in the token prefix to search for */
251054 token.p[0] = FTS5_MAIN_PREFIX;
@@ -251175,11 +251371,12 @@
251175 assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
251176 assert( pIter->pTokenDataIter || pIter->nSeg>0 );
251177 if( pIter->nSeg>0 ){
251178 /* This is a prefix term iterator. */
251179 if( pT==0 ){
251180 pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
 
251181 pIter->pTokenDataIter = pT;
251182 }
251183 if( pT ){
251184 fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
251185 fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
@@ -252209,11 +252406,11 @@
252209 }
252210 #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
252211
252212 #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
252213 static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
252214 int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
252215 fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
252216
252217 if( iSegid==0 ){
252218 if( iKey==FTS5_AVERAGES_ROWID ){
252219 sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
@@ -253170,13 +253367,15 @@
253170 struct Fts5Sorter {
253171 sqlite3_stmt *pStmt;
253172 i64 iRowid; /* Current rowid */
253173 const u8 *aPoslist; /* Position lists for current row */
253174 int nIdx; /* Number of entries in aIdx[] */
253175 int aIdx[1]; /* Offsets into aPoslist for current row */
253176 };
253177
 
 
253178
253179 /*
253180 ** Virtual-table cursor object.
253181 **
253182 ** iSpecial:
@@ -254050,11 +254249,11 @@
254050 int rc;
254051 const char *zRank = pCsr->zRank;
254052 const char *zRankArgs = pCsr->zRankArgs;
254053
254054 nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
254055 nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
254056 pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
254057 if( pSorter==0 ) return SQLITE_NOMEM;
254058 memset(pSorter, 0, (size_t)nByte);
254059 pSorter->nIdx = nPhrase;
254060
@@ -256576,11 +256775,11 @@
256576 int nArg, /* Number of args */
256577 sqlite3_value **apUnused /* Function arguments */
256578 ){
256579 assert( nArg==0 );
256580 UNUSED_PARAM2(nArg, apUnused);
256581 sqlite3_result_text(pCtx, "fts5: 2025-02-25 16:39:51 6f0b6d95db17e69ac7e46a39f52770291ac4cfe43eea09add224946a6e11f04e", -1, SQLITE_TRANSIENT);
256582 }
256583
256584 /*
256585 ** Implementation of fts5_locale(LOCALE, TEXT) function.
256586 **
256587
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** 18bda13e197e4b4ec7464b3e70012f71edc0 with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -465,11 +465,11 @@
465 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
466 ** [sqlite_version()] and [sqlite_source_id()].
467 */
468 #define SQLITE_VERSION "3.50.0"
469 #define SQLITE_VERSION_NUMBER 3050000
470 #define SQLITE_SOURCE_ID "2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185"
471
472 /*
473 ** CAPI3REF: Run-Time Library Version Numbers
474 ** KEYWORDS: sqlite3_version sqlite3_sourceid
475 **
@@ -5492,11 +5492,11 @@
5492 ** For all versions of SQLite up to and including 3.6.23.1, a call to
5493 ** [sqlite3_reset()] was required after sqlite3_step() returned anything
5494 ** other than [SQLITE_ROW] before any subsequent invocation of
5495 ** sqlite3_step(). Failure to reset the prepared statement using
5496 ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
5497 ** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
5498 ** sqlite3_step() began
5499 ** calling [sqlite3_reset()] automatically in this circumstance rather
5500 ** than returning [SQLITE_MISUSE]. This is not considered a compatibility
5501 ** break because any application that ever receives an SQLITE_MISUSE error
5502 ** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
@@ -7388,10 +7388,12 @@
7388 ** ^Any callback set by a previous call to this function
7389 ** for the same database connection is overridden.
7390 **
7391 ** ^The second argument is a pointer to the function to invoke when a
7392 ** row is updated, inserted or deleted in a rowid table.
7393 ** ^The update hook is disabled by invoking sqlite3_update_hook()
7394 ** with a NULL pointer as the second parameter.
7395 ** ^The first argument to the callback is a copy of the third argument
7396 ** to sqlite3_update_hook().
7397 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
7398 ** or [SQLITE_UPDATE], depending on the operation that caused the callback
7399 ** to be invoked.
@@ -15170,11 +15172,21 @@
15172 /*
15173 ** GCC does not define the offsetof() macro so we'll have to do it
15174 ** ourselves.
15175 */
15176 #ifndef offsetof
15177 #define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
15178 #endif
15179
15180 /*
15181 ** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
15182 ** to avoid complaints from -fsanitize=strict-bounds.
15183 */
15184 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
15185 # define FLEXARRAY
15186 #else
15187 # define FLEXARRAY 1
15188 #endif
15189
15190 /*
15191 ** Macros to compute minimum and maximum of two numbers.
15192 */
@@ -17405,12 +17417,12 @@
17417 SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
17418 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
17419 SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
17420 #endif
17421
17422 /* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra
17423 ** comments on each VDBE opcode.
17424 **
17425 ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
17426 ** comments in VDBE programs that show key decision points in the code
17427 ** generator.
17428 */
@@ -18945,12 +18957,16 @@
18957 u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
18958 Trigger *apTrigger[2];/* Triggers for aAction[] actions */
18959 struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
18960 int iFrom; /* Index of column in pFrom */
18961 char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
18962 } aCol[FLEXARRAY]; /* One entry for each of nCol columns */
18963 };
18964
18965 /* The size (in bytes) of an FKey object holding N columns. The answer
18966 ** does NOT include space to hold the zTo name. */
18967 #define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap))
18968
18969 /*
18970 ** SQLite supports many different ways to resolve a constraint
18971 ** error. ROLLBACK processing means that a constraint violation
18972 ** causes the operation in process to fail and for the current transaction
@@ -19009,13 +19025,16 @@
19025 u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
19026 u16 nKeyField; /* Number of key columns in the index */
19027 u16 nAllField; /* Total columns, including key plus others */
19028 sqlite3 *db; /* The database connection */
19029 u8 *aSortFlags; /* Sort order for each column. */
19030 CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
19031 };
19032
19033 /* The size (in bytes) of a KeyInfo object with up to N fields */
19034 #define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
19035
19036 /*
19037 ** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
19038 */
19039 #define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
19040 #define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
@@ -19584,12 +19603,17 @@
19603 u16 iAlias; /* Index into Parse.aAlias[] for zName */
19604 } x;
19605 int iConstExprReg; /* Register in which Expr value is cached. Used only
19606 ** by Parse.pConstExpr */
19607 } u;
19608 } a[FLEXARRAY]; /* One slot for each expression in the list */
19609 };
19610
19611 /* The size (in bytes) of an ExprList object that is big enough to hold
19612 ** as many as N expressions. */
19613 #define SZ_EXPRLIST(N) \
19614 (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item))
19615
19616 /*
19617 ** Allowed values for Expr.a.eEName
19618 */
19619 #define ENAME_NAME 0 /* The AS clause of a result set */
@@ -19614,13 +19638,16 @@
19638 */
19639 struct IdList {
19640 int nId; /* Number of identifiers on the list */
19641 struct IdList_item {
19642 char *zName; /* Name of the identifier */
19643 } a[FLEXARRAY];
19644 };
19645
19646 /* The size (in bytes) of an IdList object that can hold up to N IDs. */
19647 #define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item))
19648
19649 /*
19650 ** Allowed values for IdList.eType, which determines which value of the a.u4
19651 ** is valid.
19652 */
19653 #define EU4_NONE 0 /* Does not use IdList.a.u4 */
@@ -19736,14 +19763,22 @@
19763 ** is used to hold the FROM clause of a SELECT statement. SrcList also
19764 ** represents the target tables for DELETE, INSERT, and UPDATE statements.
19765 **
19766 */
19767 struct SrcList {
19768 int nSrc; /* Number of tables or subqueries in the FROM clause */
19769 u32 nAlloc; /* Number of entries allocated in a[] below */
19770 SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
19771 };
19772
19773 /* Size (in bytes) of a SrcList object that can hold as many as N
19774 ** SrcItem objects. */
19775 #define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
19776
19777 /* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
19778 ** special case of SZ_SRCITEM(1) that comes up often. */
19779 #define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
19780
19781 /*
19782 ** Permitted values of the SrcList.a.jointype field
19783 */
19784 #define JT_INNER 0x01 /* Any kind of inner or cross join */
@@ -20804,12 +20839,16 @@
20839 */
20840 struct With {
20841 int nCte; /* Number of CTEs in the WITH clause */
20842 int bView; /* Belongs to the outermost Select of a view */
20843 With *pOuter; /* Containing WITH clause, or NULL */
20844 Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */
20845 };
20846
20847 /* The size (in bytes) of a With object that can hold as many
20848 ** as N different CTEs. */
20849 #define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte))
20850
20851 /*
20852 ** The Cte object is not guaranteed to persist for the entire duration
20853 ** of code generation. (The query flattener or other parser tree
20854 ** edits might delete it.) The following object records information
@@ -20835,12 +20874,16 @@
20874 */
20875 struct DbClientData {
20876 DbClientData *pNext; /* Next in a linked list */
20877 void *pData; /* The data */
20878 void (*xDestructor)(void*); /* Destructor. Might be NULL */
20879 char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
20880 };
20881
20882 /* The size (in bytes) of a DbClientData object that can has a name
20883 ** that is N bytes long, including the zero-terminator. */
20884 #define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
20885
20886 #ifdef SQLITE_DEBUG
20887 /*
20888 ** An instance of the TreeView object is used for printing the content of
20889 ** data structures on sqlite3DebugPrintf() using a tree-like view.
@@ -22673,10 +22716,13 @@
22716 "EXTRA_IFNULLROW",
22717 #endif
22718 #ifdef SQLITE_EXTRA_INIT
22719 "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
22720 #endif
22721 #ifdef SQLITE_EXTRA_INIT_MUTEXED
22722 "EXTRA_INIT_MUTEXED=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT_MUTEXED),
22723 #endif
22724 #ifdef SQLITE_EXTRA_SHUTDOWN
22725 "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
22726 #endif
22727 #ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
22728 "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
@@ -23657,16 +23703,23 @@
23703 #ifdef SQLITE_ENABLE_COLUMN_USED_MASK
23704 u64 maskUsed; /* Mask of columns used by this cursor */
23705 #endif
23706 VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
23707
23708 /* Space is allocated for aType to hold at least 2*nField+1 entries:
23709 ** nField slots for aType[] and nField+1 array slots for aOffset[] */
23710 u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
 
23711 };
23712
23713 /*
23714 ** The size (in bytes) of a VdbeCursor object that has an nField value of N
23715 ** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
23716 ** of 8.
23717 */
23718 #define SZ_VDBECURSOR(N) \
23719 (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
23720
23721 /* Return true if P is a null-only cursor
23722 */
23723 #define IsNullCursor(P) \
23724 ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
23725
@@ -23919,13 +23972,20 @@
23972 int iOp; /* Instruction number of OP_Function */
23973 int isError; /* Error code returned by the function. */
23974 u8 enc; /* Encoding to use for results */
23975 u8 skipFlag; /* Skip accumulator loading if true */
23976 u16 argc; /* Number of arguments */
23977 sqlite3_value *argv[FLEXARRAY]; /* Argument set */
23978 };
23979
23980 /*
23981 ** The size (in bytes) of an sqlite3_context object that holds N
23982 ** argv[] arguments.
23983 */
23984 #define SZ_CONTEXT(N) \
23985 (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*))
23986
23987
23988 /* The ScanStatus object holds a single value for the
23989 ** sqlite3_stmt_scanstatus() interface.
23990 **
23991 ** aAddrRange[]:
@@ -24055,11 +24115,11 @@
24115 struct PreUpdate {
24116 Vdbe *v;
24117 VdbeCursor *pCsr; /* Cursor to read old values from */
24118 int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
24119 u8 *aRecord; /* old.* database record */
24120 KeyInfo *pKeyinfo; /* Key information */
24121 UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
24122 UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
24123 int iNewReg; /* Register for new.* values */
24124 int iBlobWrite; /* Value returned by preupdate_blobwrite() */
24125 i64 iKey1; /* First key value passed to hook */
@@ -24067,10 +24127,11 @@
24127 Mem oldipk; /* Memory cell holding "old" IPK value */
24128 Mem *aNew; /* Array of new.* values */
24129 Table *pTab; /* Schema object being updated */
24130 Index *pPk; /* PK index if pTab is WITHOUT ROWID */
24131 sqlite3_value **apDflt; /* Array of default values, if required */
24132 u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */
24133 };
24134
24135 /*
24136 ** An instance of this object is used to pass an vector of values into
24137 ** OP_VFilter, the xFilter method of a virtual table. The vector is the
@@ -26000,11 +26061,11 @@
26061 ** Return the number of days after the most recent Sunday.
26062 **
26063 ** In other words, return the day of the week according
26064 ** to this code:
26065 **
26066 ** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday
26067 */
26068 static int daysAfterSunday(DateTime *pDate){
26069 assert( pDate->validJD );
26070 return (int)((pDate->iJD+129600000)/86400000) % 7;
26071 }
@@ -32378,11 +32439,11 @@
32439 u32 nBack = 0;
32440 u32 nCtrl = 0;
32441 for(k=0; k<i; k++){
32442 if( escarg[k]=='\\' ){
32443 nBack++;
32444 }else if( ((u8*)escarg)[k]<=0x1f ){
32445 nCtrl++;
32446 }
32447 }
32448 if( nCtrl || xtype==etESCAPE_q ){
32449 n += nBack + 5*nCtrl;
@@ -32416,11 +32477,11 @@
32477 bufpt[j++] = ch = escarg[i];
32478 if( ch==q ){
32479 bufpt[j++] = ch;
32480 }else if( ch=='\\' ){
32481 bufpt[j++] = '\\';
32482 }else if( ((unsigned char)ch)<=0x1f ){
32483 bufpt[j-1] = '\\';
32484 bufpt[j++] = 'u';
32485 bufpt[j++] = '0';
32486 bufpt[j++] = '0';
32487 bufpt[j++] = ch>=0x10 ? '1' : '0';
@@ -37067,11 +37128,11 @@
37128 return 0;
37129 #endif
37130 }
37131
37132 /*
37133 ** Compute the absolute value of a 32-bit signed integer, if possible. Or
37134 ** if the integer has a value of -2147483648, return +2147483647
37135 */
37136 SQLITE_PRIVATE int sqlite3AbsInt32(int x){
37137 if( x>=0 ) return x;
37138 if( x==(int)0x80000000 ) return 0x7fffffff;
@@ -45614,11 +45675,11 @@
45675 sp.tv_sec = microseconds / 1000000;
45676 sp.tv_nsec = (microseconds % 1000000) * 1000;
45677
45678 /* Almost all modern unix systems support nanosleep(). But if you are
45679 ** compiling for one of the rare exceptions, you can use
45680 ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if
45681 ** usleep() is available) in order to bypass the use of nanosleep() */
45682 nanosleep(&sp, NULL);
45683
45684 UNUSED_PARAMETER(NotUsed);
45685 return microseconds;
@@ -56047,14 +56108,10 @@
56108 void *pStart, *pEnd; /* Bounds of global page cache memory */
56109 /* Above requires no mutex. Use mutex below for variable that follow. */
56110 sqlite3_mutex *mutex; /* Mutex for accessing the following: */
56111 PgFreeslot *pFree; /* Free page blocks */
56112 int nFreeSlot; /* Number of unused pcache slots */
 
 
 
 
56113 int bUnderPressure; /* True if low on PAGECACHE memory */
56114 } pcache1_g;
56115
56116 /*
56117 ** All code in this file should access the global structure above via the
@@ -56098,11 +56155,11 @@
56155 pcache1.szSlot = sz;
56156 pcache1.nSlot = pcache1.nFreeSlot = n;
56157 pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
56158 pcache1.pStart = pBuf;
56159 pcache1.pFree = 0;
56160 AtomicStore(&pcache1.bUnderPressure,0);
56161 while( n-- ){
56162 p = (PgFreeslot*)pBuf;
56163 p->pNext = pcache1.pFree;
56164 pcache1.pFree = p;
56165 pBuf = (void*)&((char*)pBuf)[sz];
@@ -56166,11 +56223,11 @@
56223 sqlite3_mutex_enter(pcache1.mutex);
56224 p = (PgHdr1 *)pcache1.pFree;
56225 if( p ){
56226 pcache1.pFree = pcache1.pFree->pNext;
56227 pcache1.nFreeSlot--;
56228 AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
56229 assert( pcache1.nFreeSlot>=0 );
56230 sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
56231 sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
56232 }
56233 sqlite3_mutex_leave(pcache1.mutex);
@@ -56205,11 +56262,11 @@
56262 sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
56263 pSlot = (PgFreeslot*)p;
56264 pSlot->pNext = pcache1.pFree;
56265 pcache1.pFree = pSlot;
56266 pcache1.nFreeSlot++;
56267 AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
56268 assert( pcache1.nFreeSlot<=pcache1.nSlot );
56269 sqlite3_mutex_leave(pcache1.mutex);
56270 }else{
56271 assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
56272 sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
@@ -56336,11 +56393,11 @@
56393 ** allocating a new page cache entry in order to avoid stressing
56394 ** the heap even further.
56395 */
56396 static int pcache1UnderMemoryPressure(PCache1 *pCache){
56397 if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
56398 return AtomicLoad(&pcache1.bUnderPressure);
56399 }else{
56400 return sqlite3HeapNearlyFull();
56401 }
56402 }
56403
@@ -66177,12 +66234,16 @@
66234 int iNext; /* Next slot in aIndex[] not yet returned */
66235 ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
66236 u32 *aPgno; /* Array of page numbers. */
66237 int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
66238 int iZero; /* Frame number associated with aPgno[0] */
66239 } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */
66240 };
66241
66242 /* Size (in bytes) of a WalIterator object suitable for N or fewer segments */
66243 #define SZ_WALITERATOR(N) \
66244 (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment))
66245
66246 /*
66247 ** Define the parameters of the hash tables in the wal-index file. There
66248 ** is a hash-table following every HASHTABLE_NPAGE page numbers in the
66249 ** wal-index.
@@ -67540,12 +67601,11 @@
67601 assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
67602 iLast = pWal->hdr.mxFrame;
67603
67604 /* Allocate space for the WalIterator object. */
67605 nSegment = walFramePage(iLast) + 1;
67606 nByte = SZ_WALITERATOR(nSegment)
 
67607 + iLast*sizeof(ht_slot);
67608 p = (WalIterator *)sqlite3_malloc64(nByte
67609 + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
67610 );
67611 if( !p ){
@@ -86029,16 +86089,14 @@
86089 int nArg, /* Number of argument */
86090 const FuncDef *pFunc, /* The function to be invoked */
86091 int eCallCtx /* Calling context */
86092 ){
86093 Vdbe *v = pParse->pVdbe;
 
86094 int addr;
86095 sqlite3_context *pCtx;
86096 assert( v );
86097 pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg));
 
86098 if( pCtx==0 ){
86099 assert( pParse->db->mallocFailed );
86100 freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
86101 return 0;
86102 }
@@ -91110,25 +91168,26 @@
91168
91169 preupdate.v = v;
91170 preupdate.pCsr = pCsr;
91171 preupdate.op = op;
91172 preupdate.iNewReg = iReg;
91173 preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace;
91174 preupdate.pKeyinfo->db = db;
91175 preupdate.pKeyinfo->enc = ENC(db);
91176 preupdate.pKeyinfo->nKeyField = pTab->nCol;
91177 preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
91178 preupdate.iKey1 = iKey1;
91179 preupdate.iKey2 = iKey2;
91180 preupdate.pTab = pTab;
91181 preupdate.iBlobWrite = iBlobWrite;
91182
91183 db->pPreUpdate = &preupdate;
91184 db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
91185 db->pPreUpdate = 0;
91186 sqlite3DbFree(db, preupdate.aRecord);
91187 vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked);
91188 vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked);
91189 sqlite3VdbeMemRelease(&preupdate.oldipk);
91190 if( preupdate.aNew ){
91191 int i;
91192 for(i=0; i<pCsr->nField; i++){
91193 sqlite3VdbeMemRelease(&preupdate.aNew[i]);
@@ -93363,11 +93422,11 @@
93422 nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
93423 aRec = sqlite3DbMallocRaw(db, nRec);
93424 if( !aRec ) goto preupdate_old_out;
93425 rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
93426 if( rc==SQLITE_OK ){
93427 p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec);
93428 if( !p->pUnpacked ) rc = SQLITE_NOMEM;
93429 }
93430 if( rc!=SQLITE_OK ){
93431 sqlite3DbFree(db, aRec);
93432 goto preupdate_old_out;
@@ -93428,11 +93487,11 @@
93487 #ifdef SQLITE_ENABLE_API_ARMOR
93488 p = db!=0 ? db->pPreUpdate : 0;
93489 #else
93490 p = db->pPreUpdate;
93491 #endif
93492 return (p ? p->pKeyinfo->nKeyField : 0);
93493 }
93494 #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
93495
93496 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
93497 /*
@@ -93511,11 +93570,11 @@
93570 UnpackedRecord *pUnpack = p->pNewUnpacked;
93571 if( !pUnpack ){
93572 Mem *pData = &p->v->aMem[p->iNewReg];
93573 rc = ExpandBlob(pData);
93574 if( rc!=SQLITE_OK ) goto preupdate_new_out;
93575 pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z);
93576 if( !pUnpack ){
93577 rc = SQLITE_NOMEM;
93578 goto preupdate_new_out;
93579 }
93580 p->pNewUnpacked = pUnpack;
@@ -94305,13 +94364,13 @@
94364 */
94365 Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
94366
94367 i64 nByte;
94368 VdbeCursor *pCx = 0;
94369 nByte = SZ_VDBECURSOR(nField);
94370 assert( ROUND8(nByte)==nByte );
94371 if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize();
94372
94373 assert( iCur>=0 && iCur<p->nCursor );
94374 if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
94375 sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
94376 p->apCsr[iCur] = 0;
@@ -94340,12 +94399,12 @@
94399 memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
94400 pCx->eCurType = eCurType;
94401 pCx->nField = nField;
94402 pCx->aOffset = &pCx->aType[nField];
94403 if( eCurType==CURTYPE_BTREE ){
94404 assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) );
94405 pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)];
94406 sqlite3BtreeCursorZero(pCx->uc.pCursor);
94407 }
94408 return pCx;
94409 }
94410
@@ -100083,11 +100142,11 @@
100142 pCrsr = pC->uc.pCursor;
100143
100144 /* The OP_RowData opcodes always follow OP_NotExists or
100145 ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
100146 ** that might invalidate the cursor.
100147 ** If this were not the case, one of the following assert()s
100148 ** would fail. Should this ever change (because of changes in the code
100149 ** generator) then the fix would be to insert a call to
100150 ** sqlite3VdbeCursorMoveto().
100151 */
100152 assert( pC->deferredMoveto==0 );
@@ -101732,11 +101791,11 @@
101791 ** cell in which to store the accumulation. Be careful that the memory
101792 ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
101793 **
101794 ** Note: We could avoid this by using a regular memory cell from aMem[] for
101795 ** the accumulator, instead of allocating one here. */
101796 nAlloc = ROUND8P( SZ_CONTEXT(n) );
101797 pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
101798 if( pCtx==0 ) goto no_mem;
101799 pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
101800 assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
101801
@@ -103390,10 +103449,11 @@
103449 int iCol; /* Index of zColumn in row-record */
103450 int rc = SQLITE_OK;
103451 char *zErr = 0;
103452 Table *pTab;
103453 Incrblob *pBlob = 0;
103454 int iDb;
103455 Parse sParse;
103456
103457 #ifdef SQLITE_ENABLE_API_ARMOR
103458 if( ppBlob==0 ){
103459 return SQLITE_MISUSE_BKPT;
@@ -103435,11 +103495,14 @@
103495 if( pTab && IsView(pTab) ){
103496 pTab = 0;
103497 sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
103498 }
103499 #endif
103500 if( pTab==0
103501 || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 &&
103502 sqlite3OpenTempDatabase(&sParse))
103503 ){
103504 if( sParse.zErrMsg ){
103505 sqlite3DbFree(db, zErr);
103506 zErr = sParse.zErrMsg;
103507 sParse.zErrMsg = 0;
103508 }
@@ -103446,11 +103509,11 @@
103509 rc = SQLITE_ERROR;
103510 sqlite3BtreeLeaveAll(db);
103511 goto blob_open_out;
103512 }
103513 pBlob->pTab = pTab;
103514 pBlob->zDb = db->aDb[iDb].zDbSName;
103515
103516 /* Now search pTab for the exact column. */
103517 iCol = sqlite3ColumnIndex(pTab, zColumn);
103518 if( iCol<0 ){
103519 sqlite3DbFree(db, zErr);
@@ -103530,11 +103593,10 @@
103593 {OP_Column, 0, 0, 1}, /* 3 */
103594 {OP_ResultRow, 1, 0, 0}, /* 4 */
103595 {OP_Halt, 0, 0, 0}, /* 5 */
103596 };
103597 Vdbe *v = (Vdbe *)pBlob->pStmt;
 
103598 VdbeOp *aOp;
103599
103600 sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
103601 pTab->pSchema->schema_cookie,
103602 pTab->pSchema->iGeneration);
@@ -104108,12 +104170,15 @@
104170 u8 bUsePMA; /* True if one or more PMAs created */
104171 u8 bUseThreads; /* True to use background threads */
104172 u8 iPrev; /* Previous thread used to flush PMA */
104173 u8 nTask; /* Size of aTask[] array */
104174 u8 typeMask;
104175 SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */
104176 };
104177
104178 /* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */
104179 #define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask))
104180
104181 #define SORTER_TYPE_INTEGER 0x01
104182 #define SORTER_TYPE_TEXT 0x02
104183
104184 /*
@@ -104742,12 +104807,12 @@
104807 assert( pCsr->pKeyInfo );
104808 assert( !pCsr->isEphemeral );
104809 assert( pCsr->eCurType==CURTYPE_SORTER );
104810 assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
104811 < 0x7fffffff );
104812 szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
104813 sz = SZ_VDBESORTER(nWorker+1);
104814
104815 pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
104816 pCsr->uc.pSorter = pSorter;
104817 if( pSorter==0 ){
104818 rc = SQLITE_NOMEM_BKPT;
@@ -105207,10 +105272,14 @@
105272 }
105273
105274 p->u.pNext = 0;
105275 for(i=0; aSlot[i]; i++){
105276 p = vdbeSorterMerge(pTask, p, aSlot[i]);
105277 /* ,--Each aSlot[] holds twice as much as the previous. So we cannot use
105278 ** | up all 64 aSlots[] with only a 64-bit address space.
105279 ** v */
105280 assert( i<ArraySize(aSlot) );
105281 aSlot[i] = 0;
105282 }
105283 aSlot[i] = p;
105284 p = pNext;
105285 }
@@ -109981,32 +110050,34 @@
110050 Table *pTab, /* The table being referenced, or NULL */
110051 int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
110052 Expr *pExpr, /* Expression to resolve. May be NULL. */
110053 ExprList *pList /* Expression list to resolve. May be NULL. */
110054 ){
110055 SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */
110056 NameContext sNC; /* Name context for pParse->pNewTable */
110057 int rc;
110058 u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */
110059
110060 assert( type==0 || pTab!=0 );
110061 assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
110062 || type==NC_GenCol || pTab==0 );
110063 memset(&sNC, 0, sizeof(sNC));
110064 pSrc = (SrcList*)srcSpace;
110065 memset(pSrc, 0, SZ_SRCLIST_1);
110066 if( pTab ){
110067 pSrc->nSrc = 1;
110068 pSrc->a[0].zName = pTab->zName;
110069 pSrc->a[0].pSTab = pTab;
110070 pSrc->a[0].iCursor = -1;
110071 if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
110072 /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
110073 ** schema elements */
110074 type |= NC_FromDDL;
110075 }
110076 }
110077 sNC.pParse = pParse;
110078 sNC.pSrcList = pSrc;
110079 sNC.ncFlags = type | NC_IsDDL;
110080 if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
110081 if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
110082 return rc;
110083 }
@@ -111751,11 +111822,11 @@
111822 */
111823 #ifndef SQLITE_OMIT_CTE
111824 SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){
111825 With *pRet = 0;
111826 if( p ){
111827 sqlite3_int64 nByte = SZ_WITH(p->nCte);
111828 pRet = sqlite3DbMallocZero(db, nByte);
111829 if( pRet ){
111830 int i;
111831 pRet->nCte = p->nCte;
111832 for(i=0; i<p->nCte; i++){
@@ -111878,15 +111949,13 @@
111949 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
111950 || !defined(SQLITE_OMIT_SUBQUERY)
111951 SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
111952 SrcList *pNew;
111953 int i;
 
111954 assert( db!=0 );
111955 if( p==0 ) return 0;
111956 pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) );
 
111957 if( pNew==0 ) return 0;
111958 pNew->nSrc = pNew->nAlloc = p->nSrc;
111959 for(i=0; i<p->nSrc; i++){
111960 SrcItem *pNewItem = &pNew->a[i];
111961 const SrcItem *pOldItem = &p->a[i];
@@ -111944,11 +112013,11 @@
112013 SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
112014 IdList *pNew;
112015 int i;
112016 assert( db!=0 );
112017 if( p==0 ) return 0;
112018 pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId));
112019 if( pNew==0 ) return 0;
112020 pNew->nId = p->nId;
112021 for(i=0; i<p->nId; i++){
112022 struct IdList_item *pNewItem = &pNew->a[i];
112023 const struct IdList_item *pOldItem = &p->a[i];
@@ -112028,11 +112097,11 @@
112097 Expr *pExpr /* Expression to be appended. Might be NULL */
112098 ){
112099 struct ExprList_item *pItem;
112100 ExprList *pList;
112101
112102 pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4));
112103 if( pList==0 ){
112104 sqlite3ExprDelete(db, pExpr);
112105 return 0;
112106 }
112107 pList->nAlloc = 4;
@@ -112048,12 +112117,11 @@
112117 Expr *pExpr /* Expression to be appended. Might be NULL */
112118 ){
112119 struct ExprList_item *pItem;
112120 ExprList *pNew;
112121 pList->nAlloc *= 2;
112122 pNew = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc));
 
112123 if( pNew==0 ){
112124 sqlite3ExprListDelete(db, pList);
112125 sqlite3ExprDelete(db, pExpr);
112126 return 0;
112127 }else{
@@ -114685,11 +114753,11 @@
114753 return -1; /* Not found */
114754 }
114755
114756
114757 /*
114758 ** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This
114759 ** function checks the Parse.pIdxPartExpr list to see if this column
114760 ** can be replaced with a constant value. If so, it generates code to
114761 ** put the constant value in a register (ideally, but not necessarily,
114762 ** register iTarget) and returns the register number.
114763 **
@@ -118531,10 +118599,11 @@
118599 sqlite3 *db, /* Database handle */
118600 const char *zSql, /* SQL to parse */
118601 int bTemp /* True if SQL is from temp schema */
118602 ){
118603 int rc;
118604 u64 flags;
118605
118606 sqlite3ParseObjectInit(p, db);
118607 if( zSql==0 ){
118608 return SQLITE_NOMEM;
118609 }
@@ -118549,11 +118618,15 @@
118618 db->init.iDb = (u8)iDb;
118619 }
118620 p->eParseMode = PARSE_MODE_RENAME;
118621 p->db = db;
118622 p->nQueryLoop = 1;
118623 flags = db->flags;
118624 testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );
118625 db->flags |= SQLITE_Comments;
118626 rc = sqlite3RunParser(p, zSql);
118627 db->flags = flags;
118628 if( db->mallocFailed ) rc = SQLITE_NOMEM;
118629 if( rc==SQLITE_OK
118630 && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
118631 ){
118632 rc = SQLITE_CORRUPT_BKPT;
@@ -119445,11 +119518,11 @@
119518 int rc;
119519 Parse sParse;
119520 u64 flags = db->flags;
119521 if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
119522 rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
119523 db->flags = flags;
119524 if( rc==SQLITE_OK ){
119525 if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
119526 NameContext sNC;
119527 memset(&sNC, 0, sizeof(sNC));
119528 sNC.pParse = &sParse;
@@ -126268,11 +126341,11 @@
126341 "columns in the referenced table");
126342 goto fk_end;
126343 }else{
126344 nCol = pFromCol->nExpr;
126345 }
126346 nByte = SZ_FKEY(nCol) + pTo->n + 1;
126347 if( pToCol ){
126348 for(i=0; i<pToCol->nExpr; i++){
126349 nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
126350 }
126351 }
@@ -127327,16 +127400,15 @@
127400 */
127401 SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
127402 sqlite3 *db = pParse->db;
127403 int i;
127404 if( pList==0 ){
127405 pList = sqlite3DbMallocZero(db, SZ_IDLIST(1));
127406 if( pList==0 ) return 0;
127407 }else{
127408 IdList *pNew;
127409 pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1));
 
127410 if( pNew==0 ){
127411 sqlite3IdListDelete(db, pList);
127412 return 0;
127413 }
127414 pList = pNew;
@@ -127431,12 +127503,11 @@
127503 sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
127504 SQLITE_MAX_SRCLIST);
127505 return 0;
127506 }
127507 if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
127508 pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc));
 
127509 if( pNew==0 ){
127510 assert( db->mallocFailed );
127511 return 0;
127512 }
127513 pSrc = pNew;
@@ -127507,11 +127578,11 @@
127578 assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
127579 assert( pParse!=0 );
127580 assert( pParse->db!=0 );
127581 db = pParse->db;
127582 if( pList==0 ){
127583 pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1));
127584 if( pList==0 ) return 0;
127585 pList->nAlloc = 1;
127586 pList->nSrc = 1;
127587 memset(&pList->a[0], 0, sizeof(pList->a[0]));
127588 pList->a[0].iCursor = -1;
@@ -128393,14 +128464,13 @@
128464 }
128465 }
128466 }
128467
128468 if( pWith ){
128469 pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1));
 
128470 }else{
128471 pNew = sqlite3DbMallocZero(db, SZ_WITH(1));
128472 }
128473 assert( (pNew!=0 && zName!=0) || db->mallocFailed );
128474
128475 if( db->mallocFailed ){
128476 sqlite3CteDelete(db, pCte);
@@ -131933,11 +132003,11 @@
132003 **
132004 ** The SUM() function follows the (broken) SQL standard which means
132005 ** that it returns NULL if it sums over no inputs. TOTAL returns
132006 ** 0.0 in that case. In addition, TOTAL always returns a float where
132007 ** SUM might return an integer if it never encounters a floating point
132008 ** value. TOTAL never fails, but SUM might throw an exception if
132009 ** it overflows an integer.
132010 */
132011 static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
132012 SumCtx *p;
132013 int type;
@@ -139748,52 +139818,52 @@
139818 /* 11 */ "notnull",
139819 /* 12 */ "dflt_value",
139820 /* 13 */ "pk",
139821 /* 14 */ "hidden",
139822 /* table_info reuses 8 */
139823 /* 15 */ "name", /* Used by: function_list */
139824 /* 16 */ "builtin",
139825 /* 17 */ "type",
139826 /* 18 */ "enc",
139827 /* 19 */ "narg",
139828 /* 20 */ "flags",
139829 /* 21 */ "schema", /* Used by: table_list */
139830 /* 22 */ "name",
139831 /* 23 */ "type",
139832 /* 24 */ "ncol",
139833 /* 25 */ "wr",
139834 /* 26 */ "strict",
139835 /* 27 */ "seqno", /* Used by: index_xinfo */
139836 /* 28 */ "cid",
139837 /* 29 */ "name",
139838 /* 30 */ "desc",
139839 /* 31 */ "coll",
139840 /* 32 */ "key",
139841 /* 33 */ "seq", /* Used by: index_list */
139842 /* 34 */ "name",
139843 /* 35 */ "unique",
139844 /* 36 */ "origin",
139845 /* 37 */ "partial",
139846 /* 38 */ "tbl", /* Used by: stats */
139847 /* 39 */ "idx",
139848 /* 40 */ "wdth",
139849 /* 41 */ "hght",
139850 /* 42 */ "flgs",
139851 /* 43 */ "table", /* Used by: foreign_key_check */
139852 /* 44 */ "rowid",
139853 /* 45 */ "parent",
139854 /* 46 */ "fkid",
139855 /* 47 */ "busy", /* Used by: wal_checkpoint */
139856 /* 48 */ "log",
139857 /* 49 */ "checkpointed",
139858 /* 50 */ "seq", /* Used by: database_list */
139859 /* 51 */ "name",
139860 /* 52 */ "file",
139861 /* index_info reuses 27 */
 
139862 /* 53 */ "database", /* Used by: lock_status */
139863 /* 54 */ "status",
139864 /* collation_list reuses 33 */
139865 /* 55 */ "cache_size", /* Used by: default_cache_size */
139866 /* module_list pragma_list reuses 9 */
139867 /* 56 */ "timeout", /* Used by: busy_timeout */
139868 };
139869
@@ -139882,11 +139952,11 @@
139952 #endif
139953 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139954 {/* zName: */ "collation_list",
139955 /* ePragTyp: */ PragTyp_COLLATION_LIST,
139956 /* ePragFlg: */ PragFlg_Result0,
139957 /* ColNames: */ 33, 2,
139958 /* iArg: */ 0 },
139959 #endif
139960 #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
139961 {/* zName: */ "compile_options",
139962 /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
@@ -139917,11 +139987,11 @@
139987 #endif
139988 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
139989 {/* zName: */ "database_list",
139990 /* ePragTyp: */ PragTyp_DATABASE_LIST,
139991 /* ePragFlg: */ PragFlg_Result0,
139992 /* ColNames: */ 50, 3,
139993 /* iArg: */ 0 },
139994 #endif
139995 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
139996 {/* zName: */ "default_cache_size",
139997 /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
@@ -139997,11 +140067,11 @@
140067 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
140068 #if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
140069 {/* zName: */ "function_list",
140070 /* ePragTyp: */ PragTyp_FUNCTION_LIST,
140071 /* ePragFlg: */ PragFlg_Result0,
140072 /* ColNames: */ 15, 6,
140073 /* iArg: */ 0 },
140074 #endif
140075 #endif
140076 {/* zName: */ "hard_heap_limit",
140077 /* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT,
@@ -140026,21 +140096,21 @@
140096 #endif
140097 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
140098 {/* zName: */ "index_info",
140099 /* ePragTyp: */ PragTyp_INDEX_INFO,
140100 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140101 /* ColNames: */ 27, 3,
140102 /* iArg: */ 0 },
140103 {/* zName: */ "index_list",
140104 /* ePragTyp: */ PragTyp_INDEX_LIST,
140105 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140106 /* ColNames: */ 33, 5,
140107 /* iArg: */ 0 },
140108 {/* zName: */ "index_xinfo",
140109 /* ePragTyp: */ PragTyp_INDEX_INFO,
140110 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140111 /* ColNames: */ 27, 6,
140112 /* iArg: */ 1 },
140113 #endif
140114 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
140115 {/* zName: */ "integrity_check",
140116 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
@@ -140215,11 +140285,11 @@
140285 #endif
140286 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
140287 {/* zName: */ "stats",
140288 /* ePragTyp: */ PragTyp_STATS,
140289 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
140290 /* ColNames: */ 38, 5,
140291 /* iArg: */ 0 },
140292 #endif
140293 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
140294 {/* zName: */ "synchronous",
140295 /* ePragTyp: */ PragTyp_SYNCHRONOUS,
@@ -140234,11 +140304,11 @@
140304 /* ColNames: */ 8, 6,
140305 /* iArg: */ 0 },
140306 {/* zName: */ "table_list",
140307 /* ePragTyp: */ PragTyp_TABLE_LIST,
140308 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
140309 /* ColNames: */ 21, 6,
140310 /* iArg: */ 0 },
140311 {/* zName: */ "table_xinfo",
140312 /* ePragTyp: */ PragTyp_TABLE_INFO,
140313 /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
140314 /* ColNames: */ 8, 7,
@@ -140311,11 +140381,11 @@
140381 /* ColNames: */ 0, 0,
140382 /* iArg: */ 0 },
140383 {/* zName: */ "wal_checkpoint",
140384 /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
140385 /* ePragFlg: */ PragFlg_NeedSchema,
140386 /* ColNames: */ 47, 3,
140387 /* iArg: */ 0 },
140388 #endif
140389 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
140390 {/* zName: */ "writable_schema",
140391 /* ePragTyp: */ PragTyp_FLAG,
@@ -140333,11 +140403,11 @@
140403 ** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands
140404 ** will be run with an analysis_limit set to the lessor of the value of
140405 ** the following macro or to the actual analysis_limit if it is non-zero,
140406 ** in order to prevent PRAGMA optimize from running for too long.
140407 **
140408 ** The value of 2000 is chosen empirically so that the worst-case run-time
140409 ** for PRAGMA optimize does not exceed 100 milliseconds against a variety
140410 ** of test databases on a RaspberryPI-4 compiled using -Os and without
140411 ** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
140412 ** this paragraph, "worst-case" means that ANALYZE ends up being
140413 ** run on every table in the database. The worst case typically only
@@ -144622,11 +144692,11 @@
144692 pNew->iOffset = 0;
144693 pNew->selId = ++pParse->nSelect;
144694 pNew->addrOpenEphm[0] = -1;
144695 pNew->addrOpenEphm[1] = -1;
144696 pNew->nSelectRow = 0;
144697 if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
144698 pNew->pSrc = pSrc;
144699 pNew->pWhere = pWhere;
144700 pNew->pGroupBy = pGroupBy;
144701 pNew->pHaving = pHaving;
144702 pNew->pOrderBy = pOrderBy;
@@ -146005,20 +146075,20 @@
146075 /*
146076 ** Allocate a KeyInfo object sufficient for an index of N key columns and
146077 ** X extra columns.
146078 */
146079 SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
146080 int nExtra = (N+X)*(sizeof(CollSeq*)+1);
146081 KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
146082 if( p ){
146083 p->aSortFlags = (u8*)&p->aColl[N+X];
146084 p->nKeyField = (u16)N;
146085 p->nAllField = (u16)(N+X);
146086 p->enc = ENC(db);
146087 p->db = db;
146088 p->nRef = 1;
146089 memset(p->aColl, 0, nExtra);
146090 }else{
146091 return (KeyInfo*)sqlite3OomFault(db);
146092 }
146093 return p;
146094 }
@@ -150530,11 +150600,11 @@
150600 }
150601 pTabList = p->pSrc;
150602 pEList = p->pEList;
150603 if( pParse->pWith && (p->selFlags & SF_View) ){
150604 if( p->pWith==0 ){
150605 p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) );
150606 if( p->pWith==0 ){
150607 return WRC_Abort;
150608 }
150609 }
150610 p->pWith->bView = 1;
@@ -151669,10 +151739,11 @@
151739 ** * The subquery is a UNION ALL of two or more terms
151740 ** * The subquery does not have a LIMIT clause
151741 ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
151742 ** * The outer query is a simple count(*) with no WHERE clause or other
151743 ** extraneous syntax.
151744 ** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10)
151745 **
151746 ** Return TRUE if the optimization is undertaken.
151747 */
151748 static int countOfViewOptimization(Parse *pParse, Select *p){
151749 Select *pSub, *pPrior;
@@ -151701,11 +151772,15 @@
151772 if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */
151773 do{
151774 if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
151775 if( pSub->pWhere ) return 0; /* No WHERE clause */
151776 if( pSub->pLimit ) return 0; /* No LIMIT clause */
151777 if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){
151778 testcase( pSub->selFlags & SF_Aggregate );
151779 testcase( pSub->selFlags & SF_Distinct );
151780 return 0; /* Not an aggregate nor DISTINCT */
151781 }
151782 assert( pSub->pHaving==0 ); /* Due to the previous */
151783 pSub = pSub->pPrior; /* Repeat over compound */
151784 }while( pSub );
151785
151786 /* If we reach this point then it is OK to perform the transformation */
@@ -151713,11 +151788,11 @@
151788 db = pParse->db;
151789 pCount = pExpr;
151790 pExpr = 0;
151791 pSub = sqlite3SubqueryDetach(db, pFrom);
151792 sqlite3SrcListDelete(db, p->pSrc);
151793 p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
151794 while( pSub ){
151795 Expr *pTerm;
151796 pPrior = pSub->pPrior;
151797 pSub->pPrior = 0;
151798 pSub->pNext = 0;
@@ -154504,11 +154579,12 @@
154579 Vdbe *v = pParse->pVdbe;
154580 sqlite3 *db = pParse->db;
154581 ExprList *pNew;
154582 Returning *pReturning;
154583 Select sSelect;
154584 SrcList *pFrom;
154585 u8 fromSpace[SZ_SRCLIST_1];
154586
154587 assert( v!=0 );
154588 if( !pParse->bReturning ){
154589 /* This RETURNING trigger must be for a different statement as
154590 ** this statement lacks a RETURNING clause. */
@@ -154520,17 +154596,18 @@
154596 if( pTrigger != &(pReturning->retTrig) ){
154597 /* This RETURNING trigger is for a different statement */
154598 return;
154599 }
154600 memset(&sSelect, 0, sizeof(sSelect));
154601 pFrom = (SrcList*)fromSpace;
154602 memset(pFrom, 0, SZ_SRCLIST_1);
154603 sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
154604 sSelect.pSrc = pFrom;
154605 pFrom->nSrc = 1;
154606 pFrom->a[0].pSTab = pTab;
154607 pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
154608 pFrom->a[0].iCursor = -1;
154609 sqlite3SelectPrep(pParse, &sSelect, 0);
154610 if( pParse->nErr==0 ){
154611 assert( db->mallocFailed==0 );
154612 sqlite3GenerateColumnNames(pParse, &sSelect);
154613 }
@@ -156927,11 +157004,11 @@
157004 saved_flags = db->flags;
157005 saved_mDbFlags = db->mDbFlags;
157006 saved_nChange = db->nChange;
157007 saved_nTotalChange = db->nTotalChange;
157008 saved_mTrace = db->mTrace;
157009 db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
157010 db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
157011 db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
157012 | SQLITE_Defensive | SQLITE_CountRows);
157013 db->mTrace = 0;
157014
@@ -159056,13 +159133,18 @@
159133 WhereLoop *pLoops; /* List of all WhereLoop objects */
159134 WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
159135 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
159136 WhereClause sWC; /* Decomposition of the WHERE clause */
159137 WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
159138 WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */
159139 };
159140
159141 /*
159142 ** The size (in bytes) of a WhereInfo object that holds N WhereLevels.
159143 */
159144 #define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel))
159145
159146 /*
159147 ** Private interfaces - callable only by other where.c routines.
159148 **
159149 ** where.c:
159150 */
@@ -161509,12 +161591,11 @@
161591 */
161592 if( pWInfo->nLevel>1 ){
161593 int nNotReady; /* The number of notReady tables */
161594 SrcItem *origSrc; /* Original list of tables */
161595 nNotReady = pWInfo->nLevel - iLevel - 1;
161596 pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
 
161597 if( pOrTab==0 ) return notReady;
161598 pOrTab->nAlloc = (u8)(nNotReady + 1);
161599 pOrTab->nSrc = pOrTab->nAlloc;
161600 memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
161601 origSrc = pWInfo->pTabList->a;
@@ -162053,11 +162134,12 @@
162134 Expr *pSubWhere = 0;
162135 WhereClause *pWC = &pWInfo->sWC;
162136 WhereInfo *pSubWInfo;
162137 WhereLoop *pLoop = pLevel->pWLoop;
162138 SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
162139 SrcList *pFrom;
162140 u8 fromSpace[SZ_SRCLIST_1];
162141 Bitmask mAll = 0;
162142 int k;
162143
162144 ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
162145 sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
@@ -162097,17 +162179,18 @@
162179 if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
162180 pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
162181 sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
162182 }
162183 }
162184 pFrom = (SrcList*)fromSpace;
162185 pFrom->nSrc = 1;
162186 pFrom->nAlloc = 1;
162187 memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
162188 pFrom->a[0].fg.jointype = 0;
162189 assert( pParse->withinRJSubrtn < 100 );
162190 pParse->withinRJSubrtn++;
162191 pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
162192 WHERE_RIGHT_JOIN, 0);
162193 if( pSubWInfo ){
162194 int iCur = pLevel->iTabCur;
162195 int r = ++pParse->nMem;
162196 int nPk;
@@ -164091,15 +164174,20 @@
164174 WhereClause *pWC; /* The Where clause being analyzed */
164175 Parse *pParse; /* The parsing context */
164176 int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
164177 u32 mIn; /* Mask of terms that are <col> IN (...) */
164178 u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */
164179 sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST
164180 ** Extra space is allocated to hold up
164181 ** to nTerm such values */
164182 };
164183
164184 /* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as
164185 ** many as N constraints */
164186 #define SZ_HIDDENINDEXINFO(N) \
164187 (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*))
164188
164189 /* Forward declaration of methods */
164190 static int whereLoopResize(sqlite3*, WhereLoop*, int);
164191
164192 /*
164193 ** Return the estimated number of output rows from a WHERE clause
@@ -165573,12 +165661,12 @@
165661
165662 /* Allocate the sqlite3_index_info structure
165663 */
165664 pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
165665 + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
165666 + sizeof(*pIdxOrderBy)*nOrderBy
165667 + SZ_HIDDENINDEXINFO(nTerm) );
165668 if( pIdxInfo==0 ){
165669 sqlite3ErrorMsg(pParse, "out of memory");
165670 return 0;
165671 }
165672 pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
@@ -170768,14 +170856,11 @@
170856 ** struct, the contents of WhereInfo.a[], the WhereClause structure
170857 ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
170858 ** field (type Bitmask) it must be aligned on an 8-byte boundary on
170859 ** some architectures. Hence the ROUND8() below.
170860 */
170861 nByteWInfo = SZ_WHEREINFO(nTabList);
 
 
 
170862 pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
170863 if( db->mallocFailed ){
170864 sqlite3DbFree(db, pWInfo);
170865 pWInfo = 0;
170866 goto whereBeginError;
@@ -181607,11 +181692,15 @@
181692 tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
181693 }else if( tokenType==TK_FILTER ){
181694 assert( n==6 );
181695 tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
181696 #endif /* SQLITE_OMIT_WINDOWFUNC */
181697 }else if( tokenType==TK_COMMENT
181698 && (db->init.busy || (db->flags & SQLITE_Comments)!=0)
181699 ){
181700 /* Ignore SQL comments if either (1) we are reparsing the schema or
181701 ** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */
181702 zSql += n;
181703 continue;
181704 }else if( tokenType!=TK_QNUMBER ){
181705 Token x;
181706 x.z = zSql;
@@ -182502,10 +182591,18 @@
182591 }
182592 #endif
182593 if( rc==SQLITE_OK ){
182594 sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
182595 sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
182596 #ifdef SQLITE_EXTRA_INIT_MUTEXED
182597 {
182598 int SQLITE_EXTRA_INIT_MUTEXED(const char*);
182599 rc = SQLITE_EXTRA_INIT_MUTEXED(0);
182600 }
182601 #endif
182602 }
182603 if( rc==SQLITE_OK ){
182604 sqlite3MemoryBarrier();
182605 sqlite3GlobalConfig.isInit = 1;
182606 #ifdef SQLITE_EXTRA_INIT
182607 bRunExtraInit = 1;
182608 #endif
@@ -184063,10 +184160,14 @@
184160 sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt));
184161 sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC);
184162 }
184163 }
184164 sqlite3BtreeLeaveAll(db);
184165 #endif
184166 #if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
184167 UNUSED_PARAMETER(db);
184168 UNUSED_PARAMETER(flags);
184169 #endif
184170 return SQLITE_OK;
184171 }
184172
184173 /*
@@ -186032,11 +186133,11 @@
186133 }else if( pData==0 ){
186134 sqlite3_mutex_leave(db->mutex);
186135 return SQLITE_OK;
186136 }else{
186137 size_t n = strlen(zName);
186138 p = sqlite3_malloc64( SZ_DBCLIENTDATA(n+1) );
186139 if( p==0 ){
186140 if( xDestructor ) xDestructor(pData);
186141 sqlite3_mutex_leave(db->mutex);
186142 return SQLITE_NOMEM;
186143 }
@@ -186398,12 +186499,12 @@
186499 #endif
186500
186501 /* sqlite3_test_control(SQLITE_TESTCTRL_FK_NO_ACTION, sqlite3 *db, int b);
186502 **
186503 ** If b is true, then activate the SQLITE_FkNoAction setting. If b is
186504 ** false then clear that setting. If the SQLITE_FkNoAction setting is
186505 ** enabled, all foreign key ON DELETE and ON UPDATE actions behave as if
186506 ** they were NO ACTION, regardless of how they are defined.
186507 **
186508 ** NB: One must usually run "PRAGMA writable_schema=RESET" after
186509 ** using this test-control, before it will take full effect. failing
186510 ** to reset the schema can result in some unexpected behavior.
@@ -187746,11 +187847,11 @@
187847 ** }
187848 **
187849 ** Here, array { X } means zero or more occurrences of X, adjacent in
187850 ** memory. A "position" is an index of a token in the token stream
187851 ** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
187852 ** in the same logical place as the position element, and act as sentinels
187853 ** ending a position list array. POS_END is 0. POS_COLUMN is 1.
187854 ** The positions numbers are not stored literally but rather as two more
187855 ** than the difference from the prior position, or the just the position plus
187856 ** 2 for the first position. Example:
187857 **
@@ -188433,10 +188534,23 @@
188534
188535 #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
188536 #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
188537
188538 #define deliberate_fall_through
188539
188540 /*
188541 ** Macros needed to provide flexible arrays in a portable way
188542 */
188543 #ifndef offsetof
188544 # define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
188545 #endif
188546 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
188547 # define FLEXARRAY
188548 #else
188549 # define FLEXARRAY 1
188550 #endif
188551
188552
188553 #endif /* SQLITE_AMALGAMATION */
188554
188555 #ifdef SQLITE_DEBUG
188556 SQLITE_PRIVATE int sqlite3Fts3Corrupt(void);
@@ -188538,11 +188652,11 @@
188652 int inTransaction; /* True after xBegin but before xCommit/xRollback */
188653 int mxSavepoint; /* Largest valid xSavepoint integer */
188654 #endif
188655
188656 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
188657 /* True to disable the incremental doclist optimization. This is controlled
188658 ** by special insert command 'test-no-incr-doclist'. */
188659 int bNoIncrDoclist;
188660
188661 /* Number of segments in a level */
188662 int nMergeCount;
@@ -188590,11 +188704,11 @@
188704 #define FTS3_EVAL_NEXT 1
188705 #define FTS3_EVAL_MATCHINFO 2
188706
188707 /*
188708 ** The Fts3Cursor.eSearch member is always set to one of the following.
188709 ** Actually, Fts3Cursor.eSearch can be greater than or equal to
188710 ** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
188711 ** of the column to be searched. For example, in
188712 **
188713 ** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
188714 ** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
@@ -188663,12 +188777,16 @@
188777 /* Variables below this point are populated by fts3_expr.c when parsing
188778 ** a MATCH expression. Everything above is part of the evaluation phase.
188779 */
188780 int nToken; /* Number of tokens in the phrase */
188781 int iColumn; /* Index of column this phrase must match */
188782 Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */
188783 };
188784
188785 /* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */
188786 #define SZ_FTS3PHRASE(N) \
188787 (offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken))
188788
188789 /*
188790 ** A tree of these objects forms the RHS of a MATCH operator.
188791 **
188792 ** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
@@ -191243,11 +191361,11 @@
191361 **
191362 ** The space required to store the output is therefore the sum of the
191363 ** sizes of the two inputs, plus enough space for exactly one of the input
191364 ** docids to grow.
191365 **
191366 ** A symmetric argument may be made if the doclists are in descending
191367 ** order.
191368 */
191369 aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
191370 if( !aOut ) return SQLITE_NOMEM;
191371
@@ -193341,11 +193459,11 @@
193459 **
193460 ** * features at least one token that uses an incremental doclist, and
193461 **
193462 ** * does not contain any deferred tokens.
193463 **
193464 ** Advance it to the next matching document in the database and populate
193465 ** the Fts3Doclist.pList and nList fields.
193466 **
193467 ** If there is no "next" entry and no error occurs, then *pbEof is set to
193468 ** 1 before returning. Otherwise, if no error occurs and the iterator is
193469 ** successfully advanced, *pbEof is set to 0.
@@ -194348,11 +194466,11 @@
194466
194467 return rc;
194468 }
194469
194470 /*
194471 ** Restart iteration for expression pExpr so that the next call to
194472 ** fts3EvalNext() visits the first row. Do not allow incremental
194473 ** loading or merging of phrase doclists for this iteration.
194474 **
194475 ** If *pRc is other than SQLITE_OK when this function is called, it is
194476 ** a no-op. If an error occurs within this function, *pRc is set to an
@@ -195539,10 +195657,27 @@
195657 /*
195658 ** Function getNextNode(), which is called by fts3ExprParse(), may itself
195659 ** call fts3ExprParse(). So this forward declaration is required.
195660 */
195661 static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
195662
195663 /*
195664 ** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
195665 ** is defined, search for '(' and ')' as well. Return the index of the first
195666 ** such character in the buffer. If there is no such character, return -1.
195667 */
195668 static int findBarredChar(const char *z, int n){
195669 int ii;
195670 for(ii=0; ii<n; ii++){
195671 if( (z[ii]=='"')
195672 || (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')'))
195673 ){
195674 return ii;
195675 }
195676 }
195677 return -1;
195678 }
195679
195680 /*
195681 ** Extract the next token from buffer z (length n) using the tokenizer
195682 ** and other information (column names etc.) in pParse. Create an Fts3Expr
195683 ** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
@@ -195564,38 +195699,42 @@
195699 sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
195700 sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
195701 int rc;
195702 sqlite3_tokenizer_cursor *pCursor;
195703 Fts3Expr *pRet = 0;
195704
195705 *pnConsumed = n;
195706 rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
 
 
 
 
 
 
 
195707 if( rc==SQLITE_OK ){
195708 const char *zToken;
195709 int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
195710 sqlite3_int64 nByte; /* total space to allocate */
195711
195712 rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
195713 if( rc==SQLITE_OK ){
195714 /* Check that this tokenization did not gobble up any " characters. Or,
195715 ** if enable_parenthesis is true, that it did not gobble up any
195716 ** open or close parenthesis characters either. If it did, call
195717 ** getNextToken() again, but pass only that part of the input buffer
195718 ** up to the first such character. */
195719 int iBarred = findBarredChar(z, iEnd);
195720 if( iBarred>=0 ){
195721 pModule->xClose(pCursor);
195722 return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
195723 }
195724
195725 nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
195726 pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
195727 if( !pRet ){
195728 rc = SQLITE_NOMEM;
195729 }else{
195730 pRet->eType = FTSQUERY_PHRASE;
195731 pRet->pPhrase = (Fts3Phrase *)&pRet[1];
195732 pRet->pPhrase->nToken = 1;
195733 pRet->pPhrase->iColumn = iCol;
195734 pRet->pPhrase->aToken[0].n = nToken;
195735 pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
195736 memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
195737
195738 if( iEnd<n && z[iEnd]=='*' ){
195739 pRet->pPhrase->aToken[0].isPrefix = 1;
195740 iEnd++;
@@ -195615,11 +195754,15 @@
195754 }
195755 }
195756
195757 }
195758 *pnConsumed = iEnd;
195759 }else if( n && rc==SQLITE_DONE ){
195760 int iBarred = findBarredChar(z, n);
195761 if( iBarred>=0 ){
195762 *pnConsumed = iBarred;
195763 }
195764 rc = SQLITE_OK;
195765 }
195766
195767 pModule->xClose(pCursor);
195768 }
@@ -195664,11 +195807,11 @@
195807 Fts3Expr *p = 0;
195808 sqlite3_tokenizer_cursor *pCursor = 0;
195809 char *zTemp = 0;
195810 i64 nTemp = 0;
195811
195812 const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
195813 int nToken = 0;
195814
195815 /* The final Fts3Expr data structure, including the Fts3Phrase,
195816 ** Fts3PhraseToken structures token buffers are all stored as a single
195817 ** allocation so that the expression can be freed with a single call to
@@ -196036,11 +196179,11 @@
196179 int eType = p->eType;
196180 isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
196181
196182 /* The isRequirePhrase variable is set to true if a phrase or
196183 ** an expression contained in parenthesis is required. If a
196184 ** binary operator (AND, OR, NOT or NEAR) is encountered when
196185 ** isRequirePhrase is set, this is a syntax error.
196186 */
196187 if( !isPhrase && isRequirePhrase ){
196188 sqlite3Fts3ExprFree(p);
196189 rc = SQLITE_ERROR;
@@ -196618,11 +196761,10 @@
196761 pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
196762 );
196763 }
196764
196765 if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
 
196766 sqlite3_result_error(context, "Error parsing expression", -1);
196767 }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
196768 sqlite3_result_error_nomem(context);
196769 }else{
196770 sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
@@ -196861,11 +197003,11 @@
197003 pEntry->count++;
197004 pEntry->chain = pNew;
197005 }
197006
197007
197008 /* Resize the hash table so that it contains "new_size" buckets.
197009 ** "new_size" must be a power of 2. The hash table might fail
197010 ** to resize if sqliteMalloc() fails.
197011 **
197012 ** Return non-zero if a memory allocation error occurs.
197013 */
@@ -197316,11 +197458,11 @@
197458 isConsonant(z+2);
197459 }
197460
197461 /*
197462 ** If the word ends with zFrom and xCond() is true for the stem
197463 ** of the word that precedes the zFrom ending, then change the
197464 ** ending to zTo.
197465 **
197466 ** The input word *pz and zFrom are both in reverse order. zTo
197467 ** is in normal order.
197468 **
@@ -202899,11 +203041,11 @@
203041 ** previous term. Before this function returns, it is updated to contain a
203042 ** copy of zTerm/nTerm.
203043 **
203044 ** It is assumed that the buffer associated with pNode is already large
203045 ** enough to accommodate the new entry. The buffer associated with pPrev
203046 ** is extended by this function if required.
203047 **
203048 ** If an error (i.e. OOM condition) occurs, an SQLite error code is
203049 ** returned. Otherwise, SQLITE_OK.
203050 */
203051 static int fts3AppendToNode(
@@ -204562,11 +204704,11 @@
204704 #endif
204705
204706 /*
204707 ** SQLite value pRowid contains the rowid of a row that may or may not be
204708 ** present in the FTS3 table. If it is, delete it and adjust the contents
204709 ** of subsidiary data structures accordingly.
204710 */
204711 static int fts3DeleteByRowid(
204712 Fts3Table *p,
204713 sqlite3_value *pRowid,
204714 int *pnChng, /* IN/OUT: Decrement if row is deleted */
@@ -204888,12 +205030,16 @@
205030 struct MatchinfoBuffer {
205031 u8 aRef[3];
205032 int nElem;
205033 int bGlobal; /* Set if global data is loaded */
205034 char *zMatchinfo;
205035 u32 aMI[FLEXARRAY];
205036 };
205037
205038 /* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */
205039 #define SZ_MATCHINFOBUFFER(N) \
205040 (offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64))
205041
205042
205043 /*
205044 ** The snippet() and offsets() functions both return text values. An instance
205045 ** of the following structure is used to accumulate those values while the
@@ -204915,17 +205061,17 @@
205061 ** Allocate a two-slot MatchinfoBuffer object.
205062 */
205063 static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
205064 MatchinfoBuffer *pRet;
205065 sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
205066 + SZ_MATCHINFOBUFFER(1);
205067 sqlite3_int64 nStr = strlen(zMatchinfo);
205068
205069 pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
205070 if( pRet ){
205071 pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
205072 pRet->aMI[1+nElem] = pRet->aMI[0]
205073 + sizeof(u32)*((int)nElem+1);
205074 pRet->nElem = (int)nElem;
205075 pRet->zMatchinfo = ((char*)pRet) + nByte;
205076 memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
205077 pRet->aRef[0] = 1;
@@ -204935,14 +205081,14 @@
205081 }
205082
205083 static void fts3MIBufferFree(void *p){
205084 MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
205085
205086 assert( (u32*)p==&pBuf->aMI[1]
205087 || (u32*)p==&pBuf->aMI[pBuf->nElem+2]
205088 );
205089 if( (u32*)p==&pBuf->aMI[1] ){
205090 pBuf->aRef[1] = 0;
205091 }else{
205092 pBuf->aRef[2] = 0;
205093 }
205094
@@ -204955,32 +205101,32 @@
205101 void (*xRet)(void*) = 0;
205102 u32 *aOut = 0;
205103
205104 if( p->aRef[1]==0 ){
205105 p->aRef[1] = 1;
205106 aOut = &p->aMI[1];
205107 xRet = fts3MIBufferFree;
205108 }
205109 else if( p->aRef[2]==0 ){
205110 p->aRef[2] = 1;
205111 aOut = &p->aMI[p->nElem+2];
205112 xRet = fts3MIBufferFree;
205113 }else{
205114 aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
205115 if( aOut ){
205116 xRet = sqlite3_free;
205117 if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32));
205118 }
205119 }
205120
205121 *paOut = aOut;
205122 return xRet;
205123 }
205124
205125 static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
205126 p->bGlobal = 1;
205127 memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32));
205128 }
205129
205130 /*
205131 ** Free a MatchinfoBuffer object allocated using fts3MIBufferNew()
205132 */
@@ -205391,11 +205537,11 @@
205537 if( nAppend<0 ){
205538 nAppend = (int)strlen(zAppend);
205539 }
205540
205541 /* If there is insufficient space allocated at StrBuffer.z, use realloc()
205542 ** to grow the buffer until so that it is big enough to accommodate the
205543 ** appended data.
205544 */
205545 if( pStr->n+nAppend+1>=pStr->nAlloc ){
205546 sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
205547 char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
@@ -207766,11 +207912,11 @@
207912 **
207913 ** When a match if found, the matching entry is moved to become the
207914 ** most-recently used entry if it isn't so already.
207915 **
207916 ** The JsonParse object returned still belongs to the Cache and might
207917 ** be deleted at any moment. If the caller wants the JsonParse to
207918 ** linger, it needs to increment the nPJRef reference counter.
207919 */
207920 static JsonParse *jsonCacheSearch(
207921 sqlite3_context *ctx, /* The SQL statement context holding the cache */
207922 sqlite3_value *pArg /* Function argument containing SQL text */
@@ -210811,11 +210957,11 @@
210957 **
210958 ** This goes against all historical documentation about how the SQLite
210959 ** JSON functions were suppose to work. From the beginning, blob was
210960 ** reserved for expansion and a blob value should have raised an error.
210961 ** But it did not, due to a bug. And many applications came to depend
210962 ** upon this buggy behavior, especially when using the CLI and reading
210963 ** JSON text using readfile(), which returns a blob. For this reason
210964 ** we will continue to support the bug moving forward.
210965 ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
210966 */
210967 }
@@ -212911,10 +213057,18 @@
213057 # define NEVER(X) ((X)?(assert(0),1):0)
213058 #else
213059 # define ALWAYS(X) (X)
213060 # define NEVER(X) (X)
213061 #endif
213062 #ifndef offsetof
213063 #define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
213064 #endif
213065 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
213066 # define FLEXARRAY
213067 #else
213068 # define FLEXARRAY 1
213069 #endif
213070 #endif /* !defined(SQLITE_AMALGAMATION) */
213071
213072 /* Macro to check for 4-byte alignment. Only used inside of assert() */
213073 #ifdef SQLITE_DEBUG
213074 # define FOUR_BYTE_ALIGNED(X) ((((char*)(X) - (char*)0) & 3)==0)
@@ -213231,13 +213385,17 @@
213385 struct RtreeMatchArg {
213386 u32 iSize; /* Size of this object */
213387 RtreeGeomCallback cb; /* Info about the callback functions */
213388 int nParam; /* Number of parameters to the SQL function */
213389 sqlite3_value **apSqlParam; /* Original SQL parameter values */
213390 RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */
213391 };
213392
213393 /* Size of an RtreeMatchArg object with N parameters */
213394 #define SZ_RTREEMATCHARG(N) \
213395 (offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue))
213396
213397 #ifndef MAX
213398 # define MAX(x,y) ((x) < (y) ? (y) : (x))
213399 #endif
213400 #ifndef MIN
213401 # define MIN(x,y) ((x) > (y) ? (y) : (x))
@@ -214922,11 +215080,11 @@
215080
215081 return rc;
215082 }
215083
215084 /*
215085 ** Return the N-dimensional volume of the cell stored in *p.
215086 */
215087 static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
215088 RtreeDValue area = (RtreeDValue)1;
215089 assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
215090 #ifndef SQLITE_RTREE_INT_ONLY
@@ -216688,11 +216846,11 @@
216846 }
216847
216848 /*
216849 ** The second and subsequent arguments to this function are a printf()
216850 ** style format string and arguments. This function formats the string and
216851 ** appends it to the report being accumulated in pCheck.
216852 */
216853 static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
216854 va_list ap;
216855 va_start(ap, zFmt);
216856 if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){
@@ -217876,11 +218034,11 @@
218034
218035 /*
218036 ** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
218037 ** Returns:
218038 **
218039 ** +2 x0,y0 is on the line segment
218040 **
218041 ** +1 x0,y0 is beneath line segment
218042 **
218043 ** 0 x0,y0 is not on or beneath the line segment or the line segment
218044 ** is vertical and x0,y0 is not on the line segment
@@ -217982,11 +218140,11 @@
218140 }
218141 sqlite3_free(p1);
218142 sqlite3_free(p2);
218143 }
218144
218145 /* Objects used by the overlap algorithm. */
218146 typedef struct GeoEvent GeoEvent;
218147 typedef struct GeoSegment GeoSegment;
218148 typedef struct GeoOverlap GeoOverlap;
218149 struct GeoEvent {
218150 double x; /* X coordinate at which event occurs */
@@ -219029,12 +219187,11 @@
219187 RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
219188 RtreeMatchArg *pBlob;
219189 sqlite3_int64 nBlob;
219190 int memErr = 0;
219191
219192 nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*);
 
219193 pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
219194 if( !pBlob ){
219195 sqlite3_result_error_nomem(ctx);
219196 }else{
219197 int i;
@@ -220125,11 +220282,11 @@
220282 ** to read from the original database snapshot. In other words, partially
220283 ** applied transactions are not visible to other clients.
220284 **
220285 ** "RBU" stands for "Resumable Bulk Update". As in a large database update
220286 ** transmitted via a wireless network to a mobile device. A transaction
220287 ** applied using this extension is hence referred to as an "RBU update".
220288 **
220289 **
220290 ** LIMITATIONS
220291 **
220292 ** An "RBU update" transaction is subject to the following limitations:
@@ -220422,11 +220579,11 @@
220579 ** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
220580 ** of the state tables within the state database are zeroed. This way,
220581 ** the next call to sqlite3rbu_vacuum() opens a handle that starts a
220582 ** new RBU vacuum operation.
220583 **
220584 ** As with sqlite3rbu_open(), Zipvfs users should refer to the comment
220585 ** describing the sqlite3rbu_create_vfs() API function below for
220586 ** a description of the complications associated with using RBU with
220587 ** zipvfs databases.
220588 */
220589 SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
@@ -220518,11 +220675,11 @@
220675 /*
220676 ** Close an RBU handle.
220677 **
220678 ** If the RBU update has been completely applied, mark the RBU database
220679 ** as fully applied. Otherwise, assuming no error has occurred, save the
220680 ** current state of the RBU update application to the RBU database.
220681 **
220682 ** If an error has already occurred as part of an sqlite3rbu_step()
220683 ** or sqlite3rbu_open() call, or if one occurs within this function, an
220684 ** SQLite error code is returned. Additionally, if pzErrmsg is not NULL,
220685 ** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted
@@ -225444,11 +225601,11 @@
225601 int rc;
225602 rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
225603
225604 /* If this is an RBU vacuum operation and this is the target database,
225605 ** pretend that it has at least one page. Otherwise, SQLite will not
225606 ** check for the existence of a *-wal file. rbuVfsRead() contains
225607 ** similar logic. */
225608 if( rc==SQLITE_OK && *pSize==0
225609 && p->pRbu && rbuIsVacuum(p->pRbu)
225610 && (p->openFlags & SQLITE_OPEN_MAIN_DB)
225611 ){
@@ -228674,11 +228831,11 @@
228831 }
228832
228833 /*
228834 ** This function is called to initialize the SessionTable.nCol, azCol[]
228835 ** abPK[] and azDflt[] members of SessionTable object pTab. If these
228836 ** fields are already initialized, this function is a no-op.
228837 **
228838 ** If an error occurs, an error code is stored in sqlite3_session.rc and
228839 ** non-zero returned. Or, if no error occurs but the table has no primary
228840 ** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to
228841 ** indicate that updates on this table should be ignored. SessionTable.abPK
@@ -230497,11 +230654,11 @@
230654 int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
230655 void **ppChangeset /* OUT: Buffer containing changeset */
230656 ){
230657 sqlite3 *db = pSession->db; /* Source database handle */
230658 SessionTable *pTab; /* Used to iterate through attached tables */
230659 SessionBuffer buf = {0,0,0}; /* Buffer in which to accumulate changeset */
230660 int rc; /* Return code */
230661
230662 assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
230663 assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );
230664
@@ -234931,10 +235088,22 @@
235088 # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
235089 #else
235090 # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
235091 #endif
235092
235093 /*
235094 ** Macros needed to provide flexible arrays in a portable way
235095 */
235096 #ifndef offsetof
235097 # define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
235098 #endif
235099 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
235100 # define FLEXARRAY
235101 #else
235102 # define FLEXARRAY 1
235103 #endif
235104
235105 #endif
235106
235107 /* Truncate very long tokens to this many bytes. Hard limit is
235108 ** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
235109 ** field that occurs at the start of each leaf page (see fts5_index.c). */
@@ -235003,14 +235172,15 @@
235172 **
235173 ** This object is used by fts5_expr.c and fts5_index.c.
235174 */
235175 struct Fts5Colset {
235176 int nCol;
235177 int aiCol[FLEXARRAY];
235178 };
235179
235180 /* Size (int bytes) of a complete Fts5Colset object with N columns. */
235181 #define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2))
235182
235183 /**************************************************************************
235184 ** Interface to code in fts5_config.c. fts5_config.c contains contains code
235185 ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
235186 */
@@ -235835,11 +236005,11 @@
236005 *************************************************************************
236006 ** Driver template for the LEMON parser generator.
236007 **
236008 ** The "lemon" program processes an LALR(1) input grammar file, then uses
236009 ** this template to construct a parser. The "lemon" program inserts text
236010 ** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
236011 ** interstitial "-" characters) contained in this template is changed into
236012 ** the value of the %name directive from the grammar. Otherwise, the content
236013 ** of this template is copied straight through into the generate parser
236014 ** source file.
236015 **
@@ -237989,11 +238159,11 @@
238159 ** where "N" is the total number of documents in the set and nHit
238160 ** is the number that contain at least one instance of the phrase
238161 ** under consideration.
238162 **
238163 ** The problem with this is that if (N < 2*nHit), the IDF is
238164 ** negative. Which is undesirable. So the minimum allowable IDF is
238165 ** (1e-6) - roughly the same as a term that appears in just over
238166 ** half of set of 5,000,000 documents. */
238167 double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
238168 if( idf<=0.0 ) idf = 1e-6;
238169 p->aIDF[i] = idf;
@@ -238452,11 +238622,11 @@
238622 **
238623 ** * All non-ASCII characters,
238624 ** * The 52 upper and lower case ASCII characters, and
238625 ** * The 10 integer ASCII characters.
238626 ** * The underscore character "_" (0x5F).
238627 ** * The unicode "substitute" character (0x1A).
238628 */
238629 static int sqlite3Fts5IsBareword(char t){
238630 u8 aBareword[128] = {
238631 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 .. 0x0F */
238632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */
@@ -239770,12 +239940,16 @@
239940 Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */
239941
239942 /* Child nodes. For a NOT node, this array always contains 2 entries. For
239943 ** AND or OR nodes, it contains 2 or more entries. */
239944 int nChild; /* Number of child nodes */
239945 Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */
239946 };
239947
239948 /* Size (in bytes) of an Fts5ExprNode object that holds up to N children */
239949 #define SZ_FTS5EXPRNODE(N) \
239950 (offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*))
239951
239952 #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
239953
239954 /*
239955 ** Invoke the xNext method of an Fts5ExprNode object. This macro should be
@@ -239803,24 +239977,31 @@
239977 */
239978 struct Fts5ExprPhrase {
239979 Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
239980 Fts5Buffer poslist; /* Current position list */
239981 int nTerm; /* Number of entries in aTerm[] */
239982 Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */
239983 };
239984
239985 /* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */
239986 #define SZ_FTS5EXPRPHRASE(N) \
239987 (offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm))
239988
239989 /*
239990 ** One or more phrases that must appear within a certain token distance of
239991 ** each other within each matching document.
239992 */
239993 struct Fts5ExprNearset {
239994 int nNear; /* NEAR parameter */
239995 Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
239996 int nPhrase; /* Number of entries in aPhrase[] array */
239997 Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */
239998 };
239999
240000 /* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */
240001 #define SZ_FTS5EXPRNEARSET(N) \
240002 (offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*))
240003
240004 /*
240005 ** Parse context.
240006 */
240007 struct Fts5Parse {
@@ -239976,11 +240157,11 @@
240157 assert_expr_depth_ok(sParse.rc, sParse.pExpr);
240158
240159 /* If the LHS of the MATCH expression was a user column, apply the
240160 ** implicit column-filter. */
240161 if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
240162 int n = SZ_FTS5COLSET(1);
240163 Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
240164 if( pColset ){
240165 pColset->nCol = 1;
240166 pColset->aiCol[0] = iCol;
240167 sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
@@ -241334,11 +241515,11 @@
241515 Fts5ExprNearset *pRet = 0;
241516
241517 if( pParse->rc==SQLITE_OK ){
241518 if( pNear==0 ){
241519 sqlite3_int64 nByte;
241520 nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1);
241521 pRet = sqlite3_malloc64(nByte);
241522 if( pRet==0 ){
241523 pParse->rc = SQLITE_NOMEM;
241524 }else{
241525 memset(pRet, 0, (size_t)nByte);
@@ -241345,11 +241526,11 @@
241526 }
241527 }else if( (pNear->nPhrase % SZALLOC)==0 ){
241528 int nNew = pNear->nPhrase + SZALLOC;
241529 sqlite3_int64 nByte;
241530
241531 nByte = SZ_FTS5EXPRNEARSET(nNew+1);
241532 pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
241533 if( pRet==0 ){
241534 pParse->rc = SQLITE_NOMEM;
241535 }
241536 }else{
@@ -241436,16 +241617,16 @@
241617 if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){
241618 Fts5ExprPhrase *pNew;
241619 int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
241620
241621 pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
241622 SZ_FTS5EXPRPHRASE(nNew+1)
241623 );
241624 if( pNew==0 ){
241625 rc = SQLITE_NOMEM;
241626 }else{
241627 if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1));
241628 pCtx->pPhrase = pPhrase = pNew;
241629 pNew->nTerm = nNew - SZALLOC;
241630 }
241631 }
241632
@@ -241549,11 +241730,11 @@
241730 }
241731
241732 if( sCtx.pPhrase==0 ){
241733 /* This happens when parsing a token or quoted phrase that contains
241734 ** no token characters at all. (e.g ... MATCH '""'). */
241735 sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1));
241736 }else if( sCtx.pPhrase->nTerm ){
241737 sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
241738 }
241739 assert( pParse->apPhrase!=0 );
241740 pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
@@ -241584,23 +241765,22 @@
241765 if( rc==SQLITE_OK ){
241766 pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
241767 sizeof(Fts5ExprPhrase*));
241768 }
241769 if( rc==SQLITE_OK ){
241770 pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1));
 
241771 }
241772 if( rc==SQLITE_OK ){
241773 pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
241774 SZ_FTS5EXPRNEARSET(2));
241775 }
241776 if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
241777 Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
241778 if( pColsetOrig ){
241779 sqlite3_int64 nByte;
241780 Fts5Colset *pColset;
241781 nByte = SZ_FTS5COLSET(pColsetOrig->nCol);
241782 pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
241783 if( pColset ){
241784 memcpy(pColset, pColsetOrig, (size_t)nByte);
241785 }
241786 pNew->pRoot->pNear->pColset = pColset;
@@ -241624,11 +241804,11 @@
241804 }
241805 }
241806 }else{
241807 /* This happens when parsing a token or quoted phrase that contains
241808 ** no token characters at all. (e.g ... MATCH '""'). */
241809 sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1));
241810 }
241811 }
241812
241813 if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
241814 /* All the allocations succeeded. Put the expression object together. */
@@ -241718,11 +241898,11 @@
241898 Fts5Colset *pNew; /* New colset object to return */
241899
241900 assert( pParse->rc==SQLITE_OK );
241901 assert( iCol>=0 && iCol<pParse->pConfig->nCol );
241902
241903 pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1));
241904 if( pNew==0 ){
241905 pParse->rc = SQLITE_NOMEM;
241906 }else{
241907 int *aiCol = pNew->aiCol;
241908 int i, j;
@@ -241753,11 +241933,11 @@
241933 static Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
241934 Fts5Colset *pRet;
241935 int nCol = pParse->pConfig->nCol;
241936
241937 pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
241938 SZ_FTS5COLSET(nCol+1)
241939 );
241940 if( pRet ){
241941 int i;
241942 int iOld = 0;
241943 for(i=0; i<nCol; i++){
@@ -241814,11 +241994,11 @@
241994 ** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
241995 */
241996 static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
241997 Fts5Colset *pRet;
241998 if( pOrig ){
241999 sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol);
242000 pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
242001 if( pRet ){
242002 memcpy(pRet, pOrig, (size_t)nByte);
242003 }
242004 }else{
@@ -241982,21 +242162,21 @@
242162 Fts5ExprNode *pRet;
242163
242164 assert( pNear->nPhrase==1 );
242165 assert( pParse->bPhraseToAnd );
242166
242167 nByte = SZ_FTS5EXPRNODE(nTerm+1);
242168 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
242169 if( pRet ){
242170 pRet->eType = FTS5_AND;
242171 pRet->nChild = nTerm;
242172 pRet->iHeight = 1;
242173 fts5ExprAssignXNext(pRet);
242174 pParse->nPhrase--;
242175 for(ii=0; ii<nTerm; ii++){
242176 Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
242177 &pParse->rc, SZ_FTS5EXPRPHRASE(1)
242178 );
242179 if( pPhrase ){
242180 if( parseGrowPhraseArray(pParse) ){
242181 fts5ExprPhraseFree(pPhrase);
242182 }else{
@@ -242061,11 +242241,11 @@
242241 nChild = 2;
242242 if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
242243 if( pRight->eType==eType ) nChild += pRight->nChild-1;
242244 }
242245
242246 nByte = SZ_FTS5EXPRNODE(nChild);
242247 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
242248
242249 if( pRet ){
242250 pRet->eType = eType;
242251 pRet->pNear = pNear;
@@ -242936,11 +243116,11 @@
243116 }
243117 return rc;
243118 }
243119
243120 /*
243121 ** Clear the token mappings for all Fts5IndexIter objects managed by
243122 ** the expression passed as the only argument.
243123 */
243124 static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
243125 int ii;
243126 for(ii=0; ii<pExpr->nPhrase; ii++){
@@ -242971,11 +243151,11 @@
243151
243152 typedef struct Fts5HashEntry Fts5HashEntry;
243153
243154 /*
243155 ** This file contains the implementation of an in-memory hash table used
243156 ** to accumulate "term -> doclist" content before it is flushed to a level-0
243157 ** segment.
243158 */
243159
243160
243161 struct Fts5Hash {
@@ -243028,11 +243208,11 @@
243208 int iPos; /* Position of last value written */
243209 i64 iRowid; /* Rowid of last value written */
243210 };
243211
243212 /*
243213 ** Equivalent to:
243214 **
243215 ** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
243216 */
243217 #define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
243218
@@ -243964,13 +244144,17 @@
244144 int nRef; /* Object reference count */
244145 u64 nWriteCounter; /* Total leaves written to level 0 */
244146 u64 nOriginCntr; /* Origin value for next top-level segment */
244147 int nSegment; /* Total segments in this structure */
244148 int nLevel; /* Number of levels in this index */
244149 Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */
244150 };
244151
244152 /* Size (in bytes) of an Fts5Structure object holding up to N levels */
244153 #define SZ_FTS5STRUCTURE(N) \
244154 (offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel))
244155
244156 /*
244157 ** An object of type Fts5SegWriter is used to write to segments.
244158 */
244159 struct Fts5PageWriter {
244160 int pgno; /* Page number for this page */
@@ -244096,14 +244280,18 @@
244280
244281 /*
244282 ** Array of tombstone pages. Reference counted.
244283 */
244284 struct Fts5TombstoneArray {
244285 int nRef; /* Number of pointers to this object */
244286 int nTombstone;
244287 Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */
244288 };
244289
244290 /* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */
244291 #define SZ_FTS5TOMBSTONEARRAY(N) \
244292 (offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*))
244293
244294 /*
244295 ** Argument is a pointer to an Fts5Data structure that contains a
244296 ** leaf page.
244297 */
@@ -244169,12 +244357,15 @@
244357 int bRev; /* True to iterate in reverse order */
244358 u8 bSkipEmpty; /* True to skip deleted entries */
244359
244360 i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
244361 Fts5CResult *aFirst; /* Current merge state (see above) */
244362 Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */
244363 };
244364
244365 /* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */
244366 #define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter))
244367
244368 /*
244369 ** An instance of the following type is used to iterate through the contents
244370 ** of a doclist-index record.
244371 **
@@ -244198,12 +244389,16 @@
244389 i64 iRowid; /* First rowid on leaf iLeafPgno */
244390 };
244391 struct Fts5DlidxIter {
244392 int nLvl;
244393 int iSegid;
244394 Fts5DlidxLvl aLvl[FLEXARRAY];
244395 };
244396
244397 /* Size (in bytes) of an Fts5DlidxIter object with up to N levels */
244398 #define SZ_FTS5DLIDXITER(N) \
244399 (offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl))
244400
244401 static void fts5PutU16(u8 *aOut, u16 iVal){
244402 aOut[0] = (iVal>>8);
244403 aOut[1] = (iVal&0xFF);
244404 }
@@ -244568,11 +244763,11 @@
244763 ** an error occurs, (*pRc) is set to an SQLite error code before returning.
244764 */
244765 static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
244766 Fts5Structure *p = *pp;
244767 if( *pRc==SQLITE_OK && p->nRef>1 ){
244768 i64 nByte = SZ_FTS5STRUCTURE(p->nLevel);
244769 Fts5Structure *pNew;
244770 pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
244771 if( pNew ){
244772 int i;
244773 memcpy(pNew, p, nByte);
@@ -244642,14 +244837,11 @@
244837 if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
244838 || nSegment>FTS5_MAX_SEGMENT || nSegment<0
244839 ){
244840 return FTS5_CORRUPT;
244841 }
244842 nByte = SZ_FTS5STRUCTURE(nLevel);
 
 
 
244843 pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
244844
244845 if( pRet ){
244846 pRet->nRef = 1;
244847 pRet->nLevel = nLevel;
@@ -244725,14 +244917,11 @@
244917 fts5StructureMakeWritable(pRc, ppStruct);
244918 assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK );
244919 if( *pRc==SQLITE_OK ){
244920 Fts5Structure *pStruct = *ppStruct;
244921 int nLevel = pStruct->nLevel;
244922 sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2);
 
 
 
244923
244924 pStruct = sqlite3_realloc64(pStruct, nByte);
244925 if( pStruct ){
244926 memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
244927 pStruct->nLevel++;
@@ -245267,11 +245456,11 @@
245456 Fts5DlidxIter *pIter = 0;
245457 int i;
245458 int bDone = 0;
245459
245460 for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
245461 sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1);
245462 Fts5DlidxIter *pNew;
245463
245464 pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
245465 if( pNew==0 ){
245466 p->rc = SQLITE_NOMEM;
@@ -245485,11 +245674,11 @@
245674 ** leave an error in the Fts5Index object.
245675 */
245676 static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
245677 const int nTomb = pIter->pSeg->nPgTombstone;
245678 if( nTomb>0 ){
245679 int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
245680 Fts5TombstoneArray *pNew;
245681 pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
245682 if( pNew ){
245683 pNew->nTombstone = nTomb;
245684 pNew->nRef = 1;
@@ -246946,12 +247135,11 @@
247135 Fts5Iter *pNew;
247136 i64 nSlot; /* Power of two >= nSeg */
247137
247138 for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
247139 pNew = fts5IdxMalloc(p,
247140 SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */
 
247141 sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
247142 );
247143 if( pNew ){
247144 pNew->nSeg = nSlot;
247145 pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
@@ -249313,11 +249501,11 @@
249501 static Fts5Structure *fts5IndexOptimizeStruct(
249502 Fts5Index *p,
249503 Fts5Structure *pStruct
249504 ){
249505 Fts5Structure *pNew = 0;
249506 sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1);
249507 int nSeg = pStruct->nSegment;
249508 int i;
249509
249510 /* Figure out if this structure requires optimization. A structure does
249511 ** not require optimization if either:
@@ -249343,10 +249531,11 @@
249531 }
249532 assert( pStruct->aLevel[i].nMerge<=nThis );
249533 }
249534
249535 nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
249536 assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
249537 pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
249538
249539 if( pNew ){
249540 Fts5StructureLevel *pLvl;
249541 nByte = nSeg * sizeof(Fts5StructureSegment);
@@ -249919,12 +250108,16 @@
250108 /* The following are used for other full-token tokendata queries only. */
250109 int nIter;
250110 int nIterAlloc;
250111 Fts5PoslistReader *aPoslistReader;
250112 int *aPoslistToIter;
250113 Fts5Iter *apIter[FLEXARRAY];
250114 };
250115
250116 /* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */
250117 #define SZ_FTS5TOKENDATAITER(N) \
250118 (offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter))
250119
250120 /*
250121 ** The two input arrays - a1[] and a2[] - are in sorted order. This function
250122 ** merges the two arrays together and writes the result to output array
250123 ** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
@@ -249993,11 +250186,11 @@
250186 }
250187
250188 /*
250189 ** Sort the contents of the pT->aMap[] array.
250190 **
250191 ** The sorting algorithm requires a malloc(). If this fails, an error code
250192 ** is left in Fts5Index.rc before returning.
250193 */
250194 static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
250195 Fts5TokenDataMap *aTmp = 0;
250196 int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
@@ -250184,11 +250377,11 @@
250377 if( iIdx==0
250378 && p->pConfig->eDetail==FTS5_DETAIL_FULL
250379 && p->pConfig->bPrefixInsttoken
250380 ){
250381 s.pTokendata = &s2;
250382 s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1));
250383 }
250384
250385 if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
250386 s.xMerge = fts5MergeRowidLists;
250387 s.xAppend = fts5AppendRowid;
@@ -250312,19 +250505,21 @@
250505 ** The %_data table is completely empty when this function is called. This
250506 ** function populates it with the initial structure objects for each index,
250507 ** and the initial version of the "averages" record (a zero-byte blob).
250508 */
250509 static int sqlite3Fts5IndexReinit(Fts5Index *p){
250510 Fts5Structure *pTmp;
250511 u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
250512 fts5StructureInvalidate(p);
250513 fts5IndexDiscardData(p);
250514 pTmp = (Fts5Structure*)tmpSpace;
250515 memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
250516 if( p->pConfig->bContentlessDelete ){
250517 pTmp->nOriginCntr = 1;
250518 }
250519 fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
250520 fts5StructureWrite(p, pTmp);
250521 return fts5IndexReturn(p);
250522 }
250523
250524 /*
250525 ** Open a new Fts5Index handle. If the bCreate argument is true, create
@@ -250528,11 +250723,11 @@
250723 Fts5TokenDataIter *pRet = pIn;
250724
250725 if( p->rc==SQLITE_OK ){
250726 if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
250727 int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
250728 int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
250729 Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
250730
250731 if( pNew==0 ){
250732 p->rc = SQLITE_NOMEM;
250733 }else{
@@ -251044,11 +251239,12 @@
251239
251240 memset(&ctx, 0, sizeof(ctx));
251241
251242 fts5BufferGrow(&p->rc, &token, nToken+1);
251243 assert( token.p!=0 || p->rc!=SQLITE_OK );
251244 ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
251245 SZ_FTS5TOKENDATAITER(1));
251246
251247 if( p->rc==SQLITE_OK ){
251248
251249 /* Fill in the token prefix to search for */
251250 token.p[0] = FTS5_MAIN_PREFIX;
@@ -251175,11 +251371,12 @@
251371 assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
251372 assert( pIter->pTokenDataIter || pIter->nSeg>0 );
251373 if( pIter->nSeg>0 ){
251374 /* This is a prefix term iterator. */
251375 if( pT==0 ){
251376 pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
251377 SZ_FTS5TOKENDATAITER(1));
251378 pIter->pTokenDataIter = pT;
251379 }
251380 if( pT ){
251381 fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
251382 fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
@@ -252209,11 +252406,11 @@
252406 }
252407 #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
252408
252409 #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
252410 static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
252411 int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid components */
252412 fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
252413
252414 if( iSegid==0 ){
252415 if( iKey==FTS5_AVERAGES_ROWID ){
252416 sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
@@ -253170,13 +253367,15 @@
253367 struct Fts5Sorter {
253368 sqlite3_stmt *pStmt;
253369 i64 iRowid; /* Current rowid */
253370 const u8 *aPoslist; /* Position lists for current row */
253371 int nIdx; /* Number of entries in aIdx[] */
253372 int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
253373 };
253374
253375 /* Size (int bytes) of an Fts5Sorter object with N indexes */
253376 #define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
253377
253378 /*
253379 ** Virtual-table cursor object.
253380 **
253381 ** iSpecial:
@@ -254050,11 +254249,11 @@
254249 int rc;
254250 const char *zRank = pCsr->zRank;
254251 const char *zRankArgs = pCsr->zRankArgs;
254252
254253 nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
254254 nByte = SZ_FTS5SORTER(nPhrase);
254255 pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
254256 if( pSorter==0 ) return SQLITE_NOMEM;
254257 memset(pSorter, 0, (size_t)nByte);
254258 pSorter->nIdx = nPhrase;
254259
@@ -256576,11 +256775,11 @@
256775 int nArg, /* Number of args */
256776 sqlite3_value **apUnused /* Function arguments */
256777 ){
256778 assert( nArg==0 );
256779 UNUSED_PARAM2(nArg, apUnused);
256780 sqlite3_result_text(pCtx, "fts5: 2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185", -1, SQLITE_TRANSIENT);
256781 }
256782
256783 /*
256784 ** Implementation of fts5_locale(LOCALE, TEXT) function.
256785 **
256786
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149149
#define SQLITE_VERSION "3.50.0"
150150
#define SQLITE_VERSION_NUMBER 3050000
151
-#define SQLITE_SOURCE_ID "2025-02-25 18:10:47 e6784af6d50f715338ae3218fc8ba1b894883c27d797f0b7fd2625cac17d9cd7"
151
+#define SQLITE_SOURCE_ID "2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185"
152152
153153
/*
154154
** CAPI3REF: Run-Time Library Version Numbers
155155
** KEYWORDS: sqlite3_version sqlite3_sourceid
156156
**
@@ -5173,11 +5173,11 @@
51735173
** For all versions of SQLite up to and including 3.6.23.1, a call to
51745174
** [sqlite3_reset()] was required after sqlite3_step() returned anything
51755175
** other than [SQLITE_ROW] before any subsequent invocation of
51765176
** sqlite3_step(). Failure to reset the prepared statement using
51775177
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
5178
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
5178
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
51795179
** sqlite3_step() began
51805180
** calling [sqlite3_reset()] automatically in this circumstance rather
51815181
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
51825182
** break because any application that ever receives an SQLITE_MISUSE error
51835183
** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
@@ -7069,10 +7069,12 @@
70697069
** ^Any callback set by a previous call to this function
70707070
** for the same database connection is overridden.
70717071
**
70727072
** ^The second argument is a pointer to the function to invoke when a
70737073
** row is updated, inserted or deleted in a rowid table.
7074
+** ^The update hook is disabled by invoking sqlite3_update_hook()
7075
+** with a NULL pointer as the second parameter.
70747076
** ^The first argument to the callback is a copy of the third argument
70757077
** to sqlite3_update_hook().
70767078
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
70777079
** or [SQLITE_UPDATE], depending on the operation that caused the callback
70787080
** to be invoked.
70797081
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.50.0"
150 #define SQLITE_VERSION_NUMBER 3050000
151 #define SQLITE_SOURCE_ID "2025-02-25 18:10:47 e6784af6d50f715338ae3218fc8ba1b894883c27d797f0b7fd2625cac17d9cd7"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -5173,11 +5173,11 @@
5173 ** For all versions of SQLite up to and including 3.6.23.1, a call to
5174 ** [sqlite3_reset()] was required after sqlite3_step() returned anything
5175 ** other than [SQLITE_ROW] before any subsequent invocation of
5176 ** sqlite3_step(). Failure to reset the prepared statement using
5177 ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
5178 ** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
5179 ** sqlite3_step() began
5180 ** calling [sqlite3_reset()] automatically in this circumstance rather
5181 ** than returning [SQLITE_MISUSE]. This is not considered a compatibility
5182 ** break because any application that ever receives an SQLITE_MISUSE error
5183 ** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
@@ -7069,10 +7069,12 @@
7069 ** ^Any callback set by a previous call to this function
7070 ** for the same database connection is overridden.
7071 **
7072 ** ^The second argument is a pointer to the function to invoke when a
7073 ** row is updated, inserted or deleted in a rowid table.
 
 
7074 ** ^The first argument to the callback is a copy of the third argument
7075 ** to sqlite3_update_hook().
7076 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
7077 ** or [SQLITE_UPDATE], depending on the operation that caused the callback
7078 ** to be invoked.
7079
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,11 +146,11 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.50.0"
150 #define SQLITE_VERSION_NUMBER 3050000
151 #define SQLITE_SOURCE_ID "2025-03-16 00:13:29 18bda13e197e4b4ec7464b3e70012f71edc05f73d8b14bb48bad452f81c7e185"
152
153 /*
154 ** CAPI3REF: Run-Time Library Version Numbers
155 ** KEYWORDS: sqlite3_version sqlite3_sourceid
156 **
@@ -5173,11 +5173,11 @@
5173 ** For all versions of SQLite up to and including 3.6.23.1, a call to
5174 ** [sqlite3_reset()] was required after sqlite3_step() returned anything
5175 ** other than [SQLITE_ROW] before any subsequent invocation of
5176 ** sqlite3_step(). Failure to reset the prepared statement using
5177 ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
5178 ** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
5179 ** sqlite3_step() began
5180 ** calling [sqlite3_reset()] automatically in this circumstance rather
5181 ** than returning [SQLITE_MISUSE]. This is not considered a compatibility
5182 ** break because any application that ever receives an SQLITE_MISUSE error
5183 ** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
@@ -7069,10 +7069,12 @@
7069 ** ^Any callback set by a previous call to this function
7070 ** for the same database connection is overridden.
7071 **
7072 ** ^The second argument is a pointer to the function to invoke when a
7073 ** row is updated, inserted or deleted in a rowid table.
7074 ** ^The update hook is disabled by invoking sqlite3_update_hook()
7075 ** with a NULL pointer as the second parameter.
7076 ** ^The first argument to the callback is a copy of the third argument
7077 ** to sqlite3_update_hook().
7078 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
7079 ** or [SQLITE_UPDATE], depending on the operation that caused the callback
7080 ** to be invoked.
7081
+1 -1
--- src/add.c
+++ src/add.c
@@ -78,11 +78,11 @@
7878
static int numManifests;
7979
8080
if( cachedManifest == -1 ){
8181
int i;
8282
Blob repo;
83
- cachedManifest = db_get_manifest_setting();
83
+ cachedManifest = db_get_manifest_setting(0);
8484
numManifests = 0;
8585
for(i=0; i<count(aManifestflags); i++){
8686
if( cachedManifest&aManifestflags[i].flg ) {
8787
azManifests[numManifests++] = aManifestflags[i].fname;
8888
}
8989
--- src/add.c
+++ src/add.c
@@ -78,11 +78,11 @@
78 static int numManifests;
79
80 if( cachedManifest == -1 ){
81 int i;
82 Blob repo;
83 cachedManifest = db_get_manifest_setting();
84 numManifests = 0;
85 for(i=0; i<count(aManifestflags); i++){
86 if( cachedManifest&aManifestflags[i].flg ) {
87 azManifests[numManifests++] = aManifestflags[i].fname;
88 }
89
--- src/add.c
+++ src/add.c
@@ -78,11 +78,11 @@
78 static int numManifests;
79
80 if( cachedManifest == -1 ){
81 int i;
82 Blob repo;
83 cachedManifest = db_get_manifest_setting(0);
84 numManifests = 0;
85 for(i=0; i<count(aManifestflags); i++){
86 if( cachedManifest&aManifestflags[i].flg ) {
87 azManifests[numManifests++] = aManifestflags[i].fname;
88 }
89
+27 -6
--- src/alerts.c
+++ src/alerts.c
@@ -51,10 +51,11 @@
5151
@ -- f - Forum posts
5252
@ -- k - ** Special: Unsubscribed using /oneclickunsub
5353
@ -- n - New forum threads
5454
@ -- r - Replies to my own forum posts
5555
@ -- t - Ticket changes
56
+@ -- u - Elevation of users' permissions (admins only)
5657
@ -- w - Wiki changes
5758
@ -- x - Edits to forum posts
5859
@ -- Probably different codes will be added in the future. In the future
5960
@ -- we might also add a separate table that allows subscribing to email
6061
@ -- notifications for specific branches or tags or tickets.
@@ -1133,11 +1134,11 @@
11331134
** designated host and port and all times.
11341135
*/
11351136
11361137
11371138
/*
1138
-** COMMAND: alerts* abbreviated-subcommands
1139
+** COMMAND: alerts* abbrv-subcom
11391140
**
11401141
** Usage: %fossil alerts SUBCOMMAND ARGS...
11411142
**
11421143
** Subcommands:
11431144
**
@@ -1258,11 +1259,11 @@
12581259
g.argc = 3;
12591260
}
12601261
pSetting = setting_info(&nSetting);
12611262
for(; nSetting>0; nSetting--, pSetting++ ){
12621263
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
1263
- print_setting(pSetting, 0);
1264
+ print_setting(pSetting, 0, 0);
12641265
}
12651266
}else
12661267
if( strncmp(zCmd, "status", nCmd)==0 ){
12671268
Stmt q;
12681269
int iCutoff;
@@ -1273,11 +1274,11 @@
12731274
verify_all_options();
12741275
if( g.argc!=3 ) usage("status");
12751276
pSetting = setting_info(&nSetting);
12761277
for(; nSetting>0; nSetting--, pSetting++ ){
12771278
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
1278
- print_setting(pSetting, 0);
1279
+ print_setting(pSetting, 0, 0);
12791280
}
12801281
n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
12811282
fossil_print(zFmt/*works-like:"%s%d"*/, "pending-alerts", n);
12821283
n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentDigest");
12831284
fossil_print(zFmt/*works-like:"%s%d"*/, "pending-digest-alerts", n);
@@ -1563,10 +1564,11 @@
15631564
if( g.perm.Read && PB("sc") ) ssub[nsub++] = 'c';
15641565
if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
15651566
if( g.perm.RdForum && PB("sn") ) ssub[nsub++] = 'n';
15661567
if( g.perm.RdForum && PB("sr") ) ssub[nsub++] = 'r';
15671568
if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
1569
+ if( g.perm.Admin && PB("su") ) ssub[nsub++] = 'u';
15681570
if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
15691571
if( g.perm.RdForum && PB("sx") ) ssub[nsub++] = 'x';
15701572
ssub[nsub] = 0;
15711573
zCode = db_text(0,
15721574
"INSERT INTO subscriber(semail,suname,"
@@ -1627,10 +1629,11 @@
16271629
if( g.perm.Read ) cgi_set_parameter_nocopy("sc","1",1);
16281630
if( g.perm.RdForum ) cgi_set_parameter_nocopy("sf","1",1);
16291631
if( g.perm.RdForum ) cgi_set_parameter_nocopy("sn","1",1);
16301632
if( g.perm.RdForum ) cgi_set_parameter_nocopy("sr","1",1);
16311633
if( g.perm.RdTkt ) cgi_set_parameter_nocopy("st","1",1);
1634
+ if( g.perm.Admin ) cgi_set_parameter_nocopy("su","1",1);
16321635
if( g.perm.RdWiki ) cgi_set_parameter_nocopy("sw","1",1);
16331636
}
16341637
@ <p>To receive email notifications for changes to this
16351638
@ repository, fill out the form below and press the "Submit" button.</p>
16361639
form_begin(0, "%R/subscribe");
@@ -1699,10 +1702,14 @@
16991702
}
17001703
if( g.perm.RdWiki ){
17011704
@ <label><input type="checkbox" name="sw" %s(PCK("sw"))> \
17021705
@ Wiki</label><br>
17031706
}
1707
+ if( g.perm.Admin ){
1708
+ @ <label><input type="checkbox" name="su" %s(PCK("su"))> \
1709
+ @ User permission elevation</label>
1710
+ }
17041711
di = PB("di");
17051712
@ </td></tr>
17061713
@ <tr>
17071714
@ <td class="form_label">Delivery:</td>
17081715
@ <td><select size="1" name="di">
@@ -1820,11 +1827,11 @@
18201827
** verifying the email address.
18211828
*/
18221829
void alert_page(void){
18231830
const char *zName = 0; /* Value of the name= query parameter */
18241831
Stmt q; /* For querying the database */
1825
- int sa, sc, sf, st, sw, sx; /* Types of notifications requested */
1832
+ int sa, sc, sf, st, su, sw, sx; /* Types of notifications requested */
18261833
int sn, sr;
18271834
int sdigest = 0, sdonotcall = 0, sverified = 0; /* Other fields */
18281835
int isLogin; /* True if logged in as an individual */
18291836
const char *ssub = 0; /* Subscription flags */
18301837
const char *semail = 0; /* Email address */
@@ -1881,10 +1888,11 @@
18811888
if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
18821889
if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
18831890
if( g.perm.RdForum && PB("sn") ) newSsub[nsub++] = 'n';
18841891
if( g.perm.RdForum && PB("sr") ) newSsub[nsub++] = 'r';
18851892
if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
1893
+ if( g.perm.Admin && PB("su") ) newSsub[nsub++] = 'u';
18861894
if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
18871895
if( g.perm.RdForum && PB("sx") ) newSsub[nsub++] = 'x';
18881896
newSsub[nsub] = 0;
18891897
ssub = newSsub;
18901898
blob_init(&update, "UPDATE subscriber SET", -1);
@@ -1979,10 +1987,11 @@
19791987
sc = strchr(ssub,'c')!=0;
19801988
sf = strchr(ssub,'f')!=0;
19811989
sn = strchr(ssub,'n')!=0;
19821990
sr = strchr(ssub,'r')!=0;
19831991
st = strchr(ssub,'t')!=0;
1992
+ su = strchr(ssub,'u')!=0;
19841993
sw = strchr(ssub,'w')!=0;
19851994
sx = strchr(ssub,'x')!=0;
19861995
smip = db_column_text(&q, 5);
19871996
mtime = db_column_text(&q, 7);
19881997
sctime = db_column_text(&q, 8);
@@ -2097,11 +2106,19 @@
20972106
@ <label><input type="checkbox" name="st" %s(st?"checked":"")>\
20982107
@ Ticket changes</label><br>
20992108
}
21002109
if( g.perm.RdWiki ){
21012110
@ <label><input type="checkbox" name="sw" %s(sw?"checked":"")>\
2102
- @ Wiki</label>
2111
+ @ Wiki</label><br>
2112
+ }
2113
+ if( g.perm.Admin ){
2114
+ /* Corner-case bug: if an admin assigns 'u' to a non-admin, that
2115
+ ** subscription will get removed if the user later edits their
2116
+ ** subscriptions, as non-admins are not permitted to add that
2117
+ ** subscription. */
2118
+ @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\
2119
+ @ User permission elevation</label>
21032120
}
21042121
@ </td></tr>
21052122
if( strchr(ssub,'k')!=0 ){
21062123
@ <tr><td></td><td>&nbsp;&uarr;&nbsp;
21072124
@ Note: User did a one-click unsubscribe</td></tr>
@@ -2529,15 +2546,16 @@
25292546
** f An original forum post
25302547
** n New forum threads
25312548
** r Replies to my forum posts
25322549
** x An edit to a prior forum post
25332550
** t A new ticket or a change to an existing ticket
2551
+** u A user was added or received new permissions
25342552
** w A change to a wiki page
25352553
** x Edits to forum posts
25362554
*/
25372555
struct EmailEvent {
2538
- int type; /* 'c', 'f', 'n', 'r', 't', 'w', 'x' */
2556
+ int type; /* 'c', 'f', 'n', 'r', 't', 'u', 'w', 'x' */
25392557
int needMod; /* Pending moderator approval */
25402558
Blob hdr; /* Header content, for forum entries */
25412559
Blob txt; /* Text description to appear in an alert */
25422560
char *zFromName; /* Human name of the sender */
25432561
char *zPriors; /* Upthread sender IDs for forum posts */
@@ -2932,10 +2950,11 @@
29322950
);
29332951
if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n");
29342952
if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n");
29352953
if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n");
29362954
if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n");
2955
+ if( strchr(zSub, 'u') ) blob_appendf(pBody, " * User permission elevation\n");
29372956
if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n");
29382957
blob_appendf(pBody, "\n"
29392958
"If you take no action, your subscription will expire and you will be\n"
29402959
"unsubscribed in about %d days. To make other changes or to unsubscribe\n"
29412960
"immediately, visit the following webpage:\n\n"
@@ -3144,10 +3163,11 @@
31443163
switch( p->type ){
31453164
case 'x': case 'f':
31463165
case 'n': case 'r': xType = '5'; break;
31473166
case 't': xType = 'q'; break;
31483167
case 'w': xType = 'l'; break;
3168
+ /* Note: case 'u' is not handled here */
31493169
}
31503170
if( strchr(zCap,xType)==0 ) continue;
31513171
}
31523172
}else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){
31533173
/* Setup and admin users can get any notification that does not
@@ -3160,10 +3180,11 @@
31603180
case 'c': xType = 'o'; break;
31613181
case 'x': case 'f':
31623182
case 'n': case 'r': xType = '2'; break;
31633183
case 't': xType = 'r'; break;
31643184
case 'w': xType = 'j'; break;
3185
+ /* Note: case 'u' is not handled here */
31653186
}
31663187
if( strchr(zCap,xType)==0 ) continue;
31673188
}
31683189
if( blob_size(&p->hdr)>0 ){
31693190
/* This alert should be sent as a separate email */
31703191
--- src/alerts.c
+++ src/alerts.c
@@ -51,10 +51,11 @@
51 @ -- f - Forum posts
52 @ -- k - ** Special: Unsubscribed using /oneclickunsub
53 @ -- n - New forum threads
54 @ -- r - Replies to my own forum posts
55 @ -- t - Ticket changes
 
56 @ -- w - Wiki changes
57 @ -- x - Edits to forum posts
58 @ -- Probably different codes will be added in the future. In the future
59 @ -- we might also add a separate table that allows subscribing to email
60 @ -- notifications for specific branches or tags or tickets.
@@ -1133,11 +1134,11 @@
1133 ** designated host and port and all times.
1134 */
1135
1136
1137 /*
1138 ** COMMAND: alerts* abbreviated-subcommands
1139 **
1140 ** Usage: %fossil alerts SUBCOMMAND ARGS...
1141 **
1142 ** Subcommands:
1143 **
@@ -1258,11 +1259,11 @@
1258 g.argc = 3;
1259 }
1260 pSetting = setting_info(&nSetting);
1261 for(; nSetting>0; nSetting--, pSetting++ ){
1262 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
1263 print_setting(pSetting, 0);
1264 }
1265 }else
1266 if( strncmp(zCmd, "status", nCmd)==0 ){
1267 Stmt q;
1268 int iCutoff;
@@ -1273,11 +1274,11 @@
1273 verify_all_options();
1274 if( g.argc!=3 ) usage("status");
1275 pSetting = setting_info(&nSetting);
1276 for(; nSetting>0; nSetting--, pSetting++ ){
1277 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
1278 print_setting(pSetting, 0);
1279 }
1280 n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
1281 fossil_print(zFmt/*works-like:"%s%d"*/, "pending-alerts", n);
1282 n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentDigest");
1283 fossil_print(zFmt/*works-like:"%s%d"*/, "pending-digest-alerts", n);
@@ -1563,10 +1564,11 @@
1563 if( g.perm.Read && PB("sc") ) ssub[nsub++] = 'c';
1564 if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
1565 if( g.perm.RdForum && PB("sn") ) ssub[nsub++] = 'n';
1566 if( g.perm.RdForum && PB("sr") ) ssub[nsub++] = 'r';
1567 if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
 
1568 if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
1569 if( g.perm.RdForum && PB("sx") ) ssub[nsub++] = 'x';
1570 ssub[nsub] = 0;
1571 zCode = db_text(0,
1572 "INSERT INTO subscriber(semail,suname,"
@@ -1627,10 +1629,11 @@
1627 if( g.perm.Read ) cgi_set_parameter_nocopy("sc","1",1);
1628 if( g.perm.RdForum ) cgi_set_parameter_nocopy("sf","1",1);
1629 if( g.perm.RdForum ) cgi_set_parameter_nocopy("sn","1",1);
1630 if( g.perm.RdForum ) cgi_set_parameter_nocopy("sr","1",1);
1631 if( g.perm.RdTkt ) cgi_set_parameter_nocopy("st","1",1);
 
1632 if( g.perm.RdWiki ) cgi_set_parameter_nocopy("sw","1",1);
1633 }
1634 @ <p>To receive email notifications for changes to this
1635 @ repository, fill out the form below and press the "Submit" button.</p>
1636 form_begin(0, "%R/subscribe");
@@ -1699,10 +1702,14 @@
1699 }
1700 if( g.perm.RdWiki ){
1701 @ <label><input type="checkbox" name="sw" %s(PCK("sw"))> \
1702 @ Wiki</label><br>
1703 }
 
 
 
 
1704 di = PB("di");
1705 @ </td></tr>
1706 @ <tr>
1707 @ <td class="form_label">Delivery:</td>
1708 @ <td><select size="1" name="di">
@@ -1820,11 +1827,11 @@
1820 ** verifying the email address.
1821 */
1822 void alert_page(void){
1823 const char *zName = 0; /* Value of the name= query parameter */
1824 Stmt q; /* For querying the database */
1825 int sa, sc, sf, st, sw, sx; /* Types of notifications requested */
1826 int sn, sr;
1827 int sdigest = 0, sdonotcall = 0, sverified = 0; /* Other fields */
1828 int isLogin; /* True if logged in as an individual */
1829 const char *ssub = 0; /* Subscription flags */
1830 const char *semail = 0; /* Email address */
@@ -1881,10 +1888,11 @@
1881 if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
1882 if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
1883 if( g.perm.RdForum && PB("sn") ) newSsub[nsub++] = 'n';
1884 if( g.perm.RdForum && PB("sr") ) newSsub[nsub++] = 'r';
1885 if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
 
1886 if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
1887 if( g.perm.RdForum && PB("sx") ) newSsub[nsub++] = 'x';
1888 newSsub[nsub] = 0;
1889 ssub = newSsub;
1890 blob_init(&update, "UPDATE subscriber SET", -1);
@@ -1979,10 +1987,11 @@
1979 sc = strchr(ssub,'c')!=0;
1980 sf = strchr(ssub,'f')!=0;
1981 sn = strchr(ssub,'n')!=0;
1982 sr = strchr(ssub,'r')!=0;
1983 st = strchr(ssub,'t')!=0;
 
1984 sw = strchr(ssub,'w')!=0;
1985 sx = strchr(ssub,'x')!=0;
1986 smip = db_column_text(&q, 5);
1987 mtime = db_column_text(&q, 7);
1988 sctime = db_column_text(&q, 8);
@@ -2097,11 +2106,19 @@
2097 @ <label><input type="checkbox" name="st" %s(st?"checked":"")>\
2098 @ Ticket changes</label><br>
2099 }
2100 if( g.perm.RdWiki ){
2101 @ <label><input type="checkbox" name="sw" %s(sw?"checked":"")>\
2102 @ Wiki</label>
 
 
 
 
 
 
 
 
2103 }
2104 @ </td></tr>
2105 if( strchr(ssub,'k')!=0 ){
2106 @ <tr><td></td><td>&nbsp;&uarr;&nbsp;
2107 @ Note: User did a one-click unsubscribe</td></tr>
@@ -2529,15 +2546,16 @@
2529 ** f An original forum post
2530 ** n New forum threads
2531 ** r Replies to my forum posts
2532 ** x An edit to a prior forum post
2533 ** t A new ticket or a change to an existing ticket
 
2534 ** w A change to a wiki page
2535 ** x Edits to forum posts
2536 */
2537 struct EmailEvent {
2538 int type; /* 'c', 'f', 'n', 'r', 't', 'w', 'x' */
2539 int needMod; /* Pending moderator approval */
2540 Blob hdr; /* Header content, for forum entries */
2541 Blob txt; /* Text description to appear in an alert */
2542 char *zFromName; /* Human name of the sender */
2543 char *zPriors; /* Upthread sender IDs for forum posts */
@@ -2932,10 +2950,11 @@
2932 );
2933 if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n");
2934 if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n");
2935 if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n");
2936 if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n");
 
2937 if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n");
2938 blob_appendf(pBody, "\n"
2939 "If you take no action, your subscription will expire and you will be\n"
2940 "unsubscribed in about %d days. To make other changes or to unsubscribe\n"
2941 "immediately, visit the following webpage:\n\n"
@@ -3144,10 +3163,11 @@
3144 switch( p->type ){
3145 case 'x': case 'f':
3146 case 'n': case 'r': xType = '5'; break;
3147 case 't': xType = 'q'; break;
3148 case 'w': xType = 'l'; break;
 
3149 }
3150 if( strchr(zCap,xType)==0 ) continue;
3151 }
3152 }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){
3153 /* Setup and admin users can get any notification that does not
@@ -3160,10 +3180,11 @@
3160 case 'c': xType = 'o'; break;
3161 case 'x': case 'f':
3162 case 'n': case 'r': xType = '2'; break;
3163 case 't': xType = 'r'; break;
3164 case 'w': xType = 'j'; break;
 
3165 }
3166 if( strchr(zCap,xType)==0 ) continue;
3167 }
3168 if( blob_size(&p->hdr)>0 ){
3169 /* This alert should be sent as a separate email */
3170
--- src/alerts.c
+++ src/alerts.c
@@ -51,10 +51,11 @@
51 @ -- f - Forum posts
52 @ -- k - ** Special: Unsubscribed using /oneclickunsub
53 @ -- n - New forum threads
54 @ -- r - Replies to my own forum posts
55 @ -- t - Ticket changes
56 @ -- u - Elevation of users' permissions (admins only)
57 @ -- w - Wiki changes
58 @ -- x - Edits to forum posts
59 @ -- Probably different codes will be added in the future. In the future
60 @ -- we might also add a separate table that allows subscribing to email
61 @ -- notifications for specific branches or tags or tickets.
@@ -1133,11 +1134,11 @@
1134 ** designated host and port and all times.
1135 */
1136
1137
1138 /*
1139 ** COMMAND: alerts* abbrv-subcom
1140 **
1141 ** Usage: %fossil alerts SUBCOMMAND ARGS...
1142 **
1143 ** Subcommands:
1144 **
@@ -1258,11 +1259,11 @@
1259 g.argc = 3;
1260 }
1261 pSetting = setting_info(&nSetting);
1262 for(; nSetting>0; nSetting--, pSetting++ ){
1263 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
1264 print_setting(pSetting, 0, 0);
1265 }
1266 }else
1267 if( strncmp(zCmd, "status", nCmd)==0 ){
1268 Stmt q;
1269 int iCutoff;
@@ -1273,11 +1274,11 @@
1274 verify_all_options();
1275 if( g.argc!=3 ) usage("status");
1276 pSetting = setting_info(&nSetting);
1277 for(; nSetting>0; nSetting--, pSetting++ ){
1278 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
1279 print_setting(pSetting, 0, 0);
1280 }
1281 n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
1282 fossil_print(zFmt/*works-like:"%s%d"*/, "pending-alerts", n);
1283 n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentDigest");
1284 fossil_print(zFmt/*works-like:"%s%d"*/, "pending-digest-alerts", n);
@@ -1563,10 +1564,11 @@
1564 if( g.perm.Read && PB("sc") ) ssub[nsub++] = 'c';
1565 if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
1566 if( g.perm.RdForum && PB("sn") ) ssub[nsub++] = 'n';
1567 if( g.perm.RdForum && PB("sr") ) ssub[nsub++] = 'r';
1568 if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
1569 if( g.perm.Admin && PB("su") ) ssub[nsub++] = 'u';
1570 if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
1571 if( g.perm.RdForum && PB("sx") ) ssub[nsub++] = 'x';
1572 ssub[nsub] = 0;
1573 zCode = db_text(0,
1574 "INSERT INTO subscriber(semail,suname,"
@@ -1627,10 +1629,11 @@
1629 if( g.perm.Read ) cgi_set_parameter_nocopy("sc","1",1);
1630 if( g.perm.RdForum ) cgi_set_parameter_nocopy("sf","1",1);
1631 if( g.perm.RdForum ) cgi_set_parameter_nocopy("sn","1",1);
1632 if( g.perm.RdForum ) cgi_set_parameter_nocopy("sr","1",1);
1633 if( g.perm.RdTkt ) cgi_set_parameter_nocopy("st","1",1);
1634 if( g.perm.Admin ) cgi_set_parameter_nocopy("su","1",1);
1635 if( g.perm.RdWiki ) cgi_set_parameter_nocopy("sw","1",1);
1636 }
1637 @ <p>To receive email notifications for changes to this
1638 @ repository, fill out the form below and press the "Submit" button.</p>
1639 form_begin(0, "%R/subscribe");
@@ -1699,10 +1702,14 @@
1702 }
1703 if( g.perm.RdWiki ){
1704 @ <label><input type="checkbox" name="sw" %s(PCK("sw"))> \
1705 @ Wiki</label><br>
1706 }
1707 if( g.perm.Admin ){
1708 @ <label><input type="checkbox" name="su" %s(PCK("su"))> \
1709 @ User permission elevation</label>
1710 }
1711 di = PB("di");
1712 @ </td></tr>
1713 @ <tr>
1714 @ <td class="form_label">Delivery:</td>
1715 @ <td><select size="1" name="di">
@@ -1820,11 +1827,11 @@
1827 ** verifying the email address.
1828 */
1829 void alert_page(void){
1830 const char *zName = 0; /* Value of the name= query parameter */
1831 Stmt q; /* For querying the database */
1832 int sa, sc, sf, st, su, sw, sx; /* Types of notifications requested */
1833 int sn, sr;
1834 int sdigest = 0, sdonotcall = 0, sverified = 0; /* Other fields */
1835 int isLogin; /* True if logged in as an individual */
1836 const char *ssub = 0; /* Subscription flags */
1837 const char *semail = 0; /* Email address */
@@ -1881,10 +1888,11 @@
1888 if( g.perm.Read && PB("sc") ) newSsub[nsub++] = 'c';
1889 if( g.perm.RdForum && PB("sf") ) newSsub[nsub++] = 'f';
1890 if( g.perm.RdForum && PB("sn") ) newSsub[nsub++] = 'n';
1891 if( g.perm.RdForum && PB("sr") ) newSsub[nsub++] = 'r';
1892 if( g.perm.RdTkt && PB("st") ) newSsub[nsub++] = 't';
1893 if( g.perm.Admin && PB("su") ) newSsub[nsub++] = 'u';
1894 if( g.perm.RdWiki && PB("sw") ) newSsub[nsub++] = 'w';
1895 if( g.perm.RdForum && PB("sx") ) newSsub[nsub++] = 'x';
1896 newSsub[nsub] = 0;
1897 ssub = newSsub;
1898 blob_init(&update, "UPDATE subscriber SET", -1);
@@ -1979,10 +1987,11 @@
1987 sc = strchr(ssub,'c')!=0;
1988 sf = strchr(ssub,'f')!=0;
1989 sn = strchr(ssub,'n')!=0;
1990 sr = strchr(ssub,'r')!=0;
1991 st = strchr(ssub,'t')!=0;
1992 su = strchr(ssub,'u')!=0;
1993 sw = strchr(ssub,'w')!=0;
1994 sx = strchr(ssub,'x')!=0;
1995 smip = db_column_text(&q, 5);
1996 mtime = db_column_text(&q, 7);
1997 sctime = db_column_text(&q, 8);
@@ -2097,11 +2106,19 @@
2106 @ <label><input type="checkbox" name="st" %s(st?"checked":"")>\
2107 @ Ticket changes</label><br>
2108 }
2109 if( g.perm.RdWiki ){
2110 @ <label><input type="checkbox" name="sw" %s(sw?"checked":"")>\
2111 @ Wiki</label><br>
2112 }
2113 if( g.perm.Admin ){
2114 /* Corner-case bug: if an admin assigns 'u' to a non-admin, that
2115 ** subscription will get removed if the user later edits their
2116 ** subscriptions, as non-admins are not permitted to add that
2117 ** subscription. */
2118 @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\
2119 @ User permission elevation</label>
2120 }
2121 @ </td></tr>
2122 if( strchr(ssub,'k')!=0 ){
2123 @ <tr><td></td><td>&nbsp;&uarr;&nbsp;
2124 @ Note: User did a one-click unsubscribe</td></tr>
@@ -2529,15 +2546,16 @@
2546 ** f An original forum post
2547 ** n New forum threads
2548 ** r Replies to my forum posts
2549 ** x An edit to a prior forum post
2550 ** t A new ticket or a change to an existing ticket
2551 ** u A user was added or received new permissions
2552 ** w A change to a wiki page
2553 ** x Edits to forum posts
2554 */
2555 struct EmailEvent {
2556 int type; /* 'c', 'f', 'n', 'r', 't', 'u', 'w', 'x' */
2557 int needMod; /* Pending moderator approval */
2558 Blob hdr; /* Header content, for forum entries */
2559 Blob txt; /* Text description to appear in an alert */
2560 char *zFromName; /* Human name of the sender */
2561 char *zPriors; /* Upthread sender IDs for forum posts */
@@ -2932,10 +2950,11 @@
2950 );
2951 if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n");
2952 if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n");
2953 if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n");
2954 if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n");
2955 if( strchr(zSub, 'u') ) blob_appendf(pBody, " * User permission elevation\n");
2956 if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n");
2957 blob_appendf(pBody, "\n"
2958 "If you take no action, your subscription will expire and you will be\n"
2959 "unsubscribed in about %d days. To make other changes or to unsubscribe\n"
2960 "immediately, visit the following webpage:\n\n"
@@ -3144,10 +3163,11 @@
3163 switch( p->type ){
3164 case 'x': case 'f':
3165 case 'n': case 'r': xType = '5'; break;
3166 case 't': xType = 'q'; break;
3167 case 'w': xType = 'l'; break;
3168 /* Note: case 'u' is not handled here */
3169 }
3170 if( strchr(zCap,xType)==0 ) continue;
3171 }
3172 }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){
3173 /* Setup and admin users can get any notification that does not
@@ -3160,10 +3180,11 @@
3180 case 'c': xType = 'o'; break;
3181 case 'x': case 'f':
3182 case 'n': case 'r': xType = '2'; break;
3183 case 't': xType = 'r'; break;
3184 case 'w': xType = 'j'; break;
3185 /* Note: case 'u' is not handled here */
3186 }
3187 if( strchr(zCap,xType)==0 ) continue;
3188 }
3189 if( blob_size(&p->hdr)>0 ){
3190 /* This alert should be sent as a separate email */
3191
+2 -1
--- src/allrepo.c
+++ src/allrepo.c
@@ -51,11 +51,11 @@
5151
blob_appendf(pExtra, " %s", g.argv[i]);
5252
}
5353
}
5454
5555
/*
56
-** COMMAND: all abbreviated-subcommands
56
+** COMMAND: all abbrv-subcom
5757
**
5858
** Usage: %fossil all SUBCOMMAND ...
5959
**
6060
** The ~/.fossil file records the location of all repositories for a
6161
** user. This command performs certain operations on all repositories
@@ -316,10 +316,11 @@
316316
zCmd = "repack";
317317
}else if( fossil_strcmp(zCmd, "set")==0
318318
|| fossil_strcmp(zCmd, "setting")==0
319319
|| fossil_strcmp(zCmd, "settings")==0 ){
320320
zCmd = "settings -R";
321
+ collect_argument(&extra, "changed", 0);
321322
collect_argv(&extra, 3);
322323
}else if( fossil_strcmp(zCmd, "unset")==0 ){
323324
zCmd = "unset -R";
324325
collect_argv(&extra, 3);
325326
}else if( fossil_strcmp(zCmd, "fts-config")==0 ){
326327
--- src/allrepo.c
+++ src/allrepo.c
@@ -51,11 +51,11 @@
51 blob_appendf(pExtra, " %s", g.argv[i]);
52 }
53 }
54
55 /*
56 ** COMMAND: all abbreviated-subcommands
57 **
58 ** Usage: %fossil all SUBCOMMAND ...
59 **
60 ** The ~/.fossil file records the location of all repositories for a
61 ** user. This command performs certain operations on all repositories
@@ -316,10 +316,11 @@
316 zCmd = "repack";
317 }else if( fossil_strcmp(zCmd, "set")==0
318 || fossil_strcmp(zCmd, "setting")==0
319 || fossil_strcmp(zCmd, "settings")==0 ){
320 zCmd = "settings -R";
 
321 collect_argv(&extra, 3);
322 }else if( fossil_strcmp(zCmd, "unset")==0 ){
323 zCmd = "unset -R";
324 collect_argv(&extra, 3);
325 }else if( fossil_strcmp(zCmd, "fts-config")==0 ){
326
--- src/allrepo.c
+++ src/allrepo.c
@@ -51,11 +51,11 @@
51 blob_appendf(pExtra, " %s", g.argv[i]);
52 }
53 }
54
55 /*
56 ** COMMAND: all abbrv-subcom
57 **
58 ** Usage: %fossil all SUBCOMMAND ...
59 **
60 ** The ~/.fossil file records the location of all repositories for a
61 ** user. This command performs certain operations on all repositories
@@ -316,10 +316,11 @@
316 zCmd = "repack";
317 }else if( fossil_strcmp(zCmd, "set")==0
318 || fossil_strcmp(zCmd, "setting")==0
319 || fossil_strcmp(zCmd, "settings")==0 ){
320 zCmd = "settings -R";
321 collect_argument(&extra, "changed", 0);
322 collect_argv(&extra, 3);
323 }else if( fossil_strcmp(zCmd, "unset")==0 ){
324 zCmd = "unset -R";
325 collect_argv(&extra, 3);
326 }else if( fossil_strcmp(zCmd, "fts-config")==0 ){
327
+1 -1
--- src/cache.c
+++ src/cache.c
@@ -255,11 +255,11 @@
255255
void cache_initialize(void){
256256
sqlite3_close(cacheOpen(1));
257257
}
258258
259259
/*
260
-** COMMAND: cache* abbreviated-subcommands
260
+** COMMAND: cache* abbrv-subcom
261261
**
262262
** Usage: %fossil cache SUBCOMMAND
263263
**
264264
** Manage the cache used for potentially expensive web pages such as
265265
** /zip and /tarball. SUBCOMMAND can be:
266266
--- src/cache.c
+++ src/cache.c
@@ -255,11 +255,11 @@
255 void cache_initialize(void){
256 sqlite3_close(cacheOpen(1));
257 }
258
259 /*
260 ** COMMAND: cache* abbreviated-subcommands
261 **
262 ** Usage: %fossil cache SUBCOMMAND
263 **
264 ** Manage the cache used for potentially expensive web pages such as
265 ** /zip and /tarball. SUBCOMMAND can be:
266
--- src/cache.c
+++ src/cache.c
@@ -255,11 +255,11 @@
255 void cache_initialize(void){
256 sqlite3_close(cacheOpen(1));
257 }
258
259 /*
260 ** COMMAND: cache* abbrv-subcom
261 **
262 ** Usage: %fossil cache SUBCOMMAND
263 **
264 ** Manage the cache used for potentially expensive web pages such as
265 ** /zip and /tarball. SUBCOMMAND can be:
266
+25 -5
--- src/cgi.c
+++ src/cgi.c
@@ -688,21 +688,41 @@
688688
}
689689
690690
691691
/*
692692
** Return true if the current request is coming from the same origin.
693
+**
694
+** If the request comes from a different origin and bErrorLog is true, then
695
+** put a warning message on the error log as this was a possible hack
696
+** attempt.
693697
*/
694
-int cgi_same_origin(void){
698
+int cgi_same_origin(int bErrorLog){
695699
const char *zRef;
700
+ char *zToFree = 0;
696701
int nBase;
702
+ int rc;
697703
if( g.zBaseURL==0 ) return 0;
698704
zRef = P("HTTP_REFERER");
699705
if( zRef==0 ) return 0;
706
+ if( strchr(zRef,'%')!=0 ){
707
+ zToFree = strdup(zRef);
708
+ dehttpize(zToFree);
709
+ zRef = zToFree;
710
+ }
700711
nBase = (int)strlen(g.zBaseURL);
701
- if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
702
- if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
703
- return 1;
712
+ if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ){
713
+ rc = 0;
714
+ }else if( zRef[nBase]!=0 && zRef[nBase]!='/' ){
715
+ rc = 0;
716
+ }else{
717
+ rc = 1;
718
+ }
719
+ if( rc==0 && bErrorLog && fossil_strcmp(P("REQUST_METHOD"),"POST")==0 ){
720
+ fossil_errorlog("warning: POST from different origin");
721
+ }
722
+ fossil_free(zToFree);
723
+ return rc;
704724
}
705725
706726
/*
707727
** Return true if the current CGI request is a POST request
708728
*/
@@ -733,11 +753,11 @@
733753
** 3: (2) plus there is a valid "csrf" token in the request
734754
*/
735755
int cgi_csrf_safe(int securityLevel){
736756
if( g.okCsrf<0 ) return 0;
737757
if( g.okCsrf==0 ){
738
- if( !cgi_same_origin() ){
758
+ if( !cgi_same_origin(1) ){
739759
g.okCsrf = -1;
740760
}else{
741761
g.okCsrf = 1;
742762
if( cgi_is_post_request() ){
743763
g.okCsrf = 2;
744764
--- src/cgi.c
+++ src/cgi.c
@@ -688,21 +688,41 @@
688 }
689
690
691 /*
692 ** Return true if the current request is coming from the same origin.
 
 
 
 
693 */
694 int cgi_same_origin(void){
695 const char *zRef;
 
696 int nBase;
 
697 if( g.zBaseURL==0 ) return 0;
698 zRef = P("HTTP_REFERER");
699 if( zRef==0 ) return 0;
 
 
 
 
 
700 nBase = (int)strlen(g.zBaseURL);
701 if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
702 if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
703 return 1;
 
 
 
 
 
 
 
 
 
704 }
705
706 /*
707 ** Return true if the current CGI request is a POST request
708 */
@@ -733,11 +753,11 @@
733 ** 3: (2) plus there is a valid "csrf" token in the request
734 */
735 int cgi_csrf_safe(int securityLevel){
736 if( g.okCsrf<0 ) return 0;
737 if( g.okCsrf==0 ){
738 if( !cgi_same_origin() ){
739 g.okCsrf = -1;
740 }else{
741 g.okCsrf = 1;
742 if( cgi_is_post_request() ){
743 g.okCsrf = 2;
744
--- src/cgi.c
+++ src/cgi.c
@@ -688,21 +688,41 @@
688 }
689
690
691 /*
692 ** Return true if the current request is coming from the same origin.
693 **
694 ** If the request comes from a different origin and bErrorLog is true, then
695 ** put a warning message on the error log as this was a possible hack
696 ** attempt.
697 */
698 int cgi_same_origin(int bErrorLog){
699 const char *zRef;
700 char *zToFree = 0;
701 int nBase;
702 int rc;
703 if( g.zBaseURL==0 ) return 0;
704 zRef = P("HTTP_REFERER");
705 if( zRef==0 ) return 0;
706 if( strchr(zRef,'%')!=0 ){
707 zToFree = strdup(zRef);
708 dehttpize(zToFree);
709 zRef = zToFree;
710 }
711 nBase = (int)strlen(g.zBaseURL);
712 if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ){
713 rc = 0;
714 }else if( zRef[nBase]!=0 && zRef[nBase]!='/' ){
715 rc = 0;
716 }else{
717 rc = 1;
718 }
719 if( rc==0 && bErrorLog && fossil_strcmp(P("REQUST_METHOD"),"POST")==0 ){
720 fossil_errorlog("warning: POST from different origin");
721 }
722 fossil_free(zToFree);
723 return rc;
724 }
725
726 /*
727 ** Return true if the current CGI request is a POST request
728 */
@@ -733,11 +753,11 @@
753 ** 3: (2) plus there is a valid "csrf" token in the request
754 */
755 int cgi_csrf_safe(int securityLevel){
756 if( g.okCsrf<0 ) return 0;
757 if( g.okCsrf==0 ){
758 if( !cgi_same_origin(1) ){
759 g.okCsrf = -1;
760 }else{
761 g.okCsrf = 1;
762 if( cgi_is_post_request() ){
763 g.okCsrf = 2;
764
+252 -70
--- src/checkin.c
+++ src/checkin.c
@@ -2281,42 +2281,165 @@
22812281
static int tagCmp(const void *a, const void *b){
22822282
char **pA = (char**)a;
22832283
char **pB = (char**)b;
22842284
return fossil_strcmp(pA[0], pB[0]);
22852285
}
2286
+
2287
+/*
2288
+** SETTING: verify-comments width=8 default=on
2289
+**
2290
+** This setting determines how much sanity checking, if any, the
2291
+** "fossil commit" and "fossil amend" commands do against check-in
2292
+** comments. Recognized values:
2293
+**
2294
+** on (Default) Check for bad syntax in check-in comments
2295
+** and offer the user a chance to continue editing for
2296
+** interactive sessions, or simply abort the commit if
2297
+** commit was entered using -m or -M
2298
+**
2299
+** off Do not do syntax checking of any kind
2300
+**
2301
+** links Similar to "on", except only check for bad hyperlinks
2302
+**
2303
+** preview Do all the same checks as "on" but also preview the
2304
+** check-in comment to the user during interactive sessions
2305
+** and provide an opportunity to accept or re-edit
2306
+*/
2307
+
2308
+#if INTERFACE
2309
+#define COMCK_LINKS 0x01 /* Check for back hyperlinks */
2310
+#define COMCK_MARKUP 0x02 /* Check markup */
2311
+#define COMCK_PREVIEW 0x04 /* Always preview, even if no issues found */
2312
+#define COMCK_NOPREVIEW 0x08 /* Never preview, even for other errors */
2313
+#endif /* INTERFACE */
2314
+
2315
+/*
2316
+** Check for possible formatting errors in the comment string pComment.
2317
+**
2318
+** If concerns are found, write a description of the problem(s) to
2319
+** stdout and return non-zero. The return value is some combination
2320
+** of the COMCK_* flags, depending on what went wrong.
2321
+**
2322
+** If no issues are seen, do not output anything and return zero.
2323
+*/
2324
+int suspicious_comment(Blob *pComment, int mFlags){
2325
+ char *zStart = blob_str(pComment);
2326
+ char *z;
2327
+ char *zEnd, *zEnd2;
2328
+ char *zSep;
2329
+ char cSave1;
2330
+ int nIssue = 0;
2331
+ int rc = mFlags & COMCK_PREVIEW;
2332
+ Blob out;
2333
+ static const char zSpecial[] = "\\&<*_`[";
2334
+
2335
+ if( mFlags==0 ) return 0;
2336
+ z = zStart;
2337
+ blob_init(&out, 0, 0);
2338
+ if( mFlags & COMCK_LINKS ){
2339
+ while( (z = strchr(z,'['))!=0 ){
2340
+ zEnd = strchr(z,']');
2341
+ if( zEnd==0 ){
2342
+ blob_appendf(&out,"\n (%d) ", ++nIssue);
2343
+ blob_appendf(&out, "Unterminated hyperlink \"%.12s...\"", z);
2344
+ break;
2345
+ }
2346
+ if( zEnd[1]=='(' && (zEnd2 = strchr(zEnd,')'))!=0 ){
2347
+ blob_appendf(&out,"\n (%d) ", ++nIssue);
2348
+ blob_appendf(&out, "Markdown hyperlink syntax: %.*s",
2349
+ (int)(zEnd2+1-z), z);
2350
+ z = zEnd2;
2351
+ continue;
2352
+ }
2353
+ zSep = strchr(z+1,'|');
2354
+ if( zSep==0 || zSep>zEnd ) zSep = zEnd;
2355
+ while( zSep>z && fossil_isspace(zSep[-1]) ) zSep--;
2356
+ cSave1 = zSep[0];
2357
+ zSep[0] = 0;
2358
+ if( !wiki_valid_link_target(z+1) ){
2359
+ blob_appendf(&out,"\n (%d) ", ++nIssue);
2360
+ blob_appendf(&out, "Broken hyperlink: [%s]", z+1);
2361
+ }
2362
+ zSep[0] = cSave1;
2363
+ z = zEnd;
2364
+ }
2365
+ }
2366
+
2367
+ if( nIssue>0
2368
+ || (mFlags & COMCK_PREVIEW)!=0
2369
+ || ((mFlags & COMCK_MARKUP)!=0 && strcspn(zStart,zSpecial)<strlen(zStart))
2370
+ ){
2371
+ char zGot[16];
2372
+ int nGot = 0;
2373
+ int i;
2374
+ if( (mFlags & COMCK_MARKUP)!=0 ){
2375
+ for(i=0; zSpecial[i]; i++){
2376
+ if( strchr(zStart,zSpecial[i]) ) zGot[nGot++] = zSpecial[i];
2377
+ }
2378
+ }
2379
+ zGot[nGot] = 0;
2380
+ if( nGot>0 ) rc |= COMCK_MARKUP;
2381
+ if( nGot>0 && nIssue>0 ){
2382
+ blob_appendf(&out,"\n (%d) Comment uses special character%s \"%s\"",
2383
+ ++nIssue, (nGot>1 ? "s" : ""), zGot);
2384
+ nGot = 0;
2385
+ }
2386
+ if( nIssue ){
2387
+ rc |= COMCK_LINKS;
2388
+ fossil_print(
2389
+ "Possible comment formatting error%s:%b\n",
2390
+ nIssue>1 ? "s" : "", &out
2391
+ );
2392
+ }
2393
+ if( (mFlags & COMCK_NOPREVIEW)==0 ){
2394
+ Blob in, html, txt;
2395
+ blob_init(&in, blob_str(pComment), -1);
2396
+ blob_init(&html, 0, 0);
2397
+ blob_init(&txt, 0, 0);
2398
+ wiki_convert(&in, &html, WIKI_INLINE);
2399
+ html_to_plaintext(blob_str(&html), &txt);
2400
+ if( nGot>0 ){
2401
+ fossil_print(
2402
+ "The comment uses special character%s \"%s\". "
2403
+ "Does it render as you expect?\n\n ",
2404
+ (nGot>1 ? "s" : ""), zGot
2405
+ );
2406
+ }else{
2407
+ fossil_print("Preview of the check-in comment:\n\n ");
2408
+ }
2409
+ comment_print(blob_str(&txt), 0, 3, -1, get_comment_format());
2410
+ blob_reset(&in);
2411
+ blob_reset(&html);
2412
+ blob_reset(&txt);
2413
+ }
2414
+ }
2415
+ blob_reset(&out);
2416
+ return rc;
2417
+}
22862418
22872419
/*
22882420
** COMMAND: ci#
22892421
** COMMAND: commit
22902422
**
22912423
** Usage: %fossil commit ?OPTIONS? ?FILE...?
22922424
** or: %fossil ci ?OPTIONS? ?FILE...?
22932425
**
2294
-** Create a new version containing all of the changes in the current
2295
-** check-out. You will be prompted to enter a check-in comment unless
2296
-** the comment has been specified on the command-line using "-m" or a
2297
-** file containing the comment using -M. The editor defined in the
2298
-** "editor" fossil option (see %fossil help set) will be used, or from
2299
-** the "VISUAL" or "EDITOR" environment variables (in that order) if
2300
-** no editor is set.
2426
+** Create a new check-in containing all of the changes in the current
2427
+** check-out. All changes are committed unless some subset of files
2428
+** is specified on the command line, in which case only the named files
2429
+** become part of the new check-in.
23012430
**
2302
-** All files that have changed will be committed unless some subset of
2303
-** files is specified on the command line.
2431
+** You will be prompted to enter a check-in comment unless the comment
2432
+** has been specified on the command-line using "-m" or "-M". The
2433
+** text editor used is determined by the "editor" setting, or by the
2434
+** "VISUAL" or "EDITOR" environment variables. Commit message text is
2435
+** interpreted as fossil-wiki format. Potentially misformatted check-in
2436
+** comment text is detected and reported unless the --no-verify-comment
2437
+** option is used.
23042438
**
23052439
** The --branch option followed by a branch name causes the new
2306
-** check-in to be placed in a newly-created branch with the name
2307
-** passed to the --branch option.
2308
-**
2309
-** Use the --branchcolor option followed by a color name (ex:
2310
-** '#ffc0c0') to specify the background color of entries in the new
2311
-** branch when shown in the web timeline interface. The use of
2312
-** the --branchcolor option is not recommended. Instead, let Fossil
2313
-** choose the branch color automatically.
2314
-**
2315
-** The --bgcolor option works like --branchcolor but only sets the
2316
-** background color for a single check-in. Subsequent check-ins revert
2317
-** to the default color.
2440
+** check-in to be placed in a newly-created branch with name specified.
23182441
**
23192442
** A check-in is not permitted to fork unless the --allow-fork option
23202443
** appears. An empty check-in (i.e. with nothing changed) is not
23212444
** allowed unless the --allow-empty option appears. A check-in may not
23222445
** be older than its ancestor unless the --allow-older option appears.
@@ -2328,68 +2451,60 @@
23282451
** unless the interactive user chooses to proceed. If there is no
23292452
** interactive user or these warnings should be skipped for some other
23302453
** reason, the --no-warnings option may be used. A check-in is not
23312454
** allowed against a closed leaf.
23322455
**
2333
-** If a commit message is blank, you will be prompted:
2334
-** ("continue (y/N)?") to confirm you really want to commit with a
2335
-** blank commit message. The default value is "N", do not commit.
2336
-**
23372456
** The --private option creates a private check-in that is never synced.
23382457
** Children of private check-ins are automatically private.
23392458
**
23402459
** The --tag option applies the symbolic tag name to the check-in.
2341
-**
2342
-** The --hash option detects edited files by computing each file's
2343
-** artifact hash rather than just checking for changes to its size or mtime.
2460
+** The --tag option can be repeated to assign multiple tags to a check-in.
2461
+** For example: "... --tag release --tag version-1.2.3 ..."
23442462
**
23452463
** Options:
23462464
** --allow-conflict Allow unresolved merge conflicts
23472465
** --allow-empty Allow a commit with no changes
23482466
** --allow-fork Allow the commit to fork
23492467
** --allow-older Allow a commit older than its ancestor
23502468
** --baseline Use a baseline manifest in the commit process
2351
-** --bgcolor COLOR Apply COLOR to this one check-in only
23522469
** --branch NEW-BRANCH-NAME Check in to this new branch
2353
-** --branchcolor COLOR Apply given COLOR to the branch
23542470
** --close Close the branch being committed
2355
-** --date-override DATETIME DATE to use instead of 'now'
2471
+** --date-override DATETIME Make DATETIME the time of the check-in.
2472
+** Useful when importing historical check-ins
2473
+** from another version control system.
23562474
** --delta Use a delta manifest in the commit process
23572475
** --hash Verify file status using hashing rather
2358
-** than relying on file mtimes
2476
+** than relying on filesystem mtimes
23592477
** --if-changes Make this command a silent no-op if there
23602478
** are no changes
23612479
** --ignore-clock-skew If a clock skew is detected, ignore it and
23622480
** behave as if the user had entered 'yes' to
23632481
** the question of whether to proceed despite
23642482
** the skew.
23652483
** --ignore-oversize Do not warn the user about oversized files
23662484
** --integrate Close all merged-in branches
2367
-** -m|--comment COMMENT-TEXT Use COMMENT-TEXT as commit comment
2368
-** -M|--message-file FILE Read the commit comment from given file
2369
-** --mimetype MIMETYPE Mimetype of check-in comment
2370
-** -n|--dry-run If given, display instead of run actions
2485
+** -m|--comment COMMENT-TEXT Use COMMENT-TEXT as the check-in comment
2486
+** -M|--message-file FILE Read the check-in comment from FILE
2487
+** -n|--dry-run Do not actually create a new check-in. Just
2488
+** show what would have happened. For debugging.
23712489
** -v|--verbose Show a diff in the commit message prompt
23722490
** --no-prompt This option disables prompting the user for
23732491
** input and assumes an answer of 'No' for every
23742492
** question.
23752493
** --no-warnings Omit all warnings about file contents
23762494
** --no-verify Do not run before-commit hooks
2495
+** --no-verify-comment Do not validate the check-in comment
23772496
** --nosign Do not attempt to sign this commit with gpg
23782497
** --nosync Do not auto-sync prior to committing
23792498
** --override-lock Allow a check-in even though parent is locked
2380
-** --private Do not sync changes and their descendants
2499
+** --private Never sync the resulting check-in and make
2500
+** all descendants private too.
23812501
** --proxy PROXY Use PROXY as http proxy during sync operation
2382
-** --tag TAG-NAME Assign given tag TAG-NAME to the check-in
2502
+** --tag TAG-NAME Add TAG-NAME to the check-in. May be repeated.
23832503
** --trace Debug tracing
2384
-** --user-override USER USER to use instead of the current default
2385
-**
2386
-** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
2387
-** year-month-day form, it may be truncated, the "T" may be replaced by
2388
-** a space, and it may also name a timezone offset from UTC as "-HH:MM"
2389
-** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
2390
-** means UTC.
2504
+** --user-override USER Record USER as the login that created the
2505
+** new check-in, rather that the current user.
23912506
**
23922507
** See also: [[branch]], [[changes]], [[update]], [[extras]], [[sync]]
23932508
*/
23942509
void commit_cmd(void){
23952510
int hasChanges; /* True if unsaved changes exist */
@@ -2415,10 +2530,11 @@
24152530
int allowConflict = 0; /* Allow unresolve merge conflicts */
24162531
int allowEmpty = 0; /* Allow a commit with no changes */
24172532
int onlyIfChanges = 0; /* No-op if there are no changes */
24182533
int allowFork = 0; /* Allow the commit to fork */
24192534
int allowOlder = 0; /* Allow a commit older than its ancestor */
2535
+ int noVerifyCom = 0; /* Allow suspicious check-in comments */
24202536
char *zManifestFile; /* Name of the manifest file */
24212537
int useCksum; /* True if checksums should be computed and verified */
24222538
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
24232539
int dryRunFlag; /* True for a test run. Debugging only */
24242540
CheckinInfo sCiInfo; /* Information about this check-in */
@@ -2440,10 +2556,11 @@
24402556
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
24412557
int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
24422558
int mxSize;
24432559
char *zCurBranch = 0; /* The current branch name of checkout */
24442560
char *zNewBranch = 0; /* The branch name after update */
2561
+ int ckComFlgs; /* Flags passed to suspicious_comment() */
24452562
24462563
memset(&sCiInfo, 0, sizeof(sCiInfo));
24472564
url_proxy_options();
24482565
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
24492566
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
@@ -2470,24 +2587,30 @@
24702587
}
24712588
zComment = find_option("comment","m",1);
24722589
forceFlag = find_option("force", "f", 0)!=0;
24732590
allowConflict = find_option("allow-conflict",0,0)!=0;
24742591
allowEmpty = find_option("allow-empty",0,0)!=0;
2592
+ noVerifyCom = find_option("no-verify-comment",0,0)!=0;
24752593
onlyIfChanges = find_option("if-changes",0,0)!=0;
24762594
allowFork = find_option("allow-fork",0,0)!=0;
24772595
if( find_option("override-lock",0,0)!=0 ) allowFork = 1;
24782596
allowOlder = find_option("allow-older",0,0)!=0;
24792597
noPrompt = find_option("no-prompt", 0, 0)!=0;
24802598
noWarningFlag = find_option("no-warnings", 0, 0)!=0;
24812599
noVerify = find_option("no-verify",0,0)!=0;
24822600
bTrace = find_option("trace",0,0)!=0;
24832601
sCiInfo.zBranch = find_option("branch","b",1);
2484
- sCiInfo.zColor = find_option("bgcolor",0,1);
2485
- sCiInfo.zBrClr = find_option("branchcolor",0,1);
2602
+
2603
+ /* NB: the --bgcolor and --branchcolor flags still work, but are
2604
+ ** now undocumented, to discourage their use. --mimetype has never
2605
+ ** been used for anything, so also leave it undocumented */
2606
+ sCiInfo.zColor = find_option("bgcolor",0,1); /* Deprecated, undocumented*/
2607
+ sCiInfo.zBrClr = find_option("branchcolor",0,1); /* Deprecated, undocumented*/
2608
+ sCiInfo.zMimetype = find_option("mimetype",0,1); /* Deprecated, undocumented*/
2609
+
24862610
sCiInfo.closeFlag = find_option("close",0,0)!=0;
24872611
sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
2488
- sCiInfo.zMimetype = find_option("mimetype",0,1);
24892612
sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
24902613
while( (zTag = find_option("tag",0,1))!=0 ){
24912614
if( zTag[0]==0 ) continue;
24922615
sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag,
24932616
sizeof(char*)*(nTag+2));
@@ -2499,14 +2622,20 @@
24992622
sCiInfo.zUserOvrd = find_option("user-override",0,1);
25002623
noSign = db_get_boolean("omitsign", 0)|noSign;
25012624
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
25022625
useCksum = db_get_boolean("repo-cksum", 1);
25032626
bIgnoreSkew = find_option("ignore-clock-skew",0,0)!=0;
2504
- outputManifest = db_get_manifest_setting();
2627
+ outputManifest = db_get_manifest_setting(0);
25052628
mxSize = db_large_file_size();
25062629
if( find_option("ignore-oversize",0,0)!=0 ) mxSize = 0;
25072630
verify_all_options();
2631
+
2632
+ /* The --no-warnings flag and the --force flag each imply
2633
+ ** the --no-verify-comment flag */
2634
+ if( noWarningFlag || forceFlag ){
2635
+ noVerifyCom = 1;
2636
+ }
25082637
25092638
/* Get the ID of the parent manifest artifact */
25102639
vid = db_lget_int("checkout", 0);
25112640
if( vid==0 ){
25122641
useCksum = 1;
@@ -2607,33 +2736,35 @@
26072736
fossil_exit(1);
26082737
}
26092738
}
26102739
26112740
/* So that older versions of Fossil (that do not understand delta-
2612
- ** manifest) can continue to use this repository, do not create a new
2741
+ ** manifest) can continue to use this repository, and because
2742
+ ** delta manifests are usually a bad idea unless the repository
2743
+ ** has a really large number of files, do not create a new
26132744
** delta-manifest unless this repository already contains one or more
26142745
** delta-manifests, or unless the delta-manifest is explicitly requested
26152746
** by the --delta option.
26162747
**
2617
- ** The forbid-delta-manifests setting prevents new delta manifests.
2748
+ ** The forbid-delta-manifests setting prevents new delta manifests,
2749
+ ** even if the --delta option is used.
26182750
**
26192751
** If the remote repository sent an avoid-delta-manifests pragma on
2620
- ** the autosync above, then also try to avoid deltas, unless the
2752
+ ** the autosync above, then also forbid delta manifests, even if the
26212753
** --delta option is specified. The remote repo will send the
2622
- ** avoid-delta-manifests pragma if it has its "forbid-delta-manifests"
2623
- ** setting enabled.
2754
+ ** avoid-delta-manifests pragma if its "forbid-delta-manifests"
2755
+ ** setting is enabled.
26242756
*/
2625
- if( !db_get_boolean("seen-delta-manifest",0)
2757
+ if( !(forceDelta || db_get_boolean("seen-delta-manifest",0))
26262758
|| db_get_boolean("forbid-delta-manifests",0)
26272759
|| g.bAvoidDeltaManifests
26282760
){
2629
- if( !forceDelta ) forceBaseline = 1;
2761
+ forceBaseline = 1;
26302762
}
2631
-
26322763
26332764
/* Require confirmation to continue with the check-in if there is
2634
- ** clock skew
2765
+ ** clock skew. This helps to prevent timewarps.
26352766
*/
26362767
if( g.clockSkewSeen ){
26372768
if( bIgnoreSkew!=0 ){
26382769
cReply = 'y';
26392770
fossil_warning("Clock skew ignored due to --ignore-clock-skew.");
@@ -2788,35 +2919,86 @@
27882919
fossil_free(zNewBranch);
27892920
27902921
/* Always exit the loop on the second pass */
27912922
if( bRecheck ) break;
27922923
2924
+
2925
+ /* Figure out how much comment verification is requested */
2926
+ if( noVerifyCom ){
2927
+ ckComFlgs = 0;
2928
+ }else{
2929
+ const char *zVerComs = db_get("verify-comments","on");
2930
+ if( is_false(zVerComs) ){
2931
+ ckComFlgs = 0;
2932
+ }else if( strcmp(zVerComs,"preview")==0 ){
2933
+ ckComFlgs = COMCK_PREVIEW | COMCK_LINKS | COMCK_MARKUP;
2934
+ }else if( strcmp(zVerComs,"links")==0 ){
2935
+ ckComFlgs = COMCK_LINKS;
2936
+ }else{
2937
+ ckComFlgs = COMCK_LINKS | COMCK_MARKUP;
2938
+ }
2939
+ }
27932940
27942941
/* Get the check-in comment. This might involve prompting the
27952942
** user for the check-in comment, in which case we should resync
27962943
** to renew the check-in lock and repeat the checks for conflicts.
27972944
*/
27982945
if( zComment ){
27992946
blob_zero(&comment);
28002947
blob_append(&comment, zComment, -1);
2948
+ ckComFlgs &= ~(COMCK_PREVIEW|COMCK_MARKUP);
2949
+ ckComFlgs |= COMCK_NOPREVIEW;
2950
+ if( suspicious_comment(&comment, ckComFlgs) ){
2951
+ fossil_fatal("Commit aborted; "
2952
+ "use --no-verify-comment to override");
2953
+ }
28012954
}else if( zComFile ){
28022955
blob_zero(&comment);
28032956
blob_read_from_file(&comment, zComFile, ExtFILE);
28042957
blob_to_utf8_no_bom(&comment, 1);
2958
+ ckComFlgs &= ~(COMCK_PREVIEW|COMCK_MARKUP);
2959
+ ckComFlgs |= COMCK_NOPREVIEW;
2960
+ if( suspicious_comment(&comment, ckComFlgs) ){
2961
+ fossil_fatal("Commit aborted; "
2962
+ "use --no-verify-comment to override");
2963
+ }
28052964
}else if( !noPrompt ){
2806
- char *zInit = db_text(0,"SELECT value FROM vvar WHERE name='ci-comment'");
2807
- prepare_commit_comment(&comment, zInit, &sCiInfo, vid, dryRunFlag);
2808
- if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
2809
- prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
2810
- cReply = blob_str(&ans)[0];
2811
- blob_reset(&ans);
2812
- if( cReply!='y' && cReply!='Y' ){
2813
- fossil_fatal("Commit aborted.");
2814
- }
2815
- }
2816
- free(zInit);
2817
- db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment);
2965
+ while( 1/*exit-by-break*/ ){
2966
+ int rc;
2967
+ char *zInit;
2968
+ zInit = db_text(0,"SELECT value FROM vvar WHERE name='ci-comment'");
2969
+ prepare_commit_comment(&comment, zInit, &sCiInfo, vid, dryRunFlag);
2970
+ db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment);
2971
+ if( (rc = suspicious_comment(&comment, ckComFlgs))!=0 ){
2972
+ if( rc==COMCK_PREVIEW ){
2973
+ prompt_user("\nContinue (Y/n/e=edit)? ", &ans);
2974
+ }else{
2975
+ prompt_user("\nContinue (y/n/E=edit)? ", &ans);
2976
+ }
2977
+ cReply = blob_str(&ans)[0];
2978
+ cReply = fossil_tolower(cReply);
2979
+ blob_reset(&ans);
2980
+ if( cReply=='n' ){
2981
+ fossil_fatal("Commit aborted.");
2982
+ }
2983
+ if( cReply=='e' || (cReply!='y' && rc!=COMCK_PREVIEW) ){
2984
+ fossil_free(zInit);
2985
+ continue;
2986
+ }
2987
+ }
2988
+ if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
2989
+ prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
2990
+ cReply = blob_str(&ans)[0];
2991
+ blob_reset(&ans);
2992
+ if( cReply!='y' && cReply!='Y' ){
2993
+ fossil_fatal("Commit aborted.");
2994
+ }
2995
+ }
2996
+ fossil_free(zInit);
2997
+ break;
2998
+ }
2999
+
28183000
db_end_transaction(0);
28193001
db_begin_transaction();
28203002
if( !g.markPrivate && vid!=0 && !allowFork && !forceFlag ){
28213003
/* Do another auto-pull, renewing the check-in lock. Then set
28223004
** bRecheck so that we loop back above to verify that the check-in
28233005
--- src/checkin.c
+++ src/checkin.c
@@ -2281,42 +2281,165 @@
2281 static int tagCmp(const void *a, const void *b){
2282 char **pA = (char**)a;
2283 char **pB = (char**)b;
2284 return fossil_strcmp(pA[0], pB[0]);
2285 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2286
2287 /*
2288 ** COMMAND: ci#
2289 ** COMMAND: commit
2290 **
2291 ** Usage: %fossil commit ?OPTIONS? ?FILE...?
2292 ** or: %fossil ci ?OPTIONS? ?FILE...?
2293 **
2294 ** Create a new version containing all of the changes in the current
2295 ** check-out. You will be prompted to enter a check-in comment unless
2296 ** the comment has been specified on the command-line using "-m" or a
2297 ** file containing the comment using -M. The editor defined in the
2298 ** "editor" fossil option (see %fossil help set) will be used, or from
2299 ** the "VISUAL" or "EDITOR" environment variables (in that order) if
2300 ** no editor is set.
2301 **
2302 ** All files that have changed will be committed unless some subset of
2303 ** files is specified on the command line.
 
 
 
 
 
2304 **
2305 ** The --branch option followed by a branch name causes the new
2306 ** check-in to be placed in a newly-created branch with the name
2307 ** passed to the --branch option.
2308 **
2309 ** Use the --branchcolor option followed by a color name (ex:
2310 ** '#ffc0c0') to specify the background color of entries in the new
2311 ** branch when shown in the web timeline interface. The use of
2312 ** the --branchcolor option is not recommended. Instead, let Fossil
2313 ** choose the branch color automatically.
2314 **
2315 ** The --bgcolor option works like --branchcolor but only sets the
2316 ** background color for a single check-in. Subsequent check-ins revert
2317 ** to the default color.
2318 **
2319 ** A check-in is not permitted to fork unless the --allow-fork option
2320 ** appears. An empty check-in (i.e. with nothing changed) is not
2321 ** allowed unless the --allow-empty option appears. A check-in may not
2322 ** be older than its ancestor unless the --allow-older option appears.
@@ -2328,68 +2451,60 @@
2328 ** unless the interactive user chooses to proceed. If there is no
2329 ** interactive user or these warnings should be skipped for some other
2330 ** reason, the --no-warnings option may be used. A check-in is not
2331 ** allowed against a closed leaf.
2332 **
2333 ** If a commit message is blank, you will be prompted:
2334 ** ("continue (y/N)?") to confirm you really want to commit with a
2335 ** blank commit message. The default value is "N", do not commit.
2336 **
2337 ** The --private option creates a private check-in that is never synced.
2338 ** Children of private check-ins are automatically private.
2339 **
2340 ** The --tag option applies the symbolic tag name to the check-in.
2341 **
2342 ** The --hash option detects edited files by computing each file's
2343 ** artifact hash rather than just checking for changes to its size or mtime.
2344 **
2345 ** Options:
2346 ** --allow-conflict Allow unresolved merge conflicts
2347 ** --allow-empty Allow a commit with no changes
2348 ** --allow-fork Allow the commit to fork
2349 ** --allow-older Allow a commit older than its ancestor
2350 ** --baseline Use a baseline manifest in the commit process
2351 ** --bgcolor COLOR Apply COLOR to this one check-in only
2352 ** --branch NEW-BRANCH-NAME Check in to this new branch
2353 ** --branchcolor COLOR Apply given COLOR to the branch
2354 ** --close Close the branch being committed
2355 ** --date-override DATETIME DATE to use instead of 'now'
 
 
2356 ** --delta Use a delta manifest in the commit process
2357 ** --hash Verify file status using hashing rather
2358 ** than relying on file mtimes
2359 ** --if-changes Make this command a silent no-op if there
2360 ** are no changes
2361 ** --ignore-clock-skew If a clock skew is detected, ignore it and
2362 ** behave as if the user had entered 'yes' to
2363 ** the question of whether to proceed despite
2364 ** the skew.
2365 ** --ignore-oversize Do not warn the user about oversized files
2366 ** --integrate Close all merged-in branches
2367 ** -m|--comment COMMENT-TEXT Use COMMENT-TEXT as commit comment
2368 ** -M|--message-file FILE Read the commit comment from given file
2369 ** --mimetype MIMETYPE Mimetype of check-in comment
2370 ** -n|--dry-run If given, display instead of run actions
2371 ** -v|--verbose Show a diff in the commit message prompt
2372 ** --no-prompt This option disables prompting the user for
2373 ** input and assumes an answer of 'No' for every
2374 ** question.
2375 ** --no-warnings Omit all warnings about file contents
2376 ** --no-verify Do not run before-commit hooks
 
2377 ** --nosign Do not attempt to sign this commit with gpg
2378 ** --nosync Do not auto-sync prior to committing
2379 ** --override-lock Allow a check-in even though parent is locked
2380 ** --private Do not sync changes and their descendants
 
2381 ** --proxy PROXY Use PROXY as http proxy during sync operation
2382 ** --tag TAG-NAME Assign given tag TAG-NAME to the check-in
2383 ** --trace Debug tracing
2384 ** --user-override USER USER to use instead of the current default
2385 **
2386 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
2387 ** year-month-day form, it may be truncated, the "T" may be replaced by
2388 ** a space, and it may also name a timezone offset from UTC as "-HH:MM"
2389 ** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
2390 ** means UTC.
2391 **
2392 ** See also: [[branch]], [[changes]], [[update]], [[extras]], [[sync]]
2393 */
2394 void commit_cmd(void){
2395 int hasChanges; /* True if unsaved changes exist */
@@ -2415,10 +2530,11 @@
2415 int allowConflict = 0; /* Allow unresolve merge conflicts */
2416 int allowEmpty = 0; /* Allow a commit with no changes */
2417 int onlyIfChanges = 0; /* No-op if there are no changes */
2418 int allowFork = 0; /* Allow the commit to fork */
2419 int allowOlder = 0; /* Allow a commit older than its ancestor */
 
2420 char *zManifestFile; /* Name of the manifest file */
2421 int useCksum; /* True if checksums should be computed and verified */
2422 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
2423 int dryRunFlag; /* True for a test run. Debugging only */
2424 CheckinInfo sCiInfo; /* Information about this check-in */
@@ -2440,10 +2556,11 @@
2440 int bRecheck = 0; /* Repeat fork and closed-branch checks*/
2441 int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
2442 int mxSize;
2443 char *zCurBranch = 0; /* The current branch name of checkout */
2444 char *zNewBranch = 0; /* The branch name after update */
 
2445
2446 memset(&sCiInfo, 0, sizeof(sCiInfo));
2447 url_proxy_options();
2448 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2449 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
@@ -2470,24 +2587,30 @@
2470 }
2471 zComment = find_option("comment","m",1);
2472 forceFlag = find_option("force", "f", 0)!=0;
2473 allowConflict = find_option("allow-conflict",0,0)!=0;
2474 allowEmpty = find_option("allow-empty",0,0)!=0;
 
2475 onlyIfChanges = find_option("if-changes",0,0)!=0;
2476 allowFork = find_option("allow-fork",0,0)!=0;
2477 if( find_option("override-lock",0,0)!=0 ) allowFork = 1;
2478 allowOlder = find_option("allow-older",0,0)!=0;
2479 noPrompt = find_option("no-prompt", 0, 0)!=0;
2480 noWarningFlag = find_option("no-warnings", 0, 0)!=0;
2481 noVerify = find_option("no-verify",0,0)!=0;
2482 bTrace = find_option("trace",0,0)!=0;
2483 sCiInfo.zBranch = find_option("branch","b",1);
2484 sCiInfo.zColor = find_option("bgcolor",0,1);
2485 sCiInfo.zBrClr = find_option("branchcolor",0,1);
 
 
 
 
 
 
2486 sCiInfo.closeFlag = find_option("close",0,0)!=0;
2487 sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
2488 sCiInfo.zMimetype = find_option("mimetype",0,1);
2489 sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
2490 while( (zTag = find_option("tag",0,1))!=0 ){
2491 if( zTag[0]==0 ) continue;
2492 sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag,
2493 sizeof(char*)*(nTag+2));
@@ -2499,14 +2622,20 @@
2499 sCiInfo.zUserOvrd = find_option("user-override",0,1);
2500 noSign = db_get_boolean("omitsign", 0)|noSign;
2501 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
2502 useCksum = db_get_boolean("repo-cksum", 1);
2503 bIgnoreSkew = find_option("ignore-clock-skew",0,0)!=0;
2504 outputManifest = db_get_manifest_setting();
2505 mxSize = db_large_file_size();
2506 if( find_option("ignore-oversize",0,0)!=0 ) mxSize = 0;
2507 verify_all_options();
 
 
 
 
 
 
2508
2509 /* Get the ID of the parent manifest artifact */
2510 vid = db_lget_int("checkout", 0);
2511 if( vid==0 ){
2512 useCksum = 1;
@@ -2607,33 +2736,35 @@
2607 fossil_exit(1);
2608 }
2609 }
2610
2611 /* So that older versions of Fossil (that do not understand delta-
2612 ** manifest) can continue to use this repository, do not create a new
 
 
2613 ** delta-manifest unless this repository already contains one or more
2614 ** delta-manifests, or unless the delta-manifest is explicitly requested
2615 ** by the --delta option.
2616 **
2617 ** The forbid-delta-manifests setting prevents new delta manifests.
 
2618 **
2619 ** If the remote repository sent an avoid-delta-manifests pragma on
2620 ** the autosync above, then also try to avoid deltas, unless the
2621 ** --delta option is specified. The remote repo will send the
2622 ** avoid-delta-manifests pragma if it has its "forbid-delta-manifests"
2623 ** setting enabled.
2624 */
2625 if( !db_get_boolean("seen-delta-manifest",0)
2626 || db_get_boolean("forbid-delta-manifests",0)
2627 || g.bAvoidDeltaManifests
2628 ){
2629 if( !forceDelta ) forceBaseline = 1;
2630 }
2631
2632
2633 /* Require confirmation to continue with the check-in if there is
2634 ** clock skew
2635 */
2636 if( g.clockSkewSeen ){
2637 if( bIgnoreSkew!=0 ){
2638 cReply = 'y';
2639 fossil_warning("Clock skew ignored due to --ignore-clock-skew.");
@@ -2788,35 +2919,86 @@
2788 fossil_free(zNewBranch);
2789
2790 /* Always exit the loop on the second pass */
2791 if( bRecheck ) break;
2792
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2793
2794 /* Get the check-in comment. This might involve prompting the
2795 ** user for the check-in comment, in which case we should resync
2796 ** to renew the check-in lock and repeat the checks for conflicts.
2797 */
2798 if( zComment ){
2799 blob_zero(&comment);
2800 blob_append(&comment, zComment, -1);
 
 
 
 
 
 
2801 }else if( zComFile ){
2802 blob_zero(&comment);
2803 blob_read_from_file(&comment, zComFile, ExtFILE);
2804 blob_to_utf8_no_bom(&comment, 1);
 
 
 
 
 
 
2805 }else if( !noPrompt ){
2806 char *zInit = db_text(0,"SELECT value FROM vvar WHERE name='ci-comment'");
2807 prepare_commit_comment(&comment, zInit, &sCiInfo, vid, dryRunFlag);
2808 if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
2809 prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
2810 cReply = blob_str(&ans)[0];
2811 blob_reset(&ans);
2812 if( cReply!='y' && cReply!='Y' ){
2813 fossil_fatal("Commit aborted.");
2814 }
2815 }
2816 free(zInit);
2817 db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2818 db_end_transaction(0);
2819 db_begin_transaction();
2820 if( !g.markPrivate && vid!=0 && !allowFork && !forceFlag ){
2821 /* Do another auto-pull, renewing the check-in lock. Then set
2822 ** bRecheck so that we loop back above to verify that the check-in
2823
--- src/checkin.c
+++ src/checkin.c
@@ -2281,42 +2281,165 @@
2281 static int tagCmp(const void *a, const void *b){
2282 char **pA = (char**)a;
2283 char **pB = (char**)b;
2284 return fossil_strcmp(pA[0], pB[0]);
2285 }
2286
2287 /*
2288 ** SETTING: verify-comments width=8 default=on
2289 **
2290 ** This setting determines how much sanity checking, if any, the
2291 ** "fossil commit" and "fossil amend" commands do against check-in
2292 ** comments. Recognized values:
2293 **
2294 ** on (Default) Check for bad syntax in check-in comments
2295 ** and offer the user a chance to continue editing for
2296 ** interactive sessions, or simply abort the commit if
2297 ** commit was entered using -m or -M
2298 **
2299 ** off Do not do syntax checking of any kind
2300 **
2301 ** links Similar to "on", except only check for bad hyperlinks
2302 **
2303 ** preview Do all the same checks as "on" but also preview the
2304 ** check-in comment to the user during interactive sessions
2305 ** and provide an opportunity to accept or re-edit
2306 */
2307
2308 #if INTERFACE
2309 #define COMCK_LINKS 0x01 /* Check for back hyperlinks */
2310 #define COMCK_MARKUP 0x02 /* Check markup */
2311 #define COMCK_PREVIEW 0x04 /* Always preview, even if no issues found */
2312 #define COMCK_NOPREVIEW 0x08 /* Never preview, even for other errors */
2313 #endif /* INTERFACE */
2314
2315 /*
2316 ** Check for possible formatting errors in the comment string pComment.
2317 **
2318 ** If concerns are found, write a description of the problem(s) to
2319 ** stdout and return non-zero. The return value is some combination
2320 ** of the COMCK_* flags, depending on what went wrong.
2321 **
2322 ** If no issues are seen, do not output anything and return zero.
2323 */
2324 int suspicious_comment(Blob *pComment, int mFlags){
2325 char *zStart = blob_str(pComment);
2326 char *z;
2327 char *zEnd, *zEnd2;
2328 char *zSep;
2329 char cSave1;
2330 int nIssue = 0;
2331 int rc = mFlags & COMCK_PREVIEW;
2332 Blob out;
2333 static const char zSpecial[] = "\\&<*_`[";
2334
2335 if( mFlags==0 ) return 0;
2336 z = zStart;
2337 blob_init(&out, 0, 0);
2338 if( mFlags & COMCK_LINKS ){
2339 while( (z = strchr(z,'['))!=0 ){
2340 zEnd = strchr(z,']');
2341 if( zEnd==0 ){
2342 blob_appendf(&out,"\n (%d) ", ++nIssue);
2343 blob_appendf(&out, "Unterminated hyperlink \"%.12s...\"", z);
2344 break;
2345 }
2346 if( zEnd[1]=='(' && (zEnd2 = strchr(zEnd,')'))!=0 ){
2347 blob_appendf(&out,"\n (%d) ", ++nIssue);
2348 blob_appendf(&out, "Markdown hyperlink syntax: %.*s",
2349 (int)(zEnd2+1-z), z);
2350 z = zEnd2;
2351 continue;
2352 }
2353 zSep = strchr(z+1,'|');
2354 if( zSep==0 || zSep>zEnd ) zSep = zEnd;
2355 while( zSep>z && fossil_isspace(zSep[-1]) ) zSep--;
2356 cSave1 = zSep[0];
2357 zSep[0] = 0;
2358 if( !wiki_valid_link_target(z+1) ){
2359 blob_appendf(&out,"\n (%d) ", ++nIssue);
2360 blob_appendf(&out, "Broken hyperlink: [%s]", z+1);
2361 }
2362 zSep[0] = cSave1;
2363 z = zEnd;
2364 }
2365 }
2366
2367 if( nIssue>0
2368 || (mFlags & COMCK_PREVIEW)!=0
2369 || ((mFlags & COMCK_MARKUP)!=0 && strcspn(zStart,zSpecial)<strlen(zStart))
2370 ){
2371 char zGot[16];
2372 int nGot = 0;
2373 int i;
2374 if( (mFlags & COMCK_MARKUP)!=0 ){
2375 for(i=0; zSpecial[i]; i++){
2376 if( strchr(zStart,zSpecial[i]) ) zGot[nGot++] = zSpecial[i];
2377 }
2378 }
2379 zGot[nGot] = 0;
2380 if( nGot>0 ) rc |= COMCK_MARKUP;
2381 if( nGot>0 && nIssue>0 ){
2382 blob_appendf(&out,"\n (%d) Comment uses special character%s \"%s\"",
2383 ++nIssue, (nGot>1 ? "s" : ""), zGot);
2384 nGot = 0;
2385 }
2386 if( nIssue ){
2387 rc |= COMCK_LINKS;
2388 fossil_print(
2389 "Possible comment formatting error%s:%b\n",
2390 nIssue>1 ? "s" : "", &out
2391 );
2392 }
2393 if( (mFlags & COMCK_NOPREVIEW)==0 ){
2394 Blob in, html, txt;
2395 blob_init(&in, blob_str(pComment), -1);
2396 blob_init(&html, 0, 0);
2397 blob_init(&txt, 0, 0);
2398 wiki_convert(&in, &html, WIKI_INLINE);
2399 html_to_plaintext(blob_str(&html), &txt);
2400 if( nGot>0 ){
2401 fossil_print(
2402 "The comment uses special character%s \"%s\". "
2403 "Does it render as you expect?\n\n ",
2404 (nGot>1 ? "s" : ""), zGot
2405 );
2406 }else{
2407 fossil_print("Preview of the check-in comment:\n\n ");
2408 }
2409 comment_print(blob_str(&txt), 0, 3, -1, get_comment_format());
2410 blob_reset(&in);
2411 blob_reset(&html);
2412 blob_reset(&txt);
2413 }
2414 }
2415 blob_reset(&out);
2416 return rc;
2417 }
2418
2419 /*
2420 ** COMMAND: ci#
2421 ** COMMAND: commit
2422 **
2423 ** Usage: %fossil commit ?OPTIONS? ?FILE...?
2424 ** or: %fossil ci ?OPTIONS? ?FILE...?
2425 **
2426 ** Create a new check-in containing all of the changes in the current
2427 ** check-out. All changes are committed unless some subset of files
2428 ** is specified on the command line, in which case only the named files
2429 ** become part of the new check-in.
 
 
 
2430 **
2431 ** You will be prompted to enter a check-in comment unless the comment
2432 ** has been specified on the command-line using "-m" or "-M". The
2433 ** text editor used is determined by the "editor" setting, or by the
2434 ** "VISUAL" or "EDITOR" environment variables. Commit message text is
2435 ** interpreted as fossil-wiki format. Potentially misformatted check-in
2436 ** comment text is detected and reported unless the --no-verify-comment
2437 ** option is used.
2438 **
2439 ** The --branch option followed by a branch name causes the new
2440 ** check-in to be placed in a newly-created branch with name specified.
 
 
 
 
 
 
 
 
 
 
 
2441 **
2442 ** A check-in is not permitted to fork unless the --allow-fork option
2443 ** appears. An empty check-in (i.e. with nothing changed) is not
2444 ** allowed unless the --allow-empty option appears. A check-in may not
2445 ** be older than its ancestor unless the --allow-older option appears.
@@ -2328,68 +2451,60 @@
2451 ** unless the interactive user chooses to proceed. If there is no
2452 ** interactive user or these warnings should be skipped for some other
2453 ** reason, the --no-warnings option may be used. A check-in is not
2454 ** allowed against a closed leaf.
2455 **
 
 
 
 
2456 ** The --private option creates a private check-in that is never synced.
2457 ** Children of private check-ins are automatically private.
2458 **
2459 ** The --tag option applies the symbolic tag name to the check-in.
2460 ** The --tag option can be repeated to assign multiple tags to a check-in.
2461 ** For example: "... --tag release --tag version-1.2.3 ..."
 
2462 **
2463 ** Options:
2464 ** --allow-conflict Allow unresolved merge conflicts
2465 ** --allow-empty Allow a commit with no changes
2466 ** --allow-fork Allow the commit to fork
2467 ** --allow-older Allow a commit older than its ancestor
2468 ** --baseline Use a baseline manifest in the commit process
 
2469 ** --branch NEW-BRANCH-NAME Check in to this new branch
 
2470 ** --close Close the branch being committed
2471 ** --date-override DATETIME Make DATETIME the time of the check-in.
2472 ** Useful when importing historical check-ins
2473 ** from another version control system.
2474 ** --delta Use a delta manifest in the commit process
2475 ** --hash Verify file status using hashing rather
2476 ** than relying on filesystem mtimes
2477 ** --if-changes Make this command a silent no-op if there
2478 ** are no changes
2479 ** --ignore-clock-skew If a clock skew is detected, ignore it and
2480 ** behave as if the user had entered 'yes' to
2481 ** the question of whether to proceed despite
2482 ** the skew.
2483 ** --ignore-oversize Do not warn the user about oversized files
2484 ** --integrate Close all merged-in branches
2485 ** -m|--comment COMMENT-TEXT Use COMMENT-TEXT as the check-in comment
2486 ** -M|--message-file FILE Read the check-in comment from FILE
2487 ** -n|--dry-run Do not actually create a new check-in. Just
2488 ** show what would have happened. For debugging.
2489 ** -v|--verbose Show a diff in the commit message prompt
2490 ** --no-prompt This option disables prompting the user for
2491 ** input and assumes an answer of 'No' for every
2492 ** question.
2493 ** --no-warnings Omit all warnings about file contents
2494 ** --no-verify Do not run before-commit hooks
2495 ** --no-verify-comment Do not validate the check-in comment
2496 ** --nosign Do not attempt to sign this commit with gpg
2497 ** --nosync Do not auto-sync prior to committing
2498 ** --override-lock Allow a check-in even though parent is locked
2499 ** --private Never sync the resulting check-in and make
2500 ** all descendants private too.
2501 ** --proxy PROXY Use PROXY as http proxy during sync operation
2502 ** --tag TAG-NAME Add TAG-NAME to the check-in. May be repeated.
2503 ** --trace Debug tracing
2504 ** --user-override USER Record USER as the login that created the
2505 ** new check-in, rather that the current user.
 
 
 
 
 
2506 **
2507 ** See also: [[branch]], [[changes]], [[update]], [[extras]], [[sync]]
2508 */
2509 void commit_cmd(void){
2510 int hasChanges; /* True if unsaved changes exist */
@@ -2415,10 +2530,11 @@
2530 int allowConflict = 0; /* Allow unresolve merge conflicts */
2531 int allowEmpty = 0; /* Allow a commit with no changes */
2532 int onlyIfChanges = 0; /* No-op if there are no changes */
2533 int allowFork = 0; /* Allow the commit to fork */
2534 int allowOlder = 0; /* Allow a commit older than its ancestor */
2535 int noVerifyCom = 0; /* Allow suspicious check-in comments */
2536 char *zManifestFile; /* Name of the manifest file */
2537 int useCksum; /* True if checksums should be computed and verified */
2538 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
2539 int dryRunFlag; /* True for a test run. Debugging only */
2540 CheckinInfo sCiInfo; /* Information about this check-in */
@@ -2440,10 +2556,11 @@
2556 int bRecheck = 0; /* Repeat fork and closed-branch checks*/
2557 int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
2558 int mxSize;
2559 char *zCurBranch = 0; /* The current branch name of checkout */
2560 char *zNewBranch = 0; /* The branch name after update */
2561 int ckComFlgs; /* Flags passed to suspicious_comment() */
2562
2563 memset(&sCiInfo, 0, sizeof(sCiInfo));
2564 url_proxy_options();
2565 /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
2566 useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
@@ -2470,24 +2587,30 @@
2587 }
2588 zComment = find_option("comment","m",1);
2589 forceFlag = find_option("force", "f", 0)!=0;
2590 allowConflict = find_option("allow-conflict",0,0)!=0;
2591 allowEmpty = find_option("allow-empty",0,0)!=0;
2592 noVerifyCom = find_option("no-verify-comment",0,0)!=0;
2593 onlyIfChanges = find_option("if-changes",0,0)!=0;
2594 allowFork = find_option("allow-fork",0,0)!=0;
2595 if( find_option("override-lock",0,0)!=0 ) allowFork = 1;
2596 allowOlder = find_option("allow-older",0,0)!=0;
2597 noPrompt = find_option("no-prompt", 0, 0)!=0;
2598 noWarningFlag = find_option("no-warnings", 0, 0)!=0;
2599 noVerify = find_option("no-verify",0,0)!=0;
2600 bTrace = find_option("trace",0,0)!=0;
2601 sCiInfo.zBranch = find_option("branch","b",1);
2602
2603 /* NB: the --bgcolor and --branchcolor flags still work, but are
2604 ** now undocumented, to discourage their use. --mimetype has never
2605 ** been used for anything, so also leave it undocumented */
2606 sCiInfo.zColor = find_option("bgcolor",0,1); /* Deprecated, undocumented*/
2607 sCiInfo.zBrClr = find_option("branchcolor",0,1); /* Deprecated, undocumented*/
2608 sCiInfo.zMimetype = find_option("mimetype",0,1); /* Deprecated, undocumented*/
2609
2610 sCiInfo.closeFlag = find_option("close",0,0)!=0;
2611 sCiInfo.integrateFlag = find_option("integrate",0,0)!=0;
 
2612 sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0;
2613 while( (zTag = find_option("tag",0,1))!=0 ){
2614 if( zTag[0]==0 ) continue;
2615 sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag,
2616 sizeof(char*)*(nTag+2));
@@ -2499,14 +2622,20 @@
2622 sCiInfo.zUserOvrd = find_option("user-override",0,1);
2623 noSign = db_get_boolean("omitsign", 0)|noSign;
2624 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
2625 useCksum = db_get_boolean("repo-cksum", 1);
2626 bIgnoreSkew = find_option("ignore-clock-skew",0,0)!=0;
2627 outputManifest = db_get_manifest_setting(0);
2628 mxSize = db_large_file_size();
2629 if( find_option("ignore-oversize",0,0)!=0 ) mxSize = 0;
2630 verify_all_options();
2631
2632 /* The --no-warnings flag and the --force flag each imply
2633 ** the --no-verify-comment flag */
2634 if( noWarningFlag || forceFlag ){
2635 noVerifyCom = 1;
2636 }
2637
2638 /* Get the ID of the parent manifest artifact */
2639 vid = db_lget_int("checkout", 0);
2640 if( vid==0 ){
2641 useCksum = 1;
@@ -2607,33 +2736,35 @@
2736 fossil_exit(1);
2737 }
2738 }
2739
2740 /* So that older versions of Fossil (that do not understand delta-
2741 ** manifest) can continue to use this repository, and because
2742 ** delta manifests are usually a bad idea unless the repository
2743 ** has a really large number of files, do not create a new
2744 ** delta-manifest unless this repository already contains one or more
2745 ** delta-manifests, or unless the delta-manifest is explicitly requested
2746 ** by the --delta option.
2747 **
2748 ** The forbid-delta-manifests setting prevents new delta manifests,
2749 ** even if the --delta option is used.
2750 **
2751 ** If the remote repository sent an avoid-delta-manifests pragma on
2752 ** the autosync above, then also forbid delta manifests, even if the
2753 ** --delta option is specified. The remote repo will send the
2754 ** avoid-delta-manifests pragma if its "forbid-delta-manifests"
2755 ** setting is enabled.
2756 */
2757 if( !(forceDelta || db_get_boolean("seen-delta-manifest",0))
2758 || db_get_boolean("forbid-delta-manifests",0)
2759 || g.bAvoidDeltaManifests
2760 ){
2761 forceBaseline = 1;
2762 }
 
2763
2764 /* Require confirmation to continue with the check-in if there is
2765 ** clock skew. This helps to prevent timewarps.
2766 */
2767 if( g.clockSkewSeen ){
2768 if( bIgnoreSkew!=0 ){
2769 cReply = 'y';
2770 fossil_warning("Clock skew ignored due to --ignore-clock-skew.");
@@ -2788,35 +2919,86 @@
2919 fossil_free(zNewBranch);
2920
2921 /* Always exit the loop on the second pass */
2922 if( bRecheck ) break;
2923
2924
2925 /* Figure out how much comment verification is requested */
2926 if( noVerifyCom ){
2927 ckComFlgs = 0;
2928 }else{
2929 const char *zVerComs = db_get("verify-comments","on");
2930 if( is_false(zVerComs) ){
2931 ckComFlgs = 0;
2932 }else if( strcmp(zVerComs,"preview")==0 ){
2933 ckComFlgs = COMCK_PREVIEW | COMCK_LINKS | COMCK_MARKUP;
2934 }else if( strcmp(zVerComs,"links")==0 ){
2935 ckComFlgs = COMCK_LINKS;
2936 }else{
2937 ckComFlgs = COMCK_LINKS | COMCK_MARKUP;
2938 }
2939 }
2940
2941 /* Get the check-in comment. This might involve prompting the
2942 ** user for the check-in comment, in which case we should resync
2943 ** to renew the check-in lock and repeat the checks for conflicts.
2944 */
2945 if( zComment ){
2946 blob_zero(&comment);
2947 blob_append(&comment, zComment, -1);
2948 ckComFlgs &= ~(COMCK_PREVIEW|COMCK_MARKUP);
2949 ckComFlgs |= COMCK_NOPREVIEW;
2950 if( suspicious_comment(&comment, ckComFlgs) ){
2951 fossil_fatal("Commit aborted; "
2952 "use --no-verify-comment to override");
2953 }
2954 }else if( zComFile ){
2955 blob_zero(&comment);
2956 blob_read_from_file(&comment, zComFile, ExtFILE);
2957 blob_to_utf8_no_bom(&comment, 1);
2958 ckComFlgs &= ~(COMCK_PREVIEW|COMCK_MARKUP);
2959 ckComFlgs |= COMCK_NOPREVIEW;
2960 if( suspicious_comment(&comment, ckComFlgs) ){
2961 fossil_fatal("Commit aborted; "
2962 "use --no-verify-comment to override");
2963 }
2964 }else if( !noPrompt ){
2965 while( 1/*exit-by-break*/ ){
2966 int rc;
2967 char *zInit;
2968 zInit = db_text(0,"SELECT value FROM vvar WHERE name='ci-comment'");
2969 prepare_commit_comment(&comment, zInit, &sCiInfo, vid, dryRunFlag);
2970 db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment);
2971 if( (rc = suspicious_comment(&comment, ckComFlgs))!=0 ){
2972 if( rc==COMCK_PREVIEW ){
2973 prompt_user("\nContinue (Y/n/e=edit)? ", &ans);
2974 }else{
2975 prompt_user("\nContinue (y/n/E=edit)? ", &ans);
2976 }
2977 cReply = blob_str(&ans)[0];
2978 cReply = fossil_tolower(cReply);
2979 blob_reset(&ans);
2980 if( cReply=='n' ){
2981 fossil_fatal("Commit aborted.");
2982 }
2983 if( cReply=='e' || (cReply!='y' && rc!=COMCK_PREVIEW) ){
2984 fossil_free(zInit);
2985 continue;
2986 }
2987 }
2988 if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
2989 prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
2990 cReply = blob_str(&ans)[0];
2991 blob_reset(&ans);
2992 if( cReply!='y' && cReply!='Y' ){
2993 fossil_fatal("Commit aborted.");
2994 }
2995 }
2996 fossil_free(zInit);
2997 break;
2998 }
2999
3000 db_end_transaction(0);
3001 db_begin_transaction();
3002 if( !g.markPrivate && vid!=0 && !allowFork && !forceFlag ){
3003 /* Do another auto-pull, renewing the check-in lock. Then set
3004 ** bRecheck so that we loop back above to verify that the check-in
3005
+1 -1
--- src/checkout.c
+++ src/checkout.c
@@ -173,11 +173,11 @@
173173
*/
174174
void manifest_to_disk(int vid){
175175
char *zManFile;
176176
int flg;
177177
178
- flg = db_get_manifest_setting();
178
+ flg = db_get_manifest_setting(0);
179179
180180
if( flg & MFESTFLG_RAW ){
181181
Blob manifest = BLOB_INITIALIZER;
182182
content_get(vid, &manifest);
183183
sterilize_manifest(&manifest, CFTYPE_MANIFEST);
184184
--- src/checkout.c
+++ src/checkout.c
@@ -173,11 +173,11 @@
173 */
174 void manifest_to_disk(int vid){
175 char *zManFile;
176 int flg;
177
178 flg = db_get_manifest_setting();
179
180 if( flg & MFESTFLG_RAW ){
181 Blob manifest = BLOB_INITIALIZER;
182 content_get(vid, &manifest);
183 sterilize_manifest(&manifest, CFTYPE_MANIFEST);
184
--- src/checkout.c
+++ src/checkout.c
@@ -173,11 +173,11 @@
173 */
174 void manifest_to_disk(int vid){
175 char *zManFile;
176 int flg;
177
178 flg = db_get_manifest_setting(0);
179
180 if( flg & MFESTFLG_RAW ){
181 Blob manifest = BLOB_INITIALIZER;
182 content_get(vid, &manifest);
183 sterilize_manifest(&manifest, CFTYPE_MANIFEST);
184
--- src/configure.c
+++ src/configure.c
@@ -891,10 +891,11 @@
891891
}
892892
url_parse(zServer, URL_PROMPT_PW|URL_USE_CONFIG);
893893
if( g.url.protocol==0 ) fossil_fatal("no server URL specified");
894894
user_select();
895895
url_enable_proxy("via proxy: ");
896
+ g.zHttpAuth = get_httpauth();
896897
if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
897898
if( strncmp(zMethod, "push", n)==0 ){
898899
client_sync(0,0,(unsigned)mask,0,0);
899900
}else if( strncmp(zMethod, "pull", n)==0 ){
900901
if( overwriteFlag ) db_unprotect(PROTECT_USER);
901902
--- src/configure.c
+++ src/configure.c
@@ -891,10 +891,11 @@
891 }
892 url_parse(zServer, URL_PROMPT_PW|URL_USE_CONFIG);
893 if( g.url.protocol==0 ) fossil_fatal("no server URL specified");
894 user_select();
895 url_enable_proxy("via proxy: ");
 
896 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
897 if( strncmp(zMethod, "push", n)==0 ){
898 client_sync(0,0,(unsigned)mask,0,0);
899 }else if( strncmp(zMethod, "pull", n)==0 ){
900 if( overwriteFlag ) db_unprotect(PROTECT_USER);
901
--- src/configure.c
+++ src/configure.c
@@ -891,10 +891,11 @@
891 }
892 url_parse(zServer, URL_PROMPT_PW|URL_USE_CONFIG);
893 if( g.url.protocol==0 ) fossil_fatal("no server URL specified");
894 user_select();
895 url_enable_proxy("via proxy: ");
896 g.zHttpAuth = get_httpauth();
897 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
898 if( strncmp(zMethod, "push", n)==0 ){
899 client_sync(0,0,(unsigned)mask,0,0);
900 }else if( strncmp(zMethod, "pull", n)==0 ){
901 if( overwriteFlag ) db_unprotect(PROTECT_USER);
902
+194 -73
--- src/db.c
+++ src/db.c
@@ -3204,23 +3204,16 @@
32043204
32053205
db_unprotect(PROTECT_ALL);
32063206
db_set("content-schema", CONTENT_SCHEMA, 0);
32073207
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
32083208
db_set("rebuilt", get_version(), 0);
3209
- db_set("admin-log", "1", 0);
3210
- db_set("access-log", "1", 0);
32113209
db_multi_exec(
32123210
"INSERT INTO config(name,value,mtime)"
32133211
" VALUES('server-code', lower(hex(randomblob(20))),now());"
32143212
"INSERT INTO config(name,value,mtime)"
32153213
" VALUES('project-code', lower(hex(randomblob(20))),now());"
32163214
);
3217
- if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
3218
- if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
3219
- if( !db_is_global("timeline-plaintext") ){
3220
- db_set_int("timeline-plaintext", 1, 0);
3221
- }
32223215
db_create_default_users(0, zDefaultUser);
32233216
if( zDefaultUser ) g.zLogin = zDefaultUser;
32243217
user_select();
32253218
32263219
if( zTemplate ){
@@ -3647,66 +3640,79 @@
36473640
**
36483641
** If the zNonVersionedSetting parameter is not NULL then it holds the
36493642
** non-versioned value for this setting. If both a versioned and a
36503643
** non-versioned value exist and are not equal, then a warning message
36513644
** might be generated.
3645
+**
3646
+** zCkin is normally NULL. In that case, the versioned setting is
3647
+** take from the local check-out, if a local checkout exists, or from
3648
+** checkin named by the g.zOpenRevision global variable. If zCkin is
3649
+** not NULL, then zCkin is the name of the specific checkin from which
3650
+** versioned setting value is taken. When zCkin is not NULL, the cache
3651
+** is bypassed.
36523652
*/
3653
-char *db_get_versioned(const char *zName, char *zNonVersionedSetting){
3653
+char *db_get_versioned(
3654
+ const char *zName,
3655
+ char *zNonVersionedSetting,
3656
+ const char *zCkin
3657
+){
36543658
char *zVersionedSetting = 0;
36553659
int noWarn = 0;
36563660
int found = 0;
36573661
struct _cacheEntry {
36583662
struct _cacheEntry *next;
36593663
const char *zName, *zValue;
36603664
} *cacheEntry = 0;
36613665
static struct _cacheEntry *cache = 0;
36623666
3663
- if( !g.localOpen && g.zOpenRevision==0 ) return zNonVersionedSetting;
3667
+ if( !g.localOpen && g.zOpenRevision==0 && zCkin==0 ){
3668
+ return zNonVersionedSetting;
3669
+ }
3670
+
36643671
/* Look up name in cache */
3665
- cacheEntry = cache;
3666
- while( cacheEntry!=0 ){
3667
- if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
3668
- zVersionedSetting = fossil_strdup(cacheEntry->zValue);
3669
- break;
3670
- }
3671
- cacheEntry = cacheEntry->next;
3672
- }
3672
+ if( zCkin==0 ){
3673
+ cacheEntry = cache;
3674
+ while( cacheEntry!=0 ){
3675
+ if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
3676
+ zVersionedSetting = fossil_strdup(cacheEntry->zValue);
3677
+ break;
3678
+ }
3679
+ cacheEntry = cacheEntry->next;
3680
+ }
3681
+ }
3682
+
36733683
/* Attempt to read value from file in check-out if there wasn't a cache hit.*/
36743684
if( cacheEntry==0 ){
36753685
Blob versionedPathname;
36763686
Blob setting;
3677
- blob_zero(&versionedPathname);
3678
- blob_zero(&setting);
3679
- blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
3680
- g.zLocalRoot, zName);
3681
- if( !g.localOpen ){
3682
- /* Repository is in the process of being opened, but files have not been
3683
- * written to disk. Load from the database. */
3684
- Blob noWarnFile;
3685
- if( historical_blob(g.zOpenRevision, blob_str(&versionedPathname),
3686
- &setting, 0) ){
3687
- found = 1;
3688
- }
3689
- /* See if there's a no-warn flag */
3690
- blob_append(&versionedPathname, ".no-warn", -1);
3691
- blob_zero(&noWarnFile);
3692
- if( historical_blob(g.zOpenRevision, blob_str(&versionedPathname),
3693
- &noWarnFile, 0) ){
3694
- noWarn = 1;
3695
- }
3696
- blob_reset(&noWarnFile);
3697
- }else if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3698
- /* File exists, and contains the value for this setting. Load from
3699
- ** the file. */
3700
- const char *zFile = blob_str(&versionedPathname);
3701
- if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){
3702
- found = 1;
3703
- }
3704
- /* See if there's a no-warn flag */
3705
- blob_append(&versionedPathname, ".no-warn", -1);
3706
- if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3707
- noWarn = 1;
3687
+ blob_init(&versionedPathname, 0, 0);
3688
+ blob_init(&setting, 0, 0);
3689
+ if( !g.localOpen || zCkin!=0 ){
3690
+ /* Repository is in the process of being opened, but files have not been
3691
+ * written to disk. Load from the database. */
3692
+ blob_appendf(&versionedPathname, ".fossil-settings/%s", zName);
3693
+ if( historical_blob(zCkin ? zCkin : g.zOpenRevision,
3694
+ blob_str(&versionedPathname),
3695
+ &setting, 0)
3696
+ ){
3697
+ found = 1;
3698
+ }
3699
+ }else{
3700
+ blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
3701
+ g.zLocalRoot, zName);
3702
+ if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3703
+ /* File exists, and contains the value for this setting. Load from
3704
+ ** the file. */
3705
+ const char *zFile = blob_str(&versionedPathname);
3706
+ if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){
3707
+ found = 1;
3708
+ }
3709
+ /* See if there's a no-warn flag */
3710
+ blob_append(&versionedPathname, ".no-warn", -1);
3711
+ if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3712
+ noWarn = 1;
3713
+ }
37083714
}
37093715
}
37103716
blob_reset(&versionedPathname);
37113717
if( found ){
37123718
blob_strip_comment_lines(&setting, &setting);
@@ -3713,20 +3719,27 @@
37133719
blob_trim(&setting); /* Avoid non-obvious problems with line endings
37143720
** on boolean properties */
37153721
zVersionedSetting = fossil_strdup(blob_str(&setting));
37163722
}
37173723
blob_reset(&setting);
3724
+
37183725
/* Store result in cache, which can be the value or 0 if not found */
3719
- cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry));
3720
- cacheEntry->next = cache;
3721
- cacheEntry->zName = zName;
3722
- cacheEntry->zValue = fossil_strdup(zVersionedSetting);
3723
- cache = cacheEntry;
3726
+ if( zCkin==0 ){
3727
+ cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(*cacheEntry));
3728
+ cacheEntry->next = cache;
3729
+ cacheEntry->zName = zName;
3730
+ cacheEntry->zValue = fossil_strdup(zVersionedSetting);
3731
+ cache = cacheEntry;
3732
+ }
37243733
}
3734
+
37253735
/* Display a warning? */
3726
- if( zVersionedSetting!=0 && zNonVersionedSetting!=0
3727
- && zNonVersionedSetting[0]!='\0' && !noWarn
3736
+ if( zVersionedSetting!=0
3737
+ && zNonVersionedSetting!=0
3738
+ && zNonVersionedSetting[0]!='\0'
3739
+ && zCkin==0
3740
+ && !noWarn
37283741
){
37293742
/* There's a versioned setting, and a non-versioned setting. Tell
37303743
** the user about the conflict */
37313744
fossil_warning(
37323745
"setting %s has both versioned and non-versioned values: using "
@@ -3735,10 +3748,11 @@
37353748
"\"%/.fossil-settings/%s.no-warn\" in the check-out root, or delete "
37363749
"the non-versioned setting with \"fossil unset %s\")", zName,
37373750
g.zLocalRoot, zName, g.zLocalRoot, zName, zName
37383751
);
37393752
}
3753
+
37403754
/* Prefer the versioned setting */
37413755
return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
37423756
}
37433757
37443758
@@ -3778,11 +3792,11 @@
37783792
}
37793793
if( pSetting!=0 && pSetting->versionable ){
37803794
/* This is a versionable setting, try and get the info from a
37813795
** checked-out file */
37823796
char * zZ = z;
3783
- z = db_get_versioned(zName, z);
3797
+ z = db_get_versioned(zName, z, 0);
37843798
if(zZ != z){
37853799
fossil_free(zZ);
37863800
}
37873801
}
37883802
if( z==0 ){
@@ -3919,11 +3933,11 @@
39193933
}
39203934
fossil_free(zVal);
39213935
return dflt;
39223936
}
39233937
int db_get_versioned_boolean(const char *zName, int dflt){
3924
- char *zVal = db_get_versioned(zName, 0);
3938
+ char *zVal = db_get_versioned(zName, 0, 0);
39253939
if( zVal==0 ) return dflt;
39263940
if( is_truth(zVal) ) return 1;
39273941
if( is_false(zVal) ) return 0;
39283942
return dflt;
39293943
}
@@ -4048,14 +4062,30 @@
40484062
** Get the manifest setting. For backwards compatibility first check if the
40494063
** value is a boolean. If it's not a boolean, treat each character as a flag
40504064
** to enable a manifest type. This system puts certain boundary conditions on
40514065
** which letters can be used to represent flags (any permutation of flags must
40524066
** not be able to fully form one of the boolean values).
4067
+**
4068
+** "manifest" is a versionable setting. But we do not issue a warning
4069
+** if there is a conflict. Instead, the value returned is the value for
4070
+** the versioned setting if the versioned setting exists, or the ordinary
4071
+** setting otherwise.
4072
+**
4073
+** The argument zCkin is the specific check-in for which we want the
4074
+** manifest setting.
40534075
*/
4054
-int db_get_manifest_setting(void){
4076
+int db_get_manifest_setting(const char *zCkin){
40554077
int flg;
4056
- char *zVal = db_get("manifest", 0);
4078
+ char *zVal;
4079
+
4080
+ /* Look for the versioned setting first */
4081
+ zVal = db_get_versioned("manifest", 0, zCkin);
4082
+
4083
+ if( zVal==0 && g.repositoryOpen ){
4084
+ /* No versioned setting, look for the repository setting second */
4085
+ zVal = db_text(0, "SELECT value FROM config WHERE name='manifest'");
4086
+ }
40574087
if( zVal==0 || is_false(zVal) ){
40584088
return 0;
40594089
}else if( is_truth(zVal) ){
40604090
return MFESTFLG_RAW|MFESTFLG_UUID;
40614091
}
@@ -4068,10 +4098,37 @@
40684098
}
40694099
zVal++;
40704100
}
40714101
return flg;
40724102
}
4103
+
4104
+/*
4105
+** COMMAND: test-manifest-setting
4106
+**
4107
+** Usage: %fossil test-manifest-setting VERSION VERSION ...
4108
+**
4109
+** Display the value for the "manifest" setting for various versions
4110
+** of the repository.
4111
+*/
4112
+void test_manfest_setting_cmd(void){
4113
+ int i;
4114
+ db_find_and_open_repository(0, 0);
4115
+ for(i=2; i<g.argc; i++){
4116
+ int m = db_get_manifest_setting(g.argv[i]);
4117
+ fossil_print("%s:\n", g.argv[i]);
4118
+ fossil_print(" flags = 0x%02x\n", m);
4119
+ if( m & MFESTFLG_RAW ){
4120
+ fossil_print(" manifest\n");
4121
+ }
4122
+ if( m & MFESTFLG_UUID ){
4123
+ fossil_print(" manifest.uuid\n");
4124
+ }
4125
+ if( m & MFESTFLG_TAGS ){
4126
+ fossil_print(" manifest.tags\n");
4127
+ }
4128
+ }
4129
+}
40734130
40744131
40754132
/*
40764133
** Record the name of a local repository in the global_config() database.
40774134
** The repository filename %s is recorded as an entry with a "name" field
@@ -4371,16 +4428,37 @@
43714428
}
43724429
}
43734430
g.argc = 2;
43744431
info_cmd();
43754432
}
4433
+
4434
+/*
4435
+** Return true if pSetting has its default value assuming its
4436
+** current value is zVal.
4437
+*/
4438
+int setting_has_default_value(const Setting *pSetting, const char *zVal){
4439
+ if( zVal==0 ) return 1;
4440
+ if( pSetting->def==0 ) return 0;
4441
+ if( pSetting->width==0 ){
4442
+ return is_false(pSetting->def)==is_false(zVal);
4443
+ }
4444
+ if( fossil_strcmp(pSetting->def, zVal)==0 ) return 1;
4445
+ if( is_false(zVal) && is_false(pSetting->def) ) return 1;
4446
+ if( is_truth(zVal) && is_truth(pSetting->def) ) return 1;
4447
+ return 0;
4448
+}
43764449
43774450
/*
43784451
** Print the current value of a setting identified by the pSetting
43794452
** pointer.
4453
+**
4454
+** Only show the value, not the setting name, if valueOnly is true.
4455
+**
4456
+** Show nothing if bIfChng is true and the setting is not currently set
4457
+** or is set to its default value.
43804458
*/
4381
-void print_setting(const Setting *pSetting, int valueOnly){
4459
+void print_setting(const Setting *pSetting, int valueOnly, int bIfChng){
43824460
Stmt q;
43834461
int versioned = 0;
43844462
if( pSetting->versionable && g.localOpen ){
43854463
/* Check to see if this is overridden by a versionable settings file */
43864464
Blob versionedPathname;
@@ -4391,11 +4469,16 @@
43914469
versioned = 1;
43924470
}
43934471
blob_reset(&versionedPathname);
43944472
}
43954473
if( valueOnly && versioned ){
4396
- fossil_print("%s\n", db_get_versioned(pSetting->name, NULL));
4474
+ const char *zVal = db_get_versioned(pSetting->name, NULL, NULL);
4475
+ if( !bIfChng || (zVal!=0 && fossil_strcmp(zVal, pSetting->def)!=0) ){
4476
+ fossil_print("%s\n", db_get_versioned(pSetting->name, NULL, NULL));
4477
+ }else{
4478
+ versioned = 0;
4479
+ }
43974480
return;
43984481
}
43994482
if( g.repositoryOpen ){
44004483
db_prepare(&q,
44014484
"SELECT '(local)', value FROM config WHERE name=%Q"
@@ -4408,20 +4491,47 @@
44084491
"SELECT '(global)', value FROM global_config WHERE name=%Q",
44094492
pSetting->name
44104493
);
44114494
}
44124495
if( db_step(&q)==SQLITE_ROW ){
4413
- if( valueOnly ){
4496
+ const char *zVal = db_column_text(&q,1);
4497
+ if( bIfChng && setting_has_default_value(pSetting,zVal) ){
4498
+ if( versioned ){
4499
+ fossil_print("%-24s (versioned)\n", pSetting->name);
4500
+ versioned = 0;
4501
+ }
4502
+ }else if( valueOnly ){
44144503
fossil_print("%s\n", db_column_text(&q, 1));
44154504
}else{
4416
- fossil_print("%-20s %-8s %s\n", pSetting->name, db_column_text(&q, 0),
4417
- db_column_text(&q, 1));
4505
+ const char *zVal = (const char*)db_column_text(&q,1);
4506
+ const char *zName = (const char*)db_column_text(&q,0);
4507
+ if( zVal==0 ) zVal = "NULL";
4508
+ if( strchr(zVal,'\n')==0 ){
4509
+ fossil_print("%-24s %-11s %s\n", pSetting->name, zName, zVal);
4510
+ }else{
4511
+ fossil_print("%-24s %-11s\n", pSetting->name, zName);
4512
+ while( zVal[0] ){
4513
+ char *zNL = strchr(zVal, '\n');
4514
+ if( zNL==0 ){
4515
+ fossil_print(" %s\n", zVal);
4516
+ break;
4517
+ }else{
4518
+ int n = (int)(zNL - zVal);
4519
+ while( n>0 && fossil_isspace(zVal[n-1]) ){ n--; }
4520
+ fossil_print(" %.*s\n", n, zVal);
4521
+ zVal = zNL+1;
4522
+ }
4523
+ }
4524
+ }
44184525
}
4526
+ }else if( bIfChng ){
4527
+ /* Display nothing */
4528
+ versioned = 0;
44194529
}else if( valueOnly ){
44204530
fossil_print("\n");
44214531
}else{
4422
- fossil_print("%-20s\n", pSetting->name);
4532
+ fossil_print("%-24s\n", pSetting->name);
44234533
}
44244534
if( versioned ){
44254535
fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
44264536
pSetting->name);
44274537
}
@@ -4454,21 +4564,22 @@
44544564
char versionable; /* Is this setting versionable? */
44554565
char forceTextArea; /* Force using a text area for display? */
44564566
char sensitive; /* True if this a security-sensitive setting */
44574567
const char *def; /* Default value */
44584568
};
4569
+
44594570
#endif /* INTERFACE */
44604571
44614572
/*
4462
-** SETTING: access-log boolean default=off
4573
+** SETTING: access-log boolean default=on
44634574
**
44644575
** When the access-log setting is enabled, all login attempts (successful
44654576
** and unsuccessful) on the web interface are recorded in the "access" table
44664577
** of the repository.
44674578
*/
44684579
/*
4469
-** SETTING: admin-log boolean default=off
4580
+** SETTING: admin-log boolean default=on
44704581
**
44714582
** When the admin-log setting is enabled, configuration changes are recorded
44724583
** in the "admin_log" table of the repository.
44734584
*/
44744585
/*
@@ -4707,10 +4818,18 @@
47074818
*/
47084819
/*
47094820
** SETTING: editor width=32 sensitive
47104821
** The value is an external command that will launch the
47114822
** text editor command used for check-in comments.
4823
+**
4824
+** If this value is not set, then environment variables VISUAL and
4825
+** EDITOR are consulted, in that order. If neither of those are set,
4826
+** then a search is made for common text editors, including
4827
+** "notepad", "nano", "pico", "jove", "edit", "vi", "vim", and "ed".
4828
+**
4829
+** If this setting is false ("off", "no", "false", or "0") then no
4830
+** text editor is used.
47124831
*/
47134832
/*
47144833
** SETTING: empty-dirs width=40 versionable block-text
47154834
** The value is a list of pathnames parsed according to the same rules as
47164835
** the *-glob settings. On update and checkout commands, if no directory
@@ -4757,13 +4876,14 @@
47574876
** send the "pragma avoid-delta-manifests" statement in its reply,
47584877
** which will cause the client to avoid generating a delta
47594878
** manifest.
47604879
*/
47614880
/*
4762
-** SETTING: gdiff-command width=40 default=gdiff sensitive
4881
+** SETTING: gdiff-command width=40 sensitive
47634882
** The value is an external command to run when performing a graphical
4764
-** diff. If undefined, text diff will be used.
4883
+** diff. If undefined, a --tk diff is done if commands "tclsh" and "wish"
4884
+** are on PATH, or a --by diff is done if "tclsh" or "wish" are unavailable.
47654885
*/
47664886
/*
47674887
** SETTING: gmerge-command width=40 sensitive
47684888
** The value is a graphical merge conflict resolver command operating
47694889
** on four files. Examples:
@@ -5152,20 +5272,22 @@
51525272
** configuration database. If both a local and a global value exists for a
51535273
** setting, the local value takes precedence. This command normally operates
51545274
** on the local settings. Use the --global option to change global settings.
51555275
**
51565276
** Options:
5277
+** --changed Only show settings if the value differs from the default
5278
+** --exact Only consider exact name matches
51575279
** --global Set or unset the given property globally instead of
51585280
** setting or unsetting it for the open repository only
5159
-** --exact Only consider exact name matches
51605281
** --value Only show the value of a given property (implies --exact)
51615282
**
51625283
** See also: [[configuration]]
51635284
*/
51645285
void setting_cmd(void){
51655286
int i;
51665287
int globalFlag = find_option("global","g",0)!=0;
5288
+ int bIfChng = find_option("changed",0,0)!=0;
51675289
int exactFlag = find_option("exact",0,0)!=0;
51685290
int valueFlag = find_option("value",0,0)!=0;
51695291
/* Undocumented "--test-for-subsystem SUBSYS" option used to test
51705292
** the db_get_for_subsystem() interface: */
51715293
const char *zSubsys = find_option("test-for-subsystem",0,1);
@@ -5186,16 +5308,15 @@
51865308
}
51875309
if( valueFlag ){
51885310
if( g.argc!=3 ){
51895311
fossil_fatal("--value is only supported when qurying a given property");
51905312
}
5191
- exactFlag = 1;
51925313
}
51935314
51945315
if( g.argc==2 ){
51955316
for(i=0; i<nSetting; i++){
5196
- print_setting(&aSetting[i], 0);
5317
+ print_setting(&aSetting[i], 0, bIfChng);
51975318
}
51985319
}else if( g.argc==3 || g.argc==4 ){
51995320
const char *zName = g.argv[2];
52005321
int n = (int)strlen(zName);
52015322
const Setting *pSetting = db_find_setting(zName, !exactFlag);
@@ -5246,11 +5367,11 @@
52465367
fossil_print(" [%s]", zValue);
52475368
fossil_free(zValue);
52485369
}
52495370
fossil_print("\n");
52505371
}else{
5251
- print_setting(pSetting, valueFlag);
5372
+ print_setting(pSetting, valueFlag, bIfChng);
52525373
}
52535374
pSetting++;
52545375
}
52555376
}
52565377
}else{
52575378
--- src/db.c
+++ src/db.c
@@ -3204,23 +3204,16 @@
3204
3205 db_unprotect(PROTECT_ALL);
3206 db_set("content-schema", CONTENT_SCHEMA, 0);
3207 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
3208 db_set("rebuilt", get_version(), 0);
3209 db_set("admin-log", "1", 0);
3210 db_set("access-log", "1", 0);
3211 db_multi_exec(
3212 "INSERT INTO config(name,value,mtime)"
3213 " VALUES('server-code', lower(hex(randomblob(20))),now());"
3214 "INSERT INTO config(name,value,mtime)"
3215 " VALUES('project-code', lower(hex(randomblob(20))),now());"
3216 );
3217 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
3218 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
3219 if( !db_is_global("timeline-plaintext") ){
3220 db_set_int("timeline-plaintext", 1, 0);
3221 }
3222 db_create_default_users(0, zDefaultUser);
3223 if( zDefaultUser ) g.zLogin = zDefaultUser;
3224 user_select();
3225
3226 if( zTemplate ){
@@ -3647,66 +3640,79 @@
3647 **
3648 ** If the zNonVersionedSetting parameter is not NULL then it holds the
3649 ** non-versioned value for this setting. If both a versioned and a
3650 ** non-versioned value exist and are not equal, then a warning message
3651 ** might be generated.
 
 
 
 
 
 
 
3652 */
3653 char *db_get_versioned(const char *zName, char *zNonVersionedSetting){
 
 
 
 
3654 char *zVersionedSetting = 0;
3655 int noWarn = 0;
3656 int found = 0;
3657 struct _cacheEntry {
3658 struct _cacheEntry *next;
3659 const char *zName, *zValue;
3660 } *cacheEntry = 0;
3661 static struct _cacheEntry *cache = 0;
3662
3663 if( !g.localOpen && g.zOpenRevision==0 ) return zNonVersionedSetting;
 
 
 
3664 /* Look up name in cache */
3665 cacheEntry = cache;
3666 while( cacheEntry!=0 ){
3667 if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
3668 zVersionedSetting = fossil_strdup(cacheEntry->zValue);
3669 break;
3670 }
3671 cacheEntry = cacheEntry->next;
3672 }
 
 
 
3673 /* Attempt to read value from file in check-out if there wasn't a cache hit.*/
3674 if( cacheEntry==0 ){
3675 Blob versionedPathname;
3676 Blob setting;
3677 blob_zero(&versionedPathname);
3678 blob_zero(&setting);
3679 blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
3680 g.zLocalRoot, zName);
3681 if( !g.localOpen ){
3682 /* Repository is in the process of being opened, but files have not been
3683 * written to disk. Load from the database. */
3684 Blob noWarnFile;
3685 if( historical_blob(g.zOpenRevision, blob_str(&versionedPathname),
3686 &setting, 0) ){
3687 found = 1;
3688 }
3689 /* See if there's a no-warn flag */
3690 blob_append(&versionedPathname, ".no-warn", -1);
3691 blob_zero(&noWarnFile);
3692 if( historical_blob(g.zOpenRevision, blob_str(&versionedPathname),
3693 &noWarnFile, 0) ){
3694 noWarn = 1;
3695 }
3696 blob_reset(&noWarnFile);
3697 }else if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3698 /* File exists, and contains the value for this setting. Load from
3699 ** the file. */
3700 const char *zFile = blob_str(&versionedPathname);
3701 if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){
3702 found = 1;
3703 }
3704 /* See if there's a no-warn flag */
3705 blob_append(&versionedPathname, ".no-warn", -1);
3706 if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3707 noWarn = 1;
3708 }
3709 }
3710 blob_reset(&versionedPathname);
3711 if( found ){
3712 blob_strip_comment_lines(&setting, &setting);
@@ -3713,20 +3719,27 @@
3713 blob_trim(&setting); /* Avoid non-obvious problems with line endings
3714 ** on boolean properties */
3715 zVersionedSetting = fossil_strdup(blob_str(&setting));
3716 }
3717 blob_reset(&setting);
 
3718 /* Store result in cache, which can be the value or 0 if not found */
3719 cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry));
3720 cacheEntry->next = cache;
3721 cacheEntry->zName = zName;
3722 cacheEntry->zValue = fossil_strdup(zVersionedSetting);
3723 cache = cacheEntry;
 
 
3724 }
 
3725 /* Display a warning? */
3726 if( zVersionedSetting!=0 && zNonVersionedSetting!=0
3727 && zNonVersionedSetting[0]!='\0' && !noWarn
 
 
 
3728 ){
3729 /* There's a versioned setting, and a non-versioned setting. Tell
3730 ** the user about the conflict */
3731 fossil_warning(
3732 "setting %s has both versioned and non-versioned values: using "
@@ -3735,10 +3748,11 @@
3735 "\"%/.fossil-settings/%s.no-warn\" in the check-out root, or delete "
3736 "the non-versioned setting with \"fossil unset %s\")", zName,
3737 g.zLocalRoot, zName, g.zLocalRoot, zName, zName
3738 );
3739 }
 
3740 /* Prefer the versioned setting */
3741 return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
3742 }
3743
3744
@@ -3778,11 +3792,11 @@
3778 }
3779 if( pSetting!=0 && pSetting->versionable ){
3780 /* This is a versionable setting, try and get the info from a
3781 ** checked-out file */
3782 char * zZ = z;
3783 z = db_get_versioned(zName, z);
3784 if(zZ != z){
3785 fossil_free(zZ);
3786 }
3787 }
3788 if( z==0 ){
@@ -3919,11 +3933,11 @@
3919 }
3920 fossil_free(zVal);
3921 return dflt;
3922 }
3923 int db_get_versioned_boolean(const char *zName, int dflt){
3924 char *zVal = db_get_versioned(zName, 0);
3925 if( zVal==0 ) return dflt;
3926 if( is_truth(zVal) ) return 1;
3927 if( is_false(zVal) ) return 0;
3928 return dflt;
3929 }
@@ -4048,14 +4062,30 @@
4048 ** Get the manifest setting. For backwards compatibility first check if the
4049 ** value is a boolean. If it's not a boolean, treat each character as a flag
4050 ** to enable a manifest type. This system puts certain boundary conditions on
4051 ** which letters can be used to represent flags (any permutation of flags must
4052 ** not be able to fully form one of the boolean values).
 
 
 
 
 
 
 
 
4053 */
4054 int db_get_manifest_setting(void){
4055 int flg;
4056 char *zVal = db_get("manifest", 0);
 
 
 
 
 
 
 
 
4057 if( zVal==0 || is_false(zVal) ){
4058 return 0;
4059 }else if( is_truth(zVal) ){
4060 return MFESTFLG_RAW|MFESTFLG_UUID;
4061 }
@@ -4068,10 +4098,37 @@
4068 }
4069 zVal++;
4070 }
4071 return flg;
4072 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4073
4074
4075 /*
4076 ** Record the name of a local repository in the global_config() database.
4077 ** The repository filename %s is recorded as an entry with a "name" field
@@ -4371,16 +4428,37 @@
4371 }
4372 }
4373 g.argc = 2;
4374 info_cmd();
4375 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4376
4377 /*
4378 ** Print the current value of a setting identified by the pSetting
4379 ** pointer.
 
 
 
 
 
4380 */
4381 void print_setting(const Setting *pSetting, int valueOnly){
4382 Stmt q;
4383 int versioned = 0;
4384 if( pSetting->versionable && g.localOpen ){
4385 /* Check to see if this is overridden by a versionable settings file */
4386 Blob versionedPathname;
@@ -4391,11 +4469,16 @@
4391 versioned = 1;
4392 }
4393 blob_reset(&versionedPathname);
4394 }
4395 if( valueOnly && versioned ){
4396 fossil_print("%s\n", db_get_versioned(pSetting->name, NULL));
 
 
 
 
 
4397 return;
4398 }
4399 if( g.repositoryOpen ){
4400 db_prepare(&q,
4401 "SELECT '(local)', value FROM config WHERE name=%Q"
@@ -4408,20 +4491,47 @@
4408 "SELECT '(global)', value FROM global_config WHERE name=%Q",
4409 pSetting->name
4410 );
4411 }
4412 if( db_step(&q)==SQLITE_ROW ){
4413 if( valueOnly ){
 
 
 
 
 
 
4414 fossil_print("%s\n", db_column_text(&q, 1));
4415 }else{
4416 fossil_print("%-20s %-8s %s\n", pSetting->name, db_column_text(&q, 0),
4417 db_column_text(&q, 1));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4418 }
 
 
 
4419 }else if( valueOnly ){
4420 fossil_print("\n");
4421 }else{
4422 fossil_print("%-20s\n", pSetting->name);
4423 }
4424 if( versioned ){
4425 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
4426 pSetting->name);
4427 }
@@ -4454,21 +4564,22 @@
4454 char versionable; /* Is this setting versionable? */
4455 char forceTextArea; /* Force using a text area for display? */
4456 char sensitive; /* True if this a security-sensitive setting */
4457 const char *def; /* Default value */
4458 };
 
4459 #endif /* INTERFACE */
4460
4461 /*
4462 ** SETTING: access-log boolean default=off
4463 **
4464 ** When the access-log setting is enabled, all login attempts (successful
4465 ** and unsuccessful) on the web interface are recorded in the "access" table
4466 ** of the repository.
4467 */
4468 /*
4469 ** SETTING: admin-log boolean default=off
4470 **
4471 ** When the admin-log setting is enabled, configuration changes are recorded
4472 ** in the "admin_log" table of the repository.
4473 */
4474 /*
@@ -4707,10 +4818,18 @@
4707 */
4708 /*
4709 ** SETTING: editor width=32 sensitive
4710 ** The value is an external command that will launch the
4711 ** text editor command used for check-in comments.
 
 
 
 
 
 
 
 
4712 */
4713 /*
4714 ** SETTING: empty-dirs width=40 versionable block-text
4715 ** The value is a list of pathnames parsed according to the same rules as
4716 ** the *-glob settings. On update and checkout commands, if no directory
@@ -4757,13 +4876,14 @@
4757 ** send the "pragma avoid-delta-manifests" statement in its reply,
4758 ** which will cause the client to avoid generating a delta
4759 ** manifest.
4760 */
4761 /*
4762 ** SETTING: gdiff-command width=40 default=gdiff sensitive
4763 ** The value is an external command to run when performing a graphical
4764 ** diff. If undefined, text diff will be used.
 
4765 */
4766 /*
4767 ** SETTING: gmerge-command width=40 sensitive
4768 ** The value is a graphical merge conflict resolver command operating
4769 ** on four files. Examples:
@@ -5152,20 +5272,22 @@
5152 ** configuration database. If both a local and a global value exists for a
5153 ** setting, the local value takes precedence. This command normally operates
5154 ** on the local settings. Use the --global option to change global settings.
5155 **
5156 ** Options:
 
 
5157 ** --global Set or unset the given property globally instead of
5158 ** setting or unsetting it for the open repository only
5159 ** --exact Only consider exact name matches
5160 ** --value Only show the value of a given property (implies --exact)
5161 **
5162 ** See also: [[configuration]]
5163 */
5164 void setting_cmd(void){
5165 int i;
5166 int globalFlag = find_option("global","g",0)!=0;
 
5167 int exactFlag = find_option("exact",0,0)!=0;
5168 int valueFlag = find_option("value",0,0)!=0;
5169 /* Undocumented "--test-for-subsystem SUBSYS" option used to test
5170 ** the db_get_for_subsystem() interface: */
5171 const char *zSubsys = find_option("test-for-subsystem",0,1);
@@ -5186,16 +5308,15 @@
5186 }
5187 if( valueFlag ){
5188 if( g.argc!=3 ){
5189 fossil_fatal("--value is only supported when qurying a given property");
5190 }
5191 exactFlag = 1;
5192 }
5193
5194 if( g.argc==2 ){
5195 for(i=0; i<nSetting; i++){
5196 print_setting(&aSetting[i], 0);
5197 }
5198 }else if( g.argc==3 || g.argc==4 ){
5199 const char *zName = g.argv[2];
5200 int n = (int)strlen(zName);
5201 const Setting *pSetting = db_find_setting(zName, !exactFlag);
@@ -5246,11 +5367,11 @@
5246 fossil_print(" [%s]", zValue);
5247 fossil_free(zValue);
5248 }
5249 fossil_print("\n");
5250 }else{
5251 print_setting(pSetting, valueFlag);
5252 }
5253 pSetting++;
5254 }
5255 }
5256 }else{
5257
--- src/db.c
+++ src/db.c
@@ -3204,23 +3204,16 @@
3204
3205 db_unprotect(PROTECT_ALL);
3206 db_set("content-schema", CONTENT_SCHEMA, 0);
3207 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
3208 db_set("rebuilt", get_version(), 0);
 
 
3209 db_multi_exec(
3210 "INSERT INTO config(name,value,mtime)"
3211 " VALUES('server-code', lower(hex(randomblob(20))),now());"
3212 "INSERT INTO config(name,value,mtime)"
3213 " VALUES('project-code', lower(hex(randomblob(20))),now());"
3214 );
 
 
 
 
 
3215 db_create_default_users(0, zDefaultUser);
3216 if( zDefaultUser ) g.zLogin = zDefaultUser;
3217 user_select();
3218
3219 if( zTemplate ){
@@ -3647,66 +3640,79 @@
3640 **
3641 ** If the zNonVersionedSetting parameter is not NULL then it holds the
3642 ** non-versioned value for this setting. If both a versioned and a
3643 ** non-versioned value exist and are not equal, then a warning message
3644 ** might be generated.
3645 **
3646 ** zCkin is normally NULL. In that case, the versioned setting is
3647 ** take from the local check-out, if a local checkout exists, or from
3648 ** checkin named by the g.zOpenRevision global variable. If zCkin is
3649 ** not NULL, then zCkin is the name of the specific checkin from which
3650 ** versioned setting value is taken. When zCkin is not NULL, the cache
3651 ** is bypassed.
3652 */
3653 char *db_get_versioned(
3654 const char *zName,
3655 char *zNonVersionedSetting,
3656 const char *zCkin
3657 ){
3658 char *zVersionedSetting = 0;
3659 int noWarn = 0;
3660 int found = 0;
3661 struct _cacheEntry {
3662 struct _cacheEntry *next;
3663 const char *zName, *zValue;
3664 } *cacheEntry = 0;
3665 static struct _cacheEntry *cache = 0;
3666
3667 if( !g.localOpen && g.zOpenRevision==0 && zCkin==0 ){
3668 return zNonVersionedSetting;
3669 }
3670
3671 /* Look up name in cache */
3672 if( zCkin==0 ){
3673 cacheEntry = cache;
3674 while( cacheEntry!=0 ){
3675 if( fossil_strcmp(cacheEntry->zName, zName)==0 ){
3676 zVersionedSetting = fossil_strdup(cacheEntry->zValue);
3677 break;
3678 }
3679 cacheEntry = cacheEntry->next;
3680 }
3681 }
3682
3683 /* Attempt to read value from file in check-out if there wasn't a cache hit.*/
3684 if( cacheEntry==0 ){
3685 Blob versionedPathname;
3686 Blob setting;
3687 blob_init(&versionedPathname, 0, 0);
3688 blob_init(&setting, 0, 0);
3689 if( !g.localOpen || zCkin!=0 ){
3690 /* Repository is in the process of being opened, but files have not been
3691 * written to disk. Load from the database. */
3692 blob_appendf(&versionedPathname, ".fossil-settings/%s", zName);
3693 if( historical_blob(zCkin ? zCkin : g.zOpenRevision,
3694 blob_str(&versionedPathname),
3695 &setting, 0)
3696 ){
3697 found = 1;
3698 }
3699 }else{
3700 blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
3701 g.zLocalRoot, zName);
3702 if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3703 /* File exists, and contains the value for this setting. Load from
3704 ** the file. */
3705 const char *zFile = blob_str(&versionedPathname);
3706 if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){
3707 found = 1;
3708 }
3709 /* See if there's a no-warn flag */
3710 blob_append(&versionedPathname, ".no-warn", -1);
3711 if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
3712 noWarn = 1;
3713 }
 
 
 
 
3714 }
3715 }
3716 blob_reset(&versionedPathname);
3717 if( found ){
3718 blob_strip_comment_lines(&setting, &setting);
@@ -3713,20 +3719,27 @@
3719 blob_trim(&setting); /* Avoid non-obvious problems with line endings
3720 ** on boolean properties */
3721 zVersionedSetting = fossil_strdup(blob_str(&setting));
3722 }
3723 blob_reset(&setting);
3724
3725 /* Store result in cache, which can be the value or 0 if not found */
3726 if( zCkin==0 ){
3727 cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(*cacheEntry));
3728 cacheEntry->next = cache;
3729 cacheEntry->zName = zName;
3730 cacheEntry->zValue = fossil_strdup(zVersionedSetting);
3731 cache = cacheEntry;
3732 }
3733 }
3734
3735 /* Display a warning? */
3736 if( zVersionedSetting!=0
3737 && zNonVersionedSetting!=0
3738 && zNonVersionedSetting[0]!='\0'
3739 && zCkin==0
3740 && !noWarn
3741 ){
3742 /* There's a versioned setting, and a non-versioned setting. Tell
3743 ** the user about the conflict */
3744 fossil_warning(
3745 "setting %s has both versioned and non-versioned values: using "
@@ -3735,10 +3748,11 @@
3748 "\"%/.fossil-settings/%s.no-warn\" in the check-out root, or delete "
3749 "the non-versioned setting with \"fossil unset %s\")", zName,
3750 g.zLocalRoot, zName, g.zLocalRoot, zName, zName
3751 );
3752 }
3753
3754 /* Prefer the versioned setting */
3755 return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting;
3756 }
3757
3758
@@ -3778,11 +3792,11 @@
3792 }
3793 if( pSetting!=0 && pSetting->versionable ){
3794 /* This is a versionable setting, try and get the info from a
3795 ** checked-out file */
3796 char * zZ = z;
3797 z = db_get_versioned(zName, z, 0);
3798 if(zZ != z){
3799 fossil_free(zZ);
3800 }
3801 }
3802 if( z==0 ){
@@ -3919,11 +3933,11 @@
3933 }
3934 fossil_free(zVal);
3935 return dflt;
3936 }
3937 int db_get_versioned_boolean(const char *zName, int dflt){
3938 char *zVal = db_get_versioned(zName, 0, 0);
3939 if( zVal==0 ) return dflt;
3940 if( is_truth(zVal) ) return 1;
3941 if( is_false(zVal) ) return 0;
3942 return dflt;
3943 }
@@ -4048,14 +4062,30 @@
4062 ** Get the manifest setting. For backwards compatibility first check if the
4063 ** value is a boolean. If it's not a boolean, treat each character as a flag
4064 ** to enable a manifest type. This system puts certain boundary conditions on
4065 ** which letters can be used to represent flags (any permutation of flags must
4066 ** not be able to fully form one of the boolean values).
4067 **
4068 ** "manifest" is a versionable setting. But we do not issue a warning
4069 ** if there is a conflict. Instead, the value returned is the value for
4070 ** the versioned setting if the versioned setting exists, or the ordinary
4071 ** setting otherwise.
4072 **
4073 ** The argument zCkin is the specific check-in for which we want the
4074 ** manifest setting.
4075 */
4076 int db_get_manifest_setting(const char *zCkin){
4077 int flg;
4078 char *zVal;
4079
4080 /* Look for the versioned setting first */
4081 zVal = db_get_versioned("manifest", 0, zCkin);
4082
4083 if( zVal==0 && g.repositoryOpen ){
4084 /* No versioned setting, look for the repository setting second */
4085 zVal = db_text(0, "SELECT value FROM config WHERE name='manifest'");
4086 }
4087 if( zVal==0 || is_false(zVal) ){
4088 return 0;
4089 }else if( is_truth(zVal) ){
4090 return MFESTFLG_RAW|MFESTFLG_UUID;
4091 }
@@ -4068,10 +4098,37 @@
4098 }
4099 zVal++;
4100 }
4101 return flg;
4102 }
4103
4104 /*
4105 ** COMMAND: test-manifest-setting
4106 **
4107 ** Usage: %fossil test-manifest-setting VERSION VERSION ...
4108 **
4109 ** Display the value for the "manifest" setting for various versions
4110 ** of the repository.
4111 */
4112 void test_manfest_setting_cmd(void){
4113 int i;
4114 db_find_and_open_repository(0, 0);
4115 for(i=2; i<g.argc; i++){
4116 int m = db_get_manifest_setting(g.argv[i]);
4117 fossil_print("%s:\n", g.argv[i]);
4118 fossil_print(" flags = 0x%02x\n", m);
4119 if( m & MFESTFLG_RAW ){
4120 fossil_print(" manifest\n");
4121 }
4122 if( m & MFESTFLG_UUID ){
4123 fossil_print(" manifest.uuid\n");
4124 }
4125 if( m & MFESTFLG_TAGS ){
4126 fossil_print(" manifest.tags\n");
4127 }
4128 }
4129 }
4130
4131
4132 /*
4133 ** Record the name of a local repository in the global_config() database.
4134 ** The repository filename %s is recorded as an entry with a "name" field
@@ -4371,16 +4428,37 @@
4428 }
4429 }
4430 g.argc = 2;
4431 info_cmd();
4432 }
4433
4434 /*
4435 ** Return true if pSetting has its default value assuming its
4436 ** current value is zVal.
4437 */
4438 int setting_has_default_value(const Setting *pSetting, const char *zVal){
4439 if( zVal==0 ) return 1;
4440 if( pSetting->def==0 ) return 0;
4441 if( pSetting->width==0 ){
4442 return is_false(pSetting->def)==is_false(zVal);
4443 }
4444 if( fossil_strcmp(pSetting->def, zVal)==0 ) return 1;
4445 if( is_false(zVal) && is_false(pSetting->def) ) return 1;
4446 if( is_truth(zVal) && is_truth(pSetting->def) ) return 1;
4447 return 0;
4448 }
4449
4450 /*
4451 ** Print the current value of a setting identified by the pSetting
4452 ** pointer.
4453 **
4454 ** Only show the value, not the setting name, if valueOnly is true.
4455 **
4456 ** Show nothing if bIfChng is true and the setting is not currently set
4457 ** or is set to its default value.
4458 */
4459 void print_setting(const Setting *pSetting, int valueOnly, int bIfChng){
4460 Stmt q;
4461 int versioned = 0;
4462 if( pSetting->versionable && g.localOpen ){
4463 /* Check to see if this is overridden by a versionable settings file */
4464 Blob versionedPathname;
@@ -4391,11 +4469,16 @@
4469 versioned = 1;
4470 }
4471 blob_reset(&versionedPathname);
4472 }
4473 if( valueOnly && versioned ){
4474 const char *zVal = db_get_versioned(pSetting->name, NULL, NULL);
4475 if( !bIfChng || (zVal!=0 && fossil_strcmp(zVal, pSetting->def)!=0) ){
4476 fossil_print("%s\n", db_get_versioned(pSetting->name, NULL, NULL));
4477 }else{
4478 versioned = 0;
4479 }
4480 return;
4481 }
4482 if( g.repositoryOpen ){
4483 db_prepare(&q,
4484 "SELECT '(local)', value FROM config WHERE name=%Q"
@@ -4408,20 +4491,47 @@
4491 "SELECT '(global)', value FROM global_config WHERE name=%Q",
4492 pSetting->name
4493 );
4494 }
4495 if( db_step(&q)==SQLITE_ROW ){
4496 const char *zVal = db_column_text(&q,1);
4497 if( bIfChng && setting_has_default_value(pSetting,zVal) ){
4498 if( versioned ){
4499 fossil_print("%-24s (versioned)\n", pSetting->name);
4500 versioned = 0;
4501 }
4502 }else if( valueOnly ){
4503 fossil_print("%s\n", db_column_text(&q, 1));
4504 }else{
4505 const char *zVal = (const char*)db_column_text(&q,1);
4506 const char *zName = (const char*)db_column_text(&q,0);
4507 if( zVal==0 ) zVal = "NULL";
4508 if( strchr(zVal,'\n')==0 ){
4509 fossil_print("%-24s %-11s %s\n", pSetting->name, zName, zVal);
4510 }else{
4511 fossil_print("%-24s %-11s\n", pSetting->name, zName);
4512 while( zVal[0] ){
4513 char *zNL = strchr(zVal, '\n');
4514 if( zNL==0 ){
4515 fossil_print(" %s\n", zVal);
4516 break;
4517 }else{
4518 int n = (int)(zNL - zVal);
4519 while( n>0 && fossil_isspace(zVal[n-1]) ){ n--; }
4520 fossil_print(" %.*s\n", n, zVal);
4521 zVal = zNL+1;
4522 }
4523 }
4524 }
4525 }
4526 }else if( bIfChng ){
4527 /* Display nothing */
4528 versioned = 0;
4529 }else if( valueOnly ){
4530 fossil_print("\n");
4531 }else{
4532 fossil_print("%-24s\n", pSetting->name);
4533 }
4534 if( versioned ){
4535 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
4536 pSetting->name);
4537 }
@@ -4454,21 +4564,22 @@
4564 char versionable; /* Is this setting versionable? */
4565 char forceTextArea; /* Force using a text area for display? */
4566 char sensitive; /* True if this a security-sensitive setting */
4567 const char *def; /* Default value */
4568 };
4569
4570 #endif /* INTERFACE */
4571
4572 /*
4573 ** SETTING: access-log boolean default=on
4574 **
4575 ** When the access-log setting is enabled, all login attempts (successful
4576 ** and unsuccessful) on the web interface are recorded in the "access" table
4577 ** of the repository.
4578 */
4579 /*
4580 ** SETTING: admin-log boolean default=on
4581 **
4582 ** When the admin-log setting is enabled, configuration changes are recorded
4583 ** in the "admin_log" table of the repository.
4584 */
4585 /*
@@ -4707,10 +4818,18 @@
4818 */
4819 /*
4820 ** SETTING: editor width=32 sensitive
4821 ** The value is an external command that will launch the
4822 ** text editor command used for check-in comments.
4823 **
4824 ** If this value is not set, then environment variables VISUAL and
4825 ** EDITOR are consulted, in that order. If neither of those are set,
4826 ** then a search is made for common text editors, including
4827 ** "notepad", "nano", "pico", "jove", "edit", "vi", "vim", and "ed".
4828 **
4829 ** If this setting is false ("off", "no", "false", or "0") then no
4830 ** text editor is used.
4831 */
4832 /*
4833 ** SETTING: empty-dirs width=40 versionable block-text
4834 ** The value is a list of pathnames parsed according to the same rules as
4835 ** the *-glob settings. On update and checkout commands, if no directory
@@ -4757,13 +4876,14 @@
4876 ** send the "pragma avoid-delta-manifests" statement in its reply,
4877 ** which will cause the client to avoid generating a delta
4878 ** manifest.
4879 */
4880 /*
4881 ** SETTING: gdiff-command width=40 sensitive
4882 ** The value is an external command to run when performing a graphical
4883 ** diff. If undefined, a --tk diff is done if commands "tclsh" and "wish"
4884 ** are on PATH, or a --by diff is done if "tclsh" or "wish" are unavailable.
4885 */
4886 /*
4887 ** SETTING: gmerge-command width=40 sensitive
4888 ** The value is a graphical merge conflict resolver command operating
4889 ** on four files. Examples:
@@ -5152,20 +5272,22 @@
5272 ** configuration database. If both a local and a global value exists for a
5273 ** setting, the local value takes precedence. This command normally operates
5274 ** on the local settings. Use the --global option to change global settings.
5275 **
5276 ** Options:
5277 ** --changed Only show settings if the value differs from the default
5278 ** --exact Only consider exact name matches
5279 ** --global Set or unset the given property globally instead of
5280 ** setting or unsetting it for the open repository only
 
5281 ** --value Only show the value of a given property (implies --exact)
5282 **
5283 ** See also: [[configuration]]
5284 */
5285 void setting_cmd(void){
5286 int i;
5287 int globalFlag = find_option("global","g",0)!=0;
5288 int bIfChng = find_option("changed",0,0)!=0;
5289 int exactFlag = find_option("exact",0,0)!=0;
5290 int valueFlag = find_option("value",0,0)!=0;
5291 /* Undocumented "--test-for-subsystem SUBSYS" option used to test
5292 ** the db_get_for_subsystem() interface: */
5293 const char *zSubsys = find_option("test-for-subsystem",0,1);
@@ -5186,16 +5308,15 @@
5308 }
5309 if( valueFlag ){
5310 if( g.argc!=3 ){
5311 fossil_fatal("--value is only supported when qurying a given property");
5312 }
 
5313 }
5314
5315 if( g.argc==2 ){
5316 for(i=0; i<nSetting; i++){
5317 print_setting(&aSetting[i], 0, bIfChng);
5318 }
5319 }else if( g.argc==3 || g.argc==4 ){
5320 const char *zName = g.argv[2];
5321 int n = (int)strlen(zName);
5322 const Setting *pSetting = db_find_setting(zName, !exactFlag);
@@ -5246,11 +5367,11 @@
5367 fossil_print(" [%s]", zValue);
5368 fossil_free(zValue);
5369 }
5370 fossil_print("\n");
5371 }else{
5372 print_setting(pSetting, valueFlag, bIfChng);
5373 }
5374 pSetting++;
5375 }
5376 }
5377 }else{
5378
--- src/default.css
+++ src/default.css
@@ -750,10 +750,11 @@
750750
body.tkt div.content ol.tkt-changes > li:target > ol {
751751
border-left: 1px solid gold;
752752
}
753753
body.cpage-ckout .file-change-line,
754754
body.cpage-info .file-change-line,
755
+body.cpage-vinfo .file-change-line,
755756
body.cpage-vdiff .file-change-line {
756757
margin-top: 16px;
757758
margin-bottom: 16px;
758759
margin-right: 1em /* keep it from nudging right up against the scrollbar-reveal zone */;
759760
display: flex;
760761
--- src/default.css
+++ src/default.css
@@ -750,10 +750,11 @@
750 body.tkt div.content ol.tkt-changes > li:target > ol {
751 border-left: 1px solid gold;
752 }
753 body.cpage-ckout .file-change-line,
754 body.cpage-info .file-change-line,
 
755 body.cpage-vdiff .file-change-line {
756 margin-top: 16px;
757 margin-bottom: 16px;
758 margin-right: 1em /* keep it from nudging right up against the scrollbar-reveal zone */;
759 display: flex;
760
--- src/default.css
+++ src/default.css
@@ -750,10 +750,11 @@
750 body.tkt div.content ol.tkt-changes > li:target > ol {
751 border-left: 1px solid gold;
752 }
753 body.cpage-ckout .file-change-line,
754 body.cpage-info .file-change-line,
755 body.cpage-vinfo .file-change-line,
756 body.cpage-vdiff .file-change-line {
757 margin-top: 16px;
758 margin-bottom: 16px;
759 margin-right: 1em /* keep it from nudging right up against the scrollbar-reveal zone */;
760 display: flex;
761
+7 -1
--- src/diff.c
+++ src/diff.c
@@ -3175,11 +3175,13 @@
31753175
}
31763176
g.diffCnt[1] += nIns;
31773177
g.diffCnt[2] += nDel;
31783178
if( nIns+nDel ){
31793179
g.diffCnt[0]++;
3180
- blob_appendf(pOut, "%10d %10d", nIns, nDel);
3180
+ if( !(pCfg->diffFlags & DIFF_BRIEF) ){
3181
+ blob_appendf(pOut, "%10d %10d", nIns, nDel);
3182
+ }
31813183
}
31823184
}else if( pCfg->diffFlags & (DIFF_RAW|DIFF_BY_TOKEN) ){
31833185
const int *R = c.aEdit;
31843186
unsigned int r;
31853187
for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
@@ -3335,10 +3337,14 @@
33353337
if( zDiffBinary ){
33363338
if( is_truth(zDiffBinary) ) diffFlags |= DIFF_INCBINARY;
33373339
}else if( db_get_boolean("diff-binary", 1) ){
33383340
diffFlags |= DIFF_INCBINARY;
33393341
}
3342
+ }else if( isGDiff) {
3343
+ /* No external gdiff command found, using --by */
3344
+ diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER
3345
+ |DIFF_SIDEBYSIDE;
33403346
}
33413347
}
33423348
if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE;
33433349
/* Deprecated, but retained for script compatibility. */
33443350
else if( find_option("new-file","N",0)!=0 ) diffFlags |= DIFF_VERBOSE;
33453351
--- src/diff.c
+++ src/diff.c
@@ -3175,11 +3175,13 @@
3175 }
3176 g.diffCnt[1] += nIns;
3177 g.diffCnt[2] += nDel;
3178 if( nIns+nDel ){
3179 g.diffCnt[0]++;
3180 blob_appendf(pOut, "%10d %10d", nIns, nDel);
 
 
3181 }
3182 }else if( pCfg->diffFlags & (DIFF_RAW|DIFF_BY_TOKEN) ){
3183 const int *R = c.aEdit;
3184 unsigned int r;
3185 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
@@ -3335,10 +3337,14 @@
3335 if( zDiffBinary ){
3336 if( is_truth(zDiffBinary) ) diffFlags |= DIFF_INCBINARY;
3337 }else if( db_get_boolean("diff-binary", 1) ){
3338 diffFlags |= DIFF_INCBINARY;
3339 }
 
 
 
 
3340 }
3341 }
3342 if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE;
3343 /* Deprecated, but retained for script compatibility. */
3344 else if( find_option("new-file","N",0)!=0 ) diffFlags |= DIFF_VERBOSE;
3345
--- src/diff.c
+++ src/diff.c
@@ -3175,11 +3175,13 @@
3175 }
3176 g.diffCnt[1] += nIns;
3177 g.diffCnt[2] += nDel;
3178 if( nIns+nDel ){
3179 g.diffCnt[0]++;
3180 if( !(pCfg->diffFlags & DIFF_BRIEF) ){
3181 blob_appendf(pOut, "%10d %10d", nIns, nDel);
3182 }
3183 }
3184 }else if( pCfg->diffFlags & (DIFF_RAW|DIFF_BY_TOKEN) ){
3185 const int *R = c.aEdit;
3186 unsigned int r;
3187 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
@@ -3335,10 +3337,14 @@
3337 if( zDiffBinary ){
3338 if( is_truth(zDiffBinary) ) diffFlags |= DIFF_INCBINARY;
3339 }else if( db_get_boolean("diff-binary", 1) ){
3340 diffFlags |= DIFF_INCBINARY;
3341 }
3342 }else if( isGDiff) {
3343 /* No external gdiff command found, using --by */
3344 diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER
3345 |DIFF_SIDEBYSIDE;
3346 }
3347 }
3348 if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE;
3349 /* Deprecated, but retained for script compatibility. */
3350 else if( find_option("new-file","N",0)!=0 ) diffFlags |= DIFF_VERBOSE;
3351
+36 -7
--- src/diff.tcl
+++ src/diff.tcl
@@ -90,28 +90,56 @@
9090
set x [lindex $difftxt $ii]
9191
incr ii
9292
return $x
9393
}
9494
95
-proc readDiffs {fossilcmd} {
95
+proc reloadDiff {} {
96
+ global fossilcmd difftxt
97
+ unset -nocomplain difftxt
98
+ set idx [.txtA index @0,0]
99
+ readDiffs $fossilcmd 1
100
+ update
101
+ viewDiff $idx
102
+}
103
+
104
+proc readDiffs {fossilcmd redo} {
96105
global difftxt debug
97106
if {![info exists difftxt]} {
98107
if {$debug} {
99108
puts "# [list open $fossilcmd r]"
100109
flush stdout
101110
}
102
- set in [open $fossilcmd r]
103
- fconfigure $in -encoding utf-8
104
- set difftxt [split [read $in] \n]
105
- close $in
111
+ if {[catch {
112
+ set in [open $fossilcmd r]
113
+ fconfigure $in -encoding utf-8
114
+ set difftxt [split [read $in] \n]
115
+ close $in
116
+ } msg]} {
117
+ if {$redo} {
118
+ tk_messageBox -type ok -title Error -message "Unable to refresh:\n$msg"
119
+ return 0
120
+ } else {
121
+ puts $msg
122
+ exit 1
123
+ }
124
+ }
106125
}
107126
set N [llength $difftxt]
108127
set ii 0
109128
set nDiffs 0
110129
set n1 0
111130
set n2 0
112131
array set widths {txt 3 ln 3 mkr 1}
132
+ if {$redo} {
133
+ foreach c [cols] {$c config -state normal}
134
+ .lnA delete 1.0 end
135
+ .txtA delete 1.0 end
136
+ .lnB delete 1.0 end
137
+ .txtB delete 1.0 end
138
+ .mkr delete 1.0 end
139
+ .wfiles.lb delete 0 end
140
+ }
113141
114142
115143
set fromIndex [lsearch -glob $fossilcmd *-from]
116144
set toIndex [lsearch -glob $fossilcmd *-to]
117145
set branchIndex [lsearch -glob $fossilcmd *-branch]
@@ -459,11 +487,11 @@
459487
::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
460488
::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
461489
::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
462490
frame .spacer
463491
464
-if {[readDiffs $fossilcmd] == 0} {
492
+if {[readDiffs $fossilcmd 0] == 0} {
465493
tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
466494
exit
467495
}
468496
update idletasks
469497
@@ -574,14 +602,15 @@
574602
$w tag config search -background {#fcc000}
575603
}
576604
set ::search $w
577605
}
578606
::ttk::button .bb.quit -text {Quit} -command exit
607
+::ttk::button .bb.reload -text {Reload} -command reloadDiff
579608
::ttk::button .bb.invert -text {Invert} -command invertDiff
580609
::ttk::button .bb.save -text {Save As...} -command saveDiff
581610
::ttk::button .bb.search -text {Search} -command searchOnOff
582
-pack .bb.quit .bb.invert -side left
611
+pack .bb.quit .bb.reload .bb.invert -side left
583612
if {$fossilcmd!=""} {pack .bb.save -side left}
584613
pack .bb.files .bb.search -side left
585614
grid rowconfigure . 1 -weight 1
586615
grid columnconfigure . 1 -weight 1
587616
grid columnconfigure . 4 -weight 1
588617
--- src/diff.tcl
+++ src/diff.tcl
@@ -90,28 +90,56 @@
90 set x [lindex $difftxt $ii]
91 incr ii
92 return $x
93 }
94
95 proc readDiffs {fossilcmd} {
 
 
 
 
 
 
 
 
 
96 global difftxt debug
97 if {![info exists difftxt]} {
98 if {$debug} {
99 puts "# [list open $fossilcmd r]"
100 flush stdout
101 }
102 set in [open $fossilcmd r]
103 fconfigure $in -encoding utf-8
104 set difftxt [split [read $in] \n]
105 close $in
 
 
 
 
 
 
 
 
 
 
106 }
107 set N [llength $difftxt]
108 set ii 0
109 set nDiffs 0
110 set n1 0
111 set n2 0
112 array set widths {txt 3 ln 3 mkr 1}
 
 
 
 
 
 
 
 
 
113
114
115 set fromIndex [lsearch -glob $fossilcmd *-from]
116 set toIndex [lsearch -glob $fossilcmd *-to]
117 set branchIndex [lsearch -glob $fossilcmd *-branch]
@@ -459,11 +487,11 @@
459 ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
460 ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
461 ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
462 frame .spacer
463
464 if {[readDiffs $fossilcmd] == 0} {
465 tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
466 exit
467 }
468 update idletasks
469
@@ -574,14 +602,15 @@
574 $w tag config search -background {#fcc000}
575 }
576 set ::search $w
577 }
578 ::ttk::button .bb.quit -text {Quit} -command exit
 
579 ::ttk::button .bb.invert -text {Invert} -command invertDiff
580 ::ttk::button .bb.save -text {Save As...} -command saveDiff
581 ::ttk::button .bb.search -text {Search} -command searchOnOff
582 pack .bb.quit .bb.invert -side left
583 if {$fossilcmd!=""} {pack .bb.save -side left}
584 pack .bb.files .bb.search -side left
585 grid rowconfigure . 1 -weight 1
586 grid columnconfigure . 1 -weight 1
587 grid columnconfigure . 4 -weight 1
588
--- src/diff.tcl
+++ src/diff.tcl
@@ -90,28 +90,56 @@
90 set x [lindex $difftxt $ii]
91 incr ii
92 return $x
93 }
94
95 proc reloadDiff {} {
96 global fossilcmd difftxt
97 unset -nocomplain difftxt
98 set idx [.txtA index @0,0]
99 readDiffs $fossilcmd 1
100 update
101 viewDiff $idx
102 }
103
104 proc readDiffs {fossilcmd redo} {
105 global difftxt debug
106 if {![info exists difftxt]} {
107 if {$debug} {
108 puts "# [list open $fossilcmd r]"
109 flush stdout
110 }
111 if {[catch {
112 set in [open $fossilcmd r]
113 fconfigure $in -encoding utf-8
114 set difftxt [split [read $in] \n]
115 close $in
116 } msg]} {
117 if {$redo} {
118 tk_messageBox -type ok -title Error -message "Unable to refresh:\n$msg"
119 return 0
120 } else {
121 puts $msg
122 exit 1
123 }
124 }
125 }
126 set N [llength $difftxt]
127 set ii 0
128 set nDiffs 0
129 set n1 0
130 set n2 0
131 array set widths {txt 3 ln 3 mkr 1}
132 if {$redo} {
133 foreach c [cols] {$c config -state normal}
134 .lnA delete 1.0 end
135 .txtA delete 1.0 end
136 .lnB delete 1.0 end
137 .txtB delete 1.0 end
138 .mkr delete 1.0 end
139 .wfiles.lb delete 0 end
140 }
141
142
143 set fromIndex [lsearch -glob $fossilcmd *-from]
144 set toIndex [lsearch -glob $fossilcmd *-to]
145 set branchIndex [lsearch -glob $fossilcmd *-branch]
@@ -459,11 +487,11 @@
487 ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
488 ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
489 ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
490 frame .spacer
491
492 if {[readDiffs $fossilcmd 0] == 0} {
493 tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
494 exit
495 }
496 update idletasks
497
@@ -574,14 +602,15 @@
602 $w tag config search -background {#fcc000}
603 }
604 set ::search $w
605 }
606 ::ttk::button .bb.quit -text {Quit} -command exit
607 ::ttk::button .bb.reload -text {Reload} -command reloadDiff
608 ::ttk::button .bb.invert -text {Invert} -command invertDiff
609 ::ttk::button .bb.save -text {Save As...} -command saveDiff
610 ::ttk::button .bb.search -text {Search} -command searchOnOff
611 pack .bb.quit .bb.reload .bb.invert -side left
612 if {$fossilcmd!=""} {pack .bb.save -side left}
613 pack .bb.files .bb.search -side left
614 grid rowconfigure . 1 -weight 1
615 grid columnconfigure . 1 -weight 1
616 grid columnconfigure . 4 -weight 1
617
+69 -30
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -127,16 +127,16 @@
127127
DIFF_HTML|DIFF_WEBPAGE|DIFF_BROWSER|DIFF_JSON|DIFF_TCL))==0 ){
128128
fossil_print("Fossil-Diff-From: %s\n",
129129
zFrom[0]=='(' ? zFrom : mprintf("%S %s",
130130
rid_to_uuid(symbolic_name_to_rid(zFrom, "ci")),
131131
db_text("","SELECT datetime(%f)||' UTC'",
132
- symbolic_name_to_mtime(zFrom, 0))));
132
+ symbolic_name_to_mtime(zFrom, 0, 0))));
133133
fossil_print("Fossil-Diff-To: %s\n",
134134
zTo[0]=='(' ? zTo : mprintf("%S %s",
135135
rid_to_uuid(symbolic_name_to_rid(zTo, "ci")),
136136
db_text("","SELECT datetime(%f)||' UTC'",
137
- symbolic_name_to_mtime(zTo, 0))));
137
+ symbolic_name_to_mtime(zTo, 0, 1))));
138138