Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ba2a38363 | |||
| bb80d688ac | |||
| fe57e14b49 | |||
| 18f99f43bc | |||
| f6c8adf3a2 | |||
| 72afb50a6d | |||
| 7fa89ea907 | |||
| c1454ee833 | |||
| ea6b2a87d1 | |||
| f270460366 | |||
| 33478099c9 | |||
| 93ad2e083e | |||
| ffaf9110f6 | |||
| 7e4e866baf | |||
| e293b2d835 | |||
| 83de60bd7b | |||
| a000db9754 | |||
| 7ac310d0c6 | |||
| afaf7ea2e4 | |||
| f707e2ec5d | |||
| 7d9fbe6476 | |||
| c67a538168 | |||
| 57d7a20ce7 | |||
| d22d0edc48 | |||
| 5dfccfb0bb | |||
| 5a6eef2fb2 | |||
| 8bc78bebfb | |||
| a86c6017e7 | |||
| 1a152ea92a | |||
| f45c695471 | |||
| 46bf39e396 | |||
| b1a73ba34d | |||
| 9d65290207 | |||
| da67225f04 | |||
| d2e27e5d54 | |||
| ffd9892a02 | |||
| 9235f9b049 | |||
| 9dac613f04 | |||
| 95fe5b9c38 | |||
| 9bc017423c | |||
| 60f132bf12 | |||
| f8681fb638 | |||
| 283f33233b | |||
| 8642ca2025 | |||
| 699959ff25 | |||
| 7aba858597 | |||
| 4428aa842c | |||
| 24ef9fbb19 | |||
| aec283385e | |||
| ac5ee556eb | |||
| 62546d4b1f | |||
| 9e395efec6 | |||
| d447df4205 | |||
| 20c65785cd | |||
| e8750019c2 | |||
| cac09127e1 | |||
| 37ee141d25 | |||
| 7549e784a8 | |||
| 8c3e8dce41 | |||
| 31d4e56b29 | |||
| 530f536ce7 | |||
| eb8c4c5742 | |||
| 0b5e944480 | |||
| 63338e3ba8 | |||
| 6315919ba8 | |||
| 5c977eaa0a | |||
| 1105c33900 | |||
| 7b93f1a387 | |||
| c47bc0ffca | |||
| 990d861038 | |||
| 23e57bc7cd | |||
| 7d49eb1dff | |||
| df59c5da78 |
@@ -2660,23 +2660,6 @@ sqltclsh.exe: sqltclsh.c $(SHELL_CORE_DEP) $(LIBRESOBJS)
|
||||
sqlite3_expert.exe: $(SQLITE3C) $(TOP)\ext\expert\sqlite3expert.h $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c $(SQLITE3C) $(TLIBS)
|
||||
|
||||
CHECKER_DEPS =\
|
||||
$(TOP)\tool\mkccode.tcl \
|
||||
sqlite3.c \
|
||||
tclsqlite-ex.c \
|
||||
$(TOP)\ext\repair\sqlite3_checker.tcl \
|
||||
$(TOP)\ext\repair\checkindex.c \
|
||||
$(TOP)\ext\repair\checkfreelist.c \
|
||||
$(TOP)\ext\misc\btreeinfo.c \
|
||||
$(TOP)\ext\repair\sqlite3_checker.c.in
|
||||
|
||||
sqlite3_checker.c: $(CHECKER_DEPS)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
|
||||
|
||||
sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
|
||||
|
||||
+1
-1
@@ -455,7 +455,7 @@ static void fts5SnippetFunction(
|
||||
|
||||
iBestCol = (iCol>=0 ? iCol : 0);
|
||||
nPhrase = pApi->xPhraseCount(pFts);
|
||||
aSeen = sqlite3_malloc(nPhrase);
|
||||
aSeen = sqlite3_malloc64(nPhrase);
|
||||
if( aSeen==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
|
||||
if( nIn<0 ){
|
||||
nIn = (int)strlen(pIn);
|
||||
}
|
||||
zRet = (char*)sqlite3_malloc(nIn+1);
|
||||
zRet = (char*)sqlite3_malloc64((i64)nIn+1);
|
||||
if( zRet ){
|
||||
memcpy(zRet, pIn, nIn);
|
||||
zRet[nIn] = '\0';
|
||||
|
||||
@@ -576,7 +576,7 @@ int sqlite3Fts5ConfigParse(
|
||||
sqlite3_int64 nByte;
|
||||
int bUnindexed = 0; /* True if there are one or more UNINDEXED */
|
||||
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc64(sizeof(Fts5Config));
|
||||
if( pRet==0 ) return SQLITE_NOMEM;
|
||||
memset(pRet, 0, sizeof(Fts5Config));
|
||||
pRet->pGlobal = pGlobal;
|
||||
@@ -1123,5 +1123,3 @@ void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ int sqlite3Fts5ExprNew(
|
||||
|
||||
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
|
||||
if( sParse.rc==SQLITE_OK ){
|
||||
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
|
||||
*ppNew = pNew = sqlite3_malloc64(sizeof(Fts5Expr));
|
||||
if( pNew==0 ){
|
||||
sParse.rc = SQLITE_NOMEM;
|
||||
sqlite3Fts5ParseNodeFree(sParse.pExpr);
|
||||
@@ -466,7 +466,7 @@ int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
|
||||
p2->pRoot = 0;
|
||||
|
||||
if( sParse.rc==SQLITE_OK ){
|
||||
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
|
||||
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc64(
|
||||
p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
|
||||
);
|
||||
if( ap==0 ){
|
||||
|
||||
@@ -91,7 +91,7 @@ int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
|
||||
int rc = SQLITE_OK;
|
||||
Fts5Hash *pNew;
|
||||
|
||||
*ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
|
||||
*ppNew = pNew = (Fts5Hash*)sqlite3_malloc64(sizeof(Fts5Hash));
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
||||
+15
-14
@@ -2093,7 +2093,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||
|
||||
/* If necessary, grow the pIter->aRowidOffset[] array. */
|
||||
if( iRowidOffset>=pIter->nRowidOffset ){
|
||||
int nNew = pIter->nRowidOffset + 8;
|
||||
i64 nNew = pIter->nRowidOffset + 8;
|
||||
int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
|
||||
if( aNew==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
@@ -6418,16 +6418,16 @@ struct Fts5TokenDataMap {
|
||||
** aMap[] variables.
|
||||
*/
|
||||
struct Fts5TokenDataIter {
|
||||
int nMapAlloc; /* Allocated size of aMap[] in entries */
|
||||
int nMap; /* Number of valid entries in aMap[] */
|
||||
i64 nMapAlloc; /* Allocated size of aMap[] in entries */
|
||||
i64 nMap; /* Number of valid entries in aMap[] */
|
||||
Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
|
||||
|
||||
/* The following are used for prefix-queries only. */
|
||||
Fts5Buffer terms;
|
||||
|
||||
/* The following are used for other full-token tokendata queries only. */
|
||||
int nIter;
|
||||
int nIterAlloc;
|
||||
i64 nIter;
|
||||
i64 nIterAlloc;
|
||||
Fts5PoslistReader *aPoslistReader;
|
||||
int *aPoslistToIter;
|
||||
Fts5Iter *apIter[FLEXARRAY];
|
||||
@@ -6483,11 +6483,11 @@ static void fts5TokendataIterAppendMap(
|
||||
){
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( pT->nMap==pT->nMapAlloc ){
|
||||
int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
|
||||
int nAlloc = nNew * sizeof(Fts5TokenDataMap);
|
||||
i64 nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
|
||||
i64 nAlloc = nNew * sizeof(Fts5TokenDataMap);
|
||||
Fts5TokenDataMap *aNew;
|
||||
|
||||
aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
|
||||
aNew = (Fts5TokenDataMap*)sqlite3_realloc64(pT->aMap, nAlloc);
|
||||
if( aNew==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
return;
|
||||
@@ -6513,7 +6513,7 @@ static void fts5TokendataIterAppendMap(
|
||||
*/
|
||||
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
|
||||
Fts5TokenDataMap *aTmp = 0;
|
||||
int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
|
||||
i64 nByte = pT->nMap * sizeof(Fts5TokenDataMap);
|
||||
|
||||
aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
if( aTmp ){
|
||||
@@ -7047,9 +7047,10 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
|
||||
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
|
||||
int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
|
||||
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
|
||||
i64 nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
|
||||
i64 nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
|
||||
Fts5TokenDataIter *pNew;
|
||||
pNew = (Fts5TokenDataIter*)sqlite3_realloc64(pIn, nByte);
|
||||
|
||||
if( pNew==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
@@ -7146,8 +7147,8 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
|
||||
|
||||
/* Ensure the token-mapping is large enough */
|
||||
if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){
|
||||
int nNew = (pT->nMapAlloc + nByte) * 2;
|
||||
Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc(
|
||||
i64 nNew = (pT->nMapAlloc + nByte) * 2;
|
||||
Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc64(
|
||||
pT->aMap, nNew*sizeof(Fts5TokenDataMap)
|
||||
);
|
||||
if( aNew==0 ){
|
||||
|
||||
@@ -631,7 +631,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
|
||||
idxStr = (char*)sqlite3_malloc64((i64)pInfo->nConstraint * 8 + 1);
|
||||
if( idxStr==0 ) return SQLITE_NOMEM;
|
||||
pInfo->idxStr = idxStr;
|
||||
pInfo->needToFreeIdxStr = 1;
|
||||
@@ -3763,7 +3763,7 @@ static int fts5Init(sqlite3 *db){
|
||||
int rc;
|
||||
Fts5Global *pGlobal = 0;
|
||||
|
||||
pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
|
||||
pGlobal = (Fts5Global*)sqlite3_malloc64(sizeof(Fts5Global));
|
||||
if( pGlobal==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
||||
+4
-4
@@ -391,7 +391,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
break;
|
||||
}
|
||||
CASE(12, "xSetAuxdata") {
|
||||
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
|
||||
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc64(sizeof(F5tAuxData));
|
||||
if( pData==0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", (char*)0);
|
||||
return TCL_ERROR;
|
||||
@@ -780,7 +780,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
}
|
||||
|
||||
if( nText>0 ){
|
||||
pCopy = sqlite3_malloc(nText);
|
||||
pCopy = sqlite3_malloc64(nText);
|
||||
if( pCopy==0 ){
|
||||
tokenizer.xDelete(pTok);
|
||||
Tcl_AppendResult(interp, "error in sqlite3_malloc()", (char*)0);
|
||||
@@ -1420,7 +1420,7 @@ static int f5tOrigintextCreate(
|
||||
void *pTokCtx = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pTok = (OriginTextTokenizer*)sqlite3_malloc(sizeof(OriginTextTokenizer));
|
||||
pTok = (OriginTextTokenizer*)sqlite3_malloc64(sizeof(OriginTextTokenizer));
|
||||
if( pTok==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( nArg<1 ){
|
||||
@@ -1480,7 +1480,7 @@ static int xOriginToken(
|
||||
int nReq = nToken + 1 + (iEnd-iStart);
|
||||
if( nReq>p->nBuf ){
|
||||
sqlite3_free(p->aBuf);
|
||||
p->aBuf = sqlite3_malloc(nReq*2);
|
||||
p->aBuf = sqlite3_malloc64(nReq*2);
|
||||
if( p->aBuf==0 ) return SQLITE_NOMEM;
|
||||
p->nBuf = nReq*2;
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ static int fts5tokConnectMethod(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pTab = (Fts5tokTable*)sqlite3_malloc(sizeof(Fts5tokTable));
|
||||
pTab = (Fts5tokTable*)sqlite3_malloc64(sizeof(Fts5tokTable));
|
||||
if( pTab==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -275,7 +275,7 @@ static int fts5tokBestIndexMethod(
|
||||
static int fts5tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
|
||||
Fts5tokCursor *pCsr;
|
||||
|
||||
pCsr = (Fts5tokCursor *)sqlite3_malloc(sizeof(Fts5tokCursor));
|
||||
pCsr = (Fts5tokCursor *)sqlite3_malloc64(sizeof(Fts5tokCursor));
|
||||
if( pCsr==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -347,7 +347,7 @@ static int fts5tokCb(
|
||||
if( pCsr->nRow ){
|
||||
pRow->iPos = pRow[-1].iPos + ((tflags & FTS5_TOKEN_COLOCATED) ? 0 : 1);
|
||||
}
|
||||
pRow->zToken = sqlite3_malloc(nToken+1);
|
||||
pRow->zToken = sqlite3_malloc64((sqlite3_int64)nToken+1);
|
||||
if( pRow->zToken==0 ) return SQLITE_NOMEM;
|
||||
memcpy(pRow->zToken, pToken, nToken);
|
||||
pRow->zToken[nToken] = 0;
|
||||
@@ -373,8 +373,8 @@ static int fts5tokFilterMethod(
|
||||
fts5tokResetCursor(pCsr);
|
||||
if( idxNum==1 ){
|
||||
const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
|
||||
int nByte = sqlite3_value_bytes(apVal[0]);
|
||||
pCsr->zInput = sqlite3_malloc(nByte+1);
|
||||
sqlite3_int64 nByte = sqlite3_value_bytes(apVal[0]);
|
||||
pCsr->zInput = sqlite3_malloc64(nByte+1);
|
||||
if( pCsr->zInput==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
||||
@@ -72,7 +72,7 @@ static int fts5AsciiCreate(
|
||||
if( nArg%2 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p = sqlite3_malloc(sizeof(AsciiTokenizer));
|
||||
p = sqlite3_malloc64(sizeof(AsciiTokenizer));
|
||||
if( p==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -367,7 +367,7 @@ static int fts5UnicodeCreate(
|
||||
if( nArg%2 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer));
|
||||
p = (Unicode61Tokenizer*)sqlite3_malloc64(sizeof(Unicode61Tokenizer));
|
||||
if( p ){
|
||||
const char *zCat = "L* N* Co";
|
||||
int i;
|
||||
@@ -590,7 +590,7 @@ static int fts5PorterCreate(
|
||||
zBase = azArg[0];
|
||||
}
|
||||
|
||||
pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer));
|
||||
pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
|
||||
if( pRet ){
|
||||
memset(pRet, 0, sizeof(PorterTokenizer));
|
||||
rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2);
|
||||
@@ -1297,7 +1297,7 @@ static int fts5TriCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int i;
|
||||
pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
|
||||
pNew = (TrigramTokenizer*)sqlite3_malloc64(sizeof(*pNew));
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
||||
@@ -666,7 +666,7 @@ static int fts5VocabFilterMethod(
|
||||
const char *zCopy = (const char *)sqlite3_value_text(pLe);
|
||||
if( zCopy==0 ) zCopy = "";
|
||||
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
|
||||
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
|
||||
pCsr->zLeTerm = sqlite3_malloc64((i64)pCsr->nLeTerm+1);
|
||||
if( pCsr->zLeTerm==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
|
||||
@@ -379,9 +379,6 @@ do_execsql_test 12.2 {
|
||||
db close
|
||||
sqlite3 db test.db -readonly 1
|
||||
|
||||
explain_i {
|
||||
PRAGMA integrity_check
|
||||
}
|
||||
do_execsql_test 12.3 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
@@ -319,7 +319,7 @@ static int intckGetToken(const char *z){
|
||||
char c = z[0];
|
||||
int iRet = 1;
|
||||
if( c=='\'' || c=='"' || c=='`' ){
|
||||
while( 1 ){
|
||||
while( z[iRet] ){
|
||||
if( z[iRet]==c ){
|
||||
iRet++;
|
||||
if( z[iRet]!=c ) break;
|
||||
|
||||
+38
-5
@@ -291,12 +291,36 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
|
||||
sqlite3_result_text(pCtx, z, i, sqlite3_free);
|
||||
}
|
||||
|
||||
/*
|
||||
** Round a decimal value to N significant digits. N must be positive.
|
||||
*/
|
||||
static void decimal_round(Decimal *p, int N){
|
||||
int i;
|
||||
int nZero;
|
||||
if( N<1 ) return;
|
||||
for(nZero=0; nZero<p->nDigit && p->a[nZero]==0; nZero++){}
|
||||
N += nZero;
|
||||
if( p->nDigit<=N ) return;
|
||||
if( p->a[N]>4 ){
|
||||
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--;
|
||||
}
|
||||
}
|
||||
memset(&p->a[N], 0, p->nDigit - N);
|
||||
}
|
||||
|
||||
/*
|
||||
** Make the given Decimal the result in an format similar to '%+#e'.
|
||||
** In other words, show exponential notation with leading and trailing
|
||||
** zeros omitted.
|
||||
*/
|
||||
static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
|
||||
static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p, int N){
|
||||
char *z; /* The output buffer */
|
||||
int i; /* Loop counter */
|
||||
int nZero; /* Number of leading zeros */
|
||||
@@ -314,7 +338,8 @@ static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
|
||||
sqlite3_result_null(pCtx);
|
||||
return;
|
||||
}
|
||||
for(nDigit=p->nDigit; nDigit>0 && p->a[nDigit-1]==0; nDigit--){}
|
||||
if( N<1 ) N = 0;
|
||||
for(nDigit=p->nDigit; nDigit>N && p->a[nDigit-1]==0; nDigit--){}
|
||||
for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
|
||||
nFrac = p->nFrac + (nDigit - p->nDigit);
|
||||
nDigit -= nZero;
|
||||
@@ -677,10 +702,16 @@ static void decimalFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
Decimal *p = decimal_new(context, argv[0], 0);
|
||||
UNUSED_PARAMETER(argc);
|
||||
int N;
|
||||
if( argc==2 ){
|
||||
N = sqlite3_value_int(argv[1]);
|
||||
if( N>0 ) decimal_round(p, N);
|
||||
}else{
|
||||
N = 0;
|
||||
}
|
||||
if( p ){
|
||||
if( sqlite3_user_data(context)!=0 ){
|
||||
decimal_result_sci(context, p);
|
||||
decimal_result_sci(context, p, N);
|
||||
}else{
|
||||
decimal_result(context, p);
|
||||
}
|
||||
@@ -850,7 +881,7 @@ static void decimalPow2Func(
|
||||
UNUSED_PARAMETER(argc);
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
|
||||
Decimal *pA = decimalPow2(sqlite3_value_int(argv[0]));
|
||||
decimal_result_sci(context, pA);
|
||||
decimal_result_sci(context, pA, 0);
|
||||
decimal_free(pA);
|
||||
}
|
||||
}
|
||||
@@ -871,7 +902,9 @@ int sqlite3_decimal_init(
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
} aFunc[] = {
|
||||
{ "decimal", 1, 0, decimalFunc },
|
||||
{ "decimal", 2, 0, decimalFunc },
|
||||
{ "decimal_exp", 1, 1, decimalFunc },
|
||||
{ "decimal_exp", 2, 1, decimalFunc },
|
||||
{ "decimal_cmp", 2, 0, decimalCmpFunc },
|
||||
{ "decimal_add", 2, 0, decimalAddFunc },
|
||||
{ "decimal_sub", 2, 0, decimalSubFunc },
|
||||
|
||||
+173
-57
@@ -94,12 +94,16 @@ SQLITE_EXTENSION_INIT1
|
||||
# include <utime.h>
|
||||
# include <sys/time.h>
|
||||
# define STRUCT_STAT struct stat
|
||||
# include <limits.h>
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "windirent.h"
|
||||
# include <direct.h>
|
||||
# define STRUCT_STAT struct _stat
|
||||
# define chmod(path,mode) fileio_chmod(path,mode)
|
||||
# define mkdir(path,mode) fileio_mkdir(path)
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
@@ -131,12 +135,9 @@ SQLITE_EXTENSION_INIT1
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
static int fileio_chmod(const char *zPath, int pmode){
|
||||
sqlite3_int64 sz = strlen(zPath);
|
||||
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
if( b1==0 ) return -1;
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
|
||||
b1[sz] = 0;
|
||||
rc = _wchmod(b1, pmode);
|
||||
sqlite3_free(b1);
|
||||
return rc;
|
||||
@@ -148,12 +149,9 @@ static int fileio_chmod(const char *zPath, int pmode){
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
static int fileio_mkdir(const char *zPath){
|
||||
sqlite3_int64 sz = strlen(zPath);
|
||||
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
if( b1==0 ) return -1;
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
|
||||
b1[sz] = 0;
|
||||
rc = _wmkdir(b1);
|
||||
sqlite3_free(b1);
|
||||
return rc;
|
||||
@@ -266,50 +264,7 @@ static sqlite3_uint64 fileTimeToUnixTime(
|
||||
|
||||
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
|
||||
}
|
||||
|
||||
|
||||
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
|
||||
# /* To allow a standalone DLL, use this next replacement function: */
|
||||
# undef sqlite3_win32_utf8_to_unicode
|
||||
# define sqlite3_win32_utf8_to_unicode utf8_to_utf16
|
||||
#
|
||||
LPWSTR utf8_to_utf16(const char *z){
|
||||
int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
|
||||
LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
|
||||
if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
|
||||
return rv;
|
||||
sqlite3_free(rv);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function attempts to normalize the time values found in the stat()
|
||||
** buffer to UTC. This is necessary on Win32, where the runtime library
|
||||
** appears to return these values as local times.
|
||||
*/
|
||||
static void statTimesToUtc(
|
||||
const char *zPath,
|
||||
STRUCT_STAT *pStatBuf
|
||||
){
|
||||
HANDLE hFindFile;
|
||||
WIN32_FIND_DATAW fd;
|
||||
LPWSTR zUnicodeName;
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
if( zUnicodeName ){
|
||||
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
|
||||
hFindFile = FindFirstFileW(zUnicodeName, &fd);
|
||||
if( hFindFile!=NULL ){
|
||||
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
|
||||
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
|
||||
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
|
||||
FindClose(hFindFile);
|
||||
}
|
||||
sqlite3_free(zUnicodeName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
** This function is used in place of stat(). On Windows, special handling
|
||||
@@ -321,14 +276,22 @@ static int fileStat(
|
||||
STRUCT_STAT *pStatBuf
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
sqlite3_int64 sz = strlen(zPath);
|
||||
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
if( b1==0 ) return 1;
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
|
||||
b1[sz] = 0;
|
||||
rc = _wstat(b1, pStatBuf);
|
||||
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
|
||||
if( rc==0 ){
|
||||
HANDLE hFindFile;
|
||||
WIN32_FIND_DATAW fd;
|
||||
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
|
||||
hFindFile = FindFirstFileW(b1, &fd);
|
||||
if( hFindFile!=NULL ){
|
||||
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
|
||||
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
|
||||
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
|
||||
FindClose(hFindFile);
|
||||
}
|
||||
}
|
||||
sqlite3_free(b1);
|
||||
return rc;
|
||||
#else
|
||||
@@ -1093,6 +1056,154 @@ static int fsdirRegister(sqlite3 *db){
|
||||
# define fsdirRegister(x) SQLITE_OK
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This version of realpath() works on any system. The string
|
||||
** returned is held in memory allocated using sqlite3_malloc64().
|
||||
** The caller is responsible for calling sqlite3_free().
|
||||
*/
|
||||
static char *portable_realpath(const char *zPath){
|
||||
#if !defined(_WIN32) /* BEGIN unix */
|
||||
|
||||
char *zOut = 0; /* Result */
|
||||
char *z; /* Temporary buffer */
|
||||
#if defined(PATH_MAX)
|
||||
char zBuf[PATH_MAX+1]; /* Space for the temporary buffer */
|
||||
#endif
|
||||
|
||||
if( zPath==0 ) return 0;
|
||||
#if defined(PATH_MAX)
|
||||
z = realpath(zPath, zBuf);
|
||||
if( z ){
|
||||
zOut = sqlite3_mprintf("%s", zBuf);
|
||||
}
|
||||
#endif /* defined(PATH_MAX) */
|
||||
if( zOut==0 ){
|
||||
/* Try POSIX.1-2008 malloc behavior */
|
||||
z = realpath(zPath, NULL);
|
||||
if( z ){
|
||||
zOut = sqlite3_mprintf("%s", z);
|
||||
free(z);
|
||||
}
|
||||
}
|
||||
return zOut;
|
||||
|
||||
#else /* End UNIX, Begin WINDOWS */
|
||||
|
||||
wchar_t *zPath16; /* UTF16 translation of zPath */
|
||||
char *zOut = 0; /* Result */
|
||||
wchar_t *z = 0; /* Temporary buffer */
|
||||
|
||||
if( zPath==0 ) return 0;
|
||||
|
||||
zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
if( zPath16==0 ) return 0;
|
||||
z = _wfullpath(NULL, zPath16, 0);
|
||||
sqlite3_free(zPath16);
|
||||
if( z ){
|
||||
zOut = sqlite3_win32_unicode_to_utf8(z);
|
||||
free(z);
|
||||
}
|
||||
return zOut;
|
||||
|
||||
#endif /* End WINDOWS, Begin common code */
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL function: realpath(X)
|
||||
**
|
||||
** Try to convert file or pathname X into its real, absolute pathname.
|
||||
** Return NULL if unable.
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
static void realpathFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zPath; /* Original input path */
|
||||
char *zCopy; /* An editable copy of zPath */
|
||||
char *zOut; /* The result */
|
||||
char cSep = 0; /* Separator turned into \000 */
|
||||
size_t len; /* Prefix length before cSep */
|
||||
#ifdef _WIN32
|
||||
const int isWin = 1;
|
||||
#else
|
||||
const int isWin = 0;
|
||||
#endif
|
||||
|
||||
(void)argc;
|
||||
zPath = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zPath==0 ) return;
|
||||
if( zPath[0]==0 ) zPath = ".";
|
||||
zCopy = sqlite3_mprintf("%s",zPath);
|
||||
len = strlen(zCopy);
|
||||
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
|
||||
len--;
|
||||
}
|
||||
zCopy[len] = 0;
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
zOut = portable_realpath(zCopy);
|
||||
zCopy[len] = cSep;
|
||||
if( zOut ){
|
||||
if( cSep ){
|
||||
zOut = sqlite3_mprintf("%z%s",zOut,&zCopy[len]);
|
||||
}
|
||||
break;
|
||||
}else{
|
||||
size_t i = len-1;
|
||||
while( i>0 ){
|
||||
if( zCopy[i]=='/' || (isWin && zCopy[i]=='\\') ) break;
|
||||
i--;
|
||||
}
|
||||
if( i<=0 ){
|
||||
if( zCopy[0]=='/' ){
|
||||
zOut = zCopy;
|
||||
zCopy = 0;
|
||||
}else if( (zOut = portable_realpath("."))!=0 ){
|
||||
zOut = sqlite3_mprintf("%z/%s", zOut, zCopy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
cSep = zCopy[i];
|
||||
zCopy[i] = 0;
|
||||
len = i;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zCopy);
|
||||
if( zOut ){
|
||||
/* Simplify any "/./" or "/../" that might have snuck into the
|
||||
** pathname due to appending of zCopy. We only have to consider
|
||||
** unix "/" separators, because the _wfilepath() system call on
|
||||
** Windows will have already done this simplification for us. */
|
||||
size_t i, j, n;
|
||||
n = strlen(zOut);
|
||||
for(i=j=0; i<n; i++){
|
||||
if( zOut[i]=='/' ){
|
||||
if( zOut[i+1]=='/' ) continue;
|
||||
if( zOut[i+1]=='.' && i+2<n && zOut[i+2]=='/' ){
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if( zOut[i+1]=='.' && i+3<n && zOut[i+2]=='.' && zOut[i+3]=='/' ){
|
||||
while( j>0 && zOut[j-1]!='/' ){ j--; }
|
||||
if( j>0 ){ j--; }
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
zOut[j++] = zOut[i];
|
||||
}
|
||||
zOut[j] = 0;
|
||||
|
||||
/* Return the result */
|
||||
sqlite3_result_text(context, zOut, -1, sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
@@ -1119,5 +1230,10 @@ int sqlite3_fileio_init(
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fsdirRegister(db);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "realpath", 1,
|
||||
SQLITE_UTF8, 0,
|
||||
realpathFunc, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+1
-1
@@ -617,7 +617,7 @@ static int fuzzerRender(
|
||||
int *pnBuf /* Size of the buffer */
|
||||
){
|
||||
const fuzzer_rule *pRule = pStem->pRule;
|
||||
int n; /* Size of output term without nul-term */
|
||||
sqlite3_int64 n; /* Size of output term without nul-term */
|
||||
char *z; /* Buffer to assemble output term in */
|
||||
|
||||
n = pStem->nBasis + pRule->nTo - pRule->nFrom;
|
||||
|
||||
@@ -259,6 +259,38 @@ static void ieee754func_to_blob(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Functions to convert between 64-bit integers and floats.
|
||||
**
|
||||
** The bit patterns are copied. The numeric values are different.
|
||||
*/
|
||||
static void ieee754func_from_int(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAMETER(argc);
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
|
||||
double r;
|
||||
sqlite3_int64 v = sqlite3_value_int64(argv[0]);
|
||||
memcpy(&r, &v, sizeof(r));
|
||||
sqlite3_result_double(context, r);
|
||||
}
|
||||
}
|
||||
static void ieee754func_to_int(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
UNUSED_PARAMETER(argc);
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_FLOAT ){
|
||||
double r = sqlite3_value_double(argv[0]);
|
||||
sqlite3_uint64 v;
|
||||
memcpy(&v, &r, sizeof(v));
|
||||
sqlite3_result_int64(context, v);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL Function: ieee754_inc(r,N)
|
||||
**
|
||||
@@ -311,6 +343,8 @@ int sqlite3_ieee_init(
|
||||
{ "ieee754_exponent", 1, 2, ieee754func },
|
||||
{ "ieee754_to_blob", 1, 0, ieee754func_to_blob },
|
||||
{ "ieee754_from_blob", 1, 0, ieee754func_from_blob },
|
||||
{ "ieee754_to_int", 1, 0, ieee754func_to_int },
|
||||
{ "ieee754_from_int", 1, 0, ieee754func_from_int },
|
||||
{ "ieee754_inc", 2, 0, ieee754inc },
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
@@ -484,6 +484,7 @@ static void tmstmpPutU32(u32 v, unsigned char *a){
|
||||
/* Free a TmstmpLog object */
|
||||
static void tmstmpLogFree(TmstmpLog *pLog){
|
||||
if( pLog==0 ) return;
|
||||
if( pLog->log ) fclose(pLog->log);
|
||||
sqlite3_free(pLog->zLogname);
|
||||
sqlite3_free(pLog);
|
||||
}
|
||||
@@ -502,6 +503,7 @@ static int tmstmpLogFlush(TmstmpFile *p){
|
||||
}
|
||||
}
|
||||
(void)fwrite(pLog->a, pLog->n, 1, pLog->log);
|
||||
fflush(pLog->log);
|
||||
pLog->n = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -619,7 +621,7 @@ static int tmstmpWrite(
|
||||
u32 x = 0;
|
||||
p->iFrame = (iOfst - 32)/(p->pgsz+24)+1;
|
||||
p->pgno = tmstmpGetU32((const u8*)zBuf);
|
||||
p->salt1 = tmstmpGetU32(((const u8*)zBuf)+16);
|
||||
p->salt1 = tmstmpGetU32(((const u8*)zBuf)+8);
|
||||
memcpy(&x, ((const u8*)zBuf)+4, 4);
|
||||
p->isCommit = (x!=0);
|
||||
p->iOfst = iOfst;
|
||||
@@ -637,7 +639,7 @@ static int tmstmpWrite(
|
||||
memset(s, 0, TMSTMP_RESERVE);
|
||||
tmstmpPutTS(p, s+2);
|
||||
tmstmpPutU32(p->iFrame, s+8);
|
||||
tmstmpPutU32(p->pPartner->salt1, s+12);
|
||||
tmstmpPutU32(p->pPartner->salt1 & 0xffffff, s+12);
|
||||
assert( p->pgsz>0 );
|
||||
tmstmpEvent(p, ELOG_CKPT_PAGE, 0, (iOfst/p->pgsz)+1, p->iFrame, 0);
|
||||
}else if( p->pPartner==0 ){
|
||||
@@ -647,7 +649,7 @@ static int tmstmpWrite(
|
||||
tmstmpPutTS(p, s+2);
|
||||
s[12] = 2;
|
||||
assert( p->pgsz>0 );
|
||||
tmstmpEvent(p, ELOG_DB_PAGE, 0, (u32)(iOfst/p->pgsz), 0, s+2);
|
||||
tmstmpEvent(p, ELOG_DB_PAGE, 0, (u32)(iOfst/p->pgsz)+1, 0, s+2);
|
||||
}
|
||||
return pSub->pMethods->xWrite(pSub,zBuf,iAmt,iOfst);
|
||||
}
|
||||
@@ -879,7 +881,9 @@ static int tmstmpOpen(
|
||||
r1 = 0;
|
||||
pLog = sqlite3_malloc64( sizeof(TmstmpLog) );
|
||||
if( pLog==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
pSubFile->pMethods->xClose(pSubFile);
|
||||
rc = SQLITE_NOMEM;
|
||||
goto tmstmp_open_done;
|
||||
}
|
||||
memset(pLog, 0, sizeof(pLog[0]));
|
||||
p->pLog = pLog;
|
||||
|
||||
+6
-1
@@ -705,7 +705,12 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
|
||||
u8 *p = aExtra;
|
||||
u8 *pEnd = &aExtra[nExtra];
|
||||
|
||||
while( p<pEnd ){
|
||||
/* Stop when there are less than 9 bytes left to scan in the buffer. This
|
||||
** is because the timestamp field requires exactly 9 bytes - 4 bytes of
|
||||
** header fields and 5 bytes of data. If there are less than 9 bytes
|
||||
** remaining, either it is some other field or else the extra data
|
||||
** is corrupt. Either way, do not process it. */
|
||||
while( p+(2*sizeof(u16) + 1 + sizeof(u32))<=pEnd ){
|
||||
u16 id = zipfileRead16(p);
|
||||
u16 nByte = zipfileRead16(p);
|
||||
|
||||
|
||||
+2
-2
@@ -2630,7 +2630,7 @@ static void qrfOneSimpleRow(Qrf *p){
|
||||
do{
|
||||
int nThis, nWide, iNext;
|
||||
qrfWrapLine(zVal, mxW, bWW, &nThis, &nWide, &iNext);
|
||||
if( cnt ) sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+3,' ');
|
||||
if( cnt ) sqlite3_str_appendchar(p->pOut,p->u.sLine.mxColWth+2,' ');
|
||||
cnt++;
|
||||
if( cnt>p->mxHeight ){
|
||||
zVal = "...";
|
||||
@@ -2900,7 +2900,7 @@ static void qrfFinalize(Qrf *p){
|
||||
char *zCombined;
|
||||
sz = strlen(p->spec.pzOutput[0]);
|
||||
n = sqlite3_str_length(p->pOut);
|
||||
zCombined = sqlite3_realloc(p->spec.pzOutput[0], sz+n+1);
|
||||
zCombined = sqlite3_realloc64(p->spec.pzOutput[0], sz+n+1);
|
||||
if( zCombined==0 ){
|
||||
sqlite3_free(p->spec.pzOutput[0]);
|
||||
p->spec.pzOutput[0] = 0;
|
||||
|
||||
@@ -2269,8 +2269,8 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
|
||||
|
||||
/* If necessary, grow the pIter->aIdxCol[] array */
|
||||
if( iIdxCol==nIdxAlloc ){
|
||||
RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc(
|
||||
pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan)
|
||||
RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc64(
|
||||
pIter->aIdxCol, nIdxAlloc*sizeof(RbuSpan) + 16*sizeof(RbuSpan)
|
||||
);
|
||||
if( aIdxCol==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
This folder contains extensions and utility programs intended to analyze
|
||||
live database files, detect problems, and possibly fix them.
|
||||
|
||||
As SQLite is being used on larger and larger databases, database sizes
|
||||
are growing into the terabyte range. At that size, hardware malfunctions
|
||||
and/or cosmic rays will occasionally corrupt a database file. Detecting
|
||||
problems and fixing errors a terabyte-sized databases can take hours or days,
|
||||
and it is undesirable to take applications that depend on the databases
|
||||
off-line for such a long time.
|
||||
The utilities in the folder are intended to provide mechanisms for
|
||||
detecting and fixing problems in large databases while those databases
|
||||
are in active use.
|
||||
|
||||
The utilities and extensions in this folder are experimental and under
|
||||
active development at the time of this writing (2017-10-12). If and when
|
||||
they stabilize, this README will be updated to reflect that fact.
|
||||
@@ -1,310 +0,0 @@
|
||||
/*
|
||||
** 2017 October 11
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This module exports a single C function:
|
||||
**
|
||||
** int sqlite3_check_freelist(sqlite3 *db, const char *zDb);
|
||||
**
|
||||
** This function checks the free-list in database zDb (one of "main",
|
||||
** "temp", etc.) and reports any errors by invoking the sqlite3_log()
|
||||
** function. It returns SQLITE_OK if successful, or an SQLite error
|
||||
** code otherwise. It is not an error if the free-list is corrupted but
|
||||
** no IO or OOM errors occur.
|
||||
**
|
||||
** If this file is compiled and loaded as an SQLite loadable extension,
|
||||
** it adds an SQL function "checkfreelist" to the database handle, to
|
||||
** be invoked as follows:
|
||||
**
|
||||
** SELECT checkfreelist(<database-name>);
|
||||
**
|
||||
** This function performs the same checks as sqlite3_check_freelist(),
|
||||
** except that it returns all error messages as a single text value,
|
||||
** separated by newline characters. If the freelist is not corrupted
|
||||
** in any way, an empty string is returned.
|
||||
**
|
||||
** To compile this module for use as an SQLite loadable extension:
|
||||
**
|
||||
** gcc -Os -fPIC -shared checkfreelist.c -o checkfreelist.so
|
||||
*/
|
||||
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
||||
# endif
|
||||
# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
# elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
# else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
# endif
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#define get4byte(x) ( \
|
||||
((u32)((x)[0])<<24) + \
|
||||
((u32)((x)[1])<<16) + \
|
||||
((u32)((x)[2])<<8) + \
|
||||
((u32)((x)[3])) \
|
||||
)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Execute a single PRAGMA statement and return the integer value returned
|
||||
** via output parameter (*pnOut).
|
||||
**
|
||||
** The SQL statement passed as the third argument should be a printf-style
|
||||
** format string containing a single "%s" which will be replace by the
|
||||
** value passed as the second argument. e.g.
|
||||
**
|
||||
** sqlGetInteger(db, "main", "PRAGMA %s.page_count", pnOut)
|
||||
**
|
||||
** executes "PRAGMA main.page_count" and stores the results in (*pnOut).
|
||||
*/
|
||||
static int sqlGetInteger(
|
||||
sqlite3 *db, /* Database handle */
|
||||
const char *zDb, /* Database name ("main", "temp" etc.) */
|
||||
const char *zFmt, /* SQL statement format */
|
||||
u32 *pnOut /* OUT: Integer value */
|
||||
){
|
||||
int rc, rc2;
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int bOk = 0;
|
||||
|
||||
zSql = sqlite3_mprintf(zFmt, zDb);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
*pnOut = (u32)sqlite3_column_int(pStmt, 0);
|
||||
bOk = 1;
|
||||
}
|
||||
|
||||
rc2 = sqlite3_finalize(pStmt);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_ERROR;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument zFmt must be a printf-style format string and must be
|
||||
** followed by its required arguments. If argument pzOut is NULL,
|
||||
** then the results of printf()ing the format string are passed to
|
||||
** sqlite3_log(). Otherwise, they are appended to the string
|
||||
** at (*pzOut).
|
||||
*/
|
||||
static int checkFreelistError(char **pzOut, const char *zFmt, ...){
|
||||
int rc = SQLITE_OK;
|
||||
char *zErr = 0;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, zFmt);
|
||||
zErr = sqlite3_vmprintf(zFmt, ap);
|
||||
if( zErr==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( pzOut ){
|
||||
*pzOut = sqlite3_mprintf("%s%z%s", *pzOut?"\n":"", *pzOut, zErr);
|
||||
if( *pzOut==0 ) rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_log(SQLITE_ERROR, "checkfreelist: %s", zErr);
|
||||
}
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int checkFreelist(
|
||||
sqlite3 *db,
|
||||
const char *zDb,
|
||||
char **pzOut
|
||||
){
|
||||
/* This query returns one row for each page on the free list. Each row has
|
||||
** two columns - the page number and page content. */
|
||||
const char *zTrunk =
|
||||
"WITH freelist_trunk(i, d, n) AS ("
|
||||
"SELECT 1, NULL, sqlite_readint32(data, 32) "
|
||||
"FROM sqlite_dbpage(:1) WHERE pgno=1 "
|
||||
"UNION ALL "
|
||||
"SELECT n, data, sqlite_readint32(data) "
|
||||
"FROM freelist_trunk, sqlite_dbpage(:1) WHERE pgno=n "
|
||||
")"
|
||||
"SELECT i, d FROM freelist_trunk WHERE i!=1;";
|
||||
|
||||
int rc, rc2; /* Return code */
|
||||
sqlite3_stmt *pTrunk = 0; /* Compilation of zTrunk */
|
||||
u32 nPage = 0; /* Number of pages in db */
|
||||
u32 nExpected = 0; /* Expected number of free pages */
|
||||
u32 nFree = 0; /* Number of pages on free list */
|
||||
|
||||
if( zDb==0 ) zDb = "main";
|
||||
|
||||
if( (rc = sqlGetInteger(db, zDb, "PRAGMA %s.page_count", &nPage))
|
||||
|| (rc = sqlGetInteger(db, zDb, "PRAGMA %s.freelist_count", &nExpected))
|
||||
){
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
|
||||
while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
|
||||
u32 i;
|
||||
u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
|
||||
const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
|
||||
u32 nData = (u32)sqlite3_column_bytes(pTrunk, 1);
|
||||
u32 iNext = get4byte(&aData[0]);
|
||||
u32 nLeaf = get4byte(&aData[4]);
|
||||
|
||||
if( nLeaf>((nData/4)-2-6) ){
|
||||
rc = checkFreelistError(pzOut,
|
||||
"leaf count out of range (%d) on trunk page %d",
|
||||
(int)nLeaf, (int)iTrunk
|
||||
);
|
||||
nLeaf = (nData/4) - 2 - 6;
|
||||
}
|
||||
|
||||
nFree += 1+nLeaf;
|
||||
if( iNext>nPage ){
|
||||
rc = checkFreelistError(pzOut,
|
||||
"trunk page %d is out of range", (int)iNext
|
||||
);
|
||||
}
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nLeaf; i++){
|
||||
u32 iLeaf = get4byte(&aData[8 + 4*i]);
|
||||
if( iLeaf==0 || iLeaf>nPage ){
|
||||
rc = checkFreelistError(pzOut,
|
||||
"leaf page %d is out of range (child %d of trunk page %d)",
|
||||
(int)iLeaf, (int)i, (int)iTrunk
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && nFree!=nExpected ){
|
||||
rc = checkFreelistError(pzOut,
|
||||
"free-list count mismatch: actual=%d header=%d",
|
||||
(int)nFree, (int)nExpected
|
||||
);
|
||||
}
|
||||
|
||||
rc2 = sqlite3_finalize(pTrunk);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3_check_freelist(sqlite3 *db, const char *zDb){
|
||||
return checkFreelist(db, zDb, 0);
|
||||
}
|
||||
|
||||
static void checkfreelist_function(
|
||||
sqlite3_context *pCtx,
|
||||
int nArg,
|
||||
sqlite3_value **apArg
|
||||
){
|
||||
const char *zDb;
|
||||
int rc;
|
||||
char *zOut = 0;
|
||||
sqlite3 *db = sqlite3_context_db_handle(pCtx);
|
||||
|
||||
assert( nArg==1 );
|
||||
zDb = (const char*)sqlite3_value_text(apArg[0]);
|
||||
rc = checkFreelist(db, zDb, &zOut);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_text(pCtx, zOut?zOut:"ok", -1, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_error_code(pCtx, rc);
|
||||
}
|
||||
|
||||
sqlite3_free(zOut);
|
||||
}
|
||||
|
||||
/*
|
||||
** An SQL function invoked as follows:
|
||||
**
|
||||
** sqlite_readint32(BLOB) -- Decode 32-bit integer from start of blob
|
||||
*/
|
||||
static void readint_function(
|
||||
sqlite3_context *pCtx,
|
||||
int nArg,
|
||||
sqlite3_value **apArg
|
||||
){
|
||||
const u8 *zBlob;
|
||||
int nBlob;
|
||||
int iOff = 0;
|
||||
u32 iRet = 0;
|
||||
|
||||
if( nArg!=1 && nArg!=2 ){
|
||||
sqlite3_result_error(
|
||||
pCtx, "wrong number of arguments to function sqlite_readint32()", -1
|
||||
);
|
||||
return;
|
||||
}
|
||||
if( nArg==2 ){
|
||||
iOff = sqlite3_value_int(apArg[1]);
|
||||
}
|
||||
|
||||
zBlob = sqlite3_value_blob(apArg[0]);
|
||||
nBlob = sqlite3_value_bytes(apArg[0]);
|
||||
|
||||
if( nBlob>=(iOff+4) ){
|
||||
iRet = get4byte(&zBlob[iOff]);
|
||||
}
|
||||
|
||||
sqlite3_result_int64(pCtx, (sqlite3_int64)iRet);
|
||||
}
|
||||
|
||||
/*
|
||||
** Register the SQL functions.
|
||||
*/
|
||||
static int cflRegister(sqlite3 *db){
|
||||
int rc = sqlite3_create_function(
|
||||
db, "sqlite_readint32", -1, SQLITE_UTF8, 0, readint_function, 0, 0
|
||||
);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
rc = sqlite3_create_function(
|
||||
db, "checkfreelist", 1, SQLITE_UTF8, 0, checkfreelist_function, 0, 0
|
||||
);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extension load function.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_checkfreelist_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
return cflRegister(db);
|
||||
}
|
||||
@@ -1,929 +0,0 @@
|
||||
/*
|
||||
** 2017 October 27
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
|
||||
/*
|
||||
** Stuff that is available inside the amalgamation, but which we need to
|
||||
** declare ourselves if this module is compiled separately.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#define get4byte(x) ( \
|
||||
((u32)((x)[0])<<24) + \
|
||||
((u32)((x)[1])<<16) + \
|
||||
((u32)((x)[2])<<8) + \
|
||||
((u32)((x)[3])) \
|
||||
)
|
||||
#endif
|
||||
|
||||
typedef struct CidxTable CidxTable;
|
||||
typedef struct CidxCursor CidxCursor;
|
||||
|
||||
struct CidxTable {
|
||||
sqlite3_vtab base; /* Base class. Must be first */
|
||||
sqlite3 *db;
|
||||
};
|
||||
|
||||
struct CidxCursor {
|
||||
sqlite3_vtab_cursor base; /* Base class. Must be first */
|
||||
sqlite3_int64 iRowid; /* Row number of the output */
|
||||
char *zIdxName; /* Copy of the index_name parameter */
|
||||
char *zAfterKey; /* Copy of the after_key parameter */
|
||||
sqlite3_stmt *pStmt; /* SQL statement that generates the output */
|
||||
};
|
||||
|
||||
typedef struct CidxColumn CidxColumn;
|
||||
struct CidxColumn {
|
||||
char *zExpr; /* Text for indexed expression */
|
||||
int bDesc; /* True for DESC columns, otherwise false */
|
||||
int bKey; /* Part of index, not PK */
|
||||
};
|
||||
|
||||
typedef struct CidxIndex CidxIndex;
|
||||
struct CidxIndex {
|
||||
char *zWhere; /* WHERE clause, if any */
|
||||
int nCol; /* Elements in aCol[] array */
|
||||
CidxColumn aCol[1]; /* Array of indexed columns */
|
||||
};
|
||||
|
||||
static void *cidxMalloc(int *pRc, int n){
|
||||
void *pRet = 0;
|
||||
assert( n!=0 );
|
||||
if( *pRc==SQLITE_OK ){
|
||||
pRet = sqlite3_malloc(n);
|
||||
if( pRet ){
|
||||
memset(pRet, 0, n);
|
||||
}else{
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
static void cidxCursorError(CidxCursor *pCsr, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
assert( pCsr->base.pVtab->zErrMsg==0 );
|
||||
pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
** Connect to the incremental_index_check virtual table.
|
||||
*/
|
||||
static int cidxConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
CidxTable *pRet;
|
||||
|
||||
#define IIC_ERRMSG 0
|
||||
#define IIC_CURRENT_KEY 1
|
||||
#define IIC_INDEX_NAME 2
|
||||
#define IIC_AFTER_KEY 3
|
||||
#define IIC_SCANNER_SQL 4
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE xyz("
|
||||
" errmsg TEXT," /* Error message or NULL if everything is ok */
|
||||
" current_key TEXT," /* SQLite quote() text of key values */
|
||||
" index_name HIDDEN," /* IN: name of the index being scanned */
|
||||
" after_key HIDDEN," /* IN: Start scanning after this key */
|
||||
" scanner_sql HIDDEN" /* debugging info: SQL used for scanner */
|
||||
")"
|
||||
);
|
||||
pRet = cidxMalloc(&rc, sizeof(CidxTable));
|
||||
if( pRet ){
|
||||
pRet->db = db;
|
||||
}
|
||||
|
||||
*ppVtab = (sqlite3_vtab*)pRet;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Disconnect from or destroy an incremental_index_check virtual table.
|
||||
*/
|
||||
static int cidxDisconnect(sqlite3_vtab *pVtab){
|
||||
CidxTable *pTab = (CidxTable*)pVtab;
|
||||
sqlite3_free(pTab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** idxNum and idxStr are not used. There are only three possible plans,
|
||||
** which are all distinguished by the number of parameters.
|
||||
**
|
||||
** No parameters: A degenerate plan. The result is zero rows.
|
||||
** 1 Parameter: Scan all of the index starting with first entry
|
||||
** 2 parameters: Scan the index starting after the "after_key".
|
||||
**
|
||||
** Provide successively smaller costs for each of these plans to encourage
|
||||
** the query planner to select the one with the most parameters.
|
||||
*/
|
||||
static int cidxBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pInfo){
|
||||
int iIdxName = -1;
|
||||
int iAfterKey = -1;
|
||||
int i;
|
||||
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
if( p->usable==0 ) continue;
|
||||
if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
|
||||
if( p->iColumn==IIC_INDEX_NAME ){
|
||||
iIdxName = i;
|
||||
}
|
||||
if( p->iColumn==IIC_AFTER_KEY ){
|
||||
iAfterKey = i;
|
||||
}
|
||||
}
|
||||
|
||||
if( iIdxName<0 ){
|
||||
pInfo->estimatedCost = 1000000000.0;
|
||||
}else{
|
||||
pInfo->aConstraintUsage[iIdxName].argvIndex = 1;
|
||||
pInfo->aConstraintUsage[iIdxName].omit = 1;
|
||||
if( iAfterKey<0 ){
|
||||
pInfo->estimatedCost = 1000000.0;
|
||||
}else{
|
||||
pInfo->aConstraintUsage[iAfterKey].argvIndex = 2;
|
||||
pInfo->aConstraintUsage[iAfterKey].omit = 1;
|
||||
pInfo->estimatedCost = 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a new btreeinfo cursor.
|
||||
*/
|
||||
static int cidxOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
CidxCursor *pRet;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pRet = cidxMalloc(&rc, sizeof(CidxCursor));
|
||||
|
||||
*ppCursor = (sqlite3_vtab_cursor*)pRet;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a btreeinfo cursor.
|
||||
*/
|
||||
static int cidxClose(sqlite3_vtab_cursor *pCursor){
|
||||
CidxCursor *pCsr = (CidxCursor*)pCursor;
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
sqlite3_free(pCsr->zIdxName);
|
||||
sqlite3_free(pCsr->zAfterKey);
|
||||
sqlite3_free(pCsr);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move a btreeinfo cursor to the next entry in the file.
|
||||
*/
|
||||
static int cidxNext(sqlite3_vtab_cursor *pCursor){
|
||||
CidxCursor *pCsr = (CidxCursor*)pCursor;
|
||||
int rc = sqlite3_step(pCsr->pStmt);
|
||||
if( rc!=SQLITE_ROW ){
|
||||
rc = sqlite3_finalize(pCsr->pStmt);
|
||||
pCsr->pStmt = 0;
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
|
||||
cidxCursorError(pCsr, "Cursor error: %s", sqlite3_errmsg(db));
|
||||
}
|
||||
}else{
|
||||
pCsr->iRowid++;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* We have reached EOF if previous sqlite3_step() returned
|
||||
** anything other than SQLITE_ROW;
|
||||
*/
|
||||
static int cidxEof(sqlite3_vtab_cursor *pCursor){
|
||||
CidxCursor *pCsr = (CidxCursor*)pCursor;
|
||||
return pCsr->pStmt==0;
|
||||
}
|
||||
|
||||
static char *cidxMprintf(int *pRc, const char *zFmt, ...){
|
||||
char *zRet = 0;
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
zRet = sqlite3_vmprintf(zFmt, ap);
|
||||
if( *pRc==SQLITE_OK ){
|
||||
if( zRet==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}
|
||||
}else{
|
||||
sqlite3_free(zRet);
|
||||
zRet = 0;
|
||||
}
|
||||
va_end(ap);
|
||||
return zRet;
|
||||
}
|
||||
|
||||
static sqlite3_stmt *cidxPrepare(
|
||||
int *pRc, CidxCursor *pCsr, const char *zFmt, ...
|
||||
){
|
||||
sqlite3_stmt *pRet = 0;
|
||||
char *zSql;
|
||||
va_list ap; /* ... printf arguments */
|
||||
va_start(ap, zFmt);
|
||||
|
||||
zSql = sqlite3_vmprintf(zFmt, ap);
|
||||
if( *pRc==SQLITE_OK ){
|
||||
if( zSql==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
|
||||
*pRc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
|
||||
if( *pRc!=SQLITE_OK ){
|
||||
cidxCursorError(pCsr, "SQL error: %s", sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
va_end(ap);
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
static void cidxFinalize(int *pRc, sqlite3_stmt *pStmt){
|
||||
int rc = sqlite3_finalize(pStmt);
|
||||
if( *pRc==SQLITE_OK ) *pRc = rc;
|
||||
}
|
||||
|
||||
char *cidxStrdup(int *pRc, const char *zStr){
|
||||
char *zRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
int n = (int)strlen(zStr);
|
||||
zRet = cidxMalloc(pRc, n+1);
|
||||
if( zRet ) memcpy(zRet, zStr, n+1);
|
||||
}
|
||||
return zRet;
|
||||
}
|
||||
|
||||
static void cidxFreeIndex(CidxIndex *pIdx){
|
||||
if( pIdx ){
|
||||
int i;
|
||||
for(i=0; i<pIdx->nCol; i++){
|
||||
sqlite3_free(pIdx->aCol[i].zExpr);
|
||||
}
|
||||
sqlite3_free(pIdx->zWhere);
|
||||
sqlite3_free(pIdx);
|
||||
}
|
||||
}
|
||||
|
||||
static int cidx_isspace(char c){
|
||||
return c==' ' || c=='\t' || c=='\r' || c=='\n';
|
||||
}
|
||||
|
||||
static int cidx_isident(char c){
|
||||
return c<0
|
||||
|| (c>='0' && c<='9') || (c>='a' && c<='z')
|
||||
|| (c>='A' && c<='Z') || c=='_';
|
||||
}
|
||||
|
||||
#define CIDX_PARSE_EOF 0
|
||||
#define CIDX_PARSE_COMMA 1 /* "," */
|
||||
#define CIDX_PARSE_OPEN 2 /* "(" */
|
||||
#define CIDX_PARSE_CLOSE 3 /* ")" */
|
||||
|
||||
/*
|
||||
** Argument zIn points into the start, middle or end of a CREATE INDEX
|
||||
** statement. If argument pbDoNotTrim is non-NULL, then this function
|
||||
** scans the input until it finds EOF, a comma (",") or an open or
|
||||
** close parenthesis character. It then sets (*pzOut) to point to said
|
||||
** character and returns a CIDX_PARSE_XXX constant as appropriate. The
|
||||
** parser is smart enough that special characters inside SQL strings
|
||||
** or comments are not returned for.
|
||||
**
|
||||
** Or, if argument pbDoNotTrim is NULL, then this function sets *pzOut
|
||||
** to point to the first character of the string that is not whitespace
|
||||
** or part of an SQL comment and returns CIDX_PARSE_EOF.
|
||||
**
|
||||
** Additionally, if pbDoNotTrim is not NULL and the element immediately
|
||||
** before (*pzOut) is an SQL comment of the form "-- comment", then
|
||||
** (*pbDoNotTrim) is set before returning. In all other cases it is
|
||||
** cleared.
|
||||
*/
|
||||
static int cidxFindNext(
|
||||
const char *zIn,
|
||||
const char **pzOut,
|
||||
int *pbDoNotTrim /* OUT: True if prev is -- comment */
|
||||
){
|
||||
const char *z = zIn;
|
||||
|
||||
while( 1 ){
|
||||
while( cidx_isspace(*z) ) z++;
|
||||
if( z[0]=='-' && z[1]=='-' ){
|
||||
z += 2;
|
||||
while( z[0]!='\n' ){
|
||||
if( z[0]=='\0' ) return CIDX_PARSE_EOF;
|
||||
z++;
|
||||
}
|
||||
while( cidx_isspace(*z) ) z++;
|
||||
if( pbDoNotTrim ) *pbDoNotTrim = 1;
|
||||
}else
|
||||
if( z[0]=='/' && z[1]=='*' ){
|
||||
z += 2;
|
||||
while( z[0]!='*' || z[1]!='/' ){
|
||||
if( z[1]=='\0' ) return CIDX_PARSE_EOF;
|
||||
z++;
|
||||
}
|
||||
z += 2;
|
||||
}else{
|
||||
*pzOut = z;
|
||||
if( pbDoNotTrim==0 ) return CIDX_PARSE_EOF;
|
||||
switch( *z ){
|
||||
case '\0':
|
||||
return CIDX_PARSE_EOF;
|
||||
case '(':
|
||||
return CIDX_PARSE_OPEN;
|
||||
case ')':
|
||||
return CIDX_PARSE_CLOSE;
|
||||
case ',':
|
||||
return CIDX_PARSE_COMMA;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
case '`': {
|
||||
char q = *z;
|
||||
z++;
|
||||
while( *z ){
|
||||
if( *z==q ){
|
||||
z++;
|
||||
if( *z!=q ) break;
|
||||
}
|
||||
z++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case '[':
|
||||
while( *z++!=']' );
|
||||
break;
|
||||
|
||||
default:
|
||||
z++;
|
||||
break;
|
||||
}
|
||||
*pbDoNotTrim = 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert( 0 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cidxParseSQL(CidxCursor *pCsr, CidxIndex *pIdx, const char *zSql){
|
||||
const char *z = zSql;
|
||||
const char *z1;
|
||||
int e;
|
||||
int rc = SQLITE_OK;
|
||||
int nParen = 1;
|
||||
int bDoNotTrim = 0;
|
||||
CidxColumn *pCol = pIdx->aCol;
|
||||
|
||||
e = cidxFindNext(z, &z, &bDoNotTrim);
|
||||
if( e!=CIDX_PARSE_OPEN ) goto parse_error;
|
||||
z1 = z+1;
|
||||
z++;
|
||||
while( nParen>0 ){
|
||||
e = cidxFindNext(z, &z, &bDoNotTrim);
|
||||
if( e==CIDX_PARSE_EOF ) goto parse_error;
|
||||
if( (e==CIDX_PARSE_COMMA || e==CIDX_PARSE_CLOSE) && nParen==1 ){
|
||||
const char *z2 = z;
|
||||
if( pCol->zExpr ) goto parse_error;
|
||||
|
||||
if( bDoNotTrim==0 ){
|
||||
while( cidx_isspace(z[-1]) ) z--;
|
||||
if( !sqlite3_strnicmp(&z[-3], "asc", 3) && 0==cidx_isident(z[-4]) ){
|
||||
z -= 3;
|
||||
while( cidx_isspace(z[-1]) ) z--;
|
||||
}else
|
||||
if( !sqlite3_strnicmp(&z[-4], "desc", 4) && 0==cidx_isident(z[-5]) ){
|
||||
z -= 4;
|
||||
while( cidx_isspace(z[-1]) ) z--;
|
||||
}
|
||||
while( cidx_isspace(z1[0]) ) z1++;
|
||||
}
|
||||
|
||||
pCol->zExpr = cidxMprintf(&rc, "%.*s", z-z1, z1);
|
||||
pCol++;
|
||||
z = z1 = z2+1;
|
||||
}
|
||||
if( e==CIDX_PARSE_OPEN ) nParen++;
|
||||
if( e==CIDX_PARSE_CLOSE ) nParen--;
|
||||
z++;
|
||||
}
|
||||
|
||||
/* Search for a WHERE clause */
|
||||
cidxFindNext(z, &z, 0);
|
||||
if( 0==sqlite3_strnicmp(z, "where", 5) ){
|
||||
pIdx->zWhere = cidxMprintf(&rc, "%s\n", &z[5]);
|
||||
}else if( z[0]!='\0' ){
|
||||
goto parse_error;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
parse_error:
|
||||
cidxCursorError(pCsr, "Parse error in: %s", zSql);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
static int cidxLookupIndex(
|
||||
CidxCursor *pCsr, /* Cursor object */
|
||||
const char *zIdx, /* Name of index to look up */
|
||||
CidxIndex **ppIdx, /* OUT: Description of columns */
|
||||
char **pzTab /* OUT: Table name */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
char *zTab = 0;
|
||||
CidxIndex *pIdx = 0;
|
||||
|
||||
sqlite3_stmt *pFindTab = 0;
|
||||
sqlite3_stmt *pInfo = 0;
|
||||
|
||||
/* Find the table for this index. */
|
||||
pFindTab = cidxPrepare(&rc, pCsr,
|
||||
"SELECT tbl_name, sql FROM sqlite_schema WHERE name=%Q AND type='index'",
|
||||
zIdx
|
||||
);
|
||||
if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pFindTab, 1);
|
||||
zTab = cidxStrdup(&rc, (const char*)sqlite3_column_text(pFindTab, 0));
|
||||
|
||||
pInfo = cidxPrepare(&rc, pCsr, "PRAGMA index_xinfo(%Q)", zIdx);
|
||||
if( rc==SQLITE_OK ){
|
||||
int nAlloc = 0;
|
||||
int iCol = 0;
|
||||
|
||||
while( sqlite3_step(pInfo)==SQLITE_ROW ){
|
||||
const char *zName = (const char*)sqlite3_column_text(pInfo, 2);
|
||||
const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
|
||||
CidxColumn *p;
|
||||
if( zName==0 ) zName = "rowid";
|
||||
if( iCol==nAlloc ){
|
||||
int nByte = sizeof(CidxIndex) + sizeof(CidxColumn)*(nAlloc+8);
|
||||
pIdx = (CidxIndex*)sqlite3_realloc(pIdx, nByte);
|
||||
nAlloc += 8;
|
||||
}
|
||||
p = &pIdx->aCol[iCol++];
|
||||
p->bDesc = sqlite3_column_int(pInfo, 3);
|
||||
p->bKey = sqlite3_column_int(pInfo, 5);
|
||||
if( zSql==0 || p->bKey==0 ){
|
||||
p->zExpr = cidxMprintf(&rc, "\"%w\" COLLATE %s",zName,zColl);
|
||||
}else{
|
||||
p->zExpr = 0;
|
||||
}
|
||||
pIdx->nCol = iCol;
|
||||
pIdx->zWhere = 0;
|
||||
}
|
||||
cidxFinalize(&rc, pInfo);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && zSql ){
|
||||
rc = cidxParseSQL(pCsr, pIdx, zSql);
|
||||
}
|
||||
}
|
||||
|
||||
cidxFinalize(&rc, pFindTab);
|
||||
if( rc==SQLITE_OK && zTab==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(zTab);
|
||||
cidxFreeIndex(pIdx);
|
||||
}else{
|
||||
*pzTab = zTab;
|
||||
*ppIdx = pIdx;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cidxDecodeAfter(
|
||||
CidxCursor *pCsr,
|
||||
int nCol,
|
||||
const char *zAfterKey,
|
||||
char ***pazAfter
|
||||
){
|
||||
char **azAfter;
|
||||
int rc = SQLITE_OK;
|
||||
int nAfterKey = (int)strlen(zAfterKey);
|
||||
|
||||
azAfter = cidxMalloc(&rc, sizeof(char*)*nCol + nAfterKey+1);
|
||||
if( rc==SQLITE_OK ){
|
||||
int i;
|
||||
char *zCopy = (char*)&azAfter[nCol];
|
||||
char *p = zCopy;
|
||||
memcpy(zCopy, zAfterKey, nAfterKey+1);
|
||||
for(i=0; i<nCol; i++){
|
||||
while( *p==' ' ) p++;
|
||||
|
||||
/* Check NULL values */
|
||||
if( *p=='N' ){
|
||||
if( memcmp(p, "NULL", 4) ) goto parse_error;
|
||||
p += 4;
|
||||
}
|
||||
|
||||
/* Check strings and blob literals */
|
||||
else if( *p=='X' || *p=='\'' ){
|
||||
azAfter[i] = p;
|
||||
if( *p=='X' ) p++;
|
||||
if( *p!='\'' ) goto parse_error;
|
||||
p++;
|
||||
while( 1 ){
|
||||
if( *p=='\0' ) goto parse_error;
|
||||
if( *p=='\'' ){
|
||||
p++;
|
||||
if( *p!='\'' ) break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check numbers */
|
||||
else{
|
||||
azAfter[i] = p;
|
||||
while( (*p>='0' && *p<='9')
|
||||
|| *p=='.' || *p=='+' || *p=='-' || *p=='e' || *p=='E'
|
||||
){
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
while( *p==' ' ) p++;
|
||||
if( *p!=(i==(nCol-1) ? '\0' : ',') ){
|
||||
goto parse_error;
|
||||
}
|
||||
*p++ = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
*pazAfter = azAfter;
|
||||
return rc;
|
||||
|
||||
parse_error:
|
||||
sqlite3_free(azAfter);
|
||||
*pazAfter = 0;
|
||||
cidxCursorError(pCsr, "%s", "error parsing after value");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
static char *cidxWhere(
|
||||
int *pRc, CidxColumn *aCol, char **azAfter, int iGt, int bLastIsNull
|
||||
){
|
||||
char *zRet = 0;
|
||||
const char *zSep = "";
|
||||
int i;
|
||||
|
||||
for(i=0; i<iGt; i++){
|
||||
zRet = cidxMprintf(pRc, "%z%s(%s) IS %s", zRet,
|
||||
zSep, aCol[i].zExpr, (azAfter[i] ? azAfter[i] : "NULL")
|
||||
);
|
||||
zSep = " AND ";
|
||||
}
|
||||
|
||||
if( bLastIsNull ){
|
||||
zRet = cidxMprintf(pRc, "%z%s(%s) IS NULL", zRet, zSep, aCol[iGt].zExpr);
|
||||
}
|
||||
else if( azAfter[iGt] ){
|
||||
zRet = cidxMprintf(pRc, "%z%s(%s) %s %s", zRet,
|
||||
zSep, aCol[iGt].zExpr, (aCol[iGt].bDesc ? "<" : ">"),
|
||||
azAfter[iGt]
|
||||
);
|
||||
}else{
|
||||
zRet = cidxMprintf(pRc, "%z%s(%s) IS NOT NULL", zRet, zSep,aCol[iGt].zExpr);
|
||||
}
|
||||
|
||||
return zRet;
|
||||
}
|
||||
|
||||
#define CIDX_CLIST_ALL 0
|
||||
#define CIDX_CLIST_ORDERBY 1
|
||||
#define CIDX_CLIST_CURRENT_KEY 2
|
||||
#define CIDX_CLIST_SUBWHERE 3
|
||||
#define CIDX_CLIST_SUBEXPR 4
|
||||
|
||||
/*
|
||||
** This function returns various strings based on the contents of the
|
||||
** CidxIndex structure and the eType parameter.
|
||||
*/
|
||||
static char *cidxColumnList(
|
||||
int *pRc, /* IN/OUT: Error code */
|
||||
const char *zIdx,
|
||||
CidxIndex *pIdx, /* Indexed columns */
|
||||
int eType /* True to include ASC/DESC */
|
||||
){
|
||||
char *zRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
const char *aDir[2] = {"", " DESC"};
|
||||
int i;
|
||||
const char *zSep = "";
|
||||
|
||||
for(i=0; i<pIdx->nCol; i++){
|
||||
CidxColumn *p = &pIdx->aCol[i];
|
||||
assert( pIdx->aCol[i].bDesc==0 || pIdx->aCol[i].bDesc==1 );
|
||||
switch( eType ){
|
||||
|
||||
case CIDX_CLIST_ORDERBY:
|
||||
zRet = cidxMprintf(pRc, "%z%s%d%s", zRet, zSep, i+1, aDir[p->bDesc]);
|
||||
zSep = ",";
|
||||
break;
|
||||
|
||||
case CIDX_CLIST_CURRENT_KEY:
|
||||
zRet = cidxMprintf(pRc, "%z%squote(i%d)", zRet, zSep, i);
|
||||
zSep = "||','||";
|
||||
break;
|
||||
|
||||
case CIDX_CLIST_SUBWHERE:
|
||||
if( p->bKey==0 ){
|
||||
zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet,
|
||||
zSep, p->zExpr, i
|
||||
);
|
||||
zSep = " AND ";
|
||||
}
|
||||
break;
|
||||
|
||||
case CIDX_CLIST_SUBEXPR:
|
||||
if( p->bKey==1 ){
|
||||
zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet,
|
||||
zSep, p->zExpr, i
|
||||
);
|
||||
zSep = " AND ";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( eType==CIDX_CLIST_ALL );
|
||||
zRet = cidxMprintf(pRc, "%z%s(%s) AS i%d", zRet, zSep, p->zExpr, i);
|
||||
zSep = ", ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return zRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate SQL (in memory obtained from sqlite3_malloc()) that will
|
||||
** continue the index scan for zIdxName starting after zAfterKey.
|
||||
*/
|
||||
int cidxGenerateScanSql(
|
||||
CidxCursor *pCsr, /* The cursor which needs the new statement */
|
||||
const char *zIdxName, /* index to be scanned */
|
||||
const char *zAfterKey, /* start after this key, if not NULL */
|
||||
char **pzSqlOut /* OUT: Write the generated SQL here */
|
||||
){
|
||||
int rc;
|
||||
char *zTab = 0;
|
||||
char *zCurrentKey = 0;
|
||||
char *zOrderBy = 0;
|
||||
char *zSubWhere = 0;
|
||||
char *zSubExpr = 0;
|
||||
char *zSrcList = 0;
|
||||
char **azAfter = 0;
|
||||
CidxIndex *pIdx = 0;
|
||||
|
||||
*pzSqlOut = 0;
|
||||
rc = cidxLookupIndex(pCsr, zIdxName, &pIdx, &zTab);
|
||||
|
||||
zOrderBy = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ORDERBY);
|
||||
zCurrentKey = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_CURRENT_KEY);
|
||||
zSubWhere = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBWHERE);
|
||||
zSubExpr = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBEXPR);
|
||||
zSrcList = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ALL);
|
||||
|
||||
if( rc==SQLITE_OK && zAfterKey ){
|
||||
rc = cidxDecodeAfter(pCsr, pIdx->nCol, zAfterKey, &azAfter);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( zAfterKey==0 ){
|
||||
*pzSqlOut = cidxMprintf(&rc,
|
||||
"SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
|
||||
"FROM (SELECT %s FROM %Q INDEXED BY %Q %s%sORDER BY %s) AS i",
|
||||
zSubExpr, zTab, zSubWhere, zCurrentKey,
|
||||
zSrcList, zTab, zIdxName,
|
||||
(pIdx->zWhere ? "WHERE " : ""), (pIdx->zWhere ? pIdx->zWhere : ""),
|
||||
zOrderBy
|
||||
);
|
||||
}else{
|
||||
const char *zSep = "";
|
||||
char *zSql;
|
||||
int i;
|
||||
|
||||
zSql = cidxMprintf(&rc,
|
||||
"SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
|
||||
zSubExpr, zTab, zSubWhere, zCurrentKey
|
||||
);
|
||||
for(i=pIdx->nCol-1; i>=0; i--){
|
||||
int j;
|
||||
if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
|
||||
for(j=0; j<2; j++){
|
||||
char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
|
||||
zSql = cidxMprintf(&rc, "%z"
|
||||
"%sSELECT * FROM ("
|
||||
"SELECT %s FROM %Q INDEXED BY %Q WHERE %s%s%z ORDER BY %s"
|
||||
")",
|
||||
zSql, zSep, zSrcList, zTab, zIdxName,
|
||||
pIdx->zWhere ? pIdx->zWhere : "",
|
||||
pIdx->zWhere ? " AND " : "",
|
||||
zWhere, zOrderBy
|
||||
);
|
||||
zSep = " UNION ALL ";
|
||||
if( pIdx->aCol[i].bDesc==0 ) break;
|
||||
}
|
||||
}
|
||||
*pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_free(zTab);
|
||||
sqlite3_free(zCurrentKey);
|
||||
sqlite3_free(zOrderBy);
|
||||
sqlite3_free(zSubWhere);
|
||||
sqlite3_free(zSubExpr);
|
||||
sqlite3_free(zSrcList);
|
||||
cidxFreeIndex(pIdx);
|
||||
sqlite3_free(azAfter);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Position a cursor back to the beginning.
|
||||
*/
|
||||
static int cidxFilter(
|
||||
sqlite3_vtab_cursor *pCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
CidxCursor *pCsr = (CidxCursor*)pCursor;
|
||||
const char *zIdxName = 0;
|
||||
const char *zAfterKey = 0;
|
||||
|
||||
sqlite3_free(pCsr->zIdxName);
|
||||
pCsr->zIdxName = 0;
|
||||
sqlite3_free(pCsr->zAfterKey);
|
||||
pCsr->zAfterKey = 0;
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
pCsr->pStmt = 0;
|
||||
|
||||
if( argc>0 ){
|
||||
zIdxName = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( argc>1 ){
|
||||
zAfterKey = (const char*)sqlite3_value_text(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if( zIdxName ){
|
||||
char *zSql = 0;
|
||||
pCsr->zIdxName = sqlite3_mprintf("%s", zIdxName);
|
||||
pCsr->zAfterKey = zAfterKey ? sqlite3_mprintf("%s", zAfterKey) : 0;
|
||||
rc = cidxGenerateScanSql(pCsr, zIdxName, zAfterKey, &zSql);
|
||||
if( zSql ){
|
||||
pCsr->pStmt = cidxPrepare(&rc, pCsr, "%z", zSql);
|
||||
}
|
||||
}
|
||||
|
||||
if( pCsr->pStmt ){
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = cidxNext(pCursor);
|
||||
}
|
||||
pCsr->iRowid = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a column value.
|
||||
*/
|
||||
static int cidxColumn(
|
||||
sqlite3_vtab_cursor *pCursor,
|
||||
sqlite3_context *ctx,
|
||||
int iCol
|
||||
){
|
||||
CidxCursor *pCsr = (CidxCursor*)pCursor;
|
||||
assert( iCol>=IIC_ERRMSG && iCol<=IIC_SCANNER_SQL );
|
||||
switch( iCol ){
|
||||
case IIC_ERRMSG: {
|
||||
const char *zVal = 0;
|
||||
if( sqlite3_column_type(pCsr->pStmt, 0)==SQLITE_INTEGER ){
|
||||
if( sqlite3_column_int(pCsr->pStmt, 0)==0 ){
|
||||
zVal = "row data mismatch";
|
||||
}
|
||||
}else{
|
||||
zVal = "row missing";
|
||||
}
|
||||
sqlite3_result_text(ctx, zVal, -1, SQLITE_STATIC);
|
||||
break;
|
||||
}
|
||||
case IIC_CURRENT_KEY: {
|
||||
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 1));
|
||||
break;
|
||||
}
|
||||
case IIC_INDEX_NAME: {
|
||||
sqlite3_result_text(ctx, pCsr->zIdxName, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case IIC_AFTER_KEY: {
|
||||
sqlite3_result_text(ctx, pCsr->zAfterKey, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case IIC_SCANNER_SQL: {
|
||||
char *zSql = 0;
|
||||
cidxGenerateScanSql(pCsr, pCsr->zIdxName, pCsr->zAfterKey, &zSql);
|
||||
sqlite3_result_text(ctx, zSql, -1, sqlite3_free);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Return the ROWID for the sqlite_btreeinfo table */
|
||||
static int cidxRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
|
||||
CidxCursor *pCsr = (CidxCursor*)pCursor;
|
||||
*pRowid = pCsr->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Register the virtual table modules with the database handle passed
|
||||
** as the only argument.
|
||||
*/
|
||||
static int ciInit(sqlite3 *db){
|
||||
static sqlite3_module cidx_module = {
|
||||
0, /* iVersion */
|
||||
0, /* xCreate */
|
||||
cidxConnect, /* xConnect */
|
||||
cidxBestIndex, /* xBestIndex */
|
||||
cidxDisconnect, /* xDisconnect */
|
||||
0, /* xDestroy */
|
||||
cidxOpen, /* xOpen - open a cursor */
|
||||
cidxClose, /* xClose - close a cursor */
|
||||
cidxFilter, /* xFilter - configure scan constraints */
|
||||
cidxNext, /* xNext - advance a cursor */
|
||||
cidxEof, /* xEof - check for end of scan */
|
||||
cidxColumn, /* xColumn - read data */
|
||||
cidxRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
0, /* xShadowName */
|
||||
0 /* xIntegrity */
|
||||
};
|
||||
return sqlite3_create_module(db, "incremental_index_check", &cidx_module, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Extension load function.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_checkindex_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
return ciInit(db);
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
** Read an SQLite database file and analyze its space utilization. Generate
|
||||
** text on standard output.
|
||||
*/
|
||||
#define TCLSH_INIT_PROC sqlite3_checker_init_proc
|
||||
#define SQLITE_ENABLE_DBPAGE_VTAB 1
|
||||
#undef SQLITE_THREADSAFE
|
||||
#define SQLITE_THREADSAFE 0
|
||||
#undef SQLITE_ENABLE_COLUMN_METADATA
|
||||
#define SQLITE_OMIT_DECLTYPE 1
|
||||
#define SQLITE_OMIT_DEPRECATED 1
|
||||
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
|
||||
#define SQLITE_OMIT_SHARED_CACHE 1
|
||||
#define SQLITE_DEFAULT_MEMSTATUS 0
|
||||
#define SQLITE_MAX_EXPR_DEPTH 0
|
||||
INCLUDE sqlite3.c
|
||||
INCLUDE $ROOT/src/tclsqlite.c
|
||||
INCLUDE $ROOT/ext/misc/btreeinfo.c
|
||||
INCLUDE $ROOT/ext/repair/checkindex.c
|
||||
INCLUDE $ROOT/ext/repair/checkfreelist.c
|
||||
|
||||
/*
|
||||
** Decode a pointer to an sqlite3 object.
|
||||
*/
|
||||
int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
|
||||
struct SqliteDb *p;
|
||||
Tcl_CmdInfo cmdInfo;
|
||||
if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
|
||||
p = (struct SqliteDb*)cmdInfo.objClientData;
|
||||
*ppDb = p->db;
|
||||
return TCL_OK;
|
||||
}else{
|
||||
*ppDb = 0;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_imposter db main rootpage {CREATE TABLE...} ;# setup an imposter
|
||||
** sqlite3_imposter db main ;# rm all imposters
|
||||
*/
|
||||
static int sqlite3_imposter(
|
||||
void *clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
const char *zSchema;
|
||||
int iRoot;
|
||||
const char *zSql;
|
||||
|
||||
if( objc!=3 && objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zSchema = Tcl_GetString(objv[2]);
|
||||
if( objc==3 ){
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1);
|
||||
}else{
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR;
|
||||
zSql = Tcl_GetString(objv[4]);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot);
|
||||
sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
const char *sqlite3_checker_init_proc(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(interp, "sqlite3_imposter",
|
||||
(Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0);
|
||||
sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init);
|
||||
sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init);
|
||||
sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init);
|
||||
return
|
||||
BEGIN_STRING
|
||||
INCLUDE $ROOT/ext/repair/sqlite3_checker.tcl
|
||||
END_STRING
|
||||
;
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
# This TCL script is the main driver script for the sqlite3_checker utility
|
||||
# program.
|
||||
#
|
||||
|
||||
# Special case:
|
||||
#
|
||||
# sqlite3_checker --test FILENAME ARGS
|
||||
#
|
||||
# uses FILENAME in place of this script.
|
||||
#
|
||||
if {[lindex $argv 0]=="--test" && [llength $argv]>1} {
|
||||
set ::argv0 [lindex $argv 1]
|
||||
set argv [lrange $argv 2 end]
|
||||
source $argv0
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Emulate a TCL shell
|
||||
#
|
||||
proc tclsh {} {
|
||||
set line {}
|
||||
while {![eof stdin]} {
|
||||
if {$line!=""} {
|
||||
puts -nonewline "> "
|
||||
} else {
|
||||
puts -nonewline "% "
|
||||
}
|
||||
flush stdout
|
||||
append line [gets stdin]
|
||||
if {[info complete $line]} {
|
||||
if {[catch {uplevel #0 $line} result]} {
|
||||
puts stderr "Error: $result"
|
||||
} elseif {$result!=""} {
|
||||
puts $result
|
||||
}
|
||||
set line {}
|
||||
} else {
|
||||
append line \n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Do an incremental integrity check of a single index
|
||||
#
|
||||
proc check_index {idxname batchsize bTrace} {
|
||||
set i 0
|
||||
set more 1
|
||||
set nerr 0
|
||||
set pct 00.0
|
||||
set max [db one {SELECT nEntry FROM sqlite_btreeinfo('main')
|
||||
WHERE name=$idxname}]
|
||||
puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
|
||||
flush stdout
|
||||
if {$bTrace} {
|
||||
set sql {SELECT errmsg, current_key AS key,
|
||||
CASE WHEN rowid=1 THEN scanner_sql END AS traceOut
|
||||
FROM incremental_index_check($idxname)
|
||||
WHERE after_key=$key
|
||||
LIMIT $batchsize}
|
||||
} else {
|
||||
set sql {SELECT errmsg, current_key AS key, NULL AS traceOut
|
||||
FROM incremental_index_check($idxname)
|
||||
WHERE after_key=$key
|
||||
LIMIT $batchsize}
|
||||
}
|
||||
while {$more} {
|
||||
set more 0
|
||||
db eval $sql {
|
||||
set more 1
|
||||
if {$errmsg!=""} {
|
||||
incr nerr
|
||||
puts "$idxname: key($key): $errmsg"
|
||||
} elseif {$traceOut!=""} {
|
||||
puts "$idxname: $traceOut"
|
||||
}
|
||||
incr i
|
||||
|
||||
}
|
||||
set x [format {%.1f} [expr {($i*100.0)/$max}]]
|
||||
if {$x!=$pct} {
|
||||
puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
|
||||
flush stdout
|
||||
set pct $x
|
||||
}
|
||||
}
|
||||
puts "$idxname: $nerr errors out of $i entries"
|
||||
}
|
||||
|
||||
# Print a usage message on standard error, then quit.
|
||||
#
|
||||
proc usage {} {
|
||||
set argv0 [file rootname [file tail [info nameofexecutable]]]
|
||||
puts stderr "Usage: $argv0 OPTIONS database-filename"
|
||||
puts stderr {
|
||||
Do sanity checking on a live SQLite3 database file specified by the
|
||||
"database-filename" argument.
|
||||
|
||||
Options:
|
||||
|
||||
--batchsize N Number of rows to check per transaction
|
||||
|
||||
--freelist Perform a freelist check
|
||||
|
||||
--index NAME Run a check of the index NAME
|
||||
|
||||
--summary Print summary information about the database
|
||||
|
||||
--table NAME Run a check of all indexes for table NAME
|
||||
|
||||
--tclsh Run the built-in TCL interpreter (for debugging)
|
||||
|
||||
--trace (Debugging only:) Output trace information on the scan
|
||||
|
||||
--version Show the version number of SQLite
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
set file_to_analyze {}
|
||||
append argv {}
|
||||
set bFreelistCheck 0
|
||||
set bSummary 0
|
||||
set zIndex {}
|
||||
set zTable {}
|
||||
set batchsize 1000
|
||||
set bAll 1
|
||||
set bTrace 0
|
||||
set argc [llength $argv]
|
||||
for {set i 0} {$i<$argc} {incr i} {
|
||||
set arg [lindex $argv $i]
|
||||
if {[regexp {^-+tclsh$} $arg]} {
|
||||
tclsh
|
||||
exit 0
|
||||
}
|
||||
if {[regexp {^-+version$} $arg]} {
|
||||
sqlite3 mem :memory:
|
||||
puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
|
||||
mem close
|
||||
exit 0
|
||||
}
|
||||
if {[regexp {^-+freelist$} $arg]} {
|
||||
set bFreelistCheck 1
|
||||
set bAll 0
|
||||
continue
|
||||
}
|
||||
if {[regexp {^-+summary$} $arg]} {
|
||||
set bSummary 1
|
||||
set bAll 0
|
||||
continue
|
||||
}
|
||||
if {[regexp {^-+trace$} $arg]} {
|
||||
set bTrace 1
|
||||
continue
|
||||
}
|
||||
if {[regexp {^-+batchsize$} $arg]} {
|
||||
incr i
|
||||
if {$i>=$argc} {
|
||||
puts stderr "missing argument on $arg"
|
||||
exit 1
|
||||
}
|
||||
set batchsize [lindex $argv $i]
|
||||
continue
|
||||
}
|
||||
if {[regexp {^-+index$} $arg]} {
|
||||
incr i
|
||||
if {$i>=$argc} {
|
||||
puts stderr "missing argument on $arg"
|
||||
exit 1
|
||||
}
|
||||
set zIndex [lindex $argv $i]
|
||||
set bAll 0
|
||||
continue
|
||||
}
|
||||
if {[regexp {^-+table$} $arg]} {
|
||||
incr i
|
||||
if {$i>=$argc} {
|
||||
puts stderr "missing argument on $arg"
|
||||
exit 1
|
||||
}
|
||||
set zTable [lindex $argv $i]
|
||||
set bAll 0
|
||||
continue
|
||||
}
|
||||
if {[regexp {^-} $arg]} {
|
||||
puts stderr "Unknown option: $arg"
|
||||
usage
|
||||
}
|
||||
if {$file_to_analyze!=""} {
|
||||
usage
|
||||
} else {
|
||||
set file_to_analyze $arg
|
||||
}
|
||||
}
|
||||
if {$file_to_analyze==""} usage
|
||||
|
||||
# If a TCL script is specified on the command-line, then run that
|
||||
# script.
|
||||
#
|
||||
if {[file extension $file_to_analyze]==".tcl"} {
|
||||
source $file_to_analyze
|
||||
exit 0
|
||||
}
|
||||
|
||||
set root_filename $file_to_analyze
|
||||
regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
|
||||
if {![file exists $root_filename]} {
|
||||
puts stderr "No such file: $root_filename"
|
||||
exit 1
|
||||
}
|
||||
if {![file readable $root_filename]} {
|
||||
puts stderr "File is not readable: $root_filename"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if {[catch {sqlite3 db $file_to_analyze} res]} {
|
||||
puts stderr "Cannot open datababase $root_filename: $res"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if {$bFreelistCheck || $bAll} {
|
||||
puts -nonewline "freelist-check: "
|
||||
flush stdout
|
||||
db eval BEGIN
|
||||
puts [db one {SELECT checkfreelist('main')}]
|
||||
db eval END
|
||||
}
|
||||
if {$bSummary} {
|
||||
set scale 0
|
||||
set pgsz [db one {PRAGMA page_size}]
|
||||
db eval {SELECT nPage*$pgsz AS sz, name, tbl_name
|
||||
FROM sqlite_btreeinfo
|
||||
WHERE type='index'
|
||||
ORDER BY 1 DESC, name} {
|
||||
if {$scale==0} {
|
||||
if {$sz>10000000} {
|
||||
set scale 1000000.0
|
||||
set unit MB
|
||||
} else {
|
||||
set scale 1000.0
|
||||
set unit KB
|
||||
}
|
||||
}
|
||||
puts [format {%7.1f %s index %s of table %s} \
|
||||
[expr {$sz/$scale}] $unit $name $tbl_name]
|
||||
}
|
||||
}
|
||||
if {$zIndex!=""} {
|
||||
check_index $zIndex $batchsize $bTrace
|
||||
}
|
||||
if {$zTable!=""} {
|
||||
foreach idx [db eval {SELECT name FROM sqlite_master
|
||||
WHERE type='index' AND rootpage>0
|
||||
AND tbl_name=$zTable}] {
|
||||
check_index $idx $batchsize $bTrace
|
||||
}
|
||||
}
|
||||
if {$bAll} {
|
||||
set allidx [db eval {SELECT name FROM sqlite_btreeinfo('main')
|
||||
WHERE type='index' AND rootpage>0
|
||||
ORDER BY nEntry}]
|
||||
foreach idx $allidx {
|
||||
check_index $idx $batchsize $bTrace
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
To run these tests, first build sqlite3_checker:
|
||||
|
||||
|
||||
> make sqlite3_checker
|
||||
|
||||
|
||||
Then run the "test.tcl" script using:
|
||||
|
||||
|
||||
> ./sqlite3_checker --test $path/test.tcl
|
||||
|
||||
|
||||
Optionally add the full pathnames of individual *.test modules
|
||||
@@ -1,92 +0,0 @@
|
||||
# 2017-10-11
|
||||
|
||||
set testprefix checkfreelist
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA page_size=1024;
|
||||
CREATE TABLE t1(a, b);
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 { SELECT checkfreelist('main') } {ok}
|
||||
do_execsql_test 1.3 {
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
|
||||
)
|
||||
INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
|
||||
DELETE FROM t1 WHERE rowid%3;
|
||||
PRAGMA freelist_count;
|
||||
} {6726}
|
||||
|
||||
do_execsql_test 1.4 { SELECT checkfreelist('main') } {ok}
|
||||
do_execsql_test 1.5 {
|
||||
WITH freelist_trunk(i, d, n) AS (
|
||||
SELECT 1, NULL, sqlite_readint32(data, 32) FROM sqlite_dbpage WHERE pgno=1
|
||||
UNION ALL
|
||||
SELECT n, data, sqlite_readint32(data)
|
||||
FROM freelist_trunk, sqlite_dbpage WHERE pgno=n
|
||||
)
|
||||
SELECT i FROM freelist_trunk WHERE i!=1;
|
||||
} {
|
||||
10009 9715 9343 8969 8595 8222 7847 7474 7102 6727 6354 5982 5608 5234
|
||||
4860 4487 4112 3740 3367 2992 2619 2247 1872 1499 1125 752 377 5
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 { SELECT checkfreelist('main') } {ok}
|
||||
|
||||
proc set_int {blob idx newval} {
|
||||
binary scan $blob I* ints
|
||||
lset ints $idx $newval
|
||||
binary format I* $ints
|
||||
}
|
||||
db func set_int set_int
|
||||
|
||||
proc get_int {blob idx} {
|
||||
binary scan $blob I* ints
|
||||
lindex $ints $idx
|
||||
}
|
||||
db func get_int get_int
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
BEGIN;
|
||||
UPDATE sqlite_dbpage
|
||||
SET data = set_int(data, 1, get_int(data, 1)-1)
|
||||
WHERE pgno=4860;
|
||||
SELECT checkfreelist('main');
|
||||
ROLLBACK;
|
||||
} {{free-list count mismatch: actual=6725 header=6726}}
|
||||
|
||||
do_execsql_test 1.8 {
|
||||
BEGIN;
|
||||
UPDATE sqlite_dbpage
|
||||
SET data = set_int(data, 5, (SELECT * FROM pragma_page_count)+1)
|
||||
WHERE pgno=4860;
|
||||
SELECT checkfreelist('main');
|
||||
ROLLBACK;
|
||||
} {{leaf page 10092 is out of range (child 3 of trunk page 4860)}}
|
||||
|
||||
do_execsql_test 1.9 {
|
||||
BEGIN;
|
||||
UPDATE sqlite_dbpage
|
||||
SET data = set_int(data, 5, 0)
|
||||
WHERE pgno=4860;
|
||||
SELECT checkfreelist('main');
|
||||
ROLLBACK;
|
||||
} {{leaf page 0 is out of range (child 3 of trunk page 4860)}}
|
||||
|
||||
do_execsql_test 1.10 {
|
||||
BEGIN;
|
||||
UPDATE sqlite_dbpage
|
||||
SET data = set_int(data, get_int(data, 1)+1, 0)
|
||||
WHERE pgno=5;
|
||||
SELECT checkfreelist('main');
|
||||
ROLLBACK;
|
||||
} {{leaf page 0 is out of range (child 247 of trunk page 5)}}
|
||||
|
||||
do_execsql_test 1.11 {
|
||||
BEGIN;
|
||||
UPDATE sqlite_dbpage
|
||||
SET data = set_int(data, 1, 249)
|
||||
WHERE pgno=5;
|
||||
SELECT checkfreelist('main');
|
||||
ROLLBACK;
|
||||
} {{leaf count out of range (249) on trunk page 5}}
|
||||
@@ -1,349 +0,0 @@
|
||||
# 2017-10-11
|
||||
#
|
||||
set testprefix checkindex
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
INSERT INTO t1 VALUES('one', 2);
|
||||
INSERT INTO t1 VALUES('two', 4);
|
||||
INSERT INTO t1 VALUES('three', 6);
|
||||
INSERT INTO t1 VALUES('four', 8);
|
||||
INSERT INTO t1 VALUES('five', 10);
|
||||
|
||||
CREATE INDEX i2 ON t1(a DESC);
|
||||
} {}
|
||||
|
||||
proc incr_index_check {idx nStep} {
|
||||
set Q {
|
||||
SELECT errmsg, current_key FROM incremental_index_check($idx, $after)
|
||||
LIMIT $nStep
|
||||
}
|
||||
|
||||
set res [list]
|
||||
while {1} {
|
||||
unset -nocomplain current_key
|
||||
set res1 [db eval $Q]
|
||||
if {[llength $res1]==0} break
|
||||
set res [concat $res $res1]
|
||||
set after [lindex $res end]
|
||||
}
|
||||
|
||||
return $res
|
||||
}
|
||||
|
||||
proc do_index_check_test {tn idx res} {
|
||||
uplevel [list do_execsql_test $tn.1 "
|
||||
SELECT errmsg, current_key FROM incremental_index_check('$idx');
|
||||
" $res]
|
||||
|
||||
uplevel [list do_test $tn.2 "incr_index_check $idx 1" [list {*}$res]]
|
||||
uplevel [list do_test $tn.3 "incr_index_check $idx 2" [list {*}$res]]
|
||||
uplevel [list do_test $tn.4 "incr_index_check $idx 5" [list {*}$res]]
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test 1.2.1 {
|
||||
SELECT rowid, errmsg IS NULL, current_key FROM incremental_index_check('i1');
|
||||
} {
|
||||
1 1 'five',5
|
||||
2 1 'four',4
|
||||
3 1 'one',1
|
||||
4 1 'three',3
|
||||
5 1 'two',2
|
||||
}
|
||||
do_execsql_test 1.2.2 {
|
||||
SELECT errmsg IS NULL, current_key, index_name, after_key, scanner_sql
|
||||
FROM incremental_index_check('i1') LIMIT 1;
|
||||
} {
|
||||
1
|
||||
'five',5
|
||||
i1
|
||||
{}
|
||||
{SELECT (SELECT a IS i.i0 FROM 't1' AS t WHERE "rowid" COLLATE BINARY IS i.i1), quote(i0)||','||quote(i1) FROM (SELECT (a) AS i0, ("rowid" COLLATE BINARY) AS i1 FROM 't1' INDEXED BY 'i1' ORDER BY 1,2) AS i}
|
||||
}
|
||||
|
||||
do_index_check_test 1.3 i1 {
|
||||
{} 'five',5
|
||||
{} 'four',4
|
||||
{} 'one',1
|
||||
{} 'three',3
|
||||
{} 'two',2
|
||||
}
|
||||
|
||||
do_index_check_test 1.4 i2 {
|
||||
{} 'two',2
|
||||
{} 'three',3
|
||||
{} 'one',1
|
||||
{} 'four',4
|
||||
{} 'five',5
|
||||
}
|
||||
|
||||
do_test 1.5 {
|
||||
set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t1' }]
|
||||
sqlite3_imposter db main $tblroot {CREATE TABLE xt1(a,b)}
|
||||
db eval {
|
||||
UPDATE xt1 SET a='six' WHERE rowid=3;
|
||||
DELETE FROM xt1 WHERE rowid = 5;
|
||||
}
|
||||
sqlite3_imposter db main
|
||||
} {}
|
||||
|
||||
do_index_check_test 1.6 i1 {
|
||||
{row missing} 'five',5
|
||||
{} 'four',4
|
||||
{} 'one',1
|
||||
{row data mismatch} 'three',3
|
||||
{} 'two',2
|
||||
}
|
||||
|
||||
do_index_check_test 1.7 i2 {
|
||||
{} 'two',2
|
||||
{row data mismatch} 'three',3
|
||||
{} 'one',1
|
||||
{} 'four',4
|
||||
{row missing} 'five',5
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
do_execsql_test 2.0 {
|
||||
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c, d);
|
||||
|
||||
INSERT INTO t2 VALUES(1, NULL, 1, 1);
|
||||
INSERT INTO t2 VALUES(2, 1, NULL, 1);
|
||||
INSERT INTO t2 VALUES(3, 1, 1, NULL);
|
||||
|
||||
INSERT INTO t2 VALUES(4, 2, 2, 1);
|
||||
INSERT INTO t2 VALUES(5, 2, 2, 2);
|
||||
INSERT INTO t2 VALUES(6, 2, 2, 3);
|
||||
|
||||
INSERT INTO t2 VALUES(7, 2, 2, 1);
|
||||
INSERT INTO t2 VALUES(8, 2, 2, 2);
|
||||
INSERT INTO t2 VALUES(9, 2, 2, 3);
|
||||
|
||||
CREATE INDEX i3 ON t2(b, c, d);
|
||||
CREATE INDEX i4 ON t2(b DESC, c DESC, d DESC);
|
||||
CREATE INDEX i5 ON t2(d, c DESC, b);
|
||||
} {}
|
||||
|
||||
do_index_check_test 2.1 i3 {
|
||||
{} NULL,1,1,1
|
||||
{} 1,NULL,1,2
|
||||
{} 1,1,NULL,3
|
||||
{} 2,2,1,4
|
||||
{} 2,2,1,7
|
||||
{} 2,2,2,5
|
||||
{} 2,2,2,8
|
||||
{} 2,2,3,6
|
||||
{} 2,2,3,9
|
||||
}
|
||||
|
||||
do_index_check_test 2.2 i4 {
|
||||
{} 2,2,3,6
|
||||
{} 2,2,3,9
|
||||
{} 2,2,2,5
|
||||
{} 2,2,2,8
|
||||
{} 2,2,1,4
|
||||
{} 2,2,1,7
|
||||
{} 1,1,NULL,3
|
||||
{} 1,NULL,1,2
|
||||
{} NULL,1,1,1
|
||||
}
|
||||
|
||||
do_index_check_test 2.3 i5 {
|
||||
{} NULL,1,1,3
|
||||
{} 1,2,2,4
|
||||
{} 1,2,2,7
|
||||
{} 1,1,NULL,1
|
||||
{} 1,NULL,1,2
|
||||
{} 2,2,2,5
|
||||
{} 2,2,2,8
|
||||
{} 3,2,2,6
|
||||
{} 3,2,2,9
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
do_execsql_test 3.0 {
|
||||
|
||||
CREATE TABLE t3(w, x, y, z PRIMARY KEY) WITHOUT ROWID;
|
||||
CREATE INDEX t3wxy ON t3(w, x, y);
|
||||
CREATE INDEX t3wxy2 ON t3(w DESC, x DESC, y DESC);
|
||||
|
||||
INSERT INTO t3 VALUES(NULL, NULL, NULL, 1);
|
||||
INSERT INTO t3 VALUES(NULL, NULL, NULL, 2);
|
||||
INSERT INTO t3 VALUES(NULL, NULL, NULL, 3);
|
||||
|
||||
INSERT INTO t3 VALUES('a', NULL, NULL, 4);
|
||||
INSERT INTO t3 VALUES('a', NULL, NULL, 5);
|
||||
INSERT INTO t3 VALUES('a', NULL, NULL, 6);
|
||||
|
||||
INSERT INTO t3 VALUES('a', 'b', NULL, 7);
|
||||
INSERT INTO t3 VALUES('a', 'b', NULL, 8);
|
||||
INSERT INTO t3 VALUES('a', 'b', NULL, 9);
|
||||
|
||||
} {}
|
||||
|
||||
do_index_check_test 3.1 t3wxy {
|
||||
{} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3
|
||||
{} 'a',NULL,NULL,4 {} 'a',NULL,NULL,5 {} 'a',NULL,NULL,6
|
||||
{} 'a','b',NULL,7 {} 'a','b',NULL,8 {} 'a','b',NULL,9
|
||||
}
|
||||
do_index_check_test 3.2 t3wxy2 {
|
||||
{} 'a','b',NULL,7 {} 'a','b',NULL,8 {} 'a','b',NULL,9
|
||||
{} 'a',NULL,NULL,4 {} 'a',NULL,NULL,5 {} 'a',NULL,NULL,6
|
||||
{} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test with an index that uses non-default collation sequences.
|
||||
#
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT);
|
||||
INSERT INTO t4 VALUES(1, 'aaa', 'bbb');
|
||||
INSERT INTO t4 VALUES(2, 'AAA', 'CCC');
|
||||
INSERT INTO t4 VALUES(3, 'aab', 'ddd');
|
||||
INSERT INTO t4 VALUES(4, 'AAB', 'EEE');
|
||||
|
||||
CREATE INDEX t4cc ON t4(c1 COLLATE nocase, c2 COLLATE nocase);
|
||||
}
|
||||
|
||||
do_index_check_test 4.1 t4cc {
|
||||
{} 'aaa','bbb',1
|
||||
{} 'AAA','CCC',2
|
||||
{} 'aab','ddd',3
|
||||
{} 'AAB','EEE',4
|
||||
}
|
||||
|
||||
do_test 4.2 {
|
||||
set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t4' }]
|
||||
sqlite3_imposter db main $tblroot \
|
||||
{CREATE TABLE xt4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT)}
|
||||
|
||||
db eval {
|
||||
UPDATE xt4 SET c1='hello' WHERE rowid=2;
|
||||
DELETE FROM xt4 WHERE rowid = 3;
|
||||
}
|
||||
sqlite3_imposter db main
|
||||
} {}
|
||||
|
||||
do_index_check_test 4.3 t4cc {
|
||||
{} 'aaa','bbb',1
|
||||
{row data mismatch} 'AAA','CCC',2
|
||||
{row missing} 'aab','ddd',3
|
||||
{} 'AAB','EEE',4
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test an index on an expression.
|
||||
#
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t5(x INTEGER PRIMARY KEY, y TEXT, UNIQUE(y));
|
||||
INSERT INTO t5 VALUES(1, '{"x":1, "y":1}');
|
||||
INSERT INTO t5 VALUES(2, '{"x":2, "y":2}');
|
||||
INSERT INTO t5 VALUES(3, '{"x":3, "y":3}');
|
||||
INSERT INTO t5 VALUES(4, '{"w":4, "z":4}');
|
||||
INSERT INTO t5 VALUES(5, '{"x":5, "y":5}');
|
||||
|
||||
CREATE INDEX t5x ON t5( json_extract(y, '$.x') );
|
||||
CREATE INDEX t5y ON t5( json_extract(y, '$.y') DESC );
|
||||
}
|
||||
|
||||
do_index_check_test 5.1.1 t5x {
|
||||
{} NULL,4 {} 1,1 {} 2,2 {} 3,3 {} 5,5
|
||||
}
|
||||
|
||||
do_index_check_test 5.1.2 t5y {
|
||||
{} 5,5 {} 3,3 {} 2,2 {} 1,1 {} NULL,4
|
||||
}
|
||||
|
||||
do_index_check_test 5.1.3 sqlite_autoindex_t5_1 {
|
||||
{} {'{"w":4, "z":4}',4}
|
||||
{} {'{"x":1, "y":1}',1}
|
||||
{} {'{"x":2, "y":2}',2}
|
||||
{} {'{"x":3, "y":3}',3}
|
||||
{} {'{"x":5, "y":5}',5}
|
||||
}
|
||||
|
||||
do_test 5.2 {
|
||||
set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t5' }]
|
||||
sqlite3_imposter db main $tblroot \
|
||||
{CREATE TABLE xt5(a INTEGER PRIMARY KEY, c1 TEXT);}
|
||||
db eval {
|
||||
UPDATE xt5 SET c1='{"x":22, "y":11}' WHERE rowid=1;
|
||||
DELETE FROM xt5 WHERE rowid = 4;
|
||||
}
|
||||
sqlite3_imposter db main
|
||||
} {}
|
||||
|
||||
do_index_check_test 5.3.1 t5x {
|
||||
{row missing} NULL,4
|
||||
{row data mismatch} 1,1
|
||||
{} 2,2
|
||||
{} 3,3
|
||||
{} 5,5
|
||||
}
|
||||
|
||||
do_index_check_test 5.3.2 sqlite_autoindex_t5_1 {
|
||||
{row missing} {'{"w":4, "z":4}',4}
|
||||
{row data mismatch} {'{"x":1, "y":1}',1}
|
||||
{} {'{"x":2, "y":2}',2}
|
||||
{} {'{"x":3, "y":3}',3}
|
||||
{} {'{"x":5, "y":5}',5}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t6(x INTEGER PRIMARY KEY, y, z);
|
||||
CREATE INDEX t6x1 ON t6(y, /* one,two,three */ z);
|
||||
CREATE INDEX t6x2 ON t6(z, -- hello,world,
|
||||
y);
|
||||
|
||||
CREATE INDEX t6x3 ON t6(z -- hello,world
|
||||
, y);
|
||||
|
||||
INSERT INTO t6 VALUES(1, 2, 3);
|
||||
INSERT INTO t6 VALUES(4, 5, 6);
|
||||
}
|
||||
|
||||
do_index_check_test 6.1 t6x1 {
|
||||
{} 2,3,1
|
||||
{} 5,6,4
|
||||
}
|
||||
do_index_check_test 6.2 t6x2 {
|
||||
{} 3,2,1
|
||||
{} 6,5,4
|
||||
}
|
||||
do_index_check_test 6.2 t6x3 {
|
||||
{} 3,2,1
|
||||
{} 6,5,4
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE t7(x INTEGER PRIMARY KEY, y, z);
|
||||
INSERT INTO t7 VALUES(1, 1, 1);
|
||||
INSERT INTO t7 VALUES(2, 2, 0);
|
||||
INSERT INTO t7 VALUES(3, 3, 1);
|
||||
INSERT INTO t7 VALUES(4, 4, 0);
|
||||
|
||||
CREATE INDEX t7i1 ON t7(y) WHERE z=1;
|
||||
CREATE INDEX t7i2 ON t7(y) /* hello,world */ WHERE z=1;
|
||||
CREATE INDEX t7i3 ON t7(y) WHERE -- yep
|
||||
z=1;
|
||||
CREATE INDEX t7i4 ON t7(y) WHERE z=1 -- yep;
|
||||
}
|
||||
do_index_check_test 7.1 t7i1 {
|
||||
{} 1,1 {} 3,3
|
||||
}
|
||||
do_index_check_test 7.2 t7i2 {
|
||||
{} 1,1 {} 3,3
|
||||
}
|
||||
do_index_check_test 7.3 t7i3 {
|
||||
{} 1,1 {} 3,3
|
||||
}
|
||||
do_index_check_test 7.4 t7i4 {
|
||||
{} 1,1 {} 3,3
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
# Run this script using
|
||||
#
|
||||
# sqlite3_checker --test $thisscript $testscripts
|
||||
#
|
||||
# The $testscripts argument is optional. If omitted, all *.test files
|
||||
# in the same directory as $thisscript are run.
|
||||
#
|
||||
set NTEST 0
|
||||
set NERR 0
|
||||
|
||||
|
||||
# Invoke the do_test procedure to run a single test
|
||||
#
|
||||
# The $expected parameter is the expected result. The result is the return
|
||||
# value from the last TCL command in $cmd.
|
||||
#
|
||||
# Normally, $expected must match exactly. But if $expected is of the form
|
||||
# "/regexp/" then regular expression matching is used. If $expected is
|
||||
# "~/regexp/" then the regular expression must NOT match. If $expected is
|
||||
# of the form "#/value-list/" then each term in value-list must be numeric
|
||||
# and must approximately match the corresponding numeric term in $result.
|
||||
# Values must match within 10%. Or if the $expected term is A..B then the
|
||||
# $result term must be in between A and B.
|
||||
#
|
||||
proc do_test {name cmd expected} {
|
||||
if {[info exists ::testprefix]} {
|
||||
set name "$::testprefix$name"
|
||||
}
|
||||
|
||||
incr ::NTEST
|
||||
puts -nonewline $name...
|
||||
flush stdout
|
||||
|
||||
if {[catch {uplevel #0 "$cmd;\n"} result]} {
|
||||
puts -nonewline $name...
|
||||
puts "\nError: $result"
|
||||
incr ::NERR
|
||||
} else {
|
||||
set ok [expr {[string compare $result $expected]==0}]
|
||||
if {!$ok} {
|
||||
puts "\n! $name expected: \[$expected\]\n! $name got: \[$result\]"
|
||||
incr ::NERR
|
||||
} else {
|
||||
puts " Ok"
|
||||
}
|
||||
}
|
||||
flush stdout
|
||||
}
|
||||
|
||||
#
|
||||
# do_execsql_test TESTNAME SQL RES
|
||||
#
|
||||
proc do_execsql_test {testname sql {result {}}} {
|
||||
uplevel [list do_test $testname [list db eval $sql] [list {*}$result]]
|
||||
}
|
||||
|
||||
if {[llength $argv]==0} {
|
||||
set dir [file dirname $argv0]
|
||||
set argv [glob -nocomplain $dir/*.test]
|
||||
}
|
||||
foreach testfile $argv {
|
||||
file delete -force test.db
|
||||
sqlite3 db test.db
|
||||
source $testfile
|
||||
catch {db close}
|
||||
}
|
||||
puts "$NERR errors out of $NTEST tests"
|
||||
+1
-1
@@ -200,7 +200,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
|
||||
/* The sqlite3AtoF() routine is much much faster than atof(), if it
|
||||
** is available */
|
||||
double r;
|
||||
(void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
|
||||
(void)sqlite3AtoF((const char*)p->z, &r);
|
||||
*pVal = r;
|
||||
#else
|
||||
*pVal = (GeoCoord)atof((const char*)p->z);
|
||||
|
||||
@@ -206,7 +206,7 @@ b.mkdir@ = if [ ! -d $(dir $@) ]; then \
|
||||
# $1 = logtag, $2 = src file(s). $3 = dest dir
|
||||
b.cp = $(call b.mkdir@); \
|
||||
echo '$(logtag.$(1)) $(emo.disk) $(2) ==> $3'; \
|
||||
cp -p $(2) $(3) || exit
|
||||
cp -f -p $(2) $(3) || exit
|
||||
|
||||
#
|
||||
# $(call b.c-pp.shcmd,LOGTAG,src,dest,-Dx=y...)
|
||||
|
||||
@@ -209,17 +209,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
and recreating it whenever a property index might be invalidated.
|
||||
*/
|
||||
class KVVfsStorage {
|
||||
#map;
|
||||
#keys;
|
||||
#getKeys(){return this.#keys ??= Object.keys(this.#map);}
|
||||
#map = Object.create(null);
|
||||
#keys = null;
|
||||
#size = 0;
|
||||
|
||||
constructor(){
|
||||
this.clear();
|
||||
}
|
||||
|
||||
#getKeys(){
|
||||
return this.#keys ??= Object.keys(this.#map);
|
||||
}
|
||||
|
||||
key(n){
|
||||
const k = this.#getKeys();
|
||||
return n<k.length ? k[n] : null;
|
||||
if(n < 0 || n >= this.#size) return null;
|
||||
return this.#getKeys()[n];
|
||||
}
|
||||
|
||||
getItem(k){
|
||||
@@ -227,14 +231,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}
|
||||
|
||||
setItem(k,v){
|
||||
if( !hop(this.#map, k) ){
|
||||
if( !(k in this.#map) ){
|
||||
++this.#size;
|
||||
this.#keys = null;
|
||||
}
|
||||
this.#map[k] = ''+v;
|
||||
}
|
||||
|
||||
removeItem(k){
|
||||
if( delete this.#map[k] ){
|
||||
if( k in this.#map ){
|
||||
delete this.#map[k];
|
||||
--this.#size;
|
||||
this.#keys = null;
|
||||
}
|
||||
}
|
||||
@@ -242,10 +249,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
clear(){
|
||||
this.#map = Object.create(null);
|
||||
this.#keys = null;
|
||||
this.#size = 0;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.#getKeys().length;
|
||||
return this.#size;
|
||||
}
|
||||
}/*KVVfsStorage*/;
|
||||
|
||||
|
||||
@@ -994,10 +994,17 @@ static void mk_fiddle(void){
|
||||
pf("$(out.%s.js): $(MAKEFILE_LIST) "
|
||||
"$(EXPORTED_FUNCTIONS.fiddle) "
|
||||
"$(fiddle.c.in) "
|
||||
"$(pre-post.%s.deps)\n",
|
||||
"$(pre-post.%s.deps)",
|
||||
zBuildName, zBuildName);
|
||||
if( isDebug ){
|
||||
pf(" $(dir.fiddle)/fiddle-worker.js"
|
||||
" $(dir.fiddle)/fiddle.js"
|
||||
" $(dir.fiddle)/index.html");
|
||||
}
|
||||
ps("");
|
||||
emit_compile_start(zBuildName);
|
||||
pf("\t$(b.cmd@)$(bin.emcc) -o $@"
|
||||
pf("\t@$(call b.mkdir@)\n"
|
||||
"\t$(b.cmd@)$(bin.emcc) -o $@"
|
||||
" $(emcc.flags.%s)" /* set in GNUmakefile */
|
||||
" $(pre-post.%s.flags)"
|
||||
" $(fiddle.c.in)"
|
||||
|
||||
@@ -1971,24 +1971,6 @@ sqlite3_expert$(T.exe): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqli
|
||||
$(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert $(LDFLAGS.libsqlite3)
|
||||
xbin: sqlite3_expert$(T.exe)
|
||||
|
||||
CHECKER_DEPS =\
|
||||
$(TOP)/tool/mkccode.tcl \
|
||||
sqlite3.c \
|
||||
tclsqlite-ex.c \
|
||||
$(TOP)/ext/repair/sqlite3_checker.tcl \
|
||||
$(TOP)/ext/repair/checkindex.c \
|
||||
$(TOP)/ext/repair/checkfreelist.c \
|
||||
$(TOP)/ext/misc/btreeinfo.c \
|
||||
$(TOP)/ext/repair/sqlite3_checker.c.in
|
||||
|
||||
sqlite3_checker.c: $(CHECKER_DEPS)
|
||||
$(B.tclsh) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
|
||||
|
||||
sqlite3_checker$(T.exe): $(T.tcl.env.sh) sqlite3_checker.c
|
||||
$(T.link.tcl) sqlite3_checker.c -o $@ $$TCL_INCLUDE_SPEC \
|
||||
$$TCL_LIB_SPEC $(LDFLAGS.libsqlite3)
|
||||
xbin: sqlite3_checker$(T.exe)
|
||||
|
||||
dbdump$(T.exe): $(TOP)/ext/misc/dbdump.c sqlite3.o
|
||||
$(T.link) -DDBDUMP_STANDALONE -o $@ \
|
||||
$(TOP)/ext/misc/dbdump.c sqlite3.o $(LDFLAGS.libsqlite3)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Avoid\sthe\sbig\spower-of-ten\slookup\stable.
|
||||
D 2026-02-15T18:41:29.104
|
||||
C Do\snot\srun\stest\sscript\swalrestart.test\swith\sthe\s"memsubsys1"\spermutation.
|
||||
D 2026-03-03T18:34:38.064
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
|
||||
F Makefile.in 3ce07126d7e87c7464301482e161fdae6a51d0a2aa06b200b8f0000ef4d6163b
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 1fa179beafd6d438b8479146cae77fb1724dd35b330b09dbfebd8a2f0823c62a
|
||||
F Makefile.msc 174764cb7e80c80f9003c46b3e388d74c68c8c40230208904b3af8fcabee5f4e
|
||||
F README.md 3fa51fc7ababc32edd175ae8b2986c86d5ea120c1cb1e57c7f7849492d1405ec
|
||||
F VERSION 74672bfd4c7826c0fc6f84762488a707c52e7d2d94af42ccb0edcc6c74311c41
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@@ -108,21 +108,21 @@ 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 da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
|
||||
F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
|
||||
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
|
||||
F ext/fts5/fts5_expr.c b8c32da1127bafaf10d6b4768b0dcb92285798524bed2d87a8686f99a8e8d259
|
||||
F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
|
||||
F ext/fts5/fts5_index.c 9b8118bfd0c2a4c3d3482d69ad28ba811fcc2d32e6ff7cf0634cec1c00b9d3da
|
||||
F ext/fts5/fts5_main.c 4e7dc11824e681215c2ac6b702124918b946616f85e0d54f88d0f156152387ee
|
||||
F ext/fts5/fts5_aux.c 042da27e97d38071312c111cf18f3cb7983b75ba5e724aa1c3164e61e90f428a
|
||||
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 f8cfa37bb7397e5ede20242e4c9cb030bc8b4584ce3f23a5e2495038c0ae64bd
|
||||
F ext/fts5/fts5_main.c 6889f1373c469d515e792fb3d783c2218e63c560433ebd66edc0f740ab086c1b
|
||||
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
|
||||
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
|
||||
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
|
||||
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
F ext/fts5/fts5_tokenize.c 49aea8cc400a690a6c4f83c4cedc67f4f8830c6789c4ee343404f62bcaebca7b
|
||||
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
|
||||
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
|
||||
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c 23e263ad94ac357cfffd19bd7e001c3f15c4420fb10fa35b5993142127e780e6
|
||||
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
|
||||
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl c5aa7cf7148b6dcffb5b61520ae18212baf169936af734ab265143f59db328fe
|
||||
@@ -199,7 +199,7 @@ F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e
|
||||
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c6766251578a103e8a14
|
||||
F ext/fts5/test/fts5integrity.test c423ce16fd1ccadcac7fc22f794226b2bb00f5a187c0ab1d9f8502521b1bae05
|
||||
F ext/fts5/test/fts5integrity.test 613efcebe16b2d7a4096f03bcfb164f79a000b3354420ceda4a6f3e035090789
|
||||
F ext/fts5/test/fts5integrity2.test 4c3636615c0201232c44a8105d5cb14fd5499fd0ee3014d7ffd7e83aac76ece8
|
||||
F ext/fts5/test/fts5interrupt.test af7834ac6c2e71c05aea42d92f272eef3655e89b7a14a5620a2cd9de35e2e8ea
|
||||
F ext/fts5/test/fts5join.test 48b7ed36956948c5b8456c8bcaa5b087808d99000675918a43c4f51a925f1514
|
||||
@@ -285,7 +285,7 @@ F ext/intck/intck_common.tcl a61fd2697ae55b0a3d89847ca0b590c6e0d8ff64bebb70920d9
|
||||
F ext/intck/intckbusy.test d5ed4ef85a4b1dc1dee2484bd14a4bb68529659cca743327df0c775f005fa387
|
||||
F ext/intck/intckcorrupt.test f6c302792326fb3db9dcfc70b554c55369bc4b52882eaaf039cfe0b74c821029
|
||||
F ext/intck/intckfault.test cff3f75dff74abb3edfcb13f6aa53f6436746ab64b09fe5e2028f051e985efab
|
||||
F ext/intck/sqlite3intck.c b1c8a86f90fc00741d13314db9c58f7e2f92d1d19c5ad1c6904ec83a6bbd5c96
|
||||
F ext/intck/sqlite3intck.c 3c4a166645a1624731f63acd342e24e81e4ffd497116d94a427d72e6cc6caa69
|
||||
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
|
||||
F ext/intck/test_intck.c 4f9eaadaedccb9df1d26ba41116a0a8e5b0c5556dc3098c8ff68633adcccdea8
|
||||
F ext/jni/GNUmakefile 8a94e3a1953b88cf117fb2a5380480feada8b4f5316f02572cab425030a720b4
|
||||
@@ -370,13 +370,13 @@ F ext/misc/completion.c c27b64fdd0943c1b7f152376599814cee2641f7d67a7bb9bd2b957c2
|
||||
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
|
||||
F ext/misc/csv.c e82124eabee0e692d7b90ab8b2c34fadbf7b375279f102567fa06e4da4b771bf
|
||||
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
|
||||
F ext/misc/decimal.c d4883de142f6dcd36eda23da40b55e2b51374e7b01eb54a7173940191389fc5e
|
||||
F ext/misc/decimal.c e1da22eee70d7e3eaa99a6b761bc03c4d01d7ffa554bf3178b1f1f184932806c
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
|
||||
F ext/misc/fileio.c 452300ca34fadafd2bb9eb09557de5a518da1fd2349f9f9cedd22b1566a7164f
|
||||
F ext/misc/fileio.c 33165b3cd99f83dcd333a338eb51491f6b01c8d96cb6ae81f96a6a096834e030
|
||||
F ext/misc/fossildelta.c 86dfa83f85f7ccd640591d8a5c6865346d0c2ee6a949d78591eceb892f1cbfec
|
||||
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
|
||||
F ext/misc/ieee754.c 7d7ecdd9490f6746ad88e0aa4f073ea66422341dce062d24d1b4d47d2e9050d6
|
||||
F ext/misc/fuzzer.c 684a4996b523ea89f495b38fd8a14a2ae00695089a88031366a4df6adc2c873b
|
||||
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
|
||||
F ext/misc/memstat.c 43705d795090efb78c85c736b89251e743c291e23daaa8382fe7a0df2c6a283d
|
||||
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
|
||||
F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
|
||||
@@ -403,7 +403,7 @@ F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bf
|
||||
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
|
||||
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
|
||||
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
|
||||
F ext/misc/tmstmpvfs.c 3eb28a9f22f58883f38085daa312467e31ddfd2042c21dcc07173e02a01d68d8
|
||||
F ext/misc/tmstmpvfs.c 240caad4441328dc52bd2871f48811db46dff858d5598030e389176837a2f4df
|
||||
F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762bc3a8
|
||||
F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
|
||||
F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
|
||||
@@ -416,11 +416,11 @@ F ext/misc/vtablog.c 402496fb38add7dd2c50f2a0ad20f83a9916ceab48dcd31e62ad621e663
|
||||
F ext/misc/vtshim.c e5bce24ab8c532f4fdc600148718fe1802cb6ed57417f1c1032d8961f72b0e8f
|
||||
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
|
||||
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
|
||||
F ext/misc/zipfile.c 837591f0505d21f7f7937ea046c9b0fc594f7fa3ca00c2bd54ffa1c94bfccd63
|
||||
F ext/misc/zipfile.c c8ee04e1b349270b5df401ad732f5d7c387146e69b33c02fa90322760cc6fee0
|
||||
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
|
||||
F ext/qrf/README.md e6e0ce2700acf6fd06312b42726a8f08ca240f30e1b122bff87c71c602046352
|
||||
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
|
||||
F ext/qrf/qrf.c 9216879683752773fa612849b8bc6a26b74f2a7cb9253bcbdd168092d8bfbbe2
|
||||
F ext/qrf/qrf.c cd48c23500c3b129be5e0627ce9d41b5df3c2d715525b00a6ccbd1f30689fb17
|
||||
F ext/qrf/qrf.h 2ac14b0aaacf44636d8c81051bfeab4afae50a98fbb2e10ff5aed0c28a87b2b2
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
|
||||
@@ -466,7 +466,7 @@ F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f3237
|
||||
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c 3fb2390575b261c365d3f6fea61ff15e74d5d89e373f2a2bfa4d80c24321e793
|
||||
F ext/rbu/sqlite3rbu.c e99400d29d029936075e27495b269a2dcdceae3cf8c86b1d0869b4af487be3ab
|
||||
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
|
||||
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
|
||||
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
|
||||
@@ -488,17 +488,8 @@ F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e
|
||||
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
|
||||
F ext/repair/checkindex.c 7639b4f8928f82c10b950169e60cc45a7f6798df0b299771d17bef025736f657
|
||||
F ext/repair/sqlite3_checker.c.in 445118c5f7fea958b36fba1b2c464283e60ed4842039ddee3265f1698115ebf7
|
||||
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
|
||||
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
|
||||
F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
|
||||
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
|
||||
F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
|
||||
F ext/rtree/geopoly.c bd1971479184d559499ff3087c37f2823977d7b0ec80916141ae66f70345c88d
|
||||
F ext/rtree/rtree.c 9331997a76b88a9bc04e156bdfd6e2fe35c0aa93bc338ebc6aa0ae470fe4a852
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
|
||||
@@ -581,7 +572,7 @@ F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009e
|
||||
F ext/session/sqlite3session.c 6ebd02be470f36d41c4bd78927f39d507b62051ba025eacaed9936c769902a07
|
||||
F ext/session/sqlite3session.h 7404723606074fcb2afdc6b72c206072cdb2b7d8ba097ca1559174a80bc26f7a
|
||||
F ext/session/test_session.c 190110e3bd9463717248dec1272b44fe9943e57b7646d0b4200dcf11e4dccee6
|
||||
F ext/wasm/GNUmakefile a2698072853b67c39e92ca19835c65fbaa8b8884078a99c4e54b72b9ede8306e
|
||||
F ext/wasm/GNUmakefile 79236447d750609aa6beda30feec1314180c5462a493ad94214122887232bfd4
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -603,7 +594,7 @@ F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1041dd645e8e821c082b628cd8d9acf70c667
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 98d90255a12d02214db634e041c8e7f2f133d9361a8ebf000ba9c9af4c6761cc
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 92d6d327a862f1627ff3e88e60fdfea9def06ad539d98929ba46490e64372736
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 17b16db29e2e0c75d00f675c17710539269e30f853da6bac9044879e298c270f
|
||||
F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 2ccf4322f42063aefc150972943e750c77f7926b866f1639d40eec05df075b6e
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 1575ea6bbcf2da1e6df6892c17521a0c1c1c199a672e9090176ea0b88de48bd9
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 88ce2078267a2d1af57525a32d896295f4a8db7664de0e17e82dc9ff006ed8d3
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81
|
||||
@@ -634,7 +625,7 @@ F ext/wasm/index.html 475bc283338749db4e3fbf24cf3f5aa020cc85a1fffb780d400a915fcb
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
|
||||
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
|
||||
F ext/wasm/mkwasmbuilds.c 5d7baa9258299fd492351578a93dff960317822a08ee3ad6dd91ef5d21209812
|
||||
F ext/wasm/mkwasmbuilds.c 0e9198eb90acae4bcf57cf62d7186f6af5aaac02efdb075a1aded33614b3805a
|
||||
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@@ -660,7 +651,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 9393d5982db60f26e72c5af24a8c11cf39374ff5e695fadb5a4e7376f28150c6
|
||||
F main.mk e1a03e9206f6a042a9147035915cb944e9242d570779bc3ccd7ed6a39df10cae
|
||||
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -681,28 +672,28 @@ F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c b744bf69d520534751c742cababe7ad28c3892f1e3a75242e75a20bca15a834a
|
||||
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 4e1afafc56504ed6253e1b115c1502de4243c2287a0c799f4967fcd2d7716ad9
|
||||
F src/build.c b993e4adef4c4cdfd7abf62e2676c467bb1923f25f40c3c7ab2a7bfbace3de7f
|
||||
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
|
||||
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2
|
||||
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
|
||||
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 901499bed747c3b4b2be45be1abe912ba50a3f6a40ba88cc006ccf279f2d0e97
|
||||
F src/expr.c c4ff8dcacbc8962fb670fc7c9723c8346398795b16ce2f78439234769baee2e6
|
||||
F src/expr.c 8c3b23cb35f43c2d0570c1058b9a269e561e769e09c81ba192992c95022c1939
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c c065da737307a29e4d240ac727758dbf4102cb3218a1f651eb689b6a6fa12531
|
||||
F src/func.c efbcfe7cb7fc92fe5299c9aaa141075eb60d2108253e99bc235384ed6a90d937
|
||||
F src/fkey.c fb0f74c57d19a2d3f113f3476826919d68feda7ff334abfdb479a9a6353b9fcd
|
||||
F src/func.c 6e7de3551ae0f8205006e5109f025223246edd20186d54d90746dee7c1c5c093
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
|
||||
F src/json.c af766b62caee01c735cfe7795cc91ffea5a5e1c555a5d8a9aa5a301f00a1b0ad
|
||||
F src/json.c 8b6341a419150b28530cc21e3951b2238c35cdc312f11b2ca29017fe4b1dedc0
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
|
||||
F src/main.c e95aa130478fc98a49181ddf094baab45f319286411129253618efe0008f0dc4
|
||||
F src/main.c 31a13302193fbd51279c7e69cdfa0320d0de7629f9151e0964c1d320e8bdd7a4
|
||||
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -712,7 +703,7 @@ F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
|
||||
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
|
||||
F src/mutex.c 06bcd9c3dbf2d9b21fcd182606c00fafb9bfe0287983c8e17acd13d2c81a2fa9
|
||||
F src/mutex.c 5dc0dd69c4216dd976bd463f4ee62a0fa0c24860c0815238ff205f62e194431f
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
|
||||
@@ -723,33 +714,33 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
|
||||
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
|
||||
F src/os_unix.c dcf7988ddbdd68619b821c9a722f9377abb46f1d26c9279eb5a50402fd43d749
|
||||
F src/os_unix.c fa5e09b4df35ad845440cad67b86908cfe1fd4c28c51915f82e23633d1992bf4
|
||||
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
|
||||
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
|
||||
F src/pager.c a81461de271ac4886ad75b7ca2cca8157a48635820c4646cd2714acdc2c17e5f
|
||||
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 7c2184b5665c671258c4e96a10bbc9dbf7e1ede462ebc4e614249de0d54c8a26
|
||||
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pragma.c ecec75795c1821520266e4f93fa8840cce48979af532db06f085e36a7813860f
|
||||
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
|
||||
F src/printf.c b1b29b5e58e1530d5daeee5963d3c318d8ab2d7e38437580e28755753e0c1ded
|
||||
F src/printf.c 9cff219dba73b1aa9a8113e83e962f03f7bea8b6eb51cefb25bc468d5a69fb2d
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 47aa7fdc9ec4c19b103ac5e79d7887d30119b5675309facf5eed1118391c868b
|
||||
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 3bbcb0dbdac61a856b1ba3e2ed64d609935eca884b20208e5df5eeb183e2413f
|
||||
F src/shell.c.in b944a21d98cc4c6107bfd1ec702440579cb4bf86435125b67ff661180e9453b5
|
||||
F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61
|
||||
F src/select.c 8fe87c39a45037dac2e3dc02e1dc13ca09c1155cc14df9daaa65e5318179beaf
|
||||
F src/shell.c.in 2acdfca982deb70cdfefb8b422822d4e0234fe4dde6ff2bd9020b26445853917
|
||||
F src/sqlite.h.in 1f853f1d836af3e5a0b451521041d05658988a45f6978aaae08286e483fee5ac
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
|
||||
F src/sqliteInt.h b30f6ec44e695d00d83f83bdf3b8dd31a6537c48d909c7abb78643c49784d988
|
||||
F src/sqliteInt.h 185abb373dc2a311e3292540ef177ea301d8140b976ecd8ba381a5a0162cd6e9
|
||||
F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 85b5a20df96016e5d1d8fdc68c8a4c279c5b93e2049b77cd806c2cc50b9d8c56
|
||||
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
|
||||
F src/test1.c 302cc00a5f0bbfa36d73b299d600c073b02ffa7f2b59fd2c81091983ccd574a8
|
||||
F src/test1.c 3e3b013f59ffcb57dce00c90d55907072d71d4e970cb0a590cb261efe11bae9c
|
||||
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
|
||||
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
|
||||
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
|
||||
@@ -762,7 +753,7 @@ F src/test_backup.c a2bfd90d2ff2511b8635507bdb30fa9b605ade19c16b533066cae3077f5b
|
||||
F src/test_bestindex.c d75fad21369d80910238032bcf8d9ca1f2bffda13c1ceec63bfbb7f704448b15
|
||||
F src/test_blob.c 77b994e17f2c87055f44fd96c9a206c5a7155bae2cda2769af60c2f3582f962c
|
||||
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
|
||||
F src/test_config.c 9b6dac5bc4ab56c9c6289ca9a6a73a156e178e58bcfdac19a69f6e17e28ad5ac
|
||||
F src/test_config.c e02566c2c4ee2916324ce17123a798b47663cead2de546cfbd71d8cddb46bb26
|
||||
F src/test_delete.c d0e8f6dc55cfc98a7c27c057fb88d512260564bf0b611482656c68b8f7f401ed
|
||||
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
@@ -799,31 +790,31 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c f297bbf02037639e7a93b37d9c6e4415b3de1273395ee8fa8183e741e1e7fb72
|
||||
F src/treeview.c feaa59f14db4f7b5aacca9c5ad5aeb562c1f98262c1ffd74371f4186ade91fc5
|
||||
F src/trigger.c cb894db98083c68c4a17c72566ed39434aa91286db20d2891279ee49e6bfec0c
|
||||
F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||
F src/util.c 0cc410d538fe13a2cda90a8d0087c82cf4c1ab0d5055b8e3a595f28266f190c7
|
||||
F src/util.c eccfa8b3b414bb64c6543421c9fd10e5f07e103baae36427a273a9131527694c
|
||||
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
|
||||
F src/vdbe.c fa28a8f740f3d94c4e6b6d42ba90c220472683486268e753017512a70ef715f5
|
||||
F src/vdbe.c 5328c99dd256ee8132383565a86e253543a85daccfd7477c52f20bac6b385a7f
|
||||
F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9
|
||||
F src/vdbeInt.h c45d0195dad0a9099132109e3b63697f4f119baddeb391c36ca226cee530a485
|
||||
F src/vdbeInt.h 42488247a80cd9d300627833c6c85ace067ae5011a99e7614e2358130d62feea
|
||||
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
|
||||
F src/vdbeaux.c 396d38a62a357b807eabae0cae441fc89d2767a57ab08026b7072bf7aa2dd00c
|
||||
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
|
||||
F src/vdbemem.c 699d2fb0a59a00cf9b77898653167673de60fa5577e07bd6bee6adaef5fdc374
|
||||
F src/vdbemem.c 317ec5e870ddb16951b606c9fe8be22baef22ecbe46f58fdefc259662238afb7
|
||||
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 505a98fbc599a971d92cb90371cf54546c404cd61e04fd093e7b0c8ff978f9b6
|
||||
F src/wal.c 88d94fd15a75f6eda831fa32d1148a267ea37bf0a4b69829a73dfde06244b08f
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c 7a7fe745dd8104d0276a3d3f6e6ac7f087af3dd9f34a90bc937e5e7aea817e15
|
||||
F src/where.c 9f09ee7b260010138d5f9fb5f195b98051119eae3096a99d72ff16c83230f4af
|
||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||
F src/wherecode.c 783ecd30061c875c919a5163e4b55f9a0eccdaf7c9b17ad2908a1668a8766bc4
|
||||
F src/whereexpr.c bb649ce81bd6dc0eabfa2533ff5656fc7a16411e520a6c59be43e73e51503cce
|
||||
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
|
||||
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
|
||||
@@ -872,6 +863,7 @@ F test/analyzeF.test 40b5cc3ad7b10e81020d7ca86f1417647ecfae7477cfd88acc5aa7ae106
|
||||
F test/analyzeG.test 623be33038c49648872746c8dd8b23b5792c08fef173c55e82f1b12fca259852
|
||||
F test/analyzer1.test b6a624ec0af92eec209e1328465b66937c8fdf2fb442a3fa45321ddb3700f4aa
|
||||
F test/atof1.test bd21c4a0e718ab1470de07a2a79f2544d7903be34feebcc80de04beee4807b00
|
||||
F test/atof2.test 12912add57230495450e2fc94cb8ad1c9f3277f8843a3bc27079cae45c9782a1
|
||||
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
|
||||
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
|
||||
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
|
||||
@@ -916,7 +908,7 @@ F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c
|
||||
F test/bestindex8.test 4d8b1e8f30a7f405988ce4dbcc2b95c0775f0bed9ec08e0291a07e2f35f7e653
|
||||
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
|
||||
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
|
||||
F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
|
||||
F test/bestindexB.test 14db2f66ec9cc5064a74996033b74e5eec0fd2f3a327fbe34ff18de67e9d2671
|
||||
F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc
|
||||
F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3
|
||||
F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49
|
||||
@@ -1070,7 +1062,7 @@ F test/e_createtable.test 31b9bcb6ac8876bc7ec342d86d9c231a84c62b442093a6651dfd0f
|
||||
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
|
||||
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
|
||||
F test/e_expr.test 0a1e175caddc78b27306647cb4ce2362c55790190f8cdd178b75fd6262eb8f76
|
||||
F test/e_expr.test 9bdb347b78b9f4eff9153ea97797facc179a821898588471a70808b4471a69b0
|
||||
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
@@ -1130,7 +1122,8 @@ F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958
|
||||
F test/fork-test.c 9ac2e6423a1d38df3d6be0e8ac15608b545de21e2b19d9d876254c5931b63edb
|
||||
F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
|
||||
F test/fp-speed-1.c b37de94eba034e1703668816225f54510ec60fb0685406608cc707afe6b8234d
|
||||
F test/fpconv1.test d5d8aa0c427533006c112fb1957cdd1ea68c1d0709470dabb9ca02c2e4c06ad8
|
||||
F test/fpconv1.test 63f352682fa65601a326563ad633086df6ab194e6ed5e7366786f38a525a7fd7
|
||||
F test/fptest01.sql 210562ad8d5a7895f26273dd3be56561a41bcb51d78a28a337af0f1ceaa3bb8d
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
|
||||
@@ -1314,6 +1307,7 @@ F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c77
|
||||
F test/instr.test 67ba309e9697c24a304e98a7c8f372456177dd4e32237d2a305e1e05f7bb79c2
|
||||
F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd0e0f44c
|
||||
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
|
||||
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
|
||||
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
|
||||
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
|
||||
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
|
||||
@@ -1342,7 +1336,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
|
||||
F test/joinI.test fc7d24a2b1e444979b83bd92c30ebb975cebb5b9eae4442ce94969bd8d083053
|
||||
F test/joinI.test 249802b168ce96d8d57943ef9abafc1e36e28d91829f68bc2b6e87f2b4d33241
|
||||
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
|
||||
@@ -1453,7 +1447,7 @@ F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4d
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
|
||||
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
|
||||
F test/mutex1.test 42cb5e244c3a77bb0ef2b967e06fa5e7ba7d32d90a9b20bed98f6f5ede185a25
|
||||
F test/mutex1.test 2cdc320a3320521d73b8090a04a2245c1e625e5f90672882517bf5fedcec8f13
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test 73ea63ab43668313e2f8cc9ef9e9a966672c7934f3ce76926fbe991235d07d91
|
||||
F test/nockpt.test 3db354270fc63b6871eebd40285d4c55324fb27be629c958adbff6d7fcaa8e14
|
||||
@@ -1518,7 +1512,7 @@ F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224c
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd
|
||||
F test/qrf01.test 1d69175c966a95c7b2897a1831ca49ba84afc1107b32f7c455e05125ac7c8d11
|
||||
F test/qrf01.test abc3e558a75ae2678a3172051b39960dc6fd4b298b6d594afa50939759f4037f
|
||||
F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92
|
||||
F test/qrf03.test e7efe46d204671726b4707585126cd78d107368de4a7d0c7b8d5157cdd8624ed
|
||||
F test/qrf04.test 0894692c998d2401dcc33449c02051b503ecce0c94217be54fb007c82d2d1379
|
||||
@@ -1562,7 +1556,7 @@ F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test 06ec0aca725bf683313d03793aa2943bc7f45a901848c7056a9665b769c8fc38
|
||||
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
|
||||
F test/rowvalue9.test 7499a8fd7ca3a3f0e19d94e135355439aa2b596f86b775ca8de79672da2ca378
|
||||
F test/rowvalueA.test be8d6ad8b476eb24c151bb20bfd487e0d50c5e99618b7b0e656035069d2fc2cf
|
||||
F test/rowvalueA.test 1c5ed13f3b0641452ae35e6488d6ecc16cefce99f2adf7c07c513530e2aac6b7
|
||||
F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972d511c54fff
|
||||
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
@@ -1618,17 +1612,17 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 5055a13bde31e92590311c91777d6b646082dc13250de8c07dc0db1efbdd864d
|
||||
F test/shell1.test 2d658ceee13d9e4361d04d0ea16340ad17784ddf378fb6e9ca6d49c682cb4bae
|
||||
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
|
||||
F test/shell3.test 603b448e917537cf77be0f265c05c6f63bc677c63a533c8e96aae923b56f4a0e
|
||||
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
|
||||
F test/shell5.test a9cd2c8b62e125049ef500937674f47dd6787f0157ac0515aa554044a4dc3ea9
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
|
||||
F test/shell8.test 641cf21a99c59404c24e3062923734951c4099a6b6b6520de00cf7a1249ee871
|
||||
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
|
||||
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
|
||||
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
|
||||
F test/shellB.test b2afd5c28aba750c066996a082210d6a4fcab8fd042cad076d9c1023164af9b1
|
||||
F test/shellB.test 7123d231158588401f332bf278754687b83ba5fc5b352ec8679fb19edfb4cc0a
|
||||
F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
@@ -1714,7 +1708,7 @@ F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3f
|
||||
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
|
||||
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
|
||||
F test/testrunner.tcl 78d67079fc39caf2af3fd9d4c30bdac78dae7ec50b9fc802835e7a5189581e07 x
|
||||
F test/testrunner_data.tcl 87b8afd37c8e517fa87b7936540b2fc1ede8291f0567fb88744b9bff272a2e8b
|
||||
F test/testrunner_data.tcl 078e251983c8fc573567125147655f68132210f226c92922daf21fb913779717
|
||||
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
@@ -1946,7 +1940,7 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
|
||||
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
||||
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
|
||||
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
||||
F test/values.test 0eda08a6ce6545f1ab012dff4cc72a7dd0fee2510f42444136bb2b2b5ed84bc0
|
||||
F test/values.test 0e037c50789ac2a308746567d07b53b2f6026c1bb3a435d1b099424600e64caf
|
||||
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
@@ -2010,6 +2004,7 @@ F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03
|
||||
F test/walpersist.test 8d78a1ec91299163451417b451a2bac3481f8eb9f455b1ca507a6625c927ca6e
|
||||
F test/walprotocol.test 1b3f922125e341703f6e946d77fdc564d38fb3e07a9385cfdc6c99cac1ecf878
|
||||
F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db868eebc131
|
||||
F test/walrestart.test 3b0a9198ad2eb9f716d8f3846b133ba9f4619fb56decb1e67bba27743c766289
|
||||
F test/walro.test 78a84bc0fdae1385c06b017215c426b6845734d6a5a3ac75c918dd9b801b1b9d
|
||||
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
|
||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||
@@ -2099,7 +2094,7 @@ F test/zeroblob.test 7b74cefc7b281dfa2b07cd237987fbe94b4a2037a7771e9e83f2d5f608b
|
||||
F test/zeroblobfault.test 861d8191a0d944dfebb3cb4d2c5b4e46a5a119eaec5a63dd996c2389f8063441
|
||||
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
|
||||
F test/zipfile.test a3fcfc43115e4226fdddadd43bdf31c8ca805ad08dad435634f1633d8f5840d9
|
||||
F test/zipfile2.test a577e0775e32ef8972e7d5e9a45bc071a5ae061b5b965a08c9c4b709ad036a25
|
||||
F test/zipfile2.test 21afaffcf4f7769df38bf16e4a9c4dfa6ba1b0f5b695f844ec61fafb92db0db7
|
||||
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
|
||||
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
|
||||
F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e04534bbf
|
||||
@@ -2156,7 +2151,7 @@ F tool/mkvsix.tcl 67b40996a50f985a573278eea32fc5a5eb6110bdf14d33f1d8086e48c69e54
|
||||
F tool/mkwinarm64ec.tcl 171f79234fa53552a129b360356df5599fdab15239caffb3d29c571292728033
|
||||
F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
|
||||
F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
|
||||
F tool/omittest.tcl bec70ef0e16255c8d9eb06ecd7edf823c07a60a836186cdbce3528fb34b67995
|
||||
F tool/omittest.tcl 436b7072e00e25e9b77145a9f67aa8e0eeabd186168827435fd03f8f981aac32
|
||||
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
|
||||
F tool/pagesig.c f98909b4168d9cac11a2de7f031adea0e2f3131faa7515a72807c03ec58eafeb
|
||||
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
|
||||
@@ -2173,7 +2168,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 68f88017de3bed3aa65c93a4cf3a04d0989d158bc6fad8f1475beeeea1aae3ac
|
||||
F tool/sqldiff.c 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
|
||||
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
|
||||
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
|
||||
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
|
||||
@@ -2194,8 +2189,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P a80c847169f307a4d2e524b6732ea557bf7f312f1a319d6c6c2e81adb0907596
|
||||
R 3eb7e8d20bd192b2f6690ce98ebbba28
|
||||
U drh
|
||||
Z 4720cdecbf1fe28948310be768602949
|
||||
P decb69015457b4f70cf574aeef87d40f9de60b94965f4a915e8d0cd7559ef2ae
|
||||
R 081029f3feecf24cb4be31bd4056634e
|
||||
U dan
|
||||
Z 6e3cc1dc135fda8b3b63884b6a3aae0a
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
branch fp-perf
|
||||
tag fp-perf
|
||||
branch wal-restart-fix
|
||||
tag wal-restart-fix
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
245ac7d9ec61e14fcef13a731e290fc5e8979efef6f4345f875eab9b882b0713
|
||||
703cbb0f760515eac1e6f72a5e5cd928258c71378e4a976082b6518c90128135
|
||||
|
||||
+9
-4
@@ -486,6 +486,7 @@ Table *sqlite3LocateTableItem(
|
||||
const char *zDb;
|
||||
if( p->fg.fixedSchema ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
|
||||
assert( iDb>=0 && iDb<pParse->db->nDb );
|
||||
zDb = pParse->db->aDb[iDb].zDbSName;
|
||||
}else{
|
||||
assert( !p->fg.isSubquery );
|
||||
@@ -2570,13 +2571,14 @@ void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
|
||||
** restored to its original value prior to this routine returning.
|
||||
*/
|
||||
int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
|
||||
char *zTail; /* Pointer to the last "_" in zName */
|
||||
const char *zTail; /* Pointer to the last "_" in zName */
|
||||
Table *pTab; /* Table that zName is a shadow of */
|
||||
char *zCopy;
|
||||
zTail = strrchr(zName, '_');
|
||||
if( zTail==0 ) return 0;
|
||||
*zTail = 0;
|
||||
pTab = sqlite3FindTable(db, zName, 0);
|
||||
*zTail = '_';
|
||||
zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName));
|
||||
pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0;
|
||||
sqlite3DbFree(db, zCopy);
|
||||
if( pTab==0 ) return 0;
|
||||
if( !IsVirtual(pTab) ) return 0;
|
||||
return sqlite3IsShadowTableOf(db, pTab, zName);
|
||||
@@ -2729,6 +2731,7 @@ void sqlite3EndTable(
|
||||
convertToWithoutRowidTable(pParse, p);
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, p->pSchema);
|
||||
assert( iDb>=0 && iDb<=db->nDb );
|
||||
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
/* Resolve names in all CHECK constraint expressions.
|
||||
@@ -3024,6 +3027,7 @@ void sqlite3CreateView(
|
||||
|
||||
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
iDb = sqlite3SchemaToIndex(db, p->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
|
||||
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
|
||||
|
||||
@@ -4620,6 +4624,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code = SQLITE_DROP_INDEX;
|
||||
|
||||
+11
-5
@@ -429,7 +429,7 @@ static int parseDateOrTime(
|
||||
return 0;
|
||||
}else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
|
||||
return setDateTimeToCurrent(context, p);
|
||||
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
|
||||
}else if( sqlite3AtoF(zDate, &r)>0 ){
|
||||
setRawDateNumber(p, r);
|
||||
return 0;
|
||||
}else if( (sqlite3StrICmp(zDate,"subsec")==0
|
||||
@@ -875,7 +875,7 @@ static int parseModifier(
|
||||
** date is already on the appropriate weekday, this is a no-op.
|
||||
*/
|
||||
if( sqlite3_strnicmp(z, "weekday ", 8)==0
|
||||
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
|
||||
&& sqlite3AtoF(&z[8], &r)>0
|
||||
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
|
||||
sqlite3_int64 Z;
|
||||
computeYMD_HMS(p);
|
||||
@@ -946,9 +946,11 @@ static int parseModifier(
|
||||
case '8':
|
||||
case '9': {
|
||||
double rRounder;
|
||||
int i;
|
||||
int i, rx;
|
||||
int Y,M,D,h,m,x;
|
||||
const char *z2 = z;
|
||||
char *zCopy;
|
||||
sqlite3 *db = sqlite3_context_db_handle(pCtx);
|
||||
char z0 = z[0];
|
||||
for(n=1; z[n]; n++){
|
||||
if( z[n]==':' ) break;
|
||||
@@ -958,7 +960,11 @@ static int parseModifier(
|
||||
if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
|
||||
}
|
||||
}
|
||||
if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
|
||||
zCopy = sqlite3DbStrNDup(db, z, n);
|
||||
if( zCopy==0 ) break;
|
||||
rx = sqlite3AtoF(zCopy, &r)<=0;
|
||||
sqlite3DbFree(db, zCopy);
|
||||
if( rx ){
|
||||
assert( rc==1 );
|
||||
break;
|
||||
}
|
||||
@@ -1778,7 +1784,7 @@ static void datedebugFunc(
|
||||
char *zJson;
|
||||
zJson = sqlite3_mprintf(
|
||||
"{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d,"
|
||||
"s:%.3f,validJD:%d,validYMS:%d,validHMS:%d,"
|
||||
"s:%.3f,validJD:%d,validYMD:%d,validHMS:%d,"
|
||||
"nFloor:%d,rawS:%d,isError:%d,useSubsec:%d,"
|
||||
"isUtc:%d,isLocal:%d}",
|
||||
x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz,
|
||||
|
||||
+1
-1
@@ -4303,7 +4303,7 @@ sqlite3ExprCodeIN_oom_error:
|
||||
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||
if( ALWAYS(z!=0) ){
|
||||
double value;
|
||||
sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
sqlite3AtoF(z, &value);
|
||||
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
|
||||
if( negateFlag ) value = -value;
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
|
||||
|
||||
@@ -908,6 +908,7 @@ void sqlite3FkCheck(
|
||||
if( !IsOrdinaryTable(pTab) ) return;
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=00 && iDb<db->nDb );
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
|
||||
/* Loop through all the foreign key constraints for which pTab is the
|
||||
|
||||
+5
-3
@@ -466,7 +466,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
|
||||
sqlite3AtoF(zBuf, &r);
|
||||
sqlite3_free(zBuf);
|
||||
}
|
||||
sqlite3_result_double(context, r);
|
||||
@@ -1104,7 +1104,7 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){
|
||||
sqlite3_str_appendf(pStr, "%!0.15g", r1);
|
||||
zVal = sqlite3_str_value(pStr);
|
||||
if( zVal ){
|
||||
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
|
||||
sqlite3AtoF(zVal, &r2);
|
||||
if( r1!=r2 ){
|
||||
sqlite3_str_reset(pStr);
|
||||
sqlite3_str_appendf(pStr, "%!0.20e", r1);
|
||||
@@ -1201,7 +1201,7 @@ static void unistrFunc(
|
||||
}
|
||||
i = j = 0;
|
||||
while( i<nIn ){
|
||||
char *z = strchr(&zIn[i],'\\');
|
||||
const char *z = strchr(&zIn[i],'\\');
|
||||
if( z==0 ){
|
||||
n = nIn - i;
|
||||
memmove(&zOut[j], &zIn[i], n);
|
||||
@@ -2364,6 +2364,8 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
|
||||
sqlite3CreateFunc(db, "like", nArg, SQLITE_UTF8, pInfo, likeFunc,
|
||||
0, 0, 0, 0, 0);
|
||||
pDef = sqlite3FindFunction(db, "like", nArg, SQLITE_UTF8, 0);
|
||||
assert( pDef!=0 ); /* The sqlite3CreateFunc() call above cannot fail
|
||||
** because the "like" SQL-function already exists */
|
||||
pDef->funcFlags |= flags;
|
||||
pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE;
|
||||
}
|
||||
|
||||
+1
-1
@@ -3266,7 +3266,7 @@ static void jsonReturnFromBlob(
|
||||
to_double:
|
||||
z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz);
|
||||
if( z==0 ) goto returnfromblob_oom;
|
||||
rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
rc = sqlite3AtoF(z, &r);
|
||||
sqlite3DbFree(db, z);
|
||||
if( rc<=0 ) goto returnfromblob_malformed;
|
||||
sqlite3_result_double(pCtx, r);
|
||||
|
||||
+10
-1
@@ -971,6 +971,14 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
|
||||
rc = setupLookaside(db, pBuf, sz, cnt);
|
||||
break;
|
||||
}
|
||||
case SQLITE_DBCONFIG_FP_DIGITS: {
|
||||
int nIn = va_arg(ap, int);
|
||||
int *pOut = va_arg(ap, int*);
|
||||
if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn;
|
||||
if( pOut ) *pOut = db->nFpDigit;
|
||||
rc = SQLITE_OK;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
static const struct {
|
||||
int op; /* The opcode */
|
||||
@@ -3378,7 +3386,7 @@ static int openDatabase(
|
||||
db = sqlite3MallocZero( sizeof(sqlite3) );
|
||||
if( db==0 ) goto opendb_out;
|
||||
if( isThreadsafe
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
#if defined(SQLITE_THREAD_MISUSE_WARNINGS)
|
||||
|| sqlite3GlobalConfig.bCoreMutex
|
||||
#endif
|
||||
){
|
||||
@@ -3399,6 +3407,7 @@ static int openDatabase(
|
||||
db->aDb = db->aDbStatic;
|
||||
db->lookaside.bDisable = 1;
|
||||
db->lookaside.sz = 0;
|
||||
db->nFpDigit = 17;
|
||||
|
||||
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
|
||||
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
|
||||
|
||||
+16
-8
@@ -27,23 +27,28 @@ static SQLITE_WSD int mutexIsInit = 0;
|
||||
|
||||
#ifndef SQLITE_MUTEX_OMIT
|
||||
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
#ifdef SQLITE_THREAD_MISUSE_WARNINGS
|
||||
/*
|
||||
** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
|
||||
** This block (enclosed by SQLITE_THREAD_MISUSE_WARNINGS) contains
|
||||
** the implementation of a wrapper around the system default mutex
|
||||
** implementation (sqlite3DefaultMutex()).
|
||||
**
|
||||
** Most calls are passed directly through to the underlying default
|
||||
** mutex implementation. Except, if a mutex is configured by calling
|
||||
** sqlite3MutexWarnOnContention() on it, then if contention is ever
|
||||
** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
|
||||
** encountered within xMutexEnter() then a warning is emitted via
|
||||
** sqlite3_log(). Furthermore, if SQLITE_THREAD_MISUSE_ABORT is
|
||||
** defined then abort() is called after the sqlite3_log() warning.
|
||||
**
|
||||
** This type of mutex is used as the database handle mutex when testing
|
||||
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
|
||||
** This type of mutex is used on the database handle mutex when testing
|
||||
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. A failure
|
||||
** indicates that the app ought to be using SQLITE_OPEN_FULLMUTEX or
|
||||
** similar because it is trying to use the same database handle from
|
||||
** two different connections at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
** Type for all mutexes used when SQLITE_THREAD_MISUSE_WARNINGS
|
||||
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
|
||||
** allocated by the system mutex implementation. Variable iType is usually set
|
||||
** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
|
||||
@@ -160,6 +165,9 @@ static void checkMutexEnter(sqlite3_mutex *p){
|
||||
sqlite3_log(SQLITE_MISUSE,
|
||||
"illegal multi-threaded access to database connection"
|
||||
);
|
||||
#if SQLITE_THREAD_MISUSE_ABORT
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
|
||||
}
|
||||
@@ -211,7 +219,7 @@ void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
|
||||
pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
|
||||
}
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
|
||||
#endif /* ifdef SQLITE_THREAD_MISUSE_WARNINGS */
|
||||
|
||||
/*
|
||||
** Initialize the mutex system.
|
||||
@@ -228,7 +236,7 @@ int sqlite3MutexInit(void){
|
||||
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
|
||||
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
#ifdef SQLITE_THREAD_MISUSE_WARNINGS
|
||||
pFrom = multiThreadedCheckMutex();
|
||||
#else
|
||||
pFrom = sqlite3DefaultMutex();
|
||||
|
||||
+1
-1
@@ -5190,7 +5190,7 @@ static int unixShmMap(
|
||||
}
|
||||
|
||||
/* Map the requested memory region into this processes address space. */
|
||||
apNew = (char **)sqlite3_realloc(
|
||||
apNew = (char **)sqlite3_realloc64(
|
||||
pShmNode->apRegion, nReqRegion*sizeof(char *)
|
||||
);
|
||||
if( !apNew ){
|
||||
|
||||
+4
-4
@@ -1235,17 +1235,17 @@ static int jrnlBufferSize(Pager *pPager){
|
||||
*/
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
/*
|
||||
** Return a 32-bit hash of the page data for pPage.
|
||||
** Return a 64-bit hash of the page data for pPage.
|
||||
*/
|
||||
static u32 pager_datahash(int nByte, unsigned char *pData){
|
||||
u32 hash = 0;
|
||||
static u64 pager_datahash(int nByte, unsigned char *pData){
|
||||
u64 hash = 0;
|
||||
int i;
|
||||
for(i=0; i<nByte; i++){
|
||||
hash = (hash*1039) + pData[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
static u32 pager_pagehash(PgHdr *pPage){
|
||||
static u64 pager_pagehash(PgHdr *pPage){
|
||||
return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
|
||||
}
|
||||
static void pager_set_pagehash(PgHdr *pPage){
|
||||
|
||||
+1
-1
@@ -1427,7 +1427,7 @@ expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
|
||||
expr(A) ::= expr(A) ISNULL|NOTNULL(E). {A = sqlite3PExprIsNull(pParse,@E,A);}
|
||||
expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExprIsNull(pParse,TK_NOTNULL,A);}
|
||||
|
||||
// expr1 IS expr2 same as expr1 IS NOT DISTICT FROM expr2
|
||||
// expr1 IS expr2 same as expr1 IS NOT DISTINCT FROM expr2
|
||||
// expr1 IS NOT expr2 same as expr1 IS DISTINCT FROM expr2
|
||||
//
|
||||
expr(A) ::= expr(A) IS expr(Y). {
|
||||
|
||||
+2
-2
@@ -29,10 +29,10 @@ struct PgHdr {
|
||||
PCache *pCache; /* PRIVATE: Cache that owns this page */
|
||||
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
|
||||
Pager *pPager; /* The pager this page is part of */
|
||||
Pgno pgno; /* Page number for this page */
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
u32 pageHash; /* Hash of page content */
|
||||
u64 pageHash; /* Hash of page content */
|
||||
#endif
|
||||
Pgno pgno; /* Page number for this page */
|
||||
u16 flags; /* PGHDR flags defined below */
|
||||
|
||||
/**********************************************************************
|
||||
|
||||
+1
-1
@@ -549,7 +549,7 @@ void sqlite3_str_vappendf(
|
||||
}else{
|
||||
iRound = precision+1;
|
||||
}
|
||||
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
|
||||
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16);
|
||||
if( s.isSpecial ){
|
||||
if( s.isSpecial==2 ){
|
||||
bufpt = flag_zeropad ? "null" : "NaN";
|
||||
|
||||
+9
-1
@@ -936,7 +936,7 @@ static int exprProbability(Expr *p){
|
||||
double r = -1.0;
|
||||
if( p->op!=TK_FLOAT ) return -1;
|
||||
assert( !ExprHasProperty(p, EP_IntValue) );
|
||||
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
|
||||
sqlite3AtoF(p->u.zToken, &r);
|
||||
assert( r>=0.0 );
|
||||
if( r>1.0 ) return -1;
|
||||
return (int)(r*134217728.0);
|
||||
@@ -2073,6 +2073,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/* If the SELECT statement contains ON clauses that were moved into
|
||||
** the WHERE clause, go through and verify that none of the terms
|
||||
** in the ON clauses reference tables to the right of the ON clause. */
|
||||
if( (p->selFlags & SF_OnToWhere) ){
|
||||
sqlite3SelectCheckOnClauses(pParse, p);
|
||||
if( pParse->nErr ) return WRC_Abort;
|
||||
}
|
||||
|
||||
/* Advance to the next term of the compound
|
||||
*/
|
||||
p = p->pPrior;
|
||||
|
||||
+2
-14
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
typedef struct DistinctCtx DistinctCtx;
|
||||
struct DistinctCtx {
|
||||
u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */
|
||||
u8 isTnct; /* 0: Not distinct. 1: DISTINCT 2: DISTINCT and ORDER BY */
|
||||
u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
|
||||
int tabTnct; /* Ephemeral table used for DISTINCT processing */
|
||||
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
|
||||
@@ -7491,7 +7491,7 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
|
||||
** Check all ON clauses in pSelect to verify that they do not reference
|
||||
** columns to the right.
|
||||
*/
|
||||
static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
|
||||
void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){
|
||||
Walker w;
|
||||
CheckOnCtx sCtx;
|
||||
int ii;
|
||||
@@ -7671,18 +7671,6 @@ int sqlite3Select(
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the SELECT statement contains ON clauses that were moved into
|
||||
** the WHERE clause, go through and verify that none of the terms
|
||||
** in the ON clauses reference tables to the right of the ON clause.
|
||||
** Do this now, after name resolution, but before query flattening
|
||||
*/
|
||||
if( p->selFlags & SF_OnToWhere ){
|
||||
selectCheckOnClauses(pParse, p);
|
||||
if( pParse->nErr ){
|
||||
goto select_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the SF_UFSrcCheck flag is set, then this function is being called
|
||||
** as part of populating the temp table for an UPDATE...FROM statement.
|
||||
** In this case, it is an error if the target object (pSrc->a[0]) name
|
||||
|
||||
+38
-21
@@ -931,7 +931,7 @@ static void shellDtostr(
|
||||
char z[400];
|
||||
if( n<1 ) n = 1;
|
||||
if( n>350 ) n = 350;
|
||||
sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
|
||||
sprintf(z, "%#+.*e", n, r);
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
@@ -6665,11 +6665,15 @@ static int arRemoveCommand(ArCommand *pAr){
|
||||
*/
|
||||
static int arExtractCommand(ArCommand *pAr){
|
||||
const char *zSql1 =
|
||||
"SELECT "
|
||||
" ($dir || name),"
|
||||
" writefile(($dir || name), %s, mode, mtime) "
|
||||
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
|
||||
" AND name NOT GLOB '*..[/\\]*'";
|
||||
"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"
|
||||
" FROM dest CROSS JOIN %s\n"
|
||||
" WHERE (%s)\n"
|
||||
" AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */
|
||||
" AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */
|
||||
" AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */
|
||||
|
||||
const char *azExtraArg[] = {
|
||||
"sqlar_uncompress(data, sz)",
|
||||
@@ -6704,24 +6708,28 @@ static int arExtractCommand(ArCommand *pAr){
|
||||
if( rc==SQLITE_OK ){
|
||||
j = sqlite3_bind_parameter_index(pSql, "$dir");
|
||||
sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
|
||||
j = sqlite3_bind_parameter_index(pSql, "$dryrun");
|
||||
sqlite3_bind_int(pSql, j, pAr->bDryRun);
|
||||
|
||||
/* Run the SELECT statement twice. The first time, writefile() is called
|
||||
** for all archive members that should be extracted. The second time,
|
||||
** only for the directories. This is because the timestamps for
|
||||
** extracted directories must be reset after they are populated (as
|
||||
** populating them changes the timestamp). */
|
||||
/* 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
|
||||
** 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++){
|
||||
j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
|
||||
j = sqlite3_bind_parameter_index(pSql, "$pass");
|
||||
sqlite3_bind_int(pSql, j, i);
|
||||
if( pAr->bDryRun ){
|
||||
cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql));
|
||||
}else{
|
||||
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->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;
|
||||
shellReset(&rc, pSql);
|
||||
}
|
||||
shellFinalize(&rc, pSql);
|
||||
@@ -9267,6 +9275,7 @@ static int do_meta_command(const char *zLine, ShellState *p){
|
||||
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
|
||||
{ "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
|
||||
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
|
||||
{ "fp_digits", SQLITE_DBCONFIG_FP_DIGITS },
|
||||
{ "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
|
||||
{ "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
|
||||
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
|
||||
@@ -9283,11 +9292,19 @@ static int do_meta_command(const char *zLine, ShellState *p){
|
||||
for(ii=0; ii<ArraySize(aDbConfig); ii++){
|
||||
if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
|
||||
if( nArg>=3 ){
|
||||
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
|
||||
if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
|
||||
sqlite3_db_config(p->db, aDbConfig[ii].op, atoi(azArg[2]), 0);
|
||||
}else{
|
||||
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
|
||||
}
|
||||
}
|
||||
sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
|
||||
cli_printf(p->out, "%19s %s\n",
|
||||
aDbConfig[ii].zName, v ? "on" : "off");
|
||||
if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
|
||||
cli_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v);
|
||||
}else{
|
||||
cli_printf(p->out, "%19s %s\n",
|
||||
aDbConfig[ii].zName, v ? "on" : "off");
|
||||
}
|
||||
if( nArg>1 ) break;
|
||||
}
|
||||
if( nArg>1 && ii==ArraySize(aDbConfig) ){
|
||||
@@ -13346,7 +13363,7 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
z = cmdline_option_value(argc,argv,++i);
|
||||
if( z[0]=='.' ){
|
||||
rc = do_meta_command(z, &data);
|
||||
if( rc && bail_on_error ){
|
||||
if( rc && (bail_on_error || rc==2) ){
|
||||
if( rc==2 ) rc = 0;
|
||||
goto shell_main_exit;
|
||||
}
|
||||
|
||||
+36
-17
@@ -2648,6 +2648,22 @@ struct sqlite3_mem_methods {
|
||||
** comments are allowed in SQL text after processing the first argument.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_FP_DIGITS]]
|
||||
** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt>
|
||||
** <dd>The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines
|
||||
** the number of significant digits that SQLite will attempt to preserve when
|
||||
** converting floating point numbers (IEEE 754 "doubles") into text. The
|
||||
** default value 17, as of SQLite version 3.52.0. The value was 15 in all
|
||||
** prior versions.<p>
|
||||
** This option takes two arguments which are an integer and a pointer
|
||||
** to an integer. The first argument is a small integer, between 3 and 23, or
|
||||
** zero. The FP_DIGITS setting is changed to that small integer, or left
|
||||
** altered if the first argument is zero or out of range. The second argument
|
||||
** is a pointer to an integer. If the pointer is not NULL, then the value of
|
||||
** the FP_DIGITS setting, after possibly being modified by the first
|
||||
** arguments, is written into the integer to which the second argument points.
|
||||
** </dd>
|
||||
**
|
||||
** </dl>
|
||||
**
|
||||
** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3>
|
||||
@@ -2665,9 +2681,10 @@ struct sqlite3_mem_methods {
|
||||
** the first argument.
|
||||
**
|
||||
** <p>While most SQLITE_DBCONFIG options use the argument format
|
||||
** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME]
|
||||
** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the
|
||||
** documentation of those exceptional options for details.
|
||||
** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME],
|
||||
** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options
|
||||
** are different. See the documentation of those exceptional options for
|
||||
** details.
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
|
||||
@@ -2692,7 +2709,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
|
||||
#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
@@ -4435,19 +4453,20 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** logs the error.
|
||||
**
|
||||
** [[SQLITE_PREPARE_FROM_DDL]] <dt>SQLITE_PREPARE_FROM_DDL</dt>
|
||||
** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to behave as if
|
||||
** the SQL statement is part of a database schema. This makes a difference
|
||||
** when the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] option is set to off.
|
||||
** When this option is used and SQLITE_DBCONFIG_TRUSTED_SCHEMA is off,
|
||||
** SQL functions may not be called unless they are tagged with
|
||||
** [SQLITE_INNOCUOUS] and virtual tables may not be used unless tagged
|
||||
** with [SQLITE_VTAB_INNOCUOUS]. Use the SQLITE_PREPARE_FROM_DDL option
|
||||
** when preparing SQL that is derived from parts of the database
|
||||
** schema. In particular, virtual table implementations that
|
||||
** run SQL statements based on the arguments to their CREATE VIRTUAL
|
||||
** TABLE statement should use [sqlite3_prepare_v3()] and set the
|
||||
** SQLITE_PREPARE_FROM_DLL flag to prevent bypass of the
|
||||
** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
|
||||
** <dd>The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce
|
||||
** security constraints that would otherwise only be enforced when parsing
|
||||
** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag
|
||||
** causes the SQL compiler to treat the SQL statement being prepared as if
|
||||
** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and
|
||||
** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called
|
||||
** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only
|
||||
** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice
|
||||
** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that
|
||||
** is derived from parts of the database schema. In particular, virtual
|
||||
** table implementations that run SQL statements that are derived from
|
||||
** arguments to their CREATE VIRTUAL TABLE statement should always use
|
||||
** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to
|
||||
** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_PREPARE_PERSISTENT 0x01
|
||||
|
||||
+29
-14
@@ -1692,6 +1692,7 @@ struct sqlite3 {
|
||||
u8 noSharedCache; /* True if no shared-cache backends */
|
||||
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
|
||||
u8 eOpenState; /* Current condition of the connection */
|
||||
u8 nFpDigit; /* Significant digits to keep on double->text */
|
||||
int nextPagesize; /* Pagesize after VACUUM if >0 */
|
||||
i64 nChange; /* Value returned by sqlite3_changes() */
|
||||
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
|
||||
@@ -3881,17 +3882,12 @@ struct Parse {
|
||||
u8 nested; /* Number of nested calls to the parser/code generator */
|
||||
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
|
||||
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
|
||||
u8 mayAbort; /* True if statement may throw an ABORT exception */
|
||||
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
|
||||
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
||||
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
||||
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
||||
u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */
|
||||
u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
|
||||
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
|
||||
u8 bReturning; /* Coding a RETURNING trigger */
|
||||
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
|
||||
u8 disableTriggers; /* True to disable triggers */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
||||
#endif
|
||||
@@ -3900,10 +3896,15 @@ struct Parse {
|
||||
u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
|
||||
** and ALTER TABLE ADD COLUMN. */
|
||||
#endif
|
||||
bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
|
||||
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 disableTriggers:1; /* True to disable triggers */
|
||||
bft mayAbort :1; /* True if statement may throw an ABORT exception */
|
||||
bft hasCompound :1; /* Need to invoke convertCompoundSelectToSubquery() */
|
||||
bft bReturning :1; /* Coding a RETURNING trigger */
|
||||
bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */
|
||||
bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
|
||||
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 */
|
||||
int nRangeReg; /* Size of the temporary register block */
|
||||
int iRangeReg; /* First register in temporary register block */
|
||||
int nErr; /* Number of errors seen */
|
||||
@@ -4786,7 +4787,20 @@ int sqlite3LookasideUsed(sqlite3*,int*);
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
||||
sqlite3_mutex *sqlite3MallocMutex(void);
|
||||
|
||||
#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
|
||||
|
||||
/* The SQLITE_THREAD_MISUSE_WARNINGS compile-time option used to be called
|
||||
** SQLITE_ENABLE_MULTITHREADED_CHECKS. Keep that older macro for backwards
|
||||
** compatibility, at least for a while... */
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
# define SQLITE_THREAD_MISUSE_WARNINGS 1
|
||||
#endif
|
||||
|
||||
/* SQLITE_THREAD_MISUSE_ABORT implies SQLITE_THREAD_MISUSE_WARNINGS */
|
||||
#ifdef SQLITE_THREAD_MISUSE_ABORT
|
||||
# define SQLITE_THREAD_MISUSE_WARNINGS 1
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_THREAD_MISUSE_WARNINGS) && !defined(SQLITE_MUTEX_OMIT)
|
||||
void sqlite3MutexWarnOnContention(sqlite3_mutex*);
|
||||
#else
|
||||
# define sqlite3MutexWarnOnContention(x)
|
||||
@@ -4820,12 +4834,12 @@ struct PrintfArguments {
|
||||
** value into an approximate decimal representation.
|
||||
*/
|
||||
struct FpDecode {
|
||||
char sign; /* '+' or '-' */
|
||||
char isSpecial; /* 1: Infinity 2: NaN */
|
||||
int n; /* Significant digits in the decode */
|
||||
int iDP; /* Location of the decimal point */
|
||||
char *z; /* Start of significant digits */
|
||||
char zBuf[24]; /* Storage for significant digits */
|
||||
char zBuf[20]; /* Storage for significant digits */
|
||||
char sign; /* '+' or '-' */
|
||||
char isSpecial; /* 1: Infinity 2: NaN */
|
||||
};
|
||||
|
||||
void sqlite3FpDecode(FpDecode*,double,int,int);
|
||||
@@ -5068,6 +5082,7 @@ Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
|
||||
Expr*,ExprList*,u32,Expr*);
|
||||
void sqlite3SelectDelete(sqlite3*, Select*);
|
||||
void sqlite3SelectDeleteGeneric(sqlite3*,void*);
|
||||
void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect);
|
||||
Table *sqlite3SrcListLookup(Parse*, SrcList*);
|
||||
int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
|
||||
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
|
||||
@@ -5289,7 +5304,7 @@ int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
|
||||
int sqlite3RealSameAsInt(double,sqlite3_int64);
|
||||
i64 sqlite3RealToI64(double);
|
||||
int sqlite3Int64ToText(i64,char*);
|
||||
int sqlite3AtoF(const char *z, double*, int, u8);
|
||||
int sqlite3AtoF(const char *z, double*);
|
||||
int sqlite3GetInt32(const char *, int*);
|
||||
int sqlite3GetUInt32(const char*, u32*);
|
||||
int sqlite3Atoi(const char*);
|
||||
|
||||
@@ -8644,6 +8644,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
|
||||
{ "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
|
||||
{ "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
|
||||
{ "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS },
|
||||
{ "FP_DIGITS", SQLITE_DBCONFIG_FP_DIGITS },
|
||||
};
|
||||
int i;
|
||||
int v = 0;
|
||||
|
||||
@@ -679,6 +679,14 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_THREAD_MISUSE_WARNINGS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "thread_misuse_warnings",
|
||||
"1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "thread_misuse_warnings",
|
||||
"0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_TRIGGER
|
||||
Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -336,6 +336,7 @@ void sqlite3FinishTrigger(
|
||||
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
|
||||
zName = pTrig->zName;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
|
||||
assert( iDb>=00 && iDb<db->nDb );
|
||||
pTrig->step_list = pStepList;
|
||||
while( pStepList ){
|
||||
pStepList->pTrig = pTrig;
|
||||
@@ -819,6 +820,7 @@ static SQLITE_NOINLINE Trigger *triggersReallyExist(
|
||||
p = pList;
|
||||
if( (pParse->db->flags & SQLITE_EnableTrigger)==0
|
||||
&& pTab->pTrigger!=0
|
||||
&& sqlite3SchemaToIndex(pParse->db, pTab->pTrigger->pSchema)!=1
|
||||
){
|
||||
/* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that
|
||||
** only TEMP triggers are allowed. Truncate the pList so that it
|
||||
|
||||
+192
-161
@@ -546,28 +546,28 @@ static u64 powerOfTen(int p){
|
||||
static const u64 aScale[] = {
|
||||
0x8049a4ac0c5811aeLLU, /* 0: 1.0e-351 << 1229 */
|
||||
0xcf42894a5dce35eaLLU, /* 1: 1.0e-324 << 1140 */
|
||||
0xa76c582338ed2621LLU, /* 2: 1.0e-297 << 1050 */
|
||||
0xa76c582338ed2622LLU, /* 2: 1.0e-297 << 1050 */
|
||||
0x873e4f75e2224e68LLU, /* 3: 1.0e-270 << 960 */
|
||||
0xda7f5bf590966848LLU, /* 4: 1.0e-243 << 871 */
|
||||
0xb080392cc4349decLLU, /* 5: 1.0e-216 << 781 */
|
||||
0xda7f5bf590966849LLU, /* 4: 1.0e-243 << 871 */
|
||||
0xb080392cc4349dedLLU, /* 5: 1.0e-216 << 781 */
|
||||
0x8e938662882af53eLLU, /* 6: 1.0e-189 << 691 */
|
||||
0xe65829b3046b0afaLLU, /* 7: 1.0e-162 << 602 */
|
||||
0xba121a4650e4ddebLLU, /* 8: 1.0e-135 << 512 */
|
||||
0xba121a4650e4ddecLLU, /* 8: 1.0e-135 << 512 */
|
||||
0x964e858c91ba2655LLU, /* 9: 1.0e-108 << 422 */
|
||||
0xf2d56790ab41c2a2LLU, /* 10: 1.0e-81 << 333 */
|
||||
0xc428d05aa4751e4cLLU, /* 11: 1.0e-54 << 243 */
|
||||
0xf2d56790ab41c2a3LLU, /* 10: 1.0e-81 << 333 */
|
||||
0xc428d05aa4751e4dLLU, /* 11: 1.0e-54 << 243 */
|
||||
0x9e74d1b791e07e48LLU, /* 12: 1.0e-27 << 153 */
|
||||
0x8000000000000000LLU, /* 13: 1.0e+0 << 63 */
|
||||
0xcecb8f27f4200f3aLLU, /* 14: 1.0e+27 >> 26 */
|
||||
0xa70c3c40a64e6c51LLU, /* 15: 1.0e+54 >> 116 */
|
||||
0xa70c3c40a64e6c52LLU, /* 15: 1.0e+54 >> 116 */
|
||||
0x86f0ac99b4e8dafdLLU, /* 16: 1.0e+81 >> 206 */
|
||||
0xda01ee641a708de9LLU, /* 17: 1.0e+108 >> 295 */
|
||||
0xda01ee641a708deaLLU, /* 17: 1.0e+108 >> 295 */
|
||||
0xb01ae745b101e9e4LLU, /* 18: 1.0e+135 >> 385 */
|
||||
0x8e41ade9fbebc27dLLU, /* 19: 1.0e+162 >> 475 */
|
||||
0xe5d3ef282a242e81LLU, /* 20: 1.0e+189 >> 564 */
|
||||
0xe5d3ef282a242e82LLU, /* 20: 1.0e+189 >> 564 */
|
||||
0xb9a74a0637ce2ee1LLU, /* 21: 1.0e+216 >> 654 */
|
||||
0x95f83d0a1fb69cd9LLU, /* 22: 1.0e+243 >> 744 */
|
||||
0xf24a01a73cf2dccfLLU, /* 23: 1.0e+270 >> 833 */
|
||||
0xf24a01a73cf2dcd0LLU, /* 23: 1.0e+270 >> 833 */
|
||||
0xc3b8358109e84f07LLU, /* 24: 1.0e+297 >> 923 */
|
||||
0x9e19db92b4e31ba9LLU, /* 25: 1.0e+324 >> 1013 */
|
||||
};
|
||||
@@ -594,7 +594,7 @@ static u64 powerOfTen(int p){
|
||||
}
|
||||
x = sqlite3Multiply128(aBase[n],y);
|
||||
if( (U64_BIT(63) & x)==0 ){
|
||||
x <<= 1;
|
||||
x = (x<<1)|1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -648,13 +648,18 @@ static int countLeadingZeros(u64 m){
|
||||
*/
|
||||
static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
|
||||
int p;
|
||||
u64 h, out;
|
||||
u64 h;
|
||||
assert( n>=1 && n<=18 );
|
||||
p = n - 1 - pwr2to10(e+63);
|
||||
h = sqlite3Multiply128(m, powerOfTen(p));
|
||||
assert( -(e + pwr10to2(p) + 3) >=0 );
|
||||
assert( -(e + pwr10to2(p) + 3) <64 );
|
||||
out = h >> -(e + pwr10to2(p) + 3);
|
||||
*pD = (out + 2 + ((out>>2)&1)) >> 2;
|
||||
assert( -(e + pwr10to2(p) + 2) >= 0 );
|
||||
assert( -(e + pwr10to2(p) + 1) <= 63 );
|
||||
if( n==18 ){
|
||||
h >>= -(e + pwr10to2(p) + 2);
|
||||
*pD = (h + ((h<<1)&2))>>1;
|
||||
}else{
|
||||
*pD = h >> -(e + pwr10to2(p) + 1);
|
||||
}
|
||||
*pP = -p;
|
||||
}
|
||||
|
||||
@@ -663,10 +668,10 @@ static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
|
||||
*/
|
||||
static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
u64 out;
|
||||
int b;
|
||||
int e1;
|
||||
int e2;
|
||||
int lz;
|
||||
int lp;
|
||||
int x;
|
||||
u64 h;
|
||||
double r;
|
||||
assert( (d & U64_BIT(63))==0 );
|
||||
@@ -677,26 +682,26 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
if( p>POWERSOF10_LAST ){
|
||||
return INFINITY;
|
||||
}
|
||||
b = 64 - countLeadingZeros(d);
|
||||
lz = countLeadingZeros(d);
|
||||
lp = pwr10to2(p);
|
||||
e1 = 53 - b - lp;
|
||||
e1 = lz - (lp + 11);
|
||||
if( e1>1074 ){
|
||||
if( -(b + lp) >= 1077 ) return 0.0;
|
||||
if( e1>=1130 ) return 0.0;
|
||||
e1 = 1074;
|
||||
}
|
||||
e2 = e1 - (64-b);
|
||||
h = sqlite3Multiply128(d<<(64-b), powerOfTen(p));
|
||||
assert( -(e2 + lp + 3) >=0 );
|
||||
assert( -(e2 + lp + 3) <64 );
|
||||
out = (h >> -(e2 + lp + 3)) | 1;
|
||||
h = sqlite3Multiply128(d<<lz, powerOfTen(p));
|
||||
x = lz - (e1 + lp + 3);
|
||||
assert( x >= 0 );
|
||||
assert( x <= 63 );
|
||||
out = h >> x;
|
||||
if( out >= U64_BIT(55)-2 ){
|
||||
out = (out>>1) | (out&1);
|
||||
out >>= 1;
|
||||
e1--;
|
||||
}
|
||||
if( e1<=(-972) ){
|
||||
return INFINITY;
|
||||
}
|
||||
out = (out + 1 + ((out>>2)&1)) >> 2;
|
||||
out = (out + 2) >> 2;
|
||||
if( (out & U64_BIT(52))!=0 ){
|
||||
out = (out & ~U64_BIT(52)) | ((u64)(1075-e1)<<52);
|
||||
}
|
||||
@@ -708,8 +713,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
** The string z[] is an text representation of a real number.
|
||||
** Convert this string to a double and write it into *pResult.
|
||||
**
|
||||
** The string z[] is length bytes in length (bytes, not characters) and
|
||||
** uses the encoding enc. The string is not necessarily zero-terminated.
|
||||
** z[] must be UTF-8 and zero-terminated.
|
||||
**
|
||||
** Return TRUE if the result is a valid real number (or integer) and FALSE
|
||||
** if the string is empty or contains extraneous text. More specifically
|
||||
@@ -736,141 +740,131 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4756)
|
||||
#endif
|
||||
int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
int sqlite3AtoF(const char *z, double *pResult){
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int incr;
|
||||
const char *zEnd;
|
||||
/* sign * significand * (10 ^ (esign * exponent)) */
|
||||
int sign = 1; /* sign of significand */
|
||||
u64 s = 0; /* significand */
|
||||
int d = 0; /* adjust exponent for shifting decimal point */
|
||||
int esign = 1; /* sign of exponent */
|
||||
int e = 0; /* exponent */
|
||||
int eValid = 1; /* True exponent is either not used or is well-formed */
|
||||
int neg = 0; /* True for a negative value */
|
||||
u64 s = 0; /* mantissa */
|
||||
int d = 0; /* Value is s * pow(10,d) */
|
||||
int nDigit = 0; /* Number of digits processed */
|
||||
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
|
||||
int eType = 1; /* 1: pure integer, 2+: fractional */
|
||||
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
*pResult = 0.0; /* Default return value, in case of an error */
|
||||
if( length==0 ) return 0;
|
||||
|
||||
if( enc==SQLITE_UTF8 ){
|
||||
incr = 1;
|
||||
zEnd = z + length;
|
||||
}else{
|
||||
int i;
|
||||
incr = 2;
|
||||
length &= ~1;
|
||||
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
||||
testcase( enc==SQLITE_UTF16LE );
|
||||
testcase( enc==SQLITE_UTF16BE );
|
||||
for(i=3-enc; i<length && z[i]==0; i+=2){}
|
||||
if( i<length ) eType = -100;
|
||||
zEnd = &z[i^1];
|
||||
z += (enc&1);
|
||||
}
|
||||
|
||||
/* skip leading spaces */
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
if( z>=zEnd ) return 0;
|
||||
while( sqlite3Isspace(*z) ) z++;
|
||||
|
||||
/* get sign of significand */
|
||||
if( *z=='-' ){
|
||||
sign = -1;
|
||||
z+=incr;
|
||||
neg = 1;
|
||||
z++;
|
||||
}else if( *z=='+' ){
|
||||
z+=incr;
|
||||
z++;
|
||||
}
|
||||
|
||||
/* copy max significant digits to significand */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
while( sqlite3Isdigit(*z) ){
|
||||
s = s*10 + (*z - '0');
|
||||
z+=incr; nDigit++;
|
||||
z++; nDigit++;
|
||||
if( s>=((LARGEST_INT64-9)/10) ){
|
||||
/* skip non-significant significand digits
|
||||
** (increase exponent by d to shift decimal left) */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
|
||||
while( sqlite3Isdigit(*z) ){ z++; d++; }
|
||||
}
|
||||
}
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
|
||||
/* if decimal point is present */
|
||||
if( *z=='.' ){
|
||||
z+=incr;
|
||||
z++;
|
||||
eType++;
|
||||
/* copy digits from after decimal to significand
|
||||
** (decrease exponent by d to shift decimal right) */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
while( sqlite3Isdigit(*z) ){
|
||||
if( s<((LARGEST_INT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
d--;
|
||||
nDigit++;
|
||||
}
|
||||
z+=incr;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
|
||||
/* if exponent is present */
|
||||
if( *z=='e' || *z=='E' ){
|
||||
z+=incr;
|
||||
eValid = 0;
|
||||
int esign = 1; /* sign of exponent */
|
||||
z++;
|
||||
eType++;
|
||||
|
||||
/* This branch is needed to avoid a (harmless) buffer overread. The
|
||||
** special comment alerts the mutation tester that the correct answer
|
||||
** is obtained even if the branch is omitted */
|
||||
if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
|
||||
|
||||
/* get sign of exponent */
|
||||
if( *z=='-' ){
|
||||
esign = -1;
|
||||
z+=incr;
|
||||
z++;
|
||||
}else if( *z=='+' ){
|
||||
z+=incr;
|
||||
z++;
|
||||
}
|
||||
/* copy digits to exponent */
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
|
||||
z+=incr;
|
||||
eValid = 1;
|
||||
if( sqlite3Isdigit(*z) ){
|
||||
int exp = *z - '0';
|
||||
z++;
|
||||
while( sqlite3Isdigit(*z) ){
|
||||
exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000;
|
||||
z++;
|
||||
}
|
||||
d += esign*exp;
|
||||
}else{
|
||||
eType = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip trailing spaces */
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
while( sqlite3Isspace(*z) ) z++;
|
||||
|
||||
do_atof_calc:
|
||||
/* Zero is a special case */
|
||||
if( s==0 ){
|
||||
*pResult = sign<0 ? -0.0 : +0.0;
|
||||
goto atof_return;
|
||||
*pResult = neg ? -0.0 : +0.0;
|
||||
}else{
|
||||
*pResult = sqlite3Fp10Convert2(s,d);
|
||||
if( neg ) *pResult = -*pResult;
|
||||
assert( !sqlite3IsNaN(*pResult) );
|
||||
}
|
||||
|
||||
/* adjust exponent by d, and update sign */
|
||||
e = (e*esign) + d;
|
||||
|
||||
*pResult = sqlite3Fp10Convert2(s,e);
|
||||
if( sign<0 ) *pResult = -*pResult;
|
||||
assert( !sqlite3IsNaN(*pResult) );
|
||||
|
||||
atof_return:
|
||||
/* return true if number and no extra non-whitespace characters after */
|
||||
if( z==zEnd && nDigit>0 && eValid && eType>0 ){
|
||||
if( z[0]==0 && nDigit>0 ){
|
||||
return eType;
|
||||
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
|
||||
}else if( eType>=2 && nDigit>0 ){
|
||||
return -1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return !sqlite3Atoi64(z, pResult, length, enc);
|
||||
return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8);
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default : 4756)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Digit pairs used to convert a U64 or I64 into text, two digits
|
||||
** at a time.
|
||||
*/
|
||||
static const union {
|
||||
char a[201];
|
||||
short int forceAlignment;
|
||||
} sqlite3DigitPairs = {
|
||||
"00010203040506070809"
|
||||
"10111213141516171819"
|
||||
"20212223242526272829"
|
||||
"30313233343536373839"
|
||||
"40414243444546474849"
|
||||
"50515253545556575859"
|
||||
"60616263646566676869"
|
||||
"70717273747576777879"
|
||||
"80818283848586878889"
|
||||
"90919293949596979899"
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Render an signed 64-bit integer as text. Store the result in zOut[] and
|
||||
** return the length of the string that was stored, in bytes. The value
|
||||
@@ -882,23 +876,35 @@ atof_return:
|
||||
int sqlite3Int64ToText(i64 v, char *zOut){
|
||||
int i;
|
||||
u64 x;
|
||||
char zTemp[22];
|
||||
if( v<0 ){
|
||||
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
|
||||
}else{
|
||||
union {
|
||||
char a[23];
|
||||
u16 forceAlignment;
|
||||
} u;
|
||||
if( v>0 ){
|
||||
x = v;
|
||||
}else if( v==0 ){
|
||||
zOut[0] = '0';
|
||||
zOut[1] = 0;
|
||||
return 1;
|
||||
}else{
|
||||
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
|
||||
}
|
||||
i = sizeof(zTemp)-2;
|
||||
zTemp[sizeof(zTemp)-1] = 0;
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
zTemp[i] = (x%10) + '0';
|
||||
x = x/10;
|
||||
if( x==0 ) break;
|
||||
i--;
|
||||
};
|
||||
if( v<0 ) zTemp[--i] = '-';
|
||||
memcpy(zOut, &zTemp[i], sizeof(zTemp)-i);
|
||||
return sizeof(zTemp)-1-i;
|
||||
i = sizeof(u.a)-1;
|
||||
u.a[i] = 0;
|
||||
while( x>=10 ){
|
||||
int kk = (x%100)*2;
|
||||
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
|
||||
assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) );
|
||||
*(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
|
||||
i -= 2;
|
||||
x /= 100;
|
||||
}
|
||||
if( x ){
|
||||
u.a[--i] = x + '0';
|
||||
}
|
||||
if( v<0 ) u.a[--i] = '-';
|
||||
memcpy(zOut, &u.a[i], sizeof(u.a)-i);
|
||||
return sizeof(u.a)-1-i;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1155,7 +1161,7 @@ int sqlite3Atoi(const char *z){
|
||||
** representation.
|
||||
**
|
||||
** If iRound<=0 then round to -iRound significant digits to the
|
||||
** the left of the decimal point, or to a maximum of mxRound total
|
||||
** the right of the decimal point, or to a maximum of mxRound total
|
||||
** significant digits.
|
||||
**
|
||||
** If iRound>0 round to min(iRound,mxRound) significant digits total.
|
||||
@@ -1168,12 +1174,14 @@ int sqlite3Atoi(const char *z){
|
||||
** The p->z[] array is *not* zero-terminated.
|
||||
*/
|
||||
void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
int i;
|
||||
u64 v;
|
||||
int e, exp = 0;
|
||||
int i; /* Index into zBuf[] where to put next character */
|
||||
int n; /* Number of digits */
|
||||
u64 v; /* mantissa */
|
||||
int e, exp = 0; /* Base-2 and base-10 exponent */
|
||||
char *zBuf; /* Local alias for p->zBuf */
|
||||
char *z; /* Local alias for p->z */
|
||||
|
||||
p->isSpecial = 0;
|
||||
p->z = p->zBuf;
|
||||
assert( mxRound>0 );
|
||||
|
||||
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
|
||||
@@ -1196,67 +1204,89 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
|
||||
p->n = 0;
|
||||
p->iDP = 0;
|
||||
p->z = p->zBuf;
|
||||
return;
|
||||
}
|
||||
v &= 0x000fffffffffffffULL;
|
||||
if( e==0 ){
|
||||
int n = countLeadingZeros(v);
|
||||
v <<= n;
|
||||
e = -1074 - n;
|
||||
int nn = countLeadingZeros(v);
|
||||
v <<= nn;
|
||||
e = -1074 - nn;
|
||||
}else{
|
||||
v = (v<<11) | U64_BIT(63);
|
||||
e -= 1086;
|
||||
}
|
||||
sqlite3Fp2Convert10(v, e, 17, &v, &exp);
|
||||
sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp);
|
||||
|
||||
/* Extract significant digits. */
|
||||
/* Extract significant digits, start at the right-most slot in p->zBuf
|
||||
** and working back to the right. "i" keeps track of the next slot in
|
||||
** which to store a digit. */
|
||||
i = sizeof(p->zBuf)-1;
|
||||
zBuf = p->zBuf;
|
||||
assert( v>0 );
|
||||
while( v>=10 ){
|
||||
static const union {
|
||||
char a[200];
|
||||
short int forAlignment;
|
||||
} dig = {
|
||||
"00010203040506070809"
|
||||
"10111213141516171819"
|
||||
"20212223242526272829"
|
||||
"30313233343536373839"
|
||||
"40414243444546474849"
|
||||
"50515253545556575859"
|
||||
"60616263646566676869"
|
||||
"70717273747576777879"
|
||||
"80818283848586878889"
|
||||
"90919293949596979899"
|
||||
};
|
||||
int kk = (v%100)*2;
|
||||
assert( TWO_BYTE_ALIGNMENT(&dig.a[kk]) );
|
||||
assert( TWO_BYTE_ALIGNMENT(&p->zBuf[i-1]) );
|
||||
*(u16*)(&p->zBuf[i-1]) = *(u16*)&dig.a[kk];
|
||||
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
|
||||
assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) );
|
||||
*(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk];
|
||||
i -= 2;
|
||||
v /= 100;
|
||||
}
|
||||
if( v ){
|
||||
assert( v<10 );
|
||||
p->zBuf[i--] = v + '0';
|
||||
zBuf[i--] = v + '0';
|
||||
}
|
||||
assert( i>=0 && i<sizeof(p->zBuf)-1 );
|
||||
p->n = sizeof(p->zBuf) - 1 - i;
|
||||
assert( p->n>0 );
|
||||
assert( p->n<sizeof(p->zBuf) );
|
||||
p->iDP = p->n + exp;
|
||||
n = sizeof(p->zBuf) - 1 - i; /* Total number of digits extracted */
|
||||
assert( n>0 );
|
||||
assert( n<sizeof(p->zBuf) );
|
||||
testcase( n==sizeof(p->zBuf)-1 );
|
||||
p->iDP = n + exp;
|
||||
if( iRound<=0 ){
|
||||
iRound = p->iDP - iRound;
|
||||
if( iRound==0 && p->zBuf[i+1]>='5' ){
|
||||
if( iRound==0 && zBuf[i+1]>='5' ){
|
||||
iRound = 1;
|
||||
p->zBuf[i--] = '0';
|
||||
p->n++;
|
||||
zBuf[i--] = '0';
|
||||
n++;
|
||||
p->iDP++;
|
||||
}
|
||||
}
|
||||
if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
|
||||
char *z = &p->zBuf[i+1];
|
||||
z = &zBuf[i+1]; /* z points to the first digit */
|
||||
if( iRound>0 && (iRound<n || n>mxRound) ){
|
||||
if( iRound>mxRound ) iRound = mxRound;
|
||||
p->n = iRound;
|
||||
if( iRound==17 ){
|
||||
/* If the precision is exactly 17, which only happens with the "!"
|
||||
** flag (ex: "%!.17g") then try to reduce the precision if that
|
||||
** yields text that will round-trip to the original floating-point.
|
||||
** value. Thus, for exaple, 49.47 will render as 49.47, rather than
|
||||
** as 49.469999999999999. */
|
||||
if( z[15]=='9' && z[14]=='9' ){
|
||||
int jj, kk;
|
||||
u64 v2;
|
||||
for(jj=14; jj>0 && z[jj-1]=='9'; jj--){}
|
||||
if( jj==0 ){
|
||||
v2 = 1;
|
||||
}else{
|
||||
v2 = z[0] - '0';
|
||||
for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0';
|
||||
v2++;
|
||||
}
|
||||
if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){
|
||||
iRound = jj+1;
|
||||
}
|
||||
}else if( p->iDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){
|
||||
int jj, kk;
|
||||
u64 v2;
|
||||
assert( z[0]!='0' );
|
||||
for(jj=14; z[jj-1]=='0'; jj--){}
|
||||
v2 = z[0] - '0';
|
||||
for(kk=1; kk<jj; kk++) v2 = (v2*10) + z[kk] - '0';
|
||||
if( r==sqlite3Fp10Convert2(v2, exp + n - jj) ){
|
||||
iRound = jj+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
n = iRound;
|
||||
if( z[iRound]>='5' ){
|
||||
int j = iRound-1;
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
@@ -1264,8 +1294,9 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
if( z[j]<='9' ) break;
|
||||
z[j] = '0';
|
||||
if( j==0 ){
|
||||
p->z[i--] = '1';
|
||||
p->n++;
|
||||
z--;
|
||||
z[0] = '1';
|
||||
n++;
|
||||
p->iDP++;
|
||||
break;
|
||||
}else{
|
||||
@@ -1274,13 +1305,13 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
||||
}
|
||||
}
|
||||
}
|
||||
p->z = &p->zBuf[i+1];
|
||||
assert( i+p->n < sizeof(p->zBuf) );
|
||||
assert( p->n>0 );
|
||||
while( p->z[p->n-1]=='0' ){
|
||||
p->n--;
|
||||
assert( p->n>0 );
|
||||
assert( n>0 );
|
||||
while( z[n-1]=='0' ){
|
||||
n--;
|
||||
assert( n>0 );
|
||||
}
|
||||
p->n = n;
|
||||
p->z = z;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+5
-3
@@ -353,10 +353,9 @@ static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
|
||||
*/
|
||||
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
|
||||
double rValue;
|
||||
u8 enc = pRec->enc;
|
||||
int rc;
|
||||
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
|
||||
rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
|
||||
rValue = sqlite3MemRealValueRC(pRec, &rc);
|
||||
if( rc<=0 ) return;
|
||||
if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
|
||||
pRec->flags |= MEM_Int;
|
||||
@@ -438,7 +437,10 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){
|
||||
int eType = sqlite3_value_type(pVal);
|
||||
if( eType==SQLITE_TEXT ){
|
||||
Mem *pMem = (Mem*)pVal;
|
||||
assert( pMem->db!=0 );
|
||||
sqlite3_mutex_enter(pMem->db->mutex);
|
||||
applyNumericAffinity(pMem, 0);
|
||||
sqlite3_mutex_leave(pMem->db->mutex);
|
||||
eType = sqlite3_value_type(pVal);
|
||||
}
|
||||
return eType;
|
||||
@@ -471,7 +473,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
|
||||
pMem->u.i = 0;
|
||||
return MEM_Int;
|
||||
}
|
||||
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
|
||||
pMem->u.r = sqlite3MemRealValueRC(pMem, &rc);
|
||||
if( rc<=0 ){
|
||||
if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
|
||||
pMem->u.i = ix;
|
||||
|
||||
+2
-1
@@ -649,13 +649,14 @@ int sqlite3VdbeMemSetZeroBlob(Mem*,int);
|
||||
int sqlite3VdbeMemIsRowSet(const Mem*);
|
||||
#endif
|
||||
int sqlite3VdbeMemSetRowSet(Mem*);
|
||||
void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
|
||||
int sqlite3VdbeMemZeroTerminateIfAble(Mem*);
|
||||
int sqlite3VdbeMemMakeWriteable(Mem*);
|
||||
int sqlite3VdbeMemStringify(Mem*, u8, u8);
|
||||
int sqlite3IntFloatCompare(i64,double);
|
||||
i64 sqlite3VdbeIntValue(const Mem*);
|
||||
int sqlite3VdbeMemIntegerify(Mem*);
|
||||
double sqlite3VdbeRealValue(Mem*);
|
||||
SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem*, int*);
|
||||
int sqlite3VdbeBooleanValue(Mem*, int ifNull);
|
||||
void sqlite3VdbeIntegerAffinity(Mem*);
|
||||
int sqlite3VdbeMemRealify(Mem*);
|
||||
|
||||
+88
-23
@@ -107,21 +107,27 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
|
||||
StrAccum acc;
|
||||
assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
|
||||
assert( sz>22 );
|
||||
if( p->flags & MEM_Int ){
|
||||
#if GCC_VERSION>=7000000
|
||||
/* Work-around for GCC bug
|
||||
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
|
||||
if( p->flags & (MEM_Int|MEM_IntReal) ){
|
||||
#if GCC_VERSION>=7000000 && GCC_VERSION<15000000 && defined(__i386__)
|
||||
/* Work-around for GCC bug or bugs:
|
||||
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270
|
||||
** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
|
||||
** The problem appears to be fixed in GCC 15 */
|
||||
i64 x;
|
||||
assert( (p->flags&MEM_Int)*2==sizeof(x) );
|
||||
memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
|
||||
assert( (MEM_Str&~p->flags)*4==sizeof(x) );
|
||||
memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4);
|
||||
p->n = sqlite3Int64ToText(x, zBuf);
|
||||
#else
|
||||
p->n = sqlite3Int64ToText(p->u.i, zBuf);
|
||||
#endif
|
||||
if( p->flags & MEM_IntReal ){
|
||||
memcpy(zBuf+p->n,".0", 3);
|
||||
p->n += 2;
|
||||
}
|
||||
}else{
|
||||
sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
|
||||
sqlite3_str_appendf(&acc, "%!.15g",
|
||||
(p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
|
||||
sqlite3_str_appendf(&acc, "%!.*g",
|
||||
(p->db ? p->db->nFpDigit : 17), p->u.r);
|
||||
assert( acc.zText==zBuf && acc.mxAlloc<=0 );
|
||||
zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
|
||||
p->n = acc.nChar;
|
||||
@@ -170,6 +176,9 @@ int sqlite3VdbeMemValidStrRep(Mem *p){
|
||||
assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
|
||||
}
|
||||
if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
|
||||
if( p->db==0 ){
|
||||
return 1; /* db->nFpDigit required to validate p->z[] */
|
||||
}
|
||||
memcpy(&tmp, p, sizeof(tmp));
|
||||
vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp);
|
||||
z = p->z;
|
||||
@@ -320,13 +329,16 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
|
||||
**
|
||||
** This is an optimization. Correct operation continues even if
|
||||
** this routine is a no-op.
|
||||
**
|
||||
** Return true if the strig is zero-terminated after this routine is
|
||||
** called and false if it is not.
|
||||
*/
|
||||
void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
|
||||
int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
|
||||
if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){
|
||||
/* pMem must be a string, and it cannot be an ephemeral or static string */
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if( pMem->enc!=SQLITE_UTF8 ) return;
|
||||
if( pMem->enc!=SQLITE_UTF8 ) return 0;
|
||||
assert( pMem->z!=0 );
|
||||
if( pMem->flags & MEM_Dyn ){
|
||||
if( pMem->xDel==sqlite3_free
|
||||
@@ -334,18 +346,19 @@ void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
|
||||
){
|
||||
pMem->z[pMem->n] = 0;
|
||||
pMem->flags |= MEM_Term;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
if( pMem->xDel==sqlite3RCStrUnref ){
|
||||
/* Blindly assume that all RCStr objects are zero-terminated */
|
||||
pMem->flags |= MEM_Term;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
}else if( pMem->szMalloc >= pMem->n+1 ){
|
||||
pMem->z[pMem->n] = 0;
|
||||
pMem->flags |= MEM_Term;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -643,18 +656,70 @@ i64 sqlite3VdbeIntValue(const Mem *pMem){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Invoke sqlite3AtoF() on the text value of pMem and return the
|
||||
** double result. If sqlite3AtoF() returns an error code, write
|
||||
** that code into *pRC if (*pRC)!=NULL.
|
||||
**
|
||||
** The caller must ensure that pMem->db!=0 and that pMem is in
|
||||
** mode MEM_Str or MEM_Blob.
|
||||
*/
|
||||
SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem *pMem, int *pRC){
|
||||
double val = (double)0;
|
||||
int rc = 0;
|
||||
assert( pMem->db!=0 );
|
||||
assert( pMem->flags & (MEM_Str|MEM_Blob) );
|
||||
if( pMem->z==0 ){
|
||||
/* no-op */
|
||||
}else if( pMem->enc==SQLITE_UTF8
|
||||
&& ((pMem->flags & MEM_Term)!=0 || sqlite3VdbeMemZeroTerminateIfAble(pMem))
|
||||
){
|
||||
rc = sqlite3AtoF(pMem->z, &val);
|
||||
}else if( pMem->n==0 ){
|
||||
/* no-op */
|
||||
}else if( pMem->enc==SQLITE_UTF8 ){
|
||||
char *zCopy = sqlite3DbStrNDup(pMem->db, pMem->z, pMem->n);
|
||||
if( zCopy ){
|
||||
rc = sqlite3AtoF(zCopy, &val);
|
||||
sqlite3DbFree(pMem->db, zCopy);
|
||||
}
|
||||
}else{
|
||||
int n, i, j;
|
||||
char *zCopy;
|
||||
const char *z;
|
||||
|
||||
n = pMem->n & ~1;
|
||||
zCopy = sqlite3DbMallocRaw(pMem->db, n/2 + 2);
|
||||
if( zCopy ){
|
||||
z = pMem->z;
|
||||
if( pMem->enc==SQLITE_UTF16LE ){
|
||||
for(i=j=0; i<n-1; i+=2, j++){
|
||||
zCopy[j] = z[i];
|
||||
if( z[i+1]!=0 ) break;
|
||||
}
|
||||
}else{
|
||||
for(i=j=0; i<n-1; i+=2, j++){
|
||||
if( z[i]!=0 ) break;
|
||||
zCopy[j] = z[i+1];
|
||||
}
|
||||
}
|
||||
assert( j<=n/2 );
|
||||
zCopy[j] = 0;
|
||||
rc = sqlite3AtoF(zCopy, &val);
|
||||
if( i<n ) rc = -100;
|
||||
sqlite3DbFree(pMem->db, zCopy);
|
||||
}
|
||||
}
|
||||
if( pRC ) *pRC = rc;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the best representation of pMem that we can get into a
|
||||
** double. If pMem is already a double or an integer, return its
|
||||
** value. If it is a string or blob, try to convert it to a double.
|
||||
** If it is a NULL, return 0.0.
|
||||
*/
|
||||
static SQLITE_NOINLINE double memRealValue(Mem *pMem){
|
||||
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
|
||||
double val = (double)0;
|
||||
sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
|
||||
return val;
|
||||
}
|
||||
double sqlite3VdbeRealValue(Mem *pMem){
|
||||
assert( pMem!=0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
@@ -665,7 +730,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
|
||||
testcase( pMem->flags & MEM_IntReal );
|
||||
return (double)pMem->u.i;
|
||||
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
|
||||
return memRealValue(pMem);
|
||||
return sqlite3MemRealValueRC(pMem, 0);
|
||||
}else{
|
||||
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
|
||||
return (double)0;
|
||||
@@ -789,7 +854,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
|
||||
sqlite3_int64 ix;
|
||||
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
|
||||
pMem->u.r = sqlite3MemRealValueRC(pMem, &rc);
|
||||
if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
|
||||
|| sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
|
||||
){
|
||||
@@ -1760,7 +1825,7 @@ static int valueFromExpr(
|
||||
if( affinity==SQLITE_AFF_BLOB ){
|
||||
if( op==TK_FLOAT ){
|
||||
assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) );
|
||||
sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8);
|
||||
sqlite3AtoF(pVal->z, &pVal->u.r);
|
||||
pVal->flags = MEM_Real;
|
||||
}else if( op==TK_INTEGER ){
|
||||
/* This case is required by -9223372036854775808 and other strings
|
||||
|
||||
@@ -2254,68 +2254,82 @@ static int walCheckpoint(
|
||||
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
|
||||
){
|
||||
u32 nBackfill = pInfo->nBackfill;
|
||||
pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
|
||||
WalIndexHdr *pLive = (WalIndexHdr*)walIndexHdr(pWal);
|
||||
|
||||
/* Sync the WAL to disk */
|
||||
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
|
||||
/* If the database may grow as a result of this checkpoint, hint
|
||||
** about the eventual size of the db file to the VFS layer.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
i64 nReq = ((i64)mxPage * szPage);
|
||||
i64 nSize; /* Current size of database file */
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
|
||||
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
|
||||
if( rc==SQLITE_OK && nSize<nReq ){
|
||||
if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)<nReq ){
|
||||
/* If the size of the final database is larger than the current
|
||||
** database plus the amount of data in the wal file, plus the
|
||||
** maximum size of the pending-byte page (65536 bytes), then
|
||||
** must be corruption somewhere. */
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Iterate through the contents of the WAL, copying data to the db file */
|
||||
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
|
||||
i64 iOffset;
|
||||
assert( walFramePgno(pWal, iFrame)==iDbpage );
|
||||
SEH_INJECT_FAULT;
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
|
||||
continue;
|
||||
}
|
||||
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
|
||||
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
|
||||
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
iOffset = (iDbpage-1)*(i64)szPage;
|
||||
testcase( IS_BIG_INT(iOffset) );
|
||||
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
|
||||
|
||||
/* If work was actually accomplished... */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
|
||||
i64 szDb = pWal->hdr.nPage*(i64)szPage;
|
||||
testcase( IS_BIG_INT(szDb) );
|
||||
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
}
|
||||
}
|
||||
/* Now that read-lock slot 0 is locked, check that the wal has not been
|
||||
** wrapped since the header was read for this checkpoint. If it was, then
|
||||
** there was no work to do anyway. In this case the
|
||||
** (pInfo->nBackfill<pWal->hdr.mxFrame) test above only passed because
|
||||
** pInfo->nBackfill had already been set to 0 by the writer that wrapped
|
||||
** the wal file. It would also be dangerous to proceed, as there may be
|
||||
** fewer than pWal->hdr.mxFrame valid frames in the wal file. */
|
||||
int bChg = memcmp(pLive->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt));
|
||||
if( 0==bChg ){
|
||||
pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT;
|
||||
|
||||
/* Sync the WAL to disk */
|
||||
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
|
||||
/* If the database may grow as a result of this checkpoint, hint
|
||||
** about the eventual size of the db file to the VFS layer.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
|
||||
i64 nReq = ((i64)mxPage * szPage);
|
||||
i64 nSize; /* Current size of database file */
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
|
||||
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
|
||||
if( rc==SQLITE_OK && nSize<nReq ){
|
||||
if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)<nReq ){
|
||||
/* If the size of the final database is larger than the current
|
||||
** database plus the amount of data in the wal file, plus the
|
||||
** maximum size of the pending-byte page (65536 bytes), then
|
||||
** must be corruption somewhere. */
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
sqlite3OsFileControlHint(
|
||||
pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Iterate through the contents of the WAL, copying data to the
|
||||
** db file */
|
||||
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
|
||||
i64 iOffset;
|
||||
assert( walFramePgno(pWal, iFrame)==iDbpage );
|
||||
SEH_INJECT_FAULT;
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
||||
break;
|
||||
}
|
||||
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
|
||||
continue;
|
||||
}
|
||||
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
|
||||
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
|
||||
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
iOffset = (iDbpage-1)*(i64)szPage;
|
||||
testcase( IS_BIG_INT(iOffset) );
|
||||
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
|
||||
|
||||
/* If work was actually accomplished... */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
|
||||
i64 szDb = pWal->hdr.nPage*(i64)szPage;
|
||||
testcase( IS_BIG_INT(szDb) );
|
||||
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4362,9 +4376,10 @@ int sqlite3WalCheckpoint(
|
||||
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Copy data from the log to the database file. */
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3FaultSim(660);
|
||||
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){
|
||||
|
||||
+1
-1
@@ -3182,7 +3182,7 @@ static int whereRangeVectorLen(
|
||||
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
|
||||
if( aff!=idxaff ) break;
|
||||
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
|
||||
if( pColl==0 ) break;
|
||||
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
|
||||
}
|
||||
|
||||
+3
-2
@@ -293,13 +293,14 @@ static int isLikeOrGlob(
|
||||
){
|
||||
int isNum;
|
||||
double rDummy;
|
||||
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
|
||||
assert( zNew[iTo]==0 );
|
||||
isNum = sqlite3AtoF(zNew, &rDummy);
|
||||
if( isNum<=0 ){
|
||||
if( iTo==1 && zNew[0]=='-' ){
|
||||
isNum = +1;
|
||||
}else{
|
||||
zNew[iTo-1]++;
|
||||
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
|
||||
isNum = sqlite3AtoF(zNew, &rDummy);
|
||||
zNew[iTo-1]--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# 2026-02-20
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests of the sqlite3AtoF() function.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Rounding cases:
|
||||
#
|
||||
do_execsql_test atof2-1.0 {
|
||||
SELECT format('%g',192.496475);
|
||||
} 192.496
|
||||
do_execsql_test atof2-1.1 {
|
||||
SELECT format('%g',192.496501);
|
||||
} 192.497
|
||||
|
||||
load_static_extension db ieee754
|
||||
do_execsql_test atof2-2.1 {
|
||||
SELECT format('%!.30f',ieee754_inc(100.0,-1));
|
||||
} 99.9999999999999858
|
||||
do_execsql_test atof2-2.2 {
|
||||
SELECT format('%!.30f',ieee754_inc(100.0,-2));
|
||||
} 99.9999999999999716
|
||||
|
||||
finish_test
|
||||
@@ -34,7 +34,7 @@ proc vtab_command {method args} {
|
||||
set orderby [$hdl orderby]
|
||||
|
||||
if {[info exists ::xbestindex_sql]} {
|
||||
explain_i $::xbestindex_sql
|
||||
# explain_i $::xbestindex_sql
|
||||
set ::xbestindex_res [ execsql $::xbestindex_sql ]
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1744,10 +1744,10 @@ do_execsql_test e_expr-32.2.8 {
|
||||
integer 9223372036854775807 \
|
||||
integer 9223372036854775807 \
|
||||
integer 9223372036854775807 \
|
||||
real 9.22337203685478e+18 \
|
||||
real 9.22337203685478e+18 \
|
||||
real 9.22337203685478e+18 \
|
||||
real 9.22337203685478e+18 \
|
||||
real 9.2233720368547758e+18 \
|
||||
real 9.2233720368547758e+18 \
|
||||
real 9.2233720368547758e+18 \
|
||||
real 9.2233720368547758e+18 \
|
||||
integer -5 \
|
||||
integer -5 \
|
||||
]
|
||||
|
||||
+60
-6
@@ -17,28 +17,82 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
|
||||
# Unusual rendering cases:
|
||||
#
|
||||
do_execsql_test fpconv1-1.0 {
|
||||
SELECT 1.23 - 2.34;
|
||||
} {-1.1099999999999999}
|
||||
# ^--- Not -1.11 as you would expect. -1.11 has a different bit pattern
|
||||
|
||||
do_execsql_test fpconv1-1.1 {
|
||||
SELECT 1.23 * 2.34;
|
||||
} {2.8781999999999996}
|
||||
# ^--- Not 2.8782 as you would expect. 2.8782 has a different bit pattern
|
||||
|
||||
# Change significant digits to 15 and get a different result.
|
||||
sqlite3_db_config db FP_DIGITS 15
|
||||
do_execsql_test fpconv1-1.2 {
|
||||
SELECT 1.23 - 2.34;
|
||||
} {-1.11}
|
||||
do_execsql_test fpconv1-1.3 {
|
||||
SELECT 1.23 * 2.34;
|
||||
} {2.8782}
|
||||
sqlite3_db_config db FP_DIGITS 17
|
||||
|
||||
|
||||
if {[catch {load_static_extension db decimal} error]} {
|
||||
puts "Skipping decimal tests, hit load error: $error"
|
||||
finish_test; return
|
||||
}
|
||||
|
||||
sqlite3_create_function db
|
||||
do_execsql_test fpconv1-1.0 {
|
||||
do_execsql_test fpconv1-2.0 {
|
||||
WITH RECURSIVE
|
||||
/* Number of random floating-point values to try.
|
||||
** On a circa 2016 x64 linux box, this test runs at
|
||||
** about 80000 cases per second -------------------vvvvvv */
|
||||
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100000),
|
||||
** On a circa 2021 Ryzen 5950X running Mint Linux, and
|
||||
** compiled with -O0 -DSQLITE_DEBUG, this test runs at
|
||||
** about 150000 cases per second ------------------vvvvvvv */
|
||||
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<500_000),
|
||||
fp(y) AS MATERIALIZED (
|
||||
SELECT CAST( format('%+d.%019d0e%+03d',
|
||||
random()%10,abs(random()),random()%200) AS real)
|
||||
FROM c
|
||||
)
|
||||
SELECT y FROM fp
|
||||
WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<15.0;
|
||||
WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<17.0;
|
||||
/* Number of digits of accuracy required -------^^^^ */
|
||||
} {}
|
||||
# ^---- Expect a empty set as the result. The output is all tested numbers
|
||||
# that fail to preserve at least 15 significant digits of accuracy.
|
||||
# that fail to preserve at least 16 significant digits of accuracy.
|
||||
|
||||
########################################################################
|
||||
# Random test to ensure that double -> text -> double conversions
|
||||
# round-trip exactly.
|
||||
#
|
||||
|
||||
load_static_extension db ieee754
|
||||
|
||||
do_execsql_test fpconv1-3.0 {
|
||||
WITH RECURSIVE
|
||||
c(x,s) AS MATERIALIZED (VALUES(1,random()&0xffefffffffffffff)
|
||||
UNION ALL
|
||||
SELECT x+1,random()&0xffefffffffffffff
|
||||
FROM c WHERE x<1_000_000),
|
||||
fp(y,s) AS (
|
||||
SELECT ieee754_from_int(s),s FROM c
|
||||
),
|
||||
fp2(yt,y,s) AS (
|
||||
SELECT y||'', y, s FROM fp
|
||||
)
|
||||
SELECT format('%#016x',s) aS 'orig-hex',
|
||||
format('%#016x',ieee754_to_int(CAST(yt AS real))) AS 'full-roundtrip',
|
||||
yt AS 'rendered-as',
|
||||
decimal_exp(yt,30) AS 'text-decimal',
|
||||
decimal_exp(ieee754_from_int(s),30) AS 'float-decimal'
|
||||
FROM fp2
|
||||
WHERE ieee754_to_int(CAST(yt AS real))<>s;
|
||||
} {}
|
||||
# ^---- Values that fail to round-trip will be reported
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#!sqlite3
|
||||
#
|
||||
# 2026-03-01
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Floating-point to text conversions
|
||||
#
|
||||
|
||||
# Verify that binary64 -> text -> binary64 conversions round-trip
|
||||
# successfully for 98,256 different edge-case binary64 values. The
|
||||
# query result is all cases that do not round-trip without change,
|
||||
# and so the query result should be an empty set.
|
||||
#
|
||||
.testcase 100
|
||||
.mode list
|
||||
WITH
|
||||
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<15),
|
||||
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
|
||||
i3(k) AS (VALUES(0x0000000000000000),
|
||||
(0x000ffffffffffff0),
|
||||
(0x0008080808080800)),
|
||||
fpint(n) AS (SELECT (j<<52)+i+k FROM i2, i1, i3),
|
||||
fp(n,r) AS (SELECT n, ieee754_from_int(n) FROM fpint)
|
||||
SELECT n, r FROM fp WHERE r<>(0.0 + (r||''));
|
||||
.check ''
|
||||
|
||||
# Another batch of 106,444 edge cases: All postiive floating point
|
||||
# values that have only a single bit set in the mantissa part of the
|
||||
# number.
|
||||
#
|
||||
.testcase 110
|
||||
WITH
|
||||
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<51),
|
||||
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
|
||||
fpint(n) AS (SELECT (j<<52)+(1<<i) FROM i2, i1),
|
||||
fp(n,r) AS (SELECT n, ieee754_from_int(n) FROM fpint)
|
||||
SELECT n, r FROM fp WHERE r<>(0.0 + (r||''));
|
||||
.check ''
|
||||
|
||||
# Verify that text -> binary64 conversions agree with system strtod().
|
||||
# for 98,256 different edge-cases.
|
||||
#
|
||||
.testcase 200
|
||||
.mode list
|
||||
WITH
|
||||
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<15),
|
||||
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
|
||||
i3(k) AS (VALUES(0x0000000000000000),
|
||||
(0x000ffffffffffff0),
|
||||
(0x0008080808080800)),
|
||||
fpint(n) AS (SELECT (j<<52)+i+k FROM i2, i1, i3),
|
||||
fp(r) AS (SELECT ieee754_from_int(n) FROM fpint)
|
||||
SELECT r FROM fp WHERE r<>strtod(r||'');
|
||||
.check ''
|
||||
|
||||
|
||||
# Another batch of 106,444 edge cases: All postiive floating point
|
||||
# values that have only a single bit set in the mantissa part of the
|
||||
# number.
|
||||
#
|
||||
.testcase 210
|
||||
WITH
|
||||
i1(i) AS (VALUES(0) UNION ALL SELECT i+1 FROM i1 WHERE i<51),
|
||||
i2(j) AS (VALUES(0) UNION ALL SELECT j+1 FROM i2 WHERE j<0x7fe),
|
||||
fpint(n) AS (SELECT (j<<52)+(1<<i) FROM i2, i1),
|
||||
fp(r) AS (SELECT ieee754_from_int(n) FROM fpint)
|
||||
SELECT r FROM fp WHERE r<>strtod(r||'');
|
||||
.check ''
|
||||
@@ -0,0 +1,23 @@
|
||||
#!sqlite3
|
||||
#
|
||||
# 2026-03-01
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Bug report sqlite.org/forum/forumpost/efc9bc9cb3
|
||||
#
|
||||
.testcase 100
|
||||
.mode quote
|
||||
.intck 1
|
||||
SELECT parse_create_index('CREATE IDEX i ON t("x',0);
|
||||
.check <<END
|
||||
1 steps, 0 errors
|
||||
NULL
|
||||
END
|
||||
@@ -121,5 +121,52 @@ do_execsql_test 5.1 {
|
||||
INNER JOIN child2 ON child2.child2key = parent1.child2key;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t5(a, d);
|
||||
CREATE TABLE t6(a, e);
|
||||
INSERT INTO t5 VALUES(1, 'red');
|
||||
INSERT INTO t6 VALUES(0, 1000);
|
||||
|
||||
CREATE TABLE t7(x);
|
||||
CREATE TABLE t8(y);
|
||||
}
|
||||
|
||||
do_catchsql_test 6.1 {
|
||||
SELECT * FROM t6 CROSS JOIN (t7 RIGHT JOIN t8 ON (t6.a));
|
||||
} {1 {no such column: t6.a}}
|
||||
|
||||
do_catchsql_test 6.4 {
|
||||
SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6;
|
||||
} {1 {ON clause references tables to its right}}
|
||||
|
||||
do_catchsql_test 6.5 {
|
||||
SELECT * FROM
|
||||
(SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6);
|
||||
} {1 {ON clause references tables to its right}}
|
||||
|
||||
do_catchsql_test 6.6 {
|
||||
SELECT *, NOT EXISTS (
|
||||
SELECT * FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
|
||||
) FROM t5;
|
||||
} {1 {ON clause references tables to its right}}
|
||||
|
||||
do_catchsql_test 6.7 {
|
||||
SELECT *, NOT EXISTS (
|
||||
SELECT 1
|
||||
EXCEPT
|
||||
SELECT 11 FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
|
||||
) FROM t5;
|
||||
} {1 {ON clause references tables to its right}}
|
||||
|
||||
do_catchsql_test 6.8 {
|
||||
SELECT *, NOT EXISTS (
|
||||
SELECT 11 FROM t7 RIGHT JOIN t8 ON (t6.a) CROSS JOIN t6
|
||||
EXCEPT
|
||||
SELECT 1
|
||||
) FROM t5;
|
||||
} {1 {ON clause references tables to its right}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+16
-10
@@ -115,6 +115,10 @@ ifcapable threadsafe1&&shared_cache {
|
||||
}
|
||||
} {
|
||||
|
||||
ifcapable thread_misuse_warnings {
|
||||
if {$mode ne "serialized"} continue
|
||||
}
|
||||
|
||||
# For journal_mode=memory, the static_prng mutex is not required. This
|
||||
# is because the header of an in-memory journal does not contain
|
||||
# any random bytes, and so no call to sqlite3_randomness() is made.
|
||||
@@ -177,16 +181,18 @@ ifcapable threadsafe1&&shared_cache {
|
||||
|
||||
# Open and use a connection in "nomutex" mode. Test that no recursive
|
||||
# mutexes are obtained.
|
||||
do_test mutex1.3.1 {
|
||||
catch {db close}
|
||||
clear_mutex_counters
|
||||
sqlite3 db test.db -nomutex 1
|
||||
execsql { SELECT * FROM abc }
|
||||
} {1 2 3 1 2 3 1 2 3}
|
||||
do_test mutex1.3.2 {
|
||||
mutex_counters counters
|
||||
set counters(recursive)
|
||||
} {0}
|
||||
ifcapable !thread_misuse_warnings {
|
||||
do_test mutex1.3.1 {
|
||||
catch {db close}
|
||||
clear_mutex_counters
|
||||
sqlite3 db test.db -nomutex 1
|
||||
execsql { SELECT * FROM abc }
|
||||
} {1 2 3 1 2 3 1 2 3}
|
||||
do_test mutex1.3.2 {
|
||||
mutex_counters counters
|
||||
set counters(recursive)
|
||||
} {0}
|
||||
}
|
||||
}
|
||||
|
||||
# Test the sqlite3_db_mutex() function.
|
||||
|
||||
+8
-8
@@ -697,13 +697,13 @@ do_test 5.2b {
|
||||
mtime: 1333101221
|
||||
datetime(...: 2012-03-30 09:53:41
|
||||
value: x'cc7c57616c706861b535332e31313638383732334762
|
||||
657461c73071726657696474685072696e7428702c2070
|
||||
2d3e704f75742c202d702d3e752e734c696e652e6d7843
|
||||
...
|
||||
657461c73071726657696474685072696e7428702c2070
|
||||
2d3e704f75742c202d702d3e752e734c696e652e6d7843
|
||||
...
|
||||
|
||||
name: one
|
||||
two
|
||||
three
|
||||
two
|
||||
three
|
||||
mtime: 1333206973
|
||||
datetime(...: 2012-03-31 15:16:13
|
||||
value:
|
||||
@@ -712,9 +712,9 @@ datetime(...: 2012-03-31 15:16:13
|
||||
mtime: 1708791504
|
||||
datetime(...: 2024-02-24 16:18:24
|
||||
value: x'00000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000
|
||||
...
|
||||
0000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000
|
||||
...
|
||||
}
|
||||
set sql "SELECT name, mtime, datetime(mtime,'unixepoch') AS time,\
|
||||
value FROM t1 ORDER BY mtime"
|
||||
|
||||
@@ -73,4 +73,29 @@ do_catchsql_test 2.3 {
|
||||
SELECT 2 IN ( (1, 2), (3, 4), (5, 6) )
|
||||
} {1 {row value misused}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the fix for forum post https://sqlite.org/forum/forumpost/6ceca07fc3
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE x2 (x, y);
|
||||
INSERT INTO x2 VALUES (1234, 'abc');
|
||||
|
||||
CREATE TABLE x1 (a, b PRIMARY KEY COLLATE NOCASE) WITHOUT ROWID;
|
||||
INSERT INTO x1 VALUES (1234, 'ABCD');
|
||||
}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM x2 CROSS JOIN x1 WHERE (1234, x2.y) > (x1.a, x1.b);
|
||||
} {1234 abc 1234 ABCD}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
CREATE INDEX x1a ON x1(a);
|
||||
}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
SELECT * FROM x2 CROSS JOIN x1 WHERE (1234, x2.y) > (x1.a, x1.b);
|
||||
} {1234 abc 1234 ABCD}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1121,6 +1121,7 @@ do_test shell1-4.7 {
|
||||
|
||||
# Test using arbitrary byte data with the shell via standard input/output.
|
||||
#
|
||||
if 0 { # Causes a valgrind error in TCL. Seems to be a TCL problem.
|
||||
do_test shell1-5.0 {
|
||||
#
|
||||
# NOTE: Skip NUL byte because it appears to be incompatible with command
|
||||
@@ -1187,6 +1188,7 @@ do_test shell1-5.0 {
|
||||
}
|
||||
}
|
||||
} {}
|
||||
}
|
||||
|
||||
# These test cases do not work on MinGW
|
||||
if 0 {
|
||||
|
||||
@@ -217,6 +217,46 @@ if {$tcl_platform(platform)=="unix"} {
|
||||
do_test 3.3 {
|
||||
catchcmd shell8.db {.ar -x}
|
||||
} {0 {}}
|
||||
|
||||
# Test defenses against using symlinks to write outside
|
||||
# of the destination directory. See forum thread at
|
||||
# sqlite.org/forum/forumpost/2026-02-21T11:04:36z
|
||||
#
|
||||
forcedelete shell8.db
|
||||
forcedelete ar1
|
||||
forcedelete ar2
|
||||
forcedelete ar3
|
||||
file mkdir ar2
|
||||
file mkdir ar3
|
||||
set pwd [pwd]
|
||||
sqlite3 db shell8.db
|
||||
db eval {
|
||||
CREATE TABLE sqlar(
|
||||
name TEXT PRIMARY KEY, -- name of the file
|
||||
mode INT, -- access permissions
|
||||
mtime INT, -- last modification time
|
||||
sz INT, -- original file size
|
||||
data BLOB -- compressed content
|
||||
);
|
||||
INSERT INTO sqlar VALUES
|
||||
('abc',33188,0,-1,'content for abc'),
|
||||
('escape',40960,0,-1,$pwd||'/ar3'),
|
||||
('escape/def',33188,0,-1,'content for escape/def'),
|
||||
('ghi',33188,0,-1,'content for ghi');
|
||||
}
|
||||
do_test 3.4.1 {
|
||||
catchcmd shell8.db {.ar -x --directory ar2}
|
||||
lsort [glob -tails -directory ar2 -nocomplain *]
|
||||
} {abc escape ghi}
|
||||
do_test 3.4.2 {
|
||||
lsort [glob -tails -directory ar3 -nocomplain *]
|
||||
} {}
|
||||
# ^^--- An extraction into ar2 should not leak any files into ar3
|
||||
|
||||
forcedelete shell8.db
|
||||
forcedelete ar2
|
||||
forcedelete ar3
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -46,6 +46,8 @@ do_clitest imposter1.sql
|
||||
do_clitest dotcmd01.sql
|
||||
ifcapable vtab {
|
||||
do_clitest import01.sql
|
||||
do_clitest intck01.sql
|
||||
}
|
||||
do_clitest fptest01.sql
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -192,6 +192,7 @@ namespace eval trd {
|
||||
-DSQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
-DSQLITE_MAX_ATTACHED=125
|
||||
-DSQLITE_MUTATION_TEST
|
||||
-DSQLITE_THREAD_MISUSE_ABORT
|
||||
--enable-fts5
|
||||
}
|
||||
set build(Debug-Two) {
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@ do_execsql_test 1.0 {
|
||||
}
|
||||
|
||||
|
||||
explain_i {
|
||||
INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||
}
|
||||
#explain_i {
|
||||
# INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||
#}
|
||||
do_execsql_test 1.1.1 {
|
||||
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# 2026-03-03
|
||||
#
|
||||
# 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 file is testing a race condition in WAL restart.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
if {$::tcl_platform(platform) ne "unix"} {
|
||||
# This test only works on unix
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set testprefix walrestart
|
||||
|
||||
if {[permutation]=="memsubsys1"} {
|
||||
# memsubsys1 configures a very small page-cache, which causes different
|
||||
# numbers of frames to be written to the wal file for some transactions,
|
||||
# which causes some of the tests in this file to fail.
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
|
||||
proc faultsim {n} { return 0 }
|
||||
sqlite3_test_control_fault_install faultsim
|
||||
|
||||
# Populate database. Create a large wal file and checkpoint it.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<20
|
||||
)
|
||||
INSERT INTO t1 SELECT NULL, randomblob(600) FROM s;
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
PRAGMA wal_checkpoint;
|
||||
} {wal 0 49 49}
|
||||
do_execsql_test 1.1 {
|
||||
UPDATE t1 SET b=randomblob(600);
|
||||
PRAGMA wal_checkpoint;
|
||||
} {0 45 45}
|
||||
|
||||
# We have a completely checkpointed wal file on disk. mxFrame=$large,
|
||||
# nBackfill=$large. Do another checkpoint with [db]. This time, after [db]
|
||||
# reads mxFrame but before it reads nBackfill, write to the db such
|
||||
# that 0 < mxFrame < large.
|
||||
#
|
||||
proc faultsim {n} {
|
||||
if {$n==660} {
|
||||
db2 eval { UPDATE t1 SET b=randomblob(600) WHERE a<5 }
|
||||
}
|
||||
return 0
|
||||
}
|
||||
sqlite3 db2 test.db
|
||||
do_execsql_test 1.2 {
|
||||
PRAGMA wal_checkpoint;
|
||||
} {0 45 0}
|
||||
|
||||
# Now write another big update to the wal file and checkpoint it.
|
||||
#
|
||||
do_execsql_test -db db2 1.3 {
|
||||
UPDATE t1 SET b=randomblob(600);
|
||||
}
|
||||
proc faultsim {n} { return 0 }
|
||||
do_execsql_test 1.4 {
|
||||
PRAGMA wal_checkpoint;
|
||||
} {0 58 58}
|
||||
|
||||
do_catchsql_test 1.5 {
|
||||
PRAGMA integrity_check
|
||||
} {0 ok}
|
||||
|
||||
finish_test
|
||||
@@ -302,4 +302,19 @@ do_execsql_test 7.1 {
|
||||
SELECT length(name) FROM t1;
|
||||
} {60000}
|
||||
|
||||
|
||||
# https://sqlite.org/forum/forumpost/721a05d2c5
|
||||
#
|
||||
if {[catch { load_static_extension db fileio }]==0} {
|
||||
forcedelete test.zip
|
||||
set fd [open test.zip wb]
|
||||
fconfigure $fd -translation binary
|
||||
puts -nonewline $fd [db one {SELECT X'504b0506000000000100010030000000160000000000504b01021400140000000000000000000000000000000000000000000100010000000000000000000000000000006100'}]
|
||||
close $fd
|
||||
|
||||
do_catchsql_test 8.0 {
|
||||
SELECT name,sz FROM zipfile(readfile('test.zip'));
|
||||
} {1 {failed to read LFH at offset 0}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -123,7 +123,6 @@ set CompileOptionsToTest {
|
||||
SQLITE_ENABLE_MEMSYS
|
||||
SQLITE_ENABLE_MODULE_COMMENTS
|
||||
SQLITE_ENABLE_MULTIPLEX
|
||||
SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
SQLITE_ENABLE_NORMALIZE
|
||||
SQLITE_ENABLE_NULL_TRIM
|
||||
SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
@@ -152,6 +151,7 @@ set CompileOptionsToTest {
|
||||
SQLITE_ENABLE_VFSTRACE
|
||||
SQLITE_ENABLE_WHERETRACE
|
||||
SQLITE_ENABLE_ZIPVFS
|
||||
SQLITE_THREAD_MISUSE_WARNINGS
|
||||
}
|
||||
|
||||
# Parse command-line options.
|
||||
|
||||
+20
-17
@@ -28,6 +28,9 @@
|
||||
#include "sqlite3.h"
|
||||
#include "sqlite3_stdio.h"
|
||||
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef sqlite3_uint64 u64;
|
||||
|
||||
/*
|
||||
** All global variables are gathered into the "g" singleton.
|
||||
*/
|
||||
@@ -202,12 +205,12 @@ static char **columnNames(
|
||||
int *pbRowid /* OUT: True if PK is an implicit rowid */
|
||||
){
|
||||
char **az = 0; /* List of column names to be returned */
|
||||
int naz = 0; /* Number of entries in az[] */
|
||||
i64 naz = 0; /* Number of entries in az[] */
|
||||
sqlite3_stmt *pStmt; /* SQL statement being run */
|
||||
char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */
|
||||
int truePk = 0; /* PRAGMA table_info identifies the PK to use */
|
||||
int nPK = 0; /* Number of PRIMARY KEY columns */
|
||||
int i, j; /* Loop counters */
|
||||
i64 nPK = 0; /* Number of PRIMARY KEY columns */
|
||||
i64 i, j; /* Loop counters */
|
||||
|
||||
if( g.bSchemaPK==0 ){
|
||||
/* Normal case: Figure out what the true primary key is for the table.
|
||||
@@ -271,7 +274,7 @@ static char **columnNames(
|
||||
}
|
||||
*pnPKey = nPK;
|
||||
naz = nPK;
|
||||
az = sqlite3_malloc( sizeof(char*)*(nPK+1) );
|
||||
az = sqlite3_malloc64( sizeof(char*)*(nPK+1) );
|
||||
if( az==0 ) runtimeError("out of memory");
|
||||
memset(az, 0, sizeof(char*)*(nPK+1));
|
||||
if( g.bSchemaCompare ){
|
||||
@@ -288,7 +291,7 @@ static char **columnNames(
|
||||
|| !(strcmp(sid,"rootpage")==0
|
||||
||strcmp(sid,"name")==0
|
||||
||strcmp(sid,"type")==0)){
|
||||
az = sqlite3_realloc(az, sizeof(char*)*(naz+2) );
|
||||
az = sqlite3_realloc64(az, sizeof(char*)*(naz+2) );
|
||||
if( az==0 ) runtimeError("out of memory");
|
||||
az[naz++] = sid;
|
||||
}
|
||||
@@ -954,7 +957,7 @@ static int rbuDeltaCreate(
|
||||
unsigned int i, base;
|
||||
char *zOrigDelta = zDelta;
|
||||
hash h;
|
||||
int nHash; /* Number of hash table entries */
|
||||
i64 nHash; /* Number of hash table entries */
|
||||
int *landmark; /* Primary hash table */
|
||||
int *collide; /* Collision chain */
|
||||
int lastRead = -1; /* Last byte of zSrc read by a COPY command */
|
||||
@@ -982,7 +985,7 @@ static int rbuDeltaCreate(
|
||||
** source file.
|
||||
*/
|
||||
nHash = lenSrc/NHASH;
|
||||
collide = sqlite3_malloc( nHash*2*sizeof(int) );
|
||||
collide = sqlite3_malloc64( nHash*2*sizeof(int) );
|
||||
landmark = &collide[nHash];
|
||||
memset(landmark, -1, nHash*sizeof(int));
|
||||
memset(collide, -1, nHash*sizeof(int));
|
||||
@@ -1286,9 +1289,9 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
}
|
||||
}else{
|
||||
char *zOtaControl;
|
||||
int nOtaControl = sqlite3_column_bytes(pStmt, nCol);
|
||||
i64 nOtaControl = sqlite3_column_bytes(pStmt, nCol);
|
||||
|
||||
zOtaControl = (char*)sqlite3_malloc(nOtaControl+1);
|
||||
zOtaControl = (char*)sqlite3_malloc64(nOtaControl+1);
|
||||
memcpy(zOtaControl, sqlite3_column_text(pStmt, nCol), nOtaControl+1);
|
||||
|
||||
for(i=0; i<nCol; i++){
|
||||
@@ -1300,11 +1303,11 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
|
||||
const char *aSrc = sqlite3_column_blob(pStmt, nCol+1+i);
|
||||
int nSrc = sqlite3_column_bytes(pStmt, nCol+1+i);
|
||||
const char *aFinal = sqlite3_column_blob(pStmt, i);
|
||||
int nFinal = sqlite3_column_bytes(pStmt, i);
|
||||
i64 nFinal = sqlite3_column_bytes(pStmt, i);
|
||||
char *aDelta;
|
||||
int nDelta;
|
||||
|
||||
aDelta = sqlite3_malloc(nFinal + 60);
|
||||
aDelta = sqlite3_malloc64(nFinal + 60);
|
||||
nDelta = rbuDeltaCreate(aSrc, nSrc, aFinal, nFinal, aDelta);
|
||||
if( nDelta<nFinal ){
|
||||
int j;
|
||||
@@ -1549,10 +1552,10 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
sqlite3_stmt *pStmt; /* SQL statment */
|
||||
char *zId = safeId(zTab); /* Escaped name of the table */
|
||||
char **azCol = 0; /* List of escaped column names */
|
||||
int nCol = 0; /* Number of columns */
|
||||
i64 nCol = 0; /* Number of columns */
|
||||
int *aiFlg = 0; /* 0 if column is not part of PK */
|
||||
int *aiPk = 0; /* Column numbers for each PK column */
|
||||
int nPk = 0; /* Number of PRIMARY KEY columns */
|
||||
i64 nPk = 0; /* Number of PRIMARY KEY columns */
|
||||
sqlite3_str *pSql; /* SQL for the diff query */
|
||||
int i, k; /* Loop counters */
|
||||
const char *zSep; /* List separator */
|
||||
@@ -1564,16 +1567,16 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
nCol++;
|
||||
azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol);
|
||||
azCol = sqlite3_realloc64(azCol, sizeof(char*)*nCol);
|
||||
if( azCol==0 ) runtimeError("out of memory");
|
||||
aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol);
|
||||
aiFlg = sqlite3_realloc64(aiFlg, sizeof(int)*nCol);
|
||||
if( aiFlg==0 ) runtimeError("out of memory");
|
||||
azCol[nCol-1] = safeId((const char*)sqlite3_column_text(pStmt,1));
|
||||
aiFlg[nCol-1] = i = sqlite3_column_int(pStmt,5);
|
||||
if( i>0 ){
|
||||
if( i>nPk ){
|
||||
nPk = i;
|
||||
aiPk = sqlite3_realloc(aiPk, sizeof(int)*nPk);
|
||||
aiPk = sqlite3_realloc64(aiPk, sizeof(int)*nPk);
|
||||
if( aiPk==0 ) runtimeError("out of memory");
|
||||
}
|
||||
aiPk[i-1] = nCol-1;
|
||||
@@ -1913,7 +1916,7 @@ int main(int argc, char **argv){
|
||||
FILE *out = stdout;
|
||||
void (*xDiff)(const char*,FILE*) = diff_one_table;
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
int nExt = 0;
|
||||
i64 nExt = 0;
|
||||
char **azExt = 0;
|
||||
#endif
|
||||
int useTransaction = 0;
|
||||
|
||||
Reference in New Issue
Block a user