Compare commits
88 Commits
right-ref-cte
...
release
| Author | SHA1 | Date | |
|---|---|---|---|
| ccc132c5be | |||
| 5e132e142f | |||
| b9e656f6f7 | |||
| c867ce4b89 | |||
| ceb66403bb | |||
| 6c1aa834f6 | |||
| e7d405200a | |||
| c911dda3d3 | |||
| edec48cd40 | |||
| f7915390d5 | |||
| 42be6fdf22 | |||
| 31a9e5c5d9 | |||
| 0851e6a4fe | |||
| b2543d0098 | |||
| 4902f35e63 | |||
| 2a95fade33 | |||
| 193a8f3673 | |||
| 81ceb00b00 | |||
| 8626a528e1 | |||
| b8c5fe2c19 | |||
| c3a422d794 | |||
| d542c33c9d | |||
| fa5d2efbfc | |||
| c22fe7a31c | |||
| a15c394233 | |||
| d38b6c0a19 | |||
| 600eb440c2 | |||
| e9b5658888 | |||
| e44fc2ba34 | |||
| 18bc656fe1 | |||
| 2e6dc01ea7 | |||
| bf5c8d7d16 | |||
| 48aa50931a | |||
| 9bb1173b4f | |||
| 2b6b982a77 | |||
| 22bce652b3 | |||
| c4a831733f | |||
| 9f426fa956 | |||
| 18bdf31933 | |||
| 2c6e131593 | |||
| f034bd10f0 | |||
| 0d8e4e27b7 | |||
| dfc91368e7 | |||
| d75e0a89ad | |||
| 0d56a90b3d | |||
| 62587d292b | |||
| 4e2383b65b | |||
| 0b223f1027 | |||
| 83f261d5a0 | |||
| 8d36080bd5 | |||
| 1cddaab5f9 | |||
| a66d74e1de | |||
| 574d888a10 | |||
| a523e20bba | |||
| 3580d166e5 | |||
| 1e4ec59e3f | |||
| af24f5e21e | |||
| 7678510ff2 | |||
| 066b667313 | |||
| e0b995b2a6 | |||
| 9db56a4935 | |||
| a5ce91b319 | |||
| 0268517163 | |||
| ccd445d76a | |||
| b14b7681f4 | |||
| 55f2cf294f | |||
| 10305aa4a4 | |||
| 20847aca95 | |||
| e64e95b437 | |||
| 27e808ff2c | |||
| 0e4b46a649 | |||
| 2ba7864bc4 | |||
| 2114d8bbd2 | |||
| 928890f18f | |||
| 7b3ed290d3 | |||
| 002226b549 | |||
| 7ad112014b | |||
| f9c7f9fb52 | |||
| 02bd4aa037 | |||
| 8113b83c01 | |||
| 4c6c2ed134 | |||
| df330b6f92 | |||
| ef152ec09f | |||
| 2c01c19968 | |||
| 81fa34e507 | |||
| 1bb371e6d3 | |||
| 916f74e485 | |||
| 282e2cea0a |
@@ -1896,9 +1896,6 @@ RSYNC_OPT = \
|
||||
sqlite3_rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
|
||||
$(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
|
||||
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
srcck1.exe: $(TOP)\tool\srcck1.c
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c
|
||||
|
||||
|
||||
@@ -1745,8 +1745,12 @@ proc sqlite-handle-env-quirks {} {
|
||||
set autoDll 0; # true if --out-implib/--dll-basename should be implied
|
||||
set host [get-define host]
|
||||
switch -glob -- $host {
|
||||
*apple* -
|
||||
*darwin* { set instName darwin }
|
||||
*-*-darwin* {
|
||||
set instName darwin
|
||||
# We don't look for *apple* because:
|
||||
# https://sqlite.org/forum/forumpost/7b218c3c9f207646
|
||||
# There's at least one Linux out there which matches *apple*.
|
||||
}
|
||||
default {
|
||||
set x [sqlite-env-is-unix-on-windows $host]
|
||||
if {"" ne $x} {
|
||||
|
||||
+11
-1
@@ -302,6 +302,12 @@
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Assume any b-tree layer with more levels than this is corrupt.
|
||||
*/
|
||||
#define FTS3_MAX_BTREE_HEIGHT 48
|
||||
|
||||
typedef struct Fts3HashWrapper Fts3HashWrapper;
|
||||
struct Fts3HashWrapper {
|
||||
Fts3Hash hash; /* Hash table */
|
||||
@@ -2018,7 +2024,11 @@ static int fts3SelectLeaf(
|
||||
assert( piLeaf || piLeaf2 );
|
||||
|
||||
fts3GetVarint32(zNode, &iHeight);
|
||||
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
|
||||
if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
}else{
|
||||
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
|
||||
}
|
||||
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
|
||||
|
||||
if( rc==SQLITE_OK && iHeight>1 ){
|
||||
|
||||
+1
-1
@@ -341,7 +341,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
/* State 3. The integer just read is a column number. */
|
||||
default: assert( eState==3 );
|
||||
iCol = (int)v;
|
||||
if( iCol<1 ){
|
||||
if( iCol<1 || iCol>(pFts3->nColumn+1) ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -471,6 +471,7 @@ static int getNextNode(
|
||||
assert( nKey==4 );
|
||||
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
|
||||
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
|
||||
if( nNear>=1000000000 ) nNear = 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -887,7 +887,7 @@ static int fts3ExprLHits(
|
||||
if( p->flag==FTS3_MATCHINFO_LHITS ){
|
||||
p->aMatchinfo[iStart + iCol] = (u32)nHit;
|
||||
}else if( nHit ){
|
||||
p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
|
||||
p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
|
||||
}
|
||||
}
|
||||
assert( *pIter==0x00 || *pIter==0x01 );
|
||||
|
||||
+16
-5
@@ -922,7 +922,7 @@ static void fts5DataRelease(Fts5Data *pData){
|
||||
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
|
||||
Fts5Data *pRet = fts5DataRead(p, iRowid);
|
||||
if( pRet ){
|
||||
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
|
||||
if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
fts5DataRelease(pRet);
|
||||
pRet = 0;
|
||||
@@ -2576,6 +2576,10 @@ static void fts5LeafSeek(
|
||||
if( nKeep<nMatch ){
|
||||
goto search_failed;
|
||||
}
|
||||
if( (iOff+nNew)>n ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
return;
|
||||
}
|
||||
|
||||
assert( nKeep>=nMatch );
|
||||
if( nKeep==nMatch ){
|
||||
@@ -3552,8 +3556,7 @@ static void fts5PoslistFilterCallback(
|
||||
|
||||
do {
|
||||
while( i<nChunk && pChunk[i]!=0x01 ){
|
||||
while( pChunk[i] & 0x80 ) i++;
|
||||
i++;
|
||||
fts5IndexSkipVarint(pChunk, i);
|
||||
}
|
||||
if( pCtx->eState ){
|
||||
fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
|
||||
@@ -3702,7 +3705,7 @@ static void fts5IndexExtractColset(
|
||||
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
|
||||
** not part of a varint */
|
||||
while( p<pEnd && *p!=0x01 ){
|
||||
while( *p++ & 0x80 );
|
||||
while( p<pEnd && (*p++ & 0x80) );
|
||||
}
|
||||
|
||||
if( pColset->aiCol[i]==iCurrent ){
|
||||
@@ -3799,8 +3802,11 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
|
||||
|
||||
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
|
||||
assert( pIter->pColset );
|
||||
assert( pIter->poslist.nSpace>=pIter->pIndex->pConfig->nCol );
|
||||
|
||||
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
|
||||
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
|
||||
|| pSeg->nPos>pIter->pIndex->pConfig->nCol
|
||||
){
|
||||
fts5IterSetOutputs_Col(pIter, pSeg);
|
||||
}else{
|
||||
u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
|
||||
@@ -5294,6 +5300,11 @@ static void fts5DoSecureDelete(
|
||||
}else{
|
||||
iStart = fts5GetU16(&aPg[0]);
|
||||
}
|
||||
if( iStart>nPg ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
sqlite3_free(aIdx);
|
||||
return;
|
||||
}
|
||||
|
||||
iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
|
||||
assert_nc( iSOP<=pSeg->iLeafOffset );
|
||||
|
||||
@@ -586,8 +586,14 @@ static int fts5PorterCreate(
|
||||
const char *zBase = "unicode61";
|
||||
fts5_tokenizer_v2 *pV2 = 0;
|
||||
|
||||
if( nArg>0 ){
|
||||
zBase = azArg[0];
|
||||
while( nArg>0 ){
|
||||
if( sqlite3_stricmp(azArg[0],"porter")==0 ){
|
||||
nArg--;
|
||||
azArg++;
|
||||
}else{
|
||||
zBase = azArg[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
|
||||
|
||||
@@ -15153,9 +15153,9 @@ do_execsql_test 78.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col');
|
||||
}
|
||||
|
||||
do_execsql_test 78.2 {
|
||||
do_catchsql_test 78.2 {
|
||||
SELECT count(rowid) FROM t3 WHERE term>='nsocse';
|
||||
} 2
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -1220,7 +1220,7 @@ do_test 8.0 {
|
||||
|
||||
do_catchsql_test 8.1 {
|
||||
SELECT rowid FROM t1('a* NOT ý') ;
|
||||
} {0 {1 2 3 4 5 6 7}}
|
||||
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1917,6 +1917,222 @@ do_catchsql_test 11.3 {
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 12.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 24576 pagesize 4096 filename p.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 03 00 00 00 06 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
|
||||
| 96: 00 2e 76 89 0d 00 00 00 06 0d ed 00 0f bb 0f 64 ..v............d
|
||||
| 112: 0e f9 0e a2 0e 45 0d ed 00 00 00 00 00 00 00 00 .....E..........
|
||||
| 3552: 00 00 00 00 00 00 00 00 00 00 00 00 00 56 06 06 .............V..
|
||||
| 3568: 17 1f 1f 01 7d 74 61 62 6c 65 66 74 5f 63 6f 6e .....tableft_con
|
||||
| 3584: 66 69 67 66 74 5f 63 6f 6e 66 69 67 06 43 52 45 figft_config.CRE
|
||||
| 3600: 41 54 45 20 54 41 42 4c 45 20 27 66 74 5f 63 6f ATE TABLE 'ft_co
|
||||
| 3616: 6e 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 nfig'(k PRIMARY
|
||||
| 3632: 4b 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 KEY, v) WITHOUT
|
||||
| 3648: 52 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 ROWID[...!!...ta
|
||||
| 3664: 62 6c 65 66 74 5f 64 6f 63 73 69 7a 65 66 74 5f bleft_docsizeft_
|
||||
| 3680: 64 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 docsize.CREATE T
|
||||
| 3696: 41 42 4c 45 20 27 66 74 5f 64 6f 63 73 69 7a 65 ABLE 'ft_docsize
|
||||
| 3712: 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 '(id INTEGER PRI
|
||||
| 3728: 4d 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f MARY KEY, sz BLO
|
||||
| 3744: 42 29 55 04 06 17 21 21 01 77 74 61 62 6c 65 66 B)U...!!.wtablef
|
||||
| 3760: 74 5f 63 6f 6e 74 65 6e 74 66 74 5f 63 6f 6e 74 t_contentft_cont
|
||||
| 3776: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
|
||||
| 3792: 20 27 66 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 'ft_content'(id
|
||||
| 3808: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
|
||||
| 3824: 20 4b 45 59 2c 20 63 30 29 69 03 07 17 19 19 01 KEY, c0)i......
|
||||
| 3840: 81 2d 74 61 62 6c 65 66 74 5f 69 64 78 66 74 5f .-tableft_idxft_
|
||||
| 3856: 69 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 idx.CREATE TABLE
|
||||
| 3872: 20 27 66 74 5f 69 64 78 27 28 73 65 67 69 64 2c 'ft_idx'(segid,
|
||||
| 3888: 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 term, pgno, PRI
|
||||
| 3904: 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 MARY KEY(segid,
|
||||
| 3920: 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 term)) WITHOUT R
|
||||
| 3936: 4f 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 OWIDU........tab
|
||||
| 3952: 6c 65 66 74 5f 64 61 74 61 66 74 5f 64 61 74 61 left_dataft_data
|
||||
| 3968: 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 66 .CREATE TABLE 'f
|
||||
| 3984: 74 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 t_data'(id INTEG
|
||||
| 4000: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 4016: 62 6c 6f 63 6b 20 42 4c 4f 42 29 43 01 06 17 11 block BLOB)C....
|
||||
| 4032: 11 08 75 74 61 62 6c 65 66 74 66 74 43 52 45 41 ..utableftftCREA
|
||||
| 4048: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
|
||||
| 4064: 20 66 74 20 55 53 49 4e 47 20 66 74 73 35 28 61 ft USING fts5(a
|
||||
| 4080: 2c 20 64 65 74 61 69 6c 3d 63 6f 6c 75 6d 6e 29 , detail=column)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 03 0f 7f 00 0f e8 0f ef 0f 7f 00 00 ................
|
||||
| 3952: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 62 ...............b
|
||||
| 3968: 84 80 80 80 80 01 04 00 81 48 00 00 00 54 04 30 .........H...T.0
|
||||
| 3984: 61 61 61 01 81 02 02 02 02 02 02 02 02 02 02 02 aaa.............
|
||||
| 4000: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 4016: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 4032: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 ................
|
||||
| 4048: 02 02 02 02 02 02 02 03 6a 6a 6a 01 02 02 04 08 ........jjj.....
|
||||
| 4064: 08 08 08 08 08 08 08 08 05 01 03 00 10 01 0a 0f ................
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 01 0f d4 00 0f d4 00 00 00 00 00 00 ................
|
||||
| 4048: 00 00 00 00 2a 01 03 00 5b 61 61 61 20 62 62 62 ....*...[aaa bbb
|
||||
| 4064: 20 63 63 63 20 64 64 64 20 65 65 65 20 66 66 66 ccc ddd eee fff
|
||||
| 4080: 20 67 67 67 20 68 68 68 20 69 69 69 20 6a 6a 6a ggg hhh iii jjj
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 04 01 03 00 0e 0a ................
|
||||
| page 6 offset 20480
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| end p.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 12.1 {
|
||||
SELECT rowid FROM ft('a:aaa')
|
||||
} {0 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 13.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 24576 pagesize 4096 filename vuln_001.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 03 00 00 00 06 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
|
||||
| 96: 00 2e 76 89 0d 00 00 00 06 0e 09 00 0f ca 0f 77 ..v............w
|
||||
| 112: 0f 0f 0e b7 0e 5e 0e 09 00 00 00 00 00 00 00 00 .....^..........
|
||||
| 3584: 00 00 00 00 00 00 00 00 00 53 06 06 17 1d 1d 01 .........S......
|
||||
| 3600: 7b 74 61 62 6c 65 74 5f 63 6f 6e 66 69 67 74 5f .tablet_configt_
|
||||
| 3616: 63 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 41 config.CREATE TA
|
||||
| 3632: 42 4c 45 20 27 74 5f 63 6f 6e 66 69 67 27 28 6b BLE 't_config'(k
|
||||
| 3648: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3664: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 57 05 WITHOUT ROWIDW.
|
||||
| 3680: 06 17 1f 1f 01 7f 74 61 62 6c 65 74 5f 64 6f 63 ......tablet_doc
|
||||
| 3696: 73 69 7a 65 74 5f 64 6f 63 73 69 7a 65 05 43 52 sizet_docsize.CR
|
||||
| 3712: 45 41 54 45 20 54 41 42 4c 45 20 27 74 5f 64 6f EATE TABLE 't_do
|
||||
| 3728: 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 45 csize'(id INTEGE
|
||||
| 3744: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 R PRIMARY KEY, s
|
||||
| 3760: 7a 20 42 4c 4f 42 29 56 04 06 17 1f 1f 01 7d 74 z BLOB)V.......t
|
||||
| 3776: 61 62 6c 65 74 5f 63 6f 6e 74 65 6e 74 74 5f 63 ablet_contentt_c
|
||||
| 3792: 6f 6e 74 65 6e 74 04 43 52 45 41 54 45 20 54 41 ontent.CREATE TA
|
||||
| 3808: 42 4c 45 20 27 74 5f 63 6f 6e 74 65 6e 74 27 28 BLE 't_content'(
|
||||
| 3824: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
|
||||
| 3840: 52 59 20 4b 45 59 2c 20 63 30 2c 20 63 31 29 66 RY KEY, c0, c1)f
|
||||
| 3856: 03 07 17 17 17 01 81 2b 74 61 62 6c 65 74 5f 69 .......+tablet_i
|
||||
| 3872: 64 78 74 5f 69 64 78 03 43 52 45 41 54 45 20 54 dxt_idx.CREATE T
|
||||
| 3888: 41 42 4c 45 20 27 74 5f 69 64 78 27 28 73 65 67 ABLE 't_idx'(seg
|
||||
| 3904: 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 id, term, pgno,
|
||||
| 3920: 50 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 PRIMARY KEY(segi
|
||||
| 3936: 64 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 d, term)) WITHOU
|
||||
| 3952: 54 20 52 4f 57 49 44 51 02 06 17 19 19 01 7f 74 T ROWIDQ.......t
|
||||
| 3968: 61 62 6c 65 74 5f 64 61 74 61 74 5f 64 61 74 61 ablet_datat_data
|
||||
| 3984: 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 4000: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
|
||||
| 4016: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
|
||||
| 4032: 6c 6f 63 6b 20 42 4c 4f 42 29 34 01 06 17 0f 0f lock BLOB)4.....
|
||||
| 4048: 08 5b 74 61 62 6c 65 74 74 43 52 45 41 54 45 20 .[tablettCREATE
|
||||
| 4064: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 20 VIRTUAL TABLE t
|
||||
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 00 00 00 04 0b da 00 0f e7 0f ef 0f ce 0b da ................
|
||||
| 3024: 00 00 00 00 00 00 00 00 00 00 87 6c 84 80 80 80 ...........l....
|
||||
| 3040: 80 02 04 00 8f 5c 00 00 03 e8 80 80 80 80 80 80 ................
|
||||
| 3056: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3072: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3088: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3104: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3120: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3136: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3152: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3168: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3184: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3200: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3216: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3232: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3248: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3264: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3280: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3296: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3312: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3328: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3344: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3360: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3376: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3392: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3408: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3424: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3440: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3456: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3472: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3488: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3504: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3520: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3536: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3552: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3568: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3584: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3600: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3616: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3632: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3648: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3664: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3680: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3696: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3712: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3728: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3744: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3760: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3776: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3792: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3808: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3824: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3840: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3856: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3872: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3888: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3904: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3920: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3936: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3952: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3968: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 3984: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 4000: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 4016: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ................
|
||||
| 4032: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 12 84 ................
|
||||
| 4048: 80 80 80 80 01 03 00 2a 00 0b 00 0e 06 30 68 65 .......*.....0he
|
||||
| 4064: 6c 6c 6f 01 04 04 04 06 01 03 00 12 01 02 02 0f llo.............
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 02 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 01 0f e8 00 0f e8 00 00 00 00 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 16 01 04 00 23 1b 68 65 ............#.he
|
||||
| 4080: 6c 6c 6f 20 77 6f 72 6c 64 66 6f 6f 20 62 61 72 llo worldfoo bar
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 01 0f f9 00 0f f9 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 05 01 03 00 10 02 02 ................
|
||||
| page 6 offset 20480
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| end vuln_001.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 13.1 {
|
||||
SELECT * FROM t('a:hello')
|
||||
} {0 {{hello world} {foo bar}}}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -125,4 +125,40 @@ do_catchsql_test 2.3 {
|
||||
DELETE FROM t1 WHERE rowid = 1
|
||||
} {/.*fts5: corrupt.*/}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
PRAGMA page_size=4096;
|
||||
PRAGMA journal_mode=DELETE;
|
||||
CREATE VIRTUAL TABLE t USING fts5(x, detail=none);
|
||||
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<5000
|
||||
)
|
||||
INSERT INTO t(rowid, x) SELECT i, 'vulnerabilitytest' FROM s;
|
||||
|
||||
INSERT INTO t(t) VALUES('optimize');
|
||||
INSERT INTO t(t, rank) VALUES('secure-delete', 1);
|
||||
} {delete}
|
||||
|
||||
do_test 3.1 {
|
||||
db eval { SELECT rowid AS rowid, block FROM t_data ORDER BY rowid } {
|
||||
if {$rowid>=10 && [string length $block]>=4} {
|
||||
binary scan $block Su first_rowid_off
|
||||
set pgno [expr ($rowid & 0x7FFFFFFF)]
|
||||
if {$pgno>=2 && $first_rowid_off>0} break
|
||||
}
|
||||
}
|
||||
|
||||
set bad [binary format a*a* "\xFF\xFF" [string range $block 2 end]]
|
||||
db eval {
|
||||
UPDATE t_data SET block = $bad WHERE rowid=$rowid
|
||||
}
|
||||
} {}
|
||||
|
||||
do_catchsql_test 3.2 {
|
||||
DELETE FROM t WHERE rowid=4500;
|
||||
} {1 {fts5: corruption in table "t"}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
# 2026 May 11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corruptA
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
sqlite3_fts5_may_be_corrupt 1
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts5(x, detail='full');
|
||||
INSERT INTO t(t, rank) VALUES('pgsz', 32);
|
||||
}
|
||||
|
||||
set big [string repeat "a " 200]
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO t(rowid, x) VALUES(1, $big)
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
db eval {
|
||||
SELECT min(rowid) AS base_rowid, count(*) AS page_count FROM t_data
|
||||
WHERE rowid>1000
|
||||
} {}
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
for {set ii 0} {$ii < 5} {incr ii} {
|
||||
db eval {
|
||||
INSERT INTO t_data(rowid, block)
|
||||
VALUES( $base_rowid + $page_count + $ii, zeroblob(4) );
|
||||
}
|
||||
}
|
||||
db eval {
|
||||
INSERT INTO t_data(rowid, block)
|
||||
VALUES( $base_rowid + $page_count + 5,
|
||||
unhex('00000080' || 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC') );
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
db close
|
||||
|
||||
do_test 1.4 {
|
||||
set hex [hexio_read test.db 0 [file size test.db]]
|
||||
|
||||
set off [string first "023061018310" $hex]
|
||||
set hex [string replace $hex $off [expr $off+11] 023061018370]
|
||||
hexio_write test.db 0 $hex
|
||||
} {6144}
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.5 {
|
||||
SELECT rowid FROM t WHERE t MATCH 'a'
|
||||
} {1 {fts5: corruption found reading blob 137438953481 from table "t"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
BEGIN;
|
||||
INSERT INTO t1(rowid, a) VALUES(1, 'aaaa');
|
||||
INSERT INTO t1(rowid, a) VALUES(2, 'bbbb');
|
||||
INSERT INTO t1(rowid, a) VALUES(3, 'cccc');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
do_test 2.1 {
|
||||
set hex [hexio_read test.db 0 [file size test.db]]
|
||||
set off [string first "010463636363" $hex]
|
||||
set hex [string replace $hex $off [expr $off+11] 017F63636363]
|
||||
hexio_write test.db 0 $hex
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT rowid FROM t1('cccccccccccccccccccccccccccccccccccccccccccccccc');
|
||||
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
|
||||
INSERT INTO t1 VALUES(
|
||||
'hello',
|
||||
'alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu',
|
||||
'ant bear cat dog elephant fox gorilla hippo iguana jaguar kangaroo lion monkey newt octopus panda quail rabbit snake turtle unicorn vulture walrus xerus yak zebra'
|
||||
);
|
||||
|
||||
UPDATE t1_data SET block = unhex(
|
||||
-- Preserve bytes 0-168: header through hello's nSz field
|
||||
hex(substr(block, 1, 169))
|
||||
-- Inject 448 bytes of 0xFF: corrupted poslist + subsequent term data
|
||||
|| replace(hex(zeroblob(448)), '00', 'FF')
|
||||
-- Preserve 16 bytes of page index needed for hello lookup
|
||||
|| hex(substr(block, 618, 16))
|
||||
-- Corrupt remaining 37 footer bytes (not needed for hello lookup)
|
||||
|| replace(hex(zeroblob(37)), '00', 'FF')
|
||||
)
|
||||
WHERE id = 137438953473;
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
execsql { SELECT * FROM t1 WHERE t1 MATCH '{a b}: hello' }
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
@@ -371,4 +371,14 @@ do_execsql_test 10.10 {
|
||||
a 2 2 b 2 2 c 2 2 d 1 1 e 1 1 f 1 1
|
||||
}
|
||||
|
||||
# Bug report 2026-05-18T05:19:01Z
|
||||
#
|
||||
set manyporters {porter Porter}
|
||||
for {set i 0} {$i<18} {incr i} {
|
||||
set manyporters "$manyporters $manyporters"
|
||||
}
|
||||
do_execsql_test 11.1 "
|
||||
CREATE VIRTUAL TABLE t11 USING fts5(a,b,tokenize=\"$manyporters\");
|
||||
" {}
|
||||
|
||||
finish_test
|
||||
|
||||
+4
-4
@@ -362,7 +362,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
const UChar *zInput; /* Pointer to input string */
|
||||
UChar *zOutput = 0; /* Pointer to output buffer */
|
||||
int nInput; /* Size of utf-16 input string in bytes */
|
||||
int nOut; /* Size of output buffer in bytes */
|
||||
sqlite3_int64 nOut; /* Size of output buffer in bytes */
|
||||
int cnt;
|
||||
int bToUpper; /* True for toupper(), false for tolower() */
|
||||
UErrorCode status;
|
||||
@@ -385,7 +385,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
}
|
||||
|
||||
for(cnt=0; cnt<2; cnt++){
|
||||
UChar *zNew = sqlite3_realloc(zOutput, nOut);
|
||||
UChar *zNew = sqlite3_realloc64(zOutput, nOut);
|
||||
if( zNew==0 ){
|
||||
sqlite3_free(zOutput);
|
||||
sqlite3_result_error_nomem(p);
|
||||
@@ -394,9 +394,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
zOutput = zNew;
|
||||
status = U_ZERO_ERROR;
|
||||
if( bToUpper ){
|
||||
nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}else{
|
||||
nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}
|
||||
|
||||
if( U_SUCCESS(status) ){
|
||||
|
||||
@@ -60,6 +60,10 @@ static void compressFunc(
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
nOut = 13 + nIn + (nIn+999)/1000;
|
||||
pOut = sqlite3_malloc64( nOut+5 );
|
||||
if( pOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
for(i=4; i>=0; i--){
|
||||
x[i] = (nIn >> (7*(4-i)))&0x7f;
|
||||
}
|
||||
@@ -99,6 +103,10 @@ static void uncompressFunc(
|
||||
if( (pIn[i]&0x80)!=0 ){ i++; break; }
|
||||
}
|
||||
pOut = sqlite3_malloc64( nOut+1 );
|
||||
if( pOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
|
||||
if( rc==Z_OK ){
|
||||
sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
|
||||
|
||||
+37
-37
@@ -340,45 +340,45 @@ static void percentSort(double *a, unsigned int n){
|
||||
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
|
||||
int i; /* Loop counter */
|
||||
double rPivot; /* The pivot value */
|
||||
|
||||
assert( n>=2 );
|
||||
if( a[0]>a[n-1] ){
|
||||
SWAP_DOUBLE(a[0],a[n-1])
|
||||
}
|
||||
if( n==2 ) return;
|
||||
iGt = n-1;
|
||||
i = n/2;
|
||||
if( a[0]>a[i] ){
|
||||
SWAP_DOUBLE(a[0],a[i])
|
||||
}else if( a[i]>a[iGt] ){
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}
|
||||
if( n==3 ) return;
|
||||
rPivot = a[i];
|
||||
iLt = i = 1;
|
||||
do{
|
||||
if( a[i]<rPivot ){
|
||||
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
||||
iLt++;
|
||||
i++;
|
||||
}else if( a[i]>rPivot ){
|
||||
do{
|
||||
iGt--;
|
||||
}while( iGt>i && a[iGt]>rPivot );
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}else{
|
||||
i++;
|
||||
|
||||
while( n>=2 ){
|
||||
if( a[0]>a[n-1] ){
|
||||
SWAP_DOUBLE(a[0],a[n-1])
|
||||
}
|
||||
if( n==2 ) return;
|
||||
iGt = n-1;
|
||||
i = n/2;
|
||||
if( a[0]>a[i] ){
|
||||
SWAP_DOUBLE(a[0],a[i])
|
||||
}else if( a[i]>a[iGt] ){
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}
|
||||
if( n==3 ) return;
|
||||
rPivot = a[i];
|
||||
iLt = i = 1;
|
||||
do{
|
||||
if( a[i]<rPivot ){
|
||||
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
||||
iLt++;
|
||||
i++;
|
||||
}else if( a[i]>rPivot ){
|
||||
do{
|
||||
iGt--;
|
||||
}while( iGt>i && a[iGt]>rPivot );
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}while( i<iGt );
|
||||
if( iLt>n/2 ){
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
||||
n = iLt;
|
||||
}else{
|
||||
if( iLt>=2 ) percentSort(a, iLt);
|
||||
a += iGt;
|
||||
n -= iGt;
|
||||
}
|
||||
}while( i<iGt );
|
||||
if( iLt>=2 ) percentSort(a, iLt);
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
||||
|
||||
/* Uncomment for testing */
|
||||
#if 0
|
||||
for(i=0; i<n-1; i++){
|
||||
assert( a[i]<=a[i+1] );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-1
@@ -289,10 +289,14 @@ static void prefixLengthFunc(
|
||||
int nL = sqlite3_value_bytes(apVal[0]);
|
||||
int nR = sqlite3_value_bytes(apVal[1]);
|
||||
int i;
|
||||
if( zL==0 || zR==0 ){
|
||||
sqlite3_result_int(ctx, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
nByte = (nL > nR ? nL : nR);
|
||||
for(i=0; i<nByte; i++){
|
||||
if( zL[i]!=zR[i] ) break;
|
||||
if( zL[i]==0 || zL[i]!=zR[i] ) break;
|
||||
if( (zL[i] & 0xC0)!=0x80 ) nRet++;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,610 +0,0 @@
|
||||
/*
|
||||
** 2016-05-05
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file implements a utility function (and a utility program) that
|
||||
** makes a copy of an SQLite database while simultaneously zeroing out all
|
||||
** deleted content.
|
||||
**
|
||||
** Normally (when PRAGMA secure_delete=OFF, which is the default) when SQLite
|
||||
** deletes content, it does not overwrite the deleted content but rather marks
|
||||
** the region of the file that held that content as being reusable. This can
|
||||
** cause deleted content to recoverable from the database file. This stale
|
||||
** content is removed by the VACUUM command, but VACUUM can be expensive for
|
||||
** large databases. When in PRAGMA secure_delete=ON mode, the deleted content
|
||||
** is zeroed, but secure_delete=ON has overhead as well.
|
||||
**
|
||||
** This utility attempts to make a copy of a complete SQLite database where
|
||||
** all of the deleted content is zeroed out in the copy, and it attempts to
|
||||
** do so while being faster than running VACUUM.
|
||||
**
|
||||
** Usage:
|
||||
**
|
||||
** int sqlite3_scrub_backup(
|
||||
** const char *zSourceFile, // Source database filename
|
||||
** const char *zDestFile, // Destination database filename
|
||||
** char **pzErrMsg // Write error message here
|
||||
** );
|
||||
**
|
||||
** Simply call the API above specifying the filename of the source database
|
||||
** and the name of the backup copy. The source database must already exist
|
||||
** and can be in active use. (A read lock is held during the backup.) The
|
||||
** destination file should not previously exist. If the pzErrMsg parameter
|
||||
** is non-NULL and if an error occurs, then an error message might be written
|
||||
** into memory obtained from sqlite3_malloc() and *pzErrMsg made to point to
|
||||
** that error message. But if the error is an OOM, the error might not be
|
||||
** reported. The routine always returns non-zero if there is an error.
|
||||
**
|
||||
** If compiled with -DSCRUB_STANDALONE then a main() procedure is added and
|
||||
** this file becomes a standalone program that can be run as follows:
|
||||
**
|
||||
** ./sqlite3scrub SOURCE DEST
|
||||
*/
|
||||
#include "sqlite3.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct ScrubState ScrubState;
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
|
||||
/* State information for a scrub-and-backup operation */
|
||||
struct ScrubState {
|
||||
const char *zSrcFile; /* Name of the source file */
|
||||
const char *zDestFile; /* Name of the destination file */
|
||||
int rcErr; /* Error code */
|
||||
char *zErr; /* Error message text */
|
||||
sqlite3 *dbSrc; /* Source database connection */
|
||||
sqlite3_file *pSrc; /* Source file handle */
|
||||
sqlite3 *dbDest; /* Destination database connection */
|
||||
sqlite3_file *pDest; /* Destination file handle */
|
||||
u32 szPage; /* Page size */
|
||||
u32 szUsable; /* Usable bytes on each page */
|
||||
u32 nPage; /* Number of pages */
|
||||
u32 iLastPage; /* Page number of last page written so far*/
|
||||
u8 *page1; /* Content of page 1 */
|
||||
};
|
||||
|
||||
/* Store an error message */
|
||||
static void scrubBackupErr(ScrubState *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
sqlite3_free(p->zErr);
|
||||
va_start(ap, zFormat);
|
||||
p->zErr = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( p->rcErr==0 ) p->rcErr = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* Allocate memory to hold a single page of content */
|
||||
static u8 *scrubBackupAllocPage(ScrubState *p){
|
||||
u8 *pPage;
|
||||
if( p->rcErr ) return 0;
|
||||
pPage = sqlite3_malloc64( p->szPage );
|
||||
if( pPage==0 ) p->rcErr = SQLITE_NOMEM;
|
||||
return pPage;
|
||||
}
|
||||
|
||||
/* Read a page from the source database into memory. Use the memory
|
||||
** provided by pBuf if not NULL or allocate a new page if pBuf==NULL.
|
||||
*/
|
||||
static u8 *scrubBackupRead(ScrubState *p, int pgno, u8 *pBuf){
|
||||
int rc;
|
||||
sqlite3_int64 iOff;
|
||||
u8 *pOut = pBuf;
|
||||
if( p->rcErr ) return 0;
|
||||
if( pOut==0 ){
|
||||
pOut = scrubBackupAllocPage(p);
|
||||
if( pOut==0 ) return 0;
|
||||
}
|
||||
iOff = (pgno-1)*(sqlite3_int64)p->szPage;
|
||||
rc = p->pSrc->pMethods->xRead(p->pSrc, pOut, p->szPage, iOff);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( pBuf==0 ) sqlite3_free(pOut);
|
||||
pOut = 0;
|
||||
scrubBackupErr(p, "read failed for page %d", pgno);
|
||||
p->rcErr = SQLITE_IOERR;
|
||||
}
|
||||
return pOut;
|
||||
}
|
||||
|
||||
/* Write a page to the destination database */
|
||||
static void scrubBackupWrite(ScrubState *p, int pgno, const u8 *pData){
|
||||
int rc;
|
||||
sqlite3_int64 iOff;
|
||||
if( p->rcErr ) return;
|
||||
iOff = (pgno-1)*(sqlite3_int64)p->szPage;
|
||||
rc = p->pDest->pMethods->xWrite(p->pDest, pData, p->szPage, iOff);
|
||||
if( rc!=SQLITE_OK ){
|
||||
scrubBackupErr(p, "write failed for page %d", pgno);
|
||||
p->rcErr = SQLITE_IOERR;
|
||||
}
|
||||
if( (u32)pgno>p->iLastPage ) p->iLastPage = pgno;
|
||||
}
|
||||
|
||||
/* Prepare a statement against the "db" database. */
|
||||
static sqlite3_stmt *scrubBackupPrepare(
|
||||
ScrubState *p, /* Backup context */
|
||||
sqlite3 *db, /* Database to prepare against */
|
||||
const char *zSql /* SQL statement */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
if( p->rcErr ) return 0;
|
||||
p->rcErr = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( p->rcErr ){
|
||||
scrubBackupErr(p, "SQL error \"%s\" on \"%s\"",
|
||||
sqlite3_errmsg(db), zSql);
|
||||
sqlite3_finalize(pStmt);
|
||||
return 0;
|
||||
}
|
||||
return pStmt;
|
||||
}
|
||||
|
||||
|
||||
/* Open the source database file */
|
||||
static void scrubBackupOpenSrc(ScrubState *p){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
/* Open the source database file */
|
||||
p->rcErr = sqlite3_open_v2(p->zSrcFile, &p->dbSrc,
|
||||
SQLITE_OPEN_READWRITE |
|
||||
SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
|
||||
if( p->rcErr ){
|
||||
scrubBackupErr(p, "cannot open source database: %s",
|
||||
sqlite3_errmsg(p->dbSrc));
|
||||
return;
|
||||
}
|
||||
p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_schema; BEGIN;",
|
||||
0, 0, 0);
|
||||
if( p->rcErr ){
|
||||
scrubBackupErr(p,
|
||||
"cannot start a read transaction on the source database: %s",
|
||||
sqlite3_errmsg(p->dbSrc));
|
||||
return;
|
||||
}
|
||||
rc = sqlite3_wal_checkpoint_v2(p->dbSrc, "main", SQLITE_CHECKPOINT_FULL,
|
||||
0, 0);
|
||||
if( rc ){
|
||||
scrubBackupErr(p, "cannot checkpoint the source database");
|
||||
return;
|
||||
}
|
||||
pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_size");
|
||||
if( pStmt==0 ) return;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
p->szPage = sqlite3_column_int(pStmt, 0);
|
||||
}else{
|
||||
scrubBackupErr(p, "unable to determine the page size");
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
if( p->rcErr ) return;
|
||||
pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_count");
|
||||
if( pStmt==0 ) return;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
p->nPage = sqlite3_column_int(pStmt, 0);
|
||||
}else{
|
||||
scrubBackupErr(p, "unable to determine the size of the source database");
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_file_control(p->dbSrc, "main", SQLITE_FCNTL_FILE_POINTER, &p->pSrc);
|
||||
if( p->pSrc==0 || p->pSrc->pMethods==0 ){
|
||||
scrubBackupErr(p, "cannot get the source file handle");
|
||||
p->rcErr = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create and open the destination file */
|
||||
static void scrubBackupOpenDest(ScrubState *p){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
char *zSql;
|
||||
if( p->rcErr ) return;
|
||||
p->rcErr = sqlite3_open_v2(p->zDestFile, &p->dbDest,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
||||
SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
|
||||
if( p->rcErr ){
|
||||
scrubBackupErr(p, "cannot open destination database: %s",
|
||||
sqlite3_errmsg(p->dbDest));
|
||||
return;
|
||||
}
|
||||
zSql = sqlite3_mprintf("PRAGMA page_size(%u);", p->szPage);
|
||||
if( zSql==0 ){
|
||||
p->rcErr = SQLITE_NOMEM;
|
||||
return;
|
||||
}
|
||||
p->rcErr = sqlite3_exec(p->dbDest, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( p->rcErr ){
|
||||
scrubBackupErr(p,
|
||||
"cannot set the page size on the destination database: %s",
|
||||
sqlite3_errmsg(p->dbDest));
|
||||
return;
|
||||
}
|
||||
sqlite3_exec(p->dbDest, "PRAGMA journal_mode=OFF;", 0, 0, 0);
|
||||
p->rcErr = sqlite3_exec(p->dbDest, "BEGIN EXCLUSIVE;", 0, 0, 0);
|
||||
if( p->rcErr ){
|
||||
scrubBackupErr(p,
|
||||
"cannot start a write transaction on the destination database: %s",
|
||||
sqlite3_errmsg(p->dbDest));
|
||||
return;
|
||||
}
|
||||
pStmt = scrubBackupPrepare(p, p->dbDest, "PRAGMA page_count;");
|
||||
if( pStmt==0 ) return;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc!=SQLITE_ROW ){
|
||||
scrubBackupErr(p, "cannot measure the size of the destination");
|
||||
}else if( sqlite3_column_int(pStmt, 0)>1 ){
|
||||
scrubBackupErr(p, "destination database is not empty - holds %d pages",
|
||||
sqlite3_column_int(pStmt, 0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_file_control(p->dbDest, "main", SQLITE_FCNTL_FILE_POINTER, &p->pDest);
|
||||
if( p->pDest==0 || p->pDest->pMethods==0 ){
|
||||
scrubBackupErr(p, "cannot get the destination file handle");
|
||||
p->rcErr = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a 32-bit big-endian integer */
|
||||
static u32 scrubBackupInt32(const u8 *a){
|
||||
u32 v = a[3];
|
||||
v += ((u32)a[2])<<8;
|
||||
v += ((u32)a[1])<<16;
|
||||
v += ((u32)a[0])<<24;
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Read a 16-bit big-endian integer */
|
||||
static u32 scrubBackupInt16(const u8 *a){
|
||||
return (a[0]<<8) + a[1];
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a varint. Put the value in *pVal and return the number of bytes.
|
||||
*/
|
||||
static int scrubBackupVarint(const u8 *z, sqlite3_int64 *pVal){
|
||||
sqlite3_int64 v = 0;
|
||||
int i;
|
||||
for(i=0; i<8; i++){
|
||||
v = (v<<7) + (z[i]&0x7f);
|
||||
if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
|
||||
}
|
||||
v = (v<<8) + (z[i]&0xff);
|
||||
*pVal = v;
|
||||
return 9;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of bytes in a varint.
|
||||
*/
|
||||
static int scrubBackupVarintSize(const u8 *z){
|
||||
int i;
|
||||
for(i=0; i<8; i++){
|
||||
if( (z[i]&0x80)==0 ){ return i+1; }
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy the freelist trunk page given, and all its descendents,
|
||||
** zeroing out as much as possible in the process.
|
||||
*/
|
||||
static void scrubBackupFreelist(ScrubState *p, int pgno, u32 nFree){
|
||||
u8 *a, *aBuf;
|
||||
u32 n, mx;
|
||||
|
||||
if( p->rcErr ) return;
|
||||
aBuf = scrubBackupAllocPage(p);
|
||||
if( aBuf==0 ) return;
|
||||
|
||||
while( pgno && nFree){
|
||||
a = scrubBackupRead(p, pgno, aBuf);
|
||||
if( a==0 ) break;
|
||||
n = scrubBackupInt32(&a[4]);
|
||||
mx = p->szUsable/4 - 2;
|
||||
if( n<mx ){
|
||||
memset(&a[n*4+8], 0, 4*(mx-n));
|
||||
}
|
||||
scrubBackupWrite(p, pgno, a);
|
||||
pgno = scrubBackupInt32(a);
|
||||
#if 0
|
||||
/* There is really no point in copying the freelist leaf pages.
|
||||
** Simply leave them uninitialized in the destination database. The
|
||||
** OS filesystem should zero those pages for us automatically.
|
||||
*/
|
||||
for(i=0; i<n && nFree; i++){
|
||||
u32 iLeaf = scrubBackupInt32(&a[i*4+8]);
|
||||
if( aZero==0 ){
|
||||
aZero = scrubBackupAllocPage(p);
|
||||
if( aZero==0 ){ pgno = 0; break; }
|
||||
memset(aZero, 0, p->szPage);
|
||||
}
|
||||
scrubBackupWrite(p, iLeaf, aZero);
|
||||
nFree--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sqlite3_free(aBuf);
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy an overflow chain from source to destination. Zero out any
|
||||
** unused tail at the end of the overflow chain.
|
||||
*/
|
||||
static void scrubBackupOverflow(ScrubState *p, int pgno, u32 nByte){
|
||||
u8 *a, *aBuf;
|
||||
|
||||
aBuf = scrubBackupAllocPage(p);
|
||||
if( aBuf==0 ) return;
|
||||
while( nByte>0 && pgno!=0 ){
|
||||
a = scrubBackupRead(p, pgno, aBuf);
|
||||
if( a==0 ) break;
|
||||
if( nByte >= (p->szUsable)-4 ){
|
||||
nByte -= (p->szUsable) - 4;
|
||||
}else{
|
||||
u32 x = (p->szUsable - 4) - nByte;
|
||||
u32 i = p->szUsable - x;
|
||||
memset(&a[i], 0, x);
|
||||
nByte = 0;
|
||||
}
|
||||
scrubBackupWrite(p, pgno, a);
|
||||
pgno = scrubBackupInt32(a);
|
||||
}
|
||||
sqlite3_free(aBuf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Copy B-Tree page pgno, and all of its children, from source to destination.
|
||||
** Zero out deleted content during the copy.
|
||||
*/
|
||||
static void scrubBackupBtree(ScrubState *p, int pgno, int iDepth){
|
||||
u8 *a;
|
||||
u32 i, n, pc;
|
||||
u32 nCell;
|
||||
u32 nPrefix;
|
||||
u32 szHdr;
|
||||
u32 iChild;
|
||||
u8 *aTop;
|
||||
u8 *aCell;
|
||||
u32 x, y;
|
||||
int ln = 0;
|
||||
|
||||
|
||||
if( p->rcErr ) return;
|
||||
if( iDepth>50 ){
|
||||
scrubBackupErr(p, "corrupt: b-tree too deep at page %d", pgno);
|
||||
return;
|
||||
}
|
||||
if( pgno==1 ){
|
||||
a = p->page1;
|
||||
}else{
|
||||
a = scrubBackupRead(p, pgno, 0);
|
||||
if( a==0 ) return;
|
||||
}
|
||||
nPrefix = pgno==1 ? 100 : 0;
|
||||
aTop = &a[nPrefix];
|
||||
szHdr = 8 + 4*(aTop[0]==0x02 || aTop[0]==0x05);
|
||||
aCell = aTop + szHdr;
|
||||
nCell = scrubBackupInt16(&aTop[3]);
|
||||
|
||||
/* Zero out the gap between the cell index and the start of the
|
||||
** cell content area */
|
||||
x = scrubBackupInt16(&aTop[5]); /* First byte of cell content area */
|
||||
if( x>p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
|
||||
y = szHdr + nPrefix + nCell*2;
|
||||
if( y>x ){ ln=__LINE__; goto btree_corrupt; }
|
||||
if( y<x ) memset(a+y, 0, x-y); /* Zero the gap */
|
||||
|
||||
/* Zero out all the free blocks */
|
||||
pc = scrubBackupInt16(&aTop[1]);
|
||||
if( pc>0 && pc<x ){ ln=__LINE__; goto btree_corrupt; }
|
||||
while( pc ){
|
||||
if( pc>(p->szUsable)-4 ){ ln=__LINE__; goto btree_corrupt; }
|
||||
n = scrubBackupInt16(&a[pc+2]);
|
||||
if( pc+n>(p->szUsable) ){ ln=__LINE__; goto btree_corrupt; }
|
||||
if( n>4 ) memset(&a[pc+4], 0, n-4);
|
||||
x = scrubBackupInt16(&a[pc]);
|
||||
if( x<pc+4 && x>0 ){ ln=__LINE__; goto btree_corrupt; }
|
||||
pc = x;
|
||||
}
|
||||
|
||||
/* Write this one page */
|
||||
scrubBackupWrite(p, pgno, a);
|
||||
|
||||
/* Walk the tree and process child pages */
|
||||
for(i=0; i<nCell; i++){
|
||||
u32 X, M, K, nLocal;
|
||||
sqlite3_int64 P;
|
||||
pc = scrubBackupInt16(&aCell[i*2]);
|
||||
if( pc <= szHdr ){ ln=__LINE__; goto btree_corrupt; }
|
||||
if( pc > p->szUsable-3 ){ ln=__LINE__; goto btree_corrupt; }
|
||||
if( aTop[0]==0x05 || aTop[0]==0x02 ){
|
||||
if( pc+4 > p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
|
||||
iChild = scrubBackupInt32(&a[pc]);
|
||||
pc += 4;
|
||||
scrubBackupBtree(p, iChild, iDepth+1);
|
||||
if( aTop[0]==0x05 ) continue;
|
||||
}
|
||||
pc += scrubBackupVarint(&a[pc], &P);
|
||||
if( pc >= p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
|
||||
if( aTop[0]==0x0d ){
|
||||
X = p->szUsable - 35;
|
||||
}else{
|
||||
X = ((p->szUsable - 12)*64/255) - 23;
|
||||
}
|
||||
if( P<=X ){
|
||||
/* All content is local. No overflow */
|
||||
continue;
|
||||
}
|
||||
M = ((p->szUsable - 12)*32/255)-23;
|
||||
K = M + ((P-M)%(p->szUsable-4));
|
||||
if( aTop[0]==0x0d ){
|
||||
pc += scrubBackupVarintSize(&a[pc]);
|
||||
if( pc > (p->szUsable-4) ){ ln=__LINE__; goto btree_corrupt; }
|
||||
}
|
||||
nLocal = K<=X ? K : M;
|
||||
if( pc+nLocal > p->szUsable-4 ){ ln=__LINE__; goto btree_corrupt; }
|
||||
iChild = scrubBackupInt32(&a[pc+nLocal]);
|
||||
scrubBackupOverflow(p, iChild, (u32)(P-nLocal));
|
||||
}
|
||||
|
||||
/* Walk the right-most tree */
|
||||
if( aTop[0]==0x05 || aTop[0]==0x02 ){
|
||||
iChild = scrubBackupInt32(&aTop[8]);
|
||||
scrubBackupBtree(p, iChild, iDepth+1);
|
||||
}
|
||||
|
||||
/* All done */
|
||||
if( pgno>1 ) sqlite3_free(a);
|
||||
return;
|
||||
|
||||
btree_corrupt:
|
||||
scrubBackupErr(p, "corruption on page %d of source database (errid=%d)",
|
||||
pgno, ln);
|
||||
if( pgno>1 ) sqlite3_free(a);
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy all ptrmap pages from source to destination.
|
||||
** This routine is only called if the source database is in autovacuum
|
||||
** or incremental vacuum mode.
|
||||
*/
|
||||
static void scrubBackupPtrmap(ScrubState *p){
|
||||
u32 pgno = 2;
|
||||
u32 J = p->szUsable/5;
|
||||
u32 iLock = (1073742335/p->szPage)+1;
|
||||
u8 *a, *pBuf;
|
||||
if( p->rcErr ) return;
|
||||
pBuf = scrubBackupAllocPage(p);
|
||||
if( pBuf==0 ) return;
|
||||
while( pgno<=p->nPage ){
|
||||
a = scrubBackupRead(p, pgno, pBuf);
|
||||
if( a==0 ) break;
|
||||
scrubBackupWrite(p, pgno, a);
|
||||
pgno += J+1;
|
||||
if( pgno==iLock ) pgno++;
|
||||
}
|
||||
sqlite3_free(pBuf);
|
||||
}
|
||||
|
||||
int sqlite3_scrub_backup(
|
||||
const char *zSrcFile, /* Source file */
|
||||
const char *zDestFile, /* Destination file */
|
||||
char **pzErr /* Write error here if non-NULL */
|
||||
){
|
||||
ScrubState s;
|
||||
u32 n, i;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.zSrcFile = zSrcFile;
|
||||
s.zDestFile = zDestFile;
|
||||
|
||||
/* Open both source and destination databases */
|
||||
scrubBackupOpenSrc(&s);
|
||||
scrubBackupOpenDest(&s);
|
||||
|
||||
/* Read in page 1 */
|
||||
s.page1 = scrubBackupRead(&s, 1, 0);
|
||||
if( s.page1==0 ) goto scrub_abort;
|
||||
s.szUsable = s.szPage - s.page1[20];
|
||||
|
||||
/* Copy the freelist */
|
||||
n = scrubBackupInt32(&s.page1[36]);
|
||||
i = scrubBackupInt32(&s.page1[32]);
|
||||
if( n ) scrubBackupFreelist(&s, i, n);
|
||||
|
||||
/* Copy ptrmap pages */
|
||||
n = scrubBackupInt32(&s.page1[52]);
|
||||
if( n ) scrubBackupPtrmap(&s);
|
||||
|
||||
/* Copy all of the btrees */
|
||||
scrubBackupBtree(&s, 1, 0);
|
||||
pStmt = scrubBackupPrepare(&s, s.dbSrc,
|
||||
"SELECT rootpage FROM sqlite_schema WHERE coalesce(rootpage,0)>0");
|
||||
if( pStmt==0 ) goto scrub_abort;
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
i = (u32)sqlite3_column_int(pStmt, 0);
|
||||
scrubBackupBtree(&s, i, 0);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
/* If the last page of the input db file is a free-list leaf, then the
|
||||
** backup file on disk is still smaller than the size indicated within
|
||||
** the database header. In this case, write a page of zeroes to the
|
||||
** last page of the backup database so that SQLite does not mistakenly
|
||||
** think the db is corrupt. */
|
||||
if( s.iLastPage<s.nPage ){
|
||||
u8 *aZero = scrubBackupAllocPage(&s);
|
||||
if( aZero ){
|
||||
memset(aZero, 0, s.szPage);
|
||||
scrubBackupWrite(&s, s.nPage, aZero);
|
||||
sqlite3_free(aZero);
|
||||
}
|
||||
}
|
||||
|
||||
scrub_abort:
|
||||
/* Close the destination database without closing the transaction. If we
|
||||
** commit, page zero will be overwritten. */
|
||||
sqlite3_close(s.dbDest);
|
||||
|
||||
/* But do close out the read-transaction on the source database */
|
||||
sqlite3_exec(s.dbSrc, "COMMIT;", 0, 0, 0);
|
||||
sqlite3_close(s.dbSrc);
|
||||
sqlite3_free(s.page1);
|
||||
if( pzErr ){
|
||||
*pzErr = s.zErr;
|
||||
}else{
|
||||
sqlite3_free(s.zErr);
|
||||
}
|
||||
return s.rcErr;
|
||||
}
|
||||
|
||||
#ifdef SCRUB_STANDALONE
|
||||
/* Error and warning log */
|
||||
static void errorLogCallback(void *pNotUsed, int iErr, const char *zMsg){
|
||||
const char *zType;
|
||||
switch( iErr&0xff ){
|
||||
case SQLITE_WARNING: zType = "WARNING"; break;
|
||||
case SQLITE_NOTICE: zType = "NOTICE"; break;
|
||||
default: zType = "ERROR"; break;
|
||||
}
|
||||
fprintf(stderr, "%s: %s\n", zType, zMsg);
|
||||
}
|
||||
|
||||
/* The main() routine when this utility is run as a stand-alone program */
|
||||
int main(int argc, char **argv){
|
||||
char *zErr = 0;
|
||||
int rc;
|
||||
if( argc!=3 ){
|
||||
fprintf(stderr,"Usage: %s SOURCE DESTINATION\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, 0);
|
||||
rc = sqlite3_scrub_backup(argv[1], argv[2], &zErr);
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
fprintf(stderr, "%s: out of memory\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if( zErr ){
|
||||
fprintf(stderr, "%s: %s\n", argv[0], zErr);
|
||||
sqlite3_free(zErr);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
+2
-2
@@ -536,7 +536,7 @@ static int seriesFilter(
|
||||
if( r<(double)SMALLEST_INT64 ){
|
||||
iMin = SMALLEST_INT64;
|
||||
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
|
||||
iMin = (sqlite3_int64)seriesCeil(r+1.0);
|
||||
iMin = (sqlite3_int64)seriesCeil(r)+1;
|
||||
}else{
|
||||
iMin = (sqlite3_int64)seriesCeil(r);
|
||||
}
|
||||
@@ -557,7 +557,7 @@ static int seriesFilter(
|
||||
if( r>(double)LARGEST_INT64 ){
|
||||
iMax = LARGEST_INT64;
|
||||
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
|
||||
iMax = (sqlite3_int64)(r-1.0);
|
||||
iMax = ((sqlite3_int64)r)-1;
|
||||
}else{
|
||||
iMax = (sqlite3_int64)seriesFloor(r);
|
||||
}
|
||||
|
||||
+21
-11
@@ -32,6 +32,7 @@ SQLITE_EXTENSION_INIT1
|
||||
# define NEVER(X) 0
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef sqlite3_int64 i64;
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -192,7 +193,7 @@ static const unsigned char className[] = ".ABCDHLRMY9 ?";
|
||||
** Return NULL if memory allocation fails.
|
||||
*/
|
||||
static unsigned char *phoneticHash(const unsigned char *zIn, int nIn){
|
||||
unsigned char *zOut = sqlite3_malloc64( nIn + 1 );
|
||||
unsigned char *zOut = sqlite3_malloc64( (i64)nIn + 1 );
|
||||
int i;
|
||||
int nOut = 0;
|
||||
char cPrev = 0x77;
|
||||
@@ -352,6 +353,7 @@ static int substituteCost(char cPrev, char cFrom, char cTo){
|
||||
** -1 One of the inputs is NULL
|
||||
** -2 Non-ASCII characters on input
|
||||
** -3 Unable to allocate memory
|
||||
** -4 Inputs too large
|
||||
**
|
||||
** If pnMatch is not NULL, then *pnMatch is set to the number of bytes
|
||||
** of zB that matched the pattern in zA. If zA does not end with a '*',
|
||||
@@ -390,9 +392,11 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
for(nA=0; zA[nA]; nA++){
|
||||
if( zA[nA]&0x80 ) return -2;
|
||||
}
|
||||
if( nA>=100000 ) return -4;
|
||||
for(nB=0; zB[nB]; nB++){
|
||||
if( zB[nB]&0x80 ) return -2;
|
||||
}
|
||||
if( nB>=100000 ) return -4;
|
||||
|
||||
/* Special processing if either string is empty */
|
||||
if( nA==0 ){
|
||||
@@ -419,7 +423,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
if( nB<(sizeof(mStack)*4)/(sizeof(mStack[0])*5) ){
|
||||
m = mStack;
|
||||
}else{
|
||||
m = toFree = sqlite3_malloc64( (nB+1)*5*sizeof(m[0])/4 );
|
||||
m = toFree = sqlite3_malloc64( ((i64)nB+1)*5LL*sizeof(m[0])/4 );
|
||||
if( m==0 ) return -3;
|
||||
}
|
||||
cx = (char*)&m[nB+1];
|
||||
@@ -527,6 +531,8 @@ static void editdistSqlFunc(
|
||||
if( res<0 ){
|
||||
if( res==(-3) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( res==(-4) ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( res==(-2) ){
|
||||
sqlite3_result_error(context, "non-ASCII input to editdist()", -1);
|
||||
}else{
|
||||
@@ -767,7 +773,7 @@ static int editDist3ConfigLoad(
|
||||
if( iCost>=10000 ) continue; /* Costs above 10K are considered infinite */
|
||||
if( pLang==0 || iLang!=iLangPrev ){
|
||||
EditDist3Lang *pNew;
|
||||
pNew = sqlite3_realloc64(p->a, (p->nLang+1)*sizeof(p->a[0]));
|
||||
pNew = sqlite3_realloc64(p->a, ((i64)p->nLang+1)*sizeof(p->a[0]));
|
||||
if( pNew==0 ){ rc = SQLITE_NOMEM; break; }
|
||||
p->a = pNew;
|
||||
pLang = &p->a[p->nLang];
|
||||
@@ -901,7 +907,7 @@ static EditDist3FromString *editDist3FromStringNew(
|
||||
|
||||
if( z==0 ) return 0;
|
||||
if( n<0 ) n = (int)strlen(z);
|
||||
pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 );
|
||||
pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + (i64)n + 1 );
|
||||
if( pStr==0 ) return 0;
|
||||
pStr->a = (EditDist3From*)&pStr[1];
|
||||
memset(pStr->a, 0, sizeof(pStr->a[0])*n);
|
||||
@@ -927,13 +933,13 @@ static EditDist3FromString *editDist3FromStringNew(
|
||||
if( matchFrom(p, z+i, n-i)==0 ) continue;
|
||||
if( p->nTo==0 ){
|
||||
apNew = sqlite3_realloc64(pFrom->apDel,
|
||||
sizeof(*apNew)*(pFrom->nDel+1));
|
||||
sizeof(*apNew)*((i64)pFrom->nDel+1));
|
||||
if( apNew==0 ) break;
|
||||
pFrom->apDel = apNew;
|
||||
apNew[pFrom->nDel++] = p;
|
||||
}else{
|
||||
apNew = sqlite3_realloc64(pFrom->apSubst,
|
||||
sizeof(*apNew)*(pFrom->nSubst+1));
|
||||
sizeof(*apNew)*((i64)pFrom->nSubst+1));
|
||||
if( apNew==0 ) break;
|
||||
pFrom->apSubst = apNew;
|
||||
apNew[pFrom->nSubst++] = p;
|
||||
@@ -1008,6 +1014,8 @@ static int editDist3Core(
|
||||
unsigned int stackSpace[SQLITE_SPELLFIX_STACKALLOC_SZ/sizeof(unsigned int)];
|
||||
|
||||
/* allocate the Wagner matrix and the aTo[] array for the TO string */
|
||||
if( n2>10000 ) return -2;
|
||||
if( f.n>10000 ) return -2;
|
||||
n = (f.n+1)*(n2+1);
|
||||
n = (n+1)&~1;
|
||||
nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2;
|
||||
@@ -1198,6 +1206,8 @@ static void editDist3SqlFunc(
|
||||
editDist3FromStringDelete(pFrom);
|
||||
if( dist==(-1) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( dist==(-2) ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else{
|
||||
sqlite3_result_int(context, dist);
|
||||
}
|
||||
@@ -1712,9 +1722,9 @@ static const Transliteration *spellfixFindTranslit(int c, int *pxTop){
|
||||
*/
|
||||
static unsigned char *transliterate(const unsigned char *zIn, int nIn){
|
||||
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
|
||||
unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 );
|
||||
unsigned char *zOut = sqlite3_malloc64( (i64)nIn*5 + 1 );
|
||||
#else
|
||||
unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
|
||||
unsigned char *zOut = sqlite3_malloc64( (i64)nIn*4 + 1 );
|
||||
#endif
|
||||
int c, sz, nOut;
|
||||
if( zOut==0 ) return 0;
|
||||
@@ -2057,7 +2067,7 @@ static int spellfix1Init(
|
||||
int i;
|
||||
|
||||
nDbName = (int)strlen(zDbName);
|
||||
pNew = sqlite3_malloc64( sizeof(*pNew) + nDbName + 1);
|
||||
pNew = sqlite3_malloc64( sizeof(*pNew) + (i64)nDbName + 1);
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -2461,7 +2471,7 @@ static void spellfix1RunQuery(MatchQuery *p, const char *zQuery, int nQuery){
|
||||
iDist = editdist1(p->zPattern, zK1, 0);
|
||||
}
|
||||
if( iDist<0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
p->rc = iDist==(-4) ? SQLITE_TOOBIG : SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
pCur->nSearch++;
|
||||
@@ -2773,7 +2783,7 @@ static int spellfix1Column(
|
||||
if( !zTranslit ) return SQLITE_NOMEM;
|
||||
res = editdist1(pCur->zPattern, zTranslit, &iMatchlen);
|
||||
sqlite3_free(zTranslit);
|
||||
if( res<0 ) return SQLITE_NOMEM;
|
||||
if( res<0 ) return res==(-4) ? SQLITE_TOOBIG : SQLITE_NOMEM;
|
||||
iMatchlen = translen_to_charlen(zWord, nWord, iMatchlen);
|
||||
}else{
|
||||
iMatchlen = utf8Charlen(zWord, nWord);
|
||||
|
||||
+11
-4
@@ -488,6 +488,7 @@ static void zipfileResetCursor(ZipfileCsr *pCsr){
|
||||
pNext = p->pNext;
|
||||
zipfileEntryFree(p);
|
||||
}
|
||||
pCsr->pFreeEntry = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -890,7 +891,13 @@ static int zipfileGetEntry(
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
u32 *pt = &pNew->mUnixTime;
|
||||
pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
|
||||
/* aRead[0..nFile-1] might contain embedded \000 characters
|
||||
** See Bug 2026-05-31T11:43:05Z */
|
||||
pNew->cds.zFile = sqlite3_malloc64(nFile+1);
|
||||
if( pNew->cds.zFile!=0 ){
|
||||
memcpy(pNew->cds.zFile, aRead, nFile);
|
||||
pNew->cds.zFile[nFile] = 0;
|
||||
}
|
||||
pNew->aExtra = (u8*)&pNew[1];
|
||||
memcpy(pNew->aExtra, &aRead[nFile], nExtra);
|
||||
if( pNew->cds.zFile==0 ){
|
||||
@@ -1994,10 +2001,10 @@ struct ZipfileCtx {
|
||||
};
|
||||
|
||||
static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
|
||||
if( pBuf->n+nByte>pBuf->nAlloc ){
|
||||
if( (pBuf->nAlloc-pBuf->n)<nByte ){
|
||||
u8 *aNew;
|
||||
sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
|
||||
int nReq = pBuf->n + nByte;
|
||||
i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512;
|
||||
i64 nReq = pBuf->n + nByte;
|
||||
|
||||
while( nNew<nReq ) nNew = nNew*2;
|
||||
aNew = sqlite3_realloc64(pBuf->a, nNew);
|
||||
|
||||
+2
-2
@@ -911,7 +911,7 @@ static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){
|
||||
sqlite3_str_append(pOut, (const char*)z, i);
|
||||
}
|
||||
switch( z[i] ){
|
||||
case '>': sqlite3_str_append(pOut, "<", 4); break;
|
||||
case '>': sqlite3_str_append(pOut, ">", 4); break;
|
||||
case '&': sqlite3_str_append(pOut, "&", 5); break;
|
||||
case '<': sqlite3_str_append(pOut, "<", 4); break;
|
||||
case '"': sqlite3_str_append(pOut, """, 6); break;
|
||||
@@ -1391,7 +1391,7 @@ static void qrfWrapLine(
|
||||
for(k=i-1; k>=i/2; k--){
|
||||
if( qrfSpace(z[k]) ) break;
|
||||
}
|
||||
if( k<i/2 ){
|
||||
if( k<i/2 && i/2>0 ){
|
||||
for(k=i; k>=i/2; k--){
|
||||
if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
|
||||
}
|
||||
|
||||
@@ -532,18 +532,39 @@ static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Run a single SQL statement in zSql. If zSql contains two or more
|
||||
** SQL statements separated by ';', only the first is run.
|
||||
**
|
||||
** Return the sqlite3_finalizer() or sqlite3_prepare() result code
|
||||
** from running the zSql statement.
|
||||
*/
|
||||
static int recoverOneStmt(sqlite3 *db, const char *zSql){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc;
|
||||
if( zSql==0 ) return SQLITE_OK;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is a no-op if recover handle p already contains an error
|
||||
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this
|
||||
** case.
|
||||
**
|
||||
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
|
||||
** Or, if an error occurs, leave an error code and message in the recover
|
||||
** handle and return a copy of the error code.
|
||||
** Otherwise, execute a single SQL statment in zSql. Even if zSql contains
|
||||
** two or more SQL statements separated by ';', only execute the first one.
|
||||
** If successful, return SQLITE_OK. Or, if an error occurs, leave an error
|
||||
** code and message in the recover handle and return a copy of the error code.
|
||||
*/
|
||||
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
int rc = sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
int rc = recoverOneStmt(db, zSql);
|
||||
if( rc ){
|
||||
recoverDbError(p, db);
|
||||
}
|
||||
@@ -943,7 +964,8 @@ static void recoverTransferSettings(sqlite3_recover *p){
|
||||
}
|
||||
recoverFinalize(p, p1);
|
||||
}
|
||||
recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
|
||||
recoverExec(p, db2, "CREATE TABLE t1(a)");
|
||||
recoverExec(p, db2, "DROP TABLE t1");
|
||||
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
sqlite3 *db = p->dbOut;
|
||||
@@ -1025,12 +1047,12 @@ static int recoverOpenOutput(sqlite3_recover *p){
|
||||
static void recoverOpenRecovery(sqlite3_recover *p){
|
||||
char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
|
||||
recoverExec(p, p->dbOut, zSql);
|
||||
recoverExec(p, p->dbOut,
|
||||
"PRAGMA writable_schema = 1;"
|
||||
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);"
|
||||
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
|
||||
);
|
||||
sqlite3_free(zSql);
|
||||
recoverExec(p, p->dbOut, "PRAGMA writable_schema = 1");
|
||||
recoverExec(p, p->dbOut,
|
||||
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT)");
|
||||
recoverExec(p, p->dbOut,
|
||||
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql)");
|
||||
}
|
||||
|
||||
|
||||
@@ -1170,7 +1192,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
")"
|
||||
"SELECT rootpage, tbl, isVirtual, name, sql"
|
||||
" FROM dbschema "
|
||||
" WHERE tbl OR isIndex"
|
||||
" WHERE (tbl OR isIndex) AND sql GLOB 'CREATE *'"
|
||||
" ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
|
||||
);
|
||||
|
||||
@@ -1196,7 +1218,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
zName, zName, zSql
|
||||
));
|
||||
}
|
||||
rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbOut, zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
recoverSqlCallback(p, zSql);
|
||||
if( bTable && !bVirtual ){
|
||||
@@ -1238,15 +1260,17 @@ static int recoverWriteSchema2(sqlite3_recover *p){
|
||||
p->bSlowIndexes ?
|
||||
"SELECT rootpage, sql FROM recovery.schema "
|
||||
" WHERE type!='table' AND type!='index'"
|
||||
" AND sql GLOB 'CREATE *'"
|
||||
:
|
||||
"SELECT rootpage, sql FROM recovery.schema "
|
||||
" WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
|
||||
" AND sql GLOB 'CREATE *'"
|
||||
);
|
||||
|
||||
if( pSelect ){
|
||||
while( sqlite3_step(pSelect)==SQLITE_ROW ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
|
||||
int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
|
||||
int rc = recoverOneStmt(p->dbOut, zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
recoverSqlCallback(p, zSql);
|
||||
}else if( rc!=SQLITE_ERROR ){
|
||||
@@ -2624,7 +2648,7 @@ static void recoverStep(sqlite3_recover *p){
|
||||
if( bUseWrapper ) recoverUninstallWrapper(p);
|
||||
}while( p->errCode==SQLITE_NOTADB
|
||||
&& (bUseWrapper--)
|
||||
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
|
||||
&& SQLITE_OK==recoverOneStmt(p->dbIn, "ROLLBACK")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2689,7 +2713,7 @@ static void recoverStep(sqlite3_recover *p){
|
||||
** database. Regardless of whether or not an error has occurred, make
|
||||
** an attempt to end the read transaction on the input database. */
|
||||
recoverExec(p, p->dbOut, "COMMIT");
|
||||
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbIn, "END");
|
||||
if( p->errCode==SQLITE_OK ) p->errCode = rc;
|
||||
|
||||
recoverSqlCallback(p, "PRAGMA writable_schema = off");
|
||||
@@ -2885,7 +2909,7 @@ int sqlite3_recover_finish(sqlite3_recover *p){
|
||||
}else{
|
||||
recoverFinalCleanup(p);
|
||||
if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
|
||||
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbIn, "END");
|
||||
if( p->errCode==SQLITE_OK ) p->errCode = rc;
|
||||
}
|
||||
rc = p->errCode;
|
||||
|
||||
@@ -1251,6 +1251,11 @@ static int geopolyInit(
|
||||
int ii;
|
||||
(void)pAux;
|
||||
|
||||
if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
|
||||
*pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
|
||||
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
||||
|
||||
|
||||
+7
-4
@@ -166,7 +166,7 @@ struct Rtree {
|
||||
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
|
||||
u8 nBytesPerCell; /* Bytes consumed per cell */
|
||||
u8 inWrTrans; /* True if inside write transaction */
|
||||
u8 nAux; /* # of auxiliary columns in %_rowid */
|
||||
u16 nAux; /* # of auxiliary columns in %_rowid */
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
u8 nAuxNotNull; /* Number of initial not-null aux columns */
|
||||
#endif
|
||||
@@ -1402,7 +1402,7 @@ static int nodeRowidIndex(
|
||||
){
|
||||
int ii;
|
||||
int nCell = NCELL(pNode);
|
||||
assert( nCell<200 );
|
||||
assert( nCell<65536 && nCell>=0 );
|
||||
for(ii=0; ii<nCell; ii++){
|
||||
if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
|
||||
*piIndex = ii;
|
||||
@@ -1664,7 +1664,10 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
|
||||
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
|
||||
if( rc ) return rc;
|
||||
nCell = NCELL(pNode);
|
||||
assert( nCell<200 );
|
||||
if( nCell>RTREE_MAXCELLS ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
|
||||
while( p->iCell<nCell ){
|
||||
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
|
||||
@@ -3641,7 +3644,7 @@ static int rtreeInit(
|
||||
"Auxiliary rtree columns must be last" /* 4 */
|
||||
};
|
||||
|
||||
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
|
||||
assert( RTREE_MAX_AUX_COLUMN<256 );
|
||||
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
|
||||
return SQLITE_ERROR;
|
||||
|
||||
@@ -18,6 +18,7 @@ if {![info exists testdir]} {
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
set testprefix rtreeA
|
||||
|
||||
proc create_t1 {} {
|
||||
db close
|
||||
@@ -258,5 +259,33 @@ do_test rtreeA-7.120 {
|
||||
sqlite3_extended_errcode db
|
||||
} {SQLITE_CORRUPT_VTAB}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
set N 300
|
||||
set rec [binary format SS 0 $N]
|
||||
for {set ii 1} {$ii<=$N} {incr ii} {
|
||||
set cell [binary format Wff $ii $ii [expr $ii+1]]
|
||||
set rec [binary format a*a* $rec $cell]
|
||||
}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
|
||||
INSERT INTO rt VALUES(1, 0.0, 1.0);
|
||||
UPDATE rt_node SET data = $rec WHERE nodeno = 1;
|
||||
DELETE FROM rt_rowid;
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300
|
||||
)
|
||||
INSERT INTO rt_rowid SELECT i, 1 FROM s;
|
||||
DELETE FROM rt_parent;
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
SELECT count(*) FROM rt WHERE id = 1
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -324,5 +324,47 @@ do_test 6.3.2 { sqlite3_errcode db2 } {SQLITE_ERROR}
|
||||
do_test 6.4 {
|
||||
catchsql { INSERT INTO c1 VALUES(100, 200) } db2
|
||||
} {1 {no such table: main.p1}}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
PRAGMA trusted_schema=OFF;
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
|
||||
CREATE TABLE t2(e TEXT PRIMARY KEY NOT NULL, f, g);
|
||||
CREATE TABLE t3(w REAL PRIMARY KEY NOT NULL, x, y);
|
||||
CREATE TABLE t4(z PRIMARY KEY) WITHOUT ROWID;
|
||||
CREATE TABLE tc(a INTEGER, b INTEGER, c BLOB, d TEXT, PRIMARY KEY(a,b));
|
||||
CREATE TABLE wr(a TEXT, b INT, c, PRIMARY KEY(a,b)) WITHOUT ROWID;
|
||||
CREATE TABLE child(x INTEGER PRIMARY KEY, y INTEGER REFERENCES t1(a) ON DELETE CASCADE, z TEXT);
|
||||
INSERT INTO t1 VALUES(1,2,3,4),(2,3.5,'four',x'556677'),(3,NULL,'xyz',15),(4,'bubba',2147483648,0.0);
|
||||
INSERT INTO t1 SELECT a+4,c,d,b FROM t1;
|
||||
INSERT INTO t2 VALUES('x1y',2,3),('x2y','four',x'556677'),('x3y',NULL,'xyz');
|
||||
INSERT INTO t3 VALUES(1.1,'a','b'),(2.2,x'00ff','c');
|
||||
INSERT INTO t4 VALUES('alpha'),('beta'),('gamma');
|
||||
INSERT INTO tc VALUES(1,1,x'0102','one'),(1,2,x'0304','two'),(2,1,x'0506','three');
|
||||
INSERT INTO wr VALUES('a',1,'wa'),('b',2,'wb');
|
||||
INSERT INTO child VALUES(1,1,'c1'),(2,2,'c2');
|
||||
}
|
||||
|
||||
set C [db one "SELECT unhex('
|
||||
54 0401 0200 0074 6300 1700 0100 0000
|
||||
0000 0000 0101 0000 0000 0069 0001 0402
|
||||
0102 0303 6f6e 6500 0004 2008 40a1 4c0b
|
||||
0d3f 3730 5d92 3f18 f2c9 66a6 4220 a873
|
||||
04cc 5281 ce5c d9d4 dc8b 7003 056f 6e65
|
||||
2d75 1700 0100 0002 5004 0100 0000 6d69
|
||||
7800 1700 0302 6b31 0409 1100
|
||||
', ' \n')"]
|
||||
|
||||
|
||||
proc conflict_handler {args} {
|
||||
return "OMIT"
|
||||
}
|
||||
do_test 7.1 {
|
||||
list [catch {sqlite3changeset_apply_v2 db $::C conflict_handler} msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -259,6 +259,18 @@ foreach {tn type C2hex C3hex} {
|
||||
} {1 SQLITE_CORRUPT}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
set CSD 5402010074000900010000000000000001030441414141
|
||||
set CSI 5402010074001200010000000000000001063258585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858
|
||||
|
||||
do_test 7.0 {
|
||||
sqlite3changegroup grp
|
||||
grp add [db one {SELECT unhex($CSD)}]
|
||||
list [catch { grp add [db one {SELECT unhex($CSI)}] } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
grp delete
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -82,6 +82,9 @@ do_test 2.2.1 {
|
||||
# It is not possible to apply the changeset generated by the following
|
||||
# SQL, as none of the three updated rows may be updated as part of the
|
||||
# first pass.
|
||||
#
|
||||
# UPDATE 19/05/2026 - it is now possible to apply such an update.
|
||||
#
|
||||
do_then_apply_sql -ignorenoop {
|
||||
UPDATE t1 SET b=0 WHERE a=1;
|
||||
UPDATE t1 SET b=1 WHERE a=2;
|
||||
@@ -89,7 +92,7 @@ do_test 2.2.1 {
|
||||
UPDATE t1 SET b=3 WHERE a=1;
|
||||
}
|
||||
db2 eval { SELECT a, b FROM t1 }
|
||||
} {1 1 2 2 3 3}
|
||||
} {1 3 2 1 3 2}
|
||||
do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
Executable
+298
@@ -0,0 +1,298 @@
|
||||
# 2026 May 18
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionconflict2
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.1 {
|
||||
do_then_apply_sql {
|
||||
UPDATE t1 SET c=NULL WHERE a=1;
|
||||
UPDATE t1 SET c=1 WHERE a=3;
|
||||
UPDATE t1 SET c=3 WHERE a=1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db 1.2 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 1.3 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
db2 close
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 2.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE) WITHOUT ROWID;
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 2.1 {
|
||||
do_then_apply_sql {
|
||||
UPDATE t1 SET c=NULL WHERE a=1;
|
||||
UPDATE t1 SET c=1 WHERE a=3;
|
||||
UPDATE t1 SET c=3 WHERE a=1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db 2.2 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 1 3
|
||||
2 2 2
|
||||
3 3 1
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 2.3 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 1 3
|
||||
2 2 2
|
||||
3 3 1
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
db2 close
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 3.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 3.1 {
|
||||
do_then_apply_sql {
|
||||
UPDATE t1 SET c=NULL WHERE a=1;
|
||||
UPDATE t1 SET c=1 WHERE a=3;
|
||||
UPDATE t1 SET c=3 WHERE a=1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db 3.2 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 3.3 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
db2 close
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
set ::conflict_list [list]
|
||||
proc xConflict {args} {
|
||||
lappend ::conflict_list $args
|
||||
return "OMIT"
|
||||
}
|
||||
|
||||
proc do_conflict_test {tn bNoUpdateLoop script clist} {
|
||||
|
||||
uplevel [list do_test $tn.1 [subst -nocommands {
|
||||
sqlite3session S db "main"
|
||||
S attach *
|
||||
eval {$script}
|
||||
set ::changeset [S changeset]
|
||||
S delete
|
||||
}] {}]
|
||||
|
||||
if {$bNoUpdateLoop} {
|
||||
uplevel [list do_test $tn.2.no {
|
||||
set ::conflict_list [list]
|
||||
sqlite3changeset_apply_v2 -noupdateloop db2 $::changeset xConflict
|
||||
set ::conflict_list
|
||||
} [list {*}$clist]]
|
||||
} else {
|
||||
uplevel [list do_test $tn.2 {
|
||||
set ::conflict_list [list]
|
||||
sqlite3changeset_apply_v2 db2 $::changeset xConflict
|
||||
set ::conflict_list
|
||||
} [list {*}$clist]]
|
||||
}
|
||||
}
|
||||
|
||||
do_test 4.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i, i, i FROM s;
|
||||
}
|
||||
} {}
|
||||
|
||||
proc swap {tbl pkcol valcol pk1 pk2} {
|
||||
set val1 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk1"]
|
||||
set val2 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk2"]
|
||||
|
||||
db eval "
|
||||
UPDATE $tbl SET $valcol = NULL WHERE $pkcol IN (\$pk1, \$pk2);
|
||||
UPDATE $tbl SET $valcol = \$val2 WHERE $pkcol = \$pk1;
|
||||
UPDATE $tbl SET $valcol = \$val1 WHERE $pkcol = \$pk2;
|
||||
"
|
||||
}
|
||||
|
||||
do_conflict_test 4.1.1 0 {
|
||||
swap t1 a c 4 5
|
||||
swap t1 a c 2 3
|
||||
swap t1 a c 8 1
|
||||
} {
|
||||
}
|
||||
|
||||
do_execsql_test -db db 4.1.2 {
|
||||
SELECT a, c FROM t1
|
||||
} {
|
||||
1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
|
||||
}
|
||||
do_execsql_test -db db2 4.1.3 {
|
||||
SELECT a, c FROM t1
|
||||
} {
|
||||
1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
|
||||
}
|
||||
|
||||
do_conflict_test 4.2.1 0 {
|
||||
swap t1 a d 10 9
|
||||
swap t1 a d 8 7
|
||||
swap t1 a d 7 6
|
||||
swap t1 a d 5 4
|
||||
swap t1 a d 4 8
|
||||
} {
|
||||
}
|
||||
|
||||
do_execsql_test -db db 4.2.2 {
|
||||
SELECT a, d FROM t1
|
||||
} {
|
||||
1 1 2 2 3 3 4 7 5 4 6 8 7 6 8 5 9 10 10 9
|
||||
}
|
||||
do_execsql_test -db db2 4.2.3 {
|
||||
SELECT a, d FROM t1
|
||||
} {
|
||||
1 1 2 2 3 3 4 7 5 4 6 8 7 6 8 5 9 10 10 9
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3 {
|
||||
INSERT INTO t1(a, b, c, d) VALUES(11, 11, 11, 11);
|
||||
}
|
||||
|
||||
do_conflict_test 4.3.1 0 {
|
||||
swap t1 a c 3 6
|
||||
db eval { UPDATE t1 SET d=11 WHERE a=10; }
|
||||
swap t1 a d 4 8
|
||||
} {
|
||||
{UPDATE t1 CONSTRAINT {i 10 {} {} {} {} i 9} {{} {} {} {} {} {} i 11}}
|
||||
}
|
||||
|
||||
do_conflict_test 4.3.2 0 {
|
||||
swap t1 a c 1 2
|
||||
swap t1 a c 3 4
|
||||
db eval { UPDATE t1 SET c=11 WHERE a=10; }
|
||||
swap t1 a d 5 6
|
||||
swap t1 a d 4 5
|
||||
} {
|
||||
{UPDATE t1 CONSTRAINT {i 10 {} {} i 10 {} {}} {{} {} {} {} i 11 {} {}}}
|
||||
}
|
||||
|
||||
do_conflict_test 4.3.3 0 {
|
||||
swap t1 a c 1 2
|
||||
swap t1 a c 2 3
|
||||
swap t1 a c 3 4
|
||||
swap t1 a c 4 1
|
||||
} {
|
||||
}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 5.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b UNIQUE);
|
||||
INSERT INTO t1 VALUES('one', 'one');
|
||||
INSERT INTO t1 VALUES('two', 'two');
|
||||
INSERT INTO t1 VALUES('three', 'three');
|
||||
INSERT INTO t1 VALUES('four', 'four');
|
||||
INSERT INTO t1 VALUES('five', 'five');
|
||||
}
|
||||
} {}
|
||||
|
||||
do_conflict_test 5.1 1 {
|
||||
} {
|
||||
}
|
||||
|
||||
do_conflict_test 5.2 1 {
|
||||
swap t1 a b one two
|
||||
} {
|
||||
{UPDATE t1 CONSTRAINT {t two t two} {{} {} t one}}
|
||||
{UPDATE t1 CONSTRAINT {t one t one} {{} {} t two}}
|
||||
}
|
||||
|
||||
do_conflict_test 5.2 0 {
|
||||
swap t1 a b four five
|
||||
} {
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -94,4 +94,45 @@ do_faultsim_test 2 -faults oom-t* -prep {
|
||||
catch { S delete }
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
INSERT INTO t1 VALUES(3, 'three');
|
||||
INSERT INTO t1 VALUES(4, 'four');
|
||||
INSERT INTO t1 VALUES(5, 'five');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
faultsim_restore_and_reopen
|
||||
|
||||
set C [changeset_from_sql {
|
||||
UPDATE t1 SET b=NULL WHERE a IN (1, 3, 5);
|
||||
UPDATE t1 SET b='three' WHERE a=1;
|
||||
UPDATE t1 SET b='five' WHERE a=3;
|
||||
UPDATE t1 SET b='one' WHERE a=5;
|
||||
}]
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 three 2 two 3 five 4 four 5 one
|
||||
}
|
||||
|
||||
proc xConflict {args} {
|
||||
lappend ::conflict_list $args
|
||||
return "OMIT"
|
||||
}
|
||||
|
||||
do_faultsim_test 3 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_schema}
|
||||
} -body {
|
||||
sqlite3changeset_apply_v2 db $::C xConflict
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -181,5 +181,11 @@ do_invert_test 4.1 {
|
||||
{UPDATE t1 0 X. {i 4 t three} {{} {} t four}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_test 5.0 {
|
||||
set C [db one {SELECT unhex('54000009')}]
|
||||
list [catch { sqlite3changeset_invert $C } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -228,5 +228,30 @@ do_execsql_test 3.8 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER);
|
||||
ATTACH ':memory:' AS aux;
|
||||
CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER);
|
||||
}
|
||||
|
||||
do_test 4.1 {
|
||||
sqlite3session S db main
|
||||
S diff aux t1
|
||||
} {}
|
||||
|
||||
do_test 4.2 {
|
||||
sqlite3changeset_apply_v2 -ignorenoop -noaction db "" conflict
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
do_test 4.3 {
|
||||
S diff aux t1
|
||||
} {}
|
||||
|
||||
S delete
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+384
-47
@@ -638,10 +638,11 @@ static int sessionSerialLen(const u8 *a){
|
||||
int n;
|
||||
assert( a!=0 );
|
||||
e = *a;
|
||||
if( e==0 || e==0xFF ) return 1;
|
||||
if( e==SQLITE_NULL ) return 1;
|
||||
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
|
||||
return sessionVarintGet(&a[1], &n) + 1 + n;
|
||||
if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
|
||||
return sessionVarintGet(&a[1], &n) + 1 + n;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -664,17 +665,17 @@ static unsigned int sessionChangeHash(
|
||||
u8 *a = aRecord; /* Used to iterate through change record */
|
||||
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
int eType = *a;
|
||||
int isPK = pTab->abPK[i];
|
||||
if( bPkOnly && isPK==0 ) continue;
|
||||
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|
||||
|| eType==SQLITE_NULL || eType==0
|
||||
);
|
||||
|
||||
if( isPK ){
|
||||
a++;
|
||||
int eType = *a++;
|
||||
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|
||||
|| eType==SQLITE_NULL || eType==0
|
||||
);
|
||||
|
||||
h = sessionHashAppendType(h, eType);
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
h = sessionHashAppendI64(h, sessionGetI64(a));
|
||||
@@ -1544,6 +1545,16 @@ static int sessionPrepareDfltStmt(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
|
||||
** called, set it to the results of the sqlite3_finalize() call. Or, if
|
||||
** it is already set to an error code, leave it as is.
|
||||
*/
|
||||
static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
|
||||
int rc = sqlite3_finalize(pStmt);
|
||||
if( *pRc==SQLITE_OK ) *pRc = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Table pTab has one or more existing change-records with old.* records
|
||||
** with fewer than pTab->nCol columns. This function updates all such
|
||||
@@ -1566,9 +1577,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
|
||||
}
|
||||
}
|
||||
|
||||
sessionFinalizeStmt(pStmt, &rc);
|
||||
pSession->rc = rc;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
|
||||
return pSession->rc;
|
||||
}
|
||||
|
||||
@@ -2136,7 +2146,7 @@ static int sessionDiffFindNew(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_stmt *pStmt;
|
||||
rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
|
||||
pDiffCtx->pStmt = pStmt;
|
||||
@@ -2199,7 +2209,7 @@ static int sessionDiffFindModified(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_stmt *pStmt;
|
||||
rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
|
||||
@@ -2894,11 +2904,11 @@ static int sessionSelectStmt(
|
||||
);
|
||||
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
|
||||
}else{
|
||||
#if 0
|
||||
#if 0
|
||||
if( bRowid ){
|
||||
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
for(i=0; i<nCol; i++){
|
||||
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
|
||||
sessionAppendIdent(&cols, azCol[i], &rc);
|
||||
@@ -3702,9 +3712,11 @@ static int sessionChangesetBufferRecord(
|
||||
rc = sessionInputBuffer(pIn, nByte);
|
||||
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
nByte += 8;
|
||||
}else if( eType!=0 && eType!=SQLITE_NULL ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
if( (pIn->iNext+nByte)>pIn->nData ){
|
||||
if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
@@ -4150,7 +4162,13 @@ static int sessionChangesetInvert(
|
||||
|
||||
/* Test for EOF. */
|
||||
if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
|
||||
if( pInput->iNext>=pInput->nData ) break;
|
||||
if( pInput->iNext+1>=pInput->nData ){
|
||||
if( pInput->iNext!=pInput->nData ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto finished_invert;
|
||||
}
|
||||
break;
|
||||
}
|
||||
eType = pInput->aData[pInput->iNext];
|
||||
|
||||
switch( eType ){
|
||||
@@ -4346,6 +4364,7 @@ struct SessionApplyCtx {
|
||||
u8 bRebaseStarted; /* If table header is already in rebase */
|
||||
u8 bRebase; /* True to collect rebase information */
|
||||
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
|
||||
u8 bNoUpdateLoop; /* No update-loop processing */
|
||||
int bRowid;
|
||||
char *zErr; /* Error message, if any */
|
||||
};
|
||||
@@ -4919,7 +4938,7 @@ static int sessionConflictHandler(
|
||||
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
|
||||
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
|
||||
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
|
||||
|| eType==SQLITE_CHANGESET_CONFLICT
|
||||
){
|
||||
@@ -5041,7 +5060,7 @@ static int sessionApplyOneOp(
|
||||
for(i=0; rc==SQLITE_OK && i<nCol; i++){
|
||||
sqlite3_value *pOld = sessionChangesetOld(pIter, i);
|
||||
sqlite3_value *pNew = sessionChangesetNew(pIter, i);
|
||||
if( p->abPK[i] || (bPatchset==0 && pOld) ){
|
||||
if( pOld && (p->abPK[i] || bPatchset==0) ){
|
||||
rc = sessionBindValue(pUp, i*2+2, pOld);
|
||||
}
|
||||
if( rc==SQLITE_OK && pNew ){
|
||||
@@ -5167,7 +5186,264 @@ static int sessionApplyOneWithRetry(
|
||||
}
|
||||
|
||||
/*
|
||||
** Retry the changes accumulated in the pApply->constraints buffer.
|
||||
** Create an iterator to iterate through the retry buffer pRetry.
|
||||
*/
|
||||
static int sessionRetryIterInit(
|
||||
SessionBuffer *pRetry, /* Buffer to iterate through */
|
||||
int bPatchset, /* True for patchset, false for changeset */
|
||||
const char *zTab, /* Table name */
|
||||
SessionApplyCtx *pApply, /* Session apply context */
|
||||
sqlite3_changeset_iter **ppIter /* OUT: New iterator */
|
||||
){
|
||||
sqlite3_changeset_iter *pRet = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
rc = sessionChangesetStart(
|
||||
&pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
|
||||
pRet->bPatchset = bPatchset;
|
||||
pRet->zTab = (char*)zTab;
|
||||
pRet->nCol = pApply->nCol;
|
||||
pRet->abPK = pApply->abPK;
|
||||
sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
|
||||
pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
|
||||
if( rc==SQLITE_OK ){
|
||||
memset(pRet->apValue, 0, nByte);
|
||||
}else{
|
||||
sqlite3changeset_finalize(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*ppIter = pRet;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to apply all the changes in retry buffer pRetry to the database.
|
||||
** Except, if parameter iSkip is greater than or equal to 0, skip change
|
||||
** iSkip.
|
||||
*/
|
||||
static int sessionApplyRetryBuffer(
|
||||
SessionBuffer *pRetry, /* Buffer to apply changes from */
|
||||
int iSkip, /* If >=0, index of change to omit */
|
||||
sqlite3 *db, /* Database handle */
|
||||
int bPatchset, /* True for patchset, false for changeset */
|
||||
const char *zTab, /* Name of table to write to */
|
||||
SessionApplyCtx *pApply, /* Apply context */
|
||||
int(*xConflict)(void*, int, sqlite3_changeset_iter*),
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int rc2 = SQLITE_OK;
|
||||
int ii = 0;
|
||||
sqlite3_changeset_iter *pIter = 0;
|
||||
|
||||
assert( pApply->constraints.nBuf==0 );
|
||||
|
||||
rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
|
||||
|
||||
for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
|
||||
if( ii!=iSkip ){
|
||||
rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
|
||||
}
|
||||
}
|
||||
|
||||
rc2 = sqlite3changeset_finalize(pIter);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if table zTab in the "main" database of db is a WITHOUT ROWID
|
||||
** table.
|
||||
**
|
||||
** If no error occurs, return SQLITE_OK and set output variable (*pbWR) to
|
||||
** true if zTab is a WITHOUT ROWID table, or false otherwise. Or, if an
|
||||
** error does occur, return an SQLite error code. The final value of (*pbWR)
|
||||
** is undefined in this case.
|
||||
*/
|
||||
static int sessionTableIsWithoutRowid(sqlite3 *db, const char *zTab, int *pbWR){
|
||||
sqlite3_stmt *pList = 0;
|
||||
char *zSql = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
zSql = sqlite3_mprintf("PRAGMA table_list = %Q", zTab);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pList, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pList);
|
||||
*pbWR = sqlite3_column_int(pList, 4);
|
||||
rc = sqlite3_finalize(pList);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterator pUp points to an UPDATE change. This function deletes the
|
||||
** affected row from the database and creates an INSERT statement that
|
||||
** may be used to reinsert the row as it is after the UPDATE change
|
||||
** has been applied.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned and output variable (*ppInsert)
|
||||
** is left pointing to a prepared INSERT statement. It is the responsibility
|
||||
** of the caller to eventually free this statement using sqlite3_finalize().
|
||||
** Or, if an error occurs, an SQLite error code is returned and (*ppInsert)
|
||||
** set to NULL. pApply->zErr may be set to an error message in this case.
|
||||
*/
|
||||
static int sessionUpdateToDeleteInsert(
|
||||
sqlite3 *db, /* Database to write to */
|
||||
const char *zTab, /* Table name */
|
||||
SessionApplyCtx *pApply, /* Apply context */
|
||||
sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
|
||||
sqlite3_stmt **ppInsert /* OUT: INSERT statement */
|
||||
){
|
||||
sqlite3_stmt *pRet = 0; /* The INSERT statement */
|
||||
sqlite3_stmt *pSelect = 0; /* SELECT to read current values of row */
|
||||
int rc = SQLITE_OK;
|
||||
int bWR = 0;
|
||||
|
||||
rc = sessionTableIsWithoutRowid(db, zTab, &bWR);
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zSelect = 0;
|
||||
char *zInsert = 0;
|
||||
SessionBuffer cols = {0, 0, 0};
|
||||
SessionBuffer insbind = {0, 0, 0};
|
||||
SessionBuffer pkcols = {0, 0, 0};
|
||||
SessionBuffer selbind = {0, 0, 0};
|
||||
|
||||
const char *zComma = "";
|
||||
const char *zComma2 = "";
|
||||
int ii;
|
||||
for(ii=0; ii<pApply->nCol; ii++){
|
||||
sessionAppendStr(&cols, zComma, &rc);
|
||||
sessionAppendIdent(&cols, pApply->azCol[ii], &rc);
|
||||
sessionAppendStr(&insbind, zComma, &rc);
|
||||
sessionAppendStr(&insbind, "?", &rc);
|
||||
zComma = ", ";
|
||||
|
||||
if( pApply->abPK[ii] ){
|
||||
sessionAppendStr(&pkcols, zComma2, &rc);
|
||||
sessionAppendIdent(&pkcols, pApply->azCol[ii], &rc);
|
||||
sessionAppendStr(&selbind, zComma2, &rc);
|
||||
sessionAppendPrintf(&selbind, &rc, "?%d", ii+1);
|
||||
zComma2 = ", ";
|
||||
}
|
||||
}
|
||||
if( bWR==0 ){
|
||||
sessionAppendStr(&cols, zComma, &rc);
|
||||
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
||||
sessionAppendStr(&insbind, zComma, &rc);
|
||||
sessionAppendStr(&insbind, "?", &rc);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zSelect = sqlite3_mprintf("SELECT %s FROM %Q WHERE (%s) IS (%s)",
|
||||
cols.aBuf, zTab, pkcols.aBuf, selbind.aBuf
|
||||
);
|
||||
if( zSelect==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
zInsert = sqlite3_mprintf("INSERT INTO %Q(%s) VALUES(%s)",
|
||||
zTab, cols.aBuf, insbind.aBuf
|
||||
);
|
||||
if( zInsert==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &pSelect, &pApply->zErr, zSelect);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &pRet, &pApply->zErr, zInsert);
|
||||
}
|
||||
|
||||
sqlite3_free(zSelect);
|
||||
sqlite3_free(zInsert);
|
||||
sqlite3_free(cols.aBuf);
|
||||
sqlite3_free(insbind.aBuf);
|
||||
sqlite3_free(pkcols.aBuf);
|
||||
sqlite3_free(selbind.aBuf);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionBindRow(
|
||||
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pSelect
|
||||
);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
|
||||
int iCol;
|
||||
for(iCol=0; iCol<pApply->nCol; iCol++){
|
||||
sqlite3_value *pVal = pUp->apValue[iCol+pApply->nCol];
|
||||
if( pVal==0 ){
|
||||
pVal = sqlite3_column_value(pSelect, iCol);
|
||||
}
|
||||
rc = sqlite3_bind_value(pRet, iCol+1, pVal);
|
||||
}
|
||||
if( bWR==0 ){
|
||||
sqlite3_bind_int64(pRet, iCol+1, sqlite3_column_int64(pSelect, iCol));
|
||||
}
|
||||
}
|
||||
sessionFinalizeStmt(pSelect, &rc);
|
||||
|
||||
/* Delete the row from the database. */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionBindRow(
|
||||
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pApply->pDelete
|
||||
);
|
||||
sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pApply->pDelete);
|
||||
rc = sqlite3_reset(pApply->pDelete);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_finalize(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
|
||||
*ppInsert = pRet;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Retry the changes accumulated in the pApply->constraints buffer. The
|
||||
** pApply->constraints buffer contains all changes to table zTab that
|
||||
** could not be applied due to SQLITE_CONSTRAINT errors. This function
|
||||
** attempts to apply them as follows:
|
||||
**
|
||||
** 1) It runs through the buffer and attempts to retry each change,
|
||||
** removing any that are successfully applied from the buffer. This
|
||||
** is repeated until no further progress can be made.
|
||||
**
|
||||
** 2) For each UPDATE change in the buffer, try the following in a
|
||||
** savepoint transaction:
|
||||
**
|
||||
** a) DELETE the affected row,
|
||||
** b) Attempt step (1) with remaining changes,
|
||||
** c) Attempt to INSERT a row equivalent to the one that would be
|
||||
** created by applying this UPDATE change.
|
||||
**
|
||||
** If the INSERT in (c) succeeds, the savepoint is committed and all
|
||||
** successfully applied changes are removed from the buffer. Step (2)
|
||||
** is then repeated.
|
||||
**
|
||||
** 3) Once step (2) has been attempted for each UPDATE in the change,
|
||||
** a final attempt is made to apply each remaining change. This time,
|
||||
** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
|
||||
** is invoked and the user has to decide whether to omit the change
|
||||
** or rollback the entire _apply() operation.
|
||||
*/
|
||||
static int sessionRetryConstraints(
|
||||
sqlite3 *db,
|
||||
@@ -5178,41 +5454,101 @@ static int sessionRetryConstraints(
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int iUpdate = 0;
|
||||
|
||||
/* Step (1) */
|
||||
while( pApply->constraints.nBuf ){
|
||||
sqlite3_changeset_iter *pIter2 = 0;
|
||||
SessionBuffer cons = pApply->constraints;
|
||||
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
||||
|
||||
rc = sessionChangesetStart(
|
||||
&pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
|
||||
rc = sessionApplyRetryBuffer(
|
||||
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
|
||||
int rc2;
|
||||
pIter2->bPatchset = bPatchset;
|
||||
pIter2->zTab = (char*)zTab;
|
||||
pIter2->nCol = pApply->nCol;
|
||||
pIter2->abPK = pApply->abPK;
|
||||
sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
|
||||
pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
|
||||
if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
|
||||
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
|
||||
rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
|
||||
}
|
||||
|
||||
rc2 = sqlite3changeset_finalize(pIter2);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
|
||||
|
||||
sqlite3_free(cons.aBuf);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
if( pApply->constraints.nBuf>=cons.nBuf ){
|
||||
/* No progress was made on the last round. */
|
||||
pApply->bDeferConstraints = 0;
|
||||
|
||||
/* If no progress has been made this round, break out of the loop. */
|
||||
if( pApply->constraints.nBuf>=cons.nBuf ) break;
|
||||
}
|
||||
|
||||
/* Step (2) */
|
||||
while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
|
||||
SessionBuffer cons = {0, 0, 0};
|
||||
sqlite3_changeset_iter *pUp = 0;
|
||||
sqlite3_stmt *pInsert = 0;
|
||||
int iSkip = 0;
|
||||
|
||||
rc = sessionRetryIterInit(
|
||||
&pApply->constraints, bPatchset, zTab, pApply, &pUp
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
int iThis = -1;
|
||||
while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
|
||||
if( pUp->op==SQLITE_UPDATE ) iThis++;
|
||||
if( iThis==iUpdate ) break;
|
||||
iSkip++;
|
||||
}
|
||||
if( iThis==iUpdate ){
|
||||
rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionUpdateToDeleteInsert(db, zTab, pApply, pUp, &pInsert);
|
||||
}
|
||||
}
|
||||
sqlite3changeset_finalize(pUp);
|
||||
if( iThis!=iUpdate ) break;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
cons = pApply->constraints;
|
||||
|
||||
while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
|
||||
SessionBuffer app = pApply->constraints;
|
||||
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
||||
rc = sessionApplyRetryBuffer(
|
||||
&app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
|
||||
);
|
||||
if( app.aBuf!=cons.aBuf ){
|
||||
sqlite3_free(app.aBuf);
|
||||
}
|
||||
if( pApply->constraints.nBuf>=app.nBuf ){
|
||||
break;
|
||||
}
|
||||
iSkip = -1;
|
||||
}
|
||||
}
|
||||
|
||||
iUpdate++;
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
rc = sqlite3_finalize(pInsert);
|
||||
if( rc==SQLITE_CONSTRAINT ){
|
||||
rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
|
||||
sqlite3_free(pApply->constraints.aBuf);
|
||||
pApply->constraints = cons;
|
||||
memset(&cons, 0, sizeof(cons));
|
||||
}else if( rc==SQLITE_OK ){
|
||||
iUpdate = 0;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
|
||||
}
|
||||
}else{
|
||||
sqlite3_finalize(pInsert);
|
||||
}
|
||||
|
||||
sqlite3_free(cons.aBuf);
|
||||
}
|
||||
|
||||
/* Step (3) */
|
||||
if( rc==SQLITE_OK && pApply->constraints.nBuf ){
|
||||
SessionBuffer cons = pApply->constraints;
|
||||
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
||||
pApply->bDeferConstraints = 0;
|
||||
rc = sessionApplyRetryBuffer(
|
||||
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
|
||||
);
|
||||
sqlite3_free(cons.aBuf);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -5266,6 +5602,7 @@ static int sessionChangesetApply(
|
||||
sApply.bRebase = (ppRebase && pnRebase);
|
||||
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
|
||||
sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
|
||||
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
|
||||
}
|
||||
@@ -7077,7 +7414,7 @@ int sqlite3changegroup_change_blob(
|
||||
const void *pVal,
|
||||
int nVal
|
||||
){
|
||||
sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + nVal;
|
||||
sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + (i64)nVal;
|
||||
int rc = SQLITE_OK;
|
||||
SessionBuffer *pBuf = 0;
|
||||
|
||||
|
||||
@@ -1366,11 +1366,23 @@ int sqlite3changeset_apply_v3(
|
||||
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
||||
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
||||
** or SET DEFAULT.
|
||||
**
|
||||
** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
|
||||
** Sometimes, a changeset contains two or more update statements such that
|
||||
** although after applying all updates the database will contain no
|
||||
** constraint violations, no single update can be applied before the others.
|
||||
** The simplest example of this is a pair of UPDATEs that have "swapped"
|
||||
** two column values with a UNIQUE constraint.
|
||||
** <p>
|
||||
** Usually, sqlite3changeset_apply() and similar functions work hard to try
|
||||
** to find a way to apply such a changeset. However, if this flag is set,
|
||||
** then all such updates are considered CONSTRAINT conflicts.
|
||||
*/
|
||||
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
||||
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
||||
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
||||
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
||||
#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||
|
||||
@@ -914,6 +914,9 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
}
|
||||
else if( n>2 && n<=11 && 0==sqlite3_strnicmp("-ignorenoop", z1, n) ){
|
||||
flags |= SQLITE_CHANGESETAPPLY_IGNORENOOP;
|
||||
}
|
||||
else if( n>3 && n<=13 && 0==sqlite3_strnicmp("-noupdateloop", z1, n) ){
|
||||
flags |= SQLITE_CHANGESETAPPLY_NOUPDATELOOP;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
@@ -1095,7 +1098,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_invert(
|
||||
memset(&sIn, 0, sizeof(sIn));
|
||||
memset(&sOut, 0, sizeof(sOut));
|
||||
sIn.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
|
||||
sIn.aData = Tcl_GetByteArrayFromObj(objv[1], &nn);
|
||||
sIn.aData = testGetByteArrayFromObj(objv[1], &nn);
|
||||
sIn.nData = (int)nn;
|
||||
|
||||
if( sIn.nStream ){
|
||||
@@ -1112,6 +1115,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_invert(
|
||||
Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n));
|
||||
}
|
||||
sqlite3_free(sOut.p);
|
||||
free(sIn.aData);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,20 +1099,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return promiseResolve_(sqlite3);
|
||||
};
|
||||
const options = opfsUtil.options;
|
||||
let proxyUri = options.proxyUri +(
|
||||
//#if not target:es6-bundler-friendly
|
||||
const proxyUri = options.proxyUri +(
|
||||
(options.proxyUri.indexOf('?')<0) ? '?' : '&'
|
||||
)+'vfs='+vfsName;
|
||||
//sqlite3.config.error("proxyUri",options.proxyUri, (new Error()));
|
||||
//#/if
|
||||
const W = opfsVfs.worker =
|
||||
//#if target:es6-bundler-friendly
|
||||
(()=>{
|
||||
/* _Sigh_... */
|
||||
switch(vfsName){
|
||||
case 'opfs':
|
||||
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs", import.meta.url));
|
||||
case 'opfs-wl':
|
||||
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs-wl", import.meta.url));
|
||||
}
|
||||
/* Discussion explaining this formulation:
|
||||
https://github.com/sqlite/sqlite-wasm/pull/159 */
|
||||
const url = new URL('sqlite3-opfs-async-proxy.js', import.meta.url);
|
||||
url.searchParams.set('vfs', vfsName);
|
||||
return new Worker(url.toString());
|
||||
})();
|
||||
//#elif target:es6-module
|
||||
new Worker(new URL(proxyUri, import.meta.url));
|
||||
|
||||
@@ -1559,18 +1559,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
only argument. On success, returns the result of the
|
||||
callback. Throws on error.
|
||||
|
||||
Note that transactions may not be nested, so this will throw if
|
||||
it is called recursively. For nested transactions, use the
|
||||
Transactions may not be nested, so this will throw if it is
|
||||
called recursively. For nested transactions, use the
|
||||
savepoint() method or manually manage SAVEPOINTs using exec().
|
||||
|
||||
If called with 2 arguments, the first must be a keyword which
|
||||
is legal immediately after a BEGIN statement, e.g. one of
|
||||
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE". Though the exact list
|
||||
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE", though the exact list
|
||||
of supported keywords is not hard-coded here, in order to be
|
||||
future-compatible, if the argument does not look like a single
|
||||
keyword then an exception is triggered with a description of
|
||||
the problem.
|
||||
*/
|
||||
*/
|
||||
transaction: function(/* [beginQualifier,] */callback){
|
||||
let opener = 'BEGIN';
|
||||
if(arguments.length>1){
|
||||
|
||||
@@ -1949,8 +1949,6 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
}/*changeset/preupdate additions*/
|
||||
|
||||
/**
|
||||
EXPERIMENTAL. For tentative addition in 3.53.0.
|
||||
|
||||
sqlite3_js_retry_busy(maxTimes,callback[,beforeRetry])
|
||||
|
||||
Calls the given _synchronous_ callback function. If that function
|
||||
@@ -1971,11 +1969,14 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
(so it starts with 2, not 1). If it throws, the exception is
|
||||
handled as described above. Its result value is ignored.
|
||||
|
||||
To effectively retry "forever", pass a negative maxTimes value,
|
||||
with the caveat that there is no recovery from that unless the
|
||||
beforeRetry() can figure out when to throw.
|
||||
To effectively retry "forever", pass a huge maxTimes value such
|
||||
as Number.MAX_SAFE_INTEGER, with the caveat that there is no
|
||||
recovery from that unless the beforeRetry() can figure out when
|
||||
to throw.
|
||||
|
||||
TODO: an async variant of this.
|
||||
Added in 3.53.0.
|
||||
|
||||
TODO?: an async variant of this.
|
||||
*/
|
||||
capi.sqlite3_js_retry_busy = function(maxTimes, callback, beforeRetry){
|
||||
for(let n = 1; n <= maxTimes; ++n){
|
||||
|
||||
@@ -1021,11 +1021,15 @@ static void mk_fiddle(void){
|
||||
pf("\t@$(call b.call.wasm-strip,%s)\n", zBuildName);
|
||||
pf("\t@$(call b.strip-js-emcc-bindings,$(logtag.%s))\n",
|
||||
zBuildName);
|
||||
pf("\t@$(call b.cp,%s,$(dir.dout)/sqlite3-opfs-async-proxy.js,"
|
||||
"$(dir $@)"
|
||||
")\n", zBuildName);
|
||||
if( isDebug ){
|
||||
pf("\t@$(call b.cp,%s,"
|
||||
"$(dir.fiddle)/index.html "
|
||||
"$(dir.fiddle)/fiddle.js "
|
||||
"$(dir.fiddle)/fiddle-worker.js,"
|
||||
"$(dir.fiddle)/fiddle-worker.js "
|
||||
"$(dir.fiddle)/sqlite3-opfs-async-proxy.js,"
|
||||
"$(dir $@)"
|
||||
")\n",
|
||||
zBuildName);
|
||||
|
||||
@@ -386,7 +386,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
|
||||
This function initializes the db described by ctorOptFunc(...),
|
||||
writes some secret info into it, and re-opens it twice to
|
||||
confirmi that it can be read with an SEE key and cannot be read
|
||||
confirm that it can be read with an SEE key and cannot be read
|
||||
without one.
|
||||
*/
|
||||
T.seeBaseCheck = function(ctor, ctorOptFunc, dbUnlink){
|
||||
@@ -3940,7 +3940,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
//#/query
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
T.g('OPFS SyncAccessHandle Pool VFS',
|
||||
(sqlite3)=>(!!sqlite3.installOpfsSAHPoolVfs || "requires OPFS SAH Pool APIs"))
|
||||
(sqlite3)=>(isWorker() && !!sqlite3.installOpfsSAHPoolVfs || "requires OPFS SAH Pool APIs"))
|
||||
.t({
|
||||
name: 'SAH sanity checks',
|
||||
test: async function(sqlite3){
|
||||
|
||||
@@ -1678,7 +1678,8 @@ tclsqlite3.c: sqlite3.c tclsqlite-ex.c
|
||||
#
|
||||
# $(CFLAGS.tclextension) = CFLAGS for the tclextension* targets.
|
||||
#
|
||||
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS)
|
||||
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) \
|
||||
$(OPT_FEATURE_FLAGS) $(OPTS) $(CFLAGS.icu)
|
||||
#
|
||||
# Build the SQLite TCL extension in a way that make it compatible
|
||||
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
|
||||
@@ -1686,7 +1687,8 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
|
||||
#
|
||||
tclextension: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
|
||||
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
|
||||
|
||||
#
|
||||
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
|
||||
@@ -1694,7 +1696,8 @@ tclextension: tclsqlite3.c
|
||||
#
|
||||
tclextension-install: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
|
||||
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
|
||||
|
||||
#
|
||||
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
|
||||
@@ -2232,11 +2235,6 @@ install: install-man1
|
||||
install-pc: sqlite3.pc $(install-dir.pkgconfig)
|
||||
$(INSTALL.noexec) sqlite3.pc "$(install-dir.pkgconfig)"
|
||||
|
||||
scrub$(T.exe): $(TOP)/ext/misc/scrub.c sqlite3.o
|
||||
$(T.link) -o $@ -I. -DSCRUB_STANDALONE \
|
||||
$(TOP)/ext/misc/scrub.c sqlite3.o $(LDFLAGS.libsqlite3)
|
||||
xbin: scrub$(T.exe)
|
||||
|
||||
srcck1$(B.exe): $(TOP)/tool/srcck1.c
|
||||
$(B.cc) -o srcck1$(B.exe) $(TOP)/tool/srcck1.c
|
||||
xbin: srcck1$(B.exe)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
C Version\s3.53.0
|
||||
D 2026-04-09T11:41:38.498
|
||||
C Version\s3.53.2
|
||||
D 2026-06-03T19:12:13.350
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
|
||||
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 92391304cf70f4c178b127aa83b88637abd28d1b83ede451616144037ea1d3dd
|
||||
F Makefile.msc 1d6098faf066e14bc181f9460b002285248eee32cfaaa7babcb37f4381928408
|
||||
F README.md f49fbd826941842e348242f3ab62f240c985ceafdf8fbe576abf4eb75317468c
|
||||
F VERSION 31435e19ded2aae3c1c67dacf06a995a37fd1b253baec5899b78d64cd29db4f7
|
||||
F VERSION 7441adea0de9103e8e0541375ba322afed1a5d614a39bffcdbda09b69619bba7
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -47,7 +47,7 @@ F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1
|
||||
F autosetup/jimsh0.c 916bbdf8023fbda9937afae57d81a853d8c2ea00f2320aa27becbc33574f963d
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl ce301197f364f7ce2acabbbd84b43d19e917ec73653157ca134a06f32d322712
|
||||
F autosetup/sqlite-config.tcl 8fecce2838b7e7d990d161d08998034f3e3b0b2ddf4d7a99dbfafba9c902e302
|
||||
F autosetup/sqlite-config.tcl 7ff8dad28d6ea2ad95f0288c61274042e6594145511b58ec4d42daacbee15f0d
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
|
||||
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
|
||||
@@ -79,16 +79,16 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
|
||||
F ext/fts3/README.syntax b72477722e9b4fe43f8403227d790a1c94221bfad15c27863a4b36d1052e892b
|
||||
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 6cc7bbc307f27e7b6ee2e1d5ff63ffff4df3b42529dfe00eb34ddded417961b3
|
||||
F ext/fts3/fts3.c 1716994c40715223431d98e5132c40a3c1a00c011c5bde2270bad1bd06be3ccd
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 277f32f304e82f4397fc2a74793c0a95318b7abb9670b519e4805a00946cbd9b
|
||||
F ext/fts3/fts3_aux.c 37ba1b10bbd163ddc6b05dbc3a306a0d5d68aee3d30f33b4dc5794955cc50887
|
||||
F ext/fts3/fts3_expr.c 5c13796638d8192c388777166075cdc8bc4b6712024cd5b72c31acdbefce5984
|
||||
F ext/fts3/fts3_aux.c bbb614abcc995bf748cba4717e9fd8de67898e33c80f60379f6feb2358189b4b
|
||||
F ext/fts3/fts3_expr.c 907dd64deb881c0586d5ecbabc96cfebdbe2ff9e7a052d379fd3b606edfa21ea
|
||||
F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
|
||||
F ext/fts3/fts3_porter.c 024417020c57dd1ab39816f5fe6cf45222a857b78a1f6412f040ada1ceabd4ff
|
||||
F ext/fts3/fts3_snippet.c abe3b2998e7cb6d1ab6019f87f021758a0df3ee4010fe144a174a524cff96fe6
|
||||
F ext/fts3/fts3_snippet.c 65e178107b59ad4724a11339a645f2e3789f3cf59b2f4e29c90efd864e53c5b4
|
||||
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
|
||||
F ext/fts3/fts3_test.c cc329471e573f95a6ea9fbca87e89dcfa1d355591c80172ffcd759ac521d25d8
|
||||
F ext/fts3/fts3_tokenize_vtab.c 66eba6c2baa04b2b15e80d68341b8fd0b4d3831f6b2edb33916a2906ff2d4389
|
||||
@@ -113,13 +113,13 @@ F ext/fts5/fts5_buffer.c dcc3f0352339fe79c9d8abbc1c2009bc3469206467880bf43558447
|
||||
F ext/fts5/fts5_config.c bfba970fe1e4eed18ee57c8d51458e226db9a960ddf775c5e50e3d76603a667e
|
||||
F ext/fts5/fts5_expr.c 71d48e8cf0358deace4949276647d317ff7665db6db09f40b81e2e7fe6664c7c
|
||||
F ext/fts5/fts5_hash.c d5871df92ce3fa210a650cf419ee916b87c29977e86084d06612edf772bff6f5
|
||||
F ext/fts5/fts5_index.c f8cfa37bb7397e5ede20242e4c9cb030bc8b4584ce3f23a5e2495038c0ae64bd
|
||||
F ext/fts5/fts5_index.c 1627d9c184dec6be913647ba1e31a906e825b8460c9575e1c367ee27fe847f0c
|
||||
F ext/fts5/fts5_main.c b0fed47b3b4420ba6810373480a75bc28a9c0b7d16478d19a396436fb3ff17d7
|
||||
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
|
||||
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
|
||||
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
|
||||
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
|
||||
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
|
||||
F ext/fts5/fts5_tokenize.c 21078ea9f496ba9b0c4dd15ac2404933251df8bebab9907f6a5a47d4321c77fd
|
||||
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
|
||||
@@ -162,13 +162,14 @@ F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b
|
||||
F ext/fts5/test/fts5contentless5.test 38cd0392c730dc7090c550321ce3c24ba4c392bc97308b51a4180e9959dca7b5
|
||||
F ext/fts5/test/fts5corrupt.test 237fce1c3261bb3a5bec333b0f0dbf5b105ec32627ef14cccbda3cfe13833193
|
||||
F ext/fts5/test/fts5corrupt2.test 4a03a158c2cb617c9f76d26b35c1ef2534124bc0bbddcea38dfd5b170ebea27b
|
||||
F ext/fts5/test/fts5corrupt3.test e489b51b6c4ded2a808e0f78bdbe126f6d369de41a59ac2717878e37fc3db0e8
|
||||
F ext/fts5/test/fts5corrupt3.test 121a8a7622dfe1be1bc55cbe70eddd6a3416f76a837dc8c06a11a32e781595a4
|
||||
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
|
||||
F ext/fts5/test/fts5corrupt5.test 73985d4fe6d8f0d5d5c7bcf79ae7c6522c376cd6ad710a0ff2f26e0c2e222abe
|
||||
F ext/fts5/test/fts5corrupt5.test b9085599389721b38f080f501660c931cd608f8ecbc93c23644344f74ef7aa21
|
||||
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
|
||||
F ext/fts5/test/fts5corrupt7.test 814aab492d7a09abb5bfdd81cc66fc206d7f3868f9a3bae91876e02efc466fb3
|
||||
F ext/fts5/test/fts5corrupt7.test 9664c15360e8b649ad76f457a0bbf5a7271b8eff1a8ee141ea039bc63240c934
|
||||
F ext/fts5/test/fts5corrupt8.test 0b10750caf8aa23fa1c379ca4caf6130d41454505e4d5315590f4061eedcbe44
|
||||
F ext/fts5/test/fts5corrupt9.test 4253b9b59f33effac8b67da72ec34309c738aca2d5e8e2656bfbbd6a489a1dfe
|
||||
F ext/fts5/test/fts5corruptA.test 7b31551444569420903d34ae50a55a1227d16969264f0b50de2dc812bc0b3414
|
||||
F ext/fts5/test/fts5corruptbig.test 9f95b40fa36e292feceab02b2ef06e21878bfa1ac7afefa138aae05518b51774
|
||||
F ext/fts5/test/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
|
||||
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
|
||||
@@ -253,7 +254,7 @@ F ext/fts5/test/fts5synonym2.test 58f357b997cf2fedeeb9d0de4db9f880fa96fa2fe27a74
|
||||
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
F ext/fts5/test/fts5tokendata.test 7cad79af82e8e81b7a36b450087233d2fca051bb0d584421afc375d6dd26d6f6
|
||||
F ext/fts5/test/fts5tokenizer.test 7937cec672b148223fff8746d21d3e7ed0965fd7caf35ccdc888a005bb452f98
|
||||
F ext/fts5/test/fts5tokenizer.test 738e9c3e1b338028e202d0fcd33aa39f1bd3f8444d14f9a408e8a617b1361d3f
|
||||
F ext/fts5/test/fts5tokenizer2.test ddb8b10fbe4b84b2a75812671f127774c1d2e3e2bf82d2e0e4f0bb1cd8a2b2d6
|
||||
F ext/fts5/test/fts5tokenizer3.test eea778f7bb7024c3e904e28915f9d53286141671b138722148be22a9c758bdc3
|
||||
F ext/fts5/test/fts5trigram.test a55fde7065ae69a0f82c5a7a5bf5286a97de11ae4bff6537fd3e27ca9a01416f
|
||||
@@ -278,7 +279,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
F ext/fts5/tool/mkfts5c.tcl 135b9e160f8e10211c10c5873d5e8c3eaebd3da9ec56a12ae4db157d4738ffe4
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt 1f8d76e10d2385fc77914a14ccd99acfbaf68111dfcf26a360ad9063787f57fb
|
||||
F ext/icu/icu.c 9837f4611915baad1edbe38222f3ee7d1b5e118ab16fec9ba603720f72c78b2a
|
||||
F ext/icu/icu.c 535d0d61f109e760a56e1afc450414ebfb0e2d594e2233b30315b815e3433ac2
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/intck/intck1.test 53d885075abeb45aeb1eeffeaa8560b329060835ade4af5c44cf5fcb581c1e63
|
||||
F ext/intck/intck2.test a29343a8e65c5c3400e10747f394924f3df95a5b2de94f46e9b5c9b97f5e7339
|
||||
@@ -368,7 +369,7 @@ F ext/misc/btreeinfo.c 13bc9e9f1c13cde370d0e4a6a2683e9f1926a4cead7fb72c71871b11a
|
||||
F ext/misc/cksumvfs.c 9d7d0cf1a8893ac5d48922bfe9f3f217b4a61a6265f559263a02bb2001259913
|
||||
F ext/misc/closure.c c983987a8d7846c3e52b1885ed3e20af7d4ca52a81a8f94ec6d1cd68f93acc86
|
||||
F ext/misc/completion.c 3f5db28e88c3313103b2dd86d910a2944fd500c46754e473493968ce81e994a4
|
||||
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
|
||||
F ext/misc/compress.c 5cc142aa82d1589a31c384657d0418c0eb0871348a2201e5dca32d24a0dd6654
|
||||
F ext/misc/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
|
||||
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
|
||||
F ext/misc/decimal.c 23698283d9365ce66d54b5bb97c01e69b4aa7ac804f226f9117a0d42efd15a65
|
||||
@@ -385,19 +386,18 @@ F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58
|
||||
F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5a0
|
||||
F ext/misc/normalize.c fbb144a861809686ff2b5b6eee8bb2e1207f9bf13ce7376e5273c700a1eafbd5
|
||||
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
|
||||
F ext/misc/percentile.c 72e05a21db20a2fa85264b99515941f00ae698824c9db82d7edfbb16cea8ec80
|
||||
F ext/misc/prefixes.c aa15fd268e7d1336d1a1d4bc79265860d1d2ad68bba4cbcab61f83e4989dc68c
|
||||
F ext/misc/percentile.c b6b9c740f0dc42838efd776eec0f68a93bc5ac86524c71337a70950860bf6c4d
|
||||
F ext/misc/prefixes.c e7d3e7a39174db412c5f77c266fa221c2dc3cb2621a9422835a607ad08805eb2
|
||||
F ext/misc/qpvtab.c 470a5fffba005c8e1994209e59c1848122351e19522de71beb68d666c4fa39a5
|
||||
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
|
||||
F ext/misc/regexp.c 9dada9e9aa91f0cc23e35429e5d1111f110cc201b4c8dcc49aa6d2fc4b2a865d
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c df54e202887e480bf9cd73168c9ac829e3b0211381b68b9809e0cb5bc1bdc2cf
|
||||
F ext/misc/series.c 9454c7ef27d3729432496f31caabc892aeee1c21377d403f681126d93c09d6e9
|
||||
F ext/misc/series.c 496f43bac9bad2ee2cea63fb5212036f30ad3003b4cd317d5c2d6f3ad7c7d264
|
||||
F ext/misc/sha1.c 8bf60344c11a525384c2efd1ae77f160b06be336db679effaadf292d4b41451c
|
||||
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 693c8fd3293087fa821322967a97e59dfa24051e5d2ca7fa85790a4034db6fa4
|
||||
F ext/misc/spellfix.c e9e951f9712b6c302e4ee84f5db5a7b18daab87aa229867c66f34684d2dfbb40
|
||||
F ext/misc/sqlar.c 97c100b010159c08a7a9acd8eb1ea510a5522e64741aaafcd7b6c629de682edc
|
||||
F ext/misc/sqlite3_stdio.c b43a0f530c6f0fb3d41d9af8c0b40f3f71198a1db55ab8ffffbef5c8cc329d22
|
||||
F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bfa08ab1ce99f
|
||||
@@ -417,11 +417,11 @@ F ext/misc/vtablog.c 6c0c11c4822ab6c1a205718ea7c6d1bb561d96b27104b9c1fe84d01aa62
|
||||
F ext/misc/vtshim.c f5ab480d1e33fa46a0b138359bedc9979e32798d72348e04bbe6093f9ae95c7b
|
||||
F ext/misc/wholenumber.c aa5e6d786fe8d79bc100ea0e852249c026a91ae65a5c1bcb2b869cd1a7cdd6d5
|
||||
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
|
||||
F ext/misc/zipfile.c 5a583b5e72b4d777dc9f845529e6bd185d58024b633aafc93588679c78719700
|
||||
F ext/misc/zipfile.c 58d535e6f177709c3f3607e19aa8e1b4c3c57c1f2c78bd4cdfac15e0b2f53e5a
|
||||
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
|
||||
F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
|
||||
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
|
||||
F ext/qrf/qrf.c 9bef1f01e0c33a8693a9a7c1b666b8dee1aa60b8bc880d562eb4dfff551a6009
|
||||
F ext/qrf/qrf.c b82987a8b9bc24710e44e5f0120ee6be8d55f270688f0ddad2baa331d20ba7a5
|
||||
F ext/qrf/qrf.h fbb223ff5789b324b3e9c22e787e4c1f53e217cff7cc5a243164d4b2e8410f4b
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
|
||||
@@ -486,12 +486,12 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
|
||||
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
|
||||
F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
|
||||
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
|
||||
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
|
||||
F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f8cc843b2e20217e
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
|
||||
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
|
||||
F ext/rtree/geopoly.c bd1971479184d559499ff3087c37f2823977d7b0ec80916141ae66f70345c88d
|
||||
F ext/rtree/rtree.c 44abdd5df278ca1901daf29c82cce6785f0ee82ce59e28160ee988c17a9a185b
|
||||
F ext/rtree/geopoly.c 77bad24162b6ae84a2fd6de3f1f8ad0b255a4ceb572f50f8771d1ac9d4d986d8
|
||||
F ext/rtree/rtree.c e350bb1c7adefab45cd4ce77e11393c7f3a9ee21c27345a684b6e1c04fae1a12
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
@@ -502,7 +502,7 @@ F ext/rtree/rtree6.test 2f5ffc69670395c1a84fad7924e2d49e82a25460c5293fb1e54e1aa9
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 4da84c7f328bbdca15052fa13da6e8b8d426433347bf75fc85574c2f5a411a02
|
||||
F ext/rtree/rtree9.test fd3c9384ef8aabbc127b3878764070398f136eebc551cd20484b570f2cc1956a
|
||||
F ext/rtree/rtreeA.test 14e67fccc5b41efbad7ea99d21d11aaa66d2067da7d5b296ee86e4de64391d82
|
||||
F ext/rtree/rtreeA.test c90dd34792aeb7e15909530b5e0e91a8ad69f4d4b7bb52c14c4ef5c60050cace
|
||||
F ext/rtree/rtreeB.test ab93136c45cf25af78d22665c2a6d75068eef6bf3a710356e4ba8d5f37bed364
|
||||
F ext/rtree/rtreeC.test 2978b194d09b13e106bdb0e1c5b408b9d42eb338c1082bf43c87ef43bd626147
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
@@ -537,14 +537,14 @@ F ext/session/session4.test ad0ddaaddb9a99dac433d83fc6674aae2af072b8f57e63a6b3f2
|
||||
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
|
||||
F ext/session/session6.test 35279f2ec45448cd2e24a61688219dc6cf7871757716063acf4a8b5455e1e926
|
||||
F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605e6607ee29904
|
||||
F ext/session/session9.test 0c4a8fbe7a5031f50855f020f3408e1f07fd7859f1daa1629eadcec3422072d6
|
||||
F ext/session/session9.test ce2b898aa4caf0e492b57c29cb707224e0a33479e4f019785a81828273143ba5
|
||||
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
|
||||
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
|
||||
F ext/session/sessionC.test 2bd42225efdf5f5b1a20f75b672665bcd4f67e2a6d7ddf7420fe7bf523ba41f8
|
||||
F ext/session/sessionC.test de98b5e173fd86c79af0d0541534398d2ea75dc0d5d74a00103eb26151b76959
|
||||
F ext/session/sessionD.test 470ff917dc849e2eb78142ade63aaabd729d773833cff0ff01bca0eda68a21ce
|
||||
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
|
||||
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
|
||||
F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d085eb8efdad0a
|
||||
F ext/session/sessionG.test 64c2b69531aebdb36d5977a5f832d77e4c8bda0c746a6c630adf23660bb1c7c2
|
||||
F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859
|
||||
F ext/session/sessionI.test 11e7b6729fc942982a5104a40132f70a2e964d64d60dc5809b8206465af74822
|
||||
F ext/session/session_common.tcl a31f537a929a695a852d241c9434f2847cadf329856401921139fbb03a5a7697
|
||||
@@ -557,13 +557,14 @@ F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194
|
||||
F ext/session/sessionchange.test 6618cb1c1338a4b6df173b6ac42d09623fb71269962abf23ebb7617fe9f45a50
|
||||
F ext/session/sessionchange2.test 6b5b7e3d1cc4ede43817f7fb68e3771aac4aa6500adb21a458b3e5a9fd841f83
|
||||
F ext/session/sessionconflict.test 19e4a53795c4c930bfec49e809311e09b2a9e202d9446e56d7a8b139046a0c07 x
|
||||
F ext/session/sessionconflict2.test d7f4caf59360dbca8a4698b9a3a322adf6f547f810ad41d131cacb730e02dd5e x
|
||||
F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
|
||||
F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
|
||||
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
|
||||
F ext/session/sessionfault3.test 9397819ec25b0960c5bc03c78613f9cb5cacc970f83e817aec1775c2a839a787
|
||||
F ext/session/sessioninvert.test 9018f6a7387ac745084b6374c5e1aa14d648b372e6e1181cfab3df632b662d26 x
|
||||
F ext/session/sessionfault3.test aea5331fa6dbe5ca4e19826605e624c0e1767545411479f27c5ef82b41046925
|
||||
F ext/session/sessioninvert.test 7ccb7609a2c11e4e13e606df439bf3d484ba8e455d0bd3aa8d4828a940e1a242 x
|
||||
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
|
||||
F ext/session/sessionnoact.test 4c7ae5c7d351cb5323bca62b6b095592ad24bd90a6713c178b62ab0063d23e19
|
||||
F ext/session/sessionnoact.test 2cf060c12a7a23e663f0ec796561e58638c5c10a846653d37be886414b06ddc9
|
||||
F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
|
||||
F ext/session/sessionnoop2.test 2d8146321785bdc7cee8966d984560184cfca83fd46da2ff81ea883d6e977b36
|
||||
F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2
|
||||
@@ -571,9 +572,9 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
|
||||
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
|
||||
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c d5c91d5b07d2b8e860f2782ae23f7b44ce929280e00645418ee84a0fd14525b2
|
||||
F ext/session/sqlite3session.h 063e7bf7be2fff874456f452a224b5b3013b25682d108933b0351c93a1279b9c
|
||||
F ext/session/test_session.c 2a02a68b522e2f3d4a64b2a4733af54b0f3e500769aeccd5bcbdd440103db069
|
||||
F ext/session/sqlite3session.c 1010718d9d88eeb1efd1bf3d6bcbc85e598e9d5bb094c2d202515622d2233481
|
||||
F ext/session/sqlite3session.h ca7c4422c1514a95056cc8d333217df6b1829d39058126b1de85d10cd62d7a9c
|
||||
F ext/session/test_session.c 95fbf8fc721fdb1a0d00268f930d6763c5299ed766b317f9dd3cf9ca5262e337
|
||||
F ext/wasm/GNUmakefile 68c750f173106d9d63f12c1edf1256c6f4bad9894b155da5db64322f4912de4b
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
|
||||
@@ -587,13 +588,13 @@ F ext/wasm/api/README.md a905d5c6bfc3e2df875bd391d6d6b7b48d41b43bdee02ad115b4724
|
||||
F ext/wasm/api/extern-post-js.c-pp.js 80accc53cc6ea1e61c721595f42ba95baa7c7ea636807d9507e69403301f8c54
|
||||
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
|
||||
F ext/wasm/api/opfs-common-inline.c-pp.js 496ca858af09b7fef2efaece467960611d35f57254078424bcdeac42ded9e85d
|
||||
F ext/wasm/api/opfs-common-shared.c-pp.js d0bff21d34fa05a7eb975c4ee608165f96387332101cb05e976953c77434374d
|
||||
F ext/wasm/api/opfs-common-shared.c-pp.js 5b5880ced26977931a4fb33aafc6c71206fbee519e82abf9614898d8fa5ec241
|
||||
F ext/wasm/api/post-js-footer.js a50c1a2c4d008aede7b2aa1f18891a7ee71437c2f415b8aeb3db237ddce2935b
|
||||
F ext/wasm/api/post-js-header.js f35d2dcf1ab7f22a93d565f8e0b622a2934fc4e743edf3b708e4dd8140eeff55
|
||||
F ext/wasm/api/pre-js.c-pp.js d6bf82f83f60caa2904bddb95a29cb738b310f672d2796cdc5fe54463ab0d6cd
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js 31a721ada7225838a61310a9f3f797fa5275353f8e9b0ae769d85b437be061f5
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 5f203f5bb5d48a9e43ec51e791dc411c24dca825842bfb6a2d979d871bf8cfaf
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 4336f02ac24ba58e68e355adb9da2804a1eef15a4aee961fa813c7d812a56b54
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 35e4727010f15fd72ead0dd1eb4e3c2c9bb1cc60e51544cbdff1f7c14f209de2
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 29ca376ff5d5f189714cf10b2b93b136e91b06ec8616579b53b2af9dfb4796bf
|
||||
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1fa34e9b0e3b90a8898e4f700d7125e44c81877f182627bb8564b97989bc6e78
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 98d90255a12d02214db634e041c8e7f2f133d9361a8ebf000ba9c9af4c6761cc
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.c-pp.js 25e31482b04293a33d7599f1459eb552b3eb36ca10c02c816122d3308bf80cb2
|
||||
@@ -630,7 +631,7 @@ F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
|
||||
F ext/wasm/libcmpp.c 0e2cec7de7c9cbe7941e6a4dc0c123cec736578a3eeae7828ac18706acd3cea6
|
||||
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
|
||||
F ext/wasm/mkwasmbuilds.c d4479af2774a43104b819d9286961b7c09793ca39440e20191e693ceff21f911
|
||||
F ext/wasm/mkwasmbuilds.c 60706fb66db7f1e24d876e3cb2493484cfb27e7b103c7741c384505dd678769c
|
||||
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@@ -646,7 +647,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.c-pp.html 7171022e7f4da8f46e5f50ea81dd6ce840b9235c47653a5deeb3764ccc2fe472
|
||||
F ext/wasm/tester1.c-pp.html bd927ccf51ddd65e924660a0487add99e1b044afe03950e49d87ccf44efdddb6
|
||||
F ext/wasm/tester1.c-pp.js 581be6f3228351bc77512ba743912d1ad52f40dde1fef1a943fd568b0cfc51b1
|
||||
F ext/wasm/tester1.c-pp.js 54ce4a08d3752cb52cf60926d7da47a21ae63d620f90679770dd9c04002722b4
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 706eab6308343c04ac2360aba6001af4ffaf46d8f33a0ccd02c64d93e3216a43
|
||||
F ext/wasm/tests/opfs/concurrency/test.js 6919778fceaac1b7cc78caf41d796f545d2c4433b31188aa9689f05b5ad28828
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 704d82c5e287e47f612349e027765943a58ad967dcf178fb5a1c3a8eaafb09af
|
||||
@@ -656,7 +657,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk bf77c630aeef4ed4b9270e1fd52c35147b529412c00b74ed6eb8aca3466763f6
|
||||
F main.mk 582cb3ab67cb5b8887c087265e700f7a132dace4316e1656419e8e4c049ba683
|
||||
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -667,14 +668,14 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
|
||||
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
|
||||
F src/alter.c fc36b19273ffe364aeb4d00ba04bda8798ad7a67fec7a035ee8ee56272e1bdbe
|
||||
F src/alter.c d7cbe4332a7a2c3a21ab58ee2609efade493f6ae78254613ada0759898629ee3
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/attach.c 7cf07d4fa42b9fc8662237c60c40b730326c30aa90ae5fffc0b18b2d726ebf61
|
||||
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
|
||||
F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c fb350c445316c1cc0529703c0b76450770a1de0ab0440641a56b19f05d6fefbe
|
||||
F src/btree.c 377b98fbe170ae38298a3fcea5355ec88404f63238f80741992cda765ac91aeb
|
||||
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 8581de0af3b6c448f5d64e2d18a91ac1e7057b3bcb8b8827e1240f80d87486a4
|
||||
@@ -682,20 +683,20 @@ F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804a
|
||||
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
|
||||
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
|
||||
F src/dbpage.c 98c716bc5c0c70af4e7934bfcddd707f14e78b5d4cf1e0602a07b485e1af2e74
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
|
||||
F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930
|
||||
F src/expr.c 8a458928fe502526d4ce90fa4e084a6e1a4dceb6da747381973b5b0086b1492c
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
|
||||
F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7
|
||||
F src/func.c 6f6abe78831fba92ebb5c3d347273f37656ae357f5902e1fb48aa297d57fbcc6
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
|
||||
F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
|
||||
F src/json.c 82b685636c9ff9d677734682e170f637fbfef3a14febf8cb274c4b7e7a272dcc
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
|
||||
F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
|
||||
@@ -705,7 +706,7 @@ F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
|
||||
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
|
||||
F src/memdb.c 0a0e827311cec57fdea2ed3142d6684704a1b90e7995b286f74fd7d1a6c5a62c
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
|
||||
F src/mutex.c 00b8cee206a67fd764d001f3a148494331d8d0b3b9c3974ecd69ff29bb444462
|
||||
@@ -719,27 +720,27 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
|
||||
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
|
||||
F src/os_unix.c fa5e09b4df35ad845440cad67b86908cfe1fd4c28c51915f82e23633d1992bf4
|
||||
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
|
||||
F src/os_unix.c 92a1773139e0c6206a927c7e1648b06287583570b6e253210a06ee3886739d39
|
||||
F src/os_win.c 938805c15e855819cb0874aea560c3a7250175d311a5494b47a4f8b69dcd59c0
|
||||
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
|
||||
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
|
||||
F src/pager.c 5e98a67fad5e33c9588460c42063859d22aca8d3140865fd411056dd360b26c2
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
|
||||
F src/parse.y d5a3c5b0277a441c38b35071c05e2b61ff5fc918a63309c809f4b6706179c320
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
|
||||
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
|
||||
F src/printf.c 41fb76fcb5ed7e16aaddc659d3b23891abebea45549fe125fc2e6ec380cc7175
|
||||
F src/printf.c ed43bcd6b551b590e47b905115aa1c35504267f532680590102e79894230a06b
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
|
||||
F src/resolve.c f5a780a7b604d43b78bca290cace7479bca0c7d8ef9ce855830d9498b975baec
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
|
||||
F src/shell.c.in a3288615aba1b375f7dca9801874c806e8d0d047dfe4e9253a944f4b47c7459e
|
||||
F src/select.c 5c3a5e3c1e6c3f8ccabeb414e18dce64e6f3e797de225ee93034f2c9e76f289c
|
||||
F src/shell.c.in cbb7ae029cea6d8789924d9009574081b4f3c0619ce736ed36e8c7564ef13547
|
||||
F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
|
||||
F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5
|
||||
F src/sqliteInt.h 9f152ad54b9ce85040365b96eb6d2a985146dc760bb295cc645f48d38100ad85
|
||||
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -799,7 +800,7 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||
F src/util.c 4f0abc15f63829e12cdfeeb490faf25ac65894b0bcc20d660e3f3757b8e2360b
|
||||
F src/util.c 2053344769bc602b2c23ce193f4d24f89777ab67fa768b80fa197d3876dc3017
|
||||
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
|
||||
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
|
||||
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
|
||||
@@ -816,10 +817,10 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
|
||||
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c bffca5e4ef20d0bfbdc24f1dc13fd3f955284225a8ad25a4454635f6be39aad0
|
||||
F src/where.c a1caeb656f74e58de7e7310ee91c6dfb40e975c7dd9b18e61a965aea46a610f2
|
||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||
F src/wherecode.c 676cb6cb02878643e817d9917a2d3522b83a3736b2cedd3dc8a01d7bb92af6c2
|
||||
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
|
||||
F src/wherecode.c bc39ccbe3648f01157038b16cc55bdbff128590972b7185521b5526dc2815765
|
||||
F src/whereexpr.c 61b1c9d98d39f6bcd79fcb4ebb4c9478effb259fefac4c7d3e78e4957f97f75a
|
||||
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
|
||||
@@ -837,8 +838,8 @@ F test/alter4.test 37cafe164067a6590a0ee4cec780bddbbaa33dc50b11542dcfbe0e6562649
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
|
||||
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
|
||||
F test/altercons.test ea18def4a0f26b9066da56095c9c480df705df4d02e4ae151708fae76f7e3884
|
||||
F test/altercons2.test 3c1f58312817df43aeada3b1827fdc3ce3fc50c6f49a95ef62cf4cbbae8583a0
|
||||
F test/altercons.test 9b036a956268eccd64761a6af3ab6f7b313c738392c7460b747d8aacd32589a2
|
||||
F test/altercons2.test 4933eadb035fc0ccfc34ed879f69a09051c53907f9dae9c3d36d25f93519ccc7
|
||||
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
|
||||
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
|
||||
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
||||
@@ -914,7 +915,7 @@ F test/bestindex8.test 4d8b1e8f30a7f405988ce4dbcc2b95c0775f0bed9ec08e0291a07e2f3
|
||||
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
|
||||
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
|
||||
F test/bestindexB.test 14db2f66ec9cc5064a74996033b74e5eec0fd2f3a327fbe34ff18de67e9d2671
|
||||
F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc
|
||||
F test/bestindexC.test f44eb3d77359e9487222a2dde27f8ecf11a8e4932803c0dd9477f75e114f1c55
|
||||
F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3
|
||||
F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49
|
||||
F test/bestindexF.test 4e53d606cbde40a2254aa016d500c5b71766a4065b8541202d195a3d9fe11b1c
|
||||
@@ -943,6 +944,7 @@ F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1
|
||||
F test/btreefault.test a82a23b0578bc587afbf9a622c8f54a54f63762f062ba8a35613cfee38ab42f9
|
||||
F test/busy.test caff7164c16ce06a53af51f9e4c2753d4cc64250e00790a5e48b9c4f4be37597
|
||||
F test/busy2.test 20823a5d7c42fb257d9f108c66312d90b1bb4ec3d80ba6b4e371073727560f98
|
||||
F test/c/changeblob1.c c2f51ff87ed628634badfe635d987c21ffcc6a03554a29bff7f68607e6deb9ab
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
|
||||
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
|
||||
@@ -952,7 +954,7 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a490f7
|
||||
F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/carray01.test 17c1cf8287862b15dda949dba626fd5fee5c58471dcc1cae0341471c2ae7da01
|
||||
F test/carray01.test 4a77d9f5711212bd209598913405d36dd48cc4f5f643e78cf589daa4d3047c54
|
||||
F test/carray02.test 9d070b54f24a34d1f3b3c552ba34db0375a9d1c4219067416fb07d1595987c9d
|
||||
F test/carrayfault.test 108a7d83904fc267c448e27c13b2a857c700bd6ddaa2f1e2518be718b159cb6b
|
||||
F test/cast.test a2a3b32df86e3c0601ffa2e9f028a18796305d251801efea807092dbf374a040
|
||||
@@ -1039,7 +1041,7 @@ F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8b
|
||||
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
|
||||
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
|
||||
F test/dblwidth-a.sql 59dd59aa78ce8fd8ab631a3816516831f4e947b143039257e6fe132c3cea4171
|
||||
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
|
||||
F test/dbpage.test 2e3a50548edea551ef974b8f121f975852de9c5b16cb3284ac4bf2c9f2ed5a62
|
||||
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52
|
||||
@@ -1097,7 +1099,7 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
|
||||
F test/exclusive2.test cd70b1d9c6fffd336f9795b711dcc5d9ceba133ad3f7001da3fda63615bdc91e
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/existsexpr.test 75c1c13cda18b53f68c135fe644afc034d72a6de5b0774b0219ca4a6dc4b96b0
|
||||
F test/existsexpr.test 1ce70ac41fb6d52525774388aa23e982428e883a850f9d56d49776d234865552
|
||||
F test/existsexpr2.test dc23e76389eff3d29f6488ff733012a3560cd67ec8cfaecbecd52cced5d5af11
|
||||
F test/existsfault.test ff41c11f3052c1bbd4f8dd557802310026253d67d7c4e3a180c16d2f0862973e
|
||||
F test/expr.test db981f8a85520e99ae20aab7ad2e9b5b0437ed09159b57ced434c672075d2e61
|
||||
@@ -1164,7 +1166,7 @@ F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cd
|
||||
F test/fts3corrupt4.test c7f414fe29b97a478d15c90382c4ae077a2bbd2283bf8c63bf66dadaaed3edb8
|
||||
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
|
||||
F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
|
||||
F test/fts3corrupt7.test 1da31776e24bb91d3c028e663456b61280b121a74496ccf2fef3fe33790ad2b0
|
||||
F test/fts3corrupt7.test 93622a4336b161a733accbd66311d93749660243cdda268fd647c21e1e680770
|
||||
F test/fts3cov.test 1e5ecea0e4c1394cea97adcfb9fd3d2d5998fd563dacf465f413e6c7fa5cffb3
|
||||
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
|
||||
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
|
||||
@@ -1316,7 +1318,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
|
||||
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
|
||||
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
|
||||
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
|
||||
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
|
||||
F test/interrupt2.test 7eaa40a975d950826cd56e6c37f0f0629adfa2d1a8d3333aff0ff7cf86069963
|
||||
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
|
||||
F test/intreal.test 68829a8bb073ee1610ca3f8f9e0f99b0371fb36e0fa64862dd5ced4ef03c2343
|
||||
F test/io.test d267fdc8915444a45e19841489033ebe70bb69f6db605b00df70be16b2a80f59
|
||||
@@ -1343,7 +1345,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
|
||||
F test/joinI.test a4d37143fcc39e915d9feb08e614a13f88dfe332d77152a3c526a2370ddb9a70
|
||||
F test/joinI.test f5e8613c3262f056c56249cc98255bf5fa1a764d7667b8ceb9fe08b4c965f061
|
||||
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
|
||||
@@ -1355,7 +1357,7 @@ F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd286
|
||||
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
|
||||
F test/json/json-speed-check.sh 45862b216f1f8bbf16d74e2ad6ea20c773ee77774b299a7e0f76a22eb98e91f1 x
|
||||
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
|
||||
F test/json101.test cf53254f0f0c1399a01b21fc58fee0e63a12a556be91b9ee9faccdb8b82c083c
|
||||
F test/json101.test 34109fe1bfa384774ceea2a174de00e0b77e8a7b586bf30bdc9a60d7377ed15b
|
||||
F test/json102.test ea5c9811e408e115c8fc539548deef431fda4924c23cacd79dd4b783f4449f07
|
||||
F test/json103.test e626d109cd0bdb8282ec9bf755af3befa50e3e03a255362fc53433d31e1d66d4
|
||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||
@@ -1420,7 +1422,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
F test/memdb1.test c737ac9aa5895092332b1dde24fae7ae494b7fcbcd346d22d600891096a3836d
|
||||
F test/memdb1.test 916093ae5ad097660a742890a9986d1f217a620ac95efb64884041ee4c408603
|
||||
F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4
|
||||
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
|
||||
F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e
|
||||
@@ -1441,7 +1443,7 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test d595599972ec0b436985f0f02f243b68500ffc977b9b3194ec66c0866cfddcab
|
||||
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
|
||||
F test/misuse.test 859f37014d9824ca66bd90c36372c08c80c51c9593a7cfa8a31d4f92cd4d5b7f
|
||||
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
|
||||
F test/mjournal.test 3570ca4241b0d19ca1f47616f5293722f7c2fc9f2d359fc7933d67ef51dc2137
|
||||
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
|
||||
F test/mmap2.test dba452dc7db91e9df10f70bdd73dc4190c7b8ee7b5133b4684f04277ada0b9ac
|
||||
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
|
||||
@@ -1449,7 +1451,7 @@ F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
|
||||
F test/mmapcorrupt.test 470fb44fe92e99c1d23701d156f8c17865f5b027063c9119dcfdb842791f4465
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
|
||||
F test/modeA.sql fc64f646b0a1d0806af122fad6db2c89de63c51106655c09d44a652052a14d05
|
||||
F test/modeA.sql 859e608297646e2d573e431507f38e465bc1513fa5862916ec8fb20a1d6314a4
|
||||
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
|
||||
@@ -1467,7 +1469,7 @@ F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed
|
||||
F test/notnull2.test c2c7b670fb8fa6ffe5f9cc08af88864fbb8237e28b56ad528e8dee921019c5fe
|
||||
F test/notnullfault.test fc4bb7845582a2b3db376001ef49118393b1b11abe0d24adb03db057ee2b73d5
|
||||
F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
|
||||
F test/nulls1.test 7a5e4346ee4285034100b4cd20e6784f16a9d6c927e44ecdf10034086bbee9c9
|
||||
F test/nulls1.test 8fc70d75ab363b0f2ce9151669c2cb897def5064e2e30f7d9322970480bf6e87
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
|
||||
F test/offset1.test c21e67d2d5ae8ed310243fbe84fc2f0dca49e9ffed3ea89110c0d5914c0de620
|
||||
@@ -1503,7 +1505,7 @@ F test/parser1.test 131f4733472252d53d8ed681115257866f55740ab697fa05900d76604934
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
|
||||
F test/percentile.test eaee1ff3e35d5fe933ac98d927c9a7d2f4f1a1a19ee22e7d45e97a6d9ee32077
|
||||
F test/percentile.test fd78896fa882fa4fbf693640097859721f3629926c2ccf804af5bcb7001fd35b
|
||||
F test/permutations.test e6de4f5777f7785737ac3d1d964b8656e5477a134665b2fe8a91884ab9b685b3
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 7d07b7bb76e273215d6a20c4f83c3062cc28976c737ccb70a686025801e86c8f
|
||||
@@ -1513,13 +1515,13 @@ F test/pragma4.test 396ef9bff1fb966d41721545ad4b12bfc26aae315f5fe51d9b917828d49e
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
|
||||
F test/prefixes.test fe52bb0c2fee10fb9b918a095d443ebf31dd48e5e2c7a1b21feba594fe7ff2d0
|
||||
F test/printf.test bcb093ef5cbd17e2d94d93d62045ee61ed0f465c1ca123f284774e474e73a9ea
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd
|
||||
F test/qrf01.test 09caa00e6b4deea5fcd8958b4062233fcef5ef1b354312ec956ec4bc3a09572a
|
||||
F test/qrf01.test 0b5095dfc841eaa12806fe20fc0ede72573885390b3152edc0edb66378fb55f7
|
||||
F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
|
||||
F test/qrf03.test e7efe46d204671726b4707585126cd78d107368de4a7d0c7b8d5157cdd8624ed
|
||||
F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
|
||||
@@ -1554,7 +1556,7 @@ F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190c
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
|
||||
F test/rowvalue.test 93474d8e1c496e970bdcc3a7f54ac835adda667d2fd971957b4bce0c0b11707b
|
||||
F test/rowvalue.test ba43ff378f78c81579dd0f9f2b1e92876d29fb767f090acb7d4cbc6ff4a3c42c
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 103e9a224ca0548dd0d67e439f39c5dd16de4200221a333927372408c025324c
|
||||
F test/rowvalue4.test 6e160977d44ee715e142f63ec0e339586c61f12bbbffacee369b1cdc0b7390f0
|
||||
@@ -1563,7 +1565,7 @@ F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test 06ec0aca725bf683313d03793aa2943bc7f45a901848c7056a9665b769c8fc38
|
||||
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
|
||||
F test/rowvalue9.test 7499a8fd7ca3a3f0e19d94e135355439aa2b596f86b775ca8de79672da2ca378
|
||||
F test/rowvalueA.test 7d28bf6c2f8a2af8adbba2c4eda9136a4dd36250b8966ba05b34c0954f78efd7
|
||||
F test/rowvalueA.test 5849865659f27ec50ba3185b2e18928a92077ceddf121ee6b95bf32300d44c91
|
||||
F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972d511c54fff
|
||||
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
@@ -1669,7 +1671,7 @@ F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce8
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
|
||||
F test/spellfix4.test 7c56a09de68b95051ef0627fe235e514efbba2aa816dc2a9c5c670d98877e632
|
||||
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
|
||||
F test/sqllimits1.test 408131e4975d61868711c83f101a56d4602313cc5cae88d3eee81c1da364fd89
|
||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||
@@ -1687,7 +1689,7 @@ F test/subquery.test 23087f9b1c15ab9cc5231d04946bdebc51db527c95eb9d7434a2222127e
|
||||
F test/subquery2.test ab96ff3fa9c4e3dce0d699f74e61c50250ed4335bc8f400e127707d552a8999e
|
||||
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
|
||||
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
|
||||
F test/subtype1.test 96fd2a59bfc845c955b5f339d23b37ef4d50de5f8a04acd1450a68605fa2e3e7
|
||||
F test/subtype1.test 1ca002dbda34c342c2dee7cffac220b77d67edfbffd43124978956747f534a96
|
||||
F test/superlock.test 85256830339a6871ce36a2ef591c3f67716a701b5497788fb2068b90159c2442
|
||||
F test/swarmvtab.test 250231404fcac88f61a6c147bb0e3a118ed879278cd3ccb0ae2d3a729e1e8e26
|
||||
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
|
||||
@@ -1699,7 +1701,7 @@ F test/sync.test a619e407ede58a7b6e3e44375328628559fc9695a9c24c47cb5690a866b0031
|
||||
F test/sync2.test 06152269ed73128782c450c355988fe8dd794d305833af75e1a5e79edd4dae47
|
||||
F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test cfa96a9a235c39fb0cae69928b989b28bfec108f62d2533486f76e32dcedfdfb
|
||||
F test/tabfunc01.test 7827c2dfd57a094125b059f51a2200eaf04d417af6b1e720c34a8cbf54e8a14f
|
||||
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
|
||||
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
@@ -1714,7 +1716,7 @@ F test/temptrigfault.tes fc5918e64f3867156fefe7cfca9d8e1f495134a5229b2b511b0dc11
|
||||
F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3fb4769d61
|
||||
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
|
||||
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
|
||||
F test/testrunner.tcl 6b232f0d4825dec8b967754503080fc9609fad077f582d02f86bd2d95bec4110 x
|
||||
F test/testrunner.tcl 8d92cacf9989aefdf33229c414adac56d389b5b6d9d31d9ebed34d5ab4e13833 x
|
||||
F test/testrunner_data.tcl 48c8a230fcada37f4809f95c2ba49e44bc3d520b6165c09173249c6e65b01cc1
|
||||
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
@@ -1884,7 +1886,7 @@ F test/trace3.test 2deeac66359c9f007f0fc9fb6336994a5d68fc1a65129f322a9e9546fd537
|
||||
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/transitive1.test f8ee983600b33d167da1885657f064aec404e1c0d0bc8765fdf163f4c749237a
|
||||
F test/transitive1.test d6252d06ddc104d13372fce0da93af501546bf5d75cb4d2a1f83b8c27238997a
|
||||
F test/trigger1.test 141bd2bbfa82fa91aed7391f50517373c9823ff8f55af35e56313dbc75112ca1
|
||||
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
|
||||
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
@@ -1922,7 +1924,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test d2366ef2d3d95249314307861d748924d9ab4f24305541159a08be61ccd4a9ee
|
||||
F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
|
||||
F test/update.test 258dcf26d401177d3cb7fdf0beab14d671dbe72e8ff6e0435fd85a08fcd57bd9
|
||||
F test/update.test 93fba5f7505f7a7b25d66135d98d9b055b7f1bd627a7e514dbba1ea6213f0c41
|
||||
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
|
||||
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
|
||||
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
|
||||
@@ -2026,7 +2028,7 @@ F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9
|
||||
F test/walthread.test d562f51a61191ccfab64940df7aa1cef87c902fa5ab742590ef7f859dfe6a44b
|
||||
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
|
||||
F test/where.test 5087c72d26fd075a1644c8512be9fe18de9bf2d2b0754f7fd9b74a1c6540c4fc
|
||||
F test/where2.test 1dbff4ab847068a52b927a0c1a7cf7faed4c8cae081fbcdac9b052a3a209aefa
|
||||
F test/where2.test b73f8ee8f94b850764c429efe2d48171090628737dcc3df64a9f2214da02089f
|
||||
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
@@ -2073,10 +2075,10 @@ F test/window8.tcl c57364e64d816f6e26df60437e1202e2c1031c7b818a1a67535d1006862a0
|
||||
F test/window8.test 3d931e58802b8ab8063da00f0cf30aa3351640238a952c0efb5a129e2349a4bb
|
||||
F test/window9.test 7b98a7916dd87763ea35f56ea023e3b29e99744582204ccf2937a3bac411cd4d
|
||||
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
|
||||
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
|
||||
F test/windowB.test bba3bee77c1d3321077ff8951d543161d74f08f78633d84433ced7d6261dc2c2
|
||||
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
|
||||
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
|
||||
F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f
|
||||
F test/windowE.test a82a4213c7b923220de5e457cb76c537a5d10d5e94641e3055ba21b79870a7fb
|
||||
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
|
||||
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
|
||||
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
|
||||
@@ -2100,7 +2102,7 @@ F test/writecrash.test 13520af28f376bfc8c0bcd130efc1fff20bb165198e8b94cf153f1f75
|
||||
F test/zeroblob.test 7b74cefc7b281dfa2b07cd237987fbe94b4a2037a7771e9e83f2d5f608b1d99e
|
||||
F test/zeroblobfault.test 861d8191a0d944dfebb3cb4d2c5b4e46a5a119eaec5a63dd996c2389f8063441
|
||||
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
|
||||
F test/zipfile.test a3fcfc43115e4226fdddadd43bdf31c8ca805ad08dad435634f1633d8f5840d9
|
||||
F test/zipfile.test 7b5c2f43ce9f7c882237e74822a331d94f4f83891e7a64c503519b434d06a5bf
|
||||
F test/zipfile2.test 21afaffcf4f7769df38bf16e4a9c4dfa6ba1b0f5b695f844ec61fafb92db0db7
|
||||
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
|
||||
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
|
||||
@@ -2108,7 +2110,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
F tool/build-all-msvc.bat 1ee9dbadcc07fc23268025854e97b392bcbad72376b47aee7b22f3797a4f2c87 x
|
||||
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
|
||||
F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
|
||||
F tool/buildtclext.tcl b58df93e772fec8b2ae44ee1a82d13378e13edb1e94c4ab2f7ee3440a9523bff
|
||||
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
|
||||
@@ -2178,7 +2180,7 @@ F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d
|
||||
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
|
||||
F tool/sqldiff.c 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
|
||||
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
|
||||
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
|
||||
F tool/sqlite3_rsync.c d9ce999e5b3aa9f36de44b321755622e52258774889bd804ba56f00eca01af50
|
||||
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
F tool/src-verify.c 6c655d9a8d6b30f3648fc78a79bf3838ed68f8543869d380c43ea9f17b3b8501
|
||||
@@ -2197,11 +2199,10 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P cda5dd9bcbef2135bb9855139a11d0e22a092f9498d82eb18e7d4401264b6eb8
|
||||
R 78f8c181262c6bdd7ab10b5492ff03ea
|
||||
T +sym-major-release *
|
||||
P ac00a18dcf132180295d41299f31fbc68087a27b61782d00b9633dd9661ded2b
|
||||
R 58c568d42a018658d9c21e84f3d9ab9d
|
||||
T +sym-release *
|
||||
T +sym-version-3.53.0 *
|
||||
T +sym-version-3.53.2 *
|
||||
U drh
|
||||
Z 5cc2d306947f7e965f5f798b08602c26
|
||||
Z a64dcb64a02448f95d399730d70f1fe2
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+3
-4
@@ -1,5 +1,4 @@
|
||||
branch trunk
|
||||
tag trunk
|
||||
branch branch-3.53
|
||||
tag release
|
||||
tag major-release
|
||||
tag version-3.53.0
|
||||
tag branch-3.53
|
||||
tag version-3.53.2
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b
|
||||
d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24
|
||||
|
||||
+19
-5
@@ -2798,7 +2798,9 @@ void sqlite3AlterDropConstraint(
|
||||
if( !pTab ) return;
|
||||
|
||||
if( pCons ){
|
||||
zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
|
||||
char *z = sqlite3NameFromToken(db, pCons);
|
||||
zArg = sqlite3MPrintf(db, "%Q", z);
|
||||
sqlite3DbFree(db, z);
|
||||
}else{
|
||||
int iCol;
|
||||
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
|
||||
@@ -2985,19 +2987,31 @@ void sqlite3AlterAddConstraint(
|
||||
SrcList *pSrc, /* Table to add constraint to */
|
||||
Token *pFirst, /* First token of new constraint */
|
||||
Token *pName, /* Name of new constraint. NULL if name omitted. */
|
||||
const char *pExpr, /* Text of CHECK expression */
|
||||
int nExpr /* Size of pExpr in bytes */
|
||||
const char *zExpr, /* Text of CHECK expression */
|
||||
int nExpr, /* Size of pExpr in bytes */
|
||||
Expr *pExpr /* The parsed CHECK expression */
|
||||
){
|
||||
Table *pTab = 0; /* Table identified by pSrc */
|
||||
int iDb = 0; /* Which schema does pTab live in */
|
||||
const char *zDb = 0; /* Name of the schema in which pTab lives */
|
||||
const char *pCons = 0; /* Text of the constraint */
|
||||
int nCons; /* Bytes of text to use from pCons[] */
|
||||
int rc; /* Result from error checking pExpr */
|
||||
|
||||
/* Look up the table being altered. */
|
||||
assert( pSrc->nSrc==1 );
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
|
||||
if( !pTab ) return;
|
||||
if( !pTab ){
|
||||
sqlite3ExprDelete(pParse->db, pExpr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Verify that the new CHECK constraint does not contain any
|
||||
** internal-use-only function. Forum post 2026-05-10T01:11:28Z
|
||||
*/
|
||||
rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
|
||||
sqlite3ExprDelete(pParse->db, pExpr);
|
||||
if( rc ) return;
|
||||
|
||||
/* If this new constraint has a name, check that it is not a duplicate of
|
||||
** an existing constraint. It is an error if it is. */
|
||||
@@ -3018,7 +3032,7 @@ void sqlite3AlterAddConstraint(
|
||||
sqlite3NestedParse(pParse,
|
||||
"SELECT sqlite_fail('constraint failed', %d) "
|
||||
"FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
|
||||
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr
|
||||
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
|
||||
);
|
||||
|
||||
/* Edit the SQL for the named table. */
|
||||
|
||||
+11
-2
@@ -106,6 +106,16 @@ static void attachFunc(
|
||||
** from sqlite3_deserialize() to close database db->init.iDb and
|
||||
** reopen it as a MemDB */
|
||||
Btree *pNewBt = 0;
|
||||
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
assert( pNew->pBt!=0 );
|
||||
if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE
|
||||
|| sqlite3BtreeIsInBackup(pNew->pBt)
|
||||
){
|
||||
rc = SQLITE_BUSY;
|
||||
goto attach_error;
|
||||
}
|
||||
|
||||
pVfs = sqlite3_vfs_find("memdb");
|
||||
if( pVfs==0 ) return;
|
||||
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
|
||||
@@ -115,8 +125,7 @@ static void attachFunc(
|
||||
/* Both the Btree and the new Schema were allocated successfully.
|
||||
** Close the old db and update the aDb[] slot with the new memdb
|
||||
** values. */
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
|
||||
sqlite3BtreeClose(pNew->pBt);
|
||||
pNew->pBt = pNewBt;
|
||||
pNew->pSchema = pNewSchema;
|
||||
}else{
|
||||
|
||||
+9
-1
@@ -5185,7 +5185,9 @@ static int accessPayload(
|
||||
** means "not yet known" (the cache is lazily populated).
|
||||
*/
|
||||
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
|
||||
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
|
||||
i64 nOvfl = pCur->info.nPayload;
|
||||
testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
|
||||
nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
|
||||
if( pCur->aOverflow==0
|
||||
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
|
||||
){
|
||||
@@ -5290,6 +5292,12 @@ static int accessPayload(
|
||||
(eOp==0 ? PAGER_GET_READONLY : 0)
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( eOp!=0
|
||||
&& (sqlite3PagerPageRefcount(pDbPage)!=1
|
||||
|| NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit)) ){
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
return SQLITE_CORRUPT_PAGE(pPage);
|
||||
}
|
||||
aPayload = sqlite3PagerGetData(pDbPage);
|
||||
nextPage = get4byte(aPayload);
|
||||
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
|
||||
|
||||
+3
-2
@@ -259,12 +259,13 @@ static int dbpageFilter(
|
||||
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
|
||||
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
|
||||
if( idxNum & 1 ){
|
||||
i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
|
||||
assert( argc>(idxNum>>1) );
|
||||
pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
|
||||
if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
|
||||
if( iPg<1 || iPg>pCsr->mxPgno ){
|
||||
pCsr->pgno = 1;
|
||||
pCsr->mxPgno = 0;
|
||||
}else{
|
||||
pCsr->pgno = (Pgno)iPg;
|
||||
pCsr->mxPgno = pCsr->pgno;
|
||||
}
|
||||
}else{
|
||||
|
||||
+34
-14
@@ -4262,7 +4262,16 @@ static void sqlite3ExprCodeIN(
|
||||
CollSeq *pColl;
|
||||
int r3 = sqlite3GetTempReg(pParse);
|
||||
p = sqlite3VectorFieldSubexpr(pLeft, i);
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
|
||||
}else{
|
||||
/* If the RHS of the IN(...) expression are scalar expressions, do
|
||||
** not consider their collation sequences. The documentation says
|
||||
** "The collating sequence used for expressions of the form "x IN (y, z,
|
||||
** ...)" is the collating sequence of x.". */
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
|
||||
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
|
||||
(void*)pColl, P4_COLLSEQ);
|
||||
@@ -4685,26 +4694,37 @@ static int exprCodeInlineFunction(
|
||||
}
|
||||
|
||||
/*
|
||||
** Expression Node callback for sqlite3ExprCanReturnSubtype().
|
||||
** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
|
||||
** pExpr is able to return a subtype, set pWalker->eCode and abort
|
||||
** the search. If pExpr can never return a subtype, prune search.
|
||||
**
|
||||
** Only a function call is able to return a subtype. So if the node
|
||||
** is not a function call, return WRC_Prune immediately.
|
||||
** The only expressions that can return a subtype are:
|
||||
**
|
||||
** A function call is able to return a subtype if it has the
|
||||
** SQLITE_RESULT_SUBTYPE property.
|
||||
** 1. A function
|
||||
** 2. The no-op "+" operator
|
||||
** 3. A CASE...END expression
|
||||
** 4. A CAST() expression
|
||||
** 5. A "expr COLLATE colseq" expression.
|
||||
**
|
||||
** Assume that every function is able to pass-through a subtype from
|
||||
** one of its argument (using sqlite3_result_value()). Most functions
|
||||
** are not this way, but we don't have a mechanism to distinguish those
|
||||
** that are from those that are not, so assume they all work this way.
|
||||
** That means that if one of its arguments is another function and that
|
||||
** other function is able to return a subtype, then this function is
|
||||
** able to return a subtype.
|
||||
** For any other kind of expression, prune the search.
|
||||
**
|
||||
** For case 1, the expression can yield a subtype if the function has
|
||||
** the SQLITE_RESULT_SUBTYPE property. Functions can also return
|
||||
** a subtype (via sqlite3_result_value()) if any of the arguments can
|
||||
** return a subtype.
|
||||
**
|
||||
** In all cases 1 through 5, the expression might also return a subtype
|
||||
** if any operand can return a subtype.
|
||||
*/
|
||||
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
||||
int n;
|
||||
FuncDef *pDef;
|
||||
sqlite3 *db;
|
||||
if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
|
||||
|| pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
|
||||
){
|
||||
return WRC_Continue;
|
||||
}
|
||||
if( pExpr->op!=TK_FUNCTION ){
|
||||
return WRC_Prune;
|
||||
}
|
||||
@@ -4714,7 +4734,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
|
||||
pWalker->eCode = 1;
|
||||
return WRC_Prune;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
+60
-47
@@ -326,9 +326,18 @@ static void printfFunc(
|
||||
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
str.printfFlags = SQLITE_PRINTF_SQLFUNC;
|
||||
sqlite3_str_appendf(&str, zFormat, &x);
|
||||
n = str.nChar;
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
|
||||
SQLITE_DYNAMIC);
|
||||
if( str.accError==SQLITE_OK ){
|
||||
n = str.nChar;
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
|
||||
SQLITE_DYNAMIC);
|
||||
}else{
|
||||
if( str.accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_result_error_toobig(context);
|
||||
}
|
||||
sqlite3_str_reset(&str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1966,11 +1975,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
assert( p->cnt>0 );
|
||||
p->cnt--;
|
||||
if( !p->approx ){
|
||||
if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
|
||||
p->ovrfl = 1;
|
||||
p->approx = 1;
|
||||
i64 x = p->iSum;
|
||||
if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
|
||||
p->iSum = x;
|
||||
return;
|
||||
}
|
||||
}else if( type==SQLITE_INTEGER ){
|
||||
p->ovrfl = 1;
|
||||
p->approx = 1;
|
||||
kahanBabuskaNeumaierInit(p, p->iSum);
|
||||
}
|
||||
if( type==SQLITE_INTEGER ){
|
||||
i64 iVal = sqlite3_value_int64(argv[0]);
|
||||
if( iVal!=SMALLEST_INT64 ){
|
||||
kahanBabuskaNeumaierStepInt64(p, -iVal);
|
||||
@@ -2942,47 +2956,46 @@ static void percentSort(double *a, unsigned int n){
|
||||
int iGt; /* Entries at or after a[iGt] are greater than rPivot */
|
||||
int i; /* Loop counter */
|
||||
double rPivot; /* The pivot value */
|
||||
|
||||
assert( n>=2 );
|
||||
if( a[0]>a[n-1] ){
|
||||
SWAP_DOUBLE(a[0],a[n-1])
|
||||
}
|
||||
if( n==2 ) return;
|
||||
iGt = n-1;
|
||||
i = n/2;
|
||||
if( a[0]>a[i] ){
|
||||
SWAP_DOUBLE(a[0],a[i])
|
||||
}else if( a[i]>a[iGt] ){
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}
|
||||
if( n==3 ) return;
|
||||
rPivot = a[i];
|
||||
iLt = i = 1;
|
||||
do{
|
||||
if( a[i]<rPivot ){
|
||||
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
||||
iLt++;
|
||||
i++;
|
||||
}else if( a[i]>rPivot ){
|
||||
do{
|
||||
iGt--;
|
||||
}while( iGt>i && a[iGt]>rPivot );
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}while( i<iGt );
|
||||
if( iLt>=2 ) percentSort(a, iLt);
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
||||
|
||||
/* Uncomment for testing */
|
||||
#if 0
|
||||
for(i=0; i<n-1; i++){
|
||||
assert( a[i]<=a[i+1] );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while( n>=2 ){
|
||||
if( a[0]>a[n-1] ){
|
||||
SWAP_DOUBLE(a[0],a[n-1])
|
||||
}
|
||||
if( n==2 ) return;
|
||||
iGt = n-1;
|
||||
i = n/2;
|
||||
if( a[0]>a[i] ){
|
||||
SWAP_DOUBLE(a[0],a[i])
|
||||
}else if( a[i]>a[iGt] ){
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}
|
||||
if( n==3 ) return;
|
||||
rPivot = a[i];
|
||||
iLt = i = 1;
|
||||
do{
|
||||
if( a[i]<rPivot ){
|
||||
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
||||
iLt++;
|
||||
i++;
|
||||
}else if( a[i]>rPivot ){
|
||||
do{
|
||||
iGt--;
|
||||
}while( iGt>i && a[iGt]>rPivot );
|
||||
SWAP_DOUBLE(a[i],a[iGt])
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}while( i<iGt );
|
||||
if( iLt>n/2 ){
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
||||
n = iLt;
|
||||
}else{
|
||||
if( iLt>=2 ) percentSort(a, iLt);
|
||||
a += iGt;
|
||||
n -= iGt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The "inverse" function for percentile(Y,P) is called to remove a
|
||||
|
||||
+67
-13
@@ -810,7 +810,7 @@ static void jsonAppendSqlValue(
|
||||
break;
|
||||
}
|
||||
case SQLITE_FLOAT: {
|
||||
jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
|
||||
jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
@@ -2124,9 +2124,10 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
|
||||
u8 x;
|
||||
u32 sz;
|
||||
u32 n;
|
||||
assert( i<=pParse->nBlob );
|
||||
x = pParse->aBlob[i]>>4;
|
||||
if( x<=11 ){
|
||||
if( i>=pParse->nBlob ){
|
||||
*pSz = 0;
|
||||
return 0;
|
||||
}else if( (x = pParse->aBlob[i]>>4)<=11 ){
|
||||
sz = x;
|
||||
n = 1;
|
||||
}else if( x==12 ){
|
||||
@@ -4909,11 +4910,9 @@ static void jsonGroupInverse(
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
#ifdef NEVER
|
||||
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
|
||||
** always have been called to initialize it */
|
||||
if( NEVER(!pStr) ) return;
|
||||
#endif
|
||||
z = pStr->zBuf;
|
||||
for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
|
||||
if( c=='"' ){
|
||||
@@ -4942,6 +4941,13 @@ static void jsonGroupInverse(
|
||||
** json_group_obj(NAME,VALUE)
|
||||
**
|
||||
** Return a JSON object composed of all names and values in the aggregate.
|
||||
**
|
||||
** Rows for which NAME is NULL do not result in a new entry. However, we
|
||||
** do initially insert a "@" entry into the growing string for each null entry
|
||||
** and change the first character of the string to "@" to signal that the
|
||||
** string contains null entries. The "@" markers are needed in order to
|
||||
** correctly process xInverse() requests. The initial "@" is converted
|
||||
** back into "{" and the "@" null values are removed by jsonObjectCompute().
|
||||
*/
|
||||
static void jsonObjectStep(
|
||||
sqlite3_context *ctx,
|
||||
@@ -4959,7 +4965,7 @@ static void jsonObjectStep(
|
||||
if( pStr->zBuf==0 ){
|
||||
jsonStringInit(pStr, ctx);
|
||||
jsonAppendChar(pStr, '{');
|
||||
}else if( pStr->nUsed>1 && z!=0 ){
|
||||
}else if( pStr->nUsed>1 ){
|
||||
jsonAppendChar(pStr, ',');
|
||||
}
|
||||
pStr->pCtx = ctx;
|
||||
@@ -4967,6 +4973,9 @@ static void jsonObjectStep(
|
||||
jsonAppendString(pStr, z, n);
|
||||
jsonAppendChar(pStr, ':');
|
||||
jsonAppendSqlValue(pStr, argv[1]);
|
||||
}else{
|
||||
pStr->zBuf[0] = '@';
|
||||
jsonAppendRawNZ(pStr, "@", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4975,20 +4984,64 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
||||
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
if( pStr ){
|
||||
jsonAppendRawNZ(pStr, "}", 2);
|
||||
jsonStringTrimOneChar(pStr);
|
||||
JsonString *pOgStr = pStr;
|
||||
JsonString tmpStr;
|
||||
jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
|
||||
jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
|
||||
pStr->pCtx = ctx;
|
||||
if( pStr->eErr ){
|
||||
jsonReturnString(pStr, 0, 0);
|
||||
return;
|
||||
}else if( flags & JSON_BLOB ){
|
||||
}
|
||||
if( pStr->zBuf[0]!='{' ){
|
||||
/* The string contains null entries that need to be removed */
|
||||
u64 i, j;
|
||||
int inStr = 0;
|
||||
if( !isFinal ){
|
||||
/* Work with a temporary copy of the string if this is not the
|
||||
** final result */
|
||||
jsonStringInit(&tmpStr, ctx);
|
||||
jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
|
||||
pStr = &tmpStr;
|
||||
if( pStr->eErr ){
|
||||
jsonReturnString(pStr, 0, 0);
|
||||
return;
|
||||
}
|
||||
jsonStringTrimOneChar(pStr); /* Remove zero terminator */
|
||||
}
|
||||
/* Fix up the string by changing the initial "@" flag back to
|
||||
** to "{" and removing all subsequence "@" entries, with their
|
||||
** associated comma delimeters. */
|
||||
pStr->zBuf[0] = '{';
|
||||
for(i=j=1; i<pStr->nUsed; i++){
|
||||
char c = pStr->zBuf[i];
|
||||
if( c=='"' ){
|
||||
inStr = !inStr;
|
||||
pStr->zBuf[j++] = '"';
|
||||
}else if( c=='\\' ){
|
||||
pStr->zBuf[j++] = '\\';
|
||||
pStr->zBuf[j++] = pStr->zBuf[++i];
|
||||
}else if( c=='@' && !inStr ){
|
||||
assert( i+1<pStr->nUsed );
|
||||
if( pStr->zBuf[i+1]==',' ){
|
||||
i++;
|
||||
}else if( pStr->zBuf[j-1]==',' ){
|
||||
j--;
|
||||
}
|
||||
}else{
|
||||
pStr->zBuf[j++] = c;
|
||||
}
|
||||
}
|
||||
pStr->zBuf[j] = 0; /* Restore zero terminator */
|
||||
pStr->nUsed = j; /* Truncate the string */
|
||||
}
|
||||
if( flags & JSON_BLOB ){
|
||||
jsonReturnStringAsBlob(pStr);
|
||||
if( isFinal ){
|
||||
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
|
||||
}else{
|
||||
jsonStringTrimOneChar(pStr);
|
||||
jsonStringTrimOneChar(pOgStr);
|
||||
}
|
||||
return;
|
||||
}else if( isFinal ){
|
||||
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
|
||||
pStr->bStatic ? SQLITE_TRANSIENT :
|
||||
@@ -4996,8 +5049,9 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
||||
pStr->bStatic = 1;
|
||||
}else{
|
||||
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
||||
jsonStringTrimOneChar(pStr);
|
||||
jsonStringTrimOneChar(pOgStr);
|
||||
}
|
||||
if( pStr!=pOgStr ) jsonStringReset(pStr);
|
||||
}else if( flags & JSON_BLOB ){
|
||||
static const unsigned char emptyObject = 0x0c;
|
||||
sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
|
||||
|
||||
+3
-4
@@ -876,10 +876,10 @@ int sqlite3_deserialize(
|
||||
if( rc ) goto end_deserialize;
|
||||
db->init.iDb = (u8)iDb;
|
||||
db->init.reopenMemdb = 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
sqlite3_step(pStmt);
|
||||
db->init.reopenMemdb = 0;
|
||||
if( rc!=SQLITE_DONE ){
|
||||
rc = SQLITE_ERROR;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_deserialize;
|
||||
}
|
||||
p = memdbFromDbSchema(db, zSchema);
|
||||
@@ -900,7 +900,6 @@ int sqlite3_deserialize(
|
||||
}
|
||||
|
||||
end_deserialize:
|
||||
sqlite3_finalize(pStmt);
|
||||
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
|
||||
+6
-6
@@ -5140,9 +5140,9 @@ static int unixShmMap(
|
||||
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
|
||||
|
||||
if( pShmNode->nRegion<nReqRegion ){
|
||||
char **apNew; /* New apRegion[] array */
|
||||
int nByte = nReqRegion*szRegion; /* Minimum required file size */
|
||||
struct stat sStat; /* Used by fstat() */
|
||||
char **apNew; /* New apRegion[] array */
|
||||
i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
|
||||
struct stat sStat; /* Used by fstat() */
|
||||
|
||||
pShmNode->szRegion = szRegion;
|
||||
|
||||
@@ -5173,7 +5173,7 @@ static int unixShmMap(
|
||||
*/
|
||||
else{
|
||||
static const int pgsz = 4096;
|
||||
int iPg;
|
||||
i64 iPg;
|
||||
|
||||
/* Write to the last byte of each newly allocated or extended page */
|
||||
assert( (nByte % pgsz)==0 );
|
||||
@@ -5199,8 +5199,8 @@ static int unixShmMap(
|
||||
}
|
||||
pShmNode->apRegion = apNew;
|
||||
while( pShmNode->nRegion<nReqRegion ){
|
||||
int nMap = szRegion*nShmPerMap;
|
||||
int i;
|
||||
i64 nMap = (i64)szRegion*(i64)nShmPerMap;
|
||||
i64 i;
|
||||
void *pMem;
|
||||
if( pShmNode->hShm>=0 ){
|
||||
pMem = osMmap(0, nMap,
|
||||
|
||||
+6
-7
@@ -4582,7 +4582,7 @@ static int winShmMap(
|
||||
if( pShmNode->nRegion<=iRegion ){
|
||||
HANDLE hShared = pShmNode->hSharedShm;
|
||||
struct ShmRegion *apNew; /* New aRegion[] array */
|
||||
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
|
||||
i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
|
||||
sqlite3_int64 sz; /* Current size of wal-index file */
|
||||
|
||||
pShmNode->szRegion = szRegion;
|
||||
@@ -4613,7 +4613,7 @@ static int winShmMap(
|
||||
|
||||
/* Map the requested memory region into this processes address space. */
|
||||
apNew = (struct ShmRegion*)sqlite3_realloc64(
|
||||
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
|
||||
pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
|
||||
);
|
||||
if( !apNew ){
|
||||
rc = SQLITE_IOERR_NOMEM_BKPT;
|
||||
@@ -4635,15 +4635,14 @@ static int winShmMap(
|
||||
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
|
||||
hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
|
||||
#endif
|
||||
|
||||
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
|
||||
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
|
||||
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
|
||||
hMap ? "ok" : "failed"));
|
||||
if( hMap ){
|
||||
int iOffset = pShmNode->nRegion*szRegion;
|
||||
i64 iOffset = pShmNode->nRegion*szRegion;
|
||||
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
|
||||
pMap = osMapViewOfFile(hMap, flags,
|
||||
0, iOffset - iOffsetShift, szRegion + iOffsetShift
|
||||
0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
|
||||
);
|
||||
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
|
||||
osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
|
||||
@@ -4665,7 +4664,7 @@ static int winShmMap(
|
||||
|
||||
shmpage_out:
|
||||
if( pShmNode->nRegion>iRegion ){
|
||||
int iOffset = iRegion*szRegion;
|
||||
i64 iOffset = (i64)iRegion*(i64)szRegion;
|
||||
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
|
||||
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
|
||||
*pp = (void *)&p[iOffsetShift];
|
||||
|
||||
+4
-4
@@ -2566,7 +2566,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
if( rc!=SQLITE_OK ) goto delsuper_out;
|
||||
nSuperPtr = 1 + (i64)pVfs->mxPathname;
|
||||
assert( nSuperJournal>=0 && nSuperPtr>0 );
|
||||
zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
|
||||
zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
|
||||
if( !zFree ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto delsuper_out;
|
||||
@@ -2827,10 +2827,10 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
**
|
||||
** TODO: Technically the following is an error because it assumes that
|
||||
** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
|
||||
** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
|
||||
** ((pPager->pageSize+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
|
||||
** mxPathname is 512, which is the same as the minimum allowable value
|
||||
** for pageSize.
|
||||
*/
|
||||
** for pageSize, and so this assumption holds. But it might not for some
|
||||
** custom VFS. */
|
||||
zSuper = pPager->pTmpSpace;
|
||||
rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
|
||||
if( rc==SQLITE_OK && zSuper[0] ){
|
||||
|
||||
+9
-6
@@ -1334,9 +1334,11 @@ expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
|
||||
ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
|
||||
A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
||||
if( A ){
|
||||
int i;
|
||||
A->x.pList = pList;
|
||||
if( ALWAYS(pList->nExpr) ){
|
||||
A->flags |= pList->a[0].pExpr->flags & EP_Propagate;
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
assert( pList->a[i].pExpr!=0 );
|
||||
A->flags |= pList->a[i].pExpr->flags & EP_Propagate;
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
@@ -1476,6 +1478,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
|
||||
if( A ){
|
||||
A->x.pList = pList;
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
@@ -1909,11 +1912,11 @@ cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) DROP NOT NULL. {
|
||||
cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) SET NOT(Z) NULL onconf. {
|
||||
sqlite3AlterSetNotNull(pParse, X, &Y, &Z);
|
||||
}
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1));
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr(E) RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1), E);
|
||||
}
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1));
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr(E) RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1), E);
|
||||
}
|
||||
|
||||
kwcolumn_opt ::= .
|
||||
|
||||
+40
-16
@@ -165,7 +165,7 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
|
||||
return 0;
|
||||
}
|
||||
z = sqlite3DbMallocRaw(pAccum->db, n);
|
||||
z = sqlite3_malloc(n);
|
||||
if( z==0 ){
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
|
||||
}
|
||||
@@ -623,11 +623,27 @@ void sqlite3_str_vappendf(
|
||||
|
||||
szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+10;
|
||||
if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
|
||||
if( sqlite3StrAccumEnlargeIfNeeded(pAccum, szBufNeeded) ){
|
||||
width = length = 0;
|
||||
break;
|
||||
if( szBufNeeded + pAccum->nChar >= pAccum->nAlloc ){
|
||||
if( pAccum->mxAlloc==0 && pAccum->accError==0 ){
|
||||
/* Unable to allocate space in pAccum, perhaps because it
|
||||
** is coming from sqlite3_snprintf() or similar. We'll have
|
||||
** to render into temporary space and the memcpy() it over. */
|
||||
bufpt = sqlite3_malloc(szBufNeeded);
|
||||
if( bufpt==0 ){
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
|
||||
return;
|
||||
}
|
||||
zExtra = bufpt;
|
||||
}else if( sqlite3StrAccumEnlarge(pAccum, szBufNeeded)<szBufNeeded ){
|
||||
width = length = 0;
|
||||
break;
|
||||
}else{
|
||||
bufpt = pAccum->zText + pAccum->nChar;
|
||||
}
|
||||
}else{
|
||||
bufpt = pAccum->zText + pAccum->nChar;
|
||||
}
|
||||
bufpt = zOut = pAccum->zText + pAccum->nChar;
|
||||
zOut = bufpt;
|
||||
|
||||
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
|
||||
/* The sign in front of the number */
|
||||
@@ -728,14 +744,22 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
length = width;
|
||||
}
|
||||
pAccum->nChar += length;
|
||||
zOut[length] = 0;
|
||||
|
||||
/* Floating point conversions render directly into the output
|
||||
** buffer. Hence, don't just break out of the switch(). Bypass the
|
||||
** output buffer writing that occurs after the switch() by continuing
|
||||
** to the next character in the format string. */
|
||||
continue;
|
||||
if( zExtra==0 ){
|
||||
/* The result is being rendered directory into pAccum. This
|
||||
** is the command and fast case */
|
||||
pAccum->nChar += length;
|
||||
zOut[length] = 0;
|
||||
continue;
|
||||
}else{
|
||||
/* We were unable to render directly into pAccum because we
|
||||
** couldn't allocate sufficient memory. We need to memcpy()
|
||||
** the rendering (or some prefix thereof) into the output
|
||||
** buffer. */
|
||||
bufpt[0] = 0;
|
||||
bufpt = zExtra;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case etSIZE:
|
||||
if( !bArgList ){
|
||||
@@ -782,7 +806,7 @@ void sqlite3_str_vappendf(
|
||||
if( sqlite3StrAccumEnlargeIfNeeded(pAccum, nCopyBytes) ){
|
||||
break;
|
||||
}
|
||||
sqlite3_str_append(pAccum,
|
||||
sqlite3_str_append(pAccum,
|
||||
&pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
|
||||
precision -= nPrior;
|
||||
nPrior *= 2;
|
||||
@@ -885,8 +909,8 @@ void sqlite3_str_vappendf(
|
||||
** all control characters, and for backslash itself.
|
||||
** For %#Q, do the same but only if there is at least
|
||||
** one control character. */
|
||||
u32 nBack = 0;
|
||||
u32 nCtrl = 0;
|
||||
i64 nBack = 0;
|
||||
i64 nCtrl = 0;
|
||||
for(k=0; k<i; k++){
|
||||
if( escarg[k]=='\\' ){
|
||||
nBack++;
|
||||
@@ -1298,7 +1322,7 @@ void sqlite3_str_reset(StrAccum *p){
|
||||
** of its content, all in one call.
|
||||
*/
|
||||
void sqlite3_str_free(sqlite3_str *p){
|
||||
if( p ){
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
sqlite3_str_reset(p);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
+22
-4
@@ -774,6 +774,7 @@ static int lookupName(
|
||||
pExpr->op = TK_FUNCTION;
|
||||
pExpr->u.zToken = "coalesce";
|
||||
pExpr->x.pList = pFJMatch;
|
||||
pExpr->affExpr = SQLITE_AFF_DEFER;
|
||||
cnt = 1;
|
||||
goto lookupname_end;
|
||||
}else{
|
||||
@@ -942,6 +943,26 @@ static int exprProbability(Expr *p){
|
||||
return (int)(r*134217728.0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the EP_SubtArg property on every expression inside of
|
||||
** pList. If any subexpression is actually a subquery, then
|
||||
** also set the EP_SubtArg property on the first result-set
|
||||
** column of that subquery.
|
||||
*/
|
||||
static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
|
||||
int nn, ii;
|
||||
nn = pList ? pList->nExpr : 0;
|
||||
for(ii=0; ii<nn; ii++){
|
||||
Expr *pExpr = pList->a[ii].pExpr;
|
||||
ExprSetProperty(pExpr, EP_SubtArg);
|
||||
if( pExpr->op==TK_SELECT ){
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
assert( pExpr->x.pSelect!=0 );
|
||||
resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is callback for sqlite3WalkExpr().
|
||||
**
|
||||
@@ -1186,10 +1207,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
if( (pDef->funcFlags & SQLITE_SUBTYPE)
|
||||
|| ExprHasProperty(pExpr, EP_SubtArg)
|
||||
){
|
||||
int ii;
|
||||
for(ii=0; ii<n; ii++){
|
||||
ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
|
||||
}
|
||||
resolveSetExprSubtypeArg(pList);
|
||||
}
|
||||
|
||||
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
||||
|
||||
+5
-2
@@ -7324,6 +7324,7 @@ static SQLITE_NOINLINE void existsToJoin(
|
||||
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
|
||||
&& ALWAYS(p->pSrc!=0)
|
||||
&& p->pSrc->nSrc<BMS
|
||||
&& (p->pLimit==0 || p->pLimit->pRight==0)
|
||||
){
|
||||
if( pWhere->op==TK_AND ){
|
||||
Expr *pRight = pWhere->pRight;
|
||||
@@ -7371,7 +7372,6 @@ static SQLITE_NOINLINE void existsToJoin(
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
existsToJoin(pParse, p, pSubWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7432,8 +7432,11 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
|
||||
** does not refer to a table to the right of CheckOnCtx.iJoin. */
|
||||
do {
|
||||
SrcList *pSrc = pCtx->pSrc;
|
||||
int nSrc = pSrc->nSrc;
|
||||
int iTab = pExpr->iTable;
|
||||
if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
|
||||
int ii;
|
||||
for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){}
|
||||
if( ii<nSrc ){
|
||||
if( pCtx->iJoin && iTab>pCtx->iJoin ){
|
||||
sqlite3ErrorMsg(pWalker->pParse,
|
||||
"%s references tables to its right",
|
||||
|
||||
+10
-5
@@ -3787,7 +3787,7 @@ static const char *(azHelp[]) = {
|
||||
" --schema SCHEMA Use SCHEMA instead of \"main\"",
|
||||
" --help Show CMD details",
|
||||
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
|
||||
",headers on|off Turn display of headers on or off",
|
||||
".headers on|off Turn display of headers on or off",
|
||||
".help ?-all? ?PATTERN? Show help text for PATTERN",
|
||||
#ifndef SQLITE_SHELL_FIDDLE
|
||||
".import FILE TABLE Import data from FILE into TABLE",
|
||||
@@ -8570,8 +8570,7 @@ static int dotCmdOutput(ShellState *p){
|
||||
zBom = zBomUtf8;
|
||||
}else if( cli_strcmp(z,"-plain")==0 ){
|
||||
bPlain = 1;
|
||||
}else if( c=='o' && z[0]=='1' && z[1]!=0 && z[2]==0
|
||||
&& (z[1]=='x' || z[1]=='e' || z[1]=='w') ){
|
||||
}else if( c=='o' && sqlite3_strglob("-[ewx]",z)==0 ){
|
||||
if( bKeep || eMode ){
|
||||
dotCmdError(p, i, "incompatible with prior options",0);
|
||||
goto dotCmdOutput_error;
|
||||
@@ -12316,7 +12315,9 @@ static int runOneSqlLine(
|
||||
rc = shell_exec(p, zSql, &zErrMsg);
|
||||
END_TIMER(p);
|
||||
if( rc || zErrMsg ){
|
||||
char zPrefix[100];
|
||||
char zPrefix[2048
|
||||
/* must be relatively large:
|
||||
** https://sqlite.org/forum/forumpost/205f73db1b2806f5 */];
|
||||
const char *zErrorTail;
|
||||
const char *zErrorType;
|
||||
if( zErrMsg==0 ){
|
||||
@@ -13288,7 +13289,7 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
#ifndef SQLITE_SHELL_FIDDLE
|
||||
sqlite3_appendvfs_init(0,0,0);
|
||||
#ifdef SQLITE_DEBUG
|
||||
sqlite3_auto_extension( (void (*)())auto_ext_leak_tester );
|
||||
sqlite3_auto_extension( (void (*)(void))auto_ext_leak_tester );
|
||||
#endif
|
||||
#endif
|
||||
modeDefault(&data);
|
||||
@@ -13555,6 +13556,10 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
modePop(&data);
|
||||
data.nPopMode = 0;
|
||||
}
|
||||
if( rc ){
|
||||
goto shell_main_exit;
|
||||
}
|
||||
|
||||
}
|
||||
if( data.nPopOutput && azCmd[i][0]!='.' ){
|
||||
output_reset(&data);
|
||||
|
||||
+9
-1
@@ -5453,7 +5453,15 @@ void sqlite3AlterFunctions(void);
|
||||
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
|
||||
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
|
||||
void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
|
||||
void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
|
||||
void sqlite3AlterAddConstraint(
|
||||
Parse *pParse, /* Parse context */
|
||||
SrcList *pSrc, /* Table to add constraint to */
|
||||
Token *pFirst, /* First token of new constraint */
|
||||
Token *pName, /* Name of new constraint. NULL if name omitted. */
|
||||
const char *zExpr, /* Text of CHECK expression */
|
||||
int nExpr, /* Size of pExpr in bytes */
|
||||
Expr *pExpr /* The parsed CHECK expression */
|
||||
);
|
||||
void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
|
||||
i64 sqlite3GetToken(const unsigned char *, int *);
|
||||
void sqlite3NestedParse(Parse*, const char*, ...);
|
||||
|
||||
+11
-6
@@ -458,15 +458,20 @@ u8 sqlite3StrIHash(const char *z){
|
||||
return h;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_DISABLE_INTRINSIC) \
|
||||
&& (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || \
|
||||
(defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
|
||||
#define SQLITE_USE_UINT128
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Two inputs are multiplied to get a 128-bit result. Write the
|
||||
** lower 64-bits of the result into *pLo, and return the high-order
|
||||
** 64 bits.
|
||||
*/
|
||||
static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
|
||||
#if (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
|
||||
&& !defined(SQLITE_DISABLE_INTRINSIC)
|
||||
#if defined(SQLITE_USE_UINT128)
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
*pLo = (u64)r;
|
||||
return (u64)(r>>64);
|
||||
@@ -500,9 +505,7 @@ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
|
||||
** The lower 64 bits of A*B are discarded.
|
||||
*/
|
||||
static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
|
||||
#if (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
|
||||
&& !defined(SQLITE_DISABLE_INTRINSIC)
|
||||
#if defined(SQLITE_USE_UINT128)
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
r += ((__uint128_t)aLo * b) >> 32;
|
||||
*pLo = (r>>32)&0xffffffff;
|
||||
@@ -540,6 +543,8 @@ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SQLITE_USE_UINT128
|
||||
|
||||
/*
|
||||
** Return a u64 with the N-th bit set.
|
||||
*/
|
||||
|
||||
+7
-22
@@ -3187,7 +3187,8 @@ static int whereRangeVectorLen(
|
||||
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
|
||||
if( aff!=idxaff ) break;
|
||||
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
|
||||
if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
||||
if( pColl==0 ) break;
|
||||
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
|
||||
}
|
||||
@@ -7583,27 +7584,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
|
||||
}
|
||||
if( pTabList->a[pLevel->iFrom].fg.fromExists
|
||||
&& (i==pWInfo->nLevel-1
|
||||
|| pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
|
||||
){
|
||||
/* This is an EXISTS-to-JOIN optimization which is either the
|
||||
** inner-most loop, or the inner-most of a group of nested
|
||||
** EXISTS-to-JOIN optimization loops. If this loop sees a successful
|
||||
** row, it should break out of itself as well as other EXISTS-to-JOIN
|
||||
** loops in which is is directly nested. */
|
||||
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
|
||||
while( nOuter<i ){
|
||||
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
|
||||
nOuter++;
|
||||
}
|
||||
testcase( nOuter>0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
|
||||
if( nOuter ){
|
||||
VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
|
||||
}else{
|
||||
VdbeComment((v, "EXISTS break %d", i));
|
||||
}
|
||||
if( pTabList->a[pLevel->iFrom].fg.fromExists ){
|
||||
/* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
|
||||
** successful row, it should break out of itself. */
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
||||
VdbeComment((v, "EXISTS break %d", i));
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
||||
if( pLevel->op!=OP_Noop ){
|
||||
|
||||
+10
-2
@@ -2297,7 +2297,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
|
||||
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
|
||||
*/
|
||||
if( pWInfo->nLevel>1 ){
|
||||
if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
|
||||
int nNotReady; /* The number of notReady tables */
|
||||
SrcItem *origSrc; /* Original list of tables */
|
||||
nNotReady = pWInfo->nLevel - iLevel - 1;
|
||||
@@ -2310,6 +2310,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
for(k=1; k<=nNotReady; k++){
|
||||
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
|
||||
}
|
||||
|
||||
/* Clear the fromExists flag on the OR-optimized table entry so that
|
||||
** the calls to sqlite3WhereEnd() do not code early-exits after the
|
||||
** first row is visited. The early exit applies to this table's
|
||||
** overall loop - including the multiple OR branches and any WHERE
|
||||
** conditions not passed to the sub-loops - not to the sub-loops. */
|
||||
pOrTab->a[0].fg.fromExists = 0;
|
||||
}else{
|
||||
pOrTab = pWInfo->pTabList;
|
||||
}
|
||||
@@ -2553,7 +2560,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
assert( pLevel->op==OP_Return );
|
||||
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
||||
|
||||
if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
|
||||
if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
|
||||
if( !untestedTerms ) disableTerm(pLevel, pTerm);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
|
||||
@@ -2710,6 +2717,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
WO_EQ|WO_IN|WO_IS, 0);
|
||||
if( pAlt==0 ) continue;
|
||||
if( pAlt->wtFlags & (TERM_CODED) ) continue;
|
||||
if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
|
||||
if( (pAlt->eOperator & WO_IN)
|
||||
&& ExprUseXSelect(pAlt->pExpr)
|
||||
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
|
||||
|
||||
+5
-9
@@ -954,8 +954,8 @@ static void exprAnalyzeOrTerm(
|
||||
** 3. Not originating in the ON clause of an OUTER JOIN
|
||||
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
|
||||
** 5. The affinities of A and B must be compatible
|
||||
** 6a. Both operands use the same collating sequence OR
|
||||
** 6b. The overall collating sequence is BINARY
|
||||
** 6. Both operands use the same collating sequence, and they must not
|
||||
** use explicit COLLATE clauses.
|
||||
** If this routine returns TRUE, that means that the RHS can be substituted
|
||||
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
|
||||
** This is an optimization. No harm comes from returning 0. But if 1 is
|
||||
@@ -963,10 +963,9 @@ static void exprAnalyzeOrTerm(
|
||||
*/
|
||||
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
||||
char aff1, aff2;
|
||||
CollSeq *pColl;
|
||||
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
|
||||
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
|
||||
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
|
||||
if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
|
||||
assert( pSrc!=0 );
|
||||
if( pExpr->op==TK_IS
|
||||
&& pSrc->nSrc>=2
|
||||
@@ -981,10 +980,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
||||
){
|
||||
return 0; /* (5) */
|
||||
}
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
|
||||
if( !sqlite3IsBinary(pColl)
|
||||
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
|
||||
){
|
||||
if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
|
||||
return 0; /* (6) */
|
||||
}
|
||||
return 1;
|
||||
@@ -1316,7 +1312,7 @@ static void exprAnalyze(
|
||||
/* Analyze a term that is composed of two or more subterms connected by
|
||||
** an OR operator.
|
||||
*/
|
||||
else if( pExpr->op==TK_OR ){
|
||||
else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
|
||||
assert( pWC->op==TK_AND );
|
||||
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
|
||||
+15
-1
@@ -438,5 +438,19 @@ do_execsql_test 9.2.5 {
|
||||
SELECT sql FROM aux.sqlite_schema WHERE name='t2';
|
||||
} {{CREATE TABLE t2(x, y, z)}}
|
||||
|
||||
finish_test
|
||||
# Cannot add constraints the use internal functions.
|
||||
# Forum post 2026-05-10T01:11:28Z
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 10.1 {
|
||||
CREATE TABLE t1(x,y,z);
|
||||
INSERT INTO t1 VALUES(1,'two',x'3333');
|
||||
}
|
||||
do_catchsql_test 10.2 {
|
||||
ALTER TABLE t1 ADD CONSTRAINT c1 CHECK( sqlite_drop_column(22,'CREATE TABLE a(b,c)', 0));
|
||||
} {1 {no such function: sqlite_drop_column}}
|
||||
do_catchsql_test 10.3 {
|
||||
ALTER TABLE t1 ADD CONSTRAINT c1 CHECK( x>#2 );
|
||||
} {1 {near "#2": syntax error}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -243,5 +243,53 @@ do_execsql_test 11.2.3 {
|
||||
do_execsql_test 11.2.2 {ALTER TABLE t2 ALTER b SET NOT NULL --new cons
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 12.0 {
|
||||
CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER,
|
||||
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
ALTER TABLE Test DROP CONSTRAINT BooleanZeroOrOne
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {
|
||||
{CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER)}
|
||||
}
|
||||
|
||||
do_execsql_test 12.3 {
|
||||
DROP TABLE Test;
|
||||
CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER,
|
||||
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 12.4 {
|
||||
ALTER TABLE Test DROP CONSTRAINT "BooleanZeroOrOne"
|
||||
}
|
||||
|
||||
do_execsql_test 12.5 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {
|
||||
{CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER)}
|
||||
}
|
||||
|
||||
do_execsql_test 12.6 {
|
||||
CREATE TABLE t1(a, b CONSTRAINT "a""b" CHECK (b IS NOT NULL));
|
||||
}
|
||||
|
||||
do_execsql_test 12.7 {
|
||||
ALTER TABLE t1 DROP CONSTRAINT "a""b"
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+32
-15
@@ -333,20 +333,39 @@ do_execsql_test 5.7 {
|
||||
INSERT INTO t1(rowid, a, b, c, d) VALUES(7, 'X', 'Y', 'z', 'seven');
|
||||
}
|
||||
|
||||
do_execsql_test 5.8 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {
|
||||
zero two three
|
||||
}
|
||||
|
||||
do_execsql_test 5.9 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' COLLATE nocase
|
||||
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {
|
||||
zero four two
|
||||
three six seven
|
||||
if {1} {
|
||||
# Since 2026-05-18, SQLite does not attempt the OR-optimization on
|
||||
# conjuncts that contain COLLATE operators, due to
|
||||
# bug report 2026-05-17T11:46:40Z.
|
||||
do_catchsql_test 5.8 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {1 {no query solution}}
|
||||
|
||||
do_catchsql_test 5.9 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' COLLATE nocase
|
||||
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {1 {no query solution}}
|
||||
} else {
|
||||
# This case would work if SQLite knew how to deal with conjuncts that
|
||||
# contain COLLATE operators.
|
||||
do_execsql_test 5.8 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {
|
||||
zero two three
|
||||
}
|
||||
|
||||
do_execsql_test 5.9 {
|
||||
SELECT d FROM x1
|
||||
WHERE a='x' COLLATE nocase
|
||||
AND ((b='y' AND c='z') OR (b='Y' AND c='z' COLLATE nocase))
|
||||
} {
|
||||
zero four two
|
||||
three six seven
|
||||
}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
@@ -422,5 +441,3 @@ do_execsql_test 6.6 {
|
||||
} {555}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
int main(void){
|
||||
#ifdef SQLITE_ENABLE_SESSION
|
||||
sqlite3 *db;
|
||||
sqlite3_changegroup *pGrp;
|
||||
char *zErr = 0;
|
||||
char *buf = malloc(64);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
sqlite3_open(":memory:", &db);
|
||||
sqlite3_exec(db, "CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);", 0, 0, 0);
|
||||
|
||||
sqlite3changegroup_new(&pGrp);
|
||||
sqlite3changegroup_schema(pGrp, db, "main");
|
||||
sqlite3changegroup_change_begin(pGrp, SQLITE_INSERT, "t1", 0, &zErr);
|
||||
sqlite3changegroup_change_int64(pGrp, 1, 0, 42);
|
||||
|
||||
memset(buf, 'X', 64);
|
||||
|
||||
/* This should return an OOM error: */
|
||||
rc = sqlite3changegroup_change_blob(pGrp, 1, 1, buf, 2147483647);
|
||||
|
||||
free(buf);
|
||||
sqlite3changegroup_delete(pGrp);
|
||||
sqlite3_close(db);
|
||||
return (rc==7) ? 0 : -1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -164,4 +164,18 @@ do_test 300 {
|
||||
sqlite3_finalize $STMT
|
||||
sqlite3_finalize $STMT2
|
||||
|
||||
# 2026-05-31 dbsqlfuzz case 55c60cf7eb9e0f14c811b7c9227b8d2a0c32f022
|
||||
# 2026-06-01 dbsqlfuzz case 78e187a0fb61b19ff2e0cb76d4e8609df5248302
|
||||
# Probably also Bug 2026-06-01T07:23:11Z
|
||||
do_catchsql_test 400 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b INT) WITHOUT ROWID;
|
||||
WITH c(x) AS (
|
||||
VALUES(1)
|
||||
UNION
|
||||
SELECT x+1 FROM (carray NATURAL FULL JOIN carray(t1.b)), t1, c
|
||||
)
|
||||
SELECT * FROM c;
|
||||
} {1 {table-function argument references tables to its right}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -251,5 +251,19 @@ do_execsql_test 720 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 800 {
|
||||
CREATE TABLE x1(x);
|
||||
}
|
||||
|
||||
do_execsql_test 810 {
|
||||
SELECT pgno FROM sqlite_dbpage WHERE pgno=555
|
||||
} {}
|
||||
|
||||
do_execsql_test 820 {
|
||||
SELECT pgno FROM sqlite_dbpage WHERE pgno=4294967297
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -476,6 +476,29 @@ catch { optimization_control db exists-to-join 0 }
|
||||
db cache flush
|
||||
do_execsql_test 9.6 $Q {{big string value}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Forum post 2026-04-21T10:57:09Z
|
||||
do_execsql_test 9.7.1 {
|
||||
DROP TABLE t3;
|
||||
CREATE TABLE t3(x INT, y INT);
|
||||
CREATE TABLE t4(z INT);
|
||||
INSERT INTO t3 VALUES (1,0),(2,2),(3,3);
|
||||
INSERT INTO t4 VALUES (4),(5);
|
||||
}
|
||||
set Q {
|
||||
SELECT x FROM t3
|
||||
WHERE EXISTS(SELECT 1 FROM t4 WHERE z>y)
|
||||
LIMIT 1 OFFSET 1
|
||||
}
|
||||
catch { optimization_control db all 1 }
|
||||
db cache flush
|
||||
do_execsql_test 9.7.2 $Q {2}
|
||||
catch { optimization_control db exists-to-join 0 }
|
||||
db cache flush
|
||||
do_execsql_test 9.7.3 $Q {2}
|
||||
catch { optimization_control db all 1 }
|
||||
db cache flush
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -514,4 +537,96 @@ do_execsql_test 11.1 {
|
||||
GROUP BY id;
|
||||
} {1 p1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 12.0 {
|
||||
CREATE TABLE t2(id INT, data INT);
|
||||
CREATE TABLE t3(amount INT);
|
||||
|
||||
INSERT INTO t2 VALUES (1,0),(2,0);
|
||||
INSERT INTO t3 VALUES (1),(1);
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
SELECT * FROM t2
|
||||
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
|
||||
} {
|
||||
1 0
|
||||
2 0
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT * FROM t2
|
||||
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
|
||||
LIMIT 2 OFFSET 3
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 13.0 {
|
||||
CREATE TABLE t1(b,c);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE TABLE t3(p,q);
|
||||
|
||||
INSERT INTO t1 VALUES(7,10);
|
||||
INSERT INTO t2 VALUES(1,1), (4,7);
|
||||
INSERT INTO t3 VALUES(4,7);
|
||||
|
||||
PRAGMA automatic_index = 0;
|
||||
}
|
||||
|
||||
do_execsql_test 13.1 {
|
||||
SELECT * FROM t1 WHERE EXISTS (
|
||||
SELECT 1 FROM t2
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM t3 WHERE t3.p=t2.x AND t3.q=t1.b
|
||||
)
|
||||
)
|
||||
} {7 10}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Forum post https://sqlite.org/forum/forumpost/c8b205720c
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 14.1.0 {
|
||||
CREATE TABLE t(n INTEGER, parent INTEGER);
|
||||
CREATE INDEX idx ON t(parent);
|
||||
INSERT INTO t VALUES (1, NULL);
|
||||
INSERT INTO t VALUES (10, NULL);
|
||||
}
|
||||
|
||||
do_execsql_test 14.1.1 {
|
||||
SELECT count(*) FROM t b
|
||||
WHERE (b.parent IS NULL OR b.parent = 99)
|
||||
AND 5 <= +b.n
|
||||
} 1
|
||||
|
||||
do_execsql_test 14.1.2 {
|
||||
SELECT 'match' WHERE EXISTS (
|
||||
SELECT 1 FROM t b
|
||||
WHERE (b.parent IS NULL OR b.parent = 99)
|
||||
AND 5 <= +b.n
|
||||
)
|
||||
} {match}
|
||||
|
||||
do_execsql_test 14.2.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(20, 20);
|
||||
|
||||
CREATE TABLE t2(c, d);
|
||||
CREATE INDEX t2c ON t2(c);
|
||||
CREATE INDEX t2d ON t2(d);
|
||||
|
||||
INSERT INTO t2 VALUES(20, -1);
|
||||
INSERT INTO t2 VALUES(20, 0);
|
||||
}
|
||||
|
||||
do_execsql_test 14.2.2 {
|
||||
SELECT * FROM t1 WHERE EXISTS (
|
||||
SELECT 1 FROM t2 WHERE (c=a OR d=a) AND (d+1)>0
|
||||
)
|
||||
} {20 20}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -277,4 +277,72 @@ do_catchsql_test 2.1 {
|
||||
SELECT 0 FROM t1 WHERE t1 MATCH 'rtree NEAR rtree"json1 enable"';
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
set DEPTH 40000
|
||||
|
||||
proc fts3_put_varint {v} {
|
||||
set l [list]
|
||||
while {$v >= 0x80} {
|
||||
lappend l [expr ($v & 0x7F) | 0x80]
|
||||
set v [expr $v >> 7]
|
||||
}
|
||||
lappend l [expr $v & 0x7F]
|
||||
|
||||
binary format cu* $l
|
||||
}
|
||||
|
||||
proc make_interior_node {height child_blockid} {
|
||||
binary format a*a* [fts3_put_varint $height] [fts3_put_varint $child_blockid]
|
||||
}
|
||||
db func make_interior_node make_interior_node
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE fts USING fts3(content TEXT);
|
||||
INSERT INTO fts(content) VALUES ('hello world');
|
||||
DELETE FROM fts_segdir;
|
||||
INSERT INTO fts_segdir
|
||||
(level, idx, start_block, leaves_end_block, end_block, root) VALUES
|
||||
(0, 0, 100, 100 + $DEPTH, 100 + $DEPTH, make_interior_node($DEPTH+1, 100));
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
execsql BEGIN
|
||||
for {set ii 0} {$ii<$DEPTH} {incr ii} {
|
||||
execsql {
|
||||
INSERT INTO fts_segments(blockid, block)
|
||||
VALUES($ii+100, make_interior_node($DEPTH-$ii, 101+$ii))
|
||||
}
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM fts WHERE fts MATCH 'x';
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(content);
|
||||
DELETE FROM t1_segments;
|
||||
DELETE FROM t1_segdir;
|
||||
}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
INSERT INTO t1_segdir
|
||||
(level, idx, start_block, leaves_end_block, end_block, root)
|
||||
VALUES(0, 0, 0, 0, 0, X'000568656C6C6F08010201FFFFFF7F00');
|
||||
}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
CREATE VIRTUAL TABLE t1_terms USING fts4aux(t1);
|
||||
}
|
||||
|
||||
do_catchsql_test 4.4 {
|
||||
SELECT * FROM t1_terms;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
+17
-1
@@ -30,12 +30,19 @@ tvfs filter xWrite
|
||||
tvfs script write_cb
|
||||
|
||||
set ::trigger_interrupt 0
|
||||
set ::dbpointer ""
|
||||
proc write_cb {method args} {
|
||||
set filename [lindex $args 0]
|
||||
if {[file tail $filename]=="test.db" && $::trigger_interrupt} {
|
||||
if {$::trigger_interrupt} {
|
||||
incr ::trigger_interrupt -1
|
||||
if {$::trigger_interrupt==0} { sqlite3_interrupt db }
|
||||
if {$::trigger_interrupt==0} {
|
||||
if {$::dbpointer!=""} {
|
||||
sqlite3_interrupt $::dbpointer
|
||||
} else {
|
||||
sqlite3_interrupt db
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
@@ -110,8 +117,17 @@ db_save_and_close
|
||||
db_restore_and_reopen
|
||||
do_test 3.1.1 {
|
||||
set ::trigger_interrupt 10
|
||||
|
||||
# Set dbpointer here so that the write-callback can use the (sqlite3*)
|
||||
# pointer with sqlite3_interrupt() directly instead of looking up the
|
||||
# command. On at least some versions of Tcl9, looking up a command from
|
||||
# within Tcl_DeleteCommand apparently returns a bad pointer.
|
||||
#
|
||||
set ::dbpointer [sqlite3_connection_pointer db]
|
||||
db eval { SELECT * FROM sqlite_master }
|
||||
db close
|
||||
set ::dbpointer ""
|
||||
|
||||
set {} {}
|
||||
} {}
|
||||
do_test 3.1.2 {
|
||||
|
||||
+37
-1
@@ -211,5 +211,41 @@ do_execsql_test 7.3 {
|
||||
);
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
#--------------------------------------------------------------------------
|
||||
# Forum post 2026-05-15T11:23:01Z
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
CREATE TABLE t1(x REAL);
|
||||
CREATE TABLE t2(x REAL);
|
||||
INSERT INTO t1 VALUES(2.5);
|
||||
INSERT INTO t2 VALUES(2.5);
|
||||
SELECT x FROM t1 JOIN t2 USING(x) WHERE x='2.5';
|
||||
} 2.5
|
||||
do_execsql_test 8.1 {
|
||||
SELECT x FROM t1 LEFT JOIN t2 USING(x) WHERE x='2.5';
|
||||
} 2.5
|
||||
do_execsql_test 8.2 {
|
||||
SELECT x FROM t1 RIGHT JOIN t2 USING(x) WHERE x='2.5';
|
||||
} 2.5
|
||||
do_execsql_test 8.3 {
|
||||
SELECT x FROM t1 FULL JOIN t2 USING(x) WHERE x='2.5';
|
||||
} 2.5
|
||||
do_execsql_test 8.10 {
|
||||
CREATE TABLE t3(x TEXT COLLATE nocase);
|
||||
CREATE TABLE t4(x TEXT COLLATE nocase);
|
||||
INSERT INTO t3 VALUES('abc');
|
||||
INSERT INTO t4 VALUES('ABC');
|
||||
SELECT lower(x) FROM t3 JOIN t4 USING(x) WHERE x='Abc';
|
||||
} abc
|
||||
do_execsql_test 8.11 {
|
||||
SELECT lower(x) FROM t3 LEFT JOIN t4 USING(x) WHERE x='Abc';
|
||||
} abc
|
||||
do_execsql_test 8.12 {
|
||||
SELECT lower(x) FROM t3 RIGHT JOIN t4 USING(x) WHERE x='Abc';
|
||||
} abc
|
||||
do_execsql_test 8.13 {
|
||||
SELECT lower(x) FROM t3 FULL JOIN t4 USING(x) WHERE x='Abc';
|
||||
} abc
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1178,4 +1178,11 @@ foreach {id start path ins set repl} {
|
||||
} [list [tx $repl]]
|
||||
}
|
||||
|
||||
# 2026-05-29
|
||||
# JSON floating point precision
|
||||
#
|
||||
do_execsql_test json101-25.1 {
|
||||
SELECT json_array(0.1234567890123456789)->>0 = 0.1234567890123456789;
|
||||
} 1
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -280,4 +280,41 @@ do_test 900 {
|
||||
} 1
|
||||
dbempty close
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Make sure a database cannot be overwritten by deserialize() if
|
||||
# there is an open transaction on it.
|
||||
#
|
||||
do_execsql_test 1000 {
|
||||
CREATE TABLE t(x);
|
||||
INSERT INTO t VALUES(1),(2);
|
||||
}
|
||||
|
||||
set blob [db serialize main]
|
||||
|
||||
do_test 1010 {
|
||||
set seen 0
|
||||
list [catch {
|
||||
db eval {SELECT x FROM t} {
|
||||
incr seen
|
||||
if {$seen == 1} {
|
||||
db deserialize main $blob
|
||||
}
|
||||
}
|
||||
} msg] $msg
|
||||
} {1 {unable to set MEMDB content}}
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
do_test 1020 {
|
||||
set seen 0
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 2
|
||||
set res [list [catch {
|
||||
db deserialize main $blob
|
||||
} msg] $msg]
|
||||
B finish
|
||||
set res
|
||||
} {1 {unable to set MEMDB content}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -159,4 +159,60 @@ do_hasmj_test 2.3 {
|
||||
COMMIT;
|
||||
} {0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
PRAGMA synchronous = OFF;
|
||||
CREATE TABLE t1(x, y);
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(100, 200);
|
||||
}
|
||||
|
||||
db_save
|
||||
db close
|
||||
db_restore
|
||||
|
||||
do_test 3.2 {
|
||||
|
||||
# Append super-journal name to test.db-journal
|
||||
#
|
||||
set mjname [file join [pwd] test.db-super]
|
||||
binary scan $mjname c* bytes
|
||||
set cksum 0
|
||||
foreach b $bytes { incr cksum $b }
|
||||
set fd [open test.db-journal a+]
|
||||
fconfigure $fd -translation binary -encoding iso8859-1
|
||||
puts -nonewline $fd $mjname
|
||||
puts -nonewline $fd [binary format I [string length $mjname]]
|
||||
puts -nonewline $fd [binary format I $cksum]
|
||||
puts -nonewline $fd [binary decode hex "d9d505f920a163d7"]
|
||||
close $fd
|
||||
|
||||
# Create super-journal
|
||||
#
|
||||
set fd [open test.db-super w]
|
||||
fconfigure $fd -translation binary -encoding iso8859-1
|
||||
puts -nonewline $fd "test2.db-journal\0test.db-journal\0"
|
||||
close $fd
|
||||
|
||||
# Create corrupt child journal
|
||||
#
|
||||
set fd [open test2.db-journal w]
|
||||
fconfigure $fd -translation binary -encoding iso8859-1
|
||||
puts -nonewline $fd [binary decode hex "00200001[string repeat 41 512]"]
|
||||
puts -nonewline $fd [binary decode hex "0000020000008200d9d505f920a163d7"]
|
||||
close $fd
|
||||
} {}
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 3.3 {
|
||||
SELECT type, name, tbl_name, sql FROM sqlite_schema
|
||||
} {table t1 t1 {CREATE TABLE t1(x, y)}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -79,7 +79,23 @@ SELECT * FROM t2;
|
||||
│ │ Quoted" │ │ │
|
||||
╰────────────┴────────────┴─────────┴─────────╯
|
||||
END
|
||||
.testcase 121
|
||||
.mode tty --wrap 1 --limits off
|
||||
SELECT 'xyz123' AS a, 2 AS b;
|
||||
.check <<END
|
||||
╭───┬───╮
|
||||
│ a │ b │
|
||||
╞═══╪═══╡
|
||||
│ x │ 2 │
|
||||
│ y │ │
|
||||
│ z │ │
|
||||
│ 1 │ │
|
||||
│ 2 │ │
|
||||
│ 3 │ │
|
||||
╰───┴───╯
|
||||
END
|
||||
.testcase 130
|
||||
.mode tty -wrap 10
|
||||
.mode
|
||||
.check <<END
|
||||
.mode qbox --limits on --quote relaxed --sw auto --textjsonb on
|
||||
|
||||
@@ -336,6 +336,34 @@ do_execsql_test 10.51 {
|
||||
ORDER BY +d NULLS LAST, +c NULLS LAST;
|
||||
} {X 3 X | X 4 X | X 5 X | X 7 X | X {} X | {} {} {} | Y {} {} |}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
CREATE TABLE t1(a TEXT COLLATE NOCASE, b TEXT);
|
||||
INSERT INTO t1 VALUES('Hello', 'world');
|
||||
}
|
||||
|
||||
foreach {tn sql res} {
|
||||
0 "SELECT null" NULL
|
||||
|
||||
1 "SELECT ('hello', NULL) IN (SELECT a, b FROM t1)" NULL
|
||||
2 "SELECT NOT ('hello', NULL) IN (SELECT a, b FROM t1)" NULL
|
||||
|
||||
3 "SELECT ('Hello', NULL) IN (SELECT a, b FROM t1)" NULL
|
||||
4 "SELECT ('Hello' COLLATE NOCASE, NULL) IN (SELECT a, b FROM t1)" NULL
|
||||
5 "SELECT ('hello', 'world') IN (SELECT a, b FROM t1)" 1
|
||||
|
||||
6 "SELECT ('hi', NULL) IN (SELECT a, b FROM t1)" 0
|
||||
|
||||
7 "SELECT ('hello', NULL) IN ((a, b), (3, 4), (5, 6)) FROM t1" 0
|
||||
8 "SELECT (a, b) IN (('hello', NULL), (3, 4), (5, 6)) FROM t1" NULL
|
||||
|
||||
9 "SELECT ('Hello', NULL) IN ((a, b), (3, 4), (5, 6)) FROM t1" NULL
|
||||
} {
|
||||
db nullvalue NULL
|
||||
do_execsql_test 11.2.$tn $sql $res
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -592,4 +592,15 @@ do_execsql_test percentile-6.0 {
|
||||
SELECT median(iif(n%2,0.1,1.0)) FROM c;
|
||||
} 0.55
|
||||
|
||||
# Bug 2026-06-03T07:26:42Z
|
||||
# Use tail recursion in percentSort() to prevent stack overflow
|
||||
#
|
||||
do_execsql_test percentile-7.0 {
|
||||
WITH RECURSIVE t1(n,x) AS (
|
||||
VALUES(1,1.0)
|
||||
UNION ALL
|
||||
SELECT n+1, if(n%2,n*2.0,999998.0-2.0*n) FROM t1 WHERE n<1000000
|
||||
) SELECT median(x) FROM t1;
|
||||
} 499998.0
|
||||
|
||||
finish_test
|
||||
|
||||
+13
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix unionvtab
|
||||
set testprefix prefixes
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
@@ -85,4 +85,16 @@ foreach {tn INPUT expected} {
|
||||
} $expected
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT prefix_length(null,'abc');
|
||||
} 0
|
||||
do_execsql_test 3.2 {
|
||||
SELECT prefix_length('abc',null);
|
||||
} 0
|
||||
|
||||
# Bug 2026-06-03T07:42:00Z
|
||||
do_execsql_test 3.3 {
|
||||
SELECT prefix_length(zeroblob(15000),zeroblob(5000));
|
||||
} 0
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -239,6 +239,20 @@ do_test 1.71 {
|
||||
<TD>Ἀμήν
|
||||
</TR>
|
||||
}
|
||||
do_test 1.72 {
|
||||
set result "\n[db format -style html {
|
||||
SELECT 'ab<cd' AS a, 'ab&cd' as b,
|
||||
'ab>cd' AS c, 'ab"cd' AS d,
|
||||
'xy''z' AS e}]"
|
||||
} {
|
||||
<TR>
|
||||
<TD>ab<cd
|
||||
<TD>ab&cd
|
||||
<TD>ab>cd
|
||||
<TD>ab"cd
|
||||
<TD>xy'z
|
||||
</TR>
|
||||
}
|
||||
|
||||
do_test 1.80 {
|
||||
set result "\n[db format -style insert {SELECT * FROM t1}]"
|
||||
|
||||
@@ -854,5 +854,19 @@ do_execsql_test 35.1 {
|
||||
SELECT (1, 'a') IN (SELECT c2, c1 from t1);
|
||||
} 1
|
||||
|
||||
# Forum post 2026-05-09T07:55:45Z
|
||||
#
|
||||
do_execsql_test 36.0 {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1),(2),(3);
|
||||
SELECT (1,2,3,max(x)) IN () FROM t1;
|
||||
} 0
|
||||
do_execsql_test 36.1 {
|
||||
SELECT (1,2,max(x),3) IN () FROM t1;
|
||||
} 0
|
||||
do_execsql_test 36.2 {
|
||||
SELECT (max(x),1,23) IN () FROM t1;
|
||||
} 0
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -121,5 +121,25 @@ do_execsql_test 4.3 {
|
||||
SELECT * FROM t0, t1 WHERE (t1.c1, t1.c0) <= (t0.c0, t0.c0);
|
||||
} {True a 1 True a True}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Bug report https://sqlite.org/bugs/info/2026-05-17T11:59:19Z
|
||||
#
|
||||
do_execsql_test 5.1 {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a TEXT, b TEXT);
|
||||
CREATE INDEX t1_ab ON t1(a COLLATE NOCASE, b COLLATE NOCASE);
|
||||
INSERT INTO t1 VALUES('a',null),('b', 'ABCD');
|
||||
}
|
||||
db null NULL
|
||||
do_execsql_test 5.2 {
|
||||
SELECT * FROM t1
|
||||
WHERE ('B' COLLATE nocase,'abc')>(a,b)
|
||||
ORDER BY +a;
|
||||
} {a NULL b ABCD}
|
||||
do_execsql_test 5.3 {
|
||||
SELECT * FROM t1 NOT INDEXED
|
||||
WHERE ('B' COLLATE nocase,'abc')>(a,b)
|
||||
ORDER BY +a;
|
||||
} {a NULL b ABCD}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -350,4 +350,14 @@ do_execsql_test 320 {
|
||||
)
|
||||
} {69d0a31872203a775e19325ea98cd053}
|
||||
|
||||
do_catchsql_test 400 {
|
||||
SELECT editdist3(format('%.10001c','x'),'abc');
|
||||
} {1 {string or blob too big}}
|
||||
do_catchsql_test 401 {
|
||||
SELECT editdist3('xxxabc',format('%.10001c','x'));
|
||||
} {1 {string or blob too big}}
|
||||
do_catchsql_test 410 {
|
||||
SELECT editdist3(format('abc%.9997c','x'),format('abc%.9997c','x'));
|
||||
} {0 0}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -84,4 +84,33 @@ do_execsql_test subtype1-400 {
|
||||
SELECT id, subtype(if(json_valid(j,6),j->'a')) FROM t400;
|
||||
} {1 74 2 0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that indexes on expressions do not alter subtypes.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test subtype1-500 {
|
||||
CREATE TABLE t1(id, j);
|
||||
INSERT INTO t1 VALUES (1,'{a:{x:1,y:2},b:{x:3,y:4}}'), (2,'not json');
|
||||
}
|
||||
|
||||
foreach {tn expr st} {
|
||||
510 "(CASE WHEN json_valid(j, 6) THEN j->'a' ELSE j END)" 74
|
||||
520 "+(CASE WHEN json_valid(j, 6) THEN j->'a' ELSE j END)" 74
|
||||
530 "-(CASE WHEN json_valid(j, 6) THEN j->'a' ELSE j END)" 0
|
||||
540 "if( json_valid(j, 6), j->'a' ) " 74
|
||||
550 "if( json_valid(j, 6), j->'a' ) COLLATE nocase" 74
|
||||
560 "CAST( if( json_valid(j, 6), j->'a' ) AS TEXT )" 74
|
||||
} {
|
||||
do_execsql_test subtype1-$tn.1 "
|
||||
SELECT id, subtype( $expr ) FROM t1;
|
||||
" [list 1 $st 2 0]
|
||||
|
||||
do_execsql_test subtype1-$tn.2 "
|
||||
DROP INDEX IF EXISTS i1;
|
||||
CREATE INDEX i1 ON t1( $expr );
|
||||
SELECT id, subtype( $expr ) FROM t1 INDEXED BY i1 ORDER BY id;
|
||||
" [list 1 $st 2 0]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -668,6 +668,39 @@ do_execsql_test 1370 {
|
||||
SELECT * FROM generate_series(0,0,0);
|
||||
} {}
|
||||
|
||||
# Forum post 2026-05-09T07:41:32Z
|
||||
set subtest 1
|
||||
foreach bound {
|
||||
9007199254740991.0
|
||||
9007199254740991.1
|
||||
9007199254740991.5
|
||||
9007199254740991.9
|
||||
9007199254740992.0
|
||||
9007199254740992.1
|
||||
9007199254740992.5
|
||||
9007199254740992.9
|
||||
9007199254740993.0
|
||||
9007199254740993.1
|
||||
9007199254740993.5
|
||||
} {
|
||||
foreach {range boundsign} {
|
||||
(+9007199254740990,+9007199254740995) +
|
||||
(-9007199254740995,-9007199254740990) -
|
||||
} {
|
||||
set bx $boundsign$bound
|
||||
foreach op {< > <= >=} {
|
||||
do_execsql_test 1380.$subtest "
|
||||
SELECT 'value $op $bx' WHERE (
|
||||
SELECT group_concat(value) FROM generate_series $range
|
||||
WHERE value $op $bx)<>(
|
||||
SELECT group_concat(value) FROM generate_series $range
|
||||
WHERE +value $op $bx);
|
||||
" {}
|
||||
incr subtest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reset_db
|
||||
load_static_extension db series
|
||||
do_execsql_test 1400 {
|
||||
|
||||
@@ -127,6 +127,7 @@ Special values for PERMUTATION include:
|
||||
mdevtest - tests recommended prior to normal development check-ins.
|
||||
devtest - alias for "mdevtest"
|
||||
release - full release test with various builds.
|
||||
c - tests in test/c directory only.
|
||||
sdevtest - like mdevtest but using ASAN and UBSAN.
|
||||
all - all tcl test scripts, plus a subset of test scripts rerun
|
||||
with various permutations.
|
||||
@@ -1514,6 +1515,13 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
}
|
||||
}
|
||||
|
||||
c {
|
||||
set patternlist [lrange $patternlist 1 end]
|
||||
foreach b [trd_builds $TRG(platform)] {
|
||||
add_c_jobs $b $patternlist
|
||||
}
|
||||
}
|
||||
|
||||
list {
|
||||
set allperm [array names ::testspec]
|
||||
lappend allperm all devtest mdevtest sdevtest release list
|
||||
|
||||
+98
-1
@@ -14,6 +14,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix transitive1
|
||||
|
||||
do_execsql_test transitive1-100 {
|
||||
CREATE TABLE t1(a TEXT, b TEXT, c TEXT COLLATE NOCASE);
|
||||
@@ -351,7 +352,7 @@ do_execsql_test transitive1-570 {
|
||||
do_execsql_test transitive1-570eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
|
||||
} {/SEARCH c1 USING INDEX c1x/}
|
||||
} {/SCAN c1/}
|
||||
|
||||
# 2021-05-04 forum https://sqlite.org/forum/forumpost/eb8613976a
|
||||
reset_db
|
||||
@@ -426,4 +427,100 @@ do_execsql_test transitive1-813 {
|
||||
SELECT * FROM t3 WHERE a=b AND a='5x';
|
||||
} {}
|
||||
|
||||
# Bug 2026-05-21T03:39:28Z
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test transitive1-900 {
|
||||
CREATE TABLE t1(a TEXT);
|
||||
CREATE TABLE t2(b TEXT COLLATE NOCASE);
|
||||
INSERT INTO t1 VALUES('abc');
|
||||
INSERT INTO t2 VALUES('abc');
|
||||
SELECT * FROM t1 CROSS JOIN t2 WHERE a=b AND b='ABC';
|
||||
} {abc abc}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
db cache size 0
|
||||
|
||||
do_execsql_test 1000 {
|
||||
PRAGMA automatic_index = 0;
|
||||
|
||||
CREATE TABLE t1(a TEXT);
|
||||
CREATE TABLE t2(b TEXT);
|
||||
|
||||
INSERT INTO t1 VALUES ('hello');
|
||||
INSERT INTO t1 VALUES ('Hello');
|
||||
INSERT INTO t1 VALUES ('HELLO');
|
||||
INSERT INTO t1 VALUES ('HeLLo');
|
||||
|
||||
INSERT INTO t2 VALUES ('hello');
|
||||
INSERT INTO t2 VALUES ('Hello');
|
||||
INSERT INTO t2 VALUES ('HELLO');
|
||||
INSERT INTO t2 VALUES ('HeLLo');
|
||||
}
|
||||
|
||||
optimization_control db transitive 1
|
||||
|
||||
do_execsql_test 1010 {
|
||||
SELECT t1.a, t2.b
|
||||
FROM t1 CROSS JOIN t2
|
||||
WHERE t1.a = t2.b
|
||||
AND t2.b COLLATE NOCASE = 'Hello';
|
||||
} {
|
||||
hello hello
|
||||
Hello Hello
|
||||
HELLO HELLO
|
||||
HeLLo HeLLo
|
||||
}
|
||||
|
||||
optimization_control db transitive 0
|
||||
|
||||
do_execsql_test 1020 {
|
||||
SELECT t1.a, t2.b
|
||||
FROM t1 CROSS JOIN t2
|
||||
WHERE t1.a = t2.b
|
||||
AND t2.b COLLATE NOCASE = 'Hello';
|
||||
} {
|
||||
hello hello
|
||||
Hello Hello
|
||||
HELLO HELLO
|
||||
HeLLo HeLLo
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 1100 {
|
||||
PRAGMA automatic_index = 0;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(y);
|
||||
|
||||
INSERT INTO t1 VALUES('ABC');
|
||||
INSERT INTO t2 VALUES('abc');
|
||||
}
|
||||
|
||||
do_execsql_test 1110 {
|
||||
SELECT * FROM t1 CROSS JOIN t2
|
||||
WHERE (t1.x COLLATE nocase) = (t2.y COLLATE nocase)
|
||||
AND (t2.y = 'ABC')
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 1200 {
|
||||
PRAGMA automatic_index = 0;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE TABLE t2(y);
|
||||
|
||||
INSERT INTO t1 VALUES('ABC');
|
||||
INSERT INTO t2 VALUES('ABC');
|
||||
}
|
||||
|
||||
do_execsql_test 1210 {
|
||||
SELECT * FROM t1 CROSS JOIN t2
|
||||
WHERE t1.x = t2.y
|
||||
AND (t1.x COLLATE nocase = 'abc')
|
||||
} {ABC ABC}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -787,4 +787,14 @@ do_eqp_test update-21.12 {
|
||||
`--SEARCH t3 USING AUTOMATIC COVERING INDEX (x=?)
|
||||
}
|
||||
|
||||
# /forumpost/2026-04-21T19:10:55Z
|
||||
do_execsql_test update-22.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x INT, y INT);
|
||||
INSERT INTO t1(x) VALUES(1),(2),(3),(4),(5);
|
||||
UPDATE t1 SET x=x+100, y=x<=(SELECT min(x) FROM t1)
|
||||
WHERE x<3 OR (1 BETWEEN 0 AND x<=(SELECT min(x)+2 FROM t1));
|
||||
SELECT x FROM t1 WHERE x<100 ORDER BY x;
|
||||
} {4 5}
|
||||
|
||||
finish_test
|
||||
|
||||
+12
-2
@@ -828,7 +828,17 @@ do_execsql_test where2-16.2 {
|
||||
AND t1.a=t4.h;
|
||||
} {~/.* t[34] .* t1 .*/}
|
||||
|
||||
|
||||
|
||||
# 2026-05-18 bug report 2026-05-17T11:46:40Z
|
||||
#
|
||||
do_execsql_test where2-17.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a TEXT);
|
||||
INSERT INTO t1 VALUES('A'),('b');
|
||||
SELECT * FROM t1 WHERE (a='a' COLLATE nocase) OR a='b' ORDER BY +a;
|
||||
} {A b}
|
||||
do_execsql_test where2-17.1 {
|
||||
CREATE INDEX t1_a ON t1(a);
|
||||
SELECT * FROM t1 WHERE (a='a' COLLATE nocase) OR a='b' ORDER BY +a;
|
||||
} {A b}
|
||||
|
||||
finish_test
|
||||
|
||||
+122
-1
@@ -201,6 +201,128 @@ ifcapable json1 {
|
||||
{{"a":{"a":1,"e":9}}}
|
||||
{{"c":{"c":3,"e":9}}}
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Bug report 2026-05-18T12:34:42Z
|
||||
#
|
||||
# The xInverse() method used by json_group_object() should correctly
|
||||
# account for NULL entries.
|
||||
#
|
||||
do_execsql_test 3.8 {
|
||||
CREATE TABLE t1(id INT, k TEXT, v INT);
|
||||
INSERT INTO t1 VALUES
|
||||
(1, 'a', 1),
|
||||
(2, 'b', 2),
|
||||
(3, 'c', 3),
|
||||
(4, 'd', 4),
|
||||
(5, 'f', 5),
|
||||
(6, 'g', 6),
|
||||
(7, 'h', 7);
|
||||
}
|
||||
do_execsql_test 3.9 {
|
||||
SELECT id, json_group_object(if(id<>1,k),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{"b":2}}
|
||||
2 {{"b":2,"c":3}}
|
||||
3 {{"b":2,"c":3,"d":4}}
|
||||
4 {{"c":3,"d":4,"f":5}}
|
||||
5 {{"d":4,"f":5,"g":6}}
|
||||
6 {{"f":5,"g":6,"h":7}}
|
||||
7 {{"g":6,"h":7}}
|
||||
}
|
||||
do_execsql_test 3.10 {
|
||||
SELECT id, json_group_object(if(id>4,k),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{}}
|
||||
2 {{}}
|
||||
3 {{}}
|
||||
4 {{"f":5}}
|
||||
5 {{"f":5,"g":6}}
|
||||
6 {{"f":5,"g":6,"h":7}}
|
||||
7 {{"g":6,"h":7}}
|
||||
}
|
||||
do_execsql_test 3.11 {
|
||||
SELECT id, json_group_object(if(id>4,k||'@'),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{}}
|
||||
2 {{}}
|
||||
3 {{}}
|
||||
4 {{"f@":5}}
|
||||
5 {{"f@":5,"g@":6}}
|
||||
6 {{"f@":5,"g@":6,"h@":7}}
|
||||
7 {{"g@":6,"h@":7}}
|
||||
}
|
||||
do_execsql_test 3.12 {
|
||||
SELECT id, json_group_object(k,v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{"a":1,"b":2}}
|
||||
2 {{"a":1,"b":2,"c":3}}
|
||||
3 {{"b":2,"c":3,"d":4}}
|
||||
4 {{"c":3,"d":4,"f":5}}
|
||||
5 {{"d":4,"f":5,"g":6}}
|
||||
6 {{"f":5,"g":6,"h":7}}
|
||||
7 {{"g":6,"h":7}}
|
||||
}
|
||||
do_execsql_test 3.13 {
|
||||
SELECT id, json_group_object(if(id>1 AND id<7,k),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{"b":2}}
|
||||
2 {{"b":2,"c":3}}
|
||||
3 {{"b":2,"c":3,"d":4}}
|
||||
4 {{"c":3,"d":4,"f":5}}
|
||||
5 {{"d":4,"f":5,"g":6}}
|
||||
6 {{"f":5,"g":6}}
|
||||
7 {{"g":6}}
|
||||
}
|
||||
do_execsql_test 3.14 {
|
||||
SELECT id, json_group_object(if(id>2 AND id<6,k),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{}}
|
||||
2 {{"c":3}}
|
||||
3 {{"c":3,"d":4}}
|
||||
4 {{"c":3,"d":4,"f":5}}
|
||||
5 {{"d":4,"f":5}}
|
||||
6 {{"f":5}}
|
||||
7 {{}}
|
||||
}
|
||||
do_execsql_test 3.15 {
|
||||
SELECT id, json_group_object(if(id<2 OR id>6,k),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{"a":1}}
|
||||
2 {{"a":1}}
|
||||
3 {{}}
|
||||
4 {{}}
|
||||
5 {{}}
|
||||
6 {{"h":7}}
|
||||
7 {{"h":7}}
|
||||
}
|
||||
do_execsql_test 3.16 {
|
||||
SELECT id, json_group_object(if(id<3 OR id>5,k),v) OVER
|
||||
(ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS jx
|
||||
FROM t1;
|
||||
} {
|
||||
1 {{"a":1,"b":2}}
|
||||
2 {{"a":1,"b":2}}
|
||||
3 {{"b":2}}
|
||||
4 {{}}
|
||||
5 {{"g":6}}
|
||||
6 {{"g":6,"h":7}}
|
||||
7 {{"g":6,"h":7}}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -483,4 +605,3 @@ if {[permutation]!="no_optimization"} {
|
||||
}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+58
-1
@@ -62,7 +62,6 @@ do_execsql_test 2.0 {
|
||||
|
||||
sqlite3_create_aggregate db
|
||||
|
||||
breakpoint
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT min(x) OVER w1 FROM t1
|
||||
WINDOW w1 AS (PARTITION BY x_count(x) OVER w1);
|
||||
@@ -105,6 +104,64 @@ do_execsql_test 3.1 {
|
||||
537 1.0 538 1.0 539 1.0 540 1.0 543 1.0 544 1.0
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(2, 9223372036854775807);
|
||||
INSERT INTO t1 VALUES(3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4);
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
SELECT a,
|
||||
total(b) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
|
||||
FROM t1;
|
||||
} {
|
||||
1 9.22337203685478e+18 2 9.22337203685478e+18 3 7.0 4 4.0
|
||||
}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
SELECT a,
|
||||
total(b) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM t1;
|
||||
} {
|
||||
1 9.22337203685478e+18 2 9.22337203685478e+18 3 7.0 4 4.0
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t(id, x);
|
||||
INSERT INTO t VALUES(1, -1);
|
||||
INSERT INTO t VALUES(2, 9223372036854775807);
|
||||
INSERT INTO t VALUES(3, 1);
|
||||
INSERT INTO t VALUES(4, 0.5);
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
SELECT id,
|
||||
sum(id) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM t t1
|
||||
} {
|
||||
1 6
|
||||
2 9
|
||||
3 7
|
||||
4 4
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 5.2 {
|
||||
SELECT id,
|
||||
sum(x) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING)
|
||||
FROM t t1
|
||||
} {
|
||||
1 9223372036854775807
|
||||
2 9.22337203685478e+18
|
||||
3 1.5
|
||||
4 0.5
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -914,4 +914,31 @@ do_catchsql_test 21.0 {
|
||||
SELECT * FROM zipfile(X'504B03040A0000000000000000000000000000000000000000000100000078504B010200000A0000000000000000000000000000000000000000000100000000000000000000000000E2FFFFFF78504B050600000000010001002F0000001F0000000000');
|
||||
} {1 {failed to read LFH at offset -30}}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
load_static_extension db zipfile
|
||||
|
||||
# This test requires a non-default SQLITE_MAX_LENGTH value to run.
|
||||
#
|
||||
if {[catch {db one {SELECT length( zeroblob(1200000000) )}}]==0} {
|
||||
do_catchsql_test 23.0 {
|
||||
SELECT length(zipfile(name,0,0,data,0)) FROM (
|
||||
SELECT 'a' AS name, zeroblob(1000000000) AS data
|
||||
UNION ALL SELECT 'b', zeroblob(1200000000)
|
||||
);
|
||||
} {1 {out of memory}}
|
||||
}
|
||||
|
||||
# Bug 2026-06-03T10:58:51Z
|
||||
do_catchsql_test 25.0 {
|
||||
WITH t(v) AS (
|
||||
SELECT unhex(
|
||||
'504B03041400000000000000000000000000000000000000000001000000
|
||||
61504B01021E031400000000000000000000000000000000000000000001
|
||||
000000000000000000000000000000000061504B05060000000001000100
|
||||
2F0000001F0000000000',char(10,13,32))
|
||||
UNION ALL SELECT 'x'
|
||||
) SELECT z.name FROM t, zipfile(t.v) AS z;
|
||||
} {1 {cannot open file: x}}
|
||||
finish_test
|
||||
|
||||
+10
-5
@@ -17,7 +17,8 @@ Options:
|
||||
--uninstall Uninstall the extension
|
||||
--version-check Check extension version against this source tree
|
||||
--destdir DIR Installation root (used by "make install DESTDIR=...")
|
||||
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
|
||||
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
|
||||
--extlibs LDFLAGS required for external libs, e.g. ICU.
|
||||
|
||||
Other options are retained and passed through into the compiler.}
|
||||
|
||||
@@ -29,8 +30,9 @@ set infoonly 0
|
||||
set versioncheck 0
|
||||
set CC {}
|
||||
set OPTS {}
|
||||
set DESTDIR ""; # --destdir "$(DESTDIR)"
|
||||
set DESTDIR "" ; # --destdir "$(DESTDIR)"
|
||||
set tclConfigSh ""; # --tclConfig.sh FILE
|
||||
set LIBS {} ; # --extlibs "-lx -ly ..."
|
||||
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
|
||||
set a0 [lindex $argv $ii]
|
||||
if {$a0=="--install-only"} {
|
||||
@@ -61,6 +63,9 @@ for {set ii 0} {$ii<[llength $argv]} {incr ii} {
|
||||
} elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} {
|
||||
incr ii
|
||||
set tclConfigSh [lindex $argv $ii]
|
||||
} elseif {$a0=="--extlibs" && $ii+1<[llength $argv]} {
|
||||
incr ii
|
||||
lappend LIBS [lindex $argv $ii]
|
||||
} elseif {[string match -* $a0]} {
|
||||
append OPTS " $a0"
|
||||
} else {
|
||||
@@ -152,8 +157,8 @@ if {$tcl_platform(platform) eq "windows"} {
|
||||
}
|
||||
set CFLAGS -fPIC
|
||||
regexp {TCL_SHLIB_CFLAGS='([^']+)'} $tclConfig all CFLAGS
|
||||
set LIBS {}
|
||||
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBS
|
||||
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBSTUB
|
||||
lappend LIBS $LIBSTUB
|
||||
set INC "-I$srcdir/src"
|
||||
set inc {}
|
||||
regexp {TCL_INCLUDE_SPEC='([^']+)'} $tclConfig all inc
|
||||
@@ -312,7 +317,7 @@ package ifneeded sqlite3 $VERSION \\
|
||||
|
||||
# Generate and execute the command with which to do the compilation.
|
||||
#
|
||||
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT $LIBS"
|
||||
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT [join $LIBS { }]"
|
||||
puts $cmd
|
||||
file delete -force $OUT
|
||||
catch {exec {*}$cmd} errmsg
|
||||
|
||||
@@ -2193,7 +2193,7 @@ int main(int argc, char const * const *argv){
|
||||
printf("%s\n", sqlite3_str_value(pStr));
|
||||
return 0;
|
||||
}
|
||||
if( z[i]=='-' ){
|
||||
if( z[0]=='-' ){
|
||||
fprintf(stderr,
|
||||
"unknown option: \"%s\". Use --help for more detail.\n", z);
|
||||
return 1;
|
||||
@@ -2262,7 +2262,7 @@ int main(int argc, char const * const *argv){
|
||||
append_escaped_arg(pStr, zSsh, 1);
|
||||
if( iPort>0 ) sqlite3_str_appendf(pStr, " -p %d", iPort);
|
||||
sqlite3_str_appendf(pStr, " -e none");
|
||||
append_escaped_arg(pStr, ctx.zOrigin, 0);
|
||||
append_escaped_arg(pStr, ctx.zOrigin, 1);
|
||||
if( iRetry ) add_path_argument(pStr);
|
||||
append_escaped_arg(pStr, zExe, 1);
|
||||
append_escaped_arg(pStr, "--origin", 0);
|
||||
@@ -2311,7 +2311,7 @@ int main(int argc, char const * const *argv){
|
||||
append_escaped_arg(pStr, zSsh, 1);
|
||||
if( iPort>0 ) sqlite3_str_appendf(pStr, " -p %d", iPort);
|
||||
sqlite3_str_appendf(pStr, " -e none");
|
||||
append_escaped_arg(pStr, ctx.zReplica, 0);
|
||||
append_escaped_arg(pStr, ctx.zReplica, 1);
|
||||
if( iRetry==1 ) add_path_argument(pStr);
|
||||
append_escaped_arg(pStr, zExe, 1);
|
||||
append_escaped_arg(pStr, "--replica", 0);
|
||||
|
||||
Reference in New Issue
Block a user