Compare commits
118 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7644162026 | |||
| fa8e52021f | |||
| ec4f18fed8 | |||
| 9487f6d441 | |||
| 7b386a77ff | |||
| 3a697a26de | |||
| 593b55cb78 | |||
| 8c4a4acc02 | |||
| 978b0abe4d | |||
| e070f37183 | |||
| b5d0d980be | |||
| 3dbf444538 | |||
| 3f7bf4ef2f | |||
| c9bffdb35e | |||
| ffc14a20ad | |||
| aa1579de80 | |||
| 8227408b6f | |||
| 9fb225190c | |||
| b7c32f2f29 | |||
| 09c84c70ee | |||
| 9a5801af3a | |||
| a0dc22438d | |||
| f0075cd2e4 | |||
| b348459070 | |||
| 458dfb94d0 | |||
| 91a3aa3646 | |||
| 1b5bd0edf1 | |||
| a2fd301a6a | |||
| 53f419e2c8 | |||
| 0cdc6432f7 | |||
| 667d1b15c1 | |||
| b1bbff20a0 | |||
| 23e50585eb | |||
| b273dc8de1 | |||
| 9c2ac0b6e3 | |||
| a5e5116228 | |||
| 5d59375ac8 | |||
| 1b828b8770 | |||
| 36e9e015de | |||
| d8f6cc7ea4 | |||
| 2884421c05 | |||
| 7459c01689 | |||
| 053048a40f | |||
| 2ca10782d2 | |||
| 2429af2e0c | |||
| 865a8f3072 | |||
| 124f449319 | |||
| 76ad3be617 | |||
| 23d0a08176 | |||
| b14202f86e | |||
| 0b9f4ee89c | |||
| d1b9001a7f | |||
| d57abdb017 | |||
| 970b3bc4c4 | |||
| d688d1551a | |||
| dacabb4a33 | |||
| 2bd7ac6716 | |||
| 49edbe2150 | |||
| 062016c2fd | |||
| 84ead09d94 | |||
| 2cb57d9d4a | |||
| 2f5d281796 | |||
| 6a1efec20a | |||
| 082e41f17b | |||
| 19a2ba1f5b | |||
| b677c5afd4 | |||
| 7340b032d1 | |||
| 2bc3763ec5 | |||
| a6812a4242 | |||
| 6bf7825ac5 | |||
| 192b3a539b | |||
| 002d33d8c5 | |||
| ee181f479a | |||
| 076db92d85 | |||
| 2dacda40a6 | |||
| 62a3734e78 | |||
| 95d072cc81 | |||
| 0120735de1 | |||
| d80528ad4d | |||
| c2d29194a8 | |||
| 61523e22f9 | |||
| 51b2c3863b | |||
| 6feeafc7de | |||
| a735462db6 | |||
| d2240cc988 | |||
| 942b7c555a | |||
| 069e5acd63 | |||
| 1c0a370472 | |||
| 2acb57c1be | |||
| 2a28b15748 | |||
| b1637e5408 | |||
| b48ca02d64 | |||
| c28f2d22b6 | |||
| 48a591fa6b | |||
| 2c351bbf82 | |||
| ddea119f82 | |||
| 03aa9a7b50 | |||
| 62d17739bc | |||
| f55434ab30 | |||
| 0a04687373 | |||
| c079bd08a2 | |||
| 5cae890219 | |||
| f3eea1efa4 | |||
| 3040da55a8 | |||
| 1a760748a6 | |||
| 5481274912 | |||
| 6c218ba0ad | |||
| ca8593ce68 | |||
| af6fdd2673 | |||
| 1cd9eb3811 | |||
| 7437c19a01 | |||
| d076d98ec8 | |||
| 72f0bd609c | |||
| 7aad2942c2 | |||
| 07ded24fbb | |||
| 5b98467d28 | |||
| 3d006d0d00 | |||
| 991cbd78b3 |
+17
-5
@@ -1766,11 +1766,11 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\analyze.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base64.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base85.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\completion.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\decimal.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\diskused.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\ieee754.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\regexp.c
|
||||
@@ -1897,9 +1897,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
|
||||
|
||||
@@ -2343,12 +2340,12 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\intck\sqlite3intck.c \
|
||||
$(TOP)\ext\intck\sqlite3intck.h \
|
||||
$(TOP)\ext\misc\analyze.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\base64.c \
|
||||
$(TOP)\ext\misc\base85.c \
|
||||
$(TOP)\ext\misc\completion.c \
|
||||
$(TOP)\ext\misc\decimal.c \
|
||||
$(TOP)\ext\misc\diskused.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
@@ -2757,6 +2754,21 @@ THREADTEST3_SRC = \
|
||||
threadtest3.exe: $(THREADTEST3_SRC) $(TOP)\src\test_multiplex.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\test\threadtest3.c $(TOP)\src\test_multiplex.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
# Convenienced targets for common executables that omit
|
||||
# the .exe suffix
|
||||
#
|
||||
sqldiff: sqldiff.exe
|
||||
sqlite3_rsync: sqlite3_rsync.exe
|
||||
fuzzcheck: fuzzcheck.exe
|
||||
testfixture: testfixture.exe
|
||||
sqlite3: $(SQLITE3EXE)
|
||||
showdb: showdb.exe
|
||||
LogEst: LogEst.exe
|
||||
wordcount: wordcount.exe
|
||||
speedtest1: speedtest1.exe
|
||||
kvtest: kvtest.exe
|
||||
jimsh0: jimsh0.exe
|
||||
|
||||
# Display key variables that control which version of TCL is to be used.
|
||||
#
|
||||
tcl-env:
|
||||
|
||||
@@ -466,7 +466,7 @@ proc sqlite-configure {buildMode configScript} {
|
||||
proc sqlite-configure-phase1 {buildMode} {
|
||||
define PACKAGE_NAME sqlite
|
||||
define PACKAGE_URL {https://sqlite.org}
|
||||
define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
|
||||
define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/bugs
|
||||
define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]"
|
||||
proj-xfer-options-aliases {
|
||||
# Carry values from hidden --flag aliases over to their canonical
|
||||
|
||||
@@ -606,4 +606,40 @@ ifcapable fts5 {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
set ci {CREATE INDEX i1 ON t1(a COLLATE "binary,sqlite_expert_rem(999,0)");}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE t1(a TEXT, b TEXT);
|
||||
INSERT INTO t1 VALUES('v0','d0');
|
||||
INSERT INTO t1 VALUES('v1','d1');
|
||||
INSERT INTO t1 VALUES('v2','d2');
|
||||
INSERT INTO t1 VALUES('v3','d3');
|
||||
INSERT INTO t1 VALUES('v4','d4');
|
||||
INSERT INTO t1 VALUES('v5','d5');
|
||||
INSERT INTO t1 VALUES('v6','d6');
|
||||
INSERT INTO t1 VALUES('v7','d7');
|
||||
INSERT INTO t1 VALUES('v8','d8');
|
||||
INSERT INTO t1 VALUES('v9','d9');
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
COMMIT;
|
||||
PRAGMA writable_schema = ON;
|
||||
UPDATE sqlite_schema SET sql = $ci WHERE name = 'i1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_test 8.1 {
|
||||
set expert [sqlite3_expert_new db]
|
||||
$expert sql { SELECT 1234 }
|
||||
list [catch { $expert analyze } msg] $msg
|
||||
} {1 {no such collation sequence: binary,sqlite_expert_rem(999,0)}}
|
||||
|
||||
$expert destroy
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1501,7 +1501,7 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
/* The statement the vtab will pass to sqlite3_declare_vtab() */
|
||||
zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
|
||||
zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %Q",
|
||||
(i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
|
||||
);
|
||||
}
|
||||
@@ -1701,7 +1701,7 @@ static int idxPopulateOneStat1(
|
||||
return sqlite3_reset(pIndexXInfo);
|
||||
}
|
||||
zCols = idxAppendText(&rc, zCols,
|
||||
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
|
||||
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %Q",
|
||||
zComma, zName, nCol, zName, zColl
|
||||
);
|
||||
zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
|
||||
|
||||
+18
-3
@@ -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 ){
|
||||
@@ -2063,8 +2073,13 @@ static void fts3PutDeltaVarint(
|
||||
sqlite3_int64 iVal /* Write this value to the list */
|
||||
){
|
||||
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
|
||||
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
|
||||
*piPrev = iVal;
|
||||
if( iVal-(*piPrev)>=0 ){
|
||||
/* Refuse to write a negative delta integer. This only happens with a
|
||||
** corrupt db (see the assert above) and can cause buffer overwrites
|
||||
** in some cases. */
|
||||
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
|
||||
*piPrev = iVal;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+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 || iCol>0x3fffffff ){
|
||||
if( iCol<1 || iCol>(pFts3->nColumn+1) ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
|
||||
+9
-10
@@ -132,10 +132,9 @@ struct StrBuffer {
|
||||
/*
|
||||
** Allocate a two-slot MatchinfoBuffer object.
|
||||
*/
|
||||
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
static MatchinfoBuffer *fts3MIBufferNew(i64 nElem, const char *zMatchinfo){
|
||||
MatchinfoBuffer *pRet;
|
||||
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
|
||||
+ SZ_MATCHINFOBUFFER(1);
|
||||
sqlite3_int64 nByte = sizeof(u32) * (2*(i64)nElem+1) + SZ_MATCHINFOBUFFER(1);
|
||||
sqlite3_int64 nStr = strlen(zMatchinfo);
|
||||
|
||||
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
|
||||
@@ -1006,8 +1005,8 @@ static int fts3MatchinfoCheck(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
|
||||
size_t nVal; /* Number of integers output by cArg */
|
||||
static i64 fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
|
||||
i64 nVal; /* Number of integers output by cArg */
|
||||
|
||||
switch( cArg ){
|
||||
case FTS3_MATCHINFO_NDOC:
|
||||
@@ -1023,16 +1022,16 @@ static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
|
||||
break;
|
||||
|
||||
case FTS3_MATCHINFO_LHITS:
|
||||
nVal = (size_t)pInfo->nCol * pInfo->nPhrase;
|
||||
nVal = (i64)pInfo->nCol * pInfo->nPhrase;
|
||||
break;
|
||||
|
||||
case FTS3_MATCHINFO_LHITS_BM:
|
||||
nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
|
||||
nVal = (i64)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( cArg==FTS3_MATCHINFO_HITS );
|
||||
nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3;
|
||||
nVal = (i64)pInfo->nCol * pInfo->nPhrase * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1314,7 +1313,7 @@ static int fts3MatchinfoValues(
|
||||
|
||||
case FTS3_MATCHINFO_LHITS_BM:
|
||||
case FTS3_MATCHINFO_LHITS: {
|
||||
size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
|
||||
i64 nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
|
||||
memset(pInfo->aMatchinfo, 0, nZero);
|
||||
rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
|
||||
break;
|
||||
@@ -1383,7 +1382,7 @@ static void fts3GetMatchinfo(
|
||||
** initialize those elements that are constant for every row.
|
||||
*/
|
||||
if( pCsr->pMIBuffer==0 ){
|
||||
size_t nMatchinfo = 0; /* Number of u32 elements in match-info */
|
||||
i64 nMatchinfo = 0; /* Number of u32 elements in match-info */
|
||||
int i; /* Used to iterate through zArg */
|
||||
|
||||
/* Determine the number of phrases in the query */
|
||||
|
||||
@@ -3129,6 +3129,10 @@ static void fts3ReadEndBlockField(
|
||||
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
|
||||
iVal = iVal*10 + (zText[i] - '0');
|
||||
}
|
||||
|
||||
/* This if() clause is just to avoid an integer overflow. The record is
|
||||
** corrupt in this case. */
|
||||
if( (i64)iVal==SMALLEST_INT64 ) iMul = 1;
|
||||
*pnByte = ((i64)iVal * (i64)iMul);
|
||||
}
|
||||
}
|
||||
@@ -4355,7 +4359,7 @@ static int fts3IncrmergeLoad(
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
|
||||
pWriter->nLeafEst = (int)(((iEnd - iStart)+1)/FTS_MAX_APPENDABLE_HEIGHT);
|
||||
pWriter->iStart = iStart;
|
||||
pWriter->iEnd = iEnd;
|
||||
pWriter->iAbsLevel = iAbsLevel;
|
||||
|
||||
+2
-2
@@ -426,7 +426,7 @@ static void fts5SnippetFunction(
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int iCol; /* 1st argument to snippet() */
|
||||
const char *zEllips; /* 4th argument to snippet() */
|
||||
int nToken; /* 5th argument to snippet() */
|
||||
i64 nToken; /* 5th argument to snippet() */
|
||||
int nInst = 0; /* Number of instance matches this row */
|
||||
int i; /* Used to iterate through instances */
|
||||
int nPhrase; /* Number of phrases in query */
|
||||
@@ -451,7 +451,7 @@ static void fts5SnippetFunction(
|
||||
ctx.zClose = fts5ValueToText(apVal[2]);
|
||||
ctx.iRangeEnd = -1;
|
||||
zEllips = fts5ValueToText(apVal[3]);
|
||||
nToken = sqlite3_value_int(apVal[4]);
|
||||
nToken = (int)(MIN( MAX(sqlite3_value_int64(apVal[4]), 0), 64));
|
||||
|
||||
iBestCol = (iCol>=0 ? iCol : 0);
|
||||
nPhrase = pApi->xPhraseCount(pFts);
|
||||
|
||||
@@ -807,7 +807,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
|
||||
i64 iPos = a[i].reader.iPos;
|
||||
Fts5PoslistWriter *pWriter = &a[i].writer;
|
||||
if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){
|
||||
sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos);
|
||||
sqlite3Fts5PoslistSafeAppend(a[i].pOut, &pWriter->iPrev, iPos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1758,10 +1758,10 @@ static int fts5ParseTokenize(
|
||||
memset(pSyn, 0, (size_t)nByte);
|
||||
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
|
||||
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
|
||||
memcpy(pSyn->pTerm, pToken, nToken);
|
||||
if( pCtx->pConfig->bTokendata ){
|
||||
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
|
||||
}
|
||||
memcpy(pSyn->pTerm, pToken, nToken);
|
||||
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
|
||||
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ int sqlite3Fts5HashWrite(
|
||||
** + 5 bytes for the new position offset (32-bit max).
|
||||
*/
|
||||
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
|
||||
sqlite3_int64 nNew = p->nAlloc * 2;
|
||||
sqlite3_int64 nNew = (i64)p->nAlloc * 2;
|
||||
Fts5HashEntry *pNew;
|
||||
Fts5HashEntry **pp;
|
||||
pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
|
||||
|
||||
+24
-16
@@ -1166,7 +1166,7 @@ static int fts5StructureDecode(
|
||||
i += fts5GetVarint32(&pData[i], nTotal);
|
||||
if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
|
||||
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
|
||||
nTotal * sizeof(Fts5StructureSegment)
|
||||
(i64)nTotal * sizeof(Fts5StructureSegment)
|
||||
);
|
||||
nSegment -= nTotal;
|
||||
}
|
||||
@@ -1695,6 +1695,7 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
|
||||
pLvl->bEof = 1;
|
||||
}else{
|
||||
u8 *a = pLvl->pData->p;
|
||||
int nn = pLvl->pData->nn;
|
||||
|
||||
pLvl->iOff = 0;
|
||||
fts5DlidxLvlNext(pLvl);
|
||||
@@ -1703,7 +1704,7 @@ static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
|
||||
int ii = pLvl->iOff;
|
||||
u64 delta = 0;
|
||||
|
||||
while( a[ii]==0 ){
|
||||
while( ii<nn && a[ii]==0 ){
|
||||
nZero++;
|
||||
ii++;
|
||||
}
|
||||
@@ -2122,7 +2123,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||
while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
|
||||
Fts5Data *pNew;
|
||||
pIter->iLeafPgno--;
|
||||
pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
|
||||
pNew = fts5LeafRead(p, FTS5_SEGMENT_ROWID(
|
||||
pIter->pSeg->iSegid, pIter->iLeafPgno
|
||||
));
|
||||
if( pNew ){
|
||||
@@ -3556,8 +3557,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);
|
||||
@@ -5301,6 +5301,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 );
|
||||
@@ -7986,8 +7991,8 @@ static void fts5IndexTombstoneRebuild(
|
||||
){
|
||||
const int MINSLOT = 32;
|
||||
int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey);
|
||||
int nSlot = 0; /* Number of slots in each output page */
|
||||
int nOut = 0;
|
||||
i64 nSlot = 0; /* Number of slots in each output page */
|
||||
i64 nOut = 0;
|
||||
|
||||
/* Figure out how many output pages (nOut) and how many slots per
|
||||
** page (nSlot). There are three possibilities:
|
||||
@@ -8012,23 +8017,26 @@ static void fts5IndexTombstoneRebuild(
|
||||
nSlot = MINSLOT;
|
||||
}else if( pSeg->nPgTombstone==1 ){
|
||||
/* Case 2. */
|
||||
int nElem = (int)fts5GetU32(&pData1->p[4]);
|
||||
u32 nElem = fts5GetU32(&pData1->p[4]);
|
||||
assert( pData1 && iPg1==0 );
|
||||
nOut = 1;
|
||||
nSlot = MAX(nElem*4, MINSLOT);
|
||||
if( nSlot>nSlotPerPage ) nOut = 0;
|
||||
if( nElem>((u32)nSlotPerPage/4) ){
|
||||
nOut = 0;
|
||||
}else{
|
||||
nOut = 1;
|
||||
nSlot = MAX((i64)nElem*4, MINSLOT);
|
||||
}
|
||||
}
|
||||
if( nOut==0 ){
|
||||
/* Case 3. */
|
||||
nOut = (pSeg->nPgTombstone * 2 + 1);
|
||||
nOut = ((i64)pSeg->nPgTombstone * 2 + 1);
|
||||
nSlot = nSlotPerPage;
|
||||
}
|
||||
|
||||
/* Allocate the required array and output pages */
|
||||
while( 1 ){
|
||||
int res = 0;
|
||||
int ii = 0;
|
||||
int szPage = 0;
|
||||
i64 ii = 0;
|
||||
i64 szPage = 0;
|
||||
Fts5Data **apOut = 0;
|
||||
|
||||
/* Allocate space for the new hash table */
|
||||
@@ -8566,7 +8574,7 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
/* Check any rowid-less pages that occur before the current leaf. */
|
||||
for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){
|
||||
iKey = FTS5_SEGMENT_ROWID(iSegid, iPg);
|
||||
pLeaf = fts5DataRead(p, iKey);
|
||||
pLeaf = fts5LeafRead(p, iKey);
|
||||
if( pLeaf ){
|
||||
if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey);
|
||||
fts5DataRelease(pLeaf);
|
||||
@@ -8577,7 +8585,7 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
/* Check that the leaf page indicated by the iterator really does
|
||||
** contain the rowid suggested by the same. */
|
||||
iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf);
|
||||
pLeaf = fts5DataRead(p, iKey);
|
||||
pLeaf = fts5LeafRead(p, iKey);
|
||||
if( pLeaf ){
|
||||
i64 iRowid;
|
||||
int iRowidOff = fts5LeafFirstRowidOff(pLeaf);
|
||||
|
||||
+23
-26
@@ -365,34 +365,31 @@ int sqlite3Fts5StorageOpen(
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pConfig->eContent==FTS5_CONTENT_UNINDEXED
|
||||
){
|
||||
int nDefn = 32 + pConfig->nCol*10;
|
||||
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
|
||||
if( zDefn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int i;
|
||||
int iOff;
|
||||
sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
|
||||
iOff = (int)strlen(zDefn);
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pConfig->abUnindexed[i]
|
||||
){
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
int i = 0;
|
||||
char *zDefn = 0;
|
||||
sqlite3_str *pDefn = sqlite3_str_new(pConfig->db);
|
||||
|
||||
sqlite3_str_appendf(pDefn, "id INTEGER PRIMARY KEY");
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->abUnindexed[i] ){
|
||||
sqlite3_str_appendf(pDefn, ", c%d", i);
|
||||
}
|
||||
if( pConfig->bLocale ){
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
}
|
||||
sqlite3_free(zDefn);
|
||||
if( pConfig->bLocale ){
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
sqlite3_str_appendf(pDefn, ", l%d", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
zDefn = sqlite3_str_finish(pDefn);
|
||||
|
||||
if( zDefn ){
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
sqlite3_free(zDefn);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
|
||||
@@ -191,6 +191,29 @@ do_execsql_test 5.6 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ' || x'DB');
|
||||
} {{[x a a a a a...}}
|
||||
|
||||
do_execsql_test 5.7.1 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', -2147483647) FROM p1('x OR ' || x'DB')
|
||||
} {{[x...}}
|
||||
do_execsql_test 5.7.2 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', -2147483648) FROM p1('x OR ' || x'DB')
|
||||
} {{[x...}}
|
||||
do_execsql_test 5.7.3 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', -2147483649) FROM p1('x OR ' || x'DB')
|
||||
} {{[x...}}
|
||||
do_execsql_test 5.7.4 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 0) FROM p1('x OR ' || x'DB')
|
||||
} {{[x...}}
|
||||
|
||||
do_execsql_test 5.8.1 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 2147483647) FROM p1('x OR ' || x'DB')
|
||||
} {{[x a a a a a a a a a a}}
|
||||
do_execsql_test 5.8.2 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 2147483648) FROM p1('x OR ' || x'DB')
|
||||
} {{[x a a a a a a a a a a}}
|
||||
do_execsql_test 5.8.3 {
|
||||
SELECT snippet(p1, 0, '[', NULL, '...', 2147483649) FROM p1('x OR ' || x'DB')
|
||||
} {{[x a a a a a a a a a a}}
|
||||
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
reset_db
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# 2026 June 19
|
||||
#
|
||||
# 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. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5bigtok2
|
||||
return_if_no_fts5
|
||||
|
||||
set big [string repeat a 1080000000]
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts5(x);
|
||||
}
|
||||
|
||||
do_catchsql_test 1.1 { INSERT INTO t VALUES($big); } {1 {out of memory}}
|
||||
|
||||
set big {}
|
||||
|
||||
finish_test
|
||||
@@ -1998,6 +1998,219 @@ 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}}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 14.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 0a 00 0f c7 0f 74 ..v............t
|
||||
| 112: 0f 0c 0e b8 0e 5f 0e 0a 00 00 00 00 00 00 00 00 ....._..........
|
||||
| 3584: 00 00 00 00 00 00 00 00 00 00 53 06 06 17 1d 1d ..........S.....
|
||||
| 3600: 01 7b 74 61 62 6c 65 74 5f 63 6f 6e 66 69 67 74 ..tablet_configt
|
||||
| 3616: 5f 63 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 _config.CREATE T
|
||||
| 3632: 41 42 4c 45 20 27 74 5f 63 6f 6e 66 69 67 27 28 ABLE 't_config'(
|
||||
| 3648: 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 k PRIMARY KEY, v
|
||||
| 3664: 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 57 ) WITHOUT ROWIDW
|
||||
| 3680: 05 06 17 1f 1f 01 7f 74 61 62 6c 65 74 5f 64 6f .......tablet_do
|
||||
| 3696: 63 73 69 7a 65 74 5f 64 6f 63 73 69 7a 65 05 43 csizet_docsize.C
|
||||
| 3712: 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 5f 64 REATE TABLE 't_d
|
||||
| 3728: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
|
||||
| 3744: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3760: 73 7a 20 42 4c 4f 42 29 52 04 06 17 1f 1f 01 75 sz BLOB)R......u
|
||||
| 3776: 74 61 62 6c 65 74 5f 63 6f 6e 74 65 6e 74 74 5f tablet_contentt_
|
||||
| 3792: 63 6f 6e 74 65 6e 74 04 43 52 45 41 54 45 20 54 content.CREATE T
|
||||
| 3808: 41 42 4c 45 20 27 74 5f 63 6f 6e 74 65 6e 74 27 ABLE 't_content'
|
||||
| 3824: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
|
||||
| 3840: 41 52 59 20 4b 45 59 2c 20 63 30 29 66 03 07 17 ARY KEY, c0)f...
|
||||
| 3856: 17 17 01 81 2b 74 61 62 6c 65 74 5f 69 64 78 74 ....+tablet_idxt
|
||||
| 3872: 5f 69 64 78 03 43 52 45 41 54 45 20 54 41 42 4c _idx.CREATE TABL
|
||||
| 3888: 45 20 27 74 5f 69 64 78 27 28 73 65 67 69 64 2c E 't_idx'(segid,
|
||||
| 3904: 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 term, pgno, PRI
|
||||
| 3920: 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 MARY KEY(segid,
|
||||
| 3936: 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 term)) WITHOUT R
|
||||
| 3952: 4f 57 49 44 51 02 06 17 19 19 01 7f 74 61 62 6c OWIDQ.......tabl
|
||||
| 3968: 65 74 5f 64 61 74 61 74 5f 64 61 74 61 02 43 52 et_datat_data.CR
|
||||
| 3984: 45 41 54 45 20 54 41 42 4c 45 20 27 74 5f 64 61 EATE TABLE 't_da
|
||||
| 4000: 74 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 ta'(id INTEGER P
|
||||
| 4016: 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 RIMARY KEY, bloc
|
||||
| 4032: 6b 20 42 4c 4f 42 29 37 01 06 17 0f 0f 08 61 74 k BLOB)7......at
|
||||
| 4048: 61 62 6c 65 74 74 43 52 45 41 54 45 20 56 49 52 ablettCREATE VIR
|
||||
| 4064: 54 55 41 4c 20 54 41 42 4c 45 20 74 20 55 53 49 TUAL TABLE t USI
|
||||
| 4080: 4e 47 20 66 74 73 35 28 63 6f 6e 74 65 6e 74 29 NG fts5(content)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0f ef 00 03 0f ac 00 0f e8 0f ac 0f c4 00 00 ................
|
||||
| 4000: 00 00 00 00 00 00 00 00 00 00 00 00 16 0a 03 00 ................
|
||||
| 4016: 32 01 00 00 00 01 01 01 00 d5 aa d5 2b 01 01 01 2...........+...
|
||||
| 4032: 83 74 01 01 1d 84 80 80 80 80 01 03 00 40 00 00 .t...........@..
|
||||
| 4048: 00 18 06 30 68 65 6c 6c 6f 01 02 02 01 05 77 6f ...0hello.....wo
|
||||
| 4064: 72 6c 64 01 02 03 04 0a 05 01 03 00 10 01 02 00 rld.............
|
||||
| 4080: 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 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 f0 00 0f f0 00 00 00 00 00 00 ................
|
||||
| 4080: 0e 01 03 00 23 68 65 6c 6c 6f 20 77 6f 72 6c 64 ....#hello world
|
||||
| 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 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 14.1 {
|
||||
SELECT * FROM t('hello');
|
||||
} {1 {out of memory}}
|
||||
|
||||
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
|
||||
|
||||
@@ -124,5 +124,150 @@ do_test 3.1 {
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(content);
|
||||
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
|
||||
BEGIN;
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<5000
|
||||
)
|
||||
INSERT INTO t1(content) SELECT 'xyzterm' FROM s;
|
||||
COMMIT;
|
||||
INSERT INTO t1(t1) VALUES('optimize');
|
||||
}
|
||||
|
||||
do_test 4.1 {
|
||||
db eval {
|
||||
SELECT rowid AS a, hex(block) AS block FROM t1_data
|
||||
WHERE ((rowid>>36) & 0x01)==1
|
||||
AND ((rowid>>31) & 0x1F)==0
|
||||
} {
|
||||
set n [string length $block]
|
||||
set block [string range $block 0 11]
|
||||
append block [string repeat "00" [expr ($n/2)-7-2]]
|
||||
append block "8080"
|
||||
db eval {
|
||||
UPDATE t1_data SET block = unhex($block) WHERE rowid = $a
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
do_catchsql_test 4.2 {
|
||||
SELECT count(*) FROM (
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid ASC
|
||||
)
|
||||
} {0 5000}
|
||||
|
||||
do_catchsql_test 4.3 {
|
||||
SELECT count(*) FROM (
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid DESC
|
||||
)
|
||||
} {0 4987}
|
||||
|
||||
do_test 4.4 {
|
||||
db eval {
|
||||
SELECT rowid AS a, hex(block) AS block FROM t1_data
|
||||
WHERE ((rowid>>36) & 0x01)==1
|
||||
AND ((rowid>>31) & 0x1F)==0
|
||||
} {
|
||||
set n [string length $block]
|
||||
set block [string range $block 0 $n-5]
|
||||
append block [string repeat "00" 2]
|
||||
db eval {
|
||||
UPDATE t1_data SET block = unhex($block) WHERE rowid = $a
|
||||
}
|
||||
}
|
||||
} {}
|
||||
|
||||
do_catchsql_test 4.5 {
|
||||
SELECT count(*) FROM (
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid ASC
|
||||
)
|
||||
} {0 5000}
|
||||
|
||||
do_catchsql_test 4.6 {
|
||||
SELECT count(*) FROM (
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'xyzterm' ORDER BY rowid DESC
|
||||
)
|
||||
} {0 4879}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts5(x);
|
||||
INSERT INTO t(t,rank) VALUES('pgsz', 64);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<80
|
||||
)
|
||||
INSERT INTO t SELECT 'shared word' || (i%10) || ' shared shared' FROM s;
|
||||
INSERT INTO t(t) VALUES('optimize');
|
||||
}
|
||||
|
||||
set lLeaf [db eval { SELECT id FROM t_data }]
|
||||
db_save_and_close
|
||||
|
||||
foreach leaf $lLeaf {
|
||||
db_restore_and_reopen
|
||||
set leaf [expr $leaf]
|
||||
set hex [db one {
|
||||
SELECT hex(block) FROM t_data WHERE id=$leaf
|
||||
}]
|
||||
|
||||
# Replace the first 4 bytes of each leaf page with the size of the leaf in
|
||||
# bytes plus 50 as a 2 byte integer, followed by 0x7FFF.
|
||||
#
|
||||
set nn [expr [string length $hex]/2]
|
||||
set first "[format %.4x [expr $nn+50]]7FFF"
|
||||
set hex [string replace $hex 0 7 $first]
|
||||
|
||||
db eval { UPDATE t_data SET block=unhex($hex) WHERE id=$leaf }
|
||||
do_test 5.1.$leaf {
|
||||
catchsql {
|
||||
SELECT rowid FROM t WHERE t MATCH 'shared' ORDER BY rowid DESC;
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_test 5.1.$leaf.2 {
|
||||
catchsql {
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts5(x, content='', contentless_delete=1);
|
||||
INSERT INTO t(rowid,x)
|
||||
VALUES(1,'a b'), (2,'c d'), (3,'e f'), (4,'g h'), (5,'i j');
|
||||
INSERT INTO t(t) VALUES('optimize');
|
||||
DELETE FROM t WHERE rowid=2;
|
||||
}
|
||||
|
||||
do_test 6.1 {
|
||||
db eval {
|
||||
SELECT rowid AS rid, hex(block) AS blk
|
||||
FROM t_data WHERE rowid>1_000_000_000_000
|
||||
} {}
|
||||
|
||||
set blk [string replace $blk 8 15 20000000]
|
||||
execsql {
|
||||
UPDATE t_data SET block = unhex($blk) WHERE rowid=$rid
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
DELETE FROM t WHERE rowid=3;
|
||||
}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -743,6 +743,19 @@ do_execsql_test 15.4 {
|
||||
SELECT c, fts5_columnlocale(ft, 2) FROM ft
|
||||
} {three {} three loc}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
set nMaxCol 500
|
||||
set nStep 20
|
||||
|
||||
for {set ii $nStep} {$ii <= $nMaxCol} {incr ii $nStep} {
|
||||
set C [list]
|
||||
for {set iCol 0} {$iCol<$ii} {incr iCol} {
|
||||
lappend C col$iCol
|
||||
}
|
||||
set ct "CREATE VIRTUAL TABLE t$ii USING fts5([join $C ,], locale=1)"
|
||||
do_execsql_test 16.$ii $ct
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -66,5 +66,18 @@ do_near_test 1.23 "a b c d e f g h i" { NEAR(a+b+c+d i b+c, 4) } 0
|
||||
do_near_test 1.24 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 5) } 1
|
||||
do_near_test 1.25 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 4) } 0
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that https://sqlite.org/bugs/forumpost/16bb36f7e8 is fixed.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts5(x, tokenize=trigram);
|
||||
INSERT INTO t
|
||||
VALUES('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT count(*) FROM t WHERE t MATCH 'NEAR(aaa aaa, 4)';
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -418,6 +418,34 @@ do_execsql_test 7.1.2 {
|
||||
INSERT INTO t2(t2) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
reset_db
|
||||
fts5_aux_test_functions db
|
||||
|
||||
proc tcl_create {args} { return "tcl_tokenize" }
|
||||
sqlite3_fts5_create_tokenizer db tcl tcl_create
|
||||
|
||||
proc tcl_tokenize {tflags text} {
|
||||
foreach {w iStart iEnd} [fts5_tokenize_split $text] {
|
||||
sqlite3_fts5_token $w $iStart $iEnd
|
||||
if {$w=="usa"} {
|
||||
sqlite3_fts5_token -colo "united" $iStart $iEnd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize='tcl', tokendata=1);
|
||||
INSERT INTO t1 VALUES('usa is great');
|
||||
INSERT INTO t1 VALUES('canada is cool');
|
||||
INSERT INTO t1 VALUES('australia is what matters');
|
||||
}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'usa*';
|
||||
} {{usa is great}}
|
||||
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -105,6 +105,9 @@ static const unsigned char icuUtf8Trans1[] = {
|
||||
while( (*zIn & 0xc0)==0x80 ){ \
|
||||
c = (c<<6) + (0x3f & *(zIn++)); \
|
||||
} \
|
||||
if( c<0x80 \
|
||||
|| (c&0xFFFFF800)==0xD800 \
|
||||
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
|
||||
}
|
||||
|
||||
#define SQLITE_ICU_SKIP_UTF8(zIn) \
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
** 2019-03-30
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** An SQL function that uses the incremental BLOB I/O mechanism of SQLite
|
||||
** to read or write part of a blob. This is intended for debugging use
|
||||
** in the CLI.
|
||||
**
|
||||
** readblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,N)
|
||||
**
|
||||
** Returns N bytes of the blob starting at OFFSET.
|
||||
**
|
||||
** writeblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,NEWDATA)
|
||||
**
|
||||
** NEWDATA must be a blob. The content of NEWDATA overwrites the
|
||||
** existing BLOB data at SCHEMA.TABLE.COLUMN for row ROWID beginning
|
||||
** at OFFSET bytes into the blob.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static void readblobFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3_blob *pBlob = 0;
|
||||
const char *zSchema;
|
||||
const char *zTable;
|
||||
const char *zColumn;
|
||||
sqlite3_int64 iRowid;
|
||||
int iOfst;
|
||||
unsigned char *aData;
|
||||
int nData;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
zSchema = (const char*)sqlite3_value_text(argv[0]);
|
||||
zTable = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( zTable==0 ){
|
||||
sqlite3_result_error(context, "bad table name", -1);
|
||||
return;
|
||||
}
|
||||
zColumn = (const char*)sqlite3_value_text(argv[2]);
|
||||
if( zTable==0 ){
|
||||
sqlite3_result_error(context, "bad column name", -1);
|
||||
return;
|
||||
}
|
||||
iRowid = sqlite3_value_int64(argv[3]);
|
||||
iOfst = sqlite3_value_int(argv[4]);
|
||||
nData = sqlite3_value_int(argv[5]);
|
||||
if( nData<=0 ) return;
|
||||
aData = sqlite3_malloc64( nData+1 );
|
||||
if( aData==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
db = sqlite3_context_db_handle(context);
|
||||
rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 0, &pBlob);
|
||||
if( rc ){
|
||||
sqlite3_free(aData);
|
||||
sqlite3_result_error(context, "cannot open BLOB pointer", -1);
|
||||
return;
|
||||
}
|
||||
rc = sqlite3_blob_read(pBlob, aData, nData, iOfst);
|
||||
sqlite3_blob_close(pBlob);
|
||||
if( rc ){
|
||||
sqlite3_free(aData);
|
||||
sqlite3_result_error(context, "BLOB read failed", -1);
|
||||
}else{
|
||||
sqlite3_result_blob(context, aData, nData, sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
static void writeblobFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3_blob *pBlob = 0;
|
||||
const char *zSchema;
|
||||
const char *zTable;
|
||||
const char *zColumn;
|
||||
sqlite3_int64 iRowid;
|
||||
int iOfst;
|
||||
unsigned char *aData;
|
||||
int nData;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
zSchema = (const char*)sqlite3_value_text(argv[0]);
|
||||
zTable = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( zTable==0 ){
|
||||
sqlite3_result_error(context, "bad table name", -1);
|
||||
return;
|
||||
}
|
||||
zColumn = (const char*)sqlite3_value_text(argv[2]);
|
||||
if( zTable==0 ){
|
||||
sqlite3_result_error(context, "bad column name", -1);
|
||||
return;
|
||||
}
|
||||
iRowid = sqlite3_value_int64(argv[3]);
|
||||
iOfst = sqlite3_value_int(argv[4]);
|
||||
if( sqlite3_value_type(argv[5])!=SQLITE_BLOB ){
|
||||
sqlite3_result_error(context, "6th argument must be a BLOB", -1);
|
||||
return;
|
||||
}
|
||||
nData = sqlite3_value_bytes(argv[5]);
|
||||
aData = (unsigned char *)sqlite3_value_blob(argv[5]);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 1, &pBlob);
|
||||
if( rc ){
|
||||
sqlite3_result_error(context, "cannot open BLOB pointer", -1);
|
||||
return;
|
||||
}
|
||||
rc = sqlite3_blob_write(pBlob, aData, nData, iOfst);
|
||||
sqlite3_blob_close(pBlob);
|
||||
if( rc ){
|
||||
sqlite3_result_error(context, "BLOB write failed", -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_blobio_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "readblob", 6, SQLITE_UTF8, 0,
|
||||
readblobFunc, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "writeblob", 6, SQLITE_UTF8, 0,
|
||||
writeblobFunc, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
+7
-2
@@ -547,6 +547,10 @@ static int csvtabConnect(
|
||||
if( nCol<=0 ){
|
||||
csv_errmsg(&sRdr, "column= value must be positive");
|
||||
goto csvtab_connect_error;
|
||||
}else if( nCol>sqlite3_limit(db,SQLITE_LIMIT_COLUMN,-1) ){
|
||||
csv_errmsg(&sRdr, "column= value too big, max %d",
|
||||
sqlite3_limit(db, SQLITE_LIMIT_COLUMN,-1));
|
||||
goto csvtab_connect_error;
|
||||
}
|
||||
}else
|
||||
{
|
||||
@@ -709,8 +713,9 @@ static int csvtabClose(sqlite3_vtab_cursor *cur){
|
||||
static int csvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
CsvTable *pTab = (CsvTable*)p;
|
||||
CsvCursor *pCur;
|
||||
size_t nByte;
|
||||
nByte = sizeof(*pCur) + (sizeof(char*)+sizeof(i64))*pTab->nCol;
|
||||
sqlite3_int64 nByte = pTab->nCol;
|
||||
assert( pTab->nCol<32768 );
|
||||
nByte = sizeof(*pCur) + (sizeof(char*)+sizeof(i64))*nByte;
|
||||
pCur = sqlite3_malloc64( nByte );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, nByte);
|
||||
|
||||
+15
-6
@@ -299,28 +299,37 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
|
||||
sqlite3_result_text(pCtx, z, i, sqlite3_free);
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static void decimal_expand(Decimal *p, int nDigit, int nFrac);
|
||||
|
||||
/*
|
||||
** Round a decimal value to N significant digits. N must be positive.
|
||||
*/
|
||||
static void decimal_round(Decimal *p, int N){
|
||||
int i;
|
||||
int nZero;
|
||||
int nZero; /* Number of leading zeros */
|
||||
if( N<1 ) return;
|
||||
if( p==0 ) return;
|
||||
if( p->nDigit<=N ) return;
|
||||
for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
|
||||
N += nZero;
|
||||
if( p->nDigit<=N ) return;
|
||||
if( p->a[N]>4 ){
|
||||
if( p->a[N]>=5 ){
|
||||
/* If all leading digits are 9, increase the number of digits
|
||||
** by adding a new 0 to the front */
|
||||
for(i=0; i<N && p->a[i]==9; i++){}
|
||||
if( i==N ){
|
||||
decimal_expand(p, p->nDigit+1, 0);
|
||||
if( p->oom ) return;
|
||||
}
|
||||
|
||||
/* Do the rounding */
|
||||
p->a[N-1]++;
|
||||
for(i=N-1; i>0 && p->a[i]>9; i--){
|
||||
p->a[i] = 0;
|
||||
p->a[i-1]++;
|
||||
}
|
||||
if( p->a[0]>9 ){
|
||||
p->a[0] = 1;
|
||||
p->nFrac--;
|
||||
}
|
||||
assert( p->a[0]<=9 );
|
||||
}
|
||||
memset(&p->a[N], 0, p->nDigit - N);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,17 @@
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** Partial reimplement of the sqlite3_analyzer utility program as
|
||||
** loadable SQL function.
|
||||
** This extension implements an SQL function:
|
||||
**
|
||||
** diskused(X)
|
||||
**
|
||||
** Where X is the schema name (typically 'main'). The output is text
|
||||
** that describes how much filesystem space the various tables and indexes
|
||||
** of the database consume.
|
||||
**
|
||||
** This function is a replacement for the (now deprecated)
|
||||
** "sqlite3_analyzer" utility program. This function is built
|
||||
** into the CLI and is used to implement the ".diskused" command there.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
@@ -23,8 +32,8 @@ SQLITE_EXTENSION_INIT1
|
||||
/*
|
||||
** State information for the analysis
|
||||
*/
|
||||
typedef struct Analysis Analysis;
|
||||
struct Analysis {
|
||||
typedef struct DiskUsed DiskUsed;
|
||||
struct DiskUsed {
|
||||
sqlite3 *db; /* Database connection */
|
||||
sqlite3_context *context; /* SQL function context */
|
||||
sqlite3_str *pOut; /* Write output here */
|
||||
@@ -33,14 +42,14 @@ struct Analysis {
|
||||
};
|
||||
|
||||
/*
|
||||
** Free all resources that the Analysis object references and
|
||||
** reset the Analysis object.
|
||||
** Free all resources that the DiskUsed object references and
|
||||
** reset the DiskUsed object.
|
||||
**
|
||||
** Call this routine multiple times on the same Analysis object
|
||||
** Call this routine multiple times on the same DiskUsed object
|
||||
** is a harmless no-op, as long as the memory for the object itself
|
||||
** has not been freed.
|
||||
*/
|
||||
static void analysisReset(Analysis *p){
|
||||
static void diskusedReset(DiskUsed *p){
|
||||
if( p->zSU ){
|
||||
char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
|
||||
if( zSql ){
|
||||
@@ -57,7 +66,7 @@ static void analysisReset(Analysis *p){
|
||||
** Report an error using formatted text. If zFormat==NULL then report
|
||||
** an OOM error.
|
||||
*/
|
||||
static void analysisError(Analysis *p, const char *zFormat, ...){
|
||||
static void diskusedError(DiskUsed *p, const char *zFormat, ...){
|
||||
char *zErr;
|
||||
if( zFormat ){
|
||||
va_list ap;
|
||||
@@ -73,34 +82,34 @@ static void analysisError(Analysis *p, const char *zFormat, ...){
|
||||
sqlite3_result_error(p->context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
analysisReset(p);
|
||||
diskusedReset(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare and return an SQL statement.
|
||||
*/
|
||||
static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
|
||||
static sqlite3_stmt *diskusedVPrep(DiskUsed *p, const char *zFmt, va_list ap){
|
||||
char *zSql;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
zSql = sqlite3_vmprintf(zFmt, ap);
|
||||
if( zSql==0 ){ analysisError(p,0); return 0; }
|
||||
if( zSql==0 ){ diskusedError(p,0); return 0; }
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
|
||||
diskusedError(p, "SQL parse error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), zSql);
|
||||
sqlite3_finalize(pStmt);
|
||||
analysisReset(p);
|
||||
diskusedReset(p);
|
||||
pStmt = 0;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
return pStmt;
|
||||
}
|
||||
static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
|
||||
static sqlite3_stmt *diskusedPrepare(DiskUsed *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
pStmt = diskusedVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
return pStmt;
|
||||
}
|
||||
@@ -113,14 +122,14 @@ static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
|
||||
**
|
||||
** The prepared statement is closed in either case.
|
||||
*/
|
||||
static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
|
||||
static int diskusedStmtFinish(DiskUsed *p, int rc, sqlite3_stmt *pStmt){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
analysisReset(p);
|
||||
diskusedReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
@@ -129,21 +138,21 @@ static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
|
||||
/*
|
||||
** Run SQL. Return the number of errors.
|
||||
*/
|
||||
static int analysisSql(Analysis *p, const char *zFormat, ...){
|
||||
static int diskusedSql(DiskUsed *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
pStmt = diskusedVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( pStmt==0 ) return 1;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
analysisReset(p);
|
||||
diskusedReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
@@ -153,8 +162,8 @@ static int analysisSql(Analysis *p, const char *zFormat, ...){
|
||||
** Run an SQL query that returns an integer. Write that integer
|
||||
** into *piRes. Return the number of errors.
|
||||
*/
|
||||
static int analysisSqlInt(
|
||||
Analysis *p,
|
||||
static int diskusedSqlInt(
|
||||
DiskUsed *p,
|
||||
sqlite3_int64 *piRes,
|
||||
const char *zFormat, ...
|
||||
){
|
||||
@@ -162,7 +171,7 @@ static int analysisSqlInt(
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
pStmt = diskusedVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( pStmt==0 ) return 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
@@ -174,10 +183,10 @@ static int analysisSqlInt(
|
||||
}else{
|
||||
if( p->db ){
|
||||
/* p->db is NULL if there was some prior error */
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
}
|
||||
analysisReset(p);
|
||||
diskusedReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
@@ -190,7 +199,7 @@ static int analysisSqlInt(
|
||||
** comment. Otherwise begin with a new-line. Always finish with a
|
||||
** newline.
|
||||
*/
|
||||
static void analysisTitle(Analysis *p, const char *zFormat, ...){
|
||||
static void diskusedTitle(DiskUsed *p, const char *zFormat, ...){
|
||||
char *zFirst;
|
||||
char *zTitle;
|
||||
size_t nTitle;
|
||||
@@ -199,7 +208,7 @@ static void analysisTitle(Analysis *p, const char *zFormat, ...){
|
||||
zTitle = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zTitle==0 ){
|
||||
analysisError(p, 0);
|
||||
diskusedError(p, 0);
|
||||
return;
|
||||
}
|
||||
zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
|
||||
@@ -218,8 +227,8 @@ static void analysisTitle(Analysis *p, const char *zFormat, ...){
|
||||
** 50 columns with "." characters, and followed by whatever text is
|
||||
** described by zFormat.
|
||||
*/
|
||||
static void analysisLine(
|
||||
Analysis *p, /* Analysis context */
|
||||
static void diskusedLine(
|
||||
DiskUsed *p, /* DiskUsed context */
|
||||
const char *zDesc, /* Description */
|
||||
const char *zFormat, /* Argument to the description */
|
||||
...
|
||||
@@ -231,10 +240,10 @@ static void analysisLine(
|
||||
zTxt = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zTxt==0 ){
|
||||
analysisError(p, 0);
|
||||
diskusedError(p, 0);
|
||||
return;
|
||||
}
|
||||
nDesc = strlen(zDesc);
|
||||
nDesc = zDesc ? strlen(zDesc) : 0;
|
||||
if( nDesc>=50 ){
|
||||
sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
|
||||
}else{
|
||||
@@ -248,7 +257,7 @@ static void analysisLine(
|
||||
** two or three significant digits, with the decimal point being the fourth
|
||||
** character.
|
||||
*/
|
||||
static void analysisPercent(Analysis *p, double r){
|
||||
static void diskusedPercent(DiskUsed *p, double r){
|
||||
char zNum[100];
|
||||
char *zDP;
|
||||
int nLeadingDigit;
|
||||
@@ -277,8 +286,8 @@ static void analysisPercent(Analysis *p, double r){
|
||||
** a boolean expression that can go in the WHERE clause to select
|
||||
** the relevant rows of the s.zSU table.
|
||||
*/
|
||||
static int analysisSubreport(
|
||||
Analysis *p, /* Analysis context */
|
||||
static int diskusedSubreport(
|
||||
DiskUsed *p, /* DiskUsed context */
|
||||
char *zTitle, /* Title for this subreport */
|
||||
char *zWhere, /* WHERE clause for this subreport */
|
||||
sqlite3_int64 pgsz, /* Database page size */
|
||||
@@ -306,10 +315,10 @@ static int analysisSubreport(
|
||||
int rc;
|
||||
|
||||
if( zTitle==0 || zWhere==0 ){
|
||||
analysisError(p, 0);
|
||||
diskusedError(p, 0);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pStmt = analysisPrepare(p,
|
||||
pStmt = diskusedPrepare(p,
|
||||
"SELECT\n"
|
||||
" sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
|
||||
" sum(payload),\n" /* 1 */
|
||||
@@ -330,7 +339,7 @@ static int analysisSubreport(
|
||||
if( pStmt==0 ) return 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
analysisTitle(p, "%s", zTitle);
|
||||
diskusedTitle(p, "%s", zTitle);
|
||||
|
||||
nentry = sqlite3_column_int64(pStmt, 0);
|
||||
payload = sqlite3_column_int64(pStmt, 1);
|
||||
@@ -349,69 +358,69 @@ static int analysisSubreport(
|
||||
rc = SQLITE_DONE;
|
||||
|
||||
total_pages = leaf_pages + int_pages + ovfl_pages;
|
||||
analysisLine(p, "Percentage of total database", "%.3g%%\n",
|
||||
diskusedLine(p, "Percentage of total database", "%.3g%%\n",
|
||||
(total_pages*100.0)/(double)nPage);
|
||||
analysisLine(p, "Number of entries", "%lld\n", nentry);
|
||||
diskusedLine(p, "Number of entries", "%lld\n", nentry);
|
||||
storage = total_pages*pgsz;
|
||||
analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
|
||||
analysisLine(p, "Bytes of payload", "%-11lld ", payload);
|
||||
analysisPercent(p, payload*100.0/(double)storage);
|
||||
diskusedLine(p, "Bytes of storage consumed", "%lld\n", storage);
|
||||
diskusedLine(p, "Bytes of payload", "%-11lld ", payload);
|
||||
diskusedPercent(p, payload*100.0/(double)storage);
|
||||
if( ovfl_cnt>0 ){
|
||||
analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
|
||||
analysisPercent(p, ovfl_payload*100.0/(double)payload);
|
||||
diskusedLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
|
||||
diskusedPercent(p, ovfl_payload*100.0/(double)payload);
|
||||
}
|
||||
total_unused = leaf_unused + int_unused + ovfl_unused;
|
||||
total_meta = storage - payload - total_unused;
|
||||
analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
|
||||
analysisPercent(p, total_meta*100.0/(double)storage);
|
||||
diskusedLine(p, "Bytes of metadata","%-11lld ", total_meta);
|
||||
diskusedPercent(p, total_meta*100.0/(double)storage);
|
||||
if( cnt==1 ){
|
||||
analysisLine(p, "B-tree depth", "%lld\n", depth);
|
||||
diskusedLine(p, "B-tree depth", "%lld\n", depth);
|
||||
if( int_cell>1 ){
|
||||
analysisLine(p, "Average fanout", "%.1f\n",
|
||||
diskusedLine(p, "Average fanout", "%.1f\n",
|
||||
(double)(int_cell+int_pages)/(double)int_pages);
|
||||
}
|
||||
}
|
||||
if( nentry>0 ){
|
||||
analysisLine(p, "Average payload per entry", "%.1f\n",
|
||||
diskusedLine(p, "Average payload per entry", "%.1f\n",
|
||||
(double)payload/(double)nentry);
|
||||
analysisLine(p, "Average unused bytes per entry", "%.1f\n",
|
||||
diskusedLine(p, "Average unused bytes per entry", "%.1f\n",
|
||||
(double)total_unused/(double)nentry);
|
||||
analysisLine(p, "Average metadata per entry", "%.1f\n",
|
||||
diskusedLine(p, "Average metadata per entry", "%.1f\n",
|
||||
(double)total_meta/(double)nentry);
|
||||
}
|
||||
analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
|
||||
diskusedLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
|
||||
if( nentry>0 ){
|
||||
analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
|
||||
analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
|
||||
diskusedLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
|
||||
diskusedPercent(p, ovfl_cnt*100.0/(double)nentry);
|
||||
}
|
||||
if( int_pages>0 ){
|
||||
analysisLine(p, "Index pages used", "%lld\n", int_pages);
|
||||
diskusedLine(p, "Index pages used", "%lld\n", int_pages);
|
||||
}
|
||||
analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
|
||||
diskusedLine(p, "Primary pages used", "%lld\n", leaf_pages);
|
||||
if( ovfl_cnt ){
|
||||
analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
|
||||
diskusedLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
|
||||
}
|
||||
analysisLine(p, "Total pages used", "%lld\n", total_pages);
|
||||
diskusedLine(p, "Total pages used", "%lld\n", total_pages);
|
||||
if( int_pages>0 ){
|
||||
analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
|
||||
diskusedLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
|
||||
}
|
||||
analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
|
||||
diskusedLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
|
||||
if( ovfl_cnt ){
|
||||
analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
|
||||
diskusedLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
|
||||
}
|
||||
analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
|
||||
analysisPercent(p, total_unused*100.0/(double)storage);
|
||||
diskusedLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
|
||||
diskusedPercent(p, total_unused*100.0/(double)storage);
|
||||
}
|
||||
return analysisStmtFinish(p, rc, pStmt);
|
||||
return diskusedStmtFinish(p, rc, pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL Function: analyze(SCHEMA)
|
||||
** SQL Function: diskused(SCHEMA)
|
||||
**
|
||||
** Analyze the database schema named in the argument. Return text
|
||||
** containing the analysis.
|
||||
** containing the space utilization stats.
|
||||
*/
|
||||
static void analyzeFunc(
|
||||
static void diskusedFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
@@ -426,7 +435,7 @@ static void analyzeFunc(
|
||||
sqlite3_int64 nFreeList;
|
||||
sqlite3_int64 nIndex;
|
||||
sqlite3_int64 nWORowid;
|
||||
Analysis s;
|
||||
DiskUsed s;
|
||||
sqlite3_uint64 r[2];
|
||||
|
||||
(void)argc;
|
||||
@@ -435,34 +444,34 @@ static void analyzeFunc(
|
||||
s.context = context;
|
||||
s.pOut = sqlite3_str_new(0);
|
||||
if( sqlite3_str_errcode(s.pOut) ){
|
||||
analysisError(&s, 0);
|
||||
diskusedError(&s, 0);
|
||||
return;
|
||||
}
|
||||
s.zSchema = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( s.zSchema==0 ){
|
||||
s.zSchema = "main";
|
||||
}else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
|
||||
analysisReset(&s);
|
||||
diskusedReset(&s);
|
||||
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
|
||||
rc = diskusedSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
|
||||
" WHERE name=%Q COLLATE nocase",s.zSchema);
|
||||
if( rc || ii==0 ){
|
||||
analysisReset(&s);
|
||||
diskusedReset(&s);
|
||||
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
|
||||
if( s.zSU==0 ){ analysisError(&s, 0); return; }
|
||||
s.zSU = sqlite3_mprintf("diskused%016llx%016llx", r[0], r[1]);
|
||||
if( s.zSU==0 ){ diskusedError(&s, 0); return; }
|
||||
|
||||
/* The s.zSU table contains the data used for the analysis.
|
||||
** The table name contains 128-bits of randomness to avoid
|
||||
** collisions with preexisting tables in temp.
|
||||
*/
|
||||
rc = analysisSql(&s,
|
||||
rc = diskusedSql(&s,
|
||||
"CREATE TABLE temp.%s(\n"
|
||||
" name text, -- A table or index\n"
|
||||
" tblname text, -- Table that owns name\n"
|
||||
@@ -489,7 +498,7 @@ static void analyzeFunc(
|
||||
|
||||
/* Populate the s.zSU table
|
||||
*/
|
||||
rc = analysisSql(&s,
|
||||
rc = diskusedSql(&s,
|
||||
"WITH\n"
|
||||
" allidx(idxname) AS (\n"
|
||||
" SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
|
||||
@@ -541,38 +550,38 @@ static void analyzeFunc(
|
||||
if( rc ) return;
|
||||
|
||||
nPage = 0;
|
||||
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
|
||||
rc = diskusedSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( nPage<=0 ){
|
||||
/* Very brief reply for an empty database */
|
||||
analysisReset(&s);
|
||||
diskusedReset(&s);
|
||||
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Begin generating the report */
|
||||
analysisTitle(&s, "Database storage utilization report");
|
||||
diskusedTitle(&s, "Database storage utilization report");
|
||||
pgsz = 0;
|
||||
rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
|
||||
rc = diskusedSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
|
||||
analysisLine(&s, "Pages in the database", "%lld\n", nPage);
|
||||
diskusedLine(&s, "Page size in bytes","%lld\n",pgsz);
|
||||
diskusedLine(&s, "Pages in the database", "%lld\n", nPage);
|
||||
|
||||
nPageInUse = 0;
|
||||
rc = analysisSqlInt(&s, &nPageInUse,
|
||||
rc = diskusedSqlInt(&s, &nPageInUse,
|
||||
"SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
|
||||
analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
|
||||
diskusedLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
|
||||
diskusedPercent(&s, (nPageInUse*100.0)/(double)nPage);
|
||||
|
||||
nFreeList = 0;
|
||||
rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
|
||||
rc = diskusedSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
|
||||
analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
|
||||
diskusedLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
|
||||
diskusedPercent(&s, (nFreeList*100.0)/(double)nPage);
|
||||
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
|
||||
rc = diskusedSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( ii==0 || nPage<=1 ){
|
||||
ii = 0;
|
||||
@@ -581,97 +590,99 @@ static void analyzeFunc(
|
||||
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
|
||||
ii = (sqlite3_int64)ceil(rAvPage);
|
||||
}
|
||||
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
|
||||
analysisPercent(&s, (ii*100.0)/(double)nPage);
|
||||
diskusedLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
|
||||
diskusedPercent(&s, (ii*100.0)/(double)nPage);
|
||||
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
rc = diskusedSqlInt(&s, &ii,
|
||||
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of tables", "%lld\n", ii);
|
||||
diskusedLine(&s, "Number of tables", "%lld\n", ii);
|
||||
nWORowid = 0;
|
||||
rc = analysisSqlInt(&s, &nWORowid,
|
||||
rc = diskusedSqlInt(&s, &nWORowid,
|
||||
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
if( nWORowid>0 ){
|
||||
analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
|
||||
analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
|
||||
diskusedLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
|
||||
diskusedLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
|
||||
}
|
||||
nIndex = 0;
|
||||
rc = analysisSqlInt(&s, &nIndex,
|
||||
rc = diskusedSqlInt(&s, &nIndex,
|
||||
"SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
|
||||
diskusedLine(&s, "Number of indexes", "%lld\n", nIndex);
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
rc = diskusedSqlInt(&s, &ii,
|
||||
"SELECT count(*) FROM \"%w\".sqlite_schema"
|
||||
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
|
||||
analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
|
||||
analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
|
||||
diskusedLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
|
||||
diskusedLine(&s, "Number of implied indexes", "%lld\n", ii);
|
||||
diskusedLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
rc = diskusedSqlInt(&s, &ii,
|
||||
"SELECT sum(payload) FROM temp.%s"
|
||||
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
|
||||
s.zSU);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
|
||||
analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
|
||||
diskusedLine(&s, "Bytes of payload", "%-11lld ", ii);
|
||||
diskusedPercent(&s, ii*100.0/(double)(pgsz*nPage));
|
||||
|
||||
analysisTitle(&s, "Page counts for all tables with their indexes");
|
||||
pStmt = analysisPrepare(&s,
|
||||
diskusedTitle(&s, "Page counts for all tables with their indexes");
|
||||
pStmt = diskusedPrepare(&s,
|
||||
"SELECT upper(tblname),\n"
|
||||
" sum(int_pages+leaf_pages+ovfl_pages)\n"
|
||||
" FROM temp.%s\n"
|
||||
" WHERE tblname IS NOT NULL\n"
|
||||
" GROUP BY 1\n"
|
||||
" ORDER BY 2 DESC, 1;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
analysisPercent(&s, (nn*100.0)/(double)nPage);
|
||||
diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
diskusedPercent(&s, (nn*100.0)/(double)nPage);
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
if( diskusedStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
analysisTitle(&s, "Page counts for all tables and indexes separately");
|
||||
pStmt = analysisPrepare(&s,
|
||||
diskusedTitle(&s, "Page counts for all tables and indexes separately");
|
||||
pStmt = diskusedPrepare(&s,
|
||||
"SELECT upper(name),\n"
|
||||
" sum(int_pages+leaf_pages+ovfl_pages)\n"
|
||||
" FROM temp.%s\n"
|
||||
" WHERE name IS NOT NULL\n"
|
||||
" GROUP BY 1\n"
|
||||
" ORDER BY 2 DESC, 1;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
analysisPercent(&s, (nn*100.0)/(double)nPage);
|
||||
diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
diskusedPercent(&s, (nn*100.0)/(double)nPage);
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
if( diskusedStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
if( nWORowid>0 ){
|
||||
rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
|
||||
rc = diskusedSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
|
||||
pgsz, nPage);
|
||||
if( rc ) return;
|
||||
rc = analysisSubreport(&s, "All rowid tables",
|
||||
rc = diskusedSubreport(&s, "All rowid tables",
|
||||
"NOT is_without_rowid AND NOT is_index",
|
||||
pgsz, nPage);
|
||||
if( rc ) return;
|
||||
}
|
||||
rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, "All indexes", "is_index", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
|
||||
pStmt = analysisPrepare(&s,
|
||||
pStmt = diskusedPrepare(&s,
|
||||
"SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
|
||||
" GROUP BY 1 ORDER BY 1",
|
||||
s.zSU);
|
||||
@@ -683,7 +694,7 @@ static void analyzeFunc(
|
||||
if( nSubIndex==0 ){
|
||||
char *zTitle = sqlite3_mprintf("Table %s", zUpper);
|
||||
char *zWhere = sqlite3_mprintf("name=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
@@ -691,25 +702,25 @@ static void analyzeFunc(
|
||||
sqlite3_stmt *pS2;
|
||||
char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
|
||||
char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
|
||||
zWhere = sqlite3_mprintf("name=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
if( nSubIndex>1 ){
|
||||
zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
|
||||
zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}
|
||||
pS2 = analysisPrepare(&s,
|
||||
pS2 = diskusedPrepare(&s,
|
||||
"SELECT name, upper(name) FROM temp.%s"
|
||||
" WHERE is_index AND tblname=%Q",
|
||||
s.zSU, zName);
|
||||
@@ -722,21 +733,21 @@ static void analyzeFunc(
|
||||
const char *zN = (const char*)sqlite3_column_text(pS2, 0);
|
||||
zTitle = sqlite3_mprintf("Index %s", zU);
|
||||
zWhere = sqlite3_mprintf("name=%Q", zN);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}
|
||||
rc = analysisStmtFinish(&s, rc, pS2);
|
||||
rc = diskusedStmtFinish(&s, rc, pS2);
|
||||
if( rc ) break;
|
||||
}
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
if( diskusedStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
/* Append SQL statements that will recreate the raw data used for
|
||||
** the analysis.
|
||||
*/
|
||||
analysisTitle(&s, "Raw data used to generate this report");
|
||||
diskusedTitle(&s, "Raw data used to generate this report");
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
"The following SQL will create a table named \"space_used\" which\n"
|
||||
"contains most of the information used to generate the report above.\n"
|
||||
@@ -766,7 +777,7 @@ static void analyzeFunc(
|
||||
");\n"
|
||||
"INSERT INTO space_used VALUES\n"
|
||||
);
|
||||
pStmt = analysisPrepare(&s,
|
||||
pStmt = diskusedPrepare(&s,
|
||||
"SELECT quote(name), quote(tblname),\n" /* 0..1 */
|
||||
" is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
|
||||
" depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
|
||||
@@ -801,7 +812,7 @@ static void analyzeFunc(
|
||||
sqlite3_column_int64(pStmt, 17));
|
||||
}
|
||||
if( rc!=SQLITE_DONE ){
|
||||
analysisError(&s, "SQL run-time error: %s\nSQL: %s",
|
||||
diskusedError(&s, "SQL run-time error: %s\nSQL: %s",
|
||||
sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
|
||||
sqlite3_finalize(pStmt);
|
||||
return;
|
||||
@@ -814,14 +825,14 @@ static void analyzeFunc(
|
||||
sqlite3_free);
|
||||
s.pOut = 0;
|
||||
}
|
||||
analysisReset(&s);
|
||||
diskusedReset(&s);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_analyze_init(
|
||||
int sqlite3_diskused_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
@@ -829,8 +840,8 @@ int sqlite3_analyze_init(
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "analyze", 1,
|
||||
rc = sqlite3_create_function(db, "diskused", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
0, analyzeFunc, 0, 0);
|
||||
0, diskusedFunc, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
@@ -1165,6 +1165,9 @@ static char *portable_realpath(const char *zPath){
|
||||
** The file or directory X is not required to exist. The answer is formed
|
||||
** by calling system realpath() on the prefix of X that does exist and
|
||||
** appending the tail of X that does not (yet) exist.
|
||||
**
|
||||
** FIXME: This routine sometimes returns NULL rather than raising
|
||||
** an SQLITE_NOMEM error if an OOM is encountered.
|
||||
*/
|
||||
static void realpathFunc(
|
||||
sqlite3_context *context,
|
||||
@@ -1187,6 +1190,7 @@ static void realpathFunc(
|
||||
if( zPath==0 ) return;
|
||||
if( zPath[0]==0 ) zPath = ".";
|
||||
zCopy = sqlite3_mprintf("%s",zPath);
|
||||
if( zCopy==0 ) return;
|
||||
len = strlen(zCopy);
|
||||
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
|
||||
len--;
|
||||
|
||||
+23
-10
@@ -179,16 +179,26 @@ static unsigned int deltaGetInt(const char **pz, int *pLen){
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
|
||||
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
|
||||
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
};
|
||||
unsigned int v = 0;
|
||||
int c;
|
||||
unsigned char *z = (unsigned char*)*pz;
|
||||
unsigned char *zStart = z;
|
||||
while( (c = zValue[0x7f&*(z++)])>=0 ){
|
||||
v = (v<<6) + c;
|
||||
unsigned char *zEnd = z + (*pLen);
|
||||
while( z<zEnd && (c = zValue[*z])>=0 ){
|
||||
v = (v<<6) + c;
|
||||
z++;
|
||||
}
|
||||
z--;
|
||||
*pLen -= z - zStart;
|
||||
|
||||
*pLen -= (int)(z - (unsigned char*)*pz);
|
||||
*pz = (char*)z;
|
||||
return v;
|
||||
}
|
||||
@@ -278,7 +288,8 @@ static unsigned int checksum(const char *zIn, size_t N){
|
||||
** The delta string will be NUL-terminated, but it might also contain
|
||||
** embedded NUL characters if either the zSrc or zOut files are
|
||||
** binary. This function returns the length of the delta string
|
||||
** in bytes, excluding the final NUL terminator character.
|
||||
** in bytes, excluding the final NUL terminator character. It returns
|
||||
** 0 if an OOM occurs.
|
||||
**
|
||||
** Output Format:
|
||||
**
|
||||
@@ -370,6 +381,7 @@ static int delta_create(
|
||||
*/
|
||||
nHash = lenSrc/NHASH;
|
||||
collide = sqlite3_malloc64( (sqlite3_int64)nHash*2*sizeof(int) );
|
||||
if( collide==0 ) return 0;
|
||||
memset(collide, -1, nHash*2*sizeof(int));
|
||||
landmark = &collide[nHash];
|
||||
for(i=0; i<lenSrc-NHASH; i+=NHASH){
|
||||
@@ -520,7 +532,7 @@ static int delta_create(
|
||||
static int delta_output_size(const char *zDelta, int lenDelta){
|
||||
int size;
|
||||
size = deltaGetInt(&zDelta, &lenDelta);
|
||||
if( *zDelta!='\n' ){
|
||||
if( lenDelta<=0 || *zDelta!='\n' ){
|
||||
/* ERROR: size integer not terminated by "\n" */
|
||||
return -1;
|
||||
}
|
||||
@@ -562,7 +574,7 @@ static int delta_apply(
|
||||
#endif
|
||||
|
||||
limit = deltaGetInt(&zDelta, &lenDelta);
|
||||
if( *zDelta!='\n' ){
|
||||
if( lenDelta<=0 || *zDelta!='\n' ){
|
||||
/* ERROR: size integer not terminated by "\n" */
|
||||
return -1;
|
||||
}
|
||||
@@ -570,6 +582,7 @@ static int delta_apply(
|
||||
while( *zDelta && lenDelta>0 ){
|
||||
unsigned int cnt, ofst;
|
||||
cnt = deltaGetInt(&zDelta, &lenDelta);
|
||||
if( lenDelta<=0 ) return -1;
|
||||
switch( zDelta[0] ){
|
||||
case '@': {
|
||||
zDelta++; lenDelta--;
|
||||
@@ -889,7 +902,7 @@ static int deltaparsevtabNext(sqlite3_vtab_cursor *cur){
|
||||
}
|
||||
z = pCur->aDelta + pCur->iCursor;
|
||||
pCur->a1 = deltaGetInt(&z, &i);
|
||||
switch( z[0] ){
|
||||
switch( i>0 ? z[0] : 0 ){
|
||||
case '@': {
|
||||
z++;
|
||||
if( pCur->iNext>=pCur->nDelta ){
|
||||
@@ -1019,7 +1032,7 @@ static int deltaparsevtabFilter(
|
||||
a = pCur->aDelta;
|
||||
pCur->eOp = DELTAPARSE_OP_SIZE;
|
||||
pCur->a1 = deltaGetInt(&a, &i);
|
||||
if( a[0]!='\n' ){
|
||||
if( i<=0 || a[0]!='\n' ){
|
||||
pCur->eOp = DELTAPARSE_OP_ERROR;
|
||||
pCur->a1 = pCur->a2 = 0;
|
||||
pCur->iNext = pCur->nDelta;
|
||||
|
||||
+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
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -296,7 +296,7 @@ static void prefixLengthFunc(
|
||||
|
||||
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
-1
@@ -363,7 +363,7 @@ static int qpvtabBestIndex(
|
||||
}
|
||||
sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
|
||||
i,
|
||||
azColname[iCol],
|
||||
iCol>=0 ? azColname[iCol] : "rowid",
|
||||
op,
|
||||
pIdxInfo->aConstraint[i].usable);
|
||||
pVal = 0;
|
||||
|
||||
@@ -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
|
||||
+29
-11
@@ -400,6 +400,16 @@ static double seriesFloor(double r){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert a floating point value to its closest integer. Do so in
|
||||
** a way that avoids 'outside the range of representable values' warnings
|
||||
** from UBSAN.
|
||||
*/
|
||||
sqlite3_int64 seriesRealToI64(double r){
|
||||
if( r<-9223372036854774784.0 ) return SMALLEST_INT64;
|
||||
if( r>+9223372036854774784.0 ) return LARGEST_INT64;
|
||||
return (sqlite3_int64)r;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is called to "rewind" the series_cursor object back
|
||||
** to the first row of output. This method is always called at least
|
||||
@@ -522,7 +532,7 @@ static int seriesFilter(
|
||||
&& r>=(double)SMALLEST_INT64
|
||||
&& r<=(double)LARGEST_INT64
|
||||
){
|
||||
iMin = iMax = (sqlite3_int64)r;
|
||||
iMin = iMax = seriesRealToI64(r);
|
||||
}else{
|
||||
goto series_no_rows;
|
||||
}
|
||||
@@ -530,15 +540,19 @@ static int seriesFilter(
|
||||
iMin = iMax = sqlite3_value_int64(argv[iArg++]);
|
||||
}
|
||||
}else{
|
||||
if( idxNum & 0x0300 ){ /* value>X or value>=X */
|
||||
if( idxNum & 0x0300 ){ /* value>X (0x200) or value>=X (0x100) */
|
||||
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
|
||||
double r = sqlite3_value_double(argv[iArg++]);
|
||||
if( r<(double)SMALLEST_INT64 ){
|
||||
if( r<=(double)SMALLEST_INT64 ){
|
||||
iMin = SMALLEST_INT64;
|
||||
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
|
||||
iMin = (sqlite3_int64)seriesCeil(r)+1;
|
||||
}else if( r>(double)LARGEST_INT64 ){
|
||||
goto series_no_rows;
|
||||
}else{
|
||||
iMin = (sqlite3_int64)seriesCeil(r);
|
||||
iMin = seriesRealToI64(seriesCeil(r));
|
||||
if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
|
||||
if( iMin==LARGEST_INT64 ) goto series_no_rows;
|
||||
iMin++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
iMin = sqlite3_value_int64(argv[iArg++]);
|
||||
@@ -551,15 +565,19 @@ static int seriesFilter(
|
||||
}
|
||||
}
|
||||
}
|
||||
if( idxNum & 0x3000 ){ /* value<X or value<=X */
|
||||
if( idxNum & 0x3000 ){ /* value<X (0x2000) or value<=X (0x1000) */
|
||||
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
|
||||
double r = sqlite3_value_double(argv[iArg++]);
|
||||
if( r>(double)LARGEST_INT64 ){
|
||||
if( r>=(double)LARGEST_INT64 ){
|
||||
iMax = LARGEST_INT64;
|
||||
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
|
||||
iMax = ((sqlite3_int64)r)-1;
|
||||
}else if( r<=(double)SMALLEST_INT64 ){
|
||||
goto series_no_rows;
|
||||
}else{
|
||||
iMax = (sqlite3_int64)seriesFloor(r);
|
||||
iMax = seriesRealToI64(seriesFloor(r));
|
||||
if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
|
||||
if( iMax==SMALLEST_INT64 ) goto series_no_rows;
|
||||
iMax--;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
iMax = sqlite3_value_int64(argv[iArg++]);
|
||||
|
||||
+1
-1
@@ -175,7 +175,7 @@ static void hash_step(
|
||||
}else{
|
||||
i = 0;
|
||||
}
|
||||
(void)memcpy(&p->buffer[j], &data[i], len - i);
|
||||
if( len-i>0 ) (void)memcpy(&p->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
/* Compute a string using sqlite3_vsnprintf() and hash it */
|
||||
|
||||
+10
-9
@@ -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;
|
||||
@@ -422,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)*5LL*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];
|
||||
@@ -772,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];
|
||||
@@ -906,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);
|
||||
@@ -932,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;
|
||||
@@ -1721,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;
|
||||
@@ -2066,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{
|
||||
|
||||
@@ -120,6 +120,7 @@ static int sqlite3UuidStrToBlob(
|
||||
unsigned char *aBlob /* Write results here */
|
||||
){
|
||||
int i;
|
||||
if( zStr==0 ) return 1;
|
||||
if( zStr[0]=='{' ) zStr++;
|
||||
for(i=0; i<16; i++){
|
||||
if( zStr[0]=='-' ) zStr++;
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
** This file implements a virtual table that returns the whole numbers
|
||||
** between 1 and 4294967295, inclusive.
|
||||
**
|
||||
** TESTING AND DEBUG USE ONLY -> This is not production code. This is
|
||||
** not a deliverable. Use the generate_series() virtual table for
|
||||
** real-world applications instead of this extension. THIS EXTENSION
|
||||
** MAY CONTAIN BUGS.
|
||||
**
|
||||
** Example:
|
||||
**
|
||||
** CREATE VIRTUAL TABLE nums USING wholenumber;
|
||||
@@ -154,12 +159,14 @@ static int wholenumberFilter(
|
||||
pCur->iValue = 1;
|
||||
pCur->mxValue = 0xffffffff; /* 4294967295 */
|
||||
if( idxNum & 3 ){
|
||||
v = sqlite3_value_int64(argv[0]) + (idxNum&1);
|
||||
v = sqlite3_value_int64(argv[0]);
|
||||
if( v<=pCur->mxValue && (idxNum&1)!=0 ) v++;
|
||||
if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v;
|
||||
i++;
|
||||
}
|
||||
if( idxNum & 12 ){
|
||||
v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1);
|
||||
v = sqlite3_value_int64(argv[i]);
|
||||
if( v>0 && ((idxNum>>2)&1)!=0 ) v--;
|
||||
if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
|
||||
+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);
|
||||
|
||||
+21
-10
@@ -516,16 +516,26 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
|
||||
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
|
||||
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
};
|
||||
unsigned int v = 0;
|
||||
int c;
|
||||
unsigned char *z = (unsigned char*)*pz;
|
||||
unsigned char *zStart = z;
|
||||
while( (c = zValue[0x7f&*(z++)])>=0 ){
|
||||
v = (v<<6) + c;
|
||||
unsigned char *zEnd = z + (*pLen);
|
||||
while( z<zEnd && (c = zValue[*z])>=0 ){
|
||||
v = (v<<6) + c;
|
||||
z++;
|
||||
}
|
||||
z--;
|
||||
*pLen -= (int)(z - zStart);
|
||||
|
||||
*pLen -= (int)(z - (unsigned char*)*pz);
|
||||
*pz = (char*)z;
|
||||
return v;
|
||||
}
|
||||
@@ -601,7 +611,7 @@ static int rbuDeltaApply(
|
||||
#endif
|
||||
|
||||
limit = rbuDeltaGetInt(&zDelta, &lenDelta);
|
||||
if( *zDelta!='\n' ){
|
||||
if( lenDelta<=0 || *zDelta!='\n' ){
|
||||
/* ERROR: size integer not terminated by "\n" */
|
||||
return -1;
|
||||
}
|
||||
@@ -609,11 +619,12 @@ static int rbuDeltaApply(
|
||||
while( *zDelta && lenDelta>0 ){
|
||||
unsigned int cnt, ofst;
|
||||
cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
|
||||
if( lenDelta<=0 ) return -1;
|
||||
switch( zDelta[0] ){
|
||||
case '@': {
|
||||
zDelta++; lenDelta--;
|
||||
ofst = rbuDeltaGetInt(&zDelta, &lenDelta);
|
||||
if( lenDelta>0 && zDelta[0]!=',' ){
|
||||
if( lenDelta>0 || zDelta[0]!=',' ){
|
||||
/* ERROR: copy command not terminated by ',' */
|
||||
return -1;
|
||||
}
|
||||
@@ -638,7 +649,7 @@ static int rbuDeltaApply(
|
||||
/* ERROR: insert command gives an output larger than predicted */
|
||||
return -1;
|
||||
}
|
||||
if( (int)cnt>lenDelta ){
|
||||
if( (i64)cnt>(i64)lenDelta ){
|
||||
/* ERROR: insert count exceeds size of delta */
|
||||
return -1;
|
||||
}
|
||||
@@ -676,7 +687,7 @@ static int rbuDeltaApply(
|
||||
static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){
|
||||
int size;
|
||||
size = rbuDeltaGetInt(&zDelta, &lenDelta);
|
||||
if( *zDelta!='\n' ){
|
||||
if( lenDelta<=0 || *zDelta!='\n' ){
|
||||
/* ERROR: size integer not terminated by "\n" */
|
||||
return -1;
|
||||
}
|
||||
@@ -724,7 +735,7 @@ static void rbuFossilDeltaFunc(
|
||||
return;
|
||||
}
|
||||
|
||||
aOut = sqlite3_malloc(nOut+1);
|
||||
aOut = sqlite3_malloc64((i64)nOut+1);
|
||||
if( aOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+6
-3
@@ -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
|
||||
@@ -761,6 +761,9 @@ static int nodeAcquire(
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
}
|
||||
}else if( iNode<=0 ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
|
||||
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
|
||||
if( !pNode ){
|
||||
@@ -1402,7 +1405,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;
|
||||
@@ -3644,7 +3647,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
|
||||
|
||||
@@ -1557,7 +1557,7 @@ SQLITE_WASM_EXPORT2(int,sqlite3__wasm_posix_create_file,
|
||||
SQLITE_WASM_EXPORT2(const char *,sqlite3__wasm_kvvfsMakeKey,
|
||||
(const char *zClass, const char *zKeyIn)){
|
||||
static char buf[SQLITE_KVOS_SZ+1] = {0};
|
||||
assert(sqlite3KvvfsMethods.nKeySize>24);
|
||||
assert(sqlite3KvvfsMethods.nKeySize>32);
|
||||
if( zClass && *zClass ){
|
||||
kvrecordMakeKey(zClass, zKeyIn, buf);
|
||||
return buf;
|
||||
|
||||
@@ -982,11 +982,11 @@ FUZZCHECK_SRC = sqlite3.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/test/vt02.c \
|
||||
$(TOP)/ext/misc/analyze.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/diskused.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/randomjson.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
@@ -2236,11 +2236,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)
|
||||
@@ -2345,12 +2340,12 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
$(TOP)/ext/intck/sqlite3intck.h \
|
||||
$(TOP)/ext/misc/analyze.c \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
$(TOP)/ext/misc/decimal.c \
|
||||
$(TOP)/ext/misc/diskused.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Avoid\sa\sresource\sleak\sin\san\serror\spath\sin\sthe\sicu\sextension.
|
||||
D 2026-05-28T11:29:05.704
|
||||
C Use\sSQLITE_FINISH\sin\sa\sfew\splaces\sin\sthe\score,\sto\shelp\sensure\sthat\spath\sis\nwell\stested.
|
||||
D 2026-06-19T22:57:44.085
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -7,7 +7,7 @@ F AGENTS.md 44ddfb38ef23e277888bd70ae378e6cbf5f5cab0e2a4420bd21d89b6caff7a4a
|
||||
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
|
||||
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 6f4294982758b5eeeac740c1a263186c3fcb9ba51d1b48261e321bcb37a41dbb
|
||||
F Makefile.msc ae6c8f8c39ed9cec7e3fc27390209117a943acd81941b5e81e8cd828b1875d93
|
||||
F README.md f00091ffb5c6379b783afb57ca5f443a5742e119082f37c407f64a5e16c56346
|
||||
F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@@ -48,7 +48,7 @@ F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1
|
||||
F autosetup/jimsh0.c 740dc8cbfaedaff1f27b54b32e0015b22fa6c1a439492b9795968d61e56bab75
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl 67683f214977a416baafc4c1020f9940ff047a7306b2292c5872d6287460b7d5
|
||||
F autosetup/sqlite-config.tcl 2205b8bcc193a5d46584ebc1cf44c7a93a977d155e20dc38b18dcce720e58074
|
||||
F autosetup/sqlite-config.tcl a503f8b418547c2872348dbcb71abb09726f3970088625ec90d8000035b06b32
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
|
||||
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
|
||||
@@ -72,24 +72,24 @@ F doc/wal-lock.md 7db0cd61e2000b545b78ce89b0c2a9a8dd8d64c097839258ac10d7c5c4156e
|
||||
F ext/README.md 6eb1ac267d917767952ed0ef63f55de003b6a5da433ce1fa389e1a9532e73132
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test d9dfbf7fb527cfd43049e30a6238ef02c94484041fa4461ed41acbc6435425d6
|
||||
F ext/expert/sqlite3expert.c 546010043fbec93544f762de5161b3d553165859e6bd853c4b85c05f93484260
|
||||
F ext/expert/expert1.test 5292f9f488ca396fa0973e8ed5d26914bc29a0cdb5979db3d9e05416f30858c3
|
||||
F ext/expert/sqlite3expert.c 1a5296245bf80c201b2f5fa5947ef54a7d2b7e90428cb86240dd18076242ec1f
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c c395134bd6d4efa594a7d26578a1cb624c4027b79b4b5fcd44736c5ef1f5f725
|
||||
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
|
||||
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 4e62e96794ee8a5e73b1357e63d9b7749c30e0f712db3dfe27cd515e50afce9d
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 277f32f304e82f4397fc2a74793c0a95318b7abb9670b519e4805a00946cbd9b
|
||||
F ext/fts3/fts3_aux.c c105f6502df588f49a383eb22aed953844fb0e31265361a0cc8dd73037b37e39
|
||||
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 65e178107b59ad4724a11339a645f2e3789f3cf59b2f4e29c90efd864e53c5b4
|
||||
F ext/fts3/fts3_snippet.c 004923c49dca8c711f83fd31d3abe2e663df174afeae096b1c902cc52fda2097
|
||||
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
|
||||
F ext/fts3/fts3_test.c cc329471e573f95a6ea9fbca87e89dcfa1d355591c80172ffcd759ac521d25d8
|
||||
F ext/fts3/fts3_tokenize_vtab.c 66eba6c2baa04b2b15e80d68341b8fd0b4d3831f6b2edb33916a2906ff2d4389
|
||||
@@ -98,7 +98,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c c1de4ae28356ad98ccb8b2e3388a7fdcce7607b5523738c9afb6275dab765154
|
||||
F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
|
||||
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
|
||||
F ext/fts3/fts3_write.c d218b687fb55bce8c9340c6dbb368a10d94647cbe39801d85492d576a4e7da75
|
||||
F ext/fts3/fts3_write.c 3a78030f52747d53ef8c9bdff8ad137957834ce2ff7367db5de2b0fabdbefb5f
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
|
||||
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
|
||||
@@ -109,14 +109,14 @@ F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a0
|
||||
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
|
||||
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
|
||||
F ext/fts5/fts5Int.h 8d98f8e180fe28d6067e240ed45b9011735d29d5cfb5bac194e1e376baa7c708
|
||||
F ext/fts5/fts5_aux.c 042da27e97d38071312c111cf18f3cb7983b75ba5e724aa1c3164e61e90f428a
|
||||
F ext/fts5/fts5_aux.c 27af933e1a052d9f12d62a45bc60e0b65023997e0cea8f0476ef3cf66e724599
|
||||
F ext/fts5/fts5_buffer.c dcc3f0352339fe79c9d8abbc1c2009bc3469206467880bf43558447ef4f846fb
|
||||
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 87faf9a9ca65ec7be0886e13e9f7571d0d2416ab88e77a06d57bbaf3734bd51f
|
||||
F ext/fts5/fts5_expr.c b906c59e9e842805cc3eea4e131b822e586bb01260e542f67920c61798dcb53d
|
||||
F ext/fts5/fts5_hash.c 341a08ad0153b397b819ef3d7a7959c1dc3c84a6988a431d93dece8bd62ae10e
|
||||
F ext/fts5/fts5_index.c 5a2ab65d170a4b3314a927c5861740ba9070aa5bf326717690de5dd90fbb7b54
|
||||
F ext/fts5/fts5_main.c b0fed47b3b4420ba6810373480a75bc28a9c0b7d16478d19a396436fb3ff17d7
|
||||
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
|
||||
F ext/fts5/fts5_storage.c 46b0024fdd8002fbfba162230e5cc212c8f019ba4075396860354bfaf549a546
|
||||
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
|
||||
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
|
||||
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
|
||||
@@ -132,7 +132,7 @@ F ext/fts5/test/fts5ab.test c7e5c1519afb20366cb40d0179897a3c39d9fc06ba6b9c286d79
|
||||
F ext/fts5/test/fts5ac.test 4a73626de86f3d17c95738034880c4f0de8d54741fb943d819b528373657e59b
|
||||
F ext/fts5/test/fts5ad.test 058e616612964e61d19f70295f0e6eaedceb4b29b1fbf4f859615ef7e779dc22
|
||||
F ext/fts5/test/fts5ae.test 3d49edbd50bb0684199a2e7568aeb30d1d29718f5c0f61751983740fa836d15f
|
||||
F ext/fts5/test/fts5af.test ae81f08b8da4c5f9b3ec1ef538a4ab6b7c278e92fa9058d6dc5d842c5d9771b9
|
||||
F ext/fts5/test/fts5af.test 06f05ef35e8c66d8200204379e03d386673cf0c6f052bd67ddc3091dac3d32e9
|
||||
F ext/fts5/test/fts5ag.test 6667807b5d3fbf460892e756763fbe3d87a2fffe345a06514ba010ca6f6641f7
|
||||
F ext/fts5/test/fts5ah.test e1f01314b35745a30e1b494b46045b82005d71cae74f1ebd9f1338566b77f9fc
|
||||
F ext/fts5/test/fts5ai.test cbe26d78030998f535bc103f37915350b137a822c71a9db439a077d7666a3539
|
||||
@@ -147,6 +147,7 @@ F ext/fts5/test/fts5auxdata.test 372549088ff792655f73e62b9dfaf4863ce74f5e604c06c
|
||||
F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
|
||||
F ext/fts5/test/fts5bigpl.test 8f09858aab866c33593560e6480b2b6975ae7ff29ca32ad7b77e2da61402f8ef
|
||||
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
|
||||
F ext/fts5/test/fts5bigtok2.test d519c0c7c45fcbe75093cb9f4ea47defabbb4e8dd5d44411c8b12da47df538d9
|
||||
F ext/fts5/test/fts5blob.test 9644a5f917306690e08c5f89a470a3f2489376eaa52026eeca3209d149d6af74
|
||||
F ext/fts5/test/fts5cat.test bf67dd335f964482ee658287521b81e2b88697b45eb7f73933e15f198ed447cb
|
||||
F ext/fts5/test/fts5circref.test 0918c69440a73fff429bc9797b07086fc74d018eb3abb1cf9738980390bb2713
|
||||
@@ -165,12 +166,12 @@ F ext/fts5/test/fts5corrupt.test 237fce1c3261bb3a5bec333b0f0dbf5b105ec32627ef14c
|
||||
F ext/fts5/test/fts5corrupt2.test 4a03a158c2cb617c9f76d26b35c1ef2534124bc0bbddcea38dfd5b170ebea27b
|
||||
F ext/fts5/test/fts5corrupt3.test 121a8a7622dfe1be1bc55cbe70eddd6a3416f76a837dc8c06a11a32e781595a4
|
||||
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
|
||||
F ext/fts5/test/fts5corrupt5.test bdf6c04a1c9176507c8c0e66842b78b3fbcafccde20a41bb22a1b19896784b54
|
||||
F ext/fts5/test/fts5corrupt5.test 541dcee99eee8736f6b252d996a1262a778aa9fbe6344c781f9ea2becfae0bf5
|
||||
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/fts5corruptA.test 43bc56d8ec0ac87f82f6ac1700c16c902d952451f75f5c7dc02292c7b0a1d1b1
|
||||
F ext/fts5/test/fts5corruptbig.test 9f95b40fa36e292feceab02b2ef06e21878bfa1ac7afefa138aae05518b51774
|
||||
F ext/fts5/test/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
|
||||
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
|
||||
@@ -208,14 +209,14 @@ F ext/fts5/test/fts5join.test 3791e30d034050281191cd8141d969849f6c060135f1e3938f
|
||||
F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
|
||||
F ext/fts5/test/fts5leftjoin.test 1c14b51f4d1344a89e488160882f05a2246dd7e70c5cf077c8fb473e03c66338
|
||||
F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
|
||||
F ext/fts5/test/fts5locale.test 83ba7ee12628b540d3098f39c39c1de0c0440eddff8f7512c8c698d0c4a3ae3c
|
||||
F ext/fts5/test/fts5locale.test e662cc85b348d27247a7881409d1d1a5f910686c016591094be959d7a1b5a0ba
|
||||
F ext/fts5/test/fts5matchinfo.test bc9e74157773db7f00aec1e85587f1145956ebdf1672c136f0f04323b2752aa0
|
||||
F ext/fts5/test/fts5merge.test 088133e135ef7dcd6701753c95b8b10be3c52fa1a99507933e00756d6437489e
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test 83d6c5101a092c5db8fb631cfdd69a6482e20528b2750427641ac9050d9d0381
|
||||
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||
F ext/fts5/test/fts5near.test 33d60867581066e5db7016deb5d651628125d7ff4e0233a88175aa5b65874c74
|
||||
F ext/fts5/test/fts5near.test b173a56a3c45ac9fdd1626db2ddf923c42632489a4ccedfe68a806c1a0734286
|
||||
F ext/fts5/test/fts5onepass.test b56d4109e841c2bc83555c162515748780ea6e0c455c54cf4afd4bd940d14b84
|
||||
F ext/fts5/test/fts5optimize.test 264b9101721c17d06d1d174feb743fda3ddc89fad41dee980fef821428258e47
|
||||
F ext/fts5/test/fts5optimize2.test 795d4ae5f66a7239cf8d5aef4c2ea96aeb8bcd907bd9be0cfe22064fc71a44ed
|
||||
@@ -250,7 +251,7 @@ F ext/fts5/test/fts5securefault.test c34a28c7cd2f31a8b8907563889e1329a97da975c08
|
||||
F ext/fts5/test/fts5simple.test 302cdb4f8a3350b091f4f1bccd82d05610428657f6f9e81c17703ba48267ec40
|
||||
F ext/fts5/test/fts5simple2.test d10d963a357b8ec77b99032e4c816459b4dbdb1f6eee25eada7ef3ed245cb2dc
|
||||
F ext/fts5/test/fts5simple3.test 4e03b82e669dc07bf9c9a04c306fa493764bc49c93e539896d87d88bd374fece
|
||||
F ext/fts5/test/fts5synonym.test becc8cea6cfc958a50b30c572c68cbfdf7455971d0fe988202ce67638d2c6cf6
|
||||
F ext/fts5/test/fts5synonym.test e7facc771e5d00f24df64e169d466cb544b584f5cccc9a346eb30235e6dff82c
|
||||
F ext/fts5/test/fts5synonym2.test 58f357b997cf2fedeeb9d0de4db9f880fa96fa2fe27a743bfe7d7b96895bdd87
|
||||
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
@@ -280,7 +281,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 1bc9a5b60e6ec12fc9795aa3a416547e44ee826d954e28a4c36de28eec14d907
|
||||
F ext/icu/icu.c 4793f95ec022a2f77eade71a7fb2199095756e5b8187b4753ada0e25dbd134b5
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/intck/intck1.test 53d885075abeb45aeb1eeffeaa8560b329060835ade4af5c44cf5fcb581c1e63
|
||||
F ext/intck/intck2.test a29343a8e65c5c3400e10747f394924f3df95a5b2de94f46e9b5c9b97f5e7339
|
||||
@@ -360,25 +361,24 @@ F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b6
|
||||
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
|
||||
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
|
||||
F ext/misc/amatch.c 972a250631d481f38736b46740bf7f5c9646a0f2bb53800543299a746ff1bac6
|
||||
F ext/misc/analyze.c d311ad12179ef4f945f18fbe7917a3a602765afd152e5bd71d358ee9a7c67473
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
|
||||
F ext/misc/base85.c c713c7c81b05558c488cbdd8c68d612d5a97f9f0b8adf1167148dd7c89ce3f96
|
||||
F ext/misc/basexx.c 89ad6b76558efbceb627afd5e2ef1d84b2e96d9aaf9b7ecb20e3d00b51be6fcf
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
F ext/misc/btreeinfo.c 5fe97f798a9ee90e92b3031ed7969ec3f558661bb36b821c3ba045a17cfb951c
|
||||
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/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
|
||||
F ext/misc/compress.c 5cc142aa82d1589a31c384657d0418c0eb0871348a2201e5dca32d24a0dd6654
|
||||
F ext/misc/csv.c 5ca451b9ce77322c4ce8476766e7ed18160e5c8b19e7cab76e13006d631b9e8f
|
||||
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
|
||||
F ext/misc/decimal.c 432e5b03a0e2a68a1846a9852a565a1b546ca9b295deda834e4653f0f5577daa
|
||||
F ext/misc/decimal.c 75f206e86072bd772041e6731d153517094e298a4b8c763a9f68d73d21b52651
|
||||
F ext/misc/diskused.c 8acb4f27488fd8b9bdb0a3d300a7bd761b797b6e7858ac8038398263cededc48
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 9670c8ff7b255eea7845abc5123a4958e74016c16990b10497e56380f91704b9
|
||||
F ext/misc/fileio.c 936c0a7b3382a047d833ad33f62ba59a3847b79ea745bf529797cd344966fbb0
|
||||
F ext/misc/fossildelta.c 6aa3f15279cd2d796583e3ff654be7d2df745fdbea7987c1640e78ce1fac899e
|
||||
F ext/misc/fileio.c a8caf3ffb59af6e9870d1a1c739981727ba165cd667bda085fa21ccfc8694059
|
||||
F ext/misc/fossildelta.c 37b67b2710a0dd2da7b3aeea19388a069471eb0fc04702a0521237770d0d04f1
|
||||
F ext/misc/fuzzer.c decaca5a3479dfba69576cd41d4e17161eaf154a5438e12d316bbc5853571802
|
||||
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
|
||||
F ext/misc/memstat.c 03ab52d2d841eb3f55118105c1964d5225f152b23bd708844c648b48d14ccbcf
|
||||
@@ -388,19 +388,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 efc261429fd8ab43cedc0d38b94d86d87437af5550651bceb618bd7e84e25125
|
||||
F ext/misc/qpvtab.c 470a5fffba005c8e1994209e59c1848122351e19522de71beb68d666c4fa39a5
|
||||
F ext/misc/percentile.c b6b9c740f0dc42838efd776eec0f68a93bc5ac86524c71337a70950860bf6c4d
|
||||
F ext/misc/prefixes.c e7d3e7a39174db412c5f77c266fa221c2dc3cb2621a9422835a607ad08805eb2
|
||||
F ext/misc/qpvtab.c eeb04e4fcead64648629d6375077a5d5fd48c0384023edd21defa32730714d5e
|
||||
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
|
||||
F ext/misc/regexp.c 378e6e84516952a4b9f3f4df88927f20e6538e2609f55b773ed78899dab8206e
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c df54e202887e480bf9cd73168c9ac829e3b0211381b68b9809e0cb5bc1bdc2cf
|
||||
F ext/misc/series.c 496f43bac9bad2ee2cea63fb5212036f30ad3003b4cd317d5c2d6f3ad7c7d264
|
||||
F ext/misc/sha1.c 9a11826db885e8afd997c0a1b28bb799a43e462ef770ac33f19e744887c9c6fa
|
||||
F ext/misc/series.c ba66183ae4da6875e5cdafc065322118fd7f455a568ea2f22b45eff85f639f42
|
||||
F ext/misc/sha1.c eed0ad67ad7c69798278183a74523d95623d4864821a3f4dd82b234568e307c1
|
||||
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 36b0f4893ff583b6dcc727beca44cc262e7855713aea57a0154766936352cf81
|
||||
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
|
||||
@@ -412,15 +411,15 @@ F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762b
|
||||
F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
|
||||
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
|
||||
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
|
||||
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
||||
F ext/misc/uuid.c 37297e61935c2d0c425b742100f904d02c866fdeabe0427fe59aed1543e7c0ec
|
||||
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
||||
F ext/misc/vfsstat.c 2b21efa93062ce814fbe28e6dff2acfafa4073a14b8d02cacfb4da1d604d05a5
|
||||
F ext/misc/vfstrace.c fc8c393a8316a8c20867b7e6e92908c4f81060c9e1f24d6ad9aefdc91c01dd13
|
||||
F ext/misc/vtablog.c 6c0c11c4822ab6c1a205718ea7c6d1bb561d96b27104b9c1fe84d01aa62d6c9c
|
||||
F ext/misc/vtshim.c f5ab480d1e33fa46a0b138359bedc9979e32798d72348e04bbe6093f9ae95c7b
|
||||
F ext/misc/wholenumber.c aa5e6d786fe8d79bc100ea0e852249c026a91ae65a5c1bcb2b869cd1a7cdd6d5
|
||||
F ext/misc/wholenumber.c e41953e078894e66a0ff05dd6c76a61f904828c9a4620c7255fac26754f30d3a
|
||||
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
|
||||
@@ -470,7 +469,7 @@ F ext/rbu/rbuvacuum.test e3585cfda220038e8186c583e9bd2aaa9eccd0a5c2e40ed861de3c9
|
||||
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c 28246b647831409e84dfb8286fbeda55f1de89e934571509a23a67ada572d0c0
|
||||
F ext/rbu/sqlite3rbu.c c84dd68888640c56aa4d713e38013a202b10bf1ef2e423f7be2167bd826e69d8
|
||||
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
|
||||
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
|
||||
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
|
||||
@@ -493,8 +492,8 @@ F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f
|
||||
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 acc098e82686fa278c20973d601b4c2489389f5d580d42efe0f799d2cf8cdf38
|
||||
F ext/rtree/geopoly.c 77bad24162b6ae84a2fd6de3f1f8ad0b255a4ceb572f50f8771d1ac9d4d986d8
|
||||
F ext/rtree/rtree.c 0e7e3dd53ef90ab540ed991df3395f4e2e2204e85351a2e6bc3e6ae55c23640c
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
@@ -505,7 +504,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
|
||||
@@ -607,7 +606,7 @@ F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 4325cb9a5ebfbff7cd3060e309b16711
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-wl.c-pp.js 3dbd918ef037cd8fa9c7b4dccb3c8637b228638654c429e7df6acab5981c75e2
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3da8fe72dc9e76614a9c102b92e777ce03f81d788b607701c828d8fcbac44b06
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81
|
||||
F ext/wasm/api/sqlite3-wasm.c ddf9d435b2e901eaceb805ff694e9609c2f32b5cf89a4f164e734a6fa303fdd2
|
||||
F ext/wasm/api/sqlite3-wasm.c 0bcc42b1faff0e4543bba1b595fe9cfde80e0c29e3abc475bce725f2a326a8e5
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 46919740f8176c10f691431a81c769c35657e3b537e2ed2bde691f9017b0ee8a
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 21b20d3b8d43471d1647123616a7e5435b1e4b6fa447714f91ffc7f950ea01e8
|
||||
F ext/wasm/common/SqliteTestUtil.js dae753b95e72248c4395d8de8359e0d055cd9928488e8dd84aef89e46d23b32e
|
||||
@@ -660,7 +659,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 d9cbbee974a8cd3999430130378878bd87b8c5754397a69ec322f4c9cc3e4e41
|
||||
F main.mk 77e33a16a795abd4a07a55f7eb2e11136326998db597b67c8655d5d2d9b98054
|
||||
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -671,38 +670,38 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
|
||||
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
|
||||
F src/alter.c d7cbe4332a7a2c3a21ab58ee2609efade493f6ae78254613ada0759898629ee3
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/alter.c ff7f795c602751a574488780cfa1259f24cccbf32ddf2205b6283c0e6998ae50
|
||||
F src/analyze.c 73162482c656187823217f4c00758c9ee13a420c8745bc542129e0279b792287
|
||||
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
|
||||
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
|
||||
F src/backup.c 6ebe22ccbedfcb92423833992130e8d65824be4e6599c3a03f540ab38fc7d13c
|
||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c 2f74489af68281d143f5c4e9ef8ba280cee86fce67a64b3eff9344bbabc5dadf
|
||||
F src/btree.c c9b13797b0b68e0c057ec796976b1ab1e8b4e766d1a7c7f919b2d8a1d2193a80
|
||||
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 866e584cdf40fbc83f530af9fd4d0991582a6fdbd8a9911b7cdbbea5f26a4a9e
|
||||
F src/build.c 09946336c3011c2ae2faccdf04e33336e1cd51fd836651be0cd7eb5814f7f6a0
|
||||
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
|
||||
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
|
||||
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
|
||||
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
|
||||
F src/date.c 86d9530729eeb5b3d833e7403de495f4d4b79f3d5f7e74bcc8abda237f5aeafb
|
||||
F src/dbpage.c c6a9de13b0a01f0bc94a41e16213ab1ecd15ccfe86df7255ced40fda9446257d
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
|
||||
F src/expr.c d2188a699ded4522f15cf23d4c82da0ad73dcda09cd943982906824ef019947f
|
||||
F src/expr.c e97dd9f6ada4c448764e225d8963091bf630b3efb2c92e4d0762571cca2a14e5
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
|
||||
F src/func.c e8525e6c5493149680b0ebd3352e7f004ee7283181f24809b603329afe911443
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/func.c 7e049176003271095ba560bca90995c8cb7c1e944aee539513daba015b172a18
|
||||
F src/global.c 7eea537ac0c113ac55cb2dd4d8fc2a6a91ae478be34231b4efaffc46817fee85
|
||||
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
|
||||
F src/hwtime.h 5cb15147c8583d0fc4748e1c12ea6f38c9deaeefa147a4d8d379fd9bc81fee9a
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 8dbc22f6ddcc5f0af3abf11daeb89b1978f00059cda15ebc61251fa7724fc7ee
|
||||
F src/json.c 83122c47ac1c86a3870398e872b1d1afa6439f46fdb92975aa435267771c7ee4
|
||||
F src/insert.c e6e9b574b4863649e2c433f2260f226183e697df1ab73fcb8da9a85d5abcd390
|
||||
F src/json.c f058c449acb9fdb1d3d1bb9f7e97b225ba773f5b6fdcec4310d3f49980125ed4
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 78d5b06f18996ffa1203129b28fea043f63a87a4117539678f1d761c30b4ff65
|
||||
F src/main.c 6180079f53ccdd784df2eddc3751f49ea7153c5959bee792b19ad9f4bdbcf437
|
||||
F src/loadext.c 5cd4cd7ec6e1a46416806899086363fbf95eecd3bfb9a388b436c9a77243c902
|
||||
F src/main.c efd782fadd65b8e67952f439d56d7605134582346573018a614a8e082e074bd7
|
||||
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -718,32 +717,32 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c caec9862aeebad01f6c8997cf709a239abeb0715fcce1895720b87fe7e2ef42f
|
||||
F src/mutex_w32.c d44e94c064f8ab39e0318fb6fa00171cf7e5645bd4241129b07d655a8ddbd44b
|
||||
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
|
||||
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
|
||||
F src/os.c 9566966dd14376099fe8f715e744ab4fef204f55bd89126c5ddd06eb37df9457
|
||||
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
|
||||
F src/os_kv.c b9df749ad64c498e8d398d83bb085cfc0ef381b2c103be6c63ac22fc4f2cf680
|
||||
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
|
||||
F src/os_unix.c 83759942d1ea8d59daed50901c123016f845fada74caf3496b8a2537c9a08838
|
||||
F src/os_win.c 8df4b34ec6a08616a7ac33164999524ef773fa359d39ae9ae0e7e1ae4f167440
|
||||
F src/os_win.c 68b1c31693a5aeeb8126f618c95f7b53fb39e254836f9a95fbf2733461a7e01d
|
||||
F src/os_win.h c06ccc3a090cf54202ea58981c298817f3309d4c9e4d52ad0a02927346493721
|
||||
F src/pager.c e0b3b6e39c3a783957d640b28401401d1f3c556803c80695958dd2b9db4ef72d
|
||||
F src/pager.c f88073a00933c885b167b6d25afc4d1b83c1706943572f5653fb64a7f5bde105
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y d5a3c5b0277a441c38b35071c05e2b61ff5fc918a63309c809f4b6706179c320
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pcache1.c d7ee0f95992501a65379f620b3de1430b64e52e397769938668a9fd9dd1c8145
|
||||
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
|
||||
F src/prepare.c 084a037fd3810cb7ffbfc001cd58c0ffac68ba36598a5084b55ea2a090014ebd
|
||||
F src/printf.c 2bc09ee91d69c709528575bbbee2199e16d6a7e68e1508ac7cf998a7289170ca
|
||||
F src/prepare.c d055c59c23b917367ed199a52888132316aa9cb9f7653ca71f0c45bd267206fd
|
||||
F src/printf.c 6916d50913c3271aefe96d3483701ceca8644331ec4c7b23a5aa54a9ba36230f
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 7e936a09405cb59e2b3e51a3ad23753e4803afc5269c5171a54c9bdd70f4fc50
|
||||
F src/resolve.c d0724113da9f5c0430d2052808ce59519f51ae7c4fbb1f5ef21fe3a832956086
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
|
||||
F src/shell.c.in 691fac6a7f6f6fc72836aa2779d81b8cf67c896a15699c65e810cd1e8c6270f4
|
||||
F src/sqlite.h.in 749454ec71c875bc130d399ff9a7e47191d143d1b9d8b4af3839b6028df9eda9
|
||||
F src/select.c 80ea6935f8470b97d1212bc1b759b7fadb28351797877f493d0cf598be1fef5e
|
||||
F src/shell.c.in a4e83895cfa336065ad7f7a7dea8fc2a19d050f7ce7466621c67208acaac9e44
|
||||
F src/sqlite.h.in 8c70db561507478176b942a3f88cac396e00993eafb827ed31d48c191f327408
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
|
||||
F src/sqliteInt.h 5bec8cfdc8346a122b35312452eb6af33fc750a6c901f2c651a2f53eba0b979f
|
||||
F src/sqlite3ext.h 0efd4723bad9124ea1f581d9f1ea0254ac1c6f3e5fb29e4f3dcf36c72485a456
|
||||
F src/sqliteInt.h 92563b8edc673513b82d87bf6a8d7aeb554b2c7b7d5e30992fbca04010db79ac
|
||||
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -799,32 +798,32 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 85d8b9f05f78211c61e3739ab5db761d7118766d1916ae7f2764735106bc4e13
|
||||
F src/tokenize.c e9d52d9f7374d82dadcd11726bea8a597d43709d6672704f3f0375bf1d726912
|
||||
F src/treeview.c feaa59f14db4f7b5aacca9c5ad5aeb562c1f98262c1ffd74371f4186ade91fc5
|
||||
F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
|
||||
F src/trigger.c 5028874dd1f4fd3085bacd55c30114b5ad651525508656f65af09adf227181d5
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/upsert.c dd9f0fcccbfb4f20e1026a21a7254ba3f2c08e9cfa92affaff5b5ec3b00ea549
|
||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||
F src/util.c 98cf12c8ba65623a76c1eb6e6afa98ff40107c9919bf79af42f4bfc70e654232
|
||||
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
|
||||
F src/vdbe.c 8ed6f274dff8b9fb961d050a9ab933e7f6509221718bec862e85729d171c1606
|
||||
F src/vdbe.c 39658ee12b9d6bf5fc546e1ede20b307d86d9e988ae709c9b461249a8312513d
|
||||
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
|
||||
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
|
||||
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
|
||||
F src/vdbeaux.c bd3aaf77593a5590f617ce173e8677a21eca18522eadc1c4bc81b53f6d1c7e19
|
||||
F src/vdbeapi.c 15c55a4be8edc06055502e15f60f444c8fc5cb6134e38b8486742e89670d5e8f
|
||||
F src/vdbeaux.c a052c43fcf342651f655e6771003c175d49b237a9473c3c4d79d44725f494dae
|
||||
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
|
||||
F src/vdbemem.c efacb8f229422d2a4db0ed38e49b7f3897862a98d82b261aa3b43d7a2d98c6da
|
||||
F src/vdbemem.c 6e7ad67507c9a8e625b46256a9c003929331d6a27b99bbe139b8f0dab636e1f2
|
||||
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
|
||||
F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c 5437ce986db2f70e639ce8a3fe68dcdfe64b0f1abb14eaebecdabd5e0766cc68
|
||||
F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
|
||||
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
|
||||
F src/wal.c abfd99239725a258af4f733681b24dd7a9ee298babe389a36d29c197e2443ebf
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c 33e4a6558ee69f33d6a4e7069e3a40a55959d14e5653a9a83926e70305d471f3
|
||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||
F src/wherecode.c 4d573077652f79780d6b50840ab8cbb72053dbb4eb230780dd2a146ab034475d
|
||||
F src/whereexpr.c d111a5cb6147253a54010d883474b6aecc0b3009d352c087ee5295d74697bfef
|
||||
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
|
||||
F src/wherecode.c bc39ccbe3648f01157038b16cc55bdbff128590972b7185521b5526dc2815765
|
||||
F src/whereexpr.c 906d30c21470bbafc31bbc2cd07a0753bdd57169caed6ba75b8b4fc0ecb24134
|
||||
F src/window.c 0d7dacdf2e84c6ee8ff498d5cc881dd245fcb2f14f6c5976e97e112ce96e90dc
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
|
||||
F test/affinity3.test 9b7d1133e11d5edd7805573c4ab6f3ba73b0b74a1f280d5b130d4bf3506a93ff
|
||||
@@ -959,7 +958,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
|
||||
@@ -1030,7 +1029,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test 85cdfdae5c3de331cd888d6c66e1aba575b47c2e3c3cc4a1d6f54140699f5165
|
||||
F test/cse.test 00b3aea44b16828833c94fbe92475fd6977583fcb064ae0bc590986812b38d0c
|
||||
F test/csv01.test 2ab5514005fd308995c8910bc313e47f0368b94213b9d6c27f9a2da78796a091
|
||||
F test/csv01.test 96bc1634961682363a7b4ad5c0e38450e6e9743b38ac626422e1b56cbdc06cd8
|
||||
F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c4773
|
||||
F test/cursorhint.test 05cf0febe5c5f8a31f199401fd1c9322249e753950d55f26f9d5aca61408a270
|
||||
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
|
||||
@@ -1050,7 +1049,7 @@ F test/dbpage.test 2e3a50548edea551ef974b8f121f975852de9c5b16cb3284ac4bf2c9f2ed5
|
||||
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52
|
||||
F test/decimal.test a11b87a2c3294eb4c11b55f3168aeac63d683fa8ada35921a6ec1d511eff7648
|
||||
F test/decimal.test 9e1c40ff2835775a3dae88e1e2f0d81438070e987aafa4d9aeb0a22d60e5bf44
|
||||
F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277
|
||||
F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
@@ -1075,7 +1074,7 @@ F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
|
||||
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
|
||||
F test/e_expr.test 9bdb347b78b9f4eff9153ea97797facc179a821898588471a70808b4471a69b0
|
||||
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
|
||||
F test/e_fkey.test 2a4ad815372a4b57dad91cd37932e18e68bf545f6c946e9a4cb3e7bde92b8e84
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
F test/e_reindex.test 027bb13d2c7e9e865886eed6349f126a273f8037899b636bf5fb53c7fc815921
|
||||
@@ -1171,8 +1170,8 @@ F test/fts3corrupt2.test e318f0676e5e78d5a4b702637e2bb25265954c08a1b1e4aaf93c788
|
||||
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
|
||||
F test/fts3corrupt4.test c7f414fe29b97a478d15c90382c4ae077a2bbd2283bf8c63bf66dadaaed3edb8
|
||||
F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5
|
||||
F test/fts3corrupt6.test f417c910254f32c0bc9ead7affa991a1d5aec35b3b32a183ffb05eea78289525
|
||||
F test/fts3corrupt7.test 1da31776e24bb91d3c028e663456b61280b121a74496ccf2fef3fe33790ad2b0
|
||||
F test/fts3corrupt6.test 9ea944e3cd17a36c64451059022fabff53bd338a43356d1f49264ce8aa9477ad
|
||||
F test/fts3corrupt7.test 8564d278801a7947d1c74d8819adee7dfed18b81574d0c42f8a1acc6759fc65a
|
||||
F test/fts3cov.test 1e5ecea0e4c1394cea97adcfb9fd3d2d5998fd563dacf465f413e6c7fa5cffb3
|
||||
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
|
||||
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
|
||||
@@ -1253,7 +1252,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 5048a2426bd6968a1b9a00cef7f3aa37442a261df3b532c9e44a1f829bddbede
|
||||
F test/fuzzcheck.c 674d246742da18270abeef9e8510e3cd9e0e14cddca1f1e8131428928e996a6f
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1274,9 +1273,9 @@ F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 2d89bf9480646feb8093be3a58ea502d6521906779ed960de31dd9c4502c0541
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
|
||||
F test/icu.test 3903d97f414741036e48d74af6be904eb69170f5bca7a0031ff3b33925c85582
|
||||
F test/ieee754.test 0d3ab84ab2069c9994c833a7cd820ee6037f0cf888e206a4a7fc05f735d5790a
|
||||
F test/import01.sql 11a5f8325b8b04c66fe489d30558d462411432adf750cef1c0f7b06564691a8c
|
||||
F test/import01.sql d9561059f4ad3f14eff20c269e64b09afd697b1aad00b03a7d5010e167dcba83
|
||||
F test/imposter1.sql fc5ad0945bb19622688c7a1cd7dfd1cefa4b013bac9e2628c22b03c7309f021f
|
||||
F test/imposter1.test 5a20b2cdeb53e65fc57cdb10a33750bd4ef6259909eaf1972253b9e79f7a3fb2
|
||||
F test/in.test edf979bff3244b9e47849e2b43886631354c8213791f42da92216f08012141af
|
||||
@@ -1308,7 +1307,7 @@ F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a91
|
||||
F test/index9.test 2ac891806a4136ef3e91280477e23114e67575207dc331e6797fa0ed9379f997
|
||||
F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4974
|
||||
F test/indexedby.test 444fb04ce0b21a3daf79f84e6735b49e5a5b3396623b37df5431eb09c8b8f557
|
||||
F test/indexexpr1.test 830fec7ce07102f8e065f9486fa51d733f7443173f66c084d36232fa1628e635
|
||||
F test/indexexpr1.test e1e6a851d1054fa4fa43b60ad51f350519fabe756e313bc687af430a1efbff6e
|
||||
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
|
||||
F test/indexexpr3.test 47b91bc7999805c9a34d356f672259bc49295ecc797448511cae554a309b47cd
|
||||
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
|
||||
@@ -1363,7 +1362,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
|
||||
@@ -1475,7 +1474,8 @@ 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 642c27ae0792d5fc92969815eb8c4a17636cdcc164cb5b20f3d2b55a1a5d169d
|
||||
F test/nulls2.test 20356ab1de69f78363faed9c2cd8eb455bb92f805572c405131f1c5d8f2d37fb
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
|
||||
F test/offset1.test c21e67d2d5ae8ed310243fbe84fc2f0dca49e9ffed3ea89110c0d5914c0de620
|
||||
@@ -1510,10 +1510,10 @@ F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
|
||||
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
|
||||
F test/parser1.test 131f4733472252d53d8ed681115257866f55740ab697fa05900d766049348f27
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/pcache2.test 8a801d2b8e4b0ebb99701f026a67a9e84634c8aa24799a842c44003b93250da1
|
||||
F test/pendingrace.test e99efc5ab3584da3dfc8cd6a0ec4e5a42214820574f5ea24ee93f1d84655f463
|
||||
F test/percentile.test eaee1ff3e35d5fe933ac98d927c9a7d2f4f1a1a19ee22e7d45e97a6d9ee32077
|
||||
F test/permutations.test e6de4f5777f7785737ac3d1d964b8656e5477a134665b2fe8a91884ab9b685b3
|
||||
F test/percentile.test fd78896fa882fa4fbf693640097859721f3629926c2ccf804af5bcb7001fd35b
|
||||
F test/permutations.test 99c5e11130387da85c216a839412b882a779596f3f2e0ecb7e0703c564182cdb
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 7d07b7bb76e273215d6a20c4f83c3062cc28976c737ccb70a686025801e86c8f
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
@@ -1522,7 +1522,7 @@ F test/pragma4.test 396ef9bff1fb966d41721545ad4b12bfc26aae315f5fe51d9b917828d49e
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test f2c4f30d5d439ca203ec69d72f5e1cc408916104e5310423542faef8003cf013
|
||||
F test/prefixes.test fe52bb0c2fee10fb9b918a095d443ebf31dd48e5e2c7a1b21feba594fe7ff2d0
|
||||
F test/printf.test 854ddc19b31e83de41142a6b0c8dbb812fcdbbb127cdcafc0c5efef58b790eee
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
@@ -1629,13 +1629,13 @@ F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell-prompt.sql 8a320a78812d75349bd5e1a95178f7ff1f2194bb4cceee572865d127c51684b3
|
||||
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
|
||||
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
|
||||
F test/shell1.test 72893bc7957ff6402552ce4e31aa98a94478fa91bf5c4009a458711ad2e6efac
|
||||
F test/shell2.test e0842ea6a28f86f1ef235e117b3a381d16b999e7bdd9655b1de663026dd8ea27
|
||||
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
|
||||
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
|
||||
F test/shell5.test a0c43d82a811a463a5d07d6418c5a045ab01a072544db8aa31ae394e93845d8d
|
||||
F test/shell6.test 596f2eb385a1097d4e9130b4d4f663a24cba294b35f13b774b8f13553dec307d
|
||||
F test/shell7.test 4468c1abb7e2708a3aa3f84c8918ca31fbf7909b1c19063853f2abb0a072dfab
|
||||
F test/shell7.test 6b006d296b569a7ec78b8168af77578b3bde8f58b79c32d9f46cff1eaf763a29
|
||||
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
|
||||
F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89
|
||||
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
|
||||
@@ -1709,7 +1709,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 7827c2dfd57a094125b059f51a2200eaf04d417af6b1e720c34a8cbf54e8a14f
|
||||
F test/tabfunc01.test 23d1f92fbbbaaef4cb3a1ee15fd5b44e70bde1f3ee1a6b9df9ce43b05cf0b630
|
||||
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
|
||||
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
@@ -1894,7 +1894,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 342b398e4c68deee65a940c5af22a95f44c3090b6539c7a19175afb48ac3fb93
|
||||
F test/transitive1.test d6252d06ddc104d13372fce0da93af501546bf5d75cb4d2a1f83b8c27238997a
|
||||
F test/trigger1.test 141bd2bbfa82fa91aed7391f50517373c9823ff8f55af35e56313dbc75112ca1
|
||||
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
|
||||
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
@@ -1906,7 +1906,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 1724b595661da3dd3c8d79f0ebae818132a39e65c241bad2049f66952b1dc29d
|
||||
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test 29f5a28d0fe39e6e2c01f6e1f53f08c0955170ae10a63ad023e33cb0a1682a51
|
||||
F test/triggerC.test 1faacf5249a7abe8bdc44aafe170f2141a72cb2abcef300dc91e3d55c4158f41
|
||||
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
|
||||
F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642b22ee
|
||||
F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
|
||||
@@ -1944,7 +1944,7 @@ F test/upsert1.test 77e3cbabd6b5c773056aca39bda7a690901f1dbd08b0a26ee3b5aec9e9e2
|
||||
F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
|
||||
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
|
||||
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
|
||||
F test/upsert5.test 9953b180d02d1369cdbb6c73c900834e5fef8cb78e98e07511c8762ec21cc176
|
||||
F test/upsert5.test 8d0230b358965e0c11f7306b87ba1238970e44b8339e34609f44d0468c4ed458
|
||||
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
|
||||
F test/uri.test 1250724af9beeed2d6c3716f5b990c483200c54f408d3c0ec9543a3c7961f8fc
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
@@ -1961,7 +1961,7 @@ F test/values.test 0e037c50789ac2a308746567d07b53b2f6026c1bb3a435d1b099424600e64
|
||||
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test 3c23d7a068e9e4a0c4e6907498042772adea725f0630c3d9638ffd4e5a08b92b
|
||||
F test/view.test 79cfd77b29ce49c172fee2ed9ec98d34924e70bebc75c8edb65f6a9bcd80d569
|
||||
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
|
||||
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
|
||||
F test/vt02.c c2faf56d74470d569cd00741acb3f1719ee95d668f84ef58acc3872635789680
|
||||
@@ -2036,7 +2036,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 b73f8ee8f94b850764c429efe2d48171090628737dcc3df64a9f2214da02089f
|
||||
F test/where2.test 5d93a8aec78386539aa01cf72926eb39d90de4ce1bfb6d517f56ae9bf704ba8a
|
||||
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
@@ -2110,7 +2110,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 756af25d30ffd25073b113865f1ebeb12f7edfa5dddd8c37bca70e4c3150ab62
|
||||
F test/zipfile2.test 21afaffcf4f7769df38bf16e4a9c4dfa6ba1b0f5b695f844ec61fafb92db0db7
|
||||
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
|
||||
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
|
||||
@@ -2125,7 +2125,7 @@ F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629c
|
||||
F tool/cp.tcl 9a0d663ad45828de13763ee7ca0200f31f56c6d742cf104a56ae80e027c242d8
|
||||
F tool/custom.txt 24ed55e71c5edae0067ba159bbf09240d58b160331f7716e95816cd3aa0ba5c4
|
||||
F tool/dbhash.c 5da0c61032d23d74f2ab84ffc5740f0e8abec94f2c45c0b4306be7eb3ae96df0
|
||||
F tool/dbtotxt.c cfeb957571735af345f253ba8417256031fa0dddf79468eefad184262d17211e
|
||||
F tool/dbtotxt.c 88805565e06596f8b2f7143054f74d7aeaf022769b4c3d916f148a1fa17082ef
|
||||
F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
|
||||
F tool/emcc.sh.in 41a049468c8155433e37e656ba5bae063a000768b1d627025f277732c4e7c4a4
|
||||
F tool/enlargedb.c 3e8b2612b985cfa7e3e8800031ee191b43ae80de96abb5abbd5eada62651ee21
|
||||
@@ -2187,7 +2187,7 @@ F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdadd
|
||||
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
|
||||
F tool/sqldiff.c de59a4eecbc802db8ad053889c10e6f8b8427b6f349199ee79938c92c20860dd
|
||||
F tool/sqldiff.c e581749af18f02a72cd18f56b465df1bef630544aebdf13993e2be55e4158f94
|
||||
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
|
||||
F tool/sqlite3_rsync.c d9ce999e5b3aa9f36de44b321755622e52258774889bd804ba56f00eca01af50
|
||||
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
|
||||
@@ -2208,8 +2208,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P 646e9b49153ebd7e09e3ef72cc4f64fb685d0cfd8b158ef7d11d37c50c3f0b7e
|
||||
R 81bf729d8c4142161698f7ae0f57bcc2
|
||||
U dan
|
||||
Z a8503d1e8f8b2786c97fea82e248cce7
|
||||
P 2fe53e6d68c3f9f1c4b064fa40fe8efe12025179a973182f0bb256acb9b5d58d
|
||||
R 3de030f0b5267bf636ad519cf6229737
|
||||
U drh
|
||||
Z e6a5bf5d9c5bcab97848f385d89977e5
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
branch trunk
|
||||
tag trunk
|
||||
branch sqlite3-result-str
|
||||
tag sqlite3-result-str
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10
|
||||
7356bf3a813bcd9082a7fdef5e2cc38c7a0f142f0ef4c948f78e4dafa216c039
|
||||
|
||||
+6
-9
@@ -2661,9 +2661,8 @@ static void addConstraintFunc(
|
||||
int iCol = sqlite3_value_int(argv[2]);
|
||||
int iOff = 0;
|
||||
int ii;
|
||||
char *zNew = 0;
|
||||
sqlite3_str *pNew;
|
||||
int t = 0;
|
||||
sqlite3 *db;
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
|
||||
if( skipCreateTable(ctx, zSql, &iOff) ) return;
|
||||
@@ -2683,13 +2682,11 @@ static void addConstraintFunc(
|
||||
|
||||
iOff += getWhitespace(&zSql[iOff]);
|
||||
|
||||
db = sqlite3_context_db_handle(ctx);
|
||||
if( iCol<0 ){
|
||||
zNew = sqlite3MPrintf(db, "%.*s, %s%s", iOff, zSql, zCons, &zSql[iOff]);
|
||||
}else{
|
||||
zNew = sqlite3MPrintf(db, "%.*s %s%s", iOff, zSql, zCons, &zSql[iOff]);
|
||||
}
|
||||
sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC);
|
||||
pNew = sqlite3_str_new(sqlite3_context_db_handle(ctx));
|
||||
sqlite3_str_append(pNew, zSql, iOff);
|
||||
if( iCol<0 ) sqlite3_str_append(pNew, ",", 1);
|
||||
sqlite3_str_appendf(pNew, " %s%s", zCons, &zSql[iOff]);
|
||||
sqlite3_result_str(ctx, pNew, SQLITE_FINISH);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+6
-6
@@ -876,7 +876,7 @@ static void statGet(
|
||||
assert( p->current.anEq[i] || p->nRow==0 );
|
||||
#endif
|
||||
}
|
||||
sqlite3ResultStrAccum(context, &sStat);
|
||||
sqlite3_result_str(context, &sStat, SQLITE_XFER);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
else if( eCall==STAT_GET_ROWID ){
|
||||
@@ -913,7 +913,7 @@ static void statGet(
|
||||
sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]);
|
||||
}
|
||||
if( sStat.nChar ) sStat.nChar--;
|
||||
sqlite3ResultStrAccum(context, &sStat);
|
||||
sqlite3_result_str(context, &sStat, SQLITE_XFER);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT4 */
|
||||
#ifndef SQLITE_DEBUG
|
||||
@@ -1814,9 +1814,9 @@ static int loadStatTbl(
|
||||
}
|
||||
pIdx->nSampleCol = nIdxCol;
|
||||
pIdx->mxSample = nSample;
|
||||
nByte = ROUND8(sizeof(IndexSample) * nSample);
|
||||
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
|
||||
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
|
||||
nByte = ROUND8(sizeof64(IndexSample) * nSample);
|
||||
nByte += sizeof64(tRowcnt) * nIdxCol * 3 * nSample;
|
||||
nByte += nIdxCol * sizeof64(tRowcnt); /* Space for Index.aAvgEq[] */
|
||||
|
||||
pIdx->aSample = sqlite3DbMallocZero(db, nByte);
|
||||
if( pIdx->aSample==0 ){
|
||||
@@ -1824,7 +1824,7 @@ static int loadStatTbl(
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pPtr = (u8*)pIdx->aSample;
|
||||
pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
|
||||
pPtr += ROUND8(nSample*sizeof64(pIdx->aSample[0]));
|
||||
pSpace = (tRowcnt*)pPtr;
|
||||
assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
|
||||
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
|
||||
|
||||
@@ -10984,6 +10984,11 @@ static int checkTreePage(
|
||||
doCoverageCheck = 0;
|
||||
continue;
|
||||
}
|
||||
if( info.nPayload && info.pPayload[0]<2 ){
|
||||
checkAppendMsg(pCheck, "Bad cell header size");
|
||||
doCoverageCheck = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for integer primary key out of range */
|
||||
if( pPage->intKey ){
|
||||
|
||||
+3
-2
@@ -70,6 +70,7 @@ static SQLITE_NOINLINE void lockTable(
|
||||
|
||||
assert( pToplevel->nTableLock < 0x7fff0000 );
|
||||
nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
|
||||
if( pToplevel->nTableLock==0 ) pToplevel->aTableLock = 0;
|
||||
pToplevel->aTableLock =
|
||||
sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
|
||||
if( pToplevel->aTableLock ){
|
||||
@@ -236,7 +237,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
|
||||
/* Initialize any AUTOINCREMENT data structures required.
|
||||
*/
|
||||
if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse);
|
||||
if( pParse->usesAinc ) sqlite3AutoincrementBegin(pParse);
|
||||
|
||||
/* Code constant expressions that were factored out of inner loops.
|
||||
*/
|
||||
@@ -269,7 +270,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
if( pParse->nErr==0 ){
|
||||
/* A minimum of one cursor is required if autoincrement is used
|
||||
* See ticket [a696379c1f08866] */
|
||||
assert( pParse->pAinc==0 || pParse->nTab>0 );
|
||||
assert( pParse->usesAinc==0 || pParse->nTab>0 );
|
||||
sqlite3VdbeMakeReady(v, pParse);
|
||||
pParse->rc = SQLITE_DONE;
|
||||
}else{
|
||||
|
||||
+31
-31
@@ -1416,38 +1416,38 @@ static void strftimeFunc(
|
||||
size_t i,j;
|
||||
sqlite3 *db;
|
||||
const char *zFmt;
|
||||
sqlite3_str sRes;
|
||||
sqlite3_str *pRes;
|
||||
|
||||
|
||||
if( argc==0 ) return;
|
||||
zFmt = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
|
||||
db = sqlite3_context_db_handle(context);
|
||||
sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
pRes = sqlite3_str_new(db);
|
||||
|
||||
computeJD(&x);
|
||||
computeYMD_HMS(&x);
|
||||
for(i=j=0; zFmt[i]; i++){
|
||||
char cf;
|
||||
if( zFmt[i]!='%' ) continue;
|
||||
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
|
||||
if( j<i ) sqlite3_str_append(pRes, zFmt+j, (int)(i-j));
|
||||
i++;
|
||||
j = i + 1;
|
||||
cf = zFmt[i];
|
||||
switch( cf ){
|
||||
case 'd': /* Fall thru */
|
||||
case 'e': {
|
||||
sqlite3_str_appendf(&sRes, cf=='d' ? "%02d" : "%2d", x.D);
|
||||
sqlite3_str_appendf(pRes, cf=='d' ? "%02d" : "%2d", x.D);
|
||||
break;
|
||||
}
|
||||
case 'f': { /* Fractional seconds. (Non-standard) */
|
||||
double s = x.s;
|
||||
if( NEVER(s>59.999) ) s = 59.999;
|
||||
sqlite3_str_appendf(&sRes, "%06.3f", s);
|
||||
sqlite3_str_appendf(pRes, "%06.3f", s);
|
||||
break;
|
||||
}
|
||||
case 'F': {
|
||||
sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
|
||||
sqlite3_str_appendf(pRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
|
||||
break;
|
||||
}
|
||||
case 'G': /* Fall thru */
|
||||
@@ -1459,15 +1459,15 @@ static void strftimeFunc(
|
||||
y.validYMD = 0;
|
||||
computeYMD(&y);
|
||||
if( cf=='g' ){
|
||||
sqlite3_str_appendf(&sRes, "%02d", y.Y%100);
|
||||
sqlite3_str_appendf(pRes, "%02d", y.Y%100);
|
||||
}else{
|
||||
sqlite3_str_appendf(&sRes, "%04d", y.Y);
|
||||
sqlite3_str_appendf(pRes, "%04d", y.Y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'H':
|
||||
case 'k': {
|
||||
sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
|
||||
sqlite3_str_appendf(pRes, cf=='H' ? "%02d" : "%2d", x.h);
|
||||
break;
|
||||
}
|
||||
case 'I': /* Fall thru */
|
||||
@@ -1475,65 +1475,65 @@ static void strftimeFunc(
|
||||
int h = x.h;
|
||||
if( h>12 ) h -= 12;
|
||||
if( h==0 ) h = 12;
|
||||
sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
|
||||
sqlite3_str_appendf(pRes, cf=='I' ? "%02d" : "%2d", h);
|
||||
break;
|
||||
}
|
||||
case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */
|
||||
sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1);
|
||||
sqlite3_str_appendf(pRes,"%03d",daysAfterJan01(&x)+1);
|
||||
break;
|
||||
}
|
||||
case 'J': { /* Julian day number. (Non-standard) */
|
||||
sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
|
||||
sqlite3_str_appendf(pRes,"%.16g",x.iJD/86400000.0);
|
||||
break;
|
||||
}
|
||||
case 'm': {
|
||||
sqlite3_str_appendf(&sRes,"%02d",x.M);
|
||||
sqlite3_str_appendf(pRes,"%02d",x.M);
|
||||
break;
|
||||
}
|
||||
case 'M': {
|
||||
sqlite3_str_appendf(&sRes,"%02d",x.m);
|
||||
sqlite3_str_appendf(pRes,"%02d",x.m);
|
||||
break;
|
||||
}
|
||||
case 'p': /* Fall thru */
|
||||
case 'P': {
|
||||
if( x.h>=12 ){
|
||||
sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2);
|
||||
sqlite3_str_append(pRes, cf=='p' ? "PM" : "pm", 2);
|
||||
}else{
|
||||
sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2);
|
||||
sqlite3_str_append(pRes, cf=='p' ? "AM" : "am", 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'R': {
|
||||
sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m);
|
||||
sqlite3_str_appendf(pRes, "%02d:%02d", x.h, x.m);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
if( x.useSubsec ){
|
||||
sqlite3_str_appendf(&sRes,"%.3f",
|
||||
sqlite3_str_appendf(pRes,"%.3f",
|
||||
(x.iJD - 21086676*(i64)10000000)/1000.0);
|
||||
}else{
|
||||
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
|
||||
sqlite3_str_appendf(&sRes,"%lld",iS);
|
||||
sqlite3_str_appendf(pRes,"%lld",iS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'S': {
|
||||
sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
|
||||
sqlite3_str_appendf(pRes,"%02d",(int)x.s);
|
||||
break;
|
||||
}
|
||||
case 'T': {
|
||||
sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
|
||||
sqlite3_str_appendf(pRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
|
||||
break;
|
||||
}
|
||||
case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */
|
||||
case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */
|
||||
char c = (char)daysAfterSunday(&x) + '0';
|
||||
if( c=='0' && cf=='u' ) c = '7';
|
||||
sqlite3_str_appendchar(&sRes, 1, c);
|
||||
sqlite3_str_appendchar(pRes, 1, c);
|
||||
break;
|
||||
}
|
||||
case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */
|
||||
sqlite3_str_appendf(&sRes,"%02d",
|
||||
sqlite3_str_appendf(pRes,"%02d",
|
||||
(daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7);
|
||||
break;
|
||||
}
|
||||
@@ -1544,30 +1544,30 @@ static void strftimeFunc(
|
||||
y.iJD += (3 - daysAfterMonday(&x))*86400000;
|
||||
y.validYMD = 0;
|
||||
computeYMD(&y);
|
||||
sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1);
|
||||
sqlite3_str_appendf(pRes,"%02d", daysAfterJan01(&y)/7+1);
|
||||
break;
|
||||
}
|
||||
case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */
|
||||
sqlite3_str_appendf(&sRes,"%02d",
|
||||
sqlite3_str_appendf(pRes,"%02d",
|
||||
(daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7);
|
||||
break;
|
||||
}
|
||||
case 'Y': {
|
||||
sqlite3_str_appendf(&sRes,"%04d",x.Y);
|
||||
sqlite3_str_appendf(pRes,"%04d",x.Y);
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
sqlite3_str_appendchar(&sRes, 1, '%');
|
||||
sqlite3_str_appendchar(pRes, 1, '%');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sqlite3_str_reset(&sRes);
|
||||
sqlite3_str_free(pRes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
|
||||
sqlite3ResultStrAccum(context, &sRes);
|
||||
if( j<i ) sqlite3_str_append(pRes, zFmt+j, (int)(i-j));
|
||||
sqlite3_result_str(context, pRes, SQLITE_FINISH);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1703,7 +1703,7 @@ static void timediffFunc(
|
||||
sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
|
||||
sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
|
||||
sign, Y, M, d1.D-1, d1.h, d1.m, d1.s);
|
||||
sqlite3ResultStrAccum(context, &sRes);
|
||||
sqlite3_result_str(context, &sRes, SQLITE_XFER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+16
-4
@@ -4170,6 +4170,7 @@ static void sqlite3ExprCodeIN(
|
||||
int rLhsOrig = rLhs;
|
||||
rLhs = sqlite3GetTempRange(pParse, nVector);
|
||||
for(i=0; i<nVector; i++){
|
||||
testcase( aiMap[i]!=i );
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, rLhsOrig);
|
||||
@@ -4190,7 +4191,8 @@ static void sqlite3ExprCodeIN(
|
||||
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
|
||||
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
|
||||
if( sqlite3ExprCanBeNull(p) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
|
||||
testcase( aiMap[i]!=i );
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+aiMap[i], destStep2);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
}
|
||||
@@ -4264,9 +4266,19 @@ static void sqlite3ExprCodeIN(
|
||||
CollSeq *pColl;
|
||||
int r3 = sqlite3GetTempReg(pParse);
|
||||
p = sqlite3VectorFieldSubexpr(pLeft, i);
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
|
||||
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
|
||||
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);
|
||||
}
|
||||
testcase( aiMap[i]!=i );
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTab, aiMap[i], r3);
|
||||
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+aiMap[i], destNotNull, r3,
|
||||
(void*)pColl, P4_COLLSEQ);
|
||||
VdbeCoverage(v);
|
||||
sqlite3ReleaseTempReg(pParse, r3);
|
||||
|
||||
+97
-74
@@ -320,7 +320,6 @@ static void printfFunc(
|
||||
PrintfArguments x;
|
||||
StrAccum str;
|
||||
const char *zFormat;
|
||||
int n;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
|
||||
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
|
||||
@@ -330,9 +329,7 @@ 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);
|
||||
sqlite3_result_str(context, &str, SQLITE_XFER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1279,12 +1276,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
UNUSED_PARAMETER(argc);
|
||||
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context)));
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
|
||||
SQLITE_DYNAMIC);
|
||||
if( str.accError!=SQLITE_OK ){
|
||||
sqlite3_result_null(context);
|
||||
sqlite3_result_error_code(context, str.accError);
|
||||
}
|
||||
sqlite3_result_str(context, &str, SQLITE_XFER);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1504,7 +1496,7 @@ static void replaceFunc(
|
||||
int nRep; /* Size of zRep */
|
||||
i64 nOut; /* Maximum size of zOut */
|
||||
int loopLimit; /* Last zStr[] that might match zPattern[] */
|
||||
int i, j; /* Loop counters */
|
||||
i64 i, j; /* Loop counters */
|
||||
unsigned cntExpand; /* Number zOut expansions */
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
|
||||
@@ -2317,7 +2309,7 @@ static void groupConcatFinalize(sqlite3_context *context){
|
||||
GroupConcatCtx *pGCC
|
||||
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
|
||||
if( pGCC ){
|
||||
sqlite3ResultStrAccum(context, &pGCC->str);
|
||||
sqlite3_result_str(context, &pGCC->str, SQLITE_XFER);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
sqlite3_free(pGCC->pnSepLengths);
|
||||
#endif
|
||||
@@ -2327,18 +2319,8 @@ static void groupConcatFinalize(sqlite3_context *context){
|
||||
static void groupConcatValue(sqlite3_context *context){
|
||||
GroupConcatCtx *pGCC
|
||||
= (GroupConcatCtx*)sqlite3_aggregate_context(context, 0);
|
||||
if( pGCC ){
|
||||
StrAccum *pAccum = &pGCC->str;
|
||||
if( pAccum->accError==SQLITE_TOOBIG ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
|
||||
sqlite3_result_text(context, "", 1, SQLITE_STATIC);
|
||||
}else{
|
||||
const char *zText = sqlite3_str_value(pAccum);
|
||||
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
|
||||
}
|
||||
if( pGCC && pGCC->nAccum>0 ){
|
||||
sqlite3_result_str(context, &pGCC->str, SQLITE_COPY);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -2958,53 +2940,91 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
|
||||
** (1) To avoid a dependency on qsort()
|
||||
** (2) To avoid the function call to the comparison routine for each
|
||||
** comparison.
|
||||
**
|
||||
** If parameter iReq is non-negative, then the caller will only access
|
||||
** elements a[iReq] and a[iReq+1] (if it exists) of the sorted array and
|
||||
** so it is not necessary to position any other elements. Or if iReq is
|
||||
** negative, then the final array must be fully sorted.
|
||||
*/
|
||||
static void percentSort(double *a, unsigned int n){
|
||||
static void percentSort(
|
||||
double *a, /* Array to sort */
|
||||
unsigned int n, /* Number of elements in array a[] */
|
||||
int iReq /* Element caller cares about (or -ve) */
|
||||
){
|
||||
int iLt; /* Entries before a[iLt] are less than rPivot */
|
||||
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
|
||||
}
|
||||
|
||||
assert( n>=2 );
|
||||
do{
|
||||
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 );
|
||||
|
||||
assert( a[iLt]==rPivot );
|
||||
assert( iGt>iLt );
|
||||
|
||||
if( iReq>=0 ){
|
||||
/* In this case, the only elements that the caller requires sorted into
|
||||
** the correct positions are elements a[iReq] and a[iReq+1]. At this
|
||||
** point we know that element a[iLt] is in the correct position and
|
||||
** all elements smaller than a[iLt] are in the left-hand partition.
|
||||
** So if (iReq<iLt), then it is only necessary to sort the left
|
||||
** partition.
|
||||
**
|
||||
** If (iReq>=iLt), then elements iReq and iReq+1 are either in the
|
||||
** right partition or the equal partition (elements for which
|
||||
** iLt<=iElem<iGt). Therefore it is always sufficient to sort only
|
||||
** the right partition in this case. */
|
||||
if( iReq<iLt ){
|
||||
n = iLt;
|
||||
}else{
|
||||
a += iGt;
|
||||
n -= iGt;
|
||||
iReq = MAX(0, iReq-iGt);
|
||||
}
|
||||
}else{
|
||||
/* Recurse on the smaller partition only. The smaller partition
|
||||
** will hold n/2 or fewer entries, which assures that the stack
|
||||
** depth will not exceed O(log(n)), even for pathological cases.
|
||||
** Loop without recursion for the larger partition. */
|
||||
if( iLt>(int)(n/2) ){
|
||||
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt, -1);
|
||||
n = iLt;
|
||||
}else{
|
||||
if( iLt>=2 ) percentSort(a, iLt, -1);
|
||||
a += iGt;
|
||||
n -= iGt;
|
||||
}
|
||||
}
|
||||
}while( n>=2 );
|
||||
}
|
||||
|
||||
/*
|
||||
** The "inverse" function for percentile(Y,P) is called to remove a
|
||||
@@ -3038,7 +3058,7 @@ static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){
|
||||
}
|
||||
if( p->bSorted==0 ){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
percentSort(p->a, p->nUsed, -1);
|
||||
p->bSorted = 1;
|
||||
}
|
||||
p->bKeepSorted = 1;
|
||||
@@ -3067,13 +3087,17 @@ static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
|
||||
if( p==0 ) return;
|
||||
if( p->a==0 ) return;
|
||||
if( p->nUsed ){
|
||||
if( p->bSorted==0 ){
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed);
|
||||
p->bSorted = 1;
|
||||
}
|
||||
ix = p->rPct*(p->nUsed-1);
|
||||
i1 = (unsigned)ix;
|
||||
if( p->bSorted==0 ){
|
||||
/* In cases where bIsFinal is non-zero, setting Percentile.bSorted
|
||||
** after the percentSort() call here is not technically correct, as
|
||||
** the array is not fully sorted. But in this case the object will be
|
||||
** freed below anyway, so it doesn't matter. */
|
||||
assert( p->nUsed>1 );
|
||||
percentSort(p->a, p->nUsed, (bIsFinal ? (int)i1 : -1));
|
||||
p->bSorted = 1;
|
||||
}
|
||||
if( settings & 1 ){
|
||||
vx = p->a[i1];
|
||||
}else{
|
||||
@@ -3141,8 +3165,7 @@ static void filestatFunc(
|
||||
if( rc ) sqlite3_str_append(pStr, "null", 4);
|
||||
}
|
||||
sqlite3_str_append(pStr, "}", 1);
|
||||
sqlite3_result_text(context, sqlite3_str_finish(pStr), -1,
|
||||
sqlite3_free);
|
||||
sqlite3_result_str(context, pStr, SQLITE_FINISH);
|
||||
}
|
||||
sqlite3BtreeLeave(pBtree);
|
||||
}else{
|
||||
@@ -3258,8 +3281,8 @@ static void parseuriFunc(
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_result_text(ctx, sqlite3_str_finish(pResult), -1, sqlite3_free);
|
||||
}
|
||||
sqlite3_result_str(ctx, pResult, SQLITE_FINISH);
|
||||
sqlite3_free_filename(zFile);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
|
||||
@@ -308,6 +308,16 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
*/
|
||||
FuncDefHash sqlite3BuiltinFunctions;
|
||||
|
||||
/*
|
||||
** This singleton is an sqlite3_str object that is returned if
|
||||
** sqlite3_malloc() fails to provide space for a real one. This
|
||||
** sqlite3_str object accepts no new text and always returns
|
||||
** an SQLITE_NOMEM error.
|
||||
*/
|
||||
const sqlite3_str sqlite3OomStr = {
|
||||
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
|
||||
};
|
||||
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** Counter used for coverage testing. Does not come into play for
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \
|
||||
(defined(i386) || defined(__i386__) || defined(_M_IX86))
|
||||
(defined(i586) || defined(__i586__) || defined(_M_IX86))
|
||||
|
||||
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
||||
unsigned int lo, hi;
|
||||
|
||||
+7
-1
@@ -433,6 +433,9 @@ static int autoIncBegin(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( pToplevel->usesAinc==0 ){
|
||||
pToplevel->pAinc = 0;
|
||||
}
|
||||
pInfo = pToplevel->pAinc;
|
||||
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
|
||||
if( pInfo==0 ){
|
||||
@@ -442,6 +445,7 @@ static int autoIncBegin(
|
||||
if( pParse->db->mallocFailed ) return 0;
|
||||
pInfo->pNext = pToplevel->pAinc;
|
||||
pToplevel->pAinc = pInfo;
|
||||
pToplevel->usesAinc = 1;
|
||||
pInfo->pTab = pTab;
|
||||
pInfo->iDb = iDb;
|
||||
pToplevel->nMem++; /* Register to hold name of table */
|
||||
@@ -470,6 +474,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
|
||||
assert( sqlite3IsToplevel(pParse) );
|
||||
|
||||
assert( v ); /* We failed long ago if this is not so */
|
||||
assert( pParse->usesAinc );
|
||||
for(p = pParse->pAinc; p; p = p->pNext){
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList autoInc[] = {
|
||||
@@ -537,6 +542,7 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
|
||||
assert( v );
|
||||
assert( pParse->usesAinc );
|
||||
for(p = pParse->pAinc; p; p = p->pNext){
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList autoIncEnd[] = {
|
||||
@@ -569,7 +575,7 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
|
||||
}
|
||||
}
|
||||
void sqlite3AutoincrementEnd(Parse *pParse){
|
||||
if( pParse->pAinc ) autoIncrementEnd(pParse);
|
||||
if( pParse->usesAinc ) autoIncrementEnd(pParse);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
|
||||
+1
-1
@@ -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: {
|
||||
|
||||
+3
-1
@@ -533,7 +533,9 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
sqlite3_incomplete
|
||||
/* Version 3.54.0 and later */
|
||||
sqlite3_incomplete,
|
||||
sqlite3_result_str
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
+1
-1
@@ -518,7 +518,7 @@ int sqlite3_config(int op, ...){
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_SMALL_MALLOC: {
|
||||
sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int)!=0;
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_PAGECACHE: {
|
||||
|
||||
@@ -300,7 +300,7 @@ int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
||||
}else{
|
||||
double r;
|
||||
rc = pVfs->xCurrentTime(pVfs, &r);
|
||||
*pTimeOut = (sqlite3_int64)(r*86400000.0);
|
||||
*pTimeOut = sqlite3RealToI64(r*86400000.0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+31
-1
@@ -13,6 +13,22 @@
|
||||
** This file contains an experimental VFS layer that operates on a
|
||||
** Key/Value storage engine where both keys and values must be pure
|
||||
** text.
|
||||
**
|
||||
** DEBUG AND TEST
|
||||
**
|
||||
** For testing on Unix, compile using:
|
||||
**
|
||||
** make clean sqlite3d CFLAGS='-DSQLITE_OS_KV_OPTIONAL'
|
||||
**
|
||||
** Then start up a shell using something like:
|
||||
**
|
||||
** ./sqlite3d 'file:dbname?vfs=kvvfs'
|
||||
**
|
||||
** Each K/V entry is stored in a separate file in the working
|
||||
** directory that has a name like "kvvfs-dbname-*". Due to limitations
|
||||
** on the key size, the name of the database must be very short - just
|
||||
** a few characters. If the database name is too long, the VFS will
|
||||
** malfunction and you will get SQLITE_CORRUPT errors.
|
||||
*/
|
||||
#include <sqliteInt.h>
|
||||
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
|
||||
@@ -465,12 +481,14 @@ int kvvfsDecode(const char *a, char *aOut, int nOut){
|
||||
memset(&aOut[j], 0, n);
|
||||
j += n;
|
||||
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
|
||||
}else{
|
||||
}else if( j<nOut ){
|
||||
aOut[j] = c<<4;
|
||||
c = kvvfsHexValue[aIn[++i]];
|
||||
if( c<0 ) return -1 /* hex bytes are always in pairs */;
|
||||
aOut[j++] += c;
|
||||
i++;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
@@ -896,6 +914,18 @@ static int kvvfsOpen(
|
||||
pFile->base.pMethods = &kvvfs_db_io_methods;
|
||||
}
|
||||
if( !pFile->zClass ){
|
||||
#ifdef SQLITE_WASM
|
||||
if( strlen(zName) >= (KVRECORD_KEY_SZ
|
||||
- 6 /* "kvvfs-" */
|
||||
- 11 /* "-##########" */) ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
#else
|
||||
if( 0!=strcmp(zName, "local") && 0!=strcmp(zName, "session") ){
|
||||
/* Historical naming restriction which journaling depends on. */
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
#endif
|
||||
pFile->zClass = zName;
|
||||
}
|
||||
pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
|
||||
|
||||
+20
-2
@@ -3257,11 +3257,29 @@ int sqlite3_win_test_unc_locking = 0;
|
||||
|
||||
/*
|
||||
** Return true if the string passed as the only argument is likely
|
||||
** to be a UNC path. In other words, if it starts with "\\".
|
||||
** to be a UNC path. Return false if note.
|
||||
**
|
||||
** Return true if:
|
||||
**
|
||||
** (1) The name begins with "\\"
|
||||
** (2) But does not begin with "\\?\C:\" where C can be any alphabetic
|
||||
** character.
|
||||
**
|
||||
** For testing, also return true in all cases if the global variable
|
||||
** sqlite3_win_test_unc_locking is true.
|
||||
*/
|
||||
static int winIsUNCPath(const char *zFile){
|
||||
if( zFile[0]=='\\' && zFile[1]=='\\' ){
|
||||
return 1;
|
||||
if( zFile[2]=='?'
|
||||
&& zFile[3]=='\\'
|
||||
&& sqlite3Isalpha(zFile[4])
|
||||
&& zFile[5]==':'
|
||||
&& winIsDirSep(zFile[6])
|
||||
){
|
||||
return sqlite3_win_test_unc_locking;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return sqlite3_win_test_unc_locking;
|
||||
}
|
||||
|
||||
+68
-74
@@ -1272,39 +1272,43 @@ static void checkPage(PgHdr *pPg){
|
||||
#endif /* SQLITE_CHECK_PAGES */
|
||||
|
||||
/*
|
||||
** When this is called the journal file for pager pPager must be open.
|
||||
** This function attempts to read a super-journal file name from the
|
||||
** end of the file and, if successful, copies it into memory supplied
|
||||
** by the caller. See comments above writeSuperJournal() for the format
|
||||
** used to store a super-journal file name at the end of a journal file.
|
||||
**
|
||||
** zSuper must point to a buffer of at least nSuper bytes allocated by
|
||||
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
|
||||
** enough space to write the super-journal name). If the super-journal
|
||||
** name in the journal is longer than nSuper bytes (including a
|
||||
** nul-terminator), then this is handled as if no super-journal name
|
||||
** were present in the journal.
|
||||
**
|
||||
** If a super-journal file name is present at the end of the journal
|
||||
** file, then it is copied into the buffer pointed to by zSuper. A
|
||||
** nul-terminator byte is appended to the buffer following the
|
||||
** super-journal file name.
|
||||
**
|
||||
** If it is determined that no super-journal file name is present
|
||||
** zSuper[0] is set to 0 and SQLITE_OK returned.
|
||||
**
|
||||
** If an error occurs while reading from the journal file, an SQLite
|
||||
** error code is returned.
|
||||
** Free a buffer allocated by the readSuperJournal() function.
|
||||
*/
|
||||
static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
|
||||
static void freeSuperJournal(char *zSuper){
|
||||
if( zSuper ){
|
||||
sqlite3_free(&zSuper[-4]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter pJrnl is a file-handle open on a journal file. This function
|
||||
** attempts to read a super-journal file name from the end of the journal
|
||||
** file. If successful, it sets output parameter (*pzSuper) to point to a
|
||||
** buffer containing the super-journal name as a nul-terminated string.
|
||||
** The caller is responsible for freeing the buffer using freeSuperJournal().
|
||||
**
|
||||
** Refer to comments above writeSuperJournal() for the format used to store
|
||||
** a super-journal file name at the end of a journal file.
|
||||
**
|
||||
** Parameter nSuper is passed the maximum allowable size of the super journal
|
||||
** name in bytes. If the super-journal name in the journal is longer than
|
||||
** nSuper bytes (including a nul-terminator), then this is handled as if no
|
||||
** super-journal name were present in the journal.
|
||||
**
|
||||
** If there is no super-journal name at the end of pJrnl, (*pzSuper) is
|
||||
** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading
|
||||
** the super-journal name, an SQLite error code is returned and (*pzSuper)
|
||||
** is set to 0.
|
||||
*/
|
||||
static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){
|
||||
int rc; /* Return code */
|
||||
u32 len; /* Length in bytes of super-journal name */
|
||||
i64 szJ; /* Total size in bytes of journal file pJrnl */
|
||||
u32 cksum; /* MJ checksum value read from journal */
|
||||
u32 u; /* Unsigned loop counter */
|
||||
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
||||
zSuper[0] = '\0';
|
||||
char *zOut = 0;
|
||||
|
||||
*pzSuper = 0;
|
||||
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|
||||
|| szJ<16
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|
||||
@@ -1314,27 +1318,34 @@ static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|
||||
|| memcmp(aMagic, aJournalMagic, 8)
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
|
||||
){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* See if the checksum matches the super-journal name */
|
||||
for(u=0; u<len; u++){
|
||||
cksum -= zSuper[u];
|
||||
zOut = (char*)sqlite3MallocZero(4 + len + 2);
|
||||
if( !zOut ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
zOut = &zOut[4];
|
||||
if( SQLITE_OK==(rc = sqlite3OsRead(pJrnl, zOut, len, szJ-16-len)) ){
|
||||
u32 u; /* Unsigned loop counter */
|
||||
/* See if the checksum matches the super-journal name */
|
||||
for(u=0; u<len; u++){
|
||||
cksum -= zOut[u];
|
||||
}
|
||||
}
|
||||
if( rc!=SQLITE_OK || cksum ){
|
||||
/* If the checksum doesn't add up, then one or more of the disk sectors
|
||||
** containing the super-journal filename is corrupted. This means
|
||||
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
||||
** super-journal filename. */
|
||||
freeSuperJournal(zOut);
|
||||
zOut = 0;
|
||||
}
|
||||
}
|
||||
if( cksum ){
|
||||
/* If the checksum doesn't add up, then one or more of the disk sectors
|
||||
** containing the super-journal filename is corrupted. This means
|
||||
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
||||
** super-journal filename.
|
||||
*/
|
||||
len = 0;
|
||||
}
|
||||
zSuper[len] = '\0';
|
||||
zSuper[len+1] = '\0';
|
||||
|
||||
return SQLITE_OK;
|
||||
|
||||
*pzSuper = zOut;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2539,9 +2550,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
char *zSuperJournal = 0; /* Contents of super-journal file */
|
||||
i64 nSuperJournal; /* Size of super-journal file */
|
||||
char *zJournal; /* Pointer to one journal within MJ file */
|
||||
char *zSuperPtr; /* Space to hold super-journal filename */
|
||||
char *zFree = 0; /* Free this buffer */
|
||||
i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
|
||||
|
||||
/* Allocate space for both the pJournal and pSuper file descriptors.
|
||||
** If successful, open the super-journal file for reading.
|
||||
@@ -2564,9 +2573,8 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
*/
|
||||
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
|
||||
if( rc!=SQLITE_OK ) goto delsuper_out;
|
||||
nSuperPtr = 1 + (i64)pVfs->mxPathname;
|
||||
assert( nSuperJournal>=0 && nSuperPtr>0 );
|
||||
zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
|
||||
assert( nSuperJournal>=0 );
|
||||
zFree = sqlite3Malloc(4 + nSuperJournal + 2);
|
||||
if( !zFree ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto delsuper_out;
|
||||
@@ -2575,7 +2583,6 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
}
|
||||
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
|
||||
zSuperJournal = &zFree[4];
|
||||
zSuperPtr = &zSuperJournal[nSuperJournal+2];
|
||||
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
|
||||
if( rc!=SQLITE_OK ) goto delsuper_out;
|
||||
zSuperJournal[nSuperJournal] = 0;
|
||||
@@ -2589,6 +2596,8 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
goto delsuper_out;
|
||||
}
|
||||
if( exists ){
|
||||
char *zSuperPtr = 0;
|
||||
|
||||
/* One of the journals pointed to by the super-journal exists.
|
||||
** Open it and check if it points at the super-journal. If
|
||||
** so, return without deleting the super-journal file.
|
||||
@@ -2603,13 +2612,15 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
goto delsuper_out;
|
||||
}
|
||||
|
||||
rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
|
||||
rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr);
|
||||
sqlite3OsClose(pJournal);
|
||||
if( rc!=SQLITE_OK ){
|
||||
assert( zSuperPtr==0 );
|
||||
goto delsuper_out;
|
||||
}
|
||||
|
||||
c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
|
||||
c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0;
|
||||
freeSuperJournal(zSuperPtr);
|
||||
if( c ){
|
||||
/* We have a match. Do not delete the super-journal file. */
|
||||
goto delsuper_out;
|
||||
@@ -2824,19 +2835,11 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
** If a super-journal file name is specified, but the file is not
|
||||
** present on disk, then the journal is not hot and does not need to be
|
||||
** played back.
|
||||
**
|
||||
** 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+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
|
||||
** mxPathname is 512, which is the same as the minimum allowable value
|
||||
** 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] ){
|
||||
*/
|
||||
rc = readSuperJournal(pPager->jfd, 1+(i64)pPager->pVfs->mxPathname, &zSuper);
|
||||
if( rc==SQLITE_OK && zSuper ){
|
||||
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
|
||||
}
|
||||
zSuper = 0;
|
||||
if( rc!=SQLITE_OK || !res ){
|
||||
goto end_playback;
|
||||
}
|
||||
@@ -2965,30 +2968,20 @@ end_playback:
|
||||
*/
|
||||
pPager->changeCountDone = pPager->tempFile;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Leave 4 bytes of space before the super-journal filename in memory.
|
||||
** This is because it may end up being passed to sqlite3OsOpen(), in
|
||||
** which case it requires 4 0x00 bytes in memory immediately before
|
||||
** the filename. */
|
||||
zSuper = &pPager->pTmpSpace[4];
|
||||
rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc==SQLITE_OK
|
||||
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
|
||||
){
|
||||
rc = sqlite3PagerSync(pPager, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
|
||||
rc = pager_end_transaction(pPager, zSuper!=0, 0);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc==SQLITE_OK && zSuper[0] && res ){
|
||||
if( rc==SQLITE_OK && zSuper && res ){
|
||||
/* If there was a super-journal and this routine will return success,
|
||||
** see if it is possible to delete the super-journal.
|
||||
*/
|
||||
assert( zSuper==&pPager->pTmpSpace[4] );
|
||||
memset(pPager->pTmpSpace, 0, 4);
|
||||
assert( memcmp(&zSuper[-4], "\0\0\0\0", 4)==0 );
|
||||
rc = pager_delsuper(pPager, zSuper);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
@@ -3001,6 +2994,7 @@ end_playback:
|
||||
** back a journal created by a process with a different sector size
|
||||
** value. Reset it to the correct value for this process.
|
||||
*/
|
||||
freeSuperJournal(zSuper);
|
||||
setSectorSize(pPager);
|
||||
return rc;
|
||||
}
|
||||
|
||||
+18
-16
@@ -309,22 +309,24 @@ static int pcache1InitBulk(PCache1 *pCache){
|
||||
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
|
||||
szBulk = pCache->szAlloc*(i64)pCache->nMax;
|
||||
}
|
||||
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
|
||||
sqlite3EndBenignMalloc();
|
||||
if( zBulk ){
|
||||
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
|
||||
do{
|
||||
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
|
||||
pX->page.pBuf = zBulk;
|
||||
pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
|
||||
assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
|
||||
pX->isBulkLocal = 1;
|
||||
pX->isAnchor = 0;
|
||||
pX->pNext = pCache->pFree;
|
||||
pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
|
||||
pCache->pFree = pX;
|
||||
zBulk += pCache->szAlloc;
|
||||
}while( --nBulk );
|
||||
if( szBulk>=pCache->szAlloc ){
|
||||
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
|
||||
sqlite3EndBenignMalloc();
|
||||
if( zBulk ){
|
||||
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
|
||||
do{
|
||||
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
|
||||
pX->page.pBuf = zBulk;
|
||||
pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
|
||||
assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
|
||||
pX->isBulkLocal = 1;
|
||||
pX->isAnchor = 0;
|
||||
pX->pNext = pCache->pFree;
|
||||
pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
|
||||
pCache->pFree = pX;
|
||||
zBulk += pCache->szAlloc;
|
||||
}while( --nBulk );
|
||||
}
|
||||
}
|
||||
return pCache->pFree!=0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -581,7 +581,7 @@ void sqlite3ParseObjectReset(Parse *pParse){
|
||||
assert( db->pParse==pParse );
|
||||
assert( pParse->nested==0 );
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
|
||||
if( pParse->nTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
|
||||
#endif
|
||||
while( pParse->pCleanup ){
|
||||
ParseCleanup *pCleanup = pParse->pCleanup;
|
||||
|
||||
+7
-31
@@ -991,8 +991,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++;
|
||||
@@ -1322,37 +1322,11 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
return p->zText;
|
||||
}
|
||||
|
||||
/*
|
||||
** Use the content of the StrAccum passed as the second argument
|
||||
** as the result of an SQL function.
|
||||
*/
|
||||
void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
|
||||
if( p->accError ){
|
||||
sqlite3_result_error_code(pCtx, p->accError);
|
||||
sqlite3_str_reset(p);
|
||||
}else if( isMalloced(p) ){
|
||||
sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
|
||||
}else{
|
||||
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
|
||||
sqlite3_str_reset(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This singleton is an sqlite3_str object that is returned if
|
||||
** sqlite3_malloc() fails to provide space for a real one. This
|
||||
** sqlite3_str object accepts no new text and always returns
|
||||
** an SQLITE_NOMEM error.
|
||||
*/
|
||||
static sqlite3_str sqlite3OomStr = {
|
||||
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
|
||||
};
|
||||
|
||||
/* Finalize a string created using sqlite3_str_new().
|
||||
*/
|
||||
char *sqlite3_str_finish(sqlite3_str *p){
|
||||
char *z;
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){
|
||||
z = sqlite3StrAccumFinish(p);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
@@ -1393,6 +1367,8 @@ void sqlite3_str_reset(StrAccum *p){
|
||||
if( isMalloced(p) ){
|
||||
sqlite3DbFree(p->db, p->zText);
|
||||
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
|
||||
}else if( p==(sqlite3_str*)&sqlite3OomStr ){
|
||||
return;
|
||||
}
|
||||
p->nAlloc = 0;
|
||||
p->nChar = 0;
|
||||
@@ -1404,7 +1380,7 @@ void sqlite3_str_reset(StrAccum *p){
|
||||
** of its content, all in one call.
|
||||
*/
|
||||
void sqlite3_str_free(sqlite3_str *p){
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
if( p!=0 && p!=(sqlite3_str*)&sqlite3OomStr ){
|
||||
sqlite3_str_reset(p);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
@@ -1441,7 +1417,7 @@ sqlite3_str *sqlite3_str_new(sqlite3 *db){
|
||||
sqlite3StrAccumInit(p, 0, 0, 0,
|
||||
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
|
||||
}else{
|
||||
p = &sqlite3OomStr;
|
||||
p = (sqlite3_str*)&sqlite3OomStr;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
+13
-4
@@ -754,7 +754,7 @@ static int lookupName(
|
||||
** cnt>1 means there were two or more matches.
|
||||
**
|
||||
** cnt==0 is always an error. cnt>1 is often an error, but might
|
||||
** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
|
||||
** be multiple matches for a NATURAL OUTER JOIN or a OUTER JOIN USING.
|
||||
*/
|
||||
assert( pFJMatch==0 || cnt>0 );
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
|
||||
@@ -837,9 +837,18 @@ lookupname_end:
|
||||
if( cnt==1 ){
|
||||
assert( pNC!=0 );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){
|
||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||
}
|
||||
if( db->xAuth ){
|
||||
if( pFJMatch ){
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
assert( sqlite3_stricmp(pExpr->u.zToken,"coalesce")==0 );
|
||||
assert( pExpr->x.pList==pFJMatch );
|
||||
assert( pFJMatch->nExpr>0 );
|
||||
pExpr = pFJMatch->a[0].pExpr;
|
||||
}
|
||||
if( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ){
|
||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Increment the nRef value on all name contexts from TopNC up to
|
||||
** the point where the name matched. */
|
||||
|
||||
+13
-1
@@ -2441,6 +2441,13 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
|
||||
sqlite3 *db = pParse->db;
|
||||
u64 savedFlags;
|
||||
|
||||
pParse->nNestSel++;
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
if( pParse->nNestSel >= db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
|
||||
sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
savedFlags = db->flags;
|
||||
db->flags &= ~(u64)SQLITE_FullColNames;
|
||||
db->flags |= SQLITE_ShortColNames;
|
||||
@@ -2462,6 +2469,8 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
|
||||
sqlite3DeleteTable(db, pTab);
|
||||
return 0;
|
||||
}
|
||||
pParse->nNestSel--;
|
||||
assert( pParse->nNestSel>=0 );
|
||||
return pTab;
|
||||
}
|
||||
|
||||
@@ -7432,8 +7441,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",
|
||||
|
||||
+123
-64
@@ -301,7 +301,7 @@ INCLUDE ../ext/intck/sqlite3intck.h
|
||||
INCLUDE ../ext/intck/sqlite3intck.c
|
||||
INCLUDE ../ext/misc/stmtrand.c
|
||||
INCLUDE ../ext/misc/vfstrace.c
|
||||
INCLUDE ../ext/misc/analyze.c
|
||||
INCLUDE ../ext/misc/diskused.c
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
||||
#define SQLITE_SHELL_HAVE_RECOVER 1
|
||||
@@ -934,7 +934,7 @@ static char *local_getline(char *zLine, FILE *in){
|
||||
** or if the NO_COLOR environment variable exists
|
||||
*/
|
||||
static int shellNoColor(void){
|
||||
#ifdef SQLITE_NO_COLOR
|
||||
#if defined(SQLITE_NO_COLOR) || defined(SQLITE_SHELL_FIDDLE)
|
||||
return 1;
|
||||
#else
|
||||
return getenv("NO_COLOR")!=0;
|
||||
@@ -2104,6 +2104,43 @@ static void modeSetStr(char **az, const char *zNew){
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward reference */
|
||||
static int pickStr(const char *zArg, char **pzErr, ...);
|
||||
|
||||
/*
|
||||
** Change the limits on the display mode. Return 0 on
|
||||
** success. Return non-zero if zArg is mis-formatted.
|
||||
**
|
||||
** Valid arguments:
|
||||
**
|
||||
** "on" Default limits
|
||||
** "off" All limits turned off
|
||||
** L,C Line and Characters limits set
|
||||
** L,C,T Line, Character, and Title limits set
|
||||
**
|
||||
** Anything else returns non-zero
|
||||
*/
|
||||
static int modeSetLimit(ShellState *p, const char *zArg){
|
||||
int k = zArg==0 ? 1 : pickStr(zArg,0,"on","off","");
|
||||
if( k==0 ){
|
||||
p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
|
||||
p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
|
||||
p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
|
||||
}else if( k==1 ){
|
||||
p->mode.spec.nLineLimit = 0;
|
||||
p->mode.spec.nCharLimit = 0;
|
||||
p->mode.spec.nTitleLimit = 0;
|
||||
}else{
|
||||
int L, C, T = 0;
|
||||
int nNum = sscanf(zArg, "%d,%d,%d", &L, &C, &T);
|
||||
if( nNum<2 || L<0 || C<0 || T<0) return 1;
|
||||
p->mode.spec.nLineLimit = L;
|
||||
p->mode.spec.nCharLimit = C;
|
||||
if( nNum==3 ) p->mode.spec.nTitleLimit = T;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the mode to eMode
|
||||
*/
|
||||
@@ -2140,6 +2177,7 @@ static void modeChange(ShellState *p, unsigned char eMode){
|
||||
u8 mFlags = p->mode.mFlags;
|
||||
modeFree(&p->mode);
|
||||
modeChange(p, MODE_List);
|
||||
modeSetLimit(p, "off");
|
||||
p->mode.mFlags = mFlags;
|
||||
}else if( eMode==MODE_TTY ){
|
||||
u8 mFlags = p->mode.mFlags;
|
||||
@@ -4228,8 +4266,8 @@ static const char *(azHelp[]) = {
|
||||
#if SQLITE_SHELL_HAVE_RECOVER
|
||||
".dbinfo ?DB? Show status information about the database",
|
||||
#endif
|
||||
".dbstat ?SCHEMA? Report database space and size stats",
|
||||
".dbtotxt Hex dump of the database file",
|
||||
".diskused ?SCHEMA? Report database space and size stats",
|
||||
".dump ?OBJECTS? Render database content as SQL",
|
||||
" Options:",
|
||||
" --data-only Output only INSERT statements",
|
||||
@@ -5058,7 +5096,7 @@ static void open_db(ShellState *p, int openFlags){
|
||||
sqlite3_regexp_init(p->db, 0, 0);
|
||||
sqlite3_ieee_init(p->db, 0, 0);
|
||||
sqlite3_series_init(p->db, 0, 0);
|
||||
sqlite3_analyze_init(p->db, 0, 0);
|
||||
sqlite3_diskused_init(p->db, 0, 0);
|
||||
#ifndef SQLITE_SHELL_FIDDLE
|
||||
sqlite3_fileio_init(p->db, 0, 0);
|
||||
sqlite3_completion_init(p->db, 0, 0);
|
||||
@@ -6864,7 +6902,7 @@ struct ArCommand {
|
||||
u8 eCmd; /* An AR_CMD_* value */
|
||||
u8 bVerbose; /* True if --verbose */
|
||||
u8 bZip; /* True if the archive is a ZIP */
|
||||
u8 bDryRun; /* True if --dry-run */
|
||||
u8 bDryRun; /* 1 for --dry-run, 2 for --debug */
|
||||
u8 bAppend; /* True if --append */
|
||||
u8 bGlob; /* True if --glob */
|
||||
u8 fromCmdLine; /* Run from -A instead of .archive */
|
||||
@@ -6926,6 +6964,7 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
|
||||
#define AR_SWITCH_APPEND 11
|
||||
#define AR_SWITCH_DRYRUN 12
|
||||
#define AR_SWITCH_GLOB 13
|
||||
#define AR_SWITCH_DEBUG 14
|
||||
|
||||
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||
switch( eSwitch ){
|
||||
@@ -6943,7 +6982,10 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||
break;
|
||||
|
||||
case AR_SWITCH_DRYRUN:
|
||||
pAr->bDryRun = 1;
|
||||
if( pAr->bDryRun<2 ) pAr->bDryRun = 1;
|
||||
break;
|
||||
case AR_SWITCH_DEBUG:
|
||||
pAr->bDryRun = 2;
|
||||
break;
|
||||
case AR_SWITCH_GLOB:
|
||||
pAr->bGlob = 1;
|
||||
@@ -6994,6 +7036,7 @@ static int arParseCommand(
|
||||
{ "append", 'a', AR_SWITCH_APPEND, 1 },
|
||||
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
|
||||
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
|
||||
{ "debug", 0, AR_SWITCH_DEBUG, 0 },
|
||||
{ "glob", 'g', AR_SWITCH_GLOB, 0 },
|
||||
};
|
||||
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
|
||||
@@ -7294,14 +7337,37 @@ static int arRemoveCommand(ArCommand *pAr){
|
||||
** Implementation of .ar "eXtract" command.
|
||||
*/
|
||||
static int arExtractCommand(ArCommand *pAr){
|
||||
/* The zSql1[] string is a template for the query that does the
|
||||
** extraction. Notes:
|
||||
**
|
||||
** * $dir is the directory into which the archive is to be extracted
|
||||
** * $pass is the integer pass number: 0, 1, or 2
|
||||
** * The dest CTE is created so that realpath($dir) only needs
|
||||
** to be called once.
|
||||
*/
|
||||
const char *zSql1 =
|
||||
"WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n"
|
||||
"SELECT ($dir || name),\n"
|
||||
" CASE WHEN $dryrun THEN 0\n"
|
||||
" ELSE writefile($dir||name, %s, mode, mtime) END\n"
|
||||
"WITH dest(dpath,dlen) AS (\n"
|
||||
#ifdef _WIN32
|
||||
" SELECT realpath($dir) || '\\',\n"
|
||||
#else
|
||||
" SELECT realpath($dir) || '/',\n"
|
||||
#endif
|
||||
" 1+length(realpath($dir))\n"
|
||||
")\n"
|
||||
"SELECT\n"
|
||||
" ($dir || name),\n"
|
||||
" CASE $dryrun\n" /* vv--- azExtraArg */
|
||||
" WHEN 0 THEN writefile($dir||name, %s, mode, mtime)\n"
|
||||
" WHEN 1 THEN 0\n"
|
||||
" ELSE shell_putsnl(format('writefile(%%Q,%%s,%%0o,%%d)',"
|
||||
"$dir||name,quote(%s),mode,mtime)) IS NULL\n"
|
||||
" END\n" /* ^^--- azExtraArg */
|
||||
" FROM dest CROSS JOIN %s\n"
|
||||
" WHERE (%s)\n"
|
||||
" AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */
|
||||
" WHERE (%s)\n" /* ^^-- pAr->zSrcTable */
|
||||
/* ^^--- zWhere */
|
||||
" AND (CASE $pass WHEN 0 THEN (mode&0xf000)<>0xa000\n"
|
||||
" WHEN 1 THEN (mode&0xf000)=0xa000\n"
|
||||
" ELSE data IS NULL END)\n"
|
||||
" AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
|
||||
" AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
|
||||
|
||||
@@ -7332,7 +7398,10 @@ static int arExtractCommand(ArCommand *pAr){
|
||||
}
|
||||
|
||||
shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
|
||||
azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
|
||||
azExtraArg[pAr->bZip],
|
||||
azExtraArg[pAr->bZip],
|
||||
pAr->zSrcTable,
|
||||
zWhere
|
||||
);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -7342,25 +7411,31 @@ static int arExtractCommand(ArCommand *pAr){
|
||||
sqlite3_bind_int(pSql, j, pAr->bDryRun);
|
||||
|
||||
/* Run the SELECT statement twice
|
||||
** (0) writefile() all files and directories
|
||||
** (1) writefile() for directory again
|
||||
** The second pass is so that the timestamps for extracted directories
|
||||
** (0) writefile() files and directories
|
||||
** (1) writefile() symlinks
|
||||
** (2) writefile() for directory again
|
||||
** The third pass is so that the timestamps for extracted directories
|
||||
** will be reset to the value in the archive, since populating them
|
||||
** in the first pass will have changed the timestamp. */
|
||||
for(i=0; i<2; i++){
|
||||
for(i=0; i<3; i++){
|
||||
if( pAr->bDryRun>=2 ){
|
||||
cli_printf(pAr->out, "*** BEGIN PASS %d ***\n", i+1);
|
||||
}
|
||||
j = sqlite3_bind_parameter_index(pSql, "$pass");
|
||||
sqlite3_bind_int(pSql, j, i);
|
||||
if( pAr->bDryRun ){
|
||||
if( pAr->bDryRun && i==0 ){
|
||||
cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
|
||||
if( pAr->bVerbose==0 ) break;
|
||||
}
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||
if( i==0 && pAr->bVerbose ){
|
||||
cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0));
|
||||
}
|
||||
}
|
||||
if( pAr->bDryRun ) break;
|
||||
if( pAr->bDryRun==1 ) break;
|
||||
shellReset(&rc, pSql);
|
||||
if( pAr->bDryRun>=2 ){
|
||||
cli_printf(pAr->out, "*** END PASS %d ***\n", i+1);
|
||||
}
|
||||
}
|
||||
shellFinalize(&rc, pSql);
|
||||
}
|
||||
@@ -7875,7 +7950,7 @@ SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
|
||||
SELECT\
|
||||
'('||x'0a'\
|
||||
|| group_concat(\
|
||||
cname||' ANY',\
|
||||
cname,\
|
||||
','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
|
||||
||')' AS ColsSpec \
|
||||
FROM (\
|
||||
@@ -8720,26 +8795,10 @@ static int dotCmdMode(ShellState *p){
|
||||
dotCmdError(p, i-1, "missing argument", 0);
|
||||
return 1;
|
||||
}
|
||||
k = pickStr(azArg[i],0,"on","off","");
|
||||
if( k==0 ){
|
||||
p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
|
||||
p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
|
||||
p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
|
||||
}else if( k==1 ){
|
||||
p->mode.spec.nLineLimit = 0;
|
||||
p->mode.spec.nCharLimit = 0;
|
||||
p->mode.spec.nTitleLimit = 0;
|
||||
}else{
|
||||
int L, C, T = 0;
|
||||
int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
|
||||
if( nNum<2 || L<0 || C<0 || T<0){
|
||||
dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
|
||||
" and T are unsigned integers");
|
||||
return 1;
|
||||
}
|
||||
p->mode.spec.nLineLimit = L;
|
||||
p->mode.spec.nCharLimit = C;
|
||||
if( nNum==3 ) p->mode.spec.nTitleLimit = T;
|
||||
if( modeSetLimit(p, azArg[i]) ){
|
||||
dotCmdError(p, i, "bad argument", "Should be \"on\" or \"off\" or "
|
||||
"\"L,C,T\" where L, C, and T are unsigned integers");
|
||||
return 1;
|
||||
}
|
||||
chng = 1;
|
||||
}else if( optionMatch(z,"list") ){
|
||||
@@ -9957,7 +10016,12 @@ static int do_meta_command(const char *zLine, ShellState *p){
|
||||
}else
|
||||
#endif /* SQLITE_SHELL_HAVE_RECOVER */
|
||||
|
||||
if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
|
||||
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
|
||||
open_db(p, 0);
|
||||
rc = shell_dbtotxt_command(p, nArg, azArg);
|
||||
}else
|
||||
|
||||
if( c=='d' && n==8 && cli_strncmp(azArg[0], "diskused", n)==0 ){
|
||||
const char *zSchema = 0;
|
||||
int ii;
|
||||
char *zSql;
|
||||
@@ -9976,23 +10040,15 @@ static int do_meta_command(const char *zLine, ShellState *p){
|
||||
}
|
||||
zSchema = z;
|
||||
}
|
||||
zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
|
||||
zSql = sqlite3_mprintf("SELECT diskused(%Q)", zSchema);
|
||||
shell_check_oom(zSql);
|
||||
modePush(p);
|
||||
modeChange(p, MODE_BATCH);
|
||||
p->mode.spec.nLineLimit = 0;
|
||||
p->mode.spec.nCharLimit = 0;
|
||||
p->mode.spec.nTitleLimit = 0;
|
||||
shell_exec(p, zSql, 0);
|
||||
modePop(p);
|
||||
sqlite3_free(zSql);
|
||||
}else
|
||||
|
||||
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
|
||||
open_db(p, 0);
|
||||
rc = shell_dbtotxt_command(p, nArg, azArg);
|
||||
}else
|
||||
|
||||
if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
|
||||
char *zLike = 0;
|
||||
char *zSql;
|
||||
@@ -13352,13 +13408,13 @@ static const char zOptions[] =
|
||||
" -A ARGS... run \".archive ARGS\" and exit\n"
|
||||
#endif
|
||||
" -append append the database to the end of the file\n"
|
||||
" -ascii set output mode to 'ascii'\n"
|
||||
" -ascii set '.mode ascii'\n"
|
||||
" -bail stop after hitting an error\n"
|
||||
" -batch force batch I/O\n"
|
||||
" -box set output mode to 'box'\n"
|
||||
" -box set '.mode box'\n"
|
||||
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
|
||||
" -column set output mode to 'column'\n"
|
||||
" -csv set output mode to 'csv'\n"
|
||||
" -column set '.mode column'\n"
|
||||
" -csv set '.mode csv -limits off'\n"
|
||||
#if !defined(SQLITE_OMIT_DESERIALIZE)
|
||||
" -deserialize open the database using sqlite3_deserialize()\n"
|
||||
#endif
|
||||
@@ -13370,14 +13426,14 @@ static const char zOptions[] =
|
||||
" -heap SIZE Size of heap for memsys3 or memsys5\n"
|
||||
#endif
|
||||
" -help show this message\n"
|
||||
" -html set output mode to HTML\n"
|
||||
" -html set '.mode html'\n"
|
||||
" -ifexists only open if database already exists\n"
|
||||
" -interactive force interactive I/O\n"
|
||||
" -json set output mode to 'json'\n"
|
||||
" -line set output mode to 'line'\n"
|
||||
" -list set output mode to 'list'\n"
|
||||
" -json set '.mode json'\n"
|
||||
" -line set '.mode line'\n"
|
||||
" -list set '.mode list'\n"
|
||||
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
|
||||
" -markdown set output mode to 'markdown'\n"
|
||||
" -markdown set '.mode markdown'\n"
|
||||
#if !defined(SQLITE_OMIT_DESERIALIZE)
|
||||
" -maxsize N maximum size for a --deserialize database\n"
|
||||
#endif
|
||||
@@ -13394,7 +13450,7 @@ static const char zOptions[] =
|
||||
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
||||
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
|
||||
" -pcachetrace trace all page cache operations\n"
|
||||
" -quote set output mode to 'quote'\n"
|
||||
" -quote set '.mode quote'\n"
|
||||
" -readonly open the database read-only\n"
|
||||
" -safe enable safe-mode\n"
|
||||
" -screenwidth N use N as the default screenwidth \n"
|
||||
@@ -13403,8 +13459,8 @@ static const char zOptions[] =
|
||||
" -sorterref SIZE sorter references threshold size\n"
|
||||
#endif
|
||||
" -stats print memory stats before each finalize\n"
|
||||
" -table set output mode to 'table'\n"
|
||||
" -tabs set output mode to 'tabs'\n"
|
||||
" -table set '.mode table'\n"
|
||||
" -tabs set '.mode tabs'\n"
|
||||
" -unsafe-testing allow unsafe commands and modes for testing\n"
|
||||
" -version show SQLite version\n"
|
||||
" -vfs NAME use NAME as the default VFS\n"
|
||||
@@ -13506,7 +13562,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){
|
||||
/*
|
||||
** The callback from atexit().
|
||||
*/
|
||||
static void abnormalExit(void){
|
||||
static void SQLITE_CDECL abnormalExit(void){
|
||||
if( seenInterrupt ) eputz("Program interrupted.\n");
|
||||
if( globalShellState ){
|
||||
clearTempFile(globalShellState, 1, 1);
|
||||
@@ -14006,6 +14062,7 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
modeChange(&data, MODE_Box);
|
||||
}else if( cli_strcmp(z,"-csv")==0 ){
|
||||
modeChange(&data, MODE_Csv);
|
||||
modeSetLimit(&data, "off");
|
||||
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
|
||||
/* See similar code at tag-20250224-1 */
|
||||
const char *zEsc = argv[++i];
|
||||
@@ -14064,8 +14121,10 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
cmdline_option_value(argc,argv,++i));
|
||||
}else if( cli_strcmp(z,"-header")==0 ){
|
||||
data.mode.spec.bTitles = QRF_Yes;
|
||||
data.mode.mFlags |= MFLG_HDR;
|
||||
}else if( cli_strcmp(z,"-noheader")==0 ){
|
||||
data.mode.spec.bTitles = QRF_No;
|
||||
data.mode.mFlags |= MFLG_HDR;
|
||||
}else if( cli_strcmp(z,"-echo")==0 ){
|
||||
data.mode.mFlags |= MFLG_ECHO;
|
||||
}else if( cli_strcmp(z,"-eqp")==0 ){
|
||||
|
||||
+61
-9
@@ -3413,7 +3413,7 @@ void sqlite3_randomness(int N, void *P);
|
||||
**
|
||||
** ^The first parameter to the authorizer callback is a copy of the third
|
||||
** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
|
||||
** to the callback is an integer [SQLITE_COPY | action code] that specifies
|
||||
** to the callback is an integer [SQLITE_READ | action code] that specifies
|
||||
** the particular action to be authorized. ^The third through sixth parameters
|
||||
** to the callback are either NULL pointers or zero-terminated strings
|
||||
** that contain additional details about the action to be authorized.
|
||||
@@ -3545,9 +3545,14 @@ int sqlite3_set_authorizer(
|
||||
#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
|
||||
#define SQLITE_FUNCTION 31 /* NULL Function Name */
|
||||
#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
|
||||
#define SQLITE_COPY 0 /* No longer used */
|
||||
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
||||
|
||||
/*
|
||||
** Note: The SQLITE_COPY macro (with value 0) used to be one of the
|
||||
** action codes above. That macro has now been repurposed as a possible
|
||||
** value to the 3rd argument to sqlite3_result_str().
|
||||
*/
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Tracing And Profiling Functions
|
||||
** DEPRECATED
|
||||
@@ -4377,7 +4382,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** or in an ORDER BY or GROUP BY clause.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
|
||||
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
|
||||
** <dd>The maximum depth of the parse tree on any expression and
|
||||
** the maximum nesting depth for subqueries and VIEWs</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt>
|
||||
** <dd>The maximum depth of the LALR(1) parser stack used to analyze
|
||||
@@ -4408,7 +4414,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
|
||||
** <dd>The maximum depth of recursion for triggers.</dd>)^
|
||||
** <dd>The maximum depth of recursion for triggers, and the maximum
|
||||
** nesting depth for separate triggers.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
|
||||
** <dd>The maximum number of auxiliary worker threads that a single
|
||||
@@ -5285,7 +5292,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
||||
** [prepared statement]. ^In the "v2" interface,
|
||||
** the more specific error code is returned directly by sqlite3_step().
|
||||
**
|
||||
** [SQLITE_MISUSE] means that the this routine was called inappropriately.
|
||||
** [SQLITE_MISUSE] means that this routine was called inappropriately.
|
||||
** Perhaps it was called on a [prepared statement] that has
|
||||
** already been [sqlite3_finalize | finalized] or on one that had
|
||||
** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
|
||||
@@ -8796,8 +8803,8 @@ int sqlite3_keyword_check(const char*,int);
|
||||
** <li> ^The sqlite3_str object is created using [sqlite3_str_new()].
|
||||
** <li> ^Text is appended to the sqlite3_str object using various
|
||||
** methods, such as [sqlite3_str_appendf()].
|
||||
** <li> ^The sqlite3_str object is destroyed and the string it created
|
||||
** is returned using the [sqlite3_str_finish()] interface.
|
||||
** <li> The sqlite3_str object is destroyed and the string it created
|
||||
** is returned using [sqlite3_str_finish()] or [sqlite3_result_str()].
|
||||
** </ol>
|
||||
*/
|
||||
typedef struct sqlite3_str sqlite3_str;
|
||||
@@ -8849,6 +8856,40 @@ sqlite3_str *sqlite3_str_new(sqlite3*);
|
||||
char *sqlite3_str_finish(sqlite3_str*);
|
||||
void sqlite3_str_free(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return A Dynamic String From an SQL Function
|
||||
**
|
||||
** The [sqlite3_result_str(C,S,F)] interface causes the
|
||||
** [sqlite3_str|dynamic string] S to become the return value for the
|
||||
** application-defined function or virtual table that uses
|
||||
** [sqlite3_context] C. The F flag can be one of [SQLITE_COPY]
|
||||
** or [SQLITE_XFER] or [SQLITE_FINISH].
|
||||
**
|
||||
** If the dynamic string is invalid or incomplete due to an out-of-memory
|
||||
** or string-too-large error, then this routine transfers that error
|
||||
** over to the SQL function.
|
||||
**
|
||||
** If the F argument is SQLITE_COPY, then a copy of the dynamic string
|
||||
** content is made and the dynamic string object is unchanged.
|
||||
** If the F argument is SQLITE_XFER, then ownership of the content
|
||||
** in the dynamic is transferred to the SQL function (via a pointer copy
|
||||
** rather than a string copy) and the dynamic string is reset to an
|
||||
** empty string. The SQLITE_FINISH value for F works like SQLITE_RESET
|
||||
** except that it also invokes the [sqlite3_str_free(S)] destructor
|
||||
** on the dynamic string object.
|
||||
*/
|
||||
void sqlite3_result_str(sqlite3_context*, sqlite3_str*, int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Control Flags For sqlite3_result_str()
|
||||
**
|
||||
** The following integers can be used as the third "F" argument
|
||||
** to [sqlite3_result_str(C,S,F)].
|
||||
*/
|
||||
#define SQLITE_COPY 0 /* Results copied. Dynamic string unchanged */
|
||||
#define SQLITE_XFER 1 /* Results transfered. Dynamic string reset */
|
||||
#define SQLITE_FINISH 2 /* Like SQLITE_XFER, plus dynamic string freed */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add Content To A Dynamic String
|
||||
** METHOD: sqlite3_str
|
||||
@@ -11214,8 +11255,19 @@ unsigned char *sqlite3_serialize(
|
||||
** used. The serialized database P is N bytes in size. M is the size
|
||||
** of the buffer P, which might be larger than N. If M is larger than
|
||||
** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
|
||||
** SQLite is permitted to add content to the in-memory database as
|
||||
** long as the total size does not exceed M bytes.
|
||||
** SQLite is permitted to add content to the in-memory database, in
|
||||
** page-sized chunks, as long as the total size does not exceed M bytes.
|
||||
**
|
||||
** The parameter M must be greater than or equal to N. Ideally, M
|
||||
** should have a value which is N+(512×K)+20 where K determines how
|
||||
** must extra space is available to hold new content as the database
|
||||
** grows. K can be 0 if the database is read-only.
|
||||
**
|
||||
** If the database content in P is malformed in a malicious way then
|
||||
** it is possible that SQLite might try to read a few more than N bytes
|
||||
** from P. If the veracity of the database content P is uncertain,
|
||||
** then applications are advised to allocate about 20 extra bytes on
|
||||
** the end of the P buffer to avoid a memory error.
|
||||
**
|
||||
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
|
||||
** invoke sqlite3_free() on the serialization buffer when the database
|
||||
|
||||
@@ -378,6 +378,7 @@ struct sqlite3_api_routines {
|
||||
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
|
||||
/* Version 3.54.0 and later */
|
||||
sqlite3_int64 (*incomplete)(const char*);
|
||||
void (*result_str)(sqlite3_context*,sqlite3_str*,int);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -723,6 +724,7 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
|
||||
/* Version 3.54.0 and later */
|
||||
#define sqlite3_incomplete sqlite3_api->incomplete
|
||||
#define sqlite3_result_str sqlite3_api->result_str
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+17
-4
@@ -767,6 +767,13 @@
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** sizeof64() is like sizeof(), but always returns a 64-bit value, even
|
||||
** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit
|
||||
** arithmetic is used consistently in both 32-bit and 64-bit builds.
|
||||
*/
|
||||
#define sizeof64(X) ((sqlite3_int64)sizeof(X))
|
||||
|
||||
/*
|
||||
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
|
||||
** to avoid complaints from -fsanitize=strict-bounds.
|
||||
@@ -3904,14 +3911,15 @@ struct Parse {
|
||||
bft bHasWith :1; /* True if statement contains WITH */
|
||||
bft okConstFactor:1; /* OK to factor out constants */
|
||||
bft checkSchema :1; /* Causes schema cookie check after an error */
|
||||
bft usesAinc :1; /* True if pAinc is valid */
|
||||
int nRangeReg; /* Size of the temporary register block */
|
||||
int iRangeReg; /* First register in temporary register block */
|
||||
int nErr; /* Number of errors seen */
|
||||
int nTab; /* Number of previously allocated VDBE cursors */
|
||||
int nMem; /* Number of memory cells used so far */
|
||||
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
|
||||
int iSelfTab; /* Table associated with an index on expr, or negative
|
||||
** of the base register during check-constraint eval */
|
||||
int nNestSel; /* Number of nested SELECT statements and/or VIEWs */
|
||||
int nLabel; /* The *negative* of the number of labels used */
|
||||
int nLabelAlloc; /* Number of slots in aLabel */
|
||||
int *aLabel; /* Space to hold the labels */
|
||||
@@ -3927,9 +3935,7 @@ struct Parse {
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
int nTableLock; /* Number of locks in aTableLock */
|
||||
TableLock *aTableLock; /* Required table locks for shared-cache mode */
|
||||
#endif
|
||||
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
|
||||
Parse *pToplevel; /* Parse structure for main program (or NULL) */
|
||||
Table *pTriggerTab; /* Table triggers are being coded for */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
@@ -3958,6 +3964,13 @@ struct Parse {
|
||||
Returning *pReturning; /* The RETURNING clause */
|
||||
} d;
|
||||
} u1;
|
||||
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters. Only
|
||||
** valid if Parse.usesAinc is true */
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
TableLock *aTableLock; /* Required table locks for shared-cache mode. Only
|
||||
** valid if Parse.nTableLock>0 */
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************
|
||||
** Above is constant between recursions. Below is reset before and after
|
||||
@@ -5491,6 +5504,7 @@ extern const unsigned char *sqlite3aGTb;
|
||||
extern const unsigned char sqlite3CtypeMap[];
|
||||
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
|
||||
extern FuncDefHash sqlite3BuiltinFunctions;
|
||||
extern const sqlite3_str sqlite3OomStr;
|
||||
#ifndef SQLITE_OMIT_WSD
|
||||
extern int sqlite3PendingByte;
|
||||
#endif
|
||||
@@ -5593,7 +5607,6 @@ int sqlite3StrAccumEnlarge(StrAccum*, i64);
|
||||
int sqlite3StrAccumEnlargeIfNeeded(StrAccum*, i64);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumSetError(StrAccum*, u8);
|
||||
void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
|
||||
void sqlite3SelectDestInit(SelectDest*,int,int);
|
||||
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
|
||||
void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
|
||||
|
||||
+15
-1
@@ -1234,7 +1234,7 @@ static TriggerPrg *codeRowTrigger(
|
||||
Table *pTab, /* The table pTrigger is attached to */
|
||||
int orconf /* ON CONFLICT policy to code trigger program with */
|
||||
){
|
||||
Parse *pTop = sqlite3ParseToplevel(pParse);
|
||||
Parse *pTop; /* Top level Parse object */
|
||||
sqlite3 *db = pParse->db; /* Database handle */
|
||||
TriggerPrg *pPrg; /* Value to return */
|
||||
Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
|
||||
@@ -1243,10 +1243,24 @@ static TriggerPrg *codeRowTrigger(
|
||||
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
|
||||
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
|
||||
Parse sSubParse; /* Parse context for sub-vdbe */
|
||||
int nDepth; /* Trigger depth */
|
||||
|
||||
/* Ensure that triggers are not chained too deep. This test is linear
|
||||
** in the chaining depth, but sensible code ought not be chaining
|
||||
** triggers excessively, so that shouldn't be a problem.
|
||||
*/
|
||||
pTop = pParse;
|
||||
for(nDepth=0; pTop->pOuterParse; pTop = pTop->pOuterParse, nDepth++){}
|
||||
if( nDepth>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
|
||||
sqlite3ErrorMsg(pParse, "triggers nested too deep");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pTop = sqlite3ParseToplevel(pParse);
|
||||
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
|
||||
assert( pTop->pVdbe );
|
||||
|
||||
|
||||
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
|
||||
** are freed if an error occurs, link them into the Parse.pTriggerPrg
|
||||
** list of the top-level Parse object sooner rather than later. */
|
||||
|
||||
+2
-1
@@ -318,7 +318,8 @@ void sqlite3UpsertDoUpdate(
|
||||
/* excluded.* columns of type REAL need to be converted to a hard real */
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
|
||||
int iStorage = pTop->regData + sqlite3TableColumnToStorage(pTab, i);
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, iStorage);
|
||||
}
|
||||
}
|
||||
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
|
||||
|
||||
+1
-1
@@ -7560,7 +7560,7 @@ case OP_Program: { /* jump0 */
|
||||
|
||||
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3VdbeError(p, "too many levels of trigger recursion");
|
||||
sqlite3VdbeError(p, "triggers nested too deep");
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
|
||||
|
||||
+74
-9
@@ -374,15 +374,18 @@ void sqlite3_value_free(sqlite3_value *pOld){
|
||||
|
||||
|
||||
/**************************** sqlite3_result_ *******************************
|
||||
** The following routines are used by user-defined functions to specify
|
||||
** the function result.
|
||||
** The following routines are used by application-defined SQL functions to
|
||||
** specify the function return value. There are many variations on
|
||||
** sqlite3_result_xxxx() for different types of return values.
|
||||
**
|
||||
** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
|
||||
** result as a string or blob. Appropriate errors are set if the string/blob
|
||||
** is too big or if an OOM occurs.
|
||||
** The setStrOrError() function is a helper function that invokes
|
||||
** sqlite3VdbeMemSetStr() to store the result as a string or blob.
|
||||
** Appropriate errors are set if the string/blob is too big or if
|
||||
** an OOM occurs.
|
||||
**
|
||||
** The invokeValueDestructor(P,X) routine invokes destructor function X()
|
||||
** on value P if P is not going to be used and need to be destroyed.
|
||||
** The invokeValueDestructor(P,X) helper function invokes the destructor
|
||||
** function X() on value P if P is not going to be used and need to
|
||||
** be destroyed.
|
||||
*/
|
||||
static void setResultStrOrError(
|
||||
sqlite3_context *pCtx, /* Function context */
|
||||
@@ -695,7 +698,7 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
||||
}
|
||||
}
|
||||
|
||||
/* Force an SQLITE_TOOBIG error. */
|
||||
/* Cause the SQL function to raise an SQLITE_TOOBIG error. */
|
||||
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCtx==0 ) return;
|
||||
@@ -706,7 +709,7 @@ void sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
||||
SQLITE_UTF8, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/* An SQLITE_NOMEM error. */
|
||||
/* Cause the SQL function to raise an SQLITE_NOMEM error. */
|
||||
void sqlite3_result_error_nomem(sqlite3_context *pCtx){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCtx==0 ) return;
|
||||
@@ -717,6 +720,68 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){
|
||||
sqlite3OomFault(pCtx->pOut->db);
|
||||
}
|
||||
|
||||
/* Make the return value of the SQL function or virtual table pCtx
|
||||
** be the content of the sqlite3_str object pStr. The eOwn flag
|
||||
** determines ownership of the sqlite3_str object and its content.
|
||||
**
|
||||
** eOwn Ownership transfer
|
||||
** ------------- ------------------------------------------------
|
||||
**
|
||||
** SQLITE_COPY The SQL function returns a copy the sqlite3_str
|
||||
** content and leaves the sqlite3_str object itself
|
||||
** unchanged.
|
||||
**
|
||||
** SQLITE_XFER The content of the sqlite3_str is transferred to
|
||||
** the SQL function and the SQL function takes
|
||||
** responsibility for freeing that content when it is
|
||||
** no longer needed. The sqlite3_str object is reset
|
||||
** to an empty string.
|
||||
**
|
||||
** SQLITE_FINISH Like SQLITE_XFER except that the pStr is also
|
||||
** freed using sqlite3_str_free().
|
||||
*/
|
||||
void sqlite3_result_str(sqlite3_context *pCtx, sqlite3_str *pStr, int eOwn){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCtx==0 ) return;
|
||||
if( pStr==0 ) return;
|
||||
#endif
|
||||
if( pStr->accError==0 ){
|
||||
if( pStr->nChar==0 ){
|
||||
setResultStrOrError(pCtx, "", 0, SQLITE_UTF8_ZT, SQLITE_STATIC);
|
||||
if( eOwn ) sqlite3_str_reset(pStr);
|
||||
}else{
|
||||
const char *zText = sqlite3_str_value(pStr);
|
||||
/* Only internal code has the ability to capture a pointer to
|
||||
** an sqlite3_str object that uses static buffer. And none of
|
||||
** those internal use cases every invoke the sqlite3_result_str()
|
||||
** interface on a static-buffer sqlite3_str. Should this change
|
||||
** in the future, the following assert() will let us know. */
|
||||
assert( isMalloced(pStr) );
|
||||
if( eOwn==SQLITE_COPY ){
|
||||
setResultStrOrError(pCtx, zText, pStr->nChar,
|
||||
SQLITE_UTF8, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
setResultStrOrError(pCtx, zText, pStr->nChar,
|
||||
SQLITE_UTF8_ZT, SQLITE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
}else if( pStr->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}else{
|
||||
assert( pStr->accError==SQLITE_TOOBIG );
|
||||
sqlite3_result_error_toobig(pCtx);
|
||||
}
|
||||
if( eOwn ){
|
||||
testcase( pStr==(sqlite3_str*)&sqlite3OomStr );
|
||||
if( pStr->accError==0 ){
|
||||
sqlite3StrAccumInit(pStr, pStr->db, 0, 0, pStr->mxAlloc);
|
||||
}
|
||||
if( eOwn==SQLITE_FINISH ){
|
||||
sqlite3_str_free(pStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_UNTESTABLE
|
||||
/* Force the INT64 value currently stored as the result to be
|
||||
** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL
|
||||
|
||||
+3
-5
@@ -41,7 +41,6 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
|
||||
assert( pParse->aLabel==0 );
|
||||
assert( pParse->nLabel==0 );
|
||||
assert( p->nOpAlloc==0 );
|
||||
assert( pParse->szOpAlloc==0 );
|
||||
sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
|
||||
return p;
|
||||
}
|
||||
@@ -191,8 +190,7 @@ static int growOpArray(Vdbe *v, int nOp){
|
||||
assert( nNew>=(v->nOpAlloc+nOp) );
|
||||
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
|
||||
if( pNew ){
|
||||
p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
|
||||
v->nOpAlloc = p->szOpAlloc/sizeof(Op);
|
||||
v->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
|
||||
v->aOp = pNew;
|
||||
}
|
||||
return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
|
||||
@@ -627,7 +625,7 @@ int sqlite3VdbeMakeLabel(Parse *pParse){
|
||||
** a prior call to sqlite3VdbeMakeLabel().
|
||||
*/
|
||||
static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
|
||||
int nNewSize = 10 - p->nLabel;
|
||||
int nNewSize = 25 - p->nLabel;
|
||||
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
|
||||
nNewSize*sizeof(p->aLabel[0]));
|
||||
if( p->aLabel==0 ){
|
||||
@@ -2695,7 +2693,7 @@ void sqlite3VdbeMakeReady(
|
||||
n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
|
||||
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
|
||||
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
|
||||
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
|
||||
x.nFree = ROUNDDOWN8((p->nOpAlloc-p->nOp)*sizeof(Op)); /* Bytes unused mem */
|
||||
assert( x.nFree>=0 );
|
||||
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
|
||||
|
||||
|
||||
+2
-2
@@ -114,8 +114,8 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
|
||||
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
|
||||
** The problem appears to be fixed in GCC 15 */
|
||||
i64 x;
|
||||
assert( (MEM_Str&~p->flags)*4==sizeof(x) );
|
||||
memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4);
|
||||
assert( (sqlite3Config.bSmallMalloc!=0xee)*8==sizeof(x) );
|
||||
memcpy(&x, (char*)&p->u.i, (sqlite3Config.bSmallMalloc!=0xee)*8);
|
||||
p->n = sqlite3Int64ToText(x, zBuf);
|
||||
#else
|
||||
p->n = sqlite3Int64ToText(p->u.i, zBuf);
|
||||
|
||||
@@ -1023,6 +1023,12 @@ static int walDecodeFrame(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Need a valid page size
|
||||
*/
|
||||
if( !pWal->szPage ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A frame is only valid if a checksum of the WAL header,
|
||||
** all prior frames, the first 16 bytes of this frame-header,
|
||||
** and the frame-data matches the checksum in the last 8
|
||||
@@ -2877,7 +2883,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
|
||||
|
||||
/* Allocate a buffer to read frames into */
|
||||
assert( (pWal->szPage & (pWal->szPage-1))==0 );
|
||||
assert( pWal->szPage>=512 && pWal->szPage<=65536 );
|
||||
assert( (pWal->szPage>=512 && pWal->szPage<=65536) || pWal->szPage==0 );
|
||||
szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
|
||||
aFrame = (u8 *)sqlite3_malloc64(szFrame);
|
||||
if( aFrame==0 ){
|
||||
|
||||
@@ -2717,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)
|
||||
|
||||
+45
-10
@@ -515,7 +515,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
|
||||
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
|
||||
pWC->a[iChild].iParent = iParent;
|
||||
pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
|
||||
assert( pWC->a[iParent].nChild < UMXV(pWC->a[0].nChild) );
|
||||
pWC->a[iParent].nChild++;
|
||||
testcase( pWC->a[iParent].nChild == UMXV(pWC->a[0].nChild) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -904,29 +907,56 @@ static void exprAnalyzeOrTerm(
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point, okToChngToIN is true if original pTerm satisfies
|
||||
** case 1. In that case, construct a new virtual term that is
|
||||
** pTerm converted into an IN operator.
|
||||
/* At this point, okToChngToIN is true if original pTerm is a
|
||||
** candidate to satisfy case 1, though we are not yet certain that
|
||||
** the collating sequences are all compatible. Try to construct a
|
||||
** new virtual term that is pTerm converted from an OR operator
|
||||
** into an IN operator.
|
||||
**
|
||||
** During construction, verify that the collating sequences on all
|
||||
** subterms of the OR are compatible. Omit the construction of the
|
||||
** new IN operator if there are any collating sequence mismatches.
|
||||
*/
|
||||
if( okToChngToIN ){
|
||||
Expr *pDup; /* A transient duplicate expression */
|
||||
ExprList *pList = 0; /* The RHS of the IN operator */
|
||||
Expr *pLeft = 0; /* The LHS of the IN operator */
|
||||
CollSeq *pCollSeq = 0; /* Collating sequence to use */
|
||||
Expr *pNew; /* The complete IN operator */
|
||||
|
||||
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
|
||||
Expr *pThis;
|
||||
if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
|
||||
assert( pOrTerm->eOperator & WO_EQ );
|
||||
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
|
||||
assert( pOrTerm->leftCursor==iCursor );
|
||||
assert( pOrTerm->u.x.leftColumn==iColumn );
|
||||
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
|
||||
pThis = pOrTerm->pExpr;
|
||||
pDup = sqlite3ExprDup(db, pThis->pRight, 0);
|
||||
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
|
||||
pLeft = pOrTerm->pExpr->pLeft;
|
||||
if( pLeft==0 ){
|
||||
pLeft = pThis->pLeft;
|
||||
pCollSeq = sqlite3ExprCompareCollSeq(pParse, pThis);
|
||||
}else{
|
||||
assert( 0==sqlite3ExprCompare(pParse, pThis->pLeft, pLeft, -1) );
|
||||
if( pCollSeq!=sqlite3ExprCompareCollSeq(pParse, pThis) ){
|
||||
pLeft = 0; /* Collating sequence mismatch */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pLeft==0 ){
|
||||
pNew = 0; /* Collating sequence mismatch */
|
||||
}else{
|
||||
pDup = sqlite3ExprDup(db, pLeft, 0);
|
||||
if( sqlite3ExprCollSeq(pParse, pDup)!=pCollSeq
|
||||
&& ALWAYS(pCollSeq!=0)
|
||||
){
|
||||
assert( pCollSeq->zName!=0 );
|
||||
pDup = sqlite3ExprAddCollateString(pParse, pDup, pCollSeq->zName);
|
||||
}
|
||||
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
|
||||
}
|
||||
assert( pLeft!=0 );
|
||||
pDup = sqlite3ExprDup(db, pLeft, 0);
|
||||
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
|
||||
if( pNew ){
|
||||
int idxNew;
|
||||
transferJoinMarkings(pNew, pExpr);
|
||||
@@ -954,7 +984,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
|
||||
** 6. Both operands use the same collating sequence
|
||||
** 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
|
||||
@@ -964,7 +995,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
||||
char aff1, aff2;
|
||||
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
|
||||
@@ -1291,6 +1322,7 @@ static void exprAnalyze(
|
||||
pList = pExpr->x.pList;
|
||||
assert( pList!=0 );
|
||||
assert( pList->nExpr==2 );
|
||||
assert( pWC->a[idxTerm].nChild==0 );
|
||||
for(i=0; i<2; i++){
|
||||
Expr *pNewExpr;
|
||||
int idxNew;
|
||||
@@ -1501,8 +1533,11 @@ static void exprAnalyze(
|
||||
&& pExpr->x.pSelect->pWin==0
|
||||
#endif
|
||||
&& pWC->op==TK_AND
|
||||
&& pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild)
|
||||
/* ^-- See bug 2026-06-04T10:00:49Z */
|
||||
){
|
||||
int i;
|
||||
assert( pTerm->nChild==0 );
|
||||
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
|
||||
int idxNew;
|
||||
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
|
||||
|
||||
+1
-1
@@ -222,7 +222,7 @@ static void nth_valueStepFunc(
|
||||
break;
|
||||
case SQLITE_FLOAT: {
|
||||
double fVal = sqlite3_value_double(apArg[1]);
|
||||
if( ((i64)fVal)!=fVal ) goto error_out;
|
||||
if( sqlite3RealToI64(fVal)!=fVal ) goto error_out;
|
||||
iVal = (i64)fVal;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -275,5 +275,15 @@ for {set ii 0} {$ii < 20} {incr ii} {
|
||||
} [list abcd $T]
|
||||
}
|
||||
|
||||
# Bug 2026-06-14T15:22:47Z
|
||||
#
|
||||
reset_db
|
||||
load_static_extension db csv
|
||||
do_catchsql_test 8.1 {
|
||||
CREATE VIRTUAL TABLE abc USING csv(
|
||||
data='1,2,3,4,5,6',
|
||||
columns=32768
|
||||
);
|
||||
} {1 {column= value too big, max 2000}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -206,6 +206,36 @@ do_execsql_test 6130 {
|
||||
SELECT printf('%.8e',ieee754_from_blob(x'ffefffffffffffff'));
|
||||
} {-1.79769313e+308}
|
||||
|
||||
# Bug 2026-06-15T03:49:42Z
|
||||
#
|
||||
do_execsql_test 7000 {
|
||||
SELECT decimal('999999999999999', 1);
|
||||
} {1000000000000000}
|
||||
# 999999999999999
|
||||
do_execsql_test 7010 {
|
||||
SELECT decimal('999999999999999', 2);
|
||||
} {1000000000000000}
|
||||
do_execsql_test 7020 {
|
||||
SELECT decimal('999999999999999', 14);
|
||||
} {1000000000000000}
|
||||
do_execsql_test 7030 {
|
||||
SELECT decimal('999999999999999', 15);
|
||||
} {999999999999999}
|
||||
do_execsql_test 7040 {
|
||||
SELECT decimal('899999999999999', 1);
|
||||
} {900000000000000}
|
||||
do_execsql_test 7050 {
|
||||
SELECT decimal('899999999999999', 14);
|
||||
} {900000000000000}
|
||||
do_execsql_test 7060 {
|
||||
SELECT decimal('899999999999999', 15);
|
||||
} {899999999999999}
|
||||
do_execsql_test 7070 {
|
||||
SELECT decimal('989999999999999', 14);
|
||||
} {990000000000000}
|
||||
do_execsql_test 7080 {
|
||||
SELECT decimal('998999999999999', 14);
|
||||
} {999000000000000}
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -2982,14 +2982,14 @@ if {[clang_sanitize_address]==0} {
|
||||
} {0 0}
|
||||
do_test e_fkey-63.1.2 {
|
||||
test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
} {1 {triggers nested too deep}}
|
||||
do_test e_fkey-63.1.3 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
|
||||
test_on_delete_recursion 5
|
||||
} {0 0}
|
||||
do_test e_fkey-63.1.4 {
|
||||
test_on_delete_recursion 6
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
} {1 {triggers nested too deep}}
|
||||
do_test e_fkey-63.1.5 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
|
||||
} {5}
|
||||
@@ -2998,14 +2998,14 @@ if {[clang_sanitize_address]==0} {
|
||||
} {0 0}
|
||||
do_test e_fkey-63.2.2 {
|
||||
test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
} {1 {triggers nested too deep}}
|
||||
do_test e_fkey-63.2.3 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
|
||||
test_on_update_recursion 5
|
||||
} {0 0}
|
||||
do_test e_fkey-63.2.4 {
|
||||
test_on_update_recursion 6
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
} {1 {triggers nested too deep}}
|
||||
do_test e_fkey-63.2.5 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
|
||||
} {5}
|
||||
|
||||
+38
-1
@@ -64,7 +64,6 @@ do_execsql_test 2.1 {
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
breakpoint
|
||||
do_catchsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE main.Table0 USING fts3();
|
||||
INSERT INTO Table0 VALUES (1), (printf('%8.1280000X') ), (1), (printf('%8.1280000X') ), (1) ;
|
||||
@@ -75,5 +74,43 @@ do_catchsql_test 3.0 {
|
||||
INSERT INTO Table0(Table0) VALUES('merge=6,8');
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts4(c);
|
||||
INSERT INTO t(t) VALUES('nodesize=200');
|
||||
INSERT INTO t VALUES('alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november');
|
||||
INSERT INTO t VALUES('oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu alpha bravo');
|
||||
INSERT INTO t(t) VALUES('merge=16,4');
|
||||
UPDATE t_segdir SET end_block = start_block + 2147483647 WHERE level=0;
|
||||
INSERT OR REPLACE INTO t_segments(blockid,block)
|
||||
SELECT start_block+2147483647, NULL FROM t_segdir WHERE level=0;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
INSERT INTO t VALUES(
|
||||
'mike november oscar papa quebec romeo
|
||||
sierra tango uniform victor whiskey xray yankee'
|
||||
);
|
||||
INSERT INTO t VALUES(
|
||||
'charlie delta echo foxtrot golf hotel india
|
||||
juliet kilo lima mike november oscar papa'
|
||||
);
|
||||
INSERT INTO t(t) VALUES('merge=16,4');
|
||||
SELECT blockid FROM t_segments ORDER BY blockid;
|
||||
} {
|
||||
2147483647 2147483648 2147483649 2147483775
|
||||
}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
|
||||
set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -277,4 +277,100 @@ 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}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts3(x);
|
||||
INSERT INTO t_segdir(level,idx,start_block,leaves_end_block,end_block,root)
|
||||
VALUES(1,0,0,0,'0 -9223372036854775808',x'00');
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
INSERT INTO t(x) VALUES('alpha');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts4(x);
|
||||
INSERT INTO t_content(docid,c0x) VALUES(1,'a b');
|
||||
DELETE FROM t_segments;
|
||||
DELETE FROM t_segdir;
|
||||
INSERT INTO t_segdir(level,idx,start_block,leaves_end_block,end_block,root)
|
||||
VALUES(0,0,0,0,0,x'000161110150028001500a818080800103038101000001622c010281008101ffffffffffffffffff010204ffffffffffffffffff01ffffffffffffffffff01c80109323200');
|
||||
}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
SELECT count(*) FROM t WHERE t MATCH 'a NEAR/100 b';
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-2
@@ -172,11 +172,11 @@ static struct GlobalVars {
|
||||
extern int sqlite3_vt02_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_randomjson_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_series_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_analyze_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_base64_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_base85_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_completion_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_decimal_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_diskused_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_ieee_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_regexp_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_shathree_init(sqlite3*,char**,void*);
|
||||
@@ -1394,11 +1394,11 @@ int runCombinedDbSqlInput(
|
||||
/* Activate extensions */
|
||||
sqlite3_randomjson_init(cx.db, 0, 0);
|
||||
sqlite3_series_init(cx.db, 0, 0);
|
||||
sqlite3_analyze_init(cx.db, 0, 0);
|
||||
sqlite3_base64_init(cx.db, 0, 0);
|
||||
sqlite3_base85_init(cx.db, 0, 0);
|
||||
sqlite3_completion_init(cx.db, 0, 0);
|
||||
sqlite3_decimal_init(cx.db, 0, 0);
|
||||
sqlite3_diskused_init(cx.db, 0, 0);
|
||||
sqlite3_ieee_init(cx.db, 0, 0);
|
||||
sqlite3_regexp_init(cx.db, 0, 0);
|
||||
sqlite3_shathree_init(cx.db, 0, 0);
|
||||
|
||||
+18
-1
@@ -141,7 +141,7 @@ ifcapable icu {
|
||||
do_catchsql_test icu-5.5 {SELECT 'abc' REGEXP } {1 {incomplete input}}
|
||||
do_catchsql_test icu-5.6 {SELECT 'abc' REGEXP, 1} {1 {near ",": syntax error}}
|
||||
|
||||
do_malloc_test icu-6.10 -sqlbody {
|
||||
do_malloc_test icu-5.10 -sqlbody {
|
||||
SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
|
||||
}
|
||||
}
|
||||
@@ -180,4 +180,21 @@ do_execsql_test icu-7.3 {
|
||||
SELECT char(0x100)=='a', char(0x100)=='a' COLLATE dflt, char(0x100)=='a' COLLATE prim;
|
||||
} {0 0 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test icu-8.1 {
|
||||
CREATE TABLE t1(x TEXT);
|
||||
INSERT INTO t1 VALUES('abcdefg');
|
||||
INSERT INTO t1 VALUES('1234567');
|
||||
}
|
||||
|
||||
do_execsql_test icu-8.2 {
|
||||
SELECT * FROM t1 WHERE x LIKE CAST(x'C0A5' AS TEXT);
|
||||
} {}
|
||||
|
||||
do_execsql_test icu-8.3 {
|
||||
SELECT * FROM t1 WHERE x LIKE CAST(x'C19F' AS TEXT) || 'bcdefg';
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+7
-7
@@ -119,12 +119,12 @@ END
|
||||
.testcase 141
|
||||
SELECT sql FROM sqlite_schema WHERE name='t1';
|
||||
.check <<END
|
||||
╭───────────────────────────────────╮
|
||||
│ sql │
|
||||
╞═══════════════════════════════════╡
|
||||
│ CREATE TABLE "t1"( │
|
||||
│ "abc" ANY, "def" ANY, "xy z" ANY) │
|
||||
╰───────────────────────────────────╯
|
||||
╭───────────────────────╮
|
||||
│ sql │
|
||||
╞═══════════════════════╡
|
||||
│ CREATE TABLE "t1"( │
|
||||
│ "abc", "def", "xy z") │
|
||||
╰───────────────────────╯
|
||||
END
|
||||
|
||||
.testcase 150
|
||||
@@ -138,7 +138,7 @@ SELECT * FROM t1;
|
||||
.check <<END
|
||||
Column separator ",", row separator "\n"
|
||||
CREATE TABLE "main"."t1"(
|
||||
"abc" ANY, "def" ANY, "xy z" ANY)
|
||||
"abc", "def", "xy z")
|
||||
|
||||
Added 2 rows with 0 errors using 3 lines of input
|
||||
╭──────┬─────┬──────╮
|
||||
|
||||
@@ -686,4 +686,24 @@ do_execsql_test indexexpr1-2300 {
|
||||
SELECT json_insert('{}', '$.a', json(y)) FROM t1;
|
||||
} {{{"a":{"b":5}}}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
proc addone {n} {
|
||||
return $n+1
|
||||
}
|
||||
db func addone addone
|
||||
|
||||
do_execsql_test indexexpr1-2400 {
|
||||
CREATE TABLE t1(x, y);
|
||||
}
|
||||
do_catchsql_test indexexpr1-2310 {
|
||||
CREATE INDEX i1 ON t1( (addone(x)) );
|
||||
} {1 {non-deterministic functions prohibited in index expressions}}
|
||||
do_catchsql_test indexexpr1-2310 {
|
||||
CREATE INDEX i2 ON t1( ~(addone(x)) );
|
||||
} {1 {non-deterministic functions prohibited in index expressions}}
|
||||
do_catchsql_test indexexpr1-2310 {
|
||||
CREATE INDEX i2 ON t1( ~(addone(DISTINCT x)) );
|
||||
} {1 {non-deterministic functions prohibited in index expressions}}
|
||||
|
||||
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
|
||||
|
||||
@@ -336,7 +336,44 @@ 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 {} {} |}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
foreach {tn idx} {
|
||||
1 {}
|
||||
2 { CREATE INDEX i1 ON t1(a, b) }
|
||||
3 { CREATE INDEX i1 ON t1(b, a) }
|
||||
} {
|
||||
reset_db
|
||||
|
||||
do_execsql_test 11.$tn.1 {
|
||||
CREATE TABLE t1(a TEXT COLLATE NOCASE, b TEXT);
|
||||
INSERT INTO t1 VALUES('Hello', 'world');
|
||||
}
|
||||
|
||||
do_execsql_test 11.$tn.2 $idx
|
||||
|
||||
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.$tn.3.$tn $sql $res
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# 2026 June 4
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix nulls2
|
||||
|
||||
foreach {tn idx} {
|
||||
1 {}
|
||||
2 { CREATE INDEX i1 ON t1(a, b, c) }
|
||||
3 { CREATE INDEX i1 ON t1(b, c, a) }
|
||||
4 { CREATE INDEX i1 ON t1(c, a, b) }
|
||||
5 { CREATE INDEX i1 ON t1(c, b, a) }
|
||||
} {
|
||||
reset_db
|
||||
|
||||
do_execsql_test 1.$tn.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
|
||||
INSERT INTO t1 VALUES(1, 1, NULL);
|
||||
INSERT INTO t1 VALUES(2, 2, NULL);
|
||||
|
||||
CREATE TABLE t2(d NOT NULL, e NOT NULL, f);
|
||||
INSERT INTO t2 VALUES(1, 1, NULL);
|
||||
INSERT INTO t2 VALUES(2, 2, NULL);
|
||||
}
|
||||
|
||||
execsql $idx
|
||||
|
||||
# This should return zero rows, as "f" is always NULL.
|
||||
#
|
||||
do_execsql_test 1.$tn.1 {
|
||||
SELECT rowid FROM t2 WHERE (d, e, f) IN (
|
||||
SELECT a, b, c FROM t1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
foreach {tn idx} {
|
||||
1 {}
|
||||
2 { CREATE INDEX i1 ON t1(a, b, c) }
|
||||
3 { CREATE INDEX i1 ON t1(b, c, a) }
|
||||
4 { CREATE INDEX i1 ON t1(c, a, b) }
|
||||
5 { CREATE INDEX i1 ON t1(c, b, a) }
|
||||
} {
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.$tn.0 {
|
||||
CREATE TABLE t1(a, b, c COLLATE nocase);
|
||||
INSERT INTO t1 VALUES('one', 'two', 'THREE');
|
||||
INSERT INTO t1 VALUES('four', 'five', 'SIX');
|
||||
}
|
||||
|
||||
execsql $idx
|
||||
|
||||
do_execsql_test 1.$tn.1 {
|
||||
SELECT (NULL, 'two', 'three') IN (
|
||||
SELECT a, b, c FROM t1
|
||||
) IS NULL
|
||||
} 1
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -71,6 +71,25 @@ do_test pcache2-1.4 {
|
||||
sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0
|
||||
} {0 13 13}
|
||||
|
||||
# Check that a small (1KB) bulk cache allocation is handled.
|
||||
#
|
||||
do_test pcache2-2.1 {
|
||||
catch {db2 close}
|
||||
db close
|
||||
sqlite3_reset_auto_extension
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache 0 -1
|
||||
sqlite3_config singlethread
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
} {0}
|
||||
|
||||
reset_db
|
||||
do_execsql_test pcache2-2.2 {
|
||||
PRAGMA page_size = 4096;
|
||||
CREATE TABLE t1(x);
|
||||
}
|
||||
|
||||
db close
|
||||
catch {db2 close}
|
||||
sqlite3_reset_auto_extension
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -142,6 +142,7 @@ set allquicktests [test_set $alltests -exclude {
|
||||
|
||||
writecrash.test view3.test
|
||||
fts5dlidx.test fts5ac.test fts4merge3.test fts5prefix.test
|
||||
fts5bigtok2.test
|
||||
sessionB.test
|
||||
}]
|
||||
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user